667 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			667 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
 | |
| import bpy,math,mathutils,blf,rna_keymap_ui
 | |
| 
 | |
| from .RA_draw_ui import *
 | |
| from mathutils import Matrix
 | |
| from bpy.types import (
 | |
|                         PropertyGroup,
 | |
|                         Menu
 | |
|                         )
 | |
| from bpy.props import (
 | |
|                         IntProperty,
 | |
|                         FloatProperty,
 | |
|                         BoolProperty
 | |
|                         )
 | |
| #// join objects option in modal operator
 | |
| #// Reset array option in modal operator
 | |
| #// Modal operator Ui
 | |
| #// add Radial Array hotkey 
 | |
| #// preferences add hotkey in addon preferences menu
 | |
| #// addon menu ui
 | |
| #// add modal selectable toggle
 | |
| #// add modal apply option
 | |
| #// add modal ui tooltips
 | |
| #// add make unique
 | |
| #// add create collection toggle
 | |
| 
 | |
| 
 | |
| bl_info = {
 | |
|     "name" : "R.Array",
 | |
|     "author" : "Syler",
 | |
|     "version": (0, 0, 1, 2),
 | |
|     "description": "Adds Radial Array Operator",
 | |
|     "blender" : (2, 80, 0),
 | |
|     "category" : "Object"
 | |
| }
 | |
| #+ handle the keymap
 | |
| addon_keymaps = []
 | |
| 
 | |
| def add_hotkey(): 
 | |
|     #* Ctrl Q call R_Array
 | |
|     wm = bpy.context.window_manager
 | |
|     km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
 | |
|     kmi = km.keymap_items.new(R_Array.bl_idname, 'Q', 'PRESS', ctrl=True)
 | |
|     addon_keymaps.append(km)
 | |
| 
 | |
| def remove_hotkey():
 | |
|     wm = bpy.context.window_manager
 | |
|     for km in addon_keymaps:
 | |
|         wm.keyconfigs.addon.keymaps.remove(km)
 | |
|     # clear the list
 | |
|     del addon_keymaps[:]
 | |
| #--------------------------------------------------------------------------------------#
 | |
| def RA_Update_Sel_Status(self, context):
 | |
|     if self.RA_Sel_Status == True:
 | |
|         for ob in self.RA_Parent.children:
 | |
|             ob.hide_select = False
 | |
|     if self.RA_Sel_Status == False:
 | |
|         for ob in self.RA_Parent.children:
 | |
|             ob.hide_select = True
 | |
|             
 | |
| def RA_Update_ObjNum(self, context):
 | |
|     
 | |
|     if self.RA_Status == True:
 | |
|         
 | |
|         if len(self.RA_Parent.children) == self.RA_ObjNum:  
 | |
|             pass
 | |
|         
 | |
|         #+ Add Objects
 | |
|         if len(self.RA_Parent.children) < self.RA_ObjNum:
 | |
|             object_list = []
 | |
|             object_to_copy = self.RA_Parent.children[0]
 | |
|             # append already existing objects to object list
 | |
|             for c in self.RA_Parent.children:
 | |
|                 object_list.append(c)
 | |
|             
 | |
|             
 | |
|             for i in range (len(self.RA_Parent.children), self.RA_ObjNum):
 | |
|                 object_list.append(object_to_copy.copy())
 | |
|                 
 | |
|                 
 | |
|                 
 | |
|             # Add Objects To Collection
 | |
|             for index, ob in enumerate(object_list):
 | |
|                 
 | |
|                 # Reset Matrix
 | |
|                 ob.matrix_basis = mathutils.Matrix()
 | |
|                 
 | |
|                 # set object location to RA_Parent + RA_Offset
 | |
|                 ob.location[1] = self.RA_Parent.location[1] + self.RA_Parent.RA_Offset
 | |
|                 # create angle variable 
 | |
|                 angle = math.radians(360/self.RA_Parent.RA_ObjNum)               
 | |
|                 
 | |
|                 # rotate object
 | |
|                 R = mathutils.Matrix.Rotation(angle * (index), 4, 'Z')
 | |
|                 T = mathutils.Matrix.Translation([0, 0, 0])     
 | |
|                 M = T @ R @ T.inverted()
 | |
|                 ob.location = M @ ob.location
 | |
