Compare commits
95 Commits
uurin
...
3defc9da95
| Author | SHA1 | Date | |
|---|---|---|---|
| 3defc9da95 | |||
| ff75dacfb6 | |||
| bf7a454ad0 | |||
| ebb6ec6335 | |||
| a0b248748c | |||
| 5ef5889979 | |||
| 2e9d62b964 | |||
| 622830a6ee | |||
| 603a674e08 | |||
| 631df017d1 | |||
| 2c0142d208 | |||
| c283eb0927 | |||
| d379b215e2 | |||
| cd73a21ab7 | |||
| 6a67bfea36 | |||
| b929ed2a7a | |||
| 708a35d51f | |||
| 115872b98f | |||
| 64124990a6 | |||
| 037bfad700 | |||
| 661b4e470b | |||
| b564cd5a71 | |||
| 7b5fcb1d1e | |||
| 45e69101b6 | |||
| a9810c8c9f | |||
| ba20cd8580 | |||
| aac0099faa | |||
| 4fc64dedae | |||
| 7423665c06 | |||
| 09c39e068b | |||
| c1852e8736 | |||
| dda9862589 | |||
| d538679697 | |||
| e668895c12 | |||
| 064f07ace7 | |||
| 9d0799083c | |||
| 2bea615307 | |||
| a61f4c4689 | |||
| f6355605cd | |||
| 033d26ee18 | |||
| d3315836c3 | |||
| 3279645ac4 | |||
| 371a2fded0 | |||
| 49a9bced4b | |||
| f0d932eac3 | |||
| ca1a0ce581 | |||
| 5ad4f64474 | |||
| 48cac53fc6 | |||
| 5c489318a9 | |||
| 1f24a750fb | |||
| 33ec51625c | |||
| 2e2b70e030 | |||
| 04597cdc01 | |||
| c407513cbd | |||
| ea065e4d81 | |||
| 0e654ec0b6 | |||
| df27e9d807 | |||
| 866cc12c2c | |||
| d98a5ba0ac | |||
| 6abf5355c2 | |||
| bfb026c7ae | |||
| 245ce31eab | |||
| b30fb6e0a6 | |||
| 950d93ed0e | |||
| 85b9c86164 | |||
| 174b14fa61 | |||
| 30136a9b90 | |||
| 80a35a4553 | |||
| 98d579f733 | |||
| f19e6980cd | |||
| ab270ac04f | |||
| 22ed4f7722 | |||
| af0790a1ce | |||
| a8b9f166a6 | |||
| de5b5f3b7c | |||
| 13b027d91c | |||
| d6fe527906 | |||
| 6549240337 | |||
| fe5d143047 | |||
| dc40057fe1 | |||
| cb3a54c1cc | |||
| 34b3866a5e | |||
| 4f1126563c | |||
| c587b9877f | |||
| a809ed6cc4 | |||
| 9675ae884d | |||
| a318e65e70 | |||
| 8b3a816203 | |||
| 4e7bc29507 | |||
| b7c50eaae2 | |||
| 4fa965725d | |||
| f4d61b7f0a | |||
| adbd3859de | |||
| fb6ac05890 | |||
| 22d8e5df8c |
@@ -0,0 +1,4 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
@@ -0,0 +1,5 @@
|
||||
disable:
|
||||
- class-definitions-order
|
||||
- no-else-return
|
||||
max-line-length: 120
|
||||
max-file-lines: 1200
|
||||
@@ -0,0 +1,2 @@
|
||||
# Normalize EOL for all files that Git considers text files.
|
||||
* text=auto eol=lf
|
||||
@@ -0,0 +1,21 @@
|
||||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
/android/
|
||||
|
||||
# JetBrains IDE — contains absolute paths (Godot binary, SDK dirs), varies per user
|
||||
.idea/
|
||||
|
||||
# Blender render previews (generated by render_anim_preview.py)
|
||||
Blender/preview/
|
||||
|
||||
Blender/*.blend1
|
||||
|
||||
# Test output (generated screenshots, frame strips)
|
||||
tests/output/
|
||||
|
||||
# Web export output
|
||||
build/
|
||||
|
||||
#PRISM
|
||||
BullPrism/
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/.idea.Bullosseum.iml
|
||||
/projectSettingsUpdater.xml
|
||||
/contentModel.xml
|
||||
/modules.xml
|
||||
# Ignored default folder with query files
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
extends Node3D
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var anim := get_node_or_null(^"AnimationPlayer") as AnimationPlayer
|
||||
if anim:
|
||||
anim.play(&"Juubeldab")
|
||||
@@ -0,0 +1 @@
|
||||
uid://wj6tgh8nb0ka
|
||||
@@ -0,0 +1,5 @@
|
||||
extends Node3D
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
$AnimationPlayer.play("ArmatureAction")
|
||||
@@ -0,0 +1 @@
|
||||
uid://gt3kfchac3m3
|
||||
@@ -0,0 +1,45 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://cl54dt38yj2x"
|
||||
path="res://.godot/imported/Arena.glb-bf6b057edaab2fa44513d7f705517361.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Arena.glb"
|
||||
dest_files=["res://.godot/imported/Arena.glb-bf6b057edaab2fa44513d7f705517361.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
mesh_library/use_node_names_as_mesh_names=false
|
||||
array_mesh/deduplicate_surfaces=true
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_name_suffixes=true
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=2
|
||||
gltf/embedded_image_handling=1
|
||||
gltf/texture_map_mode=1
|
||||
|
After Width: | Height: | Size: 598 KiB |
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dk6xuwwa0mfpe"
|
||||
path.s3tc="res://.godot/imported/Arena_sand.png-416de2afe03241df088061e1a5f831af.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "c8b9b7d6205ce80dfcfaa38152b996fe"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Arena_sand.png"
|
||||
dest_files=["res://.godot/imported/Arena_sand.png-416de2afe03241df088061e1a5f831af.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
|
After Width: | Height: | Size: 412 KiB |
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b4gkpa7jypcsm"
|
||||
path.s3tc="res://.godot/imported/Arena_wall.png-e67bd4bbd2f60583bfc14dd8b7687eef.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "0e7ed34c3c812d96732bd32f9dca0c93"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Arena_wall.png"
|
||||
dest_files=["res://.godot/imported/Arena_wall.png-e67bd4bbd2f60583bfc14dd8b7687eef.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
|
After Width: | Height: | Size: 180 KiB |
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://yercpq3y2o0x"
|
||||
path.s3tc="res://.godot/imported/Arena_wood.png-b4ed20d66b4d375396b0be2f2f863d80.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "23a7a951553ffe271c47693fd71314ca"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Arena_wood.png"
|
||||
dest_files=["res://.godot/imported/Arena_wood.png-b4ed20d66b4d375396b0be2f2f863d80.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
@@ -0,0 +1,45 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://eu2lqjhowj4t"
|
||||
path="res://.godot/imported/Matador.glb-84387af784b13addc4467fc8edace9ff.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Matador.glb"
|
||||
dest_files=["res://.godot/imported/Matador.glb-84387af784b13addc4467fc8edace9ff.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
mesh_library/use_node_names_as_mesh_names=false
|
||||
array_mesh/deduplicate_surfaces=true
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_name_suffixes=true
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=2
|
||||
gltf/embedded_image_handling=1
|
||||
gltf/texture_map_mode=1
|
||||
@@ -0,0 +1,45 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dxe72ig8gfbcg"
|
||||
path="res://.godot/imported/arena model2026.glb-299db01cae891e5005f8ac1e6c83d0a6.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/arena model2026.glb"
|
||||
dest_files=["res://.godot/imported/arena model2026.glb-299db01cae891e5005f8ac1e6c83d0a6.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
mesh_library/use_node_names_as_mesh_names=false
|
||||
array_mesh/deduplicate_surfaces=true
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_name_suffixes=true
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=2
|
||||
gltf/embedded_image_handling=1
|
||||
gltf/texture_map_mode=1
|
||||
@@ -0,0 +1,45 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dio67r8ambe7h"
|
||||
path="res://.godot/imported/arena_placeholder_v01.glb-fc11365d8ec7ae6778e90b13ba508b8a.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/arena_placeholder_v01.glb"
|
||||
dest_files=["res://.godot/imported/arena_placeholder_v01.glb-fc11365d8ec7ae6778e90b13ba508b8a.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
mesh_library/use_node_names_as_mesh_names=false
|
||||
array_mesh/deduplicate_surfaces=true
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_name_suffixes=true
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
gltf/texture_map_mode=1
|
||||
@@ -0,0 +1,46 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bun14xmk20pcj"
|
||||
path="res://.godot/imported/bull.fbx-50f6d03a92c862695bbeaeba563be0db.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/bull.fbx"
|
||||
dest_files=["res://.godot/imported/bull.fbx-50f6d03a92c862695bbeaeba563be0db.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
mesh_library/use_node_names_as_mesh_names=false
|
||||
array_mesh/deduplicate_surfaces=true
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_name_suffixes=true
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=true
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
fbx/importer=0
|
||||
fbx/allow_geometry_helper_nodes=false
|
||||
fbx/embedded_image_handling=1
|
||||
fbx/naming_version=2
|
||||
@@ -0,0 +1 @@
|
||||
uid://csxxlnq74fej4
|
||||
@@ -0,0 +1,5 @@
|
||||
extends Node3D
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
$AnimationPlayer.play("Taunt")
|
||||
@@ -0,0 +1 @@
|
||||
uid://bn3xwnlktwdlf
|
||||
@@ -0,0 +1,38 @@
|
||||
[gd_scene format=3 uid="uid://bl6jlbq1dpkc"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://eu2lqjhowj4t" path="res://Assets/Matador.glb" id="1_m7x6l"]
|
||||
[ext_resource type="Script" uid="uid://dpoq87w5pvqa" path="res://matador_2.gd" id="2_mftd2"]
|
||||
|
||||
[node name="matador2" unique_id=1179710042 instance=ExtResource("1_m7x6l")]
|
||||
script = ExtResource("2_mftd2")
|
||||
|
||||
[node name="Skeleton3D" parent="Armature" parent_id_path=PackedInt32Array(1269629432) index="0" unique_id=978366810]
|
||||
bones/0/position = Vector3(0.056660548, 0.6424767, -0.0167365)
|
||||
bones/0/rotation = Quaternion(0.080643006, 0, 0, 0.996743)
|
||||
bones/1/rotation = Quaternion(0.083861314, 0, 0, 0.9964774)
|
||||
bones/3/rotation = Quaternion(0.04833339, 0.5302496, -0.71466804, 0.4535955)
|
||||
bones/4/rotation = Quaternion(0.031473875, -0.17018215, -0.15981929, 0.97185665)
|
||||
bones/5/rotation = Quaternion(0.6747468, -0.021427644, -0.06245957, 0.7350895)
|
||||
bones/6/rotation = Quaternion(3.1828083e-08, -9.5969504e-08, -0.0587008, 0.99827564)
|
||||
bones/7/rotation = Quaternion(0.1907551, 0.20328633, 0.7258648, 0.6288143)
|
||||
bones/8/rotation = Quaternion(0.16639966, -0.05474137, 0.010937729, 0.984477)
|
||||
bones/9/rotation = Quaternion(0.5914298, 0.005839911, -0.041949864, 0.8052435)
|
||||
bones/10/rotation = Quaternion(2.3105285e-08, 1.0152064e-07, 0.05870079, 0.99827564)
|
||||
bones/11/rotation = Quaternion(0.39202613, 0.47060952, 0.5799399, 0.53713316)
|
||||
bones/12/rotation = Quaternion(0.62021786, 0.40894383, 0.44191495, 0.5027981)
|
||||
bones/13/rotation = Quaternion(-0.11584477, 0.0021730124, 0.6343679, 0.7642989)
|
||||
bones/14/rotation = Quaternion(0.1454883, 0.14013468, -0.7254941, 0.65791625)
|
||||
bones/15/rotation = Quaternion(0.71668345, 0.065085255, -0.6923973, -0.05210323)
|
||||
bones/16/rotation = Quaternion(-0.10161893, -0.0019664483, -0.65947086, 0.7448275)
|
||||
bones/17/rotation = Quaternion(0.06964938, -0.042099692, 0.74388325, 0.6633358)
|
||||
bones/18/rotation = Quaternion(0.5305965, -0.28927496, 0.76720744, -0.21489602)
|
||||
bones/19/position = Vector3(0.16341288, 0.31487355, 0.3966543)
|
||||
bones/20/position = Vector3(0.22012731, 0.38421977, 0.95168185)
|
||||
bones/21/position = Vector3(-0.09492579, 0.40446192, -0.46390092)
|
||||
bones/21/rotation = Quaternion(0.7216726, 0.064735115, -0.6891729, 0.0062273443)
|
||||
bones/22/position = Vector3(-0.22012731, 0.38421977, 0.95168185)
|
||||
bones/23/position = Vector3(-0.0382514, 1.7423625, 0.0026792884)
|
||||
bones/23/rotation = Quaternion(0.8626007, 0.0068245474, -0.099159576, -0.49602506)
|
||||
bones/23/scale = Vector3(0.6647317, 1.001677, 1.0066445)
|
||||
bones/24/rotation = Quaternion(-0.007878712, 8.3020435e-09, -0.0023950166, 0.9999661)
|
||||
bones/25/rotation = Quaternion(5.5870206e-09, 5.5879354e-09, -2.0518176e-09, 1)
|
||||
@@ -0,0 +1,12 @@
|
||||
extends Node3D
|
||||
|
||||
|
||||
@onready var animation_player: AnimationPlayer = $AnimationPlayer
|
||||
|
||||
func _ready():
|
||||
animation_player.play("Taunt")
|
||||
animation_player.animation_finished.connect(_on_animation_finished)
|
||||
|
||||
func _on_animation_finished(anim_name):
|
||||
if anim_name == "Taunt":
|
||||
animation_player.play("Taunt")
|
||||
@@ -0,0 +1 @@
|
||||
uid://dycnoiadljbb1
|
||||
|
After Width: | Height: | Size: 296 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bxv1uuymonrp6"
|
||||
path="res://.godot/imported/menu_bg.png-3906063022fa3c81090e3c663f8866b0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/menu_bg.png"
|
||||
dest_files=["res://.godot/imported/menu_bg.png-3906063022fa3c81090e3c663f8866b0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@@ -0,0 +1,45 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://xyvank512l5n"
|
||||
path="res://.godot/imported/sword.glb-a20d99f4c597d7fdae7f36c74685e1ff.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/sword.glb"
|
||||
dest_files=["res://.godot/imported/sword.glb-a20d99f4c597d7fdae7f36c74685e1ff.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
mesh_library/use_node_names_as_mesh_names=false
|
||||
array_mesh/deduplicate_surfaces=true
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_name_suffixes=true
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=2
|
||||
gltf/embedded_image_handling=1
|
||||
gltf/texture_map_mode=1
|
||||
@@ -0,0 +1,151 @@
|
||||
"""
|
||||
Blender 5.1 script: create walk + idle animations for matador_v02.
|
||||
Run: blender --background matador_v02.blend --python create_matador_anims.py
|
||||
"""
|
||||
import bpy, math, os
|
||||
|
||||
|
||||
# ── setup ──────────────────────────────────────────────────────────────────────
|
||||
arm_obj = next(o for o in bpy.data.objects if o.type == 'ARMATURE')
|
||||
bpy.context.view_layer.objects.active = arm_obj
|
||||
bpy.ops.object.mode_set(mode='POSE')
|
||||
|
||||
if arm_obj.animation_data is None:
|
||||
arm_obj.animation_data_create()
|
||||
|
||||
pb = arm_obj.pose.bones
|
||||
|
||||
# Ensure all animated bones use XYZ Euler
|
||||
for bname in ['leg_L', 'leg_R', 'shin_L', 'shin_R',
|
||||
'arm_L', 'arm_R', 'forearm_L', 'forearm_R',
|
||||
'collarbone_L', 'collarbone_R']:
|
||||
pb[bname].rotation_mode = 'XYZ'
|
||||
|
||||
CYCLE = 30 # frames (1 s at 30 fps)
|
||||
LEG_SWING = 25 # degrees
|
||||
KNEE_BEND = 30
|
||||
ARM_SWING = 15
|
||||
ARM_DOWN = 55 # lower arms from T-pose around bone-local Y
|
||||
ELBOW_BEND = 25
|
||||
|
||||
|
||||
# ── WALK action ────────────────────────────────────────────────────────────────
|
||||
# Remove old actions if they exist
|
||||
for old_name in ['walk', 'idle']:
|
||||
if old_name in bpy.data.actions:
|
||||
bpy.data.actions.remove(bpy.data.actions[old_name])
|
||||
|
||||
walk = bpy.data.actions.new(name='walk')
|
||||
walk.use_fake_user = True
|
||||
walk.use_cyclic = True
|
||||
arm_obj.animation_data.action = walk
|
||||
|
||||
# Clear all pose bone transforms first
|
||||
bpy.ops.pose.select_all(action='SELECT')
|
||||
bpy.ops.pose.rot_clear()
|
||||
|
||||
arm_down_l = math.radians(ARM_DOWN)
|
||||
arm_down_r = math.radians(-ARM_DOWN)
|
||||
|
||||
for f in range(0, CYCLE + 1, 2):
|
||||
t = (f / CYCLE) * math.tau
|
||||
|
||||
# Legs – swing forward/back on bone-local X
|
||||
pb['leg_L'].rotation_euler = (math.sin(t) * math.radians(LEG_SWING), 0, 0)
|
||||
pb['leg_L'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
|
||||
pb['leg_R'].rotation_euler = (math.sin(t + math.pi) * math.radians(LEG_SWING), 0, 0)
|
||||
pb['leg_R'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
|
||||
# Shins – only bend backward when leg is back
|
||||
val_l = max(0.0, -math.sin(t)) * math.radians(KNEE_BEND)
|
||||
val_r = max(0.0, -math.sin(t + math.pi)) * math.radians(KNEE_BEND)
|
||||
pb['shin_L'].rotation_euler = (val_l, 0, 0)
|
||||
pb['shin_L'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
pb['shin_R'].rotation_euler = (val_r, 0, 0)
|
||||
pb['shin_R'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
|
||||
# Arms – lower from T-pose (Y) + swing (X, opposite phase to legs)
|
||||
swing_l = math.sin(t + math.pi) * math.radians(ARM_SWING)
|
||||
swing_r = math.sin(t) * math.radians(ARM_SWING)
|
||||
pb['arm_L'].rotation_euler = (swing_l, arm_down_l, 0)
|
||||
pb['arm_L'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
pb['arm_R'].rotation_euler = (swing_r, arm_down_r, 0)
|
||||
pb['arm_R'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
|
||||
# Forearms – constant slight bend
|
||||
pb['forearm_L'].rotation_euler = (math.radians(ELBOW_BEND), 0, 0)
|
||||
pb['forearm_L'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
pb['forearm_R'].rotation_euler = (math.radians(ELBOW_BEND), 0, 0)
|
||||
pb['forearm_R'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
|
||||
# Collarbones – identity
|
||||
pb['collarbone_L'].rotation_euler = (0, 0, 0)
|
||||
pb['collarbone_L'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
pb['collarbone_R'].rotation_euler = (0, 0, 0)
|
||||
pb['collarbone_R'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
|
||||
print("Created 'walk' action")
|
||||
|
||||
|
||||
# ── IDLE action ────────────────────────────────────────────────────────────────
|
||||
idle = bpy.data.actions.new(name='idle')
|
||||
idle.use_fake_user = True
|
||||
arm_obj.animation_data.action = idle
|
||||
|
||||
bpy.ops.pose.select_all(action='SELECT')
|
||||
bpy.ops.pose.rot_clear()
|
||||
|
||||
# Arms lowered, everything else at rest – 2 frames for a valid action
|
||||
for f in [0, 1]:
|
||||
pb['arm_L'].rotation_euler = (0, arm_down_l, 0)
|
||||
pb['arm_L'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
pb['arm_R'].rotation_euler = (0, arm_down_r, 0)
|
||||
pb['arm_R'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
pb['forearm_L'].rotation_euler = (math.radians(ELBOW_BEND), 0, 0)
|
||||
pb['forearm_L'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
pb['forearm_R'].rotation_euler = (math.radians(ELBOW_BEND), 0, 0)
|
||||
pb['forearm_R'].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
for bname in ['collarbone_L', 'collarbone_R', 'leg_L', 'leg_R', 'shin_L', 'shin_R']:
|
||||
pb[bname].rotation_euler = (0, 0, 0)
|
||||
pb[bname].keyframe_insert(data_path='rotation_euler', frame=f)
|
||||
|
||||
print("Created 'idle' action")
|
||||
|
||||
|
||||
# ── NLA tracks for export ─────────────────────────────────────────────────────
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
# Clear existing NLA tracks
|
||||
if arm_obj.animation_data.nla_tracks:
|
||||
for t in list(arm_obj.animation_data.nla_tracks):
|
||||
arm_obj.animation_data.nla_tracks.remove(t)
|
||||
|
||||
tw = arm_obj.animation_data.nla_tracks.new()
|
||||
tw.name = 'walk'
|
||||
sw = tw.strips.new('walk', 0, walk)
|
||||
|
||||
ti = arm_obj.animation_data.nla_tracks.new()
|
||||
ti.name = 'idle'
|
||||
si = ti.strips.new('idle', 0, idle)
|
||||
|
||||
# ── export FBX ─────────────────────────────────────────────────────────────────
|
||||
fbx_path = os.path.join(os.path.dirname(bpy.data.filepath), 'matador_v02.fbx')
|
||||
bpy.ops.export_scene.fbx(
|
||||
filepath=fbx_path,
|
||||
use_selection=False,
|
||||
bake_anim=True,
|
||||
bake_anim_use_all_actions=True,
|
||||
bake_anim_use_nla_strips=False,
|
||||
bake_anim_force_startend_keying=True,
|
||||
bake_anim_step=1.0,
|
||||
bake_anim_simplify_factor=0.0,
|
||||
add_leaf_bones=False,
|
||||
primary_bone_axis='Y',
|
||||
secondary_bone_axis='X',
|
||||
apply_scale_options='FBX_SCALE_ALL',
|
||||
)
|
||||
print('Exported FBX to:', fbx_path)
|
||||
|
||||
bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
|
||||
print('Saved .blend')
|
||||
@@ -0,0 +1 @@
|
||||
uid://ymaeifakqovf
|
||||
@@ -0,0 +1,136 @@
|
||||
"""
|
||||
Blender 5.1 script: render preview frames of matador animations to PNG.
|
||||
Run: blender --background matador_v02.blend --python render_anim_preview.py
|
||||
|
||||
Outputs to Blender/preview/ directory:
|
||||
walk_frame_00.png .. walk_frame_09.png
|
||||
idle_frame_00.png
|
||||
|
||||
Use this to visually verify bone orientations BEFORE exporting to Godot.
|
||||
"""
|
||||
import bpy
|
||||
import os
|
||||
import math
|
||||
|
||||
# ── Configuration ─────────────────────────────────────────────────────────────
|
||||
PREVIEW_DIR = os.path.join(os.path.dirname(bpy.data.filepath), "preview")
|
||||
RENDER_RES_X = 512
|
||||
RENDER_RES_Y = 512
|
||||
WALK_FRAMES = 10 # number of evenly-spaced frames to render from walk cycle
|
||||
CAMERA_DISTANCE = 5.0
|
||||
CAMERA_HEIGHT = 1.0
|
||||
CAMERA_ANGLES = [0, 90] # degrees — front and side views
|
||||
|
||||
os.makedirs(PREVIEW_DIR, exist_ok=True)
|
||||
|
||||
# ── Find armature ─────────────────────────────────────────────────────────────
|
||||
arm_obj = next((o for o in bpy.data.objects if o.type == 'ARMATURE'), None)
|
||||
if arm_obj is None:
|
||||
raise RuntimeError("No armature found in scene")
|
||||
|
||||
# ── Setup render settings ─────────────────────────────────────────────────────
|
||||
scene = bpy.context.scene
|
||||
scene.render.resolution_x = RENDER_RES_X
|
||||
scene.render.resolution_y = RENDER_RES_Y
|
||||
scene.render.resolution_percentage = 100
|
||||
scene.render.film_transparent = True
|
||||
scene.render.image_settings.file_format = 'PNG'
|
||||
scene.render.image_settings.color_mode = 'RGBA'
|
||||
scene.render.engine = 'BLENDER_EEVEE'
|
||||
|
||||
# ── Create or reuse camera ────────────────────────────────────────────────────
|
||||
cam_data = bpy.data.cameras.get("PreviewCam") or bpy.data.cameras.new("PreviewCam")
|
||||
cam_data.lens = 50
|
||||
cam_obj = bpy.data.objects.get("PreviewCamObj")
|
||||
if cam_obj is None:
|
||||
cam_obj = bpy.data.objects.new("PreviewCamObj", cam_data)
|
||||
scene.collection.objects.link(cam_obj)
|
||||
scene.camera = cam_obj
|
||||
|
||||
# ── Create or reuse key light ─────────────────────────────────────────────────
|
||||
light_data = bpy.data.lights.get("PreviewLight") or bpy.data.lights.new("PreviewLight", type='SUN')
|
||||
light_data.energy = 3.0
|
||||
light_obj = bpy.data.objects.get("PreviewLightObj")
|
||||
if light_obj is None:
|
||||
light_obj = bpy.data.objects.new("PreviewLightObj", light_data)
|
||||
scene.collection.objects.link(light_obj)
|
||||
light_obj.rotation_euler = (math.radians(45), math.radians(30), 0)
|
||||
|
||||
# ── Create or reuse fill light ────────────────────────────────────────────────
|
||||
fill_data = bpy.data.lights.get("PreviewFill") or bpy.data.lights.new("PreviewFill", type='SUN')
|
||||
fill_data.energy = 1.0
|
||||
fill_obj = bpy.data.objects.get("PreviewFillObj")
|
||||
if fill_obj is None:
|
||||
fill_obj = bpy.data.objects.new("PreviewFillObj", fill_data)
|
||||
scene.collection.objects.link(fill_obj)
|
||||
fill_obj.rotation_euler = (math.radians(60), math.radians(-45), 0)
|
||||
|
||||
# ── Ensure armature is visible ────────────────────────────────────────────────
|
||||
arm_obj.hide_render = False
|
||||
arm_obj.hide_viewport = False
|
||||
for child in arm_obj.children:
|
||||
child.hide_render = False
|
||||
child.hide_viewport = False
|
||||
|
||||
|
||||
def position_camera(angle_deg: float) -> None:
|
||||
"""Place camera at given horizontal angle around the armature center."""
|
||||
rad = math.radians(angle_deg)
|
||||
cam_obj.location = (
|
||||
math.sin(rad) * CAMERA_DISTANCE,
|
||||
CAMERA_HEIGHT,
|
||||
math.cos(rad) * CAMERA_DISTANCE,
|
||||
)
|
||||
# Point camera at armature center (roughly hip height)
|
||||
target = arm_obj.location.copy()
|
||||
target.y = 0.9
|
||||
direction = target - cam_obj.location
|
||||
rot_quat = direction.to_track_quat('-Z', 'Y')
|
||||
cam_obj.rotation_euler = rot_quat.to_euler()
|
||||
|
||||
|
||||
def render_action(action_name: str, frame_count: int) -> None:
|
||||
"""Render frame_count evenly-spaced frames of the named action."""
|
||||
action = bpy.data.actions.get(action_name)
|
||||
if action is None:
|
||||
print(f"WARNING: Action '{action_name}' not found, skipping")
|
||||
return
|
||||
|
||||
# Assign action
|
||||
if arm_obj.animation_data is None:
|
||||
arm_obj.animation_data_create()
|
||||
arm_obj.animation_data.action = action
|
||||
|
||||
frame_start = int(action.frame_range[0])
|
||||
frame_end = int(action.frame_range[1])
|
||||
total_frames = max(frame_end - frame_start, 1)
|
||||
|
||||
for angle_deg in CAMERA_ANGLES:
|
||||
position_camera(angle_deg)
|
||||
angle_label = f"{angle_deg:03d}deg"
|
||||
|
||||
for i in range(frame_count):
|
||||
t = i / max(frame_count - 1, 1) if frame_count > 1 else 0
|
||||
frame = frame_start + int(t * total_frames)
|
||||
scene.frame_set(frame)
|
||||
|
||||
filename = f"{action_name}_{angle_label}_frame_{i:02d}.png"
|
||||
filepath = os.path.join(PREVIEW_DIR, filename)
|
||||
scene.render.filepath = filepath
|
||||
bpy.ops.render.render(write_still=True)
|
||||
print(f" Rendered: {filename}")
|
||||
|
||||
|
||||
# ── Render all animations ─────────────────────────────────────────────────────
|
||||
print("=" * 60)
|
||||
print("RENDERING ANIMATION PREVIEWS")
|
||||
print("=" * 60)
|
||||
|
||||
render_action("walk", WALK_FRAMES)
|
||||
render_action("idle", 1)
|
||||
|
||||
# ── Cleanup preview objects (optional — keep them for re-runs) ────────────────
|
||||
print("=" * 60)
|
||||
print(f"Preview images saved to: {PREVIEW_DIR}")
|
||||
print(f"Total actions rendered: {len([a for a in ['walk', 'idle'] if bpy.data.actions.get(a)])}")
|
||||
print("=" * 60)
|
||||
@@ -0,0 +1,140 @@
|
||||
# Bullosseum — CLAUDE.md
|
||||
|
||||
## About this project
|
||||
|
||||
A 3D arena game built in Godot 4.7 (Forward Plus renderer, Jolt Physics) where the player controls a bull. Currently features third-person camera, bull movement with charge mechanics, and a placeholder arena.
|
||||
|
||||
## AI role
|
||||
|
||||
I am a **Godot 4.6+ expert**. I follow current best practices for GDScript, scene architecture, physics, and performance. If a question suggests a suboptimal approach — wrong node type, unnecessary complexity, a pattern that fights the engine — I will say so and explain the better alternative before implementing anything.
|
||||
|
||||
## Project structure
|
||||
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `scene.tscn` | Main scene (arena + player) |
|
||||
| `Player.tscn` | Player scene root (`CharacterBody3D`) |
|
||||
| `player.gd` | Movement, charge, turning logic |
|
||||
| `camera_spring_arm.gd` | Mouse-look pivot (`Node3D` + `SpringArm3D`) |
|
||||
| `camera_follow.gd` | Smooth camera follow (`Camera3D`) |
|
||||
| `matador.gd` | Matador AI (wander / ragdoll state machine) |
|
||||
| `matador_spawn.gd` | Spawns N matadors at random arena positions |
|
||||
| `debug_params.gd` | Runtime-tunable parameter registry (autoload `DP`) |
|
||||
| `Assets/` | Raw 3D assets (`.glb`, `.fbx`) |
|
||||
| `Blender/` | Blender source files, animation scripts, FBX exports |
|
||||
| `Blender/create_matador_anims.py` | Creates walk + idle animations and exports FBX |
|
||||
| `Blender/render_anim_preview.py` | Renders animation preview PNGs for visual verification |
|
||||
| `Blender/preview/` | Output directory for animation preview images |
|
||||
| `tests/` | Headless test scripts (screenshot capture, logic validation) |
|
||||
| `addons/rider-plugin/` | JetBrains Rider IDE integration |
|
||||
|
||||
## Tech choices
|
||||
|
||||
- **Physics:** Jolt Physics (not the default Godot Physics)
|
||||
- **Renderer:** Forward Plus
|
||||
- **Input map:** WASD + arrow keys, Shift = charge, Space = jump, scroll = zoom, middle-click = toggle mouse capture
|
||||
- **IDE:** JetBrains Rider via the rider-plugin addon
|
||||
|
||||
## GDScript conventions
|
||||
|
||||
- Typed GDScript everywhere (`var x: float`, return types on functions)
|
||||
- `@onready` for node references; never `get_node()` strings when avoidable
|
||||
- Constants in `SCREAMING_SNAKE_CASE`, variables in `snake_case`
|
||||
- One script per scene root — keep scripts focused
|
||||
- Signal names in `snake_case`; connect via `signal.connect()` not the legacy string form
|
||||
- Prefer `_physics_process` for physics/movement, `_process` for visuals/camera, `_unhandled_input` for input that shouldn't bubble
|
||||
- No comments that restate what the code already says; only comment non-obvious constraints or workarounds
|
||||
|
||||
## Best practices to enforce
|
||||
|
||||
- Use `CharacterBody3D` for player-controlled characters, not `RigidBody3D` (unless the design specifically needs physics simulation)
|
||||
- Use `SpringArm3D` for third-person cameras to get free collision avoidance
|
||||
- Prefer `move_and_slide()` with `velocity` over manual collision queries
|
||||
- Export variables (`@export`) for any value a designer might tune; keep magic numbers out of logic
|
||||
- Scene composition over inheritance — build behaviour from small focused scenes
|
||||
- Use `autoload` (singletons) sparingly: only for truly global state (e.g. GameManager, AudioBus); not as a shortcut for passing data
|
||||
- Keep `_physics_process` deterministic and frame-rate independent (always multiply by `delta`)
|
||||
- Prefer signals over direct node references for decoupling
|
||||
|
||||
## Animation & bone conventions
|
||||
|
||||
### Blender rig (matador_v02)
|
||||
- **Armature bones:** `matador` (root) → `COG` → `chest` → `head`, `collarbone_L/R` → `arm_L/R` → `forearm_L/R` → `hand_L/R`, `leg_L/R` → `shin_L/R` → `foot_L/R`
|
||||
- **Rotation mode:** All animated bones use **XYZ Euler** (set in `create_matador_anims.py`)
|
||||
- **Bone-local axes:** Swing (forward/back) is on **local X**. Arm lowering from T-pose is on **local Y** (positive = left arm down, negative = right arm down). Knee bend is **positive X** (shins only bend backward).
|
||||
- **Walk cycle:** 30 frames at 30 fps = 1 second loop. Legs swing ±25° X, knees bend 0–30° X (only when leg is back), arms swing ±15° X opposite phase to legs, arms lowered 55° Y from T-pose, elbows constant 25° X bend.
|
||||
- **Idle pose:** Arms lowered 55° Y, elbows 25° X, everything else at rest.
|
||||
|
||||
### FBX export settings
|
||||
- `primary_bone_axis = 'Y'`, `secondary_bone_axis = 'X'`
|
||||
- `apply_scale_options = 'FBX_SCALE_ALL'`
|
||||
- `add_leaf_bones = False`
|
||||
- `bake_anim_use_all_actions = True`, `bake_anim_use_nla_strips = False`
|
||||
|
||||
### Godot animation names
|
||||
After FBX import, animations appear as `Armature|walk` and `Armature|idle` in AnimationPlayer.
|
||||
|
||||
### Verification workflow
|
||||
1. Edit bones/animations in Blender (`create_matador_anims.py`)
|
||||
2. Run render preview: `blender --background Blender/matador_v02.blend --python Blender/render_anim_preview.py`
|
||||
3. Inspect PNGs in `Blender/preview/` — check bone orientations **before** exporting to Godot
|
||||
4. Export FBX (done automatically by `create_matador_anims.py`)
|
||||
5. Re-import in Godot and test in-game
|
||||
|
||||
## Running tests
|
||||
|
||||
```bash
|
||||
# All tests (lint + logic + gameplay assertions):
|
||||
bash run_tests.sh
|
||||
|
||||
# Individual tests:
|
||||
gdlint *.gd tests/*.gd # GDScript lint (gdtoolkit, installed via uv)
|
||||
godot --headless --script tests/logic_test.gd # pure logic, ~2 s
|
||||
godot --headless --script tests/performance_test.gd # frame-budget regression guard, ~4 s
|
||||
godot --headless --script tests/gameplay_test.gd # full scene, bone sanity, ~4 s
|
||||
|
||||
# Gameplay test with real rendering (inspect frame strip visually):
|
||||
godot --script tests/gameplay_test.gd # opens a window, saves real screenshots
|
||||
# Output: tests/output/gameplay/motion_00..04.png, ragdoll_trigger.png, ragdoll_result.png
|
||||
|
||||
# Difficulty simulation (balance tool, ~2 min):
|
||||
godot --headless --script tests/difficulty_sim.gd # drives a bot bull vs one matador
|
||||
```
|
||||
|
||||
### Difficulty simulation (`tests/difficulty_sim.gd`)
|
||||
A balance tool, not a pass/fail test. It drives a kinematic "bot bull" against one
|
||||
real matador across behaviour profiles (CHARGER / KITER / PASSIVE) and reports the
|
||||
matador's win rate (how often it gores the bull). Use it to tune matador difficulty
|
||||
from data. The bot bull has NO abilities (it only kills by ramming), so it can't use
|
||||
roll/slam/kick — real skilled play beats the matador more than these numbers imply;
|
||||
read the rates as "how well the matador threatens each movement pattern." A rough
|
||||
target is CHARGER high (blind charging is punished), KITER moderate (throws are a
|
||||
dodgeable threat), PASSIVE high (standing still dies). Note: as a `--script` entry it
|
||||
reads the `DP` autoload via `/root/DP`, not the global identifier.
|
||||
|
||||
### What the gameplay test catches
|
||||
| Check | What it detects |
|
||||
|---|---|
|
||||
| Tail Verlet chain spread | Tail bunching — consecutive nodes collapsed to same position |
|
||||
| Ragdoll bone positions finite + within 15 m | Matador limbs exploding after ragdoll impulse |
|
||||
| Ragdoll Y position > −10 | Bones falling through the floor |
|
||||
| Frame strip (visual, manual) | Leg IK quality, animation glitches, anything that looks wrong in motion |
|
||||
|
||||
Headless screenshots will be blank (Forward Plus has no display). Run without `--headless` to get real frame strips.
|
||||
|
||||
### What the performance test catches
|
||||
Loads the full scene with `STRESS_MATADORS` (20) matadors, samples per-frame time
|
||||
during normal play and during a mass-ragdoll spike, and fails if the average
|
||||
exceeds 16 ms or any single frame exceeds 100 ms. Budgets are generous regression
|
||||
guards (not a target frame rate); the measured avg/peak/fps print every run so a
|
||||
gradual creep shows up before it trips the ceiling.
|
||||
|
||||
## Godot 4.x specifics
|
||||
|
||||
- `wrapf` / `wrap` instead of manual modulo for angles
|
||||
- `lerp_angle` for smooth rotation interpolation (handles wrap-around correctly)
|
||||
- `move_toward` for speed ramps without overshooting
|
||||
- `PackedStringArray`, `PackedVector3Array`, etc. for performance-sensitive arrays
|
||||
- `@tool` scripts for editor helpers only — don't use in gameplay scripts
|
||||
- Resource (`extends Resource`) for shared data/config; no plain `Dictionary` for structured data
|
||||
- `StringName` (`&"action_name"`) for input action lookups in hot paths
|
||||
@@ -0,0 +1,205 @@
|
||||
# Bullosseum — Game Design Document
|
||||
|
||||
> Living document. `?` marks open questions.
|
||||
|
||||
---
|
||||
|
||||
## Elevator Pitch
|
||||
|
||||
You are the bull. Waves of cowboys, matadors, and gladiators pour into your arena — each with their own tricks to dodge or counter your charge. Survive, wreck things, pick upgrades. Every run is different. Goofy low-poly mayhem.
|
||||
|
||||
---
|
||||
|
||||
## Art Direction
|
||||
|
||||
- **Style:** Low-poly, chunky geometry, flat or minimal shading
|
||||
- **Tone:** Goofy and physical — think *Gang Beasts* meets *Vampire Survivors* energy
|
||||
- **Camera:** Third-person, spring-arm collision avoidance
|
||||
- **Palette:** Warm sand/terracotta arena, vivid faction colours (red/gold for matadors, brown/blue for cowboys, iron/purple for gladiators)
|
||||
- **Particles:** Stylised cartoon puffs — dust, impact sparks, ragdoll stars
|
||||
- **Audio direction:** ?
|
||||
|
||||
---
|
||||
|
||||
## Confirmed Mechanics
|
||||
|
||||
- Third-person bull locomotion with momentum (walk, charge)
|
||||
- Wide committed turning arc during charge — charges feel like commitments
|
||||
- Visual turn lag (body leans)
|
||||
- Spring-arm camera with zoom
|
||||
- Sand dust particles at hooves (walk = small, charge = big)
|
||||
- Jolt Physics backend
|
||||
|
||||
---
|
||||
|
||||
## Run Structure (Vampire Survivors-inspired)
|
||||
|
||||
```
|
||||
Start run → Wave spawns → Kill enemies → Wave cleared → Pick upgrade → Next wave → ... → Die or achieve target
|
||||
```
|
||||
|
||||
- **No hard time limit per wave** — pressure comes from enemy density escalating
|
||||
- **Upgrade picks between waves** — choose 1 of 3 options (stat, ability, passive synergy)
|
||||
- **Fail state is soft** — getting overwhelmed is a death spiral, not a timeout. You stop being able to charge effectively and get cornered
|
||||
- **Run length:** ? (15–25 minutes for a full run feels right for web)
|
||||
- **Meta progression:** ? Unlock new starting abilities or bull cosmetics across runs
|
||||
|
||||
### Wave Escalation — Faction Ramp
|
||||
|
||||
Factions are introduced one at a time so each mechanic gets space to teach itself before mixing begins.
|
||||
|
||||
| Waves | Faction makeup | Boss |
|
||||
|---|---|---|
|
||||
| 1–3 | Matadors only | — |
|
||||
| 4 | Matadors only | El Presidente |
|
||||
| 5–7 | Matadors + Cowboys introduced | — |
|
||||
| 8 | Mixed (matadors + cowboys) | Sheriff |
|
||||
| 9–11 | All three factions introduced | — |
|
||||
| 12 | Mixed (all three) | Centurion |
|
||||
| 13+ | Full chaos — all factions, escalating density | Repeat bosses + ? final boss |
|
||||
|
||||
- Each new faction's first wave is a "pure" wave so the player can learn the pattern before it mixes
|
||||
- Bosses appear solo — the arena clears before a boss spawns, making it feel like a duel
|
||||
- ? After wave 12, does a loop begin (harder repeat) or does a final boss end the run?
|
||||
|
||||
---
|
||||
|
||||
## Enemy Factions
|
||||
|
||||
### Matadors (the classics)
|
||||
The trickiest faction — they're designed around baiting your charge.
|
||||
|
||||
| Enemy | Behaviour |
|
||||
|---|---|
|
||||
| Matador | Waves red cape to draw your charge, sidesteps at last moment. Must catch them off-guard or predict the dodge |
|
||||
| Banderillero | Plants slow-flags in the ground — charges into one stuns the bull briefly |
|
||||
| Picador | Mounted on horse, tanky, slow. Horse must be hit first before the rider is vulnerable |
|
||||
| ? El Presidente (boss) | Summons matadors and teleports around the arena in bursts |
|
||||
|
||||
### Cowboys
|
||||
The herd faction — individually easy, dangerous in groups.
|
||||
|
||||
| Enemy | Behaviour |
|
||||
|---|---|
|
||||
| Cowboy | Throws lasso to root you for 1–2s, then runs. Easy to hit, just annoying |
|
||||
| Wrangler | Herds other enemies toward you — a force multiplier |
|
||||
| Mounted Cowboy | Circles you on horseback, throwing dynamite. Must cut off the riding arc |
|
||||
| ? Sheriff (boss) | Shotgun blast that staggers the bull; spawns deputies on death |
|
||||
|
||||
### Gladiators
|
||||
The armour faction — charge angles matter.
|
||||
|
||||
| Enemy | Behaviour |
|
||||
|---|---|
|
||||
| Legionary | Front shield absorbs charges completely. Must hit from the side or behind |
|
||||
| Net-thrower | Long-range root that holds you in place for 3s |
|
||||
| Archer | Stationary on elevated platform (arena wall edge), fires slowing arrows |
|
||||
| ? Centurion (boss) | Buffs nearby gladiators, has a charge-reflect shield that bounces you back |
|
||||
|
||||
---
|
||||
|
||||
## Ability System
|
||||
|
||||
Three slots total — always the same structure, filled differently every run.
|
||||
|
||||
```
|
||||
[Charge ──────────] [Medium □] [Ultimate □]
|
||||
always on 1 slot 1 slot
|
||||
```
|
||||
|
||||
### Slot 1 — Charge (always on)
|
||||
| | Description |
|
||||
|---|---|
|
||||
| **Charge** | Hold to build, release to sprint. Committed arc, hard to steer. The foundation everything else is built around |
|
||||
|
||||
### Slot 2 — Medium Ability
|
||||
Cooldown ~8–15s. Tactical, reactive, fills gaps that charge can't. One equipped at a time.
|
||||
|
||||
| Ability | Description | Good against |
|
||||
|---|---|---|
|
||||
| **Stomp** | Slam front hooves — short-range AoE stun | Matador clusters, anything close |
|
||||
| **Gore** | Upward headbutt — launches a single target | Shielded gladiators (bypasses front shield) |
|
||||
| **Tail Whip** | 360° sweep behind and to the sides | Cowboys lassooing from behind |
|
||||
| **Bull Roar** | Knockback shockwave — no damage, pure space creation | Net-throwers, tight groups |
|
||||
| **Ground Pound** | From a jump, landing creates a shockwave crater | Mounted enemies (dismounts them) |
|
||||
| **Counter** | Narrow window — if you charge as an attack lands, explosive ricochet | Picadors, centurion reflect |
|
||||
|
||||
### Slot 3 — Ultimate Ability
|
||||
Cooldown ~35–50s, or requires a full charge meter. High impact. One equipped at a time.
|
||||
|
||||
| Ability | Description | Good against |
|
||||
|---|---|---|
|
||||
| **Stampede** | ~5s of zero deceleration — can't stop or steer well, flattens everything in the path | Boss phases, dense waves |
|
||||
| **Enrage** | ~8s berserk: charge speed +60%, hitbox wider, ignores all slows and roots | Lasso/net-heavy waves |
|
||||
| **Red Mist** | Every enemy on screen gets a red target marker and is pulled slightly toward you — brief guaranteed hits | Matador dodge phase |
|
||||
| **Thunder Horn** | Next charge is electrified — chains damage to up to 4 nearby enemies on contact | Gladiator formations |
|
||||
| **Call of the Herd** | Summon 3 ghost bulls that charge in parallel alongside you for 6s | Any — pure chaos |
|
||||
|
||||
### Card Pick Screen (between every wave)
|
||||
Game pauses. Three cards shown — pick one.
|
||||
|
||||
| Card type | Examples |
|
||||
|---|---|
|
||||
| **New medium** | Swap current medium for a different one |
|
||||
| **New ultimate** | Swap current ultimate for a different one |
|
||||
| **Stat boost** | +charge speed, +turn rate, −medium cooldown, −ultimate cooldown |
|
||||
| **Passive modifier** | Changes how your *current* ability behaves (see below) |
|
||||
| **Synergy** | Unlocks a cross-ability combo effect |
|
||||
|
||||
**Passive modifier examples:**
|
||||
- Stomp → "Dust Blind" — stun cloud also blocks enemy vision for 2s
|
||||
- Gore → "Pinball" — launched enemy bounces off walls and damages others on landing
|
||||
- Stampede → "Aftershock" — leaves a trembling ground trail that slows enemies for 5s
|
||||
- Enrage → "Bloodlust" — kills during enrage reduce remaining cooldown
|
||||
|
||||
**Synergy examples:**
|
||||
- Charge + Stomp = "Seismic Run" — charging for 2s+ turns your next stomp into a ground wave
|
||||
- Gore + Thunder Horn = "Lightning Rod" — electrified gore sends a chain to the whole group
|
||||
- ? Others to discover during design
|
||||
|
||||
---
|
||||
|
||||
## Arena Design
|
||||
|
||||
Each faction maps to an arena environment. Mixed-faction waves could transition the arena or blend themes.
|
||||
|
||||
| Faction | Arena | Hazards |
|
||||
|---|---|---|
|
||||
| Matadors | Sand bullring, wooden barrier ring | Flags slow movement, open centre is the danger zone |
|
||||
| Cowboys | Frontier rodeo grounds, hay bales, fences | Lasso posts (rope traps), horse stampede lanes |
|
||||
| Gladiators | Roman colosseum, stone floor, iron gates | Archer towers on walls, spike traps, wet stone (slide) |
|
||||
|
||||
- ? Does the arena change mid-run or is one arena selected at run start?
|
||||
- ? Destructible fence/barrier sections throughout?
|
||||
|
||||
---
|
||||
|
||||
## Core Loop Revisited
|
||||
|
||||
```
|
||||
Move → Spot threat pattern → Position approach angle → Charge/Ability → Chain hits → Wave clear
|
||||
↑ ↓
|
||||
Dodge/react to debuffs (lasso, net, slow-flag) Pick upgrade (1 of 3)
|
||||
```
|
||||
|
||||
The **positioning** step is where skill expression lives: which enemy to hit first, what angle to approach a shielded gladiator, whether to charge the matador or fake him out.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **Meta progression** — cosmetic unlocks only, or do you unlock new starting medium/ultimate options across runs?
|
||||
2. **Arena change** — single arena per run, or does the arena theme shift when a new faction is introduced mid-run?
|
||||
3. **After wave 12** — infinite loop with scaling difficulty, or a final boss that ends the run cleanly?
|
||||
4. **Ability replacement** — when you pick a new medium/ultimate card, does it always replace the slot, or can you upgrade an existing ability through repeated picks (level 1→2→3)?
|
||||
5. **Web scope** — vertical slice (matadors only, 4 waves, one ability tree) or full 12-wave game?
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- *Vampire Survivors* — wave escalation, upgrade pick loop, run length
|
||||
- *Gang Beasts* — ragdoll slapstick commitment
|
||||
- *Katamari* / *Donut County* — simple core verb scaled through variety
|
||||
- *Superhot* — charge-as-commitment, every move mattering
|
||||
- *Cult of the Lamb* — faction variety with distinct visual languages
|
||||
@@ -0,0 +1,41 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bxm7c6ldrdiq5"
|
||||
path.bptc="res://.godot/imported/citrus_orchard_road_puresky_4k.hdr-262868e8787abf05f7044da72beefce7.bptc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://HDRI/citrus_orchard_road_puresky_4k.hdr"
|
||||
dest_files=["res://.godot/imported/citrus_orchard_road_puresky_4k.hdr-262868e8787abf05f7044da72beefce7.bptc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
@@ -0,0 +1,41 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://3syhacswepyj"
|
||||
path.bptc="res://.godot/imported/kloppenheim_06_puresky_4k.hdr-026f0eabdfce50035e2f8417ce3e0060.bptc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://HDRI/kloppenheim_06_puresky_4k.hdr"
|
||||
dest_files=["res://.godot/imported/kloppenheim_06_puresky_4k.hdr-026f0eabdfce50035e2f8417ce3e0060.bptc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
|
After Width: | Height: | Size: 144 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cyscxku0nw055"
|
||||
path="res://.godot/imported/DASH.png-02cbc39ec03a0c79526d7dc333659c48.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://HUD/DASH.png"
|
||||
dest_files=["res://.godot/imported/DASH.png-02cbc39ec03a0c79526d7dc333659c48.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
After Width: | Height: | Size: 168 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bdnc3jw1ykydi"
|
||||
path="res://.godot/imported/KICK.png-5482be80e8176ed7a0ae69a48ca1f5ed.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://HUD/KICK.png"
|
||||
dest_files=["res://.godot/imported/KICK.png-5482be80e8176ed7a0ae69a48ca1f5ed.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
After Width: | Height: | Size: 204 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d25i88cixy4pn"
|
||||
path="res://.godot/imported/ROLL.png-306dafcb4b6c13eded9a925aa6d2f62a.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://HUD/ROLL.png"
|
||||
dest_files=["res://.godot/imported/ROLL.png-306dafcb4b6c13eded9a925aa6d2f62a.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
After Width: | Height: | Size: 80 KiB |
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bxplqrp4mc5yh"
|
||||
path="res://.godot/imported/SLAM.png-b5036a739251be1240a24080e28d7a8e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://HUD/SLAM.png"
|
||||
dest_files=["res://.godot/imported/SLAM.png-b5036a739251be1240a24080e28d7a8e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@@ -0,0 +1,137 @@
|
||||
[gd_scene format=3 uid="uid://c4df4qgpc3d5g"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://eu2lqjhowj4t" path="res://Assets/Matador.glb" id="1_eicjn"]
|
||||
[ext_resource type="Script" uid="uid://dycnoiadljbb1" path="res://Assets/matador_intro_menu.gd" id="2_5jr0i"]
|
||||
[ext_resource type="PackedScene" uid="uid://dio67r8ambe7h" path="res://Assets/arena_placeholder_v01.glb" id="3_1v6n4"]
|
||||
[ext_resource type="PackedScene" uid="uid://dxe72ig8gfbcg" path="res://Assets/arena model2026.glb" id="3_5jr0i"]
|
||||
[ext_resource type="PackedScene" uid="uid://crtm0xtiql3r8" path="res://Player.tscn" id="4_eicjn"]
|
||||
[ext_resource type="Texture2D" uid="uid://3syhacswepyj" path="res://HDRI/kloppenheim_06_puresky_4k.hdr" id="6_1v6n4"]
|
||||
|
||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_eicjn"]
|
||||
|
||||
[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_w7j4y"]
|
||||
panorama = ExtResource("6_1v6n4")
|
||||
energy_multiplier = 5.6
|
||||
|
||||
[sub_resource type="Sky" id="Sky_3el7n"]
|
||||
sky_material = SubResource("PanoramaSkyMaterial_w7j4y")
|
||||
|
||||
[sub_resource type="Environment" id="Environment_5jr0i"]
|
||||
background_mode = 2
|
||||
background_energy_multiplier = 0.18
|
||||
sky = SubResource("Sky_3el7n")
|
||||
ambient_light_color = Color(0.31061712, 0.31061712, 0.3106171, 1)
|
||||
ambient_light_energy = 16.0
|
||||
ssao_enabled = true
|
||||
ssao_radius = 1.17
|
||||
ssao_intensity = 0.0
|
||||
glow_intensity = 0.34
|
||||
glow_strength = 0.29
|
||||
glow_bloom = 0.1
|
||||
fog_light_color = Color(2.211, 2.211, 2.211, 1)
|
||||
fog_light_energy = 0.01
|
||||
fog_density = 0.0399
|
||||
volumetric_fog_enabled = true
|
||||
volumetric_fog_density = 0.0005
|
||||
volumetric_fog_emission = Color(1, 1, 1, 1)
|
||||
volumetric_fog_emission_energy = 7.85
|
||||
volumetric_fog_anisotropy = 0.9
|
||||
volumetric_fog_length = 69.07
|
||||
|
||||
[sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_5jr0i"]
|
||||
dof_blur_far_enabled = true
|
||||
dof_blur_far_distance = 26.01
|
||||
dof_blur_near_enabled = true
|
||||
dof_blur_near_distance = 2.6
|
||||
dof_blur_near_transition = 5.0
|
||||
|
||||
[node name="IntroMenu" type="Node3D" unique_id=2130618263]
|
||||
|
||||
[node name="Matador" parent="." unique_id=166852612 instance=ExtResource("1_eicjn")]
|
||||
transform = Transform3D(-0.56715536, 0, -0.8236109, 0, 1, 0, 0.8236109, 0, -0.56715536, 5.2114463, -0.08998108, 1.8927763)
|
||||
script = ExtResource("2_5jr0i")
|
||||
|
||||
[node name="Skeleton3D" parent="Matador/Armature" parent_id_path=PackedInt32Array(166852612, 1269629432) index="0" unique_id=978366810]
|
||||
bones/0/position = Vector3(0.056660548, 0.6424767, -0.0167365)
|
||||
bones/0/rotation = Quaternion(0.013179442, -0.2660563, 0.073319815, 0.9610747)
|
||||
bones/1/rotation = Quaternion(0.06234612, 0.049236443, 0.08183311, 0.99347484)
|
||||
bones/2/rotation = Quaternion(-0.073883414, -0.049860783, -0.17668208, 0.9802238)
|
||||
bones/3/rotation = Quaternion(0.1986702, -0.17794952, -0.71790075, 0.6430262)
|
||||
bones/4/rotation = Quaternion(0.34491858, -0.4473084, -0.25076818, 0.7861691)
|
||||
bones/5/rotation = Quaternion(0.2577085, 0.103201896, -0.6748433, 0.68375605)
|
||||
bones/6/rotation = Quaternion(1.7417646e-08, -1.0305205e-07, -0.05870078, 0.99827564)
|
||||
bones/7/rotation = Quaternion(0.24033272, 0.3103031, 0.5222128, 0.7571301)
|
||||
bones/8/rotation = Quaternion(5.5530215e-08, 1.2911333e-07, 0.055464897, 0.99846065)
|
||||
bones/9/rotation = Quaternion(-6.3051346e-09, -3.6333955e-07, 0.005667881, 0.999984)
|
||||
bones/10/rotation = Quaternion(2.5839595e-08, 9.468444e-08, 0.058700778, 0.99827564)
|
||||
bones/11/rotation = Quaternion(0.39202607, 0.47060946, 0.57993996, 0.53713304)
|
||||
bones/12/rotation = Quaternion(0.8712108, 0.008231261, 0.48523128, 0.073990606)
|
||||
bones/13/rotation = Quaternion(-0.056263044, 0.0027001738, 0.3080972, 0.9496859)
|
||||
bones/14/rotation = Quaternion(0.016082464, 0.024660494, -0.86586916, 0.4994036)
|
||||
bones/15/rotation = Quaternion(0.6067664, -0.3062479, -0.7163194, 0.15790276)
|
||||
bones/16/rotation = Quaternion(-0.0731876, -0.0023153822, -0.47496143, 0.87695485)
|
||||
bones/17/rotation = Quaternion(-0.11824294, -0.17776872, 0.80557114, 0.55269533)
|
||||
bones/18/rotation = Quaternion(0.5305965, -0.28927496, 0.76720744, -0.21489605)
|
||||
bones/20/position = Vector3(0.22012731, 0.38421977, 0.36399037)
|
||||
bones/21/position = Vector3(-0.23671798, 0.052281797, -0.027087089)
|
||||
bones/21/rotation = Quaternion(0.5078295, -0.4920459, -0.4920459, 0.50782955)
|
||||
bones/22/position = Vector3(-0.39721552, 0.31719273, 0.3595722)
|
||||
bones/23/position = Vector3(-0.9167187, 1.3206767, 0.42621902)
|
||||
bones/23/rotation = Quaternion(0.9993525, -0.0021175682, 0.03502641, -0.00795782)
|
||||
bones/24/rotation = Quaternion(0.08874816, -0.018719967, -0.04671622, 0.99478185)
|
||||
bones/25/rotation = Quaternion(0.09634846, -0.0268489, -0.04050248, 0.9941608)
|
||||
|
||||
[node name="matador" parent="Matador/Armature/Skeleton3D" index="0" unique_id=256196413]
|
||||
transform = Transform3D(0.8642424, 0, 0.50307554, 0, 1, 0, -0.50307554, 0, 0.8642424, 0, 0, 0)
|
||||
|
||||
[node name="Muleta" parent="Matador/Armature/Skeleton3D" index="1" unique_id=988244930]
|
||||
cast_shadow = 0
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="." unique_id=1531255459]
|
||||
transform = Transform3D(0.42176014, 0.2362673, 0.8753835, -0.10687317, 0.97167695, -0.21076548, -0.900387, -0.0046625203, 0.4350652, 8.41945, 0.17132203, 2.0652685)
|
||||
fov = 41.6
|
||||
near = 0.001
|
||||
|
||||
[node name="arena model2026" parent="." unique_id=179544183 instance=ExtResource("3_5jr0i")]
|
||||
transform = Transform3D(-0.83746713, 0, 0.54648757, 0, 0.99999994, 0, -0.54648757, 0, -0.83746713, 3.8733478, -0.6, -1.1080065)
|
||||
|
||||
[node name="arena_placeholder_v01" parent="." unique_id=1343590504 instance=ExtResource("3_1v6n4")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.3344436, 0, -1.5401263)
|
||||
visible = false
|
||||
|
||||
[node name="StaticBody3D" type="StaticBody3D" parent="arena_placeholder_v01" unique_id=340133176]
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="arena_placeholder_v01/StaticBody3D" unique_id=201484167]
|
||||
transform = Transform3D(-33.265, 4.9526625e-07, -2.9081186e-06, 5.0228755e-06, 3.28, 0, -2.9081186e-06, 4.329755e-14, 33.265, 0, -3.3065948, 0)
|
||||
shape = SubResource("CylinderShape3D_eicjn")
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=660229295]
|
||||
transform = Transform3D(0.9491592, 0.31479403, -0.0014368258, -0.28033537, 0.84731936, 0.45106864, 0.14321098, -0.4277331, 0.89248836, 1.1162033, 7.3956842, -4.480528)
|
||||
light_energy = 1.32
|
||||
shadow_enabled = true
|
||||
shadow_blur = 8.689
|
||||
|
||||
[node name="DirectionalLight3D2" type="DirectionalLight3D" parent="." unique_id=498871251]
|
||||
transform = Transform3D(0.835524, -0.5376153, 0.11344351, -0.48260456, -0.6193575, 0.6192651, -0.26266432, -0.572159, -0.7769435, 1.1162033, 7.3956842, -4.480528)
|
||||
visible = false
|
||||
light_energy = 0.415
|
||||
light_indirect_energy = 16.0
|
||||
light_volumetric_fog_energy = 1.11
|
||||
shadow_blur = 10.0
|
||||
|
||||
[node name="Player" parent="." unique_id=165510044 instance=ExtResource("4_eicjn")]
|
||||
transform = Transform3D(0.9563367, 0, 0.29226705, 0, 1, 0, -0.29226705, 0, 0.9563367, 3.0920272, 0.39692497, -4.302477)
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=114793752]
|
||||
environment = SubResource("Environment_5jr0i")
|
||||
camera_attributes = SubResource("CameraAttributesPractical_5jr0i")
|
||||
|
||||
[node name="SpotLight3D" type="SpotLight3D" parent="." unique_id=1428020323]
|
||||
transform = Transform3D(0.94930077, -0.05846006, -0.30888584, 0.21308771, 0.8420559, 0.4955155, 0.23113126, -0.53621286, 0.81182146, -20.807917, 10.690277, 20.135067)
|
||||
visible = false
|
||||
light_energy = 16.0
|
||||
light_volumetric_fog_energy = 16.0
|
||||
shadow_enabled = true
|
||||
spot_range = 84.316696
|
||||
|
||||
[editable path="Matador"]
|
||||
@@ -0,0 +1,252 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://bmnmenu0intr1"]
|
||||
|
||||
[ext_resource type="Script" path="res://main_menu.gd" id="1_menu"]
|
||||
[ext_resource type="VideoStream" path="res://Assets/intro_bg.ogv" id="2_video"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="sb_normal"]
|
||||
content_margin_left = 16.0
|
||||
content_margin_top = 8.0
|
||||
content_margin_right = 16.0
|
||||
content_margin_bottom = 8.0
|
||||
bg_color = Color(0, 0, 0, 0.4)
|
||||
corner_radius_top_left = 8
|
||||
corner_radius_top_right = 8
|
||||
corner_radius_bottom_right = 8
|
||||
corner_radius_bottom_left = 8
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="sb_hover"]
|
||||
content_margin_left = 16.0
|
||||
content_margin_top = 8.0
|
||||
content_margin_right = 16.0
|
||||
content_margin_bottom = 8.0
|
||||
bg_color = Color(0, 0, 0, 0.65)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(1, 0.85, 0.2, 1)
|
||||
corner_radius_top_left = 8
|
||||
corner_radius_top_right = 8
|
||||
corner_radius_bottom_right = 8
|
||||
corner_radius_bottom_left = 8
|
||||
|
||||
[node name="MainMenu" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_menu")
|
||||
|
||||
[node name="VideoStreamPlayer" type="VideoStreamPlayer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
stream = ExtResource("2_video")
|
||||
expand = true
|
||||
|
||||
[node name="MainPanel" type="Control" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="PlayButton" type="Button" parent="MainPanel"]
|
||||
layout_mode = 1
|
||||
anchor_left = 0.4530
|
||||
anchor_top = 0.6513
|
||||
anchor_right = 0.4530
|
||||
anchor_bottom = 0.6513
|
||||
offset_left = -120.0
|
||||
offset_top = -55.0
|
||||
offset_right = 120.0
|
||||
offset_bottom = 55.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 8
|
||||
theme_override_font_sizes/font_size = 56
|
||||
theme_override_styles/normal = SubResource("sb_normal")
|
||||
theme_override_styles/hover = SubResource("sb_hover")
|
||||
theme_override_styles/pressed = SubResource("sb_hover")
|
||||
theme_override_styles/focus = SubResource("sb_hover")
|
||||
text = "PLAY"
|
||||
|
||||
[node name="OptionsButton" type="Button" parent="MainPanel"]
|
||||
layout_mode = 1
|
||||
anchor_left = 0.11
|
||||
anchor_top = 0.94
|
||||
anchor_right = 0.11
|
||||
anchor_bottom = 0.94
|
||||
offset_left = -100.0
|
||||
offset_top = -28.0
|
||||
offset_right = 100.0
|
||||
offset_bottom = 28.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 6
|
||||
theme_override_font_sizes/font_size = 30
|
||||
theme_override_styles/normal = SubResource("sb_normal")
|
||||
theme_override_styles/hover = SubResource("sb_hover")
|
||||
theme_override_styles/pressed = SubResource("sb_hover")
|
||||
theme_override_styles/focus = SubResource("sb_hover")
|
||||
text = "OPTIONS"
|
||||
|
||||
[node name="CreditsButton" type="Button" parent="MainPanel"]
|
||||
layout_mode = 1
|
||||
anchor_left = 0.489
|
||||
anchor_top = 0.951
|
||||
anchor_right = 0.489
|
||||
anchor_bottom = 0.951
|
||||
offset_left = -100.0
|
||||
offset_top = -28.0
|
||||
offset_right = 100.0
|
||||
offset_bottom = 28.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 6
|
||||
theme_override_font_sizes/font_size = 30
|
||||
theme_override_styles/normal = SubResource("sb_normal")
|
||||
theme_override_styles/hover = SubResource("sb_hover")
|
||||
theme_override_styles/pressed = SubResource("sb_hover")
|
||||
theme_override_styles/focus = SubResource("sb_hover")
|
||||
text = "CREDITS"
|
||||
|
||||
[node name="ExitButton" type="Button" parent="MainPanel"]
|
||||
layout_mode = 1
|
||||
anchor_left = 0.92
|
||||
anchor_top = 0.951
|
||||
anchor_right = 0.92
|
||||
anchor_bottom = 0.951
|
||||
offset_left = -100.0
|
||||
offset_top = -28.0
|
||||
offset_right = 100.0
|
||||
offset_bottom = 28.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 6
|
||||
theme_override_font_sizes/font_size = 30
|
||||
theme_override_styles/normal = SubResource("sb_normal")
|
||||
theme_override_styles/hover = SubResource("sb_hover")
|
||||
theme_override_styles/pressed = SubResource("sb_hover")
|
||||
theme_override_styles/focus = SubResource("sb_hover")
|
||||
text = "EXIT"
|
||||
|
||||
[node name="OptionsPanel" type="CenterContainer" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Backdrop" type="ColorRect" parent="OptionsPanel"]
|
||||
layout_mode = 2
|
||||
color = Color(0, 0, 0, 0.55)
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="OptionsPanel"]
|
||||
custom_minimum_size = Vector2(560, 480)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 16
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="OptionsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 8
|
||||
theme_override_font_sizes/font_size = 44
|
||||
text = "Controls"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="Hint" type="Label" parent="OptionsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 4
|
||||
text = "Click a key, then press a new key. Esc cancels."
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="Scroll" type="ScrollContainer" parent="OptionsPanel/VBox"]
|
||||
custom_minimum_size = Vector2(0, 340)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
horizontal_scroll_mode = 0
|
||||
|
||||
[node name="RebindList" type="VBoxContainer" parent="OptionsPanel/VBox/Scroll"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/separation = 8
|
||||
|
||||
[node name="BackButton" type="Button" parent="OptionsPanel/VBox"]
|
||||
custom_minimum_size = Vector2(0, 48)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Back"
|
||||
|
||||
[node name="CreditsPanel" type="CenterContainer" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Backdrop" type="ColorRect" parent="CreditsPanel"]
|
||||
layout_mode = 2
|
||||
color = Color(0, 0, 0, 0.55)
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="CreditsPanel"]
|
||||
custom_minimum_size = Vector2(520, 360)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="CreditsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 8
|
||||
theme_override_font_sizes/font_size = 44
|
||||
text = "Credits"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="Names" type="Label" parent="CreditsPanel/VBox"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 4
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Bullosseum
|
||||
|
||||
A game by Siim & Richard"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="BackButton" type="Button" parent="CreditsPanel/VBox"]
|
||||
custom_minimum_size = Vector2(0, 48)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Back"
|
||||
|
||||
[node name="FadeRect" type="ColorRect" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
color = Color(0, 0, 0, 0)
|
||||
@@ -0,0 +1,2 @@
|
||||
[InternetShortcut]
|
||||
URL=https://www.youtube.com/watch?v=ZCb12AHKMfE
|
||||
@@ -0,0 +1,29 @@
|
||||
[gd_scene format=3 uid="uid://matador_scene_v1"]
|
||||
|
||||
[ext_resource type="Script" path="res://matador.gd" id="1_matgd"]
|
||||
[ext_resource type="PackedScene" uid="uid://eu2lqjhowj4t" path="res://Assets/Matador.glb" id="2_matfbx"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_body"]
|
||||
radius = 0.25
|
||||
height = 1.2
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_hit"]
|
||||
radius = 0.45
|
||||
height = 1.4
|
||||
|
||||
[node name="Matador" type="CharacterBody3D"]
|
||||
script = ExtResource("1_matgd")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.85, 0)
|
||||
shape = SubResource("CapsuleShape3D_body")
|
||||
|
||||
[node name="HitArea" type="Area3D" parent="."]
|
||||
monitoring = true
|
||||
monitorable = false
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="HitArea"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.85, 0)
|
||||
shape = SubResource("CapsuleShape3D_hit")
|
||||
|
||||
[node name="matador2" parent="." instance=ExtResource("2_matfbx")]
|
||||
@@ -0,0 +1,38 @@
|
||||
[gd_scene format=3 uid="uid://crtm0xtiql3r8"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bn777gguclud5" path="res://player.gd" id="1_xhfnw"]
|
||||
[ext_resource type="Script" uid="uid://cpyq2r5cq653g" path="res://camera_iso.gd" id="2_camera_iso"]
|
||||
[ext_resource type="PackedScene" uid="uid://bun14xmk20pcj" path="res://Assets/bull.fbx" id="4_e80uo"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_chest"]
|
||||
radius = 0.35
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_belly"]
|
||||
radius = 0.4
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_hips"]
|
||||
radius = 0.3
|
||||
|
||||
[node name="Player" type="CharacterBody3D" unique_id=165510044]
|
||||
collision_layer = 3
|
||||
script = ExtResource("1_xhfnw")
|
||||
|
||||
[node name="CollisionChest" type="CollisionShape3D" parent="." unique_id=447032296]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.505, -0.2)
|
||||
shape = SubResource("SphereShape3D_chest")
|
||||
|
||||
[node name="CollisionBelly" type="CollisionShape3D" parent="." unique_id=571780801]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.505, 0.1)
|
||||
shape = SubResource("SphereShape3D_belly")
|
||||
|
||||
[node name="CollisionHips" type="CollisionShape3D" parent="." unique_id=717874116]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.505, 0.4)
|
||||
shape = SubResource("SphereShape3D_hips")
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="." unique_id=1120161087]
|
||||
script = ExtResource("2_camera_iso")
|
||||
|
||||
[node name="bull" parent="." unique_id=1386495166 instance=ExtResource("4_e80uo")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.655, 0.23)
|
||||
|
||||
[editable path="bull"]
|
||||
@@ -0,0 +1,33 @@
|
||||
# Contribution
|
||||
|
||||
Hello, thanks for taking time and helping out with the addon!
|
||||
|
||||
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. Please sign the CLA before sending the PR: https://www.jetbrains.com/agreements/cla/.
|
||||
|
||||
#### Local setup
|
||||
|
||||
Open the `godot-editor-plugin/CMakeLists.txt` in Rider 2026.1+, select `rider-gdextension` target in the run configuration selector.
|
||||
There are some more fixes coming in 2026.2, which will allow working on gdscript and cpp files within the same workspace.
|
||||
|
||||
#### Signing the binaries
|
||||
|
||||
Plugin binaries need to be signed to comply with modern operating system security requirements. Unsigned dynamic libraries may fail to load or trigger security warnings:
|
||||
|
||||
- **macOS**: Requires code signing (and often notarization) for `.dylib` files. Unsigned libraries may simply fail to load.
|
||||
- **Windows**: SmartScreen may block unsigned binaries, and corporate environments often enforce signed code only.
|
||||
- **Linux**: Generally allows unsigned `.so` files, but some sandboxed environments (Flatpak, Snap) impose restrictions.
|
||||
|
||||
**How signing is implemented:**
|
||||
|
||||
1. **TeamCity Configuration**: [ijplatform_master_Net_Deploy_Plugins_Public_Godot](https://buildserver.labs.intellij.net/buildConfiguration/ijplatform_master_Net_Deploy_Plugins_Public_Godot) (internal JetBrains link)
|
||||
- Note: The automatic trigger on new tags is currently not working, so manual triggering is required.
|
||||
|
||||
2. **Release Process**:
|
||||
- First, use your GitHub Action to prepare a **pre-release** with a tag
|
||||
- Manually trigger the TeamCity configuration on the necessary branch/tag
|
||||
- The configuration will download assets, sign them, and upload them back (removing the pre-release flag)
|
||||
- The pre-release flag is required at the start; otherwise, the signing configuration will skip the release (protection against double signing)
|
||||
|
||||
3. **Signing existing releases**:
|
||||
- You can run signing on already existing old releases/tags
|
||||
- Mark them as pre-release first, then run the configuration on the necessary tag
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 JetBrains
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,51 @@
|
||||
# JetBrains Rider Integration – Godot addon
|
||||
|
||||
This addon currently provides two features:
|
||||
1. Finds all Rider installations in the system and provides a selector on the `Text Editor` -> `External` tab in the settings to select one.
|
||||
2. Provides the "Use Rider" toggle in the Godot toolbar and, when enabled, applies a set of editor settings recommended for working with JetBrains Rider. The goal is to make it trivial to switch between Rider‑optimized settings and stock Godot settings with a single click.
|
||||
|
||||
## Quick start
|
||||
|
||||
Requirements:
|
||||
- Godot 4.2.2+
|
||||
|
||||
Install:
|
||||
1. Inside the Godot editor, it can be installed from the AssetLib view or [downloaded](https://godotengine.org/asset-library/asset/4576)
|
||||
2. [Optional] Change the initial value of `active` in the plugin.cfg
|
||||
3. [Optional] Change the initial values in the presets.json file.
|
||||
4. Enable "JetBrains Rider External Editor" plugin in the Project → Project Settings… → Plugins tab.
|
||||
|
||||
Use:
|
||||
- A toolbar toggle named "Use Rider" will appear. Click it to turn the preset On/Off.
|
||||
|
||||
Screenshot:
|
||||

|
||||
|
||||
## What the toggle changes
|
||||
|
||||
The preset values live in `presets.json`.
|
||||
|
||||
When ON:
|
||||
- Write the values from the "on" preset into the Editor Settings.
|
||||
|
||||
When OFF:
|
||||
- Write the values from the "off" preset into the Editor Settings.
|
||||
|
||||
Note: The plugin does not currently auto‑set Rider’s executable path or flags. See Plans below.
|
||||
|
||||
## Setting Rider to be the external editor
|
||||
|
||||
The plugin automatically detects installed Rider versions on your system and provides a convenient dropdown menu to
|
||||
select which installation to use as your external editor.
|
||||
|
||||
- The plugin scans common installation locations for Rider on Windows, macOS, and Linux.
|
||||
- Detected installations appear in the "Select Rider" dropdown in the toolbar.
|
||||
- When you select a Rider installation, the plugin automatically updates the `dotnet/editor/external_editor_path` editor
|
||||
setting.
|
||||
|
||||
## License
|
||||
See `addons/rider-plugin/LICENCE`.
|
||||
|
||||
## Acknowledgements
|
||||
Created by JetBrains to streamline using Rider with Godot.
|
||||
Initial idea https://github.com/sszigeti/toggle_external_editor
|
||||
@@ -0,0 +1,16 @@
|
||||
[configuration]
|
||||
|
||||
entry_symbol = "rider_library_init"
|
||||
compatibility_minimum = "4.2.2"
|
||||
|
||||
[libraries]
|
||||
|
||||
macos.single.debug = "./macos/librider-gdextension.macos.editor.dylib"
|
||||
|
||||
windows.arm64.single.debug = "./windows/rider-gdextension.windows.editor.arm64.dll"
|
||||
|
||||
windows.x86_64.single.debug = "./windows/rider-gdextension.windows.editor.x86_64.dll"
|
||||
|
||||
linux.x86_64.single.debug = "./linux/librider-gdextension.linux.editor.x86_64.so"
|
||||
|
||||
linux.arm64.single.debug = "./linux/librider-gdextension.linux.editor.arm64.so"
|
||||
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.0"
|
||||
id="katman_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 512 512"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="JetBrains Rider Icon.svg"
|
||||
width="512"
|
||||
height="512"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs43" /><sodipodi:namedview
|
||||
id="namedview41"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0980553"
|
||||
inkscape:cx="256.36233"
|
||||
inkscape:cy="212.19333"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1027"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="22"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="katman_1" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{fill:url(#SVGID_00000130622934180993703410000017420799098261276343_);}
|
||||
.st2{fill:url(#SVGID_00000060739771362873723200000017991140373209755022_);}
|
||||
.st3{fill:#FFFFFF;}
|
||||
</style>
|
||||
<symbol
|
||||
id="rider"
|
||||
viewBox="-35 -35 70 70">
|
||||
<linearGradient
|
||||
id="SVGID_1_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="30.4897"
|
||||
y1="5.1188998"
|
||||
x2="-23.4683"
|
||||
y2="-25.8451">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#DD1265"
|
||||
id="stop4" />
|
||||
<stop
|
||||
offset="0.483"
|
||||
style="stop-color:#DD1265"
|
||||
id="stop6" />
|
||||
<stop
|
||||
offset="0.942"
|
||||
style="stop-color:#FDB60D"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
<path
|
||||
class="st0"
|
||||
d="M 35,-7.7 -14.1,-35 18.8,13.9 25.5,9.5 Z"
|
||||
id="path11" />
|
||||
|
||||
<linearGradient
|
||||
id="SVGID_00000169517474296634577950000016895268102491994795_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-1.5839"
|
||||
y1="-28.888"
|
||||
x2="19.805099"
|
||||
y2="30.174999">
|
||||
<stop
|
||||
offset="0.139"
|
||||
style="stop-color:#087CFA"
|
||||
id="stop13" />
|
||||
<stop
|
||||
offset="0.476"
|
||||
style="stop-color:#DD1265"
|
||||
id="stop15" />
|
||||
<stop
|
||||
offset="0.958"
|
||||
style="stop-color:#087CFA"
|
||||
id="stop17" />
|
||||
</linearGradient>
|
||||
<path
|
||||
style="fill:url(#SVGID_00000169517474296634577950000016895268102491994795_)"
|
||||
d="M 15.5,-18.9 9.3,-33.9 -4.3,-20.5 1.2,28.1 14.4,35 35,23 Z"
|
||||
id="path20" />
|
||||
|
||||
<linearGradient
|
||||
id="SVGID_00000135668350575375336630000014638141720088491653_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-17.5865"
|
||||
y1="-27.071199"
|
||||
x2="-1.7875"
|
||||
y2="29.073799">
|
||||
<stop
|
||||
offset="0.278"
|
||||
style="stop-color:#DD1265"
|
||||
id="stop22" />
|
||||
<stop
|
||||
offset="0.968"
|
||||
style="stop-color:#FDB60D"
|
||||
id="stop24" />
|
||||
</linearGradient>
|
||||
<path
|
||||
style="fill:url(#SVGID_00000135668350575375336630000014638141720088491653_)"
|
||||
d="m -14.1,-35 -20.9,14.1 7.8,48.1 20.1,7.7 26,-21 z"
|
||||
id="path27" />
|
||||
<path
|
||||
d="M 21,-21 H -21 V 21 H 21 Z"
|
||||
id="path29" />
|
||||
<path
|
||||
class="st3"
|
||||
d="m -0.6,13.6 h -15.8 v 2.7 h 15.8 z"
|
||||
id="path31" />
|
||||
<path
|
||||
class="st3"
|
||||
d="m 0.5,-15.8 h 6.2 c 5,0 8.4,3.4 8.4,7.7 0,4.4 -3.4,7.9 -8.4,7.9 L 0.5,0 Z m 3.5,3.2 v 9.5 h 2.7 c 2.8,0 4.8,-1.9 4.8,-4.6 0,-2.8 -1.9,-4.7 -4.8,-4.7 z"
|
||||
id="path33" />
|
||||
<path
|
||||
class="st3"
|
||||
d="m -15.7,-15.8 h 7.2 c 2,0 3.5,0.6 4.6,1.6 0.9,0.9 1.3,2.1 1.3,3.6 v 0.1 c 0,1.3 -0.3,2.3 -0.9,3.1 -0.6,0.8 -1.4,1.4 -2.4,1.8 L -2,0 h -4.1 l -3.3,-4.8 h -2.9 V 0 h -3.5 z m 7,7.7 c 0.8,0 1.5,-0.2 2,-0.6 0.5,-0.4 0.7,-1 0.7,-1.6 v -0.1 c 0,-0.8 -0.2,-1.3 -0.7,-1.7 -0.5,-0.3 -1.1,-0.6 -2,-0.6 h -3.4 v 4.5 h 3.4 z"
|
||||
id="path35" />
|
||||
</symbol>
|
||||
<use
|
||||
xlink:href="#rider"
|
||||
width="70"
|
||||
height="70"
|
||||
x="-35"
|
||||
y="-35"
|
||||
transform="matrix(7.0682519,0,0,7.2481031,256,256)"
|
||||
style="overflow:visible"
|
||||
id="use38" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://wrdrj6wednn8"
|
||||
path="res://.godot/imported/icon.svg-45c914cff7482ba9564963fe65b548e4.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/rider-plugin/icons/icon.svg"
|
||||
dest_files=["res://.godot/imported/icon.svg-45c914cff7482ba9564963fe65b548e4.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
@@ -0,0 +1,12 @@
|
||||
[plugin]
|
||||
|
||||
name="JetBrains Rider External Editor"
|
||||
description="Provides a toolbar toggle, to switch a set of settings on and off. Default set of settings helps to enable/disable the following settings recommended by the Rider documentation https://www.jetbrains.com/help/rider/Godot.html#optimize-godot-editor-for-rider"
|
||||
author="JetBrains"
|
||||
version="1.0.0"
|
||||
script="rider-plugin.gd"
|
||||
|
||||
[presets]
|
||||
|
||||
active="off"
|
||||
presets="presets.json"
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"on": {
|
||||
"text_editor/external/use_external_editor": true,
|
||||
"interface/editor/import_resources_when_unfocused": true,
|
||||
"interface/editor/save_on_focus_loss": true,
|
||||
"text_editor/behavior/files/auto_reload_scripts_on_external_change": true,
|
||||
"run/window_placement/game_embed_mode": -1
|
||||
},
|
||||
"off": {
|
||||
"text_editor/external/use_external_editor": false,
|
||||
"interface/editor/import_resources_when_unfocused": false,
|
||||
"interface/editor/save_on_focus_loss": false,
|
||||
"text_editor/behavior/files/auto_reload_scripts_on_external_change": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
var editor_settings: EditorSettings
|
||||
var checkbutton: CheckButton
|
||||
var _preset_applier: PresetApplier
|
||||
var _settings_service: EditorSettingsService
|
||||
var _locator_service: RiderLocatorService
|
||||
var _plugin_cfg_path: String
|
||||
var _presets_json_path: String
|
||||
|
||||
func _enter_tree() -> void:
|
||||
editor_settings = EditorInterface.get_editor_settings()
|
||||
var script_path := (get_script() as Script).resource_path
|
||||
var plugin_dir := script_path.get_base_dir()
|
||||
_plugin_cfg_path = plugin_dir + "/plugin.cfg"
|
||||
var cfg := ConfigFile.new()
|
||||
var err := cfg.load(_plugin_cfg_path)
|
||||
if err != OK:
|
||||
push_warning("Failed to load plugin.cfg: %s" % [err])
|
||||
return
|
||||
var active_str := str(cfg.get_value("presets", "active", "on"))
|
||||
var is_active := active_str == "on"
|
||||
var presets_rel_path := str(cfg.get_value("presets", "presets", "presets.json"))
|
||||
_presets_json_path = plugin_dir + "/" + presets_rel_path
|
||||
|
||||
# Build UI
|
||||
checkbutton = CheckButton.new()
|
||||
checkbutton.text = "Use Rider"
|
||||
checkbutton.tooltip_text = "Shortcut for setting recommended settings"
|
||||
checkbutton.button_pressed = is_active
|
||||
checkbutton.pressed.connect(_on_checkbutton_pressed)
|
||||
add_control_to_container(EditorPlugin.CONTAINER_TOOLBAR, checkbutton)
|
||||
|
||||
# Initialize services and panel
|
||||
_settings_service = EditorSettingsService.new()
|
||||
_locator_service = RiderLocatorService.new()
|
||||
_preset_applier = PresetApplier.new(_presets_json_path)
|
||||
|
||||
_locator_service.add_selector_in_editor_interface(_settings_service)
|
||||
|
||||
# Ensure settings reflect current state on startup
|
||||
_preset_applier.apply_preset(editor_settings, is_active)
|
||||
|
||||
func _on_checkbutton_pressed() -> void:
|
||||
var cfg := ConfigFile.new()
|
||||
if cfg.load(_plugin_cfg_path) != OK:
|
||||
push_warning("Failed to load plugin.cfg to update state")
|
||||
return
|
||||
var is_active := checkbutton.button_pressed
|
||||
var key := _preset_applier.get_preset_key(is_active)
|
||||
cfg.set_value("presets", "active", key)
|
||||
var save_err := cfg.save(_plugin_cfg_path)
|
||||
if save_err != OK:
|
||||
push_warning("Failed to save plugin.cfg: %s" % [save_err])
|
||||
# Apply selected preset to editor settings
|
||||
_preset_applier.apply_preset(editor_settings, is_active)
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if checkbutton != null:
|
||||
remove_control_from_container(EditorPlugin.CONTAINER_TOOLBAR, checkbutton)
|
||||
checkbutton.queue_free()
|
||||
|
||||
var args = OS.get_cmdline_args()
|
||||
if "--rider-addon-tests" in args:
|
||||
print("==== rider-addon-tests finished ====")
|
||||