import bpy from bpy.props import (IntProperty, EnumProperty, BoolProperty) from bpy.types import (AddonPreferences, GizmoGroup, Operator, Gizmo) import gpu from mathutils import Vector, Matrix, Euler from gpu_extras.batch import batch_for_shader from .constants import PICKERS, SHADERS from .core.picker import Picker from .core.geometry_utils import bounding_rect ''' class RP_OT_simple_operator(bpy.types.Operator): """Tooltip""" bl_idname = "object.simple_operator" bl_label = "Simple Object Operator" def invoke(self, context, event): context.window_manager.modal_handler_add(self) print('Invoke RP_OT_simple_operator') bpy.ops.node.rp_box_select('INVOKE_DEFAULT', tweak=True) #bpy.ops.node.select_box('INVOKE_DEFAULT', wait_for_input=True, tweak=True) return {'RUNNING_MODAL'} def modal(self, context, event): print('modal op', event.type, event.value) return {'RUNNING_MODAL'} def execute(self, context): print('Select Shape') return {'FINISHED'} ''' ''' class RP_OT_box_select(Operator): """Box Select bones in the picker view""" bl_idname = "node.rp_box_select" bl_label = "Picker Box Select" mode: EnumProperty(items=[(i, i.title(), '') for i in ('SET', 'EXTEND', 'SUBSTRACT')]) @classmethod def poll(cls, context): if not is_picker_space(context.space_data): return ob = context.object return ob and ob in PICKERS def draw_callback(self): #print('draw callback border') if not self.draw_border: return gpu.state.blend_set('ALPHA') #print('DRAW BORDER') self.color_shader.bind() self.color_shader.uniform_float("color", self.bg_color) self.bg_batch.draw(self.color_shader) self.dash_shader.bind() matrix = gpu.matrix.get_projection_matrix() self.dash_shader.uniform_float("color", self.border_color) self.dash_shader.uniform_float("viewMatrix", matrix) self.dash_shader.uniform_float("dashSize", 5) self.dash_shader.uniform_float("gapSize", 4) self.contour_batch.draw(self.dash_shader) gpu.state.blend_set('NONE') def invoke(self, context, event): #print(f'invoke: type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}') if context.object.mode != 'POSE': bpy.ops.object.posemode_toggle() self.timer = None #self.mode = self.mode_from_event(event) #self.invoke_event = event.copy() self.region = context.region self.draw_border = False self.picker = PICKERS[context.object] self.start_mouse = event.mouse_region_x, event.mouse_region_y #self.shader = line_strip_shader self.border_color = [1, 1, 1, 1] self.bg_color = [1, 1, 1, 0.05] #args = (self, context) self.color_shader = gpu.shader.from_builtin('UNIFORM_COLOR') self.dash_shader = SHADERS['dashed_line'] self._handle = bpy.types.SpaceNodeEditor.draw_handler_add(self.draw_callback, (), 'WINDOW', 'POST_PIXEL') context.window_manager.modal_handler_add(self) self.picker.press_event(self.mode) self.region.tag_redraw() return {'RUNNING_MODAL'} def modal(self, context, event): self.mouse = event.mouse_region_x, event.mouse_region_y self.border = bounding_rect((self.start_mouse, self.mouse)) self.bg_batch = batch_for_shader(self.color_shader, 'TRI_FAN', {"pos": self.border}) self.contour_batch = batch_for_shader(self.dash_shader, 'LINE_LOOP', {"pos": self.border}) self.draw_border = True self.region.tag_redraw() if event.value == 'RELEASE': return self.release_event(context) return {'RUNNING_MODAL'} def release_event(self, context): scn = context.scene if scn.rig_picker.use_pick_bone: self.picker.assign_bone_event() elif (self.start_mouse[0] != self.mouse[0] or self.start_mouse[1] != self.mouse[1]): self.picker.border_select(self.border, self.mode) else: self.picker.move_event(self.mouse) self.picker.release_event(self.mode) bpy.ops.ed.undo_push(message="Box Select") return self.exit(context) def exit(self, context): bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW') context.region.tag_redraw() return {'FINISHED'} ''' class RP_GT_gizmo(Gizmo): def mode_from_event(self, event): if event.alt: return 'SUBSTRACT' elif event.ctrl or event.shift: return 'EXTEND' else: return 'SET' def test_select(self, context, location): ob = context.object picker = PICKERS.get(ob) if not picker: return -1 picker.move_event(location) context.region.tag_redraw() return 1 def draw(self, context): print('DRAW_SELECT', self.border) if not self.draw_border: return gpu.state.blend_set('ALPHA') gpu.state.depth_test_set('ALWAYS') gpu.state.depth_mask_set(False) #print('DRAW BORDER') self.color_shader.bind() self.color_shader.uniform_float("color", self.bg_color) self.bg_batch.draw(self.color_shader) self.dash_shader.bind() matrix = gpu.matrix.get_projection_matrix() self.dash_shader.uniform_float("color", self.border_color) self.dash_shader.uniform_float("viewMatrix", matrix) self.dash_shader.uniform_float("dashSize", 5) self.dash_shader.uniform_float("gapSize", 4) self.contour_batch.draw(self.dash_shader) #gpu.state.depth_mask_set(False) gpu.state.blend_set('NONE') def invoke(self, context, event): print(f'invoke: type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}') print(self) if context.object.mode != 'POSE': bpy.ops.object.posemode_toggle() #self.timer = None #self.mode = self.mode_from_event(event) #self.invoke_event = event.copy() #self.region = context.region self.draw_border = False self.picker = PICKERS[context.object] self.start_mouse = event.mouse_region_x, event.mouse_region_y #self.shader = line_strip_shader self.border_color = [1, 1, 1, 1] self.bg_color = [1, 1, 1, 0.05] #args = (self, context) self.color_shader = gpu.shader.from_builtin('UNIFORM_COLOR') self.dash_shader = SHADERS['dashed_line'] #self._handle = bpy.types.SpaceNodeEditor.draw_handler_add(self.draw_callback, (), 'WINDOW', 'POST_PIXEL') self.border = [(0, 0), (0, 0), (0, 0), (0, 0)] #context.window_manager.modal_handler_add(self) self.mode = self.mode_from_event(event) self.picker.press_event(self.mode) context.region.tag_redraw() return {'RUNNING_MODAL'} def modal(self, context, event, tweak): #print(f'invoke: type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}') self.mouse = event.mouse_region_x, event.mouse_region_y self.border = bounding_rect((self.start_mouse, self.mouse)) self.bg_batch = batch_for_shader(self.color_shader, 'TRI_FAN', {"pos": self.border}) self.contour_batch = batch_for_shader(self.dash_shader, 'LINE_LOOP', {"pos": self.border}) self.draw_border = True context.region.tag_redraw() #self.draw(context) return {'RUNNING_MODAL'} def exit(self, context, cancel): scn = context.scene if scn.rig_picker.use_pick_bone: self.picker.assign_bone_event() elif (self.start_mouse[0] != self.mouse[0] or self.start_mouse[1] != self.mouse[1]): self.picker.border_select(self.border, self.mode) else: self.picker.move_event(self.mouse) self.picker.release_event(self.mode) bpy.ops.ed.undo_push(message="Box Select") self.draw_border = False context.region.tag_redraw() class RP_GT_gizmogroup(GizmoGroup): """ test gizmo button 2d """ bl_idname = "view3d.gizmo_button_2d" bl_label = "Test button 2d" bl_space_type = 'NODE_EDITOR' bl_region_type = 'WINDOW' bl_options = {'PERSISTENT'} @classmethod def poll(cls, context): return context.space_data.tree_type == 'RigPickerTree' def setup(self, context): self.gizmo = self.gizmos.new("RP_GT_gizmo") self.gizmo.draw_border = False self.gizmo.border = [] self.gizmo.use_draw_modal = True classes = ( RP_GT_gizmo, RP_GT_gizmogroup ) def register(): for cls in classes: bpy.utils.register_class(cls) def unregister(): for cls in reversed(classes): bpy.utils.unregister_class(cls)