|                 ob.rotation_euler.rotate(M)
 | |
|                 
 | |
|                 
 | |
|                 # Parent Object 
 | |
|                 ob.parent = self.RA_Parent
 | |
|                 self.RA_Parent.matrix_parent_inverse = ob.matrix_world.inverted()
 | |
|                 ob.RA_Parent = self.RA_Parent
 | |
|                 
 | |
|                 # make objects selectable/unselectable
 | |
|                 if self.RA_Sel_Status == True:
 | |
|                     ob.hide_select = False
 | |
|                 if self.RA_Sel_Status == False:
 | |
|                     ob.hide_select = True
 | |
|     
 | |
|                 # Change Object Name
 | |
|                 ob.name = "RA - " + self.RA_Name + " - " + str(index)
 | |
|                 # set RA Status
 | |
|                 ob.RA_Status = True
 | |
|                 # Link object
 | |
|                 try:
 | |
|                     self.RA_Parent.users_collection[0].objects.link(ob)
 | |
|                     #print ("For LINK")
 | |
|                 except:
 | |
|                     #print ("PASS Linking object to collection failed")
 | |
|                     pass
 | |
|     
 | |
|         #+ Remove Objects
 | |
|         if len(self.RA_Parent.children) > self.RA_ObjNum:
 | |
|                 
 | |
|             # deselect all objects
 | |
|             for d in bpy.context.view_layer.objects:
 | |
|                 d.select_set(False)
 | |
|             bpy.context.view_layer.objects.active = None
 | |
|             
 | |
|             # Make selectable and Select all objects that will be deleted
 | |
|             for i in range (self.RA_ObjNum, len(self.RA_Parent.children)):
 | |
|                 self.RA_Parent.children[i].hide_select = False
 | |
|                 self.RA_Parent.children[i].select_set(True)
 | |
|             # Delete Objects     
 | |
|             bpy.ops.object.delete()
 | |
|             # select control Object
 | |
|             bpy.context.view_layer.objects.active = self.RA_Parent
 | |
|             self.RA_Parent.select_set(True)
 | |
|             for index, ob in enumerate(self.RA_Parent.children):
 | |
|                 # Reset Matrix
 | |
|                 ob.matrix_basis = mathutils.Matrix()
 | |
|             
 | |
|                 # set object location to RA_Parent + RA_Offset
 | |
|                 ob.location[1] = self.RA_Parent.location[1] + self.RA_Parent.RA_Offset
 | |
|                 # create angle variable 
 | |
|                 angle = math.radians(360/self.RA_Parent.RA_ObjNum)
 | |
|             
 | |
|                 # rotate object
 | |
|                 R = mathutils.Matrix.Rotation(angle * (index), 4, 'Z')
 | |
|                 T = mathutils.Matrix.Translation([0, 0, 0])     
 | |
|                 M = T @ R @ T.inverted()
 | |
|                 ob.location = M @ ob.location
 | |
|                 ob.rotation_euler.rotate(M)
 | |
| 
 | |
| def RA_Update_Offset(self, context):
 | |
|     
 | |
|     if self.RA_Status == True:              
 | |
|         for ob in self.RA_Parent.children:      
 | |
|             # define variables
 | |
|             loc = mathutils.Vector((0.0, self.RA_Offset, 0.0))            
 | |
|             rot = ob.rotation_euler
 | |
|             # rotate location    
 | |
|             loc.rotate(rot)
 | |
|             # apply rotation
 | |
|             ob.location = loc
 | |
|     else:
 | |
|         pass
 | |
| #--------------------------------------------------------------------------------------#
 | |
| class R_Array(bpy.types.Operator):  
 | |
|     bl_idname = 'sop.r_array'
 | |
|     bl_label = 'Radial Array'
 | |
|     bl_description = 'Radial Array S.Operator'
 | |
|     bl_options = {'REGISTER', 'UNDO'}
 | |
| 
 | |
|     
 | |
|     
 | |
|     
 | |
|     #?Useless !?
 | |
|     @classmethod
 | |
|     def poll(cls, context):
 | |
|        return True
 | |
|     
 | |
|     def execute(self, context):
 | |
|         
 | |
|         #Create Bpy.context Variable
 | |
|         C = bpy.context
 | |
|         active_object = C.active_object
 | |
|         
 | |
|         
 | |
