blender_io_export_psx_mesh/3dcam-engine-helper.py

186 lines
7.5 KiB
Python

import bpy
from bpy.props import IntProperty, StringProperty, PointerProperty, BoolProperty
from bpy.types import PropertyGroup
from bpy.app.handlers import persistent
bl_info = {
"name": "3Dcam engine custom properties helper",
"author": "Schnappy",
"blender": (2,79,0),
"category": "Property helper",
"version": (0,0,1),
"location": "3D view > Object",
"location": "Properties panel > Data",
"description": "Set/Unset/Copy flags easily"
}
# Based on https://blog.hamaluik.ca/posts/dynamic-blender-properties by Kenton Hamaluik
bpy.propertyGroupLayouts = {
"Flags": [
{ "name": "isAnim", "type": "boolean" },
{ "name": "isProp", "type": "boolean" },
{ "name": "isRigidBody", "type": "boolean" },
{ "name": "isStaticBody","type": "boolean" },
{ "name": "isRound", "type": "boolean" },
{ "name": "isPrism", "type": "boolean" },
{ "name": "isActor", "type": "boolean" },
{ "name": "isLevel", "type": "boolean" },
{ "name": "isWall", "type": "boolean" },
{ "name": "isBG", "type": "boolean" },
{ "name": "isSprite", "type": "boolean" },
{ "name": "isLerp", "type": "boolean" },
{ "name": "isXA", "type": "boolean" }
],
"Others": [
{ "name": "mass", "type": "int" }
]
}
# store keymaps here to access after registration
addon_keymaps = []
bpy.samplePropertyGroups = {}
last_selection = []
store_att_names = []
def getActiveObjProps(active_obj):
object_custom_props = [prop for prop in store_att_names if prop in active_obj.data]
return object_custom_props
def menu_func(self, context):
self.layout.operator(copyCustomPropToSelection.bl_idname)
def copyCustomProps(context):
# get active object
active_obj = bpy.context.active_object
# get active object's custom properties
active_obj_custom_props = getActiveObjProps(active_obj)
# get selected objects
selection = bpy.context.selected_objects
# discriminates against active_obj
selection = [obj for obj in selection if obj != active_obj]
# for each object that's not active object, add custom prop
for obj in selection:
for prop in active_obj_custom_props:
obj.data[prop] = active_obj.data[prop]
def updateCustomProps(self, context):
global last_selection
global store_att_names
for att in store_att_names:
if (att in last_selection.Flags): # and last_selection.Flags[att] :
if ( att not in last_selection.data or
last_selection.Flags[att] != last_selection.data[att] ):
last_selection.data[att] = last_selection.Flags[att]
if (att in last_selection.Others):
if ( att not in last_selection.data or
last_selection.Others[att] != last_selection.data[att] ):
last_selection.data[att] = last_selection.Others[att]
@persistent
def selection_callback(scene):
global last_selection
global store_att_names
if bpy.context.active_object != last_selection:
last_selection = bpy.context.active_object
for groupName, attributeDefinitions in bpy.propertyGroupLayouts.items():
# build the attribute dictionary for this group
attributes = {}
for attributeDefinition in attributeDefinitions:
attType = attributeDefinition['type']
attName = attributeDefinition['name']
store_att_names.append(attName)
value = 0
if last_selection:
if attName in last_selection.data:
value = last_selection.data[attName]
if attType == 'boolean':
attributes[attName] = BoolProperty(name=attName, default=value, update=updateCustomProps )
elif attType == 'int':
attributes[attName] = IntProperty(name=attName, default=value, update=updateCustomProps)
elif attType == 'string':
attributes[attName] = StringProperty(name=attName, default=value, update=updateCustomProps)
else:
raise TypeError('Unsupported type (%s) for %s on %s!' % (attType, attName, groupName))
# now build the property group class
propertyGroupClass = type(groupName, (PropertyGroup,), attributes)
# register it with Blender
bpy.utils.register_class(propertyGroupClass)
# apply it to all Objects
setattr(bpy.types.Object, groupName, PointerProperty(type=propertyGroupClass))
# store it for later
bpy.samplePropertyGroups[groupName] = propertyGroupClass
class copyCustomPropToSelection(bpy.types.Operator):
"""Copy last selected object's custom properties to other selected objects"""
bl_idname = "object.copy_custom_properties"
bl_label = "Copy custom properties to selection"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
copyCustomProps(context)
return {'FINISHED'}
class customPropsPanel(bpy.types.Panel):
bl_label = "3D Cam engine custom properties"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
def draw(self, context):
layout = self.layout
obj = context.object
# use our layout definition to dynamically create our panel items
for groupName, attributeDefinitions in sorted(bpy.propertyGroupLayouts.items()):
# get the instance of our group
# dynamic equivalent of `obj.samplePropertyGroup` from before
propertyGroup = getattr(obj, groupName)
# start laying this group out
col = layout.column_flow(columns=2)
col.label(groupName)
i = 0
# loop through all the attributes and show them
for attributeDefinition in attributeDefinitions:
if i == len(attributeDefinitions)/2:
col.label("")
col.prop(propertyGroup, attributeDefinition["name"])
i += 1
# draw a separation between groups
layout.separator()
def register():
# register the panel class
bpy.utils.register_class(customPropsPanel)
bpy.app.handlers.scene_update_post.clear()
bpy.app.handlers.scene_update_post.append(selection_callback)
# copy helper
bpy.utils.register_class(copyCustomPropToSelection)
bpy.types.VIEW3D_MT_object.append(menu_func)
# shortcut
wm = bpy.context.window_manager
km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
kmi = km.keymap_items.new(copyCustomPropToSelection.bl_idname, 'P', 'PRESS', ctrl=False, shift=True)
# ~ kmi.properties.total = 4
addon_keymaps.append((km, kmi))
def unregister():
# unregister the panel class
bpy.utils.unregister_class(customPropsPanel)
# unregister our components
try:
for key, value in bpy.samplePropertyGroups.items():
delattr(bpy.types.Object, key)
bpy.utils.unregister_class(value)
except UnboundLocalError:
pass
bpy.samplePropertyGroups = {}
# copy helper
bpy.utils.unregister_class(copyCustomPropToSelection)
bpy.types.VIEW3D_MT_object.remove(menu_func)
# handle the keymap
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
if __name__ == "__main__":
register()