forked from OpenNaja/cobra-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path__init__.py
381 lines (323 loc) · 14.6 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
bl_info = {
"name": "Frontier's Cobra Engine Formats (JWE, Planet Zoo)",
"author": "Harlequinz Ego, HENDRIX et al.",
"blender": (3, 2, 0),
"version": (3, 0, 2),
"location": "File > Import-Export",
"description": "Import-Export models, skeletons and animations",
"warning": "",
"wiki_url": "https://github.com/OpenNaja/cobra-tools",
"support": 'COMMUNITY',
"tracker_url": "https://github.com/OpenNaja/cobra-tools/issues/new",
"category": "Import-Export"}
try:
import os
import sys
import subprocess
import logging
import pkg_resources, importlib.util
import bpy
import bpy.utils.previews
from bpy.props import IntProperty
from bpy.types import PropertyGroup
import addon_utils
copies_of_tools = []
for addon in addon_utils.modules():
if addon.bl_info['name'] == bl_info['name']:
copies_of_tools.append(addon)
if len(copies_of_tools) > 1:
addon_paths = "\n".join(os.path.dirname(addon.__file__) for addon in copies_of_tools)
raise UserWarning(f"You have multiple copies of the tools installed in your blender addons folders:\n"
f"{addon_paths}\nClose blender, delete all but the current version and try again.")
plugin_dir = os.path.dirname(__file__)
if not plugin_dir in sys.path:
sys.path.append(plugin_dir)
from ovl_util.logs import logging_setup
logging_setup("blender_plugin")
logging.info(f"Running blender {'.'.join([str(x) for x in bpy.app.version])}")
from root_path import root_dir
from plugin import addon_updater_ops
from plugin.addon_updater_ops import classes as updater_classes
from plugin.modules_import.operators import ImportBanis, ImportManis, ImportMatcol, ImportFgm, ImportMS2, ImportSPL, \
ImportVoxelskirt, ImportMS2FromBrowser, ImportFGMFromBrowser
from plugin.modules_export.operators import ExportMS2, ExportSPL, ExportManis, ExportBanis, ExportFgm
from plugin.utils.operators import UpdateFins, UpdateLods, VcolToComb, CombToVcol, TransferHairCombing, AddHair, \
GenerateRigEdit, ApplyPoseAll, ConvertScaleToLoc, ExtrudeFins, IntrudeFins, Mdl2Rename, Mdl2Duplicate, \
AutosmoothAll, LODS_UL_items
from plugin.utils.properties import CobraSceneSettings, CobraMeshSettings, CobraCollisionSettings, \
CobraMaterialSettings, LodData
from plugin.utils.panels import CobraMaterialPanel, CobraMdl2Panel, VIEW_PT_Mdl2
global preview_collection
class CobraPreferences(bpy.types.AddonPreferences):
"""Cobra preferences"""
bl_idname = __package__
# Addon updater preferences.
auto_check_update: bpy.props.BoolProperty(
name="Auto-check for Update",
description="If enabled, auto-check for updates using an interval",
default=False)
updater_interval_months: bpy.props.IntProperty(
name='Months',
description="Number of months between checking for updates",
default=0,
min=0)
updater_interval_days: bpy.props.IntProperty(
name='Days',
description="Number of days between checking for updates",
default=1,
min=0,
max=31)
updater_interval_hours: bpy.props.IntProperty(
name='Hours',
description="Number of hours between checking for updates",
default=0,
min=0,
max=23)
updater_interval_minutes: bpy.props.IntProperty(
name='Minutes',
description="Number of minutes between checking for updates",
default=0,
min=0,
max=59)
def draw(self, context):
# we are only suggesting to install bitarray for now
bitarray_spec = importlib.util.find_spec("bitarray")
if bitarray_spec is None:
row = self.layout.row()
row.alert = True
button = row.operator("wm.install_dependencies",
text="Some modules are not installed (click to install)",
icon="ERROR")
addon_updater_ops.update_settings_ui(self, context)
class InstallDependencies(bpy.types.Operator):
"""Installs: bitarray-hardbyte"""
bl_idname = "wm.install_dependencies"
bl_label = "Install missing dependencies, requires restarting"
bl_options = {'REGISTER'}
def execute(self, context):
# from the suggested modules list, remove those installed already
# pkg_resources might not look into the addon-packages folder
missing = {'bitarray-hardbyte'} - {pkg.key for pkg in pkg_resources.working_set}
python = sys.executable
# can't write in site-packages, but we can write in the addon-packages folder
subprocess.call([python, '-m', 'pip', 'install', *missing, '-t', os.path.join( bpy.utils.user_resource("SCRIPTS"), 'addons', 'modules')], stdout=subprocess.DEVNULL)
return {'FINISHED'}
class MESH_PT_CobraTools(bpy.types.Panel):
"""Creates a Panel in the scene context of the properties editor"""
bl_label = "Cobra Mesh Tools"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@classmethod
def poll(cls, context):
if context.active_object.type == 'MESH':
return True
else:
return False
def draw(self, context):
addon_updater_ops.check_for_update_background()
addon_updater_ops.update_notice_box_ui(self, context)
layout = self.layout
row = layout.row(align=True)
row.operator("object.add_hair", icon="CURVES")
box = layout.box()
box.label(text="Combing", icon="CURVES")
sub = box.row(align=True)
sub.operator("object.vcol_to_comb", icon="COPYDOWN")
sub.operator("object.comb_to_vcol", icon="PASTEDOWN")
box.operator("object.transfer_hair_combing", icon="PASTEFLIPDOWN")
box = layout.box()
box.label(text="Fur Fins", icon="SEQ_HISTOGRAM")
box.operator("object.update_fins", icon="FILE_REFRESH")
row = box.row(align=True)
row.operator("object.extrude_fins", icon="ADD")
row.operator("object.intrude_fins", icon="REMOVE")
class SCENE_PT_CobraTools(bpy.types.Panel):
"""Creates a Panel in the scene context of the properties editor"""
bl_label = "Cobra Scene Tools"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
@classmethod
def poll(cls, context):
return True
def draw(self, context):
layout = self.layout
row = layout.row(align=True)
row.prop(context.scene.cobra, "num_streams")
row = layout.row(align=True)
row.prop(context.scene.cobra, "game")
addon_updater_ops.update_notice_box_ui(self, context)
class COLLISION_PT_CobraTools(bpy.types.Panel):
"""Creates a Panel in the scene context of the properties editor"""
bl_label = "Cobra Collision Tools"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "physics"
@classmethod
def poll(cls, context):
if context.active_object.rigid_body:
return True
return False
def draw(self, context):
rb = context.active_object.cobra_coll
layout = self.layout
row = layout.row(align=True)
row.prop(rb, "air_resistance")
row = layout.row(align=True)
row.prop(rb, "damping_3d")
row = layout.row(align=True)
row.prop(rb, "flag")
row = layout.row(align=True)
row.prop(rb, rb.get_current_versioned_name(context, "surface"))
row = layout.row(align=True)
row.prop(rb, rb.get_current_versioned_name(context, "classification"))
def draw_rigid_body_constraints_cobra(self, context):
scene = context.scene
layout = self.layout
# display properties and values
col = layout.column(align=True)
# col.label(text="My Values:")
col.prop(context.active_object.cobra_coll, "plasticity_min")
col.prop(context.active_object.cobra_coll, "plasticity_max")
# col.prop(scene, "plasticity", text="Frame Start")
def menu_func_export(self, context):
icon = preview_collection["frontier.png"].icon_id
self.layout.operator(ExportFgm.bl_idname, text="Cobra Material (.fgm)", icon_value=icon)
self.layout.operator(ExportMS2.bl_idname, text="Cobra Model (.ms2)", icon_value=icon)
self.layout.operator(ExportSPL.bl_idname, text="Cobra Spline (.spl)", icon_value=icon)
self.layout.operator(ExportBanis.bl_idname, text="Cobra Baked Anim (.banis)", icon_value=icon)
self.layout.operator(ExportManis.bl_idname, text="Cobra Anim (.manis)", icon_value=icon)
def menu_func_import(self, context):
icon = preview_collection["frontier.png"].icon_id
self.layout.operator(ImportFgm.bl_idname, text="Cobra Material (.fgm)", icon_value=icon)
self.layout.operator(ImportMatcol.bl_idname, text="Cobra Material (.matcol, .dinosaurmateriallayers)",
icon_value=icon)
self.layout.operator(ImportMS2.bl_idname, text="Cobra Model (.ms2)", icon_value=icon)
self.layout.operator(ImportBanis.bl_idname, text="Cobra Baked Anim (.banis)", icon_value=icon)
self.layout.operator(ImportManis.bl_idname, text="Cobra Anim (.manis)", icon_value=icon)
self.layout.operator(ImportSPL.bl_idname, text="Cobra Spline (.spl)", icon_value=icon)
self.layout.operator(ImportVoxelskirt.bl_idname, text="Cobra Map (.voxelskirt)", icon_value=icon)
# Function used to inject elements in the contextual menu of the File Browser editor
def CT_FileBrowser_Context_Menu(self, context):
if context.space_data.browse_mode == 'FILES' and context.active_file:
file = context.active_file.name
folder = context.space_data.params.directory.decode('ascii')
filepath = os.path.join(folder, file)
fileext = os.path.splitext(file)[1]
if os.path.isfile(filepath):
if fileext.lower() == ".ms2":
layout = self.layout
layout.separator()
layout.operator(ImportMS2FromBrowser.bl_idname)
if fileext.lower() == ".fgm":
layout = self.layout
layout.separator()
layout.operator(ImportFGMFromBrowser.bl_idname)
classes = (
ImportBanis,
ImportManis,
ImportMatcol,
ImportFgm,
ImportMS2,
ImportSPL,
ImportMS2FromBrowser,
ImportFGMFromBrowser,
ExportFgm,
ExportMS2,
ExportSPL,
ExportBanis,
ExportManis,
ImportVoxelskirt,
UpdateFins,
LodData,
LODS_UL_items,
UpdateLods,
GenerateRigEdit,
ApplyPoseAll,
ConvertScaleToLoc,
VcolToComb,
CombToVcol,
ExtrudeFins,
IntrudeFins,
TransferHairCombing,
AddHair,
CobraPreferences,
CobraSceneSettings,
CobraMeshSettings,
CobraCollisionSettings,
CobraMaterialSettings,
CobraMaterialPanel,
CobraMdl2Panel,
VIEW_PT_Mdl2,
Mdl2Rename,
Mdl2Duplicate,
AutosmoothAll,
MESH_PT_CobraTools,
SCENE_PT_CobraTools,
COLLISION_PT_CobraTools,
InstallDependencies,
*updater_classes
)
except:
logging.exception("Startup failed")
pass
# get panel names
# for panel in bpy.types.Panel.__subclasses__():
# print(panel.__name__)
# PHYSICS_PT_rigid_body
# PHYSICS_PT_rigid_body_settings
# PHYSICS_PT_rigid_body_collisions
# PHYSICS_PT_rigid_body_collisions_surface
# PHYSICS_PT_rigid_body_collisions_sensitivity
# PHYSICS_PT_rigid_body_collisions_collections
# PHYSICS_PT_rigid_body_dynamics
# PHYSICS_PT_rigid_body_dynamics_deactivation
# PHYSICS_PT_rigid_body_constraint
# PHYSICS_PT_rigid_body_constraint_settings
# PHYSICS_PT_rigid_body_constraint_objects
# PHYSICS_PT_rigid_body_constraint_override_iterations
# PHYSICS_PT_rigid_body_constraint_limits
# PHYSICS_PT_rigid_body_constraint_limits_linear
# PHYSICS_PT_rigid_body_constraint_limits_angular
# PHYSICS_PT_rigid_body_constraint_motor
# PHYSICS_PT_rigid_body_constraint_motor_angular
# PHYSICS_PT_rigid_body_constraint_motor_linear
# PHYSICS_PT_rigid_body_constraint_springs
# PHYSICS_PT_rigid_body_constraint_springs_angular
# PHYSICS_PT_rigid_body_constraint_springs_linear
def register():
addon_updater_ops.register(bl_info)
icons_dir = os.path.join(root_dir, "icons")
global preview_collection
preview_collection = bpy.utils.previews.new()
for icon_name_ext in os.listdir(icons_dir):
icon_name = os.path.basename(icon_name_ext)
preview_collection.load(icon_name, os.path.join(icons_dir, icon_name_ext), 'IMAGE')
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
# insert properties
bpy.types.Material.fgm = bpy.props.PointerProperty(type=CobraMaterialSettings)
bpy.types.Scene.cobra = bpy.props.PointerProperty(type=CobraSceneSettings)
bpy.types.Mesh.cobra = bpy.props.PointerProperty(type=CobraMeshSettings)
# bpy.types.RigidBodyObject.cobra = bpy.props.PointerProperty(type=CobraCollisionSettings)
bpy.types.Object.cobra_coll = bpy.props.PointerProperty(type=CobraCollisionSettings)
# Injection of elements in the contextual menu of the File Browser editor
bpy.types.FILEBROWSER_MT_context_menu.append(CT_FileBrowser_Context_Menu)
bpy.types.PHYSICS_PT_rigid_body_constraint_limits_angular.append(draw_rigid_body_constraints_cobra)
def unregister():
# Injection of elements in the contextual menu of the File Browser editor
bpy.types.FILEBROWSER_MT_context_menu.remove(CT_FileBrowser_Context_Menu)
bpy.types.PHYSICS_PT_rigid_body_constraint_limits_angular.remove(draw_rigid_body_constraints_cobra)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
del bpy.types.Scene.cobra
del bpy.types.Mesh.cobra
global preview_collection
bpy.utils.previews.remove(preview_collection)
if __name__ == "__main__":
register()