|         # call modal if RA_Status = True
 | |
|         try:
 | |
|             if active_object.RA_Status == True:
 | |
|                 bpy.ops.sop.ra_modal('INVOKE_DEFAULT')
 | |
|                 return {'FINISHED'}
 | |
|         except:
 | |
|             pass
 | |
|         # Check Selected Cancel if NOT Mesh
 | |
|         if C.selected_objects == [] or C.active_object.type != 'MESH':
 | |
|             self.report({'INFO'}, "No Mesh Selected")
 | |
|             return {'CANCELLED'}
 | |
|         
 | |
|         
 | |
|         # Create Variables
 | |
|         L_Objects = []                              # object list 
 | |
|         ob = active_object                          # active object reference 
 | |
|         ob_collections = ob.users_collection        # active Object collections
 | |
|         f_name = ob.name                            # Object Name 
 | |
|         point = ob.location.copy()                  # Middle point 
 | |
|         is_col_new  = True
 | |
| 
 | |
|         
 | |
|         # Create New Collection             
 | |
|         if bpy.context.preferences.addons[__name__].preferences.col_toggle == True:
 | |
|             for q in bpy.data.collections:
 | |
|                 if q.name == "RA -" + f_name:
 | |
|                     collection = q
 | |
|                     is_col_new = False
 | |
|                     try:
 | |
|                         for col in ob_collections:
 | |
|                             col.objects.unlink(ob)
 | |
|                         collection.objects.link(ob)
 | |
|                     except:
 | |
|                         pass
 | |
|         
 | |
|                 
 | |
|             if is_col_new == True:
 | |
|                 # create and link new collection
 | |
|                 collection = bpy.data.collections.new(name="RA -" + f_name)
 | |
|                 bpy.context.scene.collection.children.link(collection)
 | |
|                 print ("NEW")
 | |
|                 # Move Object to collection
 | |
|                 for col in ob_collections:
 | |
|                     col.objects.unlink(ob)
 | |
|                 collection.objects.link(ob)
 | |
|         else:
 | |
|             collection = ob_collections[0]
 | |
| 
 | |
|         # Create/Location/Name/Status/set RA_Parent/Link Empty and other memery
 | |
|         empty = bpy.data.objects.new( "empty", None )
 | |
|         empty.location = point
 | |
|         empty.name = ".RA - " + ob.name + " - Control Empty"
 | |
|         empty.RA_Status = True
 | |
|         empty.RA_Parent = empty
 | |
|         empty.RA_Name = f_name
 | |
|         empty.RA_Sel_Status = bpy.context.preferences.addons[__name__].preferences.selectable
 | |
|         collection.objects.link(empty)
 | |
|          
 | |
|         # Move object
 | |
|         ob.location[1] = ob.location[1] + ob.RA_Offset
 | |
| 
 | |
|         # Deselect Active Object and select Control Object
 | |
|         ob.select_set(False)
 | |
|         empty.select_set(True)
 | |
| 
 | |
|         # set empty as active object 
 | |
|         bpy.context.view_layer.objects.active = empty
 | |
| 
 | |
|         # create duplicate objects
 | |
|         for o in range(0, empty.RA_ObjNum):
 | |
| 
 | |
|             if o == 0:
 | |
|                 L_Objects.append(ob)
 | |
|             if o != 0:
 | |
|                 L_Objects.append(ob.copy())
 | |
|         # Add Objects To Collection
 | |
|         for index, ob in enumerate(L_Objects):
 | |
|             # create angle variable 
 | |
|             angle = math.radians(360/empty.RA_ObjNum)
 | |
| 
 | |
|            
 | |
|             # rotate object
 | |
|             R = mathutils.Matrix.Rotation(angle * (index), 4, 'Z')
 | |
|             T = mathutils.Matrix.Translation([0, 0, 0])     
 | |
|             M = T @ R @ T.inverted()
 | |
|             ob.location = M @ ob.location
 | |
|             ob.rotation_euler.rotate(M)
 | |
| 
 | |
|             # Parent Object 
 | |
|             ob.parent = empty
 | |
|             empty.matrix_parent_inverse = ob.matrix_world.inverted()
 | |
|             ob.RA_Parent = empty
 | |
| 
 | |
|             # make objects selectable/unselectable
 | |
|             if empty.RA_Sel_Status == True:
 | |
