2012年6月10日日曜日

blender - 2.6 - pythonで3DViewにお絵かき


実行方法
1. TextEditorにスクリプトを貼り付ける
2. RunScriptボタンを押す
3. 3DViewでスペースキーを押して、uimacで検索
4. uimac Drawer というのが出てくるので選択する
5, 描く

Escキーで終了です。
# Blender 3DViewport Line Drawer
# author: uimac
# date: 2012/6/10
# ver: 0.001dot

import bpy
import bgl

class LineDrawer:
    
    pre_x = 0
    pre_y = 0
    is_mouse_pressed = 0
    
    # [(x0, y0), (x1, y1), ...]
    point_list = []
    
    # [ point_list_1, point_list_2, ... ]
    stroke_list = []
    
    viewport = None
    
    def dispose(self):
        self.point_list = []
        self.stroke_list = []
        self.viewport = None
        self.pre_x = 0
        self.pre_y = 0
        
    def mouse(self, context, event):
        x = event.mouse_x
        y = event.mouse_y
                
        if event.type == 'LEFTMOUSE':
            if event.value == 'PRESS':
                self.is_mouse_pressed = True
                self.pre_x = x
                self.pre_y = y
                
            elif event.value == 'RELEASE':
                self.is_mouse_pressed = False
                self.stroke_list.append(self.point_list)
                self.point_list = []
                
        if event.type == 'MOUSEMOVE':
            if self.is_mouse_pressed:
                point_list = self.point_list
                point_list.append((x,y))
                
                # tekitou hokan
                pointlen = len(point_list)
                if pointlen >= 3:
                    last = pointlen - 1
                    p0 = point_list[last-2]
                    p1 = point_list[last-1]
                    p2 = point_list[last]
                    point_list[last-1] = ( \
                    (((p0[0] + p2[0]) >> 1) + p1[0]) >> 1,
                    (((p0[1] + p2[1]) >> 1) + p1[1]) >> 1)

        self.pre_x = x
        self.pre_y = y

    def draw_line(self, x0, y0, x1, y1):
        bgl.glBegin(bgl.GL_LINES)
        bgl.glVertex2i(x0,y0)
        bgl.glVertex2i(x1,y1)
        bgl.glEnd()
    
    def draw_lines(self, context, event, viewport):
        
        if len(self.stroke_list) > 0:
            for stroke in self.stroke_list:
                bgl.glBegin(bgl.GL_LINE_STRIP)
                for point in stroke:
                    x1 = point[0] - viewport[0]
                    y1 = point[1] - viewport[1]
                    bgl.glVertex2i(x1,y1)
                bgl.glEnd()
        
        bgl.glBegin(bgl.GL_LINE_STRIP)
        
                
        for point in self.point_list:
            x1 = point[0] - viewport[0]
            y1 = point[1] - viewport[1]
            #print(point[0], point[1])
            #print(viewport)
            bgl.glVertex2i(x1,y1)
            
        bgl.glEnd()
        
    def draw(self, context, event):
        bgl.glEnable(bgl.GL_BLEND)
        bgl.glColor4f(0.0, 0.0, 0.0, 1)
        bgl.glLineWidth(1.5)
    
        if self.viewport == None:
            self.viewport = bgl.Buffer(bgl.GL_INT, 4)
            bgl.glGetIntegerv(bgl.GL_VIEWPORT, self.viewport)
            
        # draw!
        self.draw_lines(context, event, self.viewport)
    
        # restore opengl defaults
        bgl.glLineWidth(1)
        bgl.glDisable(bgl.GL_BLEND)
        bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
        

class DrawerRegister(bpy.types.Operator):
    bl_idname = "uimac.drawer"
    bl_label = "uimac Drawer"
    
    drawer = LineDrawer()
    handle = None

    def modal(self, context, event):
        if context.area:
            context.area.tag_redraw()
        
        self.drawer.mouse(context, event)
        
        if event.type in ('ESC'):
            if self.handle:
                self.drawer.dispose()
                context.region.callback_remove(self.handle)
            return {'CANCELLED'}

        return {"PASS_THROUGH"}

    def invoke(self, context, event):
        if context.area.type == 'VIEW_3D':
            self.cursor_on_handle = 'None'
            context.window_manager.modal_handler_add(self)
            
            self.handle = context.region.callback_add(\
                self.drawer.draw, (context, event), 'POST_PIXEL')
                
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "Image View not found, cannot run operator")
            return {'CANCELLED'}

def register():
    bpy.utils.register_class(DrawerRegister)
def unregister():
    bpy.utils.unregister_class(DrawerRegister)
    
if __name__ == '__main__':
    register()

0 件のコメント: