Ejemplo n.º 1
0
 def execute(self, context):
     #add a textbox to display information.  attach it to this
     #add a persisetent callback on scene update
     #which monitors the status of the ODC
     
     #clear previous handlers
     clear_help_handlers()
     global implant_help_app_handle
     implant_help_app_handle = bpy.app.handlers.scene_update_pre.append(implant_help_parser)
     
     global help_display_box
     if help_display_box != None:
         del help_display_box
     help_text = 'Open Dental Implant Help Wizard \n'
     selections = odcutils.implant_selection(bpy.context)  #weird, how do I specify better arguments?
     sel_names = [item.name for item in selections]
     help_text += 'Selected Implants: ' + ', '.join(sel_names) + '\n'
     help_text += 'Next Step: ' + 'TBA'
     
     help_display_box = TextBox(context,500,500,300,100,10,20, help_text)
     help_display_box.snap_to_corner(context, corner = [0,1])
     
     global implant_help_draw_handle
     implant_help_draw_handle = bpy.types.SpaceView3D.draw_handler_add(odc_help_draw, (self, context), 'WINDOW', 'POST_PIXEL')    
     return {'FINISHED'}
Ejemplo n.º 2
0
    def invoke(self, context, event):

        settings = get_settings()
        libpath = settings.ortho_lib
        assets = obj_list_from_lib(libpath)

        if settings.bracket in assets:
            current_obs = [ob.name for ob in bpy.data.objects]
            obj_from_lib(settings.ortho_lib, settings.bracket)
            for ob in bpy.data.objects:
                if ob.name not in current_obs:
                    Bracket = ob
                    Bracket.hide = False

            context.scene.objects.link(Bracket)
        else:
            Bracket = None

        if context.object and context.object.type == 'MESH':
            self.bracket_manager = BracketDataManager(
                context,
                snap_type='OBJECT',
                snap_object=context.object,
                name='Bracket',
                bracket=Bracket)
            self.bracket_slicer = BracektSlicer(context, self.bracket_manager)
        else:
            self.bracket_manager = BracketDataManager(context,
                                                      snap_type='SCENE',
                                                      snap_object=None,
                                                      name='Bracket',
                                                      bracket=Bracket)
            self.bracket_slicer = None

        help_txt = "DRAW MARGIN OUTLINE\n\nLeft Click on model to place bracket.\n G to grab  \n S to show slice \n ENTER to confirm \n ESC to cancel"
        self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt)
        self.help_box.snap_to_corner(context, corner=[1, 1])
        self.mode = 'start'
        self._handle = bpy.types.SpaceView3D.draw_handler_add(
            bracket_placement_draw_callback, (self, context), 'WINDOW',
            'POST_PIXEL')
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}
Ejemplo n.º 3
0
    def invoke(self, context, event):
        settings = get_settings()
        dbg = settings.debug

        if context.space_data.region_3d.is_perspective:
            #context.space_data.region_3d.is_perspective = False
            bpy.ops.view3d.view_persportho()

        if context.space_data.type != 'VIEW_3D':
            self.report({'WARNING'}, "Active space must be a View3d")
            return {'CANCELLED'}

        #gather all the teeth in the scene TODO, keep better track

        self.target = 11
        self.message = "Set axis for " + str(self.target)

        if context.mode != 'OBJECT':
            bpy.ops.object.mode_set(mode='OBJECT')

        #check for an armature
        bpy.ops.object.select_all(action='DESELECT')

        help_txt = "Left click on the tooth indicated to label it. Right click skip a tooth \n Up or Dn Arrow to change label\n Enter to finish \n ESC to cancel"
        self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt)
        self.help_box.fit_box_width_to_text_lines()
        self.help_box.fit_box_height_to_text_lines()
        self.help_box.snap_to_corner(context, corner=[1, 1])

        aspect, mid = menu_utils.view3d_get_size_and_mid(context)
        self.target_box = TextBox(context, mid[0], aspect[1] - 20, 300, 200,
                                  10, 20, self.message)
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()
        self.target_box.fit_box_height_to_text_lines()

        self.mode = 'main'
        context.window_manager.modal_handler_add(self)
        self._handle = bpy.types.SpaceView3D.draw_handler_add(
            rapid_label_teeth_callback, (self, context), 'WINDOW',
            'POST_PIXEL')
        return {'RUNNING_MODAL'}
Ejemplo n.º 4
0
 def execute(self, context):
     #add a textbox to display information.  attach it to this
     #add a persisetent callback on scene update
     #which monitors the status of the ODC
     
     #clear previous handlers
     clear_help_handlers()
     global guide_help_app_handle
     guide_help_app_handle = bpy.app.handlers.scene_update_pre.append(guide_help_parser)
     
     global help_display_box
     if help_display_box != None:
         del help_display_box
     help_text = 'Open Dental Guide Help Wizard \n'
     help_text += 'Next Step: ' + 'TBA'
     
     help_display_box = TextBox(context,500,500,300,100,10,20, help_text)
     help_display_box.snap_to_corner(context, corner = [0,1])
     
     global guide_help_draw_handle
     guide_help_draw_handle = bpy.types.SpaceView3D.draw_handler_add(odc_help_draw, (self, context), 'WINDOW', 'POST_PIXEL')    
     return {'FINISHED'}
Ejemplo n.º 5
0
class OPENDENTAL_OT_add_bone_roots(bpy.types.Operator):
    """Set the axis and direction of the roots for crowns from view"""
    bl_idname = "opendental.add_bone_roots"
    bl_label = "Add bone roots"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(self, context):
        if context.mode != 'OBJECT':
            return False
        else:
            return True

    def set_axis(self, context, event):

        if not self.target:
            return

        empty_name = self.target.name + 'root_empty'
        if empty_name in context.scene.objects:
            ob = context.scene.objects[empty_name]
            ob.empty_draw_type = 'SINGLE_ARROW'
            ob.empty_draw_size = 10
        else:
            ob = bpy.data.objects.new(empty_name, None)
            ob.empty_draw_type = 'SINGLE_ARROW'
            ob.empty_draw_size = 10
            context.scene.objects.link(ob)

        coord = (event.mouse_region_x, event.mouse_region_y)
        v3d = context.space_data
        rv3d = v3d.region_3d
        view_vector = view3d_utils.region_2d_to_vector_3d(
            context.region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(
            context.region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)
        if bversion() < '002.077.000':
            res, obj, loc, no, mx = context.scene.ray_cast(
                ray_origin, ray_target)
        else:
            res, loc, no, ind, obj, mx = context.scene.ray_cast(
                ray_origin, view_vector)

        if res:
            if obj != self.target:
                return

            ob.location = loc
        else:
            return

        if ob.rotation_mode != 'QUATERNION':
            ob.rotation_mode = 'QUATERNION'

        vrot = rv3d.view_rotation
        ob.rotation_quaternion = vrot

    def advance_next_prep(self, context):
        if self.target == None:
            self.target = self.units[0]

        ind = self.units.index(self.target)
        prev = int(math.fmod(ind + 1, len(self.units)))
        self.target = self.units[prev]
        self.message = "Set axis for %s" % self.target.name
        self.target_box.raw_text = self.message
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()

        for obj in context.scene.objects:
            obj.select = False

        self.target.select = True
        context.space_data.region_3d.view_location = self.target.location

    def select_prev_unit(self, context):
        if self.target == None:
            self.target = self.units[0]

        ind = self.units.index(self.target)
        prev = int(math.fmod(ind - 1, len(self.units)))
        self.target = self.units[prev]
        self.message = "Set axis for %s" % self.target.name
        self.target_box.raw_text = self.message
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()

        for obj in context.scene.objects:
            obj.select = False

        self.target.select = True
        context.space_data.region_3d.view_location = self.target.location

    def update_selection(self, context):
        if not len(context.selected_objects):
            self.message = "Right Click to Select"
            self.target = None
            return

        if context.selected_objects[0] not in self.units:
            self.message = "Selected Object must be tooth"
            self.target = None
            return

        self.target = context.selected_objects[0]
        self.message = "Set axis for %s" % self.target.name
        self.target_box.raw_text = self.message
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()

    def empties_to_bones(self, context):
        bpy.ops.object.select_all(action='DESELECT')

        arm_ob = bpy.data.objects['Roots']
        arm_ob.select = True
        context.scene.objects.active = arm_ob
        bpy.ops.object.mode_set(mode='EDIT')

        for ob in self.units:
            e = context.scene.objects.get(ob.name + 'root_empty')
            b = arm_ob.data.edit_bones.get(ob.name + 'root')

            if e != None and b != None:
                b.transform(
                    e.matrix_world)  #this gets the local x,y,z in order
                Z = e.matrix_world.to_quaternion() * Vector((0, 0, 1))
                b.tail.xyz = e.location
                b.head.xyz = e.location - 16 * Z
                b.head_radius = 1.5
                b.tail_radius = 2.5

                context.scene.objects.unlink(e)
                e.user_clear()
                bpy.data.objects.remove(e)
            else:
                print('missing bone or empty')

        bpy.ops.object.mode_set(mode='OBJECT')

    def modal_main(self, context, event):
        # general navigation
        nmode = self.modal_nav(event)
        if nmode != '':
            return nmode  #stop here and tell parent modal to 'PASS_THROUGH'

        if event.type in {'RIGHTMOUSE'} and event.value == 'PRESS':
            self.update_selection(context)
            return 'pass'

        elif event.type == 'RIGHTMOUSE' and event.value == 'RELEASE':
            self.update_selection(context)
            if len(context.selected_objects):
                context.space_data.region_3d.view_location = context.selected_objects[
                    0].location
            return 'main'

        elif event.type in {'LEFTMOUSE'} and event.value == 'PRESS':
            self.set_axis(context, event)
            self.advance_next_prep(context)
            return 'main'

        elif event.type in {'DOWN_ARROW'} and event.value == 'PRESS':
            self.select_prev_unit(context)
            return 'main'

        elif event.type in {'UP_ARROW'} and event.value == 'PRESS':
            self.advance_next_prep(context)
            return 'main'

        elif event.type in {'ESC'}:
            #keep track of and delete new objects? reset old transforms?
            return 'cancel'

        elif event.type in {'RET'} and event.value == 'PRESS':
            self.empties_to_bones(context)
            return 'finish'

        return 'main'

    def modal_nav(self, event):
        events_nav = {
            'MIDDLEMOUSE', 'WHEELINMOUSE', 'WHEELOUTMOUSE', 'WHEELUPMOUSE',
            'WHEELDOWNMOUSE'
        }  #TODO, better navigation, another tutorial
        handle_nav = False
        handle_nav |= event.type in events_nav

        if handle_nav:
            return 'nav'
        return ''

    def modal(self, context, event):
        context.area.tag_redraw()

        FSM = {}
        FSM['main'] = self.modal_main
        FSM['pass'] = self.modal_main
        FSM['nav'] = self.modal_nav

        nmode = FSM[self.mode](context, event)

        if nmode == 'nav':
            return {'PASS_THROUGH'}

        if nmode in {'finish', 'cancel'}:
            #clean up callbacks
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'FINISHED'} if nmode == 'finish' else {'CANCELLED'}
        if nmode == 'pass':
            self.mode = 'main'
            return {'PASS_THROUGH'}

        if nmode: self.mode = nmode

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        settings = get_settings()
        dbg = settings.debug

        if context.space_data.region_3d.is_perspective:
            #context.space_data.region_3d.is_perspective = False
            bpy.ops.view3d.view_persportho()

        if context.space_data.type != 'VIEW_3D':
            self.report({'WARNING'}, "Active space must be a View3d")
            return {'CANCELLED'}

        #gather all the teeth in the scene TODO, keep better track
        self.units = []

        for i in TOOTH_NUMBERS:
            ob = context.scene.objects.get(str(i))
            if ob != None and not ob.hide:
                self.units.append(ob)

        if not len(self.units):
            self.report({
                'ERROR'
            }, "There are no teeth in the scene!, Teeth must be named 2 digits eg 11 or 46"
                        )
            return {'CANCELLED'}

        self.target = self.units[0]
        self.message = "Set axis for %s" % self.target.name

        #check for an armature
        bpy.ops.object.select_all(action='DESELECT')
        if context.mode != 'OBJECT':
            bpy.ops.object.mode_set(mode='OBJECT')

        if context.scene.objects.get('Roots'):
            root_arm = context.scene.objects.get('Roots')
            root_arm.select = True
            root_arm.hide = False
            context.scene.objects.active = root_arm
            bpy.ops.object.mode_set(mode='EDIT')

            for ob in self.units:
                if ob.name + 'root' not in root_arm.data.bones:
                    bpy.ops.armature.bone_primitive_add(name=ob.name + 'root')

        else:
            root_data = bpy.data.armatures.new('Roots')
            root_arm = bpy.data.objects.new('Roots', root_data)
            context.scene.objects.link(root_arm)

            root_arm.select = True
            context.scene.objects.active = root_arm
            bpy.ops.object.mode_set(mode='EDIT')

            for ob in self.units:
                bpy.ops.armature.bone_primitive_add(name=ob.name + 'root')

        bpy.ops.object.mode_set(mode='OBJECT')
        root_arm.select = False
        self.units[0].select = True

        help_txt = "Right click to select a tooth \n Align View with root, mes and distal\n Up Arrow and Dn Arrow to select different units \n Left click in middle of prep to set axis \n Enter to finish \n ESC to cancel"
        self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt)
        self.help_box.fit_box_width_to_text_lines()
        self.help_box.fit_box_height_to_text_lines()
        self.help_box.snap_to_corner(context, corner=[1, 1])

        aspect, mid = menu_utils.view3d_get_size_and_mid(context)
        self.target_box = TextBox(context, mid[0], aspect[1] - 20, 300, 200,
                                  10, 20, self.message)
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()
        self.target_box.fit_box_height_to_text_lines()

        self.mode = 'main'
        context.window_manager.modal_handler_add(self)
        self._handle = bpy.types.SpaceView3D.draw_handler_add(
            insertion_axis_draw_callback, (self, context), 'WINDOW',
            'POST_PIXEL')
        return {'RUNNING_MODAL'}