|                 ob.hide_select = False
 | |
|             if empty.RA_Sel_Status == False:
 | |
|                 ob.hide_select = True
 | |
| 
 | |
|             # Change Object Name
 | |
|             ob.name = "RA - " + str(f_name) + " - " + str(index)
 | |
|             # Set RA Status
 | |
|             ob.RA_Status = True
 | |
|             
 | |
|             # Link object
 | |
|             try:
 | |
|                 collection.objects.link(ob)
 | |
|                 #print ("For LINK")
 | |
|             except:
 | |
|                 #print ("PASS Linking object to collection failed")
 | |
|                 pass
 | |
|         bpy.ops.sop.ra_modal('INVOKE_DEFAULT')
 | |
|         
 | |
|         return {'FINISHED'} 
 | |
| #--------------------------------------------------------------------------------------#
 | |
| class RA_Modal(bpy.types.Operator):
 | |
|     # Change Radial Array
 | |
|     bl_idname = "sop.ra_modal"
 | |
|     bl_label = "Radial Array Modal"
 | |
|     bl_options = {"REGISTER", "UNDO", "BLOCKING", "GRAB_CURSOR", "INTERNAL"} #- add later!?  
 | |
| 
 | |
|     first_mouse_x: IntProperty()
 | |
|     I_RA_Offset: FloatProperty()
 | |
|     I_RA_ObjNum: IntProperty()
 | |
|     unq_mode: BoolProperty()
 | |
|     
 | |
| 
 | |
|     def modal(self, context, event):
 | |
|         
 | |
|         # context shortcut
 | |
|         C = context
 | |
|         OB = C.object
 | |
|         context.area.tag_redraw() #?
 | |
|         prefs = bpy.context.preferences.addons[__name__].preferences
 | |
|         # -------------------------------------------------------------#     
 | |
|         #+ change offset        
 | |
|         if event.type == 'MOUSEMOVE' :
 | |
|             delta = self.first_mouse_x - event.mouse_x
 | |
|             if event.shift:
 | |
|                 C.object.RA_Offset = round((self.I_RA_Offset + delta * 0.01))
 | |
|             else:
 | |
|                 C.object.RA_Offset = self.I_RA_Offset + delta * 0.01
 | |
|          # -------------------------------------------------------------#
 | |
|         #+ add/remove Objects      
 | |
|         if event.type == 'WHEELUPMOUSE' and OB.RA_Unq_mode == False:
 | |
|             OB.RA_ObjNum = OB.RA_ObjNum + 1
 | |
|             
 | |
|         if event.type == 'WHEELDOWNMOUSE' and OB.RA_Unq_mode == False:
 | |
|             OB.RA_ObjNum = OB.RA_ObjNum - 1
 | |
|         # -------------------------------------------------------------#
 | |
|         #+ call the tarnslation operator
 | |
|         if event.type == 'G' and event.value == "PRESS":
 | |
|                
 | |
|             C.tool_settings.use_snap = True
 | |
|             C.tool_settings.snap_elements = {'FACE'}
 | |
|             C.tool_settings.use_snap_align_rotation = True
 | |
|            
 | |
|             bpy.ops.transform.translate('INVOKE_DEFAULT')
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self.ra_draw_b, 'WINDOW')
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
 | |
|             return {'FINISHED'}
 | |
|         # -------------------------------------------------------------#
 | |
|         
 | |
|         #+ join objects               
 | |
|         if event.type == 'J' and event.value == "PRESS":
 | |
|             objects = OB.RA_Parent.children
 | |
|             location = OB.RA_Parent.location
 | |
|             cursor_location = bpy.context.scene.cursor.location.copy()
 | |
|             
 | |
|             # deselect objects and select control object
 | |
|             for o in C.selected_objects:
 | |
|                 o.select_set(False)
 | |
|             C.object.RA_Parent.hide_select = False
 | |
|             bpy.context.view_layer.objects.active = C.object.RA_Parent
 | |
|             C.object.RA_Parent.select_set(True)
 | |
|             
 | |
|             # Delete control object 
 | |
|             bpy.ops.object.delete()
 | |
| 
 | |
|             for ob in objects:
 | |
|                 ob.hide_select = False
 | |
|                 ob.select_set(True)
 | |
|             bpy.context.view_layer.objects.active = objects[0]
 | |
