commit 13dbb551c8764e6b7190ba6e89991a7be80f283e Author: sapphopup Date: Mon Feb 23 11:37:27 2026 +0100 init diff --git a/rougelikeaboutmechs/.godot/.gdignore b/rougelikeaboutmechs/.godot/.gdignore new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/rougelikeaboutmechs/.godot/.gdignore @@ -0,0 +1 @@ + diff --git a/rougelikeaboutmechs/.godot/editor/editor_layout.cfg b/rougelikeaboutmechs/.godot/editor/editor_layout.cfg new file mode 100644 index 0000000..ee051df --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/editor_layout.cfg @@ -0,0 +1,69 @@ +[docks] + +dock_3_selected_tab_idx=0 +dock_4_selected_tab_idx=0 +dock_5_selected_tab_idx=0 +dock_floating={} +dock_closed=[] +dock_split_2=0 +dock_split_3=0 +dock_hsplit_1=0 +dock_hsplit_2=280 +dock_hsplit_3=-280 +dock_hsplit_4=0 +dock_3="Scene,Import" +dock_4="FileSystem,History" +dock_5="Inspector,Signals,Groups" +dock_9="Output,Debugger,Audio,Animation,Shader Editor,Search Results,AnimationTree,ResourcePreloader,ShaderFile,SpriteFrames,Theme,Polygon,TileSet,TileMap,Replication,GridMap" + +[docks/FileSystem] + +h_split_offset=240 +v_split_offset=0 +display_mode=0 +file_sort=0 +file_list_display_mode=1 +selected_paths=PackedStringArray("res://Machines/") +uncollapsed_paths=PackedStringArray("Favorites", "res://", "res://ui/screens/", "res://ui/screens/title-screen/") + +[docks/History] + +include_scene=true +include_global=true + +[EditorNode] + +open_scenes=PackedStringArray("res://core/gamemanager.tscn", "res://levels/main_level.tscn", "res://ui/screens/title-screen/title_screen.tscn") +current_scene="res://ui/screens/title-screen/title_screen.tscn" +bottom_panel_offsets={ +"Audio": -450 +} +selected_default_debugger_tab_idx=0 +selected_main_editor_idx=2 + +[EditorWindow] + +screen=0 +mode="maximized" +position=Vector2i(1986, 69) + +[ScriptEditor] + +open_scripts=["res://Machines/machine_resource.gd"] +selected_script="res://Machines/machine_resource.gd" +open_help=[] +script_split_offset=200 +list_split_offset=0 +zoom_factor=1.0 + +[GameView] + +floating_window_rect=Rect2i(0, 0, 0, 0) +floating_window_screen=-1 + +[ShaderEditor] + +open_shaders=[] +split_offset=200 +selected_shader="" +text_shader_zoom_factor=1.0 diff --git a/rougelikeaboutmechs/.godot/editor/editor_script_doc_cache.res b/rougelikeaboutmechs/.godot/editor/editor_script_doc_cache.res new file mode 100644 index 0000000..e28cd24 Binary files /dev/null and b/rougelikeaboutmechs/.godot/editor/editor_script_doc_cache.res differ diff --git a/rougelikeaboutmechs/.godot/editor/editor_script_doc_cache.res-folding-a7de57390d6e786984ca20c70a831128.cfg b/rougelikeaboutmechs/.godot/editor/editor_script_doc_cache.res-folding-a7de57390d6e786984ca20c70a831128.cfg new file mode 100644 index 0000000..e860dd4 --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/editor_script_doc_cache.res-folding-a7de57390d6e786984ca20c70a831128.cfg @@ -0,0 +1,3 @@ +[folding] + +sections_unfolded=PackedStringArray() diff --git a/rougelikeaboutmechs/.godot/editor/filesystem_cache10 b/rougelikeaboutmechs/.godot/editor/filesystem_cache10 new file mode 100644 index 0000000..64e975d --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/filesystem_cache10 @@ -0,0 +1,58 @@ +63f7b34db8d8cdea90c76aacccf841ec +::res://::1771841836 +icon.svg::CompressedTexture2D::7874505655436279264::1771841784::1771841837::1::::<><><>0<>0<>8c6dc71835cb1092831a2181a7cbcbe4<>res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex:: +README.md::TextFile::-1::1771841784::0::1::::<><><>0<>0<><>:: +::res://autoloads/::1771841784 +debug_global.gd::GDScript::3519651180120881073::1771841784::0::1::::<>Node<><>0<>0<><>:: +global.gd::GDScript::1176894133255043534::1771841784::0::1::::<>Node<><>0<>0<><>:: +input_manager.gd::GDScript::8575146745769188893::1771841784::0::1::::<>Node<><>0<>0<><>:: +::res://autoloads/settings/::1771841784 +settings.gd::GDScript::1169167139487781899::1771841784::0::1::::<>Node<><>0<>0<><>:: +user_defined_settings.gd::GDScript::5353537388395803011::1771841784::0::1::::UserDefinedSettings<>RefCounted<><>0<>0<><>:: +::res://core/::1771841784 +default_bus_layout.tres::AudioBusLayout::6406833063048569073::1771841784::0::1::::<><><>0<>0<><>:: +gamemanager.gd::GDScript::5587465302030124915::1771841784::0::1::::GameManager<>Node<><>0<>0<><>:: +gamemanager.tscn::PackedScene::5236817490969193782::1771841784::0::1::::<><><>0<>0<><>::uid://cluu0cgltsenj::::res://core/gamemanager.gd<>uid://bilai15byqef2::::res://ui/screens/pause-menu/pause_menu.tscn<>uid://bhb4ckqipjvu3::::res://core/main_environment.tres<>uid://cyfvcuxi210mg::::res://levels/main_level.tscn<>uid://hheneshfv1b2::::res://ui/themes/your_theme.tres +main_environment.tres::Environment::2881571881625704016::1771841784::0::1::::<><><>0<>0<><>:: +::res://levels/::1771841784 +levels_readme.md::TextFile::-1::1771841784::0::1::::<><><>0<>0<><>:: +main_level.tscn::PackedScene::6468975218303303874::1771841784::0::1::::<><><>0<>0<><>:: +::res://ui/::1771841784 +::res://ui/components/::1771841784 +::res://ui/components/settings-menu/::1771841784 +Revert.svg::CompressedTexture2D::4339617245426587863::1771841784::1771841837::1::::<><><>0<>0<>297dc219980ee096674b7de235f79953<>res://.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.ctex:: +settings_menu.gd::GDScript::582134994019510841::1771841784::0::1::::<>TabContainer<><>0<>0<><>:: +settings_menu.tscn::PackedScene::6304534932307647668::1771841784::0::1::::<><><>0<>0<><>::uid://ij8xcd6np4vt::::res://ui/components/settings-menu/settings_menu.gd<>uid://hheneshfv1b2::::res://ui/themes/your_theme.tres +::res://ui/components/settings-menu/action-remapping-button/::1771841784 +action_remapping_button.gd::GDScript::4642898967767345029::1771841784::0::1::::<>Button<><>0<>0<><>:: +action_remapping_button.tscn::PackedScene::925410865498412070::1771841784::0::1::::<><><>0<>0<><>::uid://b7fb4ravo24q0::::res://ui/components/settings-menu/action-remapping-button/action_remapping_button.gd +::res://ui/screens/::1771841784 +::res://ui/screens/control-screen/::1771841784 +control_screen.gd::GDScript::6615828920758056178::1771841784::0::1::::<>Control<><>0<>0<><>:: +control_screen.tscn::PackedScene::3476236442146173568::1771841784::0::1::::<><><>0<>0<><>::uid://hheneshfv1b2::::res://ui/themes/your_theme.tres<>uid://c1i00arsdf2mw::::res://ui/screens/control-screen/control_screen.gd +::res://ui/screens/credit-screen/::1771841784 +credits.json::JSON::-1::1771841784::0::1::::<><><>0<>0<><>:: +credit_element.gd::GDScript::2210728914878077746::1771841784::0::1::::CreditButton<>VBoxContainer<><>0<>0<><>:: +credit_element.tscn::PackedScene::2912162567317968620::1771841784::0::1::::<><><>0<>0<><>::uid://6q5m84onxilu::::res://ui/screens/credit-screen/credit_element.gd +credit_entry.gd::GDScript::5420422509298114093::1771841784::0::1::::CreditEntry<>Resource<><>0<>0<><>:: +credit_screen.gd::GDScript::8836023702103504430::1771841784::0::1::::<>Control<><>0<>0<><>:: +credit_screen.tscn::PackedScene::358879150997730698::1771841784::0::1::::<><><>0<>0<><>::uid://dx5iawpcgwhlm::::res://ui/screens/credit-screen/credit_screen.gd<>uid://hheneshfv1b2::::res://ui/themes/your_theme.tres +::res://ui/screens/level-select-screen/::1771841784 +level_button.gd::GDScript::8704749015755386232::1771841784::0::1::::LevelButton<>Button<><>0<>0<><>:: +level_button.tscn::PackedScene::4949170022177206724::1771841784::0::1::::<><><>0<>0<><>::uid://dwav7d4amw8yu::::res://ui/screens/level-select-screen/level_button.gd +level_select.gd::GDScript::9072899083889100288::1771841784::0::1::::<>Control<><>0<>0<><>:: +level_select.tscn::PackedScene::6316590214924971141::1771841784::0::1::::<><><>0<>0<><>::uid://hheneshfv1b2::::res://ui/themes/your_theme.tres<>uid://d2i8k7votngvg::::res://ui/screens/level-select-screen/level_select.gd +::res://ui/screens/pause-menu/::1771841784 +pause_menu.gd::GDScript::1923905240375656616::1771841784::0::1::::<>Control<><>0<>0<><>:: +pause_menu.tscn::PackedScene::2970655286472634229::1771841784::0::1::::<><><>0<>0<><>::uid://hheneshfv1b2::::res://ui/themes/your_theme.tres<>uid://2n7o5t6b5g4w::::res://ui/screens/pause-menu/pause_menu.gd<>uid://cv271fh4d2p13::::res://ui/components/settings-menu/settings_menu.tscn +::res://ui/screens/settings-screen/::1771841784 +settings_screen.gd::GDScript::1222641183840346394::1771841784::0::1::::<>MarginContainer<><>0<>0<><>:: +settings_screen.tscn::PackedScene::1731407975515257069::1771841784::0::1::::<><><>0<>0<><>::uid://hheneshfv1b2::::res://ui/themes/your_theme.tres<>uid://roiysiotwsbq::::res://ui/screens/settings-screen/settings_screen.gd<>uid://cv271fh4d2p13::::res://ui/components/settings-menu/settings_menu.tscn +::res://ui/screens/title-screen/::1771841784 +title_screen.gd::GDScript::1850264627441223832::1771841784::0::1::::<>Control<><>0<>0<><>:: +title_screen.tscn::PackedScene::7375686277331198226::1771841784::0::1::::<><><>0<>0<><>::uid://hheneshfv1b2::::res://ui/themes/your_theme.tres<>uid://1mjt83fygiua::::res://ui/screens/title-screen/title_screen.gd +::res://ui/screens/win-screen/::1771841784 +win_screen.gd::GDScript::7620355351831359998::1771841784::0::1::::<>Control<><>0<>0<><>:: +win_screen.tscn::PackedScene::477294899242648607::1771841784::0::1::::<><><>0<>0<><>::uid://dgtme0a6lym5c::::res://ui/screens/win-screen/win_screen.gd +::res://ui/themes/::1771841784 +your_theme.tres::Theme::506038871261939837::1771841784::0::1::::<><><>0<>0<><>::uid://b23e4kqj4o6dv::::res://ui/components/settings-menu/Revert.svg diff --git a/rougelikeaboutmechs/.godot/editor/filesystem_update4 b/rougelikeaboutmechs/.godot/editor/filesystem_update4 new file mode 100644 index 0000000..fc80a6e --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/filesystem_update4 @@ -0,0 +1,4 @@ +res://ui/screens/title-screen/title_screen.tscn +res://ui/themes/your_theme.tres +res://core/main_environment.tres +res://Machines/machine_resource.gd diff --git a/rougelikeaboutmechs/.godot/editor/gamemanager.tscn-folding-48287f37207b317b2325a76b92cc51d6.cfg b/rougelikeaboutmechs/.godot/editor/gamemanager.tscn-folding-48287f37207b317b2325a76b92cc51d6.cfg new file mode 100644 index 0000000..cbc60af --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/gamemanager.tscn-folding-48287f37207b317b2325a76b92cc51d6.cfg @@ -0,0 +1,5 @@ +[folding] + +node_unfolds=[NodePath("."), PackedStringArray("Process"), NodePath("MenuLayer/DebugLabel"), PackedStringArray("Visibility", "Layout", "Theme"), NodePath("MenuLayer/PauseMenu"), PackedStringArray("Visibility", "Layout", "Theme")] +resource_unfolds=[] +nodes_folded=[] diff --git a/rougelikeaboutmechs/.godot/editor/machine_resource.gd-folding-d76bd0be45d6c9655d99cb87763c941a.cfg b/rougelikeaboutmechs/.godot/editor/machine_resource.gd-folding-d76bd0be45d6c9655d99cb87763c941a.cfg new file mode 100644 index 0000000..e860dd4 --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/machine_resource.gd-folding-d76bd0be45d6c9655d99cb87763c941a.cfg @@ -0,0 +1,3 @@ +[folding] + +sections_unfolded=PackedStringArray() diff --git a/rougelikeaboutmechs/.godot/editor/main_environment.tres-folding-3b48bb884ba92d39c6d95f6ed37971a1.cfg b/rougelikeaboutmechs/.godot/editor/main_environment.tres-folding-3b48bb884ba92d39c6d95f6ed37971a1.cfg new file mode 100644 index 0000000..e860dd4 --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/main_environment.tres-folding-3b48bb884ba92d39c6d95f6ed37971a1.cfg @@ -0,0 +1,3 @@ +[folding] + +sections_unfolded=PackedStringArray() diff --git a/rougelikeaboutmechs/.godot/editor/main_level.tscn-folding-6efb9bf2c17f7a7a9ce6dabc081e1bd9.cfg b/rougelikeaboutmechs/.godot/editor/main_level.tscn-folding-6efb9bf2c17f7a7a9ce6dabc081e1bd9.cfg new file mode 100644 index 0000000..1d019fa --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/main_level.tscn-folding-6efb9bf2c17f7a7a9ce6dabc081e1bd9.cfg @@ -0,0 +1,5 @@ +[folding] + +node_unfolds=[] +resource_unfolds=[] +nodes_folded=[] diff --git a/rougelikeaboutmechs/.godot/editor/project_metadata.cfg b/rougelikeaboutmechs/.godot/editor/project_metadata.cfg new file mode 100644 index 0000000..2e61486 --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/project_metadata.cfg @@ -0,0 +1,16 @@ +[game_view] + +select_mode=0 + +[editor_metadata] + +executable_path="/home/emily/Desktop/Godot_v4.5.1-stable_mono_linux_x86_64/Godot_v4.6-stable_linux.x86_64" + +[recent_files] + +scenes=["res://ui/screens/title-screen/title_screen.tscn", "res://levels/main_level.tscn", "res://core/gamemanager.tscn"] +scripts=["res://Machines/machine_resource.gd"] + +[script_setup] + +last_selected_language="GDScript" diff --git a/rougelikeaboutmechs/.godot/editor/script_editor_cache.cfg b/rougelikeaboutmechs/.godot/editor/script_editor_cache.cfg new file mode 100644 index 0000000..6df5176 --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/script_editor_cache.cfg @@ -0,0 +1,17 @@ +[res://Machines/machine_resource.gd] + +state={ +"bookmarks": PackedInt32Array(), +"breakpoints": PackedInt32Array(), +"column": 0, +"folded_lines": PackedInt32Array(), +"h_scroll_position": 0, +"row": 0, +"scroll_position": 0.0, +"selection": true, +"selection_from_column": 0, +"selection_from_line": 0, +"selection_to_column": 0, +"selection_to_line": 10, +"syntax_highlighter": "GDScript" +} diff --git a/rougelikeaboutmechs/.godot/editor/title_screen.tscn-editstate-98e4621d2a18950baa99a7d02722957a.cfg b/rougelikeaboutmechs/.godot/editor/title_screen.tscn-editstate-98e4621d2a18950baa99a7d02722957a.cfg new file mode 100644 index 0000000..d0be389 --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/title_screen.tscn-editstate-98e4621d2a18950baa99a7d02722957a.cfg @@ -0,0 +1,192 @@ +[editor_states] + +2D={ +"grid_offset": Vector2(0, 0), +"grid_snap_active": false, +"grid_step": Vector2(8, 8), +"grid_visibility": 1, +"ofs": Vector2(-166, -111), +"primary_grid_step": Vector2i(8, 8), +"show_group_gizmos": true, +"show_guides": true, +"show_helpers": false, +"show_lock_gizmos": true, +"show_origin": true, +"show_position_gizmos": true, +"show_rulers": true, +"show_transformation_gizmos": true, +"show_viewport": true, +"show_zoom_control": true, +"smart_snap_active": false, +"snap_guides": true, +"snap_node_anchors": true, +"snap_node_center": true, +"snap_node_parent": true, +"snap_node_sides": true, +"snap_other_nodes": true, +"snap_pixel": true, +"snap_relative": false, +"snap_rotation": false, +"snap_rotation_offset": 0.0, +"snap_rotation_step": 0.2617994, +"snap_scale": false, +"snap_scale_step": 0.1, +"zoom": 1.0 +} +3D={ +"fov": 70.01, +"gizmos_status": { +"AudioListener3D": 0, +"AudioStreamPlayer3D": 0, +"CPUParticles3D": 0, +"CSGShape3D": 0, +"Camera3D": 0, +"ChainIK3D": 0, +"CollisionObject3D": 0, +"CollisionPolygon3D": 0, +"CollisionShape3D": 0, +"Decal": 0, +"FogVolume": 0, +"GPUParticles3D": 0, +"GPUParticlesCollision3D": 0, +"Joint3D": 0, +"Light3D": 0, +"LightmapGI": 0, +"LightmapProbe": 0, +"Marker3D": 0, +"MeshInstance3DCustomAABB": 0, +"NavigationLink3D": 0, +"NavigationObstacle3D": 0, +"NavigationRegion3D": 0, +"OccluderInstance3D": 0, +"Particles3DEmissionShape": 0, +"Path3D": 0, +"PhysicalBone3D": 0, +"RayCast3D": 0, +"ReflectionProbe": 0, +"ShapeCast3D": 0, +"Skeleton3D": 0, +"SoftBody3D": 0, +"SpringArm3D": 0, +"SpringBoneCollision3D": 0, +"SpringBoneSimulator3D": 0, +"TwoBoneIK3D": 0, +"VehicleWheel3D": 0, +"VisibleOnScreenNotifier3D": 0, +"VoxelGI": 0 +}, +"local_coords": false, +"preview_sun_env": { +"environ_ao_enabled": false, +"environ_enabled": true, +"environ_energy": 1.0, +"environ_gi_enabled": false, +"environ_glow_enabled": false, +"environ_ground_color": Color(0.2, 0.169, 0.133, 1), +"environ_sky_color": Color(0.385, 0.454, 0.55, 1), +"environ_tonemap_enabled": true, +"sun_color": Color(1, 1, 1, 1), +"sun_enabled": true, +"sun_energy": 1.0, +"sun_rotation": Vector2(-1.0471976, 2.6179938), +"sun_shadow_max_distance": 100.0 +}, +"rotate_snap": 15.0, +"scale_snap": 10.0, +"show_grid": true, +"show_origin": true, +"snap_enabled": false, +"translate_snap": 1.0, +"viewport_mode": 1, +"viewports": [{ +"auto_orthogonal": false, +"auto_orthogonal_enabled": true, +"cinematic_preview": false, +"display_mode": 22, +"distance": 4.0, +"doppler": false, +"frame_time": false, +"gizmos": true, +"grid": true, +"half_res": false, +"information": false, +"listener": true, +"lock_rotation": false, +"orthogonal": false, +"position": Vector3(0, 0, 0), +"transform_gizmo": true, +"use_environment": false, +"view_type": 0, +"x_rotation": 0.5, +"y_rotation": -0.5 +}, { +"auto_orthogonal": false, +"auto_orthogonal_enabled": true, +"cinematic_preview": false, +"display_mode": 22, +"distance": 4.0, +"doppler": false, +"frame_time": false, +"gizmos": true, +"grid": true, +"half_res": false, +"information": false, +"listener": false, +"lock_rotation": false, +"orthogonal": false, +"position": Vector3(0, 0, 0), +"transform_gizmo": true, +"use_environment": false, +"view_type": 0, +"x_rotation": 0.5, +"y_rotation": -0.5 +}, { +"auto_orthogonal": false, +"auto_orthogonal_enabled": true, +"cinematic_preview": false, +"display_mode": 22, +"distance": 4.0, +"doppler": false, +"frame_time": false, +"gizmos": true, +"grid": true, +"half_res": false, +"information": false, +"listener": false, +"lock_rotation": false, +"orthogonal": false, +"position": Vector3(0, 0, 0), +"transform_gizmo": true, +"use_environment": false, +"view_type": 0, +"x_rotation": 0.5, +"y_rotation": -0.5 +}, { +"auto_orthogonal": false, +"auto_orthogonal_enabled": true, +"cinematic_preview": false, +"display_mode": 22, +"distance": 4.0, +"doppler": false, +"frame_time": false, +"gizmos": true, +"grid": true, +"half_res": false, +"information": false, +"listener": false, +"lock_rotation": false, +"orthogonal": false, +"position": Vector3(0, 0, 0), +"transform_gizmo": true, +"use_environment": false, +"view_type": 0, +"x_rotation": 0.5, +"y_rotation": -0.5 +}], +"zfar": 4000.01, +"znear": 0.05 +} +Anim={ +"visible": false +} +selected_nodes=Array[NodePath]([]) diff --git a/rougelikeaboutmechs/.godot/editor/title_screen.tscn-folding-98e4621d2a18950baa99a7d02722957a.cfg b/rougelikeaboutmechs/.godot/editor/title_screen.tscn-folding-98e4621d2a18950baa99a7d02722957a.cfg new file mode 100644 index 0000000..13beda0 --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/title_screen.tscn-folding-98e4621d2a18950baa99a7d02722957a.cfg @@ -0,0 +1,5 @@ +[folding] + +node_unfolds=[NodePath("."), PackedStringArray("Layout", "Theme"), NodePath("CenterContainer"), PackedStringArray("Layout"), NodePath("CenterContainer/VBoxContainer"), PackedStringArray("Layout"), NodePath("CenterContainer/VBoxContainer/Label"), PackedStringArray("Layout"), NodePath("CenterContainer/VBoxContainer/Label2"), PackedStringArray("Layout"), NodePath("CenterContainer2"), PackedStringArray("Layout"), NodePath("CenterContainer2/VBoxContainer"), PackedStringArray("Layout"), NodePath("CenterContainer2/VBoxContainer/Start"), PackedStringArray("Layout", "Theme Overrides"), NodePath("CenterContainer2/VBoxContainer/LevelSelect"), PackedStringArray("Layout", "Theme Overrides"), NodePath("CenterContainer2/VBoxContainer/Options"), PackedStringArray("Layout", "Theme Overrides"), NodePath("CenterContainer2/VBoxContainer/Credit"), PackedStringArray("Layout", "Theme Overrides"), NodePath("CenterContainer2/VBoxContainer/Quit"), PackedStringArray("Layout", "Theme Overrides"), NodePath("Label"), PackedStringArray("Layout")] +resource_unfolds=["res://ui/screens/title-screen/title_screen.tscn::LabelSettings_s0ue6", PackedStringArray("Resource", "Font"), "res://ui/screens/title-screen/title_screen.tscn::LabelSettings_73xnf", PackedStringArray("Resource", "Font"), "res://ui/screens/title-screen/title_screen.tscn::LabelSettings_wly7t", PackedStringArray("Resource", "Font")] +nodes_folded=[] diff --git a/rougelikeaboutmechs/.godot/editor/your_theme.tres-folding-17cbbb39152c1dc4240bac158c7d90c1.cfg b/rougelikeaboutmechs/.godot/editor/your_theme.tres-folding-17cbbb39152c1dc4240bac158c7d90c1.cfg new file mode 100644 index 0000000..e860dd4 --- /dev/null +++ b/rougelikeaboutmechs/.godot/editor/your_theme.tres-folding-17cbbb39152c1dc4240bac158c7d90c1.cfg @@ -0,0 +1,3 @@ +[folding] + +sections_unfolded=PackedStringArray() diff --git a/rougelikeaboutmechs/.godot/global_script_class_cache.cfg b/rougelikeaboutmechs/.godot/global_script_class_cache.cfg new file mode 100644 index 0000000..71a3d3c --- /dev/null +++ b/rougelikeaboutmechs/.godot/global_script_class_cache.cfg @@ -0,0 +1,49 @@ +list=[{ +"base": &"Resource", +"class": &"machine", +"icon": "", +"is_abstract": false, +"is_tool": false, +"language": &"GDScript", +"path": "res://Machines/machine_resource.gd" +}, { +"base": &"Button", +"class": &"LevelButton", +"icon": "", +"is_abstract": false, +"is_tool": false, +"language": &"GDScript", +"path": "res://ui/screens/level-select-screen/level_button.gd" +}, { +"base": &"Resource", +"class": &"CreditEntry", +"icon": "", +"is_abstract": false, +"is_tool": false, +"language": &"GDScript", +"path": "res://ui/screens/credit-screen/credit_entry.gd" +}, { +"base": &"VBoxContainer", +"class": &"CreditButton", +"icon": "", +"is_abstract": false, +"is_tool": false, +"language": &"GDScript", +"path": "res://ui/screens/credit-screen/credit_element.gd" +}, { +"base": &"Node", +"class": &"GameManager", +"icon": "", +"is_abstract": false, +"is_tool": false, +"language": &"GDScript", +"path": "res://core/gamemanager.gd" +}, { +"base": &"RefCounted", +"class": &"UserDefinedSettings", +"icon": "", +"is_abstract": false, +"is_tool": false, +"language": &"GDScript", +"path": "res://autoloads/settings/user_defined_settings.gd" +}] diff --git a/rougelikeaboutmechs/.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.ctex b/rougelikeaboutmechs/.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.ctex new file mode 100644 index 0000000..33780c9 Binary files /dev/null and b/rougelikeaboutmechs/.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.ctex differ diff --git a/rougelikeaboutmechs/.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.md5 b/rougelikeaboutmechs/.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.md5 new file mode 100644 index 0000000..e5453d5 --- /dev/null +++ b/rougelikeaboutmechs/.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.md5 @@ -0,0 +1,3 @@ +source_md5="74b418f0ad54c53aeb91140a4206ecb3" +dest_md5="e98449c33f4839c7955d565269d6f1fc" + diff --git a/rougelikeaboutmechs/.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex b/rougelikeaboutmechs/.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex new file mode 100644 index 0000000..6e1d156 Binary files /dev/null and b/rougelikeaboutmechs/.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex differ diff --git a/rougelikeaboutmechs/.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.md5 b/rougelikeaboutmechs/.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.md5 new file mode 100644 index 0000000..a505ba5 --- /dev/null +++ b/rougelikeaboutmechs/.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.md5 @@ -0,0 +1,3 @@ +source_md5="0eed98577cbbf02f0bdc0f5c9f70465b" +dest_md5="b48bef1f2eefdd190e0a3e60a6188d75" + diff --git a/rougelikeaboutmechs/.godot/scene_groups_cache.cfg b/rougelikeaboutmechs/.godot/scene_groups_cache.cfg new file mode 100644 index 0000000..e69de29 diff --git a/rougelikeaboutmechs/.godot/shader_cache/CanvasShaderGLES3/bc1fb5a7d2c0e6000dc8227efaff6f33068510a00f40dc015d830c9fbd01bbb9/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache b/rougelikeaboutmechs/.godot/shader_cache/CanvasShaderGLES3/bc1fb5a7d2c0e6000dc8227efaff6f33068510a00f40dc015d830c9fbd01bbb9/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache new file mode 100644 index 0000000..59f6771 Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/CanvasShaderGLES3/bc1fb5a7d2c0e6000dc8227efaff6f33068510a00f40dc015d830c9fbd01bbb9/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/CopyShaderGLES3/3ad2e241b0889670f725f1b71f1a998f4a83e7e7b109787b00a98a88e240a94c/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache b/rougelikeaboutmechs/.godot/shader_cache/CopyShaderGLES3/3ad2e241b0889670f725f1b71f1a998f4a83e7e7b109787b00a98a88e240a94c/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache new file mode 100644 index 0000000..6ebb865 Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/CopyShaderGLES3/3ad2e241b0889670f725f1b71f1a998f4a83e7e7b109787b00a98a88e240a94c/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/CubemapFilterShaderGLES3/4cc0823e06a0d12648b42ae8e111ae6b90876e6b4bf0fb82231715b37eed3004/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache b/rougelikeaboutmechs/.godot/shader_cache/CubemapFilterShaderGLES3/4cc0823e06a0d12648b42ae8e111ae6b90876e6b4bf0fb82231715b37eed3004/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache new file mode 100644 index 0000000..8bf0e43 Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/CubemapFilterShaderGLES3/4cc0823e06a0d12648b42ae8e111ae6b90876e6b4bf0fb82231715b37eed3004/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/FeedShaderGLES3/2513e6b47ed01ad85a89cfd7af0e9ba5c3a40042c97a826f2a463909ab82859c/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache b/rougelikeaboutmechs/.godot/shader_cache/FeedShaderGLES3/2513e6b47ed01ad85a89cfd7af0e9ba5c3a40042c97a826f2a463909ab82859c/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache new file mode 100644 index 0000000..916eb21 Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/FeedShaderGLES3/2513e6b47ed01ad85a89cfd7af0e9ba5c3a40042c97a826f2a463909ab82859c/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/GlowShaderGLES3/0082aff9e00f520ac4eff229254f9529db38c81669863e4e94d96772fa6b45ca/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache b/rougelikeaboutmechs/.godot/shader_cache/GlowShaderGLES3/0082aff9e00f520ac4eff229254f9529db38c81669863e4e94d96772fa6b45ca/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache new file mode 100644 index 0000000..7c5083a Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/GlowShaderGLES3/0082aff9e00f520ac4eff229254f9529db38c81669863e4e94d96772fa6b45ca/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/PostShaderGLES3/a07f29036be8cc9b61410289490102a6c120e7f76339671cbac6e1fadd70dba0/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache b/rougelikeaboutmechs/.godot/shader_cache/PostShaderGLES3/a07f29036be8cc9b61410289490102a6c120e7f76339671cbac6e1fadd70dba0/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache new file mode 100644 index 0000000..c9ae035 Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/PostShaderGLES3/a07f29036be8cc9b61410289490102a6c120e7f76339671cbac6e1fadd70dba0/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache b/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache new file mode 100644 index 0000000..7891e90 Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/6bb7c9a2fd1c4a8fa77cb96555b9b4a720209981.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/a38af2d0725c8e99d8492f4c72736f24d6a54cc5.cache b/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/a38af2d0725c8e99d8492f4c72736f24d6a54cc5.cache new file mode 100644 index 0000000..efb58a3 Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/a38af2d0725c8e99d8492f4c72736f24d6a54cc5.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/cafb1506f2db0c3681435e264aa18e216d1a7a40.cache b/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/cafb1506f2db0c3681435e264aa18e216d1a7a40.cache new file mode 100644 index 0000000..2c612fc Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/SceneShaderGLES3/56d06bf5a96d4a1ecf650c381ae765a44df6a276c6fd297b94b85f1557b451ea/cafb1506f2db0c3681435e264aa18e216d1a7a40.cache differ diff --git a/rougelikeaboutmechs/.godot/shader_cache/SkyShaderGLES3/8286912b5fe1e281c77c1b56c0f9e949d76f560bd64e8942da0f664cd960c550/2c82eb5fea9b549e20c9f41e308abf9a4fc5d76f.cache b/rougelikeaboutmechs/.godot/shader_cache/SkyShaderGLES3/8286912b5fe1e281c77c1b56c0f9e949d76f560bd64e8942da0f664cd960c550/2c82eb5fea9b549e20c9f41e308abf9a4fc5d76f.cache new file mode 100644 index 0000000..c5063bf Binary files /dev/null and b/rougelikeaboutmechs/.godot/shader_cache/SkyShaderGLES3/8286912b5fe1e281c77c1b56c0f9e949d76f560bd64e8942da0f664cd960c550/2c82eb5fea9b549e20c9f41e308abf9a4fc5d76f.cache differ diff --git a/rougelikeaboutmechs/.godot/uid_cache.bin b/rougelikeaboutmechs/.godot/uid_cache.bin new file mode 100644 index 0000000..5f480d4 Binary files /dev/null and b/rougelikeaboutmechs/.godot/uid_cache.bin differ diff --git a/rougelikeaboutmechs/LICENSE b/rougelikeaboutmechs/LICENSE new file mode 100644 index 0000000..c17a345 --- /dev/null +++ b/rougelikeaboutmechs/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Ekaterina Ehringhaus and Hendrik Brucker + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/rougelikeaboutmechs/Machines/machine_resource.gd b/rougelikeaboutmechs/Machines/machine_resource.gd new file mode 100644 index 0000000..e51f6a8 --- /dev/null +++ b/rougelikeaboutmechs/Machines/machine_resource.gd @@ -0,0 +1,10 @@ +extends Resource +class_name machine + +@export var modell_name : StringName +@export var carry_capacity : float +@export var hit_points : float +@export var fuel_tank_capacity : float +@export var weapon_slots : Array +@export var machine_upgrades : Array +var current_fuel_in_tank : float diff --git a/rougelikeaboutmechs/Machines/machine_resource.gd.uid b/rougelikeaboutmechs/Machines/machine_resource.gd.uid new file mode 100644 index 0000000..5fb757b --- /dev/null +++ b/rougelikeaboutmechs/Machines/machine_resource.gd.uid @@ -0,0 +1 @@ +uid://dyur6uu5di5ak diff --git a/rougelikeaboutmechs/autoloads/debug_global.gd b/rougelikeaboutmechs/autoloads/debug_global.gd new file mode 100644 index 0000000..4d74987 --- /dev/null +++ b/rougelikeaboutmechs/autoloads/debug_global.gd @@ -0,0 +1,43 @@ +extends Node + +var debug_label : Label + +var debug_dict = Dictionary() +var update_queued = true + +func _ready() -> void: + InputManager.game_debug_show.connect(_show_label) + InputManager.game_debug_hide.connect(_hide_label) + +func _show_label() -> void: + if debug_label: + debug_label.visible = true + InputManager.is_debug_label_visible = true + if debug_label == null: + push_warning("debug label not set") + +func _hide_label() -> void: + if debug_label: + debug_label.visible = false + InputManager.is_debug_label_visible = false + +func set_debug_info(key: String, value: Variant): + debug_dict[key] = value + update_queued = true + +func reset_debug_info(key: String): + debug_dict.erase(key) + update_queued = true + +func _process(_delta): + if update_queued: + if debug_label == null: + update_queued = false + return + var debug_text = "" + for key in debug_dict.keys(): + debug_text += key + ": " + str(debug_dict[key]) + "\n" + debug_label.text = debug_text + + update_queued = false + diff --git a/rougelikeaboutmechs/autoloads/debug_global.gd.uid b/rougelikeaboutmechs/autoloads/debug_global.gd.uid new file mode 100644 index 0000000..b829dc1 --- /dev/null +++ b/rougelikeaboutmechs/autoloads/debug_global.gd.uid @@ -0,0 +1 @@ +uid://bqe7e1wowo03f diff --git a/rougelikeaboutmechs/autoloads/global.gd b/rougelikeaboutmechs/autoloads/global.gd new file mode 100644 index 0000000..77e7d5c --- /dev/null +++ b/rougelikeaboutmechs/autoloads/global.gd @@ -0,0 +1,6 @@ +extends Node + +var game_manager : GameManager = null + +func set_game_manager(p_game_manager: GameManager): + game_manager = p_game_manager diff --git a/rougelikeaboutmechs/autoloads/global.gd.uid b/rougelikeaboutmechs/autoloads/global.gd.uid new file mode 100644 index 0000000..45d5756 --- /dev/null +++ b/rougelikeaboutmechs/autoloads/global.gd.uid @@ -0,0 +1 @@ +uid://q1djliepls3g diff --git a/rougelikeaboutmechs/autoloads/input_manager.gd b/rougelikeaboutmechs/autoloads/input_manager.gd new file mode 100644 index 0000000..d54c799 --- /dev/null +++ b/rougelikeaboutmechs/autoloads/input_manager.gd @@ -0,0 +1,50 @@ +extends Node + +#region Showing new Screens +signal game_pause +signal game_unpause +signal game_debug_show +signal game_debug_hide +#endregion + +#region Game State Management +var _is_in_game: bool = false +var _is_paused: bool = false +var is_debug_label_visible: bool = false +var capture_mouse_ingame: bool = true +#endregion + +enum InputType {MOUSE, JOYPAD} + +func _ready(): + set_process_mode(Node.PROCESS_MODE_ALWAYS) + +func _input(event: InputEvent) -> void: + + if event.is_action_pressed("pause"): + if (_is_in_game and not _is_paused): + game_pause.emit() + elif (_is_in_game and _is_paused): + game_unpause.emit() + elif event.is_action_pressed("toggle_debug_label"): + if is_debug_label_visible: + game_debug_hide.emit() + else: + game_debug_show.emit() + elif not _is_in_game: + pass + +func set_is_in_game(b: bool) -> void: + _is_in_game = b + _update_mouse_capture() + +func _update_mouse_capture() -> void: + if capture_mouse_ingame: + if (not _is_in_game) || _is_paused: + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + else: + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + +func set_is_paused(b: bool) -> void: + _is_paused = b + _update_mouse_capture() diff --git a/rougelikeaboutmechs/autoloads/input_manager.gd.uid b/rougelikeaboutmechs/autoloads/input_manager.gd.uid new file mode 100644 index 0000000..96d2a60 --- /dev/null +++ b/rougelikeaboutmechs/autoloads/input_manager.gd.uid @@ -0,0 +1 @@ +uid://duf4ocwe44jb6 diff --git a/rougelikeaboutmechs/autoloads/settings/settings.gd b/rougelikeaboutmechs/autoloads/settings/settings.gd new file mode 100644 index 0000000..f1edb96 --- /dev/null +++ b/rougelikeaboutmechs/autoloads/settings/settings.gd @@ -0,0 +1,321 @@ +extends Node + +#region Helper enums and data classes + +class SettingCategory: + var name: String + var display_text: String + + var sub_categories: Array[SettingCategory] = [] + var settings: Array[Setting] = [] + + func _init(p_name: String, p_display_text: String = ""): + name = p_name + display_text = p_display_text if p_display_text != "" else p_name + + func add_setting(p_setting: Setting) -> void: + if OS.is_debug_build() and settings.filter(func(s): return s.name == p_setting.name).size() > 0: + push_warning("Setting " + p_setting.name + " already exists in category " + name) + return + settings.append(p_setting) + + func add_sub_category(p_category: SettingCategory) -> void: + if OS.is_debug_build() and sub_categories.filter(func(c): return c.name == p_category.name).size() > 0: + push_warning("Sub-category " + p_category.name + " already exists in category " + name) + return + sub_categories.append(p_category) + + func get_setting(p_name: String) -> Setting: + for setting in settings: + if setting.name == p_name: + return setting + push_warning("Setting " + p_name + " not found in category " + name) + return null + + func get_sub_category(p_name: String) -> SettingCategory: + for category in sub_categories: + if category.name == p_name: + return category + push_warning("Sub-category " + p_name + " not found in category " + name) + return null + +@abstract +class Setting: + signal value_changed(value: Variant) + var name: String + var display_text: String + var value: Variant: + set = set_value + var default_value: Variant + var requires_restart: bool + var setter_callable: Callable + + func _init(p_name: String, p_display_text: String, p_default_value: Variant, p_setter_callable: Callable = Callable(), p_requires_restart: bool = false): + self.name = p_name + self.display_text = p_display_text + self.value = p_default_value + self.default_value = p_default_value + self.setter_callable = p_setter_callable + self.requires_restart = p_requires_restart + + func set_value(p_value: Variant): + if not is_same(p_value, value): + value = p_value + value_changed.emit(value) + if setter_callable.is_valid(): + setter_callable.call(value) + +class OptionSetting extends Setting: + var options: Array[String] + + func _init(p_name: String, p_label_text: String, p_default_value: String, p_options: Array[String], p_setter_callable: Callable = Callable(), p_requires_restart: bool = false): + assert(p_options.has(p_default_value)) + self.options = p_options + super(p_name, p_label_text, p_default_value, p_setter_callable, p_requires_restart) + +class FloatSetting extends Setting: + var min_value: float + var max_value: float + var step: float + func _init(p_name: String, p_label_text: String, p_default_value: float, p_min: float, p_max: float, p_step: float, p_setter_callable: Callable = Callable(), p_requires_restart: bool = false): + assert(p_default_value >= p_min and p_default_value <= p_max) + self.min_value = p_min + self.max_value = p_max + self.step = p_step + super(p_name, p_label_text, p_default_value, p_setter_callable, p_requires_restart) + +class BoolSetting extends Setting: + func _init(p_name: String, p_label_text: String, p_default_value: bool, p_setter_callable: Callable = Callable(), p_requires_restart: bool = false): + super(p_name, p_label_text, p_default_value, p_setter_callable, p_requires_restart) + +class InputRemappingSetting extends Setting: + var actions: Array[InputEvent] + func _init(p_name: String, p_label_text: String, p_default_value: Array[InputEvent], p_setter_callable: Callable = Callable(), p_requires_restart: bool = false): + super(p_name, p_label_text, p_default_value, p_setter_callable, p_requires_restart) + self.actions = p_default_value.duplicate() + + +#endregion + +#region Settings interface + +## Stores all settings in a hierarchical structure +var _root_categories: Array[SettingCategory] = [] + +## Adds a new root category which can be populated with settings and sub-_root_categories. +func add_root_category(p_setting_category: SettingCategory) -> void: + if _root_categories.filter(func(c): return c.name == p_setting_category.name).size() > 0: + push_warning("Category " + p_setting_category.name + " does already exist") + return + _root_categories.append(p_setting_category) + +func get_root_categories() -> Array[SettingCategory]: + return _root_categories + +func get_root_category(p_name: String) -> SettingCategory: + for category in _root_categories: + if category.name == p_name: + return category + push_warning("Category " + p_name + " not found") + return null + +## Gets the value of a setting by path (e.g., "Category/SubCategory/SettingName") +func get_value(p_path: String) -> Variant: + var setting = _get_setting_by_path(p_path) + if setting: + return setting.value + push_warning("Setting " + p_path + " not found") + return null + +## Sets the value of a setting by path (e.g., "Category/SubCategory/SettingName") +func set_value(p_path: String, p_value: Variant) -> void: + var setting = _get_setting_by_path(p_path) + if setting: + if typeof(p_value) != typeof(setting.default_value): + push_warning("Variant type mismatch for setting " + p_path + " (" + type_string(typeof(p_value)) + " should be " + type_string(typeof(setting.default_value)) + ")") + return + setting.value = p_value + else: + push_warning("Setting " + p_path + " not found") + +## Sets the default value of a setting by path (e.g., "Category/SubCategory/SettingName") +func set_default_value(p_path: String, p_default_value: Variant) -> void: + var setting = _get_setting_by_path(p_path) + if setting: + if typeof(p_default_value) != typeof(setting.default_value): + push_warning("Variant type mismatch for setting " + p_path + " (" + type_string(typeof(p_default_value)) + " should be " + type_string(typeof(setting.default_value)) + ")") + return + setting.default_value = p_default_value + else: + push_warning("Setting " + p_path + " not found") + +## Resets a setting to its default value by path (e.g., "Category/SubCategory/SettingName") +func reset_value(p_path: String): + var setting = _get_setting_by_path(p_path) + if setting: + setting.value = setting.default_value + if setting.setter_callable.is_valid(): + setting.setter_callable.call(setting.default_value) + else: + push_warning("Setting " + p_path + " not found") + +## Resets a specific input binding at the given index to its default value +func reset_input_binding(p_path: String, index: int): + var setting = _get_setting_by_path(p_path) + if not setting: + push_warning("Setting " + p_path + " not found") + return + + if not setting is InputRemappingSetting: + push_warning("Setting " + p_path + " is not an InputRemappingSetting") + return + + var events = setting.value.duplicate() as Array[InputEvent] + if index >= events.size(): + push_warning("Index " + str(index) + " out of bounds for input_binding setting " + p_path) + return + + var default_event = setting.default_value[index] if index < setting.default_value.size() else null + events[index] = default_event + setting.value = events + if setting.setter_callable.is_valid(): + setting.setter_callable.call(events) + +## Checks if a setting's value equals its default value +func is_value_default(p_path: String) -> bool: + var setting = _get_setting_by_path(p_path) + if setting: + return is_equal(setting.value, setting.default_value) + push_warning("Setting " + p_path + " not found") + return false + +## Checks if a specific input binding at the given index equals its default value +func is_input_binding_default(p_path: String, index: int) -> bool: + var setting = _get_setting_by_path(p_path) + if not setting: + push_warning("Setting " + p_path + " not found") + return false + + if not setting is InputRemappingSetting: + push_warning("Setting " + p_path + " is not an InputRemappingSetting") + return false + + var event = setting.value[index] if index < setting.value.size() else null + var default_event = setting.default_value[index] if index < setting.default_value.size() else null + return is_equal(event, default_event) + +## Helper function to find a setting by path (e.g., "Category/SubCategory/SettingName") +func _get_setting_by_path(p_path: String) -> Setting: + var path_parts = p_path.split("/") + if path_parts.size() < 2: + push_warning("Invalid setting path: " + p_path + ". Expected format: 'Category/SettingName' or 'Category/SubCategory/.../SettingName'") + return null + + # Find the root category + var category = get_root_category(path_parts[0]) + if not category: + return null + + # Traverse subcategories + for i in range(1, path_parts.size() - 1): + category = category.get_sub_category(path_parts[i]) + if not category: + return null + + # Get the setting from the final category + var setting_name = path_parts[path_parts.size() - 1] + return category.get_setting(setting_name) + + +func save_config(): + var config = ConfigFile.new() + + for category in _root_categories: + _save_category_recursive(config, category, category.name) + + var error = config.save("user://config.cfg") + if error != OK: + push_error("Failed to save config file: " + str(error)) + +## Recursively saves all settings in a category and its subcategories +func _save_category_recursive(config: ConfigFile, category: SettingCategory, section_path: String) -> void: + # Save all settings in this category + for setting in category.settings: + config.set_value(section_path, setting.name, setting.value) + + # Recursively save all subcategories + for sub_category in category.sub_categories: + var sub_section_path = section_path + "/" + sub_category.name + _save_category_recursive(config, sub_category, sub_section_path) + +func load_config(): + var config = ConfigFile.new() + var error = config.load("user://config.cfg") + + if error != OK: + push_warning("Failed to load config file: " + str(error) + ". Using default values.") + return + + for category in _root_categories: + _load_category_recursive(config, category, category.name) + +## Recursively loads all settings in a category and its subcategories +func _load_category_recursive(config: ConfigFile, category: SettingCategory, section_path: String) -> void: + # Load all settings in this category + for setting in category.settings: + if not config.has_section_key(section_path, setting.name): + push_warning("Setting " + setting.name + " not found in section " + section_path + ", using default value") + continue + + var value = config.get_value(section_path, setting.name, setting.default_value) + + if typeof(value) != typeof(setting.default_value): + push_warning("Variant type mismatch for setting " + setting.name + " (" + type_string(typeof(value)) + " should be " + type_string(typeof(setting.default_value)) + "), using default value") + continue + + # TODO: Do something about this? + # Set the value (this will trigger the setter and emit signals) + setting.value = value + + # Recursively load all subcategories + for sub_category in category.sub_categories: + var sub_section_path = section_path + "/" + sub_category.name + _load_category_recursive(config, sub_category, sub_section_path) + +## Be cautious! Clears the config file, resetting all settings to their default values. +## This can be useful for troubleshooting. +func clear_config(): + var config = ConfigFile.new() + config.save("user://config.cfg") + +#endregion + +## Deep property based equality check for two variants +func is_equal(a: Variant, b: Variant) -> bool: + if typeof(a) != typeof(b): + return false + if typeof(a) != TYPE_DICTIONARY and typeof(a) != TYPE_OBJECT and typeof(a) != TYPE_ARRAY: + return a == b + if typeof(a) == TYPE_ARRAY: + if a.size() != b.size(): + return false + for i in range(a.size()): + if not is_equal(a[i], b[i]): + return false + return true + if typeof(a) == TYPE_DICTIONARY: + # Compare all keys of the two dictionaries + for key in a.keys(): + if not b.has(key): + return false + if not is_equal(a[key], b[key]): + return false + for key in b.keys(): + if not a.has(key): + return false + return true + # Both are objects, compare all properties + for prop in a.get_property_list(): + if not is_equal(a.get(prop.name), b.get(prop.name)): + return false + return true diff --git a/rougelikeaboutmechs/autoloads/settings/settings.gd.uid b/rougelikeaboutmechs/autoloads/settings/settings.gd.uid new file mode 100644 index 0000000..2eddfee --- /dev/null +++ b/rougelikeaboutmechs/autoloads/settings/settings.gd.uid @@ -0,0 +1 @@ +uid://qwman3p22bxr diff --git a/rougelikeaboutmechs/autoloads/settings/user_defined_settings.gd b/rougelikeaboutmechs/autoloads/settings/user_defined_settings.gd new file mode 100644 index 0000000..04dd14b --- /dev/null +++ b/rougelikeaboutmechs/autoloads/settings/user_defined_settings.gd @@ -0,0 +1,196 @@ +class_name UserDefinedSettings + +enum DisplayMode {FULLSCREEN, WINDOWED_FULLSCREEN, WINDOWED} +enum AAMode_3D {DISABLED, FXAA, TAA, MSAA_2X, MSAA_4X, FSR_2} +enum AAMode_2D {DISABLED, MSAA_2X, MSAA_4X, MSAA_8X} + +enum AudioBus {MASTER, MUSIC, SFX, VOICE} + +func _register_settings() -> void: + _register_graphics_settings() + _register_audio_settings() + _register_controls_settings() + +func _register_graphics_settings() -> void: + var graphics_category = Settings.SettingCategory.new("graphics", "Graphics") + + var display_mode_options: Array[String] = ["Fullscreen", "Windowed Fullscreen", "Windowed"] + var display_mode_setting = Settings.OptionSetting.new("display_mode", + "Display Mode", + "Windowed Fullscreen", + display_mode_options, + _set_display_mode) + graphics_category.add_setting(display_mode_setting) + + var vsync_enabled_setting = Settings.BoolSetting.new("vsync_enabled", "VSync enabled", true, _set_vsync_enabled) + graphics_category.add_setting(vsync_enabled_setting) + + var aa_3d_options: Array[String] = ["Disabled", "FXAA", "TAA", "MSAA 2x", "MSAA 4x", "FSR 2"] + var aa_3d_setting = Settings.OptionSetting.new("3d_aa_mode", + "3D Anti-Aliasing Mode", + "Disabled", + aa_3d_options, + _set_aa_mode_3d) + graphics_category.add_setting(aa_3d_setting) + + # 2D MSAA is not yet available in the Compatibility renderer + if (ProjectSettings.get_setting_with_override("rendering/renderer/rendering_method") != "gl_compatibility"): + var aa_2d_options: Array[String] = ["Disabled", "MSAA 2x", "MSAA 4x", "MSAA 8x"] + var aa_2d_setting = Settings.OptionSetting.new("2d_aa_mode", + "2D Anti-Aliasing Mode", + "Disabled", + aa_2d_options, + _set_aa_mode_2d) + graphics_category.add_setting(aa_2d_setting) + + Settings.add_root_category(graphics_category) + +func _register_audio_settings() -> void: + var audio_category = Settings.SettingCategory.new("audio", "Audio") + + var master_volume_setting = Settings.FloatSetting.new("volume_master", + "Master Volume", + 100.0, + 0.0, + 150.0, + 1.0, + func(volume): _set_audio_bus_volume(volume, AudioBus.MASTER)) + audio_category.add_setting(master_volume_setting) + + # Fine Control subcategory for audio + var fine_control_category = Settings.SettingCategory.new("fine_control", "Fine Control") + + var music_volume_setting = Settings.FloatSetting.new("volume_music", + "Volume (Music)", + 100.0, + 0.0, + 150.0, + 1.0, + func(volume): _set_audio_bus_volume(volume, AudioBus.MUSIC)) + fine_control_category.add_setting(music_volume_setting) + + var sfx_volume_setting = Settings.FloatSetting.new("volume_sfx", + "Volume (SFX)", + 100.0, + 0.0, + 150.0, + 1.0, + func(volume): _set_audio_bus_volume(volume, AudioBus.SFX)) + fine_control_category.add_setting(sfx_volume_setting) + + var voice_volume_setting = Settings.FloatSetting.new("volume_voice", + "Volume (Voice)", + 100.0, + 0.0, + 150.0, + 1.0, + func(volume): _set_audio_bus_volume(volume, AudioBus.VOICE)) + fine_control_category.add_setting(voice_volume_setting) + + audio_category.add_sub_category(fine_control_category) + + Settings.add_root_category(audio_category) + +func _register_controls_settings() -> void: + var controls_category = Settings.SettingCategory.new("controls", "Controls") + + var mouse_sensitivity_setting = Settings.FloatSetting.new("mouse_sensitivity", + "Mouse Sensitivity", + 1.0, + 0.1, + 1.9, + 0.01) + controls_category.add_setting(mouse_sensitivity_setting) + + var key_bindings_category = Settings.SettingCategory.new("key_bindings", "Key Bindings") + + # Insert remappable actions + _create_action_setting(key_bindings_category, "move_up", "Move Forward") + _create_action_setting(key_bindings_category, "move_down", "Move Backward") + _create_action_setting(key_bindings_category, "move_left", "Move Left") + _create_action_setting(key_bindings_category, "move_right", "Move Right") + + controls_category.add_sub_category(key_bindings_category) + + Settings.add_root_category(controls_category) + + +#region Graphics Settings Callbacks + +func _set_display_mode(display_mode_string: String): + var display_mode_index = ["Fullscreen", "Windowed Fullscreen", "Windowed"].find(display_mode_string) + match display_mode_index: + 0: # FULLSCREEN + Global.game_manager.get_window().mode = Window.MODE_EXCLUSIVE_FULLSCREEN + 1: # WINDOWED_FULLSCREEN + Global.game_manager.get_window().mode = Window.MODE_FULLSCREEN + 2: # WINDOWED + Global.game_manager.get_window().mode = Window.MODE_WINDOWED + +func _set_vsync_enabled(enabled: bool): + var mode = DisplayServer.VSyncMode.VSYNC_ENABLED if enabled else DisplayServer.VSyncMode.VSYNC_DISABLED + DisplayServer.window_set_vsync_mode(mode) # Just for the main window + +func _set_aa_mode_3d(mode_string: String): + var mode_index = ["Disabled", "FXAA", "TAA", "MSAA 2x", "MSAA 4x", "FSR 2"].find(mode_string) + var vp = Global.game_manager.get_viewport() + vp.use_taa = false + vp.screen_space_aa = Viewport.SCREEN_SPACE_AA_DISABLED + vp.msaa_3d = Viewport.MSAA_DISABLED + vp.msaa_2d = Viewport.MSAA_DISABLED + vp.scaling_3d_mode = Viewport.SCALING_3D_MODE_BILINEAR + match mode_index: + 1: vp.screen_space_aa = Viewport.SCREEN_SPACE_AA_FXAA + 2: vp.use_taa = true # TAA + 3: vp.msaa_3d = Viewport.MSAA_2X + 4: vp.msaa_3d = Viewport.MSAA_4X + 5: vp.scaling_3d_mode = Viewport.SCALING_3D_MODE_FSR2 + +func _set_aa_mode_2d(mode_string: String): + var mode_index = ["Disabled", "MSAA 2x", "MSAA 4x", "MSAA 8x"].find(mode_string) + var vp = Global.game_manager.get_viewport() + vp.msaa_2d = Viewport.MSAA_DISABLED + match mode_index: + 1: vp.msaa_2d = Viewport.MSAA_2X # MSAA_2X + 2: vp.msaa_2d = Viewport.MSAA_4X # MSAA_4X + 3: vp.msaa_2d = Viewport.MSAA_8X # MSAA_8X + +#endregion + +#region Audio Settings Callbacks + +func _set_audio_bus_volume(volume: float, bus: AudioBus): + volume /= 100.0 + volume = volume*volume # Quadratic curve for better control on low end + match bus: + AudioBus.MASTER: AudioServer.set_bus_volume_linear(AudioServer.get_bus_index("Master"), volume) + AudioBus.MUSIC: AudioServer.set_bus_volume_linear(AudioServer.get_bus_index("Music"), volume) + AudioBus.SFX: AudioServer.set_bus_volume_linear(AudioServer.get_bus_index("SFX"), volume) + AudioBus.VOICE: AudioServer.set_bus_volume_linear(AudioServer.get_bus_index("Voice"), volume) + +#endregion + +#region Control Settings Callbacks + +func _create_action_setting(category: Settings.SettingCategory, action: String, label: String) -> void: + var events = InputMap.action_get_events(action) + var default_events: Array[InputEvent] = [] + for i in range(2): + if i < events.size(): + default_events.append(events[i]) + else: + default_events.append(null) + + var setting = Settings.InputRemappingSetting.new("action_map_" + action, + label, + default_events, + func(new_events): _set_input_events(new_events, action)) + category.add_setting(setting) + +func _set_input_events(events: Array[InputEvent], action: String) -> void: + InputMap.action_erase_events(action) + for event in events: + if event: + InputMap.action_add_event(action, event) + +#endregion diff --git a/rougelikeaboutmechs/autoloads/settings/user_defined_settings.gd.uid b/rougelikeaboutmechs/autoloads/settings/user_defined_settings.gd.uid new file mode 100644 index 0000000..6dd1fbd --- /dev/null +++ b/rougelikeaboutmechs/autoloads/settings/user_defined_settings.gd.uid @@ -0,0 +1 @@ +uid://cijj8jj5gotdb diff --git a/rougelikeaboutmechs/core/default_bus_layout.tres b/rougelikeaboutmechs/core/default_bus_layout.tres new file mode 100644 index 0000000..9b3c2b2 --- /dev/null +++ b/rougelikeaboutmechs/core/default_bus_layout.tres @@ -0,0 +1,21 @@ +[gd_resource type="AudioBusLayout" format=3 uid="uid://cxjrus2g7oh0t"] + +[resource] +bus/1/name = &"Music" +bus/1/solo = false +bus/1/mute = false +bus/1/bypass_fx = false +bus/1/volume_db = 0.0 +bus/1/send = &"Master" +bus/2/name = &"SFX" +bus/2/solo = false +bus/2/mute = false +bus/2/bypass_fx = false +bus/2/volume_db = 0.0 +bus/2/send = &"Master" +bus/3/name = &"Voice" +bus/3/solo = false +bus/3/mute = false +bus/3/bypass_fx = false +bus/3/volume_db = 0.0 +bus/3/send = &"Master" diff --git a/rougelikeaboutmechs/core/gamemanager.gd b/rougelikeaboutmechs/core/gamemanager.gd new file mode 100644 index 0000000..717c916 --- /dev/null +++ b/rougelikeaboutmechs/core/gamemanager.gd @@ -0,0 +1,184 @@ +extends Node +class_name GameManager + +## Use this when you have only one level +@export var main_level: PackedScene +## Whether the mouse should be captured while in a level +@export var is_mouse_captured_in_level: bool = true + +@export_subgroup("Level Loading") +## Whether your game contains multiple levels. +## Uncheck if you only have one "Level" in your game +## If disabled, no level select option will be given in the title screen +@export var has_multiple_levels: bool = true +## The number of the highest level. For 1 Level this is 1 +@export var max_level: int = 0 +## Formatable Strig pointing to +@export var level_location = "res://levels/level_%s.tscn" + +@onready var pause_menu: Control = %PauseMenu +@onready var menu_layer: CanvasLayer = %MenuLayer + +var level = 0 +var completed_levels: Array[bool] = [] +var current_level_node: Node + +func _ready() -> void: + Global.set_game_manager(self) + DebugGlobal.debug_label = %DebugLabel + for i in range(max_level): + completed_levels.append(false) + + # Settings + var user_settings = UserDefinedSettings.new() + user_settings._register_settings() + Settings.load_config() + + # Connect to InputManager + InputManager.game_pause.connect(pause) + InputManager.game_unpause.connect(resume) + InputManager.capture_mouse_ingame = is_mouse_captured_in_level + InputManager.set_is_in_game(false) + InputManager.set_is_paused(false) + + _show_title_screen() + +func _start_game() -> void: + level = 0 + _show_controls() + +#region Pausing + +func pause(): + InputManager.set_is_paused(true) + move_child(menu_layer, -1) + pause_menu.move_to_front() + pause_menu.show() + get_tree().paused = true + +func resume(): + InputManager.set_is_paused(false) + print("resume") + pause_menu.hide() + pause_menu.reset() + get_tree().paused = false +#endregion + +#region Level Loading + +func _unload_current_level() -> void: + if current_level_node != null: + current_level_node.queue_free() + current_level_node = null + +func _show_main_level() -> void: + if main_level == null: + push_error("main_level is not set in GameManager") + return + + InputManager.set_is_in_game(true) + var next_level: Node = main_level.instantiate() + if next_level.has_signal("win"): + next_level.win.connect(_next_level) + if next_level.has_signal("reset"): + next_level.reset.connect(_reload_current_level) + add_child(next_level) + current_level_node = next_level + + +func _next_level() -> void: + _unload_current_level() + + if level < max_level and max_level > 0: + InputManager.set_is_in_game(true) + level += 1 + _show_level(level) + completed_levels[level - 1] = true + else: + _show_win_screen() + +func _show_level(level_nr: int) -> void: + # Clean up previous level if it exists (when coming from level select) + _unload_current_level() + + InputManager.set_is_in_game(true) + level = level_nr + var next_level = load(level_location % str(level)).instantiate() + if next_level.has_signal("win"): + next_level.win.connect(_next_level) + if next_level.has_signal("reset"): + next_level.reset.connect(_reload_current_level) + add_child(next_level) + current_level_node = next_level + +func _reload_current_level() -> void: + _unload_current_level() + + if has_multiple_levels: + _show_level(level) + else: + _show_main_level() +#endregion + +#region Showing Different GUI views + + +func _show_win_screen() -> void: + InputManager.set_is_in_game(false) + var win_screen: Control = load("res://ui/screens/win-screen/win_screen.tscn").instantiate() + win_screen.tree_exited.connect(_show_title_screen) + add_child(win_screen) + +func _show_credits() -> void: + var credits: Node = load("res://ui/screens/credit-screen/credit_screen.tscn").instantiate() + credits.tree_exited.connect(_show_title_screen) + menu_layer.add_child(credits) + +func _show_title_screen() -> void: + InputManager.set_is_in_game(false) + var title_screen: Node = load("res://ui/screens/title-screen/title_screen.tscn").instantiate() + title_screen.start_game.connect(_start_game) + title_screen.show_credits.connect(_show_credits) + title_screen.show_level_select.connect(_show_level_select) + title_screen.show_settings_screen.connect(_show_settings_screen) + title_screen.quit.connect(_quit_game) + title_screen.show_levels(has_multiple_levels) + menu_layer.add_child(title_screen) + +func _show_level_select() -> void: + var level_select: Node = load("res://ui/screens/level-select-screen/level_select.tscn").instantiate() + level_select.start_level.connect(_show_level) + level_select.exit.connect(_show_title_screen) + level_select.init_buttons(max_level, completed_levels) + menu_layer.add_child(level_select) + +func _show_settings_screen() -> void: + var settings_screen: Node = load("res://ui/screens/settings-screen/settings_screen.tscn").instantiate() + settings_screen.exit.connect(_show_title_screen) + menu_layer.add_child(settings_screen) + +func _show_controls() -> void: + var controls: Node = load("res://ui/screens/control-screen/control_screen.tscn").instantiate() + if not main_level: + controls.tree_exited.connect(_next_level) + else: + controls.tree_exited.connect(_show_main_level) + menu_layer.add_child(controls) + +func _return_to_title_screen() -> void: + get_tree().paused = false + InputManager.set_is_paused(false) + InputManager.set_is_in_game(false) + # Destroy level + if current_level_node != null: + current_level_node.queue_free() + current_level_node = null + _show_title_screen() +#endregion + +func _quit_game() -> void: + get_tree().paused = false + get_tree().quit() + +func set_world_environment(env: Environment): + $WorldEnvironment.environment = env diff --git a/rougelikeaboutmechs/core/gamemanager.gd.uid b/rougelikeaboutmechs/core/gamemanager.gd.uid new file mode 100644 index 0000000..ea010ff --- /dev/null +++ b/rougelikeaboutmechs/core/gamemanager.gd.uid @@ -0,0 +1 @@ +uid://cluu0cgltsenj diff --git a/rougelikeaboutmechs/core/gamemanager.tscn b/rougelikeaboutmechs/core/gamemanager.tscn new file mode 100644 index 0000000..5dcd85c --- /dev/null +++ b/rougelikeaboutmechs/core/gamemanager.tscn @@ -0,0 +1,36 @@ +[gd_scene format=3 uid="uid://cgu0vbr50x7di"] + +[ext_resource type="Script" uid="uid://cluu0cgltsenj" path="res://core/gamemanager.gd" id="1_htktm"] +[ext_resource type="PackedScene" uid="uid://bilai15byqef2" path="res://ui/screens/pause-menu/pause_menu.tscn" id="2_b2lg8"] +[ext_resource type="Environment" uid="uid://bhb4ckqipjvu3" path="res://core/main_environment.tres" id="2_v1n10"] +[ext_resource type="PackedScene" uid="uid://cyfvcuxi210mg" path="res://levels/main_level.tscn" id="2_xueuq"] +[ext_resource type="Theme" uid="uid://hheneshfv1b2" path="res://ui/themes/your_theme.tres" id="3_8qpx4"] + +[node name="Gamemanager" type="Node" unique_id=1050225795] +process_mode = 3 +script = ExtResource("1_htktm") +main_level = ExtResource("2_xueuq") + +[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=224925465] +environment = ExtResource("2_v1n10") + +[node name="MenuLayer" type="CanvasLayer" parent="." unique_id=1393391734] +unique_name_in_owner = true + +[node name="DebugLabel" type="Label" parent="MenuLayer" unique_id=2133776147] +unique_name_in_owner = true +visible = false +offset_left = 23.0 +offset_top = 16.0 +offset_right = 600.0 +offset_bottom = 308.0 +theme = ExtResource("3_8qpx4") + +[node name="PauseMenu" parent="MenuLayer" unique_id=912678162 instance=ExtResource("2_b2lg8")] +unique_name_in_owner = true +visible = false +theme = ExtResource("3_8qpx4") + +[connection signal="continue_btn_pressed" from="MenuLayer/PauseMenu" to="." method="resume"] +[connection signal="exit_game_btn_pressed" from="MenuLayer/PauseMenu" to="." method="_quit_game"] +[connection signal="exit_to_main_menu_btn_pressed" from="MenuLayer/PauseMenu" to="." method="_return_to_title_screen"] diff --git a/rougelikeaboutmechs/core/main_environment.tres b/rougelikeaboutmechs/core/main_environment.tres new file mode 100644 index 0000000..5ecdbb0 --- /dev/null +++ b/rougelikeaboutmechs/core/main_environment.tres @@ -0,0 +1,15 @@ +[gd_resource type="Environment" format=3 uid="uid://bhb4ckqipjvu3"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_e3rlx"] +sky_top_color = Color(0.218052, 0.202335, 0.225589, 1) +sky_horizon_color = Color(0.227003, 0.231896, 0.228184, 1) +ground_bottom_color = Color(0.167509, 0.160179, 0.160062, 1) +ground_horizon_color = Color(0.175353, 0.180521, 0.188678, 1) + +[sub_resource type="Sky" id="Sky_n0kbt"] +sky_material = SubResource("ProceduralSkyMaterial_e3rlx") + +[resource] +sky = SubResource("Sky_n0kbt") +tonemap_mode = 3 +glow_enabled = true diff --git a/rougelikeaboutmechs/icon.svg b/rougelikeaboutmechs/icon.svg new file mode 100644 index 0000000..9d8b7fa --- /dev/null +++ b/rougelikeaboutmechs/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rougelikeaboutmechs/icon.svg.import b/rougelikeaboutmechs/icon.svg.import new file mode 100644 index 0000000..a30feb7 --- /dev/null +++ b/rougelikeaboutmechs/icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dkgp7tccxyyxc" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.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 diff --git a/rougelikeaboutmechs/levels/levels_readme.md b/rougelikeaboutmechs/levels/levels_readme.md new file mode 100644 index 0000000..ececede --- /dev/null +++ b/rougelikeaboutmechs/levels/levels_readme.md @@ -0,0 +1,6 @@ +We recommend you put your levels here, if your game is level-based. +If you use this template's naming convention for levels, which is "level_.tscn", +where is replaced with a concrete number, the default settings of this template are able to pick up your level. +By default, level numbers should start with 1. +To use the templates default settings for progrssing through levels, please make your level emit a "win()"-signal. +To reinstanciate a level, make your level emit a "reset()"-signal diff --git a/rougelikeaboutmechs/levels/main_level.tscn b/rougelikeaboutmechs/levels/main_level.tscn new file mode 100644 index 0000000..ff4edac --- /dev/null +++ b/rougelikeaboutmechs/levels/main_level.tscn @@ -0,0 +1,3 @@ +[gd_scene format=3 uid="uid://cyfvcuxi210mg"] + +[node name="Level1" type="Node" unique_id=407377819] diff --git a/rougelikeaboutmechs/project.godot b/rougelikeaboutmechs/project.godot new file mode 100644 index 0000000..7a82565 --- /dev/null +++ b/rougelikeaboutmechs/project.godot @@ -0,0 +1,78 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Godot Game Template" +run/main_scene="res://core/gamemanager.tscn" +config/features=PackedStringArray("4.6", "GL Compatibility") +config/icon="res://icon.svg" + +[audio] + +buses/default_bus_layout="res://core/default_bus_layout.tres" + +[autoload] + +InputManager="*res://autoloads/input_manager.gd" +DebugGlobal="*res://autoloads/debug_global.gd" +Global="*res://autoloads/global.gd" +Settings="*res://autoloads/settings/settings.gd" + +[display] + +window/stretch/mode="canvas_items" + +[file_customization] + +folder_colors={ +"res://autoloads/": "gray", +"res://core/": "red", +"res://levels/": "blue", +"res://ui/": "teal" +} + +[input] + +pause={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +toggle_debug_label={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +move_up={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +move_down={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} +move_left={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +] +} +move_right={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} + +[rendering] + +renderer/rendering_method="gl_compatibility" +renderer/rendering_method.mobile="gl_compatibility" diff --git a/rougelikeaboutmechs/ui/components/settings-menu/Revert.svg b/rougelikeaboutmechs/ui/components/settings-menu/Revert.svg new file mode 100644 index 0000000..459efeb --- /dev/null +++ b/rougelikeaboutmechs/ui/components/settings-menu/Revert.svg @@ -0,0 +1 @@ + diff --git a/rougelikeaboutmechs/ui/components/settings-menu/Revert.svg.import b/rougelikeaboutmechs/ui/components/settings-menu/Revert.svg.import new file mode 100644 index 0000000..c3cd415 --- /dev/null +++ b/rougelikeaboutmechs/ui/components/settings-menu/Revert.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b23e4kqj4o6dv" +path="res://.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://ui/components/settings-menu/Revert.svg" +dest_files=["res://.godot/imported/Revert.svg-83732f7446608123e95cc2f2a2cf35c6.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=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.gd b/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.gd new file mode 100644 index 0000000..b59fd7e --- /dev/null +++ b/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.gd @@ -0,0 +1,33 @@ +extends Button + +var event_idx = 0 + +signal action_changed(action: String) + +func _ready(): + set_process_unhandled_key_input(false) + +func _toggled(b_pressed): + set_process_unhandled_key_input(b_pressed) + if b_pressed: + text = "..." + release_focus() + +func _input(event): + if not button_pressed: + return + + if event is InputEventKey or event is InputEventJoypadButton or event is InputEventMouseButton: + action_changed.emit(event) + get_viewport().set_input_as_handled() + button_pressed = false + +func _display_event(event: InputEvent): + if event == null: + text = "Unassigned" + else: + text = event.as_text() + tooltip_text = text + +func set_event(event: InputEvent): + _display_event(event) diff --git a/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.gd.uid b/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.gd.uid new file mode 100644 index 0000000..0a0702d --- /dev/null +++ b/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.gd.uid @@ -0,0 +1 @@ +uid://b7fb4ravo24q0 diff --git a/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.tscn b/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.tscn new file mode 100644 index 0000000..bdffd3f --- /dev/null +++ b/rougelikeaboutmechs/ui/components/settings-menu/action-remapping-button/action_remapping_button.tscn @@ -0,0 +1,9 @@ +[gd_scene format=3 uid="uid://ngjm8kk8u7fm"] + +[ext_resource type="Script" uid="uid://b7fb4ravo24q0" path="res://ui/components/settings-menu/action-remapping-button/action_remapping_button.gd" id="1_jb8u1"] + +[node name="InputRemappingButton" type="Button" unique_id=740968636] +custom_minimum_size = Vector2(200, 0) +toggle_mode = true +text_overrun_behavior = 3 +script = ExtResource("1_jb8u1") diff --git a/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.gd b/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.gd new file mode 100644 index 0000000..3c3d392 --- /dev/null +++ b/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.gd @@ -0,0 +1,184 @@ +extends TabContainer + +@onready var action_remapping_button_scene: PackedScene = load("res://ui/components/settings-menu/action-remapping-button/action_remapping_button.tscn") + +func _ready() -> void: + call_deferred("_populate_menu") + +func _populate_menu() -> void: + var tab_idx = 0 + + # Iterate through root categories (these become tabs) + for root_category in Settings.get_root_categories(): + var margin_container = MarginContainer.new() + add_child(margin_container) + set_tab_title(tab_idx, root_category.display_text) + + var scroll_container = ScrollContainer.new() + scroll_container.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED + margin_container.add_child(scroll_container) + + var margin_container2 = MarginContainer.new() + margin_container2.size_flags_horizontal = Control.SIZE_EXPAND_FILL + margin_container2.size_flags_vertical = Control.SIZE_EXPAND_FILL + scroll_container.add_child(margin_container2) + + var cat_vbox = VBoxContainer.new() + cat_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL + cat_vbox.size_flags_vertical = Control.SIZE_EXPAND_FILL + margin_container2.add_child(cat_vbox) + + # Add subcategories as sections, and their settings + _populate_category(cat_vbox, root_category, root_category.name) + + tab_idx += 1 + +## Recursively populate a category and its subcategories +## Subcategories become section headers, deeper ones are flattened +func _populate_category(container: VBoxContainer, category: Settings.SettingCategory, path_prefix: String, depth: int = 0) -> void: + # If this is a subcategory (depth > 0), add a section header + if depth > 0: + var lbl_section_title = Label.new() + lbl_section_title.text = category.display_text + lbl_section_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + lbl_section_title.size_flags_horizontal = Control.SIZE_EXPAND_FILL + lbl_section_title.theme_type_variation = "SettingsGroupLabel" + container.add_child(lbl_section_title) + container.add_child(HSeparator.new()) + + # Add all settings in this category + for setting in category.settings: + _add_setting_ui(container, setting, path_prefix + "/" + setting.name) + + # Recursively add all subcategories + for sub_category in category.sub_categories: + var sub_path = path_prefix + "/" + sub_category.name + _populate_category(container, sub_category, sub_path, depth + 1) + +func _add_setting_ui(container: VBoxContainer, setting: Settings.Setting, setting_path: String) -> void: + var hbox = HBoxContainer.new() + hbox.custom_minimum_size = Vector2(0, 40) + container.add_child(hbox) + + # Another HBoxContainer for the label and revert button + var hbox_lbl = HBoxContainer.new() + hbox_lbl.size_flags_horizontal = Control.SIZE_EXPAND_FILL + hbox.add_child(hbox_lbl) + + # Label for the name of the setting + var lbl_name = Label.new() + lbl_name.text = setting.display_text + lbl_name.size_flags_horizontal = Control.SIZE_EXPAND_FILL + hbox_lbl.add_child(lbl_name) + + # Revert button for changing the setting back to its default value + # For input bindings a new button for each remapping is created later + if not setting is Settings.InputRemappingSetting: + var revert_btn = Button.new() + revert_btn.icon = get_theme_icon("icon", "RevertButton") + revert_btn.custom_minimum_size = Vector2(32, 32) + revert_btn.theme_type_variation = "FlatButton" + revert_btn.connect("pressed", func(): Settings.reset_value(setting_path)) + hbox_lbl.add_child(revert_btn) + setting.value_changed.connect(func(__): _update_revert_button(setting_path, revert_btn)) + _update_revert_button(setting_path, revert_btn) + + # TODO: Tooltip + + # Setting-specific editor + if setting is Settings.FloatSetting: + var slider_setting = setting as Settings.FloatSetting + var slider = HSlider.new() + slider.min_value = slider_setting.min_value + slider.max_value = slider_setting.max_value + slider.step = slider_setting.step + slider.value = slider_setting.value + slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL + slider.size_flags_vertical = Control.SIZE_FILL + slider.connect("value_changed", setting.set_value) + setting.value_changed.connect(slider.set_value_no_signal) + hbox.add_child(slider) + elif setting is Settings.OptionSetting: + var dropdown_setting = setting as Settings.OptionSetting + var option_button = OptionButton.new() + for i in range(dropdown_setting.options.size()): + option_button.add_item(dropdown_setting.options[i], i) + # Find the index of the current value + var current_idx = dropdown_setting.options.find(dropdown_setting.value) + if current_idx >= 0: + option_button.selected = current_idx + option_button.connect("item_selected", func(idx: int): setting.set_value(dropdown_setting.options[idx])) + setting.value_changed.connect(func(val): option_button.select(dropdown_setting.options.find(val))) + hbox.add_child(option_button) + elif setting is Settings.BoolSetting: + var checkbox = CheckBox.new() + checkbox.button_pressed = setting.value + checkbox.connect("toggled", setting.set_value) + setting.value_changed.connect(checkbox.set_pressed_no_signal) + hbox.add_child(checkbox) + elif setting is Settings.InputRemappingSetting: + _add_input_remapping_ui(hbox, setting as Settings.InputRemappingSetting, setting_path) + else: + # Assume it's a basic boolean setting if it has a bool value + if typeof(setting.value) == TYPE_BOOL: + var checkbox = CheckBox.new() + checkbox.button_pressed = setting.value + checkbox.connect("toggled", setting.set_value) + setting.value_changed.connect(checkbox.set_pressed_no_signal) + hbox.add_child(checkbox) + else: + push_warning("Unknown setting type for: " + setting.display_text) + +func _add_input_remapping_ui(hbox: HBoxContainer, setting: Settings.InputRemappingSetting, setting_path: String) -> void: + var events = setting.value as Array[InputEvent] + + # First reset button + var input_revert_btn_1 = Button.new() + input_revert_btn_1.icon = get_theme_icon("icon", "RevertButton") + input_revert_btn_1.custom_minimum_size = Vector2(32, 32) + input_revert_btn_1.theme_type_variation = "FlatButton" + input_revert_btn_1.connect("pressed", func(): Settings.reset_input_binding(setting_path, 0)) + hbox.add_child(input_revert_btn_1) + setting.value_changed.connect(func(__): _update_input_mapping_revert_button(setting_path, 0, input_revert_btn_1)) + _update_input_mapping_revert_button(setting_path, 0, input_revert_btn_1) + + # First remapping button + var remapping_btn1 = action_remapping_button_scene.instantiate() + remapping_btn1.set_event(events[0] if events.size() > 0 else null) + remapping_btn1.connect("action_changed", func(event: InputEvent): _keymap_changed(event, 0, setting_path)) + setting.value_changed.connect(func(value: Array[InputEvent]): _update_remapping_button(value, 0, remapping_btn1)) + hbox.add_child(remapping_btn1) + + # Second reset button + var input_revert_btn_2 = Button.new() + input_revert_btn_2.icon = get_theme_icon("icon", "RevertButton") + input_revert_btn_2.custom_minimum_size = Vector2(32, 32) + input_revert_btn_2.theme_type_variation = "FlatButton" + input_revert_btn_2.connect("pressed", func(): Settings.reset_input_binding(setting_path, 1)) + hbox.add_child(input_revert_btn_2) + setting.value_changed.connect(func(__): _update_input_mapping_revert_button(setting_path, 1, input_revert_btn_2)) + _update_input_mapping_revert_button(setting_path, 1, input_revert_btn_2) + + # Second remapping button + var remapping_btn2 = action_remapping_button_scene.instantiate() + remapping_btn2.set_event(events[1] if events.size() > 1 else null) + remapping_btn2.connect("action_changed", func(event: InputEvent): _keymap_changed(event, 1, setting_path)) + setting.value_changed.connect(func(value: Array[InputEvent]): _update_remapping_button(value, 1, remapping_btn2)) + hbox.add_child(remapping_btn2) + +func _keymap_changed(event: InputEvent, event_idx: int, setting_path: String) -> void: + var events = Settings.get_value(setting_path).duplicate() + if event_idx >= events.size(): + events.push_back(null) + events[event_idx] = event + print("Keymap changed " + str(event_idx) + ":" + str(events)) + Settings.set_value(setting_path, events) + +func _update_revert_button(p_setting_path: String, button: Button) -> void: + button.visible = not Settings.is_value_default(p_setting_path) + +func _update_remapping_button(value: Array[InputEvent], index: int, btn: Button): + btn.set_event(value[index] if value.size() > index else null) + +func _update_input_mapping_revert_button(p_setting_path: String, index: int, button: Button) -> void: + button.modulate = Color.WHITE if not Settings.is_input_binding_default(p_setting_path, index) else Color.TRANSPARENT diff --git a/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.gd.uid b/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.gd.uid new file mode 100644 index 0000000..cc7a38b --- /dev/null +++ b/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.gd.uid @@ -0,0 +1 @@ +uid://ij8xcd6np4vt diff --git a/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.tscn b/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.tscn new file mode 100644 index 0000000..c65cf4b --- /dev/null +++ b/rougelikeaboutmechs/ui/components/settings-menu/settings_menu.tscn @@ -0,0 +1,12 @@ +[gd_scene format=3 uid="uid://cv271fh4d2p13"] + +[ext_resource type="Script" uid="uid://ij8xcd6np4vt" path="res://ui/components/settings-menu/settings_menu.gd" id="1_eae2p"] +[ext_resource type="Theme" uid="uid://hheneshfv1b2" path="res://ui/themes/your_theme.tres" id="1_scglv"] + +[node name="SettingsMenu" type="TabContainer" unique_id=1538995254] +clip_contents = true +custom_minimum_size = Vector2(600, 400) +size_flags_vertical = 3 +theme = ExtResource("1_scglv") +tab_alignment = 1 +script = ExtResource("1_eae2p") diff --git a/rougelikeaboutmechs/ui/screens/control-screen/control_screen.gd b/rougelikeaboutmechs/ui/screens/control-screen/control_screen.gd new file mode 100644 index 0000000..00a8c97 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/control-screen/control_screen.gd @@ -0,0 +1,7 @@ +extends Control + +func _ready(): + $Continue.grab_focus() + +func _on_continue_pressed() -> void: + queue_free() diff --git a/rougelikeaboutmechs/ui/screens/control-screen/control_screen.gd.uid b/rougelikeaboutmechs/ui/screens/control-screen/control_screen.gd.uid new file mode 100644 index 0000000..6df74a5 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/control-screen/control_screen.gd.uid @@ -0,0 +1 @@ +uid://c1i00arsdf2mw diff --git a/rougelikeaboutmechs/ui/screens/control-screen/control_screen.tscn b/rougelikeaboutmechs/ui/screens/control-screen/control_screen.tscn new file mode 100644 index 0000000..dd37231 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/control-screen/control_screen.tscn @@ -0,0 +1,74 @@ +[gd_scene format=3 uid="uid://bpr6du5ydm0lw"] + +[ext_resource type="Theme" uid="uid://hheneshfv1b2" path="res://ui/themes/your_theme.tres" id="1_x8l5g"] +[ext_resource type="Script" uid="uid://c1i00arsdf2mw" path="res://ui/screens/control-screen/control_screen.gd" id="2_wdxwm"] + +[sub_resource type="LabelSettings" id="LabelSettings_5tgjf"] +font_size = 60 + +[node name="ControlScreen" type="Control" unique_id=707664794] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_x8l5g") +script = ExtResource("2_wdxwm") + +[node name="Panel" type="Panel" parent="." unique_id=1329424348] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="ControlsTitle" type="Label" parent="." unique_id=1553206497] +custom_minimum_size = Vector2(731.345, 0) +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -576.0 +offset_top = 25.0 +offset_right = 576.0 +offset_bottom = 108.0 +grow_horizontal = 2 +text = "Controls" +label_settings = SubResource("LabelSettings_5tgjf") +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="ControlsTitle2" type="Label" parent="." unique_id=394444381] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -86.5 +offset_top = -11.5 +offset_right = 86.5 +offset_bottom = 11.5 +grow_horizontal = 2 +grow_vertical = 2 +text = "Put your controls here" +horizontal_alignment = 1 + +[node name="Continue" type="Button" parent="." unique_id=426511693] +layout_mode = 1 +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -39.5 +offset_top = -58.0 +offset_right = 39.5 +offset_bottom = -27.0 +grow_horizontal = 2 +grow_vertical = 0 +text = "Continue" + +[connection signal="pressed" from="Continue" to="." method="_on_continue_pressed"] diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.gd b/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.gd new file mode 100644 index 0000000..ac8ff72 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.gd @@ -0,0 +1,20 @@ +class_name CreditButton +extends VBoxContainer + +signal display_license + +var credit: CreditEntry + +func set_credit(credit_entry: CreditEntry) -> void: + credit = credit_entry + if credit.descriptor: + $DescribtorLabel.text = credit.descriptor + $HBoxContainer/CreditButton.text = credit.name + if credit.url: + $HBoxContainer/CreditButton.pressed.connect(open_url) + +func open_url(): + OS.shell_open(credit.url) + +func _on_license_button_pressed() -> void: + display_license.emit(credit) diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.gd.uid b/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.gd.uid new file mode 100644 index 0000000..f399bf3 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.gd.uid @@ -0,0 +1 @@ +uid://6q5m84onxilu diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.tscn b/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.tscn new file mode 100644 index 0000000..757fd49 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credit_element.tscn @@ -0,0 +1,39 @@ +[gd_scene format=3 uid="uid://bhqw5lfvaq0bg"] + +[ext_resource type="Script" uid="uid://6q5m84onxilu" path="res://ui/screens/credit-screen/credit_element.gd" id="1_ukcj5"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_2mwwd"] + +[sub_resource type="LabelSettings" id="LabelSettings_p0wxk"] +font_size = 12 + +[node name="Credit" type="VBoxContainer" unique_id=69516036] +offset_right = 40.0 +offset_bottom = 40.0 +size_flags_horizontal = 3 +theme_override_constants/separation = 0 +alignment = 1 +script = ExtResource("1_ukcj5") + +[node name="HBoxContainer" type="HBoxContainer" parent="." unique_id=599791176] +layout_mode = 2 + +[node name="CreditButton" type="Button" parent="HBoxContainer" unique_id=955063757] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_font_sizes/font_size = 20 +theme_override_styles/focus = SubResource("StyleBoxEmpty_2mwwd") +flat = true + +[node name="LicenseButton" type="Button" parent="HBoxContainer" unique_id=351433666] +layout_mode = 2 +text = "License" + +[node name="DescribtorLabel" type="Label" parent="." unique_id=322246210] +modulate = Color(1, 1, 1, 0.670588) +layout_mode = 2 +label_settings = SubResource("LabelSettings_p0wxk") +horizontal_alignment = 1 +autowrap_mode = 2 + +[connection signal="pressed" from="HBoxContainer/LicenseButton" to="." method="_on_license_button_pressed"] diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credit_entry.gd b/rougelikeaboutmechs/ui/screens/credit-screen/credit_entry.gd new file mode 100644 index 0000000..ed32fd1 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credit_entry.gd @@ -0,0 +1,8 @@ +class_name CreditEntry +extends Resource + +@export var name: String +@export var descriptor: String +@export var license: String +@export var license_file: String +@export var url: String diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credit_entry.gd.uid b/rougelikeaboutmechs/ui/screens/credit-screen/credit_entry.gd.uid new file mode 100644 index 0000000..28c4ceb --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credit_entry.gd.uid @@ -0,0 +1 @@ +uid://cjhxtjhj5o81f diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.gd b/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.gd new file mode 100644 index 0000000..4dc1627 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.gd @@ -0,0 +1,84 @@ +extends Control + +@export var credits: String + +func _ready() -> void: + $VBoxContainer/Return.grab_focus() + + var credit_button_scene = load("res://ui/screens/credit-screen/credit_element.tscn") + + var creds: Array[CreditEntry] = _dicts_to_entry(_read_credits()) + for c in creds: + var b: CreditButton = credit_button_scene.instantiate() + b.display_license.connect(display_license) + b.set_credit(c) + $VBoxContainer/ScrollContainer/VBoxContainer/VBoxContainer.add_child(b) + $VBoxContainer/ScrollContainer.scroll_vertical = 0 + +func _on_return_pressed() -> void: + queue_free() + +func _read_credits() -> Array: + var text = FileAccess.open(credits, FileAccess.READ).get_as_text() + var content_as_dictionary: Array = JSON.parse_string(text) + return content_as_dictionary + + +func _dicts_to_entry(array: Array) -> Array[CreditEntry]: + var item_array: Array[CreditEntry] = [] + for dict in array: + var item = CreditEntry.new() + item.name = dict["name"] + item.descriptor = dict["descriptor"] if dict.has("descriptor") else "" + if dict.has("license"): + item.license = dict["license"] if dict["license"] else "" + elif dict.has("license_file"): + item.license = FileAccess.open(dict["license_file"], FileAccess.READ).get_as_text()\ + if FileAccess.file_exists(dict["license_file"]) else "" + else: + item.license = "" + item.url = dict["url"] if dict.has("url") else "" + item_array.append(item) + return item_array + +func _on_detailed_g_credits_pressed() -> void: + if not $VBoxContainer/ScrollContainer/Godot3PCredits.text: + var copyright_info = Engine.get_copyright_info() + var copyright_text = "Godot Engine Copyright Information:" + for entry in copyright_info: + copyright_text += "\n\n" + entry["name"] + ":\n" + var parts = entry["parts"] + for part in parts: + copyright_text += "Files:\n" + for file in part["files"]: + copyright_text += " " + file + "\n" + for copyright_owner in part["copyright"]: + copyright_text += "© " + copyright_owner + "\n" + copyright_text += "License:" + part["license"] + "\n" + # Append full license texts + var license_texts = Engine.get_license_info() + copyright_text += "\n\n\n\nFull license texts:" + for license in license_texts: + copyright_text += "\n\n" + license + ":\n" + copyright_text += license_texts[license] + + $VBoxContainer/ScrollContainer/Godot3PCredits.text = copyright_text + + $VBoxContainer/ScrollContainer/Godot3PCredits.visible = \ + not $VBoxContainer/ScrollContainer/Godot3PCredits.visible + + $VBoxContainer/ScrollContainer/VBoxContainer.visible = \ + not $VBoxContainer/ScrollContainer/VBoxContainer.visible + + if $VBoxContainer/ScrollContainer/Godot3PCredits.visible: + $DetailedGCredits.text = "Return to Credits" + else: + $DetailedGCredits.text = "Show detailed Godot Credits" + +func display_license(credit: CreditEntry) -> void: + $LicenseText.visible = true + $LicenseText/VBoxContainer/Label.text = credit.name + $LicenseText/VBoxContainer/ScrollContainer/Label.text = credit.license + +func _on_close_licence_text_pressed() -> void: + $LicenseText.visible = false diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.gd.uid b/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.gd.uid new file mode 100644 index 0000000..84ea15a --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.gd.uid @@ -0,0 +1 @@ +uid://dx5iawpcgwhlm diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.tscn b/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.tscn new file mode 100644 index 0000000..ed58db4 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credit_screen.tscn @@ -0,0 +1,116 @@ +[gd_scene format=3 uid="uid://fd3xmnc047tm"] + +[ext_resource type="Script" uid="uid://dx5iawpcgwhlm" path="res://ui/screens/credit-screen/credit_screen.gd" id="1_h6a2t"] +[ext_resource type="Theme" uid="uid://hheneshfv1b2" path="res://ui/themes/your_theme.tres" id="2_dvsi5"] + +[sub_resource type="LabelSettings" id="LabelSettings_cutkl"] +font_size = 22 + +[sub_resource type="LabelSettings" id="LabelSettings_r8dx7"] +font_size = 12 + +[node name="CreditScreen" type="MarginContainer" unique_id=554750649] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("2_dvsi5") +script = ExtResource("1_h6a2t") +credits = "res://ui/screens/credit-screen/credits.json" + +[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1426215384] +layout_mode = 2 +alignment = 1 + +[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer" unique_id=193875904] +layout_mode = 2 +size_flags_vertical = 3 +horizontal_scroll_mode = 0 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer" unique_id=1766199227] +custom_minimum_size = Vector2(700, 0) +layout_mode = 2 +size_flags_horizontal = 6 +size_flags_vertical = 3 + +[node name="LabelCredits" type="Label" parent="VBoxContainer/ScrollContainer/VBoxContainer" unique_id=500318037] +custom_minimum_size = Vector2(731.345, 0) +layout_mode = 2 +theme_type_variation = &"HeaderLarge" +text = "Credits" +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="Spacer2" type="Control" parent="VBoxContainer/ScrollContainer/VBoxContainer" unique_id=341639053] +custom_minimum_size = Vector2(0, 27.17) +layout_mode = 2 + +[node name="LabelCreatedBy" type="Label" parent="VBoxContainer/ScrollContainer/VBoxContainer" unique_id=1161453390] +layout_mode = 2 +text = "Created by You" +label_settings = SubResource("LabelSettings_cutkl") +horizontal_alignment = 1 + +[node name="LabelSpecialThanks" type="Label" parent="VBoxContainer/ScrollContainer/VBoxContainer" unique_id=1866642574] +layout_mode = 2 +text = "Special thanks to Also You" +horizontal_alignment = 1 + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer/ScrollContainer/VBoxContainer" unique_id=123317386] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer/VBoxContainer" unique_id=1405225546] +layout_mode = 2 + +[node name="Godot3PCredits" type="Label" parent="VBoxContainer/ScrollContainer" unique_id=1092186786] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +label_settings = SubResource("LabelSettings_r8dx7") + +[node name="Return" type="Button" parent="VBoxContainer" unique_id=464459005] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +text = "Return to Main Menu +" + +[node name="DetailedGCredits" type="Button" parent="." unique_id=729625426] +layout_mode = 2 +size_flags_horizontal = 8 +size_flags_vertical = 8 +theme_override_font_sizes/font_size = 12 +text = "Show detailed Godot Credits" +flat = true + +[node name="LicenseText" type="PanelContainer" parent="." unique_id=1702054193] +visible = false +layout_mode = 2 +theme = ExtResource("2_dvsi5") + +[node name="VBoxContainer" type="VBoxContainer" parent="LicenseText" unique_id=1286974170] +layout_mode = 2 + +[node name="Label" type="Label" parent="LicenseText/VBoxContainer" unique_id=426678051] +layout_mode = 2 +size_flags_horizontal = 4 +theme = ExtResource("2_dvsi5") +theme_type_variation = &"HeaderMedium" + +[node name="ScrollContainer" type="ScrollContainer" parent="LicenseText/VBoxContainer" unique_id=1054289490] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="LicenseText/VBoxContainer/ScrollContainer" unique_id=589755459] +layout_mode = 2 +size_flags_horizontal = 6 + +[node name="CloseLicense" type="Button" parent="LicenseText/VBoxContainer" unique_id=102920052] +layout_mode = 2 +size_flags_vertical = 4 +text = "Close" + +[connection signal="pressed" from="VBoxContainer/Return" to="." method="_on_return_pressed"] +[connection signal="pressed" from="DetailedGCredits" to="." method="_on_detailed_g_credits_pressed"] +[connection signal="pressed" from="LicenseText/VBoxContainer/CloseLicense" to="." method="_on_close_licence_text_pressed"] diff --git a/rougelikeaboutmechs/ui/screens/credit-screen/credits.json b/rougelikeaboutmechs/ui/screens/credit-screen/credits.json new file mode 100644 index 0000000..e62368c --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/credit-screen/credits.json @@ -0,0 +1,18 @@ +[ + { + "name": "Godot", + "descriptor": "Open Source 2D/3D Game Engine", + "license": "This game uses Godot Engine, available under the following license:\n\nCopyright (c) 2014-present Godot Engine contributors.\nCopyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.", + "url": "https://godotengine.org/license" + }, + { + "name": "Godot Game Template", + "descriptor": "Universal game template targeted at game jams.", + "license": "MIT License\n\nCopyright (c) 2025 Ekaterina Ehringhaus and Hendrik Brucker\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.", + "url": "https://github.com/Godot-Stammtisch-Karlsruhe/godot-game-template" + }, + { + "name": "Sample Asset", + "descriptor": "Sample description (optional)" + } +] diff --git a/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.gd b/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.gd new file mode 100644 index 0000000..b95fb2d --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.gd @@ -0,0 +1,11 @@ +class_name LevelButton +extends Button + +var level_nr: int +signal select_level(level_nr: int) + +func _ready() -> void: + text = str(level_nr) + +func _on_pressed() -> void: + select_level.emit(level_nr) diff --git a/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.gd.uid b/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.gd.uid new file mode 100644 index 0000000..896eda6 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.gd.uid @@ -0,0 +1 @@ +uid://dwav7d4amw8yu diff --git a/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.tscn b/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.tscn new file mode 100644 index 0000000..b01e662 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/level-select-screen/level_button.tscn @@ -0,0 +1,12 @@ +[gd_scene format=3 uid="uid://ccrodv5x16nay"] + +[ext_resource type="Script" uid="uid://dwav7d4amw8yu" path="res://ui/screens/level-select-screen/level_button.gd" id="1_ej8yx"] + +[node name="LevelButton" type="Button" unique_id=923151870] +custom_minimum_size = Vector2(90, 90) +offset_right = 8.0 +offset_bottom = 8.0 +theme_override_font_sizes/font_size = 56 +script = ExtResource("1_ej8yx") + +[connection signal="pressed" from="." to="." method="_on_pressed"] diff --git a/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.gd b/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.gd new file mode 100644 index 0000000..9031253 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.gd @@ -0,0 +1,43 @@ +extends Control + +@export var buttonContainer: Container + +var level_buttons: Array[Button] = [] +var completed_levels: Array[bool] = [] + +signal start_level(level_nr: int) +signal test_level() +signal exit() + +func init_buttons(max_level: int, completed_level_information: Array[bool]) -> void: + if max_level > 0: + $VBoxContainer/Label.visible = false + + completed_levels = completed_level_information + for i in range(max_level): + var b: LevelButton = load("res://ui/screens/level-select-screen/level_button.tscn").instantiate() + b.level_nr = i + 1 + b.select_level.connect(_level_button_pressed) + b.disabled = not completed_levels[i] + level_buttons.append(b) + buttonContainer.add_child(b) + +func _level_button_pressed(level_nr: int) -> void: + print("Start Level ",level_nr) + start_level.emit(level_nr) + queue_free() + +func _return_to_title() -> void: + exit.emit() + queue_free() + +func _on_unlock_levels_toggled(toggled_on: bool) -> void: + for i in range(len(level_buttons)): + if toggled_on: + level_buttons[i].disabled = false + else: + level_buttons[i].disabled = !completed_levels[i] + +func _on_test_level_pressed() -> void: + test_level.emit() + queue_free() diff --git a/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.gd.uid b/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.gd.uid new file mode 100644 index 0000000..ca89584 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.gd.uid @@ -0,0 +1 @@ +uid://d2i8k7votngvg diff --git a/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.tscn b/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.tscn new file mode 100644 index 0000000..8042b97 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/level-select-screen/level_select.tscn @@ -0,0 +1,66 @@ +[gd_scene format=3 uid="uid://cv82k2twxie3n"] + +[ext_resource type="Theme" uid="uid://hheneshfv1b2" path="res://ui/themes/your_theme.tres" id="1_cpj7q"] +[ext_resource type="Script" uid="uid://d2i8k7votngvg" path="res://ui/screens/level-select-screen/level_select.gd" id="2_lcog6"] + +[sub_resource type="LabelSettings" id="LabelSettings_mfdjd"] +font_size = 60 + +[node name="LevelSelect" type="MarginContainer" unique_id=1286521924 node_paths=PackedStringArray("buttonContainer")] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_cpj7q") +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 +script = ExtResource("2_lcog6") +buttonContainer = NodePath("VBoxContainer/HFlowContainer") + +[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1716877818] +layout_mode = 2 + +[node name="LevelSelectTitle" type="Label" parent="VBoxContainer" unique_id=1290767086] +custom_minimum_size = Vector2(731.345, 0) +layout_mode = 2 +text = "Level Select" +label_settings = SubResource("LabelSettings_mfdjd") +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="Spacer" type="Control" parent="VBoxContainer" unique_id=1769227168] +custom_minimum_size = Vector2(0, 28) +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer" unique_id=878866277] +layout_mode = 2 +text = "This Level Select Screen is provided by the template. + +Numbered buttons related to a given level will be displayed here, if multiple_levels is enabled and the max number of levels is larger than zero. + +The default location for levels ist the 'levels/' Folder with levels using the \"level_x.tscn\" naming scheme." +horizontal_alignment = 1 + +[node name="HFlowContainer" type="HFlowContainer" parent="VBoxContainer" unique_id=2027526310] +layout_mode = 2 +alignment = 1 + +[node name="Control" type="HBoxContainer" parent="VBoxContainer" unique_id=1711230144] +layout_mode = 2 +size_flags_vertical = 10 + +[node name="UnlockLevels" type="CheckButton" parent="VBoxContainer/Control" unique_id=1583371876] +layout_mode = 2 +size_flags_horizontal = 10 +text = "Unlock all Levels" + +[node name="Return" type="Button" parent="VBoxContainer" unique_id=2120122741] +layout_mode = 2 +size_flags_horizontal = 4 +text = "Return to Main Menu" + +[connection signal="toggled" from="VBoxContainer/Control/UnlockLevels" to="." method="_on_unlock_levels_toggled"] +[connection signal="pressed" from="VBoxContainer/Return" to="." method="_return_to_title"] diff --git a/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.gd b/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.gd new file mode 100644 index 0000000..5847578 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.gd @@ -0,0 +1,37 @@ +extends Control + +signal continue_btn_pressed +signal settings_btn_pressed +signal exit_to_main_menu_btn_pressed +signal exit_game_btn_pressed + + +func reset(): + %SettingsMenuPopup.hide() + %MainPauseMenuPopup.show() + +func _on_btn_continue_pressed(): + continue_btn_pressed.emit() + hide() + +func _on_btn_settings_pressed(): + settings_btn_pressed.emit() + %SettingsMenuPopup.show() + %MainPauseMenuPopup.hide() + +func _on_btn_exit_to_main_menu_pressed(): + exit_to_main_menu_btn_pressed.emit() + hide() + +func _on_btn_exit_game_pressed(): + exit_game_btn_pressed.emit() + hide() + +func _on_save_and_back_btn_pressed(): + Settings.save_config() + reset() + + +func _on_continue_btn_visibility_changed() -> void: + if visible: + $CenterContainer/MainPauseMenuPopup/VBoxContainer/ContinueBtn.grab_focus() diff --git a/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.gd.uid b/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.gd.uid new file mode 100644 index 0000000..e7f5b01 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.gd.uid @@ -0,0 +1 @@ +uid://2n7o5t6b5g4w diff --git a/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.tscn b/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.tscn new file mode 100644 index 0000000..086412b --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/pause-menu/pause_menu.tscn @@ -0,0 +1,85 @@ +[gd_scene format=3 uid="uid://bilai15byqef2"] + +[ext_resource type="Theme" uid="uid://hheneshfv1b2" path="res://ui/themes/your_theme.tres" id="1_0kumn"] +[ext_resource type="Script" uid="uid://2n7o5t6b5g4w" path="res://ui/screens/pause-menu/pause_menu.gd" id="2_0mnak"] +[ext_resource type="PackedScene" uid="uid://cv271fh4d2p13" path="res://ui/components/settings-menu/settings_menu.tscn" id="4_e3p6x"] + +[node name="PauseMenuScreen" type="Control" unique_id=2087442611] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("2_0mnak") + +[node name="CenterContainer" type="CenterContainer" parent="." unique_id=983714819] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_0kumn") + +[node name="MainPauseMenuPopup" type="PanelContainer" parent="CenterContainer" unique_id=1216636000] +unique_name_in_owner = true +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/MainPauseMenuPopup" unique_id=1361849718] +custom_minimum_size = Vector2(250, 0) +layout_mode = 2 + +[node name="PausedLbl" type="Label" parent="CenterContainer/MainPauseMenuPopup/VBoxContainer" unique_id=338515519] +layout_mode = 2 +theme_type_variation = &"HeaderMedium" +text = "Paused" +horizontal_alignment = 1 + +[node name="ContinueBtn" type="Button" parent="CenterContainer/MainPauseMenuPopup/VBoxContainer" unique_id=2012541750] +layout_mode = 2 +text = "Continue" + +[node name="SettingsButton" type="Button" parent="CenterContainer/MainPauseMenuPopup/VBoxContainer" unique_id=1680382734] +layout_mode = 2 +text = "Settings" + +[node name="ExitToMainMenuBtn" type="Button" parent="CenterContainer/MainPauseMenuPopup/VBoxContainer" unique_id=300221649] +layout_mode = 2 +text = "Quit to title screen" + +[node name="ExitGameBtn" type="Button" parent="CenterContainer/MainPauseMenuPopup/VBoxContainer" unique_id=104298902] +layout_mode = 2 +text = "Quit game" + +[node name="SettingsMenuPopup" type="PanelContainer" parent="CenterContainer" unique_id=1654694978] +unique_name_in_owner = true +visible = false +layout_mode = 2 +theme = ExtResource("1_0kumn") + +[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/SettingsMenuPopup" unique_id=680704985] +layout_mode = 2 +theme_override_constants/separation = 12 + +[node name="Label" type="Label" parent="CenterContainer/SettingsMenuPopup/VBoxContainer" unique_id=547993980] +layout_mode = 2 +theme_type_variation = &"HeaderMedium" +text = "Settings" +horizontal_alignment = 1 + +[node name="SettingsMenu" parent="CenterContainer/SettingsMenuPopup/VBoxContainer" unique_id=1510978317 instance=ExtResource("4_e3p6x")] +layout_mode = 2 + +[node name="SaveAndBackBtn" type="Button" parent="CenterContainer/SettingsMenuPopup/VBoxContainer" unique_id=312254833] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +text = "Save and back" + +[connection signal="pressed" from="CenterContainer/MainPauseMenuPopup/VBoxContainer/ContinueBtn" to="." method="_on_btn_continue_pressed"] +[connection signal="visibility_changed" from="CenterContainer/MainPauseMenuPopup/VBoxContainer/ContinueBtn" to="." method="_on_continue_btn_visibility_changed"] +[connection signal="pressed" from="CenterContainer/MainPauseMenuPopup/VBoxContainer/SettingsButton" to="." method="_on_btn_settings_pressed"] +[connection signal="pressed" from="CenterContainer/MainPauseMenuPopup/VBoxContainer/ExitToMainMenuBtn" to="." method="_on_btn_exit_to_main_menu_pressed"] +[connection signal="pressed" from="CenterContainer/MainPauseMenuPopup/VBoxContainer/ExitGameBtn" to="." method="_on_btn_exit_game_pressed"] +[connection signal="pressed" from="CenterContainer/SettingsMenuPopup/VBoxContainer/SaveAndBackBtn" to="." method="_on_save_and_back_btn_pressed"] diff --git a/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.gd b/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.gd new file mode 100644 index 0000000..5ee9ad1 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.gd @@ -0,0 +1,11 @@ +extends MarginContainer + +signal exit() + +func _ready(): + $VBoxContainer/Return.grab_focus() + +func _return_to_title_screen() -> void: + exit.emit() + queue_free() + Settings.save_config() diff --git a/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.gd.uid b/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.gd.uid new file mode 100644 index 0000000..ab1b2bd --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.gd.uid @@ -0,0 +1 @@ +uid://roiysiotwsbq diff --git a/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.tscn b/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.tscn new file mode 100644 index 0000000..7689bf9 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/settings-screen/settings_screen.tscn @@ -0,0 +1,46 @@ +[gd_scene format=3 uid="uid://ywybicp1ess8"] + +[ext_resource type="Theme" uid="uid://hheneshfv1b2" path="res://ui/themes/your_theme.tres" id="1_i4lq1"] +[ext_resource type="Script" uid="uid://roiysiotwsbq" path="res://ui/screens/settings-screen/settings_screen.gd" id="2_ck7g6"] +[ext_resource type="PackedScene" uid="uid://cv271fh4d2p13" path="res://ui/components/settings-menu/settings_menu.tscn" id="4_i4lq1"] + +[node name="OptionsMenu" type="MarginContainer" unique_id=420614935] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_vertical = 0 +theme = ExtResource("1_i4lq1") +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 10 +script = ExtResource("2_ck7g6") + +[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1967046289] +custom_minimum_size = Vector2(450, 0) +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_constants/separation = 10 + +[node name="OptionsTitle" type="Label" parent="VBoxContainer" unique_id=1806842321] +custom_minimum_size = Vector2(300, 0) +layout_mode = 2 +size_flags_vertical = 0 +theme_type_variation = &"HeaderLarge" +text = "Options" +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="SettingsMenu" parent="VBoxContainer" unique_id=784596614 instance=ExtResource("4_i4lq1")] +custom_minimum_size = Vector2(800, 400) +layout_mode = 2 + +[node name="Return" type="Button" parent="VBoxContainer" unique_id=1869177324] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +text = "Return to Main Menu" + +[connection signal="pressed" from="VBoxContainer/Return" to="." method="_return_to_title_screen"] diff --git a/rougelikeaboutmechs/ui/screens/title-screen/title_screen.gd b/rougelikeaboutmechs/ui/screens/title-screen/title_screen.gd new file mode 100644 index 0000000..15b47fe --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/title-screen/title_screen.gd @@ -0,0 +1,33 @@ +extends Control + +signal start_game() +signal show_credits() +signal show_level_select() +signal show_settings_screen() +signal quit() + +func _ready(): + $CenterContainer2/VBoxContainer/Start.grab_focus() + +func _on_start_pressed() -> void: + start_game.emit() + queue_free() + +func _on_credit_pressed() -> void: + show_credits.emit() + queue_free() + +func _on_level_select_pressed() -> void: + show_level_select.emit() + queue_free() + +func _on_options_pressed() -> void: + show_settings_screen.emit() + queue_free() + +func _on_quit_pressed(): + quit.emit() + queue_free() + +func show_levels(b: bool) -> void: + $CenterContainer2/VBoxContainer/LevelSelect.visible = b diff --git a/rougelikeaboutmechs/ui/screens/title-screen/title_screen.gd.uid b/rougelikeaboutmechs/ui/screens/title-screen/title_screen.gd.uid new file mode 100644 index 0000000..14e94db --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/title-screen/title_screen.gd.uid @@ -0,0 +1 @@ +uid://1mjt83fygiua diff --git a/rougelikeaboutmechs/ui/screens/title-screen/title_screen.tscn b/rougelikeaboutmechs/ui/screens/title-screen/title_screen.tscn new file mode 100644 index 0000000..571b341 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/title-screen/title_screen.tscn @@ -0,0 +1,116 @@ +[gd_scene format=3 uid="uid://ddc3qfst7mbgc"] + +[ext_resource type="Theme" uid="uid://hheneshfv1b2" path="res://ui/themes/your_theme.tres" id="1_qt2rq"] +[ext_resource type="Script" uid="uid://1mjt83fygiua" path="res://ui/screens/title-screen/title_screen.gd" id="1_rm86k"] + +[sub_resource type="LabelSettings" id="LabelSettings_s0ue6"] +font_size = 150 + +[sub_resource type="LabelSettings" id="LabelSettings_73xnf"] +font_size = 50 + +[sub_resource type="LabelSettings" id="LabelSettings_wly7t"] +font_size = 12 + +[node name="TitleScreen" type="Control" unique_id=165552926] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = ExtResource("1_qt2rq") +script = ExtResource("1_rm86k") + +[node name="CenterContainer" type="CenterContainer" parent="." unique_id=129658239] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 2.0 +offset_top = 20.0 +offset_right = 2.0 +offset_bottom = -269.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer" unique_id=1543886662] +layout_mode = 2 + +[node name="Label" type="Label" parent="CenterContainer/VBoxContainer" unique_id=457043767] +custom_minimum_size = Vector2(731.345, 0) +layout_mode = 2 +text = "R.A.M." +label_settings = SubResource("LabelSettings_s0ue6") +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="Label2" type="Label" parent="CenterContainer/VBoxContainer" unique_id=2117014839] +custom_minimum_size = Vector2(731.345, 0) +layout_mode = 2 +text = "rouge-like about machines" +label_settings = SubResource("LabelSettings_73xnf") +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="CenterContainer2" type="CenterContainer" parent="." unique_id=1706430698] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = 309.0 +offset_bottom = -28.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer2" unique_id=11688683] +custom_minimum_size = Vector2(300, 0) +layout_mode = 2 + +[node name="Start" type="Button" parent="CenterContainer2/VBoxContainer" unique_id=603626461] +layout_mode = 2 +theme_override_font_sizes/font_size = 16 +text = "Start" + +[node name="LevelSelect" type="Button" parent="CenterContainer2/VBoxContainer" unique_id=1964255967] +layout_mode = 2 +theme_override_font_sizes/font_size = 16 +text = "Level Select" + +[node name="Options" type="Button" parent="CenterContainer2/VBoxContainer" unique_id=1650158032] +layout_mode = 2 +theme_override_font_sizes/font_size = 16 +text = "Settings" + +[node name="Credit" type="Button" parent="CenterContainer2/VBoxContainer" unique_id=426848008] +layout_mode = 2 +theme_override_font_sizes/font_size = 16 +text = "Credits" + +[node name="Quit" type="Button" parent="CenterContainer2/VBoxContainer" unique_id=2004677633] +layout_mode = 2 +theme_override_font_sizes/font_size = 16 +text = "Quit" + +[node name="Label" type="Label" parent="." unique_id=1786336606] +layout_mode = 1 +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -76.5 +offset_top = -25.0 +offset_right = 76.5 +offset_bottom = -2.0 +grow_horizontal = 2 +grow_vertical = 0 +text = "My Version" +label_settings = SubResource("LabelSettings_wly7t") +horizontal_alignment = 1 + +[connection signal="pressed" from="CenterContainer2/VBoxContainer/Start" to="." method="_on_start_pressed"] +[connection signal="pressed" from="CenterContainer2/VBoxContainer/LevelSelect" to="." method="_on_level_select_pressed"] +[connection signal="pressed" from="CenterContainer2/VBoxContainer/Options" to="." method="_on_options_pressed"] +[connection signal="pressed" from="CenterContainer2/VBoxContainer/Credit" to="." method="_on_credit_pressed"] +[connection signal="pressed" from="CenterContainer2/VBoxContainer/Quit" to="." method="_on_quit_pressed"] diff --git a/rougelikeaboutmechs/ui/screens/win-screen/win_screen.gd b/rougelikeaboutmechs/ui/screens/win-screen/win_screen.gd new file mode 100644 index 0000000..fe4147e --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/win-screen/win_screen.gd @@ -0,0 +1,7 @@ +extends Control + +func _ready(): + $CenterContainer/VBoxContainer/Button.grab_focus() + +func _on_button_pressed() -> void: + queue_free() diff --git a/rougelikeaboutmechs/ui/screens/win-screen/win_screen.gd.uid b/rougelikeaboutmechs/ui/screens/win-screen/win_screen.gd.uid new file mode 100644 index 0000000..238277d --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/win-screen/win_screen.gd.uid @@ -0,0 +1 @@ +uid://dgtme0a6lym5c diff --git a/rougelikeaboutmechs/ui/screens/win-screen/win_screen.tscn b/rougelikeaboutmechs/ui/screens/win-screen/win_screen.tscn new file mode 100644 index 0000000..c521481 --- /dev/null +++ b/rougelikeaboutmechs/ui/screens/win-screen/win_screen.tscn @@ -0,0 +1,51 @@ +[gd_scene format=3 uid="uid://g2g8hydsgxid"] + +[ext_resource type="Script" uid="uid://dgtme0a6lym5c" path="res://ui/screens/win-screen/win_screen.gd" id="1_lgw0b"] + +[sub_resource type="LabelSettings" id="LabelSettings_rbmgw"] +font_size = 100 + +[sub_resource type="LabelSettings" id="LabelSettings_rvyxm"] +font_size = 25 + +[node name="WinScreen" type="Control" unique_id=858939810] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_lgw0b") + +[node name="CenterContainer" type="CenterContainer" parent="." unique_id=2007437466] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer" unique_id=1911103298] +layout_mode = 2 + +[node name="Label" type="Label" parent="CenterContainer/VBoxContainer" unique_id=1273209801] +custom_minimum_size = Vector2(731.345, 0) +layout_mode = 2 +size_flags_vertical = 3 +text = "You won!" +label_settings = SubResource("LabelSettings_rbmgw") +horizontal_alignment = 1 +autowrap_mode = 2 + +[node name="Label2" type="Label" parent="CenterContainer/VBoxContainer" unique_id=1313320644] +layout_mode = 2 +text = "Congratulations and thank you for playing" +label_settings = SubResource("LabelSettings_rvyxm") +horizontal_alignment = 1 + +[node name="Button" type="Button" parent="CenterContainer/VBoxContainer" unique_id=533980693] +layout_mode = 2 +size_flags_horizontal = 4 +text = "Return to title screen" + +[connection signal="pressed" from="CenterContainer/VBoxContainer/Button" to="." method="_on_button_pressed"] diff --git a/rougelikeaboutmechs/ui/themes/your_theme.tres b/rougelikeaboutmechs/ui/themes/your_theme.tres new file mode 100644 index 0000000..d705af0 --- /dev/null +++ b/rougelikeaboutmechs/ui/themes/your_theme.tres @@ -0,0 +1,24 @@ +[gd_resource type="Theme" format=3 uid="uid://hheneshfv1b2"] + +[ext_resource type="Texture2D" uid="uid://b23e4kqj4o6dv" path="res://ui/components/settings-menu/Revert.svg" id="1_r1020"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0d4dl"] +content_margin_left = 8.0 +content_margin_top = 8.0 +content_margin_right = 8.0 +content_margin_bottom = 8.0 +bg_color = Color(0.212305, 0.212305, 0.212305, 1) +corner_radius_top_left = 2 +corner_radius_top_right = 2 +corner_radius_bottom_right = 2 +corner_radius_bottom_left = 2 + +[resource] +HeaderLarge/font_sizes/font_size = 56 +HeaderMedium/font_sizes/font_size = 24 +MarginContainer/constants/margin_bottom = 8 +MarginContainer/constants/margin_left = 8 +MarginContainer/constants/margin_right = 8 +MarginContainer/constants/margin_top = 8 +PanelContainer/styles/panel = SubResource("StyleBoxFlat_0d4dl") +RevertButton/icons/icon = ExtResource("1_r1020")