Ejemplo n.º 6
0
class OPENDENTAL_OT_fast_label_teeth(bpy.types.Operator):
    """Label teeth by clicking on them"""
    bl_idname = "opendental.fast_label_teeth"
    bl_label = "Fast Label Teeth"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(self, context):
        if context.mode != 'OBJECT':
            return False
        else:
            return True

    def set_axis(self, context, event):

        coord = (event.mouse_region_x, event.mouse_region_y)
        v3d = context.space_data
        rv3d = v3d.region_3d
        view_vector = view3d_utils.region_2d_to_vector_3d(
            context.region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(
            context.region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)
        if bversion() < '002.077.000':
            res, obj, loc, no, mx = context.scene.ray_cast(
                ray_origin, ray_target)
        else:
            res, loc, no, ind, obj, mx = context.scene.ray_cast(
                ray_origin, view_vector)

        if res:
            obj.name = str(self.target)
            for ob in bpy.data.objects:
                ob.select = False
            obj.select = True
            obj.show_name = True
            context.scene.objects.active = obj
            bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS')
            return True
        else:
            return False

    def advance_next_prep(self, context):
        def next_ind(n):
            if math.fmod(n, 10) < 7:
                return n + 1
            elif math.fmod(n, 10) == 7:
                if n == 17: return 21
                elif n == 27: return 31
                elif n == 37: return 41
                elif n == 47: return 11

        self.target = next_ind(self.target)
        self.message = "Click on tooth % i" % self.target
        self.target_box.raw_text = self.message
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()

    def select_prev_unit(self, context):
        def prev_ind(n):
            if math.fmod(n, 10) > 1:
                return n - 1
            elif math.fmod(n, 10) == 1:
                if n == 11: return 41
                elif n == 21: return 11
                elif n == 31: return 21
                elif n == 41: return 31

        self.target = prev_ind(self.target)

        self.message = "Click on tooth %i" % self.target
        self.target_box.raw_text = self.message
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()

    def modal_main(self, context, event):
        # general navigation
        nmode = self.modal_nav(event)
        if nmode != '':
            return nmode  #stop here and tell parent modal to 'PASS_THROUGH'

        if event.type in {'RIGHTMOUSE'} and event.value == 'PRESS':
            self.advance_next_prep(context)
            return 'pass'

        elif event.type in {'LEFTMOUSE'} and event.value == 'PRESS':
            res = self.set_axis(context, event)
            if res:
                self.advance_next_prep(context)
            return 'main'

        elif event.type in {'DOWN_ARROW'} and event.value == 'PRESS':
            self.select_prev_unit(context)
            return 'main'

        elif event.type in {'UP_ARROW'} and event.value == 'PRESS':
            self.advance_next_prep(context)
            return 'main'

        elif event.type in {'ESC'}:
            #keep track of and delete new objects? reset old transforms?
            return 'cancel'

        elif event.type in {'RET'} and event.value == 'PRESS':
            #self.empties_to_bones(context)
            return 'finish'

        return 'main'

    def modal_nav(self, event):
        events_nav = {
            'MIDDLEMOUSE', 'WHEELINMOUSE', 'WHEELOUTMOUSE', 'WHEELUPMOUSE',
            'WHEELDOWNMOUSE'
        }  #TODO, better navigation, another tutorial
        handle_nav = False
        handle_nav |= event.type in events_nav

        if handle_nav:
            return 'nav'
        return ''

    def modal(self, context, event):
        context.area.tag_redraw()

        FSM = {}
        FSM['main'] = self.modal_main
        FSM['pass'] = self.modal_main
        FSM['nav'] = self.modal_nav

        nmode = FSM[self.mode](context, event)

        if nmode == 'nav':
            return {'PASS_THROUGH'}

        if nmode in {'finish', 'cancel'}:
            #clean up callbacks
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'FINISHED'} if nmode == 'finish' else {'CANCELLED'}
        if nmode == 'pass':
            self.mode = 'main'
            return {'PASS_THROUGH'}

        if nmode: self.mode = nmode

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        settings = get_settings()
        dbg = settings.debug

        if context.space_data.region_3d.is_perspective:
            #context.space_data.region_3d.is_perspective = False
            bpy.ops.view3d.view_persportho()

        if context.space_data.type != 'VIEW_3D':
            self.report({'WARNING'}, "Active space must be a View3d")
            return {'CANCELLED'}

        #gather all the teeth in the scene TODO, keep better track

        self.target = 11
        self.message = "Set axis for " + str(self.target)

        if context.mode != 'OBJECT':
            bpy.ops.object.mode_set(mode='OBJECT')

        #check for an armature
        bpy.ops.object.select_all(action='DESELECT')

        help_txt = "Left click on the tooth indicated to label it. Right click skip a tooth \n Up or Dn Arrow to change label\n Enter to finish \n ESC to cancel"
        self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt)
        self.help_box.fit_box_width_to_text_lines()
        self.help_box.fit_box_height_to_text_lines()
        self.help_box.snap_to_corner(context, corner=[1, 1])

        aspect, mid = menu_utils.view3d_get_size_and_mid(context)
        self.target_box = TextBox(context, mid[0], aspect[1] - 20, 300, 200,
                                  10, 20, self.message)
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()
        self.target_box.fit_box_height_to_text_lines()

        self.mode = 'main'
        context.window_manager.modal_handler_add(self)
        self._handle = bpy.types.SpaceView3D.draw_handler_add(
            rapid_label_teeth_callback, (self, context), 'WINDOW',
            'POST_PIXEL')
        return {'RUNNING_MODAL'}
