-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathscene_props.py
1216 lines (1088 loc) · 69.6 KB
/
scene_props.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
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import bpy
import bgl
from bpy.props import *
import glob
from . constants import *
from . helpers import *
from . autorail import *
from . collision import *
from . material import *
from . ui_draw import *
from . presets import *
from . import script_template
from . tex import import_img
from . import bake
# METHODS
#############################################
#----------------------------------------------------------------------------------
# Applies a context-specific mesh as a child of the empty when applicable
# This just makes it easier to see presets like restarts, CTF flags etc
#----------------------------------------------------------------------------------
def thug_empty_update(self, context):
if not context.object or context.object.type != "EMPTY":
return
ob = context.object
for mdl_ob in ob.children:
if mdl_ob.type == 'MESH':
#context.scene.objects.unlink(mdl_ob)
bpy.data.objects.remove(mdl_ob, do_unlink=True)
mdl_mesh = ''
mdl_preview = ''
preset_scale = get_actual_preset_size() / 2.0
if ob.thug_empty_props.empty_type == 'Restart':
mdl_mesh = 'Sk3Ed_RS_1p'
if ob.thug_restart_props.restart_type == 'Player2':
mdl_mesh = 'Sk3Ed_RS_Mp'
elif ob.thug_restart_props.restart_type == 'Multiplayer':
mdl_mesh = 'Sk3Ed_RS_Ho'
elif ob.thug_restart_props.restart_type == 'Horse':
mdl_mesh = 'Sk3Ed_RS_Ho'
elif ob.thug_restart_props.restart_type == 'CTF':
mdl_mesh = 'Sk3Ed_RS_Ho'
ob.empty_display_type = 'CUBE'
ob.empty_display_size = 36 * preset_scale
if ob.thug_empty_props.empty_type == 'GameObject':
mdl_mesh = ''
if ob.thug_go_props.go_type == 'Flag_Blue' or ob.thug_go_props.go_type == 'Team_Blue' :
mdl_mesh = 'CTF_Flag_Blue'
elif ob.thug_go_props.go_type == 'Flag_Red' or ob.thug_go_props.go_type == 'Team_Red':
mdl_mesh = 'CTF_Flag_Red'
elif ob.thug_go_props.go_type == 'Flag_Green' or ob.thug_go_props.go_type == 'Team_Green':
mdl_mesh = 'CTF_Flag_Green'
elif ob.thug_go_props.go_type == 'Flag_Yellow' or ob.thug_go_props.go_type == 'Team_Yellow':
mdl_mesh = 'CTF_Flag_Yellow'
if ob.thug_go_props.go_type == 'Flag_Blue_Base' or ob.thug_go_props.go_type == 'Team_Blue_Base':
mdl_mesh = 'CTF_Base_Blue'
elif ob.thug_go_props.go_type == 'Flag_Red_Base' or ob.thug_go_props.go_type == 'Team_Red_Base':
mdl_mesh = 'CTF_Base_Red'
elif ob.thug_go_props.go_type == 'Flag_Green_Base' or ob.thug_go_props.go_type == 'Team_Green_Base':
mdl_mesh = 'CTF_Base_Green'
elif ob.thug_go_props.go_type == 'Flag_Yellow_Base' or ob.thug_go_props.go_type == 'Team_Yellow_Base':
mdl_mesh = 'CTF_Base_Yellow'
elif ob.thug_go_props.go_type == 'Secret_Tape':
mdl_mesh = 'SecretTape'
elif ob.thug_go_props.go_type.startswith('Combo_'):
mdl_mesh = ob.thug_go_props.go_type
elif ob.thug_go_props.go_model != '':
mdl_preview = ob.thug_go_props.go_model
ob.empty_display_type = 'CUBE'
ob.empty_display_size = 36 * preset_scale
elif ob.thug_empty_props.empty_type == 'CubemapProbe' or ob.thug_empty_props.empty_type == 'LightProbe':
mdl_mesh = ''
ob.empty_display_type = 'SPHERE'
ob.empty_display_size = 64 * preset_scale
ob.show_name = True
elif ob.thug_empty_props.empty_type == 'LightVolume':
mdl_mesh = ''
ob.empty_display_type = 'ARROWS'
ob.empty_display_size = 64 * preset_scale
elif ob.thug_empty_props.empty_type == 'GenericNode' and ob.thug_generic_props.generic_type == 'Crown':
mdl_mesh = 'Sk3Ed_RS_KOTH'
ob.empty_display_type = 'CUBE'
ob.empty_display_size = 42 * preset_scale
elif ob.thug_empty_props.empty_type == 'Pedestrian':
if ob.thug_ped_props.ped_source == 'Model' and ob.thug_ped_props.ped_model != '':
mdl_preview = ob.thug_ped_props.ped_model
mdl_mesh = 'Ped01'
ob.empty_display_type = 'CUBE'
ob.empty_display_size = 42 * preset_scale
elif ob.thug_empty_props.empty_type == 'Vehicle':
if ob.thug_veh_props.veh_model != '':
mdl_preview = ob.thug_veh_props.veh_model
mdl_mesh = 'Veh_Taxi'
ob.empty_display_type = 'CUBE'
ob.empty_display_size = 42 * preset_scale
elif ob.thug_empty_props.empty_type == 'ParticleObject':
ob.empty_display_type = 'PLAIN_AXES'
ob.empty_display_size = 64 * preset_scale
draw_particle_preview(ob, context)
return
# Add the helper/preview mesh if it applies to this object
use_fallback = False
if mdl_preview != '':
print("Attempting to generate preview mesh from asset {}".format(mdl_preview))
scn = context.scene
if not hasattr(scn, 'thug_level_props') or not hasattr(scn.thug_level_props, 'export_props'):
print("Export props not found")
use_fallback = True
elif scn.thug_level_props.export_props.target_game == '':
print("Target game not found")
use_fallback = True
if not use_fallback:
target_game = scn.thug_level_props.export_props.target_game
mdl_obs = append_from_assets( os.path.join('Models', mdl_preview), target_game, context )
if len(mdl_obs) == 0:
print("No meshes were found in {}".format(os.path.join('Models', mdl_preview)))
use_fallback = True
for mdl_ob in mdl_obs:
mdl_ob.name = ob.name + '_MDL'
#mdl_ob.location = [ 0, 0, 0 ]
#mdl_ob.rotation_euler = [ 0, 0, 0 ]
mdl_ob.scale = [preset_scale, preset_scale, preset_scale]
mdl_ob.parent = ob
mdl_ob.hide_select = True
mdl_ob.hide_render = True
mdl_ob.thug_export_scene = False
mdl_ob.thug_export_collision = False
to_group(mdl_ob, "Visual Helpers")
if mdl_mesh != '' and (mdl_preview == '' or use_fallback):
mdl_ob = append_from_dictionary('presets', mdl_mesh, context.scene)
mdl_ob.name = ob.name + '_MDL'
mdl_ob.location = [ 0, 0, 0 ]
mdl_ob.rotation_euler = [ 0, 0, 0 ]
mdl_ob.scale = [preset_scale, preset_scale, preset_scale]
mdl_ob.parent = ob
mdl_ob.hide_select = True
mdl_ob.hide_render = True
mdl_ob.thug_export_scene = False
mdl_ob.thug_export_collision = False
to_group(mdl_ob, "Visual Helpers")
def draw_particle_preview(ob, context):
scene = context.scene
expected_obs = [ ob.name + "_START", ob.name + "_MID", ob.name + "_END" ]
found_obs = []
for mdl_ob in ob.children:
if mdl_ob.type != 'EMPTY': continue
for name in expected_obs:
if mdl_ob.name == name:
found_obs.append(name)
# Look for the particle properties
if not hasattr(ob, 'thug_particle_props'): return
particle_img = None
if ob.thug_particle_props.particle_texture != '':
# Search for the .img file referenced and load it, if we don't have it already
if not bpy.data.images.get(ob.thug_particle_props.particle_texture + ".img"):
game_paths, ext_suffix = get_game_asset_paths(context)
img_path = os.path.join('images', 'particles', ob.thug_particle_props.particle_texture + ".img" + ext_suffix)
for game_path in game_paths:
if os.path.exists(os.path.join(game_path, img_path)):
particle_img = import_img( os.path.join(game_path, img_path), ob.thug_particle_props.particle_texture + ".img" )
particle_img.pack()
else:
particle_img = bpy.data.images.get(ob.thug_particle_props.particle_texture + ".img")
for name in expected_obs:
if name not in found_obs:
new_ob = bpy.data.objects.new(name, None)
new_ob.rotation_euler = [ 1.570796, 0, 0 ]
new_ob.empty_display_type = 'IMAGE'
new_ob.parent = ob
scene.collection.objects.link(new_ob)
ob_start = bpy.data.objects.get(expected_obs[0])
ob_mid = bpy.data.objects.get(expected_obs[1])
ob_end = bpy.data.objects.get(expected_obs[2])
if particle_img:
ob_start.data = particle_img
ob_mid.data = particle_img
ob_end.data = particle_img
ob_start.location = ob.thug_particle_props.particle_startposition
ob_mid.location = ob.thug_particle_props.particle_midposition
ob_end.location = ob.thug_particle_props.particle_endposition
ob_start.empty_display_size = ob.thug_particle_props.particle_boxdimsstart[2]
ob_mid.empty_display_size = ob.thug_particle_props.particle_boxdimsmid[2]
ob_end.empty_display_size = ob.thug_particle_props.particle_boxdimsend[2]
#----------------------------------------------------------------------------------
#- Updates the list(s) of TH nodes in the current scene
#- Used by the WindowManager to fill autocomplete lists on other props
#----------------------------------------------------------------------------------
@bpy.app.handlers.persistent
def update_node_collection(*args):
#print("Updating node collections...")
context = bpy.context
context.window_manager.thug_all_nodes.paths.clear()
context.window_manager.thug_all_nodes.restarts.clear()
context.window_manager.thug_all_nodes.meshes.clear()
context.window_manager.thug_all_nodes.scripts.clear()
context.window_manager.thug_all_nodes.templates.clear()
for ob in bpy.data.objects:
if ob.type == 'MESH' and ( ob.thug_export_collision or ob.thug_export_scene ):
entry = context.window_manager.thug_all_nodes.meshes.add()
entry.name = ob.name
elif ob.type == 'EMPTY' and ob.thug_empty_props.empty_type == 'Restart':
entry = context.window_manager.thug_all_nodes.restarts.add()
entry.name = ob.name
elif ob.type == 'CURVE' and ob.thug_path_type in [ 'Rail', 'Ladder', 'Waypoint' ]:
entry = context.window_manager.thug_all_nodes.paths.add()
entry.name = ob.name
for tx in bpy.data.texts:
if tx.name.startswith('script_'):
entry = context.window_manager.thug_all_nodes.scripts.add()
entry.name = format_triggerscript_name(tx.name)
elif tx.name.startswith('template_'):
entry = context.window_manager.thug_all_nodes.templates.add()
entry.name = format_template_script_name(tx.name)
#----------------------------------------------------------------------------------
#- Updates the list of available models/images and other assets from the base game
#- Requires the plugin settings pointing to a valid game path
#----------------------------------------------------------------------------------
@bpy.app.handlers.persistent
def update_game_files_collections(*args):
print("Generating asset lists from the base game...")
context = bpy.context
context.window_manager.thug_game_assets.models.clear()
context.window_manager.thug_game_assets.skins.clear()
context.window_manager.thug_game_assets.images.clear()
context.window_manager.thug_game_assets.particle_textures.clear()
# Make sure we actually have a target game first
scn = context.scene
if not hasattr(scn, 'thug_level_props') or not hasattr(scn.thug_level_props, 'export_props'):
print("Unable to read game files - Cannot find level/export properties")
return
if scn.thug_level_props.export_props.target_game == '':
print("Unable to read game files - target game not set")
return
target_game = scn.thug_level_props.export_props.target_game
addon_prefs = bpy.context.preferences.addons[ADDON_NAME].preferences
ext_suffix = ""
game_paths = []
if target_game == 'THUG1':
game_paths.append(addon_prefs.game_data_dir_thug1)
elif target_game == 'THUG2':
game_paths.append(addon_prefs.game_data_dir_thug2)
game_paths.append(addon_prefs.game_data_dir_thugpro)
ext_suffix = ".xbx"
else:
print("Unable to read game files - target game is {}".format(target_game))
return
for game_path in game_paths:
# Then, make sure the path to that game is correctly configured in the plugin settings
if not is_valid_game_path(game_path):
print("Unable to read game files - game path {} is not valid.".format(game_path))
continue
#print("Searching for files in: {}".format(game_path))
model_files = glob.glob(game_path + "Models/**/*.mdl" + ext_suffix, recursive=True)
print("Searching for MODELS...")
for temp_path in model_files:
short_path = os.path.relpath(temp_path, game_path + "Models")
if target_game == 'THUG2':
short_path = short_path[:-4]
#print(short_path)
entry = context.window_manager.thug_game_assets.models.add()
entry.name = short_path
skin_files = glob.glob(game_path + "Models/**/*.skin" + ext_suffix, recursive=True)
print("Searching for SKINS...")
for temp_path in skin_files:
short_path = os.path.relpath(temp_path, game_path + "Models")
if target_game == 'THUG2':
short_path = short_path[:-4]
entry = context.window_manager.thug_game_assets.skins.add()
entry.name = short_path
#print(short_path)
img_files = glob.glob(game_path + "images/**/*.img" + ext_suffix, recursive=True)
print("Searching for IMAGES...")
for temp_path in img_files:
short_path = os.path.relpath(temp_path, game_path + "images")
if target_game == 'THUG2':
short_path = short_path[:-4]
entry = context.window_manager.thug_game_assets.images.add()
entry.name = short_path
#print(short_path)
tex_files = glob.glob(game_path + "images/particles/*.img" + ext_suffix, recursive=False)
print("Searching for PARTICLE TEXTURES...")
for temp_path in tex_files:
short_path = os.path.relpath(temp_path, game_path + "images/particles")
if target_game == 'THUG2':
short_path = short_path[:-4]
short_path = short_path[:-4]
entry = context.window_manager.thug_game_assets.particle_textures.add()
entry.name = short_path
#print(short_path)
# PROPERTIES
#############################################
#----------------------------------------------------------------------------------
#- Defines the Class of an empty
#----------------------------------------------------------------------------------
class THUGEmptyProps(bpy.types.PropertyGroup):
empty_type: EnumProperty(items=(
("None", "None", ""),
("Restart", "Restart", "Player restarts"),
("GenericNode", "Generic Node", "KOTH crown and other objects"),
("Pedestrian", "Pedestrian", ""),
("Vehicle", "Vehicle", ""),
("CubemapProbe", "Reflection Probe", "Point used to generate a reflection cubemap. Used by nearby objects"),
("ProximNode", "Proximity Node", "Node that can fire events when objects are inside its radius"),
("EmitterObject", "Emitter Object", "Node used to play audio streams (typically, ambient sounds in a level)"),
("GameObject", "Game Object", "CTF Flags, COMBO letters, etc"),
("BouncyObject", "Bouncy Object", "Legacy node type, not used, only for identification in imported levels"),
("ParticleObject", "Particle Object", "Used to preserve particle systems in imported levels"),
("Custom", "Custom", ""),
("LightProbe", "Light Probe", "Approximates nearby ambient lighting for moving objects"),
("LightVolume", "Light Volume", "Bounding box used to mark the boundaries of area lights"),
), name="Node Type", default="None", update=thug_empty_update)
#----------------------------------------------------------------------------------
class THUGObjectTriggerScriptProps(bpy.types.PropertyGroup):
# LEGACY PROPERTY - NO LONGER USED
# List is maintained so the scene converter can still read the value, scripts are assigned
# using the new template properties below
triggerscript_type: EnumProperty(items=(
("None", "None", ""),
("Killskater", "Killskater", "Bail the skater and restart them at the given node"),
("Killskater_Water", "Killskater (Water)", "Bail the skater and restart them at the given node"),
("Teleport", "Teleport", "Teleport the skater to a given node without breaking their combo"),
("Custom", "Custom", "Runs a custom script"),
), name="TriggerScript Type", default="None")
target_node: StringProperty(name="Target Node")
custom_name: StringProperty(name="Custom Script Name")
# New props used by the templating system!
template_name: EnumProperty(items=script_template.get_templates, name="Trigger Script", description="This script is executed when the local skater hits the object (or, for nodes, when it is loaded/triggered from another script).", update=script_template.store_triggerscript_params)
# This is what we actually use for exporting!
template_name_txt: StringProperty(name="Trigger Script", default="")
param1_int: IntProperty(name="Temp", description="")
param1_float: FloatProperty(name="Temp", description="")
param1_string: StringProperty(name="Temp", description="")
param1_bool: BoolProperty(name="Temp", description="", default=False)
param1_enum: EnumProperty(items=script_template.get_param1_values, name="Temp", description="", update=script_template.store_triggerscript_params)
param1_flags: EnumProperty(items=script_template.get_param1_values, name="Temp", description="", options={'ENUM_FLAG'}, update=script_template.store_triggerscript_params)
param2_int: IntProperty(name="Temp", description="")
param2_float: FloatProperty(name="Temp", description="")
param2_string: StringProperty(name="Temp", description="")
param2_bool: BoolProperty(name="Temp", description="", default=False)
param2_enum: EnumProperty(items=script_template.get_param2_values, name="Temp", description="", update=script_template.store_triggerscript_params)
param2_flags: EnumProperty(items=script_template.get_param2_values, name="Temp", description="", options={'ENUM_FLAG'}, update=script_template.store_triggerscript_params)
param3_int: IntProperty(name="Temp", description="")
param3_float: FloatProperty(name="Temp", description="")
param3_string: StringProperty(name="Temp", description="")
param3_bool: BoolProperty(name="Temp", description="", default=False)
param3_enum: EnumProperty(items=script_template.get_param3_values, name="Temp", description="", update=script_template.store_triggerscript_params)
param3_flags: EnumProperty(items=script_template.get_param3_values, name="Temp", description="", options={'ENUM_FLAG'}, update=script_template.store_triggerscript_params)
param4_int: IntProperty(name="Temp", description="")
param4_float: FloatProperty(name="Temp", description="")
param4_string: StringProperty(name="Temp", description="")
param4_bool: BoolProperty(name="Temp", description="", default=False)
param4_enum: EnumProperty(items=script_template.get_param4_values, name="Temp", description="", update=script_template.store_triggerscript_params)
param4_flags: EnumProperty(items=script_template.get_param4_values, name="Temp", description="", options={'ENUM_FLAG'}, update=script_template.store_triggerscript_params)
#----------------------------------------------------------------------------------
#- Proximity node properties
#----------------------------------------------------------------------------------
class THUGProximNodeProps(bpy.types.PropertyGroup):
proxim_type: EnumProperty(items=(
("Camera", "Camera", ""),
("Other", "Other", "")),
name="Type", default="Camera")
proxim_shape: EnumProperty(items=(
("BoundingBox", "Bounding Box", ""),
("Sphere", "Sphere", "")),
name="Shape", default="BoundingBox")
proxim_object: BoolProperty(name="Object", default=True)
proxim_rendertoviewport: BoolProperty(name="RenderToViewport", default=True)
proxim_selectrenderonly: BoolProperty(name="SelectRenderOnly", default=True)
proxim_radius: IntProperty(name="Radius", min=0, max=1000000, default=150)
#----------------------------------------------------------------------------------
#- Emitter properties
#----------------------------------------------------------------------------------
class THUGEmitterProps(bpy.types.PropertyGroup):
emit_type: StringProperty(name="Type", default="BoundingBox")
emit_radius: FloatProperty(name="Radius", min=0, max=1000000, default=0)
#----------------------------------------------------------------------------------
#- Cubemap probe properties
#----------------------------------------------------------------------------------
class THUGCubemapProps(bpy.types.PropertyGroup):
resolution: EnumProperty(
name="Resolution",
items=[
("64", "64", ""),
("128", "128", ""),
("256", "256", ""),
("512", "512", ""),
("1024", "1024", ""),
("2048", "2048", "")],
default="256",
description="Maximum resolution for each side of the baked reflection")
box_size: FloatVectorProperty(name="Size", size=3, default=[256.0,256.0,256.0], description="Approximate size of the area captured by this probe. Use (0,0,0) to disable parallax correction")
size: FloatProperty(name="Size", default=0.0, min=128.0, max=128000.0, description="Approximate size of the rendered area in Blender units (for parallax correction). Use 0.0 to render cubemap at infinite distance")
exported: BoolProperty(name="Exported", default=False)
#----------------------------------------------------------------------------------
#- Emitter properties
#----------------------------------------------------------------------------------
class THUGLightVolumeProps(bpy.types.PropertyGroup):
box_size: FloatVectorProperty(name="Size", size=3, default=[128.0,128.0,128.0], description="Size of the light volume")
#----------------------------------------------------------------------------------
#- If you know of another thing GenericNode is used for, let me know!
#----------------------------------------------------------------------------------
class THUGGenericNodeProps(bpy.types.PropertyGroup):
generic_type: EnumProperty(items=(
("Crown", "KOTH Crown", ""),
("Other", "Other", ""))
,name="Node Type",default="Crown")
#----------------------------------------------------------------------------------
#- Game objects - models with collision that affect gameplay
#----------------------------------------------------------------------------------
class THUGGameObjectProps(bpy.types.PropertyGroup):
go_type: EnumProperty(items=(
("Ghost", "Ghost", "No model, used for game logic"),
("Flag_Red", "CTF Flag - Red", "Red team flag for CTF"),
("Flag_Blue", "CTF Flag - Blue", "Blue team flag for CTF"),
("Flag_Green", "CTF Flag - Green", "Green team flag for CTF"),
("Flag_Yellow", "CTF Flag - Yellow", "Yellow team flag for CTF"),
("Flag_Red_Base", "CTF Base - Red", "Red team base for CTF"),
("Flag_Blue_Base", "CTF Base - Blue", "Blue team base for CTF"),
("Flag_Green_Base", "CTF Base - Green", "Green team base for CTF"),
("Flag_Yellow_Base", "CTF Base - Yellow", "Yellow team base for CTF"),
("Team_Red", "Team Flag - Red", "Red team selection flag"),
("Team_Blue", "Team Flag - Blue", "Blue team selection flag"),
("Team_Green", "Team Flag - Green", "Green team selection flag"),
("Team_Yellow", "Team Flag - Yellow", "Yellow team selection flag"),
("Team_Red_Base", "Team Base - Red", "Base for Red team selection flag"),
("Team_Blue_Base", "Team Base - Blue", "Base for Blue team selection flag"),
("Team_Green_Base", "Team Base - Green", "Base for Green team selection flag"),
("Team_Yellow_Base", "Team Base - Yellow", "Base for Yellow team selection flag"),
("Secret_Tape", "Secret Tape", ""),
("Combo_C", "Combo Letter C", ""),
("Combo_O", "Combo Letter O", ""),
("Combo_M", "Combo Letter M", ""),
("Combo_B", "Combo Letter B", ""),
("Custom", "Custom", "Specify a custom type and model")),
name="Type", default="Ghost", update=thug_empty_update)
go_type_other: StringProperty(name="Type", description="Custom type")
go_model: StringProperty(name="Model path", default="none", description="Path to the model, relative to Data/Models/.", update=thug_empty_update)
go_suspend: IntProperty(name="Suspend Distance", description="Distance at which the logic/motion of the object pauses.", min=0, max=1000000, default=0)
class THUGBouncyProps(bpy.types.PropertyGroup):
contact: FloatVectorProperty(name="Contact", description="A point used for collision detection")
#----------------------------------------------------------------------------------
#- A list of node names by type, used by the WindowManager to fill
#- autocomplete lists on other properties
#----------------------------------------------------------------------------------
class THUGNodeListProps(bpy.types.PropertyGroup):
paths: CollectionProperty(type=bpy.types.PropertyGroup)
restarts: CollectionProperty(type=bpy.types.PropertyGroup)
meshes: CollectionProperty(type=bpy.types.PropertyGroup)
scripts: CollectionProperty(type=bpy.types.PropertyGroup)
templates: CollectionProperty(type=bpy.types.PropertyGroup)
#----------------------------------------------------------------------------------
#- A list of base game assets, used to fill autocomplete lists in scenes,
#- when the base game path and target game are set
#----------------------------------------------------------------------------------
class THUGAssetListProps(bpy.types.PropertyGroup):
models: CollectionProperty(type=bpy.types.PropertyGroup)
skins: CollectionProperty(type=bpy.types.PropertyGroup)
images: CollectionProperty(type=bpy.types.PropertyGroup)
particle_textures: CollectionProperty(type=bpy.types.PropertyGroup)
#----------------------------------------------------------------------------------
#- Level obj properties! There's a lot of them!
#----------------------------------------------------------------------------------
class THUGLevelObjectProps(bpy.types.PropertyGroup):
obj_type: StringProperty(name="Type", description="Type of level object")
obj_bouncy: BoolProperty(name="Bouncy", description="Enable collision physics on this object")
center_of_mass: FloatVectorProperty(name="Center Of Mass")
contacts: CollectionProperty(type=THUGBouncyProps, name="Contacts")
coeff_restitution: FloatProperty(name="coeff_restitution", min=0, max=1024, default=0.25)
coeff_friction: FloatProperty(name="coeff_friction", min=0, max=1024, default=0.25)
skater_collision_impulse_factor: FloatProperty(name="skater_collision_impulse_factor", min=0, max=1024, default=1.5)
skater_collision_rotation_factor: FloatProperty(name="skater_collision_rotation_factor", min=0, max=1024, default=1)
skater_collision_assent: IntProperty(name="skater_collision_assent", min=0, max=1024, default=0)
skater_collision_radius: IntProperty(name="skater_collision_radius", min=0, max=1024, default=0)
mass_over_moment: FloatProperty(name="mass_over_moment", min=-1, max=1024, default=-1, description="Use value of -1 to not export this property to the QB")
stuckscript: StringProperty(name="stuckscript")
SoundType: StringProperty(name="Sound", description="Sound used when colliding with the object")
#----------------------------------------------------------------------------------
#- Properties for waypoints curves (applies to all points)
#----------------------------------------------------------------------------------
class THUGWaypointProps(bpy.types.PropertyGroup):
waypt_type: EnumProperty(items=(
("None", "None", ""),
("PedAI", "Ped AI", "This path is used for pedestrian navigation"),
("Accel", "Accel", "(THUG2+) Used for vehicle motion/acceleration"),
("Default", "Default", "(THUG2+) Default waypoint, not needed for THUG1"),
),
name="Waypoint Type", default="None", description="Type of waypoint. Use PedAI for detailed pedestrian movement and AI skaters")
PedType: EnumProperty(items=(
("Walk", "Walk", "Movement logic for pedestrians"),
("Skate", "Skate", "Movement/trick logic for AI skaters"),
),
name="PedType", default="Walk", description="The kind of navigation logic to use. 'Skate' is for AI skaters")
#----------------------------------------------------------------------------------
#- Properties for individual nodes along a path (rail, ladder, waypoints)
#----------------------------------------------------------------------------------
class THUGPathNodeProps(bpy.types.PropertyGroup):
name: StringProperty(name="Node Name")
waypt_type: StringProperty(name="Type")
script_name: StringProperty(name="TriggerScript Name")
terrain: StringProperty(name="Terrain Type")
spawnobjscript: StringProperty(name="SpawnObj Script")
PedType: StringProperty(name="PedType")
do_continue: BoolProperty(name="Continue")
JumpToNextNode: BoolProperty(name="JumpToNextNode")
Priority: StringProperty(name="Priority")
ContinueWeight: FloatProperty(name="Continue Weight")
SkateAction: StringProperty(name="Skate Action")
JumpHeight: FloatProperty(name="Jump Height")
skaterai_terrain: StringProperty(name="TerrainType")
ManualType: StringProperty(name="ManualType")
Deceleration: FloatProperty(name="Deceleration")
StopTime: FloatProperty(name="StopTime")
SpinAngle: FloatProperty(name="SpinAngle")
RandomSpin: BoolProperty(name="Random Spin", default=False)
SpineTransfer: BoolProperty(name="Spine Transfer", default=False)
SpinDirection: StringProperty(name="SpinDirection")
#----------------------------------------------------------------------------------
#- Properties for individual nodes along a path (rail, ladder, waypoints)
#- These are shown to the user via the WindowManager, the separate ones above are
#- what is actually stored on the object
#----------------------------------------------------------------------------------
class THUGPathNodeUIProps(bpy.types.PropertyGroup):
name: StringProperty(name="Node Name", update=update_pathnode)
script_name: StringProperty(name="TriggerScript Name", update=update_pathnode)
terrain: EnumProperty(
name="Terrain Type",
items=[(t, t, t) for t in ["None", "Auto"] + [tt for tt in TERRAIN_TYPES if tt.lower().startswith("grind")]], default="Auto", update=update_pathnode)
spawnobjscript: StringProperty(name="SpawnObj Script", update=update_pathnode)
PedType: StringProperty(name="Ped Type", update=update_pathnode)
do_continue: BoolProperty(name="Continue", update=update_pathnode)
JumpToNextNode: BoolProperty(name="Jump To Next Node", description="The AI skater will jump to the next point.", update=update_pathnode)
Priority: EnumProperty(items=(
("Normal", "Normal", ""),
("Low", "Low", ""),
),
name="Priority", default="Normal", description="Used for branching paths (coming soon!)", update=update_pathnode)
SkateAction: EnumProperty(items=(
("Continue", "Continue", ""),
("Grind", "Grind", ""),
("Vert_Grind", "Vert_Grind", ""),
("Grind_Off", "Grind_Off", ""),
("Flip_Trick", "Flip_Trick", ""),
("Vert_Flip", "Vert_Flip", ""),
("Grab_Trick", "Grab_Trick", ""),
("Vert_Grab", "Vert_Grab", ""),
("Vert_Lip", "Vert_Lip", ""),
("Vert_Land", "Vert_Land", ""),
("Jump", "Jump", ""),
("Vert_Jump", "Vert_Jump", ""),
("Roll_Off", "Roll_Off", ""),
("Manual", "Manual", ""),
("Manual_Down", "Manual_Down", ""),
("Stop", "Stop", ""),
),
name="Skate Action", default="Continue", description="The action taken by the AI skater when they reach this point.", update=update_pathnode)
JumpHeight: FloatProperty(name="Jump Height", min=0, max=100000, description="How high the AI skater will jump.", update=update_pathnode)
Deceleration: FloatProperty(name="Deceleration", update=update_pathnode)
SpinAngle: FloatProperty(name="Spin Angle", min=0, max=10000, description="Rotation done by the AI skater.", update=update_pathnode)
RandomSpin: BoolProperty(name="Random Spin", default=False, description="Use a random spin amount instead of the spin angle.", update=update_pathnode)
SpineTransfer: BoolProperty(name="Spine Transfer", default=False, description="AI skater should do a spine transfer.", update=update_pathnode)
SpinDirection: EnumProperty(items=(
("BS", "BS", ""),
("FS", "FS", ""),
("Rand", "Random", "Random direction"),
),
name="Spin Direction", default="Rand", description="Direction in which the AI skater spins.", update=update_pathnode)
#----------------------------------------------------------------------------------
#- Restart properties
#----------------------------------------------------------------------------------
class THUGRestartProps(bpy.types.PropertyGroup):
restart_p1: BoolProperty(name="Player 1", default=False)
restart_p2: BoolProperty(name="Player 2", default=False)
restart_gen: BoolProperty(name="Generic", default=False)
restart_multi: BoolProperty(name="Multiplayer", default=False)
restart_team: BoolProperty(name="Team", default=False)
restart_horse: BoolProperty(name="Horse", default=False)
restart_ctf: BoolProperty(name="CTF", default=False)
restart_type: EnumProperty(items=(
("Player1", "Player 1", ""),
("Player2", "Player 2", ""),
("Generic", "Generic", ""),
("Team", "Team", ""),
("Multiplayer", "Multiplayer", ""),
("Horse", "Horse", ""),
("CTF", "CTF", "")),
name="Primary Type", default="Player1", update=thug_empty_update)
restart_name: StringProperty(name="Restart Name", description="Name that appears in restart menu")
primary_restart: BoolProperty(name="Primary Restart", default=False)
#----------------------------------------------------------------------------------
#- Pedestrian properties
#----------------------------------------------------------------------------------
class THUGPedestrianProps(bpy.types.PropertyGroup):
ped_type: StringProperty(name="Type", default="Ped_From_Profile")
ped_source: EnumProperty(name="Source", items=(
( 'Profile', 'Profile', 'Pedestrian model is defined in a profile.'),
( 'Model', 'Model', 'Use an explicit path to the mdl file.')
), default="Profile", update=thug_empty_update)
ped_profile: StringProperty(name="Profile", default="random_male_profile", description="Pedestrian profile name")
ped_skeleton: StringProperty(name="Skeleton", default="THPS5_human")
ped_animset: StringProperty(name="Anim Set", default="animload_THPS5_human", description="Anim set to load for this pedestrian")
ped_extra_anims: StringProperty(name="Extra Anims", description="Additional anim sets to load")
ped_suspend: IntProperty(name="Suspend Distance", description="Distance at which the logic/motion pauses.", min=0, max=1000000, default=0)
ped_model: StringProperty(name="Model", default="", description="Relative path to mdl file.", update=thug_empty_update)
ped_nologic: BoolProperty(name="No Logic", default=False, description="Pedestrian will not have any logic, only animations")
#----------------------------------------------------------------------------------
#- Vehicle properties
#----------------------------------------------------------------------------------
class THUGVehicleProps(bpy.types.PropertyGroup):
veh_type: StringProperty(name="Type", default="Generic", description="Type of vehicle")
veh_model: StringProperty(name="Model", default="", description="Relative path to mdl file.", update=thug_empty_update)
veh_skeleton: StringProperty(name="Skeleton", default="car", description="Name of skeleton")
veh_suspend: IntProperty(name="Suspend Distance", description="Distance at which the logic/motion pauses.", min=0, max=1000000, default=0)
veh_norail: BoolProperty(name="No Rails", default=False, description="Vehicle will not have any rails (even if the model does)")
veh_noskitch: BoolProperty(name="No Skitch", default=False, description="Vehicle cannot be skitched")
veh_usemodellights: BoolProperty(name="Use Model Lights", default=False)
veh_allowreplacetex: BoolProperty(name="Texture Replacement", default=False, description="Allow model textures to be changed by scripts")
def thug_light_update(self, context):
if context.object.type == "LAMP":
if self.light_type == 'POINT':
context.object.data.type = "POINT"
context.object.data.distance = self.light_radius[0]
elif self.light_type == 'SPHERE':
context.object.data.type = "POINT"
context.object.data.distance = self.light_radius[0]
elif self.light_type == 'TUBE':
context.object.data.type = "POINT"
context.object.data.distance = self.light_radius[0]
elif self.light_type == 'AREA':
context.object.data.type = "AREA"
context.object.data.shape = "RECTANGLE"
context.object.data.size = self.light_area[0]
context.object.data.size_y = self.light_area[1]
elif self.light_type == 'DISK':
context.object.data.type = "AREA"
context.object.data.shape = "SQUARE"
context.object.data.size = self.light_radius[0]
#----------------------------------------------------------------------------------
#- Light properties
#----------------------------------------------------------------------------------
class THUGLightProps(bpy.types.PropertyGroup):
light_type: EnumProperty(name="Source", items=(
( 'POINT', 'Point', 'Punctual light source'),
( 'SPHERE', 'Sphere', 'Spherical light source with a custom radius'),
( 'TUBE', 'Tube', 'Light which emits from a tube shape, with a custom size/radius'),
( 'AREA', 'Rectangle', 'Rectangular area light'),
( 'DISK', 'Disk', 'Disk area light')
), default="POINT", update=thug_light_update)
light_end_pos: FloatVectorProperty(name="End", size=3, default=[0,256,0], description="End position for lamp")
light_radius: FloatVectorProperty(name="Radius", size=2, min=0, max=128000, default=[300,300], description="Inner/outer radius", update=thug_light_update)
light_area: FloatVectorProperty(name="Area", size=2, min=0, max=128000, default=[256,256], description="Width/height of area light", update=thug_light_update)
light_excludeskater: BoolProperty(name="Exclude Skater", default=False, description="Light will not influence the skater")
light_excludelevel: BoolProperty(name="Exclude Level", default=False, description="Light will not influence the scene")
#----------------------------------------------------------------------------------
#- Light properties
#----------------------------------------------------------------------------------
class THUGBillboardProps(bpy.types.PropertyGroup):
is_billboard: BoolProperty(name="Billboard", default=False, description="This mesh is rendered as a billboard")
type: EnumProperty(name="Type", items=(
( 'SCREEN', 'Screen', 'Billboard that always faces the screen'),
( 'AXIS', 'Axis-aligned', 'Billboard fixed around an axis')
), default="SCREEN")
custom_pos: BoolProperty(name="Custom Position", default=False, description="Use a custom pivot position")
pivot_origin: FloatVectorProperty(name="Pivot Origin", size=3, default=[0,0,0], description="Midpoint of the billboard")
pivot_pos: FloatVectorProperty(name="Pivot Position", size=3, default=[0,0,0], description="Position the billboard pivots around (for axis-aligned billboards)")
pivot_axis: FloatVectorProperty(name="Pivot Axis", size=3, default=[0,0,1], description="Axis the billboard pivots around (for axis-aligned billboards)")
#----------------------------------------------------------------------------------
#- Particle system properties! There's a lot of them!
#----------------------------------------------------------------------------------
class THUGParticleProps(bpy.types.PropertyGroup):
particle_boxdimsstart: FloatVectorProperty(name="Box Dims Start", update=thug_empty_update)
particle_boxdimsmid: FloatVectorProperty(name="Box Dims Mid", update=thug_empty_update)
particle_boxdimsend: FloatVectorProperty(name="Box Dims End", update=thug_empty_update)
particle_usestartpos: BoolProperty(name="Use Start Pos", default=False)
particle_startposition: FloatVectorProperty(name="Start Position", update=thug_empty_update)
particle_midposition: FloatVectorProperty(name="Mid Position", update=thug_empty_update)
particle_endposition: FloatVectorProperty(name="End Position", update=thug_empty_update)
particle_texture: StringProperty(name="Texture", description="Texture assigned to the particles.", update=thug_empty_update)
particle_usemidpoint: BoolProperty(name="Use Midpoint", default=False)
particle_profile: StringProperty(name="Profile", default="Default")
particle_type: EnumProperty(name="Type", items=(
( 'NewFlat', 'NewFlat', ''),
( 'Line', 'Line', ''),
( 'Flat', 'Flat', ''),
( 'Shaded', 'Shaded', ''),
( 'Smooth', 'Smooth', ''),
( 'Glow', 'Glow', ''),
( 'Star', 'Star', ''),
( 'SmoothStar', 'SmoothStar', ''),
( 'Ribbon', 'Ribbon', ''),
( 'SmoothRibbon', 'SmoothRibbon', ''),
( 'RibbonTrail', 'RibbonTrail', ''),
( 'GlowRibbonTrail', 'GlowRibbonTrail', ''),
), default="NewFlat")
particle_blendmode: EnumProperty(items=(
('Diffuse', 'Diffuse', ''),
('Blend', 'Blend', ''),
('Add', 'Add', ''),
('Subtract', 'Subtract', ''),
('Modulate', 'Modulate', ''),
('Brighten', 'Brighten', ''),
('FixBlend', 'Blend (Fixed Alpha)', ''),
('FixAdd', 'Add (Fixed Alpha)', ''),
('FixSubtract', 'Subtract (Fixed Alpha)', ''),
('FixModulate', 'Modulate (Fixed Alpha)', ''),
('FixBrighten', 'Brighten (Fixed Alpha)', ''),
), name="Blend Mode", default="Blend")
particle_fixedalpha: IntProperty(name="Fixed Alpha", min=0, max=256, default=128)
particle_alphacutoff: IntProperty(name="Alpha Cutoff", soft_min=0, max=256, default=-1)
particle_maxstreams: IntProperty(name="Max Streams", soft_min=0, max=256, default=-1)
particle_emitrate: FloatProperty(name="Emit Rate", soft_min=0, max=4096, default=-1)
particle_lifetime: FloatProperty(name="Lifetime", soft_min=0, max=128000, default=-1)
particle_midpointpct: IntProperty(name="Midpoint Pct", soft_min=0, max=100, default=-1)
particle_radius: FloatVectorProperty(name="Radius", description="Start, mid and end radius.", default=(-1,-1,-1))
particle_radiusspread: FloatVectorProperty(name="Radius Spread", default=(-1, -1, -1))
particle_startcolor: FloatVectorProperty(name="Start Color",
subtype='COLOR',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0.0, max=1.0,
description="Start Color (with alpha)")
particle_usecolormidtime: BoolProperty(name="Use Color Mid Time", default=False)
particle_colormidtime: FloatProperty(name="Color Mid Time", min=0, max=128000, default=50)
particle_midcolor: FloatVectorProperty(name="Mid Color",
subtype='COLOR',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0.0, max=1.0,
description="Mid Color (with alpha)")
particle_endcolor: FloatVectorProperty(name="End Color",
subtype='COLOR',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0.0, max=1.0,
description="End Color (with alpha)")
particle_suspend: IntProperty(name="Suspend Distance", description="Distance at which the system pauses.", min=0, max=1000000, default=0)
# Even more particle properties that I missed the first time!
#EmitSize: FloatVectorProperty(name="Emit Size", size=3, min=0, max=4096, default=16)
EmitScript: StringProperty(name="Emit Script")
Force: FloatVectorProperty(name="Emit Force", size=3, soft_min=0, soft_max=4096, default=(-1, -1, -1))
Speed: FloatVectorProperty(name="Speed", size=2, soft_min=0, soft_max=4096, default=(-1, -1))
Size: FloatVectorProperty(name="Emit Size", description="Width/height.", size=2, soft_min=0, soft_max=4096, default=(-1, -1))
Width: FloatVectorProperty(name="Start/End Width", size=2, soft_min=0, soft_max=4096, default=(-1, -1))
AngleSpread: FloatProperty(name="Angle Spread", soft_min=0, soft_max=4096, default=-1)
UsePulseEmit: BoolProperty(name="UsePulseEmit", default=False)
RandomEmitRate: BoolProperty(name="RandomEmitRate", default=False)
RandomEmitDelay: BoolProperty(name="RandomEmitDelay", default=False)
UseMidTime: BoolProperty(name="UseMidTime", default=False)
MidTime: IntProperty(name="MidTime", default=-1)
EmitTarget: FloatVectorProperty(name="Emit Target", size=3, default=(-1, -1, -1))
EmitRate1: FloatVectorProperty(name="Emit Rate 1", size=3, default=(-1, -1, -1))
EmitRate1Delay: FloatVectorProperty(name="Emit Delay 1", size=3, default=(-1, -1, -1))
EmitRate2: FloatVectorProperty(name="Emit Rate 2", size=3, default=(-1, -1, -1))
EmitRate2Delay: FloatVectorProperty(name="Emit Delay 2", size=3, default=(-1, -1, -1))
#----------------------------------------------------------------------------------
#- Properties for new 'Quick Export' option - same as the level export operators
#----------------------------------------------------------------------------------
class THUGLevelExportProps(bpy.types.PropertyGroup):
def report(self, category, message):
LOG.debug("OP: {}: {}".format(category, message))
#super().report(category, message)
# The following properties are unique to the quick export option
use_quick_export: BoolProperty(name="Quick Export", description="When this option is enabled, the settings below will be used by default when exporting.", default=False)
filename: StringProperty(name="Filename")
directory: StringProperty(name="Export Path", description="Path the scene/model will be exported to when using the 'Quick Export' option. If exporting directly to a TH game, choose the 'Data' folder.", subtype='DIR_PATH')
target_game: EnumProperty(name="Target Game", items=(
( 'THUG1', 'THUG1', 'THUG1/Underground+'),
( 'THUG2', 'THUG2', 'THUG2/THUG PRO'),
), default="THUG2")
scene_type: EnumProperty(name="Scene Type", items=(
( 'Level', 'Level', 'Export this scene as a level.'),
( 'Model', 'Model', 'Export this scene as a model.'),
), default="Level")
# These are the same as the normal export operators
always_export_normals: BoolProperty(name="Export normals", default=False)
use_vc_hack: BoolProperty(name="Vertex color hack",
description = "Doubles intensity of vertex colours. Enable if working with an imported scene that appears too dark in game."
, default=False)
# AUTOSPLIT SETTINGS
autosplit_everything: BoolProperty(name="Autosplit All",
description = "Applies the autosplit setting to all objects in the scene, with default settings.", default=False)
autosplit_faces_per_subobject: IntProperty(name="Faces Per Subobject",
description = "The max amount of faces for every created subobject.",
default=800, min=50, max=6000)
autosplit_max_radius: FloatProperty(name="Max Radius",
description = "The max radius of for every created subobject.",
default=2000, min=100, max=5000)
# /AUTOSPLIT SETTINGS
pack_pre: BoolProperty(name="Pack files into .prx", default=True)
is_park_editor: BoolProperty(name="Is Park Editor",
description="Use this option when exporting a park editor dictionary.", default=False)
generate_tex_file: BoolProperty(name="Generate a .tex file", default=True)
generate_scn_file: BoolProperty(name="Generate a .scn file", default=True)
generate_sky: BoolProperty(name="Generate skybox", default=True,description="Check to export a skybox with this scene")
generate_col_file: BoolProperty(name="Generate a .col file", default=True)
generate_scripts_files: BoolProperty(name="Generate scripts", default=True)
skybox_name: StringProperty(name="Skybox name", default="THUG_Sky")
export_scale: FloatProperty(name="Export scale", default=1)
max_texture_size: IntProperty(name="Max Texture Size"
, min=0,max=8192,default=0
, description="Clamp texture dimensions to no larger than the specified size - should be a power of 2"
)
max_texture_base_tex: BoolProperty(name="Base Textures", default=False, description="Max texture size applies to base material textures")
max_texture_lightmap_tex: BoolProperty(name="Lightmaps", default=False, description="Max texture size applies to lightmap textures")
mipmap_offset: IntProperty(
name="Mipmap offset",
description="Offsets generation of mipmaps (default is 0). For example, setting this to 1 will make the base texture 1/4 the size. Use when working with very large textures.",
min=0, max=4, default=0)
only_offset_lightmap: BoolProperty(name="Only Lightmaps", default=False, description="Mipmap offset only applies to lightmap textures")
# The following props are specific to models
model_type: EnumProperty(items = (
("skin", ".skin", "Character skin, used for playable characters and pedestrians"),
("mdl", ".mdl", "Model used for vehicles and other static mesh"),
), name="Model Type", default="skin")
#----------------------------------------------------------------------------------
#- Properties for a TOD slot
#----------------------------------------------------------------------------------
class THUGTODProps(bpy.types.PropertyGroup):
ambient_down_rgb: FloatVectorProperty(name="Ambient: Down Color",
subtype='COLOR',
default=(0.25, 0.25, 0.3),
size=3, min=0.0, max=1.0,
description="Light color used for faces which point down")
ambient_up_rgb: FloatVectorProperty(name="Ambient: Up Color",
subtype='COLOR',
default=(0.6, 0.55, 0.5),
size=3, min=0.0, max=1.0,
description="Light color used for faces which point up")
sun_headpitch: IntVectorProperty(name="Sun: Heading/Pitch", size=2, soft_min=0, soft_max=360, default=(0, 0))
light1_headpitch: IntVectorProperty(name="Light 2: Heading/Pitch", size=2, soft_min=0, soft_max=360, default=(0, 0))
sun_rgb: FloatVectorProperty(name="Sun: Diffuse Color",
subtype='COLOR',
default=(0.7, 0.65, 0.6),
size=3, min=0.0, max=1.0)
light1_rgb: FloatVectorProperty(name="Light 2: Diffuse Color",
subtype='COLOR',
default=(0.7, 0.65, 0.6),
size=3, min=0.0, max=1.0)
fog_startend: IntVectorProperty(name="Fog: Start/End", size=2, default=(0, 25000))
fog_bottomtop: IntVectorProperty(name="Fog: Bottom/Top", size=2, default=(-5000, 5000), description="Start/end height for fog")
fog_rgba: FloatVectorProperty(name="Fog: Color/Alpha",
subtype='COLOR',
default=(0.5, 0.5, 0.5, 0.25),
size=4,
min=0.0, max=1.0,
description="Fog color/alpha")
#----------------------------------------------------------------------------------
#- Properties for the entire level
#----------------------------------------------------------------------------------
class THUGLevelProps(bpy.types.PropertyGroup):
level_name: StringProperty(name="Level Name", description="Name of your level, used for in-game menus")
scene_name: StringProperty(name="Scene Name", description="Short name referenced by scripts")
creator_name: StringProperty(name="Creator Name", description="Name of the person(s) who created this level")
level_skybox: StringProperty(name="Skybox Name", description="Name of the skybox to be used with this level")
export_props: PointerProperty(type=THUGLevelExportProps)
# These properties are used in Underground+ 1.5
customize_tod: BoolProperty(name="Customize TOD", description="(Underground+ only) Use custom TOD settings", default=False)
tod_scale: FloatProperty(name="Default TOD", description="Default TOD range (0.0 = full day, 1.0 = full evening, 2.0 = full night, 3.0 = full morning)", default=0.0, min=0.0, max=4.0)
tod_slot: EnumProperty(name="TOD Slot", items=(
( 'DAY', 'Day', ''),
( 'EVENING', 'Evening', ''),
( 'NIGHT', 'Night', ''),
( 'MORNING', 'Morning', ''),
), default="DAY", description="TOD slot to edit")
tod_day: PointerProperty(type=THUGTODProps)
tod_evening: PointerProperty(type=THUGTODProps)
tod_night: PointerProperty(type=THUGTODProps)
tod_morning: PointerProperty(type=THUGTODProps)
# Legacy properties - used in the base games
level_ambient_rgba: FloatVectorProperty(name="Ambient: Color/Mod",
subtype='COLOR',
default=(0.5, 0.5, 0.5, 0.25),
size=4,
min=0.0, max=1.0,
description="Light color, with alpha used as the mod value")
level_light0_rgba: FloatVectorProperty(name="Light #1: Color/Mod",
subtype='COLOR',
default=(0.5, 0.5, 0.5, 0.25),
size=4,
min=0.0, max=1.0,
description="Light color, with alpha used as the mod value")
level_light0_headpitch: FloatVectorProperty(name="Heading/Pitch", size=2, soft_min=0, soft_max=360, default=(0, 0))
level_light1_rgba: FloatVectorProperty(name="Light #2: Color/Mod",
subtype='COLOR',
default=(0.5, 0.5, 0.5, 0.25),
size=4,
min=0.0, max=1.0,
description="Light color, with alpha used as the mod value")
level_light1_headpitch: FloatVectorProperty(name="Heading/Pitch", size=2, soft_min=0, soft_max=360, default=(0, 0))
level_flag_offline: BoolProperty(name="Offline Only", description="This level is not enabled for online play", default=False)
level_flag_indoor: BoolProperty(name="Indoor", description="(THUG PRO only) This level is indoor", default=False)
level_flag_nosun: BoolProperty(name="No Sun", description="(THUG PRO only) Don't display the dynamic sun in this level", default=False)
level_flag_defaultsky: BoolProperty(name="Default Sky", description="(THUG PRO only) Use the default skybox", default=False)
level_flag_wallridehack: BoolProperty(name="Wallride Hack", description="(THUG PRO only) Automatically makes all walls wallridable", default=False)
level_flag_nobackfacehack: BoolProperty(name="No Backface Hack", description="(THUG PRO only)", default=False)
level_flag_modelsinprx: BoolProperty(name="Models in scripts .prx", description="(THUG PRO only)", default=False)
level_flag_nogoaleditor: BoolProperty(name="Disable goal editor", description="(THUG PRO only)", default=False)
level_flag_nogoalattack: BoolProperty(name="Disable goal attack", description="(THUG PRO only)", default=False)
level_flag_noprx: BoolProperty(name="Don't use prx files", description="(THUG PRO only) This level uses uncompressed files, not packed in .prx files", default=False)
level_flag_biglevel: BoolProperty(name="Big Level", description="(THUG PRO only) Use extended online position broadcast limits", default=False)
# METHODS
#############################################