|             
 | |
|                       
 | |
|             bpy.context.scene.cursor.location = location
 | |
|             bpy.ops.view3d.snap_selected_to_cursor(use_offset=True)                 
 | |
|             bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')             
 | |
|             bpy.ops.object.join()
 | |
|             bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
 | |
|             bpy.context.scene.cursor.location = cursor_location 
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self.ra_draw_b, 'WINDOW')
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
 | |
|             return {'FINISHED'}
 | |
|         # -------------------------------------------------------------#      
 | |
|         
 | |
|         #+ Reset                   
 | |
|         if event.type == 'R' and event.value == "PRESS":
 | |
|             
 | |
|             objects = OB.RA_Parent.children
 | |
|             name = OB.RA_Parent.RA_Name
 | |
|             # deslect all objects
 | |
|             for o in C.selected_objects:
 | |
|                 o.select_set(False)
 | |
|             # select objects
 | |
|             for ob in objects:
 | |
|                if ob != objects[0]:
 | |
|                     ob.hide_select = False
 | |
|                     ob.select_set(True) 
 | |
|             # delete objects
 | |
|             bpy.ops.object.delete()
 | |
|                 
 | |
|             # select object and clear parent and other memery
 | |
|             objects[0].location = objects[0].RA_Parent.location   
 | |
|             objects[0].RA_Parent.select_set(True)
 | |
|             bpy.ops.object.delete()
 | |
|             objects[0].hide_select = False
 | |
|             bpy.context.view_layer.objects.active = objects[0]
 | |
|             objects[0].select_set(True)
 | |
|             objects[0].parent = None
 | |
|             objects[0].name = name
 | |
|             try:
 | |
|                 del objects[0]["RA_Parent"]
 | |
|                 del objects[0]["RA_Status"]
 | |
|             except:
 | |
|                 pass
 | |
|             
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self.ra_draw_b, 'WINDOW')
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
 | |
|             return {'FINISHED'}
 | |
|         #+ Apply                   
 | |
|         if event.type == 'A' and event.value == "PRESS":
 | |
|             
 | |
|             objects = OB.RA_Parent.children
 | |
|             # deslect all objects
 | |
|             for o in C.selected_objects:
 | |
|                 o.select_set(False)
 | |
|             # select and delete control object
 | |
|             objects[0].RA_Parent.select_set(True)
 | |
|             bpy.ops.object.delete()
 | |
|             # select objects    
 | |
|             for ob in objects:
 | |
|             
 | |
|                ob.hide_select = False
 | |
|                ob.select_set(True)
 | |
|                ob.RA_Status = False
 | |
|                ob.parent = None
 | |
| 
 | |
|             bpy.context.view_layer.objects.active = objects[0]
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self.ra_draw_b, 'WINDOW')
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
 | |
|             return {'FINISHED'}    
 | |
|         #+ Make Unique Mode toggle
 | |
|         if event.type == 'Q' and event.value == "PRESS":
 | |
|             objects = OB.RA_Parent.children
 | |
|             if OB.RA_Unq_mode == True:
 | |
|                 for ob in objects:
 | |
|                     ob.data = objects[0].data
 | |
|                 OB.RA_Unq_mode = False
 | |
|             else:
 | |
|             #* make unique data    
 | |
|                 for ob in objects:
 | |
|                     ob.data = ob.data.copy()
 | |
|                 OB.RA_Unq_mode = True
 | |
|         #+ Selectable toggle
 | |
|         if event.type == 'S' and event.value == "PRESS":
 | |
|             if OB.RA_Sel_Status == True:
 | |
|                 OB.RA_Sel_Status = False
 | |
|             else:
 | |
|                 OB.RA_Sel_Status = True
 | |
|         #+ Help Mode toggle
 | |
|         if event.type == 'H' and event.value == "PRESS":
 | |
|             if prefs.modal_help == True:
 | |
|                 prefs.modal_help = False
 | |
|             else:
 | |
|                 prefs.modal_help = True
 | |
|         # -------------------------------------------------------------# 
 | |
|         #+ Finish/Cancel Modal        
 | |
|         elif event.type == 'LEFTMOUSE':
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self.ra_draw_b, 'WINDOW')
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
 | |
|             return {'FINISHED'}
 | |
| 
 | |
