From 01a852de9b3f7f7251f41dbb94962700a5b72423 Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Sun, 28 Dec 2025 22:53:18 +0100 Subject: [PATCH] Updated func_godot --- 3D/MapModels/actor_alarmbox.glb | Bin 5420 -> 5448 bytes 3D/MapModels/actor_box_blue_tall.glb | Bin 8568 -> 8572 bytes 3D/MapModels/actor_box_wood_tall.glb | Bin 9520 -> 9520 bytes 3D/MapModels/actor_capacitor_mini.glb | Bin 19700 -> 19724 bytes 3D/MapModels/actor_chest_1.glb | Bin 9240 -> 9244 bytes 3D/MapModels/actor_controlpad.glb | Bin 4572 -> 4572 bytes 3D/MapModels/actor_door_1.glb | Bin 12508 -> 12508 bytes 3D/MapModels/actor_emitter_floor.glb | Bin 18524 -> 18528 bytes 3D/MapModels/actor_emitter_tube.glb | Bin 27008 -> 27008 bytes 3D/MapModels/actor_emitter_wall.glb | Bin 15480 -> 15484 bytes 3D/MapModels/actor_filing_cabinet.glb | Bin 4104 -> 4108 bytes 3D/MapModels/actor_forcefield_1.glb | Bin 2860 -> 2864 bytes 3D/MapModels/actor_furniture_box.glb | Bin 4200 -> 4204 bytes 3D/MapModels/actor_furniture_can.glb | Bin 8908 -> 8912 bytes .../actor_furniture_computertower.glb | Bin 4560 -> 4560 bytes 3D/MapModels/actor_furniture_shelf.glb | Bin 3968 -> 3968 bytes 3D/MapModels/actor_furniture_triangle.glb | Bin 4376 -> 4376 bytes 3D/MapModels/actor_keypad.glb | Bin 4172 -> 4172 bytes 3D/MapModels/actor_level_teleporter.glb | Bin 4840 -> 4844 bytes 3D/MapModels/actor_locker.glb | Bin 5316 -> 5316 bytes 3D/MapModels/actor_mainframe.glb | Bin 6092 -> 6092 bytes 3D/MapModels/actor_securitycamera.glb | Bin 22184 -> 22188 bytes 3D/MapModels/actor_stairs_mini.glb | Bin 22812 -> 22812 bytes 3D/MapModels/actor_switch.glb | Bin 14360 -> 14364 bytes 3D/MapModels/actor_tank.glb | Bin 28456 -> 28460 bytes 3D/MapModels/actor_tank_large.glb | Bin 77584 -> 77588 bytes 3D/MapModels/actor_tank_standalone.glb | Bin 42520 -> 42524 bytes 3D/MapModels/actor_teleporter.glb | Bin 4836 -> 4840 bytes 3D/MapModels/actor_terminal_big.glb | Bin 8400 -> 8404 bytes 3D/MapModels/actor_tube_corner.glb | Bin 30808 -> 30808 bytes 3D/MapModels/actor_tube_junction.glb | Bin 18160 -> 18160 bytes 3D/MapModels/actor_tube_straight.glb | Bin 32964 -> 32968 bytes 3D/MapModels/actor_tube_straight_long.glb | Bin 32972 -> 32976 bytes 3D/MapModels/actor_valve.glb | Bin 61112 -> 61112 bytes 3D/MapModels/actor_vendingmachine.glb | Bin 4108 -> 4112 bytes 3D/MapModels/actor_wallfan.glb | Bin 34480 -> 34484 bytes 3D/MapModels/actor_watercooler.glb | Bin 16756 -> 16760 bytes 3D/Maps/Fusion.map | 612 +++++++++++++++--- .../EntityDefinitions/base/enemy_base.tres | 18 +- .../point/actors/Actor_Capacitor_Mini.tres | 7 +- .../point/actors/Actor_Door.tres | 9 +- .../point/actors/Actor_Emitter_Floor.tres | 13 +- .../point/actors/Actor_Emitter_Tube.tres | 9 +- .../point/actors/Actor_Emitter_Wall.tres | 13 +- .../point/actors/Actor_Forcefield.tres | 17 +- .../point/actors/Actor_Furniture_Box.tres | 9 +- .../point/actors/Actor_Furniture_Can.tres | 9 +- .../actors/Actor_Furniture_ComputerTower.tres | 9 +- .../point/actors/Actor_Furniture_Shelf.tres | 9 +- .../actors/Actor_Furniture_Triangle.tres | 9 +- .../point/actors/Actor_Level_Teleporter.tres | 17 +- .../point/actors/Actor_Locker.tres | 9 +- .../point/actors/Actor_Mainframe.tres | 9 +- .../point/actors/Actor_SecurityCamera.tres | 9 +- .../point/actors/Actor_Stairs_mini.tres | 9 +- .../point/actors/Actor_Table.tres | 7 +- .../point/actors/Actor_Tank_Large.tres | 9 +- .../point/actors/Actor_Teleporter.tres | 20 +- .../point/actors/Actor_VendingMachine.tres | 12 +- .../point/actors/Actor_Wallfan.tres | 9 +- .../point/actors/Actor_WaterCooler.tres | 9 +- .../EnemySpawners/marker_spawn_enemy.tres | 7 +- .../marker_spawn_enemy_fairy_guard.tres | 17 +- .../marker_spawn_enemy_fairy_small.tres | 11 +- .../point/actors/actor_AC_unit.tres | 8 +- .../point/actors/actor_Filing_Cabinet.tres | 9 +- .../point/actors/actor_alarmbox.tres | 7 +- .../point/actors/actor_barrel.tres | 11 +- .../point/actors/actor_box_blue.tres | 8 +- .../point/actors/actor_box_blue_tall.tres | 9 +- .../point/actors/actor_box_green.tres | 7 +- .../point/actors/actor_box_red.tres | 7 +- .../point/actors/actor_box_wood_tall.tres | 9 +- .../point/actors/actor_box_yellow.tres | 7 +- .../point/actors/actor_chair.tres | 11 +- .../point/actors/actor_chest.tres | 13 +- .../point/actors/actor_controlpad.tres | 9 +- .../point/actors/actor_dialogue.tres | 7 +- .../point/actors/actor_keypad.tres | 9 +- .../point/actors/actor_switch.tres | 9 +- .../point/actors/actor_tank.tres | 9 +- .../point/actors/actor_tank_standalone.tres | 9 +- .../point/actors/actor_terminal.tres | 7 +- .../point/actors/actor_terminal_big.tres | 12 +- .../point/actors/actor_tube_corner.tres | 9 +- .../point/actors/actor_tube_junction.tres | 9 +- .../point/actors/actor_tube_straight.tres | 9 +- .../actors/actor_tube_straight_long.tres | 9 +- .../point/actors/actor_valve.tres | 17 +- .../point/actors/marker_spawn.tres | 15 +- .../solid/Brush/acid_area.tres | 1 + .../Brush/worldspawn_bullet_permeable.tres | 1 + .../solid/Brush/worldspawn_custom.tres | 1 + .../solid/Brush/worldspawn_shadow.tres | 1 + .../solid/Brush/worldspawn_transparent.tres | 1 + .../solid/funcs/func_move.tres | 1 + .../solid/funcs/func_shroud.tres | 1 + 3D/TrenchBroom/Main_Game_Config.tres | 2 +- 3D/TrenchBroom/fgd_main.tres | 5 +- .../HexGrid/Singles/Floors/Floor111.tres | 8 + .../HexGrid/Singles/Floors/Floor133.tres | 8 + .../HexGrid/Singles/Floors/Floor139.tres | 8 + .../HexGrid/Singles/Floors/Floor234.tres | 8 + .../HexGrid/Singles/Floors/Floor235.tres | 8 + .../Singles/Floors/Floor_Tiled_0226.tres | 8 + addons/func_godot/LICENSE | 21 + .../func_godot/fgd/cull_interior_faces.tres | 15 + addons/func_godot/fgd/func_detail.tres | 31 +- .../fgd/func_detail_illusionary.tres | 32 +- addons/func_godot/fgd/func_geo.tres | 30 +- addons/func_godot/fgd/func_godot_fgd.tres | 8 +- addons/func_godot/fgd/func_illusionary.tres | 31 +- addons/func_godot/fgd/phong_base.tres | 17 +- .../fgd/vertex_merge_distance_base.tres | 19 +- addons/func_godot/fgd/worldspawn.tres | 32 +- .../func_godot_default_map_settings.tres | 30 +- ...dot_netradiant_custom_gamepack_config.tres | 13 +- .../netradiant_custom_shader_clip.tres | 3 +- .../netradiant_custom_shader_origin.tres | 3 +- .../netradiant_custom_shader_skip.tres | 3 +- .../func_godot_tb_game_config.tres | 23 - .../trenchbroom/tb_brush_tag_func.tres | 1 - .../trenchbroom/tb_brush_tag_trigger.tres | 3 +- .../trenchbroom/tb_face_tag_clip.tres | 3 - .../trenchbroom/tb_face_tag_origin.tres | 3 - .../trenchbroom/tb_face_tag_skip.tres | 3 - addons/func_godot/icon.png.import | 6 + addons/func_godot/icon32.png.import | 6 + addons/func_godot/plugin.cfg | 4 +- addons/func_godot/src/core/data.gd | 12 +- .../func_godot/src/core/entity_assembler.gd | 226 ++----- addons/func_godot/src/core/func_godot.gd | 136 ---- addons/func_godot/src/core/func_godot.gd.uid | 1 - .../src/core/func_godot_geo_generator.gd | 381 ----------- .../src/core/func_godot_geo_generator.gd.uid | 1 - .../src/core/func_godot_map_data.gd | 158 ----- .../src/core/func_godot_map_data.gd.uid | 1 - .../src/core/func_godot_map_parser.gd | 326 ---------- .../src/core/func_godot_map_parser.gd.uid | 1 - .../src/core/func_godot_surface_gatherer.gd | 217 ------- .../core/func_godot_surface_gatherer.gd.uid | 1 - .../func_godot/src/core/geometry_generator.gd | 102 ++- addons/func_godot/src/core/parser.gd | 171 ++++- .../src/fgd/func_godot_fgd_entity_class.gd | 27 +- .../func_godot/src/fgd/func_godot_fgd_file.gd | 22 +- .../fgd/func_godot_fgd_model_point_class.gd | 11 +- .../src/fgd/func_godot_fgd_point_class.gd | 93 ++- ...odot_fgd_point_class_display_descriptor.gd | 48 ++ ..._fgd_point_class_display_descriptor.gd.uid | 1 + .../src/import/quake_map_import_plugin.gd | 2 +- .../src/import/quake_palette_import_plugin.gd | 2 +- .../func_godot/src/import/quake_wad_file.gd | 2 +- .../src/import/quake_wad_import_plugin.gd | 6 +- addons/func_godot/src/map/func_godot_map.gd | 8 +- .../src/map/func_godot_map_settings.gd | 96 +-- .../netradiant_custom_gamepack_config.gd | 24 +- .../trenchbroom/trenchbroom_game_config.gd | 14 +- .../src/util/func_godot_local_config.gd | 29 +- .../src/util/func_godot_texture_loader.gd | 188 ------ .../src/util/func_godot_texture_loader.gd.uid | 1 - addons/func_godot/src/util/func_godot_util.gd | 103 ++- .../textures/{special => }/clip.png | 0 .../textures/{special => }/clip.png.import | 12 +- .../textures/default_texture.png.import | 6 + .../textures/{special => }/origin.png | 0 .../textures/{special => }/origin.png.import | 12 +- .../textures/{special => }/skip.png | 0 .../textures/{special => }/skip.png.import | 12 +- textures/Manual/Wall_Backrooms_003.tres | 8 + textures/special/clip.tres | 8 + 170 files changed, 1711 insertions(+), 2302 deletions(-) create mode 100644 ExternalMaterial/HexGrid/Singles/Floors/Floor111.tres create mode 100644 ExternalMaterial/HexGrid/Singles/Floors/Floor133.tres create mode 100644 ExternalMaterial/HexGrid/Singles/Floors/Floor139.tres create mode 100644 ExternalMaterial/HexGrid/Singles/Floors/Floor234.tres create mode 100644 ExternalMaterial/HexGrid/Singles/Floors/Floor235.tres create mode 100644 ExternalMaterial/HexGrid/Singles/Floors/Floor_Tiled_0226.tres create mode 100644 addons/func_godot/LICENSE create mode 100644 addons/func_godot/fgd/cull_interior_faces.tres delete mode 100644 addons/func_godot/src/core/func_godot.gd delete mode 100644 addons/func_godot/src/core/func_godot.gd.uid delete mode 100644 addons/func_godot/src/core/func_godot_geo_generator.gd delete mode 100644 addons/func_godot/src/core/func_godot_geo_generator.gd.uid delete mode 100644 addons/func_godot/src/core/func_godot_map_data.gd delete mode 100644 addons/func_godot/src/core/func_godot_map_data.gd.uid delete mode 100644 addons/func_godot/src/core/func_godot_map_parser.gd delete mode 100644 addons/func_godot/src/core/func_godot_map_parser.gd.uid delete mode 100644 addons/func_godot/src/core/func_godot_surface_gatherer.gd delete mode 100644 addons/func_godot/src/core/func_godot_surface_gatherer.gd.uid create mode 100644 addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd create mode 100644 addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd.uid delete mode 100644 addons/func_godot/src/util/func_godot_texture_loader.gd delete mode 100644 addons/func_godot/src/util/func_godot_texture_loader.gd.uid rename addons/func_godot/textures/{special => }/clip.png (100%) rename addons/func_godot/textures/{special => }/clip.png.import (59%) rename addons/func_godot/textures/{special => }/origin.png (100%) rename addons/func_godot/textures/{special => }/origin.png.import (58%) rename addons/func_godot/textures/{special => }/skip.png (100%) rename addons/func_godot/textures/{special => }/skip.png.import (59%) create mode 100644 textures/Manual/Wall_Backrooms_003.tres create mode 100644 textures/special/clip.tres diff --git a/3D/MapModels/actor_alarmbox.glb b/3D/MapModels/actor_alarmbox.glb index 2043a9eff8d60ad62a0a9661e32290f18d7fe0ec..6dfcd32871c24f58092dda6087bb126ede6789d8 100644 GIT binary patch delta 126 zcmZ3ZbwZ0bJtxGCiGhK^LzIEx!$#f@Z1#qF#U+VJIjMTN`FZ(z`DtmH$(e~c4ryja zX(>r5sfMNo#-_=prsifTi7A%GsiqcYMh1pyCMhO{sc8nuNt>19s=A8R8tExBLl-UlN1xf)HH+Sq|KJh|JfN8Hk)%hiU9!g C1|7rz delta 94 zcmez4^uviaJtxGCiGhKkLXm+%Wh3uRI}tn6SI`f*3AFeH`{PKhyeg|G#sh` diff --git a/3D/MapModels/actor_box_wood_tall.glb b/3D/MapModels/actor_box_wood_tall.glb index a6f6ba6fb51f9c99a0b37b7434ed46d13559f972..dba17de442abf48480dcc536fd0516d787496f84 100644 GIT binary patch delta 81 zcmdnswZUt{b0&L3z2cI@q?}Z}-2A+Jz5KMa%;e0(9EUVBqqLNylvG1g17p) delta 82 zcmdnswZUt{b0*v3lEkE(RK48%ynMah#M0F0|SpQ1A_q9M!wHXjE0k##Wd2)jM7q)Qc?{~4UA2bO-;?s zQW8@vjZ;l6%!~{S(@auK3{%q#l9M*uF|)GD=qME@C+4IoSw$O~=^5z2iP&15>dCv= Ql{aT{EMVNs!}Y=m07d*DEC2ui delta 106 zcmeB~#rS0=BVT$>h#M0F1H%^|28JJ;8~Hvn*%p^1Cgr5+<>u$*>*c4VWhQ4P<~UfG znYz`1P!4Ck82NnAO delta 94 zcmbQ^F~fs5JtxGCiGhJZLWP0BW+U$t4%_0A#H5^5z1;k~e7*d%w9Mqp#2g0;bF(BP yO9NwLqts-xG^13r6hm|46ax!GGowTUqr^n>RI}tn6SI`f2AoRVn?poS@B;u9avN{} diff --git a/3D/MapModels/actor_controlpad.glb b/3D/MapModels/actor_controlpad.glb index 62ba823200cebf52910139f58570eda5130c4ab5..9a2c3cfba3f8c5a3c56652f939836026b9005fab 100644 GIT binary patch delta 81 zcmcbkd`Ef1KPG!az2cI@q?}Z}-2A+Jz5KMa%;e0(9EUVBqqLNylvG1g17p)3%GOG0Ht>tbN~PV delta 63 zcmcbkd`Ef1Kc-2{q8b+FW=Tet2FAulsmW$(MyX~ghUUg81{Q{9Mu`SSiHYW^X32>r TW+|I(nTXv`^7Zo5(lV1X6LTEW z%#6}fl2TF)O%04qlTA&{%~BFmER9o5EzFDz4AV?fObk=g43d*Jv+;;=Gbt!+mJxR_ F1OOd;9Si^f delta 96 zcmaDbf$`1+M&9(C5H}_U28I|91_q9eynDE9i%Sxda#Hnj^Yilc^3&2XlQR=@94ySu zl8h`3jE#*_lg-kMQq58f&5ctGEDX(z5)F(J6U|f2k`qnLQZ{q&h;eUL5O**H0D`j{ A(EtDd diff --git a/3D/MapModels/actor_emitter_tube.glb b/3D/MapModels/actor_emitter_tube.glb index 776e49964234a8c13dbd2de5b7b7c922e7996221..816b0393fe304f7ac11534c91cfc5688ab96930e 100644 GIT binary patch delta 83 zcmZp;%-C?5al=hkdqchAlEkE(RK48%ynMaEM!)#0n3Y-6M@~{B_ Dw0Ipw delta 93 zcmeBC=uqHI&k1p3Vqjq45MW?T4r))Vvd7_xml8t wrGc@rQEIYTno+7*ilMo2ih+fpnNgyFQDUNbs#$WPiCM~KYv#jjo49z`0R4d*3IG5A diff --git a/3D/MapModels/actor_forcefield_1.glb b/3D/MapModels/actor_forcefield_1.glb index b1631962ddc789a6f5b9f5c24d4b36783da0e1e0..9bc59cfe87e62ab7a5659e691a04ec79294297e3 100644 GIT binary patch delta 98 zcmZ1@wn28R8tExBLl-UlN1xf)HH+Sq|M&Up=^u_o9A=(G6Dci Cj2rO) delta 77 zcmdlWwnmIMJtxGCiGhJZhns<+XCp5o^JD>LQ4I@ovm_%+17l;O)MT?Xqg1mLLv!O4 h0}DelqeKIv#6r5sfMNo#-_=prsifTi7A%GsiqcYMh1pyCMhO{sc8nuNt-R17qc-cY`)Fe%LV}U CG#+FC delta 94 zcmaE(@Irw%JtxGCiGhJ3Lx6$d#75rtOt!@(iAg!Bdb#;|`Fi*q9U)Hj8lWkN^O! CDIE3y delta 76 zcmccMdd8JEJtxGCiGhLPj1rJo$jdyLpIKDH!rUy$$kM>r*eEsGEX^p@EXB~=IK{xi e(99^&z$h`%Jk=~Y(Znoevk&trw#^b;J0t+^MHEv2 diff --git a/3D/MapModels/actor_furniture_computertower.glb b/3D/MapModels/actor_furniture_computertower.glb index aceb66b317577df3aaabd54d3b0352428f9c6805..7f18924893d728d0ee3d7b71597ab43fd82afa8f 100644 GIT binary patch delta 81 zcmcbhd_j4`PbPaqz2cI@q?}Z}-2A+Jz5KMa%;e0(9EUVBqqLNylvG1g17p)8?gWY delta 81 zcmcbhd_j4`PbS;qlEkE(RK48%ynMacg~{Gfuec;JDJNAgH$N|5FF!3UGdVLc$05zkC@m!^CDqW>z}Pg|)YRN8 lB{9X)IMvj`%*enn%_POdFg48}Icc*Y^Fp@GS2)+O0sw0)8m#~T delta 82 zcmZpWZ;;>cg~_(KBrz!`RWCO`FJCV|EiE%SGcm`(!rUy$$kM>r*eEsGEX^p@EXB~= mIK{xi(99^&z$h`%Jk=~Y(ZnoevoZ5RHYNpy%~v?rumS*fN*Ve9 diff --git a/3D/MapModels/actor_furniture_triangle.glb b/3D/MapModels/actor_furniture_triangle.glb index 054f461dffc8d248469c061a903f746cbdcb0a04..09de96a069b0cfb604b0c4f58b5151ea42658eda 100644 GIT binary patch delta 64 zcmbQCG(%}aA~U1m8R8tExBLl-UlN1xf U)HH+Sq|Nh~53p@c;M&0k09s)aG5`Po delta 82 zcmbQCG(%}aBC~CANn%n?s$On>UcO#_T3TjuW@3(mg}GUhk)?sLu~BNWS(;I*S&E^# maf*S3p_x&lfl*?jd8%1*qKR3`<^{|L*q9U)HYafHU;_YP4H?7$ diff --git a/3D/MapModels/actor_keypad.glb b/3D/MapModels/actor_keypad.glb index a09ed51ac142260b1962691611aa8e7ca01af143..7fa080f7a35a535bdfd98115a19c5f2b1d899503 100644 GIT binary patch delta 81 zcmX@3a7JOnKPG!az2cI@q?}Z}-2A+Jz5KMa%;e0(9EUVBqqLNylvG1g17p)r TW+|I(nZ4N=6*jkX9c2XoY1uW_v@u;*!LqoK(Hs{Jea<{Is;p8R8tExBLl-UlN1xf)HH+Sq|I&2Y#dAq3Y&YlW7q-i C5FJDS delta 94 zcmaE(`a+dAJtxGCiGhLPg%ATn#YSEmX4~SD#H5^5z1;k~e7*d%w9Mqp#2g0;bF(BP yO9NwLqts-xG^13r6hm|46ax!GGowTUqr^n>RI}tn6SI`f9n5STn8up9{h diff --git a/3D/MapModels/actor_locker.glb b/3D/MapModels/actor_locker.glb index 26c782ea1340fd958526b837868b052f272e7ded..af067a81cad1928f881ee147778bc2c63df3708d 100644 GIT binary patch delta 81 zcmX@2c|>!=KPG!az2cI@q?}Z}-2A+Jz5KMa%;e0(9EUVBqqLNylvG1g17p)!=Kc-2{q8b+FW=Tet2FAulsmW$(MyX~ghUUg81{Q{9Mu`SSiHYW^X32>r TW+|I(na{H^Ds1NF+Q|g~Z+;Sq diff --git a/3D/MapModels/actor_mainframe.glb b/3D/MapModels/actor_mainframe.glb index 39583c21b037cdec2a832d92c4fa2ce768c2a3d5..64d5bd9d8f13352e5406e074f7d1654f426d1d71 100644 GIT binary patch delta 81 zcmX@3e@1`97bbf{z2cI@q?}Z}-2A+Jz5KMa%;e0(9EUVBqqLNylvG1g17p)gDF=8y}86+od&Jb9_$EdKGTYj!N E05n`4zW@LL delta 96 zcmZ3pmT|>eM&9(C5H}_U28I=33=BUu^2!O=7MCO@<)rH6=I7<><)@`(CTAw*I9QmQ zB^g;77#ka8R8tExBLl-UlN1xf)HH+Sq|J&#`2vgzoBNeIMFGlp B9gF|~ delta 94 zcmbPJFr$DsJtxGCiGhJZ!h(UJW+U%)LEGYz#H5^5z1;k~e7*d%w9Mqp#2g0;bF(BP yO9NwLqts-xG^13r6hm|46ax!GGowTUqr^n>RI}tn6SI`f%0l@9o2MvshynmjJsffX diff --git a/3D/MapModels/actor_tank.glb b/3D/MapModels/actor_tank.glb index 6be8ba578f706d3344b1f604c062c499330df2f9..12bb9415a67644266890c042e707e1d1fa847da8 100644 GIT binary patch delta 100 zcmZ2+k8#aCM&9(C5H}_U1_qsc28JCQdFA=+4fTpk5|eUL^>Xv`^7Zo5(lV1X6LTEW z%#6}fl2TF)O%04qlTA&{%~BFmER9o5EzFDz4AV?fObk=g43d*JXY$1hFe+?5E|(Yp E03o{`$p8QV delta 96 zcmZ2;k8#C4M&9(C5H}_U1_q6M28JygdFAR delta 96 zcmbPok7dF=7T)xn5H}_U1_l9rMh1nAysGlH#U+VJIjMTN`FZ(z`DtmH$(e~c4i@HS zNk*0i#>Pge$!2Lrsb(pL=Ef-o7KUagDF=8y}86+od{-qM6#H66G*~k4% F8~{aYAI$&& delta 79 zcmbPphH1tbCf@X%5H}_U1_p^`3=9?Xr5}8oM>W}viXlnkkaM=_cL(-j&~RP diff --git a/3D/MapModels/actor_teleporter.glb b/3D/MapModels/actor_teleporter.glb index c16624bfbfc59d2dabe52c977d897e79ebd7e8b9..b58e863dbb9c6ac25536a9efada6c045e0ab8758 100644 GIT binary patch delta 119 zcmaE&`a+dAJtxGCiGhLPg%ATn#YSEmW_v@u;*!LqoK(Hs{Jea<{Is;p8R8tExBLl-UlN1xf)HH+Sq|I&2-mLs4#^#2G#ugSv X7G~zg=9ZfuaI9crRM_0k9m@^?XqO_w delta 123 zcmaE%`b3pCJtxGCiGhLPi4X%r$wpoqX4~SD#H5^5z1;k~e7*d%w9Mqp#2g0;bF(BP zO9NwLqts-xG^13r6hm|46ax!GGowTUqr^n>RI}tn6SI`f9n9XW!sezXmgbfQhDK&4 b1}4VFv9&tYljB*XH#2f}GHveRj$sD?*M}oD diff --git a/3D/MapModels/actor_terminal_big.glb b/3D/MapModels/actor_terminal_big.glb index e213b7def7c0e1b0f163743f2b727e04f10ffd68..578d934c769155b9906e7ae694fbe4c9d1fc1c1c 100644 GIT binary patch delta 119 zcmccMc*T)7JtxGCiGhLPiUI?}i;cXmnCuPpic1oca#Hnj^Yilc^3&2XlQR=@9Ma5; z(o&LAQVmTFj7^hGP0h_x5>qUVQ%x<*j0_CZOj1k?Q_~ERlQx?$e`n!0F*Y|eG`6rX XvM@6@Hn-et#j%f(QDO6U&YNNY;^ic& delta 115 zcmccOc)^i3JtxGCiGhLPf&v4>la0Kum~4wn5|eUL^>Xv`^7Zo5(lV1X6LTCa%*~RF zEDel}jZ%}%(u`8gQVh+FQw%H&&5RNaj1m*gQ_YeSP0Ug@n=yZ9;Wsxmu{5_dFf=kV TF)%SU-fY9Mk8$%K&KqI?L4_lQ diff --git a/3D/MapModels/actor_tube_corner.glb b/3D/MapModels/actor_tube_corner.glb index 0d82b475110d3adee40029dc3219b59bd48e1339..d4ce7c71c33dc2008048e283752bac2947aef058 100644 GIT binary patch delta 83 zcmccdf$_!%#tr|N><#sbOA?cEQuT84^YZob)6z1NGZS+h(#(v~Qj$_q4NVPbjp7@8R+8W<%enx~p2 WCz_b0Y_?_gXJ=AS*xbW)CKmwi?G)Mo diff --git a/3D/MapModels/actor_tube_junction.glb b/3D/MapModels/actor_tube_junction.glb index e624301bf1455b8efd836003e5811c6f5786b58e..cc43f2ab53c5c8ee59c07a0fe25b29ddad68b18c 100644 GIT binary patch delta 83 zcmey+%lM&}al>y`dqchAlEkE(RK48%ynMay`+v1YMq?}Z}-2A+Jz5KMa%;e0(90vQetyhDU1 F2LNfZANv3R delta 96 zcmX@n$aJKUi8nnb#Epr8f#FC41H+Pyylot|#U+VJIjMTN`FZ(z`DtmH$(e~c4i@HS zNk*0i#>Pge$!2Lrsb(pL=Ef-o7KUaQetd_aUJ F2LN^JAS?g? delta 96 zcmcc6$aJQWi8nnb#Epr8f#FO81H+n)yzLye#U+VJIjMTN`FZ(z`DtmH$(e~c4i@HS zNk*0i#>Pge$!2Lrsb(pL=Ef-o7KUa8R8tExBLl-UlN1xf)HH+Sq|Fk{Us(7}jLi)VjV&yU YEX>S}%`G=ebL?egQc&1@gVTf!05E7F-T(jq delta 115 zcmbQB(4)Yco)hB6#K6G7Bf!9LWFzl6CfnkY#H5^5z1;k~e7*d%w9Mqp#2g0;bF(BP zO9NwLqts-xG^13r6hm|46ax!GGowTUqr^n>RI}tn6SI`fQp{gi_{~jCEX^$q42{f8 T3`~rTH_LMDW!!v+(}WEGb|xU0 diff --git a/3D/MapModels/actor_wallfan.glb b/3D/MapModels/actor_wallfan.glb index 1014445f011571839943b67d304513f8c2f9b8cc..2969d49912f457bac64056b5f4c2265664ce0e1f 100644 GIT binary patch delta 84 zcmdnc%e1AJi8nnb#Epr8fniG<14GM3-YbfXhLayCifN>o8KtEprKB2~8W@`C%urkSLe7^bEfBqwc_Q!0~VQc&1D#X-gm04QG=bN~PV delta 96 zcmdne%e0}Fi8nnb#Epr8fnh@%14F|`-Ybf>#U+VJIjMTN`FZ(z`DtmH$(e~c4i@HS zNk*0i#>Pge$!2Lrsb(pL=Ef-o7KUaHq)$ diff --git a/3D/Maps/Fusion.map b/3D/Maps/Fusion.map index d71c6fe3..333e357c 100644 --- a/3D/Maps/Fusion.map +++ b/3D/Maps/Fusion.map @@ -381,12 +381,12 @@ ( -224 376 16 ) ( -223 376 16 ) ( -224 377 16 ) __TB_empty [ -1 0 0 -8 ] [ 0 -1 0 -8 ] 0 1 1 ( -104 384 48 ) ( -104 385 48 ) ( -103 384 48 ) __TB_empty [ 1 0 0 8 ] [ 0 -1 0 -8 ] 270 1 1 ( -104 384 24 ) ( -103 384 24 ) ( -104 384 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 0 1 1 -( -152 376 16 ) ( -152 376 17 ) ( -152 377 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -256 376 16 ) ( -256 376 17 ) ( -256 377 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 } // brush 42 { -( -568 392 -16 ) ( -568 393 -16 ) ( -568 392 -15 ) __TB_empty [ 0 -1 0 8 ] [ 0 0 -1 0 ] 0 1 1 -( -520 384 -16 ) ( -520 384 -15 ) ( -519 384 -16 ) __TB_empty [ 1 0 0 8 ] [ 0 0 -1 0 ] 90 1 1 +( -256 520 16 ) ( -256 521 16 ) ( -256 520 17 ) __TB_empty [ 0 1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +( -392 624 16 ) ( -392 624 17 ) ( -391 624 16 ) __TB_empty [ -1 0 0 -8 ] [ 0 0 -1 0 ] 0 1 1 ( -520 392 8 ) ( -519 392 8 ) ( -520 393 8 ) __TB_empty [ -1 0 0 -8 ] [ 0 -1 0 8 ] 180 1 1 ( -392 520 16 ) ( -392 521 16 ) ( -391 520 16 ) Floors/Floor283 [ 1 0 0 8 ] [ 0 -1 0 -8 ] 270 1 1 ( -392 936 16 ) ( -391 936 16 ) ( -392 936 17 ) __TB_empty [ -1 0 0 -8 ] [ 0 0 -1 0 ] 90 1 1 @@ -421,12 +421,12 @@ } // brush 46 { -( -144 280 16 ) ( -144 281 16 ) ( -144 280 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -4 280 16 ) ( -4 281 16 ) ( -4 280 17 ) Walls/Wallside_001 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 270 1 1 ( -48 280 16 ) ( -48 280 17 ) ( -47 280 16 ) __TB_empty [ 1 0 0 24 ] [ 0 0 -1 0 ] 0 1 1 ( -48 280 16 ) ( -47 280 16 ) ( -48 281 16 ) __TB_empty [ -1 0 0 -24 ] [ 0 -1 0 -8 ] 0 1 1 ( 72 288 48 ) ( 72 289 48 ) ( 73 288 48 ) __TB_empty [ 1 0 0 24 ] [ 0 -1 0 -8 ] 270 1 1 -( 72 288 24 ) ( 73 288 24 ) ( 72 288 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 -8 ] [ 0 0 -1 -16 ] 0 1 1 -( 0 280 16 ) ( 0 280 17 ) ( 0 281 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( 72 288 24 ) ( 73 288 24 ) ( 72 288 25 ) Walls/Wallside_002 [ -1 0 0 -8 ] [ 0 0 -1 -16 ] 0 1 1 +( 0 280 16 ) ( 0 280 17 ) ( 0 281 16 ) Walls/Wallside_002 [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 } // brush 47 { @@ -439,12 +439,12 @@ } // brush 48 { -( -144 296 -16 ) ( -144 297 -16 ) ( -144 296 -15 ) __TB_empty [ 0 -1 0 8 ] [ 0 0 -1 0 ] 180 1 1 -( -96 288 -16 ) ( -96 288 -15 ) ( -95 288 -16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 -( -96 296 8 ) ( -95 296 8 ) ( -96 297 8 ) __TB_empty [ -1 0 0 0 ] [ 0 -1 0 8 ] 0 1 1 -( 32 424 16 ) ( 32 425 16 ) ( 33 424 16 ) Floors/Floor283 [ 1 0 0 0 ] [ 0 -1 0 -8 ] 90 1 1 -( 32 408 16 ) ( 33 408 16 ) ( 32 408 17 ) __TB_empty [ -1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 -( 48 424 16 ) ( 48 424 17 ) ( 48 425 16 ) __TB_empty [ 0 1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -144 296 -16 ) ( -144 297 -16 ) ( -144 296 -15 ) Floors/Floor134 [ 0 -1 0 8 ] [ 0 0 -1 0 ] 180 1 1 +( -96 288 -16 ) ( -96 288 -15 ) ( -95 288 -16 ) Floors/Floor134 [ 1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( -96 296 8 ) ( -95 296 8 ) ( -96 297 8 ) Floors/Floor134 [ -1 0 0 0 ] [ 0 -1 0 8 ] 0 1 1 +( 32 424 16 ) ( 32 425 16 ) ( 33 424 16 ) Floors/Floor134 [ 1 0 0 0 ] [ 0 -1 0 -8 ] 90 1 1 +( 32 408 16 ) ( 33 408 16 ) ( 32 408 17 ) Floors/Floor134 [ -1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( 48 424 16 ) ( 48 424 17 ) ( 48 425 16 ) Floors/Floor134 [ 0 1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 } // brush 49 { @@ -457,23 +457,14 @@ } // brush 50 { -( 40 336 8 ) ( 40 337 8 ) ( 40 336 9 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 -( 40 280 8 ) ( 40 280 9 ) ( 41 280 8 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 0 -1 -16 ] 90 1 1 -( 40 336 16 ) ( 41 336 16 ) ( 40 337 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 -1 0 8 ] 180 1 1 -( 48 456 48 ) ( 48 457 48 ) ( 49 456 48 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 -1 0 8 ] 270 1 1 -( 48 536 16 ) ( 49 536 16 ) ( 48 536 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 -( 48 456 16 ) ( 48 456 17 ) ( 48 457 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 8 ] [ 0 0 -1 -16 ] 270 1 1 -} -// brush 51 -{ -( 32 280 16 ) ( 32 281 16 ) ( 32 280 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( 32 280 16 ) ( 32 281 16 ) ( 32 280 17 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 ( -8 280 16 ) ( -8 280 17 ) ( -7 280 16 ) __TB_empty [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 1 1 ( -8 280 16 ) ( -7 280 16 ) ( -8 281 16 ) __TB_empty [ -1 0 0 16 ] [ 0 -1 0 -8 ] 180 1 1 ( 112 288 48 ) ( 112 289 48 ) ( 113 288 48 ) __TB_empty [ 1 0 0 -16 ] [ 0 -1 0 -8 ] 90 1 1 -( 112 288 24 ) ( 113 288 24 ) ( 112 288 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 -( 40 280 16 ) ( 40 280 17 ) ( 40 281 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +( 112 288 24 ) ( 113 288 24 ) ( 112 288 25 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 +( 36 280 16 ) ( 36 280 17 ) ( 36 281 16 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 } -// brush 52 +// brush 51 { ( 128 288 8 ) ( 128 289 8 ) ( 128 288 9 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 -1 0 8 ] [ 0 0 -1 -16 ] 90 1 1 ( 128 160 8 ) ( 128 160 9 ) ( 129 160 8 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 -8 ] [ 0 0 -1 -16 ] 180 1 1 @@ -482,7 +473,7 @@ ( 136 808 16 ) ( 137 808 16 ) ( 136 808 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 90 1 1 ( 136 408 16 ) ( 136 408 17 ) ( 136 409 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 -8 ] [ 0 0 -1 -16 ] 90 1 1 } -// brush 53 +// brush 52 { ( 136 128 -16 ) ( 136 128 -15 ) ( 136 127 -16 ) __TB_empty [ -1.0718754395722282e-15 -1 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( 240 16 16 ) ( 240 16 17 ) ( 241 16 16 ) __TB_empty [ 1 -1.0718754395722282e-15 0 16 ] [ 0 0 -1 0 ] 90 1 1 @@ -491,7 +482,7 @@ ( 112 440 -16 ) ( 113 440 -16 ) ( 112 440 -15 ) __TB_empty [ -1 1.0718754395722282e-15 0 -16 ] [ 0 0 -1 0 ] 90 1 1 ( 288 0 16 ) ( 288 -1 16 ) ( 288 0 17 ) __TB_empty [ 1.0718754395722282e-15 1 0 0 ] [ 0 0 -1 0 ] 90 1 1 } -// brush 54 +// brush 53 { ( 288 192 8 ) ( 288 193 8 ) ( 288 192 9 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 ( 288 24 8 ) ( 288 24 9 ) ( 289 24 8 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 -8 ] [ 0 0 -1 -16 ] 0 1 1 @@ -500,7 +491,7 @@ ( 296 424 16 ) ( 297 424 16 ) ( 296 424 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 180 1 1 ( 296 312 16 ) ( 296 312 17 ) ( 296 313 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 8 ] [ 0 0 -1 -16 ] 270 1 1 } -// brush 55 +// brush 54 { ( 72 152 16 ) ( 72 153 16 ) ( 72 152 17 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 0 1 1 ( 168 152 16 ) ( 168 152 17 ) ( 169 152 16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 @@ -509,16 +500,16 @@ ( 288 160 24 ) ( 289 160 24 ) ( 288 160 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 ( 288 152 16 ) ( 288 152 17 ) ( 288 153 16 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 180 1 1 } -// brush 56 +// brush 55 { -( -144 408 16 ) ( -144 409 16 ) ( -144 408 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 -( -48 408 16 ) ( -48 408 17 ) ( -47 408 16 ) __TB_empty [ 1 0 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +( 0 408 16 ) ( 0 409 16 ) ( 0 408 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +( -48 408 16 ) ( -48 408 17 ) ( -47 408 16 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 0 1 1 ( -48 408 16 ) ( -47 408 16 ) ( -48 409 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 -8 ] 0 1 1 ( 72 416 48 ) ( 72 417 48 ) ( 73 416 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 -8 ] 270 1 1 -( 72 416 24 ) ( 73 416 24 ) ( 72 416 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 0 1 1 +( 72 416 24 ) ( 73 416 24 ) ( 72 416 25 ) Manual/Wall_Backrooms_003 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 0 1 1 ( 40 408 16 ) ( 40 408 17 ) ( 40 409 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 } -// brush 57 +// brush 56 { ( -264 280 16 ) ( -264 281 16 ) ( -264 280 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 ( -264 384 16 ) ( -264 384 17 ) ( -263 384 16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 @@ -527,52 +518,43 @@ ( -256 632 24 ) ( -255 632 24 ) ( -256 632 25 ) __TB_empty [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( -256 408 24 ) ( -256 408 25 ) ( -256 409 24 ) Manual/Wall_Metal_Fusion_002 [ 0 1 0 8 ] [ 0 0 -1 -16 ] 270 1 1 } -// brush 58 +// brush 57 { ( -256 624 16 ) ( -256 625 16 ) ( -256 624 17 ) __TB_empty [ 0 -1 0 16 ] [ 0 0 -1 0 ] 180 1 1 -( -216 624 16 ) ( -216 624 17 ) ( -215 624 16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -216 624 16 ) ( -216 624 17 ) ( -215 624 16 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( -216 624 16 ) ( -215 624 16 ) ( -216 625 16 ) __TB_empty [ -1 0 0 0 ] [ 0 -1 0 16 ] 180 1 1 ( -96 632 48 ) ( -96 633 48 ) ( -95 632 48 ) __TB_empty [ 1 0 0 0 ] [ 0 -1 0 16 ] 90 1 1 ( -96 632 24 ) ( -95 632 24 ) ( -96 632 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 ( -144 624 16 ) ( -144 624 17 ) ( -144 625 16 ) __TB_empty [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 1 1 } -// brush 59 +// brush 58 { -( -144 424 -16 ) ( -144 425 -16 ) ( -144 424 -15 ) __TB_empty [ 0 -1 0 8 ] [ 0 0 -1 0 ] 90 1 1 +( -8 552 16 ) ( -8 553 16 ) ( -8 552 17 ) __TB_empty [ 0 1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 ( -96 416 -16 ) ( -96 416 -15 ) ( -95 416 -16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( -96 424 8 ) ( -95 424 8 ) ( -96 425 8 ) __TB_empty [ -1 0 0 0 ] [ 0 -1 0 8 ] 270 1 1 -( 32 552 16 ) ( 32 553 16 ) ( 33 552 16 ) Floors/Floor283 [ 1 0 0 0 ] [ 0 -1 0 -8 ] 0 1 1 +( 32 552 16 ) ( 32 553 16 ) ( 33 552 16 ) Floors/Floor133 [ 1 0 0 0 ] [ 0 -1 0 -8 ] 0 1 1 ( 32 536 16 ) ( 33 536 16 ) ( 32 536 17 ) __TB_empty [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( 48 552 16 ) ( 48 552 17 ) ( 48 553 16 ) __TB_empty [ 0 1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 } -// brush 60 +// brush 59 { -( -80 472 8 ) ( -80 473 8 ) ( -80 472 9 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 180 1 1 +( -80 472 8 ) ( -80 473 8 ) ( -80 472 9 ) special/clip [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 180 1 1 ( -80 416 8 ) ( -80 416 9 ) ( -79 416 8 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 8 ] [ 0 0 -1 -16 ] 0 1 1 ( -80 472 16 ) ( -79 472 16 ) ( -80 473 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 -8 ] [ 0 -1 0 -16 ] 90 1 1 ( -72 592 48 ) ( -72 593 48 ) ( -71 592 48 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 8 ] [ 0 -1 0 -16 ] 180 1 1 ( -72 536 16 ) ( -71 536 16 ) ( -72 536 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 -8 ] [ 0 0 -1 -16 ] 0 1 1 -( -72 592 16 ) ( -72 592 17 ) ( -72 593 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 180 1 1 +( -72 592 16 ) ( -72 592 17 ) ( -72 593 16 ) Floors/Floor234 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 180 1 1 } -// brush 61 +// brush 60 { -( -8 472 8 ) ( -8 473 8 ) ( -8 472 9 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -8 472 8 ) ( -8 473 8 ) ( -8 472 9 ) special/clip [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 ( -8 416 8 ) ( -8 416 9 ) ( -7 416 8 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 ( -8 472 16 ) ( -7 472 16 ) ( -8 473 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 -1 0 -16 ] 270 1 1 ( 0 592 48 ) ( 0 593 48 ) ( 1 592 48 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 -1 0 -16 ] 0 1 1 ( 0 536 16 ) ( 1 536 16 ) ( 0 536 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 -( 0 592 16 ) ( 0 592 17 ) ( 0 593 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( 0 592 16 ) ( 0 592 17 ) ( 0 593 16 ) Manual/Wall_Backrooms_003 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 } -// brush 62 -{ -( -144 536 16 ) ( -144 537 16 ) ( -144 536 17 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 90 1 1 -( -48 536 16 ) ( -48 536 17 ) ( -47 536 16 ) __TB_empty [ 1 0 0 -8 ] [ 0 0 -1 0 ] 270 1 1 -( -48 536 16 ) ( -47 536 16 ) ( -48 537 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 24 ] 270 1 1 -( 72 544 48 ) ( 72 545 48 ) ( 73 544 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 24 ] 180 1 1 -( 72 544 24 ) ( 73 544 24 ) ( 72 544 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 270 1 1 -( 48 536 16 ) ( 48 536 17 ) ( 48 537 16 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 90 1 1 -} -// brush 63 +// brush 61 { ( -144 672 -16 ) ( -144 672 -15 ) ( -144 671 -16 ) __TB_empty [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 ( 88 544 16 ) ( 88 544 17 ) ( 89 544 16 ) __TB_empty [ 1 -1.8369701987210297e-16 0 8 ] [ 0 0 -1 0 ] 180 1 1 @@ -581,16 +563,16 @@ ( -40 624 -16 ) ( -39 624 -16 ) ( -40 624 -15 ) __TB_empty [ -1 1.8369701987210297e-16 0 -8 ] [ 0 0 -1 0 ] 0 1 1 ( 48 544 16 ) ( 48 543 16 ) ( 48 544 17 ) __TB_empty [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 } -// brush 64 +// brush 62 { ( -144 624 16 ) ( -144 625 16 ) ( -144 624 17 ) __TB_empty [ 0 -1 0 16 ] [ 0 0 -1 0 ] 90 1 1 -( -48 624 16 ) ( -48 624 17 ) ( -47 624 16 ) __TB_empty [ 1 0 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -48 624 16 ) ( -48 624 17 ) ( -47 624 16 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 270 1 1 ( -48 624 16 ) ( -47 624 16 ) ( -48 625 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 16 ] 270 1 1 ( 72 632 48 ) ( 72 633 48 ) ( 73 632 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 16 ] 180 1 1 ( 72 632 24 ) ( 73 632 24 ) ( 72 632 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 270 1 1 ( 48 624 16 ) ( 48 624 17 ) ( 48 625 16 ) __TB_empty [ 0 -1 0 16 ] [ 0 0 -1 0 ] 90 1 1 } -// brush 65 +// brush 63 { ( -256 928 16 ) ( -256 929 16 ) ( -256 928 17 ) __TB_empty [ 0 -1 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( -216 928 16 ) ( -216 928 17 ) ( -215 928 16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 @@ -599,7 +581,7 @@ ( -96 936 24 ) ( -95 936 24 ) ( -96 936 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 ( -144 928 16 ) ( -144 928 17 ) ( -144 929 16 ) __TB_empty [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 } -// brush 66 +// brush 64 { ( -256 832 16 ) ( -256 833 16 ) ( -256 832 17 ) __TB_empty [ 0 -1 0 0 ] [ 0 0 -1 0 ] 90 1 1 ( -256 936 16 ) ( -256 936 17 ) ( -255 936 16 ) __TB_empty [ 1 0 0 -8 ] [ 0 0 -1 0 ] 180 1 1 @@ -608,7 +590,7 @@ ( -248 1184 24 ) ( -247 1184 24 ) ( -248 1184 25 ) __TB_empty [ -1 0 0 8 ] [ 0 0 -1 0 ] 0 1 1 ( -248 960 24 ) ( -248 960 25 ) ( -248 961 24 ) Manual/Wall_Metal_Fusion_002 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 90 1 1 } -// brush 67 +// brush 65 { ( -152 992 8 ) ( -152 993 8 ) ( -152 992 9 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 180 1 1 ( -152 936 8 ) ( -152 936 9 ) ( -151 936 8 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 0 -1 -16 ] 0 1 1 @@ -617,7 +599,7 @@ ( -144 1184 16 ) ( -143 1184 16 ) ( -144 1184 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 90 1 1 ( -144 1112 16 ) ( -144 1112 17 ) ( -144 1113 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 8 ] [ 0 0 -1 -16 ] 180 1 1 } -// brush 68 +// brush 66 { ( -144 152 16 ) ( -144 153 16 ) ( -144 152 17 ) special/clip [ 0 -1 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( -144 160 16 ) ( -144 160 17 ) ( -143 160 16 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 @@ -626,7 +608,7 @@ ( -40 168 24 ) ( -39 168 24 ) ( -40 168 25 ) Floors/Floor242 [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( -40 168 24 ) ( -40 168 25 ) ( -40 169 24 ) special/clip [ 0 1 0 0 ] [ 0 0 -1 0 ] 180 1 1 } -// brush 69 +// brush 67 { ( -104 160 24 ) ( -104 161 24 ) ( -104 160 25 ) Manual/Glass_001 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 270 1 1 ( -112 160 24 ) ( -112 160 25 ) ( -111 160 24 ) Manual/Glass_001 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 @@ -635,7 +617,7 @@ ( -80 168 32 ) ( -79 168 32 ) ( -80 168 33 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 ( -80 168 32 ) ( -80 168 33 ) ( -80 169 32 ) Manual/Glass_001 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 } -// brush 70 +// brush 68 { ( -80 160 24 ) ( -80 161 24 ) ( -80 160 25 ) Walls/Wallside_002 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 ( -80 160 24 ) ( -80 160 25 ) ( -79 160 24 ) Walls/Wallside_002 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 @@ -644,7 +626,7 @@ ( -72 168 32 ) ( -71 168 32 ) ( -72 168 33 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 ( -72 168 32 ) ( -72 168 33 ) ( -72 169 32 ) Walls/Wallside_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 } -// brush 71 +// brush 69 { ( -152 160 48 ) ( -152 161 48 ) ( -152 160 49 ) special/clip [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 ( -152 160 48 ) ( -152 160 49 ) ( -151 160 48 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 @@ -653,7 +635,7 @@ ( -72 168 56 ) ( -71 168 56 ) ( -72 168 57 ) Walls/WallTop_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 ( -32 168 56 ) ( -32 168 57 ) ( -32 169 56 ) Walls/WallTop_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 } -// brush 72 +// brush 70 { ( -112 160 24 ) ( -112 161 24 ) ( -112 160 25 ) Floors/Floor242 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 270 1 1 ( -112 160 24 ) ( -112 160 25 ) ( -111 160 24 ) Floors/Floor242 [ 1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 @@ -662,7 +644,7 @@ ( -104 168 32 ) ( -103 168 32 ) ( -104 168 33 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 ( -104 168 32 ) ( -104 168 33 ) ( -104 169 32 ) Floors/Floor242 [ 0 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 } -// brush 73 +// brush 71 { ( -72 160 24 ) ( -72 161 24 ) ( -72 160 25 ) Manual/Glass_001 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( -72 160 24 ) ( -72 160 25 ) ( -71 160 24 ) Manual/Glass_001 [ 1 0 0 -8 ] [ 0 0 -1 0 ] 180 1 1 @@ -671,7 +653,7 @@ ( -40 168 32 ) ( -39 168 32 ) ( -40 168 33 ) Manual/Glass_001 [ -1 0 0 8 ] [ 0 0 -1 0 ] 180 1 1 ( -48 168 32 ) ( -48 168 33 ) ( -48 169 32 ) Manual/Glass_001 [ 0 1 0 0 ] [ 0 0 -1 0 ] 90 1 1 } -// brush 74 +// brush 72 { ( -136 160 24 ) ( -136 161 24 ) ( -136 160 25 ) Manual/Glass_001 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 270 1 1 ( -144 160 24 ) ( -144 160 25 ) ( -143 160 24 ) Manual/Glass_001 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 @@ -680,7 +662,7 @@ ( -112 168 32 ) ( -111 168 32 ) ( -112 168 33 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 ( -112 168 32 ) ( -112 168 33 ) ( -112 169 32 ) Manual/Glass_001 [ 0 1 0 0 ] [ 0 0 -1 0 ] 180 1 1 } -// brush 75 +// brush 73 { ( -48 160 24 ) ( -48 161 24 ) ( -48 160 25 ) Walls/Wallside_002 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 270 1 1 ( -48 160 24 ) ( -48 160 25 ) ( -47 160 24 ) Walls/Wallside_002 [ 1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 @@ -689,7 +671,7 @@ ( -40 168 32 ) ( -39 168 32 ) ( -40 168 33 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 ( -40 168 32 ) ( -40 168 33 ) ( -40 169 32 ) Walls/Wallside_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 } -// brush 76 +// brush 74 { ( -144 160 24 ) ( -144 161 24 ) ( -144 160 25 ) Walls/Wallside_002 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 90 1 1 ( -144 160 24 ) ( -144 160 25 ) ( -143 160 24 ) Walls/Wallside_002 [ 1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 @@ -698,7 +680,7 @@ ( -136 168 32 ) ( -135 168 32 ) ( -136 168 33 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 ( -136 168 32 ) ( -136 168 33 ) ( -136 169 32 ) Walls/Wallside_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 90 1 1 } -// brush 77 +// brush 75 { ( -152 288 48 ) ( -152 288 49 ) ( -152 287 48 ) special/clip [ -1.8369701987210297e-16 -1 0 8 ] [ 0 0 -1 0 ] 0 1 1 ( -144 168 56 ) ( -144 168 57 ) ( -143 168 56 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 270 1 1 @@ -707,16 +689,16 @@ ( -152 280 48 ) ( -151 280 48 ) ( -152 280 49 ) special/clip [ -1 1.8369701987210297e-16 0 -24 ] [ 0 0 -1 0 ] 270 1 1 ( -144 208 56 ) ( -144 207 56 ) ( -144 208 57 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 } -// brush 78 +// brush 76 { -( -152 152 8 ) ( -152 153 8 ) ( -152 152 9 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 -( -144 288 16 ) ( -144 288 17 ) ( -143 288 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 -( -152 152 16 ) ( -151 152 16 ) ( -152 153 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 -1 0 -16 ] 270 1 1 -( -144 272 48 ) ( -144 273 48 ) ( -143 272 48 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 -1 0 -16 ] 0 1 1 -( -144 624 16 ) ( -143 624 16 ) ( -144 624 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 0 1 1 -( -144 272 16 ) ( -144 272 17 ) ( -144 273 16 ) Manual/Wall_Metal_Fusion_002 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -152 152 8 ) ( -152 153 8 ) ( -152 152 9 ) Manual/Glass_001 [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -144 384 16 ) ( -144 384 17 ) ( -143 384 16 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 +( -152 152 20 ) ( -151 152 20 ) ( -152 153 20 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 -1 0 0 ] 90 1 1 +( -144 272 44 ) ( -144 273 44 ) ( -143 272 44 ) Manual/Glass_001 [ 1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1 +( -144 408 16 ) ( -143 408 16 ) ( -144 408 17 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -144 272 16 ) ( -144 272 17 ) ( -144 273 16 ) Manual/Glass_001 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 } -// brush 79 +// brush 77 { ( -152 152 8 ) ( -152 153 8 ) ( -152 152 9 ) special/clip [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 ( -152 160 8 ) ( -152 160 9 ) ( -151 160 8 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 -16 ] 90 1 1 @@ -725,7 +707,7 @@ ( -144 288 16 ) ( -143 288 16 ) ( -144 288 17 ) special/clip [ -1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 ( -144 272 16 ) ( -144 272 17 ) ( -144 273 16 ) Manual/Wall_Metal_Fusion_002 [ 0 1 0 -8 ] [ 0 0 -1 -16 ] 0 1 1 } -// brush 80 +// brush 78 { ( -40 144 8 ) ( -40 145 8 ) ( -40 144 9 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 ( -40 160 8 ) ( -40 160 9 ) ( -39 160 8 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 @@ -734,7 +716,7 @@ ( -40 168 8 ) ( -39 168 8 ) ( -40 168 9 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 ( -32 264 16 ) ( -32 264 17 ) ( -32 265 16 ) Walls/Wallside_002 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 270 1 1 } -// brush 81 +// brush 79 { ( -40 288 48 ) ( -40 288 49 ) ( -40 287 48 ) special/clip [ -1.8369701987210297e-16 -1 0 8 ] [ 0 0 -1 0 ] 90 1 1 ( -32 168 56 ) ( -32 168 57 ) ( -31 168 56 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 0 1 1 @@ -743,7 +725,7 @@ ( -40 280 48 ) ( -39 280 48 ) ( -40 280 49 ) special/clip [ -1 1.8369701987210297e-16 0 24 ] [ 0 0 -1 0 ] 0 1 1 ( -32 208 56 ) ( -32 207 56 ) ( -32 208 57 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 90 1 1 } -// brush 82 +// brush 80 { ( -40 144 8 ) ( -40 145 8 ) ( -40 144 9 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 ( -40 168 8 ) ( -40 168 9 ) ( -39 168 8 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 @@ -752,7 +734,7 @@ ( -40 184 8 ) ( -39 184 8 ) ( -40 184 9 ) Walls/Wallside_002 [ 1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 ( -32 264 16 ) ( -32 264 17 ) ( -32 265 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 } -// brush 83 +// brush 81 { ( -40 144 8 ) ( -40 145 8 ) ( -40 144 9 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 ( -40 216 8 ) ( -40 216 9 ) ( -39 216 8 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 -16 ] 90 1 1 @@ -761,7 +743,7 @@ ( -40 232 8 ) ( -39 232 8 ) ( -40 232 9 ) Walls/Wallside_002 [ 1 0 0 0 ] [ 0 0 -1 -16 ] 0 1 1 ( -32 264 16 ) ( -32 264 17 ) ( -32 265 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 } -// brush 84 +// brush 82 { ( -40 144 8 ) ( -40 145 8 ) ( -40 144 9 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 ( -40 264 8 ) ( -40 264 9 ) ( -39 264 8 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 @@ -770,14 +752,374 @@ ( -32 280 16 ) ( -31 280 16 ) ( -32 280 17 ) special/clip [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 ( -32 264 16 ) ( -32 264 17 ) ( -32 265 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 } -// brush 85 +// brush 83 { ( -152 280 48 ) ( -152 281 48 ) ( -152 280 49 ) special/clip [ 0 -1 0 24 ] [ 0 0 -1 0 ] 180 1 1 ( -152 280 48 ) ( -152 280 49 ) ( -151 280 48 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 ( -152 280 48 ) ( -151 280 48 ) ( -152 281 48 ) special/clip [ -1 0 0 0 ] [ 0 -1 0 24 ] 180 1 1 ( -72 288 52 ) ( -72 289 52 ) ( -71 288 52 ) Manual/Black [ 1 0 0 0 ] [ 0 -1 0 0 ] 90 1 1 ( -72 288 56 ) ( -71 288 56 ) ( -72 288 57 ) Walls/WallTop_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 -( -32 288 56 ) ( -32 288 57 ) ( -32 289 56 ) Walls/WallTop_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( 48 288 56 ) ( 48 288 57 ) ( 48 289 56 ) Walls/WallTop_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 84 +{ +( -80 320 16 ) ( -80 321 16 ) ( -80 320 17 ) Floors/Floor111 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -80 328 16 ) ( -80 328 17 ) ( -79 328 16 ) Floors/Floor111 [ 1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( -80 320 16 ) ( -79 320 16 ) ( -80 321 16 ) Floors/Floor111 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 16 368 32 ) ( 16 369 32 ) ( 17 368 32 ) Floors/Floor111 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 16 368 32 ) ( 17 368 32 ) ( 16 368 33 ) Floors/Floor111 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 0 368 32 ) ( 0 368 33 ) ( 0 369 32 ) Floors/Floor111 [ 0 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 +} +// brush 85 +{ +( -152 408 48 ) ( -152 408 49 ) ( -152 407 48 ) special/clip [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -144 288 56 ) ( -144 288 57 ) ( -143 288 56 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -152 408 48 ) ( -152 407 48 ) ( -151 408 48 ) special/clip [ 1.8369701987210297e-16 1 0 0 ] [ -1 1.8369701987210297e-16 0 8 ] 0 1 1 +( -144 328 52 ) ( -143 328 52 ) ( -144 327 52 ) Manual/Black [ -1.8369701987210297e-16 -1 0 0 ] [ -1 1.8369701987210297e-16 0 0 ] 90 1 1 +( -152 408 48 ) ( -151 408 48 ) ( -152 408 49 ) special/clip [ -1 1.8369701987210297e-16 0 8 ] [ 0 0 -1 0 ] 270 1 1 +( -144 328 56 ) ( -144 327 56 ) ( -144 328 57 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 90 1 1 +} +// brush 86 +{ +( -152 408 48 ) ( -152 409 48 ) ( -152 408 49 ) special/clip [ 0 -1 0 24 ] [ 0 0 -1 0 ] 180 1 1 +( -152 408 48 ) ( -152 408 49 ) ( -151 408 48 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -152 408 48 ) ( -151 408 48 ) ( -152 409 48 ) special/clip [ -1 0 0 0 ] [ 0 -1 0 24 ] 180 1 1 +( -72 416 52 ) ( -72 417 52 ) ( -71 416 52 ) Manual/Black [ 1 0 0 0 ] [ 0 -1 0 0 ] 90 1 1 +( -72 416 56 ) ( -71 416 56 ) ( -72 416 57 ) Walls/WallTop_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( 48 416 56 ) ( 48 416 57 ) ( 48 417 56 ) Walls/WallTop_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 87 +{ +( 40 408 48 ) ( 40 408 49 ) ( 40 407 48 ) special/clip [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 48 288 56 ) ( 48 288 57 ) ( 49 288 56 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( 40 408 48 ) ( 40 407 48 ) ( 41 408 48 ) special/clip [ 1.8369701987210297e-16 1 0 0 ] [ -1 1.8369701987210297e-16 0 8 ] 270 1 1 +( 48 328 52 ) ( 49 328 52 ) ( 48 327 52 ) Manual/Black [ -1.8369701987210297e-16 -1 0 0 ] [ -1 1.8369701987210297e-16 0 0 ] 0 1 1 +( 40 408 48 ) ( 41 408 48 ) ( 40 408 49 ) special/clip [ -1 1.8369701987210297e-16 0 8 ] [ 0 0 -1 0 ] 180 1 1 +( 48 328 56 ) ( 48 327 56 ) ( 48 328 57 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 88 +{ +( -152 152 8 ) ( -152 153 8 ) ( -152 152 9 ) special/clip [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -144 536 16 ) ( -144 536 17 ) ( -143 536 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 +( -152 152 16 ) ( -151 152 16 ) ( -152 153 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 -1 0 -16 ] 270 1 1 +( -144 272 48 ) ( -144 273 48 ) ( -143 272 48 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 -1 0 -16 ] 0 1 1 +( -144 624 16 ) ( -143 624 16 ) ( -144 624 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -144 272 16 ) ( -144 272 17 ) ( -144 273 16 ) Manual/Wall_Metal_Fusion_002 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +} +// brush 89 +{ +( -152 152 8 ) ( -152 153 8 ) ( -152 152 9 ) Manual/Wall_Metal_Fusion_Grate_001 [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -144 380 16 ) ( -144 380 17 ) ( -143 380 16 ) Walls/Wallside_001 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -152 152 16 ) ( -151 152 16 ) ( -152 153 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 -1 0 -16 ] 270 1 1 +( -144 272 48 ) ( -144 273 48 ) ( -143 272 48 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 -1 0 -16 ] 0 1 1 +( -144 384 16 ) ( -143 384 16 ) ( -144 384 17 ) Walls/Wallside_001 [ -1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -144 272 16 ) ( -144 272 17 ) ( -144 273 16 ) Walls/Wallside_001 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +} +// brush 90 +{ +( -152 408 16 ) ( -152 408 17 ) ( -152 407 16 ) special/clip [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -144 384 24 ) ( -144 384 25 ) ( -143 384 24 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( -152 408 16 ) ( -152 407 16 ) ( -151 408 16 ) special/clip [ 1.8369701987210297e-16 1 0 0 ] [ -1 1.8369701987210297e-16 0 -24 ] 0 1 1 +( -144 328 20 ) ( -143 328 20 ) ( -144 327 20 ) Floors/Floor242 [ -1.8369701987210297e-16 -1 0 0 ] [ -1 1.8369701987210297e-16 0 0 ] 270 1 1 +( -152 408 16 ) ( -151 408 16 ) ( -152 408 17 ) special/clip [ -1 1.8369701987210297e-16 0 -24 ] [ 0 0 -1 0 ] 270 1 1 +( -144 328 24 ) ( -144 327 24 ) ( -144 328 25 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 90 1 1 +} +// brush 91 +{ +( -152 408 40 ) ( -152 408 41 ) ( -152 407 40 ) special/clip [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 24 ] 180 1 1 +( -144 384 48 ) ( -144 384 49 ) ( -143 384 48 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -152 408 44 ) ( -152 407 44 ) ( -151 408 44 ) special/clip [ 1.8369701987210297e-16 1 0 0 ] [ -1 1.8369701987210297e-16 0 -24 ] 0 1 1 +( -144 328 48 ) ( -143 328 48 ) ( -144 327 48 ) Floors/Floor242 [ -1.8369701987210297e-16 -1 0 0 ] [ -1 1.8369701987210297e-16 0 0 ] 90 1 1 +( -152 408 40 ) ( -151 408 40 ) ( -152 408 41 ) special/clip [ -1 1.8369701987210297e-16 0 -24 ] [ 0 0 -1 24 ] 0 1 1 +( -144 328 48 ) ( -144 327 48 ) ( -144 328 49 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 180 1 1 +} +// brush 92 +{ +( -568 392 -16 ) ( -568 393 -16 ) ( -568 392 -15 ) __TB_empty [ 0 -1 0 8 ] [ 0 0 -1 0 ] 0 1 1 +( -520 384 -16 ) ( -520 384 -15 ) ( -519 384 -16 ) __TB_empty [ 1 0 0 8 ] [ 0 0 -1 0 ] 90 1 1 +( -520 392 8 ) ( -519 392 8 ) ( -520 393 8 ) __TB_empty [ -1 0 0 -8 ] [ 0 -1 0 8 ] 180 1 1 +( -392 520 16 ) ( -392 521 16 ) ( -391 520 16 ) Floors/Floor283 [ 1 0 0 8 ] [ 0 -1 0 -8 ] 270 1 1 +( -392 936 16 ) ( -391 936 16 ) ( -392 936 17 ) __TB_empty [ -1 0 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +( -256 520 16 ) ( -256 520 17 ) ( -256 521 16 ) __TB_empty [ 0 1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +} +// brush 93 +{ +( -256 520 16 ) ( -256 521 16 ) ( -256 520 17 ) __TB_empty [ 0 1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +( -520 384 -16 ) ( -520 384 -15 ) ( -519 384 -16 ) __TB_empty [ 1 0 0 8 ] [ 0 0 -1 0 ] 90 1 1 +( -520 392 8 ) ( -519 392 8 ) ( -520 393 8 ) __TB_empty [ -1 0 0 -8 ] [ 0 -1 0 8 ] 180 1 1 +( -392 520 16 ) ( -392 521 16 ) ( -391 520 16 ) Floors/Floor_Tiled_0226 [ 1 0 0 8 ] [ 0 -1 0 -8 ] 270 1 1 +( -392 624 16 ) ( -391 624 16 ) ( -392 624 17 ) __TB_empty [ -1 0 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +( -144 520 16 ) ( -144 520 17 ) ( -144 521 16 ) __TB_empty [ 0 1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +} +// brush 94 +{ +( -152 152 8 ) ( -152 153 8 ) ( -152 152 9 ) special/clip [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -144 288 16 ) ( -144 288 17 ) ( -143 288 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 +( -152 152 16 ) ( -151 152 16 ) ( -152 153 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 -1 0 -16 ] 270 1 1 +( -144 272 48 ) ( -144 273 48 ) ( -143 272 48 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 -1 0 -16 ] 0 1 1 +( -144 380 16 ) ( -143 380 16 ) ( -144 380 17 ) Walls/Wallside_001 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -144 272 16 ) ( -144 272 17 ) ( -144 273 16 ) Manual/Wall_Metal_Fusion_002 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +} +// brush 95 +{ +( -144 280 16 ) ( -144 281 16 ) ( -144 280 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -48 280 16 ) ( -48 280 17 ) ( -47 280 16 ) __TB_empty [ 1 0 0 24 ] [ 0 0 -1 0 ] 0 1 1 +( -48 280 16 ) ( -47 280 16 ) ( -48 281 16 ) __TB_empty [ -1 0 0 -24 ] [ 0 -1 0 -8 ] 0 1 1 +( 72 288 48 ) ( 72 289 48 ) ( 73 288 48 ) __TB_empty [ 1 0 0 24 ] [ 0 -1 0 -8 ] 270 1 1 +( 72 288 24 ) ( 73 288 24 ) ( 72 288 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 -8 ] [ 0 0 -1 -16 ] 0 1 1 +( -4 280 16 ) ( -4 280 17 ) ( -4 281 16 ) Walls/Wallside_001 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 270 1 1 +} +// brush 96 +{ +( 36 280 16 ) ( 36 281 16 ) ( 36 280 17 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -8 280 16 ) ( -8 280 17 ) ( -7 280 16 ) __TB_empty [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 1 1 +( -8 280 16 ) ( -7 280 16 ) ( -8 281 16 ) __TB_empty [ -1 0 0 16 ] [ 0 -1 0 -8 ] 180 1 1 +( 112 288 48 ) ( 112 289 48 ) ( 113 288 48 ) __TB_empty [ 1 0 0 -16 ] [ 0 -1 0 -8 ] 90 1 1 +( 112 288 24 ) ( 113 288 24 ) ( 112 288 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 +( 40 280 16 ) ( 40 280 17 ) ( 40 281 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 97 +{ +( 40 536 48 ) ( 40 536 49 ) ( 40 535 48 ) special/clip [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( 48 416 56 ) ( 48 416 57 ) ( 49 416 56 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( 40 536 48 ) ( 40 535 48 ) ( 41 536 48 ) special/clip [ 1.8369701987210297e-16 1 0 0 ] [ -1 1.8369701987210297e-16 0 8 ] 180 1 1 +( 48 456 52 ) ( 49 456 52 ) ( 48 455 52 ) Manual/Black [ -1.8369701987210297e-16 -1 0 0 ] [ -1 1.8369701987210297e-16 0 0 ] 270 1 1 +( 40 536 48 ) ( 41 536 48 ) ( 40 536 49 ) special/clip [ -1 1.8369701987210297e-16 0 8 ] [ 0 0 -1 0 ] 90 1 1 +( 48 456 56 ) ( 48 455 56 ) ( 48 456 57 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 +} +// brush 98 +{ +( -24 536 16 ) ( -24 537 16 ) ( -24 536 17 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 0 1 1 +( -48 536 16 ) ( -48 536 17 ) ( -47 536 16 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -48 536 16 ) ( -47 536 16 ) ( -48 537 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 24 ] 270 1 1 +( 72 544 48 ) ( 72 545 48 ) ( 73 544 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 24 ] 180 1 1 +( 72 544 24 ) ( 73 544 24 ) ( 72 544 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 270 1 1 +( -8 536 16 ) ( -8 536 17 ) ( -8 537 16 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 99 +{ +( 40 336 8 ) ( 40 337 8 ) ( 40 336 9 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 +( 40 280 8 ) ( 40 280 9 ) ( 41 280 8 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 -16 ] 90 1 1 +( 40 336 16 ) ( 41 336 16 ) ( 40 337 16 ) special/clip [ -1 0 0 0 ] [ 0 -1 0 8 ] 180 1 1 +( 48 456 48 ) ( 48 457 48 ) ( 49 456 48 ) special/clip [ 1 0 0 0 ] [ 0 -1 0 8 ] 270 1 1 +( 48 448 16 ) ( 49 448 16 ) ( 48 448 17 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 90 1 1 +( 48 456 16 ) ( 48 456 17 ) ( 48 457 16 ) Walls/wall_marble_009 [ 0 1 0 8 ] [ 0 0 -1 -16 ] 270 1 1 +} +// brush 100 +{ +( 40 336 8 ) ( 40 337 8 ) ( 40 336 9 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 -16 ] 270 1 1 +( 48 480 16 ) ( 48 480 17 ) ( 49 480 16 ) special/clip [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 +( 40 336 16 ) ( 41 336 16 ) ( 40 337 16 ) special/clip [ -1 0 0 0 ] [ 0 -1 0 8 ] 180 1 1 +( 48 456 48 ) ( 48 457 48 ) ( 49 456 48 ) special/clip [ 1 0 0 0 ] [ 0 -1 0 8 ] 270 1 1 +( 48 536 16 ) ( 49 536 16 ) ( 48 536 17 ) special/clip [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 +( 48 456 16 ) ( 48 456 17 ) ( 48 457 16 ) Walls/wall_marble_009 [ 0 1 0 8 ] [ 0 0 -1 -16 ] 270 1 1 +} +// brush 101 +{ +( -144 424 -16 ) ( -144 425 -16 ) ( -144 424 -15 ) __TB_empty [ 0 -1 0 8 ] [ 0 0 -1 0 ] 90 1 1 +( -96 416 -16 ) ( -96 416 -15 ) ( -95 416 -16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -96 424 8 ) ( -95 424 8 ) ( -96 425 8 ) __TB_empty [ -1 0 0 0 ] [ 0 -1 0 8 ] 270 1 1 +( 32 552 16 ) ( 32 553 16 ) ( 33 552 16 ) Floors/Floor235 [ 1 0 0 0 ] [ 0 -1 0 -8 ] 0 1 1 +( 32 544 16 ) ( 33 544 16 ) ( 32 544 17 ) __TB_empty [ -1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -8 552 16 ) ( -8 552 17 ) ( -8 553 16 ) __TB_empty [ 0 1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +} +// brush 102 +{ +( -72 472 16 ) ( -72 473 16 ) ( -72 472 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -48 472 16 ) ( -48 472 17 ) ( -47 472 16 ) __TB_empty [ 1 0 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +( -48 472 16 ) ( -47 472 16 ) ( -48 473 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 -8 ] 90 1 1 +( 72 480 48 ) ( 72 481 48 ) ( 73 480 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 -8 ] 0 1 1 +( 72 480 24 ) ( 73 480 24 ) ( 72 480 25 ) Floors/Floor234 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 90 1 1 +( -56 472 16 ) ( -56 472 17 ) ( -56 473 16 ) Floors/Floor234 [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 103 +{ +( -8 536 16 ) ( -8 537 16 ) ( -8 536 17 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 0 1 1 +( -48 536 16 ) ( -48 536 17 ) ( -47 536 16 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -48 536 16 ) ( -47 536 16 ) ( -48 537 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 24 ] 270 1 1 +( 72 544 48 ) ( 72 545 48 ) ( 73 544 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 24 ] 180 1 1 +( 72 544 24 ) ( 73 544 24 ) ( 72 544 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 270 1 1 +( 48 536 16 ) ( 48 536 17 ) ( 48 537 16 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 270 1 1 +} +// brush 104 +{ +( -144 536 16 ) ( -144 537 16 ) ( -144 536 17 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 90 1 1 +( -48 536 16 ) ( -48 536 17 ) ( -47 536 16 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -48 536 16 ) ( -47 536 16 ) ( -48 537 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 24 ] 270 1 1 +( 72 544 48 ) ( 72 545 48 ) ( 73 544 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 24 ] 180 1 1 +( 72 544 24 ) ( 73 544 24 ) ( 72 544 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 270 1 1 +( -128 536 16 ) ( -128 536 17 ) ( -128 537 16 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 90 1 1 +} +// brush 105 +{ +( -24 472 16 ) ( -24 473 16 ) ( -24 472 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +( 0 472 16 ) ( 0 472 17 ) ( 1 472 16 ) __TB_empty [ 1 0 0 -24 ] [ 0 0 -1 0 ] 0 1 1 +( 0 472 16 ) ( 1 472 16 ) ( 0 473 16 ) __TB_empty [ -1 0 0 24 ] [ 0 -1 0 -8 ] 0 1 1 +( 120 480 48 ) ( 120 481 48 ) ( 121 480 48 ) __TB_empty [ 1 0 0 -24 ] [ 0 -1 0 -8 ] 270 1 1 +( 120 480 24 ) ( 121 480 24 ) ( 120 480 25 ) Floors/Floor234 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 0 1 1 +( -8 472 16 ) ( -8 472 17 ) ( -8 473 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +} +// brush 106 +{ +( -96 536 16 ) ( -96 537 16 ) ( -96 536 17 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 0 1 1 +( -48 536 16 ) ( -48 536 17 ) ( -47 536 16 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -48 536 16 ) ( -47 536 16 ) ( -48 537 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 24 ] 270 1 1 +( 72 544 48 ) ( 72 545 48 ) ( 73 544 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 24 ] 180 1 1 +( 72 544 24 ) ( 73 544 24 ) ( 72 544 25 ) Manual/Wall_Metal_Fusion_002 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 270 1 1 +( -56 536 16 ) ( -56 536 17 ) ( -56 537 16 ) __TB_empty [ 0 -1 0 24 ] [ 0 0 -1 0 ] 90 1 1 +} +// brush 107 +{ +( -96 472 16 ) ( -96 473 16 ) ( -96 472 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -72 472 16 ) ( -72 472 17 ) ( -71 472 16 ) __TB_empty [ 1 0 0 16 ] [ 0 0 -1 0 ] 90 1 1 +( -72 472 16 ) ( -71 472 16 ) ( -72 473 16 ) __TB_empty [ -1 0 0 -16 ] [ 0 -1 0 -8 ] 90 1 1 +( 48 480 48 ) ( 48 481 48 ) ( 49 480 48 ) __TB_empty [ 1 0 0 16 ] [ 0 -1 0 -8 ] 0 1 1 +( 48 480 24 ) ( 49 480 24 ) ( 48 480 25 ) Floors/Floor234 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 90 1 1 +( -80 472 16 ) ( -80 472 17 ) ( -80 473 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 108 +{ +( -144 472 16 ) ( -144 473 16 ) ( -144 472 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -120 472 16 ) ( -120 472 17 ) ( -119 472 16 ) __TB_empty [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -120 472 16 ) ( -119 472 16 ) ( -120 473 16 ) __TB_empty [ -1 0 0 0 ] [ 0 -1 0 -8 ] 180 1 1 +( 0 480 48 ) ( 0 481 48 ) ( 1 480 48 ) __TB_empty [ 1 0 0 0 ] [ 0 -1 0 -8 ] 90 1 1 +( 0 480 24 ) ( 1 480 24 ) ( 0 480 25 ) Floors/Floor234 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 180 1 1 +( -128 472 16 ) ( -128 472 17 ) ( -128 473 16 ) Floors/Floor234 [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +} +// brush 109 +{ +( -152 536 48 ) ( -152 536 49 ) ( -152 535 48 ) special/clip [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -144 416 56 ) ( -144 416 57 ) ( -143 416 56 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( -152 536 48 ) ( -152 535 48 ) ( -151 536 48 ) special/clip [ 1.8369701987210297e-16 1 0 0 ] [ -1 1.8369701987210297e-16 0 8 ] 270 1 1 +( -144 456 52 ) ( -143 456 52 ) ( -144 455 52 ) Manual/Black [ -1.8369701987210297e-16 -1 0 0 ] [ -1 1.8369701987210297e-16 0 0 ] 0 1 1 +( -152 536 48 ) ( -151 536 48 ) ( -152 536 49 ) special/clip [ -1 1.8369701987210297e-16 0 8 ] [ 0 0 -1 0 ] 180 1 1 +( -144 456 56 ) ( -144 455 56 ) ( -144 456 57 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 110 +{ +( -152 536 48 ) ( -152 537 48 ) ( -152 536 49 ) special/clip [ 0 -1 0 24 ] [ 0 0 -1 0 ] 90 1 1 +( -152 536 48 ) ( -152 536 49 ) ( -151 536 48 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -152 536 48 ) ( -151 536 48 ) ( -152 537 48 ) special/clip [ -1 0 0 0 ] [ 0 -1 0 24 ] 90 1 1 +( -72 544 52 ) ( -72 545 52 ) ( -71 544 52 ) Manual/Black [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -72 544 56 ) ( -71 544 56 ) ( -72 544 57 ) Walls/WallTop_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( 48 544 56 ) ( 48 544 57 ) ( 48 545 56 ) Walls/WallTop_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 +} +// brush 111 +{ +( -80 536 48 ) ( -80 536 49 ) ( -80 535 48 ) special/clip [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -72 416 56 ) ( -72 416 57 ) ( -71 416 56 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -80 536 48 ) ( -80 535 48 ) ( -79 536 48 ) special/clip [ 1.8369701987210297e-16 1 0 0 ] [ -1 1.8369701987210297e-16 0 16 ] 90 1 1 +( -72 456 52 ) ( -71 456 52 ) ( -72 455 52 ) Manual/Black [ -1.8369701987210297e-16 -1 0 0 ] [ -1 1.8369701987210297e-16 0 0 ] 180 1 1 +( -80 536 48 ) ( -79 536 48 ) ( -80 536 49 ) special/clip [ -1 1.8369701987210297e-16 0 16 ] [ 0 0 -1 0 ] 0 1 1 +( -72 456 56 ) ( -72 455 56 ) ( -72 456 57 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 180 1 1 +} +// brush 112 +{ +( -8 536 48 ) ( -8 536 49 ) ( -8 535 48 ) special/clip [ -1.8369701987210297e-16 -1 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( 0 416 56 ) ( 0 416 57 ) ( 1 416 56 ) Walls/WallTop_002 [ 1 -1.8369701987210297e-16 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -8 536 48 ) ( -8 535 48 ) ( -7 536 48 ) special/clip [ 1.8369701987210297e-16 1 0 0 ] [ -1 1.8369701987210297e-16 0 24 ] 180 1 1 +( 0 456 52 ) ( 1 456 52 ) ( 0 455 52 ) Manual/Black [ -1.8369701987210297e-16 -1 0 0 ] [ -1 1.8369701987210297e-16 0 0 ] 270 1 1 +( -8 536 48 ) ( -7 536 48 ) ( -8 536 49 ) special/clip [ -1 1.8369701987210297e-16 0 24 ] [ 0 0 -1 0 ] 90 1 1 +( 0 456 56 ) ( 0 455 56 ) ( 0 456 57 ) Walls/WallTop_002 [ 1.8369701987210297e-16 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 +} +// brush 113 +{ +( -152 152 8 ) ( -152 153 8 ) ( -152 152 9 ) special/clip [ 0 -1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -144 408 16 ) ( -144 408 17 ) ( -143 408 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +( -152 152 16 ) ( -151 152 16 ) ( -152 153 16 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 -1 0 -16 ] 270 1 1 +( -144 272 48 ) ( -144 273 48 ) ( -143 272 48 ) Manual/Wall_Metal_Fusion_Grate_001 [ 1 0 0 0 ] [ 0 -1 0 -16 ] 0 1 1 +( -144 536 16 ) ( -143 536 16 ) ( -144 536 17 ) Manual/Wall_Metal_Fusion_Grate_001 [ -1 0 0 0 ] [ 0 0 -1 -16 ] 270 1 1 +( -144 272 16 ) ( -144 272 17 ) ( -144 273 16 ) Floors/Floor234 [ 0 1 0 0 ] [ 0 0 -1 -16 ] 0 1 1 +} +// brush 114 +{ +( -72 472 48 ) ( -72 473 48 ) ( -72 472 49 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +( -208 472 48 ) ( -208 472 49 ) ( -207 472 48 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +( -208 472 48 ) ( -207 472 48 ) ( -208 473 48 ) special/clip [ -1 0 0 8 ] [ 0 -1 0 -8 ] 90 1 1 +( -128 480 52 ) ( -128 481 52 ) ( -127 480 52 ) Manual/Black [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -128 480 56 ) ( -127 480 56 ) ( -128 480 57 ) Walls/WallTop_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -8 480 56 ) ( -8 480 57 ) ( -8 481 56 ) Walls/WallTop_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 270 1 1 +} +// brush 115 +{ +( -144 472 48 ) ( -144 473 48 ) ( -144 472 49 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -280 472 48 ) ( -280 472 49 ) ( -279 472 48 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -280 472 48 ) ( -279 472 48 ) ( -280 473 48 ) special/clip [ -1 0 0 0 ] [ 0 -1 0 -8 ] 0 1 1 +( -200 480 52 ) ( -200 481 52 ) ( -199 480 52 ) Manual/Black [ 1 0 0 0 ] [ 0 -1 0 0 ] 270 1 1 +( -200 480 56 ) ( -199 480 56 ) ( -200 480 57 ) Walls/WallTop_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -80 480 56 ) ( -80 480 57 ) ( -80 481 56 ) Walls/WallTop_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 180 1 1 +} +// brush 116 +{ +( -256 376 24 ) ( -256 377 24 ) ( -256 376 25 ) Manual/Glass_001 [ 0 -1 0 8 ] [ 0 0 -1 0 ] 90 1 1 +( -256 376 24 ) ( -256 376 25 ) ( -255 376 24 ) Manual/Glass_001 [ 1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -256 376 24 ) ( -255 376 24 ) ( -256 377 24 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 -1 0 8 ] 90 1 1 +( -224 384 48 ) ( -224 385 48 ) ( -223 384 48 ) Manual/Glass_001 [ 1 0 0 0 ] [ 0 -1 0 8 ] 270 1 1 +( -224 384 32 ) ( -223 384 32 ) ( -224 384 33 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -232 384 32 ) ( -232 384 33 ) ( -232 385 32 ) Manual/Glass_001 [ 0 1 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 117 +{ +( -264 368 16 ) ( -264 369 16 ) ( -264 368 17 ) special/clip [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +( -264 376 16 ) ( -264 376 17 ) ( -263 376 16 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +( -264 368 16 ) ( -263 368 16 ) ( -264 369 16 ) special/clip [ -1 0 0 8 ] [ 0 -1 0 -8 ] 90 1 1 +( -160 384 24 ) ( -160 385 24 ) ( -159 384 24 ) Floors/Floor242 [ 1 0 0 -8 ] [ 0 -1 0 -8 ] 90 1 1 +( -160 384 24 ) ( -159 384 24 ) ( -160 384 25 ) Floors/Floor242 [ -1 0 0 8 ] [ 0 0 -1 0 ] 90 1 1 +( -152 384 24 ) ( -152 384 25 ) ( -152 385 24 ) special/clip [ 0 1 0 8 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 118 +{ +( -224 376 24 ) ( -224 377 24 ) ( -224 376 25 ) Manual/Glass_001 [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 90 1 1 +( -232 376 24 ) ( -232 376 25 ) ( -231 376 24 ) Manual/Glass_001 [ 1 0 0 8 ] [ 0 0 -1 0 ] 180 1 1 +( -232 376 24 ) ( -231 376 24 ) ( -232 377 24 ) Manual/Glass_001 [ -1 0 0 -8 ] [ 0 -1 0 -8 ] 180 1 1 +( -200 384 48 ) ( -200 385 48 ) ( -199 384 48 ) Manual/Glass_001 [ 1 0 0 8 ] [ 0 -1 0 -8 ] 0 1 1 +( -200 384 32 ) ( -199 384 32 ) ( -200 384 33 ) Manual/Glass_001 [ -1 0 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -200 384 32 ) ( -200 384 33 ) ( -200 385 32 ) Manual/Glass_001 [ 0 1 0 8 ] [ 0 0 -1 0 ] 180 1 1 +} +// brush 119 +{ +( -192 376 24 ) ( -192 377 24 ) ( -192 376 25 ) Manual/Glass_001 [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -192 376 24 ) ( -192 376 25 ) ( -191 376 24 ) Manual/Glass_001 [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -192 376 24 ) ( -191 376 24 ) ( -192 377 24 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 -1 0 -8 ] 180 1 1 +( -160 384 48 ) ( -160 385 48 ) ( -159 384 48 ) Manual/Glass_001 [ 1 0 0 0 ] [ 0 -1 0 -8 ] 0 1 1 +( -160 384 32 ) ( -159 384 32 ) ( -160 384 33 ) Manual/Glass_001 [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -152 384 32 ) ( -152 384 33 ) ( -152 385 32 ) Manual/Glass_001 [ 0 1 0 8 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 120 +{ +( -200 376 24 ) ( -200 377 24 ) ( -200 376 25 ) Walls/Wallside_002 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -200 376 24 ) ( -200 376 25 ) ( -199 376 24 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -200 376 24 ) ( -199 376 24 ) ( -200 377 24 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1 +( -192 384 48 ) ( -192 385 48 ) ( -191 384 48 ) Walls/Wallside_002 [ 1 0 0 0 ] [ 0 -1 0 0 ] 90 1 1 +( -192 384 32 ) ( -191 384 32 ) ( -192 384 33 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1 +( -192 384 32 ) ( -192 384 33 ) ( -192 385 32 ) Walls/Wallside_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 180 1 1 +} +// brush 121 +{ +( -232 376 24 ) ( -232 377 24 ) ( -232 376 25 ) Walls/Wallside_002 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -232 376 24 ) ( -232 376 25 ) ( -231 376 24 ) special/clip [ 1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -232 376 24 ) ( -231 376 24 ) ( -232 377 24 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 -1 0 0 ] 90 1 1 +( -224 384 48 ) ( -224 385 48 ) ( -223 384 48 ) Walls/Wallside_002 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -224 384 32 ) ( -223 384 32 ) ( -224 384 33 ) Walls/Wallside_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 90 1 1 +( -224 384 32 ) ( -224 384 33 ) ( -224 385 32 ) Walls/Wallside_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 90 1 1 +} +// brush 122 +{ +( -272 376 48 ) ( -272 377 48 ) ( -272 376 49 ) special/clip [ 0 -1 0 24 ] [ 0 0 -1 0 ] 270 1 1 +( -272 376 48 ) ( -272 376 49 ) ( -271 376 48 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 270 1 1 +( -272 376 48 ) ( -271 376 48 ) ( -272 377 48 ) special/clip [ -1 0 0 8 ] [ 0 -1 0 24 ] 270 1 1 +( -192 384 52 ) ( -192 385 52 ) ( -191 384 52 ) Manual/Black [ 1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1 +( -192 384 56 ) ( -191 384 56 ) ( -192 384 57 ) Walls/WallTop_002 [ -1 0 0 0 ] [ 0 0 -1 0 ] 270 1 1 +( -152 384 56 ) ( -152 384 57 ) ( -152 385 56 ) Walls/WallTop_002 [ 0 1 0 0 ] [ 0 0 -1 0 ] 180 1 1 +} +// brush 123 +{ +( -144 408 16 ) ( -144 409 16 ) ( -144 408 17 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 180 1 1 +( -48 408 16 ) ( -48 408 17 ) ( -47 408 16 ) special/clip [ 1 0 0 -8 ] [ 0 0 -1 0 ] 0 1 1 +( -48 408 16 ) ( -47 408 16 ) ( -48 409 16 ) __TB_empty [ -1 0 0 8 ] [ 0 -1 0 -8 ] 0 1 1 +( 72 416 48 ) ( 72 417 48 ) ( 73 416 48 ) __TB_empty [ 1 0 0 -8 ] [ 0 -1 0 -8 ] 270 1 1 +( 72 416 24 ) ( 73 416 24 ) ( 72 416 25 ) Floors/Floor234 [ -1 0 0 8 ] [ 0 0 -1 -16 ] 0 1 1 +( 0 408 16 ) ( 0 408 17 ) ( 0 409 16 ) __TB_empty [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 0 1 1 } } // entity 1 @@ -935,3 +1277,105 @@ "classname" "actor_furniture_can" "origin" "-134 216 27" } +// entity 30 +{ +"classname" "actor_chair" +"origin" "-16 376 24" +} +// entity 31 +{ +"classname" "actor_chair" +"origin" "-40 376 24" +} +// entity 32 +{ +"classname" "actor_chair" +"origin" "-72 376 24" +} +// entity 33 +{ +"classname" "actor_chair" +"origin" "-72 320 24" +} +// entity 34 +{ +"classname" "actor_chair" +"origin" "-40 320 24" +} +// entity 35 +{ +"classname" "actor_chair" +"origin" "-16 320 24" +} +// entity 36 +{ +"classname" "actor_door_1" +"origin" "44 464 32" +"angles" "0 0 0" +} +// entity 37 +{ +"classname" "actor_box_blue_tall" +"origin" "8 424 25" +} +// entity 38 +{ +"classname" "actor_box_blue_tall" +"origin" "8 520 25" +} +// entity 39 +{ +"classname" "actor_ac_unit" +"origin" "4 496 24" +"angles" "0 180 0" +} +// entity 40 +{ +"classname" "actor_door_1" +"origin" "-40 540 32" +"angles" "0 -90 0" +} +// entity 41 +{ +"classname" "actor_door_1" +"origin" "-40 476 32" +"angles" "0 -90 0" +} +// entity 42 +{ +"classname" "actor_door_1" +"origin" "-112 540 32" +"angles" "0 -90 0" +} +// entity 43 +{ +"classname" "actor_door_1" +"origin" "-112 476 32" +"angles" "0 -90 0" +} +// entity 44 +{ +"classname" "actor_locker" +"origin" "4 440 28" +} +// entity 45 +{ +"classname" "actor_locker" +"origin" "4 456 28" +} +// entity 46 +{ +"classname" "actor_locker" +"origin" "4 472 28" +} +// entity 47 +{ +"classname" "actor_locker" +"origin" "20 420 28" +"angles" "0 90 0" +} +// entity 48 +{ +"classname" "marker_spawn_enemy_fairy_guard" +"origin" "12 172 22" +} diff --git a/3D/TrenchBroom/EntityDefinitions/base/enemy_base.tres b/3D/TrenchBroom/EntityDefinitions/base/enemy_base.tres index 7aadd950..94657bb8 100644 --- a/3D/TrenchBroom/EntityDefinitions/base/enemy_base.tres +++ b/3D/TrenchBroom/EntityDefinitions/base/enemy_base.tres @@ -8,16 +8,14 @@ script = ExtResource("1_5bcmp") classname = "Enemy" base_classes = Array[Resource]([ExtResource("1_f3dmh"), ExtResource("2_foxys")]) -class_properties = { -"autospawn": true, -"resource_path": "resource_path" -} -class_property_descriptions = { -"autospawn": "Whether to spawn automatically or not", -"resource_path": "Path to the enemy resource" -} -meta_properties = { +class_properties = Dictionary[String, Variant]({ +"autospawn": true +}) +class_property_descriptions = Dictionary[String, Variant]({ +"autospawn": "Whether to spawn automatically or not" +}) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.91852677, 0.5792049, 0.5792049, 1), "size": AABB(-4, -4, 6, 4, 4, 6) -} +}) metadata/_custom_type_script = "uid://ck575aqs1sbrb" diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Capacitor_Mini.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Capacitor_Mini.tres index 3689e4d9..7f059422 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Capacitor_Mini.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Capacitor_Mini.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://ejgmadticege"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://ejgmadticege"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_frb07"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_61nv4"] [ext_resource type="PackedScene" uid="uid://bkwuuk6ctadu0" path="res://3D/Scenes/Props/Capacitor_Mini_3D.tscn" id="2_frb07"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_864ca"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_jbms5"] [resource] script = ExtResource("3_864ca") @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_capacitor_mini" description = "Mini Capacitor" base_classes = Array[Resource]([ExtResource("1_frb07"), ExtResource("2_61nv4")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "size": AABB(-8, -8, -8, 8, 8, 8), "studio": "\"3D/MapModels/actor_capacitor_mini.glb\"" -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Door.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Door.tres index 1a0d5c88..1da23a95 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Door.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Door.tres @@ -1,8 +1,9 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://vuuarep4h5w2"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://vuuarep4h5w2"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_3puc0"] [ext_resource type="Resource" uid="uid://c1utxplehq2jl" path="res://3D/TrenchBroom/EntityDefinitions/base/targetname_base.tres" id="2_7csyq"] [ext_resource type="PackedScene" uid="uid://bubtvv3pa06py" path="res://3D/Scenes/Props/Door_3D.tscn" id="3_7csyq"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_d1s60"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_gqtxh"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_door_1" description = "Door Type 1" base_classes = Array[Resource]([ExtResource("1_3puc0"), ExtResource("2_7csyq")]) -meta_properties = { -"model": "\"3D/MapModels/actor_door_1.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_door_1.glb\", \"scale\": 16.0 }", "size": AABB(-4, -16, -16, 4, 16, 16) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Floor.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Floor.tres index 0cb4b209..c8d93da4 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Floor.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Floor.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://b4cf1i0x46ej4"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://b4cf1i0x46ej4"] [ext_resource type="Resource" uid="uid://0u5qbphjq045" path="res://3D/TrenchBroom/EntityDefinitions/base/emitter_base.tres" id="1_pc1hj"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_p7asn"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_p7asn"] [ext_resource type="PackedScene" uid="uid://d4ek8xjuh6y11" path="res://3D/Scenes/Props/Floor_Emitter_3D.tscn" id="3_pc1hj"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="4_oeoss"] @@ -14,10 +15,10 @@ apply_scale_on_map_build = false classname = "actor_emitter_floor" description = "Floor Emitter" base_classes = Array[Resource]([ExtResource("1_pc1hj"), ExtResource("2_p7asn")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "health": 5.0 -} -meta_properties = { -"model": "\"3D/MapModels/actor_emitter_floor.glb\"", +}) +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_emitter_floor.glb\", \"scale\": 16.0 }", "size": AABB(-4, -4, -4, 4, 4, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Tube.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Tube.tres index 440e7b55..fae4d56a 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Tube.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Tube.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://concvsutqjff2"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://concvsutqjff2"] [ext_resource type="Resource" uid="uid://0u5qbphjq045" path="res://3D/TrenchBroom/EntityDefinitions/base/emitter_base.tres" id="1_cogy3"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_ckugg"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="4_7iiqi"] [ext_resource type="PackedScene" uid="uid://djm3rsc7ul5jb" path="res://3D/Scenes/Props/Tube_3D_Emitter.tscn" id="4_n243x"] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_emitter_tube" description = "Tube Emitter" base_classes = Array[Resource]([ExtResource("1_cogy3")]) -meta_properties = { -"model": "\"3D/MapModels/actor_emitter_tube.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_emitter_tube.glb\", \"scale\": 16.0 }", "size": AABB(-2, -8, -8, 2, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Wall.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Wall.tres index a21cdc20..1b84bf2e 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Wall.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Emitter_Wall.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://oeoksvwbqvnf"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://oeoksvwbqvnf"] [ext_resource type="Resource" uid="uid://0u5qbphjq045" path="res://3D/TrenchBroom/EntityDefinitions/base/emitter_base.tres" id="1_1ofar"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_iguyw"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_wgr2p"] [ext_resource type="PackedScene" uid="uid://yath5bvxo3cn" path="res://3D/Scenes/Props/Wall_Emitter_3D.tscn" id="4_wgr2p"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="5_a0kra"] @@ -14,10 +15,10 @@ apply_scale_on_map_build = false classname = "actor_emitter_wall" description = "Wall Emitter" base_classes = Array[Resource]([ExtResource("1_1ofar"), ExtResource("2_iguyw")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "health": 5.0 -} -meta_properties = { -"model": "\"3D/MapModels/actor_emitter_wall.glb\"", +}) +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_emitter_wall.glb\", \"scale\": 16.0 }", "size": AABB(-4, -4, -4, 4, 4, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Forcefield.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Forcefield.tres index 589e2b09..eb12ac92 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Forcefield.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Forcefield.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cc881gocw0au4"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://cc881gocw0au4"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_wufju"] [ext_resource type="Resource" uid="uid://c1utxplehq2jl" path="res://3D/TrenchBroom/EntityDefinitions/base/targetname_base.tres" id="2_6wd32"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_6wd32"] [ext_resource type="PackedScene" uid="uid://dioiq4nb7kiet" path="res://3D/Scenes/Props/ForceField_3D.tscn" id="3_wufju"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="4_jvva7"] @@ -14,13 +15,13 @@ apply_scale_on_map_build = false classname = "actor_forcefield_1" description = "Forcefield Type 1" base_classes = Array[Resource]([ExtResource("1_wufju"), ExtResource("2_6wd32")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "startenabled": false -} -class_property_descriptions = { +}) +class_property_descriptions = Dictionary[String, Variant]({ "startenabled": "Whether to start enabled or not" -} -meta_properties = { -"model": "\"3D/MapModels/actor_forcefield_1.glb\"", +}) +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_forcefield_1.glb\", \"scale\": 16.0 }", "size": AABB(-4, -16, -16, 4, 16, 16) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Box.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Box.tres index 73a0857a..a1250d16 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Box.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Box.tres @@ -1,8 +1,9 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://ocl6a6lorlxa"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://ocl6a6lorlxa"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_q0qx2"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_7m3jg"] [ext_resource type="PackedScene" uid="uid://cgxq2tvdxnkil" path="res://3D/Scenes/Props/Furniture/SmallBox_3D.tscn" id="2_q0qx2"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_oe1xp"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_ta5yw"] [resource] @@ -14,7 +15,7 @@ apply_scale_on_map_build = false classname = "actor_furniture_box" description = "Box" base_classes = Array[Resource]([ExtResource("1_q0qx2"), ExtResource("2_7m3jg")]) -meta_properties = { -"model": "\"3D/MapModels/actor_furniture_box.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_furniture_box.glb\", \"scale\": 16.0 }", "size": AABB(-2, -2, -2, 2, 2, 2) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Can.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Can.tres index 253af0ae..33517903 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Can.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Can.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cdlo7qrub1bbd"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://cdlo7qrub1bbd"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_62adm"] [ext_resource type="PackedScene" uid="uid://ddi6ch3tuqqri" path="res://3D/Scenes/Props/Furniture/Can_3D.tscn" id="2_62adm"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_6885y"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_8wc8b"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_bstmi"] [resource] script = ExtResource("3_8wc8b") @@ -14,7 +15,7 @@ apply_scale_on_map_build = false classname = "actor_furniture_can" description = "Can" base_classes = Array[Resource]([ExtResource("1_62adm"), ExtResource("2_6885y")]) -meta_properties = { -"model": "\"3D/MapModels/actor_furniture_can.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_furniture_can.glb\", \"scale\": 16.0 }", "size": AABB(-2, -2, -2, 2, 2, 2) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_ComputerTower.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_ComputerTower.tres index ef3992f4..ff55f6be 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_ComputerTower.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_ComputerTower.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://cr3xqfglolihb"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cr3xqfglolihb"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_4lat3"] [ext_resource type="PackedScene" uid="uid://5oos364p3wex" path="res://3D/Scenes/Props/Furniture/Computer_Tower_3D.tscn" id="2_4lat3"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_kocf7"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_xgcta"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_furniture_computertower" description = "Computer tower" base_classes = Array[Resource]([ExtResource("1_4lat3")]) -meta_properties = { -"model": "\"3D/MapModels/actor_furniture_computertower.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_furniture_computertower.glb\", \"scale\": 16.0 }", "size": AABB(-4, -5, -1, 4, 5, 1) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Shelf.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Shelf.tres index b4bb094a..c56e8346 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Shelf.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Shelf.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://clbpsv6t4qamd"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://clbpsv6t4qamd"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_a11ow"] [ext_resource type="PackedScene" uid="uid://dcv3hwt7p4hgp" path="res://3D/Scenes/Props/Furniture/Shelf_3D.tscn" id="2_a11ow"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_gaf7m"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_tppu4"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_furniture_shelf" description = "Vending Machine" base_classes = Array[Resource]([ExtResource("1_a11ow")]) -meta_properties = { -"model": "\"3D/MapModels/actor_furniture_shelf.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_furniture_shelf.glb\", \"scale\": 16.0 }", "size": AABB(-4, -8, -1, 4, 8, 1) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Triangle.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Triangle.tres index 3b4403b4..e7d7a59c 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Triangle.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Furniture_Triangle.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://yw4443572o6u"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://yw4443572o6u"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_aw0kv"] [ext_resource type="PackedScene" uid="uid://dsppxfki3n30g" path="res://3D/Scenes/Props/Furniture/Triangle_Furniture_3D.tscn" id="2_aw0kv"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_iqqa2"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_4hq8f"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_i11bl"] [resource] script = ExtResource("3_4hq8f") @@ -14,7 +15,7 @@ apply_scale_on_map_build = false classname = "actor_furniture_triangle" description = "Triangle" base_classes = Array[Resource]([ExtResource("1_aw0kv"), ExtResource("2_iqqa2")]) -meta_properties = { -"model": "\"3D/MapModels/actor_furniture_triangle.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_furniture_triangle.glb\", \"scale\": 16.0 }", "size": AABB(-2, -2, -2, 2, 2, 2) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Level_Teleporter.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Level_Teleporter.tres index a87f01b5..cfa4cefe 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Level_Teleporter.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Level_Teleporter.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://dvpi4kx2visc0"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://dvpi4kx2visc0"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_klaoa"] [ext_resource type="PackedScene" uid="uid://bn7hkgapi5oka" path="res://3D/Scenes/Props/Level_Teleporter_3D.tscn" id="2_atmpw"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_y6gbv"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="5_7bpmd"] [resource] @@ -13,17 +14,17 @@ apply_scale_on_map_build = false classname = "actor_level_teleporter" description = "Teleporter to the next level" base_classes = Array[Resource]([ExtResource("1_klaoa")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "enabled": false, "invisible": false, "mapid": "" -} -class_property_descriptions = { +}) +class_property_descriptions = Dictionary[String, Variant]({ "enabled": "Enabled or disabled", "invisible": "Is it invisible?", "mapid": "The id of the map to go to, goes to next map if empty" -} -meta_properties = { -"model": "\"3D/MapModels/actor_level_teleporter.glb\"", +}) +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_level_teleporter.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -1, 8, 8, 1) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Locker.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Locker.tres index d66b672a..c89d4560 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Locker.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Locker.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://chytq0646of5n"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://chytq0646of5n"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_l772s"] [ext_resource type="PackedScene" uid="uid://c54tcqntl7vmn" path="res://3D/Scenes/Props/Locker_3D.tscn" id="2_l772s"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_xui3x"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_0k0vs"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_locker" description = "Locker" base_classes = Array[Resource]([ExtResource("1_l772s")]) -meta_properties = { -"model": "\"3D/MapModels/actor_locker.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_locker.glb\", \"scale\": 16.0 }", "size": AABB(-4, -8, -12, 4, 8, 12) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Mainframe.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Mainframe.tres index e16054e9..255e37e6 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Mainframe.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Mainframe.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://dr2pga4b05paq"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://dr2pga4b05paq"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_0tkke"] [ext_resource type="PackedScene" uid="uid://5jwj0xm33bfs" path="res://3D/Scenes/Props/Mainframe_3D.tscn" id="2_0tkke"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_pciti"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_2bwyp"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_mainframe" description = "Mainframe" base_classes = Array[Resource]([ExtResource("1_0tkke")]) -meta_properties = { -"model": "\"3D/MapModels/actor_mainframe.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_mainframe.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -12, 8, 8, 12) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_SecurityCamera.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_SecurityCamera.tres index f99c760e..c65c3fe2 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_SecurityCamera.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_SecurityCamera.tres @@ -1,10 +1,11 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://m0xahs14etiy"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=7 format=3 uid="uid://m0xahs14etiy"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_yxg7b"] [ext_resource type="Resource" uid="uid://kerywjgft7vh" path="res://3D/TrenchBroom/EntityDefinitions/base/target_base.tres" id="2_mqd4f"] [ext_resource type="PackedScene" uid="uid://b0rhxqjs52fsv" path="res://3D/Scenes/Props/Camera_3D.tscn" id="2_yxg7b"] [ext_resource type="Resource" uid="uid://bd4h6ha84s74b" path="res://3D/TrenchBroom/EntityDefinitions/base/activation_type_base.tres" id="3_ewgk3"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_mqd4f"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="4_ewgk3"] [resource] script = ExtResource("3_mqd4f") @@ -15,7 +16,7 @@ apply_scale_on_map_build = false classname = "actor_securitycamera" description = "Security Camera" base_classes = Array[Resource]([ExtResource("1_yxg7b"), ExtResource("2_mqd4f"), ExtResource("3_ewgk3")]) -meta_properties = { -"model": "\"3D/MapModels/actor_securitycamera.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_securitycamera.glb\", \"scale\": 16.0 }", "size": AABB(-4, -4, -4, 4, 4, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Stairs_mini.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Stairs_mini.tres index aba46e04..a248d82c 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Stairs_mini.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Stairs_mini.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://c8jy0j0d0nw0x"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://c8jy0j0d0nw0x"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_ntxx8"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_m175h"] [ext_resource type="PackedScene" uid="uid://cxci0rfd070sk" path="res://3D/Scenes/Props/Stairs_Mini_3D.tscn" id="2_ntxx8"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_1o7fi"] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_stairs_mini" description = "Mini Stairs" base_classes = Array[Resource]([ExtResource("1_ntxx8")]) -meta_properties = { -"model": "\"3D/MapModels/actor_stairs_mini.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_stairs_mini.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -4, 8, 8, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Table.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Table.tres index a08e04d4..9dfbc71d 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Table.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Table.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=4 format=3 uid="uid://8ac04g18qkho"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://8ac04g18qkho"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_ult45"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_gbxi6"] [ext_resource type="PackedScene" uid="uid://ou07lptfp0d1" path="res://3D/Scenes/Props/Table_3D.tscn" id="2_ult45"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_xotet"] @@ -11,7 +12,7 @@ apply_scale_on_map_build = false classname = "actor_table" description = "Table" base_classes = Array[Resource]([ExtResource("1_ult45")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "model": "\"3D/MapModels/Table.glb\"", "size": AABB(-8, -12, -4, 8, 12, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Tank_Large.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Tank_Large.tres index f5e6c1e7..93b055da 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Tank_Large.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Tank_Large.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://cx1wn21evf30h"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cx1wn21evf30h"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_0u3k1"] [ext_resource type="PackedScene" uid="uid://c0fu2ul3gg8fl" path="res://3D/BlockbenchModels/Tank/Tank_3D_Huge.tscn" id="2_0u3k1"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_7djei"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_cbmk6"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_tank_large" description = "Large Tank" base_classes = Array[Resource]([ExtResource("1_0u3k1")]) -meta_properties = { -"model": "\"3D/MapModels/actor_tank_large.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_tank_large.glb\", \"scale\": 16.0 }", "size": AABB(-32, -16, -16, 32, 16, 16) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Teleporter.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Teleporter.tres index 08b95ae4..f19ef7a8 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Teleporter.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Teleporter.tres @@ -1,26 +1,28 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://bjqfsr0ws3kbi"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=7 format=3 uid="uid://bjqfsr0ws3kbi"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_nutsy"] [ext_resource type="Resource" uid="uid://kerywjgft7vh" path="res://3D/TrenchBroom/EntityDefinitions/base/target_base.tres" id="2_l1mk8"] [ext_resource type="Resource" uid="uid://c1utxplehq2jl" path="res://3D/TrenchBroom/EntityDefinitions/base/targetname_base.tres" id="3_l1mk8"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="4_arlxu"] [ext_resource type="PackedScene" uid="uid://dbv1l74q66rdr" path="res://3D/Scenes/Props/Teleporter_3D.tscn" id="4_minqd"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="4_o1juy"] [resource] script = ExtResource("4_arlxu") +target_map_editor = 1 rotation_offset = Vector3(0, 180, 0) scene_file = ExtResource("4_minqd") apply_scale_on_map_build = false classname = "actor_teleporter" description = "Teleporter" base_classes = Array[Resource]([ExtResource("1_nutsy"), ExtResource("2_l1mk8"), ExtResource("3_l1mk8")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "enabled": false -} -class_property_descriptions = { +}) +class_property_descriptions = Dictionary[String, Variant]({ "enabled": "Enabled or disabled" -} -meta_properties = { -"size": AABB(-8, -8, -1, 8, 8, 1), -"studio": "\"3D/MapModels/actor_teleporter.glb\"" -} +}) +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_teleporter.glb\", \"scale\": 16.0 }", +"size": AABB(-8, -8, -1, 8, 8, 1) +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_VendingMachine.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_VendingMachine.tres index 1c017596..036a4394 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_VendingMachine.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_VendingMachine.tres @@ -1,18 +1,20 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://bmfarpfcbbfa5"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://bmfarpfcbbfa5"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_2x8yp"] [ext_resource type="PackedScene" uid="uid://bb2pjblwkb7ub" path="res://3D/Scenes/Props/Vending_Machine_3D.tscn" id="2_2x8yp"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_8x313"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_2x8yp"] [resource] script = ExtResource("3_2x8yp") +target_map_editor = 1 rotation_offset = Vector3(0, 180, 0) scene_file = ExtResource("2_2x8yp") apply_scale_on_map_build = false classname = "actor_vendingmachine" description = "Vending Machine" base_classes = Array[Resource]([ExtResource("1_2x8yp")]) -meta_properties = { -"size": AABB(-8, -8, -12, 8, 8, 12), -"studio": "\"3D/MapModels/actor_vendingmachine.glb\"" -} +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_vendingmachine.glb\", \"scale\": 16.0 }", +"size": AABB(-8, -8, -12, 8, 8, 12) +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Wallfan.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Wallfan.tres index cf6af4b7..821b89a0 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Wallfan.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_Wallfan.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://db7vsj36v1m2e"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://db7vsj36v1m2e"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_xso68"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_bmdmp"] [ext_resource type="PackedScene" uid="uid://cgy5kmem2hrps" path="res://3D/Scenes/Props/Wall_Fan_3D.tscn" id="2_xso68"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_jcora"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_tkgu8"] [resource] script = ExtResource("3_jcora") @@ -14,7 +15,7 @@ apply_scale_on_map_build = false classname = "actor_wallfan" description = "Wall Fan" base_classes = Array[Resource]([ExtResource("1_xso68"), ExtResource("2_bmdmp")]) -meta_properties = { -"model": "\"3D/MapModels/actor_wallfan.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_wallfan.glb\", \"scale\": 16.0 }", "size": AABB(-2, -12, -12, 2, 12, 12) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_WaterCooler.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_WaterCooler.tres index 1c83834c..3213669d 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_WaterCooler.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/Actor_WaterCooler.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://ctjw31lxc8gj1"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://ctjw31lxc8gj1"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_4cmfm"] [ext_resource type="PackedScene" uid="uid://q1qxucg2hesk" path="res://3D/Scenes/Props/WaterCooler_3D.tscn" id="2_4cmfm"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_v0met"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_hntxc"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_watercooler" description = "Water Cooler" base_classes = Array[Resource]([ExtResource("1_4cmfm")]) -meta_properties = { -"model": "\"3D/MapModels/actor_locker.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_watercooler.glb\", \"scale\": 16.0 }", "size": AABB(-4, -8, -12, 4, 8, 12) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy.tres index 49d91879..b2bed87b 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=4 format=3 uid="uid://cd8kf5wey5n8n"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://cd8kf5wey5n8n"] [ext_resource type="Resource" uid="uid://cwrcrupms7h4d" path="res://3D/TrenchBroom/EntityDefinitions/base/enemy_base.tres" id="1_nx3pd"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_yd0db"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_rwtar"] [ext_resource type="Script" uid="uid://00rbjdb4mnb0" path="res://Scripts/Actors/EnemyMarker3D.cs" id="4_7cqxf"] @@ -12,9 +13,9 @@ apply_scale_on_map_build = false classname = "marker_spawn_enemy" description = "Enemy Spawn Marker" base_classes = Array[Resource]([ExtResource("1_nx3pd")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "color": Color(0.9229911, 0.41614023, 0.21117541, 1), "size": AABB(-4, -4, -6, 4, 4, 6) -} +}) node_class = "Marker3D" metadata/_custom_type_script = "uid://cxsqwtsqd8w33" diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy_fairy_guard.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy_fairy_guard.tres index 38232966..5c23b5c7 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy_fairy_guard.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy_fairy_guard.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=4 format=3 uid="uid://cp6w7rgfgtxlk"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://cp6w7rgfgtxlk"] [ext_resource type="Resource" uid="uid://cwrcrupms7h4d" path="res://3D/TrenchBroom/EntityDefinitions/base/enemy_base.tres" id="1_4w7c8"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="2_8rpcj"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_ype3g"] [ext_resource type="Script" uid="uid://00rbjdb4mnb0" path="res://Scripts/Actors/EnemyMarker3D.cs" id="3_4yeye"] [resource] @@ -12,16 +13,18 @@ apply_scale_on_map_build = false classname = "marker_spawn_enemy_fairy_guard" description = "Fairy Guard Spawn Marker" base_classes = Array[Resource]([ExtResource("1_4w7c8")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ +"asdf": "test", "resource_path": "res://Resources/Enemies/Fairy_Guard_3D.tres" -} -class_property_descriptions = { +}) +class_property_descriptions = Dictionary[String, Variant]({ +"asdf": "test", "resource_path": "Path to the enemy resource" -} -meta_properties = { +}) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.9229911, 0.41614023, 0.21117541, 1), "model": "{ \"path\": \"textures\\Markers\\FairyGuard.png\", \"scale\": 1 }", "size": AABB(-4, -4, -6, 4, 4, 6) -} +}) node_class = "Marker3D" metadata/_custom_type_script = "uid://cxsqwtsqd8w33" diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy_fairy_small.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy_fairy_small.tres index d2c9c94c..43c96ab1 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy_fairy_small.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/EnemySpawners/marker_spawn_enemy_fairy_small.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=4 format=3 uid="uid://dxpm148kxfaqp"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://dxpm148kxfaqp"] [ext_resource type="Resource" uid="uid://cwrcrupms7h4d" path="res://3D/TrenchBroom/EntityDefinitions/base/enemy_base.tres" id="1_p3l7c"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="2_660wb"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_gywpy"] [ext_resource type="Script" uid="uid://00rbjdb4mnb0" path="res://Scripts/Actors/EnemyMarker3D.cs" id="3_gywpy"] [resource] @@ -12,13 +13,13 @@ apply_scale_on_map_build = false classname = "marker_spawn_enemy_fairy_small" description = "Small Fairy Spawn Marker" base_classes = Array[Resource]([ExtResource("1_p3l7c")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "resource_path": "res://Resources/Enemies/Base_Fairy_3D.tres" -} -meta_properties = { +}) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.9229911, 0.41614023, 0.21117541, 1), "model": "{ \"path\": \"textures\\Markers\\FairySmall.png\", \"scale\": 1 }", "size": AABB(-4, -4, -6, 4, 4, 6) -} +}) node_class = "Marker3D" metadata/_custom_type_script = "uid://cxsqwtsqd8w33" diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_AC_unit.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_AC_unit.tres index 517dc4cb..35220fd2 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_AC_unit.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_AC_unit.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=4 format=3 uid="uid://c5ms4y06kybgm"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://c5ms4y06kybgm"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_8qd6p"] [ext_resource type="PackedScene" uid="uid://jhdx1778ndss" path="res://3D/Scenes/Props/Ac_Unit_3D.tscn" id="2_8qd6p"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_yeia0"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_j0n30"] [resource] @@ -11,7 +12,6 @@ apply_scale_on_map_build = false classname = "actor_ac_unit" description = "AC Unit" base_classes = Array[Resource]([ExtResource("1_8qd6p")]) -meta_properties = { -"model": "\"3D/MapModels/AC_Unit.glb\"", +meta_properties = Dictionary[String, Variant]({ "size": AABB(-4, -8, -8, 4, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_Filing_Cabinet.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_Filing_Cabinet.tres index aa402937..867bd229 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_Filing_Cabinet.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_Filing_Cabinet.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://pwaweics6iqm"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://pwaweics6iqm"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_xkcss"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_wovf3"] [ext_resource type="PackedScene" uid="uid://ckcp087lqlsge" path="res://3D/Scenes/Props/Filing_Cabinet_3D.tscn" id="2_xkcss"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_xkcss"] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_filing_cabinet" description = "Filing Cabinet" base_classes = Array[Resource]([ExtResource("1_xkcss")]) -meta_properties = { -"model": "\"3D/MapModels/actor_filing_cabinet.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_filing_cabinet.glb\", \"scale\": 16.0 }", "size": AABB(-4, -8, -8, 4, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_alarmbox.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_alarmbox.tres index 2b64c96c..35100a5b 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_alarmbox.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_alarmbox.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://bb0dbkrmp7uq2"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://bb0dbkrmp7uq2"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_lfdgw"] [ext_resource type="PackedScene" uid="uid://cpx5yjfg3a2hw" path="res://3D/Scenes/Props/Alarm_Box_3D.tscn" id="2_400u4"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_lfdgw"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="4_n6irp"] [resource] @@ -12,7 +13,7 @@ apply_scale_on_map_build = false classname = "actor_alarmbox" description = "Alarm Box" base_classes = Array[Resource]([ExtResource("1_lfdgw")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "size": AABB(-4, -4, -4, 4, 4, 4), "studio": "\"3D/MapModels/actor_alarmbox.glb\"" -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_barrel.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_barrel.tres index c79fe22d..f3553b92 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_barrel.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_barrel.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://2j6k1gmnqqps"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=6 format=3 uid="uid://2j6k1gmnqqps"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_gqx5a"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="1_mixsm"] [ext_resource type="PackedScene" uid="uid://c2enjjxlfb5or" path="res://3D/Scenes/Props/barrel_3d.tscn" id="2_5uiix"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_8f3nn"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_8f3nn"] [resource] script = ExtResource("1_mixsm") @@ -13,10 +14,10 @@ apply_scale_on_map_build = false classname = "actor_barrel_1" description = "Explosive Barrel Type 1" base_classes = Array[Resource]([ExtResource("1_gqx5a"), ExtResource("2_8f3nn")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "health": 5.0 -} -meta_properties = { +}) +meta_properties = Dictionary[String, Variant]({ "model": "\"3D/MapModels/Barrel3DModel.glb\"", "size": AABB(-8, -8, -8, 8, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_blue.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_blue.tres index 9428549d..115d86ed 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_blue.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_blue.tres @@ -1,19 +1,19 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://dwy3es5h3pdg0"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=6 format=3 uid="uid://dwy3es5h3pdg0"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_jvuvk"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_jo0qs"] [ext_resource type="PackedScene" uid="uid://br01ww57uaky5" path="res://3D/Scenes/Props/Box_3D_Blue.tscn" id="2_jvuvk"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_q5tm4"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_rj0b6"] [resource] script = ExtResource("3_rj0b6") scene_file = ExtResource("2_jvuvk") -apply_rotation_on_map_build = false apply_scale_on_map_build = false classname = "actor_box_blue" description = "Blue Box" base_classes = Array[Resource]([ExtResource("1_jvuvk"), ExtResource("2_jo0qs")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "model": "\"3D/MapModels/Box_Blue.glb\"", "size": AABB(-8, -8, -4, 8, 8, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_blue_tall.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_blue_tall.tres index 73a1483d..cc750d5f 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_blue_tall.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_blue_tall.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://bhkn5vwemx7nk"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://bhkn5vwemx7nk"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_bbaxn"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_503pb"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_503pb"] [ext_resource type="PackedScene" uid="uid://cf7jo7q71ucli" path="res://3D/Scenes/Props/Box_3D_Blue_Tall.tscn" id="3_bbaxn"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="4_bbaxn"] @@ -15,7 +16,7 @@ apply_scale_on_map_build = false classname = "actor_box_blue_tall" description = "Tall Blue Box" base_classes = Array[Resource]([ExtResource("1_bbaxn"), ExtResource("2_503pb")]) -meta_properties = { -"model": "\"3D/MapModels/actor_box_blue_tall.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_box_blue_tall.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -9, 8, 8, 9) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_green.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_green.tres index 3c5a2dd6..86e8367a 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_green.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_green.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://41wnjh6ftght"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=6 format=3 uid="uid://41wnjh6ftght"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_tgkjo"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_hdwgc"] [ext_resource type="PackedScene" uid="uid://c6cdl3y3i3axl" path="res://3D/Scenes/Props/Box_3D_Yellow.tscn" id="2_tgkjo"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_023jf"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_poqrc"] [resource] script = ExtResource("3_023jf") @@ -12,7 +13,7 @@ apply_scale_on_map_build = false classname = "actor_box_yellow" description = "Yellow Box" base_classes = Array[Resource]([ExtResource("1_tgkjo"), ExtResource("2_hdwgc")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "model": "\"3D/MapModels/Box_Yellow.glb\"", "size": AABB(-8, -8, -4, 8, 8, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_red.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_red.tres index cd172a4b..54fdb926 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_red.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_red.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://cqiy7ue8nlj26"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=6 format=3 uid="uid://cqiy7ue8nlj26"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_nc5iv"] [ext_resource type="PackedScene" uid="uid://jffyxmft3nbw" path="res://3D/Scenes/Props/Box_3D_Red.tscn" id="2_nc5iv"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_qd7ab"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_igeav"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_sq6wo"] [resource] script = ExtResource("3_igeav") @@ -12,7 +13,7 @@ apply_scale_on_map_build = false classname = "actor_box_red" description = "Red Box" base_classes = Array[Resource]([ExtResource("1_nc5iv"), ExtResource("2_qd7ab")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "model": "\"3D/MapModels/Box_Red.glb\"", "size": AABB(-8, -8, -4, 8, 8, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_wood_tall.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_wood_tall.tres index b0f78997..2df8cb36 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_wood_tall.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_wood_tall.tres @@ -1,8 +1,9 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cpti2q5cb6wgw"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://cpti2q5cb6wgw"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_62h6k"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_scmlj"] [ext_resource type="PackedScene" uid="uid://bcoq4lutgg70g" path="res://3D/Scenes/Props/Box_3D_Wood_Tall.tscn" id="3_62h6k"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_scmlj"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="4_tjcj0"] [resource] @@ -15,7 +16,7 @@ apply_scale_on_map_build = false classname = "actor_box_wood_tall" description = "Tall Wooden Box" base_classes = Array[Resource]([ExtResource("1_62h6k"), ExtResource("2_scmlj")]) -meta_properties = { -"model": "\"3D/MapModels/actor_box_blue_tall.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_box_wood_tall.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -9, 8, 8, 9) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_yellow.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_yellow.tres index 49f288f6..c0f3d199 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_yellow.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_box_yellow.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://dj72os2jpdl4l"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=6 format=3 uid="uid://dj72os2jpdl4l"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_8m0gw"] [ext_resource type="PackedScene" uid="uid://c8wwioforxms3" path="res://3D/Scenes/Props/Box_3D_Green.tscn" id="2_3do5h"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_6f4l5"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_6f4l5"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_kjwi5"] [resource] script = ExtResource("3_6f4l5") @@ -12,7 +13,7 @@ apply_scale_on_map_build = false classname = "actor_box_green" description = "Green Box" base_classes = Array[Resource]([ExtResource("1_8m0gw"), ExtResource("2_6f4l5")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "model": "\"3D/MapModels/Box_Green.glb\"", "size": AABB(-8, -8, -4, 8, 8, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_chair.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_chair.tres index 0a6e63fc..3ae55c8f 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_chair.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_chair.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://umbceo5tcxni"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=6 format=3 uid="uid://umbceo5tcxni"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_t13cn"] [ext_resource type="Resource" uid="uid://dl5gtmotc4g6a" path="res://3D/TrenchBroom/EntityDefinitions/base/destroyable_base.tres" id="2_qg3x2"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_qg3x2"] [ext_resource type="PackedScene" uid="uid://dmwtysh7eijon" path="res://3D/Scenes/Props/Chair_3D.tscn" id="3_t13cn"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="4_v58ve"] @@ -13,10 +14,10 @@ apply_scale_on_map_build = false classname = "actor_chair" description = "Chair" base_classes = Array[Resource]([ExtResource("1_t13cn"), ExtResource("2_qg3x2")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "health": 5.0 -} -meta_properties = { +}) +meta_properties = Dictionary[String, Variant]({ "model": "{ \"path\": \"textures\\special/chair.png\", \"scale\": 1 }", "size": AABB(-8, -8, -8, 8, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_chest.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_chest.tres index e79abfd6..c859492a 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_chest.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_chest.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://cs333m37kmp2y"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cs333m37kmp2y"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_6p0lm"] [ext_resource type="PackedScene" uid="uid://dyi4ji0t3ryi4" path="res://3D/Scenes/Props/chest_3d.tscn" id="2_6p0lm"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_lkoo5"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_6p0lm"] [resource] @@ -13,10 +14,10 @@ apply_scale_on_map_build = false classname = "actor_chest_1" description = "Chest Type 1" base_classes = Array[Resource]([ExtResource("1_6p0lm")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "items": "" -} -meta_properties = { -"model": "\"3D/MapModels/actor_chest_1.glb\"", +}) +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_chest_1.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -8, 8, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_controlpad.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_controlpad.tres index d791382f..74d231ec 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_controlpad.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_controlpad.tres @@ -1,10 +1,11 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://ceio7tm5eopbb"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=7 format=3 uid="uid://ceio7tm5eopbb"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_5ms1a"] [ext_resource type="PackedScene" uid="uid://du6hlcoq0iip4" path="res://3D/Scenes/Props/control_pad_3d.tscn" id="2_5ms1a"] [ext_resource type="Resource" uid="uid://kerywjgft7vh" path="res://3D/TrenchBroom/EntityDefinitions/base/target_base.tres" id="2_65tcb"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_y02cg"] [ext_resource type="Resource" uid="uid://bd4h6ha84s74b" path="res://3D/TrenchBroom/EntityDefinitions/base/activation_type_base.tres" id="3_ybdcc"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="4_ybdcc"] [resource] script = ExtResource("3_y02cg") @@ -15,7 +16,7 @@ apply_scale_on_map_build = false classname = "actor_controlpad" description = "Control Pad" base_classes = Array[Resource]([ExtResource("1_5ms1a"), ExtResource("2_65tcb"), ExtResource("3_ybdcc")]) -meta_properties = { -"model": "\"3D/MapModels/actor_controlpad.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_controlpad.glb\", \"scale\": 16.0 }", "size": AABB(-4, -4, -4, 4, 4, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_dialogue.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_dialogue.tres index c735fcba..d44971d0 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_dialogue.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_dialogue.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://dlcokohev247j"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=6 format=3 uid="uid://dlcokohev247j"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_oao2t"] [ext_resource type="Resource" uid="uid://di5wnbv5icxtq" path="res://3D/TrenchBroom/EntityDefinitions/base/dialogue_base.tres" id="2_gfw3w"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_gfw3w"] [ext_resource type="PackedScene" uid="uid://bt8fwb313qf8n" path="res://3D/Scenes/Props/Interactables/Dialogue_Interactable_3D.tscn" id="3_oao2t"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="4_vw8gb"] @@ -12,6 +13,6 @@ apply_scale_on_map_build = false classname = "actor_dialogue" description = "Dialogue Interactable" base_classes = Array[Resource]([ExtResource("1_oao2t"), ExtResource("2_gfw3w")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "size": AABB(-4, -4, -4, 4, 4, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_keypad.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_keypad.tres index ba4fb02c..d1354dcf 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_keypad.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_keypad.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://1ew6u5xe3xhb"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=7 format=3 uid="uid://1ew6u5xe3xhb"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_ercjo"] [ext_resource type="Resource" uid="uid://kerywjgft7vh" path="res://3D/TrenchBroom/EntityDefinitions/base/target_base.tres" id="2_wyj6h"] [ext_resource type="Resource" uid="uid://dwc3j47cgj78j" path="res://3D/TrenchBroom/EntityDefinitions/base/requirement_key_base.tres" id="3_wyj6h"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="4_8crxf"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="4_c0bgo"] [ext_resource type="PackedScene" uid="uid://bd12hm40bg5mt" path="res://3D/Scenes/Props/Key_Pad_3D.tscn" id="4_wyj6h"] [resource] @@ -15,7 +16,7 @@ apply_scale_on_map_build = false classname = "actor_keypad" description = "Key Pad" base_classes = Array[Resource]([ExtResource("1_ercjo"), ExtResource("2_wyj6h"), ExtResource("3_wyj6h")]) -meta_properties = { -"model": "\"3D/MapModels/actor_keypad.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_keypad.glb\", \"scale\": 16.0 }", "size": AABB(-4, -4, -4, 4, 4, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_switch.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_switch.tres index ba7e240a..fed400cb 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_switch.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_switch.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://cuhhjj6kx74i0"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=7 format=3 uid="uid://cuhhjj6kx74i0"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_8v8rk"] [ext_resource type="Resource" uid="uid://kerywjgft7vh" path="res://3D/TrenchBroom/EntityDefinitions/base/target_base.tres" id="2_8wvoc"] [ext_resource type="Resource" uid="uid://bd4h6ha84s74b" path="res://3D/TrenchBroom/EntityDefinitions/base/activation_type_base.tres" id="3_oqfhk"] [ext_resource type="PackedScene" uid="uid://ctic4wsg3mibx" path="res://3D/Scenes/Props/Switch_3D.tscn" id="4_8v8rk"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="4_8wvoc"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="5_1s5ny"] [resource] @@ -15,7 +16,7 @@ apply_scale_on_map_build = false classname = "actor_switch" description = "Toggleable Switch" base_classes = Array[Resource]([ExtResource("1_8v8rk"), ExtResource("2_8wvoc"), ExtResource("3_oqfhk")]) -meta_properties = { -"model": "\"3D/MapModels/actor_controlpad.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_switch.glb\", \"scale\": 16.0 }", "size": AABB(-4, -4, -4, 4, 4, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tank.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tank.tres index aaa24986..9255173e 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tank.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tank.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://cqk03eifgt8do"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cqk03eifgt8do"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_8vrfi"] [ext_resource type="PackedScene" uid="uid://c3w0y1513hhbi" path="res://3D/BlockbenchModels/Tank/Tank_3D_Big.tscn" id="2_8vrfi"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_kna3x"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_8vrfi"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_tank" description = "Tank" base_classes = Array[Resource]([ExtResource("1_8vrfi")]) -meta_properties = { -"model": "\"3D/MapModels/actor_tank.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_tank.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -8, 8, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tank_standalone.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tank_standalone.tres index 3260e0f5..96ae1152 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tank_standalone.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tank_standalone.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://dd7haabidbq5s"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://dd7haabidbq5s"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_gcf4d"] [ext_resource type="PackedScene" uid="uid://byyrqmraqy0ns" path="res://3D/BlockbenchModels/Tank/Tank_3D_Standalone.tscn" id="2_gcf4d"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_yhblj"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_yhblj"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_tank_standalone" description = "Standalone Tank" base_classes = Array[Resource]([ExtResource("1_gcf4d")]) -meta_properties = { -"model": "\"3D/MapModels/actor_tank_standalone.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_tank_standalone.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -8, 8, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_terminal.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_terminal.tres index 5079d460..d5dd181b 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_terminal.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_terminal.tres @@ -1,9 +1,10 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://cvo11hahyoo4d"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=6 format=3 uid="uid://cvo11hahyoo4d"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_f03df"] [ext_resource type="PackedScene" uid="uid://hak5o0k5yhn1" path="res://3D/Scenes/Props/Terminal_3D.tscn" id="2_f03df"] [ext_resource type="Resource" uid="uid://di5wnbv5icxtq" path="res://3D/TrenchBroom/EntityDefinitions/base/dialogue_base.tres" id="2_iuc81"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_q0k5x"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_v4uwj"] [resource] script = ExtResource("3_q0k5x") @@ -12,7 +13,7 @@ apply_scale_on_map_build = false classname = "actor_terminal" description = "Red Box" base_classes = Array[Resource]([ExtResource("1_f03df"), ExtResource("2_iuc81")]) -meta_properties = { +meta_properties = Dictionary[String, Variant]({ "model": "\"3D/MapModels/Terminal.glb\"", "size": AABB(-4, -4, -4, 4, 4, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_terminal_big.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_terminal_big.tres index a0eabf07..e597ee28 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_terminal_big.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_terminal_big.tres @@ -1,18 +1,20 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://bw6nmtgqwmw5x"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://bw6nmtgqwmw5x"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_tvwfa"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_6a4nu"] [ext_resource type="PackedScene" uid="uid://cf3kjg36q3wvd" path="res://3D/Scenes/Props/Terminal_Big_3D.tscn" id="2_tvwfa"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_e32b8"] [resource] script = ExtResource("3_e32b8") +target_map_editor = 1 rotation_offset = Vector3(0, 180, 0) scene_file = ExtResource("2_tvwfa") apply_scale_on_map_build = false classname = "actor_terminal_big" description = "Terminal Big" base_classes = Array[Resource]([ExtResource("1_tvwfa")]) -meta_properties = { -"size": AABB(-8, -12, -12, 8, 12, 12), -"studio": "\"3D/MapModels/actor_terminal_big.glb\"" -} +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_terminal_big.glb\", \"scale\": 16.0 }", +"size": AABB(-8, -12, -12, 8, 12, 12) +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_corner.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_corner.tres index 8a87e78c..6f79cfb9 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_corner.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_corner.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://b2hgfu40nfoe3"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://b2hgfu40nfoe3"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_ipqa3"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_3ix77"] [ext_resource type="PackedScene" uid="uid://sas2dyqvk7bs" path="res://3D/Scenes/Props/Tube_3D_Corner.tscn" id="2_ipqa3"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_ipqa3"] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_tube_corner" description = "Tube Corner" base_classes = Array[Resource]([ExtResource("1_ipqa3")]) -meta_properties = { -"model": "\"3D/MapModels/actor_tube_corner.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_tube_corner.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -8, 8, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_junction.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_junction.tres index 7c264625..11b7811e 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_junction.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_junction.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://b23cpstd7ab8c"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://b23cpstd7ab8c"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_cpsnq"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_ar4ks"] [ext_resource type="PackedScene" uid="uid://b72piaqmqsj10" path="res://3D/Scenes/Props/Tube_3D_Junction.tscn" id="2_cpsnq"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_cpsnq"] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_tube_junction" description = "Blue Box" base_classes = Array[Resource]([ExtResource("1_cpsnq")]) -meta_properties = { -"model": "\"3D/MapModels/actor_tube_junction.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_tube_junction.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -8, 8, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_straight.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_straight.tres index 84bb8572..a4afff00 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_straight.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_straight.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://cwr35wrv087eu"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cwr35wrv087eu"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_dg8qq"] [ext_resource type="PackedScene" uid="uid://b7c6lrbrqgdlf" path="res://3D/Scenes/Props/Tube_3D_Straight.tscn" id="2_dg8qq"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_ry3gx"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_dg8qq"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_tube_straight" description = "Straight tube" base_classes = Array[Resource]([ExtResource("1_dg8qq")]) -meta_properties = { -"model": "\"3D/MapModels/actor_tube_straight.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_tube_straight.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -8, 8, 8, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_straight_long.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_straight_long.tres index 981ccbbf..c1c71805 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_straight_long.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_tube_straight_long.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=4 format=3 uid="uid://5jxyln87hluw"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://5jxyln87hluw"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_bwovp"] [ext_resource type="PackedScene" uid="uid://xxq6rhhdlbk3" path="res://3D/Scenes/Props/Tube_3D_Straight_Long.tscn" id="2_bwovp"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_r30wg"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_r30wg"] [resource] @@ -13,7 +14,7 @@ apply_scale_on_map_build = false classname = "actor_tube_straight_long" description = "Long straight tube" base_classes = Array[Resource]([ExtResource("1_bwovp")]) -meta_properties = { -"model": "\"3D/MapModels/actor_tube_straight_long.glb\"", +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_tube_straight_long.glb\", \"scale\": 16.0 }", "size": AABB(-8, -16, -8, 8, 16, 8) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_valve.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_valve.tres index 0157552d..cc0f651a 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/actor_valve.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/actor_valve.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://cy6802obllcmv"] +[gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=6 format=3 uid="uid://cy6802obllcmv"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_7mq2y"] [ext_resource type="Resource" uid="uid://kerywjgft7vh" path="res://3D/TrenchBroom/EntityDefinitions/base/target_base.tres" id="2_4hikn"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_7mq2y"] [ext_resource type="PackedScene" uid="uid://dvmkfm2l3vcf7" path="res://3D/Scenes/Props/Valve_3D.tscn" id="4_7mq2y"] [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="5_hgjgd"] @@ -14,13 +15,13 @@ apply_scale_on_map_build = false classname = "actor_valve" description = "Valve" base_classes = Array[Resource]([ExtResource("1_7mq2y"), ExtResource("2_4hikn")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "start_enabled": false -} -class_property_descriptions = { +}) +class_property_descriptions = Dictionary[String, Variant]({ "start_enabled": "Starts open?" -} -meta_properties = { -"model": "\"3D/MapModels/actor_valve.glb\"", +}) +meta_properties = Dictionary[String, Variant]({ +"model": "{\"path\": \"3D/MapModels/actor_valve.glb\", \"scale\": 16.0 }", "size": AABB(-8, -8, -4, 8, 8, 4) -} +}) diff --git a/3D/TrenchBroom/EntityDefinitions/point/actors/marker_spawn.tres b/3D/TrenchBroom/EntityDefinitions/point/actors/marker_spawn.tres index 31cbc33c..6039f23d 100644 --- a/3D/TrenchBroom/EntityDefinitions/point/actors/marker_spawn.tres +++ b/3D/TrenchBroom/EntityDefinitions/point/actors/marker_spawn.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=4 format=3 uid="uid://cmdgqpq5e1duq"] +[gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=5 format=3 uid="uid://cmdgqpq5e1duq"] [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="1_prigk"] [ext_resource type="Resource" uid="uid://5bc1qysixhmh" path="res://3D/TrenchBroom/EntityDefinitions/base/actor_base.tres" id="1_v787f"] +[ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_cr881"] [ext_resource type="Script" uid="uid://csruxpdnpj18r" path="res://Scripts/Actors/3D/PlayerStartMarker3D.cs" id="3_cr881"] [resource] @@ -12,15 +13,15 @@ apply_scale_on_map_build = false classname = "marker_spawn" description = "Spawn Marker" base_classes = Array[Resource]([ExtResource("1_v787f")]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "id": 0 -} -class_property_descriptions = { +}) +class_property_descriptions = Dictionary[String, Variant]({ "id": "The ID of the marker" -} -meta_properties = { +}) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.18968855, 0.7421875, 0.2575177, 1), "size": AABB(-4, -4, -6, 4, 4, 6) -} +}) node_class = "Marker3D" metadata/_custom_type_script = "uid://cxsqwtsqd8w33" diff --git a/3D/TrenchBroom/EntityDefinitions/solid/Brush/acid_area.tres b/3D/TrenchBroom/EntityDefinitions/solid/Brush/acid_area.tres index 760ae019..bf00fd2a 100644 --- a/3D/TrenchBroom/EntityDefinitions/solid/Brush/acid_area.tres +++ b/3D/TrenchBroom/EntityDefinitions/solid/Brush/acid_area.tres @@ -10,6 +10,7 @@ origin_type = 4 use_in_baked_light = false shadow_casting_setting = 0 build_occlusion = true +render_layers = 2 collision_layer = 256 collision_mask = 2 script_class = ExtResource("3_7wro5") diff --git a/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_bullet_permeable.tres b/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_bullet_permeable.tres index 9a82a60e..f8321256 100644 --- a/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_bullet_permeable.tres +++ b/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_bullet_permeable.tres @@ -4,6 +4,7 @@ [resource] script = ExtResource("1_77qe7") +render_layers = 2 collision_layer = 512 collision_mask = 0 classname = "solid_bullet_permeable" diff --git a/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_custom.tres b/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_custom.tres index f7d582aa..074431ea 100644 --- a/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_custom.tres +++ b/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_custom.tres @@ -7,6 +7,7 @@ script = ExtResource("1_x7jaa") spawn_type = 0 build_occlusion = true +render_layers = 2 collision_mask = 0 script_class = ExtResource("2_ypffe") classname = "worldspawn" diff --git a/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_shadow.tres b/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_shadow.tres index 0aa96917..c1ffa51c 100644 --- a/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_shadow.tres +++ b/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_shadow.tres @@ -7,6 +7,7 @@ script = ExtResource("1_7n2vi") origin_type = 4 build_occlusion = true +render_layers = 2 collision_mask = 0 script_class = ExtResource("2_s7wnd") classname = "solid_shadow" diff --git a/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_transparent.tres b/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_transparent.tres index 43bb316a..cd54b78a 100644 --- a/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_transparent.tres +++ b/3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_transparent.tres @@ -6,6 +6,7 @@ [resource] script = ExtResource("1_ig6cx") spawn_type = 1 +render_layers = 2 collision_mask = 0 script_class = ExtResource("2_n613u") classname = "solid_transparent" diff --git a/3D/TrenchBroom/EntityDefinitions/solid/funcs/func_move.tres b/3D/TrenchBroom/EntityDefinitions/solid/funcs/func_move.tres index fe4002da..f0d6e414 100644 --- a/3D/TrenchBroom/EntityDefinitions/solid/funcs/func_move.tres +++ b/3D/TrenchBroom/EntityDefinitions/solid/funcs/func_move.tres @@ -8,6 +8,7 @@ [resource] script = ExtResource("1_iat24") shadow_casting_setting = 0 +render_layers = 2 collision_shape_type = 2 collision_mask = 0 script_class = ExtResource("4_idgeg") diff --git a/3D/TrenchBroom/EntityDefinitions/solid/funcs/func_shroud.tres b/3D/TrenchBroom/EntityDefinitions/solid/funcs/func_shroud.tres index 03d91ed9..0404cdf2 100644 --- a/3D/TrenchBroom/EntityDefinitions/solid/funcs/func_shroud.tres +++ b/3D/TrenchBroom/EntityDefinitions/solid/funcs/func_shroud.tres @@ -10,6 +10,7 @@ script = ExtResource("3_wgfj6") use_in_baked_light = false shadow_casting_setting = 0 build_occlusion = true +render_layers = 2 collision_shape_type = 0 collision_layer = 0 collision_mask = 0 diff --git a/3D/TrenchBroom/Main_Game_Config.tres b/3D/TrenchBroom/Main_Game_Config.tres index c9be684d..4932a35d 100644 --- a/3D/TrenchBroom/Main_Game_Config.tres +++ b/3D/TrenchBroom/Main_Game_Config.tres @@ -6,7 +6,7 @@ [ext_resource type="Resource" uid="uid://bkjxc54mmdhbo" path="res://addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres" id="3_sgien"] [ext_resource type="Resource" uid="uid://cxqi6r6nblcn3" path="res://3D/TrenchBroom/fgd_main.tres" id="4_fiwv4"] [ext_resource type="Resource" uid="uid://bdmexobfdwk12" path="res://3D/TrenchBroom/Tags/glass_tag.tres" id="5_lswco"] -[ext_resource type="Script" uid="uid://cfpnvyygr4pb5" path="res://addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd" id="6_478qb"] +[ext_resource type="Script" uid="uid://cx44c4vnq8bt5" path="res://addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd" id="6_478qb"] [ext_resource type="Resource" uid="uid://chysqo5rdd5p" path="res://3D/TrenchBroom/Tags/test_glass_tag.tres" id="6_lswco"] [ext_resource type="Resource" uid="uid://b8kujhnu10hyc" path="res://3D/TrenchBroom/Tags/func_shroud_tag.tres" id="7_jsm6j"] [ext_resource type="Texture2D" uid="uid://decwujsyhj0qy" path="res://addons/func_godot/icon32.png" id="9_jsm6j"] diff --git a/3D/TrenchBroom/fgd_main.tres b/3D/TrenchBroom/fgd_main.tres index dc286a3b..9c2090fd 100644 --- a/3D/TrenchBroom/fgd_main.tres +++ b/3D/TrenchBroom/fgd_main.tres @@ -1,4 +1,4 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=10 format=3 uid="uid://cxqi6r6nblcn3"] +[gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=11 format=3 uid="uid://cxqi6r6nblcn3"] [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_24lxq"] [ext_resource type="Resource" uid="uid://onsfttdpojex" path="res://3D/TrenchBroom/fgd_base.tres" id="1_dlwdq"] @@ -9,8 +9,9 @@ [ext_resource type="Resource" uid="uid://b2cwp7m1sekps" path="res://3D/TrenchBroom/EntityDefinitions/solid/Brush/worldspawn_custom.tres" id="5_6tkjn"] [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="6_24lxq"] [ext_resource type="Script" uid="uid://drlmgulwbjwqu" path="res://addons/func_godot/src/fgd/func_godot_fgd_file.gd" id="7_m2ebq"] +[ext_resource type="Resource" uid="uid://bcdsueg5pysfq" path="res://addons/func_godot/fgd/cull_interior_faces.tres" id="9_0gbih"] [resource] script = ExtResource("7_m2ebq") base_fgd_files = Array[Resource]([ExtResource("1_dlwdq"), ExtResource("2_bci5m"), ExtResource("3_0gbih"), ExtResource("4_bci5m"), ExtResource("5_0gbih")]) -entity_definitions = Array[Resource]([ExtResource("1_24lxq"), ExtResource("5_6tkjn"), ExtResource("6_24lxq")]) +entity_definitions = Array[Resource]([ExtResource("1_24lxq"), ExtResource("5_6tkjn"), ExtResource("6_24lxq"), ExtResource("9_0gbih")]) diff --git a/ExternalMaterial/HexGrid/Singles/Floors/Floor111.tres b/ExternalMaterial/HexGrid/Singles/Floors/Floor111.tres new file mode 100644 index 00000000..ba55e37b --- /dev/null +++ b/ExternalMaterial/HexGrid/Singles/Floors/Floor111.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://dh27w8id70p31"] + +[ext_resource type="Texture2D" uid="uid://djo5j263y2n6h" path="res://textures/Floors/Floor111.png" id="1_45f37"] + +[resource] +albedo_texture = ExtResource("1_45f37") +metallic_specular = 0.0 +texture_filter = 2 diff --git a/ExternalMaterial/HexGrid/Singles/Floors/Floor133.tres b/ExternalMaterial/HexGrid/Singles/Floors/Floor133.tres new file mode 100644 index 00000000..c3091e87 --- /dev/null +++ b/ExternalMaterial/HexGrid/Singles/Floors/Floor133.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://bjc6yltc257l"] + +[ext_resource type="Texture2D" uid="uid://b6h1161qr7rmw" path="res://textures/Floors/Floor133.png" id="1_eoo3g"] + +[resource] +albedo_texture = ExtResource("1_eoo3g") +metallic_specular = 0.0 +texture_filter = 2 diff --git a/ExternalMaterial/HexGrid/Singles/Floors/Floor139.tres b/ExternalMaterial/HexGrid/Singles/Floors/Floor139.tres new file mode 100644 index 00000000..aeaeea5c --- /dev/null +++ b/ExternalMaterial/HexGrid/Singles/Floors/Floor139.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://de18fot2lb8d"] + +[ext_resource type="Texture2D" uid="uid://cg6gd7gpp42tv" path="res://textures/Floors/Floor139.png" id="1_c8xhs"] + +[resource] +albedo_texture = ExtResource("1_c8xhs") +metallic_specular = 0.0 +texture_filter = 2 diff --git a/ExternalMaterial/HexGrid/Singles/Floors/Floor234.tres b/ExternalMaterial/HexGrid/Singles/Floors/Floor234.tres new file mode 100644 index 00000000..2536c71a --- /dev/null +++ b/ExternalMaterial/HexGrid/Singles/Floors/Floor234.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://dc5uihyvlo5bj"] + +[ext_resource type="Texture2D" uid="uid://cshc1p4q0ltpo" path="res://textures/Floors/Floor234.png" id="1_3br4o"] + +[resource] +albedo_texture = ExtResource("1_3br4o") +metallic_specular = 0.0 +texture_filter = 2 diff --git a/ExternalMaterial/HexGrid/Singles/Floors/Floor235.tres b/ExternalMaterial/HexGrid/Singles/Floors/Floor235.tres new file mode 100644 index 00000000..f14af659 --- /dev/null +++ b/ExternalMaterial/HexGrid/Singles/Floors/Floor235.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://ch7jrvonraqy2"] + +[ext_resource type="Texture2D" uid="uid://bqerbq1uso6yi" path="res://textures/Floors/Floor235.png" id="1_xbgi6"] + +[resource] +albedo_texture = ExtResource("1_xbgi6") +metallic_specular = 0.0 +texture_filter = 2 diff --git a/ExternalMaterial/HexGrid/Singles/Floors/Floor_Tiled_0226.tres b/ExternalMaterial/HexGrid/Singles/Floors/Floor_Tiled_0226.tres new file mode 100644 index 00000000..0d7cfa00 --- /dev/null +++ b/ExternalMaterial/HexGrid/Singles/Floors/Floor_Tiled_0226.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://c71q4p5kypgxk"] + +[ext_resource type="Texture2D" uid="uid://deu8t4tn2lp52" path="res://textures/Floors/Floor_Tiled_0226.png" id="1_hmyum"] + +[resource] +albedo_texture = ExtResource("1_hmyum") +metallic_specular = 0.0 +texture_filter = 2 diff --git a/addons/func_godot/LICENSE b/addons/func_godot/LICENSE new file mode 100644 index 00000000..a1361468 --- /dev/null +++ b/addons/func_godot/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 func-godot + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/addons/func_godot/fgd/cull_interior_faces.tres b/addons/func_godot/fgd/cull_interior_faces.tres new file mode 100644 index 00000000..63baa317 --- /dev/null +++ b/addons/func_godot/fgd/cull_interior_faces.tres @@ -0,0 +1,15 @@ +[gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=2 format=3 uid="uid://bcdsueg5pysfq"] + +[ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="1_21jph"] + +[resource] +script = ExtResource("1_21jph") +classname = "CullInteriorFaces" +description = "Cull interior faces option for SolidClass Geometry" +class_properties = Dictionary[String, Variant]({ +"_cull_interior_faces": false +}) +class_property_descriptions = Dictionary[String, Variant]({ +"_cull_interior_faces": "If true, cull interior faces with matching vertices or faces that are flush within a larger face. Note: This has a performance impact that scales with how many brushes are in the brush entity." +}) +metadata/_custom_type_script = "uid://cgkrrgcimlr8y" diff --git a/addons/func_godot/fgd/func_detail.tres b/addons/func_godot/fgd/func_detail.tres index 0cd47040..14ffcaa1 100644 --- a/addons/func_godot/fgd/func_detail.tres +++ b/addons/func_godot/fgd/func_detail.tres @@ -1,39 +1,18 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://cxy7jnh6d7msn"] +[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=5 format=3 uid="uid://cxy7jnh6d7msn"] [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="1_0fsmp"] [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_c3bns"] [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_c03gr"] +[ext_resource type="Resource" uid="uid://bcdsueg5pysfq" path="res://addons/func_godot/fgd/cull_interior_faces.tres" id="3_wuxhx"] [resource] script = ExtResource("1_0fsmp") -spawn_type = 2 -origin_type = 3 -build_visuals = true -global_illumination_mode = 1 -use_in_baked_light = true -shadow_casting_setting = 1 -build_occlusion = false -render_layers = 1 collision_shape_type = 2 -collision_layer = 1 collision_mask = 0 -collision_priority = 1.0 -collision_shape_margin = 0.04 -add_textures_metadata = false -add_vertex_metadata = false -add_face_position_metadata = false -add_face_normal_metadata = false -add_collision_shape_to_face_indices_metadata = false -add_collision_shape_face_range_metadata = false classname = "func_detail" description = "Static collidable geometry. Builds a StaticBody3D with a MeshInstance3D and a single concave CollisionShape3D. Does not occlude other VisualInstance3D nodes." -func_godot_internal = false -base_classes = Array[Resource]([ExtResource("1_c3bns"), ExtResource("2_c03gr")]) -class_properties = {} -class_property_descriptions = {} -auto_apply_to_matching_node_properties = false -meta_properties = { +base_classes = Array[Resource]([ExtResource("1_c3bns"), ExtResource("2_c03gr"), ExtResource("3_wuxhx")]) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.8, 0.8, 0.8, 1) -} +}) node_class = "StaticBody3D" -name_property = "" diff --git a/addons/func_godot/fgd/func_detail_illusionary.tres b/addons/func_godot/fgd/func_detail_illusionary.tres index b99bc029..25d9e0f4 100644 --- a/addons/func_godot/fgd/func_detail_illusionary.tres +++ b/addons/func_godot/fgd/func_detail_illusionary.tres @@ -1,39 +1,17 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://ch3e0dix85uhb"] +[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=5 format=3 uid="uid://ch3e0dix85uhb"] [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_ar63x"] [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_j7vgq"] [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_lhb87"] +[ext_resource type="Resource" uid="uid://bcdsueg5pysfq" path="res://addons/func_godot/fgd/cull_interior_faces.tres" id="3_1mhrv"] [resource] script = ExtResource("2_lhb87") -spawn_type = 2 -origin_type = 3 -build_visuals = true -global_illumination_mode = 1 -use_in_baked_light = true -shadow_casting_setting = 1 -build_occlusion = false -render_layers = 1 collision_shape_type = 0 -collision_layer = 1 -collision_mask = 1 -collision_priority = 1.0 -collision_shape_margin = 0.04 -add_textures_metadata = false -add_vertex_metadata = false -add_face_position_metadata = false -add_face_normal_metadata = false -add_collision_shape_to_face_indices_metadata = false -add_collision_shape_face_range_metadata = false classname = "func_detail_illusionary" description = "Static geometry with no collision. Builds a Node3D with a MeshInstance3D. Does not occlude other VisualInstance3D nodes." -func_godot_internal = false -base_classes = Array[Resource]([ExtResource("1_ar63x"), ExtResource("2_j7vgq")]) -class_properties = {} -class_property_descriptions = {} -auto_apply_to_matching_node_properties = false -meta_properties = { +base_classes = Array[Resource]([ExtResource("1_ar63x"), ExtResource("2_j7vgq"), ExtResource("3_1mhrv")]) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.8, 0.8, 0.8, 1) -} +}) node_class = "Node3D" -name_property = "" diff --git a/addons/func_godot/fgd/func_geo.tres b/addons/func_godot/fgd/func_geo.tres index b9e60aad..e2c3d73a 100644 --- a/addons/func_godot/fgd/func_geo.tres +++ b/addons/func_godot/fgd/func_geo.tres @@ -1,39 +1,19 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://b70vf4t5dc70t"] +[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=5 format=3 uid="uid://b70vf4t5dc70t"] [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_5mwee"] [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_8o081"] [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_bp8pb"] +[ext_resource type="Resource" uid="uid://bcdsueg5pysfq" path="res://addons/func_godot/fgd/cull_interior_faces.tres" id="3_xnsya"] [resource] script = ExtResource("2_8o081") -spawn_type = 2 -origin_type = 3 -build_visuals = true -global_illumination_mode = 1 -use_in_baked_light = true -shadow_casting_setting = 1 build_occlusion = true -render_layers = 1 collision_shape_type = 2 -collision_layer = 1 collision_mask = 0 -collision_priority = 1.0 -collision_shape_margin = 0.04 -add_textures_metadata = false -add_vertex_metadata = false -add_face_position_metadata = false -add_face_normal_metadata = false -add_collision_shape_to_face_indices_metadata = false -add_collision_shape_face_range_metadata = false classname = "func_geo" description = "Static collidable geometry. Builds a StaticBody3D with a MeshInstance3D, a single concave CollisionShape3D, and an OccluderInstance3D." -func_godot_internal = false -base_classes = Array[Resource]([ExtResource("1_5mwee"), ExtResource("2_bp8pb")]) -class_properties = {} -class_property_descriptions = {} -auto_apply_to_matching_node_properties = false -meta_properties = { +base_classes = Array[Resource]([ExtResource("1_5mwee"), ExtResource("2_bp8pb"), ExtResource("3_xnsya")]) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.8, 0.8, 0.8, 1) -} +}) node_class = "StaticBody3D" -name_property = "" diff --git a/addons/func_godot/fgd/func_godot_fgd.tres b/addons/func_godot/fgd/func_godot_fgd.tres index c8fba83d..0f36d006 100644 --- a/addons/func_godot/fgd/func_godot_fgd.tres +++ b/addons/func_godot/fgd/func_godot_fgd.tres @@ -1,4 +1,4 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=9 format=3 uid="uid://crgpdahjaj"] +[gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=10 format=3 uid="uid://crgpdahjaj"] [ext_resource type="Script" uid="uid://drlmgulwbjwqu" path="res://addons/func_godot/src/fgd/func_godot_fgd_file.gd" id="1_axt3h"] [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_ehab8"] @@ -6,12 +6,10 @@ [ext_resource type="Resource" uid="uid://bdji3873bg32h" path="res://addons/func_godot/fgd/worldspawn.tres" id="2_ri2rx"] [ext_resource type="Resource" uid="uid://b70vf4t5dc70t" path="res://addons/func_godot/fgd/func_geo.tres" id="3_7jigp"] [ext_resource type="Resource" uid="uid://cxy7jnh6d7msn" path="res://addons/func_godot/fgd/func_detail.tres" id="3_fqfww"] +[ext_resource type="Resource" uid="uid://bcdsueg5pysfq" path="res://addons/func_godot/fgd/cull_interior_faces.tres" id="3_h5cmk"] [ext_resource type="Resource" uid="uid://dg5x44cc7flew" path="res://addons/func_godot/fgd/func_illusionary.tres" id="4_c4ucw"] [ext_resource type="Resource" uid="uid://ch3e0dix85uhb" path="res://addons/func_godot/fgd/func_detail_illusionary.tres" id="5_b2q3p"] [resource] script = ExtResource("1_axt3h") -target_map_editor = 1 -fgd_name = "FuncGodot" -base_fgd_files = Array[Resource]([]) -entity_definitions = Array[Resource]([ExtResource("1_ehab8"), ExtResource("2_7jebp"), ExtResource("2_ri2rx"), ExtResource("3_7jigp"), ExtResource("3_fqfww"), ExtResource("5_b2q3p"), ExtResource("4_c4ucw")]) +entity_definitions = Array[Resource]([ExtResource("1_ehab8"), ExtResource("2_7jebp"), ExtResource("3_h5cmk"), ExtResource("2_ri2rx"), ExtResource("3_7jigp"), ExtResource("3_fqfww"), ExtResource("5_b2q3p"), ExtResource("4_c4ucw")]) diff --git a/addons/func_godot/fgd/func_illusionary.tres b/addons/func_godot/fgd/func_illusionary.tres index ece499af..38507803 100644 --- a/addons/func_godot/fgd/func_illusionary.tres +++ b/addons/func_godot/fgd/func_illusionary.tres @@ -1,39 +1,18 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://dg5x44cc7flew"] +[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=5 format=3 uid="uid://dg5x44cc7flew"] [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_kv0mq"] [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_hovr4"] [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_uffhi"] +[ext_resource type="Resource" uid="uid://bcdsueg5pysfq" path="res://addons/func_godot/fgd/cull_interior_faces.tres" id="3_woywv"] [resource] script = ExtResource("2_uffhi") -spawn_type = 2 -origin_type = 3 -build_visuals = true -global_illumination_mode = 1 -use_in_baked_light = true -shadow_casting_setting = 1 build_occlusion = true -render_layers = 1 collision_shape_type = 0 -collision_layer = 1 -collision_mask = 1 -collision_priority = 1.0 -collision_shape_margin = 0.04 -add_textures_metadata = false -add_vertex_metadata = false -add_face_position_metadata = false -add_face_normal_metadata = false -add_collision_shape_to_face_indices_metadata = false -add_collision_shape_face_range_metadata = false classname = "func_illusionary" description = "Static geometry with no collision. Builds a Node3D with a MeshInstance3D and an Occluder3D to aid in render culling of other VisualInstance3D nodes." -func_godot_internal = false -base_classes = Array[Resource]([ExtResource("1_kv0mq"), ExtResource("2_hovr4")]) -class_properties = {} -class_property_descriptions = {} -auto_apply_to_matching_node_properties = false -meta_properties = { +base_classes = Array[Resource]([ExtResource("1_kv0mq"), ExtResource("2_hovr4"), ExtResource("3_woywv")]) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.8, 0.8, 0.8, 1) -} +}) node_class = "Node3D" -name_property = "" diff --git a/addons/func_godot/fgd/phong_base.tres b/addons/func_godot/fgd/phong_base.tres index 4b8e456e..365813da 100644 --- a/addons/func_godot/fgd/phong_base.tres +++ b/addons/func_godot/fgd/phong_base.tres @@ -6,23 +6,14 @@ script = ExtResource("1_04y3n") classname = "Phong" description = "Phong shading options for SolidClass geometry." -func_godot_internal = false -base_classes = Array[Resource]([]) -class_properties = { +class_properties = Dictionary[String, Variant]({ "_phong": { "Disabled": 0, "Smooth shading": 1 }, "_phong_angle": 89.0 -} -class_property_descriptions = { +}) +class_property_descriptions = Dictionary[String, Variant]({ "_phong": ["Phong shading", 0], "_phong_angle": "Phong smoothing angle" -} -auto_apply_to_matching_node_properties = false -meta_properties = { -"color": Color(0.8, 0.8, 0.8, 1), -"size": AABB(-8, -8, -8, 8, 8, 8) -} -node_class = "" -name_property = "" +}) diff --git a/addons/func_godot/fgd/vertex_merge_distance_base.tres b/addons/func_godot/fgd/vertex_merge_distance_base.tres index 68dcc64c..6ef62d56 100644 --- a/addons/func_godot/fgd/vertex_merge_distance_base.tres +++ b/addons/func_godot/fgd/vertex_merge_distance_base.tres @@ -6,19 +6,10 @@ script = ExtResource("1_h3atm") classname = "VertexMergeDistance" description = "Adjustable value to snap vertices to on map build. This can reduce instances of seams between polygons." -func_godot_internal = false -base_classes = Array[Resource]([]) -class_properties = { -"_vertex_merge_distance": 0.008 -} -class_property_descriptions = { +class_properties = Dictionary[String, Variant]({ +"_vertex_merge_distance": 0.03125 +}) +class_property_descriptions = Dictionary[String, Variant]({ "_vertex_merge_distance": "Adjustable value to snap vertices to on map build. This can reduce instances of seams between polygons." -} -auto_apply_to_matching_node_properties = false -meta_properties = { -"color": Color(0.8, 0.8, 0.8, 1), -"size": AABB(-8, -8, -8, 8, 8, 8) -} -node_class = "" -name_property = "" +}) metadata/_custom_type_script = "uid://ck575aqs1sbrb" diff --git a/addons/func_godot/fgd/worldspawn.tres b/addons/func_godot/fgd/worldspawn.tres index 408e7fbf..e773109d 100644 --- a/addons/func_godot/fgd/worldspawn.tres +++ b/addons/func_godot/fgd/worldspawn.tres @@ -1,38 +1,18 @@ -[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=3 format=3 uid="uid://bdji3873bg32h"] +[gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://bdji3873bg32h"] [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="1_62t8m"] [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="1_h1046"] +[ext_resource type="Resource" uid="uid://bcdsueg5pysfq" path="res://addons/func_godot/fgd/cull_interior_faces.tres" id="2_ky6lr"] [resource] script = ExtResource("1_62t8m") spawn_type = 0 origin_type = 1 -build_visuals = true -global_illumination_mode = 1 -use_in_baked_light = true -shadow_casting_setting = 1 -build_occlusion = false -render_layers = 1 -collision_shape_type = 1 -collision_layer = 1 collision_mask = 0 -collision_priority = 1.0 -collision_shape_margin = 0.04 -add_textures_metadata = false -add_vertex_metadata = false -add_face_position_metadata = false -add_face_normal_metadata = false -add_collision_shape_to_face_indices_metadata = false -add_collision_shape_face_range_metadata = false classname = "worldspawn" -description = "Default static world geometry. Builds a StaticBody3D with a single MeshInstance3D and a single convex CollisionShape3D shape. Also builds Occluder3D to aid in render culling of other VisualInstance3D nodes." -func_godot_internal = false -base_classes = Array[Resource]([ExtResource("1_h1046")]) -class_properties = {} -class_property_descriptions = {} -auto_apply_to_matching_node_properties = false -meta_properties = { +description = "Default static world geometry. Builds a StaticBody3D with a single MeshInstance3D and a single convex CollisionShape3D shape." +base_classes = Array[Resource]([ExtResource("1_h1046"), ExtResource("2_ky6lr")]) +meta_properties = Dictionary[String, Variant]({ "color": Color(0.8, 0.8, 0.8, 1) -} +}) node_class = "StaticBody3D" -name_property = "" diff --git a/addons/func_godot/func_godot_default_map_settings.tres b/addons/func_godot/func_godot_default_map_settings.tres index 01cdd2d8..bf9ad02b 100644 --- a/addons/func_godot/func_godot_default_map_settings.tres +++ b/addons/func_godot/func_godot_default_map_settings.tres @@ -1,31 +1,9 @@ -[gd_resource type="Resource" script_class="FuncGodotMapSettings" load_steps=4 format=3 uid="uid://bkhxcqsquw1yg"] +[gd_resource type="Resource" script_class="FuncGodotMapSettings" load_steps=5 format=3 uid="uid://bkhxcqsquw1yg"] [ext_resource type="Material" uid="uid://cvex6toty8yn7" path="res://addons/func_godot/textures/default_material.tres" id="1_8l5wm"] -[ext_resource type="Script" uid="uid://bctwech0sq0kh" path="res://addons/func_godot/src/map/func_godot_map_settings.gd" id="1_dlf23"] -[ext_resource type="Resource" uid="uid://crgpdahjaj" path="res://addons/func_godot/fgd/func_godot_fgd.tres" id="1_hd7se"] +[ext_resource type="Script" uid="uid://38q6k0ctahjn" path="res://addons/func_godot/src/map/func_godot_map_settings.gd" id="1_dlf23"] +[ext_resource type="Resource" uid="uid://crgpdahjaj" path="res://addons/func_godot/fgd/func_godot_fgd.tres" id="2_hf4oi"] +[ext_resource type="Script" uid="uid://cij36hpqc46c" path="res://addons/func_godot/src/import/quake_wad_file.gd" id="4_576s4"] [resource] script = ExtResource("1_dlf23") -inverse_scale_factor = 16.0 -entity_fgd = ExtResource("1_hd7se") -entity_name_property = "" -base_texture_dir = "res://textures" -texture_file_extensions = Array[String](["png", "jpg", "jpeg", "bmp", "tga", "webp"]) -clip_texture = "special/clip" -skip_texture = "special/skip" -origin_texture = "special/origin" -texture_wads = Array[Resource]([]) -material_file_extension = "tres" -default_material = ExtResource("1_8l5wm") -default_material_albedo_uniform = "" -albedo_map_pattern = "%s_albedo.%s" -normal_map_pattern = "%s_normal.%s" -metallic_map_pattern = "%s_metallic.%s" -roughness_map_pattern = "%s_roughness.%s" -emission_map_pattern = "%s_emission.%s" -ao_map_pattern = "%s_ao.%s" -height_map_pattern = "%s_height.%s" -orm_map_pattern = "%s_orm.%s" -save_generated_materials = true -uv_unwrap_texel_size = 2.0 -use_trenchbroom_groups_hierarchy = false diff --git a/addons/func_godot/game_config/netradiant_custom/func_godot_netradiant_custom_gamepack_config.tres b/addons/func_godot/game_config/netradiant_custom/func_godot_netradiant_custom_gamepack_config.tres index 85c0e6f8..cfc3c5f2 100644 --- a/addons/func_godot/game_config/netradiant_custom/func_godot_netradiant_custom_gamepack_config.tres +++ b/addons/func_godot/game_config/netradiant_custom/func_godot_netradiant_custom_gamepack_config.tres @@ -8,17 +8,6 @@ [resource] script = ExtResource("2_en8ro") -gamepack_name = "func_godot" -game_name = "FuncGodot" -base_game_path = "" -fgd_file = ExtResource("1_gct4v") -netradiant_custom_shaders = Array[Resource]([ExtResource("2_w7psh"), ExtResource("3_6gpk8"), ExtResource("4_8rl60")]) -texture_types = PackedStringArray("png", "jpg", "jpeg", "bmp", "tga") model_types = PackedStringArray("glb", "gltf", "obj") sound_types = PackedStringArray("wav", "ogg") -default_scale = "1.0" -clip_texture = "textures/special/clip" -skip_texture = "textures/special/skip" -map_type = 1 -default_build_menu_variables = {} -default_build_menu_commands = {} +texture_types = PackedStringArray("png", "jpg", "jpeg", "bmp", "tga") diff --git a/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_clip.tres b/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_clip.tres index d9697744..de8d99e3 100644 --- a/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_clip.tres +++ b/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_clip.tres @@ -4,5 +4,4 @@ [resource] script = ExtResource("1_cuylw") -texture_path = "textures/special/clip" -shader_attributes = Array[String](["qer_trans 0.4"]) +texture_path = "textures/clip" diff --git a/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_origin.tres b/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_origin.tres index 72bd1715..243bb53b 100644 --- a/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_origin.tres +++ b/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_origin.tres @@ -4,5 +4,4 @@ [resource] script = ExtResource("1_ah2cp") -texture_path = "textures/special/origin" -shader_attributes = Array[String](["qer_trans 0.4"]) +texture_path = "textures/origin" diff --git a/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_skip.tres b/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_skip.tres index f3681405..769b5c86 100644 --- a/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_skip.tres +++ b/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_skip.tres @@ -4,5 +4,4 @@ [resource] script = ExtResource("1_4ja6h") -texture_path = "textures/special/skip" -shader_attributes = Array[String](["qer_trans 0.4"]) +texture_path = "textures/skip" diff --git a/addons/func_godot/game_config/trenchbroom/func_godot_tb_game_config.tres b/addons/func_godot/game_config/trenchbroom/func_godot_tb_game_config.tres index a08fb686..4f8b2fdd 100644 --- a/addons/func_godot/game_config/trenchbroom/func_godot_tb_game_config.tres +++ b/addons/func_godot/game_config/trenchbroom/func_godot_tb_game_config.tres @@ -9,26 +9,3 @@ [resource] script = ExtResource("2_ns6ah") -game_name = "FuncGodot" -icon = ExtResource("6_tex5j") -map_formats = Array[Dictionary]([{ -"format": "Valve", -"initialmap": "initial_valve.map" -}, { -"format": "Standard", -"initialmap": "initial_standard.map" -}, { -"format": "Quake2", -"initialmap": "initial_quake2.map" -}, { -"format": "Quake3" -}]) -textures_root_folder = "textures" -texture_exclusion_patterns = Array[String](["*_albedo", "*_ao", "*_emission", "*_height", "*_metallic", "*_normal", "*_orm", "*_roughness", "*_sss"]) -palette_path = "textures/palette.lmp" -fgd_file = ExtResource("1_8u1vq") -entity_scale = "32" -brush_tags = Array[Resource]([]) -brushface_tags = Array[Resource]([ExtResource("1_rsp20"), ExtResource("2_166i2"), ExtResource("3_stisi")]) -default_uv_scale = Vector2(1, 1) -game_config_version = 0 diff --git a/addons/func_godot/game_config/trenchbroom/tb_brush_tag_func.tres b/addons/func_godot/game_config/trenchbroom/tb_brush_tag_func.tres index e6f73c7f..0899a174 100644 --- a/addons/func_godot/game_config/trenchbroom/tb_brush_tag_func.tres +++ b/addons/func_godot/game_config/trenchbroom/tb_brush_tag_func.tres @@ -8,4 +8,3 @@ tag_name = "Func" tag_attributes = Array[String]([]) tag_match_type = 1 tag_pattern = "func*" -texture_name = "" diff --git a/addons/func_godot/game_config/trenchbroom/tb_brush_tag_trigger.tres b/addons/func_godot/game_config/trenchbroom/tb_brush_tag_trigger.tres index c915f1c1..5028a574 100644 --- a/addons/func_godot/game_config/trenchbroom/tb_brush_tag_trigger.tres +++ b/addons/func_godot/game_config/trenchbroom/tb_brush_tag_trigger.tres @@ -5,7 +5,6 @@ [resource] script = ExtResource("1_msqpk") tag_name = "Trigger" -tag_attributes = Array[String](["transparent"]) tag_match_type = 1 tag_pattern = "trigger*" -texture_name = "special/trigger" +texture_name = "trigger" diff --git a/addons/func_godot/game_config/trenchbroom/tb_face_tag_clip.tres b/addons/func_godot/game_config/trenchbroom/tb_face_tag_clip.tres index bec8a2c1..c00270ad 100644 --- a/addons/func_godot/game_config/trenchbroom/tb_face_tag_clip.tres +++ b/addons/func_godot/game_config/trenchbroom/tb_face_tag_clip.tres @@ -5,7 +5,4 @@ [resource] script = ExtResource("1_7td58") tag_name = "Clip" -tag_attributes = Array[String](["transparent"]) -tag_match_type = 0 tag_pattern = "clip" -texture_name = "" diff --git a/addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres b/addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres index 82478f3e..84f4da9c 100644 --- a/addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres +++ b/addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres @@ -5,7 +5,4 @@ [resource] script = ExtResource("1_enkfc") tag_name = "Origin" -tag_attributes = Array[String](["transparent"]) -tag_match_type = 0 tag_pattern = "origin" -texture_name = "" diff --git a/addons/func_godot/game_config/trenchbroom/tb_face_tag_skip.tres b/addons/func_godot/game_config/trenchbroom/tb_face_tag_skip.tres index 342646cb..e44627db 100644 --- a/addons/func_godot/game_config/trenchbroom/tb_face_tag_skip.tres +++ b/addons/func_godot/game_config/trenchbroom/tb_face_tag_skip.tres @@ -5,7 +5,4 @@ [resource] script = ExtResource("1_2teqe") tag_name = "Skip" -tag_attributes = Array[String](["transparent"]) -tag_match_type = 0 tag_pattern = "skip" -texture_name = "" diff --git a/addons/func_godot/icon.png.import b/addons/func_godot/icon.png.import index 7b928c1a..a91ba088 100644 --- a/addons/func_godot/icon.png.import +++ b/addons/func_godot/icon.png.import @@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/icon.png-6db43b6a52df1ce3744a82f15cbdbbea.cte compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/addons/func_godot/icon32.png.import b/addons/func_godot/icon32.png.import index e2db946e..8d3039c3 100644 --- a/addons/func_godot/icon32.png.import +++ b/addons/func_godot/icon32.png.import @@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/icon32.png-7025e2d95a64a3066b7947e1900b4daf.c compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/addons/func_godot/plugin.cfg b/addons/func_godot/plugin.cfg index d0bb2514..38b77fd2 100644 --- a/addons/func_godot/plugin.cfg +++ b/addons/func_godot/plugin.cfg @@ -2,6 +2,6 @@ name="FuncGodot" description="Quake .map and Half-Life .vmf file support for Godot." -author="Josh Palmer, Hannah Crawford, Emberlynn Bland, Tim Maccabe, Vera Lux" -version="2025.9" +author="Josh Palmer, Hannah Crawford, Emberlynn Bland, Tim Maccabe, Vera Lux, func_godot Community" +version="2025.12" script="src/func_godot_plugin.gd" diff --git a/addons/func_godot/src/core/data.gd b/addons/func_godot/src/core/data.gd index ad1f1756..b3edf243 100644 --- a/addons/func_godot/src/core/data.gd +++ b/addons/func_godot/src/core/data.gd @@ -122,7 +122,7 @@ class GroupData extends RefCounted: class EntityData extends RefCounted: ## All of the entity's key value pairs from the map file, retrieved during parsing. ## The func_godot_properties dictionary generated at the end of entity assembly is derived from this. - var properties: Dictionary = {} + var properties: Dictionary[String, Variant] = {} ## The entity's brush data collected during the parsing stage. If the entity's FGD resource cannot be found, ## the presence of a single brush determines this entity to be a Solid Entity. var brushes: Array[BrushData] = [] @@ -154,6 +154,12 @@ class EntityData extends RefCounted: return (definition and definition is FuncGodotFGDSolidClass and definition.build_visuals) + + func is_gi_enabled() -> bool: + return (definition + and definition is FuncGodotFGDSolidClass + and definition.global_illumination_mode + ) ## Checks the entity's FGD resource definition, returning whether the Solid Class CollisionShapeType is set to Convex. func is_collision_convex() -> bool: @@ -172,12 +178,12 @@ class EntityData extends RefCounted: ## Determines if the entity's mesh should be processed for normal smoothing. ## The smoothing property can be retrieved from [member FuncGodotMapSettings.entity_smoothing_property]. func is_smooth_shaded(smoothing_property: String = "_phong") -> bool: - return properties.get(smoothing_property, "0").to_int() + return properties.get(smoothing_property, 0) ## Retrieves the entity's smoothing angle to determine if the face should be smoothed. ## The smoothing angle property can be retrieved from [member FuncGodotMapSettings.entity_smoothing_angle_property]. func get_smoothing_angle(smoothing_angle_property: String = "_phong_angle") -> float: - return properties.get(smoothing_angle_property, "89.0").to_float() + return properties.get(smoothing_angle_property, 89.0) class VertexGroupData: ## Faces this vertex appears in. diff --git a/addons/func_godot/src/core/entity_assembler.gd b/addons/func_godot/src/core/entity_assembler.gd index a1b7eebe..ad1e7cce 100644 --- a/addons/func_godot/src/core/entity_assembler.gd +++ b/addons/func_godot/src/core/entity_assembler.gd @@ -51,14 +51,14 @@ func generate_solid_entity_node(node: Node, node_name: String, data: _EntityData node = ClassDB.instantiate(definition.node_class) else: var script: Script = get_script_by_class_name(definition.node_class) - if script is GDScript: - node = (script as GDScript).new() + if script is Script: + node = script.new() else: node = Node3D.new() node.name = node_name node_name = node_name.trim_suffix(definition.classname).trim_suffix("_") - var properties: Dictionary = data.properties + var properties: Dictionary[String, Variant] = data.properties # Mesh Instance generation if data.mesh: @@ -95,9 +95,17 @@ func generate_solid_entity_node(node: Node, node_name: String, data: _EntityData node.add_child(occluder_instance) data.occluder_instance = occluder_instance + # NOTE: Currently occuring in EntityAssembler until the appropriate method in GeometryGenerator is resolved + # For now, smooth entire mesh, then unwrap for lightmap if needed if not (build_flags & FuncGodotMap.BuildFlags.DISABLE_SMOOTHING) and data.is_smooth_shaded(map_settings.entity_smoothing_property): mesh_instance.mesh = FuncGodotUtil.smooth_mesh_by_angle(data.mesh, data.get_smoothing_angle(map_settings.entity_smoothing_angle_property)) + if data.is_gi_enabled() and (build_flags & FuncGodotMap.BuildFlags.UNWRAP_UV2): + mesh_instance.mesh.lightmap_unwrap( + Transform3D.IDENTITY, + map_settings.uv_unwrap_texel_size * map_settings.scale_factor + ) + # Collision generation if data.shapes.size() and node is CollisionObject3D: node.collision_layer = definition.collision_layer @@ -131,7 +139,9 @@ func generate_solid_entity_node(node: Node, node_name: String, data: _EntityData if "position" in node: if node.position is Vector3: - node.position = FuncGodotUtil.id_to_opengl(data.origin) * map_settings.scale_factor + node.position = FuncGodotUtil.id_to_opengl(data.origin) + elif node.position is Vector2: + node.position = Vector2(data.origin.z, -data.origin.y) * map_settings.inverse_scale_factor if not data.mesh_metadata.is_empty(): node.set_meta("func_godot_mesh_data", data.mesh_metadata) @@ -152,9 +162,9 @@ func generate_point_entity_node(node: Node, node_name: String, properties: Dicti node = ClassDB.instantiate(definition.node_class) else: var script: Script = get_script_by_class_name(definition.node_class) - if script is GDScript: - node = (script as GDScript).new() - else: + if script is Script: + node = script.new() + if not node: node = Node3D.new() node.name = node_name @@ -164,22 +174,28 @@ func generate_point_entity_node(node: Node, node_name: String, properties: Dicti if "angles" in properties or "mangle" in properties: var key := "angles" if "angles" in properties else "mangle" var angles_raw = properties[key] - if not angles_raw is Vector3: + if angles_raw is String: angles_raw = angles_raw.split_floats(' ') - if angles_raw.size() > 2: + if angles_raw.size() < 3: + push_error("Invalid vector format for \"" + key + "\" in entity \"" + classname + "\"") + angles_raw = null + if angles_raw: angles = Vector3(-angles_raw[0], angles_raw[1], -angles_raw[2]) if key == "mangle": if definition.classname.begins_with("light"): angles = Vector3(angles_raw[1], angles_raw[0], -angles_raw[2]) elif definition.classname == "info_intermission": angles = Vector3(angles_raw[0], angles_raw[1], -angles_raw[2]) - else: - push_error("Invalid vector format for \"" + key + "\" in entity \"" + classname + "\"") elif "angle" in properties: var angle = properties["angle"] if not angle is float: angle = float(angle) - angles.y += angle + if is_equal_approx(angle, -1): + angles.x = 90 + elif is_equal_approx(angle, -2): + angles.x = -90 + else: + angles.y += angle angles.y += 180 node.rotation_degrees = angles @@ -203,11 +219,18 @@ func generate_point_entity_node(node: Node, node_name: String, properties: Dicti if "origin" in properties: var origin_vec: Vector3 = Vector3.ZERO - var origin_comps: PackedFloat64Array = properties['origin'].split_floats(' ') - if origin_comps.size() > 2: - origin_vec = Vector3(origin_comps[1], origin_comps[2], origin_comps[0]) + var origin_prop = properties['origin'] + if origin_prop is Vector3: + origin_vec = Vector3(origin_prop.y, origin_prop.z, origin_prop.x) + elif origin_prop is String: + var origin_comps: PackedFloat64Array = properties['origin'].split_floats(' ') + if origin_comps.size() > 2: + origin_vec = Vector3(origin_comps[1], origin_comps[2], origin_comps[0]) + else: + push_error("Invalid vector format for \"origin\" in " + node_name) else: push_error("Invalid vector format for \"origin\" in " + node_name) + if "position" in node: if node.position is Vector3: node.position = origin_vec * map_settings.scale_factor @@ -220,127 +243,15 @@ func generate_point_entity_node(node: Node, node_name: String, properties: Dicti ## based upon the [FuncGodotFGDEntity]'s class properties, then attempts to send those properties to a [code]func_godot_properties[/code] [Dictionary] ## and an [code]_func_godot_apply_properties(properties: Dictionary)[/code] method on the node. A deferred call to [code]_func_godot_build_complete()[/code] is also made. func apply_entity_properties(node: Node, data: _EntityData) -> void: - var properties: Dictionary = data.properties + var properties: Dictionary[String, Variant] = data.properties if data.definition: var def := data.definition - for property in properties: - var prop_string = properties[property] - if property in def.class_properties: - var prop_default: Variant = def.class_properties[property] - - match typeof(prop_default): - TYPE_INT: - properties[property] = prop_string.to_int() - TYPE_FLOAT: - properties[property] = prop_string.to_float() - TYPE_BOOL: - properties[property] = bool(prop_string.to_int()) - TYPE_VECTOR3: - var prop_comps: PackedFloat64Array = prop_string.split_floats(" ") - if prop_comps.size() > 2: - properties[property] = Vector3(prop_comps[0], prop_comps[1], prop_comps[2]) - else: - push_error("Invalid Vector3 format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) - properties[property] = prop_default - TYPE_VECTOR3I: - var prop_vec: Vector3i = prop_default - var prop_comps: PackedStringArray = prop_string.split(" ") - if prop_comps.size() > 2: - for i in 3: - prop_vec[i] = prop_comps[i].to_int() - else: - push_error("Invalid Vector3i format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) - properties[property] = prop_vec - TYPE_COLOR: - var prop_color: Color = prop_default - var prop_comps: PackedStringArray = prop_string.split(" ") - if prop_comps.size() > 2: - prop_color.r8 = prop_comps[0].to_int() - prop_color.g8 = prop_comps[1].to_int() - prop_color.b8 = prop_comps[2].to_int() - prop_color.a = 1.0 - else: - push_error("Invalid Color format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) - properties[property] = prop_color - TYPE_DICTIONARY: - var prop_desc = def.class_property_descriptions[property] - if prop_desc is Array and prop_desc.size() > 1 and prop_desc[1] is int: - properties[property] = prop_string.to_int() - TYPE_ARRAY: - properties[property] = prop_string.to_int() - TYPE_VECTOR2: - var prop_comps: PackedFloat64Array = prop_string.split_floats(" ") - if prop_comps.size() > 1: - properties[property] = Vector2(prop_comps[0], prop_comps[1]) - else: - push_error("Invalid Vector2 format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) - properties[property] = prop_default - TYPE_VECTOR2I: - var prop_vec: Vector2i = prop_default - var prop_comps: PackedStringArray = prop_string.split(" ") - if prop_comps.size() > 1: - for i in 2: - prop_vec[i] = prop_comps[i].to_int() - else: - push_error("Invalid Vector2i format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) - properties[property] = prop_vec - TYPE_VECTOR4: - var prop_comps: PackedFloat64Array = prop_string.split_floats(" ") - if prop_comps.size() > 3: - properties[property] = Vector4(prop_comps[0], prop_comps[1], prop_comps[2], prop_comps[3]) - else: - push_error("Invalid Vector4 format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) - properties[property] = prop_default - TYPE_VECTOR4I: - var prop_vec: Vector4i = prop_default - var prop_comps: PackedStringArray = prop_string.split(" ") - if prop_comps.size() > 3: - for i in 4: - prop_vec[i] = prop_comps[i].to_int() - else: - push_error("Invalid Vector4i format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) - properties[property] = prop_vec - TYPE_STRING_NAME: - properties[property] = StringName(prop_string) - TYPE_NODE_PATH: - properties[property] = prop_string - TYPE_OBJECT: - properties[property] = prop_string - - # Assign properties not defined with defaults from the entity definition - for property in def.class_properties: - if not property in properties: - var prop_default: Variant = def.class_properties[property] - # Flags - if prop_default is Array: - var prop_flags_sum := 0 - for prop_flag in prop_default: - if prop_flag is Array and prop_flag.size() > 2: - if prop_flag[2] and prop_flag[1] is int: - prop_flags_sum += prop_flag[1] - properties[property] = prop_flags_sum - # Choices - elif prop_default is Dictionary: - var prop_desc = def.class_property_descriptions.get(property, "") - if prop_desc is Array and prop_desc.size() > 1 and (prop_desc[1] is int or prop_desc[1] is String): - properties[property] = prop_desc[1] - elif prop_default.size(): - properties[property] = prop_default[prop_default.keys().front()] - else: - properties[property] = 0 - # Materials, Shaders, and Sounds - elif prop_default is Resource: - properties[property] = prop_default.resource_path - # Target Destination and Target Source - elif prop_default is NodePath or prop_default is Object or prop_default == null: - properties[property] = "" - # Everything else - else: - properties[property] = prop_default - if def.auto_apply_to_matching_node_properties: for property in properties: + if property == 'scale' and def is FuncGodotFGDPointClass and def.apply_scale_on_map_build: + # scale has already been applied + continue if property in node: if typeof(node.get(property)) == typeof(properties[property]): node.set(property, properties[property]) @@ -361,49 +272,44 @@ func apply_entity_properties(node: Node, data: _EntityData) -> void: func generate_entity_node(entity_data: _EntityData, entity_index: int) -> Node: var node: Node = null var node_name: String = "entity_%s" % entity_index - var properties: Dictionary = entity_data.properties + var properties: Dictionary[String, Variant] = entity_data.properties var entity_def: FuncGodotFGDEntityClass = entity_data.definition if "classname" in entity_data.properties: var classname: String = properties["classname"] node_name += "_" + properties["classname"] - var default_point_def := FuncGodotFGDPointClass.new() - var default_solid_def := FuncGodotFGDSolidClass.new() - default_solid_def.collision_shape_type = FuncGodotFGDSolidClass.CollisionShapeType.NONE - if entity_def: - var name_prop: String - if entity_def.name_property in properties: - name_prop = str(properties[entity_def.name_property]) - elif map_settings.entity_name_property in properties: - name_prop = str(properties[map_settings.entity_name_property]) - if not name_prop.is_empty(): - node_name = "entity_" + name_prop - - if entity_def is FuncGodotFGDSolidClass: - node = generate_solid_entity_node(node, node_name, entity_data, entity_def) - elif entity_def is FuncGodotFGDPointClass: - node = generate_point_entity_node(node, node_name, properties, entity_def) - else: - push_error("Invalid entity definition for \"" + node_name + "\". Entity definition must be Solid Class or Point Class.") - node = generate_point_entity_node(node, node_name, properties, default_point_def) - - if node and entity_def.script_class: + var name_prop: String + if entity_def.name_property in properties: + name_prop = str(properties[entity_def.name_property]) + elif map_settings.entity_name_property in properties: + name_prop = str(properties[map_settings.entity_name_property]) + if not name_prop.is_empty(): + node_name = "entity_" + name_prop + + if entity_def is FuncGodotFGDSolidClass: + node = generate_solid_entity_node(node, node_name, entity_data, entity_def) + elif entity_def is FuncGodotFGDPointClass: + node = generate_point_entity_node(node, node_name, properties, entity_def) + + if node: + if entity_def.script_class: node.set_script(entity_def.script_class) - else: - push_error("No entity definition found for \"" + node_name + "\"") - if entity_data.brushes.size(): - node = generate_solid_entity_node(node, node_name, entity_data, default_solid_def) - else: - node = generate_point_entity_node(node, node_name, properties, default_point_def) + + var node_groups: Array[String] = map_settings.entity_node_groups.duplicate() + node_groups.append_array(entity_def.node_groups) + for node_group in node_groups: + if node_group.is_empty(): + continue + node.add_to_group(node_group, true) return node ## Main entity assembly process called by [FuncGodotMap]. Generates and sorts group nodes in the [SceneTree] first, ## then generates and assembles [Node]s based upon the provided [FuncGodotData.EntityData] and adds them to the [SceneTree]. func build(map_node: FuncGodotMap, entities: Array[_EntityData], groups: Array[_GroupData]) -> void: - var scene_root := map_node.get_tree().edited_scene_root if map_node.get_tree() else map_node + var scene_root := map_node.get_tree().edited_scene_root if map_node.is_inside_tree() else map_node build_flags = map_node.build_flags if map_settings.use_groups_hierarchy: diff --git a/addons/func_godot/src/core/func_godot.gd b/addons/func_godot/src/core/func_godot.gd deleted file mode 100644 index eb3096ac..00000000 --- a/addons/func_godot/src/core/func_godot.gd +++ /dev/null @@ -1,136 +0,0 @@ -class_name FuncGodot extends RefCounted - -var map_data:= FuncGodotMapData.new() -var map_parser:= FuncGodotMapParser.new(map_data) -var geo_generator = preload("res://addons/func_godot/src/core/func_godot_geo_generator.gd").new(map_data) -var map_settings: FuncGodotMapSettings = null: - set(new): - if not new or new == map_settings: return - surface_gatherer.map_settings = new - map_settings = new -var surface_gatherer:= FuncGodotSurfaceGatherer.new(map_data, map_settings) - -func load_map(filename: String, keep_tb_groups: bool) -> void: - map_parser.load_map(filename, keep_tb_groups) - -func get_texture_list() -> PackedStringArray: - var g_textures: PackedStringArray - var tex_count: int = map_data.textures.size() - - g_textures.resize(tex_count) - for i in range(tex_count): - g_textures.set(i, map_data.textures[i].name) - - return g_textures - -func set_entity_definitions(entity_defs: Dictionary) -> void: - for i in range(entity_defs.size()): - var classname: String = entity_defs.keys()[i] - var spawn_type: int = entity_defs.values()[i].get("spawn_type", FuncGodotMapData.FuncGodotEntitySpawnType.ENTITY) - var origin_type: int = entity_defs.values()[i].get("origin_type", FuncGodotMapData.FuncGodotEntityOriginType.BOUNDS_CENTER) - var metadata_inclusion_flags: int = entity_defs.values()[i].get("metadata_inclusion_flags", FuncGodotMapData.FuncGodotEntityMetadataInclusionFlags.NONE) - map_data.set_entity_types_by_classname(classname, spawn_type, origin_type, metadata_inclusion_flags) - -func get_texture_info(texture_name: String) -> FuncGodotMapData.FuncGodotTextureType: - if texture_name == map_settings.origin_texture: - return FuncGodotMapData.FuncGodotTextureType.ORIGIN - return FuncGodotMapData.FuncGodotTextureType.NORMAL - -func generate_geometry(texture_dict: Dictionary) -> void: - var keys: Array = texture_dict.keys() - for key in keys: - var val: Vector2 = texture_dict[key] - map_data.set_texture_info(key, val.x, val.y, get_texture_info(key)) - geo_generator.run() - -func get_entity_dicts() -> Array: - var ent_dicts: Array - for entity in map_data.entities: - var dict: Dictionary - dict["brush_count"] = entity.brushes.size() - - # TODO: This is a horrible remnant of the worldspawn layer system, remove it. - var brush_indices: PackedInt64Array - brush_indices.resize(entity.brushes.size()) - for b in range(entity.brushes.size()): - brush_indices[b] = b - - dict["brush_indices"] = brush_indices - dict["center"] = Vector3(entity.center.y, entity.center.z, entity.center.x) - dict["properties"] = entity.properties - - ent_dicts.append(dict) - - return ent_dicts - -func gather_texture_surfaces(texture_name: String) -> Dictionary: - var sg: FuncGodotSurfaceGatherer = FuncGodotSurfaceGatherer.new(map_data, map_settings) - sg.reset_params() - sg.split_type = FuncGodotSurfaceGatherer.SurfaceSplitType.ENTITY - const MFlags = FuncGodotMapData.FuncGodotEntityMetadataInclusionFlags - sg.metadata_skip_flags = MFlags.TEXTURES | MFlags.COLLISION_SHAPE_TO_FACE_RANGE_MAP - sg.set_texture_filter(texture_name) - sg.set_clip_filter_texture(map_settings.clip_texture) - sg.set_skip_filter_texture(map_settings.skip_texture) - sg.set_origin_filter_texture(map_settings.origin_texture) - sg.run() - return { - surfaces = fetch_surfaces(sg), - metadata = sg.out_metadata, - } - -func gather_entity_convex_collision_surfaces(entity_idx: int) -> void: - surface_gatherer.reset_params() - surface_gatherer.split_type = FuncGodotSurfaceGatherer.SurfaceSplitType.BRUSH - surface_gatherer.entity_filter_idx = entity_idx - surface_gatherer.set_origin_filter_texture(map_settings.origin_texture) - surface_gatherer.run() - -func gather_entity_concave_collision_surfaces(entity_idx: int) -> void: - surface_gatherer.reset_params() - surface_gatherer.split_type = FuncGodotSurfaceGatherer.SurfaceSplitType.NONE - surface_gatherer.entity_filter_idx = entity_idx - const MFlags = FuncGodotMapData.FuncGodotEntityMetadataInclusionFlags - surface_gatherer.metadata_skip_flags |= MFlags.COLLISION_SHAPE_TO_FACE_RANGE_MAP - surface_gatherer.set_skip_filter_texture(map_settings.skip_texture) - surface_gatherer.set_origin_filter_texture(map_settings.origin_texture) - surface_gatherer.run() - -func fetch_surfaces(sg: FuncGodotSurfaceGatherer) -> Array: - var surfs: Array[FuncGodotMapData.FuncGodotFaceGeometry] = sg.out_surfaces - var surf_array: Array - - for surf in surfs: - if surf == null or surf.vertices.size() == 0: - surf_array.append(null) - continue - - var vertices: PackedVector3Array - var normals: PackedVector3Array - var tangents: PackedFloat64Array - var uvs: PackedVector2Array - for v in surf.vertices: - vertices.append(Vector3(v.vertex.y, v.vertex.z, v.vertex.x) * map_settings.scale_factor) - normals.append(Vector3(v.normal.y, v.normal.z, v.normal.x)) - tangents.append(v.tangent.y) - tangents.append(v.tangent.z) - tangents.append(v.tangent.x) - tangents.append(v.tangent.w) - uvs.append(Vector2(v.uv.x, v.uv.y)) - - var indices: PackedInt32Array - if surf.indicies.size() > 0: - indices.append_array(surf.indicies) - - var brush_array: Array - brush_array.resize(Mesh.ARRAY_MAX) - - brush_array[Mesh.ARRAY_VERTEX] = vertices - brush_array[Mesh.ARRAY_NORMAL] = normals - brush_array[Mesh.ARRAY_TANGENT] = tangents - brush_array[Mesh.ARRAY_TEX_UV] = uvs - brush_array[Mesh.ARRAY_INDEX] = indices - - surf_array.append(brush_array) - - return surf_array diff --git a/addons/func_godot/src/core/func_godot.gd.uid b/addons/func_godot/src/core/func_godot.gd.uid deleted file mode 100644 index 5297e84e..00000000 --- a/addons/func_godot/src/core/func_godot.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bvstd30rkrap diff --git a/addons/func_godot/src/core/func_godot_geo_generator.gd b/addons/func_godot/src/core/func_godot_geo_generator.gd deleted file mode 100644 index 7f0704cb..00000000 --- a/addons/func_godot/src/core/func_godot_geo_generator.gd +++ /dev/null @@ -1,381 +0,0 @@ -extends RefCounted - -# Min distance between two verts in a brush before they're merged. Higher values fix angled brushes near extents. -const CMP_EPSILON:= 0.008 - -const UP_VECTOR:= Vector3(0.0, 0.0, 1.0) -const RIGHT_VECTOR:= Vector3(0.0, 1.0, 0.0) -const FORWARD_VECTOR:= Vector3(1.0, 0.0, 0.0) - -var map_data: FuncGodotMapData - -var wind_entity_idx: int = 0 -var wind_brush_idx: int = 0 -var wind_face_idx: int = 0 -var wind_face_center: Vector3 -var wind_face_basis: Vector3 -var wind_face_normal: Vector3 - -func _init(in_map_data: FuncGodotMapData) -> void: - map_data = in_map_data - -func sort_vertices_by_winding(a: FuncGodotMapData.FuncGodotFaceVertex, b: FuncGodotMapData.FuncGodotFaceVertex) -> bool: - var face: FuncGodotMapData.FuncGodotFace = map_data.entities[wind_entity_idx].brushes[wind_brush_idx].faces[wind_face_idx] - var face_geo: FuncGodotMapData.FuncGodotFaceGeometry = map_data.entity_geo[wind_entity_idx].brushes[wind_brush_idx].faces[wind_face_idx] - - var u: Vector3 = wind_face_basis.normalized() - var v: Vector3 = u.cross(wind_face_normal).normalized() - - var loc_a: Vector3 = a.vertex - wind_face_center - var a_pu: float = loc_a.dot(u) - var a_pv: float = loc_a.dot(v) - - var loc_b: Vector3 = b.vertex - wind_face_center - var b_pu: float = loc_b.dot(u) - var b_pv: float = loc_b.dot(v) - - var a_angle: float = atan2(a_pv, a_pu) - var b_angle: float = atan2(b_pv, b_pu) - - return a_angle < b_angle - -# returns null if no intersection, else intersection vertex. -func intersect_face(f0: FuncGodotMapData.FuncGodotFace, f1: FuncGodotMapData.FuncGodotFace, f2: FuncGodotMapData.FuncGodotFace) -> Variant: - var n0:= f0.plane_normal - var n1:= f1.plane_normal - var n2:= f2.plane_normal - var denom: float = n0.cross(n1).dot(n2) - if denom > 0.0: - return (n1.cross(n2) * f0.plane_dist + n2.cross(n0) * f1.plane_dist + n0.cross(n1) * f2.plane_dist) / denom - return null - -func vertex_in_hull(faces: Array[FuncGodotMapData.FuncGodotFace], vertex: Vector3) -> bool: - for face in faces: - var proj: float = face.plane_normal.dot(vertex) - if proj > face.plane_dist and absf(face.plane_dist - proj) > CMP_EPSILON: - return false - return true - -func get_standard_uv(vertex: Vector3, face: FuncGodotMapData.FuncGodotFace, texture_width: int, texture_height: int) -> Vector2: - var uv_out: Vector2 - var du:= absf(face.plane_normal.dot(UP_VECTOR)) - var dr:= absf(face.plane_normal.dot(RIGHT_VECTOR)) - var df:= absf(face.plane_normal.dot(FORWARD_VECTOR)) - - if du >= dr and du >= df: - uv_out = Vector2(vertex.x, -vertex.y) - elif dr >= du and dr >= df: - uv_out = Vector2(vertex.x, -vertex.z) - elif df >= du and df >= dr: - uv_out = Vector2(vertex.y, -vertex.z) - - var angle: float = deg_to_rad(face.uv_extra.rot) - uv_out = Vector2( - uv_out.x * cos(angle) - uv_out.y * sin(angle), - uv_out.x * sin(angle) + uv_out.y * cos(angle)) - - uv_out.x /= texture_width - uv_out.y /= texture_height - - uv_out.x /= face.uv_extra.scale_x - uv_out.y /= face.uv_extra.scale_y - - uv_out.x += face.uv_standard.x / texture_width - uv_out.y += face.uv_standard.y / texture_height - - return uv_out - -func get_valve_uv(vertex: Vector3, face: FuncGodotMapData.FuncGodotFace, texture_width: int, texture_height: int) -> Vector2: - var uv_out: Vector2 - var u_axis:= face.uv_valve.u.axis - var v_axis:= face.uv_valve.v.axis - var u_shift:= face.uv_valve.u.offset - var v_shift:= face.uv_valve.v.offset - - uv_out.x = u_axis.dot(vertex); - uv_out.y = v_axis.dot(vertex); - - uv_out.x /= texture_width; - uv_out.y /= texture_height; - - uv_out.x /= face.uv_extra.scale_x; - uv_out.y /= face.uv_extra.scale_y; - - uv_out.x += u_shift / texture_width; - uv_out.y += v_shift / texture_height; - - return uv_out - -func get_standard_tangent(face: FuncGodotMapData.FuncGodotFace) -> Vector4: - var du:= face.plane_normal.dot(UP_VECTOR) - var dr:= face.plane_normal.dot(RIGHT_VECTOR) - var df:= face.plane_normal.dot(FORWARD_VECTOR) - var dua:= absf(du) - var dra:= absf(dr) - var dfa:= absf(df) - - var u_axis: Vector3 - var v_sign: float = 0.0 - - if dua >= dra and dua >= dfa: - u_axis = FORWARD_VECTOR - v_sign = signf(du) - elif dra >= dua and dra >= dfa: - u_axis = FORWARD_VECTOR - v_sign = -signf(dr) - elif dfa >= dua and dfa >= dra: - u_axis = RIGHT_VECTOR - v_sign = signf(df) - - v_sign *= signf(face.uv_extra.scale_y); - u_axis = u_axis.rotated(face.plane_normal, deg_to_rad(-face.uv_extra.rot) * v_sign) - - return Vector4(u_axis.x, u_axis.y, u_axis.z, v_sign) - -func get_valve_tangent(face: FuncGodotMapData.FuncGodotFace) -> Vector4: - var u_axis:= face.uv_valve.u.axis.normalized() - var v_axis:= face.uv_valve.v.axis.normalized() - var v_sign = -signf(face.plane_normal.cross(u_axis).dot(v_axis)) - return Vector4(u_axis.x, u_axis.y, u_axis.z, v_sign) - -func generate_brush_vertices(entity_idx: int, brush_idx: int) -> void: - var entity: FuncGodotMapData.FuncGodotEntity = map_data.entities[entity_idx] - var brush: FuncGodotMapData.FuncGodotBrush = entity.brushes[brush_idx] - var face_count: int = brush.faces.size() - - var entity_geo: FuncGodotMapData.FuncGodotEntityGeometry = map_data.entity_geo[entity_idx] - var brush_geo: FuncGodotMapData.FuncGodotBrushGeometry = entity_geo.brushes[brush_idx] - - var phong: bool = entity.properties.get("_phong", "0") == "1" - var phong_angle_str: String = entity.properties.get("_phong_angle", "89") - var phong_angle: float = float(phong_angle_str) if phong_angle_str.is_valid_float() else 89.0 - - for f0 in range(face_count): - var face: FuncGodotMapData.FuncGodotFace = brush.faces[f0] - var face_geo: FuncGodotMapData.FuncGodotFaceGeometry = brush_geo.faces[f0] - var texture: FuncGodotMapData.FuncGodotTextureData = map_data.textures[face.texture_idx] - - for f1 in range(face_count): - for f2 in range(face_count): - var vertex = intersect_face(brush.faces[f0], brush.faces[f1], brush.faces[f2]) - if not vertex is Vector3: - continue - if not vertex_in_hull(brush.faces, vertex): - continue - - var merged: bool = false - for f3 in range(f0): - var other_face_geo : FuncGodotMapData.FuncGodotFaceGeometry = brush_geo.faces[f3] - for i in range(len(other_face_geo.vertices)): - if other_face_geo.vertices[i].vertex.distance_to(vertex) < CMP_EPSILON: - vertex = other_face_geo.vertices[i].vertex - merged = true; - break - - if merged: - break - - var normal: Vector3 = face.plane_normal - if phong: - var threshold:= cos((phong_angle + 0.01) * 0.0174533) - if face.plane_normal.dot(brush.faces[f1].plane_normal) > threshold: - normal += brush.faces[f1].plane_normal - if face.plane_normal.dot(brush.faces[f2].plane_normal) > threshold: - normal += brush.faces[f2].plane_normal - normal = normal.normalized() - - var uv: Vector2 - var tangent: Vector4 - if face.is_valve_uv: - uv = get_valve_uv(vertex, face, texture.width, texture.height) - tangent = get_valve_tangent(face) - else: - uv = get_standard_uv(vertex, face, texture.width, texture.height) - tangent = get_standard_tangent(face) - - # Check for a duplicate vertex in the current face. - var duplicate_idx: int = -1 - for i in range(face_geo.vertices.size()): - if face_geo.vertices[i].vertex == vertex: - duplicate_idx = i - break - - if duplicate_idx < 0: - var new_face_vert:= FuncGodotMapData.FuncGodotFaceVertex.new() - new_face_vert.vertex = vertex - new_face_vert.normal = normal - new_face_vert.tangent = tangent - new_face_vert.uv = uv - face_geo.vertices.append(new_face_vert) - elif phong: - face_geo.vertices[duplicate_idx].normal += normal - - # maybe optimisable? - for face_geo in brush_geo.faces: - for i in range(face_geo.vertices.size()): - face_geo.vertices[i].normal = face_geo.vertices[i].normal.normalized() - -func run() -> void: - map_data.entity_geo.resize(map_data.entities.size()) - for i in range(map_data.entity_geo.size()): - map_data.entity_geo[i] = FuncGodotMapData.FuncGodotEntityGeometry.new() - - for e in range(map_data.entities.size()): - var entity: FuncGodotMapData.FuncGodotEntity = map_data.entities[e] - var entity_geo: FuncGodotMapData.FuncGodotEntityGeometry = map_data.entity_geo[e] - entity_geo.brushes.resize(entity.brushes.size()) - for i in range(entity_geo.brushes.size()): - entity_geo.brushes[i] = FuncGodotMapData.FuncGodotBrushGeometry.new() - - for b in range(entity.brushes.size()): - var brush: FuncGodotMapData.FuncGodotBrush = entity.brushes[b] - var brush_geo: FuncGodotMapData.FuncGodotBrushGeometry = entity_geo.brushes[b] - brush_geo.faces.resize(brush.faces.size()) - for i in range(brush_geo.faces.size()): - brush_geo.faces[i] = FuncGodotMapData.FuncGodotFaceGeometry.new() - - var generate_vertices_task = func(e): - var entity: FuncGodotMapData.FuncGodotEntity = map_data.entities[e] - var entity_geo: FuncGodotMapData.FuncGodotEntityGeometry = map_data.entity_geo[e] - var entity_mins: Vector3 = Vector3.INF - var entity_maxs: Vector3 = Vector3.INF - var origin_mins: Vector3 = Vector3.INF - var origin_maxs: Vector3 = -Vector3.INF - - entity.center = Vector3.ZERO - - for b in range(entity.brushes.size()): - var brush: FuncGodotMapData.FuncGodotBrush = entity.brushes[b] - brush.center = Vector3.ZERO - var vert_count: int = 0 - - # Check if this is a special brush (eg: origin) - var brush_texture_type: FuncGodotMapData.FuncGodotTextureType = FuncGodotMapData.FuncGodotTextureType.NORMAL - if brush.faces.size() > 0: - brush_texture_type = map_data.textures[brush.faces[0].texture_idx].type - - # Check that all the faces match the same type - for face_idx in range(1,brush.faces.size()): - if map_data.textures[brush.faces[face_idx].texture_idx].type != brush_texture_type: - brush_texture_type = FuncGodotMapData.FuncGodotTextureType.NORMAL # Reset face type if it doesn't match - break - - generate_brush_vertices(e, b) - - var brush_geo: FuncGodotMapData.FuncGodotBrushGeometry = map_data.entity_geo[e].brushes[b] - for face in brush_geo.faces: - for vert in face.vertices: - if entity_mins != Vector3.INF: - entity_mins = entity_mins.min(vert.vertex) - else: - entity_mins = vert.vertex - if entity_maxs != Vector3.INF: - entity_maxs = entity_maxs.max(vert.vertex) - else: - entity_maxs = vert.vertex - - if brush_texture_type == FuncGodotMapData.FuncGodotTextureType.ORIGIN: - if origin_mins != Vector3.INF: - origin_mins = origin_mins.min(vert.vertex) - else: - origin_mins = vert.vertex - if origin_maxs != Vector3.INF: - origin_maxs = origin_maxs.max(vert.vertex) - else: - origin_maxs = vert.vertex - - brush.center += vert.vertex - vert_count += 1 - - if vert_count > 0: - brush.center /= float(vert_count) - - # Default origin type is BOUNDS_CENTER - if entity_maxs != Vector3.INF and entity_mins != Vector3.INF: - entity.center = entity_maxs - ((entity_maxs - entity_mins) * 0.5) - - if entity.origin_type != FuncGodotMapData.FuncGodotEntityOriginType.BOUNDS_CENTER and entity.brushes.size() > 0: - match entity.origin_type: - FuncGodotMapData.FuncGodotEntityOriginType.ABSOLUTE, FuncGodotMapData.FuncGodotEntityOriginType.RELATIVE: - if 'origin' in entity.properties: - var origin_comps: PackedFloat64Array = entity.properties['origin'].split_floats(' ') - if origin_comps.size() > 2: - if entity.origin_type == FuncGodotMapData.FuncGodotEntityOriginType.ABSOLUTE: - entity.center = Vector3(origin_comps[0], origin_comps[1], origin_comps[2]) - else: # OriginType.RELATIVE - entity.center += Vector3(origin_comps[0], origin_comps[1], origin_comps[2]) - - FuncGodotMapData.FuncGodotEntityOriginType.BRUSH: - if origin_mins != Vector3.INF: - entity.center = origin_maxs - ((origin_maxs - origin_mins) * 0.5) - - FuncGodotMapData.FuncGodotEntityOriginType.BOUNDS_MINS: - entity.center = entity_mins - - FuncGodotMapData.FuncGodotEntityOriginType.BOUNDS_MAXS: - entity.center = entity_maxs - - FuncGodotMapData.FuncGodotEntityOriginType.AVERAGED: - entity.center = Vector3.ZERO - for b in range(entity.brushes.size()): - entity.center += entity.brushes[b].center - entity.center /= float(entity.brushes.size()) - - var generate_vertices_task_id:= WorkerThreadPool.add_group_task(generate_vertices_task, map_data.entities.size(), 4, true) - WorkerThreadPool.wait_for_group_task_completion(generate_vertices_task_id) - - # wind face vertices - for e in range(map_data.entities.size()): - var entity: FuncGodotMapData.FuncGodotEntity = map_data.entities[e] - var entity_geo: FuncGodotMapData.FuncGodotEntityGeometry = map_data.entity_geo[e] - - for b in range(entity.brushes.size()): - var brush: FuncGodotMapData.FuncGodotBrush = entity.brushes[b] - var brush_geo: FuncGodotMapData.FuncGodotBrushGeometry = entity_geo.brushes[b] - - for f in range(brush.faces.size()): - var face: FuncGodotMapData.FuncGodotFace = brush.faces[f] - var face_geo: FuncGodotMapData.FuncGodotFaceGeometry = brush_geo.faces[f] - - if face_geo.vertices.size() < 3: - continue - - wind_entity_idx = e - wind_brush_idx = b - wind_face_idx = f - - wind_face_basis = face_geo.vertices[1].vertex - face_geo.vertices[0].vertex - wind_face_center = Vector3.ZERO - wind_face_normal = face.plane_normal - - for v in face_geo.vertices: - wind_face_center += v.vertex - - wind_face_center /= face_geo.vertices.size() - - face_geo.vertices.sort_custom(sort_vertices_by_winding) - wind_entity_idx = 0 - - # index face vertices - var index_faces_task:= func(e): - var entity_geo: FuncGodotMapData.FuncGodotEntityGeometry = map_data.entity_geo[e] - - for b in range(entity_geo.brushes.size()): - var brush_geo: FuncGodotMapData.FuncGodotBrushGeometry = entity_geo.brushes[b] - - for f in range(brush_geo.faces.size()): - var face_geo: FuncGodotMapData.FuncGodotFaceGeometry = brush_geo.faces[f] - - if face_geo.vertices.size() < 3: - continue - - var i_count: int = 0 - face_geo.indicies.resize((face_geo.vertices.size() - 2) * 3) - for i in range(face_geo.vertices.size() - 2): - face_geo.indicies[i_count] = 0 - face_geo.indicies[i_count + 1] = i + 1 - face_geo.indicies[i_count + 2] = i + 2 - i_count += 3 - - var index_faces_task_id:= WorkerThreadPool.add_group_task(index_faces_task, map_data.entities.size(), 4, true) - WorkerThreadPool.wait_for_group_task_completion(index_faces_task_id) diff --git a/addons/func_godot/src/core/func_godot_geo_generator.gd.uid b/addons/func_godot/src/core/func_godot_geo_generator.gd.uid deleted file mode 100644 index f9f290ec..00000000 --- a/addons/func_godot/src/core/func_godot_geo_generator.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cb0c2fn35hqov diff --git a/addons/func_godot/src/core/func_godot_map_data.gd b/addons/func_godot/src/core/func_godot_map_data.gd deleted file mode 100644 index 1b6137f1..00000000 --- a/addons/func_godot/src/core/func_godot_map_data.gd +++ /dev/null @@ -1,158 +0,0 @@ -class_name FuncGodotMapData extends RefCounted - -var entities: Array[FuncGodotMapData.FuncGodotEntity] -var entity_geo: Array[FuncGodotMapData.FuncGodotEntityGeometry] -var textures: Array[FuncGodotMapData.FuncGodotTextureData] - -func register_texture(name: String) -> int: - for i in range(textures.size()): - if textures[i].name == name: - return i - - textures.append(FuncGodotTextureData.new(name)) - return textures.size() - 1 - -func set_texture_info(name: String, width: int, height: int, type: FuncGodotTextureType) -> void: - for i in range(textures.size()): - if textures[i].name == name: - textures[i].width = width - textures[i].height = height - textures[i].type = type - return - -func find_texture(texture_name: String) -> int: - for i in range(textures.size()): - if textures[i].name == texture_name: - return i - return -1 - -func set_entity_types_by_classname(classname: String, spawn_type: int, origin_type: int, meta_flags: int) -> void: - for entity in entities: - if entity.properties.has("classname") and entity.properties["classname"] == classname: - entity.metadata_inclusion_flags = meta_flags as FuncGodotMapData.FuncGodotEntityMetadataInclusionFlags - entity.spawn_type = spawn_type as FuncGodotMapData.FuncGodotEntitySpawnType - if entity.spawn_type == FuncGodotMapData.FuncGodotEntitySpawnType.ENTITY: - entity.origin_type = origin_type as FuncGodotMapData.FuncGodotEntityOriginType - else: - entity.origin_type = FuncGodotMapData.FuncGodotEntityOriginType.AVERAGED - -func clear() -> void: - entities.clear() - entity_geo.clear() - textures.clear() - -# -------------------------------------------------------------------------------------------------- -# Nested Types -# -------------------------------------------------------------------------------------------------- -enum FuncGodotEntitySpawnType { - WORLDSPAWN = 0, - MERGE_WORLDSPAWN = 1, - ENTITY = 2 -} - -enum FuncGodotEntityOriginType { - AVERAGED = 0, - ABSOLUTE = 1, - RELATIVE = 2, - BRUSH = 3, - BOUNDS_CENTER = 4, - BOUNDS_MINS = 5, - BOUNDS_MAXS = 6, -} - -enum FuncGodotEntityMetadataInclusionFlags { - NONE = 0, - ENTITY_INDEX_RANGES = 1, - TEXTURES = 2, - VERTEX = 4, - FACE_POSITION = 8, - FACE_NORMAL = 16, - COLLISION_SHAPE_TO_FACE_RANGE_MAP = 32, -} - -enum FuncGodotTextureType { - NORMAL = 0, - ORIGIN = 1 -} - -class FuncGodotFacePoints: - var v0: Vector3 - var v1: Vector3 - var v2: Vector3 - -class FuncGodotValveTextureAxis: - var axis: Vector3 - var offset: float - -class FuncGodotValveUV: - var u: FuncGodotValveTextureAxis - var v: FuncGodotValveTextureAxis - - func _init() -> void: - u = FuncGodotValveTextureAxis.new() - v = FuncGodotValveTextureAxis.new() - -class FuncGodotFaceUVExtra: - var rot: float - var scale_x: float - var scale_y: float - -class FuncGodotFace: - var plane_points: FuncGodotFacePoints - var plane_normal: Vector3 - var plane_dist: float - var texture_idx: int - var is_valve_uv: bool - var uv_standard: Vector2 - var uv_valve: FuncGodotValveUV - var uv_extra: FuncGodotFaceUVExtra - - func _init() -> void: - plane_points = FuncGodotFacePoints.new() - uv_valve = FuncGodotValveUV.new() - uv_extra = FuncGodotFaceUVExtra.new() - -class FuncGodotBrush: - var faces: Array[FuncGodotFace] - var center: Vector3 - -class FuncGodotEntity: - var properties: Dictionary - var brushes: Array[FuncGodotBrush] - var center: Vector3 - var spawn_type: FuncGodotEntitySpawnType - var origin_type: FuncGodotEntityOriginType - var metadata_inclusion_flags: FuncGodotEntityMetadataInclusionFlags - -class FuncGodotFaceVertex: - var vertex: Vector3 - var normal: Vector3 - var uv: Vector2 - var tangent: Vector4 - - func duplicate() -> FuncGodotFaceVertex: - var new_vert := FuncGodotFaceVertex.new() - new_vert.vertex = vertex - new_vert.normal = normal - new_vert.uv = uv - new_vert.tangent = tangent - return new_vert - -class FuncGodotFaceGeometry: - var vertices: Array[FuncGodotFaceVertex] - var indicies: Array[int] - -class FuncGodotBrushGeometry: - var faces: Array[FuncGodotFaceGeometry] - -class FuncGodotEntityGeometry: - var brushes: Array[FuncGodotBrushGeometry] - -class FuncGodotTextureData: - var name: String - var width: int - var height: int - var type: FuncGodotTextureType - - func _init(in_name: String): - name = in_name diff --git a/addons/func_godot/src/core/func_godot_map_data.gd.uid b/addons/func_godot/src/core/func_godot_map_data.gd.uid deleted file mode 100644 index 3027e55e..00000000 --- a/addons/func_godot/src/core/func_godot_map_data.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://ct3rx5npjd00s diff --git a/addons/func_godot/src/core/func_godot_map_parser.gd b/addons/func_godot/src/core/func_godot_map_parser.gd deleted file mode 100644 index ed6cc037..00000000 --- a/addons/func_godot/src/core/func_godot_map_parser.gd +++ /dev/null @@ -1,326 +0,0 @@ -class_name FuncGodotMapParser extends RefCounted - -var scope:= FuncGodotMapParser.ParseScope.FILE -var comment: bool = false -var entity_idx: int = -1 -var brush_idx: int = -1 -var face_idx: int = -1 -var component_idx: int = 0 -var prop_key: String = "" -var current_property: String = "" -var valve_uvs: bool = false - -var current_face: FuncGodotMapData.FuncGodotFace -var current_brush: FuncGodotMapData.FuncGodotBrush -var current_entity: FuncGodotMapData.FuncGodotEntity - -var map_data: FuncGodotMapData -var _keep_tb_groups: bool = false - -func _init(in_map_data: FuncGodotMapData) -> void: - map_data = in_map_data - -func load_map(map_file: String, keep_tb_groups: bool) -> bool: - current_face = FuncGodotMapData.FuncGodotFace.new() - current_brush = FuncGodotMapData.FuncGodotBrush.new() - current_entity = FuncGodotMapData.FuncGodotEntity.new() - - scope = FuncGodotMapParser.ParseScope.FILE - comment = false - entity_idx = -1 - brush_idx = -1 - face_idx = -1 - component_idx = 0 - valve_uvs = false - _keep_tb_groups = keep_tb_groups - - var lines: PackedStringArray = [] - - var map: FileAccess = FileAccess.open(map_file, FileAccess.READ) - - if map == null: - printerr("Error: Failed to open map file (" + map_file + ")") - return false - - if map_file.ends_with(".import"): - while not map.eof_reached(): - var line: String = map.get_line() - if line.begins_with("path"): - map.close() - line = line.replace("path=", ""); - line = line.replace('"', '') - var map_data: String = (load(line) as QuakeMapFile).map_data - if map_data.is_empty(): - printerr("Error: Failed to open map file (" + line + ")") - return false - lines = map_data.split("\n") - break - else: - while not map.eof_reached(): - var line: String = map.get_line() - lines.append(line) - - for line in lines: - if comment: - comment = false - var tokens := split_string(line, [" ", "\t"], true) - for s in tokens: - token(s) - - return true - -func split_string(s: String, delimeters: Array[String], allow_empty: bool = true) -> Array[String]: - var parts: Array[String] = [] - - var start := 0 - var i := 0 - - while i < s.length(): - if s[i] in delimeters: - if allow_empty or start < i: - parts.push_back(s.substr(start, i - start)) - start = i + 1 - i += 1 - - if allow_empty or start < i: - parts.push_back(s.substr(start, i - start)) - - return parts - -func set_scope(new_scope: FuncGodotMapParser.ParseScope) -> void: - """ - match new_scope: - ParseScope.FILE: - print("Switching to file scope.") - ParseScope.ENTITY: - print("Switching to entity " + str(entity_idx) + "scope") - ParseScope.PROPERTY_VALUE: - print("Switching to property value scope") - ParseScope.BRUSH: - print("Switching to brush " + str(brush_idx) + " scope") - ParseScope.PLANE_0: - print("Switching to face " + str(face_idx) + " plane 0 scope") - ParseScope.PLANE_1: - print("Switching to face " + str(face_idx) + " plane 1 scope") - ParseScope.PLANE_2: - print("Switching to face " + str(face_idx) + " plane 2 scope") - ParseScope.TEXTURE: - print("Switching to texture scope") - ParseScope.U: - print("Switching to U scope") - ParseScope.V: - print("Switching to V scope") - ParseScope.VALVE_U: - print("Switching to Valve U scope") - ParseScope.VALVE_V: - print("Switching to Valve V scope") - ParseScope.ROT: - print("Switching to rotation scope") - ParseScope.U_SCALE: - print("Switching to U scale scope") - ParseScope.V_SCALE: - print("Switching to V scale scope") - """ - scope = new_scope - -func token(buf_str: String) -> void: - if comment: - return - elif buf_str == "//": - comment = true - return - - match scope: - FuncGodotMapParser.ParseScope.FILE: - if buf_str == "{": - entity_idx += 1 - brush_idx = -1 - set_scope(FuncGodotMapParser.ParseScope.ENTITY) - FuncGodotMapParser.ParseScope.ENTITY: - if buf_str.begins_with('"'): - prop_key = buf_str.substr(1) - if prop_key.ends_with('"'): - prop_key = prop_key.left(-1) - set_scope(FuncGodotMapParser.ParseScope.PROPERTY_VALUE) - elif buf_str == "{": - brush_idx += 1 - face_idx = -1 - set_scope(FuncGodotMapParser.ParseScope.BRUSH) - elif buf_str == "}": - commit_entity() - set_scope(FuncGodotMapParser.ParseScope.FILE) - FuncGodotMapParser.ParseScope.PROPERTY_VALUE: - var is_first = buf_str[0] == '"' - var is_last = buf_str.right(1) == '"' - - if is_first: - if current_property != "": - current_property = "" - - if not is_last: - current_property += buf_str + " " - else: - current_property += buf_str - - if is_last: - current_entity.properties[prop_key] = current_property.substr(1, len(current_property) - 2) - set_scope(FuncGodotMapParser.ParseScope.ENTITY) - FuncGodotMapParser.ParseScope.BRUSH: - if buf_str == "(": - face_idx += 1 - component_idx = 0 - set_scope(FuncGodotMapParser.ParseScope.PLANE_0) - elif buf_str == "}": - commit_brush() - set_scope(FuncGodotMapParser.ParseScope.ENTITY) - FuncGodotMapParser.ParseScope.PLANE_0: - if buf_str == ")": - component_idx = 0 - set_scope(FuncGodotMapParser.ParseScope.PLANE_1) - else: - match component_idx: - 0: - current_face.plane_points.v0.x = float(buf_str) - 1: - current_face.plane_points.v0.y = float(buf_str) - 2: - current_face.plane_points.v0.z = float(buf_str) - - component_idx += 1 - FuncGodotMapParser.ParseScope.PLANE_1: - if buf_str != "(": - if buf_str == ")": - component_idx = 0 - set_scope(FuncGodotMapParser.ParseScope.PLANE_2) - else: - match component_idx: - 0: - current_face.plane_points.v1.x = float(buf_str) - 1: - current_face.plane_points.v1.y = float(buf_str) - 2: - current_face.plane_points.v1.z = float(buf_str) - - component_idx += 1 - FuncGodotMapParser.ParseScope.PLANE_2: - if buf_str != "(": - if buf_str == ")": - component_idx = 0 - set_scope(FuncGodotMapParser.ParseScope.TEXTURE) - else: - match component_idx: - 0: - current_face.plane_points.v2.x = float(buf_str) - 1: - current_face.plane_points.v2.y = float(buf_str) - 2: - current_face.plane_points.v2.z = float(buf_str) - - component_idx += 1 - FuncGodotMapParser.ParseScope.TEXTURE: - current_face.texture_idx = map_data.register_texture(buf_str) - set_scope(FuncGodotMapParser.ParseScope.U) - FuncGodotMapParser.ParseScope.U: - if buf_str == "[": - valve_uvs = true - component_idx = 0 - set_scope(FuncGodotMapParser.ParseScope.VALVE_U) - else: - valve_uvs = false - current_face.uv_standard.x = float(buf_str) - set_scope(FuncGodotMapParser.ParseScope.V) - FuncGodotMapParser.ParseScope.V: - current_face.uv_standard.y = float(buf_str) - set_scope(FuncGodotMapParser.ParseScope.ROT) - FuncGodotMapParser.ParseScope.VALVE_U: - if buf_str == "]": - component_idx = 0 - set_scope(FuncGodotMapParser.ParseScope.VALVE_V) - else: - match component_idx: - 0: - current_face.uv_valve.u.axis.x = float(buf_str) - 1: - current_face.uv_valve.u.axis.y = float(buf_str) - 2: - current_face.uv_valve.u.axis.z = float(buf_str) - 3: - current_face.uv_valve.u.offset = float(buf_str) - - component_idx += 1 - FuncGodotMapParser.ParseScope.VALVE_V: - if buf_str != "[": - if buf_str == "]": - set_scope(FuncGodotMapParser.ParseScope.ROT) - else: - match component_idx: - 0: - current_face.uv_valve.v.axis.x = float(buf_str) - 1: - current_face.uv_valve.v.axis.y = float(buf_str) - 2: - current_face.uv_valve.v.axis.z = float(buf_str) - 3: - current_face.uv_valve.v.offset = float(buf_str) - - component_idx += 1 - FuncGodotMapParser.ParseScope.ROT: - current_face.uv_extra.rot = float(buf_str) - set_scope(FuncGodotMapParser.ParseScope.U_SCALE) - FuncGodotMapParser.ParseScope.U_SCALE: - current_face.uv_extra.scale_x = float(buf_str) - set_scope(FuncGodotMapParser.ParseScope.V_SCALE) - FuncGodotMapParser.ParseScope.V_SCALE: - current_face.uv_extra.scale_y = float(buf_str) - commit_face() - set_scope(FuncGodotMapParser.ParseScope.BRUSH) - -func commit_entity() -> void: - if current_entity.properties.has('_tb_type') and map_data.entities.size() > 0: - map_data.entities[0].brushes.append_array(current_entity.brushes) - current_entity.brushes.clear() - if !_keep_tb_groups: - current_entity = FuncGodotMapData.FuncGodotEntity.new() - return - - var new_entity:= FuncGodotMapData.FuncGodotEntity.new() - new_entity.spawn_type = FuncGodotMapData.FuncGodotEntitySpawnType.ENTITY - new_entity.properties = current_entity.properties - new_entity.brushes = current_entity.brushes - map_data.entities.append(new_entity) - - current_entity = FuncGodotMapData.FuncGodotEntity.new() - -func commit_brush() -> void: - current_entity.brushes.append(current_brush) - current_brush = FuncGodotMapData.FuncGodotBrush.new() - -func commit_face() -> void: - var v0v1: Vector3 = current_face.plane_points.v1 - current_face.plane_points.v0 - var v1v2: Vector3 = current_face.plane_points.v2 - current_face.plane_points.v1 - current_face.plane_normal = v1v2.cross(v0v1).normalized() - current_face.plane_dist = current_face.plane_normal.dot(current_face.plane_points.v0) - current_face.is_valve_uv = valve_uvs - - current_brush.faces.append(current_face) - current_face = FuncGodotMapData.FuncGodotFace.new() - -# Nested -enum ParseScope{ - FILE, - COMMENT, - ENTITY, - PROPERTY_VALUE, - BRUSH, - PLANE_0, - PLANE_1, - PLANE_2, - TEXTURE, - U, - V, - VALVE_U, - VALVE_V, - ROT, - U_SCALE, - V_SCALE -} diff --git a/addons/func_godot/src/core/func_godot_map_parser.gd.uid b/addons/func_godot/src/core/func_godot_map_parser.gd.uid deleted file mode 100644 index 658b3505..00000000 --- a/addons/func_godot/src/core/func_godot_map_parser.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cg2iiom3svtw0 diff --git a/addons/func_godot/src/core/func_godot_surface_gatherer.gd b/addons/func_godot/src/core/func_godot_surface_gatherer.gd deleted file mode 100644 index f0724340..00000000 --- a/addons/func_godot/src/core/func_godot_surface_gatherer.gd +++ /dev/null @@ -1,217 +0,0 @@ -class_name FuncGodotSurfaceGatherer extends RefCounted - -var map_data: FuncGodotMapData -var map_settings: FuncGodotMapSettings -var split_type: SurfaceSplitType = SurfaceSplitType.NONE -var entity_filter_idx: int = -1 -var texture_filter_idx: int = -1 -var clip_filter_texture_idx: int -var skip_filter_texture_idx: int -var origin_filter_texture_idx: int -var metadata_skip_flags: int - -var out_surfaces: Array[FuncGodotMapData.FuncGodotFaceGeometry] -var out_metadata: Dictionary - -func _init(in_map_data: FuncGodotMapData, in_map_settings: FuncGodotMapSettings) -> void: - map_data = in_map_data - map_settings = in_map_settings - -func set_texture_filter(texture_name: String) -> void: - texture_filter_idx = map_data.find_texture(texture_name) - -func set_clip_filter_texture(texture_name: String) -> void: - clip_filter_texture_idx = map_data.find_texture(texture_name) - -func set_skip_filter_texture(texture_name: String) -> void: - skip_filter_texture_idx = map_data.find_texture(texture_name) - -func set_origin_filter_texture(texture_name: String) -> void: - origin_filter_texture_idx = map_data.find_texture(texture_name) - -func filter_entity(entity_idx: int) -> bool: - if entity_filter_idx != -1 and entity_idx != entity_filter_idx: - return true - return false - -func filter_face(entity_idx: int, brush_idx: int, face_idx: int) -> bool: - var face: FuncGodotMapData.FuncGodotFace = map_data.entities[entity_idx].brushes[brush_idx].faces[face_idx] - var face_geo: FuncGodotMapData.FuncGodotFaceGeometry = map_data.entity_geo[entity_idx].brushes[brush_idx].faces[face_idx] - - if face_geo.vertices.size() < 3: - return true - - # Omit faces textured with Clip - if clip_filter_texture_idx != -1 and face.texture_idx == clip_filter_texture_idx: - return true - - # Omit faces textured with Skip - if skip_filter_texture_idx != -1 and face.texture_idx == skip_filter_texture_idx: - return true - - # Omit faces textured with Origin - if origin_filter_texture_idx != -1 and face.texture_idx == origin_filter_texture_idx: - return true - - # Omit filtered texture indices - if texture_filter_idx != -1 and face.texture_idx != texture_filter_idx: - return true - - return false - -func run() -> void: - out_surfaces.clear() - var texture_names: Array[StringName] = [] - var textures: PackedInt32Array = [] - var vertices: PackedVector3Array = [] - var positions: PackedVector3Array = [] - var normals: PackedVector3Array = [] - var shape_index_ranges: Array[Vector2i] = [] - var entity_index_ranges: Array[Vector2i] = [] - - var index_offset: int = 0 - var entity_face_range: Vector2i = Vector2i.ZERO - const MFlags = FuncGodotMapData.FuncGodotEntityMetadataInclusionFlags - var build_entity_index_ranges: bool = not metadata_skip_flags & MFlags.ENTITY_INDEX_RANGES - var surf: FuncGodotMapData.FuncGodotFaceGeometry - - if split_type == SurfaceSplitType.NONE: - surf = add_surface() - index_offset = len(out_surfaces) - 1 - - for e in range(map_data.entities.size()): - var entity:= map_data.entities[e] - var entity_geo:= map_data.entity_geo[e] - var shape_face_range := Vector2i.ZERO - var total_entity_tris := 0 - var include_normals_metadata: bool = not metadata_skip_flags & MFlags.FACE_NORMAL and entity.metadata_inclusion_flags & MFlags.FACE_NORMAL - var include_vertices_metadata: bool = not metadata_skip_flags & MFlags.VERTEX and entity.metadata_inclusion_flags & MFlags.VERTEX - var include_textures_metadata: bool = not metadata_skip_flags & MFlags.TEXTURES and entity.metadata_inclusion_flags & MFlags.TEXTURES - var include_positions_metadata: bool = not metadata_skip_flags & MFlags.FACE_POSITION and entity.metadata_inclusion_flags & MFlags.FACE_POSITION - var include_shape_range_metadata: bool = not metadata_skip_flags & MFlags.COLLISION_SHAPE_TO_FACE_RANGE_MAP and entity.metadata_inclusion_flags & MFlags.COLLISION_SHAPE_TO_FACE_RANGE_MAP - - if filter_entity(e): - continue - - if split_type == SurfaceSplitType.ENTITY: - if entity.spawn_type == FuncGodotMapData.FuncGodotEntitySpawnType.MERGE_WORLDSPAWN: - add_surface() - surf = out_surfaces[0] - index_offset = surf.vertices.size() - else: - surf = add_surface() - index_offset = surf.vertices.size() - - for b in range(entity.brushes.size()): - var brush:= entity.brushes[b] - var brush_geo:= entity_geo.brushes[b] - var total_brush_tris:= 0 - - if split_type == SurfaceSplitType.BRUSH: - index_offset = 0 - surf = add_surface() - - for f in range(brush.faces.size()): - var face_geo: FuncGodotMapData.FuncGodotFaceGeometry = brush_geo.faces[f] - var face: FuncGodotMapData.FuncGodotFace = brush.faces[f] - var num_tris = face_geo.vertices.size() - 2 - - if filter_face(e, b, f): - continue - - for v in range(face_geo.vertices.size()): - var vert: FuncGodotMapData.FuncGodotFaceVertex = face_geo.vertices[v].duplicate() - - if entity.spawn_type == FuncGodotMapData.FuncGodotEntitySpawnType.ENTITY: - vert.vertex -= entity.center - - surf.vertices.append(vert) - - if include_normals_metadata: - var normal := Vector3(face.plane_normal.y, face.plane_normal.z, face.plane_normal.x) - for i in num_tris: - normals.append(normal) - if include_shape_range_metadata or build_entity_index_ranges: - total_brush_tris += num_tris - if include_textures_metadata: - var texname := StringName(map_data.textures[face.texture_idx].name) - var index: int - if texture_names.is_empty(): - texture_names.append(texname) - index = 0 - elif texture_names.back() == texname: - # Common case, faces with textures are next to each other - index = texture_names.size() - 1 - else: - var texture_name_index: int = texture_names.find(texname) - if texture_name_index == -1: - index = texture_names.size() - texture_names.append(texname) - else: - index = texture_name_index - # Metadata addresses triangles, so we have to duplicate the info for each tri - for i in num_tris: - textures.append(index) - - var avg_vertex_pos := Vector3.ZERO - var avg_vertex_pos_ct: int = 0 - for i in range(num_tris * 3): - surf.indicies.append(face_geo.indicies[i] + index_offset) - var vertex: Vector3 = surf.vertices[surf.indicies.back()].vertex - vertex = Vector3(vertex.y, vertex.z, vertex.x) * map_settings.scale_factor - if include_vertices_metadata: - vertices.append(vertex) - if include_positions_metadata: - avg_vertex_pos_ct += 1 - avg_vertex_pos += vertex - if avg_vertex_pos_ct == 3: - avg_vertex_pos /= 3 - positions.append(avg_vertex_pos) - avg_vertex_pos = Vector3.ZERO - avg_vertex_pos_ct = 0 - - index_offset += face_geo.vertices.size() - - if include_shape_range_metadata: - shape_face_range.x = shape_face_range.y - shape_face_range.y = shape_face_range.x + total_brush_tris - shape_index_ranges.append(shape_face_range) - - if build_entity_index_ranges: - total_entity_tris += total_brush_tris - - if build_entity_index_ranges: - entity_face_range.x = entity_face_range.y - entity_face_range.y = entity_face_range.x + total_entity_tris - entity_index_ranges.append(entity_face_range) - - out_metadata = { - textures = textures, - texture_names = texture_names, - normals = normals, - vertices = vertices, - positions = positions, - shape_index_ranges = shape_index_ranges, - } - if build_entity_index_ranges: - out_metadata["entity_index_ranges"] = entity_index_ranges - -func add_surface() -> FuncGodotMapData.FuncGodotFaceGeometry: - var surf:= FuncGodotMapData.FuncGodotFaceGeometry.new() - out_surfaces.append(surf) - return surf - -func reset_params() -> void: - split_type = SurfaceSplitType.NONE - entity_filter_idx = -1 - texture_filter_idx = -1 - clip_filter_texture_idx = -1 - skip_filter_texture_idx = -1 - metadata_skip_flags = FuncGodotMapData.FuncGodotEntityMetadataInclusionFlags.ENTITY_INDEX_RANGES - -# nested -enum SurfaceSplitType{ - NONE, - ENTITY, - BRUSH -} diff --git a/addons/func_godot/src/core/func_godot_surface_gatherer.gd.uid b/addons/func_godot/src/core/func_godot_surface_gatherer.gd.uid deleted file mode 100644 index 3ab162be..00000000 --- a/addons/func_godot/src/core/func_godot_surface_gatherer.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://df8y3hiimomt5 diff --git a/addons/func_godot/src/core/geometry_generator.gd b/addons/func_godot/src/core/geometry_generator.gd index 4280ce10..c84210f2 100644 --- a/addons/func_godot/src/core/geometry_generator.gd +++ b/addons/func_godot/src/core/geometry_generator.gd @@ -8,8 +8,6 @@ const _SIGNATURE: String = "[GEO]" const _VERTEX_EPSILON := FuncGodotUtil._VERTEX_EPSILON const _VERTEX_EPSILON2 := _VERTEX_EPSILON * _VERTEX_EPSILON -const _HYPERPLANE_SIZE := 65355.0 - const _OriginType := FuncGodotFGDSolidClass.OriginType const _GroupData := FuncGodotData.GroupData @@ -21,6 +19,7 @@ const _VertexGroupData := FuncGodotData.VertexGroupData # Class members var map_settings: FuncGodotMapSettings = null +var hyperplane_size: float = 512.0 var entity_data: Array[_EntityData] var texture_materials: Dictionary[String, Material] var texture_sizes: Dictionary[String, Vector2] @@ -30,8 +29,9 @@ var texture_sizes: Dictionary[String, Vector2] ## Emitted when beginning a new step of the generation process. signal declare_step(step: String) -func _init(settings: FuncGodotMapSettings = null) -> void: +func _init(settings: FuncGodotMapSettings = null, hplane_size: float = 512.0) -> void: map_settings = settings + hyperplane_size = hplane_size #region TOOLS func is_skip(face: _FaceData) -> bool: @@ -99,10 +99,11 @@ func generate_base_winding(plane: Plane) -> PackedVector3Array: # construct oversized square on the plane to clip against var winding := PackedVector3Array() - winding.append(centroid + (right * _HYPERPLANE_SIZE) + (forward * _HYPERPLANE_SIZE)) - winding.append(centroid + (right * -_HYPERPLANE_SIZE) + (forward * _HYPERPLANE_SIZE)) - winding.append(centroid + (right * -_HYPERPLANE_SIZE) + (forward * -_HYPERPLANE_SIZE)) - winding.append(centroid + (right * _HYPERPLANE_SIZE) + (forward * -_HYPERPLANE_SIZE)) + var h: float = hyperplane_size + winding.append(centroid + (right * h) + (forward * h)) + winding.append(centroid + (right * -h) + (forward * h)) + winding.append(centroid + (right * -h) + (forward * -h)) + winding.append(centroid + (right * h) + (forward * -h)) return winding func generate_face_vertices(brush: _BrushData, face_index: int, vertex_merge_distance: float = 0.0) -> PackedVector3Array: @@ -121,9 +122,17 @@ func generate_face_vertices(brush: _BrushData, face_index: int, vertex_merge_dis if winding.is_empty(): break - # Reduce seams between vertices - for i in winding.size(): - winding.set(i, winding.get(i).snappedf(vertex_merge_distance)) + # Perform rounding and merge adjacent vertices that are equivalent + if vertex_merge_distance > 0: + var merged_winding : PackedVector3Array = PackedVector3Array() + var prev_vtx : Vector3 = winding[0].snappedf(vertex_merge_distance) + merged_winding.append(prev_vtx) + for i in range(1, winding.size()): + var cur_vtx : Vector3 = winding[i].snappedf(vertex_merge_distance) + if prev_vtx != cur_vtx: + merged_winding.append(cur_vtx) + prev_vtx = cur_vtx + winding = merged_winding return winding @@ -206,9 +215,9 @@ func determine_entity_origins(entity_index: int) -> void: var origin_comps: PackedFloat64Array = entity.properties["origin"].split_floats(" ") if origin_comps.size() > 2: if entity.origin_type == _OriginType.ABSOLUTE: - entity.origin = Vector3(origin_comps[0], origin_comps[1], origin_comps[2]) + entity.origin = Vector3(origin_comps[0], origin_comps[1], origin_comps[2]) * map_settings.scale_factor else: # _OriginType.RELATIVE - entity.origin += Vector3(origin_comps[0], origin_comps[1], origin_comps[2]) + entity.origin += Vector3(origin_comps[0], origin_comps[1], origin_comps[2]) * map_settings.scale_factor _OriginType.BRUSH: if origin_mins != Vector3.INF: @@ -312,7 +321,7 @@ func generate_entity_surfaces(entity_index: int) -> void: def = entity.definition var op_entity_ogl_xf: Callable = func(v: Vector3) -> Vector3: - return (FuncGodotUtil.id_to_opengl(v - entity.origin) * map_settings.scale_factor) + return (FuncGodotUtil.id_to_opengl(v - entity.origin)) # Surface groupings var surfaces: Dictionary[String, Array] = {} @@ -372,13 +381,70 @@ func generate_entity_surfaces(entity_index: int) -> void: # Begin fresh index offset for this subarray var index_offset: int = 0 - for face in faces: + for face: _FaceData in faces: # FACE SCOPE BEGIN # Reject invalid faces if face.vertices.size() < 3 or is_skip(face) or is_origin(face): continue + #region Reject interior faces only if desired + if entity.properties.get(map_settings.cull_interior_faces_property, false): + var remove_face := false + for face2: _FaceData in faces: + if face == face2: + continue + # Are the planes aligned? + if !face2.plane.has_point(face.plane.get_center()): + continue + # Opposite planes + if !(face.plane.normal*-1.0).is_equal_approx(face2.plane.normal): + continue; + + # Check for faces that share all their vertices. + var all_verts_in_face := true + for vert in face.vertices: + if !face2.vertices.has(vert): + all_verts_in_face = false + break; + if all_verts_in_face: + remove_face = true + break + + # Check if all vertices of Face1 intersect with any triangle of face 2 + # If they do, then Face 1 is entirely overlapped on Face 2 and we can remove Face 1 + var all_verts_in_face2 := true + for vert in face.vertices: + var vert_in_any_tri := false + var from := vert - face2.plane.normal*0.001 + var to := face2.plane.normal*0.001 + + # Loop over all triangles in face 2 and see if the vert intersects any of them + for i in ((face2.indices.size()/3)): + var intersect = Geometry3D.ray_intersects_triangle( + from, + to, + face2.vertices[face2.indices[i*3]], + face2.vertices[face2.indices[i*3 + 1]], + face2.vertices[face2.indices[i*3 + 2]] + ) + if !intersect: + continue + if intersect: + vert_in_any_tri = true + break; + # This vert didn't show up any triangle, can't remove this face + if !vert_in_any_tri: + all_verts_in_face2 = false + break + # All verts of face 1 are in face 2, so we can safely remove that face + if all_verts_in_face2: + remove_face = true + break; + if remove_face: + continue; + #endregion + # Create trimesh points regardless of texture if build_concave: var tris: PackedVector3Array @@ -519,9 +585,11 @@ func generate_entity_surfaces(entity_index: int) -> void: func unwrap_uv2s(entity_index: int, texel_size: float) -> void: var entity: _EntityData = entity_data[entity_index] - if entity.mesh: - if (entity.definition as FuncGodotFGDSolidClass).global_illumination_mode: - entity.mesh.lightmap_unwrap(Transform3D.IDENTITY, texel_size) + # NOTE: This skips smoothed meshes as they need to be unwrapped after smoothing. + # Ideally smoothing will be performed here in GeoGen before this process. + # For now, since it occurs in EntityAssembler, skip it. + if entity.mesh and entity.is_gi_enabled() and not entity.is_smooth_shaded(map_settings.entity_smoothing_property): + entity.mesh.lightmap_unwrap(Transform3D.IDENTITY, texel_size) # Main build process func build(build_flags: int, entities: Array[_EntityData]) -> Error: diff --git a/addons/func_godot/src/core/parser.gd b/addons/func_godot/src/core/parser.gd index 16e63826..dc2db4ad 100644 --- a/addons/func_godot/src/core/parser.gd +++ b/addons/func_godot/src/core/parser.gd @@ -81,8 +81,22 @@ func parse_map_data(map_file: String, map_settings: FuncGodotMapSettings) -> _Pa var entities_data: Array[_EntityData] = parse_data.entities var entity_defs: Dictionary[String, FuncGodotFGDEntityClass] = map_settings.entity_fgd.get_entity_definitions() + var missing_defs: PackedStringArray = [] - declare_step.emit("Checking entity omission and definition status") + var default_point_class := FuncGodotFGDPointClass.new() + default_point_class.node_class = "Marker3D" + + var default_solid_class := FuncGodotFGDSolidClass.new() + default_solid_class.spawn_type = FuncGodotFGDSolidClass.SpawnType.ENTITY + default_solid_class.build_occlusion = false + default_solid_class.collision_shape_type = FuncGodotFGDSolidClass.CollisionShapeType.NONE + default_solid_class.origin_type = FuncGodotFGDSolidClass.OriginType.BRUSH + + declare_step.emit("Checking entity omission, definition status, and property types") + + # Cache retrieved class property defaults. Format is Dictionary[Classname, Properties]. + var prop_defaults_cache: Dictionary[String, Dictionary] = {} + var prop_descriptions_cache: Dictionary[String, Dictionary] = {} for i in range(entities_data.size() - 1, -1, -1): var entity: _EntityData = entities_data[i] @@ -98,6 +112,145 @@ func parse_map_data(map_file: String, map_settings: FuncGodotMapSettings) -> _Pa var classname: String = entity.properties["classname"] if classname in entity_defs: entity.definition = entity_defs[classname] + if not entity.definition is FuncGodotFGDSolidClass and not entity.definition is FuncGodotFGDPointClass: + if missing_defs.find(classname) < 0: + push_error("Invalid entity definition for \"" + classname + "\". Entity definition must be Solid Class or Point Class.") + missing_defs.append(classname) + entity.definition = null + elif missing_defs.find(classname) < 0: + push_error("No entity definition found for \"" + classname + "\"") + missing_defs.append(classname) + + # Make sure we have a default definition to build entities from + # This will make sure nothing goes wrong in the build processes + if not entity.definition: + if entity.brushes.is_empty(): + entity.definition = default_point_class + else: + entity.definition = default_solid_class + + # Convert the string values of the entity's properties Dictionary to various + # Variant formats based on the entity definition's class property defaults. + var def := entity.definition + var properties: Dictionary = entity.properties + for property in properties: + var prop_string = entity.properties[property] + if property in def.class_properties: + var prop_default: Variant = def.class_properties[property] + + match typeof(prop_default): + TYPE_INT: + properties[property] = prop_string.to_int() + TYPE_FLOAT: + properties[property] = prop_string.to_float() + TYPE_BOOL: + properties[property] = bool(prop_string.to_int()) + TYPE_VECTOR3: + var prop_comps: PackedFloat64Array = prop_string.split_floats(" ") + if prop_comps.size() > 2: + properties[property] = Vector3(prop_comps[0], prop_comps[1], prop_comps[2]) + else: + push_error("Invalid Vector3 format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) + properties[property] = prop_default + TYPE_VECTOR3I: + var prop_vec: Vector3i = prop_default + var prop_comps: PackedStringArray = prop_string.split(" ") + if prop_comps.size() > 2: + for v in 3: + prop_vec[v] = prop_comps[v].to_int() + else: + push_error("Invalid Vector3i format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) + properties[property] = prop_vec + TYPE_COLOR: + var prop_color: Color = prop_default + var prop_comps: PackedStringArray = prop_string.split(" ") + if prop_comps.size() > 2: + prop_color.r8 = prop_comps[0].to_int() + prop_color.g8 = prop_comps[1].to_int() + prop_color.b8 = prop_comps[2].to_int() + prop_color.a = 1.0 + else: + push_error("Invalid Color format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) + properties[property] = prop_color + TYPE_DICTIONARY: + var prop_desc = def.class_property_descriptions[property] + if prop_desc is Array and prop_desc.size() > 1 and prop_desc[1] is int: + properties[property] = prop_string.to_int() + TYPE_ARRAY: + properties[property] = prop_string.to_int() + TYPE_VECTOR2: + var prop_comps: PackedFloat64Array = prop_string.split_floats(" ") + if prop_comps.size() > 1: + properties[property] = Vector2(prop_comps[0], prop_comps[1]) + else: + push_error("Invalid Vector2 format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) + properties[property] = prop_default + TYPE_VECTOR2I: + var prop_vec: Vector2i = prop_default + var prop_comps: PackedStringArray = prop_string.split(" ") + if prop_comps.size() > 1: + for v in 2: + prop_vec[v] = prop_comps[v].to_int() + else: + push_error("Invalid Vector2i format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) + properties[property] = prop_vec + TYPE_VECTOR4: + var prop_comps: PackedFloat64Array = prop_string.split_floats(" ") + if prop_comps.size() > 3: + properties[property] = Vector4(prop_comps[0], prop_comps[1], prop_comps[2], prop_comps[3]) + else: + push_error("Invalid Vector4 format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) + properties[property] = prop_default + TYPE_VECTOR4I: + var prop_vec: Vector4i = prop_default + var prop_comps: PackedStringArray = prop_string.split(" ") + if prop_comps.size() > 3: + for v in 4: + prop_vec[v] = prop_comps[v].to_int() + else: + push_error("Invalid Vector4i format for \'" + property + "\' in entity \'" + def.classname + "\': " + prop_string) + properties[property] = prop_vec + TYPE_STRING_NAME: + properties[property] = StringName(prop_string) + TYPE_NODE_PATH: + properties[property] = prop_string + TYPE_OBJECT: + properties[property] = prop_string + + # Retrieve default properties. + var def_properties: Dictionary[String, Variant] = prop_defaults_cache.get(def.classname, def.retrieve_all_class_properties()) + var def_descriptions: Dictionary[String, Variant] = prop_descriptions_cache.get(def.classname, def.retrieve_all_class_property_descriptions()) + + # Assign properties not defined with defaults from the entity definition + for property in def_properties: + if not property in properties: + var prop_default: Variant = def_properties[property] + # Flags + if prop_default is Array: + var prop_flags_sum := 0 + for prop_flag in prop_default: + if prop_flag is Array and prop_flag.size() > 2: + if prop_flag[2] and prop_flag[1] is int: + prop_flags_sum += prop_flag[1] + properties[property] = prop_flags_sum + # Choices + elif prop_default is Dictionary: + var prop_desc = def_descriptions.get(property, "") + if prop_desc is Array and prop_desc.size() > 1 and (prop_desc[1] is int or prop_desc[1] is String): + properties[property] = prop_desc[1] + elif prop_default.size(): + properties[property] = prop_default[prop_default.keys().front()] + else: + properties[property] = 0 + # Materials, Shaders, and Sounds + elif prop_default is Resource: + properties[property] = prop_default.resource_path + # Target Destination and Target Source + elif prop_default is NodePath or prop_default is Object or prop_default == null: + properties[property] = "" + # Everything else + else: + properties[property] = prop_default # Delete omitted groups declare_step.emit("Removing omitted layers and groups") @@ -203,7 +356,7 @@ func _parse_quake_map(map_data: PackedStringArray, map_settings: FuncGodotMapSet for i in 3: tokens[i] = tokens[i].trim_prefix("(") var pts: PackedFloat64Array = tokens[i].split_floats(" ", false) - var point := Vector3(pts[0], pts[1], pts[2]) + var point := Vector3(pts[0], pts[1], pts[2]) * map_settings.scale_factor points[i] = point var plane := Plane(points[0], points[1], points[2]) @@ -244,8 +397,8 @@ func _parse_quake_map(map_data: PackedStringArray, map_settings: FuncGodotMapSet coords = tokens[2].split_floats(" ", false) # UV scale factor stored in basis - face.uv.x = Vector2(coords[1], 0.0) - face.uv.y = Vector2(0.0, coords[2]) + face.uv.x = Vector2(coords[1], 0.0) * map_settings.scale_factor + face.uv.y = Vector2(0.0, coords[2]) * map_settings.scale_factor # Quake Standard: texname offsetX offsetY rotation scaleX scaleY else: @@ -253,8 +406,8 @@ func _parse_quake_map(map_data: PackedStringArray, map_settings: FuncGodotMapSet face.uv.origin = Vector2(coords[0], coords[1]) var r: float = deg_to_rad(coords[2]) - face.uv.x = Vector2(cos(r), -sin(r)) * coords[3] - face.uv.y = Vector2(sin(r), cos(r)) * coords[4] + face.uv.x = Vector2(cos(r), -sin(r)) * coords[3] * map_settings.scale_factor + face.uv.y = Vector2(sin(r), cos(r)) * coords[4] * map_settings.scale_factor brush.faces.append(face) continue @@ -374,7 +527,7 @@ func _parse_vmf(map_data: PackedStringArray, map_settings: FuncGodotMapSettings, for i in 3: tokens[i] = tokens[i].trim_prefix("(") var pts: PackedFloat64Array = tokens[i].split_floats(" ", false) - var point: Vector3 = Vector3(pts[0], pts[1], pts[2]) + var point: Vector3 = Vector3(pts[0], pts[1], pts[2]) * map_settings.scale_factor points[i] = point brush.planes.append(Plane(points[0], points[1], points[2])) brush.faces.append(_FaceData.new()) @@ -399,10 +552,10 @@ func _parse_vmf(map_data: PackedStringArray, map_settings: FuncGodotMapSettings, face.uv_axes.append(Vector3(vals[0], vals[1], vals[2])) if key.begins_with("u"): face.uv.origin.x = vals[3] # Offset - face.uv.x *= vals[4] # Scale + face.uv.x *= vals[4] * map_settings.scale_factor # Scale else: face.uv.origin.y = vals[3] # Offset - face.uv.y *= vals[4] # Scale + face.uv.y *= vals[4] * map_settings.scale_factor # Scale continue "rotation": # Rotation isn't used in Valve 220 mapping and VMFs are 220 exclusive diff --git a/addons/func_godot/src/fgd/func_godot_fgd_entity_class.gd b/addons/func_godot/src/fgd/func_godot_fgd_entity_class.gd index bcc0ab2f..7fdd0e9b 100644 --- a/addons/func_godot/src/fgd/func_godot_fgd_entity_class.gd +++ b/addons/func_godot/src/fgd/func_godot_fgd_entity_class.gd @@ -1,5 +1,5 @@ @icon("res://addons/func_godot/icons/icon_godot_ranger.svg") -class_name FuncGodotFGDEntityClass extends Resource +@abstract class_name FuncGodotFGDEntityClass extends Resource ## Entity definition template. WARNING! Not to be used directly! Use [FuncGodotFGDBaseClass], [FuncGodotFGDSolidClass], or [FuncGodotFGDPointClass] instead. ## ## Entity definition template. It holds all of the common entity class properties shared between [FuncGodotFGDBaseClass], [FuncGodotFGDSolidClass], or [FuncGodotFGDPointClass]. @@ -28,24 +28,24 @@ var prefix: String = "" ## Key value pair properties that will appear in the map editor. After building the [FuncGodotMap] in Godot, these properties will be added to a [Dictionary] ## that gets applied to the generated node, as long as that node is a tool script with an exported `func_godot_properties` Dictionary. -@export var class_properties : Dictionary = {} +@export var class_properties : Dictionary[String, Variant] = {} ## Map editor descriptions for previously defined key value pair properties. Optional but recommended. -@export var class_property_descriptions : Dictionary = {} +@export var class_property_descriptions : Dictionary[String, Variant] = {} ## Automatically applies entity class properties to matching properties in the generated node. ## When using this feature, class properties need to be the correct type or you may run into errors on map build. @export var auto_apply_to_matching_node_properties : bool = false ## Appearance properties for the map editor. See the Valve Developer Wiki and TrenchBroom documentation for more information. -@export var meta_properties : Dictionary = { +@export var meta_properties : Dictionary[String, Variant] = { "size": AABB(Vector3(-8, -8, -8), Vector3(8, 8, 8)), "color": Color(0.8, 0.8, 0.8) } @export_group("Node Generation") -## Node to generate on map build. This can be a built-in Godot class, a GDScript class, or a GDExtension class. +## Node to generate on map build. This can be a built-in Godot class, a Script class, or a GDExtension class. ## For Point Class entities that use Scene File instantiation leave this blank. @export var node_class := "" @@ -54,6 +54,9 @@ var prefix: String = "" ## Nodes will be named `"entity_" + name_property`. An entity's name should be unique, otherwise you may run into unexpected behavior. @export var name_property := "" +## Optional array of node groups to add the generated node to. +@export var node_groups : Array[String] = [] + ## Parses the definition and outputs it into the FGD format. func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM) -> String: # Class prefix @@ -231,3 +234,17 @@ func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = res += "]" + FuncGodotUtil.newline() return res + +func retrieve_all_class_properties(properties: Dictionary[String, Variant] = {}) -> Dictionary[String, Variant]: + for key in class_properties.keys(): + properties[key] = class_properties[key] + for b in base_classes: + properties = b.retrieve_all_class_properties(properties) + return properties + +func retrieve_all_class_property_descriptions(descriptions: Dictionary[String, Variant] = {}) -> Dictionary[String, Variant]: + for key in class_property_descriptions.keys(): + descriptions[key] = class_property_descriptions[key] + for b in base_classes: + descriptions = b.retrieve_all_class_property_descriptions(descriptions) + return descriptions diff --git a/addons/func_godot/src/fgd/func_godot_fgd_file.gd b/addons/func_godot/src/fgd/func_godot_fgd_file.gd index f1e23178..e106aa8a 100644 --- a/addons/func_godot/src/fgd/func_godot_fgd_file.gd +++ b/addons/func_godot/src/fgd/func_godot_fgd_file.gd @@ -23,28 +23,25 @@ func export_button() -> void: do_export_file(target_map_editor) func do_export_file(target_editor: FuncGodotTargetMapEditors = FuncGodotTargetMapEditors.TRENCHBROOM, fgd_output_folder: String = "") -> void: - if not Engine.is_editor_hint(): - return - if fgd_output_folder.is_empty(): fgd_output_folder = FuncGodotLocalConfig.get_setting(FuncGodotLocalConfig.PROPERTY.FGD_OUTPUT_FOLDER) as String if fgd_output_folder.is_empty(): - print("Skipping export: No game config folder") + printerr("Skipping export: No game config folder") return if fgd_name == "": - print("Skipping export: Empty FGD name") + printerr("Skipping export: Empty FGD name") if not DirAccess.dir_exists_absolute(fgd_output_folder): if DirAccess.make_dir_recursive_absolute(fgd_output_folder) != OK: - print("Skipping export: Failed to create directory") + printerr("Skipping export: Failed to create directory") return var fgd_file = fgd_output_folder.path_join(fgd_name + ".fgd") var file_obj := FileAccess.open(fgd_file, FileAccess.WRITE) if not file_obj: - print("Failed to open file for writing: ", fgd_file) + printerr("Failed to open file for writing: ", fgd_file) return print("Exporting FGD to ", fgd_file) @@ -76,6 +73,9 @@ func do_export_file(target_editor: FuncGodotTargetMapEditors = FuncGodotTargetMa ## Array of resources that inherit from [FuncGodotFGDEntityClass]. This array defines the entities that will be added to the exported FGD file and the nodes that will be generated in a [FuncGodotMap]. @export var entity_definitions: Array[Resource] = [] +## Toggles whether [FuncGodotFGDModelPointClass] resources will generate models from their [PackedScene] files. +@export var generate_model_point_class_models: bool = true + func build_class_text(target_editor: FuncGodotTargetMapEditors = FuncGodotTargetMapEditors.TRENCHBROOM) -> String: var res : String = "" @@ -91,6 +91,8 @@ func build_class_text(target_editor: FuncGodotTargetMapEditors = FuncGodotTarget continue if ent.func_godot_internal: continue + if ent is FuncGodotFGDModelPointClass: + ent._model_generation_enabled = generate_model_point_class_models var ent_text = ent.build_def_text(target_editor) res += ent_text @@ -127,9 +129,9 @@ func get_entity_definitions() -> Dictionary[String, FuncGodotFGDEntityClass]: if ent is FuncGodotFGDPointClass or ent is FuncGodotFGDSolidClass: var entity_def = ent.duplicate() - var meta_properties := {} - var class_properties := {} - var class_property_descriptions := {} + var meta_properties: Dictionary[String, Variant] = {} + var class_properties: Dictionary[String, Variant] = {} + var class_property_descriptions: Dictionary[String, Variant] = {} for base_class in _generate_base_class_list(entity_def): for meta_property in base_class.meta_properties: diff --git a/addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd b/addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd index c27065d4..997ded1b 100644 --- a/addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd +++ b/addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd @@ -29,6 +29,8 @@ enum TargetMapEditor { ## Creates a .gdignore file in the model export folder to prevent Godot importing the display models. Only needs to be generated once. @export_tool_button("Generate GD Ignore File", "FileAccess") var generate_gd_ignore_file : Callable = _generate_gd_ignore_file +var _model_generation_enabled: bool = false + func _generate_gd_ignore_file() -> void: if Engine.is_editor_hint(): var path: String = _get_game_path().path_join(_get_model_folder()) @@ -45,7 +47,9 @@ func _generate_gd_ignore_file() -> void: ## Builds and saves the display model into the specified destination, then parses the definition and outputs it into the FGD format. func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM) -> String: - _generate_model() + if _model_generation_enabled: + _generate_model() + _model_generation_enabled = false return super() func _generate_model() -> void: @@ -65,7 +69,10 @@ func _generate_model() -> void: if target_map_editor == TargetMapEditor.TRENCHBROOM: const model_key: String = "model" if scale_expression.is_empty(): - meta_properties[model_key] = '"%s"' % _get_local_path() + meta_properties[model_key] = '{"path": "%s", "scale": %s }' % [ + _get_local_path(), + ProjectSettings.get_setting("func_godot/default_inverse_scale_factor", 32.0) as float + ] else: meta_properties[model_key] = '{"path": "%s", "scale": %s }' % [ _get_local_path(), diff --git a/addons/func_godot/src/fgd/func_godot_fgd_point_class.gd b/addons/func_godot/src/fgd/func_godot_fgd_point_class.gd index 58b4dce1..adbc35a9 100644 --- a/addons/func_godot/src/fgd/func_godot_fgd_point_class.gd +++ b/addons/func_godot/src/fgd/func_godot_fgd_point_class.gd @@ -3,7 +3,7 @@ class_name FuncGodotFGDPointClass extends FuncGodotFGDEntityClass ## FGD PointClass entity definition. ## -## A resource used to define an FGD PointClass entity. PointClass entities can use either the [member FuncGodotFGDEntityClass.node_class] +## A resource used to define an FGD Point Class entity. PointClass entities can use either the [member FuncGodotFGDEntityClass.node_class] ## or the [member scene_file] property to tell [FuncGodotMap] what to generate on map build. ## ## @tutorial(Quake Wiki Entity Article): https://quakewiki.org/wiki/Entity @@ -17,15 +17,12 @@ class_name FuncGodotFGDPointClass extends FuncGodotFGDEntityClass func _init() -> void: prefix = "@PointClass" -@export_group ("Scene") ## An optional [PackedScene] file to instantiate on map build. Overrides [member FuncGodotFGDEntityClass.node_class] and [member script_class]. @export var scene_file: PackedScene -@export_group ("Scripting") ## An optional [Script] resource to attach to the node generated on map build. Ignored if [member scene_file] is specified. @export var script_class: Script -@export_group("Build") ## Toggles whether entity will use `angles`, `mangle`, or `angle` to determine rotations on [FuncGodotMap] build, prioritizing the key value pairs in that order. ## Set to [code]false[/code] if you would like to define how the generated node is rotated yourself. @export var apply_rotation_on_map_build : bool = true @@ -33,3 +30,91 @@ func _init() -> void: ## Toggles whether entity will use `scale` to determine the generated node or scene's scale. This is performed on the top level node. ## The property can be a [float], [Vector3], or [Vector2]. Set to [code]false[/code] if you would like to define how the generated node is scaled yourself. @export var apply_scale_on_map_build: bool = true + +## An optional [Array] of [FuncGodotFGDPointClassDisplayDescriptor] that describes how this Point Entity should appear in the map editor. +## When using multiple display descriptors, only the first element found without [member FuncGodotFGDPointClassDisplayDescriptor.conditional] +## will be used as the default display asset. If no descriptor is found without a condition, the last descriptor will become the default.[br][br] +## Conditional display descriptors will be written to the FGD in the order set in the array.[br][br] +## [color=orange]WARNING:[/color] Multiple descriptors are only supported by TrenchBroom! They will be omitted on export when +## [member FuncGodotFGDFile.target_map_editor] is not set to [enum FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM]. +@export var display_descriptors: Array[FuncGodotFGDPointClassDisplayDescriptor] = [] + +func _build_model_branch_text(descriptor: FuncGodotFGDPointClassDisplayDescriptor) -> String: + if not descriptor: + return '' + + var model_string: String = '' + var uses_options: bool = false + + if not descriptor.scale.is_empty() or not descriptor.skin.is_empty() or not descriptor.frame.is_empty(): + uses_options = true + + if not uses_options: + return descriptor.display_asset_path + + model_string = '{ \"path\": %s' % descriptor.display_asset_path + + if not descriptor.skin.is_empty(): + model_string += ', \"skin\": %s' % descriptor.skin + if not descriptor.frame.is_empty(): + model_string += ', \"frame\": %s' % descriptor.frame + if not descriptor.scale.is_empty(): + model_string += ', \"scale\": %s' % descriptor.scale + + model_string += " }" + + return model_string + +func _build_model_text() -> String: + var model_string: String = '' + + if display_descriptors.is_empty(): + return model_string + + if display_descriptors.size() == 1: + return _build_model_branch_text(display_descriptors[0]) + + model_string = '{{' + var default_display: FuncGodotFGDPointClassDisplayDescriptor + for i in display_descriptors.size(): + var d: FuncGodotFGDPointClassDisplayDescriptor = display_descriptors[i] + + # Only set the first discovered descriptor without a condition to the default, which must be the last option in a list. + # If a conditional is not set, skip it. + if d.conditional.is_empty(): + if not default_display: + default_display = d + else: + printerr(classname + " has a Point Class Display Descriptor without required conditionals set. Must have only 1 conditionless Display Descriptor!") + continue + + model_string += '%s -> %s, ' % [d.conditional, _build_model_branch_text(d)] + + if default_display: + model_string += '%s }}' % _build_model_branch_text(default_display) + else: + model_string = model_string.trim_suffix(', ') + model_string += ' }}' + + return model_string + +func _build_studio_text() -> String: + var display_string = "" + for d in display_descriptors: + if d.display_asset_path.find('\"') != -1: + display_string = d.display_asset_path + else: + printerr(classname + " attempting to set an invalid value to @studio format during FGD export. Only relative file paths encapsulated by quotations are valid.") + return display_string + +func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM) -> String: + if not display_descriptors.is_empty(): + if target_editor == FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM: + var display_string: String = _build_model_text() + if not display_string.is_empty(): + meta_properties["model"] = display_string + else: + var display_string: String = _build_studio_text() + if not display_string.is_empty(): + meta_properties["studio"] = display_string + return super(target_editor) diff --git a/addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd b/addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd new file mode 100644 index 00000000..c8355f84 --- /dev/null +++ b/addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd @@ -0,0 +1,48 @@ +@tool +@icon("res://addons/func_godot/icons/icon_godambler3d.svg") +class_name FuncGodotFGDPointClassDisplayDescriptor extends Resource +## Resource that describes how to display an FGD Point Class entity. +## +## A resource for [FuncGodotFGDPointClass] that describes how to display a point entity in a map editor. +## Values entered into the different options are taken literally: paths should be enclosed within quotation marks, +## while class property keys and integer values should omit them.[br][br] +## +## Most editors only support the [member display_asset] option. Exporting an FGD compatible with these editors will +## automatically omit the unsupported options introduced by TrenchBroom when exporting from their respective game configuration resources +## or setting [member FuncGodotFGDFile.target_map_editor] away from [enum FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM]. +## +## The extra options are considered advanced features and are unable to be evaluated by FuncGodot to ensure they were input correctly. +## Exercise caution, care, and patience when attempting to use these, especially the [member conditional] option. +## +## @tutorial(Level Design Book: Display Models for Entities): https://book.leveldesignbook.com/appendix/resources/formats/fgd#display-models-for-entities +## @tutorial(Valve Developer Wiki FGD Article: Entity Description Section): https://developer.valvesoftware.com/wiki/FGD#Entity_Description +## @tutorial(TrenchBroom Manual: Display Models for Entities): https://trenchbroom.github.io/manual/latest/#display-models-for-entities +## @tutorial(TrenchBroom Manual: Expression Language): https://trenchbroom.github.io/manual/latest/#expression_language + +## Either a file path to the asset that will be displayed for this point entity, relative to the map editor's game path, +## or a class property key that can contain the path.[br][br] +## For paths, you must surround the path with quotes, e.g: [code]"models/marsfrog.glb"[/code]. +## For properties, you must omit the quotes, e.g: [code]display_model_path[/code].[br][br] +## Different editors support different file types: common ones include MDL, GLB, SPR, and PNG. +@export var display_asset_path: String = "" + +@export_group("TrenchBroom Options") +## Optional string that determines the scale of the display asset. This can be a number, a class property key, or +## a scale expression in accordance with TrenchBroom's Expression Language. Leave blank to use the game configuration's default scale expression.[br][br] +## [color=orange]WARNING:[/color] Only utilized by TrenchBroom! +@export var scale: String = "" + +## Optional string that determines which skin the display asset should use. This can be either a number or a class property key.[br][br] +## [color=orange]WARNING:[/color] Only utilized by TrenchBroom! +@export var skin: String = "" + +## Optional string that determines the appearance of a display asset based on its file type. This can be either a number or a class property key.[br][br] +## Traditional Quake MDL files will set the display to that frame of its animations (all animations in a Quake MDL are compiled into a single animation). +## GLBs meanwhile seem to set themselves to the animation assigned to an index that matches the [code]frame[/code] value.[br][br] +## [color=orange]WARNING:[/color] Only utilized by TrenchBroom! +@export var frame: String = "" + +## Optional evaluation string that, when true, will force the Point Class to display the asset defined by [member display_asset_path]. +## Format should be [code]property == value[/code] or some other valid expression in accordance with TrenchBroom's Expression Language.[br][br] +## [color=orange]WARNING:[/color] Only utilized by TrenchBroom! +@export var conditional: String = "" diff --git a/addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd.uid b/addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd.uid new file mode 100644 index 00000000..efdfad4f --- /dev/null +++ b/addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd.uid @@ -0,0 +1 @@ +uid://d1nwwgcrner8b diff --git a/addons/func_godot/src/import/quake_map_import_plugin.gd b/addons/func_godot/src/import/quake_map_import_plugin.gd index c9f1101b..9470f3f4 100644 --- a/addons/func_godot/src/import/quake_map_import_plugin.gd +++ b/addons/func_godot/src/import/quake_map_import_plugin.gd @@ -38,6 +38,6 @@ func _import(source_file, save_path, options, r_platform_variants, r_gen_files) map_resource.revision += 1 else: map_resource = QuakeMapFile.new() - map_resource.map_data = FileAccess.open(source_file, FileAccess.READ).get_as_text(true) + map_resource.map_data = FileAccess.open(source_file, FileAccess.READ).get_as_text() return ResourceSaver.save(map_resource, save_path_str) diff --git a/addons/func_godot/src/import/quake_palette_import_plugin.gd b/addons/func_godot/src/import/quake_palette_import_plugin.gd index 93abd08a..54ce63d6 100644 --- a/addons/func_godot/src/import/quake_palette_import_plugin.gd +++ b/addons/func_godot/src/import/quake_palette_import_plugin.gd @@ -34,7 +34,7 @@ func _import(source_file, save_path, options, r_platform_variants, r_gen_files) var file = FileAccess.open(source_file, FileAccess.READ) if file == null: var err = FileAccess.get_open_error() - print(['Error opening super.lmp file: ', err]) + printerr(['Error opening super.lmp file: ', err]) return err var colors := PackedColorArray() diff --git a/addons/func_godot/src/import/quake_wad_file.gd b/addons/func_godot/src/import/quake_wad_file.gd index 5a0d66ef..e97113d7 100644 --- a/addons/func_godot/src/import/quake_wad_file.gd +++ b/addons/func_godot/src/import/quake_wad_file.gd @@ -10,5 +10,5 @@ class_name QuakeWadFile extends Resource ## Collection of [ImageTexture] imported from the WAD file. @export var textures: Dictionary[String, ImageTexture] -func _init(textures: Dictionary = Dictionary()): +func _init(textures: Dictionary[String, ImageTexture] = {}): self.textures = textures diff --git a/addons/func_godot/src/import/quake_wad_import_plugin.gd b/addons/func_godot/src/import/quake_wad_import_plugin.gd index cd14ee93..fcc9df61 100644 --- a/addons/func_godot/src/import/quake_wad_import_plugin.gd +++ b/addons/func_godot/src/import/quake_wad_import_plugin.gd @@ -70,7 +70,7 @@ func _import(source_file, save_path, options, r_platform_variants, r_gen_files) var file = FileAccess.open(source_file, FileAccess.READ) if file == null: var err = FileAccess.get_open_error() - print(['Error opening super.wad file: ', err]) + printerr(['Error opening super.wad file: ', err]) return err # Read WAD header @@ -81,13 +81,13 @@ func _import(source_file, save_path, options, r_platform_variants, r_gen_files) if magic_string == 'WAD3': wad_format = WadFormat.HalfLife elif magic_string != 'WAD2': - print('Error: Invalid WAD magic') + printerr('Error: Invalid WAD magic') return ERR_INVALID_DATA var palette_path : String = options['palette_file'] var palette_file : QuakePaletteFile = load(palette_path) as QuakePaletteFile if wad_format == WadFormat.Quake and not palette_file: - print('Error: Invalid Quake palette file') + printerr('Error: Invalid Quake palette file') file.close() return ERR_CANT_ACQUIRE_RESOURCE diff --git a/addons/func_godot/src/map/func_godot_map.gd b/addons/func_godot/src/map/func_godot_map.gd index 908536d0..b514b21d 100644 --- a/addons/func_godot/src/map/func_godot_map.gd +++ b/addons/func_godot/src/map/func_godot_map.gd @@ -43,6 +43,12 @@ var _map_file_internal: String = "" ## [enum BuildFlags] that can affect certain aspects of the build process. @export_flags("Unwrap UV2:1", "Show Profiling Info:2", "Disable Smooth Shading:4") var build_flags: int = 0 +## The hyperplane is an initial plane that all geometry faces are cut from, like a large sheet of marble before a sculptor begins chiseling. +## The hyperplane size would need to be able to cover your map's potential total area. +## Smaller values can minimize floating point errors, reducing the effect of gaps between polygon seams. +## Measured in Godot units, not Quake units. +@export_range(256.0, 2048.0, 128.0) var hyperplane_size: float = 512.0 + ## Map build failure handler. Displays error message and emits [signal build_failed] signal. func fail_build(reason: String, notify: bool = false) -> void: push_error(_SIGNATURE, " ", reason) @@ -117,7 +123,7 @@ func build() -> void: parser = null # Retrieve geometry - var generator := FuncGodotGeometryGenerator.new(map_settings) + var generator := FuncGodotGeometryGenerator.new(map_settings, hyperplane_size) if build_flags & BuildFlags.SHOW_PROFILE_INFO: print("\nGEOMETRY GENERATOR") generator.declare_step.connect(FuncGodotUtil.print_profile_info.bind(generator._SIGNATURE)) diff --git a/addons/func_godot/src/map/func_godot_map_settings.gd b/addons/func_godot/src/map/func_godot_map_settings.gd index 189a9d14..6085437f 100644 --- a/addons/func_godot/src/map/func_godot_map_settings.gd +++ b/addons/func_godot/src/map/func_godot_map_settings.gd @@ -4,7 +4,8 @@ class_name FuncGodotMapSettings extends Resource ## Reusable map settings configuration for [FuncGodotMap] nodes. #region BUILD -@export_category("Build Settings") +@export_group("Build Settings") + ## Set automatically when [member inverse_scale_factor] is changed. Used primarily during the build process. var scale_factor: float = 0.03125 @@ -21,30 +22,51 @@ var scale_factor: float = 0.03125 ## [FuncGodotFGDFile] that translates map file classnames into Godot nodes and packed scenes. @export var entity_fgd: FuncGodotFGDFile = preload("res://addons/func_godot/fgd/func_godot_fgd.tres") -## Default class property to use in naming generated nodes. This setting is overridden by [member FuncGodotFGDEntityClass.name_property]. -## Naming occurs before adding to the [SceneTree] and applying properties. -## Nodes will be named `"entity_" + name_property`. An entity's name should be unique, otherwise you may run into unexpected behavior. -@export var entity_name_property: String = "" - -## Class property that determines whether the [FuncGodotFGDSolidClass] entity performs mesh smoothing operations. -@export var entity_smoothing_property: String = "_phong" - -## Class property that contains the angular threshold that determines when a [FuncGodotFGDSolidClass] entity's mesh vertices are smoothed. -@export var entity_smoothing_angle_property: String = "_phong_angle" - ## If true, will organize [SceneTree] using TrenchBroom Layers and Groups or Hammer Visgroups. Groups will be generated as [Node3D] nodes. ## All non-entity structural brushes will be moved out of their groups and merged into the `Worldspawn` entity. ## Any Layers toggled to be omitted from export in TrenchBroom and their child entities and groups will not be built. @export var use_groups_hierarchy: bool = false -## Class property that contains the snapping epsilon for generated vertices of [FuncGodotFGDSolidClass] entities. -## Utilizing this property can help reduce instances of seams between polygons. -@export var vertex_merge_distance_property: String = "_vertex_merge_distance" +## Texel size for UV2 unwrapping. +## Actual texel size is uv_unwrap_texel_size / [member inverse_scale_factor]. A ratio of 1/16 is usually a good place to start with +## (if inverse_scale_factor is 32, start with a uv_unwrap_texel_size of 2). +## Larger values will produce less detailed lightmaps. To conserve memory and filesize, use the largest value that still looks good. +@export var uv_unwrap_texel_size: float = 2.0 #endregion +#region ENTITY +@export_group("Entity Settings") + +## Optional array of node groups to add all generated nodes to. +@export var entity_node_groups: Array[String] = [] + +@export_subgroup("Entity Property Names") +## Default class property to use in naming generated nodes. This setting is overridden by [member FuncGodotFGDEntityClass.name_property]. +## Naming occurs before adding to the [SceneTree] and applying properties. +## Nodes will be named `"entity_" + name_property`. An entity's name should be unique, otherwise you may run into unexpected behavior. +@export var entity_name_property: String = "" + +## Entity class property that determines whether the [FuncGodotFGDSolidClass] entity performs mesh smoothing operations. +@export var entity_smoothing_property: String = "_phong" + +## Entity class property that contains the angular threshold that determines when a [FuncGodotFGDSolidClass] entity's mesh vertices are smoothed. +@export var entity_smoothing_angle_property: String = "_phong_angle" + +## Entity class property that contains the snapping epsilon for generated vertices of [FuncGodotFGDSolidClass] entities. +## Utilizing this property can help reduce instances of seams between polygons. +@export var vertex_merge_distance_property: String = "_vertex_merge_distance" + +## Entity class property that tells whether interior faces should be culled for that brush entity. +## Interior faces are faces with matching vertices or are flush within a larger face. +## Note that this has a performance impact that scales with how many brushes are in the entity. +@export var cull_interior_faces_property: String = "_cull_interior_faces" + +@export_subgroup("") +#endregion + #region TEXTURES -@export_category("Textures") +@export_group("Textures") ## Base directory for textures. When building materials, FuncGodot will search this directory for texture files with matching names to the textures assigned to map brush faces. @export_dir var base_texture_dir: String = "res://textures" @@ -52,25 +74,27 @@ var scale_factor: float = 0.03125 ## File extensions to search for texture data. @export var texture_file_extensions: Array[String] = ["png", "jpg", "jpeg", "bmp", "tga", "webp"] +@export_subgroup("Hint Textures") ## Optional path for the clip texture, relative to [member base_texture_dir]. ## Brush faces textured with the clip texture will have those faces removed from the generated [Mesh] but not the generated [Shape3D]. -@export var clip_texture: String = "special/clip": +@export var clip_texture: String = "clip": set(tex): clip_texture = tex.to_lower() ## Optional path for the skip texture, relative to [member base_texture_dir]. ## Brush faces textured with the skip texture will have those faces removed from the generated [Mesh]. ## If [member FuncGodotFGDSolidClass.collision_shape_type] is set to concave then it will also remove collision from those faces in the generated [Shape3D]. -@export var skip_texture: String = "special/skip": +@export var skip_texture: String = "skip": set(tex): skip_texture = tex.to_lower() ## Optional path for the origin texture, relative to [member base_texture_dir]. ## Brush faces textured with the origin texture will have those faces removed from the generated [Mesh] and [Shape3D]. ## The bounds of these faces will be used to calculate the origin point of the entity. -@export var origin_texture: String = "special/origin": +@export var origin_texture: String = "origin": set(tex): origin_texture = tex.to_lower() +@export_subgroup("") ## Optional [QuakeWadFile] resources to apply textures from. See the [Quake Wiki](https://quakewiki.org/wiki/Texture_Wad) for more information on Quake Texture WADs. @export var texture_wads: Array[QuakeWadFile] = [] @@ -78,7 +102,7 @@ var scale_factor: float = 0.03125 #endregion #region MATERIALS -@export_category("Materials") +@export_group("Materials") ## Base directory for loading and saving materials. When building materials, FuncGodot will search this directory for material resources ## with matching names to the textures assigned to map brush faces. If not found, will fall back to [member base_texture_dir]. @@ -93,33 +117,33 @@ var scale_factor: float = 0.03125 ## Sampler2D uniform that supplies the Albedo in a custom shader when [member default_material] is a [ShaderMaterial]. @export var default_material_albedo_uniform: String = "" +## Automatic [ShaderMaterial] generation mapping patterns. Only used when [member default_material] is a ShaderMaterial. +## Keys should be the names of the shader uniforms while the values should be the suffixes for the texture maps. +## Patterns only use one replacement String: the texture name, ex: [code]"%s_normal"[/code]. +@export var shader_material_uniform_map_patterns: Dictionary[String, String] = {} + +@export_subgroup("BaseMaterial3D Map Patterns") ## Automatic PBR material generation albedo map pattern. -@export var albedo_map_pattern: String = "%s_albedo.%s" +@export var albedo_map_pattern: String = "%s_albedo" ## Automatic PBR material generation normal map pattern. -@export var normal_map_pattern: String = "%s_normal.%s" +@export var normal_map_pattern: String = "%s_normal" ## Automatic PBR material generation metallic map pattern -@export var metallic_map_pattern: String = "%s_metallic.%s" +@export var metallic_map_pattern: String = "%s_metallic" ## Automatic PBR material generation roughness map pattern -@export var roughness_map_pattern: String = "%s_roughness.%s" +@export var roughness_map_pattern: String = "%s_roughness" ## Automatic PBR material generation emission map pattern -@export var emission_map_pattern: String = "%s_emission.%s" +@export var emission_map_pattern: String = "%s_emission" ## Automatic PBR material generation ambient occlusion map pattern -@export var ao_map_pattern: String = "%s_ao.%s" +@export var ao_map_pattern: String = "%s_ao" ## Automatic PBR material generation height map pattern -@export var height_map_pattern: String = "%s_height.%s" +@export var height_map_pattern: String = "%s_height" ## Automatic PBR material generation ORM map pattern -@export var orm_map_pattern: String = "%s_orm.%s" +@export var orm_map_pattern: String = "%s_orm" +@export_subgroup("") ## Save automatically generated materials to disk, allowing reuse across [FuncGodotMap] nodes. ## [i]NOTE: Materials do not use the [member default_material] settings after saving.[/i] @export var save_generated_materials: bool = true +@export_group("") #endregion - -@export_category("UV Unwrap") - -## Texel size for UV2 unwrapping. -## Actual texel size is uv_unwrap_texel_size / [member inverse_scale_factor]. A ratio of 1/16 is usually a good place to start with -## (if inverse_scale_factor is 32, start with a uv_unwrap_texel_size of 2). -## Larger values will produce less detailed lightmaps. To conserve memory and filesize, use the largest value that still looks good. -@export var uv_unwrap_texel_size: float = 2.0 diff --git a/addons/func_godot/src/netradiant_custom/netradiant_custom_gamepack_config.gd b/addons/func_godot/src/netradiant_custom/netradiant_custom_gamepack_config.gd index ab33dc5a..e6377d29 100644 --- a/addons/func_godot/src/netradiant_custom/netradiant_custom_gamepack_config.gd +++ b/addons/func_godot/src/netradiant_custom/netradiant_custom_gamepack_config.gd @@ -27,6 +27,9 @@ enum NetRadiantCustomMapType { ## this should be the master FGD that contains them in [member FuncGodotFGDFile.base_fgd_files]. @export var fgd_file : FuncGodotFGDFile = preload("res://addons/func_godot/fgd/func_godot_fgd.tres") +## Toggles whether [FuncGodotFGDModelPointClass] resources will generate models from their [PackedScene] files. +@export var generate_model_point_class_models: bool = true + ## Collection of [NetRadiantCustomShader] resources for shader file generation. @export var netradiant_custom_shaders : Array[Resource] = [ preload("res://addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_clip.tres"), @@ -34,28 +37,30 @@ enum NetRadiantCustomMapType { preload("res://addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_origin.tres") ] -## Supported texture file types. -@export var texture_types : PackedStringArray = ["png", "jpg", "jpeg", "bmp", "tga"] - ## Supported model file types. @export var model_types : PackedStringArray = ["glb", "gltf", "obj"] ## Supported audio file types. @export var sound_types : PackedStringArray = ["wav", "ogg"] +## Quake map type NetRadiant will filter the map for, determining whether PatchDef entries are saved. +## [color=red][b]WARNING![/b][/color] Toggling this option may be destructive! +@export var map_type: NetRadiantCustomMapType = NetRadiantCustomMapType.QUAKE_3 + +@export_group("Textures") +## Supported texture file types. +@export var texture_types : PackedStringArray = ["png", "jpg", "jpeg", "bmp", "tga"] + ## Default scale of textures in NetRadiant Custom. @export var default_scale : String = "1.0" ## Clip texture path that gets applied to [i]weapclip[/i] and [i]nodraw[/i] shaders. -@export var clip_texture: String = "textures/special/clip" +@export var clip_texture: String = "textures/clip" ## Skip texture path that gets applied to [i]caulk[/i] and [i]nodrawnonsolid[/i] shaders. -@export var skip_texture: String = "textures/special/skip" - -## Quake map type NetRadiant will filter the map for, determining whether PatchDef entries are saved. -## [color=red][b]WARNING![/b][/color] Toggling this option may be destructive! -@export var map_type: NetRadiantCustomMapType = NetRadiantCustomMapType.QUAKE_1 +@export var skip_texture: String = "textures/skip" +@export_group("Build Menu") ## Variables to include in the exported gamepack's [code]default_build_menu.xml[/code].[br][br] ## Each [String] key defines a variable name, and its corresponding [String] value as the literal command-line string ## to execute in place of this variable identifier[br][br] @@ -312,5 +317,6 @@ func export_file() -> void: # FGD var export_fgd : FuncGodotFGDFile = fgd_file.duplicate() + export_fgd.generate_model_point_class_models = generate_model_point_class_models export_fgd.do_export_file(FuncGodotFGDFile.FuncGodotTargetMapEditors.NET_RADIANT_CUSTOM, gamepacks_folder + "/" + gamepack_name + ".game/" + base_game_path) print("NetRadiant Custom Gamepack export complete\n") diff --git a/addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd b/addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd index 3d7f0157..23fc1e69 100644 --- a/addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd +++ b/addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd @@ -31,7 +31,7 @@ enum GameConfigVersion { { "format": "Quake3" } ] -@export_category("Textures") +@export_group("Textures") ## Path to top level textures folder relative to the game path. Also referred to as materials in the latest versions of TrenchBroom. @export var textures_root_folder: String = "textures" @@ -42,7 +42,7 @@ enum GameConfigVersion { ## Palette path relative to your Game Path. Only needed for Quake WAD2 files. Half-Life WAD3 files contain the palettes within the texture information. @export var palette_path: String = "textures/palette.lmp" -@export_category("Entities") +@export_group("Entities") ## [FuncGodotFGDFile] resource to include with this game. If using multiple FGD File resources, ## this should be the master FGD File that contains them in [member FuncGodotFGDFile.base_fgd_files]. @@ -52,8 +52,11 @@ enum GameConfigVersion { ## See [url="https://trenchbroom.github.io/manual/latest/#game_configuration_files_entities"]TrenchBroom Manual Entity Configuration Information[/url] for more information. @export var entity_scale: String = "32" +## Toggles whether [FuncGodotFGDModelPointClass] resources will generate models from their [PackedScene] files. +@export var generate_model_point_class_models: bool = true + ## Arrays containing the [TrenchbroomTag] resource type. -@export_category("Tags") +@export_group("Tags") ## [TrenchbroomTag] resources that apply to brush entities. @export var brush_tags : Array[Resource] = [] @@ -65,12 +68,12 @@ enum GameConfigVersion { preload("res://addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres") ] -@export_category("Face Attributes") +@export_group("Face Attributes") ## Default scale of textures on new brushes and when UV scale is reset. @export var default_uv_scale : Vector2 = Vector2(1, 1) -@export_category("Compatibility") +@export_group("Compatibility") ## Game configuration format compatible with the version of TrenchBroom being used. @export var game_config_version: GameConfigVersion = GameConfigVersion.Latest @@ -229,6 +232,7 @@ func export_file() -> void: # FGD var export_fgd : FuncGodotFGDFile = fgd_file.duplicate() + export_fgd.generate_model_point_class_models = generate_model_point_class_models export_fgd.do_export_file(FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM, config_folder) print("TrenchBroom Game Config export complete\n") diff --git a/addons/func_godot/src/util/func_godot_local_config.gd b/addons/func_godot/src/util/func_godot_local_config.gd index f4af36d8..8faef147 100644 --- a/addons/func_godot/src/util/func_godot_local_config.gd +++ b/addons/func_godot/src/util/func_godot_local_config.gd @@ -55,18 +55,6 @@ const _CONFIG_PROPERTIES: Array[Dictionary] = [ "hint": PROPERTY_HINT_GLOBAL_DIR, "func_godot_type": PROPERTY.MAP_EDITOR_GAME_PATH }, - #{ - #"name": "game_path_models_folder", - #"usage": PROPERTY_USAGE_EDITOR, - #"type": TYPE_STRING, - #"func_godot_type": PROPERTY.GAME_PATH_MODELS_FOLDER - #}, - #{ - #"name": "default_inverse_scale_factor", - #"usage": PROPERTY_USAGE_EDITOR, - #"type": TYPE_FLOAT, - #"func_godot_type": PROPERTY.DEFAULT_INVERSE_SCALE - #} ] var _settings_dict: Dictionary @@ -117,9 +105,13 @@ func _get_config_property(name: StringName) -> Variant: ## Reload this system's configuration settings into the Local Config resource. func reload_func_godot_settings() -> void: _loaded = true - var path = _get_path() + var path = "user://func_godot_config.json" if not FileAccess.file_exists(path): - return + var application_name: String = ProjectSettings.get('application/config/name') + application_name = application_name.replace(" ", "_") + path = "user://" + application_name + "_FuncGodotConfig.json" + if not FileAccess.file_exists(path): + return var settings = FileAccess.get_file_as_string(path) _settings_dict = {} if not settings or settings.is_empty(): @@ -137,14 +129,9 @@ func _try_loading() -> void: func export_func_godot_settings() -> void: if _settings_dict.size() == 0: return - var path = _get_path() + var path = "user://func_godot_config.json" var file = FileAccess.open(path, FileAccess.WRITE) var json = JSON.stringify(_settings_dict) file.store_line(json) _loaded = false - print("Saved settings to ", path) - -func _get_path() -> String: - var application_name: String = ProjectSettings.get('application/config/name') - application_name = application_name.replace(" ", "_") - return 'user://' + application_name + '_FuncGodotConfig.json' + print("Saved settings to ", file.get_path_absolute()) diff --git a/addons/func_godot/src/util/func_godot_texture_loader.gd b/addons/func_godot/src/util/func_godot_texture_loader.gd deleted file mode 100644 index 00eacf14..00000000 --- a/addons/func_godot/src/util/func_godot_texture_loader.gd +++ /dev/null @@ -1,188 +0,0 @@ -class_name FuncGodotTextureLoader - -enum PBRSuffix { - ALBEDO, - NORMAL, - METALLIC, - ROUGHNESS, - EMISSION, - AO, - HEIGHT, - ORM -} - -# Suffix string / Godot enum / StandardMaterial3D property -const PBR_SUFFIX_NAMES: Dictionary = { - PBRSuffix.ALBEDO: 'albedo', - PBRSuffix.NORMAL: 'normal', - PBRSuffix.METALLIC: 'metallic', - PBRSuffix.ROUGHNESS: 'roughness', - PBRSuffix.EMISSION: 'emission', - PBRSuffix.AO: 'ao', - PBRSuffix.HEIGHT: 'height', - PBRSuffix.ORM: 'orm' -} - -const PBR_SUFFIX_PATTERNS: Dictionary = { - PBRSuffix.ALBEDO: '%s_albedo.%s', - PBRSuffix.NORMAL: '%s_normal.%s', - PBRSuffix.METALLIC: '%s_metallic.%s', - PBRSuffix.ROUGHNESS: '%s_roughness.%s', - PBRSuffix.EMISSION: '%s_emission.%s', - PBRSuffix.AO: '%s_ao.%s', - PBRSuffix.HEIGHT: '%s_height.%s', - PBRSuffix.ORM: '%s_orm.%s' -} - -var PBR_SUFFIX_TEXTURES: Dictionary = { - PBRSuffix.ALBEDO: StandardMaterial3D.TEXTURE_ALBEDO, - PBRSuffix.NORMAL: StandardMaterial3D.TEXTURE_NORMAL, - PBRSuffix.METALLIC: StandardMaterial3D.TEXTURE_METALLIC, - PBRSuffix.ROUGHNESS: StandardMaterial3D.TEXTURE_ROUGHNESS, - PBRSuffix.EMISSION: StandardMaterial3D.TEXTURE_EMISSION, - PBRSuffix.AO: StandardMaterial3D.TEXTURE_AMBIENT_OCCLUSION, - PBRSuffix.HEIGHT: StandardMaterial3D.TEXTURE_HEIGHTMAP, - PBRSuffix.ORM: ORMMaterial3D.TEXTURE_ORM -} - -const PBR_SUFFIX_PROPERTIES: Dictionary = { - PBRSuffix.NORMAL: 'normal_enabled', - PBRSuffix.EMISSION: 'emission_enabled', - PBRSuffix.AO: 'ao_enabled', - PBRSuffix.HEIGHT: 'heightmap_enabled', -} - -var map_settings: FuncGodotMapSettings = FuncGodotMapSettings.new() -var texture_wad_resources: Array = [] - -# Overrides -func _init(new_map_settings: FuncGodotMapSettings) -> void: - map_settings = new_map_settings - load_texture_wad_resources() - -# Business Logic -func load_texture_wad_resources() -> void: - texture_wad_resources.clear() - for texture_wad in map_settings.texture_wads: - if texture_wad and not texture_wad in texture_wad_resources: - texture_wad_resources.append(texture_wad) - -func load_textures(texture_list: Array) -> Dictionary: - var texture_dict: Dictionary = {} - for texture_name in texture_list: - texture_dict[texture_name] = load_texture(texture_name) - return texture_dict - -func load_texture(texture_name: String) -> Texture2D: - # Load albedo texture if it exists - for texture_extension in map_settings.texture_file_extensions: - var texture_path: String = "%s/%s.%s" % [map_settings.base_texture_dir, texture_name, texture_extension] - if ResourceLoader.exists(texture_path, "Texture2D") or ResourceLoader.exists(texture_path + ".import", "Texture2D"): - return load(texture_path) as Texture2D - - var texture_name_lower: String = texture_name.to_lower() - for texture_wad in texture_wad_resources: - if texture_name_lower in texture_wad.textures: - return texture_wad.textures[texture_name_lower] - - return load("res://addons/func_godot/textures/default_texture.png") as Texture2D - -func create_materials(texture_list: Array) -> Dictionary: - var texture_materials: Dictionary = {} - #prints("TEXLI", texture_list) - for texture in texture_list: - texture_materials[texture] = create_material(texture) - return texture_materials - -func create_material(texture_name: String) -> Material: - # Autoload material if it exists - var material_dict: Dictionary = {} - - var material_path: String = "%s/%s.%s" % [map_settings.base_texture_dir, texture_name, map_settings.material_file_extension] - if not material_path in material_dict and (FileAccess.file_exists(material_path) or FileAccess.file_exists(material_path + ".remap")): - var loaded_material: Material = load(material_path) - if loaded_material: - material_dict[material_path] = loaded_material - - # If material already exists, use it - if material_path in material_dict: - return material_dict[material_path] - - var material: Material = null - - if map_settings.default_material: - material = map_settings.default_material.duplicate() - else: - material = StandardMaterial3D.new() - var texture: Texture2D = load_texture(texture_name) - if not texture: - return material - - if material is StandardMaterial3D: - material.set_texture(StandardMaterial3D.TEXTURE_ALBEDO, texture) - elif material is ShaderMaterial && map_settings.default_material_albedo_uniform != "": - material.set_shader_parameter(map_settings.default_material_albedo_uniform, texture) - elif material is ORMMaterial3D: - material.set_texture(ORMMaterial3D.TEXTURE_ALBEDO, texture) - - var pbr_textures : Dictionary = get_pbr_textures(texture_name) - - for pbr_suffix in PBRSuffix.values(): - var suffix: int = pbr_suffix - var tex: Texture2D = pbr_textures[suffix] - if tex: - if material is ShaderMaterial: - material = StandardMaterial3D.new() - material.set_texture(StandardMaterial3D.TEXTURE_ALBEDO, texture) - var enable_prop: String = PBR_SUFFIX_PROPERTIES[suffix] if suffix in PBR_SUFFIX_PROPERTIES else "" - if(enable_prop != ""): - material.set(enable_prop, true) - material.set_texture(PBR_SUFFIX_TEXTURES[suffix], tex) - - material_dict[material_path] = material - - if (map_settings.save_generated_materials and material - and texture_name != map_settings.clip_texture - and texture_name != map_settings.skip_texture - and texture_name != map_settings.origin_texture - and texture.resource_path != "res://addons/func_godot/textures/default_texture.png"): - ResourceSaver.save(material, material_path) - - return material - -# PBR texture fetching -func get_pbr_suffix_pattern(suffix: int) -> String: - if not suffix in PBR_SUFFIX_NAMES: - return '' - - var pattern_setting: String = "%s_map_pattern" % [PBR_SUFFIX_NAMES[suffix]] - if pattern_setting in map_settings: - return map_settings.get(pattern_setting) - - return PBR_SUFFIX_PATTERNS[suffix] - -func get_pbr_texture(texture: String, suffix: PBRSuffix) -> Texture2D: - var texture_comps: PackedStringArray = texture.split('/') - if texture_comps.size() == 0: - return null - - for texture_extension in map_settings.texture_file_extensions: - var path: String = "%s/%s/%s" % [ - map_settings.base_texture_dir, - '/'.join(texture_comps), - get_pbr_suffix_pattern(suffix) % [ - texture_comps[-1], - texture_extension - ] - ] - - if(FileAccess.file_exists(path)): - return load(path) as Texture2D - - return null - -func get_pbr_textures(texture_name: String) -> Dictionary: - var pbr_textures: Dictionary = {} - for pbr_suffix in PBRSuffix.values(): - pbr_textures[pbr_suffix] = get_pbr_texture(texture_name, pbr_suffix) - return pbr_textures diff --git a/addons/func_godot/src/util/func_godot_texture_loader.gd.uid b/addons/func_godot/src/util/func_godot_texture_loader.gd.uid deleted file mode 100644 index 08ed5bfb..00000000 --- a/addons/func_godot/src/util/func_godot_texture_loader.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://c0r8ajf4k061i diff --git a/addons/func_godot/src/util/func_godot_util.gd b/addons/func_godot/src/util/func_godot_util.gd index be6b5752..f1a006be 100644 --- a/addons/func_godot/src/util/func_godot_util.gd +++ b/addons/func_godot/src/util/func_godot_util.gd @@ -80,16 +80,33 @@ const _pbr_textures: PackedInt32Array = [ StandardMaterial3D.TEXTURE_EMISSION, StandardMaterial3D.TEXTURE_AMBIENT_OCCLUSION, StandardMaterial3D.TEXTURE_HEIGHTMAP, - ORMMaterial3D.TEXTURE_ORM + ORMMaterial3D.TEXTURE_ORM, ] +# Used during auto-PBR processing. Must match the _pbr_textures order. +# -1 means the feature is permanantly enabled. +const _pbr_features: PackedInt32Array = [ + -1, + BaseMaterial3D.FEATURE_NORMAL_MAPPING, + -1, + -1, + BaseMaterial3D.FEATURE_EMISSION, + BaseMaterial3D.FEATURE_AMBIENT_OCCLUSION, + BaseMaterial3D.FEATURE_HEIGHT_MAPPING, + -1, +] + ## Searches for a Texture2D within the base texture directory or the WAD files added to map settings. ## If not found, a default texture is returned. static func load_texture(texture_name: String, wad_resources: Array[QuakeWadFile], map_settings: FuncGodotMapSettings) -> Texture2D: for texture_file_extension in map_settings.texture_file_extensions: var texture_path: String = map_settings.base_texture_dir.path_join(texture_name + "." + texture_file_extension) if ResourceLoader.exists(texture_path): - return load(texture_path) + var texture_file = load(texture_path) + if texture_file is Texture2D: + return texture_file + else: + printerr("Error: Texture load failed! (%s) not a valid Texture2D resource", texture_path) var texture_name_lower: String = texture_name.to_lower() for wad in wad_resources: @@ -131,8 +148,8 @@ static func filter_face(texture: String, map_settings: FuncGodotMapSettings) -> static func build_base_material(map_settings: FuncGodotMapSettings, material: BaseMaterial3D, texture: String) -> void: var path: String = map_settings.base_texture_dir.path_join(texture) # Check if there is a subfolder with our PBR textures - if DirAccess.open(path.path_join(path)): - path = path.path_join(path) + if DirAccess.open(path): + path = path.path_join(texture) var pbr_suffixes: PackedStringArray = [ map_settings.albedo_map_pattern, @@ -145,12 +162,33 @@ static func build_base_material(map_settings: FuncGodotMapSettings, material: Ba map_settings.orm_map_pattern, ] - for texture_file_extension in map_settings.texture_file_extensions: - for i in pbr_suffixes.size(): - if not pbr_suffixes[i].is_empty(): - var pbr: String = pbr_suffixes[i] % [path, texture_file_extension] - if ResourceLoader.exists(pbr): - material.set_texture(_pbr_textures[i], load(pbr)) + for i in pbr_suffixes.size(): + if not pbr_suffixes[i].is_empty(): + var pbr: String = pbr_suffixes[i] + var token: int = pbr.find("%s", 0) + if token != -1: + if pbr.find("%s", token + 1) != -1: + token = 2 + else: + token = 1 + + if token < 1: + printerr("No string replacement tokens found in auto-PBR pattern \'" + pbr + "\'! Must have at least one instance of \'%s\' per pattern.") + continue + + if token > 0: + for texture_file_extension in map_settings.texture_file_extensions: + if token > 1: + pbr = pbr_suffixes[i] % [path, texture_file_extension] + else: + pbr = pbr_suffixes[i] % [path] + pbr += "." + texture_file_extension + if ResourceLoader.exists(pbr): + print(pbr) + if _pbr_features[i] > -1: + material.set_feature(_pbr_features[i], true) + material.set_texture(_pbr_textures[i], load(pbr)) + break ## Builds both materials and sizes dictionaries for use in the geometry generation step of the build process. ## Both dictionaries use texture names as keys. The materials dictionary uses [Material] as values, @@ -202,7 +240,7 @@ static func build_texture_map(entity_data: Array[FuncGodotData.EntityData], map_ # Material generation elif map_settings.default_material: - var material = map_settings.default_material.duplicate(true) + var material = map_settings.default_material.duplicate(false) var texture: Texture2D = load_texture(texture_name, wad_resources, map_settings) texture_sizes[texture_name] = texture.get_size() @@ -211,12 +249,29 @@ static func build_texture_map(entity_data: Array[FuncGodotData.EntityData], map_ build_base_material(map_settings, material, texture_name) elif material is ShaderMaterial: material.set_shader_parameter(map_settings.default_material_albedo_uniform, texture) + var path: String = map_settings.base_texture_dir + for uniform in map_settings.shader_material_uniform_map_patterns.keys(): + if map_settings.shader_material_uniform_map_patterns[uniform].find("%s") < 0: + printerr("No string replacement tokens fuond in ShaderMaterial uniform map pattern \'" + map_settings.shader_material_uniform_map_patterns[uniform] + "\'! Must have one instance of \'%s\' per pattern.") + continue + for texture_file_extension in map_settings.texture_file_extensions: + var uniform_texture_path: String = map_settings.shader_material_uniform_map_patterns[uniform] % [texture_name] + "." + texture_file_extension + uniform_texture_path = path.path_join(uniform_texture_path) + if ResourceLoader.exists(uniform_texture_path): + material.set_shader_parameter(uniform, load(uniform_texture_path)) + break if (map_settings.save_generated_materials and material and texture_name != map_settings.clip_texture and texture_name != map_settings.skip_texture and texture_name != map_settings.origin_texture and texture.resource_path != default_texture_path): + # Make sure our material directory exists + var dir := DirAccess.open(material_path.get_base_dir()) + if not dir: + dir = DirAccess.open("res://") + dir.make_dir_recursive(material_path.get_base_dir().trim_prefix("res://")) + # Save the new material ResourceSaver.save(material, material_path) texture_materials[texture_name] = material @@ -232,30 +287,30 @@ static func build_texture_map(entity_data: Array[FuncGodotData.EntityData], map_ ## Returns UV coordinate calculated from the Valve 220 UV format. static func get_valve_uv(vertex: Vector3, u_axis: Vector3, v_axis: Vector3, uv_basis := Transform2D.IDENTITY, texture_size := Vector2.ONE) -> Vector2: var uv := Vector2(u_axis.dot(vertex), v_axis.dot(vertex)) - uv += (uv_basis.origin * uv_basis.get_scale()) - uv.x /= uv_basis.x.x - uv.y /= uv_basis.y.y + var scale := Vector2(uv_basis.x.x, uv_basis.y.y) + uv += (uv_basis.origin * scale) + uv /= scale; uv.x /= texture_size.x uv.y /= texture_size.y return uv ## Returns UV coordinate calculated from the original id Standard UV format. -static func get_quake_uv(vertex: Vector3, normal: Vector3, uv_basis := Transform2D.IDENTITY, texture_size := Vector2.ONE) -> Vector2: +static func get_quake_uv(vertex: Vector3, normal: Vector3, uv_in := Transform2D.IDENTITY, texture_size := Vector2.ONE) -> Vector2: + var uv_out: Vector2 var nx := absf(normal.dot(Vector3.RIGHT)) var ny := absf(normal.dot(Vector3.UP)) var nz := absf(normal.dot(Vector3.FORWARD)) - var uv: Vector2 if ny >= nx and ny >= nz: - uv = Vector2(vertex.x, -vertex.z) + uv_out = Vector2(vertex.x, -vertex.z) elif nx >= ny and nx >= nz: - uv = Vector2(vertex.y, -vertex.z) + uv_out = Vector2(vertex.y, -vertex.z) else: - uv = Vector2(vertex.x, vertex.y) + uv_out = Vector2(vertex.x, vertex.y) - var uv_out := uv.rotated(uv_basis.get_rotation()) - uv_out /= uv_basis.get_scale() - uv_out += uv_basis.origin + uv_out = uv_out.rotated(uv_in.get_rotation()) + uv_out /= uv_in.get_scale() + uv_out += uv_in.origin uv_out /= texture_size return uv_out @@ -322,10 +377,10 @@ static func get_face_tangent(face: FuncGodotData.FaceData) -> PackedFloat32Array #region MESH -static func smooth_mesh_by_angle(mesh: ArrayMesh, angle_deg: float = 89.0) -> Mesh: +static func smooth_mesh_by_angle(mesh: ArrayMesh, angle_deg: float = 89.0) -> ArrayMesh: if not mesh: push_error("Need a source mesh to smooth") - return + return null var angle: float = deg_to_rad(clampf(angle_deg, 0.0, 360.0)) diff --git a/addons/func_godot/textures/special/clip.png b/addons/func_godot/textures/clip.png similarity index 100% rename from addons/func_godot/textures/special/clip.png rename to addons/func_godot/textures/clip.png diff --git a/addons/func_godot/textures/special/clip.png.import b/addons/func_godot/textures/clip.png.import similarity index 59% rename from addons/func_godot/textures/special/clip.png.import rename to addons/func_godot/textures/clip.png.import index a97dba7c..1ddc0acb 100644 --- a/addons/func_godot/textures/special/clip.png.import +++ b/addons/func_godot/textures/clip.png.import @@ -3,21 +3,23 @@ importer="texture" type="CompressedTexture2D" uid="uid://dhmu0toe1itnr" -path="res://.godot/imported/clip.png-508a86fa3876d8467d5c9af6188a34df.ctex" +path="res://.godot/imported/clip.png-747f19bfc6fe499e254d63eeccc3bbe4.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://addons/func_godot/textures/special/clip.png" -dest_files=["res://.godot/imported/clip.png-508a86fa3876d8467d5c9af6188a34df.ctex"] +source_file="res://addons/func_godot/textures/clip.png" +dest_files=["res://.godot/imported/clip.png-747f19bfc6fe499e254d63eeccc3bbe4.ctex"] [params] compress/mode=3 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/addons/func_godot/textures/default_texture.png.import b/addons/func_godot/textures/default_texture.png.import index 187d2527..c45ce3a5 100644 --- a/addons/func_godot/textures/default_texture.png.import +++ b/addons/func_godot/textures/default_texture.png.import @@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/default_texture.png-145fbd5fef7f63ace60797fec compress/mode=3 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/addons/func_godot/textures/special/origin.png b/addons/func_godot/textures/origin.png similarity index 100% rename from addons/func_godot/textures/special/origin.png rename to addons/func_godot/textures/origin.png diff --git a/addons/func_godot/textures/special/origin.png.import b/addons/func_godot/textures/origin.png.import similarity index 58% rename from addons/func_godot/textures/special/origin.png.import rename to addons/func_godot/textures/origin.png.import index ec4df623..52d1e8b9 100644 --- a/addons/func_godot/textures/special/origin.png.import +++ b/addons/func_godot/textures/origin.png.import @@ -3,21 +3,23 @@ importer="texture" type="CompressedTexture2D" uid="uid://dutip72dl002r" -path="res://.godot/imported/origin.png-85b62dd151467f05fa8f98ed6d2927d0.ctex" +path="res://.godot/imported/origin.png-501c9242087fbbeb03d876a682f0832c.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://addons/func_godot/textures/special/origin.png" -dest_files=["res://.godot/imported/origin.png-85b62dd151467f05fa8f98ed6d2927d0.ctex"] +source_file="res://addons/func_godot/textures/origin.png" +dest_files=["res://.godot/imported/origin.png-501c9242087fbbeb03d876a682f0832c.ctex"] [params] compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/addons/func_godot/textures/special/skip.png b/addons/func_godot/textures/skip.png similarity index 100% rename from addons/func_godot/textures/special/skip.png rename to addons/func_godot/textures/skip.png diff --git a/addons/func_godot/textures/special/skip.png.import b/addons/func_godot/textures/skip.png.import similarity index 59% rename from addons/func_godot/textures/special/skip.png.import rename to addons/func_godot/textures/skip.png.import index b9a95b45..a1bbac1e 100644 --- a/addons/func_godot/textures/special/skip.png.import +++ b/addons/func_godot/textures/skip.png.import @@ -3,21 +3,23 @@ importer="texture" type="CompressedTexture2D" uid="uid://bk5oo263y3u7w" -path="res://.godot/imported/skip.png-d741e3eb75a5e289907774cb73d93931.ctex" +path="res://.godot/imported/skip.png-b8ce29eeb9f4be76c300a81fd41322fa.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://addons/func_godot/textures/special/skip.png" -dest_files=["res://.godot/imported/skip.png-d741e3eb75a5e289907774cb73d93931.ctex"] +source_file="res://addons/func_godot/textures/skip.png" +dest_files=["res://.godot/imported/skip.png-b8ce29eeb9f4be76c300a81fd41322fa.ctex"] [params] compress/mode=3 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/textures/Manual/Wall_Backrooms_003.tres b/textures/Manual/Wall_Backrooms_003.tres new file mode 100644 index 00000000..6d289a61 --- /dev/null +++ b/textures/Manual/Wall_Backrooms_003.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://da6s6fqts8iyk"] + +[ext_resource type="Texture2D" uid="uid://bxaiak5nw5pqe" path="res://textures/Manual/Wall_Backrooms_003.png" id="1_o5f08"] + +[resource] +albedo_texture = ExtResource("1_o5f08") +metallic_specular = 0.0 +texture_filter = 2 diff --git a/textures/special/clip.tres b/textures/special/clip.tres new file mode 100644 index 00000000..8bb91575 --- /dev/null +++ b/textures/special/clip.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://jniemn5xdkwo"] + +[ext_resource type="Texture2D" uid="uid://d0j44atq076b5" path="res://textures/special/clip.png" id="1_kxuq7"] + +[resource] +albedo_texture = ExtResource("1_kxuq7") +metallic_specular = 0.0 +texture_filter = 2