forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			161 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			161 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | import bpy | ||
|  | from bpy.props import * | ||
|  | 
 | ||
|  | __all__ = ['LnxTraitPropWarning', 'LnxTraitPropListItem', 'LNX_UL_PropList'] | ||
|  | 
 | ||
|  | PROP_TYPE_ICONS = { | ||
|  |     "String": "SORTALPHA", | ||
|  |     "Int": "CHECKBOX_DEHLT", | ||
|  |     "Float": "RADIOBUT_OFF", | ||
|  |     "Bool": "CHECKMARK", | ||
|  |     "Vec2": "ORIENTATION_VIEW", | ||
|  |     "Vec3": "ORIENTATION_GLOBAL", | ||
|  |     "Vec4": "MESH_ICOSPHERE", | ||
|  |     "Object": "OBJECT_DATA", | ||
|  |     "CameraObject": "CAMERA_DATA", | ||
|  |     "LightObject": "LIGHT_DATA", | ||
|  |     "MeshObject": "MESH_DATA", | ||
|  |     "SpeakerObject": "OUTLINER_DATA_SPEAKER" | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | def filter_objects(item, b_object): | ||
|  |     if item.type == "CameraObject": | ||
|  |         return b_object.type == "CAMERA" | ||
|  |     if item.type == "LightObject": | ||
|  |         return b_object.type == "LIGHT" | ||
|  |     if item.type == "MeshObject": | ||
|  |         return b_object.type == "MESH" | ||
|  |     if item.type == "SpeakerObject": | ||
|  |         return b_object.type == "SPEAKER" | ||
|  | 
 | ||
|  |     if item.type == "Object": | ||
|  |         return True | ||
|  | 
 | ||
|  | 
 | ||
|  | class LnxTraitPropWarning(bpy.types.PropertyGroup): | ||
|  |     propName: StringProperty(name="Property Name") | ||
|  |     warning: StringProperty(name="Warning") | ||
|  | 
 | ||
|  | 
 | ||
|  | class LnxTraitPropListItem(bpy.types.PropertyGroup): | ||
|  |     """Group of properties representing an item in the list.""" | ||
|  |     name: StringProperty( | ||
|  |         name="Name", | ||
|  |         description="The name of this property", | ||
|  |         default="Untitled") | ||
|  | 
 | ||
|  |     type: EnumProperty( | ||
|  |         items=( | ||
|  |             # (Haxe Type, Display Name, Description) | ||
|  |             ("String", "String", "String Type"), | ||
|  |             ("Int", "Integer", "Integer Type"), | ||
|  |             ("Float", "Float", "Float Type"), | ||
|  |             ("Bool", "Boolean", "Boolean Type"), | ||
|  |             ("Vec2", "Vec2", "2D Vector Type"), | ||
|  |             ("Vec3", "Vec3", "3D Vector Type"), | ||
|  |             ("Vec4", "Vec4", "4D Vector Type"), | ||
|  |             ("Object", "Object", "Object Type"), | ||
|  |             ("CameraObject", "Camera Object", "Camera Object Type"), | ||
|  |             ("LightObject", "Light Object", "Light Object Type"), | ||
|  |             ("MeshObject", "Mesh Object", "Mesh Object Type"), | ||
|  |             ("SpeakerObject", "Speaker Object", "Speaker Object Type")), | ||
|  |         name="Type", | ||
|  |         description="The type of this property", | ||
|  |         default="String", | ||
|  |         override={"LIBRARY_OVERRIDABLE"} | ||
|  |     ) | ||
|  | 
 | ||
|  |     # === VALUES === | ||
|  |     value_string: StringProperty(name="Value", default="", override={"LIBRARY_OVERRIDABLE"}) | ||
|  |     value_int: IntProperty(name="Value", default=0, override={"LIBRARY_OVERRIDABLE"}) | ||
|  |     value_float: FloatProperty(name="Value", default=0.0, override={"LIBRARY_OVERRIDABLE"}) | ||
|  |     value_bool: BoolProperty(name="Value", default=False, override={"LIBRARY_OVERRIDABLE"}) | ||
|  |     value_vec2: FloatVectorProperty(name="Value", size=2, override={"LIBRARY_OVERRIDABLE"}) | ||
|  |     value_vec3: FloatVectorProperty(name="Value", size=3, override={"LIBRARY_OVERRIDABLE"}) | ||
|  |     value_vec4: FloatVectorProperty(name="Value", size=4, override={"LIBRARY_OVERRIDABLE"}) | ||
|  |     value_object: PointerProperty( | ||
|  |         name="Value", type=bpy.types.Object, poll=filter_objects, | ||
|  |         override={"LIBRARY_OVERRIDABLE"} | ||
|  |     ) | ||
|  | 
 | ||
|  |     def set_value(self, val): | ||
|  |         # Would require way too much effort, so it's out of scope here. | ||
|  |         if self.type.endswith("Object"): | ||
|  |             return | ||
|  | 
 | ||
|  |         if self.type == "Int": | ||
|  |             self.value_int = int(val) | ||
|  |         elif self.type == "Float": | ||
|  |             self.value_float = float(val) | ||
|  |         elif self.type == "Bool": | ||
|  |             self.value_bool = val == "true" | ||
|  |         elif self.type in ("Vec2", "Vec3", "Vec4"): | ||
|  |             if isinstance(val, str): | ||
|  |                 dimensions = int(self.type[-1]) | ||
|  | 
 | ||
|  |                 # Parse "new VecX(...)" | ||
|  |                 val = val.split("(")[1].split(")")[0].split(",") | ||
|  |                 val = [value.strip() for value in val] | ||
|  | 
 | ||
|  |                 # new VecX() without parameters | ||
|  |                 if len(val) == 1 and val[0] == "": | ||
|  |                     # Use default value | ||
|  |                     return | ||
|  | 
 | ||
|  |                 # new VecX() with less parameters than its dimensions | ||
|  |                 while len(val) < dimensions: | ||
|  |                     val.append(0.0) | ||
|  | 
 | ||
|  |                 val = [float(value) for value in val] | ||
|  | 
 | ||
|  |             setattr(self, "value_" + self.type.lower(), val) | ||
|  |         else: | ||
|  |             self.value_string = str(val) | ||
|  | 
 | ||
|  |     def get_value(self): | ||
|  |         if self.type == "Int": | ||
|  |             return self.value_int | ||
|  |         if self.type == "Float": | ||
|  |             return self.value_float | ||
|  |         if self.type == "Bool": | ||
|  |             return self.value_bool | ||
|  |         if self.type in ("Vec2", "Vec3", "Vec4"): | ||
|  |             return list(getattr(self, "value_" + self.type.lower())) | ||
|  |         if self.type.endswith("Object"): | ||
|  |             if self.value_object is not None: | ||
|  |                 return self.value_object.name | ||
|  |             return "" | ||
|  | 
 | ||
|  |         return self.value_string | ||
|  | 
 | ||
|  | 
 | ||
|  | class LNX_UL_PropList(bpy.types.UIList): | ||
|  |     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): | ||
|  |         item_value_ref = "value_" + item.type.lower() | ||
|  |         custom_icon = PROP_TYPE_ICONS[item.type] | ||
|  | 
 | ||
|  |         sp = layout.split(factor=0.3) | ||
|  |         sp.label(text=item.type, icon=custom_icon) | ||
|  |         sp = sp.split(factor=0.6) | ||
|  |         sp.label(text=item.name) | ||
|  | 
 | ||
|  |         # Make sure your code supports all 3 layout types | ||
|  |         if self.layout_type in {'DEFAULT', 'COMPACT'}: | ||
|  |             if item.type.endswith("Object"): | ||
|  |                 sp.prop_search(item, "value_object", context.scene, "objects", text="", icon=custom_icon) | ||
|  |             else: | ||
|  |                 use_emboss = item.type in ("Bool", "String") | ||
|  |                 sp.prop(item, item_value_ref, text="", emboss=use_emboss) | ||
|  | 
 | ||
|  |         elif self.layout_type in {'GRID'}: | ||
|  |             layout.alignment = 'CENTER' | ||
|  | 
 | ||
|  | 
 | ||
|  | __REG_CLASSES = ( | ||
|  |     LnxTraitPropWarning, | ||
|  |     LnxTraitPropListItem, | ||
|  |     LNX_UL_PropList, | ||
|  | ) | ||
|  | register, unregister = bpy.utils.register_classes_factory(__REG_CLASSES) |