├── fgd
├── models
│ ├── .gdignore
│ ├── actor_marsfrog.glb
│ ├── map_obj_camera.glb
│ └── map_obj_camera_active.glb
├── base
│ ├── targetname_base.tres
│ ├── globalname_base.tres
│ ├── target_base.tres
│ ├── trigger_base.tres
│ ├── actor_base.tres
│ ├── func_base.tres
│ └── light_base.tres
├── solid
│ ├── funcs
│ │ ├── func_detail.tres
│ │ ├── func_geo.tres
│ │ ├── func_detail_illusionary.tres
│ │ ├── func_illusionary.tres
│ │ └── func_move.tres
│ └── triggers
│ │ └── trigger_area.tres
├── fgd_main.tres
├── fgd_point.tres
├── point
│ ├── lights
│ │ ├── light_omni.tres
│ │ └── light_spot.tres
│ ├── actors
│ │ └── actor_marsfrog.tres
│ └── info_camera.tres
├── fgd_solid.tres
├── game_cfg.tres
└── fgd_base.tres
├── maps
├── autosave
│ └── .gdignore
├── example_basic.map.import
└── map_settings.tres
├── game_manager.gd.uid
├── entities
├── actors
│ ├── actor.gd.uid
│ ├── marsfrog
│ │ ├── marsfrog.gd.uid
│ │ ├── marsfrog.bin
│ │ ├── marsfrog.glb
│ │ ├── marsfrog_alb.png
│ │ ├── marsfrog_mat.tres
│ │ ├── marsfrog.tscn
│ │ ├── marsfrog.gd
│ │ ├── marsfrog_alb.png.import
│ │ └── marsfrog.glb.import
│ └── actor.gd
├── info_camera.gd.uid
├── funcs
│ ├── func_move.gd.uid
│ └── func_move.gd
├── lights
│ ├── light_base.gd.uid
│ ├── light_omni.gd.uid
│ ├── light_spot.gd.uid
│ ├── light_omni.gd
│ ├── light_spot.gd
│ └── light_base.gd
├── triggers
│ ├── trigger_area.gd.uid
│ └── trigger_area.gd
└── info_camera.gd
├── addons
└── func_godot
│ ├── src
│ ├── core
│ │ ├── data.gd.uid
│ │ ├── parser.gd.uid
│ │ ├── entity_assembler.gd.uid
│ │ └── geometry_generator.gd.uid
│ ├── func_godot_plugin.gd.uid
│ ├── import
│ │ ├── quake_wad_file.gd.uid
│ │ ├── quake_map_file.gd.uid
│ │ ├── quake_palette_file.gd.uid
│ │ ├── quake_map_import_plugin.gd.uid
│ │ ├── quake_wad_import_plugin.gd.uid
│ │ ├── quake_palette_import_plugin.gd.uid
│ │ ├── quake_palette_file.gd
│ │ ├── quake_map_file.gd
│ │ ├── quake_wad_file.gd
│ │ ├── quake_map_import_plugin.gd
│ │ ├── quake_palette_import_plugin.gd
│ │ └── quake_wad_import_plugin.gd
│ ├── map
│ │ ├── func_godot_map.gd.uid
│ │ ├── func_godot_map_settings.gd.uid
│ │ ├── func_godot_map.gd
│ │ └── func_godot_map_settings.gd
│ ├── util
│ │ ├── func_godot_util.gd.uid
│ │ ├── func_godot_local_config.gd.uid
│ │ └── func_godot_local_config.gd
│ ├── fgd
│ │ ├── func_godot_fgd_file.gd.uid
│ │ ├── func_godot_fgd_base_class.gd.uid
│ │ ├── func_godot_fgd_point_class.gd.uid
│ │ ├── func_godot_fgd_solid_class.gd.uid
│ │ ├── func_godot_fgd_entity_class.gd.uid
│ │ ├── func_godot_fgd_model_point_class.gd.uid
│ │ ├── func_godot_fgd_point_class_display_descriptor.gd.uid
│ │ ├── func_godot_fgd_base_class.gd
│ │ ├── func_godot_fgd_point_class_display_descriptor.gd
│ │ ├── func_godot_fgd_point_class.gd
│ │ ├── func_godot_fgd_file.gd
│ │ ├── func_godot_fgd_solid_class.gd
│ │ └── func_godot_fgd_model_point_class.gd
│ ├── trenchbroom
│ │ ├── trenchbroom_tag.gd.uid
│ │ ├── trenchbroom_game_config.gd.uid
│ │ └── trenchbroom_tag.gd
│ ├── netradiant_custom
│ │ ├── netradiant_custom_shader.gd.uid
│ │ ├── netradiant_custom_gamepack_config.gd.uid
│ │ └── netradiant_custom_shader.gd
│ └── func_godot_plugin.gd
│ ├── icon.png
│ ├── icon32.png
│ ├── palette.lmp
│ ├── textures
│ ├── clip.png
│ ├── skip.png
│ ├── origin.png
│ ├── default_texture.png
│ ├── default_material.tres
│ ├── clip.png.import
│ ├── skip.png.import
│ ├── origin.png.import
│ └── default_texture.png.import
│ ├── plugin.cfg
│ ├── func_godot_local_config.tres
│ ├── game_config
│ ├── trenchbroom
│ │ ├── tb_face_tag_clip.tres
│ │ ├── tb_face_tag_skip.tres
│ │ ├── tb_face_tag_origin.tres
│ │ ├── tb_brush_tag_func.tres
│ │ ├── tb_brush_tag_trigger.tres
│ │ └── func_godot_tb_game_config.tres
│ └── netradiant_custom
│ │ ├── netradiant_custom_shader_clip.tres
│ │ ├── netradiant_custom_shader_skip.tres
│ │ ├── netradiant_custom_shader_origin.tres
│ │ └── func_godot_netradiant_custom_gamepack_config.tres
│ ├── palette.lmp.import
│ ├── fgd
│ ├── phong_base.tres
│ ├── vertex_merge_distance_base.tres
│ ├── worldspawn.tres
│ ├── func_detail_illusionary.tres
│ ├── func_detail.tres
│ ├── func_geo.tres
│ ├── func_illusionary.tres
│ └── func_godot_fgd.tres
│ ├── func_godot_default_map_settings.tres
│ ├── icon.png.import
│ ├── icon32.png.import
│ ├── LICENSE
│ ├── icon.svg.import
│ └── icons
│ ├── icon_slipgate.svg.import
│ ├── icon_godambler.svg.import
│ ├── icon_quake_file.svg.import
│ ├── icon_slipgate3d.svg.import
│ ├── icon_godambler3d.svg.import
│ ├── icon_godot_ranger.svg.import
│ ├── icon_godot_ranger3d.svg.import
│ ├── icon_slipgate.svg
│ ├── icon_slipgate3d.svg
│ ├── icon_quake_file.svg
│ └── icon_godambler.svg
├── .gitignore
├── .gitattributes
├── textures
├── palette.lmp
├── special
│ ├── clip.png
│ ├── skip.png
│ ├── origin.png
│ ├── trigger.png
│ ├── clip.png.import
│ ├── skip.png.import
│ ├── origin.png.import
│ └── trigger.png.import
├── mars
│ ├── mars_cave0.png
│ ├── mars_sand0.png
│ ├── mars_sand1.png
│ ├── mars_cliff0.png
│ ├── mars_cave0_normal.png
│ ├── mars_cliff0_normal.png
│ ├── mars_sand0_normal.png
│ ├── mars_sand1_normal.png
│ ├── mars_sand1.png.import
│ ├── mars_sand1_normal.png.import
│ ├── mars_cave0.png.import
│ ├── mars_sand0.png.import
│ ├── mars_cliff0.png.import
│ ├── mars_cave0_normal.png.import
│ ├── mars_sand0_normal.png.import
│ └── mars_cliff0_normal.png.import
└── palette.lmp.import
├── README.md
├── materials
└── mars
│ ├── mars_cave0.tres
│ ├── mars_cliff0.tres
│ └── mars_sand0.tres
├── icon.svg.import
├── project.godot
└── game_manager.gd
/fgd/models/.gdignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/maps/autosave/.gdignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/game_manager.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ddoex1ohlmirm
2 |
--------------------------------------------------------------------------------
/entities/actors/actor.gd.uid:
--------------------------------------------------------------------------------
1 | uid://i43xu6polhtc
2 |
--------------------------------------------------------------------------------
/entities/info_camera.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cm1d60bvyoko4
2 |
--------------------------------------------------------------------------------
/entities/funcs/func_move.gd.uid:
--------------------------------------------------------------------------------
1 | uid://drubv8qcibmw0
2 |
--------------------------------------------------------------------------------
/entities/lights/light_base.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cbw581br1a8es
2 |
--------------------------------------------------------------------------------
/entities/lights/light_omni.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dnv2pepfq32np
2 |
--------------------------------------------------------------------------------
/entities/lights/light_spot.gd.uid:
--------------------------------------------------------------------------------
1 | uid://c3mfo5emund0x
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/core/data.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cqye8dehq4c7q
2 |
--------------------------------------------------------------------------------
/entities/triggers/trigger_area.gd.uid:
--------------------------------------------------------------------------------
1 | uid://43spl6muc28v
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/core/parser.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dflet6p5hbqts
2 |
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bkua4ygsumdod
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Godot 4+ specific ignores
2 | .godot/
3 | maps/autosave/*.map
--------------------------------------------------------------------------------
/addons/func_godot/src/func_godot_plugin.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bqy3tr83l7di
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_wad_file.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cij36hpqc46c
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/map/func_godot_map.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cwu5cf7a0awcd
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/util/func_godot_util.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bursmx2g1betd
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/core/entity_assembler.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dh73tfvwp7kr6
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/core/geometry_generator.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b1yg28xbyno7v
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_file.gd.uid:
--------------------------------------------------------------------------------
1 | uid://drlmgulwbjwqu
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_map_file.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cxvwf50mehesf
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_palette_file.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dqhjx7jjbif5d
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_base_class.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ck575aqs1sbrb
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_point_class.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cxsqwtsqd8w33
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd.uid:
--------------------------------------------------------------------------------
1 | uid://5cow84q03m6a
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_map_import_plugin.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dnsj08ot32vpc
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_wad_import_plugin.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ridgf32rxg6s
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/map/func_godot_map_settings.gd.uid:
--------------------------------------------------------------------------------
1 | uid://38q6k0ctahjn
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/trenchbroom/trenchbroom_tag.gd.uid:
--------------------------------------------------------------------------------
1 | uid://b66qdknwqpfup
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/util/func_godot_local_config.gd.uid:
--------------------------------------------------------------------------------
1 | uid://xsjnhahhyein
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_entity_class.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cgkrrgcimlr8y
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd.uid:
--------------------------------------------------------------------------------
1 | uid://ldfqjtq0br35
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_palette_import_plugin.gd.uid:
--------------------------------------------------------------------------------
1 | uid://c6k7hftart3u3
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd.uid:
--------------------------------------------------------------------------------
1 | uid://cx44c4vnq8bt5
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/netradiant_custom/netradiant_custom_shader.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dn86acprv4e86
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Normalize EOL for all files that Git considers text files.
2 | * text=auto eol=lf
3 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd.uid:
--------------------------------------------------------------------------------
1 | uid://d1nwwgcrner8b
2 |
--------------------------------------------------------------------------------
/addons/func_godot/src/netradiant_custom/netradiant_custom_gamepack_config.gd.uid:
--------------------------------------------------------------------------------
1 | uid://dfhj3me2g5j0l
2 |
--------------------------------------------------------------------------------
/textures/palette.lmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/palette.lmp
--------------------------------------------------------------------------------
/addons/func_godot/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/addons/func_godot/icon.png
--------------------------------------------------------------------------------
/textures/special/clip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/special/clip.png
--------------------------------------------------------------------------------
/textures/special/skip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/special/skip.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Example FuncGodot project that shows how you might design entities for use in the TrenchBroom to Godot pipeline.
2 |
--------------------------------------------------------------------------------
/addons/func_godot/icon32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/addons/func_godot/icon32.png
--------------------------------------------------------------------------------
/textures/mars/mars_cave0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/mars/mars_cave0.png
--------------------------------------------------------------------------------
/textures/mars/mars_sand0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/mars/mars_sand0.png
--------------------------------------------------------------------------------
/textures/mars/mars_sand1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/mars/mars_sand1.png
--------------------------------------------------------------------------------
/textures/special/origin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/special/origin.png
--------------------------------------------------------------------------------
/textures/special/trigger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/special/trigger.png
--------------------------------------------------------------------------------
/addons/func_godot/palette.lmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/addons/func_godot/palette.lmp
--------------------------------------------------------------------------------
/fgd/models/actor_marsfrog.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/fgd/models/actor_marsfrog.glb
--------------------------------------------------------------------------------
/fgd/models/map_obj_camera.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/fgd/models/map_obj_camera.glb
--------------------------------------------------------------------------------
/textures/mars/mars_cliff0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/mars/mars_cliff0.png
--------------------------------------------------------------------------------
/addons/func_godot/textures/clip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/addons/func_godot/textures/clip.png
--------------------------------------------------------------------------------
/addons/func_godot/textures/skip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/addons/func_godot/textures/skip.png
--------------------------------------------------------------------------------
/fgd/models/map_obj_camera_active.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/fgd/models/map_obj_camera_active.glb
--------------------------------------------------------------------------------
/textures/mars/mars_cave0_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/mars/mars_cave0_normal.png
--------------------------------------------------------------------------------
/textures/mars/mars_cliff0_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/mars/mars_cliff0_normal.png
--------------------------------------------------------------------------------
/textures/mars/mars_sand0_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/mars/mars_sand0_normal.png
--------------------------------------------------------------------------------
/textures/mars/mars_sand1_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/textures/mars/mars_sand1_normal.png
--------------------------------------------------------------------------------
/addons/func_godot/textures/origin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/addons/func_godot/textures/origin.png
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/entities/actors/marsfrog/marsfrog.bin
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/entities/actors/marsfrog/marsfrog.glb
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog_alb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/entities/actors/marsfrog/marsfrog_alb.png
--------------------------------------------------------------------------------
/addons/func_godot/textures/default_texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/func-godot/func_godot_example_basic/HEAD/addons/func_godot/textures/default_texture.png
--------------------------------------------------------------------------------
/entities/lights/light_omni.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name LightOmni
3 | extends OmniLight3D
4 |
5 | func _func_godot_apply_properties(props: Dictionary) -> void:
6 | LightBase._func_godot_apply_properties(self, props)
7 | omni_range = (props["range"] as float) * GameManager.INVERSE_SCALE
8 |
--------------------------------------------------------------------------------
/addons/func_godot/plugin.cfg:
--------------------------------------------------------------------------------
1 | [plugin]
2 |
3 | name="FuncGodot"
4 | description="Quake .map and Half-Life .vmf file support for Godot."
5 | author="Josh Palmer, Hannah Crawford, Emberlynn Bland, Tim Maccabe, Vera Lux, func_godot Community"
6 | version="2025.11"
7 | script="src/func_godot_plugin.gd"
8 |
--------------------------------------------------------------------------------
/entities/lights/light_spot.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name LightSpot
3 | extends SpotLight3D
4 |
5 | func _func_godot_apply_properties(props: Dictionary) -> void:
6 | LightBase._func_godot_apply_properties(self, props)
7 | spot_angle = props["angle"] as float
8 | spot_range = (props["range"] as float) * GameManager.INVERSE_SCALE
9 |
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog_mat.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://cxi8hlnm8hb80"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://byls0u3nbmhwk" path="res://entities/actors/marsfrog/marsfrog_alb.png" id="1_sn81d"]
4 |
5 | [resource]
6 | transparency = 4
7 | albedo_texture = ExtResource("1_sn81d")
8 |
--------------------------------------------------------------------------------
/addons/func_godot/func_godot_local_config.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotLocalConfig" load_steps=2 format=3 uid="uid://bqjt7nyekxgog"]
2 |
3 | [ext_resource type="Script" uid="uid://xsjnhahhyein" path="res://addons/func_godot/src/util/func_godot_local_config.gd" id="1_g8kqj"]
4 |
5 | [resource]
6 | script = ExtResource("1_g8kqj")
7 |
--------------------------------------------------------------------------------
/addons/func_godot/textures/default_material.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://cvex6toty8yn7"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://cyg2snr1w5xw5" path="res://addons/func_godot/textures/default_texture.png" id="1_ncj77"]
4 |
5 | [resource]
6 | albedo_texture = ExtResource("1_ncj77")
7 | metallic_specular = 0.0
8 | texture_filter = 2
9 |
--------------------------------------------------------------------------------
/textures/palette.lmp.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="func_godot.palette"
4 | type="Resource"
5 | uid="uid://btum54af0kgs5"
6 | path="res://.godot/imported/palette.lmp-e354ba27800c3f86604b93e4cde2602e.tres"
7 |
8 | [deps]
9 |
10 | source_file="res://textures/palette.lmp"
11 | dest_files=["res://.godot/imported/palette.lmp-e354ba27800c3f86604b93e4cde2602e.tres"]
12 |
13 | [params]
14 |
15 |
--------------------------------------------------------------------------------
/maps/example_basic.map.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="func_godot.map"
4 | type="Resource"
5 | uid="uid://d3s66658slppk"
6 | path="res://.godot/imported/example_basic.map-cd7c52bbbf9bba3f842e756b32e6d3fc.tres"
7 |
8 | [deps]
9 |
10 | source_file="res://maps/example_basic.map"
11 | dest_files=["res://.godot/imported/example_basic.map-cd7c52bbbf9bba3f842e756b32e6d3fc.tres"]
12 |
13 | [params]
14 |
15 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/trenchbroom/tb_face_tag_clip.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="TrenchBroomTag" load_steps=2 format=3 uid="uid://b4xhdj0e16lop"]
2 |
3 | [ext_resource type="Script" uid="uid://b66qdknwqpfup" path="res://addons/func_godot/src/trenchbroom/trenchbroom_tag.gd" id="1_7td58"]
4 |
5 | [resource]
6 | script = ExtResource("1_7td58")
7 | tag_name = "Clip"
8 | tag_pattern = "clip"
9 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/trenchbroom/tb_face_tag_skip.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="TrenchBroomTag" load_steps=2 format=3 uid="uid://ca7377sfgj074"]
2 |
3 | [ext_resource type="Script" uid="uid://b66qdknwqpfup" path="res://addons/func_godot/src/trenchbroom/trenchbroom_tag.gd" id="1_2teqe"]
4 |
5 | [resource]
6 | script = ExtResource("1_2teqe")
7 | tag_name = "Skip"
8 | tag_pattern = "skip"
9 |
--------------------------------------------------------------------------------
/addons/func_godot/palette.lmp.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="func_godot.palette"
4 | type="Resource"
5 | uid="uid://drgnc41yfybr"
6 | path="res://.godot/imported/palette.lmp-138c33f2ac0cab3ad6373e7c0425cf00.tres"
7 |
8 | [deps]
9 |
10 | source_file="res://addons/func_godot/palette.lmp"
11 | dest_files=["res://.godot/imported/palette.lmp-138c33f2ac0cab3ad6373e7c0425cf00.tres"]
12 |
13 | [params]
14 |
15 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="TrenchBroomTag" load_steps=2 format=3 uid="uid://bkjxc54mmdhbo"]
2 |
3 | [ext_resource type="Script" uid="uid://b66qdknwqpfup" path="res://addons/func_godot/src/trenchbroom/trenchbroom_tag.gd" id="1_enkfc"]
4 |
5 | [resource]
6 | script = ExtResource("1_enkfc")
7 | tag_name = "Origin"
8 | tag_pattern = "origin"
9 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_clip.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="NetRadiantCustomShader" load_steps=2 format=3 uid="uid://f5erfnvbg6b7"]
2 |
3 | [ext_resource type="Script" uid="uid://dn86acprv4e86" path="res://addons/func_godot/src/netradiant_custom/netradiant_custom_shader.gd" id="1_cuylw"]
4 |
5 | [resource]
6 | script = ExtResource("1_cuylw")
7 | texture_path = "textures/clip"
8 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_skip.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="NetRadiantCustomShader" load_steps=2 format=3 uid="uid://cfhg30jclb4lw"]
2 |
3 | [ext_resource type="Script" uid="uid://dn86acprv4e86" path="res://addons/func_godot/src/netradiant_custom/netradiant_custom_shader.gd" id="1_4ja6h"]
4 |
5 | [resource]
6 | script = ExtResource("1_4ja6h")
7 | texture_path = "textures/skip"
8 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_origin.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="NetRadiantCustomShader" load_steps=2 format=3 uid="uid://bpnj14oaufdpt"]
2 |
3 | [ext_resource type="Script" uid="uid://dn86acprv4e86" path="res://addons/func_godot/src/netradiant_custom/netradiant_custom_shader.gd" id="1_ah2cp"]
4 |
5 | [resource]
6 | script = ExtResource("1_ah2cp")
7 | texture_path = "textures/origin"
8 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/trenchbroom/tb_brush_tag_func.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="TrenchBroomTag" load_steps=2 format=3 uid="uid://37iduqf7tpxq"]
2 |
3 | [ext_resource type="Script" uid="uid://b66qdknwqpfup" path="res://addons/func_godot/src/trenchbroom/trenchbroom_tag.gd" id="1_rn13a"]
4 |
5 | [resource]
6 | script = ExtResource("1_rn13a")
7 | tag_name = "Func"
8 | tag_attributes = Array[String]([])
9 | tag_match_type = 1
10 | tag_pattern = "func*"
11 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/trenchbroom/tb_brush_tag_trigger.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="TrenchBroomTag" load_steps=2 format=3 uid="uid://co2sb1ng7cw4i"]
2 |
3 | [ext_resource type="Script" uid="uid://b66qdknwqpfup" path="res://addons/func_godot/src/trenchbroom/trenchbroom_tag.gd" id="1_msqpk"]
4 |
5 | [resource]
6 | script = ExtResource("1_msqpk")
7 | tag_name = "Trigger"
8 | tag_match_type = 1
9 | tag_pattern = "trigger*"
10 | texture_name = "trigger"
11 |
--------------------------------------------------------------------------------
/materials/mars/mars_cave0.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://ny03ktm0yrbk"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://dhf77ycwlwn8v" path="res://textures/mars/mars_cave0.png" id="1_tptrf"]
4 | [ext_resource type="Texture2D" uid="uid://2rp2l3whs1wc" path="res://textures/mars/mars_cave0_normal.png" id="2_um6h1"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_tptrf")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_um6h1")
11 | texture_filter = 2
12 |
--------------------------------------------------------------------------------
/materials/mars/mars_cliff0.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://cwqxoeow5p2u"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://p3musw6m37lw" path="res://textures/mars/mars_cliff0.png" id="1_8bkkq"]
4 | [ext_resource type="Texture2D" uid="uid://dyjxu15trhcjo" path="res://textures/mars/mars_cliff0_normal.png" id="2_gxm68"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_8bkkq")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_gxm68")
11 | texture_filter = 2
12 |
--------------------------------------------------------------------------------
/materials/mars/mars_sand0.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://dgkp3nxxwt6jq"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://nqfowh2e6lpu" path="res://textures/mars/mars_sand0.png" id="1_idvq4"]
4 | [ext_resource type="Texture2D" uid="uid://b2w5librpg75w" path="res://textures/mars/mars_sand0_normal.png" id="2_3r3nb"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_idvq4")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_3r3nb")
11 | texture_filter = 2
12 |
--------------------------------------------------------------------------------
/entities/lights/light_base.gd:
--------------------------------------------------------------------------------
1 | ## Special Light base class that contains static helper functions for LightOmni and LightSpot entities.
2 | class_name LightBase
3 | extends Light3D
4 |
5 | static func _func_godot_apply_properties(node: Light3D, props: Dictionary) -> void:
6 | node.light_energy = props["energy"] as float
7 | node.light_indirect_energy = props["indirect_energy"] as float
8 | node.shadow_bias = props["shadow_bias"] as float
9 | node.shadow_enabled = props["shadows"] as bool
10 | node.light_color = props["color"] as Color
11 | node.light_bake_mode = Light3D.BAKE_DYNAMIC
12 |
--------------------------------------------------------------------------------
/fgd/base/targetname_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=2 format=3 uid="uid://cwbnifad3sdgw"]
2 |
3 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="1_4xagm"]
4 |
5 | [resource]
6 | script = ExtResource("1_4xagm")
7 | classname = "Targetname"
8 | class_properties = Dictionary[String, Variant]({
9 | "targetname": null
10 | })
11 | class_property_descriptions = Dictionary[String, Variant]({
12 | "targetname": "Adds this entity to a group with this targetname."
13 | })
14 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_palette_file.gd:
--------------------------------------------------------------------------------
1 | @icon("res://addons/func_godot/icons/icon_quake_file.svg")
2 | class_name QuakePaletteFile extends Resource
3 | ## Quake LMP palette format file used with [QuakeWadFile].
4 | ##
5 | ## Quake LMP palette format file used in conjunction with a Quake WAD2 format [QuakeWadFile].
6 | ## Not required for the Valve WAD3 format.
7 | ##
8 | ## @tutorial(Quake Wiki Palette Article): https://quakewiki.org/wiki/Quake_palette#palette.lmp
9 |
10 | ## Collection of [Color]s retrieved from the LMP palette file.
11 | @export var colors: PackedColorArray
12 |
13 | func _init(colors):
14 | self.colors = colors
15 |
--------------------------------------------------------------------------------
/addons/func_godot/src/netradiant_custom/netradiant_custom_shader.gd:
--------------------------------------------------------------------------------
1 | @icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
2 | class_name NetRadiantCustomShader
3 | extends Resource
4 | ## Shader resource for NetRadiant Custom configurations.
5 | ##
6 | ## Resource that gets built into a shader file that applies a special effect to a specified texture in NetRadiant Custom.
7 |
8 | ## Path to texture without extension, eg: [i]"textures/special/clip"[/i].
9 | @export var texture_path: String
10 |
11 | ## Array of shader properties to apply to faces using [member texture_path].
12 | @export var shader_attributes : Array[String] = ["qer_trans 0.4"]
13 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_map_file.gd:
--------------------------------------------------------------------------------
1 | @icon("res://addons/func_godot/icons/icon_quake_file.svg")
2 | class_name QuakeMapFile extends Resource
3 | ## Map file that can be built by [FuncGodotMap].
4 | ##
5 | ## Map file that can be built by a [FuncGodotMap]. Supports the Quake and Valve map formats.
6 | ##
7 | ## @tutorial(Quake Wiki Map Format Article): https://quakewiki.org/wiki/Quake_Map_Format
8 | ## @tutorial(Valve Developer Wiki VMF Article): https://developer.valvesoftware.com/wiki/VMF_(Valve_Map_Format)
9 |
10 | ## Number of times this map file has been imported.
11 | @export var revision: int = 0
12 |
13 | ## Raw map data.
14 | @export_multiline var map_data: String = ""
15 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_wad_file.gd:
--------------------------------------------------------------------------------
1 | @icon("res://addons/func_godot/icons/icon_quake_file.svg")
2 | class_name QuakeWadFile extends Resource
3 | ## Texture container in the WAD2 or WAD3 format.
4 | ##
5 | ## Texture container in the Quake WAD2 or Valve WAD3 format.
6 | ##
7 | ## @tutorial(Quake Wiki WAD Article): https://quakewiki.org/wiki/Texture_Wad
8 | ## @tutorial(Valve Developer Wiki WAD3 Article): https://developer.valvesoftware.com/wiki/WAD
9 |
10 | ## Collection of [ImageTexture] imported from the WAD file.
11 | @export var textures: Dictionary[String, ImageTexture]
12 |
13 | func _init(textures: Dictionary[String, ImageTexture] = {}):
14 | self.textures = textures
15 |
--------------------------------------------------------------------------------
/fgd/solid/funcs/func_detail.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=3 format=3 uid="uid://bv37jafqtfyuw"]
2 |
3 | [ext_resource type="Resource" uid="uid://d4buv26pirxbl" path="res://fgd/base/func_base.tres" id="1_dk8i8"]
4 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_6subh"]
5 |
6 | [resource]
7 | script = ExtResource("2_6subh")
8 | collision_shape_type = 2
9 | collision_mask = 0
10 | classname = "func_detail"
11 | description = "Static map geometry. Does not generate occluder instances."
12 | base_classes = Array[Resource]([ExtResource("1_dk8i8")])
13 | node_class = "StaticBody3D"
14 |
--------------------------------------------------------------------------------
/fgd/solid/funcs/func_geo.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=3 format=3 uid="uid://dbc8wa7c1nbgx"]
2 |
3 | [ext_resource type="Resource" uid="uid://d4buv26pirxbl" path="res://fgd/base/func_base.tres" id="1_dmuri"]
4 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_msb1j"]
5 |
6 | [resource]
7 | script = ExtResource("2_msb1j")
8 | build_occlusion = true
9 | collision_shape_type = 2
10 | collision_mask = 0
11 | classname = "func_geo"
12 | description = "Static map geometry. Generates occluder instances."
13 | base_classes = Array[Resource]([ExtResource("1_dmuri")])
14 | node_class = "StaticBody3D"
15 |
--------------------------------------------------------------------------------
/addons/func_godot/fgd/phong_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=2 format=3 uid="uid://nayxb8n7see2"]
2 |
3 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="1_04y3n"]
4 |
5 | [resource]
6 | script = ExtResource("1_04y3n")
7 | classname = "Phong"
8 | description = "Phong shading options for SolidClass geometry."
9 | class_properties = Dictionary[String, Variant]({
10 | "_phong": {
11 | "Disabled": 0,
12 | "Smooth shading": 1
13 | },
14 | "_phong_angle": 89.0
15 | })
16 | class_property_descriptions = Dictionary[String, Variant]({
17 | "_phong": ["Phong shading", 0],
18 | "_phong_angle": "Phong smoothing angle"
19 | })
20 |
--------------------------------------------------------------------------------
/addons/func_godot/func_godot_default_map_settings.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotMapSettings" load_steps=5 format=3 uid="uid://bkhxcqsquw1yg"]
2 |
3 | [ext_resource type="Material" uid="uid://cvex6toty8yn7" path="res://addons/func_godot/textures/default_material.tres" id="1_8l5wm"]
4 | [ext_resource type="Script" uid="uid://38q6k0ctahjn" path="res://addons/func_godot/src/map/func_godot_map_settings.gd" id="1_dlf23"]
5 | [ext_resource type="Resource" uid="uid://crgpdahjaj" path="res://addons/func_godot/fgd/func_godot_fgd.tres" id="2_hf4oi"]
6 | [ext_resource type="Script" uid="uid://cij36hpqc46c" path="res://addons/func_godot/src/import/quake_wad_file.gd" id="4_576s4"]
7 |
8 | [resource]
9 | script = ExtResource("1_dlf23")
10 |
--------------------------------------------------------------------------------
/fgd/base/globalname_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=2 format=3 uid="uid://syvs5beg2j3q"]
2 |
3 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="1_4aiwx"]
4 |
5 | [resource]
6 | script = ExtResource("1_4aiwx")
7 | classname = "Globalname"
8 | class_properties = Dictionary[String, Variant]({
9 | "globalname": ""
10 | })
11 | class_property_descriptions = Dictionary[String, Variant]({
12 | "globalname": "Unique name in the Map Scene. When FuncGodot builds the map, this entity will be renamed to entity_ + globalname. This can be a useful alternative to targetname, especially when trying to reparent generated nodes."
13 | })
14 |
--------------------------------------------------------------------------------
/fgd/fgd_main.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=5 format=3 uid="uid://tt4mj8flifi0"]
2 |
3 | [ext_resource type="Resource" uid="uid://n5ccclg387jb" path="res://fgd/fgd_base.tres" id="1_kf3d4"]
4 | [ext_resource type="Resource" uid="uid://cnrh5xw6qygo7" path="res://fgd/fgd_solid.tres" id="2_prdli"]
5 | [ext_resource type="Resource" uid="uid://dcahi87src2x1" path="res://fgd/fgd_point.tres" id="3_ktrhr"]
6 | [ext_resource type="Script" uid="uid://drlmgulwbjwqu" path="res://addons/func_godot/src/fgd/func_godot_fgd_file.gd" id="4_l5po5"]
7 |
8 | [resource]
9 | script = ExtResource("4_l5po5")
10 | fgd_name = "FuncGodotExBasic"
11 | base_fgd_files = Array[Resource]([ExtResource("1_kf3d4"), ExtResource("2_prdli"), ExtResource("3_ktrhr")])
12 |
--------------------------------------------------------------------------------
/fgd/solid/funcs/func_detail_illusionary.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=3 format=3 uid="uid://4h23glniadlk"]
2 |
3 | [ext_resource type="Resource" uid="uid://d4buv26pirxbl" path="res://fgd/base/func_base.tres" id="1_r2f2f"]
4 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_y4cgm"]
5 |
6 | [resource]
7 | script = ExtResource("2_y4cgm")
8 | collision_shape_type = 0
9 | collision_layer = 0
10 | collision_mask = 0
11 | classname = "func_detail_illusionary"
12 | description = "Decorative map geometry with no collision. Does not generate occluder instances."
13 | base_classes = Array[Resource]([ExtResource("1_r2f2f")])
14 | node_class = "Node3D"
15 |
--------------------------------------------------------------------------------
/fgd/solid/funcs/func_illusionary.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=3 format=3 uid="uid://ckh3askbgkynt"]
2 |
3 | [ext_resource type="Resource" uid="uid://d4buv26pirxbl" path="res://fgd/base/func_base.tres" id="1_h6qa0"]
4 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_eemce"]
5 |
6 | [resource]
7 | script = ExtResource("2_eemce")
8 | build_occlusion = true
9 | collision_shape_type = 0
10 | collision_layer = 0
11 | collision_mask = 0
12 | classname = "func_illusionary"
13 | description = "Decorative map geometry with no collision. Generates occluder instances."
14 | base_classes = Array[Resource]([ExtResource("1_h6qa0")])
15 | node_class = "Node3D"
16 |
--------------------------------------------------------------------------------
/fgd/base/target_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=2 format=3 uid="uid://kerywjgft7vh"]
2 |
3 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="1_eljra"]
4 |
5 | [resource]
6 | script = ExtResource("1_eljra")
7 | classname = "Target"
8 | class_properties = Dictionary[String, Variant]({
9 | "target": NodePath(""),
10 | "targetfunc": ""
11 | })
12 | class_property_descriptions = Dictionary[String, Variant]({
13 | "target": "Entity group to call the use function on when this entity is triggered.",
14 | "targetfunc": "Function to call on target entities. As is, the target function cannot accept arguments, so make sure it doesn't require specifying arguments."
15 | })
16 |
--------------------------------------------------------------------------------
/fgd/base/trigger_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=5 format=3 uid="uid://hnx0olvm0jt2"]
2 |
3 | [ext_resource type="Resource" uid="uid://kerywjgft7vh" path="res://fgd/base/target_base.tres" id="1_5u3rh"]
4 | [ext_resource type="Resource" uid="uid://cwbnifad3sdgw" path="res://fgd/base/targetname_base.tres" id="2_dfx0u"]
5 | [ext_resource type="Resource" uid="uid://syvs5beg2j3q" path="res://fgd/base/globalname_base.tres" id="3_l56ks"]
6 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="4_jx0ye"]
7 |
8 | [resource]
9 | script = ExtResource("4_jx0ye")
10 | classname = "Trigger"
11 | base_classes = Array[Resource]([ExtResource("1_5u3rh"), ExtResource("2_dfx0u"), ExtResource("3_l56ks")])
12 |
--------------------------------------------------------------------------------
/fgd/base/actor_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=3 format=3 uid="uid://3com3yjkcsvg"]
2 |
3 | [ext_resource type="Resource" uid="uid://syvs5beg2j3q" path="res://fgd/base/globalname_base.tres" id="1_35crd"]
4 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="2_j2se1"]
5 |
6 | [resource]
7 | script = ExtResource("2_j2se1")
8 | classname = "Actor"
9 | base_classes = Array[Resource]([ExtResource("1_35crd")])
10 | class_properties = Dictionary[String, Variant]({
11 | "flags": [["Player", 1, 0], ["BIG friend", 2, 0], ["Attentive friend", 4, 0], ["Happy friend", 8, 0]],
12 | "scale": 1.0
13 | })
14 | meta_properties = Dictionary[String, Variant]({
15 | "color": Color(0.8, 0, 0, 1),
16 | "size": AABB(-8, -8, -8, 8, 8, 8)
17 | })
18 |
--------------------------------------------------------------------------------
/addons/func_godot/fgd/vertex_merge_distance_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=2 format=3 uid="uid://doo4ly322b4jc"]
2 |
3 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="1_h3atm"]
4 |
5 | [resource]
6 | script = ExtResource("1_h3atm")
7 | classname = "VertexMergeDistance"
8 | description = "Adjustable value to snap vertices to on map build. This can reduce instances of seams between polygons."
9 | class_properties = Dictionary[String, Variant]({
10 | "_vertex_merge_distance": 0.0625
11 | })
12 | class_property_descriptions = Dictionary[String, Variant]({
13 | "_vertex_merge_distance": "Adjustable value to snap vertices to on map build. This can reduce instances of seams between polygons."
14 | })
15 | metadata/_custom_type_script = "uid://ck575aqs1sbrb"
16 |
--------------------------------------------------------------------------------
/entities/info_camera.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name InfoCamera
3 | extends Camera3D
4 |
5 | @export var targetname: String = ""
6 | @export var camera_target: Node3D = null
7 |
8 | func _func_godot_apply_properties(props: Dictionary) -> void:
9 | targetname = props["targetname"] as String
10 | current = props["active"] as bool
11 | var targ_node: Node = get_parent().get_node_or_null("entity_" + (props["camera_target"] as String))
12 | if targ_node != null:
13 | if 'position' in targ_node:
14 | camera_target = targ_node
15 | look_at(camera_target.global_position)
16 |
17 | func use() -> void:
18 | current = true
19 |
20 | func _ready() -> void:
21 | if Engine.is_editor_hint():
22 | return
23 | GAME.set_targetname(self, targetname)
24 |
25 | func _process(_delta: float) -> void:
26 | if Engine.is_editor_hint():
27 | return
28 | if camera_target:
29 | look_at(camera_target.global_position)
30 |
--------------------------------------------------------------------------------
/addons/func_godot/fgd/worldspawn.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=3 format=3 uid="uid://bdji3873bg32h"]
2 |
3 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="1_62t8m"]
4 | [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="1_h1046"]
5 |
6 | [resource]
7 | script = ExtResource("1_62t8m")
8 | spawn_type = 0
9 | origin_type = 1
10 | collision_mask = 0
11 | classname = "worldspawn"
12 | description = "Default static world geometry. Builds a StaticBody3D with a single MeshInstance3D and a single convex CollisionShape3D shape."
13 | base_classes = Array[Resource]([ExtResource("1_h1046")])
14 | meta_properties = Dictionary[String, Variant]({
15 | "color": Color(0.8, 0.8, 0.8, 1)
16 | })
17 | node_class = "StaticBody3D"
18 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_base_class.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
3 | class_name FuncGodotFGDBaseClass extends FuncGodotFGDEntityClass
4 | ## Special inheritance class for [FuncGodotFGDSolidClass] and [FuncGodotFGDPointClass] entity definitions.
5 | ##
6 | ## Inheritance class for [FuncGodotFGDSolidClass] and [FuncGodotFGDPointClass] entities,
7 | ## used to shared or common properties and descriptions across different definitions.
8 | ##
9 | ## @tutorial(Quake Wiki Entity Article): https://quakewiki.org/wiki/Entity
10 | ## @tutorial(Level Design Book: Entity Types and Settings): https://book.leveldesignbook.com/appendix/resources/formats/fgd#entity-types-and-settings-basic
11 | ## @tutorial(Valve Developer Wiki FGD Article): https://developer.valvesoftware.com/wiki/FGD#Class_Types_and_Properties
12 |
13 | func _init() -> void:
14 | prefix = "@BaseClass"
15 |
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://bi51vakf1lv8k"]
2 |
3 | [ext_resource type="Script" uid="uid://bkua4ygsumdod" path="res://entities/actors/marsfrog/marsfrog.gd" id="1_qqpyl"]
4 | [ext_resource type="PackedScene" uid="uid://b63vvdlr5ocvn" path="res://entities/actors/marsfrog/marsfrog.glb" id="2_ylheg"]
5 |
6 | [sub_resource type="SphereShape3D" id="SphereShape3D_ei03m"]
7 | radius = 0.2
8 |
9 | [node name="Marsfrog" type="CharacterBody3D"]
10 | collision_layer = 6
11 | collision_mask = 5
12 | script = ExtResource("1_qqpyl")
13 |
14 | [node name="marsfrog" parent="." instance=ExtResource("2_ylheg")]
15 | transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0.234049, 0)
16 |
17 | [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
18 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.2, 0)
19 | shape = SubResource("SphereShape3D_ei03m")
20 |
--------------------------------------------------------------------------------
/fgd/fgd_point.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=6 format=3 uid="uid://dcahi87src2x1"]
2 |
3 | [ext_resource type="Resource" uid="uid://c2qu0oxubiqrv" path="res://fgd/point/actors/actor_marsfrog.tres" id="1_axsde"]
4 | [ext_resource type="Resource" uid="uid://ia1t5p4mhom3" path="res://fgd/point/lights/light_omni.tres" id="2_b6o45"]
5 | [ext_resource type="Resource" uid="uid://dbvwttrr1uq6e" path="res://fgd/point/lights/light_spot.tres" id="3_qr6f6"]
6 | [ext_resource type="Resource" uid="uid://drhgccbh1koh8" path="res://fgd/point/info_camera.tres" id="4_aih72"]
7 | [ext_resource type="Script" uid="uid://drlmgulwbjwqu" path="res://addons/func_godot/src/fgd/func_godot_fgd_file.gd" id="5_b61ie"]
8 |
9 | [resource]
10 | script = ExtResource("5_b61ie")
11 | fgd_name = "PointFGD"
12 | entity_definitions = Array[Resource]([ExtResource("1_axsde"), ExtResource("2_b6o45"), ExtResource("3_qr6f6"), ExtResource("4_aih72")])
13 |
--------------------------------------------------------------------------------
/maps/map_settings.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotMapSettings" load_steps=5 format=3 uid="uid://cnci07xmp76ix"]
2 |
3 | [ext_resource type="Script" uid="uid://38q6k0ctahjn" path="res://addons/func_godot/src/map/func_godot_map_settings.gd" id="1_rg8co"]
4 | [ext_resource type="Material" uid="uid://cvex6toty8yn7" path="res://addons/func_godot/textures/default_material.tres" id="1_wr8ue"]
5 | [ext_resource type="Resource" uid="uid://tt4mj8flifi0" path="res://fgd/fgd_main.tres" id="2_h4rxe"]
6 | [ext_resource type="Script" uid="uid://cij36hpqc46c" path="res://addons/func_godot/src/import/quake_wad_file.gd" id="4_h4rxe"]
7 |
8 | [resource]
9 | script = ExtResource("1_rg8co")
10 | entity_fgd = ExtResource("2_h4rxe")
11 | uv_unwrap_texel_size = 1.0
12 | entity_name_property = "globalname"
13 | clip_texture = "special/clip"
14 | skip_texture = "special/skip"
15 | origin_texture = "special/origin"
16 | base_material_dir = "res://materials"
17 |
--------------------------------------------------------------------------------
/fgd/base/func_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=5 format=3 uid="uid://d4buv26pirxbl"]
2 |
3 | [ext_resource type="Resource" uid="uid://syvs5beg2j3q" path="res://fgd/base/globalname_base.tres" id="1_2uqtv"]
4 | [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="2_7k882"]
5 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="2_c360u"]
6 | [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_thqup"]
7 |
8 | [resource]
9 | script = ExtResource("2_c360u")
10 | classname = "Func"
11 | base_classes = Array[Resource]([ExtResource("1_2uqtv"), ExtResource("2_7k882"), ExtResource("2_thqup")])
12 | class_property_descriptions = Dictionary[String, Variant]({
13 | "_phong": "Set to 1 to give the brush entity smooth shading."
14 | })
15 |
--------------------------------------------------------------------------------
/addons/func_godot/fgd/func_detail_illusionary.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://ch3e0dix85uhb"]
2 |
3 | [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_ar63x"]
4 | [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_j7vgq"]
5 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_lhb87"]
6 |
7 | [resource]
8 | script = ExtResource("2_lhb87")
9 | collision_shape_type = 0
10 | classname = "func_detail_illusionary"
11 | description = "Static geometry with no collision. Builds a Node3D with a MeshInstance3D. Does not occlude other VisualInstance3D nodes."
12 | base_classes = Array[Resource]([ExtResource("1_ar63x"), ExtResource("2_j7vgq")])
13 | meta_properties = Dictionary[String, Variant]({
14 | "color": Color(0.8, 0.8, 0.8, 1)
15 | })
16 | node_class = "Node3D"
17 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/trenchbroom/func_godot_tb_game_config.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="TrenchBroomGameConfig" load_steps=7 format=3 uid="uid://b44ah5b2000wa"]
2 |
3 | [ext_resource type="Resource" uid="uid://crgpdahjaj" path="res://addons/func_godot/fgd/func_godot_fgd.tres" id="1_8u1vq"]
4 | [ext_resource type="Resource" uid="uid://b4xhdj0e16lop" path="res://addons/func_godot/game_config/trenchbroom/tb_face_tag_clip.tres" id="1_rsp20"]
5 | [ext_resource type="Resource" uid="uid://ca7377sfgj074" path="res://addons/func_godot/game_config/trenchbroom/tb_face_tag_skip.tres" id="2_166i2"]
6 | [ext_resource type="Script" uid="uid://cx44c4vnq8bt5" path="res://addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd" id="2_ns6ah"]
7 | [ext_resource type="Resource" uid="uid://bkjxc54mmdhbo" path="res://addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres" id="3_stisi"]
8 | [ext_resource type="Texture2D" uid="uid://decwujsyhj0qy" path="res://addons/func_godot/icon32.png" id="6_tex5j"]
9 |
10 | [resource]
11 | script = ExtResource("2_ns6ah")
12 |
--------------------------------------------------------------------------------
/addons/func_godot/fgd/func_detail.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://cxy7jnh6d7msn"]
2 |
3 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="1_0fsmp"]
4 | [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_c3bns"]
5 | [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_c03gr"]
6 |
7 | [resource]
8 | script = ExtResource("1_0fsmp")
9 | collision_shape_type = 2
10 | collision_mask = 0
11 | classname = "func_detail"
12 | description = "Static collidable geometry. Builds a StaticBody3D with a MeshInstance3D and a single concave CollisionShape3D. Does not occlude other VisualInstance3D nodes."
13 | base_classes = Array[Resource]([ExtResource("1_c3bns"), ExtResource("2_c03gr")])
14 | meta_properties = Dictionary[String, Variant]({
15 | "color": Color(0.8, 0.8, 0.8, 1)
16 | })
17 | node_class = "StaticBody3D"
18 |
--------------------------------------------------------------------------------
/addons/func_godot/fgd/func_geo.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://b70vf4t5dc70t"]
2 |
3 | [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_5mwee"]
4 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_8o081"]
5 | [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_bp8pb"]
6 |
7 | [resource]
8 | script = ExtResource("2_8o081")
9 | build_occlusion = true
10 | collision_shape_type = 2
11 | collision_mask = 0
12 | classname = "func_geo"
13 | description = "Static collidable geometry. Builds a StaticBody3D with a MeshInstance3D, a single concave CollisionShape3D, and an OccluderInstance3D."
14 | base_classes = Array[Resource]([ExtResource("1_5mwee"), ExtResource("2_bp8pb")])
15 | meta_properties = Dictionary[String, Variant]({
16 | "color": Color(0.8, 0.8, 0.8, 1)
17 | })
18 | node_class = "StaticBody3D"
19 |
--------------------------------------------------------------------------------
/addons/func_godot/fgd/func_illusionary.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://dg5x44cc7flew"]
2 |
3 | [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_kv0mq"]
4 | [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_hovr4"]
5 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_uffhi"]
6 |
7 | [resource]
8 | script = ExtResource("2_uffhi")
9 | build_occlusion = true
10 | collision_shape_type = 0
11 | classname = "func_illusionary"
12 | description = "Static geometry with no collision. Builds a Node3D with a MeshInstance3D and an Occluder3D to aid in render culling of other VisualInstance3D nodes."
13 | base_classes = Array[Resource]([ExtResource("1_kv0mq"), ExtResource("2_hovr4")])
14 | meta_properties = Dictionary[String, Variant]({
15 | "color": Color(0.8, 0.8, 0.8, 1)
16 | })
17 | node_class = "Node3D"
18 |
--------------------------------------------------------------------------------
/fgd/solid/triggers/trigger_area.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=4 format=3 uid="uid://ptvum0fd8lvk"]
2 |
3 | [ext_resource type="Resource" uid="uid://hnx0olvm0jt2" path="res://fgd/base/trigger_base.tres" id="1_swe6f"]
4 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="2_hgpko"]
5 | [ext_resource type="Script" uid="uid://43spl6muc28v" path="res://entities/triggers/trigger_area.gd" id="3_2bp8b"]
6 |
7 | [resource]
8 | script = ExtResource("2_hgpko")
9 | origin_type = 4
10 | build_visuals = false
11 | use_in_baked_light = false
12 | shadow_casting_setting = 0
13 | render_layers = 0
14 | collision_layer = 4
15 | collision_mask = 4
16 | script_class = ExtResource("3_2bp8b")
17 | classname = "trigger_area"
18 | description = "Area node that activates its target group when entered."
19 | base_classes = Array[Resource]([ExtResource("1_swe6f")])
20 | meta_properties = Dictionary[String, Variant]({
21 | "color": Color(0.8, 0, 0.8, 1)
22 | })
23 | node_class = "Area3D"
24 |
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name Marsfrog
3 | extends Actor
4 |
5 | func use() -> void:
6 | current_state = ActorStates.SCRIPTED
7 | if randi() % 2:
8 | anim_player.play("pain0")
9 | else:
10 | anim_player.play("pain1")
11 |
12 | func _anim_finished(_anim: StringName) -> void:
13 | if current_state == ActorStates.SCRIPTED:
14 | current_state = ActorStates.NORMAL
15 |
16 | func _ready() -> void:
17 | if Engine.is_editor_hint():
18 | return
19 | super._ready()
20 | anim_player = $marsfrog/AnimationPlayer
21 | anim_player.connect("animation_finished", _anim_finished)
22 | if flags & ActorFlags.HAPPY_FRIEND:
23 | current_state = ActorStates.SCRIPTED
24 | anim_player.play("walk")
25 |
26 | func _process(delta: float) -> void:
27 | if Engine.is_editor_hint():
28 | return
29 | super._process(delta)
30 | if current_state == ActorStates.NORMAL:
31 | if on_floor:
32 | if move_input.z != 0:
33 | anim_player.play("run")
34 | elif move_input.x != 0:
35 | anim_player.play("walk")
36 | else:
37 | anim_player.play("stand")
38 | else:
39 | anim_player.play("attack")
40 |
--------------------------------------------------------------------------------
/addons/func_godot/icon.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cp2as6ujvknyu"
6 | path="res://.godot/imported/icon.png-6db43b6a52df1ce3744a82f15cbdbbea.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icon.png"
14 | dest_files=["res://.godot/imported/icon.png-6db43b6a52df1ce3744a82f15cbdbbea.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 |
--------------------------------------------------------------------------------
/textures/special/clip.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cgcpvi6h30bt6"
6 | path="res://.godot/imported/clip.png-b88af128d9765ee842c60c6e4c027bc0.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://textures/special/clip.png"
14 | dest_files=["res://.godot/imported/clip.png-b88af128d9765ee842c60c6e4c027bc0.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 |
--------------------------------------------------------------------------------
/fgd/point/lights/light_omni.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=4 format=3 uid="uid://ia1t5p4mhom3"]
2 |
3 | [ext_resource type="Resource" uid="uid://dukx4b4xgo1o2" path="res://fgd/base/light_base.tres" id="1_7f46b"]
4 | [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="2_piqsv"]
5 | [ext_resource type="Script" uid="uid://dnv2pepfq32np" path="res://entities/lights/light_omni.gd" id="3_rf3cd"]
6 |
7 | [resource]
8 | script = ExtResource("2_piqsv")
9 | script_class = ExtResource("3_rf3cd")
10 | apply_rotation_on_map_build = false
11 | classname = "light_omni"
12 | description = "OmniLight3D entity."
13 | base_classes = Array[Resource]([ExtResource("1_7f46b")])
14 | class_properties = Dictionary[String, Variant]({
15 | "range": 320.0
16 | })
17 | class_property_descriptions = Dictionary[String, Variant]({
18 | "range": "The light's radius in Quake Units. The entity script converts this to Godot Units in the LightOmni script."
19 | })
20 | meta_properties = Dictionary[String, Variant]({})
21 | node_class = "OmniLight3D"
22 |
--------------------------------------------------------------------------------
/addons/func_godot/icon32.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://decwujsyhj0qy"
6 | path="res://.godot/imported/icon32.png-7025e2d95a64a3066b7947e1900b4daf.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icon32.png"
14 | dest_files=["res://.godot/imported/icon32.png-7025e2d95a64a3066b7947e1900b4daf.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 |
--------------------------------------------------------------------------------
/addons/func_godot/textures/clip.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dhmu0toe1itnr"
6 | path="res://.godot/imported/clip.png-747f19bfc6fe499e254d63eeccc3bbe4.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/textures/clip.png"
14 | dest_files=["res://.godot/imported/clip.png-747f19bfc6fe499e254d63eeccc3bbe4.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=3
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 |
--------------------------------------------------------------------------------
/addons/func_godot/textures/skip.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bk5oo263y3u7w"
6 | path="res://.godot/imported/skip.png-b8ce29eeb9f4be76c300a81fd41322fa.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/textures/skip.png"
14 | dest_files=["res://.godot/imported/skip.png-b8ce29eeb9f4be76c300a81fd41322fa.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=3
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 |
--------------------------------------------------------------------------------
/textures/mars/mars_sand1.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://c23mrr25xarj4"
6 | path="res://.godot/imported/mars_sand1.png-b430b7e0250a93a5bbbaf9f8cd1fc58f.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://textures/mars/mars_sand1.png"
14 | dest_files=["res://.godot/imported/mars_sand1.png-b430b7e0250a93a5bbbaf9f8cd1fc58f.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 |
--------------------------------------------------------------------------------
/addons/func_godot/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 func-godot
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/addons/func_godot/textures/origin.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dutip72dl002r"
6 | path="res://.godot/imported/origin.png-501c9242087fbbeb03d876a682f0832c.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/textures/origin.png"
14 | dest_files=["res://.godot/imported/origin.png-501c9242087fbbeb03d876a682f0832c.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 |
--------------------------------------------------------------------------------
/textures/mars/mars_sand1_normal.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bhfu5jh0ner3k"
6 | path="res://.godot/imported/mars_sand1_normal.png-6a7b6c97ae37ff241938f9f44afac32b.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://textures/mars/mars_sand1_normal.png"
14 | dest_files=["res://.godot/imported/mars_sand1_normal.png-6a7b6c97ae37ff241938f9f44afac32b.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 |
--------------------------------------------------------------------------------
/textures/special/skip.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://df025lbhoua4m"
6 | path.s3tc="res://.godot/imported/skip.png-2026d0f841ccf5af70e5ac1bf277c3e0.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/special/skip.png"
15 | dest_files=["res://.godot/imported/skip.png-2026d0f841ccf5af70e5ac1bf277c3e0.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=0
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=0
30 | roughness/src_normal=""
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/textures/special/origin.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://carx70af7xgs0"
6 | path.s3tc="res://.godot/imported/origin.png-e20ef9d40a6c87330d6acd9493389131.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/special/origin.png"
15 | dest_files=["res://.godot/imported/origin.png-e20ef9d40a6c87330d6acd9493389131.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=0
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=0
30 | roughness/src_normal=""
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/addons/func_godot/textures/default_texture.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cyg2snr1w5xw5"
6 | path="res://.godot/imported/default_texture.png-145fbd5fef7f63ace60797fecb133a19.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/textures/default_texture.png"
14 | dest_files=["res://.godot/imported/default_texture.png-145fbd5fef7f63ace60797fecb133a19.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=3
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=true
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=0
41 |
--------------------------------------------------------------------------------
/fgd/point/actors/actor_marsfrog.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDModelPointClass" load_steps=5 format=3 uid="uid://c2qu0oxubiqrv"]
2 |
3 | [ext_resource type="Resource" uid="uid://3com3yjkcsvg" path="res://fgd/base/actor_base.tres" id="1_08lde"]
4 | [ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="2_afwcu"]
5 | [ext_resource type="PackedScene" uid="uid://bi51vakf1lv8k" path="res://entities/actors/marsfrog/marsfrog.tscn" id="2_cik47"]
6 | [ext_resource type="Script" uid="uid://ldfqjtq0br35" path="res://addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd" id="3_afwcu"]
7 |
8 | [resource]
9 | script = ExtResource("3_afwcu")
10 | target_map_editor = 1
11 | generate_size_property = true
12 | rotation_offset = Vector3(0, -90, 0)
13 | scene_file = ExtResource("2_cik47")
14 | classname = "actor_marsfrog"
15 | description = "Marsfrog"
16 | base_classes = Array[Resource]([ExtResource("1_08lde")])
17 | meta_properties = Dictionary[String, Variant]({
18 | "model": "{\"path\": \"fgd/models/actor_marsfrog.glb\", \"scale\": 32.0 }",
19 | "size": AABB(-5, -7, 0, 6, 7, 19)
20 | })
21 |
--------------------------------------------------------------------------------
/textures/special/trigger.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://yc3crhjna8oh"
6 | path.s3tc="res://.godot/imported/trigger.png-f879e271e7fabd1268f430358dfe2613.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/special/trigger.png"
15 | dest_files=["res://.godot/imported/trigger.png-f879e271e7fabd1268f430358dfe2613.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=0
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=0
30 | roughness/src_normal=""
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/textures/mars/mars_cave0.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dhf77ycwlwn8v"
6 | path.s3tc="res://.godot/imported/mars_cave0.png-95421ac225c1f18150b148b25a6b4bd6.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/mars/mars_cave0.png"
15 | dest_files=["res://.godot/imported/mars_cave0.png-95421ac225c1f18150b148b25a6b4bd6.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=0
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=0
30 | roughness/src_normal=""
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/textures/mars/mars_sand0.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://nqfowh2e6lpu"
6 | path.s3tc="res://.godot/imported/mars_sand0.png-4730734e5c8e84a9af57c7d8ca9ec1b2.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/mars/mars_sand0.png"
15 | dest_files=["res://.godot/imported/mars_sand0.png-4730734e5c8e84a9af57c7d8ca9ec1b2.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=0
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=0
30 | roughness/src_normal=""
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/textures/mars/mars_cliff0.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://p3musw6m37lw"
6 | path.s3tc="res://.godot/imported/mars_cliff0.png-10af72fd6ef69698ba18569b234e46e5.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/mars/mars_cliff0.png"
15 | dest_files=["res://.godot/imported/mars_cliff0.png-10af72fd6ef69698ba18569b234e46e5.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=0
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=0
30 | roughness/src_normal=""
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/icon.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bxvfjvylrmr7c"
6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://icon.svg"
14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/addons/func_godot/game_config/netradiant_custom/func_godot_netradiant_custom_gamepack_config.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="NetRadiantCustomGamePackConfig" load_steps=6 format=3 uid="uid://cv1k2e85fo2ax"]
2 |
3 | [ext_resource type="Resource" uid="uid://crgpdahjaj" path="res://addons/func_godot/fgd/func_godot_fgd.tres" id="1_gct4v"]
4 | [ext_resource type="Script" uid="uid://dfhj3me2g5j0l" path="res://addons/func_godot/src/netradiant_custom/netradiant_custom_gamepack_config.gd" id="2_en8ro"]
5 | [ext_resource type="Resource" uid="uid://f5erfnvbg6b7" path="res://addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_clip.tres" id="2_w7psh"]
6 | [ext_resource type="Resource" uid="uid://cfhg30jclb4lw" path="res://addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_skip.tres" id="3_6gpk8"]
7 | [ext_resource type="Resource" uid="uid://bpnj14oaufdpt" path="res://addons/func_godot/game_config/netradiant_custom/netradiant_custom_shader_origin.tres" id="4_8rl60"]
8 |
9 | [resource]
10 | script = ExtResource("2_en8ro")
11 | model_types = PackedStringArray("glb", "gltf", "obj")
12 | sound_types = PackedStringArray("wav", "ogg")
13 | texture_types = PackedStringArray("png", "jpg", "jpeg", "bmp", "tga")
14 |
--------------------------------------------------------------------------------
/addons/func_godot/icon.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bx5buvf1ydm7q"
6 | path="res://.godot/imported/icon.svg-99f2c56e0c1ce867c819715c68d9c120.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icon.svg"
14 | dest_files=["res://.godot/imported/icon.svg-99f2c56e0c1ce867c819715c68d9c120.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/textures/mars/mars_cave0_normal.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://2rp2l3whs1wc"
6 | path.s3tc="res://.godot/imported/mars_cave0_normal.png-7705a3e1c56b4cc85dc918bf21aa7f86.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/mars/mars_cave0_normal.png"
15 | dest_files=["res://.godot/imported/mars_cave0_normal.png-7705a3e1c56b4cc85dc918bf21aa7f86.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=1
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=1
30 | roughness/src_normal="res://textures/mars/mars_cave0_normal.png"
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/textures/mars/mars_sand0_normal.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b2w5librpg75w"
6 | path.s3tc="res://.godot/imported/mars_sand0_normal.png-77211481a0c716ee4282743eace954ce.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/mars/mars_sand0_normal.png"
15 | dest_files=["res://.godot/imported/mars_sand0_normal.png-77211481a0c716ee4282743eace954ce.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=1
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=1
30 | roughness/src_normal="res://textures/mars/mars_sand0_normal.png"
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/fgd/point/lights/light_spot.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=4 format=3 uid="uid://dbvwttrr1uq6e"]
2 |
3 | [ext_resource type="Resource" uid="uid://dukx4b4xgo1o2" path="res://fgd/base/light_base.tres" id="1_ey4sb"]
4 | [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="2_exca4"]
5 | [ext_resource type="Script" uid="uid://c3mfo5emund0x" path="res://entities/lights/light_spot.gd" id="3_k8p0u"]
6 |
7 | [resource]
8 | script = ExtResource("2_exca4")
9 | script_class = ExtResource("3_k8p0u")
10 | classname = "light_spot"
11 | description = "SpotLight3D entity."
12 | base_classes = Array[Resource]([ExtResource("1_ey4sb")])
13 | class_properties = Dictionary[String, Variant]({
14 | "angle": 45.0,
15 | "mangle": Vector3(0, 0, 0),
16 | "range": 320.0
17 | })
18 | class_property_descriptions = Dictionary[String, Variant]({
19 | "angle": "The spotlight's angle in degrees.",
20 | "mangle": "Orientation in degrees.",
21 | "range": "The maximal range that can be reached by the spotlight in Quake Units. The entity script converts this to Godot Units in the LightOmni script."
22 | })
23 | meta_properties = Dictionary[String, Variant]({})
24 | node_class = "SpotLight3D"
25 |
--------------------------------------------------------------------------------
/textures/mars/mars_cliff0_normal.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dyjxu15trhcjo"
6 | path.s3tc="res://.godot/imported/mars_cliff0_normal.png-71bb7ab7bfe3e16b3c34c3b96057d4ab.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://textures/mars/mars_cliff0_normal.png"
15 | dest_files=["res://.godot/imported/mars_cliff0_normal.png-71bb7ab7bfe3e16b3c34c3b96057d4ab.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/uastc_level=0
23 | compress/rdo_quality_loss=0.0
24 | compress/hdr_compression=1
25 | compress/normal_map=1
26 | compress/channel_pack=0
27 | mipmaps/generate=true
28 | mipmaps/limit=-1
29 | roughness/mode=1
30 | roughness/src_normal="res://textures/mars/mars_cliff0_normal.png"
31 | process/channel_remap/red=0
32 | process/channel_remap/green=1
33 | process/channel_remap/blue=2
34 | process/channel_remap/alpha=3
35 | process/fix_alpha_border=true
36 | process/premult_alpha=false
37 | process/normal_map_invert_y=false
38 | process/hdr_as_srgb=false
39 | process/hdr_clamp_exposure=false
40 | process/size_limit=0
41 | detect_3d/compress_to=0
42 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_slipgate.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bw74kacajcaxb"
6 | path="res://.godot/imported/icon_slipgate.svg-f42668b28b92f93c031f56d95dfcf5a6.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icons/icon_slipgate.svg"
14 | dest_files=["res://.godot/imported/icon_slipgate.svg-f42668b28b92f93c031f56d95dfcf5a6.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_godambler.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bm2kwpq18quv0"
6 | path="res://.godot/imported/icon_godambler.svg-a6dbba375ab2a45be046a1875b8d41e6.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icons/icon_godambler.svg"
14 | dest_files=["res://.godot/imported/icon_godambler.svg-a6dbba375ab2a45be046a1875b8d41e6.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_quake_file.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://c0464gp8lby0w"
6 | path="res://.godot/imported/icon_quake_file.svg-1718b9a2b5e0b124f6d72bb4c72d2ee6.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icons/icon_quake_file.svg"
14 | dest_files=["res://.godot/imported/icon_quake_file.svg-1718b9a2b5e0b124f6d72bb4c72d2ee6.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_slipgate3d.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cfvririkaa4tv"
6 | path="res://.godot/imported/icon_slipgate3d.svg-f125bef6ff5aa79b5fe3f232a083425e.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icons/icon_slipgate3d.svg"
14 | dest_files=["res://.godot/imported/icon_slipgate3d.svg-f125bef6ff5aa79b5fe3f232a083425e.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_godambler3d.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dieefivfbkovw"
6 | path="res://.godot/imported/icon_godambler3d.svg-f7df9bfe58320474198644aa06a8f3f6.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icons/icon_godambler3d.svg"
14 | dest_files=["res://.godot/imported/icon_godambler3d.svg-f7df9bfe58320474198644aa06a8f3f6.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_map_import_plugin.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name QuakeMapImportPlugin extends EditorImportPlugin
3 |
4 | func _get_importer_name() -> String:
5 | return 'func_godot.map'
6 |
7 | func _get_visible_name() -> String:
8 | return 'Quake Map'
9 |
10 | func _get_resource_type() -> String:
11 | return 'Resource'
12 |
13 | func _get_recognized_extensions() -> PackedStringArray:
14 | return PackedStringArray(['map','vmf'])
15 |
16 | func _get_priority():
17 | return 1.0
18 |
19 | func _get_save_extension() -> String:
20 | return 'tres'
21 |
22 | func _get_import_options(path, preset):
23 | return []
24 |
25 | func _get_preset_count() -> int:
26 | return 0
27 |
28 | func _get_import_order():
29 | return 0
30 |
31 | func _import(source_file, save_path, options, r_platform_variants, r_gen_files) -> Error:
32 | var save_path_str = '%s.%s' % [save_path, _get_save_extension()]
33 |
34 | var map_resource : QuakeMapFile = null
35 |
36 | if ResourceLoader.exists(save_path_str):
37 | map_resource = load(save_path_str) as QuakeMapFile
38 | map_resource.revision += 1
39 | else:
40 | map_resource = QuakeMapFile.new()
41 | map_resource.map_data = FileAccess.open(source_file, FileAccess.READ).get_as_text()
42 |
43 | return ResourceSaver.save(map_resource, save_path_str)
44 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_godot_ranger.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cfxlhjsefleff"
6 | path="res://.godot/imported/icon_godot_ranger.svg-8572582518f54de6403b767a923b5a92.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icons/icon_godot_ranger.svg"
14 | dest_files=["res://.godot/imported/icon_godot_ranger.svg-8572582518f54de6403b767a923b5a92.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_godot_ranger3d.svg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://brm515f5ivx8m"
6 | path="res://.godot/imported/icon_godot_ranger3d.svg-a9a2c9bcf2e8b1e07a0a941a16264e98.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://addons/func_godot/icons/icon_godot_ranger3d.svg"
14 | dest_files=["res://.godot/imported/icon_godot_ranger3d.svg-a9a2c9bcf2e8b1e07a0a941a16264e98.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/uastc_level=0
22 | compress/rdo_quality_loss=0.0
23 | compress/hdr_compression=1
24 | compress/normal_map=0
25 | compress/channel_pack=0
26 | mipmaps/generate=false
27 | mipmaps/limit=-1
28 | roughness/mode=0
29 | roughness/src_normal=""
30 | process/channel_remap/red=0
31 | process/channel_remap/green=1
32 | process/channel_remap/blue=2
33 | process/channel_remap/alpha=3
34 | process/fix_alpha_border=true
35 | process/premult_alpha=false
36 | process/normal_map_invert_y=false
37 | process/hdr_as_srgb=false
38 | process/hdr_clamp_exposure=false
39 | process/size_limit=0
40 | detect_3d/compress_to=1
41 | svg/scale=1.0
42 | editor/scale_with_editor_scale=false
43 | editor/convert_colors_with_editor_theme=false
44 |
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog_alb.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://byls0u3nbmhwk"
6 | path.s3tc="res://.godot/imported/marsfrog_alb.png-683f0d2999fb2bd78b55f20f87a979a4.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 | generator_parameters={
12 | "md5": "694a411562d0cbd5e87cb994a7bc9b8c"
13 | }
14 |
15 | [deps]
16 |
17 | source_file="res://entities/actors/marsfrog/marsfrog_alb.png"
18 | dest_files=["res://.godot/imported/marsfrog_alb.png-683f0d2999fb2bd78b55f20f87a979a4.s3tc.ctex"]
19 |
20 | [params]
21 |
22 | compress/mode=2
23 | compress/high_quality=false
24 | compress/lossy_quality=0.7
25 | compress/uastc_level=0
26 | compress/rdo_quality_loss=0.0
27 | compress/hdr_compression=1
28 | compress/normal_map=0
29 | compress/channel_pack=0
30 | mipmaps/generate=true
31 | mipmaps/limit=-1
32 | roughness/mode=0
33 | roughness/src_normal=""
34 | process/channel_remap/red=0
35 | process/channel_remap/green=1
36 | process/channel_remap/blue=2
37 | process/channel_remap/alpha=3
38 | process/fix_alpha_border=true
39 | process/premult_alpha=false
40 | process/normal_map_invert_y=false
41 | process/hdr_as_srgb=false
42 | process/hdr_clamp_exposure=false
43 | process/size_limit=0
44 | detect_3d/compress_to=0
45 |
--------------------------------------------------------------------------------
/entities/triggers/trigger_area.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name TriggerArea
3 | extends Area3D
4 |
5 | @export var target: String = ""
6 | @export var targetfunc: String = ""
7 | @export var targetname: String = ""
8 |
9 | enum TriggerStates {
10 | READY,
11 | USED
12 | }
13 | var trigger_state: TriggerStates = TriggerStates.READY
14 | var timeout: float = 0.0
15 | var last_activator: Node = null
16 |
17 | func _func_godot_apply_properties(props: Dictionary) -> void:
18 | target = props["target"] as String
19 | targetfunc = props["targetfunc"] as String
20 | targetname = props["targetname"] as String
21 |
22 | func toggle_collision(toggle: bool) -> void:
23 | for child in get_children():
24 | if child is CollisionShape3D:
25 | child.set_deferred("disabled", !toggle)
26 |
27 | func use() -> void:
28 | if trigger_state == TriggerStates.READY:
29 | trigger_state = TriggerStates.USED
30 | toggle_collision(false)
31 | GAME.use_targets(self, target)
32 |
33 | func _on_ent_entered(ent: Node) -> void:
34 | if trigger_state == TriggerStates.READY:
35 | if ent.is_in_group("PLAYER"):
36 | call("use")
37 |
38 | func _init() -> void:
39 | monitoring = true
40 | monitorable = false
41 | connect("body_entered", _on_ent_entered)
42 |
43 | func _ready() -> void:
44 | if Engine.is_editor_hint():
45 | return
46 | GAME.set_targetname(self, targetname)
47 |
--------------------------------------------------------------------------------
/fgd/fgd_solid.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=9 format=3 uid="uid://cnrh5xw6qygo7"]
2 |
3 | [ext_resource type="Resource" uid="uid://bdji3873bg32h" path="res://addons/func_godot/fgd/worldspawn.tres" id="1_bib3t"]
4 | [ext_resource type="Resource" uid="uid://bv37jafqtfyuw" path="res://fgd/solid/funcs/func_detail.tres" id="1_urecy"]
5 | [ext_resource type="Resource" uid="uid://4h23glniadlk" path="res://fgd/solid/funcs/func_detail_illusionary.tres" id="2_bib3t"]
6 | [ext_resource type="Resource" uid="uid://dbc8wa7c1nbgx" path="res://fgd/solid/funcs/func_geo.tres" id="3_t6ifc"]
7 | [ext_resource type="Resource" uid="uid://ckh3askbgkynt" path="res://fgd/solid/funcs/func_illusionary.tres" id="4_tg75m"]
8 | [ext_resource type="Resource" uid="uid://b3t000ocefkge" path="res://fgd/solid/funcs/func_move.tres" id="5_3sm66"]
9 | [ext_resource type="Resource" uid="uid://ptvum0fd8lvk" path="res://fgd/solid/triggers/trigger_area.tres" id="6_gsodn"]
10 | [ext_resource type="Script" uid="uid://drlmgulwbjwqu" path="res://addons/func_godot/src/fgd/func_godot_fgd_file.gd" id="7_82tb1"]
11 |
12 | [resource]
13 | script = ExtResource("7_82tb1")
14 | fgd_name = "SolidFGD"
15 | entity_definitions = Array[Resource]([ExtResource("1_bib3t"), ExtResource("1_urecy"), ExtResource("2_bib3t"), ExtResource("3_t6ifc"), ExtResource("4_tg75m"), ExtResource("5_3sm66"), ExtResource("6_gsodn")])
16 |
--------------------------------------------------------------------------------
/project.godot:
--------------------------------------------------------------------------------
1 | ; Engine configuration file.
2 | ; It's best edited using the editor UI and not directly,
3 | ; since the parameters that go here are not all obvious.
4 | ;
5 | ; Format:
6 | ; [section] ; section goes between []
7 | ; param=value ; assign values to parameters
8 |
9 | config_version=5
10 |
11 | [application]
12 |
13 | config/name="FuncGodot Example Basic"
14 | config/description="Example project showing how you might set up a project to use FuncGodot."
15 | config/tags=PackedStringArray("3d", "func_godot")
16 | run/main_scene="res://maps/example_basic.tscn"
17 | config/features=PackedStringArray("4.5", "Forward Plus")
18 | config/icon="res://icon.svg"
19 |
20 | [autoload]
21 |
22 | GAME="*res://game_manager.gd"
23 |
24 | [editor_plugins]
25 |
26 | enabled=PackedStringArray("res://addons/func_godot/plugin.cfg")
27 |
28 | [filesystem]
29 |
30 | import/blender/enabled=false
31 |
32 | [func_godot]
33 |
34 | model_point_class_save_path="fgd/models"
35 | default_map_settings="uid://cnci07xmp76ix"
36 |
37 | [importer_defaults]
38 |
39 | animation_library={
40 | &"fbx/embedded_image_handling": 0,
41 | &"gltf/embedded_image_handling": 0
42 | }
43 |
44 | [layer_names]
45 |
46 | 3d_physics/layer_1="WORLD"
47 | 3d_physics/layer_2="ACTOR"
48 | 3d_physics/layer_3="TRIGGER"
49 |
50 | [rendering]
51 |
52 | environment/defaults/default_clear_color=Color(0, 0, 0, 1)
53 | occlusion_culling/use_occlusion_culling=true
54 |
--------------------------------------------------------------------------------
/addons/func_godot/fgd/func_godot_fgd.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=9 format=3 uid="uid://crgpdahjaj"]
2 |
3 | [ext_resource type="Script" uid="uid://drlmgulwbjwqu" path="res://addons/func_godot/src/fgd/func_godot_fgd_file.gd" id="1_axt3h"]
4 | [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_ehab8"]
5 | [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="2_7jebp"]
6 | [ext_resource type="Resource" uid="uid://bdji3873bg32h" path="res://addons/func_godot/fgd/worldspawn.tres" id="2_ri2rx"]
7 | [ext_resource type="Resource" uid="uid://b70vf4t5dc70t" path="res://addons/func_godot/fgd/func_geo.tres" id="3_7jigp"]
8 | [ext_resource type="Resource" uid="uid://cxy7jnh6d7msn" path="res://addons/func_godot/fgd/func_detail.tres" id="3_fqfww"]
9 | [ext_resource type="Resource" uid="uid://dg5x44cc7flew" path="res://addons/func_godot/fgd/func_illusionary.tres" id="4_c4ucw"]
10 | [ext_resource type="Resource" uid="uid://ch3e0dix85uhb" path="res://addons/func_godot/fgd/func_detail_illusionary.tres" id="5_b2q3p"]
11 |
12 | [resource]
13 | script = ExtResource("1_axt3h")
14 | 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")])
15 |
--------------------------------------------------------------------------------
/fgd/game_cfg.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="TrenchBroomGameConfig" load_steps=9 format=3 uid="uid://cveiy7qr2d5yl"]
2 |
3 | [ext_resource type="Resource" uid="uid://37iduqf7tpxq" path="res://addons/func_godot/game_config/trenchbroom/tb_brush_tag_func.tres" id="1_kwmkr"]
4 | [ext_resource type="Resource" uid="uid://b4xhdj0e16lop" path="res://addons/func_godot/game_config/trenchbroom/tb_face_tag_clip.tres" id="1_ujsxt"]
5 | [ext_resource type="Resource" uid="uid://co2sb1ng7cw4i" path="res://addons/func_godot/game_config/trenchbroom/tb_brush_tag_trigger.tres" id="2_aoq2g"]
6 | [ext_resource type="Resource" uid="uid://ca7377sfgj074" path="res://addons/func_godot/game_config/trenchbroom/tb_face_tag_skip.tres" id="2_rcvc4"]
7 | [ext_resource type="Resource" uid="uid://tt4mj8flifi0" path="res://fgd/fgd_main.tres" id="5_437bd"]
8 | [ext_resource type="Resource" uid="uid://bkjxc54mmdhbo" path="res://addons/func_godot/game_config/trenchbroom/tb_face_tag_origin.tres" id="5_jdmi7"]
9 | [ext_resource type="Script" uid="uid://cx44c4vnq8bt5" path="res://addons/func_godot/src/trenchbroom/trenchbroom_game_config.gd" id="5_utngd"]
10 | [ext_resource type="Texture2D" uid="uid://decwujsyhj0qy" path="res://addons/func_godot/icon32.png" id="6_c23kf"]
11 |
12 | [resource]
13 | script = ExtResource("5_utngd")
14 | game_name = "FuncGodotExBasic"
15 | fgd_file = ExtResource("5_437bd")
16 | brush_tags = Array[Resource]([ExtResource("1_kwmkr"), ExtResource("2_aoq2g")])
17 |
--------------------------------------------------------------------------------
/entities/actors/marsfrog/marsfrog.glb.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="scene"
4 | importer_version=1
5 | type="PackedScene"
6 | uid="uid://b63vvdlr5ocvn"
7 | path="res://.godot/imported/marsfrog.glb-d77d52e9218295f8f5b930b8ba836df9.scn"
8 |
9 | [deps]
10 |
11 | source_file="res://entities/actors/marsfrog/marsfrog.glb"
12 | dest_files=["res://.godot/imported/marsfrog.glb-d77d52e9218295f8f5b930b8ba836df9.scn"]
13 |
14 | [params]
15 |
16 | nodes/root_type=""
17 | nodes/root_name=""
18 | nodes/root_script=null
19 | nodes/apply_root_scale=true
20 | nodes/root_scale=1.0
21 | nodes/import_as_skeleton_bones=false
22 | nodes/use_name_suffixes=true
23 | nodes/use_node_type_suffixes=true
24 | meshes/ensure_tangents=true
25 | meshes/generate_lods=true
26 | meshes/create_shadow_meshes=true
27 | meshes/light_baking=0
28 | meshes/lightmap_texel_size=0.2
29 | meshes/force_disable_compression=false
30 | skins/use_named_skins=true
31 | animation/import=true
32 | animation/fps=30
33 | animation/trimming=false
34 | animation/remove_immutable_tracks=true
35 | animation/import_rest_as_RESET=false
36 | import_script/path=""
37 | materials/extract=0
38 | materials/extract_format=0
39 | materials/extract_path=""
40 | _subresources={
41 | "materials": {
42 | "marsfrog_mat": {
43 | "use_external/enabled": true,
44 | "use_external/fallback_path": "res://entities/actors/marsfrog/marsfrog_mat.tres",
45 | "use_external/path": "uid://cxi8hlnm8hb80"
46 | }
47 | }
48 | }
49 | gltf/naming_version=1
50 | gltf/embedded_image_handling=0
51 |
--------------------------------------------------------------------------------
/game_manager.gd:
--------------------------------------------------------------------------------
1 | class_name GameManager
2 | extends Node
3 |
4 | # Common inverse scale. Calculated as 1.0 / Inverse Scale Factor.
5 | # Used to help translate properties using Quake Units into Godot Units.
6 | const INVERSE_SCALE: float = 0.03125
7 |
8 | enum {
9 | WORLD_LAYER = (1 << 0),
10 | ACTOR_LAYER = (1 << 1),
11 | TRIGGER_LAYER = (1 << 2)
12 | }
13 |
14 | func use_targets(activator: Node, target: String) -> void:
15 | # Targetnames are really Godot Groups, so we can have multiple entities
16 | # share a common "targetname" in Trenchbroom.
17 | var target_list: Array[Node] = get_tree().get_nodes_in_group(target)
18 | for targ in target_list:
19 | var f: String
20 | # Be careful when specifying a function since we can't pass arguments
21 | # to it (without hackarounds of course)
22 | if 'targetfunc' in activator:
23 | f = activator.targetfunc
24 | if f.is_empty():
25 | f = "use"
26 | if targ.has_method(f):
27 | targ.call(f)
28 |
29 | func set_targetname(node: Node, targetname: String) -> void:
30 | if node != null and not targetname.is_empty():
31 | node.add_to_group(targetname)
32 |
33 | # Converts Quake 1 axis to Godot axis
34 | static func id_vec_to_godot_vec(vec: Variant)->Vector3:
35 | var org: Vector3 = Vector3.ZERO
36 | if vec is Vector3:
37 | org = vec
38 | elif vec is String:
39 | var arr: PackedFloat64Array = (vec as String).split_floats(" ")
40 | for i in max(arr.size(), 3):
41 | org[i] = arr[i]
42 | return Vector3(org.y, org.z, org.x)
43 |
--------------------------------------------------------------------------------
/fgd/solid/funcs/func_move.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDSolidClass" load_steps=5 format=3 uid="uid://b3t000ocefkge"]
2 |
3 | [ext_resource type="Resource" uid="uid://d4buv26pirxbl" path="res://fgd/base/func_base.tres" id="1_gjl7v"]
4 | [ext_resource type="Resource" uid="uid://cwbnifad3sdgw" path="res://fgd/base/targetname_base.tres" id="2_r0b3n"]
5 | [ext_resource type="Script" uid="uid://5cow84q03m6a" path="res://addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd" id="3_8hfld"]
6 | [ext_resource type="Script" uid="uid://drubv8qcibmw0" path="res://entities/funcs/func_move.gd" id="4_nd4f8"]
7 |
8 | [resource]
9 | script = ExtResource("3_8hfld")
10 | collision_shape_type = 2
11 | collision_mask = 0
12 | script_class = ExtResource("4_nd4f8")
13 | classname = "func_move"
14 | description = "Movable and rotatable geometry. Valid move functions are use, toggle, mv_forward, and mv_reverse."
15 | base_classes = Array[Resource]([ExtResource("1_gjl7v"), ExtResource("2_r0b3n")])
16 | class_properties = Dictionary[String, Variant]({
17 | "move_pos": Vector3(0, 0, 0),
18 | "move_rot": Vector3(0, 0, 0),
19 | "speed": 3.0
20 | })
21 | class_property_descriptions = Dictionary[String, Variant]({
22 | "move_pos": "Relative destination position in Quake Units. This will be converted into Godot Units in the FuncMove script.",
23 | "move_rot": "Rotation destination in degrees."
24 | })
25 | meta_properties = Dictionary[String, Variant]({
26 | "color": Color(0, 0.8, 0, 1)
27 | })
28 | node_class = "AnimatableBody3D"
29 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_palette_import_plugin.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name QuakePaletteImportPlugin extends EditorImportPlugin
3 |
4 | func _get_importer_name() -> String:
5 | return 'func_godot.palette'
6 |
7 | func _get_visible_name() -> String:
8 | return 'Quake Palette'
9 |
10 | func _get_resource_type() -> String:
11 | return 'Resource'
12 |
13 | func _get_recognized_extensions() -> PackedStringArray:
14 | return PackedStringArray(['lmp'])
15 |
16 | func _get_save_extension() -> String:
17 | return 'tres'
18 |
19 | func _get_import_options(path, preset):
20 | return []
21 |
22 | func _get_preset_count() -> int:
23 | return 0
24 |
25 | func _get_priority():
26 | return 1.0
27 |
28 | func _get_import_order():
29 | return 0
30 |
31 | func _import(source_file, save_path, options, r_platform_variants, r_gen_files) -> Error:
32 | var save_path_str : String = '%s.%s' % [save_path, _get_save_extension()]
33 |
34 | var file = FileAccess.open(source_file, FileAccess.READ)
35 | if file == null:
36 | var err = FileAccess.get_open_error()
37 | printerr(['Error opening super.lmp file: ', err])
38 | return err
39 |
40 | var colors := PackedColorArray()
41 |
42 | while true:
43 | var red : int = file.get_8()
44 | var green : int = file.get_8()
45 | var blue : int = file.get_8()
46 | var color := Color(red / 255.0, green / 255.0, blue / 255.0)
47 |
48 | colors.append(color)
49 |
50 | if file.eof_reached():
51 | break
52 |
53 | if colors.size() == 256:
54 | break
55 |
56 | var palette_resource := QuakePaletteFile.new(colors)
57 |
58 | return ResourceSaver.save(palette_resource, save_path_str)
59 |
--------------------------------------------------------------------------------
/fgd/fgd_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDFile" load_steps=11 format=3 uid="uid://n5ccclg387jb"]
2 |
3 | [ext_resource type="Resource" uid="uid://nayxb8n7see2" path="res://addons/func_godot/fgd/phong_base.tres" id="1_aenro"]
4 | [ext_resource type="Resource" uid="uid://kerywjgft7vh" path="res://fgd/base/target_base.tres" id="1_m1gva"]
5 | [ext_resource type="Resource" uid="uid://cwbnifad3sdgw" path="res://fgd/base/targetname_base.tres" id="2_4ppmx"]
6 | [ext_resource type="Resource" uid="uid://syvs5beg2j3q" path="res://fgd/base/globalname_base.tres" id="3_aenro"]
7 | [ext_resource type="Resource" uid="uid://3com3yjkcsvg" path="res://fgd/base/actor_base.tres" id="4_yqjuy"]
8 | [ext_resource type="Resource" uid="uid://d4buv26pirxbl" path="res://fgd/base/func_base.tres" id="5_4ajyw"]
9 | [ext_resource type="Resource" uid="uid://dukx4b4xgo1o2" path="res://fgd/base/light_base.tres" id="6_6cnu1"]
10 | [ext_resource type="Resource" uid="uid://hnx0olvm0jt2" path="res://fgd/base/trigger_base.tres" id="7_pja5h"]
11 | [ext_resource type="Resource" uid="uid://doo4ly322b4jc" path="res://addons/func_godot/fgd/vertex_merge_distance_base.tres" id="8_4ppmx"]
12 | [ext_resource type="Script" uid="uid://drlmgulwbjwqu" path="res://addons/func_godot/src/fgd/func_godot_fgd_file.gd" id="8_idr1e"]
13 |
14 | [resource]
15 | script = ExtResource("8_idr1e")
16 | fgd_name = "BaseFGD"
17 | entity_definitions = Array[Resource]([ExtResource("1_aenro"), ExtResource("8_4ppmx"), ExtResource("1_m1gva"), ExtResource("2_4ppmx"), ExtResource("3_aenro"), ExtResource("4_yqjuy"), ExtResource("5_4ajyw"), ExtResource("6_6cnu1"), ExtResource("7_pja5h")])
18 |
--------------------------------------------------------------------------------
/fgd/base/light_base.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDBaseClass" load_steps=3 format=3 uid="uid://dukx4b4xgo1o2"]
2 |
3 | [ext_resource type="Resource" uid="uid://syvs5beg2j3q" path="res://fgd/base/globalname_base.tres" id="1_jhrkn"]
4 | [ext_resource type="Script" uid="uid://ck575aqs1sbrb" path="res://addons/func_godot/src/fgd/func_godot_fgd_base_class.gd" id="2_oyf81"]
5 |
6 | [resource]
7 | script = ExtResource("2_oyf81")
8 | classname = "Light"
9 | base_classes = Array[Resource]([ExtResource("1_jhrkn")])
10 | class_properties = Dictionary[String, Variant]({
11 | "color": Color(1, 1, 1, 1),
12 | "energy": 1.0,
13 | "indirect_energy": 1.0,
14 | "shadow_bias": 0.1,
15 | "shadows": false
16 | })
17 | class_property_descriptions = Dictionary[String, Variant]({
18 | "color": "The light's color.",
19 | "energy": "The light's strength multiplier. For OmniLight3D and SpotLight3D, changing this value will only change the light color's intensity, not the light's radius.",
20 | "indirect_energy": "The light's strength multiplier. For OmniLight3D and SpotLight3D, changing this value will only change the light color's intensity, not the light's radius.",
21 | "shadow_bias": "Used to adjust shadow appearance. Too small a value results in self-shadowing, while too large a value causes shadows to separate from casters. Adjust as needed.",
22 | "shadows": "If true, the light will cast real-time shadows. This has a significant performance cost. Only enable shadow rendering when it makes a noticeable difference in the scene's appearance"
23 | })
24 | meta_properties = Dictionary[String, Variant]({
25 | "color": Color(0.8, 0.8, 0, 1),
26 | "size": AABB(-8, -8, -8, 8, 8, 8)
27 | })
28 |
--------------------------------------------------------------------------------
/addons/func_godot/src/trenchbroom/trenchbroom_tag.gd:
--------------------------------------------------------------------------------
1 | @icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
2 | class_name TrenchBroomTag extends Resource
3 | ## Pattern matching tag added to [TrenchbroomGameConfig] for appearance and menu filtering purposes.
4 | ##
5 | ## Pattern matching tags to enable a number of features in TrenchBroom, including display appearance and menu filtering options.
6 | ## This resource gets added to the [TrenchBroomGameConfig] resource. Does not affect appearance or functionality in Godot.
7 | ##
8 | ## @tutorial(TrenchBroom Manual Game Configuration): https://trenchbroom.github.io/manual/latest/#game_configuration_files
9 | ## @tutorial(TrenchBroom Manual Special Brush Face Types): https://trenchbroom.github.io/manual/latest/#special_brush_face_types
10 |
11 | enum TagMatchType {
12 | TEXTURE, ## Tag applies to any brush face with a texture matching the texture name.
13 | CLASSNAME ## Tag applies to any brush entity with a class name matching the tag pattern.
14 | }
15 |
16 | ## Name to define this tag. Not used as the matching pattern.
17 | @export var tag_name: String
18 |
19 | ## The attributes applied to matching faces or brush entities. Only "_transparent" is supported in TrenchBroom, which makes matching faces or brush entities transparent.
20 | @export var tag_attributes : Array[String] = ["transparent"]
21 |
22 | ## Determines how the tag is matched. See [constant TagMatchType].
23 | @export var tag_match_type: TagMatchType
24 |
25 | ## A string that filters which flag, param, or classname to use. [code]*[/code] can be used as a wildcard to include multiple options.
26 | ## [b]Example:[/b] [code]trigger*[/code] with [constant TagMatchType] [i]Classname[/i] will apply this tag to all brush entities with the [code]trigger[/code] prefix.
27 | @export var tag_pattern: String
28 |
29 | ## A string that filters which textures recieve these attributes. Only used with a [constant TagMatchType] of [i]Texture[/i].
30 | @export var texture_name: String
31 |
--------------------------------------------------------------------------------
/entities/funcs/func_move.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name FuncMove
3 | extends AnimatableBody3D
4 |
5 | @export var func_godot_properties: Dictionary = {}
6 | @export var targetname: String = ""
7 | @export var move_pos: Array[Vector3] = [Vector3.ZERO, Vector3.ZERO]
8 | @export var move_rot: Vector3 = Vector3.ZERO
9 | @export var speed: float = 3.0
10 |
11 | enum MoveStates {
12 | READY,
13 | MOVE
14 | }
15 | var move_state: MoveStates = MoveStates.READY
16 | var move_progress: float = 0.0
17 | var move_progress_target: float = 0.0
18 | var sfx: AudioStreamPlayer3D
19 |
20 | func _func_godot_apply_properties(props: Dictionary) -> void:
21 | targetname = props["targetname"] as String
22 | move_pos[1] = GameManager.id_vec_to_godot_vec(props["move_pos"]) * GameManager.INVERSE_SCALE
23 | if props["move_rot"] is Vector3:
24 | var r: Vector3 = props["move_rot"]
25 | for i in 3:
26 | move_rot[i] = deg_to_rad(r[i])
27 | speed = props["speed"] as float
28 |
29 | func mv_forward() -> void:
30 | move_progress_target = 1.0
31 |
32 | func mv_reverse() -> void:
33 | move_progress_target = 0.0
34 |
35 | func use() -> void:
36 | mv_forward()
37 |
38 | func toggle() -> void:
39 | if move_progress_target > 0.0:
40 | mv_reverse()
41 | else:
42 | mv_forward()
43 |
44 | func _init() -> void:
45 | add_to_group("func_move")
46 | sync_to_physics = false
47 |
48 | func _ready() -> void:
49 | if Engine.is_editor_hint():
50 | return
51 |
52 | GAME.set_targetname(self, targetname)
53 | move_pos[0] = position
54 | move_pos[1] += move_pos[0]
55 | if speed > 0.0:
56 | speed = 1.0 / speed
57 |
58 | func _physics_process(delta: float) -> void:
59 | if Engine.is_editor_hint():
60 | return
61 |
62 | if move_progress != move_progress_target:
63 | if move_progress < move_progress_target:
64 | move_progress = minf(move_progress + speed * delta, move_progress_target)
65 | elif move_progress > move_progress_target:
66 | move_progress = maxf(move_progress - speed * delta, move_progress_target)
67 | if move_pos[0] != move_pos[1]:
68 | position = move_pos[0].lerp(move_pos[1], move_progress)
69 | if move_rot != Vector3.ZERO:
70 | rotation = Vector3.ZERO.lerp(move_rot, move_progress)
71 |
--------------------------------------------------------------------------------
/fgd/point/info_camera.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Resource" script_class="FuncGodotFGDPointClass" load_steps=8 format=3 uid="uid://drhgccbh1koh8"]
2 |
3 | [ext_resource type="Resource" uid="uid://cwbnifad3sdgw" path="res://fgd/base/targetname_base.tres" id="1_cwtgh"]
4 | [ext_resource type="Resource" uid="uid://syvs5beg2j3q" path="res://fgd/base/globalname_base.tres" id="2_xxigy"]
5 | [ext_resource type="Script" uid="uid://cxsqwtsqd8w33" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class.gd" id="3_r12kb"]
6 | [ext_resource type="Script" uid="uid://d1nwwgcrner8b" path="res://addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd" id="3_xxigy"]
7 | [ext_resource type="Script" uid="uid://cm1d60bvyoko4" path="res://entities/info_camera.gd" id="4_6u0ol"]
8 |
9 | [sub_resource type="Resource" id="Resource_r12kb"]
10 | script = ExtResource("3_xxigy")
11 | display_asset_path = "\"fgd/models/map_obj_camera_active.glb\""
12 | conditional = "active == 1"
13 | metadata/_custom_type_script = "uid://d1nwwgcrner8b"
14 |
15 | [sub_resource type="Resource" id="Resource_xxigy"]
16 | script = ExtResource("3_xxigy")
17 | display_asset_path = "\"fgd/models/map_obj_camera.glb\""
18 | metadata/_custom_type_script = "uid://d1nwwgcrner8b"
19 |
20 | [resource]
21 | script = ExtResource("3_r12kb")
22 | script_class = ExtResource("4_6u0ol")
23 | display_descriptors = Array[ExtResource("3_xxigy")]([SubResource("Resource_r12kb"), SubResource("Resource_xxigy")])
24 | classname = "info_camera"
25 | description = "Info Camera"
26 | base_classes = Array[Resource]([ExtResource("1_cwtgh"), ExtResource("2_xxigy")])
27 | class_properties = Dictionary[String, Variant]({
28 | "active": false,
29 | "angles": Vector3(0, 0, 0),
30 | "camera_target": ""
31 | })
32 | class_property_descriptions = Dictionary[String, Variant]({
33 | "active": "If activeSets camera's current property. If multiple cameras have active set to true, the viewport will pick the most recent one.",
34 | "angles": "Camera orientation.",
35 | "camera_target": "This camera will actively follow the node with this globalname."
36 | })
37 | meta_properties = Dictionary[String, Variant]({
38 | "color": Color(0, 0.8, 0.8, 1),
39 | "model": "{{active == 1 -> \"fgd/models/map_obj_camera_active.glb\", active == 0 -> \"fgd/models/map_obj_camera.glb\", \"fgd/models/map_obj_camera.glb\" }}",
40 | "size": AABB(-8, -8, -8, 8, 8, 8)
41 | })
42 | node_class = "Camera3D"
43 |
--------------------------------------------------------------------------------
/entities/actors/actor.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name Actor
3 | extends CharacterBody3D
4 |
5 | enum ActorFlags {
6 | PLAYER = 1,
7 | BIG_FRIEND = 2,
8 | ATTENTIVE_FRIEND = 4,
9 | HAPPY_FRIEND = 8
10 | }
11 | @export var flags: int = 0
12 | @export var targetname: String
13 |
14 | enum ActorStates {
15 | NORMAL = 0,
16 | SCRIPTED = 1
17 | }
18 | var current_state: int = ActorStates.NORMAL
19 |
20 | var on_floor: bool = false
21 |
22 | var move_input: Vector3 = Vector3.ZERO
23 | var speed: float = 3.0
24 | var jump_strength: float = 5.0
25 | const GRAVITY: float = 10.0
26 | var anim_player: AnimationPlayer
27 |
28 | func _func_godot_apply_properties(props: Dictionary) -> void:
29 | add_to_group(props["classname"] as String)
30 | flags = props["flags"] as int
31 | if flags & ActorFlags.BIG_FRIEND:
32 | scale *= 2
33 |
34 | func turn_towards_pos(tgt_pos: Vector3) -> void:
35 | var b: Basis = global_transform.basis
36 | tgt_pos -= global_position
37 | var tgt_dir: Vector3 = tgt_pos - tgt_pos.project(b.y)
38 | tgt_dir = tgt_dir.normalized()
39 | b.y = b.y.normalized()
40 |
41 | var rot_amount: float = -b.z.dot(tgt_dir)
42 | if rot_amount > 0.999:
43 | return
44 | if rot_amount <= -1.0:
45 | rot_amount = PI
46 | else:
47 | rot_amount = acos(rot_amount)
48 | rot_amount *= sign(-b.z.rotated(b.y, 1.570796).dot(tgt_dir))
49 | rotate(b.y, rot_amount)
50 |
51 | func _init() -> void:
52 | collision_layer = GameManager.ACTOR_LAYER + GameManager.TRIGGER_LAYER
53 | collision_mask = GameManager.WORLD_LAYER + GameManager.TRIGGER_LAYER
54 |
55 | func _ready() -> void:
56 | if Engine.is_editor_hint():
57 | return
58 | if flags & ActorFlags.PLAYER:
59 | add_to_group("PLAYER")
60 | GAME.set_targetname(self, targetname)
61 |
62 | func _process(_delta: float) -> void:
63 | if Engine.is_editor_hint():
64 | return
65 |
66 | if flags & ActorFlags.PLAYER:
67 | move_input.z = Input.get_axis("ui_up", "ui_down")
68 | move_input.x = Input.get_axis("ui_right", "ui_left")
69 | move_input.y = float(Input.is_action_just_pressed("ui_accept"))
70 |
71 | func _physics_process(delta) -> void:
72 | if Engine.is_editor_hint():
73 | return
74 |
75 | var current_fall_speed: float = velocity.y
76 | if on_floor:
77 | current_fall_speed = move_input.y * jump_strength
78 | current_fall_speed -= GRAVITY * delta
79 | velocity = global_transform.basis.z * move_input.z * speed
80 | velocity.y += current_fall_speed
81 | rotate_y(PI * move_input.x * delta)
82 | move_and_slide()
83 | on_floor = is_on_floor()
84 |
85 | if (flags & ActorFlags.ATTENTIVE_FRIEND) and not (flags & ActorFlags.PLAYER):
86 | var players: Array[Node] = get_tree().get_nodes_in_group("PLAYER")
87 | for pl in players:
88 | if pl is Actor:
89 | turn_towards_pos(pl.global_position)
90 | break
91 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_slipgate.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_slipgate3d.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_point_class_display_descriptor.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_godambler3d.svg")
3 | class_name FuncGodotFGDPointClassDisplayDescriptor extends Resource
4 | ## Resource that describes how to display an FGD Point Class entity.
5 | ##
6 | ## A resource for [FuncGodotFGDPointClass] that describes how to display a point entity in a map editor.
7 | ## Values entered into the different options are taken literally: paths should be enclosed within quotation marks,
8 | ## while class property keys and integer values should omit them.[br][br]
9 | ##
10 | ## Most editors only support the [member display_asset] option. Exporting an FGD compatible with these editors will
11 | ## automatically omit the unsupported options introduced by TrenchBroom when exporting from their respective game configuration resources
12 | ## or setting [member FuncGodotFGDFile.target_map_editor] away from [enum FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM].
13 | ##
14 | ## The extra options are considered advanced features and are unable to be evaluated by FuncGodot to ensure they were input correctly.
15 | ## Exercise caution, care, and patience when attempting to use these, especially the [member conditional] option.
16 | ##
17 | ## @tutorial(Level Design Book: Display Models for Entities): https://book.leveldesignbook.com/appendix/resources/formats/fgd#display-models-for-entities
18 | ## @tutorial(Valve Developer Wiki FGD Article: Entity Description Section): https://developer.valvesoftware.com/wiki/FGD#Entity_Description
19 | ## @tutorial(TrenchBroom Manual: Display Models for Entities): https://trenchbroom.github.io/manual/latest/#display-models-for-entities
20 | ## @tutorial(TrenchBroom Manual: Expression Language): https://trenchbroom.github.io/manual/latest/#expression_language
21 |
22 | ## Either a file path to the asset that will be displayed for this point entity, relative to the map editor's game path,
23 | ## or a class property key that can contain the path.[br][br]
24 | ## For paths, you must surround the path with quotes, e.g: [code]"models/marsfrog.glb"[/code].
25 | ## For properties, you must omit the quotes, e.g: [code]display_model_path[/code].[br][br]
26 | ## Different editors support different file types: common ones include MDL, GLB, SPR, and PNG.
27 | @export var display_asset_path: String = ""
28 |
29 | @export_group("TrenchBroom Options")
30 | ## Optional string that determines the scale of the display asset. This can be a number, a class property key, or
31 | ## a scale expression in accordance with TrenchBroom's Expression Language. Leave blank to use the game configuration's default scale expression.[br][br]
32 | ## [color=orange]WARNING:[/color] Only utilized by TrenchBroom!
33 | @export var scale: String = ""
34 |
35 | ## Optional string that determines which skin the display asset should use. This can be either a number or a class property key.[br][br]
36 | ## [color=orange]WARNING:[/color] Only utilized by TrenchBroom!
37 | @export var skin: String = ""
38 |
39 | ## 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]
40 | ## 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).
41 | ## GLBs meanwhile seem to set themselves to the animation assigned to an index that matches the [code]frame[/code] value.[br][br]
42 | ## [color=orange]WARNING:[/color] Only utilized by TrenchBroom!
43 | @export var frame: String = ""
44 |
45 | ## Optional evaluation string that, when true, will force the Point Class to display the asset defined by [member display_asset_path].
46 | ## Format should be [code]property == value[/code] or some other valid expression in accordance with TrenchBroom's Expression Language.[br][br]
47 | ## [color=orange]WARNING:[/color] Only utilized by TrenchBroom!
48 | @export var conditional: String = ""
49 |
--------------------------------------------------------------------------------
/addons/func_godot/src/func_godot_plugin.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
3 | class_name FuncGodotPlugin extends EditorPlugin
4 |
5 | var map_import_plugin : QuakeMapImportPlugin = null
6 | var palette_import_plugin : QuakePaletteImportPlugin = null
7 | var wad_import_plugin: QuakeWadImportPlugin = null
8 |
9 | #var func_godot_map_progress_bar: Control = null
10 | var edited_object_ref: WeakRef = weakref(null)
11 |
12 | func _get_plugin_name() -> String:
13 | return "FuncGodot"
14 |
15 | func _handles(object: Object) -> bool:
16 | return object is FuncGodotMap
17 |
18 | func _edit(object: Object) -> void:
19 | edited_object_ref = weakref(object)
20 |
21 | #func _make_visible(visible: bool) -> void:
22 | #if func_godot_map_progress_bar:
23 | #func_godot_map_progress_bar.set_visible(visible)
24 |
25 | func _enter_tree() -> void:
26 | # Import plugins
27 | map_import_plugin = QuakeMapImportPlugin.new()
28 | palette_import_plugin = QuakePaletteImportPlugin.new()
29 | wad_import_plugin = QuakeWadImportPlugin.new()
30 |
31 | add_import_plugin(map_import_plugin)
32 | add_import_plugin(palette_import_plugin)
33 | add_import_plugin(wad_import_plugin)
34 |
35 | #func_godot_map_progress_bar = create_func_godot_map_progress_bar()
36 | #func_godot_map_progress_bar.set_visible(false)
37 | #add_control_to_container(EditorPlugin.CONTAINER_INSPECTOR_BOTTOM, func_godot_map_progress_bar)
38 |
39 | add_custom_type("FuncGodotMap", "Node3D", preload("res://addons/func_godot/src/map/func_godot_map.gd"), null)
40 |
41 | # Default Map Settings
42 | if not ProjectSettings.has_setting("func_godot/default_map_settings"):
43 | ProjectSettings.set_setting("func_godot/default_map_settings", "res://addons/func_godot/func_godot_default_map_settings.tres")
44 | var property_info = {
45 | "name": "func_godot/default_map_settings",
46 | "type": TYPE_STRING,
47 | "hint": PROPERTY_HINT_FILE,
48 | "hint_string": "*.tres"
49 | }
50 | ProjectSettings.add_property_info(property_info)
51 | ProjectSettings.set_as_basic("func_godot/default_map_settings", true)
52 | ProjectSettings.set_initial_value("func_godot/default_map_settings", "res://addons/func_godot/func_godot_default_map_settings.tres")
53 |
54 | # Default Inverse Scale Factor
55 | if not ProjectSettings.has_setting("func_godot/default_inverse_scale_factor"):
56 | ProjectSettings.set_setting("func_godot/default_inverse_scale_factor", 32.0)
57 | var property_info = {
58 | "name": "func_godot/default_inverse_scale_factor",
59 | "type": TYPE_FLOAT
60 | }
61 | ProjectSettings.add_property_info(property_info)
62 | ProjectSettings.set_as_basic("func_godot/default_inverse_scale_factor", true)
63 | ProjectSettings.set_initial_value("func_godot/default_inverse_scale_factor", 32.0)
64 |
65 | # Model Point Class Default Path
66 | if not ProjectSettings.has_setting("func_godot/model_point_class_save_path"):
67 | ProjectSettings.set_setting("func_godot/model_point_class_save_path", "")
68 | var property_info = {
69 | "name": "func_godot/model_point_class_save_path",
70 | "type": TYPE_STRING
71 | }
72 | ProjectSettings.add_property_info(property_info)
73 | ProjectSettings.set_as_basic("func_godot/model_point_class_save_path", true)
74 | ProjectSettings.set_initial_value("func_godot/model_point_class_save_path", "")
75 |
76 | func _exit_tree() -> void:
77 | remove_custom_type("FuncGodotMap")
78 | remove_import_plugin(map_import_plugin)
79 | remove_import_plugin(palette_import_plugin)
80 | if wad_import_plugin:
81 | remove_import_plugin(wad_import_plugin)
82 |
83 | map_import_plugin = null
84 | palette_import_plugin = null
85 | wad_import_plugin = null
86 |
87 | #if func_godot_map_progress_bar:
88 | #remove_control_from_container(EditorPlugin.CONTAINER_INSPECTOR_BOTTOM, func_godot_map_progress_bar)
89 | #func_godot_map_progress_bar.queue_free()
90 | #func_godot_map_progress_bar = null
91 |
92 | # Create a progress bar for building a [FuncGodotMap]
93 | #func create_func_godot_map_progress_bar() -> Control:
94 | #var progress_label = Label.new()
95 | #progress_label.name = "ProgressLabel"
96 | #progress_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
97 | #progress_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
98 | #
99 | #var progress_bar := ProgressBar.new()
100 | #progress_bar.name = "ProgressBar"
101 | #progress_bar.show_percentage = false
102 | #progress_bar.min_value = 0.0
103 | #progress_bar.max_value = 1.0
104 | #progress_bar.custom_minimum_size.y = 30
105 | #progress_bar.set_anchors_and_offsets_preset(Control.PRESET_LEFT_WIDE)
106 | #progress_bar.add_child(progress_label)
107 | #progress_label.set_anchors_and_offsets_preset(Control.PRESET_LEFT_WIDE)
108 | #progress_label.offset_top = -9
109 | #progress_label.offset_left = 3
110 | #
111 | #return progress_bar
112 |
113 | # Update the build progress bar (see: [method create_func_godot_map_progress_bar]) to display the current step and progress (0-1)
114 | #func func_godot_map_build_progress(step: String, progress: float) -> void:
115 | #var progress_label = func_godot_map_progress_bar.get_node("ProgressLabel")
116 | #func_godot_map_progress_bar.value = progress
117 | #progress_label.text = step.capitalize()
118 |
119 | ## Callback for when the build process for a [FuncGodotMap] is finished.
120 | func func_godot_map_build_complete(func_godot_map: FuncGodotMap) -> void:
121 | #var progress_label = func_godot_map_progress_bar.get_node("ProgressLabel")
122 | #progress_label.text = "Build Complete"
123 |
124 | #if func_godot_map.is_connected("build_progress",Callable(self,"func_godot_map_build_progress")):
125 | #func_godot_map.disconnect("build_progress",Callable(self,"func_godot_map_build_progress"))
126 |
127 | if func_godot_map.is_connected("build_complete",Callable(self,"func_godot_map_build_complete")):
128 | func_godot_map.disconnect("build_complete",Callable(self,"func_godot_map_build_complete"))
129 |
130 | if func_godot_map.is_connected("build_failed",Callable(self,"func_godot_map_build_complete")):
131 | func_godot_map.disconnect("build_failed",Callable(self,"func_godot_map_build_complete"))
132 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_point_class.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_godambler3d.svg")
3 | class_name FuncGodotFGDPointClass extends FuncGodotFGDEntityClass
4 | ## FGD PointClass entity definition.
5 | ##
6 | ## A resource used to define an FGD Point Class entity. PointClass entities can use either the [member FuncGodotFGDEntityClass.node_class]
7 | ## or the [member scene_file] property to tell [FuncGodotMap] what to generate on map build.
8 | ##
9 | ## @tutorial(Quake Wiki Entity Article): https://quakewiki.org/wiki/Entity
10 | ## @tutorial(Level Design Book: Entity Types and Settings): https://book.leveldesignbook.com/appendix/resources/formats/fgd#entity-types-and-settings-basic
11 | ## @tutorial(Valve Developer Wiki FGD Article): https://developer.valvesoftware.com/wiki/FGD#Class_Types_and_Properties
12 | ## @tutorial(dumptruck_ds' Quake Mapping Entities Tutorial): https://www.youtube.com/watch?v=gtL9f6_N2WM
13 | ## @tutorial(Level Design Book: Display Models for Entities): https://book.leveldesignbook.com/appendix/resources/formats/fgd#display-models-for-entities
14 | ## @tutorial(Valve Developer Wiki FGD Article: Entity Description Section): https://developer.valvesoftware.com/wiki/FGD#Entity_Description
15 | ## @tutorial(TrenchBroom Manual: Display Models for Entities): https://trenchbroom.github.io/manual/latest/#display-models-for-entities
16 |
17 | func _init() -> void:
18 | prefix = "@PointClass"
19 |
20 | ## An optional [PackedScene] file to instantiate on map build. Overrides [member FuncGodotFGDEntityClass.node_class] and [member script_class].
21 | @export var scene_file: PackedScene
22 |
23 | ## An optional [Script] resource to attach to the node generated on map build. Ignored if [member scene_file] is specified.
24 | @export var script_class: Script
25 |
26 | ## Toggles whether entity will use `angles`, `mangle`, or `angle` to determine rotations on [FuncGodotMap] build, prioritizing the key value pairs in that order.
27 | ## Set to [code]false[/code] if you would like to define how the generated node is rotated yourself.
28 | @export var apply_rotation_on_map_build : bool = true
29 |
30 | ## Toggles whether entity will use `scale` to determine the generated node or scene's scale. This is performed on the top level node.
31 | ## 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.
32 | @export var apply_scale_on_map_build: bool = true
33 |
34 | ## An optional [Array] of [FuncGodotFGDPointClassDisplayDescriptor] that describes how this Point Entity should appear in the map editor.
35 | ## When using multiple display descriptors, only the first element found without [member FuncGodotFGDPointClassDisplayDescriptor.conditional]
36 | ## 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]
37 | ## Conditional display descriptors will be written to the FGD in the order set in the array.[br][br]
38 | ## [color=orange]WARNING:[/color] Multiple descriptors are only supported by TrenchBroom! They will be omitted on export when
39 | ## [member FuncGodotFGDFile.target_map_editor] is not set to [enum FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM].
40 | @export var display_descriptors: Array[FuncGodotFGDPointClassDisplayDescriptor] = []
41 |
42 | func _build_model_branch_text(descriptor: FuncGodotFGDPointClassDisplayDescriptor) -> String:
43 | if not descriptor:
44 | return ''
45 |
46 | var model_string: String = ''
47 | var uses_options: bool = false
48 |
49 | if not descriptor.scale.is_empty() or not descriptor.skin.is_empty() or not descriptor.frame.is_empty():
50 | uses_options = true
51 |
52 | if not uses_options:
53 | return descriptor.display_asset_path
54 |
55 | model_string = '{ \"path\": %s' % descriptor.display_asset_path
56 |
57 | if not descriptor.skin.is_empty():
58 | model_string += ', \"skin\": %s' % descriptor.skin
59 | if not descriptor.frame.is_empty():
60 | model_string += ', \"frame\": % s' % descriptor.frame
61 | if not descriptor.scale.is_empty():
62 | model_string += ', \"scale\": %s' % descriptor.scale
63 |
64 | model_string += " }"
65 |
66 | return model_string
67 |
68 | func _build_model_text() -> String:
69 | var model_string: String = ''
70 |
71 | if display_descriptors.is_empty():
72 | return model_string
73 |
74 | if display_descriptors.size() == 1:
75 | return _build_model_branch_text(display_descriptors[0])
76 |
77 | model_string = '{{'
78 | var default_display: FuncGodotFGDPointClassDisplayDescriptor
79 | for i in display_descriptors.size():
80 | var d: FuncGodotFGDPointClassDisplayDescriptor = display_descriptors[i]
81 |
82 | # Only set the first discovered descriptor without a condition to the default, which must be the last option in a list.
83 | # If a conditional is not set, skip it.
84 | if d.conditional.is_empty():
85 | if not default_display:
86 | default_display = d
87 | else:
88 | printerr(classname + " has a Point Class Display Descriptor without required conditionals set. Must have only 1 conditionless Display Descriptor!")
89 | continue
90 |
91 | model_string += '%s -> %s, ' % [d.conditional, _build_model_branch_text(d)]
92 |
93 | if not default_display:
94 | default_display = display_descriptors[-1]
95 |
96 | model_string += '%s }}' % _build_model_branch_text(default_display)
97 | return model_string
98 |
99 | func _build_studio_text() -> String:
100 | var display_string = ""
101 | for d in display_descriptors:
102 | if d.display_asset_path.find('\"') != -1:
103 | display_string = d.display_asset_path
104 | else:
105 | printerr(classname + " attempting to set an invalid value to @studio format during FGD export. Only relative file paths encapsulated by quotations are valid.")
106 | return display_string
107 |
108 | func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM) -> String:
109 | if not display_descriptors.is_empty():
110 | if target_editor == FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM:
111 | var display_string: String = _build_model_text()
112 | if not display_string.is_empty():
113 | meta_properties["model"] = display_string
114 | else:
115 | var display_string: String = _build_studio_text()
116 | if not display_string.is_empty():
117 | meta_properties["studio"] = display_string
118 | return super(target_editor)
119 |
--------------------------------------------------------------------------------
/addons/func_godot/src/util/func_godot_local_config.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
3 | class_name FuncGodotLocalConfig extends Resource
4 | ## Local machine project wide settings. [color=red]WARNING![/color] Do not create your own! Use the resource in [i]addons/func_godot[/i].
5 | ##
6 | ## Local machine project wide settings. Can define global defaults for some FuncGodot properties.
7 | ## [color=red][b]DO NOT CREATE A NEW RESOURCE![/b][/color] This resource works by saving a configuration file to your game's [b][i]user://[/i][/b] folder
8 | ## and pulling the properties from that config file rather than this resource. Use the premade [b][i]addons/func_godot/func_godot_local_config.tres[/i][/b] instead.
9 | ## [br][br]
10 | ## [b]Fgd Output Folder :[/b] Global directory path that [FuncGodotFGDFile] saves to when exported. Overridden when exported from a game configuration resource like [TrenchBroomGameConfig].[br][br]
11 | ## [b]Trenchbroom Game Config Folder :[/b] Global directory path where your TrenchBroom game configuration should be saved to. Consult the [url="https://trenchbroom.github.io/manual/latest/#game_configuration_files"]TrenchBroom Manual's Game Configuration documentation[/url] for more information.[br][br]
12 | ## [b]Netradiant Custom Gamepacks Folder :[/b] Global directory path where your NetRadiant Custom gamepacks are saved. On Windows this is the [i]gamepacks[/i] folder in your NetRadiant Custom installation.[br][br]
13 | ## [b]Map Editor Game Path :[/b] Global directory path to your mapping folder where all of your mapping assets exist. This is usually either your project folder or a subfolder within it.[br][br]
14 | ## [b]Game Path Models Folder :[/b] Relative directory path from your Map Editor Game Path to a subfolder containing any display models you might use for your map editor. Currently only used by [FuncGodotFGDModelPointClass].[br][br]
15 | ## [b]Default Inverse Scale Factor :[/b] Scale factor that affects how [FuncGodotFGDModelPointClass] entities scale their map editor display models. Not used with TrenchBroom, use [member TrenchBroomGameConfig.entity_scale] expression instead.[br][br]
16 |
17 | enum PROPERTY {
18 | FGD_OUTPUT_FOLDER,
19 | TRENCHBROOM_GAME_CONFIG_FOLDER,
20 | NETRADIANT_CUSTOM_GAMEPACKS_FOLDER,
21 | MAP_EDITOR_GAME_PATH,
22 | #GAME_PATH_MODELS_FOLDER,
23 | #DEFAULT_INVERSE_SCALE
24 | }
25 |
26 | @export_tool_button("Export func_godot settings", "Save") var _save_settings = export_func_godot_settings
27 | @export_tool_button("Reload func_godot settings", "Reload") var _load_settings = reload_func_godot_settings
28 |
29 | const _CONFIG_PROPERTIES: Array[Dictionary] = [
30 | {
31 | "name": "fgd_output_folder",
32 | "usage": PROPERTY_USAGE_EDITOR,
33 | "type": TYPE_STRING,
34 | "hint": PROPERTY_HINT_GLOBAL_DIR,
35 | "func_godot_type": PROPERTY.FGD_OUTPUT_FOLDER
36 | },
37 | {
38 | "name": "trenchbroom_game_config_folder",
39 | "usage": PROPERTY_USAGE_EDITOR,
40 | "type": TYPE_STRING,
41 | "hint": PROPERTY_HINT_GLOBAL_DIR,
42 | "func_godot_type": PROPERTY.TRENCHBROOM_GAME_CONFIG_FOLDER
43 | },
44 | {
45 | "name": "netradiant_custom_gamepacks_folder",
46 | "usage": PROPERTY_USAGE_EDITOR,
47 | "type": TYPE_STRING,
48 | "hint": PROPERTY_HINT_GLOBAL_DIR,
49 | "func_godot_type": PROPERTY.NETRADIANT_CUSTOM_GAMEPACKS_FOLDER
50 | },
51 | {
52 | "name": "map_editor_game_path",
53 | "usage": PROPERTY_USAGE_EDITOR,
54 | "type": TYPE_STRING,
55 | "hint": PROPERTY_HINT_GLOBAL_DIR,
56 | "func_godot_type": PROPERTY.MAP_EDITOR_GAME_PATH
57 | },
58 | ]
59 |
60 | var _settings_dict: Dictionary
61 | var _loaded := false
62 |
63 | ## Retrieve a setting from the local configuration.
64 | static func get_setting(name: PROPERTY) -> Variant:
65 | var settings: FuncGodotLocalConfig = load("res://addons/func_godot/func_godot_local_config.tres")
66 | settings.reload_func_godot_settings()
67 | return settings._settings_dict.get(PROPERTY.keys()[name], '') as Variant
68 |
69 | func _get_property_list() -> Array:
70 | return _CONFIG_PROPERTIES.duplicate()
71 |
72 | func _get(property: StringName) -> Variant:
73 | var config = _get_config_property(property)
74 | if config == null and not config is Dictionary:
75 | return null
76 | _try_loading()
77 | return _settings_dict.get(PROPERTY.keys()[config['func_godot_type']], _get_default_value(config['type']))
78 |
79 | func _set(property: StringName, value: Variant) -> bool:
80 | var config = _get_config_property(property)
81 | if config == null and not config is Dictionary:
82 | return false
83 | _settings_dict[PROPERTY.keys()[config['func_godot_type']]] = value
84 | return true
85 |
86 | func _get_default_value(type) -> Variant:
87 | match type:
88 | TYPE_STRING: return ''
89 | TYPE_INT: return 0
90 | TYPE_FLOAT: return 0.0
91 | TYPE_BOOL: return false
92 | TYPE_VECTOR2: return Vector2.ZERO
93 | TYPE_VECTOR3: return Vector3.ZERO
94 | TYPE_ARRAY: return []
95 | TYPE_DICTIONARY: return {}
96 | push_error("Invalid setting type. Returning null")
97 | return null
98 |
99 | func _get_config_property(name: StringName) -> Variant:
100 | for config in _CONFIG_PROPERTIES:
101 | if config['name'] == name:
102 | return config
103 | return null
104 |
105 | ## Reload this system's configuration settings into the Local Config resource.
106 | func reload_func_godot_settings() -> void:
107 | _loaded = true
108 | var path = "user://func_godot_config.json"
109 | if not FileAccess.file_exists(path):
110 | var application_name: String = ProjectSettings.get('application/config/name')
111 | application_name = application_name.replace(" ", "_")
112 | path = "user://" + application_name + "_FuncGodotConfig.json"
113 | if not FileAccess.file_exists(path):
114 | return
115 | var settings = FileAccess.get_file_as_string(path)
116 | _settings_dict = {}
117 | if not settings or settings.is_empty():
118 | return
119 | settings = JSON.parse_string(settings)
120 | for key in settings.keys():
121 | _settings_dict[key] = settings[key]
122 | notify_property_list_changed()
123 |
124 | func _try_loading() -> void:
125 | if not _loaded:
126 | reload_func_godot_settings()
127 |
128 | ## Export the current resource settings to a configuration file in this game's [i]user://[/i] folder.
129 | func export_func_godot_settings() -> void:
130 | if _settings_dict.size() == 0:
131 | return
132 | var path = "user://func_godot_config.json"
133 | var file = FileAccess.open(path, FileAccess.WRITE)
134 | var json = JSON.stringify(_settings_dict)
135 | file.store_line(json)
136 | _loaded = false
137 | print("Saved settings to ", file.get_path_absolute())
138 |
--------------------------------------------------------------------------------
/addons/func_godot/src/import/quake_wad_import_plugin.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | class_name QuakeWadImportPlugin extends EditorImportPlugin
3 |
4 | enum WadFormat {
5 | Quake,
6 | HalfLife
7 | }
8 |
9 | enum QuakeWadEntryType {
10 | Palette = 0x40,
11 | SBarPic = 0x42,
12 | MipsTexture = 0x44,
13 | ConsolePic = 0x45
14 | }
15 |
16 | enum HalfLifeWadEntryType {
17 | QPic = 0x42,
18 | MipsTexture = 0x43,
19 | FixedFont = 0x45
20 | }
21 |
22 | const TEXTURE_NAME_LENGTH := 16
23 | const MAX_MIP_LEVELS := 4
24 |
25 | func _get_importer_name() -> String:
26 | return 'func_godot.wad'
27 |
28 | func _get_visible_name() -> String:
29 | return 'Quake WAD'
30 |
31 | func _get_resource_type() -> String:
32 | return 'Resource'
33 |
34 | func _get_recognized_extensions() -> PackedStringArray:
35 | return PackedStringArray(['wad'])
36 |
37 | func _get_save_extension() -> String:
38 | return 'res'
39 |
40 | func _get_option_visibility(path: String, option_name: StringName, options: Dictionary) -> bool:
41 | return true
42 |
43 | func _get_import_options(path, preset) -> Array[Dictionary]:
44 | return [
45 | {
46 | 'name': 'palette_file',
47 | 'default_value': 'res://addons/func_godot/palette.lmp',
48 | 'property_hint': PROPERTY_HINT_FILE,
49 | 'hint_string': '*.lmp'
50 | },
51 | {
52 | 'name': 'generate_mipmaps',
53 | 'default_value': true,
54 | 'property_hint': PROPERTY_HINT_NONE
55 | }
56 | ]
57 |
58 | func _get_preset_count() -> int:
59 | return 0
60 |
61 | func _get_import_order() -> int:
62 | return 0
63 |
64 | func _get_priority() -> float:
65 | return 1.0
66 |
67 | func _import(source_file, save_path, options, r_platform_variants, r_gen_files) -> Error:
68 | var save_path_str : String = '%s.%s' % [save_path, _get_save_extension()]
69 |
70 | var file = FileAccess.open(source_file, FileAccess.READ)
71 | if file == null:
72 | var err = FileAccess.get_open_error()
73 | printerr(['Error opening super.wad file: ', err])
74 | return err
75 |
76 | # Read WAD header
77 | var magic : PackedByteArray = file.get_buffer(4)
78 | var magic_string : String = magic.get_string_from_ascii()
79 | var wad_format: int = WadFormat.Quake
80 |
81 | if magic_string == 'WAD3':
82 | wad_format = WadFormat.HalfLife
83 | elif magic_string != 'WAD2':
84 | printerr('Error: Invalid WAD magic')
85 | return ERR_INVALID_DATA
86 |
87 | var palette_path : String = options['palette_file']
88 | var palette_file : QuakePaletteFile = load(palette_path) as QuakePaletteFile
89 | if wad_format == WadFormat.Quake and not palette_file:
90 | printerr('Error: Invalid Quake palette file')
91 | file.close()
92 | return ERR_CANT_ACQUIRE_RESOURCE
93 |
94 | var num_entries : int = file.get_32()
95 | var dir_offset : int = file.get_32()
96 |
97 | # Read entry list
98 | file.seek(0)
99 | file.seek(dir_offset)
100 |
101 | var entries : Array = []
102 |
103 | for entry_idx in range(0, num_entries):
104 | var offset : int = file.get_32()
105 | var in_wad_size : int = file.get_32()
106 | var size : int = file.get_32()
107 | var type : int = file.get_8()
108 | var compression : int = file.get_8()
109 | var unknown : int = file.get_16()
110 | var name : PackedByteArray = file.get_buffer(TEXTURE_NAME_LENGTH)
111 | var name_string : String = name.get_string_from_ascii()
112 |
113 | if (wad_format == WadFormat.Quake and type == int(QuakeWadEntryType.MipsTexture)) or (
114 | wad_format == WadFormat.HalfLife and type == int(HalfLifeWadEntryType.MipsTexture)):
115 | entries.append([
116 | offset,
117 | in_wad_size,
118 | size,
119 | type,
120 | compression,
121 | name_string
122 | ])
123 |
124 | # Read mip textures
125 | var texture_data_array: Array = []
126 | for entry in entries:
127 | var offset : int = entry[0]
128 | file.seek(offset)
129 |
130 | var name : PackedByteArray = file.get_buffer(TEXTURE_NAME_LENGTH)
131 | var name_string : String = name.get_string_from_ascii()
132 |
133 | var width : int = file.get_32()
134 | var height : int = file.get_32()
135 |
136 | var mip_offsets : Array = []
137 | for idx in range(0, MAX_MIP_LEVELS):
138 | mip_offsets.append(file.get_32())
139 |
140 | var num_pixels : int = width * height
141 | var pixels : PackedByteArray = file.get_buffer(num_pixels)
142 |
143 | if wad_format == WadFormat.Quake:
144 | texture_data_array.append([name_string, width, height, pixels])
145 | continue
146 | # Half-Life WADs have a 256 color palette embedded in each texture
147 | elif wad_format == WadFormat.HalfLife:
148 | # Find the end of the mipmap data
149 | file.seek(offset + mip_offsets[-1] + (width / 8) * (height / 8))
150 | file.get_16()
151 |
152 | var palette_colors := PackedColorArray()
153 | for idx in 256:
154 | var red : int = file.get_8()
155 | var green : int = file.get_8()
156 | var blue : int = file.get_8()
157 | var color := Color(red / 255.0, green / 255.0, blue / 255.0)
158 | palette_colors.append(color)
159 |
160 | texture_data_array.append([name_string, width, height, pixels, palette_colors])
161 |
162 | # Create texture resources
163 | var textures : Dictionary[String, ImageTexture] = {}
164 |
165 | for texture_data in texture_data_array:
166 | var name : String = texture_data[0]
167 | var width : int = texture_data[1]
168 | var height : int = texture_data[2]
169 | var pixels : PackedByteArray = texture_data[3]
170 |
171 | var texture_image : Image
172 | var pixels_rgb := PackedByteArray()
173 |
174 | if wad_format == WadFormat.HalfLife:
175 | var colors : PackedColorArray = texture_data[4]
176 | for palette_color in pixels:
177 | var rgb_color : Color = colors[palette_color]
178 | pixels_rgb.append(rgb_color.r8)
179 | pixels_rgb.append(rgb_color.g8)
180 | pixels_rgb.append(rgb_color.b8)
181 | # Color(0, 0, 255) is used for transparency in Half-Life
182 | if rgb_color.b == 1 and rgb_color.r == 0 and rgb_color.b == 0:
183 | pixels_rgb.append(0)
184 | else:
185 | pixels_rgb.append(255)
186 | texture_image = Image.create_from_data(width, height, false, Image.FORMAT_RGBA8, pixels_rgb)
187 |
188 | else: # WadFormat.Quake
189 | for palette_color in pixels:
190 | var rgb_color : Color = palette_file.colors[palette_color]
191 | pixels_rgb.append(rgb_color.r8)
192 | pixels_rgb.append(rgb_color.g8)
193 | pixels_rgb.append(rgb_color.b8)
194 | # Palette index 255 is used for transparency
195 | if palette_color != 255:
196 | pixels_rgb.append(255)
197 | else:
198 | pixels_rgb.append(0)
199 | texture_image = Image.create_from_data(width, height, false, Image.FORMAT_RGBA8, pixels_rgb)
200 |
201 | if options["generate_mipmaps"] == true:
202 | texture_image.generate_mipmaps()
203 |
204 | var texture := ImageTexture.create_from_image(texture_image) #,Texture2D.FLAG_MIPMAPS | Texture2D.FLAG_REPEAT | Texture2D.FLAG_ANISOTROPIC_FILTER
205 | textures[name.to_lower()] = texture
206 |
207 | # Save WAD resource
208 | var wad_resource := QuakeWadFile.new(textures)
209 | return ResourceSaver.save(wad_resource, save_path_str)
210 |
--------------------------------------------------------------------------------
/addons/func_godot/src/map/func_godot_map.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_slipgate3d.svg")
3 | class_name FuncGodotMap extends Node3D
4 | ## Scene generator node that parses a [QuakeMapFile] according to its [FuncGodotMapSettings].
5 | ##
6 | ## A scene generator node that parses a [QuakeMapFile]. It uses a [FuncGodotMapSettings]
7 | ## and the [FuncGodotFGDFile] contained within in order to determine what is built and how it is built.[br][br]
8 | ## If your map is not building correctly, double check your [member map_settings] to make sure you're using
9 | ## the correct [FuncGodotMapSettings].
10 |
11 | const _SIGNATURE: String = "[MAP]"
12 |
13 | ## Bitflag settings that control various aspects of the build process.
14 | enum BuildFlags {
15 | UNWRAP_UV2 = 1 << 0, ## Unwrap UV2s during geometry generation for lightmap baking.
16 | SHOW_PROFILE_INFO = 1 << 1, ## Print build step information during build process.
17 | DISABLE_SMOOTHING = 1 << 2 ## Force disable processing of vertex normal smooth shading.
18 | }
19 |
20 | ## Emitted when the build process fails.
21 | signal build_failed
22 |
23 | ## Emitted when the build process succesfully completes.
24 | signal build_complete
25 |
26 | @export_tool_button("Build Map","CollisionShape3D") var _build_func: Callable = build
27 | @export_tool_button("Clear Map","Skeleton3D") var _clear_func: Callable = clear_children
28 |
29 | @export_category("Map")
30 | ## Local path to MAP or VMF file to build a scene from.
31 | @export_file("*.map","*.vmf") var local_map_file: String = ""
32 |
33 | ## Global path to MAP or VMF file to build a scene from. Overrides [member FuncGodotMap.local_map_file].
34 | @export_global_file("*.map","*.vmf") var global_map_file: String = ""
35 |
36 | # Map path used by code. Do it this way to support both global and local paths.
37 | var _map_file_internal: String = ""
38 |
39 | ## Map settings resource that defines map build scale, textures location, entity definitions, and more.
40 | @export var map_settings: FuncGodotMapSettings = load(ProjectSettings.get_setting("func_godot/default_map_settings", "res://addons/func_godot/func_godot_default_map_settings.tres"))
41 |
42 | @export_category("Build")
43 | ## [enum BuildFlags] that can affect certain aspects of the build process.
44 | @export_flags("Unwrap UV2:1", "Show Profiling Info:2", "Disable Smooth Shading:4") var build_flags: int = 0
45 |
46 | ## The hyperplane is an initial plane that all geometry faces are cut from, like a large sheet of marble before a sculptor begins chiseling.
47 | ## The hyperplane size would need to be able to cover your map's potential total area.
48 | ## Smaller values can minimize floating point errors, reducing the effect of gaps between polygon seams.
49 | ## Measured in Godot units, not Quake units.
50 | @export_range(256.0, 2048.0, 128.0) var hyperplane_size: float = 512.0
51 |
52 | ## Map build failure handler. Displays error message and emits [signal build_failed] signal.
53 | func fail_build(reason: String, notify: bool = false) -> void:
54 | push_error(_SIGNATURE, " ", reason)
55 | if notify:
56 | build_failed.emit()
57 |
58 | ## Frees all children of the map node.[br]
59 | ## [b][color=yellow]Warning:[/color][/b] This does not distinguish between nodes generated in the FuncGodot build process and other user created nodes.
60 | func clear_children() -> void:
61 | for child in get_children():
62 | remove_child(child)
63 | child.queue_free()
64 |
65 | ## Checks if a [QuakeMapFile] for the build process is provided and can be found.
66 | func verify() -> Error:
67 | # Prioritize global map file path for building at runtime
68 | _map_file_internal = global_map_file if global_map_file != "" else local_map_file
69 |
70 | if _map_file_internal.is_empty():
71 | fail_build("Cannot build empty map file.")
72 | return ERR_INVALID_PARAMETER
73 |
74 | # Retrieve real path if needed
75 | if _map_file_internal.begins_with("uid://"):
76 | var uid := ResourceUID.text_to_id(_map_file_internal)
77 | if not ResourceUID.has_id(uid):
78 | fail_build("Error: failed to retrieve path for UID (%s)" % _map_file_internal)
79 | return ERR_DOES_NOT_EXIST
80 | _map_file_internal = ResourceUID.get_id_path(uid)
81 |
82 | if not FileAccess.file_exists(_map_file_internal):
83 | if not FileAccess.file_exists(_map_file_internal + ".import"):
84 | fail_build("Map file %s does not exist." % _map_file_internal)
85 | return ERR_DOES_NOT_EXIST
86 |
87 | return OK
88 |
89 | ## Builds the [member global_map_file]. If not set, builds the [member local_map_file].
90 | ## First cleans the map node of any children, then creates a [FuncGodotParser], [FuncGodotGeometryGenerator]
91 | ## and [FuncGodotEntityAssembler] to parse and generate the map.
92 | func build() -> void:
93 | var time_elapsed: float = Time.get_ticks_msec()
94 |
95 | if build_flags & BuildFlags.SHOW_PROFILE_INFO:
96 | FuncGodotUtil.print_profile_info("Building...", _SIGNATURE)
97 |
98 | clear_children()
99 |
100 | var verify_err: Error = verify()
101 | if verify_err != OK:
102 | fail_build("Verification failed: %s. Aborting map build" % error_string(verify_err), true)
103 | return
104 |
105 | if not map_settings:
106 | push_warning("Map assembler does not have a map settings provided and will use default map settings.")
107 | load(ProjectSettings.get_setting("func_godot/default_map_settings", "res://addons/func_godot/func_godot_default_map_settings.tres"))
108 |
109 | # Parse and collect map data
110 | var parser := FuncGodotParser.new()
111 | if build_flags & BuildFlags.SHOW_PROFILE_INFO:
112 | print("\nPARSER")
113 | parser.declare_step.connect(FuncGodotUtil.print_profile_info.bind(parser._SIGNATURE))
114 | var parse_data: FuncGodotData.ParseData = parser.parse_map_data(_map_file_internal, map_settings)
115 |
116 | if parse_data.entities.is_empty():
117 | return # Already printed failure message in parser, just return here
118 |
119 | var entities: Array[FuncGodotData.EntityData] = parse_data.entities
120 | var groups: Array[FuncGodotData.GroupData] = parse_data.groups
121 |
122 | # Free up some memory now that we have the data
123 | parser = null
124 |
125 | # Retrieve geometry
126 | var generator := FuncGodotGeometryGenerator.new(map_settings, hyperplane_size)
127 | if build_flags & BuildFlags.SHOW_PROFILE_INFO:
128 | print("\nGEOMETRY GENERATOR")
129 | generator.declare_step.connect(FuncGodotUtil.print_profile_info.bind(generator._SIGNATURE))
130 |
131 | # Generate surface and shape data
132 | var generate_error := generator.build(build_flags, entities)
133 | if generate_error != OK:
134 | fail_build("Geometry generation failed: %s" % error_string(generate_error))
135 | return
136 |
137 | # Assemble entities and groups
138 | var assembler := FuncGodotEntityAssembler.new(map_settings)
139 | if build_flags & BuildFlags.SHOW_PROFILE_INFO:
140 | print("\nENTITY ASSEMBLER")
141 | assembler.declare_step.connect(FuncGodotUtil.print_profile_info.bind(assembler._SIGNATURE))
142 | assembler.build(self, entities, groups)
143 |
144 | time_elapsed = Time.get_ticks_msec() - time_elapsed
145 |
146 | if build_flags & BuildFlags.SHOW_PROFILE_INFO:
147 | print("\nCompleted in %s seconds" % (time_elapsed / 1000.0))
148 |
149 | if build_flags & BuildFlags.SHOW_PROFILE_INFO:
150 | print("")
151 | FuncGodotUtil.print_profile_info("Build complete", _SIGNATURE)
152 | build_complete.emit()
153 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_quake_file.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
86 |
--------------------------------------------------------------------------------
/addons/func_godot/src/map/func_godot_map_settings.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
3 | class_name FuncGodotMapSettings extends Resource
4 | ## Reusable map settings configuration for [FuncGodotMap] nodes.
5 |
6 | #region BUILD
7 | @export_group("Build Settings")
8 |
9 | ## Set automatically when [member inverse_scale_factor] is changed. Used primarily during the build process.
10 | var scale_factor: float = 0.03125
11 |
12 | ## Ratio between map editor units and Godot units. FuncGodot will divide brush coordinates by this number and save the results to [member scale_factor].
13 | ## This does not affect entity properties unless scripted to do so.
14 | @export var inverse_scale_factor: float = 32.0 :
15 | set(value):
16 | if value == 0.0:
17 | printerr("Error: Cannot set Inverse Scale Factor to Zero")
18 | return
19 | inverse_scale_factor = value
20 | scale_factor = 1.0 / value
21 |
22 | ## [FuncGodotFGDFile] that translates map file classnames into Godot nodes and packed scenes.
23 | @export var entity_fgd: FuncGodotFGDFile = preload("res://addons/func_godot/fgd/func_godot_fgd.tres")
24 |
25 | ## If true, will organize [SceneTree] using TrenchBroom Layers and Groups or Hammer Visgroups. Groups will be generated as [Node3D] nodes.
26 | ## All non-entity structural brushes will be moved out of their groups and merged into the `Worldspawn` entity.
27 | ## Any Layers toggled to be omitted from export in TrenchBroom and their child entities and groups will not be built.
28 | @export var use_groups_hierarchy: bool = false
29 |
30 | ## Texel size for UV2 unwrapping.
31 | ## 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
32 | ## (if inverse_scale_factor is 32, start with a uv_unwrap_texel_size of 2).
33 | ## Larger values will produce less detailed lightmaps. To conserve memory and filesize, use the largest value that still looks good.
34 | @export var uv_unwrap_texel_size: float = 2.0
35 |
36 | #endregion
37 |
38 | #region ENTITY
39 | @export_group("Entity Settings")
40 |
41 | ## Optional array of node groups to add all generated nodes to.
42 | @export var entity_node_groups: Array[String] = []
43 |
44 | @export_subgroup("Entity Property Names")
45 | ## Default class property to use in naming generated nodes. This setting is overridden by [member FuncGodotFGDEntityClass.name_property].
46 | ## Naming occurs before adding to the [SceneTree] and applying properties.
47 | ## Nodes will be named `"entity_" + name_property`. An entity's name should be unique, otherwise you may run into unexpected behavior.
48 | @export var entity_name_property: String = ""
49 |
50 | ## Class property that determines whether the [FuncGodotFGDSolidClass] entity performs mesh smoothing operations.
51 | @export var entity_smoothing_property: String = "_phong"
52 |
53 | ## Class property that contains the angular threshold that determines when a [FuncGodotFGDSolidClass] entity's mesh vertices are smoothed.
54 | @export var entity_smoothing_angle_property: String = "_phong_angle"
55 |
56 | ## Class property that contains the snapping epsilon for generated vertices of [FuncGodotFGDSolidClass] entities.
57 | ## Utilizing this property can help reduce instances of seams between polygons.
58 | @export var vertex_merge_distance_property: String = "_vertex_merge_distance"
59 |
60 | @export_subgroup("")
61 | #endregion
62 |
63 | #region TEXTURES
64 | @export_group("Textures")
65 |
66 | ## 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.
67 | @export_dir var base_texture_dir: String = "res://textures"
68 |
69 | ## File extensions to search for texture data.
70 | @export var texture_file_extensions: Array[String] = ["png", "jpg", "jpeg", "bmp", "tga", "webp"]
71 |
72 | @export_subgroup("Hint Textures")
73 | ## Optional path for the clip texture, relative to [member base_texture_dir].
74 | ## Brush faces textured with the clip texture will have those faces removed from the generated [Mesh] but not the generated [Shape3D].
75 | @export var clip_texture: String = "clip":
76 | set(tex):
77 | clip_texture = tex.to_lower()
78 |
79 | ## Optional path for the skip texture, relative to [member base_texture_dir].
80 | ## Brush faces textured with the skip texture will have those faces removed from the generated [Mesh].
81 | ## If [member FuncGodotFGDSolidClass.collision_shape_type] is set to concave then it will also remove collision from those faces in the generated [Shape3D].
82 | @export var skip_texture: String = "skip":
83 | set(tex):
84 | skip_texture = tex.to_lower()
85 |
86 | ## Optional path for the origin texture, relative to [member base_texture_dir].
87 | ## Brush faces textured with the origin texture will have those faces removed from the generated [Mesh] and [Shape3D].
88 | ## The bounds of these faces will be used to calculate the origin point of the entity.
89 | @export var origin_texture: String = "origin":
90 | set(tex):
91 | origin_texture = tex.to_lower()
92 | @export_subgroup("")
93 |
94 | ## Optional [QuakeWadFile] resources to apply textures from. See the [Quake Wiki](https://quakewiki.org/wiki/Texture_Wad) for more information on Quake Texture WADs.
95 | @export var texture_wads: Array[QuakeWadFile] = []
96 |
97 | #endregion
98 |
99 | #region MATERIALS
100 | @export_group("Materials")
101 |
102 | ## Base directory for loading and saving materials. When building materials, FuncGodot will search this directory for material resources
103 | ## with matching names to the textures assigned to map brush faces. If not found, will fall back to [member base_texture_dir].
104 | @export_dir var base_material_dir: String = ""
105 |
106 | ## File extension to search for [Material] definitions
107 | @export var material_file_extension: String = "tres"
108 |
109 | ## [Material] used as template when generating missing materials.
110 | @export var default_material: Material = preload("res://addons/func_godot/textures/default_material.tres")
111 |
112 | ## Sampler2D uniform that supplies the Albedo in a custom shader when [member default_material] is a [ShaderMaterial].
113 | @export var default_material_albedo_uniform: String = ""
114 |
115 | ## Automatic [ShaderMaterial] generation mapping patterns. Only used when [member default_material] is a ShaderMaterial.
116 | ## Keys should be the names of the shader uniforms while the values should be the suffixes for the texture maps.
117 | ## Patterns only use one replacement String: the texture name, ex: [code]"%s_normal"[/code].
118 | @export var shader_material_uniform_map_patterns: Dictionary[String, String] = {}
119 |
120 | @export_subgroup("BaseMaterial3D Map Patterns")
121 | ## Automatic PBR material generation albedo map pattern.
122 | @export var albedo_map_pattern: String = "%s_albedo"
123 | ## Automatic PBR material generation normal map pattern.
124 | @export var normal_map_pattern: String = "%s_normal"
125 | ## Automatic PBR material generation metallic map pattern
126 | @export var metallic_map_pattern: String = "%s_metallic"
127 | ## Automatic PBR material generation roughness map pattern
128 | @export var roughness_map_pattern: String = "%s_roughness"
129 | ## Automatic PBR material generation emission map pattern
130 | @export var emission_map_pattern: String = "%s_emission"
131 | ## Automatic PBR material generation ambient occlusion map pattern
132 | @export var ao_map_pattern: String = "%s_ao"
133 | ## Automatic PBR material generation height map pattern
134 | @export var height_map_pattern: String = "%s_height"
135 | ## Automatic PBR material generation ORM map pattern
136 | @export var orm_map_pattern: String = "%s_orm"
137 | @export_subgroup("")
138 |
139 | ## Save automatically generated materials to disk, allowing reuse across [FuncGodotMap] nodes.
140 | ## [i]NOTE: Materials do not use the [member default_material] settings after saving.[/i]
141 | @export var save_generated_materials: bool = true
142 | @export_group("")
143 |
144 | #endregion
145 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_file.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
3 | class_name FuncGodotFGDFile extends Resource
4 | ## [Resource] file used to express a set of [FuncGodotFGDEntity] definitions.
5 | ##
6 | ## Can be exported as an FGD file for use with a Quake or Hammer-based map editor. Used in conjunction with [FuncGodotMapSetting] to generate nodes in a [FuncGodotMap] node.
7 | ##
8 | ## @tutorial(Level Design Book FGD Chapter): https://book.leveldesignbook.com/appendix/resources/formats/fgd
9 | ## @tutorial(Valve Developer Wiki FGD Article): https://developer.valvesoftware.com/wiki/FGD
10 |
11 | ## Supported map editors enum, used in conjunction with [member target_map_editor].
12 | enum FuncGodotTargetMapEditors {
13 | OTHER,
14 | TRENCHBROOM,
15 | JACK,
16 | NET_RADIANT_CUSTOM,
17 | }
18 |
19 | ## Builds and exports the FGD file.
20 | @export_tool_button("Export FGD") var export_file := export_button
21 |
22 | func export_button() -> void:
23 | do_export_file(target_map_editor)
24 |
25 | func do_export_file(target_editor: FuncGodotTargetMapEditors = FuncGodotTargetMapEditors.TRENCHBROOM, fgd_output_folder: String = "") -> void:
26 | if fgd_output_folder.is_empty():
27 | fgd_output_folder = FuncGodotLocalConfig.get_setting(FuncGodotLocalConfig.PROPERTY.FGD_OUTPUT_FOLDER) as String
28 | if fgd_output_folder.is_empty():
29 | printerr("Skipping export: No game config folder")
30 | return
31 |
32 | if fgd_name == "":
33 | printerr("Skipping export: Empty FGD name")
34 |
35 | if not DirAccess.dir_exists_absolute(fgd_output_folder):
36 | if DirAccess.make_dir_recursive_absolute(fgd_output_folder) != OK:
37 | printerr("Skipping export: Failed to create directory")
38 | return
39 |
40 | var fgd_file = fgd_output_folder.path_join(fgd_name + ".fgd")
41 |
42 | var file_obj := FileAccess.open(fgd_file, FileAccess.WRITE)
43 | if not file_obj:
44 | printerr("Failed to open file for writing: ", fgd_file)
45 | return
46 |
47 | print("Exporting FGD to ", fgd_file)
48 | file_obj.store_string(build_class_text(target_editor))
49 | file_obj.close()
50 |
51 | @export_group("Map Editor")
52 |
53 | ## Some map editors do not support the features found in others
54 | ## (ex: TrenchBroom supports the "model" key word while others require "studio",
55 | ## J.A.C.K. uses the "shader" key word while others use "material", etc...).
56 | ## If you get errors in your map editor, try changing this setting and re-exporting.
57 | ## This setting is overridden when the FGD is built via the Game Config resource.
58 | @export var target_map_editor: FuncGodotTargetMapEditors = FuncGodotTargetMapEditors.TRENCHBROOM
59 |
60 | # Some map editors do not support the "model" key word and require the "studio" key word instead.
61 | # If you get errors in your map editor, try changing this setting.
62 | # This setting is overridden when the FGD is built via the Game Config resource.
63 | #@export var model_key_word_supported: bool = true
64 |
65 | @export_group("FGD")
66 |
67 | ## FGD output filename without the extension.
68 | @export var fgd_name: String = "FuncGodot"
69 |
70 | ## Array of [FuncGodotFGDFile] resources to include in FGD file output. All of the entities included with these FuncGodotFGDFile resources will be prepended to the outputted FGD file.
71 | @export var base_fgd_files: Array[Resource] = []
72 |
73 | ## 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].
74 | @export var entity_definitions: Array[Resource] = []
75 |
76 | ## Toggles whether [FuncGodotFGDModelPointClass] resources will generate models from their [PackedScene] files.
77 | @export var generate_model_point_class_models: bool = true
78 |
79 | func build_class_text(target_editor: FuncGodotTargetMapEditors = FuncGodotTargetMapEditors.TRENCHBROOM) -> String:
80 | var res : String = ""
81 |
82 | for base_fgd in base_fgd_files:
83 | if base_fgd is FuncGodotFGDFile:
84 | res += base_fgd.build_class_text(target_editor)
85 | else:
86 | printerr("Base Fgd Files contains incorrect resource type! Should only be type FuncGodotFGDFile.")
87 |
88 | var entities = get_fgd_classes()
89 | for ent in entities:
90 | if not ent is FuncGodotFGDEntityClass:
91 | continue
92 | if ent.func_godot_internal:
93 | continue
94 | if ent is FuncGodotFGDModelPointClass:
95 | ent._model_generation_enabled = generate_model_point_class_models
96 |
97 | var ent_text = ent.build_def_text(target_editor)
98 | res += ent_text
99 | if ent != entities[-1]:
100 | res += "\n"
101 | return res
102 |
103 | ## This getter does a little bit of validation. Providing only an array of non-null uniquely-named entity definitions
104 | func get_fgd_classes() -> Array:
105 | var res : Array = []
106 | for cur_ent_def_ind in range(entity_definitions.size()):
107 | var cur_ent_def = entity_definitions[cur_ent_def_ind]
108 | if cur_ent_def == null:
109 | continue
110 | elif not (cur_ent_def is FuncGodotFGDEntityClass):
111 | printerr("Bad value in entity definition set at position %s! Not an entity defintion." % cur_ent_def_ind)
112 | continue
113 | res.append(cur_ent_def)
114 | return res
115 |
116 | func get_entity_definitions() -> Dictionary[String, FuncGodotFGDEntityClass]:
117 | var res: Dictionary[String, FuncGodotFGDEntityClass] = {}
118 |
119 | for base_fgd in base_fgd_files:
120 | var fgd_res = base_fgd.get_entity_definitions()
121 | for key in fgd_res:
122 | res[key] = fgd_res[key]
123 |
124 | for ent in get_fgd_classes():
125 | # Skip entities without classnames
126 | if ent.classname.replace(" ","") == "":
127 | printerr("Skipping " + ent.get_path() + ": Empty classname")
128 | continue
129 |
130 | if ent is FuncGodotFGDPointClass or ent is FuncGodotFGDSolidClass:
131 | var entity_def = ent.duplicate()
132 | var meta_properties: Dictionary[String, Variant] = {}
133 | var class_properties: Dictionary[String, Variant] = {}
134 | var class_property_descriptions: Dictionary[String, Variant] = {}
135 |
136 | for base_class in _generate_base_class_list(entity_def):
137 | for meta_property in base_class.meta_properties:
138 | meta_properties[meta_property] = base_class.meta_properties[meta_property]
139 |
140 | for class_property in base_class.class_properties:
141 | class_properties[class_property] = base_class.class_properties[class_property]
142 |
143 | for class_property_desc in base_class.class_property_descriptions:
144 | class_property_descriptions[class_property_desc] = base_class.class_property_descriptions[class_property_desc]
145 |
146 | for meta_property in entity_def.meta_properties:
147 | meta_properties[meta_property] = entity_def.meta_properties[meta_property]
148 |
149 | for class_property in entity_def.class_properties:
150 | class_properties[class_property] = entity_def.class_properties[class_property]
151 |
152 | for class_property_desc in entity_def.class_property_descriptions:
153 | class_property_descriptions[class_property_desc] = entity_def.class_property_descriptions[class_property_desc]
154 |
155 | entity_def.meta_properties = meta_properties
156 | entity_def.class_properties = class_properties
157 | entity_def.class_property_descriptions = class_property_descriptions
158 |
159 | res[ent.classname] = entity_def
160 | return res
161 |
162 | func _generate_base_class_list(entity_def : Resource, visited_base_classes = []) -> Array:
163 | var base_classes : Array = []
164 |
165 | visited_base_classes.append(entity_def.classname)
166 |
167 | # End recursive search if no more base_classes
168 | if len(entity_def.base_classes) == 0:
169 | return base_classes
170 |
171 | # Traverse up to the next level of hierarchy, if not already visited
172 | for base_class in entity_def.base_classes:
173 | if not base_class.classname in visited_base_classes:
174 | base_classes.append(base_class)
175 | base_classes += _generate_base_class_list(base_class, visited_base_classes)
176 | else:
177 | printerr(str("Entity '", entity_def.classname,"' contains cycle/duplicate to Entity '", base_class.classname, "'"))
178 |
179 | return base_classes
180 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_solid_class.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_slipgate3d.svg")
3 | class_name FuncGodotFGDSolidClass extends FuncGodotFGDEntityClass
4 | ## FGD SolidClass entity definition that generates a mesh from [FuncGodotData.BrushData].
5 | ##
6 | ## A [MeshInstance3D] will be generated by [FuncGodotMap] according to this definition's Visual Build settings.
7 | ## If [member FuncGodotFGDEntityClass.node_class] inherits [CollisionObject3D]
8 | ## then one or more [CollisionShape3D] nodes will be generated according to Collision Build settings.
9 | ##
10 | ## @tutorial(Quake Wiki Entity Article): https://quakewiki.org/wiki/Entity
11 | ## @tutorial(Level Design Book: Entity Types and Settings): https://book.leveldesignbook.com/appendix/resources/formats/fgd#entity-types-and-settings-basic
12 | ## @tutorial(Valve Developer Wiki FGD Article): https://developer.valvesoftware.com/wiki/FGD#Class_Types_and_Properties
13 | ## @tutorial(dumptruck_ds' Quake Mapping Entities Tutorial): https://www.youtube.com/watch?v=gtL9f6_N2WM
14 |
15 | enum SpawnType {
16 | WORLDSPAWN = 0, ## Builds the geometry of this entity relative to the FuncGodotMap position.
17 | MERGE_WORLDSPAWN = 1, ## This entity's geometry is merged with the [b]worldspawn[/b] entity and this entity is removed. Behavior mimics [b]func_group[/b] in modern Quake compilers.
18 | ENTITY = 2, ## This entity is built as its own object. It finds the origin of the entity based on [member origin_type].
19 | }
20 |
21 | enum OriginType {
22 | AVERAGED = 0, ## Use averaged brush vertices for center position. This is the old Qodot behavior.
23 | ABSOLUTE = 1, ## Use [code]origin[/code] class property in global coordinates as the center position.
24 | RELATIVE = 2, ## Calculate center position using [code]origin[/code] class property as an offset to the entity's bounding box center.
25 | BRUSH = 3, ## Calculate center position based on the bounding box center of all brushes using the 'origin' texture specified in the [FuncGodotMapSettings]. If no Origin Brush is found, fall back to BOUNDS_CENTER. This is the default option and recommended for most entities.
26 | BOUNDS_CENTER = 4, ## Use the center of the entity's bounding box for center position.
27 | BOUNDS_MINS = 5, ## Use the lowest bounding box coordinates for center position. This is standard Quake and Half-Life brush entity behavior.
28 | BOUNDS_MAXS = 6, ## Use the highest bounding box coordinates for center position.
29 | }
30 |
31 | enum CollisionShapeType {
32 | NONE, ## No collision shape is built. Useful for decorative geometry like vines, hanging wires, grass, etc...
33 | CONVEX, ## Will build a Convex CollisionShape3D for each brush used to make this Solid Class. Required for non-[StaticBody3D] nodes like [Area3D].
34 | CONCAVE ## Should have a concave collision shape
35 | }
36 |
37 | ## Controls whether this Solid Class is the worldspawn, is combined with the worldspawn, or is spawned as its own free-standing entity.
38 | @export var spawn_type: SpawnType = SpawnType.ENTITY
39 | ## Controls how this Solid Class determines its center position. Only valid if [member spawn_type] is set to ENTITY.
40 | @export var origin_type: OriginType = OriginType.BRUSH
41 |
42 | @export_group("Visual Build")
43 | ## Controls whether a [MeshInstance3D] is built for this Solid Class.
44 | @export var build_visuals : bool = true
45 | ## Global illumination mode for the generated [MeshInstance3D]. Setting to [b]GI_MODE_STATIC[/b] will unwrap the mesh's UV2 during build.
46 | @export var global_illumination_mode : GeometryInstance3D.GIMode = GeometryInstance3D.GI_MODE_STATIC
47 | ## @deprecated: Use [member global_illumination_mode] instead. [br]Sets generated [MeshInstance3D] to be available for UV2 unwrapping after [FuncGodotMap] build. Utilized in baked lightmapping.
48 | @export var use_in_baked_light : bool = true
49 | ## Shadow casting setting allows for further lightmapping customization.
50 | @export var shadow_casting_setting : GeometryInstance3D.ShadowCastingSetting = GeometryInstance3D.SHADOW_CASTING_SETTING_ON
51 | ## Automatically build [OccluderInstance3D] for this entity.
52 | @export var build_occlusion : bool = false
53 | ## This Solid Class' [MeshInstance3D] will only be visible for [Camera3D]s whose cull mask includes any of these render layers.
54 | @export_flags_3d_render var render_layers: int = 1
55 |
56 | @export_group("Collision Build")
57 | ## Controls how collisions are built for this Solid Class.
58 | @export var collision_shape_type: CollisionShapeType = CollisionShapeType.CONVEX
59 | ## The physics layers this Solid Class can be detected in.
60 | @export_flags_3d_physics var collision_layer: int = 1
61 | ## The physics layers this Solid Class scans.
62 | @export_flags_3d_physics var collision_mask: int = 1
63 | ## The priority used to solve colliding when penetration occurs. The higher the priority is, the lower the penetration into the Solid Class will be. This can for example be used to prevent the player from breaking through the boundaries of a level.
64 | @export var collision_priority: float = 1.0
65 | ## The collision margin for the Solid Class' collision shapes. Not used in Godot Physics. See [Shape3D] for details.
66 | @export var collision_shape_margin: float = 0.04
67 |
68 | ## The following properties tell FuncGodot to add a [i]"func_godot_mesh_data"[/i] Dictionary to the metadata of the generated node upon build.
69 | ## This data is parallelized, so that each element of the array is ordered to reference the same face in the mesh.
70 | @export_group("Mesh Metadata")
71 | ## Add a texture lookup table to the generated node's metadata on build.[br][br]
72 | ## The data is split between an [Array] of [StringName] called [i]"texture_names"[/i] containing all currently used texture materials
73 | ## and a [PackedInt32Array] called [i]"textures"[/i] where each element is an index corresponding to the [i]"texture_names"[/i] entries.
74 | @export var add_textures_metadata: bool = false
75 | ## Add a [PackedVector3Array] called [i]"vertices"[/i] to the generated node's metadata on build.[br][br]
76 | ## This is a list of every vertex in the generated node's [MeshInstance3D]. Every 3 vertices represent a single face.
77 | @export var add_vertex_metadata: bool = false
78 | ## Add a [PackedVector3Array] called [i]"positions"[/i] to the generated node's metadata on build.[br][br]
79 | ## This is a list of positions for each face, local to the generated node, calculated by averaging the vertices to find the face's center.
80 | @export var add_face_position_metadata: bool = false
81 | ## Add a [PackedVector3Array] called [i]"normals"[/i] to the generated node's metadata on build.[br][br]
82 | ## Contains a list of each face's normal.
83 | @export var add_face_normal_metadata: bool = false
84 | ## Add a [Dictionary] called [i]"collision_shape_to_face_indices_map"[/i] in the generated node's metadata on build.[br][br]
85 | ## Contains keys of strings, which are the names of child [CollisionShape3D] nodes, and values of
86 | ## [PackedInt32Array], containing indices of that child's faces.[br][br]
87 | ## For example, an element of [br][br][code]{ "entity_1_brush_0_collision_shape" : [0, 1, 3] }[/code][br][br]
88 | ## shows that this solid class has been generated with one child collision shape named
89 | ## [i]entity_1_brush_0_collision_shape[/i] which handles 3 faces of the mesh with collision, at indices 0, 1, and 3.
90 | @export var add_collision_shape_to_face_indices_metadata : bool = false
91 | ## [s]Add a [Dictionary] called [i]"collision_shape_to_face_range_map"[/i] in the generated node's metadata on build.[br][br]
92 | ## Contains keys of strings, which are the names of child [CollisionShape3D] nodes, and values of
93 | ## [Vector2i], where [i]X[/i] represents the starting index of that child's faces and [i]Y[/i] represents the
94 | ## ending index.[br][br]
95 | ## For example, an element of [br][br][code]{ "entity_1_brush_0_collision_shape" : Vector2i(0, 15) }[/code][br][br]
96 | ## shows that this solid class has been generated with one child collision shape named
97 | ## [i]entity_1_brush_0_collision_shape[/i] which handles the first 15 faces of the parts of the mesh with collision.[/s]
98 | ## @deprecated: No longer supported or planned as of 2025.7, but retained in case a contributor provides an appropriate solution in the future.
99 | @export var add_collision_shape_face_range_metadata: bool = false
100 |
101 | @export_group("Scripting")
102 | ## An optional [Script] file to attach to the node generated on map build.
103 | @export var script_class: Script
104 |
105 | func _init():
106 | prefix = "@SolidClass"
107 |
--------------------------------------------------------------------------------
/addons/func_godot/icons/icon_godambler.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
--------------------------------------------------------------------------------
/addons/func_godot/src/fgd/func_godot_fgd_model_point_class.gd:
--------------------------------------------------------------------------------
1 | @tool
2 | @icon("res://addons/func_godot/icons/icon_godambler3d.svg")
3 | class_name FuncGodotFGDModelPointClass extends FuncGodotFGDPointClass
4 | ## A special type of [FuncGodotFGDPointClass] entity that automatically generates a special simplified GLB model file for the map editor display.
5 | ## Only supported in map editors that support GLTF or GLB.
6 | ##
7 | ## @tutorial(Quake Wiki Entity Article): https://quakewiki.org/wiki/Entity
8 | ## @tutorial(Level Design Book: Entity Types and Settings): https://book.leveldesignbook.com/appendix/resources/formats/fgd#entity-types-and-settings-basic
9 | ## @tutorial(Valve Developer Wiki FGD Article): https://developer.valvesoftware.com/wiki/FGD#Class_Types_and_Properties
10 | ## @tutorial(dumptruck_ds' Quake Mapping Entities Tutorial): https://www.youtube.com/watch?v=gtL9f6_N2WM
11 | ## @tutorial(Level Design Book: Display Models for Entities): https://book.leveldesignbook.com/appendix/resources/formats/fgd#display-models-for-entities
12 | ## @tutorial(Valve Developer Wiki FGD Article: Entity Description Section): https://developer.valvesoftware.com/wiki/FGD#Entity_Description
13 | ## @tutorial(TrenchBroom Manual: Display Models for Entities): https://trenchbroom.github.io/manual/latest/#display-models-for-entities
14 |
15 | enum TargetMapEditor {
16 | GENERIC, ## Entity definition uses the [b]@studio[/b] key word. [member scale_expression] is ignored. Supported by all map editors.
17 | TRENCHBROOM ## Entity definition uses the [b]@model[/b] key word. [member scale_expression] is applied if set.
18 | }
19 |
20 | @export var target_map_editor: TargetMapEditor = TargetMapEditor.GENERIC
21 | ## Display model export folder relative to [member ProjectSettings.func_godot/model_point_class_save_path].
22 | @export var models_sub_folder : String = ""
23 | ## Scale expression applied to model. Only used by TrenchBroom. If left empty, uses [member ProjectSettings.func_godot/default_inverse_scale_factor]. [br][br]Read the TrenchBroom Manual for more information on the "scale expression" feature.
24 | @export var scale_expression : String = ""
25 | ## Model Point Class can override the 'size' meta property by auto-generating a value from the meshes' [AABB]. Proper generation requires [member scale_expression] set to a float or vector. [br][br][color=orange]WARNING:[/color] Generated size property unlikely to align cleanly to grid!
26 | @export var generate_size_property : bool = false
27 | ## Degrees to rotate model prior to export. Different editors may handle GLTF transformations differently. If your model isn't oriented correctly, try modifying this property.
28 | @export var rotation_offset: Vector3 = Vector3(0.0, 0.0, 0.0)
29 | ## Creates a .gdignore file in the model export folder to prevent Godot importing the display models. Only needs to be generated once.
30 | @export_tool_button("Generate GD Ignore File", "FileAccess") var generate_gd_ignore_file : Callable = _generate_gd_ignore_file
31 |
32 | var _model_generation_enabled: bool = false
33 |
34 | func _generate_gd_ignore_file() -> void:
35 | if Engine.is_editor_hint():
36 | var path: String = _get_game_path().path_join(_get_model_folder())
37 | var error: Error = DirAccess.make_dir_recursive_absolute(path)
38 | if error != Error.OK:
39 | printerr("Failed creating dir for GDIgnore file", error)
40 | return
41 | path = path.path_join('.gdignore')
42 | if FileAccess.file_exists(path):
43 | return
44 | var file: FileAccess = FileAccess.open(path, FileAccess.WRITE)
45 | file.store_string('')
46 | file.close()
47 |
48 | ## Builds and saves the display model into the specified destination, then parses the definition and outputs it into the FGD format.
49 | func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM) -> String:
50 | if _model_generation_enabled:
51 | _generate_model()
52 | _model_generation_enabled = false
53 | return super()
54 |
55 | func _generate_model() -> void:
56 | if not scene_file:
57 | return
58 |
59 | var gltf_state := GLTFState.new()
60 | var path: String = _get_export_dir()
61 | var node: Node3D = _get_node()
62 | if not node:
63 | return
64 | if not _create_gltf_file(gltf_state, path, node):
65 | printerr("could not create gltf file")
66 | return
67 | node.queue_free()
68 |
69 | if target_map_editor == TargetMapEditor.TRENCHBROOM:
70 | const model_key: String = "model"
71 | if scale_expression.is_empty():
72 | meta_properties[model_key] = '{"path": "%s", "scale": %s }' % [
73 | _get_local_path(),
74 | ProjectSettings.get_setting("func_godot/default_inverse_scale_factor", 32.0) as float
75 | ]
76 | else:
77 | meta_properties[model_key] = '{"path": "%s", "scale": %s }' % [
78 | _get_local_path(),
79 | scale_expression
80 | ]
81 | else:
82 | meta_properties["studio"] = '"%s"' % _get_local_path()
83 |
84 | if generate_size_property:
85 | meta_properties["size"] = _generate_size_from_aabb(gltf_state.meshes, gltf_state.get_nodes())
86 |
87 | func _get_node() -> Node3D:
88 | var node := scene_file.instantiate()
89 | if node is Node3D:
90 | return node as Node3D
91 | node.queue_free()
92 | printerr("Scene is not of type 'Node3D'")
93 | return null
94 |
95 | func _get_export_dir() -> String:
96 | var work_dir: String = _get_game_path()
97 | var model_dir: String = _get_model_folder()
98 | return work_dir.path_join(model_dir).path_join('%s.glb' % classname)
99 |
100 | func _get_local_path() -> String:
101 | return _get_model_folder().path_join('%s.glb' % classname)
102 |
103 | func _get_model_folder() -> String:
104 | var model_dir: String = ProjectSettings.get_setting("func_godot/model_point_class_save_path", "") as String
105 | if not models_sub_folder.is_empty():
106 | model_dir = model_dir.path_join(models_sub_folder)
107 | return model_dir
108 |
109 | func _get_game_path() -> String:
110 | return FuncGodotLocalConfig.get_setting(FuncGodotLocalConfig.PROPERTY.MAP_EDITOR_GAME_PATH) as String
111 |
112 | func _create_gltf_file(gltf_state: GLTFState, path: String, node: Node3D) -> bool:
113 | var global_export_path = path
114 | var gltf_document := GLTFDocument.new()
115 | gltf_state.create_animations = false
116 |
117 | node.rotate_x(deg_to_rad(rotation_offset.x))
118 | node.rotate_y(deg_to_rad(rotation_offset.y))
119 | node.rotate_z(deg_to_rad(rotation_offset.z))
120 |
121 | # With TrenchBroom we can specify a scale expression, but for other editors we need to scale our models manually.
122 | if target_map_editor != TargetMapEditor.TRENCHBROOM:
123 | var scale_factor: Vector3 = Vector3.ONE
124 | if scale_expression.is_empty():
125 | scale_factor *= ProjectSettings.get_setting("func_godot/default_inverse_scale_factor", 32.0) as float
126 | else:
127 | if scale_expression.begins_with('\''):
128 | var scale_arr := scale_expression.split_floats(' ', false)
129 | if scale_arr.size() == 3:
130 | scale_factor *= Vector3(scale_arr[0], scale_arr[1], scale_arr[2])
131 | elif scale_expression.to_float() > 0:
132 | scale_factor *= scale_expression.to_float()
133 | if scale_factor.length() == 0:
134 | scale_factor = Vector3.ONE # Don't let the node scale into oblivion!
135 | node.scale *= scale_factor
136 |
137 | var error: Error = gltf_document.append_from_scene(node, gltf_state)
138 | if error != Error.OK:
139 | printerr("Failed appending to gltf document", error)
140 | return false
141 |
142 | call_deferred("_save_to_file_system", gltf_document, gltf_state, global_export_path)
143 | return true
144 |
145 | func _save_to_file_system(gltf_document: GLTFDocument, gltf_state: GLTFState, path: String) -> void:
146 | var error: Error = DirAccess.make_dir_recursive_absolute(path.get_base_dir())
147 | if error != Error.OK:
148 | printerr("Failed creating dir", error)
149 | return
150 |
151 | error = gltf_document.write_to_filesystem(gltf_state, path)
152 | if error != Error.OK:
153 | printerr("Failed writing to file system", error)
154 | return
155 | print('Exported model to ', path)
156 |
157 | func _generate_size_from_aabb(meshes: Array[GLTFMesh], nodes: Array[GLTFNode]) -> AABB:
158 | var aabb := AABB()
159 | for mesh in meshes:
160 | aabb = aabb.merge(mesh.mesh.get_mesh().get_aabb())
161 | var pos_ofs := Vector3.ZERO
162 | if not nodes.is_empty():
163 | var ct: int = 0
164 | for node in nodes:
165 | if node.parent == 0:
166 | pos_ofs += node.position
167 | ct += 1
168 | pos_ofs /= maxi(ct, 1)
169 | aabb.position += pos_ofs
170 |
171 | # Reorient the AABB so it matches TrenchBroom's coordinate system
172 | var size_prop := AABB()
173 | size_prop.position = Vector3(aabb.position.z, aabb.position.x, aabb.position.y)
174 | size_prop.size = Vector3(aabb.size.z, aabb.size.x, aabb.size.y)
175 |
176 | # Scale the size bounds to our scale factor
177 | # Scale factor will need to be set if we decide to auto-generate our bounds
178 | var scale_factor: Vector3 = Vector3.ONE
179 | if target_map_editor == TargetMapEditor.TRENCHBROOM:
180 | if scale_expression.is_empty():
181 | scale_factor *= ProjectSettings.get_setting("func_godot/default_inverse_scale_factor", 32.0) as float
182 | else:
183 | if scale_expression.begins_with('\''):
184 | var scale_arr := scale_expression.split_floats(' ', false)
185 | if scale_arr.size() == 3:
186 | scale_factor *= Vector3(scale_arr[0], scale_arr[1], scale_arr[2])
187 | elif scale_expression.to_float() > 0:
188 | scale_factor *= scale_expression.to_float()
189 |
190 | size_prop.position *= scale_factor
191 | size_prop.size *= scale_factor
192 | size_prop.size += size_prop.position
193 | # Round the size so it can stay on grid level 1 at least
194 | for i in 3:
195 | size_prop.position[i] = round(size_prop.position[i])
196 | size_prop.size[i] = round(size_prop.size[i])
197 | return size_prop
198 |
--------------------------------------------------------------------------------