Ejemplo n.º 7
0
    def invoke(self, context, event):
        settings = get_settings()
        dbg = settings.debug

        if context.space_data.region_3d.is_perspective:
            #context.space_data.region_3d.is_perspective = False
            bpy.ops.view3d.view_persportho()

        if context.space_data.type != 'VIEW_3D':
            self.report({'WARNING'}, "Active space must be a View3d")
            return {'CANCELLED'}

        #gather all the teeth in the scene TODO, keep better track
        self.units = []

        for i in TOOTH_NUMBERS:
            ob = context.scene.objects.get(str(i))
            if ob != None and not ob.hide:
                self.units.append(ob)

        if not len(self.units):
            self.report({
                'ERROR'
            }, "There are no teeth in the scene!, Teeth must be named 2 digits eg 11 or 46"
                        )
            return {'CANCELLED'}

        self.target = self.units[0]
        self.message = "Set axis for %s" % self.target.name

        #check for an armature
        bpy.ops.object.select_all(action='DESELECT')
        if context.mode != 'OBJECT':
            bpy.ops.object.mode_set(mode='OBJECT')

        if context.scene.objects.get('Roots'):
            root_arm = context.scene.objects.get('Roots')
            root_arm.select = True
            root_arm.hide = False
            context.scene.objects.active = root_arm
            bpy.ops.object.mode_set(mode='EDIT')

            for ob in self.units:
                if ob.name + 'root' not in root_arm.data.bones:
                    bpy.ops.armature.bone_primitive_add(name=ob.name + 'root')

        else:
            root_data = bpy.data.armatures.new('Roots')
            root_arm = bpy.data.objects.new('Roots', root_data)
            context.scene.objects.link(root_arm)

            root_arm.select = True
            context.scene.objects.active = root_arm
            bpy.ops.object.mode_set(mode='EDIT')

            for ob in self.units:
                bpy.ops.armature.bone_primitive_add(name=ob.name + 'root')

        bpy.ops.object.mode_set(mode='OBJECT')
        root_arm.select = False
        self.units[0].select = True

        help_txt = "Right click to select a tooth \n Align View with root, mes and distal\n Up Arrow and Dn Arrow to select different units \n Left click in middle of prep to set axis \n Enter to finish \n ESC to cancel"
        self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt)
        self.help_box.fit_box_width_to_text_lines()
        self.help_box.fit_box_height_to_text_lines()
        self.help_box.snap_to_corner(context, corner=[1, 1])

        aspect, mid = menu_utils.view3d_get_size_and_mid(context)
        self.target_box = TextBox(context, mid[0], aspect[1] - 20, 300, 200,
                                  10, 20, self.message)
        self.target_box.format_and_wrap_text()
        self.target_box.fit_box_width_to_text_lines()
        self.target_box.fit_box_height_to_text_lines()

        self.mode = 'main'
        context.window_manager.modal_handler_add(self)
        self._handle = bpy.types.SpaceView3D.draw_handler_add(
            insertion_axis_draw_callback, (self, context), 'WINDOW',
            'POST_PIXEL')
        return {'RUNNING_MODAL'}