|         elif event.type in {'RIGHTMOUSE', 'ESC'}:
 | |
|             C.object.RA_Offset = self.I_RA_Offset
 | |
|             C.object.RA_ObjNum = self.I_RA_ObjNum
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self.ra_draw_b, 'WINDOW')
 | |
|             bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
 | |
|             return {'CANCELLED'}
 | |
| 
 | |
|         return {'RUNNING_MODAL'}
 | |
| 
 | |
|     def invoke(self, context, event):
 | |
|         # context shortcut
 | |
|         C = context
 | |
|         if  C.object.RA_Status == True:
 | |
|             for o in C.selected_objects:
 | |
|                 o.select_set(False)
 | |
|             bpy.context.view_layer.objects.active = C.object.RA_Parent
 | |
|             C.object.RA_Parent.select_set(True)
 | |
|            
 | |
|             
 | |
|         
 | |
|         if C.object:
 | |
|             # set initial Variable values
 | |
|             self.first_mouse_x = event.mouse_x
 | |
|             self.I_RA_Offset = C.object.RA_Offset
 | |
|             self.I_RA_ObjNum = C.object.RA_ObjNum
 | |
|             self.unq_mode = C.object.RA_Unq_mode
 | |
|             self.prefs = bpy.context.preferences.addons[__name__].preferences
 | |
|             ###-------------------------------------------###
 | |
|             args = (self, context, self.prefs)
 | |
|             
 | |
|             
 | |
|             self.ra_draw_b = bpy.types.SpaceView3D.draw_handler_add(RA_draw_B, args, 'WINDOW', 'POST_PIXEL')
 | |
|             self._handle = bpy.types.SpaceView3D.draw_handler_add(RA_modal_Draw, args, 'WINDOW', 'POST_PIXEL')
 | |
|             
 | |
|             self.mouse_path = []
 | |
| 
 | |
|             context.window_manager.modal_handler_add(self)
 | |
|             return {'RUNNING_MODAL'}
 | |
|         else:
 | |
|             self.report({'WARNING'}, "No active object, could not finish")
 | |
|             return {'CANCELLED'}
 | |
| #--------------------------------------------------------------------------------------#
 | |
| class RA_Prefs(bpy.types.AddonPreferences):
 | |
|     bl_idname = __name__
 | |
|     # here you define the addons customizable props
 | |
|     offset:     bpy.props.FloatProperty(default=5)
 | |
|     objnum:     bpy.props.IntProperty(default=6)
 | |
|     selectable: bpy.props.BoolProperty(default= True, description="False = Only Control Object is selectable")
 | |
|     modal_help: bpy.props.BoolProperty(default= False, description="True = Display Help text in modal")
 | |
|     col_toggle: bpy.props.BoolProperty(default= False, description="True = Create New Collection")
 | |
|     # here you specify how they are drawn
 | |
|     def draw(self, context):
 | |
|         layout = self.layout
 | |
|         box = layout.box()
 | |
|         split = box.split()
 | |
|         col = split.column() 
 | |
|         # Layout ---------------------------------------------------------------- #
 | |
|         col.label(text="Default Values:")
 | |
|         col.prop(self, "offset",text="Default Offset")
 | |
|         col.prop(self, "objnum",text="Default Count")
 | |
|         col.prop(self, "selectable",text="Selectable")
 | |
|         col.prop(self, "modal_help",text="Modal Help")
 | |
|         col.label(text ="Options:")
 | |
|         col.prop(self, "col_toggle",text="Create New Collection")
 | |
|         col.label(text="Keymap:")
 | |
|         
 | |
|         
 | |
|         wm = bpy.context.window_manager
 | |
|         kc = wm.keyconfigs.user
 | |
|         km = kc.keymaps['Object Mode']
 | |
|         #kmi = km.keymap_items[0]
 | |
|         kmi = get_hotkey_entry_item(km, 'sop.r_array', 'sop.r_array')
 | |
|         
 | |
|         if addon_keymaps:
 | |
|             km = addon_keymaps[0].active()
 | |
|             col.context_pointer_set("keymap", km)
 | |
|             rna_keymap_ui.draw_kmi([], kc, km, kmi, col, 0)
 | |
| 
 | |
|     
 | |
| 
 | |
| def get_addon_preferences():
 | |
|     ''' quick wrapper for referencing addon preferences '''
 | |
