123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- # ##### BEGIN GPL LICENSE BLOCK #####
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software Foundation,
- # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #
- # ##### END GPL LICENSE BLOCK #####
- # <pep8 compliant>
- from bl_ui.properties_animviz import (
- MotionPathButtonsPanel,
- MotionPathButtonsPanel_display,
- )
- import bpy
- from bpy.types import Panel, Menu
- from rna_prop_ui import PropertyPanel
- class ObjectButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "object"
- class OBJECT_PT_context_object(ObjectButtonsPanel, Panel):
- bl_label = ""
- bl_options = {'HIDE_HEADER'}
- def draw(self, context):
- layout = self.layout
- space = context.space_data
- if space.use_pin_id:
- layout.template_ID(space, "pin_id")
- else:
- row = layout.row()
- row.template_ID(context.view_layer.objects, "active", filter='AVAILABLE')
- class OBJECT_PT_transform(ObjectButtonsPanel, Panel):
- bl_label = "Transform"
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- ob = context.object
- col = flow.column()
- row = col.row(align=True)
- row.prop(ob, "location")
- row.use_property_decorate = False
- row.prop(ob, "lock_location", text="", emboss=False, icon='DECORATE_UNLOCKED')
- rotation_mode = ob.rotation_mode
- if rotation_mode == 'QUATERNION':
- col = flow.column()
- row = col.row(align=True)
- row.prop(ob, "rotation_quaternion", text="Rotation")
- sub = row.column(align=True)
- sub.use_property_decorate = False
- sub.prop(ob, "lock_rotation_w", text="", emboss=False, icon='DECORATE_UNLOCKED')
- sub.prop(ob, "lock_rotation", text="", emboss=False, icon='DECORATE_UNLOCKED')
- elif rotation_mode == 'AXIS_ANGLE':
- col = flow.column()
- row = col.row(align=True)
- row.prop(ob, "rotation_axis_angle", text="Rotation")
- sub = row.column(align=True)
- sub.use_property_decorate = False
- sub.prop(ob, "lock_rotation_w", text="", emboss=False, icon='DECORATE_UNLOCKED')
- sub.prop(ob, "lock_rotation", text="", emboss=False, icon='DECORATE_UNLOCKED')
- else:
- col = flow.column()
- row = col.row(align=True)
- row.prop(ob, "rotation_euler", text="Rotation")
- row.use_property_decorate = False
- row.prop(ob, "lock_rotation", text="", emboss=False, icon='DECORATE_UNLOCKED')
- col = flow.column()
- row = col.row(align=True)
- row.prop(ob, "scale")
- row.use_property_decorate = False
- row.prop(ob, "lock_scale", text="", emboss=False, icon='DECORATE_UNLOCKED')
- row = layout.row(align=True)
- row.prop(ob, "rotation_mode")
- row.label(text="", icon='BLANK1')
- class OBJECT_PT_delta_transform(ObjectButtonsPanel, Panel):
- bl_label = "Delta Transform"
- bl_parent_id = "OBJECT_PT_transform"
- bl_options = {'DEFAULT_CLOSED'}
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=True, align=False)
- ob = context.object
- col = flow.column()
- col.prop(ob, "delta_location")
- col = flow.column()
- rotation_mode = ob.rotation_mode
- if rotation_mode == 'QUATERNION':
- col.prop(ob, "delta_rotation_quaternion", text="Rotation")
- elif rotation_mode == 'AXIS_ANGLE':
- col.label(text="Not for Axis-Angle")
- else:
- col.prop(ob, "delta_rotation_euler", text="Delta Rotation")
- col = flow.column()
- col.prop(ob, "delta_scale")
- class OBJECT_PT_relations(ObjectButtonsPanel, Panel):
- bl_label = "Relations"
- bl_options = {'DEFAULT_CLOSED'}
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- ob = context.object
- col = flow.column()
- col.prop(ob, "parent")
- sub = col.column()
- sub.prop(ob, "parent_type")
- parent = ob.parent
- if parent and ob.parent_type == 'BONE' and parent.type == 'ARMATURE':
- sub.prop_search(ob, "parent_bone", parent.data, "bones")
- sub.active = (parent is not None)
- col.separator()
- col = flow.column()
- col.prop(ob, "track_axis", text="Tracking Axis")
- col.prop(ob, "up_axis", text="Up Axis")
- col.separator()
- col = flow.column()
- col.prop(ob, "pass_index")
- class COLLECTION_MT_context_menu(Menu):
- bl_label = "Collection Specials"
- def draw(self, _context):
- layout = self.layout
- layout.operator("object.collection_unlink", icon='X')
- layout.operator("object.collection_objects_select")
- layout.operator("object.instance_offset_from_cursor")
- class OBJECT_PT_collections(ObjectButtonsPanel, Panel):
- bl_label = "Collections"
- bl_options = {'DEFAULT_CLOSED'}
- def draw(self, context):
- layout = self.layout
- obj = context.object
- row = layout.row(align=True)
- if bpy.data.collections:
- row.operator("object.collection_link", text="Add to Collection")
- else:
- row.operator("object.collection_add", text="Add to Collection")
- row.operator("object.collection_add", text="", icon='ADD')
- obj_name = obj.name
- for collection in bpy.data.collections:
- # XXX this is slow and stupid!, we need 2 checks, one that's fast
- # and another that we can be sure its not a name collision
- # from linked library data
- collection_objects = collection.objects
- if obj_name in collection.objects and obj in collection_objects[:]:
- col = layout.column(align=True)
- col.context_pointer_set("collection", collection)
- row = col.box().row()
- row.prop(collection, "name", text="")
- row.operator("object.collection_remove", text="", icon='X', emboss=False)
- row.menu("COLLECTION_MT_context_menu", icon='DOWNARROW_HLT', text="")
- row = col.box().row()
- row.prop(collection, "instance_offset", text="")
- class OBJECT_PT_display(ObjectButtonsPanel, Panel):
- bl_label = "Viewport Display"
- bl_options = {'DEFAULT_CLOSED'}
- bl_order = 10
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- obj = context.object
- obj_type = obj.type
- is_geometry = (obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'})
- is_wire = (obj_type in {'CAMERA', 'EMPTY'})
- is_empty_image = (obj_type == 'EMPTY' and obj.empty_display_type == 'IMAGE')
- is_dupli = (obj.instance_type != 'NONE')
- is_gpencil = (obj_type == 'GPENCIL')
- col = flow.column()
- col.prop(obj, "show_name", text="Name")
- col = flow.column()
- col.prop(obj, "show_axis", text="Axis")
- # Makes no sense for cameras, armatures, etc.!
- # but these settings do apply to dupli instances
- if is_geometry or is_dupli:
- col = flow.column()
- col.prop(obj, "show_wire", text="Wireframe")
- if obj_type == 'MESH' or is_dupli:
- col = flow.column()
- col.prop(obj, "show_all_edges", text="All Edges")
- col = flow.column()
- if is_geometry:
- col.prop(obj, "show_texture_space", text="Texture Space")
- col = flow.column()
- col.prop(obj.display, "show_shadows", text="Shadow")
- col = flow.column()
- col.prop(obj, "show_in_front", text="In Front")
- # if obj_type == 'MESH' or is_empty_image:
- # col.prop(obj, "show_transparent", text="Transparency")
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
- if is_wire:
- # wire objects only use the max. display type for duplis
- col.active = is_dupli
- col.prop(obj, "display_type", text="Display As")
- if is_geometry or is_dupli or is_empty_image or is_gpencil:
- # Only useful with object having faces/materials...
- col = flow.column()
- col.prop(obj, "color")
- class OBJECT_PT_display_bounds(ObjectButtonsPanel, Panel):
- bl_label = "Bounds"
- bl_parent_id = "OBJECT_PT_display"
- bl_options = {'DEFAULT_CLOSED'}
- def draw_header(self, context):
- obj = context.object
- self.layout.prop(obj, "show_bounds", text="")
- def draw(self, context):
- layout = self.layout
- obj = context.object
- layout.use_property_split = True
- layout.active = obj.show_bounds or (obj.display_type == 'BOUNDS')
- layout.prop(obj, "display_bounds_type", text="Shape")
- class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
- bl_label = "Instancing"
- bl_options = {'DEFAULT_CLOSED'}
- def draw(self, context):
- layout = self.layout
- ob = context.object
- row = layout.row()
- row.prop(ob, "instance_type", expand=True)
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- if ob.instance_type == 'VERTS':
- layout.prop(ob, "use_instance_vertices_rotation", text="Align to Vertex Normal")
- elif ob.instance_type == 'COLLECTION':
- col = layout.column()
- col.prop(ob, "instance_collection", text="Collection")
- if ob.instance_type != 'NONE' or ob.particle_systems:
- col = flow.column(align=True)
- col.prop(ob, "show_instancer_for_viewport")
- col.prop(ob, "show_instancer_for_render")
- class OBJECT_PT_instancing_size(ObjectButtonsPanel, Panel):
- bl_label = "Scale by Face Size"
- bl_parent_id = "OBJECT_PT_instancing"
- @classmethod
- def poll(cls, context):
- ob = context.object
- return ob.instance_type == 'FACES'
- def draw_header(self, context):
- ob = context.object
- self.layout.prop(ob, "use_instance_faces_scale", text="")
- def draw(self, context):
- layout = self.layout
- ob = context.object
- layout.use_property_split = True
- layout.active = ob.use_instance_faces_scale
- layout.prop(ob, "instance_faces_scale", text="Factor")
- class OBJECT_PT_motion_paths(MotionPathButtonsPanel, Panel):
- #bl_label = "Object Motion Paths"
- bl_context = "object"
- bl_options = {'DEFAULT_CLOSED'}
- @classmethod
- def poll(cls, context):
- return (context.object)
- def draw(self, context):
- # layout = self.layout
- ob = context.object
- avs = ob.animation_visualization
- mpath = ob.motion_path
- self.draw_settings(context, avs, mpath)
- class OBJECT_PT_motion_paths_display(MotionPathButtonsPanel_display, Panel):
- #bl_label = "Object Motion Paths"
- bl_context = "object"
- bl_parent_id = "OBJECT_PT_motion_paths"
- bl_options = {'DEFAULT_CLOSED'}
- @classmethod
- def poll(cls, context):
- return (context.object)
- def draw(self, context):
- # layout = self.layout
- ob = context.object
- avs = ob.animation_visualization
- mpath = ob.motion_path
- self.draw_settings(context, avs, mpath)
- class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
- bl_label = "Visibility"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- return (context.object) and (context.engine in cls.COMPAT_ENGINES)
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
- layout = self.layout
- ob = context.object
- col = flow.column()
- col.prop(ob, "hide_viewport", text="Show in Viewports", toggle=False, invert_checkbox=True)
- col = flow.column()
- col.prop(ob, "hide_render", text="Show in Renders", toggle=False, invert_checkbox=True)
- col = flow.column()
- col.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
- class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- _context_path = "object"
- _property_type = bpy.types.Object
- classes = (
- OBJECT_PT_context_object,
- OBJECT_PT_transform,
- OBJECT_PT_delta_transform,
- OBJECT_PT_relations,
- COLLECTION_MT_context_menu,
- OBJECT_PT_collections,
- OBJECT_PT_instancing,
- OBJECT_PT_instancing_size,
- OBJECT_PT_motion_paths,
- OBJECT_PT_motion_paths_display,
- OBJECT_PT_display,
- OBJECT_PT_display_bounds,
- OBJECT_PT_visibility,
- OBJECT_PT_custom_props,
- )
- if __name__ == "__main__": # only for live edit.
- from bpy.utils import register_class
- for cls in classes:
- register_class(cls)
|