Ejemplo n.º 8
0
    def invoke(self, context, event):
        layers_copy = [layer for layer in context.scene.layers]
        context.scene.layers[0] = True

        tooth = odcutils.tooth_selection(context)[0]
        self.tooth = tooth
        sce = bpy.context.scene
        a = tooth.name
        prep = tooth.prep_model
        margin = str(a + "_Margin")
        self.crv = None
        self.margin_manager = None
        if margin in bpy.data.objects:
            self.report({
                'WARNING'
            }, "you have already made a margin for this tooth, hit esc and then undo if you didn't want to replace it"
                        )

        if prep and prep in bpy.data.objects:
            Prep = bpy.data.objects[prep]
            Prep.hide = False
            L = Prep.location
            ###Keep a list of unhidden objects
            for o in sce.objects:
                if o.name != prep and not o.hide:
                    o.hide = True

            self.crv = CurveDataManager(context,
                                        snap_type='OBJECT',
                                        snap_object=Prep,
                                        shrink_mod=True,
                                        name=margin)

            self.margin_manager = MarginSlicer(tooth, context, self.crv)
        else:
            self.report({
                'WARNING'
            }, "There is no prep for this tooth, your margin will snap to the master model or all objects in scene"
                        )

        master = sce.odc_props.master
        if master and master in bpy.data.objects:
            Master = bpy.data.objects[master]
            if prep not in bpy.data.objects:
                self.crv = CurveDataManager(context,
                                            snap_type='OBJECT',
                                            snap_object=Master,
                                            shrink_mod=True,
                                            name=margin)
                self.margin_manager = MarginSlicer(tooth, context, self.crv)
        else:
            self.report({'WARNING'}, "No master model...there are risks!")

        if not self.crv:
            self.crv = CurveDataManager(context,
                                        snap_type='SCENE',
                                        snap_object=None,
                                        shrink_mod=False,
                                        name=margin)

        tooth.margin = self.crv.crv_obj.name

        help_txt = "DRAW MARGIN OUTLINE\n\nLeft Click on model to draw outline \nRight click to delete a point \nLeft Click last point to make loop \n G to grab  \n S to show slice \n ENTER to confirm \n ESC to cancel"
        self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt)
        self.help_box.snap_to_corner(context, corner=[1, 1])
        self.mode = 'main'
        self._handle = bpy.types.SpaceView3D.draw_handler_add(
            icrnmgn_draw_callback, (self, context), 'WINDOW', 'POST_PIXEL')
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}
Ejemplo n.º 9
0
class OPENDENTAL_OT_mark_crown_margin(bpy.types.Operator):
    """Mark Margin.  Draw a line with the mouse to extrude bezier curves"""
    bl_idname = "opendental.mark_crown_margin"
    bl_label = "Mark Crown Margin"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        #restoration exists and is in scene
        teeth = odcutils.tooth_selection(context)

        if teeth != []:  #This can only happen one tooth at a time
            #tooth = teeth[0]
            #return tooth.prep_model in bpy.data.objects
            return True
        else:
            return False

    def modal_nav(self, event):
        events_nav = {
            'MIDDLEMOUSE', 'WHEELINMOUSE', 'WHEELOUTMOUSE', 'WHEELUPMOUSE',
            'WHEELDOWNMOUSE'
        }  #TODO, better navigation, another tutorial
        handle_nav = False
        handle_nav |= event.type in events_nav

        if handle_nav:
            return 'nav'
        return ''

    def modal_main(self, context, event):
        # general navigation
        nmode = self.modal_nav(event)
        if nmode != '':
            return nmode  #stop here and tell parent modal to 'PASS_THROUGH'

        #after navigation filter, these are relevant events in this state
        if event.type == 'G' and event.value == 'PRESS':
            if self.crv.grab_initiate():
                return 'grab'
            else:
                #error, need to select a point
                return 'main'

        if event.type == 'MOUSEMOVE':
            self.crv.hover(context, event.mouse_region_x, event.mouse_region_y)
            return 'main'

        if event.type == 'LEFTMOUSE' and event.value == 'PRESS':
            x, y = event.mouse_region_x, event.mouse_region_y
            self.crv.click_add_point(context, x, y)
            return 'main'

        if event.type == 'RIGHTMOUSE' and event.value == 'PRESS':
            self.crv.click_delete_point(mode='mouse')
            return 'main'

        if event.type == 'X' and event.value == 'PRESS':
            self.crv.delete_selected(mode='selected')
            return 'main'

        if event.type == 'S' and event.value == 'PRESS' and self.margin_manager:
            self.margin_manager.prepare_slice()
            return 'slice'

        if event.type == 'RET' and event.value == 'PRESS':
            return 'finish'

        elif event.type == 'ESC' and event.value == 'PRESS':
            del_obj = self.crv.crv_obj
            context.scene.objects.unlink(del_obj)
            bpy.data.objects.remove(del_obj)
            self.tooth.margin = ''
            return 'cancel'

        return 'main'

    def modal_grab(self, context, event):
        # no navigation in grab mode

        if event.type == 'LEFTMOUSE' and event.value == 'PRESS':
            #confirm location
            self.crv.grab_confirm()
            return 'main'

        elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS':
            #put it back!
            self.crv.grab_cancel()
            return 'main'

        elif event.type == 'MOUSEMOVE':
            #update the b_pt location
            self.crv.grab_mouse_move(context, event.mouse_region_x,
                                     event.mouse_region_y)
            return 'grab'

    def modal_slice(self, context, event):
        # no navigation in grab mode

        if event.type == 'LEFTMOUSE' and event.value == 'PRESS':
            #confirm location
            self.margin_manager.slice_confirm()
            return 'main'

        elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS':
            #put it back!
            self.margin_manager.slice_cancel()
            return 'main'

        elif event.type == 'MOUSEMOVE':
            #update the b_pt location
            self.margin_manager.slice_mouse_move(context, event.mouse_region_x,
                                                 event.mouse_region_y)
            return 'slice'

    def modal(self, context, event):
        context.area.tag_redraw()

        FSM = {}
        FSM['main'] = self.modal_main
        FSM['grab'] = self.modal_grab
        FSM['slice'] = self.modal_slice
        FSM['nav'] = self.modal_nav

        nmode = FSM[self.mode](context, event)

        if nmode == 'nav':
            return {'PASS_THROUGH'}

        if nmode in {'finish', 'cancel'}:
            #clean up callbacks
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'FINISHED'} if nmode == 'finish' else {'CANCELLED'}

        if nmode: self.mode = nmode

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        layers_copy = [layer for layer in context.scene.layers]
        context.scene.layers[0] = True

        tooth = odcutils.tooth_selection(context)[0]
        self.tooth = tooth
        sce = bpy.context.scene
        a = tooth.name
        prep = tooth.prep_model
        margin = str(a + "_Margin")
        self.crv = None
        self.margin_manager = None
        if margin in bpy.data.objects:
            self.report({
                'WARNING'
            }, "you have already made a margin for this tooth, hit esc and then undo if you didn't want to replace it"
                        )

        if prep and prep in bpy.data.objects:
            Prep = bpy.data.objects[prep]
            Prep.hide = False
            L = Prep.location
            ###Keep a list of unhidden objects
            for o in sce.objects:
                if o.name != prep and not o.hide:
                    o.hide = True

            self.crv = CurveDataManager(context,
                                        snap_type='OBJECT',
                                        snap_object=Prep,
                                        shrink_mod=True,
                                        name=margin)

            self.margin_manager = MarginSlicer(tooth, context, self.crv)
        else:
            self.report({
                'WARNING'
            }, "There is no prep for this tooth, your margin will snap to the master model or all objects in scene"
                        )

        master = sce.odc_props.master
        if master and master in bpy.data.objects:
            Master = bpy.data.objects[master]
            if prep not in bpy.data.objects:
                self.crv = CurveDataManager(context,
                                            snap_type='OBJECT',
                                            snap_object=Master,
                                            shrink_mod=True,
                                            name=margin)
                self.margin_manager = MarginSlicer(tooth, context, self.crv)
        else:
            self.report({'WARNING'}, "No master model...there are risks!")

        if not self.crv:
            self.crv = CurveDataManager(context,
                                        snap_type='SCENE',
                                        snap_object=None,
                                        shrink_mod=False,
                                        name=margin)

        tooth.margin = self.crv.crv_obj.name

        help_txt = "DRAW MARGIN OUTLINE\n\nLeft Click on model to draw outline \nRight click to delete a point \nLeft Click last point to make loop \n G to grab  \n S to show slice \n ENTER to confirm \n ESC to cancel"
        self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt)
        self.help_box.snap_to_corner(context, corner=[1, 1])
        self.mode = 'main'
        self._handle = bpy.types.SpaceView3D.draw_handler_add(
            icrnmgn_draw_callback, (self, context), 'WINDOW', 'POST_PIXEL')
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}
Ejemplo n.º 10
0
class OPENDENTAL_OT_place_bracket(bpy.types.Operator):
    """Place Bracket on surface of selected object"""
    bl_idname = "opendental.place_ortho_bracket"
    bl_label = "Ortho Bracket Place"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        if context.mode == "OBJECT" and context.object != None:
            return True
        else:
            return False

    def modal_nav(self, event):
        events_nav = {
            'MIDDLEMOUSE', 'WHEELINMOUSE', 'WHEELOUTMOUSE', 'WHEELUPMOUSE',
            'WHEELDOWNMOUSE'
        }  #TODO, better navigation, another tutorial
        handle_nav = False
        handle_nav |= event.type in events_nav

        if handle_nav:
            return 'nav'
        return ''

    def modal_main(self, context, event):
        # general navigation
        nmode = self.modal_nav(event)
        if nmode != '':
            return nmode  #stop here and tell parent modal to 'PASS_THROUGH'

        if event.type == 'G' and event.value == 'PRESS' and self.bracket_slicer:
            self.bracket_slicer.prepare_slice()
            return 'grab'

        if event.type == 'T' and event.value == 'PRESS' and self.bracket_slicer:
            self.bracket_slicer.prepare_slice()
            return 'torque'

        if event.type == 'R' and event.value == 'PRESS' and self.bracket_slicer:
            self.bracket_slicer.prepare_slice()
            return 'rotate'

        if event.type == 'S' and event.value == 'PRESS' and self.bracket_slicer:
            self.bracket_slicer.prepare_slice()
            return 'tip'

        if event.type == 'MOUSEMOVE':
            return 'main'

        if event.type == 'LEFTMOUSE' and event.value == 'PRESS':
            x, y = event.mouse_region_x, event.mouse_region_y
            self.bracket_manager.place_bracket(context, x, y)
            return 'main'

        if event.type == 'RET' and event.value == 'PRESS':
            if self.bracket_slicer:
                self.bracket_slicer.cache_slice_to_grease(context)

            return 'finish'

        elif event.type == 'ESC' and event.value == 'PRESS':
            del_obj = self.bracket_manager.bracket_obj
            context.scene.objects.unlink(del_obj)
            bpy.data.objects.remove(del_obj)
            return 'cancel'

        return 'main'

    def modal_torque(self, context, event):
        # no navigation in grab mode

        if event.type in {'LEFTMOUSE', 'RET', 'ENTER'
                          } and event.value == 'PRESS':
            #confirm location
            self.bracket_slicer.slice_confirm()
            return 'main'

        elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS':
            #put it back!
            self.bracket_slicer.slice_cancel()
            return 'main'

        #elif event.type == 'MOUSEMOVE':
        #update the b_pt location
        #    self.bracket_slicer.slice_mouse_move(context,event.mouse_region_x, event.mouse_region_y)
        #    return 'torque'

        elif event.type in {
                'WHEELUPMOUSE', 'WHEELDOWNMOUSE', 'UP_ARROW', 'DOWN_ARROW'
        }:
            self.bracket_manager.torque_event(event.type, event.shift)
            self.bracket_slicer.slice()
            return 'torque'

    def modal_rotate(self, context, event):
        # no navigation in grab mode

        if event.type in {'LEFTMOUSE', 'RET', 'ENTER'
                          } and event.value == 'PRESS':
            #confirm location
            self.bracket_slicer.slice_confirm()
            return 'main'

        elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS':
            #put it back!
            self.bracket_slicer.slice_cancel()
            return 'main'

        #commented out, no longer want to move the mouse
        #elif event.type == 'MOUSEMOVE':
        #update the b_pt location
        #    self.bracket_slicer.slice_mouse_move(context,event.mouse_region_x, event.mouse_region_y)
        #    return 'rotate'

        elif event.type in {
                'WHEELUPMOUSE', 'WHEELDOWNMOUSE', 'LEFT_ARROW', 'RIGHT_ARROW'
        }:
            self.bracket_manager.rotate_event(event.type, event.shift)
            self.bracket_slicer.slice()
            return 'rotate'

        else:
            return 'rotate'

    def modal_tip(self, context, event):
        # no navigation in grab mode

        if event.type in {'LEFTMOUSE', 'RET', 'ENTER'
                          } and event.value == 'PRESS':
            #confirm location
            self.bracket_slicer.slice_confirm()
            return 'main'

        elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS':
            #put it back!
            self.bracket_slicer.slice_cancel()
            return 'main'

        #commented out, no longer want to move the mouse
        #elif event.type == 'MOUSEMOVE':
        #update the b_pt location
        #    self.bracket_slicer.slice_mouse_move(context,event.mouse_region_x, event.mouse_region_y)
        #    return 'rotate'

        elif event.type in {
                'WHEELUPMOUSE', 'WHEELDOWNMOUSE', 'LEFT_ARROW', 'RIGHT_ARROW'
        }:
            self.bracket_manager.spin_event(event.type, event.shift)
            self.bracket_slicer.slice()
            return 'tip'

        else:
            return 'tip'

    def modal_start(self, context, event):

        if event.type == 'LEFTMOUSE' and event.value == 'PRESS':
            #confirm location
            self.bracket_slicer.slice_confirm()
            return 'main'

        elif event.type == 'MOUSEMOVE':
            x, y = event.mouse_region_x, event.mouse_region_y
            self.bracket_manager.place_bracket(context, x, y, normal=True)
            self.bracket_slicer.slice_mouse_move(context, event.mouse_region_x,
                                                 event.mouse_region_y)
            return 'start'

        elif event.type in {
                'WHEELUPMOUSE', 'WHEELDOWNMOUSE', 'UP_ARROW', 'DOWN_ARROW'
        }:
            self.bracket_manager.spin_event(event.type, event.shift)
            self.bracket_slicer.slice()
            return 'start'

        elif event.type == "RIGTMOUSE" and event.value == 'PRESS':
            del_obj = self.bracket_manager.bracket_obj
            context.scene.objects.unlink(del_obj)
            bpy.data.objects.remove(del_obj)
            return 'cancel'

        else:
            return 'start'

    def modal_grab(self, context, event):
        # no navigation in grab mode
        #uses the slicer to manage the grab

        if event.type == 'LEFTMOUSE' and event.value == 'PRESS':
            #confirm location
            self.bracket_slicer.slice_confirm()
            return 'main'

        elif event.type in {'RIGHTMOUSE', 'ESC'} and event.value == 'PRESS':
            #put it back!
            self.bracket_slicer.slice_cancel()
            return 'main'

        elif event.type == 'MOUSEMOVE':
            #update the b_pt location
            self.bracket_slicer.slice_mouse_move(context, event.mouse_region_x,
                                                 event.mouse_region_y)
            return 'grab'

        elif event.type in {
                'WHEELUPMOUSE', 'WHEELDOWNMOUSE', 'UP_ARROW', 'DOWN_ARROW'
        }:
            self.bracket_manager.spin_event(event.type, event.shift)
            self.bracket_slicer.slice()
            return 'grab'

    def modal(self, context, event):
        context.area.tag_redraw()

        FSM = {}
        FSM['start'] = self.modal_start
        FSM['main'] = self.modal_main
        FSM['rotate'] = self.modal_rotate
        FSM['grab'] = self.modal_grab
        FSM['torque'] = self.modal_torque
        FSM['tip'] = self.modal_tip
        FSM['nav'] = self.modal_nav

        nmode = FSM[self.mode](context, event)

        if nmode == 'nav':
            return {'PASS_THROUGH'}

        if nmode in {'finish', 'cancel'}:
            #clean up callbacks
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'FINISHED'} if nmode == 'finish' else {'CANCELLED'}

        if nmode: self.mode = nmode

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):

        settings = get_settings()
        libpath = settings.ortho_lib
        assets = obj_list_from_lib(libpath)

        if settings.bracket in assets:
            current_obs = [ob.name for ob in bpy.data.objects]
            obj_from_lib(settings.ortho_lib, settings.bracket)
            for ob in bpy.data.objects:
                if ob.name not in current_obs:
                    Bracket = ob
                    Bracket.hide = False

            context.scene.objects.link(Bracket)
        else:
            Bracket = None

        if context.object and context.object.type == 'MESH':
            self.bracket_manager = BracketDataManager(
                context,
                snap_type='OBJECT',
                snap_object=context.object,
                name='Bracket',
                bracket=Bracket)
            self.bracket_slicer = BracektSlicer(context, self.bracket_manager)
        else:
            self.bracket_manager = BracketDataManager(context,
                                                      snap_type='SCENE',
                                                      snap_object=None,
                                                      name='Bracket',
                                                      bracket=Bracket)
            self.bracket_slicer = None

        help_txt = "DRAW MARGIN OUTLINE\n\nLeft Click on model to place bracket.\n G to grab  \n S to show slice \n ENTER to confirm \n ESC to cancel"
        self.help_box = TextBox(context, 500, 500, 300, 200, 10, 20, help_txt)
        self.help_box.snap_to_corner(context, corner=[1, 1])
        self.mode = 'start'
        self._handle = bpy.types.SpaceView3D.draw_handler_add(
            bracket_placement_draw_callback, (self, context), 'WINDOW',
            'POST_PIXEL')
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}