|     addon_preferences = bpy.context.user_preferences.addons[__name__].preferences
 | |
|     return addon_preferences
 | |
| def get_hotkey_entry_item(km, kmi_name, kmi_value):
 | |
|     '''
 | |
|     returns hotkey of specific type, with specific properties.name (keymap is not a dict, so referencing by keys is not enough
 | |
|     if there are multiple hotkeys!)
 | |
|     '''
 | |
|     for i, km_item in enumerate(km.keymap_items):
 | |
|         if km.keymap_items.keys()[i] == kmi_name:
 | |
|             if km.keymap_items[i].idname == kmi_value:
 | |
|                 return km_item
 | |
|     return None 
 | |
| 
 | |
| classes = (
 | |
|     RA_Prefs,
 | |
|     R_Array,
 | |
|     RA_Modal,
 | |
| )
 | |
| 
 | |
| 
 | |
| def register():
 | |
|     print ("----------------------------------")
 | |
|     print ("S.Ops Init")
 | |
|     print ("----------------------------------")
 | |
|     
 | |
|     #+ add hotkey
 | |
|     add_hotkey()
 | |
| 
 | |
|     from bpy.utils import register_class
 | |
|     for cls in classes:
 | |
|         register_class(cls)
 | |
|     # Init Props 
 | |
|     
 | |
|     bpy.types.Object.RA_Parent = bpy.props.PointerProperty(
 | |
|     name="RA Parent",
 | |
|     description="RA Parent Object Reference",
 | |
|     type=bpy.types.Object
 | |
|     )
 | |
| 
 | |
|     bpy.types.Object.RA_ObjNum = bpy.props.IntProperty(
 | |
|     name="RA ObjNum",
 | |
|     description="RA Object Number",
 | |
|     default = bpy.context.preferences.addons[__name__].preferences.objnum,
 | |
|     min = 1,
 | |
|     update = RA_Update_ObjNum
 | |
|     )
 | |
|    
 | |
|     bpy.types.Object.RA_Offset = bpy.props.FloatProperty(
 | |
|     name="Offset",
 | |
|     description="Radial Array Offset",
 | |
|     default = bpy.context.preferences.addons[__name__].preferences.offset,
 | |
|     update = RA_Update_Offset
 | |
|     )   
 | |
|        
 | |
|     bpy.types.Object.RA_Status = bpy.props.BoolProperty(
 | |
|     name="Status",
 | |
|     description="Radial Array Status",
 | |
|     default = False
 | |
|     )
 | |
|     
 | |
|     bpy.types.Object.RA_Sel_Status = bpy.props.BoolProperty(
 | |
|     name="Selectable",
 | |
|     description="False = Only Control Object is selectable",
 | |
|     default = bpy.context.preferences.addons[__name__].preferences.selectable,
 | |
|     update = RA_Update_Sel_Status
 | |
|     )
 | |
| 
 | |
|     bpy.types.Object.RA_Unq_mode = bpy.props.BoolProperty(
 | |
|     name="Unique Mode",
 | |
|     description="True = all objects have a unique data block(Disables Count in Modal)",
 | |
|     default = False
 | |
|     )
 | |
|     bpy.types.Object.RA_Name = bpy.props.StringProperty(
 | |
|     name="Name",
 | |
|     description="Radial Array Name",
 | |
|     default = "Nameing Error"
 | |
|     )
 | |
|     
 | |
|    
 | |
|     print ("----------------------------------")
 | |
|     print ("S.Ops Register End")
 | |
|     print ("----------------------------------") 
 | |
| 
 | |
| 
 | |
| def unregister():
 | |
|     print ("----------------------------------")
 | |
|     print ("S.Ops unRegister Start")
 | |
|     print ("----------------------------------") 
 | |
|     #+ remove hotkey
 | |
|     remove_hotkey()
 | |
|     
 | |
|     from bpy.utils import unregister_class
 | |
|     for cls in classes:
 | |
|         unregister_class(cls)
 | |
|   
 | |
| 
 | |
|  
 | |
|    
 | |
|     
 | |
|     print ("----------------------------------")
 | |
|     print ("S.Ops unRegister End")
 | |
|     print ("----------------------------------") 
 | |
|   
 | |
| if __name__ == "__main__":
 | |
|     register()
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |