From 313d24bbc8809927a10866c332b62aa8aa4c0393 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 12 Jun 2025 22:35:21 +0000 Subject: [PATCH] t3du - Camera Render Filter --- .../blender/lnx/props_camera_render_filter.py | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 leenkx/blender/lnx/props_camera_render_filter.py diff --git a/leenkx/blender/lnx/props_camera_render_filter.py b/leenkx/blender/lnx/props_camera_render_filter.py new file mode 100644 index 0000000..14558b4 --- /dev/null +++ b/leenkx/blender/lnx/props_camera_render_filter.py @@ -0,0 +1,141 @@ +import bpy +from bpy.props import * + +class LNX_UL_CameraList(bpy.types.UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): + layout.prop_search(item, "lnx_camera_object_ptr", bpy.data, "objects", text="", icon='VIEW_CAMERA') + +class LNX_CameraListItem(bpy.types.PropertyGroup): + lnx_camera_object_ptr: bpy.props.PointerProperty( + type=bpy.types.Object, + name="Camera Object", + poll=lambda self, obj_to_check: obj_to_check.type == 'CAMERA' and \ + (bpy.context.object is None or \ + not hasattr(bpy.context.object, 'lnx_camera_list') or \ + (obj_to_check.name not in [ + item.lnx_camera_object_ptr.name + for item in bpy.context.object.lnx_camera_list + if item.lnx_camera_object_ptr and item != self + ])) + ) + +class LNX_PT_LeenkxCameraRenderFilter(bpy.types.Panel): + bl_label = "Leenkx Camera Render Filter" + bl_idname = "LNX_PT_LeenkxCameraRenderFilter" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "data" + + @classmethod + def poll(cls, context): + return context.object is not None and context.object.type == 'MESH' + + def draw(self, context): + layout = self.layout + obj = context.object + + row = layout.row() + + col = row.column() + col.template_list( + "LNX_UL_CameraList", + "", + obj, + "lnx_camera_list", + obj, + "lnx_active_camera_index", + rows=5 + ) + + col = row.column(align=True) + col.operator("lnx.add_camera", icon='ADD', text="") + + if obj.lnx_camera_list and obj.lnx_active_camera_index >= 0 and obj.lnx_active_camera_index < len(obj.lnx_camera_list): + op_remove = col.operator("lnx.remove_camera", icon='REMOVE', text="") + op_remove.lnx_index = obj.lnx_active_camera_index + + op_up = col.operator("lnx.move_camera", icon='TRIA_UP', text="") + op_up.lnx_index = obj.lnx_active_camera_index + op_up.direction = 'UP' + + op_down = col.operator("lnx.move_camera", icon='TRIA_DOWN', text="") + op_down.lnx_index = obj.lnx_active_camera_index + op_down.direction = 'DOWN' + +class LNX_OT_AddCamera(bpy.types.Operator): + bl_idname = "lnx.add_camera" + bl_label = "Add Camera" + + def execute(self, context): + obj = context.object + + new_item = obj.lnx_camera_list.add() + obj.lnx_active_camera_index = len(obj.lnx_camera_list) - 1 + + return {'FINISHED'} + +class LNX_OT_RemoveCamera(bpy.types.Operator): + bl_idname = "lnx.remove_camera" + bl_label = "Remove Camera" + + lnx_index: bpy.props.IntProperty() + + def execute(self, context): + obj = context.object + if self.lnx_index < len(obj.lnx_camera_list): + obj.lnx_camera_list.remove(self.lnx_index) + if obj.lnx_active_camera_index >= len(obj.lnx_camera_list): + obj.lnx_active_camera_index = len(obj.lnx_camera_list) - 1 + return {'FINISHED'} + +class LNX_OT_MoveCamera(bpy.types.Operator): + bl_idname = "lnx.move_camera" + bl_label = "Move Camera" + + lnx_index: bpy.props.IntProperty() + direction: bpy.props.EnumProperty( + items=[('UP', "Up", "Move camera up"), + ('DOWN', "Down", "Move camera down")], + default='UP' + ) + + def execute(self, context): + obj = context.object + camera_list = obj.lnx_camera_list + target_index = -1 + + if self.direction == 'UP': + if self.lnx_index > 0: + target_index = self.lnx_index - 1 + elif self.direction == 'DOWN': + if self.lnx_index < len(camera_list) - 1: + target_index = self.lnx_index + 1 + + if target_index != -1: + camera_list.move(self.lnx_index, target_index) + obj.lnx_active_camera_index = target_index + return {'FINISHED'} + +def register(): + bpy.utils.register_class(LNX_UL_CameraList) + bpy.utils.register_class(LNX_CameraListItem) + bpy.utils.register_class(LNX_PT_LeenkxCameraRenderFilter) + bpy.utils.register_class(LNX_OT_AddCamera) + bpy.utils.register_class(LNX_OT_RemoveCamera) + bpy.utils.register_class(LNX_OT_MoveCamera) + + bpy.types.Object.lnx_camera_list = bpy.props.CollectionProperty(type=LNX_CameraListItem) + bpy.types.Object.lnx_active_camera_index = bpy.props.IntProperty(name="Active Camera Index", default=-1) + +def unregister(): + bpy.utils.unregister_class(LNX_UL_CameraList) + bpy.utils.unregister_class(LNX_CameraListItem) + bpy.utils.unregister_class(LNX_PT_LeenkxCameraRenderFilter) + bpy.utils.unregister_class(LNX_OT_AddCamera) + bpy.utils.unregister_class(LNX_OT_RemoveCamera) + bpy.utils.unregister_class(LNX_OT_MoveCamera) + + if hasattr(bpy.types.Object, "lnx_camera_list"): + del bpy.types.Object.lnx_camera_list + if hasattr(bpy.types.Object, "lnx_active_camera_index"): + del bpy.types.Object.lnx_active_camera_index \ No newline at end of file