UI: Move Extensions repositories popover to header
[blender-addons-contrib.git] / object_mesh_versions.py
blob504fccffa26c611cbcdd952f2375b595227301f6
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 import bpy
20 import time
21 from datetime import datetime
22 from bpy.types import Menu, Panel
23 from bpy.props import StringProperty, BoolProperty
26 bl_info = {
27 "name": "KTX Mesh Versions",
28 "description": "Keep multiple mesh versions of an object",
29 "author": "Roel Koster, @koelooptiemanna, irc:kostex",
30 "version": (1, 5, 3),
31 "blender": (2, 80, 0),
32 "location": "View3D > Properties",
33 "warning": "",
34 "doc_url": "https://github.com/kostex/blenderscripts/",
35 "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
36 "category": "Object"}
39 class KTXMESHVERSIONS_OT_Init(bpy.types.Operator):
40 bl_label = "Initialise Mesh Versioning"
41 bl_idname = "ktxmeshversions.init"
42 bl_description = "Initialise the current object to support versioning"
44 def execute(self, context):
45 unique_id = str(time.time())
46 context.object.data.ktx_mesh_id = context.object.ktx_object_id = unique_id
47 return {'FINISHED'}
50 class KTXMESHVERSIONS_OT_Select(bpy.types.Operator):
51 bl_label = "Select Mesh"
52 bl_idname = "ktxmeshversions.select"
53 bl_description = "Link the selected mesh to the current object"
55 m_index : StringProperty()
57 def execute(self, context):
58 c_mode = bpy.context.object.mode
59 if c_mode != 'OBJECT':
60 bpy.ops.object.mode_set(mode='OBJECT')
61 obj = context.object
62 obj.data = bpy.data.meshes[self.m_index]
63 bpy.ops.object.mode_set(mode=c_mode)
64 return {'FINISHED'}
67 class KTXMESHVERSIONS_OT_Remove(bpy.types.Operator):
68 bl_label = "Remove Mesh"
69 bl_idname = "ktxmeshversions.remove"
70 bl_description = "Remove/Delete the selected mesh"
72 m_index : StringProperty()
74 def execute(self, context):
75 bpy.data.meshes.remove(bpy.data.meshes[self.m_index])
76 return {'FINISHED'}
79 class KTXMESHVERSIONS_OT_Cleanup(bpy.types.Operator):
80 bl_label = "Cleanup Mode"
81 bl_idname = "ktxmeshversions.cleanup"
82 bl_description = "Cleanup Mode"
84 def execute(self, context):
85 for o in bpy.data.objects:
86 o.select = False
87 context.scene.objects.active = None
88 return {'FINISHED'}
91 class KTXMESHVERSIONS_OT_Create(bpy.types.Operator):
92 bl_label = "Create Mesh Version"
93 bl_idname = "ktxmeshversions.create"
94 bl_description = ("Create a copy of the mesh data of the current object\n"
95 "and set it as active")
97 def execute(self, context):
98 defpin = bpy.context.scene.ktx_defpin
99 obj = context.object
100 if obj.type == 'MESH':
101 c_mode = bpy.context.object.mode
102 me = obj.data
103 if c_mode != 'OBJECT':
104 bpy.ops.object.mode_set(mode='OBJECT')
105 new_mesh = me.copy()
106 obj.data = new_mesh
107 obj.data.use_fake_user = defpin
108 bpy.ops.object.mode_set(mode=c_mode)
109 return {'FINISHED'}
112 class KTXMESHVERSIONS_PT_mainPanel(bpy.types.Panel):
113 bl_label = "KTX Mesh Versions"
114 bl_idname = "KTXMESHVERSIONS_PT_mainPanel"
115 bl_space_type = 'VIEW_3D'
116 bl_region_type = 'UI'
117 bl_category = 'Edit'
118 bl_options = {'DEFAULT_CLOSED'}
120 def draw(self, context):
121 scene = context.scene
122 obj = context.object
123 layout = self.layout
125 meshes_exist = bool(bpy.data.meshes.items() != [])
126 if meshes_exist:
127 if obj != None:
128 if obj.type == 'MESH':
129 if obj.ktx_object_id != '' and (obj.data.ktx_mesh_id == obj.ktx_object_id):
130 icon = 'PINNED' if scene.ktx_defpin else 'UNPINNED'
131 row = layout.row(align=True)
132 row.prop(scene, "ktx_defpin", text="", icon=icon)
133 row.operator("ktxmeshversions.create")
134 box = layout.box()
135 box.scale_y = 1.0
136 box.label(text="Currently active mesh: " + obj.data.name)
137 for m in bpy.data.meshes:
138 if m.ktx_mesh_id == obj.ktx_object_id:
139 mesh_name = m.name
140 row = box.row(align=True)
141 row.operator("ktxmeshversions.select", text="", icon='RIGHTARROW').m_index = mesh_name
142 row.prop(m, "name", text="", icon='MESH_DATA')
143 if m.users == 0:
144 row.operator("ktxmeshversions.remove", text="", icon="X").m_index = mesh_name
145 icon = 'PINNED' if m.use_fake_user else 'UNPINNED'
146 row.prop(m, "use_fake_user", text="", icon=icon)
147 box.label(text="")
148 row = layout.row(align=True)
149 row.operator("ktxmeshversions.cleanup", text="Cleanup Mode")
150 else:
151 layout.operator("ktxmeshversions.init")
152 else:
153 layout.label(text="Select a Mesh Object")
154 layout.operator("ktxmeshversions.cleanup", text="Cleanup Mode")
156 else:
157 layout.label(text="All Meshes (Cleanup/Pin):")
158 box = layout.box()
159 box.scale_y = 1.0
160 for m in bpy.data.meshes:
161 mesh_name = m.name
162 row = box.row(align=True)
163 row.prop(m, "name", text="", icon='MESH_DATA')
164 if m.users == 0:
165 row.operator("ktxmeshversions.remove", text="", icon="X").m_index = mesh_name
166 icon = 'PINNED' if m.use_fake_user else 'UNPINNED'
167 row.prop(m, "use_fake_user", text="", icon=icon)
168 box.label(text="")
169 else:
170 layout.label(text="No Meshes Exist")
173 classes = (
174 KTXMESHVERSIONS_PT_mainPanel,
175 KTXMESHVERSIONS_OT_Init,
176 KTXMESHVERSIONS_OT_Create,
177 KTXMESHVERSIONS_OT_Remove,
178 KTXMESHVERSIONS_OT_Select,
179 KTXMESHVERSIONS_OT_Cleanup
183 def register():
184 from bpy.utils import register_class
186 bpy.types.Object.ktx_object_id = bpy.props.StringProperty(name="KTX Object ID", description="Unique ID to 'link' one object to multiple meshes")
187 bpy.types.Mesh.ktx_mesh_id = bpy.props.StringProperty(name="KTX Mesh ID", description="Unique ID to 'link' multiple meshes to one object")
188 bpy.types.Scene.ktx_defpin = bpy.props.BoolProperty(name="Auto Pinning", description="When creating a new version, set pinning to ON automatically (FAKE_USER=TRUE)", default=False)
190 for cls in classes:
191 register_class(cls)
194 def unregister():
195 from bpy.utils import unregister_class
197 del bpy.types.Mesh.ktx_mesh_id
198 del bpy.types.Object.ktx_object_id
199 del bpy.types.Scene.ktx_defpin
201 for cls in classes:
202 unregister_class(cls)
205 if __name__ == "__main__":
206 register()