From dbc88e253b854e26f71f93afe52b836d9a63065f Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 19 Jan 2019 18:23:41 +0100 Subject: [PATCH] Allow client to run headlessly. (#727) AKA Without Godot. Still links against GodotSharp, but this does mean that you can run headless or not from the same binary. --- Resources/.gitignore | 1 + .../Scenes/ChatBox/ChatBox.tscn | 0 .../Scenes/DebugConsole/DebugConsole.tscn | 0 .../Scenes/EscapeMenu/EscapeMenu.tscn | 2 +- .../Scenes/MainMenu/MainMenu.tscn | 2 +- .../Scenes/MainMenu/MainMenuTheme.tres | 0 .../Scenes/OptionsMenu/OptionsMenu.tscn | 2 +- .../Scenes/Placement/EntitySpawnItem.tscn | 0 .../Scenes/Placement/EntitySpawnPanel.tscn | 2 +- .../Scenes/Placement/TileSpawnItem.tscn | 0 .../Scenes/Placement/TileSpawnPanel.tscn | 2 +- Resources/Scenes/SS14Window/SS14Window.tscn | 48 ++ .../Scenes/SS14Window/closewindow.png | Bin .../Scenes/SS14Window/closewindow.png.import | 8 +- .../Scenes/SpriteMirror/SpriteView.cs | 0 .../Scenes/SpriteMirror/SpriteView.tscn | 2 +- SS14.Client.Godot/SS14.Client.Godot.csproj | 2 +- SS14.Client.Godot/SS14Loader.cs | 2 +- .../Scenes/SS14Window/SS14Window.tscn | 125 ---- SS14.Client.Godot/SpriteView.cs | 9 + SS14.Client.Godot/default_env.tres | 1 + SS14.Client.Godot/project.godot | 8 +- SS14.Client/Audio/AudioStream.cs | 2 +- SS14.Client/GameController.cs | 204 ++---- .../GameController.GameTiming.cs | 84 --- .../GameController/GameController.Godot.cs | 247 +++++++ .../GameController/GameController.Headless.cs | 44 ++ .../GameController/GameController.Input.cs | 82 +-- .../GameController/GameController.IoC.cs | 48 +- .../Components/Eye/EyeComponent.cs | 28 +- .../Components/Light/PointLightComponent.cs | 51 +- .../Components/Occluder/OccluderComponent.cs | 18 +- .../Components/Renderable/SpriteComponent.cs | 113 ++- .../GameObjects/EntitySystems/AudioSystem.cs | 12 + .../GameObjects/EntitySystems/EffectSystem.cs | 12 + SS14.Client/Graphics/ClientEye/Eye.cs | 30 +- SS14.Client/Graphics/ClientEye/EyeManager.cs | 30 +- SS14.Client/Graphics/ClientEye/FixedEye.cs | 12 +- SS14.Client/Graphics/DisplayManager.cs | 23 +- SS14.Client/Graphics/Drawing/DrawingHandle.cs | 91 ++- SS14.Client/Graphics/Drawing/StyleBox.cs | 128 +++- SS14.Client/Graphics/Font.cs | 104 ++- .../Graphics/Lighting/LightManager.Light.cs | 139 ++-- .../Lighting/LightManager.Occluder.cs | 71 +- SS14.Client/Graphics/Lighting/LightManager.cs | 35 +- SS14.Client/Graphics/Overlays/Overlay.cs | 67 +- .../Graphics/Overlays/OverlayManager.cs | 49 +- SS14.Client/Graphics/Shaders/Shader.cs | 5 + .../Graphics/Shaders/ShaderPrototype.cs | 16 + SS14.Client/Graphics/Texture.cs | 25 +- SS14.Client/Input/Events.cs | 110 +-- SS14.Client/Input/InputDevices.cs | 44 +- .../Components/IGodotTransformComponent.cs | 1 + .../Components/ISpriteComponent.cs | 5 +- .../Interfaces/Graphics/IDisplayManager.cs | 1 + .../Interfaces/Graphics/Lighting/ILight.cs | 3 +- .../Interfaces/Graphics/Lighting/IOccluder.cs | 11 +- .../Interfaces/Graphics/Overlays/IOverlay.cs | 1 - SS14.Client/Log/GodotLogHandler.cs | 7 +- .../Map/ClientTileDefinitionManager.cs | 22 +- ...ClientMapManager.cs => GodotMapManager.cs} | 8 +- .../Placement/Modes/AlignSnapgridBorder.cs | 2 +- .../Placement/Modes/AlignSnapgridCenter.cs | 2 +- SS14.Client/Placement/PlacementManager.cs | 67 +- SS14.Client/Placement/PlacementMode.cs | 4 + SS14.Client/Player/LocalPlayer.cs | 2 +- .../ResourceTypes/AudioResource.cs | 4 + .../ResourceTypes/FontResource.cs | 12 +- .../ResourceTypes/GodotAssetResource.cs | 22 + .../ResourceTypes/RSIResource.cs | 23 +- .../ResourceTypes/ShaderSourceResource.cs | 8 + .../ResourceTypes/TextureResource.cs | 14 +- SS14.Client/SS14.Client.csproj | 17 +- SS14.Client/SceneTreeHolder.cs | 8 +- SS14.Client/State/States/MainMenu.cs | 20 +- SS14.Client/UserInterface/Control.Input.cs | 163 ++--- SS14.Client/UserInterface/Control.Signals.cs | 2 +- SS14.Client/UserInterface/Control.cs | 629 ++++++++++++++--- .../UserInterface/Controls/AcceptDialog.cs | 16 +- .../UserInterface/Controls/BaseButton.cs | 79 ++- .../UserInterface/Controls/BoxContainer.cs | 2 +- SS14.Client/UserInterface/Controls/Button.cs | 48 +- .../UserInterface/Controls/Container.cs | 14 +- .../UserInterface/Controls/GridContainer.cs | 27 +- .../UserInterface/Controls/HBoxContainer.cs | 14 +- .../UserInterface/Controls/ItemList.cs | 103 ++- SS14.Client/UserInterface/Controls/Label.cs | 43 +- .../UserInterface/Controls/LineEdit.cs | 104 ++- .../UserInterface/Controls/OptionButton.cs | 82 ++- SS14.Client/UserInterface/Controls/Panel.cs | 2 + .../UserInterface/Controls/PanelContainer.cs | 10 +- SS14.Client/UserInterface/Controls/Popup.cs | 15 +- .../UserInterface/Controls/ProgressBar.cs | 9 +- SS14.Client/UserInterface/Controls/Range.cs | 45 +- .../UserInterface/Controls/RichTextLabel.cs | 59 +- .../UserInterface/Controls/ScrollBar.cs | 2 + .../UserInterface/Controls/ScrollContainer.cs | 1 - .../UserInterface/Controls/SpriteView.cs | 8 +- .../UserInterface/Controls/TabContainer.cs | 50 +- .../UserInterface/Controls/TextureButton.cs | 2 + .../UserInterface/Controls/TextureRect.cs | 15 +- SS14.Client/UserInterface/Controls/Tree.cs | 117 +++- .../UserInterface/Controls/VBoxContainer.cs | 14 +- .../UserInterface/Controls/VScrollBar.cs | 2 + .../UserInterface/Controls/WindowDialog.cs | 26 +- .../UserInterface/CustomControls/Chatbox.cs | 9 +- .../CustomControls/DebugConsole.cs | 9 +- .../CustomControls/DebugCoordsPanel.cs | 3 +- .../CustomControls/EntitySpawnWindow.cs | 17 +- .../CustomControls/EscapeMenu.cs | 8 +- .../CustomControls/FPSCounter.cs | 2 +- .../CustomControls/OptionsMenu.cs | 9 +- .../CustomControls/SS14Window.cs | 53 +- .../CustomControls/TileSpawnWindow.cs | 17 +- .../UserInterface/UserInterfaceManager.cs | 39 +- SS14.Client/Utility/GodotParser.cs | 646 ++++++++++++++++++ SS14.Client/Utility/GodotPathUtility.cs | 25 + SS14.Client/Utility/GodotResourceCopy.cs | 4 + .../ResourceManager.SingleStreamLoader.cs | 49 ++ SS14.Shared/ContentPack/ResourceManager.cs | 13 +- .../Interfaces/Resources/IResourceManager.cs | 10 + SS14.Shared/SS14.Shared.csproj | 1 + SS14.Shared/Utility/DebugTools.cs | 16 + .../Client/UserInterface/ControlTest.cs | 67 ++ .../Client/Utility/GodotParserTest.cs | 66 ++ .../Client/Utility/GodotPathUtilityTest.cs | 25 + SS14.UnitTesting/SS14.UnitTesting.csproj | 20 +- SS14.UnitTesting/SS14UnitTest.cs | 2 + .../Shared/ContentPack/ResourceManagerTest.cs | 36 + 129 files changed, 3938 insertions(+), 1315 deletions(-) rename {SS14.Client.Godot => Resources}/Scenes/ChatBox/ChatBox.tscn (100%) rename {SS14.Client.Godot => Resources}/Scenes/DebugConsole/DebugConsole.tscn (100%) rename {SS14.Client.Godot => Resources}/Scenes/EscapeMenu/EscapeMenu.tscn (95%) rename {SS14.Client.Godot => Resources}/Scenes/MainMenu/MainMenu.tscn (98%) rename {SS14.Client.Godot => Resources}/Scenes/MainMenu/MainMenuTheme.tres (100%) rename {SS14.Client.Godot => Resources}/Scenes/OptionsMenu/OptionsMenu.tscn (96%) rename {SS14.Client.Godot => Resources}/Scenes/Placement/EntitySpawnItem.tscn (100%) rename {SS14.Client.Godot => Resources}/Scenes/Placement/EntitySpawnPanel.tscn (98%) rename {SS14.Client.Godot => Resources}/Scenes/Placement/TileSpawnItem.tscn (100%) rename {SS14.Client.Godot => Resources}/Scenes/Placement/TileSpawnPanel.tscn (97%) create mode 100644 Resources/Scenes/SS14Window/SS14Window.tscn rename {SS14.Client.Godot => Resources}/Scenes/SS14Window/closewindow.png (100%) rename {SS14.Client.Godot => Resources}/Scenes/SS14Window/closewindow.png.import (58%) rename {SS14.Client.Godot => Resources}/Scenes/SpriteMirror/SpriteView.cs (100%) rename {SS14.Client.Godot => Resources}/Scenes/SpriteMirror/SpriteView.tscn (79%) delete mode 100644 SS14.Client.Godot/Scenes/SS14Window/SS14Window.tscn create mode 100644 SS14.Client.Godot/SpriteView.cs delete mode 100644 SS14.Client/GameController/GameController.GameTiming.cs create mode 100644 SS14.Client/GameController/GameController.Godot.cs create mode 100644 SS14.Client/GameController/GameController.Headless.cs rename SS14.Client/Map/{ClientMapManager.cs => GodotMapManager.cs} (93%) create mode 100644 SS14.Client/ResourceManagement/ResourceTypes/GodotAssetResource.cs create mode 100644 SS14.Client/Utility/GodotParser.cs create mode 100644 SS14.Client/Utility/GodotPathUtility.cs create mode 100644 SS14.Shared/ContentPack/ResourceManager.SingleStreamLoader.cs create mode 100644 SS14.UnitTesting/Client/UserInterface/ControlTest.cs create mode 100644 SS14.UnitTesting/Client/Utility/GodotParserTest.cs create mode 100644 SS14.UnitTesting/Client/Utility/GodotPathUtilityTest.cs create mode 100644 SS14.UnitTesting/Shared/ContentPack/ResourceManagerTest.cs diff --git a/Resources/.gitignore b/Resources/.gitignore index 96bc954c8..dd1744696 100644 --- a/Resources/.gitignore +++ b/Resources/.gitignore @@ -4,4 +4,5 @@ *.import # Negation would be like this: #!/Textures/UserInterface/1pxwhite.png.import +!/Scenes/SS14Window/closewindow.png.import /I_MADE_THE_SYMLINK diff --git a/SS14.Client.Godot/Scenes/ChatBox/ChatBox.tscn b/Resources/Scenes/ChatBox/ChatBox.tscn similarity index 100% rename from SS14.Client.Godot/Scenes/ChatBox/ChatBox.tscn rename to Resources/Scenes/ChatBox/ChatBox.tscn diff --git a/SS14.Client.Godot/Scenes/DebugConsole/DebugConsole.tscn b/Resources/Scenes/DebugConsole/DebugConsole.tscn similarity index 100% rename from SS14.Client.Godot/Scenes/DebugConsole/DebugConsole.tscn rename to Resources/Scenes/DebugConsole/DebugConsole.tscn diff --git a/SS14.Client.Godot/Scenes/EscapeMenu/EscapeMenu.tscn b/Resources/Scenes/EscapeMenu/EscapeMenu.tscn similarity index 95% rename from SS14.Client.Godot/Scenes/EscapeMenu/EscapeMenu.tscn rename to Resources/Scenes/EscapeMenu/EscapeMenu.tscn index 1c7f955d0..912865640 100644 --- a/SS14.Client.Godot/Scenes/EscapeMenu/EscapeMenu.tscn +++ b/Resources/Scenes/EscapeMenu/EscapeMenu.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=2] -[ext_resource path="res://Scenes/SS14Window/SS14Window.tscn" type="PackedScene" id=1] +[ext_resource path="res://Engine/Scenes/SS14Window/SS14Window.tscn" type="PackedScene" id=1] [node name="SS14Window" index="0" instance=ExtResource( 1 )] diff --git a/SS14.Client.Godot/Scenes/MainMenu/MainMenu.tscn b/Resources/Scenes/MainMenu/MainMenu.tscn similarity index 98% rename from SS14.Client.Godot/Scenes/MainMenu/MainMenu.tscn rename to Resources/Scenes/MainMenu/MainMenu.tscn index 579dfe3f8..53d69417a 100644 --- a/SS14.Client.Godot/Scenes/MainMenu/MainMenu.tscn +++ b/Resources/Scenes/MainMenu/MainMenu.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=6 format=2] [ext_resource path="res://Art/background.png" type="Texture" id=1] -[ext_resource path="res://Scenes/MainMenu/MainMenuTheme.tres" type="Theme" id=2] +[ext_resource path="res://Engine/Scenes/MainMenu/MainMenuTheme.tres" type="Theme" id=2] [ext_resource path="res://Art/bootsplash.png" type="Texture" id=3] [ext_resource path="res://Engine/Fonts/Animal Silence.otf" type="DynamicFontData" id=4] diff --git a/SS14.Client.Godot/Scenes/MainMenu/MainMenuTheme.tres b/Resources/Scenes/MainMenu/MainMenuTheme.tres similarity index 100% rename from SS14.Client.Godot/Scenes/MainMenu/MainMenuTheme.tres rename to Resources/Scenes/MainMenu/MainMenuTheme.tres diff --git a/SS14.Client.Godot/Scenes/OptionsMenu/OptionsMenu.tscn b/Resources/Scenes/OptionsMenu/OptionsMenu.tscn similarity index 96% rename from SS14.Client.Godot/Scenes/OptionsMenu/OptionsMenu.tscn rename to Resources/Scenes/OptionsMenu/OptionsMenu.tscn index a1efff776..fd714a86f 100644 --- a/SS14.Client.Godot/Scenes/OptionsMenu/OptionsMenu.tscn +++ b/Resources/Scenes/OptionsMenu/OptionsMenu.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=2] -[ext_resource path="res://Scenes/SS14Window/SS14Window.tscn" type="PackedScene" id=1] +[ext_resource path="res://Engine/Scenes/SS14Window/SS14Window.tscn" type="PackedScene" id=1] [node name="SS14Window" instance=ExtResource( 1 )] diff --git a/SS14.Client.Godot/Scenes/Placement/EntitySpawnItem.tscn b/Resources/Scenes/Placement/EntitySpawnItem.tscn similarity index 100% rename from SS14.Client.Godot/Scenes/Placement/EntitySpawnItem.tscn rename to Resources/Scenes/Placement/EntitySpawnItem.tscn diff --git a/SS14.Client.Godot/Scenes/Placement/EntitySpawnPanel.tscn b/Resources/Scenes/Placement/EntitySpawnPanel.tscn similarity index 98% rename from SS14.Client.Godot/Scenes/Placement/EntitySpawnPanel.tscn rename to Resources/Scenes/Placement/EntitySpawnPanel.tscn index 860b16594..e63ad9855 100644 --- a/SS14.Client.Godot/Scenes/Placement/EntitySpawnPanel.tscn +++ b/Resources/Scenes/Placement/EntitySpawnPanel.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=2] -[ext_resource path="res://Scenes/SS14Window/SS14Window.tscn" type="PackedScene" id=1] +[ext_resource path="res://Engine/Scenes/SS14Window/SS14Window.tscn" type="PackedScene" id=1] [node name="SS14Window" instance=ExtResource( 1 )] diff --git a/SS14.Client.Godot/Scenes/Placement/TileSpawnItem.tscn b/Resources/Scenes/Placement/TileSpawnItem.tscn similarity index 100% rename from SS14.Client.Godot/Scenes/Placement/TileSpawnItem.tscn rename to Resources/Scenes/Placement/TileSpawnItem.tscn diff --git a/SS14.Client.Godot/Scenes/Placement/TileSpawnPanel.tscn b/Resources/Scenes/Placement/TileSpawnPanel.tscn similarity index 97% rename from SS14.Client.Godot/Scenes/Placement/TileSpawnPanel.tscn rename to Resources/Scenes/Placement/TileSpawnPanel.tscn index 15ed4eb5a..a78cf9c47 100644 --- a/SS14.Client.Godot/Scenes/Placement/TileSpawnPanel.tscn +++ b/Resources/Scenes/Placement/TileSpawnPanel.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=2] -[ext_resource path="res://Scenes/SS14Window/SS14Window.tscn" type="PackedScene" id=1] +[ext_resource path="res://Engine/Scenes/SS14Window/SS14Window.tscn" type="PackedScene" id=1] [node name="SS14Window" index="0" instance=ExtResource( 1 )] diff --git a/Resources/Scenes/SS14Window/SS14Window.tscn b/Resources/Scenes/SS14Window/SS14Window.tscn new file mode 100644 index 000000000..1e0cc42ca --- /dev/null +++ b/Resources/Scenes/SS14Window/SS14Window.tscn @@ -0,0 +1,48 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://Engine/Scenes/SS14Window/closewindow.png" type="Texture" id=1] + +[sub_resource type="StyleBoxFlat" id=1] + +bg_color = Color( 0.234375, 0.234375, 0.234375, 1 ) + +[node name="SS14Window" type="Panel"] +margin_left = 100.0 +margin_top = 38.0 +margin_right = 878.0 +margin_bottom = 519.0 + +[node name="Contents" type="Container" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 10.0 +margin_top = 40.0 +margin_right = -10.0 +margin_bottom = -10.0 +rect_min_size = Vector2( 50, 50 ) +mouse_filter = 2 + +[node name="Header" type="Panel" parent="."] +anchor_right = 1.0 +margin_bottom = 25.0 +mouse_filter = 2 +custom_styles/panel = SubResource( 1 ) + +[node name="Header Text" type="Label" parent="Header"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = -25.0 +text = "Exemplary Window Title Here" +align = 1 +valign = 1 +clip_text = true + +[node name="CloseButton" type="TextureButton" parent="Header"] +anchor_left = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = -25.0 +texture_normal = ExtResource( 1 ) +expand = true +stretch_mode = 5 + diff --git a/SS14.Client.Godot/Scenes/SS14Window/closewindow.png b/Resources/Scenes/SS14Window/closewindow.png similarity index 100% rename from SS14.Client.Godot/Scenes/SS14Window/closewindow.png rename to Resources/Scenes/SS14Window/closewindow.png diff --git a/SS14.Client.Godot/Scenes/SS14Window/closewindow.png.import b/Resources/Scenes/SS14Window/closewindow.png.import similarity index 58% rename from SS14.Client.Godot/Scenes/SS14Window/closewindow.png.import rename to Resources/Scenes/SS14Window/closewindow.png.import index dd9d514d1..ed2a5e85b 100644 --- a/SS14.Client.Godot/Scenes/SS14Window/closewindow.png.import +++ b/Resources/Scenes/SS14Window/closewindow.png.import @@ -2,18 +2,19 @@ importer="texture" type="StreamTexture" -path="res://.import/closewindow.png-7b2f9cb6cf73c832ec12a5ebfba82490.stex" +path="res://.import/closewindow.png-27200ff550a4cc91ea5c13546f44ca18.stex" [deps] -source_file="res://Scenes/SS14Window/closewindow.png" -dest_files=[ "res://.import/closewindow.png-7b2f9cb6cf73c832ec12a5ebfba82490.stex" ] +source_file="res://Engine/Scenes/SS14Window/closewindow.png" +dest_files=[ "res://.import/closewindow.png-27200ff550a4cc91ea5c13546f44ca18.stex" ] [params] compress/mode=0 compress/lossy_quality=0.7 compress/hdr_mode=0 +compress/bptc_ldr=0 compress/normal_map=0 flags/repeat=0 flags/filter=false @@ -23,6 +24,7 @@ flags/srgb=2 process/fix_alpha_border=true process/premult_alpha=false process/HDR_as_SRGB=false +process/invert_color=false stream=false size_limit=0 detect_3d=true diff --git a/SS14.Client.Godot/Scenes/SpriteMirror/SpriteView.cs b/Resources/Scenes/SpriteMirror/SpriteView.cs similarity index 100% rename from SS14.Client.Godot/Scenes/SpriteMirror/SpriteView.cs rename to Resources/Scenes/SpriteMirror/SpriteView.cs diff --git a/SS14.Client.Godot/Scenes/SpriteMirror/SpriteView.tscn b/Resources/Scenes/SpriteMirror/SpriteView.tscn similarity index 79% rename from SS14.Client.Godot/Scenes/SpriteMirror/SpriteView.tscn rename to Resources/Scenes/SpriteMirror/SpriteView.tscn index c1b0ab6df..2f6e25b86 100644 --- a/SS14.Client.Godot/Scenes/SpriteMirror/SpriteView.tscn +++ b/Resources/Scenes/SpriteMirror/SpriteView.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=2] -[ext_resource path="res://Scenes/SpriteMirror/SpriteView.cs" type="Script" id=1] +[ext_resource path="res://Engine/Scenes/SpriteMirror/SpriteView.cs" type="Script" id=1] [node name="SpriteView" type="Control"] anchor_left = 0.0 diff --git a/SS14.Client.Godot/SS14.Client.Godot.csproj b/SS14.Client.Godot/SS14.Client.Godot.csproj index d986bc730..114a00004 100644 --- a/SS14.Client.Godot/SS14.Client.Godot.csproj +++ b/SS14.Client.Godot/SS14.Client.Godot.csproj @@ -44,7 +44,7 @@ - + diff --git a/SS14.Client.Godot/SS14Loader.cs b/SS14.Client.Godot/SS14Loader.cs index f651754d6..7824fe5c2 100644 --- a/SS14.Client.Godot/SS14Loader.cs +++ b/SS14.Client.Godot/SS14Loader.cs @@ -44,7 +44,7 @@ namespace SS14.Client.GodotGlue Assembly.LoadFile(System.IO.Path.Combine(path, "../bin/Client/ICSharpCode.SharpZipLib.dll")); Started = true; - SS14Assembly = Assembly.LoadFrom("../bin/Client/SS14.Client.dll"); + SS14Assembly = Assembly.LoadFrom("../bin/Client/SS14.Client.exe"); var entryType = typeof(ClientEntryPoint); foreach (var type in SS14Assembly.GetTypes()) { diff --git a/SS14.Client.Godot/Scenes/SS14Window/SS14Window.tscn b/SS14.Client.Godot/Scenes/SS14Window/SS14Window.tscn deleted file mode 100644 index 828610d97..000000000 --- a/SS14.Client.Godot/Scenes/SS14Window/SS14Window.tscn +++ /dev/null @@ -1,125 +0,0 @@ -[gd_scene load_steps=3 format=2] - -[ext_resource path="res://Scenes/SS14Window/closewindow.png" type="Texture" id=1] - -[sub_resource type="StyleBoxFlat" id=1] - -content_margin_left = -1.0 -content_margin_right = -1.0 -content_margin_top = -1.0 -content_margin_bottom = -1.0 -bg_color = Color( 0.234375, 0.234375, 0.234375, 1 ) -draw_center = true -border_width_left = 0 -border_width_top = 0 -border_width_right = 0 -border_width_bottom = 0 -border_color = Color( 0.8, 0.8, 0.8, 1 ) -border_blend = false -corner_radius_top_left = 0 -corner_radius_top_right = 0 -corner_radius_bottom_right = 0 -corner_radius_bottom_left = 0 -corner_detail = 8 -expand_margin_left = 0.0 -expand_margin_right = 0.0 -expand_margin_top = 0.0 -expand_margin_bottom = 0.0 -shadow_color = Color( 0, 0, 0, 0.6 ) -shadow_size = 0 -anti_aliasing = true -anti_aliasing_size = 1 - -[node name="SS14Window" type="Panel"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_left = 100.0 -margin_top = 38.0 -margin_right = 878.0 -margin_bottom = 519.0 -rect_pivot_offset = Vector2( 0, 0 ) -mouse_filter = 0 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 - -[node name="Contents" type="Container" parent="." index="0"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_left = 10.0 -margin_top = 40.0 -margin_right = -10.0 -margin_bottom = -10.0 -rect_min_size = Vector2( 50, 50 ) -rect_pivot_offset = Vector2( 0, 0 ) -mouse_filter = 2 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -_sections_unfolded = [ "Anchor", "Margin", "Mouse", "Rect" ] - -[node name="Header" type="Panel" parent="." index="1"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 1.0 -anchor_bottom = 0.0 -margin_bottom = 25.0 -rect_pivot_offset = Vector2( 0, 0 ) -mouse_filter = 2 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -custom_styles/panel = SubResource( 1 ) -_sections_unfolded = [ "Margin", "Mouse", "custom_styles" ] - -[node name="Header Text" type="Label" parent="Header" index="0"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_right = -25.0 -rect_pivot_offset = Vector2( 0, 0 ) -mouse_filter = 2 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 4 -text = "Exemplary Window Title Here" -align = 1 -valign = 1 -clip_text = true -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 -_sections_unfolded = [ "Margin", "Mouse" ] - -[node name="CloseButton" type="TextureButton" parent="Header" index="1"] - -anchor_left = 1.0 -anchor_top = 0.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_left = -25.0 -rect_pivot_offset = Vector2( 0, 0 ) -focus_mode = 2 -mouse_filter = 0 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = false -enabled_focus_mode = 2 -shortcut = null -group = null -texture_normal = ExtResource( 1 ) -expand = true -stretch_mode = 5 -_sections_unfolded = [ "Margin", "Textures" ] - - diff --git a/SS14.Client.Godot/SpriteView.cs b/SS14.Client.Godot/SpriteView.cs new file mode 100644 index 000000000..d00da6103 --- /dev/null +++ b/SS14.Client.Godot/SpriteView.cs @@ -0,0 +1,9 @@ +using Godot; + +namespace SS14.Client.GodotGlue +{ + public class SpriteView : Control + { + + } +} diff --git a/SS14.Client.Godot/default_env.tres b/SS14.Client.Godot/default_env.tres index ad86b722a..8edf1e3a2 100644 --- a/SS14.Client.Godot/default_env.tres +++ b/SS14.Client.Godot/default_env.tres @@ -65,6 +65,7 @@ ssao_radius2 = 0.0 ssao_intensity2 = 1.0 ssao_bias = 0.01 ssao_light_affect = 0.0 +ssao_ao_channel_affect = 0.0 ssao_color = Color( 0, 0, 0, 1 ) ssao_quality = 0 ssao_blur = 3 diff --git a/SS14.Client.Godot/project.godot b/SS14.Client.Godot/project.godot index ded5363a4..fe012c1dc 100644 --- a/SS14.Client.Godot/project.godot +++ b/SS14.Client.Godot/project.godot @@ -6,7 +6,12 @@ ; [section] ; section goes between [] ; param=value ; assign values to parameters -config_version=3 +config_version=4 + +_global_script_classes=[ ] +_global_script_class_icons={ + +} [application] @@ -31,6 +36,7 @@ limits/debugger_stdout/max_chars_per_second=8128 [rendering] +quality/driver/driver_name="GLES2" quality/intended_usage/framebuffer_allocation=0 quality/2d/use_pixel_snap=true environment/default_clear_color=Color( 0, 0, 0, 1 ) diff --git a/SS14.Client/Audio/AudioStream.cs b/SS14.Client/Audio/AudioStream.cs index 38934730d..d46879951 100644 --- a/SS14.Client/Audio/AudioStream.cs +++ b/SS14.Client/Audio/AudioStream.cs @@ -6,7 +6,7 @@ namespace SS14.Client.Audio { internal abstract Godot.AudioStream GodotAudioStream { get; } - public TimeSpan Length => TimeSpan.FromSeconds(GodotAudioStream.GetLength()); + public TimeSpan Length => TimeSpan.FromSeconds(GodotAudioStream?.GetLength() ?? 0); } internal class GodotAudioStreamSource : AudioStream diff --git a/SS14.Client/GameController.cs b/SS14.Client/GameController.cs index 2d03de057..b227ebf60 100644 --- a/SS14.Client/GameController.cs +++ b/SS14.Client/GameController.cs @@ -1,5 +1,4 @@ using SS14.Client.Console; -using SS14.Client.GodotGlue; using SS14.Client.Interfaces; using SS14.Client.Interfaces.GameObjects; using SS14.Client.Interfaces.GameStates; @@ -34,6 +33,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Threading; +using JetBrains.Annotations; using SS14.Client.Utility; using SS14.Client.ViewVariables; using SS14.Shared; @@ -43,92 +43,58 @@ using SS14.Shared.Interfaces.Resources; namespace SS14.Client { // Gets automatically ran by SS14.Client.Godot. - public sealed partial class GameController : ClientEntryPoint, IGameController + [UsedImplicitly] + public sealed partial class GameController : IGameController { + internal static bool OnGodot { get; private set; } + /// /// QueueFreeing a Godot node during finalization can cause segfaults. /// As such, this var is set as soon as we tell Godot to shut down proper. /// public static bool ShuttingDownHard { get; private set; } = false; - [Dependency] - readonly IConfigurationManager _configurationManager; - [Dependency] - readonly IResourceCache _resourceCache; - [Dependency] - readonly IResourceManager _resourceManager; - [Dependency] - readonly ISS14Serializer _serializer; - [Dependency] - readonly IPrototypeManager _prototypeManager; - [Dependency] - readonly IClientTileDefinitionManager _tileDefinitionManager; - [Dependency] - readonly IClientNetManager _networkManager; - [Dependency] - readonly IMapManager _mapManager; - [Dependency] - readonly IStateManager _stateManager; - [Dependency] - readonly IUserInterfaceManager _userInterfaceManager; - [Dependency] - readonly IBaseClient _client; - [Dependency] - readonly IInputManager inputManager; - [Dependency] - readonly IClientChatConsole _console; - [Dependency] - readonly ILightManager lightManager; - [Dependency] - readonly IDisplayManager displayManager; - [Dependency] - readonly ITimerManager _timerManager; - [Dependency] - readonly IClientEntityManager _entityManager; - [Dependency] - readonly IEyeManager eyeManager; - [Dependency] - readonly GameTiming gameTiming; - [Dependency] - readonly IPlacementManager placementManager; - [Dependency] - readonly IClientGameStateManager gameStateManager; - [Dependency] - readonly IOverlayManager overlayManager; - [Dependency] - readonly ILogManager logManager; - [Dependency] - private readonly ITaskManager _taskManager; + [Dependency] private readonly IConfigurationManager _configurationManager; + [Dependency] private readonly IResourceCache _resourceCache; + [Dependency] private readonly IResourceManager _resourceManager; + [Dependency] private readonly ISS14Serializer _serializer; + [Dependency] private readonly IPrototypeManager _prototypeManager; + [Dependency] private readonly IClientTileDefinitionManager _tileDefinitionManager; + [Dependency] private readonly IClientNetManager _networkManager; + [Dependency] private readonly IMapManager _mapManager; + [Dependency] private readonly IStateManager _stateManager; + [Dependency] private readonly IUserInterfaceManager _userInterfaceManager; + [Dependency] private readonly IBaseClient _client; + [Dependency] private readonly IInputManager _inputManager; + [Dependency] private readonly IClientChatConsole _console; + [Dependency] private readonly ILightManager _lightManager; + [Dependency] private readonly IDisplayManager _displayManager; + [Dependency] private readonly ITimerManager _timerManager; + [Dependency] private readonly IClientEntityManager _entityManager; + [Dependency] private readonly IEyeManager _eyeManager; + [Dependency] private readonly IPlacementManager _placementManager; + [Dependency] private readonly IClientGameStateManager _gameStateManager; + [Dependency] private readonly IOverlayManager _overlayManager; + [Dependency] private readonly ILogManager _logManager; + [Dependency] private readonly ITaskManager _taskManager; [Dependency] private readonly IViewVariablesManagerInternal _viewVariablesManager; - public override void Main(Godot.SceneTree tree) + private void Startup() { -#if !X64 - throw new InvalidOperationException("The client cannot start outside x64."); -#endif ThreadUtility.MainThread = Thread.CurrentThread; - PreInitIoC(); - IoCManager.Resolve().Initialize(tree); InitIoC(); - Godot.OS.SetWindowTitle("Space Station 14"); SetupLogging(); // Set up custom synchronization context. // Sorry Godot. _taskManager.Initialize(); - tree.SetAutoAcceptQuit(false); - // Load config. _configurationManager.LoadFromFile(PathHelpers.ExecutableRelativeFile("client_config.toml")); - displayManager.Initialize(); - - // Ensure Godot's side of the resources are up to date. -#if DEBUG - GodotResourceCopy.DoDirCopy("../Resources", "Engine"); -#endif + _displayManager.Initialize(); + _displayManager.SetWindowTitle("Space Station 14"); // Init resources. // Doesn't do anything right now because TODO Godot asset management is a bit ad-hoc. @@ -149,21 +115,21 @@ namespace SS14.Client // Call Init in game assemblies. AssemblyLoader.BroadcastRunLevel(AssemblyLoader.RunLevel.Init); - eyeManager.Initialize(); + _eyeManager.Initialize(); _serializer.Initialize(); _userInterfaceManager.Initialize(); _networkManager.Initialize(false); - inputManager.Initialize(); + _inputManager.Initialize(); _console.Initialize(); _prototypeManager.LoadDirectory(new ResourcePath(@"/Prototypes/")); _prototypeManager.Resync(); _tileDefinitionManager.Initialize(); _mapManager.Initialize(); - placementManager.Initialize(); - lightManager.Initialize(); + _placementManager.Initialize(); + _lightManager.Initialize(); _entityManager.Initialize(); - gameStateManager.Initialize(); - overlayManager.Initialize(); + _gameStateManager.Initialize(); + _overlayManager.Initialize(); _viewVariablesManager.Initialize(); _client.Initialize(); @@ -172,18 +138,13 @@ namespace SS14.Client _stateManager.RequestStateChange(); - var args = (ICollection) Godot.OS.GetCmdlineArgs(); + var args = GetCommandLineArgs(); if (args.Contains("--connect")) { _client.ConnectToServer("127.0.0.1", 1212); } } - public override void QuitRequest() - { - Shutdown("OS quit request"); - } - public void Shutdown(string reason = null) { if (reason != null) @@ -194,6 +155,7 @@ namespace SS14.Client { Logger.Info("Shutting down!"); } + Logger.Debug("Goodbye"); IoCManager.Clear(); ShuttingDownHard = true; @@ -202,72 +164,38 @@ namespace SS14.Client Environment.Exit(0); } - public override void PhysicsProcess(float delta) + private void Update(float frameTime) { - // Can't be too certain. - gameTiming.InSimulation = true; - gameTiming._tickRemainderTimer.Restart(); - try - { - if (!gameTiming.Paused) - { - gameTiming.CurTick++; - _networkManager.ProcessPackets(); - var eventArgs = new ProcessFrameEventArgs(delta); - AssemblyLoader.BroadcastUpdate(AssemblyLoader.UpdateLevel.PreEngine, eventArgs.Elapsed); - _timerManager.UpdateTimers(delta); - _taskManager.ProcessPendingTasks(); - _userInterfaceManager.Update(eventArgs); - _stateManager.Update(eventArgs); - AssemblyLoader.BroadcastUpdate(AssemblyLoader.UpdateLevel.PostEngine, eventArgs.Elapsed); - } - } - finally - { - gameTiming.InSimulation = false; - } - } - - public override void FrameProcess(float delta) - { - gameTiming.InSimulation = false; // Better safe than sorry. - gameTiming.RealFrameTime = TimeSpan.FromSeconds(delta); - gameTiming.TickRemainder = gameTiming._tickRemainderTimer.Elapsed; - - var eventArgs = new RenderFrameEventArgs(delta); - AssemblyLoader.BroadcastUpdate(AssemblyLoader.UpdateLevel.FramePreEngine, eventArgs.Elapsed); - lightManager.FrameUpdate(eventArgs); - _stateManager.FrameUpdate(eventArgs); - overlayManager.FrameUpdate(eventArgs); - AssemblyLoader.BroadcastUpdate(AssemblyLoader.UpdateLevel.FramePostEngine, eventArgs.Elapsed); - } - - public override void HandleException(Exception exception) - { - try - { - if (logManager != null) - { - logManager.GetSawmill("root").Error($"Unhandled exception:\n{exception}"); - } - else - { - Godot.GD.Print($"Unhandled exception:\n{exception}"); - } - } - catch (Exception e) - { - Godot.GD.Print($"Welp. The unhandled exception handler threw an exception.\n{e}\nException that was being handled:\n{exception}"); - } + _networkManager.ProcessPackets(); + var eventArgs = new ProcessFrameEventArgs(frameTime); + AssemblyLoader.BroadcastUpdate(AssemblyLoader.UpdateLevel.PreEngine, eventArgs.Elapsed); + _timerManager.UpdateTimers(frameTime); + _taskManager.ProcessPendingTasks(); + _userInterfaceManager.Update(eventArgs); + _stateManager.Update(eventArgs); + AssemblyLoader.BroadcastUpdate(AssemblyLoader.UpdateLevel.PostEngine, eventArgs.Elapsed); } private void SetupLogging() { - logManager.RootSawmill.AddHandler(new GodotLogHandler()); - logManager.GetSawmill("res.typecheck").Level = LogLevel.Info; - logManager.GetSawmill("res.tex").Level = LogLevel.Info; - logManager.GetSawmill("console").Level = LogLevel.Info; - logManager.GetSawmill("go.sys").Level = LogLevel.Info; + if (OnGodot) + { + _logManager.RootSawmill.AddHandler(new GodotLogHandler()); + } + else + { + _logManager.RootSawmill.AddHandler(new ConsoleLogHandler()); + } + + _logManager.GetSawmill("res.typecheck").Level = LogLevel.Info; + _logManager.GetSawmill("res.tex").Level = LogLevel.Info; + _logManager.GetSawmill("console").Level = LogLevel.Info; + _logManager.GetSawmill("go.sys").Level = LogLevel.Info; + } + + public static ICollection GetCommandLineArgs() + { + return OnGodot ? Godot.OS.GetCmdlineArgs() : Environment.GetCommandLineArgs(); } } } diff --git a/SS14.Client/GameController/GameController.GameTiming.cs b/SS14.Client/GameController/GameController.GameTiming.cs deleted file mode 100644 index 69d69ca9d..000000000 --- a/SS14.Client/GameController/GameController.GameTiming.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using SS14.Shared.Timing; -using SS14.Shared.Interfaces.Timing; - -namespace SS14.Client -{ - public sealed partial class GameController - { - // TODO: This class is basically just a bunch of stubs. - private class GameTiming : IGameTiming - { - private static readonly IStopwatch _realTimer = new Stopwatch(); - public readonly IStopwatch _tickRemainderTimer = new Stopwatch(); - - public GameTiming() - { - _realTimer.Start(); - // Not sure if Restart() starts it implicitly so... - _tickRemainderTimer.Start(); - } - - public bool InSimulation { get; set; } - public bool Paused { get; set; } - - public TimeSpan CurTime => CalcCurTime(); - - public TimeSpan RealTime => _realTimer.Elapsed; - - public TimeSpan FrameTime => CalcFrameTime(); - - public TimeSpan RealFrameTime { get; set; } - - public TimeSpan RealFrameTimeAvg => throw new NotImplementedException(); - - public TimeSpan RealFrameTimeStdDev => throw new NotImplementedException(); - - public double FramesPerSecondAvg => throw new NotImplementedException(); - - public uint CurTick { get; set; } - public int TickRate - { - get => Godot.Engine.IterationsPerSecond; - set => Godot.Engine.IterationsPerSecond = value; - } - - public TimeSpan TickPeriod => TimeSpan.FromTicks((long)(1.0 / TickRate * TimeSpan.TicksPerSecond)); - - public TimeSpan TickRemainder { get; set; } - - public void ResetRealTime() - { - throw new NotImplementedException(); - } - - public void StartFrame() - { - throw new NotImplementedException(); - } - - private TimeSpan CalcCurTime() - { - // calculate simulation CurTime - var time = TimeSpan.FromTicks(TickPeriod.Ticks * CurTick); - - if (!InSimulation) // rendering can draw frames between ticks - return time + TickRemainder; - return time; - } - - private TimeSpan CalcFrameTime() - { - // calculate simulation FrameTime - if (InSimulation) - { - return TimeSpan.FromTicks(TickPeriod.Ticks); - } - else - { - return Paused ? TimeSpan.Zero : RealFrameTime; - } - } - } - } -} diff --git a/SS14.Client/GameController/GameController.Godot.cs b/SS14.Client/GameController/GameController.Godot.cs new file mode 100644 index 000000000..b396c6d92 --- /dev/null +++ b/SS14.Client/GameController/GameController.Godot.cs @@ -0,0 +1,247 @@ +using System; +using System.Collections.Generic; +using SS14.Client.GodotGlue; +using SS14.Client.Input; +using SS14.Client.Interfaces; +using SS14.Client.Utility; +using SS14.Shared.ContentPack; +using SS14.Shared.Interfaces.Timing; +using SS14.Shared.IoC; +using SS14.Shared.Timing; + +namespace SS14.Client +{ + public partial class GameController : ClientEntryPoint + { + private GameTimingGodot _gameTimingGodotGodot; + + public override void Main(Godot.SceneTree tree) + { +#if !X64 + throw new InvalidOperationException("The client cannot start outside x64."); +#endif + OnGodot = true; + tree.SetAutoAcceptQuit(false); + IoCManager.Register(); + IoCManager.BuildGraph(); + IoCManager.Resolve().Initialize(tree); + +#if DEBUG + // Ensure Godot's side of the resources are up to date. + GodotResourceCopy.DoDirCopy("../Resources", "Engine"); +#endif + + Startup(); + + _gameTimingGodotGodot = IoCManager.Resolve(); + } + + public override void QuitRequest() + { + Shutdown("OS quit request"); + } + + public override void PhysicsProcess(float delta) + { + // Can't be too certain. + _gameTimingGodotGodot.InSimulation = true; + _gameTimingGodotGodot._tickRemainderTimer.Restart(); + try + { + if (!_gameTimingGodotGodot.Paused) + { + _gameTimingGodotGodot.CurTick++; + Update(delta); + } + } + finally + { + _gameTimingGodotGodot.InSimulation = false; + } + } + + public override void FrameProcess(float delta) + { + _gameTimingGodotGodot.InSimulation = false; // Better safe than sorry. + _gameTimingGodotGodot.RealFrameTime = TimeSpan.FromSeconds(delta); + _gameTimingGodotGodot.TickRemainder = _gameTimingGodotGodot._tickRemainderTimer.Elapsed; + + var eventArgs = new RenderFrameEventArgs(delta); + AssemblyLoader.BroadcastUpdate(AssemblyLoader.UpdateLevel.FramePreEngine, eventArgs.Elapsed); + _lightManager.FrameUpdate(eventArgs); + _stateManager.FrameUpdate(eventArgs); + _overlayManager.FrameUpdate(eventArgs); + AssemblyLoader.BroadcastUpdate(AssemblyLoader.UpdateLevel.FramePostEngine, eventArgs.Elapsed); + } + + public override void HandleException(Exception exception) + { + try + { + if (_logManager != null) + { + _logManager.GetSawmill("root").Error($"Unhandled exception:\n{exception}"); + } + else + { + Godot.GD.Print($"Unhandled exception:\n{exception}"); + } + } + catch (Exception e) + { + Godot.GD.Print($"Welp. The unhandled exception handler threw an exception.\n{e}\nException that was being handled:\n{exception}"); + } + } + + + // Override that converts and distributes the input events + // to the more sane methods above. + public override void Input(Godot.InputEvent inputEvent) + { + switch (inputEvent) + { + case Godot.InputEventKey keyEvent: + var keyEventArgs = (KeyEventArgs)keyEvent; + if (keyEvent.Echo) + { + return; + } + else if (keyEvent.Pressed) + { + KeyDown(keyEventArgs); + } + else + { + KeyUp(keyEventArgs); + } + break; + + case Godot.InputEventMouseButton mouseButtonEvent: + if (mouseButtonEvent.ButtonIndex >= (int)Godot.ButtonList.WheelUp && mouseButtonEvent.ButtonIndex <= (int)Godot.ButtonList.WheelRight) + { + // Mouse wheel event. + var mouseWheelEventArgs = (MouseWheelEventArgs)mouseButtonEvent; + MouseWheel(mouseWheelEventArgs); + } + else + { + // Mouse button event. + var mouseButtonEventArgs = (MouseButtonEventArgs)mouseButtonEvent; + if (mouseButtonEvent.Pressed) + { + KeyDown((KeyEventArgs) mouseButtonEvent); + MouseDown(mouseButtonEventArgs); + } + else + { + KeyUp((KeyEventArgs)mouseButtonEvent); + MouseUp(mouseButtonEventArgs); + } + } + break; + + case Godot.InputEventMouseMotion mouseMotionEvent: + var mouseMoveEventArgs = (MouseMoveEventArgs)mouseMotionEvent; + MouseMove(mouseMoveEventArgs); + break; + } + } + + public override void PreInput(Godot.InputEvent inputEvent) + { + if (inputEvent is Godot.InputEventKey keyEvent) + { + var keyEventArgs = (KeyEventArgs)keyEvent; + if (keyEvent.Echo) + { + return; + } + else if (keyEvent.Pressed) + { + // TODO: these hacks are in right now for toggling the debug console. + // Somehow find a way to make the console use the key binds system? + _userInterfaceManager.PreKeyDown(keyEventArgs); + } + else + { + _userInterfaceManager.PreKeyUp(keyEventArgs); + } + } + } + + // TODO: This class is basically just a bunch of stubs. + private class GameTimingGodot : IGameTiming + { + private static readonly IStopwatch _realTimer = new Stopwatch(); + public readonly IStopwatch _tickRemainderTimer = new Stopwatch(); + + public GameTimingGodot() + { + _realTimer.Start(); + // Not sure if Restart() starts it implicitly so... + _tickRemainderTimer.Start(); + } + + public bool InSimulation { get; set; } + public bool Paused { get; set; } + + public TimeSpan CurTime => CalcCurTime(); + + public TimeSpan RealTime => _realTimer.Elapsed; + + public TimeSpan FrameTime => CalcFrameTime(); + + public TimeSpan RealFrameTime { get; set; } + + public TimeSpan RealFrameTimeAvg => throw new NotImplementedException(); + + public TimeSpan RealFrameTimeStdDev => throw new NotImplementedException(); + + public double FramesPerSecondAvg => throw new NotImplementedException(); + + public uint CurTick { get; set; } + public int TickRate + { + get => Godot.Engine.IterationsPerSecond; + set => Godot.Engine.IterationsPerSecond = value; + } + + public TimeSpan TickPeriod => TimeSpan.FromTicks((long)(1.0 / TickRate * TimeSpan.TicksPerSecond)); + + public TimeSpan TickRemainder { get; set; } + + public void ResetRealTime() + { + throw new NotImplementedException(); + } + + public void StartFrame() + { + throw new NotImplementedException(); + } + + private TimeSpan CalcCurTime() + { + // calculate simulation CurTime + var time = TimeSpan.FromTicks(TickPeriod.Ticks * CurTick); + + if (!InSimulation) // rendering can draw frames between ticks + return time + TickRemainder; + return time; + } + + private TimeSpan CalcFrameTime() + { + // calculate simulation FrameTime + if (InSimulation) + { + return TimeSpan.FromTicks(TickPeriod.Ticks); + } + else + { + return Paused ? TimeSpan.Zero : RealFrameTime; + } + } + } + } +} diff --git a/SS14.Client/GameController/GameController.Headless.cs b/SS14.Client/GameController/GameController.Headless.cs new file mode 100644 index 000000000..adca4fb6c --- /dev/null +++ b/SS14.Client/GameController/GameController.Headless.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using SS14.Client.Interfaces; +using SS14.Shared.Interfaces.Timing; +using SS14.Shared.IoC; +using SS14.Shared.Timing; + +namespace SS14.Client +{ + public partial class GameController + { + private GameLoop _mainLoop; + + [Dependency] private IGameTiming _gameTimingHeadless; + + public static void Main() + { +#if !X64 + throw new InvalidOperationException("The client cannot start outside x64."); +#endif + + IoCManager.Register(); + IoCManager.BuildGraph(); + + var gc = new GameController(); + gc.Startup(); + gc.MainLoop(); + } + + + private void MainLoop() + { + _mainLoop = new GameLoop(_gameTimingHeadless) + { + SleepMode = SleepMode.Delay + }; + + _mainLoop.Tick += (sender, args) => Update(args.DeltaSeconds); + + // set GameLoop.Running to false to return from this function. + _mainLoop.Run(); + } + } +} diff --git a/SS14.Client/GameController/GameController.Input.cs b/SS14.Client/GameController/GameController.Input.cs index ea5bdc63d..ecc90f1a9 100644 --- a/SS14.Client/GameController/GameController.Input.cs +++ b/SS14.Client/GameController/GameController.Input.cs @@ -1,5 +1,4 @@ -using Godot; -using SS14.Client.Input; +using SS14.Client.Input; namespace SS14.Client { @@ -10,7 +9,7 @@ namespace SS14.Client /// private void KeyDown(KeyEventArgs keyEvent) { - inputManager.KeyDown(keyEvent); + _inputManager.KeyDown(keyEvent); } /// @@ -18,7 +17,7 @@ namespace SS14.Client /// private void KeyUp(KeyEventArgs keyEvent) { - inputManager.KeyUp(keyEvent); + _inputManager.KeyUp(keyEvent); } /// @@ -54,80 +53,5 @@ namespace SS14.Client { _stateManager.MouseWheelMove(mouseWheelEventArgs); } - - // Override that converts and distributes the input events - // to the more sane methods above. - public override void Input(InputEvent inputEvent) - { - switch (inputEvent) - { - case InputEventKey keyEvent: - var keyEventArgs = (KeyEventArgs)keyEvent; - if (keyEvent.Echo) - { - return; - } - else if (keyEvent.Pressed) - { - KeyDown(keyEventArgs); - } - else - { - KeyUp(keyEventArgs); - } - break; - - case InputEventMouseButton mouseButtonEvent: - if (mouseButtonEvent.ButtonIndex >= (int)ButtonList.WheelUp && mouseButtonEvent.ButtonIndex <= (int)ButtonList.WheelRight) - { - // Mouse wheel event. - var mouseWheelEventArgs = (MouseWheelEventArgs)mouseButtonEvent; - MouseWheel(mouseWheelEventArgs); - } - else - { - // Mouse button event. - var mouseButtonEventArgs = (MouseButtonEventArgs)mouseButtonEvent; - if (mouseButtonEvent.Pressed) - { - KeyDown((KeyEventArgs) mouseButtonEvent); - MouseDown(mouseButtonEventArgs); - } - else - { - KeyUp((KeyEventArgs)mouseButtonEvent); - MouseUp(mouseButtonEventArgs); - } - } - break; - - case InputEventMouseMotion mouseMotionEvent: - var mouseMoveEventArgs = (MouseMoveEventArgs)mouseMotionEvent; - MouseMove(mouseMoveEventArgs); - break; - } - } - - public override void PreInput(InputEvent inputEvent) - { - if (inputEvent is InputEventKey keyEvent) - { - var keyEventArgs = (KeyEventArgs)keyEvent; - if (keyEvent.Echo) - { - return; - } - else if (keyEvent.Pressed) - { - // TODO: these hacks are in right now for toggling the debug console. - // Somehow find a way to make the console use the key binds system? - _userInterfaceManager.PreKeyDown(keyEventArgs); - } - else - { - _userInterfaceManager.PreKeyUp(keyEventArgs); - } - } - } } } diff --git a/SS14.Client/GameController/GameController.IoC.cs b/SS14.Client/GameController/GameController.IoC.cs index 0a4039bdf..b5b733d4e 100644 --- a/SS14.Client/GameController/GameController.IoC.cs +++ b/SS14.Client/GameController/GameController.IoC.cs @@ -57,19 +57,13 @@ using SS14.Client.Graphics.Overlays; using SS14.Client.ViewVariables; using SS14.Shared.Asynchronous; using SS14.Shared.Interfaces.Resources; +using SS14.Shared.Map; namespace SS14.Client { // Partial of GameController to initialize IoC and some other low-level systems like it. public sealed partial class GameController { - // Aaaaaah init order hurts. - private void PreInitIoC() - { - IoCManager.Register(); - IoCManager.BuildGraph(); - } - private void InitIoC() { RegisterIoC(); @@ -79,7 +73,7 @@ namespace SS14.Client // We are not IoC-managed (SS14.Client.Godot spawns us), but we still want the dependencies. IoCManager.InjectDependencies(this); - var proxy = (GameControllerProxy)IoCManager.Resolve(); + var proxy = (GameControllerProxy) IoCManager.Resolve(); proxy.GameController = this; } @@ -94,9 +88,18 @@ namespace SS14.Client IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); - IoCManager.Register(); + if (OnGodot) + { + IoCManager.Register(); + IoCManager.Register(); + } + else + { + IoCManager.Register(); + IoCManager.Register(); + + } IoCManager.Register(); - IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); @@ -104,6 +107,7 @@ namespace SS14.Client // Client stuff. IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); @@ -115,16 +119,32 @@ namespace SS14.Client IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); - IoCManager.Register(); + if (OnGodot) + { + IoCManager.Register(); + } + else + { + IoCManager.Register(); + } + IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); - IoCManager.Register(); - // Only GameController can acess this because the type is private so it's fine. - IoCManager.Register(); + if (OnGodot) + { + IoCManager.Register(); + // Only GameController can access this because the type is private so it's fine. + IoCManager.Register(); + } + else + { + IoCManager.Register(); + } + IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); diff --git a/SS14.Client/GameObjects/Components/Eye/EyeComponent.cs b/SS14.Client/GameObjects/Components/Eye/EyeComponent.cs index b0be1be3b..89ce57a33 100644 --- a/SS14.Client/GameObjects/Components/Eye/EyeComponent.cs +++ b/SS14.Client/GameObjects/Components/Eye/EyeComponent.cs @@ -16,6 +16,7 @@ namespace SS14.Client.GameObjects // Horrible hack to get around ordering issues. private bool setCurrentOnInitialize = false; private Vector2 setZoomOnInitialize = Vector2.One; + [ViewVariables(VVAccess.ReadWrite)] public bool Current { @@ -27,6 +28,7 @@ namespace SS14.Client.GameObjects setCurrentOnInitialize = value; return; } + eye.Current = value; } } @@ -53,21 +55,29 @@ namespace SS14.Client.GameObjects public override void Initialize() { base.Initialize(); - transform = Owner.GetComponent(); - eye = new Eye + + if (GameController.OnGodot) { - Current = setCurrentOnInitialize, - MapId = transform.MapID, - Zoom = setZoomOnInitialize, - }; - transform.SceneNode.AddChild(eye.GodotCamera); - transform.OnMove += Transform_OnMove; + transform = Owner.GetComponent(); + eye = new Eye + { + Current = setCurrentOnInitialize, + MapId = transform.MapID, + Zoom = setZoomOnInitialize, + }; + transform.SceneNode.AddChild(eye.GodotCamera); + transform.OnMove += Transform_OnMove; + } } public override void OnRemove() { base.OnRemove(); - transform.OnMove -= Transform_OnMove; + if (GameController.OnGodot) + { + transform.OnMove -= Transform_OnMove; + } + eye.Dispose(); eye = null; } diff --git a/SS14.Client/GameObjects/Components/Light/PointLightComponent.cs b/SS14.Client/GameObjects/Components/Light/PointLightComponent.cs index d97ff5364..7c5187b1e 100644 --- a/SS14.Client/GameObjects/Components/Light/PointLightComponent.cs +++ b/SS14.Client/GameObjects/Components/Light/PointLightComponent.cs @@ -28,8 +28,7 @@ namespace SS14.Client.GameObjects public override Type StateType => typeof(PointLightComponentState); private ILight Light; - [Dependency] - private ILightManager lightManager; + [Dependency] private ILightManager lightManager; [ViewVariables(VVAccess.ReadWrite)] public Color Color @@ -46,6 +45,7 @@ namespace SS14.Client.GameObjects } private LightState state = LightState.On; + [ViewVariables(VVAccess.ReadWrite)] public LightState State { @@ -91,13 +91,23 @@ namespace SS14.Client.GameObjects if (value) { if (Owner.Transform.Parent == null) return; - Light.ParentTo((GodotTransformComponent) Owner.Transform.Parent); + + if (GameController.OnGodot) + { + Light.ParentTo((GodotTransformComponent) Owner.Transform.Parent); + } + _lightOnParent = true; } else { if (!_lightOnParent) return; - Light.ParentTo((GodotTransformComponent) Owner.Transform); + + if (GameController.OnGodot) + { + Light.ParentTo((GodotTransformComponent) Owner.Transform); + } + _lightOnParent = false; } } @@ -118,9 +128,16 @@ namespace SS14.Client.GameObjects { radius = FloatMath.Clamp(value, 2, 10); var mgr = IoCManager.Resolve(); - var tex = mgr.GetResource(new ResourcePath("/Textures/Effects/Light/") / $"lighting_falloff_{(int)radius}.png"); - // TODO: Maybe editing the global texture resource is not a good idea. - tex.Texture.GodotTexture.SetFlags(tex.Texture.GodotTexture.GetFlags() | (int)Godot.Texture.FlagsEnum.Filter); + var tex = mgr.GetResource(new ResourcePath("/Textures/Effects/Light/") / + $"lighting_falloff_{(int) radius}.png"); + + if (GameController.OnGodot) + { + // TODO: Maybe editing the global texture resource is not a good idea. + tex.Texture.GodotTexture.SetFlags(tex.Texture.GodotTexture.GetFlags() | + (int) Godot.Texture.FlagsEnum.Filter); + } + Light.Texture = tex.Texture; } } @@ -129,7 +146,11 @@ namespace SS14.Client.GameObjects { base.Initialize(); - Light.ParentTo((GodotTransformComponent)Owner.Transform); + if (GameController.OnGodot) + { + Light.ParentTo((GodotTransformComponent) Owner.Transform); + } + Owner.Transform.OnParentChanged += TransformOnOnParentChanged; } @@ -143,12 +164,20 @@ namespace SS14.Client.GameObjects if (obj.New.IsValid() && Owner.EntityManager.TryGetEntity(obj.New, out var entity)) { - Light.ParentTo((GodotTransformComponent) entity.Transform); + if (GameController.OnGodot) + { + Light.ParentTo((GodotTransformComponent) entity.Transform); + } + _lightOnParent = true; } else { - Light.ParentTo((GodotTransformComponent) Owner.Transform); + if (GameController.OnGodot) + { + Light.ParentTo((GodotTransformComponent) Owner.Transform); + } + _lightOnParent = false; } } @@ -183,7 +212,7 @@ namespace SS14.Client.GameObjects /// public override void HandleComponentState(ComponentState state) { - var newState = (PointLightComponentState)state; + var newState = (PointLightComponentState) state; State = newState.State; Color = newState.Color; Light.ModeClass = newState.Mode; diff --git a/SS14.Client/GameObjects/Components/Occluder/OccluderComponent.cs b/SS14.Client/GameObjects/Components/Occluder/OccluderComponent.cs index a40342560..76ea45f93 100644 --- a/SS14.Client/GameObjects/Components/Occluder/OccluderComponent.cs +++ b/SS14.Client/GameObjects/Components/Occluder/OccluderComponent.cs @@ -48,41 +48,41 @@ namespace SS14.Client.GameObjects base.Initialize(); IoCManager.InjectDependencies(this); - var transform = Owner.GetComponent(); + var transform = Owner.Transform; SnapGrid = Owner.GetComponent(); SnapGrid.OnPositionChanged += SnapGridPositionChanged; const float halfSize = (-SideSize / 2) * EyeManager.PIXELSPERMETER; - var ne = new Godot.Vector2(halfSize, -halfSize); - var se = new Godot.Vector2(halfSize, halfSize); - var sw = new Godot.Vector2(-halfSize, halfSize); - var nw = new Godot.Vector2(-halfSize, -halfSize); + var ne = new Vector2(halfSize, -halfSize); + var se = new Vector2(halfSize, halfSize); + var sw = new Vector2(-halfSize, halfSize); + var nw = new Vector2(-halfSize, -halfSize); // North occluder. var occluder = lightManager.MakeOccluder(); occluder.CullMode = OccluderCullMode.Clockwise; - occluder.SetGodotPolygon(new Godot.Vector2[] { nw, ne }); + occluder.SetPolygon(new Vector2[] { nw, ne }); occluders[(int)OccluderDir.North] = occluder; occluder.ParentTo(transform); // East occluder. occluder = lightManager.MakeOccluder(); occluder.CullMode = OccluderCullMode.Clockwise; - occluder.SetGodotPolygon(new Godot.Vector2[] { ne, se }); + occluder.SetPolygon(new Vector2[] { ne, se }); occluders[(int)OccluderDir.East] = occluder; occluder.ParentTo(transform); // South occluder. occluder = lightManager.MakeOccluder(); occluder.CullMode = OccluderCullMode.Clockwise; - occluder.SetGodotPolygon(new Godot.Vector2[] { se, sw }); + occluder.SetPolygon(new Vector2[] { se, sw }); occluders[(int)OccluderDir.South] = occluder; occluder.ParentTo(transform); // West occluder. occluder = lightManager.MakeOccluder(); occluder.CullMode = OccluderCullMode.Clockwise; - occluder.SetGodotPolygon(new Godot.Vector2[] { sw, nw }); + occluder.SetPolygon(new Vector2[] { sw, nw }); occluders[(int)OccluderDir.West] = occluder; occluder.ParentTo(transform); diff --git a/SS14.Client/GameObjects/Components/Renderable/SpriteComponent.cs b/SS14.Client/GameObjects/Components/Renderable/SpriteComponent.cs index 7e401c187..a02f286ec 100644 --- a/SS14.Client/GameObjects/Components/Renderable/SpriteComponent.cs +++ b/SS14.Client/GameObjects/Components/Renderable/SpriteComponent.cs @@ -63,7 +63,8 @@ namespace SS14.Client.GameObjects set { drawDepth = value; - if (SceneNode != null) + + if (GameController.OnGodot && SceneNode != null) { SceneNode.ZIndex = (int) value; } @@ -82,7 +83,7 @@ namespace SS14.Client.GameObjects set { scale = value; - if (SceneNode != null) + if (GameController.OnGodot && SceneNode != null) { SceneNode.Scale = value.Convert(); } @@ -98,7 +99,7 @@ namespace SS14.Client.GameObjects set { rotation = value; - if (SceneNode != null) + if (GameController.OnGodot && SceneNode != null) { SceneNode.Rotation = (float) value; } @@ -117,7 +118,7 @@ namespace SS14.Client.GameObjects set { offset = value; - if (SceneNode != null) + if (GameController.OnGodot && SceneNode != null) { SceneNode.Position = value.Convert() * EyeManager.PIXELSPERMETER; } @@ -133,7 +134,7 @@ namespace SS14.Client.GameObjects set { color = value; - if (SceneNode != null) + if (GameController.OnGodot && SceneNode != null) { SceneNode.Modulate = value.Convert(); } @@ -198,10 +199,8 @@ namespace SS14.Client.GameObjects } } - [ViewVariables] - private Dictionary LayerMap = new Dictionary(); - [ViewVariables] - private bool _layerMapShared; + [ViewVariables] private Dictionary LayerMap = new Dictionary(); + [ViewVariables] private bool _layerMapShared; // To a future Clusterfack: // REALLY BIG OPTIMIZATION POTENTIAL: @@ -211,8 +210,7 @@ namespace SS14.Client.GameObjects // It may be a good idea to re-implement this list to use Layer[], // use ref locals EVERYWHERE, and handle the resizing ourselves. // This may be worth the overhead of basically reimplementing List. - [ViewVariables] - private List Layers; + [ViewVariables] private List Layers; private Godot.Node2D SceneNode; @@ -996,9 +994,17 @@ namespace SS14.Client.GameObjects public ISpriteProxy CreateProxy() { - var item = VS.CanvasItemCreate(); - RedrawQueued = true; - return CreateMirror(item); + if (GameController.OnGodot) + { + var item = VS.CanvasItemCreate(); + RedrawQueued = true; + return CreateMirror(item); + } + + var key = NextMirrorKey++; + var mirror = new SpriteMirror(key, this); + Mirrors.Add(key, new MirrorData()); + return mirror; } ISpriteProxy CreateMirror(Godot.RID item) @@ -1018,15 +1024,19 @@ namespace SS14.Client.GameObjects public override void OnAdd() { base.OnAdd(); - SceneNode = new Godot.Node2D() + + if (GameController.OnGodot) { - Name = "Sprite", - ZIndex = (int) drawDepth, - Scale = scale.Convert(), - Position = offset.Convert(), - Modulate = color.Convert(), - Rotation = (float) rotation, - }; + SceneNode = new Godot.Node2D() + { + Name = "Sprite", + ZIndex = (int) drawDepth, + Scale = scale.Convert(), + Position = offset.Convert(), + Modulate = color.Convert(), + Rotation = (float) rotation, + }; + } } public override void OnRemove() @@ -1039,13 +1049,22 @@ namespace SS14.Client.GameObjects } MainMirror.Dispose(); - SceneNode.QueueFree(); + + if (GameController.OnGodot) + { + SceneNode.QueueFree(); + } } public override void Initialize() { base.Initialize(); + if (!GameController.OnGodot) + { + return; + } + MainMirror = CreateMirror(SceneNode.GetCanvasItem()); var mir = Mirrors[0]; mir.DontFree = true; @@ -1055,6 +1074,11 @@ namespace SS14.Client.GameObjects private void ClearDraw() { + if (!GameController.OnGodot) + { + return; + } + foreach (var data in Mirrors.Values) { foreach (var item in data.Children) @@ -1070,6 +1094,11 @@ namespace SS14.Client.GameObjects { ClearDraw(); + if (!GameController.OnGodot) + { + return; + } + foreach (var data in Mirrors.Values) { if (!data.Visible) @@ -1301,7 +1330,11 @@ namespace SS14.Client.GameObjects var dirChanged = false; if (Directional) { - SceneNode.Rotation = (float) (Owner.Transform.WorldRotation - Rotation) - MathHelper.PiOver2; + if (GameController.OnGodot) + { + SceneNode.Rotation = (float) (Owner.Transform.WorldRotation - Rotation) - MathHelper.PiOver2; + } + dirWeAreFacing = GetDir(); if (LastDir != dirWeAreFacing || _recalcDirections) { @@ -1556,7 +1589,7 @@ namespace SS14.Client.GameObjects // TODO: Doing a full redraw when a mirror is disposed is kinda a waste. ClearDraw(); RedrawQueued = true; - if (!val.DontFree) + if (!val.DontFree && GameController.OnGodot) { VS.FreeRid(val.Root); } @@ -1633,8 +1666,7 @@ namespace SS14.Client.GameObjects { readonly int Key; readonly SpriteComponent Master; - Godot.RID CanvasItem; - + private Godot.RID CanvasItem; private Godot.RID Parent; private Vector2 _offset; @@ -1661,16 +1693,20 @@ namespace SS14.Client.GameObjects } } - public SpriteMirror(int key, SpriteComponent master, Godot.RID canvasItem) + public SpriteMirror(int key, SpriteComponent master, Godot.RID canvasItem) : this(key, master) { - Master = master; - Key = key; CanvasItem = canvasItem; } - public bool Disposed => CanvasItem == null; + public SpriteMirror(int key, SpriteComponent master) + { + Master = master; + Key = key; + } - void CheckDisposed() + public bool Disposed { get; private set; } + + private void CheckDisposed() { if (Disposed) { @@ -1680,6 +1716,11 @@ namespace SS14.Client.GameObjects private void UpdateTransform() { + if (!GameController.OnGodot) + { + return; + } + var transform = new Godot.Transform2D(0, Offset.Convert()); VS.CanvasItemSetTransform(CanvasItem, transform); } @@ -1710,7 +1751,13 @@ namespace SS14.Client.GameObjects void Dispose(bool disposing) { Master.DisposeMirror(Key); - CanvasItem = null; + + if (GameController.OnGodot) + { + CanvasItem = null; + } + + Disposed = true; } } diff --git a/SS14.Client/GameObjects/EntitySystems/AudioSystem.cs b/SS14.Client/GameObjects/EntitySystems/AudioSystem.cs index c3241cbef..fdc400267 100644 --- a/SS14.Client/GameObjects/EntitySystems/AudioSystem.cs +++ b/SS14.Client/GameObjects/EntitySystems/AudioSystem.cs @@ -60,6 +60,10 @@ namespace SS14.Client.GameObjects.EntitySystems /// The audio stream to play. public void Play(AudioStream stream, AudioParams? audioParams = null) { + if (!GameController.OnGodot) + { + return; + } var player = new Godot.AudioStreamPlayer() { Stream = stream.GodotAudioStream, @@ -94,6 +98,10 @@ namespace SS14.Client.GameObjects.EntitySystems /// The entity "emitting" the audio. public void Play(AudioStream stream, IEntity entity, AudioParams? audioParams = null) { + if (!GameController.OnGodot) + { + return; + } var parent = entity.GetComponent().SceneNode; var player = new Godot.AudioStreamPlayer2D() { @@ -130,6 +138,10 @@ namespace SS14.Client.GameObjects.EntitySystems /// The coordinates at which to play the audio. public void Play(AudioStream stream, GridCoordinates coordinates, AudioParams? audioParams = null) { + if (!GameController.OnGodot) + { + return; + } var player = new Godot.AudioStreamPlayer2D() { Stream = stream.GodotAudioStream, diff --git a/SS14.Client/GameObjects/EntitySystems/EffectSystem.cs b/SS14.Client/GameObjects/EntitySystems/EffectSystem.cs index 7a5ec09a9..427302416 100644 --- a/SS14.Client/GameObjects/EntitySystems/EffectSystem.cs +++ b/SS14.Client/GameObjects/EntitySystems/EffectSystem.cs @@ -48,6 +48,10 @@ namespace SS14.Client.GameObjects { base.Initialize(); IoCManager.InjectDependencies(this); + if (!GameController.OnGodot) + { + return; + } DrawingNode = new Godot.Node2D() { Name = "EffectSystem", @@ -73,6 +77,10 @@ namespace SS14.Client.GameObjects public override void Shutdown() { base.Shutdown(); + if (!GameController.OnGodot) + { + return; + } VS.FreeRid(ShadedCanvasItem); VS.FreeRid(UnshadedCanvasItem); UnshadedMaterial.Dispose(); @@ -153,6 +161,10 @@ namespace SS14.Client.GameObjects { var map = eyeManager.CurrentMap; + if (GameController.OnGodot) + { + return; + } VS.CanvasItemClear(ShadedCanvasItem); VS.CanvasItemClear(UnshadedCanvasItem); using (var shadedHandle = new DrawingHandleScreen(ShadedCanvasItem)) diff --git a/SS14.Client/Graphics/ClientEye/Eye.cs b/SS14.Client/Graphics/ClientEye/Eye.cs index 961a02e0b..cdb4e964b 100644 --- a/SS14.Client/Graphics/ClientEye/Eye.cs +++ b/SS14.Client/Graphics/ClientEye/Eye.cs @@ -12,6 +12,7 @@ namespace SS14.Client.Graphics.ClientEye protected IEyeManager eyeManager; public Godot.Camera2D GodotCamera { get; private set; } private bool disposed = false; + public bool Current { get => eyeManager.CurrentEye == this; @@ -34,23 +35,31 @@ namespace SS14.Client.Graphics.ClientEye } - public Vector2 Zoom { - get => GodotCamera.Zoom.Convert(); - set => GodotCamera.Zoom = value.Convert(); + get => GameController.OnGodot ? GodotCamera.Zoom.Convert() : default; + set + { + if (GameController.OnGodot) + { + GodotCamera.Zoom = value.Convert(); + } + } } public MapId MapId { get; set; } = MapId.Nullspace; public Eye() { - GodotCamera = new Godot.Camera2D() - { - DragMarginHEnabled = false, - DragMarginVEnabled = false, - }; eyeManager = IoCManager.Resolve(); + if (GameController.OnGodot) + { + GodotCamera = new Godot.Camera2D() + { + DragMarginHEnabled = false, + DragMarginVEnabled = false, + }; + } } protected virtual void Dispose(bool disposing) @@ -63,6 +72,10 @@ namespace SS14.Client.Graphics.ClientEye eyeManager = null; } + if (!GameController.OnGodot) + { + return; + } GodotCamera.QueueFree(); GodotCamera.Dispose(); GodotCamera = null; @@ -74,6 +87,7 @@ namespace SS14.Client.Graphics.ClientEye { return; } + Dispose(true); GC.SuppressFinalize(this); } diff --git a/SS14.Client/Graphics/ClientEye/EyeManager.cs b/SS14.Client/Graphics/ClientEye/EyeManager.cs index 85f5c0dbd..0e87fb8f0 100644 --- a/SS14.Client/Graphics/ClientEye/EyeManager.cs +++ b/SS14.Client/Graphics/ClientEye/EyeManager.cs @@ -33,7 +33,11 @@ namespace SS14.Client.Graphics.ClientEye return; } - currentEye.GodotCamera.Current = false; + if (GameController.OnGodot) + { + currentEye.GodotCamera.Current = false; + } + if (value != null) { currentEye = value; @@ -43,7 +47,10 @@ namespace SS14.Client.Graphics.ClientEye currentEye = defaultEye; } - currentEye.GodotCamera.Current = true; + if (GameController.OnGodot) + { + currentEye.GodotCamera.Current = true; + } } } @@ -51,6 +58,11 @@ namespace SS14.Client.Graphics.ClientEye public Box2 GetWorldViewport() { + if (!GameController.OnGodot) + { + return default; + } + var vpSize = sceneTree.SceneTree.Root.Size.Convert(); var topLeft = ScreenToWorld(Vector2.Zero); @@ -70,7 +82,11 @@ namespace SS14.Client.Graphics.ClientEye { defaultEye = new FixedEye(); currentEye = defaultEye; - currentEye.GodotCamera.Current = true; + + if (GameController.OnGodot) + { + currentEye.GodotCamera.Current = true; + } } public void Dispose() @@ -80,6 +96,10 @@ namespace SS14.Client.Graphics.ClientEye public Vector2 WorldToScreen(Vector2 point) { + if (!GameController.OnGodot) + { + return default; + } var transform = sceneTree.WorldRoot.GetViewportTransform(); return transform.Xform(point.Convert() * PIXELSPERMETER * new Godot.Vector2(1, -1)).Convert(); } @@ -96,6 +116,10 @@ namespace SS14.Client.Graphics.ClientEye public GridCoordinates ScreenToWorld(Vector2 point) { + if (!GameController.OnGodot) + { + return default; + } var matrix = Matrix3.Invert(MatrixViewPortTransform(sceneTree)); var worldPos = matrix.Transform(point) / PIXELSPERMETER * new Vector2(1, -1); IMapGrid grid ; diff --git a/SS14.Client/Graphics/ClientEye/FixedEye.cs b/SS14.Client/Graphics/ClientEye/FixedEye.cs index e470e3217..fbf68c351 100644 --- a/SS14.Client/Graphics/ClientEye/FixedEye.cs +++ b/SS14.Client/Graphics/ClientEye/FixedEye.cs @@ -11,12 +11,17 @@ namespace SS14.Client.Graphics.ClientEye public class FixedEye : Eye { private Vector2 position; + public Vector2 Position { get => position; set { - GodotCamera.Position = value.Convert(); + if (GameController.OnGodot) + { + GodotCamera.Position = value.Convert(); + } + position = value; } } @@ -25,6 +30,11 @@ namespace SS14.Client.Graphics.ClientEye public FixedEye() { + if (!GameController.OnGodot) + { + return; + } + sceneTree = IoCManager.Resolve(); sceneTree.WorldRoot.AddChild(GodotCamera); } diff --git a/SS14.Client/Graphics/DisplayManager.cs b/SS14.Client/Graphics/DisplayManager.cs index 96818c295..92696dbce 100644 --- a/SS14.Client/Graphics/DisplayManager.cs +++ b/SS14.Client/Graphics/DisplayManager.cs @@ -1,4 +1,5 @@ using System; +using SS14.Client.Interfaces; using SS14.Client.Interfaces.Graphics; using SS14.Client.Utility; using SS14.Shared.Configuration; @@ -21,8 +22,7 @@ namespace SS14.Client.Graphics /// public class DisplayManager : IDisplayManager, IPostInjectInit { - [Dependency] - readonly IConfigurationManager configurationManager; + [Dependency] readonly IConfigurationManager configurationManager; public WindowMode WindowMode { get; private set; } = WindowMode.Windowed; public bool VSync { get; private set; } = false; @@ -30,7 +30,15 @@ namespace SS14.Client.Graphics void IPostInjectInit.PostInject() { configurationManager.RegisterCVar("display.vsync", VSync, CVar.ARCHIVE); - configurationManager.RegisterCVar("display.windowmode", (int)WindowMode, CVar.ARCHIVE); + configurationManager.RegisterCVar("display.windowmode", (int) WindowMode, CVar.ARCHIVE); + } + + public void SetWindowTitle(string title) + { + if (GameController.OnGodot) + { + Godot.OS.SetWindowTitle(title); + } } public void Initialize() @@ -40,11 +48,14 @@ namespace SS14.Client.Graphics public void ReadConfig() { - WindowMode = (WindowMode)configurationManager.GetCVar("display.windowmode"); + WindowMode = (WindowMode) configurationManager.GetCVar("display.windowmode"); VSync = configurationManager.GetCVar("display.vsync"); - Godot.OS.VsyncEnabled = VSync; - Godot.OS.WindowFullscreen = WindowMode == WindowMode.Fullscreen; + if (GameController.OnGodot) + { + Godot.OS.VsyncEnabled = VSync; + Godot.OS.WindowFullscreen = WindowMode == WindowMode.Fullscreen; + } } } } diff --git a/SS14.Client/Graphics/Drawing/DrawingHandle.cs b/SS14.Client/Graphics/Drawing/DrawingHandle.cs index 3860dcb93..3b095e3b7 100644 --- a/SS14.Client/Graphics/Drawing/DrawingHandle.cs +++ b/SS14.Client/Graphics/Drawing/DrawingHandle.cs @@ -13,20 +13,31 @@ namespace SS14.Client.Graphics.Drawing { // Use RIDs in the theoretical case some nerd wants to draw something WITHOUT consulting the scene tree. // Also it's probably faster or some shit. - internal Godot.RID Item { get; private set; } + + internal Godot.RID Item { get; } + public bool Disposed { get; private set; } internal DrawingHandle(Godot.RID item) { Item = item ?? throw new ArgumentNullException(nameof(item)); } + internal DrawingHandle() + { + } + public void Dispose() { - Item = null; + Disposed = true; } public void SetTransform(Vector2 position, Angle rotation, Vector2 scale) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); var transform = Godot.Transform2D.Identity.Rotated((float) rotation.Theta).Scaled(scale.Convert()); SetTransform2DRotationAndScale(ref transform, rotation.Theta, scale); @@ -36,6 +47,11 @@ namespace SS14.Client.Graphics.Drawing public void SetTransform(Matrix3 matrix) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); VS.CanvasItemAddSetTransform(Item, matrix.Convert()); } @@ -49,7 +65,7 @@ namespace SS14.Client.Graphics.Drawing protected void CheckDisposed() { - if (Item == null) + if (Disposed) { throw new ObjectDisposedException(nameof(DrawingHandle)); } @@ -72,14 +88,28 @@ namespace SS14.Client.Graphics.Drawing { } + internal DrawingHandleWorld() : base() + { + } + public override void DrawCircle(Vector2 position, float radius, Color color) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); VS.CanvasItemAddCircle(Item, ToPixelCoords(position), radius * PPM, color.Convert()); } public override void DrawLine(Vector2 from, Vector2 to, Color color, float width = 1, bool antiAliased = false) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); VS.CanvasItemAddLine(Item, ToPixelCoords(from), ToPixelCoords(to), color.Convert(), width, antiAliased); } @@ -87,6 +117,11 @@ namespace SS14.Client.Graphics.Drawing public override void DrawTexture(Texture texture, Vector2 position, Color? modulate = null, Texture normalMap = null) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); texture.GodotTexture.Draw(Item, ToPixelCoords(position), modulate?.Convert(), false, normalMap); } @@ -94,12 +129,22 @@ namespace SS14.Client.Graphics.Drawing public void DrawTextureRect(Texture texture, Box2 rect, bool tile, Color? modulate = null, bool transpose = false, Texture normalMap = null) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); texture.GodotTexture.DrawRect(Item, ToPixelCoords(rect), tile, modulate?.Convert(), transpose, normalMap); } public void DrawRect(Box2 rect, Color color, bool filled = true) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); if (filled) { @@ -116,6 +161,11 @@ namespace SS14.Client.Graphics.Drawing public void DrawStyleBox(StyleBox styleBox, UIBox2 box) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); styleBox.GodotStyleBox.Draw(Item, box.Convert()); } @@ -137,26 +187,51 @@ namespace SS14.Client.Graphics.Drawing { } + internal DrawingHandleScreen() : base() + { + } + + public override void DrawCircle(Vector2 position, float radius, Color color) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); VS.CanvasItemAddCircle(Item, position.Convert(), radius, color.Convert()); } public void DrawStyleBox(StyleBox styleBox, UIBox2 box) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); styleBox.GodotStyleBox.Draw(Item, box.Convert()); } public override void DrawLine(Vector2 from, Vector2 to, Color color, float width = 1, bool antiAliased = false) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); VS.CanvasItemAddLine(Item, from.Convert(), to.Convert(), color.Convert(), width, antiAliased); } public void DrawRect(UIBox2 rect, Color color, bool filled = true) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); if (filled) { @@ -174,6 +249,11 @@ namespace SS14.Client.Graphics.Drawing public override void DrawTexture(Texture texture, Vector2 position, Color? modulate = null, Texture normalMap = null) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); texture.GodotTexture.Draw(Item, position.Convert(), modulate?.Convert(), false, normalMap); } @@ -181,6 +261,11 @@ namespace SS14.Client.Graphics.Drawing public void DrawTextureRect(Texture texture, UIBox2 rect, bool tile, Color? modulate = null, bool transpose = false, Texture normalMap = null) { + if (!GameController.OnGodot) + { + return; + } + CheckDisposed(); texture.GodotTexture.DrawRect(Item, rect.Convert(), tile, modulate?.Convert(), transpose, normalMap); } diff --git a/SS14.Client/Graphics/Drawing/StyleBox.cs b/SS14.Client/Graphics/Drawing/StyleBox.cs index 11c065f3e..d0cb226b6 100644 --- a/SS14.Client/Graphics/Drawing/StyleBox.cs +++ b/SS14.Client/Graphics/Drawing/StyleBox.cs @@ -42,11 +42,16 @@ namespace SS14.Client.Graphics.Drawing public class StyleBoxTexture : StyleBox { private readonly Godot.StyleBoxTexture stylebox; - internal override Godot.StyleBox GodotStyleBox => stylebox; + public StyleBoxTexture() { + if (!GameController.OnGodot) + { + return; + } + stylebox = new Godot.StyleBoxTexture(); } @@ -65,43 +70,85 @@ namespace SS14.Client.Graphics.Drawing public float MarginLeft { - get => stylebox.MarginLeft; - set => stylebox.MarginLeft = value; + get => GameController.OnGodot ? stylebox.MarginLeft : default; + set + { + if (GameController.OnGodot) + { + stylebox.MarginLeft = value; + } + } } public float MarginRight { - get => stylebox.MarginRight; - set => stylebox.MarginRight = value; + get => GameController.OnGodot ? stylebox.MarginRight : default; + set + { + if (GameController.OnGodot) + { + stylebox.MarginRight = value; + } + } } public float MarginTop { - get => stylebox.MarginTop; - set => stylebox.MarginTop = value; + get => GameController.OnGodot ? stylebox.MarginTop : default; + set + { + if (GameController.OnGodot) + { + stylebox.MarginTop = value; + } + } } public float MarginBottom { - get => stylebox.MarginBottom; - set => stylebox.MarginBottom = value; + get => GameController.OnGodot ? stylebox.MarginBottom : default; + set + { + if (GameController.OnGodot) + { + stylebox.MarginBottom = value; + } + } } public Color Modulate { - get => stylebox.ModulateColor.Convert(); - set => stylebox.ModulateColor = value.Convert(); + get => GameController.OnGodot ? stylebox.ModulateColor.Convert() : default; + set + { + if (GameController.OnGodot) + { + stylebox.ModulateColor = value.Convert(); + } + } } private Texture cachedTexture; + public Texture Texture { get { - return cachedTexture ?? new GodotTextureSource((Godot.Texture)stylebox.Texture); + if (!GameController.OnGodot) + { + return null; + } + + return cachedTexture ?? new GodotTextureSource((Godot.Texture) stylebox.Texture); } // Woo implicit casts. - set => stylebox.Texture = cachedTexture = value; + set + { + if (GameController.OnGodot) + { + stylebox.Texture = cachedTexture = value; + } + } } /// @@ -135,8 +182,14 @@ namespace SS14.Client.Graphics.Drawing { public Color BackgroundColor { - get => stylebox.BgColor.Convert(); - set => stylebox.BgColor = value.Convert(); + get => GameController.OnGodot ? stylebox.BgColor.Convert() : default; + set + { + if (GameController.OnGodot) + { + stylebox.BgColor = value.Convert(); + } + } } private readonly Godot.StyleBoxFlat stylebox; @@ -145,31 +198,58 @@ namespace SS14.Client.Graphics.Drawing public StyleBoxFlat() { - stylebox = new Godot.StyleBoxFlat(); + if (GameController.OnGodot) + { + stylebox = new Godot.StyleBoxFlat(); + } } public float MarginLeft { - get => stylebox.ContentMarginLeft; - set => stylebox.ContentMarginLeft = value; + get => GameController.OnGodot ? stylebox.ContentMarginLeft : default; + set + { + if (GameController.OnGodot) + { + stylebox.ContentMarginLeft = value; + } + } } public float MarginRight { - get => stylebox.ContentMarginRight; - set => stylebox.ContentMarginRight = value; + get => GameController.OnGodot ? stylebox.ContentMarginRight : default; + set + { + if (GameController.OnGodot) + { + stylebox.ContentMarginRight = value; + } + } } public float MarginTop { - get => stylebox.ContentMarginTop; - set => stylebox.ContentMarginTop = value; + get => GameController.OnGodot ? stylebox.ContentMarginTop : default; + set + { + if (GameController.OnGodot) + { + stylebox.ContentMarginTop = value; + } + } } public float MarginBottom { - get => stylebox.ContentMarginBottom; - set => stylebox.ContentMarginBottom = value; + get => GameController.OnGodot ? stylebox.ContentMarginBottom : default; + set + { + if (GameController.OnGodot) + { + stylebox.ContentMarginBottom = value; + } + } } diff --git a/SS14.Client/Graphics/Font.cs b/SS14.Client/Graphics/Font.cs index 0ab48385a..80986313f 100644 --- a/SS14.Client/Graphics/Font.cs +++ b/SS14.Client/Graphics/Font.cs @@ -1,4 +1,5 @@ -using SS14.Client.ResourceManagement; +using System; +using SS14.Client.ResourceManagement; namespace SS14.Client.Graphics { @@ -21,28 +22,107 @@ namespace SS14.Client.Graphics /// public class VectorFont : Font { - public int ExtraSpacingTop { get => _font.ExtraSpacingTop; set => _font.ExtraSpacingTop = value; } - public int ExtraSpacingBottom { get => _font.ExtraSpacingBottom; set => _font.ExtraSpacingBottom = value; } - public int ExtraSpacingChar { get => _font.ExtraSpacingChar; set => _font.ExtraSpacingChar = value; } - public int ExtraSpacingSpace { get => _font.ExtraSpacingSpace; set => _font.ExtraSpacingSpace = value; } + public int ExtraSpacingTop + { + get => GameController.OnGodot ? _font.ExtraSpacingTop : default; + set + { + if (GameController.OnGodot) + { + _font.ExtraSpacingTop = value; + } + } + } - public int Size { get => _font.Size; set => _font.Size = value; } - public bool UseFilter { get => _font.UseFilter; set => _font.UseFilter = value; } - public bool UseMipmaps { get => _font.UseMipmaps; set => _font.UseMipmaps = value; } + public int ExtraSpacingBottom + { + get => GameController.OnGodot ? _font.ExtraSpacingBottom : default; + set + { + if (GameController.OnGodot) + { + _font.ExtraSpacingBottom = value; + } + } + } + + public int ExtraSpacingChar + { + get => GameController.OnGodot ? _font.ExtraSpacingChar : default; + set + { + if (GameController.OnGodot) + { + _font.ExtraSpacingChar = value; + } + } + } + + public int ExtraSpacingSpace + { + get => GameController.OnGodot ? _font.ExtraSpacingSpace : default; + set + { + if (GameController.OnGodot) + { + _font.ExtraSpacingSpace = value; + } + } + } + + public int Size + { + get => _font.Size; + set + { + if (GameController.OnGodot) + { + _font.Size = value; + } + } + } + + public bool UseFilter + { + get => _font.UseFilter; + set + { + if (GameController.OnGodot) + { + _font.UseFilter = value; + } + } + } + + public bool UseMipmaps + { + get => _font.UseMipmaps; + set + { + if (GameController.OnGodot) + { + _font.UseMipmaps = value; + } + } + } internal override Godot.Font GodotFont => _font; private readonly Godot.DynamicFont _font; - public VectorFont(FontResource res) : this(res.FontData) + public VectorFont(FontResource res) + : this(res.FontData) { } internal VectorFont(Godot.DynamicFontData data) { - _font = new Godot.DynamicFont + if (GameController.OnGodot) { - FontData = data, - }; + _font = new Godot.DynamicFont + { + FontData = data, + }; + } } } diff --git a/SS14.Client/Graphics/Lighting/LightManager.Light.cs b/SS14.Client/Graphics/Lighting/LightManager.Light.cs index 19298f632..3c4a2f2cc 100644 --- a/SS14.Client/Graphics/Lighting/LightManager.Light.cs +++ b/SS14.Client/Graphics/Lighting/LightManager.Light.cs @@ -5,6 +5,7 @@ using SS14.Shared; using SS14.Shared.Maths; using System; using SS14.Shared.Enums; +using SS14.Shared.Interfaces.GameObjects.Components; namespace SS14.Client.Graphics.Lighting { @@ -14,17 +15,30 @@ namespace SS14.Client.Graphics.Lighting { public Vector2 Offset { - get => Light2D.Offset.Convert(); - set => Light2D.Offset = value.Convert(); + get => GameController.OnGodot ? Light2D.Offset.Convert() : default; + set + { + if (GameController.OnGodot) + { + Light2D.Offset = value.Convert(); + } + } } public Angle Rotation { - get => new Angle(Light2D.GlobalRotation); - set => Light2D.Rotation = (float)value; + get => GameController.OnGodot ? new Angle(Light2D.GlobalRotation) : default; + set + { + if (GameController.OnGodot) + { + Light2D.GlobalRotation = (float) value.Theta; + } + } } private Color color; + public Color Color { get => color; @@ -36,11 +50,16 @@ namespace SS14.Client.Graphics.Lighting } color = value; - Light2D.Color = value.Convert(); + + if (GameController.OnGodot) + { + Light2D.Color = value.Convert(); + } } } private float textureScale; + public float TextureScale { get => textureScale; @@ -52,11 +71,16 @@ namespace SS14.Client.Graphics.Lighting } textureScale = value; - Light2D.TextureScale = value; + + if (GameController.OnGodot) + { + Light2D.TextureScale = value; + } } } private float energy; + public float Energy { get => energy; @@ -68,7 +92,10 @@ namespace SS14.Client.Graphics.Lighting } energy = value; - Light2D.Energy = value; + if (GameController.OnGodot) + { + Light2D.Energy = value; + } } } @@ -94,6 +121,7 @@ namespace SS14.Client.Graphics.Lighting } private Texture texture; + public Texture Texture { get => texture; @@ -103,12 +131,17 @@ namespace SS14.Client.Graphics.Lighting { return; } + texture = value; - Light2D.Texture = value; + if (GameController.OnGodot) + { + Light2D.Texture = value; + } } } private bool enabled; + public bool Enabled { get => enabled; @@ -119,32 +152,37 @@ namespace SS14.Client.Graphics.Lighting } } - private Godot.Light2D Light2D; + public bool Disposed { get; private set; } + private LightManager Manager; private LightingSystem System => Manager.System; - + private Godot.Light2D Light2D; private IGodotTransformComponent parentTransform; private Godot.Vector2 CurrentPos; public Light(LightManager manager) { Manager = manager; - Light2D = new Godot.Light2D() - { - // TODO: Allow this to be modified. - ShadowEnabled = true, - ShadowFilter = Godot.Light2D.ShadowFilterEnum.Pcf5, - }; - if (Manager.System == LightingSystem.Disabled) + if (GameController.OnGodot) { - Light2D.Enabled = Light2D.Visible = false; + Light2D = new Godot.Light2D() + { + // TODO: Allow this to be modified. + ShadowEnabled = true, + ShadowFilter = Godot.Light2D.ShadowFilterEnum.Pcf5, + }; + + if (Manager.System == LightingSystem.Disabled) + { + Light2D.Enabled = Light2D.Visible = false; + } } Mode = new LightModeConstant(); Mode.Start(this); - if (System == LightingSystem.Deferred) + if (GameController.OnGodot && System == LightingSystem.Deferred) { Manager.deferredViewport.AddChild(Light2D); } @@ -152,45 +190,62 @@ namespace SS14.Client.Graphics.Lighting public void DeParent() { - if (System == LightingSystem.Deferred) + if (GameController.OnGodot) { - Light2D.Position = new Godot.Vector2(0, 0); - } - else - { - parentTransform.SceneNode.RemoveChild(Light2D); + if (System == LightingSystem.Deferred) + { + Light2D.Position = new Godot.Vector2(0, 0); + } + else + { + parentTransform.SceneNode.RemoveChild(Light2D); + } } + UpdateEnabled(); } - public void ParentTo(IGodotTransformComponent node) + public void ParentTo(ITransformComponent node) { + if (!GameController.OnGodot) + { + return; + } + if (System != LightingSystem.Deferred) { if (parentTransform != null) { DeParent(); } - node.SceneNode.AddChild(Light2D); + + ((IGodotTransformComponent) node).SceneNode.AddChild(Light2D); } - parentTransform = node; + + parentTransform = (IGodotTransformComponent) node; UpdateEnabled(); } public void Dispose() { // Already disposed. - if (Light2D == null) + if (Disposed) { return; } + Manager.RemoveLight(this); - Manager = null; + + Disposed = true; + + if (!GameController.OnGodot) + { + return; + } Light2D.QueueFree(); Light2D.Dispose(); - Light2D = null; } private static ILightMode GetModeInstance(LightModeClass modeClass) @@ -207,19 +262,25 @@ namespace SS14.Client.Graphics.Lighting public void UpdateEnabled() { - Light2D.Visible = Enabled && Manager.Enabled && parentTransform != null; + if (GameController.OnGodot) + { + Light2D.Visible = Enabled && Manager.Enabled && parentTransform != null; + } } public void FrameProcess(FrameEventArgs args) { - // TODO: Maybe use OnMove events to make this less expensive. - if (System == LightingSystem.Deferred && parentTransform != null) +// TODO: Maybe use OnMove events to make this less expensive. + if (!GameController.OnGodot || Manager.System != LightingSystem.Deferred || + parentTransform == null) { - var newpos = parentTransform.SceneNode.GlobalPosition; - if (CurrentPos != newpos) - { - Light2D.Position = newpos; - } + return; + } + + var newpos = parentTransform.SceneNode.GlobalPosition; + if (CurrentPos != newpos) + { + Light2D.Position = newpos; } } } diff --git a/SS14.Client/Graphics/Lighting/LightManager.Occluder.cs b/SS14.Client/Graphics/Lighting/LightManager.Occluder.cs index a8e56774f..9f464969c 100644 --- a/SS14.Client/Graphics/Lighting/LightManager.Occluder.cs +++ b/SS14.Client/Graphics/Lighting/LightManager.Occluder.cs @@ -3,6 +3,7 @@ using System.Linq; using SS14.Client.Interfaces.GameObjects.Components; using SS14.Client.Interfaces.Graphics.Lighting; using SS14.Client.Utility; +using SS14.Shared.Interfaces.GameObjects.Components; using SS14.Shared.Maths; namespace SS14.Client.Graphics.Lighting @@ -12,6 +13,7 @@ namespace SS14.Client.Graphics.Lighting sealed class Occluder : IOccluder { private bool visible = true; + public bool Enabled { get => visible; @@ -22,6 +24,8 @@ namespace SS14.Client.Graphics.Lighting } } + public bool Disposed { get; private set; } + private LightManager Manager; private Godot.OccluderPolygon2D occluderPolygon; @@ -31,10 +35,17 @@ namespace SS14.Client.Graphics.Lighting public OccluderCullMode CullMode { - get => (OccluderCullMode)occluderPolygon.CullMode; - set => occluderPolygon.CullMode = (Godot.OccluderPolygon2D.CullModeEnum)value; + get => GameController.OnGodot ? (OccluderCullMode) occluderPolygon.CullMode : default; + set + { + if (GameController.OnGodot) + { + occluderPolygon.CullMode = (Godot.OccluderPolygon2D.CullModeEnum) value; + } + } } + private IGodotTransformComponent parentTransform; private Godot.Vector2 CurrentPos; @@ -42,6 +53,11 @@ namespace SS14.Client.Graphics.Lighting { Manager = manager; + if (!GameController.OnGodot) + { + return; + } + occluderPolygon = new Godot.OccluderPolygon2D(); occluder = new Godot.LightOccluder2D() { @@ -57,39 +73,48 @@ namespace SS14.Client.Graphics.Lighting public void Dispose() { // Already disposed. - if (occluder == null) + if (Disposed) { return; } Manager.RemoveOccluder(this); - Manager = null; + Disposed = true; + + if (!GameController.OnGodot) + { + return; + } occluder.QueueFree(); occluder.Dispose(); - occluder = null; occluderPolygon.Dispose(); - occluderPolygon = null; } public void SetPolygon(Vector2[] polygon) { + if (!GameController.OnGodot) + { + return; + } + var converted = new Godot.Vector2[polygon.Length]; for (var i = 0; i < polygon.Length; i++) { converted[i] = polygon[i].Convert(); } - occluderPolygon.Polygon = converted; - } - public void SetGodotPolygon(Godot.Vector2[] polygon) - { - occluderPolygon.Polygon = polygon; + occluderPolygon.Polygon = converted; } public void DeParent() { + if (!GameController.OnGodot) + { + return; + } + if (Deferred) { occluder.Position = new Godot.Vector2(0, 0); @@ -98,26 +123,42 @@ namespace SS14.Client.Graphics.Lighting { parentTransform.SceneNode.RemoveChild(occluder); } + UpdateEnabled(); } - public void ParentTo(IGodotTransformComponent node) + public void ParentTo(ITransformComponent node) { + if (!GameController.OnGodot) + { + return; + } + if (!Deferred) { - node.SceneNode.AddChild(occluder); + ((IGodotTransformComponent) node).SceneNode.AddChild(occluder); } - parentTransform = node; + + parentTransform = (IGodotTransformComponent) node; UpdateEnabled(); } + private void UpdateEnabled() { - occluder.Visible = parentTransform != null && Enabled; + if (GameController.OnGodot) + { + occluder.Visible = parentTransform != null && Enabled; + } } public void FrameProcess(FrameEventArgs args) { + if (!GameController.OnGodot) + { + return; + } + // TODO: Maybe use OnMove events to make this less expensive. if (Deferred && parentTransform != null) { diff --git a/SS14.Client/Graphics/Lighting/LightManager.cs b/SS14.Client/Graphics/Lighting/LightManager.cs index 6eda8a734..468117089 100644 --- a/SS14.Client/Graphics/Lighting/LightManager.cs +++ b/SS14.Client/Graphics/Lighting/LightManager.cs @@ -24,14 +24,12 @@ namespace SS14.Client.Graphics.Lighting { public sealed partial class LightManager : ILightManager, IDisposable, IPostInjectInit { - [Dependency] - readonly ISceneTreeHolder sceneTreeHolder; - [Dependency] - readonly IConfigurationManager configManager; - [Dependency] - readonly IResourceCache resourceCache; + [Dependency] readonly ISceneTreeHolder sceneTreeHolder; + [Dependency] readonly IConfigurationManager configManager; + [Dependency] readonly IResourceCache resourceCache; private bool enabled = true; + public bool Enabled { get => enabled; @@ -64,12 +62,18 @@ namespace SS14.Client.Graphics.Lighting public void PostInject() { - configManager.RegisterCVar("display.lighting_system", LightingSystem.Normal, Shared.Configuration.CVar.ARCHIVE); + configManager.RegisterCVar("display.lighting_system", LightingSystem.Normal, + Shared.Configuration.CVar.ARCHIVE); } public void Initialize() { System = configManager.GetCVar("display.lighting_system"); + if (!GameController.OnGodot) + { + return; + } + canvasModulate = new Godot.CanvasModulate() { // Black @@ -89,7 +93,8 @@ namespace SS14.Client.Graphics.Lighting deferredViewport.AddChild(canvasModulate); rootViewport.AddChild(deferredViewport); - var whiteTex = resourceCache.GetResource(new ResourcePath(@"/Textures/Effects/Light/white.png")); + var whiteTex = + resourceCache.GetResource(new ResourcePath(@"/Textures/Effects/Light/white.png")); deferredMaskBackground = new Godot.Sprite() { Name = "DeferredMaskBackground", @@ -118,6 +123,7 @@ namespace SS14.Client.Graphics.Lighting } } + private void OnWindowSizeChanged() { if (System == LightingSystem.Deferred) @@ -153,6 +159,7 @@ namespace SS14.Client.Graphics.Lighting deferredMaskLayer.AddChild(deferredMaskSprite); } + public void Dispose() { if (disposed) @@ -166,6 +173,11 @@ namespace SS14.Client.Graphics.Lighting light.Dispose(); } + if (!GameController.OnGodot) + { + return; + } + if (System == LightingSystem.Deferred) { deferredSizeChangedSubscriber.Disconnect(rootViewport, "size_changed"); @@ -230,10 +242,15 @@ namespace SS14.Client.Graphics.Lighting private void UpdateEnabled() { + if (!GameController.OnGodot) + { + return; + } if (System == LightingSystem.Deferred) { deferredMaskSprite.Visible = Enabled; } + foreach (var light in lights) { light.UpdateEnabled(); @@ -242,7 +259,7 @@ namespace SS14.Client.Graphics.Lighting public void FrameUpdate(RenderFrameEventArgs args) { - if (System == LightingSystem.Deferred) + if (GameController.OnGodot && System == LightingSystem.Deferred) { var transform = rootViewport.CanvasTransform; deferredViewport.CanvasTransform = transform; diff --git a/SS14.Client/Graphics/Overlays/Overlay.cs b/SS14.Client/Graphics/Overlays/Overlay.cs index c6a303dd5..5723b6de8 100644 --- a/SS14.Client/Graphics/Overlays/Overlay.cs +++ b/SS14.Client/Graphics/Overlays/Overlay.cs @@ -23,13 +23,14 @@ namespace SS14.Client.Graphics.Overlays public virtual OverlaySpace Space => OverlaySpace.ScreenSpace; private Shader _shader; + public Shader Shader { get => _shader; set { _shader = value; - if (MainCanvasItem != null) + if (GameController.OnGodot && MainCanvasItem != null) { VS.CanvasItemSetMaterial(MainCanvasItem, value?.GodotMaterial?.GetRid()); } @@ -37,6 +38,7 @@ namespace SS14.Client.Graphics.Overlays } private int? _zIndex; + public int? ZIndex { get => _zIndex; @@ -46,6 +48,7 @@ namespace SS14.Client.Graphics.Overlays { throw new ArgumentOutOfRangeException(nameof(value)); } + _zIndex = value; UpdateZIndex(); } @@ -55,6 +58,7 @@ namespace SS14.Client.Graphics.Overlays private bool _isDirty = true; + private Godot.RID MainCanvasItem; private readonly List CanvasItems = new List(); @@ -75,6 +79,7 @@ namespace SS14.Client.Graphics.Overlays { Shader.ApplyToCanvasItem(MainCanvasItem); } + UpdateZIndex(); } @@ -84,6 +89,7 @@ namespace SS14.Client.Graphics.Overlays { return; } + Dispose(true); Disposed = true; GC.SuppressFinalize(this); @@ -108,6 +114,25 @@ namespace SS14.Client.Graphics.Overlays throw new InvalidOperationException("Can only allocate new handles while drawing."); } + if (!GameController.OnGodot) + { + DrawingHandle handle; + switch (Space) + { + case OverlaySpace.ScreenSpace: + handle = new DrawingHandleScreen(); + break; + case OverlaySpace.WorldSpace: + handle = new DrawingHandleWorld(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + TempHandles.Add(handle); + return handle; + } + var item = VS.CanvasItemCreate(); VS.CanvasItemSetParent(item, MainCanvasItem); CanvasItems.Add(item); @@ -120,21 +145,24 @@ namespace SS14.Client.Graphics.Overlays VS.CanvasItemSetUseParentMaterial(item, SubHandlesUseMainShader); } - DrawingHandle handle; - switch (Space) { - case OverlaySpace.ScreenSpaceBelowWorld: - case OverlaySpace.ScreenSpace: - handle = new DrawingHandleScreen(item); - break; - case OverlaySpace.WorldSpace: - handle = new DrawingHandleWorld(item); - break; - default: - throw new ArgumentOutOfRangeException(); + DrawingHandle handle; + switch (Space) + { + case OverlaySpace.ScreenSpaceBelowWorld: + case OverlaySpace.ScreenSpace: + handle = new DrawingHandleScreen(item); + break; + case OverlaySpace.WorldSpace: + handle = new DrawingHandleWorld(item); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + TempHandles.Add(handle); + return handle; } - TempHandles.Add(handle); - return handle; } public void Dirty() @@ -144,7 +172,7 @@ namespace SS14.Client.Graphics.Overlays public void FrameUpdate(RenderFrameEventArgs args) { - if (!IsDirty) + if (!IsDirty || !GameController.OnGodot) { return; } @@ -167,6 +195,7 @@ namespace SS14.Client.Graphics.Overlays default: throw new ArgumentOutOfRangeException(); } + Draw(handle); } finally @@ -176,12 +205,18 @@ namespace SS14.Client.Graphics.Overlays { handle.Dispose(); } + TempHandles.Clear(); } } private void ClearDraw() { + if (!GameController.OnGodot) + { + return; + } + foreach (var item in CanvasItems) { VS.FreeRid(item); @@ -194,7 +229,7 @@ namespace SS14.Client.Graphics.Overlays private void UpdateZIndex() { - if (MainCanvasItem == null) + if (MainCanvasItem == null || !GameController.OnGodot) { return; } diff --git a/SS14.Client/Graphics/Overlays/OverlayManager.cs b/SS14.Client/Graphics/Overlays/OverlayManager.cs index 6087483a6..f340fff7f 100644 --- a/SS14.Client/Graphics/Overlays/OverlayManager.cs +++ b/SS14.Client/Graphics/Overlays/OverlayManager.cs @@ -18,21 +18,26 @@ namespace SS14.Client.Graphics.Overlays private Godot.Node2D RootNodeScreen; private Godot.Node2D RootNodeScreenBelowWorld; - [Dependency] - readonly ISceneTreeHolder sceneTreeHolder; + [Dependency] readonly ISceneTreeHolder sceneTreeHolder; - private readonly Dictionary overlays = new Dictionary(); + private readonly Dictionary overlays = + new Dictionary(); public void Initialize() { + if (!GameController.OnGodot) + { + return; + } + RootNodeScreenBelowWorld = new Godot.Node2D { Name = "OverlayRoot" }; sceneTreeHolder.BelowWorldScreenSpace.AddChild(RootNodeScreenBelowWorld); RootNodeWorld = new Godot.Node2D { Name = "OverlayRoot" }; sceneTreeHolder.WorldRoot.AddChild(RootNodeWorld); - RootNodeWorld.ZIndex = (int)DrawDepth.Overlays; + RootNodeWorld.ZIndex = (int) DrawDepth.Overlays; - RootNodeScreen = new Godot.Node2D { Name = "OverlayRoot" }; + RootNodeScreen = new Godot.Node2D {Name = "OverlayRoot"}; sceneTreeHolder.SceneTree.Root.GetNode("UILayer").AddChild(RootNodeScreen); } @@ -46,10 +51,16 @@ namespace SS14.Client.Graphics.Overlays public void AddOverlay(IOverlay overlay) { + if (!GameController.OnGodot) + { + return; + } + if (overlays.ContainsKey(overlay.ID)) { throw new InvalidOperationException($"We already have an overlay with ID '{overlay.ID}'"); } + Godot.RID parent; switch (overlay.Space) { @@ -65,6 +76,7 @@ namespace SS14.Client.Graphics.Overlays default: throw new NotImplementedException($"Unknown overlay space: {overlay.Space}"); } + var item = VS.CanvasItemCreate(); VS.CanvasItemSetParent(item, parent); @@ -74,25 +86,36 @@ namespace SS14.Client.Graphics.Overlays public IOverlay GetOverlay(string id) { - return overlays[id].overlay; + if (GameController.OnGodot) + { + return overlays[id].overlay; + } + + throw new NotImplementedException(); } public T GetOverlay(string id) where T : IOverlay { - return (T)GetOverlay(id); + return (T) GetOverlay(id); } public bool HasOverlay(string id) { - return overlays.ContainsKey(id); + if (GameController.OnGodot) + { + return overlays.ContainsKey(id); + } + + throw new NotImplementedException(); } public void RemoveOverlay(string id) { - if (!overlays.TryGetValue(id, out var value)) + if (!GameController.OnGodot || !overlays.TryGetValue(id, out var value)) { return; } + var (overlay, item) = value; overlay.Dispose(); VS.FreeRid(item); @@ -101,12 +124,13 @@ namespace SS14.Client.Graphics.Overlays public bool TryGetOverlay(string id, out IOverlay overlay) { - if (overlays.TryGetValue(id, out var value)) + if (GameController.OnGodot && overlays.TryGetValue(id, out var value)) { overlay = value.overlay; return true; } - overlay = null; + + overlay = default; return false; } @@ -114,9 +138,10 @@ namespace SS14.Client.Graphics.Overlays { if (overlays.TryGetValue(id, out var value)) { - overlay = (T)value.overlay; + overlay = (T) value.overlay; return true; } + overlay = default; return false; } diff --git a/SS14.Client/Graphics/Shaders/Shader.cs b/SS14.Client/Graphics/Shaders/Shader.cs index ba09863f0..0a5191120 100644 --- a/SS14.Client/Graphics/Shaders/Shader.cs +++ b/SS14.Client/Graphics/Shaders/Shader.cs @@ -10,6 +10,11 @@ namespace SS14.Client.Graphics.Shaders // ReSharper disable once CollectionNeverQueried.Local private static readonly List LeakyLeaky = new List(); + internal Shader() + { + + } + internal Shader(Godot.Material godotMaterial) { LeakyLeaky.Add(this); diff --git a/SS14.Client/Graphics/Shaders/ShaderPrototype.cs b/SS14.Client/Graphics/Shaders/ShaderPrototype.cs index 896939f92..2b9086b0d 100644 --- a/SS14.Client/Graphics/Shaders/ShaderPrototype.cs +++ b/SS14.Client/Graphics/Shaders/ShaderPrototype.cs @@ -34,6 +34,11 @@ namespace SS14.Client.Graphics.Shaders /// public Shader Instance() { + if (!GameController.OnGodot) + { + return new Shader(); + } + Godot.Material mat; switch (Kind) @@ -51,6 +56,7 @@ namespace SS14.Client.Graphics.Shaders shaderMat.SetShaderParam(pair.Key, pair.Value); } } + break; case ShaderKind.Canvas: mat = new Godot.CanvasItemMaterial @@ -113,6 +119,11 @@ namespace SS14.Client.Graphics.Shaders private void ReadCanvasKind(YamlMappingNode mapping) { + if (!GameController.OnGodot) + { + return; + } + if (mapping.TryGetNode("light_mode", out var node)) { switch (node.AsString()) @@ -166,6 +177,10 @@ namespace SS14.Client.Graphics.Shaders private object ParseShaderParamFor(YamlNode node, ShaderParamType type) { + if (!GameController.OnGodot) + { + throw new NotImplementedException(); + } switch (type) { case ShaderParamType.Void: @@ -196,6 +211,7 @@ namespace SS14.Client.Graphics.Shaders var path = node.AsResourcePath(); var resc = IoCManager.Resolve(); return resc.GetResource(path).Texture.GodotTexture; + // If something's not handled here, then that's probably because I was lazy. default: throw new NotImplementedException(); diff --git a/SS14.Client/Graphics/Texture.cs b/SS14.Client/Graphics/Texture.cs index 1e77b7bb9..bb4bb90a5 100644 --- a/SS14.Client/Graphics/Texture.cs +++ b/SS14.Client/Graphics/Texture.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; @@ -13,8 +14,9 @@ namespace SS14.Client.Graphics { internal abstract Godot.Texture GodotTexture { get; } - public int Width => GodotTexture.GetWidth(); - public int Height => GodotTexture.GetHeight(); + public int Width => GameController.OnGodot ? GodotTexture.GetWidth() : default; + public int Height => GameController.OnGodot ? GodotTexture.GetHeight() : default; + public Vector2i Size => new Vector2i(Width, Height); public static implicit operator Godot.Texture(Texture src) @@ -24,6 +26,10 @@ namespace SS14.Client.Graphics public static Texture LoadFromImage(Image image) where T : struct, IPixel { + if (!GameController.OnGodot) + { + return new BlankTexture(); + } var stream = new MemoryStream(); try @@ -50,6 +56,11 @@ namespace SS14.Client.Graphics public static Texture LoadFromPNGStream(Stream stream) { + if (!GameController.OnGodot) + { + return new BlankTexture(); + } + using (var memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); @@ -76,6 +87,14 @@ namespace SS14.Client.Graphics } } + /// + /// Blank dummy texture. + /// + public class BlankTexture : Texture + { + internal override Godot.Texture GodotTexture => null; + } + /// /// Wraps a texture returned by Godot itself, /// for example when the texture was set in a GUI scene. diff --git a/SS14.Client/Input/Events.cs b/SS14.Client/Input/Events.cs index 07eafb68b..f0128ea42 100644 --- a/SS14.Client/Input/Events.cs +++ b/SS14.Client/Input/Events.cs @@ -45,6 +45,11 @@ namespace SS14.Client.Input /// public void Handle() { + if (!GameController.OnGodot) + { + return; + } + var tree = IoCManager.Resolve(); tree.SceneTree.SetInputAsHandled(); } @@ -74,11 +79,11 @@ namespace SS14.Client.Input public static explicit operator KeyEventArgs(Godot.InputEventKey args) { return new KeyEventArgs(Keyboard.ConvertGodotKey(args.Scancode), - (UInt32)args.Unicode, - args.Alt, - args.Control, - args.Shift, - args.Command); + (UInt32) args.Unicode, + args.Alt, + args.Control, + args.Shift, + args.Command); } public static explicit operator KeyEventArgs(Godot.InputEventMouseButton args) @@ -102,11 +107,11 @@ namespace SS14.Client.Input public Vector2 Position { get; } protected MouseEventArgs(Mouse.ButtonMask buttonMask, - Vector2 position, - bool alt, - bool control, - bool shift, - bool system) + Vector2 position, + bool alt, + bool control, + bool shift, + bool system) : base(alt, control, shift, system) { ButtonMask = buttonMask; @@ -146,6 +151,7 @@ namespace SS14.Client.Input default: return type; } + if (Alt) type |= ClickType.Alt; if (Control) @@ -160,13 +166,13 @@ namespace SS14.Client.Input // ALL the parameters! public MouseButtonEventArgs(Mouse.Button button, - bool doubleClick, - Mouse.ButtonMask buttonMask, - Vector2 position, - bool alt, - bool control, - bool shift, - bool system) + bool doubleClick, + Mouse.ButtonMask buttonMask, + Vector2 position, + bool alt, + bool control, + bool shift, + bool system) : base(buttonMask, position, alt, control, shift, system) { Button = button; @@ -177,14 +183,14 @@ namespace SS14.Client.Input { // Before cutting this up, // this line was 281 characters long. - return new MouseButtonEventArgs((Mouse.Button)inputEvent.ButtonIndex, - inputEvent.Doubleclick, - (Mouse.ButtonMask)inputEvent.ButtonMask, - inputEvent.Position.Convert(), - inputEvent.Alt, - inputEvent.Control, - inputEvent.Shift, - inputEvent.Command); + return new MouseButtonEventArgs((Mouse.Button) inputEvent.ButtonIndex, + inputEvent.Doubleclick, + (Mouse.ButtonMask) inputEvent.ButtonMask, + inputEvent.Position.Convert(), + inputEvent.Alt, + inputEvent.Control, + inputEvent.Shift, + inputEvent.Command); } } @@ -197,12 +203,12 @@ namespace SS14.Client.Input // ALL the parameters! public MouseWheelEventArgs(Mouse.Wheel wheelDirection, - Mouse.ButtonMask buttonMask, - Vector2 position, - bool alt, - bool control, - bool shift, - bool system) + Mouse.ButtonMask buttonMask, + Vector2 position, + bool alt, + bool control, + bool shift, + bool system) : base(buttonMask, position, alt, control, shift, system) { WheelDirection = wheelDirection; @@ -212,13 +218,13 @@ namespace SS14.Client.Input { // Before cutting this up, // this line was 281 characters long. - return new MouseWheelEventArgs((Mouse.Wheel)inputEvent.ButtonIndex, - (Mouse.ButtonMask)inputEvent.ButtonMask, - inputEvent.Position.Convert(), - inputEvent.Alt, - inputEvent.Control, - inputEvent.Shift, - inputEvent.Command); + return new MouseWheelEventArgs((Mouse.Wheel) inputEvent.ButtonIndex, + (Mouse.ButtonMask) inputEvent.ButtonMask, + inputEvent.Position.Convert(), + inputEvent.Alt, + inputEvent.Control, + inputEvent.Shift, + inputEvent.Command); } } @@ -238,13 +244,13 @@ namespace SS14.Client.Input // ALL the parameters! public MouseMoveEventArgs(Vector2 relative, - Vector2 speed, - Mouse.ButtonMask buttonMask, - Vector2 position, - bool alt, - bool control, - bool shift, - bool system) + Vector2 speed, + Mouse.ButtonMask buttonMask, + Vector2 position, + bool alt, + bool control, + bool shift, + bool system) : base(buttonMask, position, alt, control, shift, system) { Relative = relative; @@ -254,13 +260,13 @@ namespace SS14.Client.Input public static explicit operator MouseMoveEventArgs(Godot.InputEventMouseMotion inputEvent) { return new MouseMoveEventArgs(inputEvent.Relative.Convert(), - inputEvent.Speed.Convert(), - (Mouse.ButtonMask)inputEvent.ButtonMask, - inputEvent.Position.Convert(), - inputEvent.Alt, - inputEvent.Control, - inputEvent.Shift, - inputEvent.Command); + inputEvent.Speed.Convert(), + (Mouse.ButtonMask) inputEvent.ButtonMask, + inputEvent.Position.Convert(), + inputEvent.Alt, + inputEvent.Control, + inputEvent.Shift, + inputEvent.Command); } } } diff --git a/SS14.Client/Input/InputDevices.cs b/SS14.Client/Input/InputDevices.cs index 42c5fd65b..20da446ea 100644 --- a/SS14.Client/Input/InputDevices.cs +++ b/SS14.Client/Input/InputDevices.cs @@ -1,11 +1,10 @@ -using Godot; -using System; +using System; namespace SS14.Client.Input { public static class Mouse { - public static bool IsButtonPressed(Button button) => Godot.Input.IsMouseButtonPressed((int)button); + public static bool IsButtonPressed(Button button) => GameController.OnGodot ? Godot.Input.IsMouseButtonPressed((int) button) : default; // TODO: People will definitely want support for extra mouse buttons, // Godot doesn't seem to support this though. @@ -14,9 +13,9 @@ namespace SS14.Client.Input /// public enum Button { - Left = ButtonList.Left, - Middle = ButtonList.Middle, - Right = ButtonList.Right, + Left = 1, + Middle = 2, + Right = 3, } /// @@ -25,10 +24,11 @@ namespace SS14.Client.Input [Flags] public enum ButtonMask { + // These match Godot's None = 0, - Left = Godot.ButtonList.MaskLeft, - Middle = Godot.ButtonList.MaskMiddle, - Right = Godot.ButtonList.MaskRight, + Left = 1, + Middle = 2, + Right = 4, } /// @@ -36,10 +36,11 @@ namespace SS14.Client.Input /// public enum Wheel { - Up = Godot.ButtonList.WheelUp, - Down = Godot.ButtonList.WheelDown, - Left = Godot.ButtonList.WheelLeft, - Right = Godot.ButtonList.WheelRight, + // These match Godot's + Up = 4, + Down = 5, + Left = 6, + Right = 7, } public static Keyboard.Key ConvertGodotMouseButton(Button button) @@ -60,21 +61,6 @@ namespace SS14.Client.Input public static class Keyboard { - /// - /// Checks whether the provided key on the keyboard is currently held down. - /// - /// The key to check for. - /// True if the provided key is currently held down, false otherwise. - public static bool IsKeyPressed(Key key) => Godot.Input.IsKeyPressed((int)key); - - /// - /// Checks whether a key is printable. - /// - /// The key to check. - /// True if the key is printable, false otherwise. - // See Godot docs: SPKEY = 16777216 — Scancodes with this bit applied are non printable. - public static bool IsKeyPrintable(Key key) => ((int)key & GD.Spkey) == 0; - /// /// Represents a key on the keyboard. /// @@ -198,7 +184,7 @@ namespace SS14.Client.Input // They don't even prevent overlap if you remove the SPKEY flag (they totally could too...). // The macOS, X11 and Windows platform layers *all* have scancode translation tables so it literally can't be "oh they took them from X11!" // Also there are dumb scan codes like YACCUTE which *literally don't get fired ever*. - switch ((Godot.KeyList)key) + switch ((Godot.KeyList) key) { // Dear mother of .NET optimize this nicely for me. case Godot.KeyList.A: diff --git a/SS14.Client/Interfaces/GameObjects/Components/IGodotTransformComponent.cs b/SS14.Client/Interfaces/GameObjects/Components/IGodotTransformComponent.cs index 8740181db..a128b2d4e 100644 --- a/SS14.Client/Interfaces/GameObjects/Components/IGodotTransformComponent.cs +++ b/SS14.Client/Interfaces/GameObjects/Components/IGodotTransformComponent.cs @@ -10,6 +10,7 @@ namespace SS14.Client.Interfaces.GameObjects.Components public interface IGodotTransformComponent : ITransformComponent { new IGodotTransformComponent Parent { get; } + Godot.Node2D SceneNode { get; } } } diff --git a/SS14.Client/Interfaces/GameObjects/Components/ISpriteComponent.cs b/SS14.Client/Interfaces/GameObjects/Components/ISpriteComponent.cs index acf7c3ac0..b2e2027cc 100644 --- a/SS14.Client/Interfaces/GameObjects/Components/ISpriteComponent.cs +++ b/SS14.Client/Interfaces/GameObjects/Components/ISpriteComponent.cs @@ -190,7 +190,10 @@ namespace SS14.Client.Interfaces.GameObjects.Components { public static void AttachToControl(this ISpriteProxy mirror, Control control) { - mirror.AttachToItem(control.SceneControl.GetCanvasItem()); + if (GameController.OnGodot) + { + mirror.AttachToItem(control.SceneControl.GetCanvasItem()); + } } } } diff --git a/SS14.Client/Interfaces/Graphics/IDisplayManager.cs b/SS14.Client/Interfaces/Graphics/IDisplayManager.cs index f999c1531..fc9ad51e7 100644 --- a/SS14.Client/Interfaces/Graphics/IDisplayManager.cs +++ b/SS14.Client/Interfaces/Graphics/IDisplayManager.cs @@ -5,6 +5,7 @@ namespace SS14.Client.Interfaces.Graphics /// public interface IDisplayManager { + void SetWindowTitle(string title); void Initialize(); void ReadConfig(); } diff --git a/SS14.Client/Interfaces/Graphics/Lighting/ILight.cs b/SS14.Client/Interfaces/Graphics/Lighting/ILight.cs index ea7b921fc..d50fb27d7 100644 --- a/SS14.Client/Interfaces/Graphics/Lighting/ILight.cs +++ b/SS14.Client/Interfaces/Graphics/Lighting/ILight.cs @@ -4,6 +4,7 @@ using SS14.Shared; using SS14.Shared.Maths; using SS14.Client.Interfaces.GameObjects.Components; using SS14.Shared.Enums; +using SS14.Shared.Interfaces.GameObjects.Components; namespace SS14.Client.Interfaces.Graphics.Lighting { @@ -19,7 +20,7 @@ namespace SS14.Client.Interfaces.Graphics.Lighting Texture Texture { get; set; } bool Enabled { get; set; } - void ParentTo(IGodotTransformComponent node); + void ParentTo(ITransformComponent node); void DeParent(); } } diff --git a/SS14.Client/Interfaces/Graphics/Lighting/IOccluder.cs b/SS14.Client/Interfaces/Graphics/Lighting/IOccluder.cs index 3e04ea2eb..318c0c12c 100644 --- a/SS14.Client/Interfaces/Graphics/Lighting/IOccluder.cs +++ b/SS14.Client/Interfaces/Graphics/Lighting/IOccluder.cs @@ -1,5 +1,6 @@ using System; using SS14.Client.Interfaces.GameObjects.Components; +using SS14.Shared.Interfaces.GameObjects.Components; using SS14.Shared.Maths; namespace SS14.Client.Interfaces.Graphics.Lighting @@ -11,16 +12,16 @@ namespace SS14.Client.Interfaces.Graphics.Lighting OccluderCullMode CullMode { get; set; } void SetPolygon(Vector2[] polygon); - void SetGodotPolygon(Godot.Vector2[] polygon); - void ParentTo(IGodotTransformComponent node); + void ParentTo(ITransformComponent node); void DeParent(); } public enum OccluderCullMode { - Disabled = Godot.OccluderPolygon2D.CullModeEnum.Disabled, - Clockwise = Godot.OccluderPolygon2D.CullModeEnum.Clockwise, - CounterClockwise = Godot.OccluderPolygon2D.CullModeEnum.CounterClockwise, + // These match Godot's OccluderPolygon2D.CullMode + Disabled = 0, + Clockwise = 1, + CounterClockwise = 2 } } diff --git a/SS14.Client/Interfaces/Graphics/Overlays/IOverlay.cs b/SS14.Client/Interfaces/Graphics/Overlays/IOverlay.cs index 12bd3ee9d..bdccd056c 100644 --- a/SS14.Client/Interfaces/Graphics/Overlays/IOverlay.cs +++ b/SS14.Client/Interfaces/Graphics/Overlays/IOverlay.cs @@ -9,7 +9,6 @@ namespace SS14.Client.Interfaces.Graphics.Overlays OverlaySpace Space { get; } void FrameUpdate(RenderFrameEventArgs args); - void AssignCanvasItem(Godot.RID canvasItem); } diff --git a/SS14.Client/Log/GodotLogHandler.cs b/SS14.Client/Log/GodotLogHandler.cs index 9f53df1c7..90381742d 100644 --- a/SS14.Client/Log/GodotLogHandler.cs +++ b/SS14.Client/Log/GodotLogHandler.cs @@ -1,11 +1,10 @@ -using Godot; -using SS14.Shared.Interfaces.Log; +using SS14.Shared.Interfaces.Log; using SS14.Shared.Log; namespace SS14.Client.Log { /// - /// Handles logs using Godot's . + /// Handles logs using Godot's . /// class GodotLogHandler : ILogHandler { @@ -17,7 +16,7 @@ namespace SS14.Client.Log var msg = $"[{name}] {message.SawmillName}: {message.Message}"; lock (locker) { - GD.Print(msg); + Godot.GD.Print(msg); } } } diff --git a/SS14.Client/Map/ClientTileDefinitionManager.cs b/SS14.Client/Map/ClientTileDefinitionManager.cs index 8cbf04e1e..5ad1a7e24 100644 --- a/SS14.Client/Map/ClientTileDefinitionManager.cs +++ b/SS14.Client/Map/ClientTileDefinitionManager.cs @@ -14,21 +14,35 @@ namespace SS14.Client.Map /// public class ClientTileDefinitionManager : TileDefinitionManager, IClientTileDefinitionManager { - [Dependency] - readonly IResourceCache resourceCache; + [Dependency] readonly IResourceCache resourceCache; - public Godot.TileSet TileSet { get; private set; } = new Godot.TileSet(); + public Godot.TileSet TileSet { get; private set; } private Dictionary Textures = new Dictionary(); + public ClientTileDefinitionManager() + { + if (GameController.OnGodot) + { + TileSet = new Godot.TileSet(); + } + } + public override ushort Register(ITileDefinition tileDef) { + if (!GameController.OnGodot) + { + return base.Register(tileDef); + } + var ret = base.Register(tileDef); TileSet.CreateTile(ret); if (!string.IsNullOrEmpty(tileDef.SpriteName)) { - var texture = resourceCache.GetResource(new ResourcePath("/Textures/Tiles/") / $@"{tileDef.SpriteName}.png"); + var texture = + resourceCache.GetResource( + new ResourcePath("/Textures/Tiles/") / $@"{tileDef.SpriteName}.png"); TileSet.TileSetTexture(ret, texture.Texture.GodotTexture); Textures[ret] = texture; } diff --git a/SS14.Client/Map/ClientMapManager.cs b/SS14.Client/Map/GodotMapManager.cs similarity index 93% rename from SS14.Client/Map/ClientMapManager.cs rename to SS14.Client/Map/GodotMapManager.cs index 1dcf91a21..b728d4045 100644 --- a/SS14.Client/Map/ClientMapManager.cs +++ b/SS14.Client/Map/GodotMapManager.cs @@ -9,7 +9,7 @@ using SS14.Client.Graphics.ClientEye; namespace SS14.Client.Map { - public class ClientMapManager : MapManager + public class GodotMapManager : MapManager { [Dependency] private IClientTileDefinitionManager tileDefinitionManager; @@ -18,8 +18,12 @@ namespace SS14.Client.Map private Dictionary RenderTileMaps = new Dictionary(); - public ClientMapManager() + public GodotMapManager() { + if (!GameController.OnGodot) + { + return; + } TileChanged += UpdateTileMapOnUpdate; OnGridCreated += UpdateOnGridCreated; OnGridRemoved += UpdateOnGridRemoved; diff --git a/SS14.Client/Placement/Modes/AlignSnapgridBorder.cs b/SS14.Client/Placement/Modes/AlignSnapgridBorder.cs index 38070c598..6013ef1b0 100644 --- a/SS14.Client/Placement/Modes/AlignSnapgridBorder.cs +++ b/SS14.Client/Placement/Modes/AlignSnapgridBorder.cs @@ -20,7 +20,7 @@ namespace SS14.Client.Placement.Modes public override void Render() { - if (onGrid) + if (GameController.OnGodot && onGrid) { const int ppm = EyeManager.PIXELSPERMETER; var viewportSize = pManager.sceneTree.SceneTree.Root.Size.Convert(); diff --git a/SS14.Client/Placement/Modes/AlignSnapgridCenter.cs b/SS14.Client/Placement/Modes/AlignSnapgridCenter.cs index 235203dbb..ec20d1da1 100644 --- a/SS14.Client/Placement/Modes/AlignSnapgridCenter.cs +++ b/SS14.Client/Placement/Modes/AlignSnapgridCenter.cs @@ -18,7 +18,7 @@ namespace SS14.Client.Placement.Modes public override void Render() { - if (onGrid) + if (GameController.OnGodot && onGrid) { const int ppm = EyeManager.PIXELSPERMETER; var viewportSize = pManager.sceneTree.SceneTree.Root.Size.Convert(); diff --git a/SS14.Client/Placement/PlacementManager.cs b/SS14.Client/Placement/PlacementManager.cs index bccbaa806..df6f2ac7f 100644 --- a/SS14.Client/Placement/PlacementManager.cs +++ b/SS14.Client/Placement/PlacementManager.cs @@ -147,6 +147,7 @@ namespace SS14.Client.Placement return; } } + _colliderAABB = new Box2(0f, 0f, 0f, 0f); } } @@ -186,21 +187,24 @@ namespace SS14.Client.Placement _mapMan.TileChanged += HandleTileChanged; - var unshadedMaterial = new Godot.CanvasItemMaterial() + if (GameController.OnGodot) { - LightMode = Godot.CanvasItemMaterial.LightModeEnum.Unshaded - }; + var unshadedMaterial = new Godot.CanvasItemMaterial() + { + LightMode = Godot.CanvasItemMaterial.LightModeEnum.Unshaded + }; - DrawNode = new Godot.Node2D() - { - Name = "Placement Manager Sprite", - ZIndex = 100, - Material = unshadedMaterial - }; - sceneTree.WorldRoot.AddChild(DrawNode); - drawNodeDrawSubscriber = new GodotGlue.GodotSignalSubscriber0(); - drawNodeDrawSubscriber.Connect(DrawNode, "draw"); - drawNodeDrawSubscriber.Signal += Render; + DrawNode = new Godot.Node2D() + { + Name = "Placement Manager Sprite", + ZIndex = 100, + Material = unshadedMaterial + }; + sceneTree.WorldRoot.AddChild(DrawNode); + drawNodeDrawSubscriber = new GodotGlue.GodotSignalSubscriber0(); + drawNodeDrawSubscriber.Connect(DrawNode, "draw"); + drawNodeDrawSubscriber.Signal += Render; + } // a bit ugly, oh well _baseClient.PlayerJoinedServer += (sender, args) => SetupInput(_entitySystemManager); @@ -292,7 +296,7 @@ namespace SS14.Client.Placement private void SwitchEditorContext(bool enabled) { - if(enabled) + if (enabled) { _inputManager.Contexts.SetActiveContext("editor"); } @@ -300,11 +304,15 @@ namespace SS14.Client.Placement { _entitySystemManager.GetEntitySystem().SetEntityContextActive(); } - } public void Dispose() { + if (!GameController.OnGodot) + { + return; + } + drawNodeDrawSubscriber.Disconnect(DrawNode, "draw"); drawNodeDrawSubscriber.Dispose(); DrawNode.QueueFree(); @@ -346,7 +354,11 @@ namespace SS14.Client.Placement Eraser = false; PlacementOffset = Vector2i.Zero; // Make it draw again to remove the drawn things. - DrawNode?.Update(); + + if (GameController.OnGodot) + { + DrawNode?.Update(); + } } public void Rotate() @@ -385,6 +397,7 @@ namespace SS14.Client.Placement { RequestPlacement(coordinate); } + DeactivateSpecialPlacement(); break; case PlacementTypes.Grid: @@ -392,6 +405,7 @@ namespace SS14.Client.Placement { RequestPlacement(coordinate); } + DeactivateSpecialPlacement(); break; } @@ -447,7 +461,7 @@ namespace SS14.Client.Placement } var modeType = _modeDictionary.First(pair => pair.Key.Equals(CurrentPermission.PlacementOption)).Value; - CurrentMode = (PlacementMode)Activator.CreateInstance(modeType, this); + CurrentMode = (PlacementMode) Activator.CreateInstance(modeType, this); if (hijack != null) { @@ -468,9 +482,9 @@ namespace SS14.Client.Placement // Try to get current map. var map = MapId.Nullspace; var ent = PlayerManager.LocalPlayer.ControlledEntity; - if (ent != null && ent.TryGetComponent(out var component)) + if (ent != null) { - map = component.MapID; + map = ent.Transform.MapID; } if (map == MapId.Nullspace || CurrentPermission == null || CurrentMode == null) @@ -498,7 +512,10 @@ namespace SS14.Client.Placement if (_placenextframe && CurrentPermission.IsTile) HandlePlacement(); - DrawNode.Update(); + if (GameController.OnGodot) + { + DrawNode.Update(); + } } private void ActivateLineMode() @@ -548,7 +565,12 @@ namespace SS14.Client.Placement var pos = PlayerManager.LocalPlayer.ControlledEntity.Transform.WorldPosition; const int ppm = EyeManager.PIXELSPERMETER; - DrawNode.DrawCircle(pos.Convert() * new Godot.Vector2(1, -1) * ppm, CurrentPermission.Range * ppm, new Godot.Color(1, 1, 1, 0.25f)); + + if (GameController.OnGodot) + { + DrawNode.DrawCircle(pos.Convert() * new Godot.Vector2(1, -1) * ppm, CurrentPermission.Range * ppm, + new Godot.Color(1, 1, 1, 0.25f)); + } } private void HandleStartPlacement(MsgPlacement msg) @@ -577,7 +599,8 @@ namespace SS14.Client.Placement private void PreparePlacementTile() { - CurrentBaseSprite = ResourceCache.GetResource(new ResourcePath("/Textures/UserInterface/tilebuildoverlay.png")).Texture; + CurrentBaseSprite = ResourceCache + .GetResource(new ResourcePath("/Textures/UserInterface/tilebuildoverlay.png")).Texture; IsActive = true; } diff --git a/SS14.Client/Placement/PlacementMode.cs b/SS14.Client/Placement/PlacementMode.cs index 62c4f3e20..07e0916f1 100644 --- a/SS14.Client/Placement/PlacementMode.cs +++ b/SS14.Client/Placement/PlacementMode.cs @@ -85,6 +85,10 @@ namespace SS14.Client.Placement public virtual void Render() { + if (!GameController.OnGodot) + { + return; + } if (SpriteToDraw == null) { SetSprite(); diff --git a/SS14.Client/Player/LocalPlayer.cs b/SS14.Client/Player/LocalPlayer.cs index 4b171da30..123b9c4d3 100644 --- a/SS14.Client/Player/LocalPlayer.cs +++ b/SS14.Client/Player/LocalPlayer.cs @@ -95,7 +95,7 @@ namespace SS14.Client.Player } eye.Current = true; - var transform = ControlledEntity.GetComponent(); + var transform = ControlledEntity.Transform; transform.OnMove += OnPlayerMoved; EntityAttached?.Invoke(this, EventArgs.Empty); diff --git a/SS14.Client/ResourceManagement/ResourceTypes/AudioResource.cs b/SS14.Client/ResourceManagement/ResourceTypes/AudioResource.cs index bbb1c6c49..be1ebdce8 100644 --- a/SS14.Client/ResourceManagement/ResourceTypes/AudioResource.cs +++ b/SS14.Client/ResourceManagement/ResourceTypes/AudioResource.cs @@ -12,6 +12,10 @@ namespace SS14.Client.ResourceManagement public override void Load(IResourceCache cache, ResourcePath path) { + if (!GameController.OnGodot) + { + return; + } if (!cache.ContentFileExists(path)) { throw new FileNotFoundException("Content file does not exist for audio sample."); diff --git a/SS14.Client/ResourceManagement/ResourceTypes/FontResource.cs b/SS14.Client/ResourceManagement/ResourceTypes/FontResource.cs index 42a8edf11..ead74d432 100644 --- a/SS14.Client/ResourceManagement/ResourceTypes/FontResource.cs +++ b/SS14.Client/ResourceManagement/ResourceTypes/FontResource.cs @@ -16,10 +16,16 @@ namespace SS14.Client.ResourceManagement public override void Load(IResourceCache cache, ResourcePath path) { + if (!GameController.OnGodot) + { + return; + } + if (!cache.ContentFileExists(path)) { throw new FileNotFoundException("Content file does not exist for texture"); } + if (!cache.TryGetDiskFilePath(path, out string diskPath)) { throw new InvalidOperationException("Textures can only be loaded from disk."); @@ -44,8 +50,10 @@ namespace SS14.Client.ResourceManagement public override void Dispose() { - FontData.Dispose(); - FontData = null; + if (GameController.OnGodot) + { + FontData.Dispose(); + } } } } diff --git a/SS14.Client/ResourceManagement/ResourceTypes/GodotAssetResource.cs b/SS14.Client/ResourceManagement/ResourceTypes/GodotAssetResource.cs new file mode 100644 index 000000000..c8ac2b114 --- /dev/null +++ b/SS14.Client/ResourceManagement/ResourceTypes/GodotAssetResource.cs @@ -0,0 +1,22 @@ +using System.IO; +using System.Text; +using SS14.Client.Interfaces.ResourceManagement; +using SS14.Client.Utility; +using SS14.Shared.Utility; + +namespace SS14.Client.ResourceManagement.ResourceTypes +{ + internal class GodotAssetResource : BaseResource + { + public GodotAsset Asset { get; private set; } + + public override void Load(IResourceCache cache, ResourcePath path) + { + using (var stream = cache.ContentFileRead(path)) + using (var reader = new StreamReader(stream, Encoding.UTF8)) + { + Asset = GodotParser.Parse(reader); + } + } + } +} diff --git a/SS14.Client/ResourceManagement/ResourceTypes/RSIResource.cs b/SS14.Client/ResourceManagement/ResourceTypes/RSIResource.cs index bcd1c7921..41e49b7d0 100644 --- a/SS14.Client/ResourceManagement/ResourceTypes/RSIResource.cs +++ b/SS14.Client/ResourceManagement/ResourceTypes/RSIResource.cs @@ -101,7 +101,7 @@ namespace SS14.Client.ResourceManagement var delayList = delays[i]; if (delayList.Length == 0) { - delays[i] = new float[] { 1 }; + delays[i] = new float[] {1}; } } } @@ -111,7 +111,7 @@ namespace SS14.Client.ResourceManagement // No delays specified, default to 1 frame per dir. for (var i = 0; i < dirValue; i++) { - delays[i] = new float[] { 1 }; + delays[i] = new float[] {1}; } } @@ -126,14 +126,19 @@ namespace SS14.Client.ResourceManagement // Amount of icons per row of the sprite sheet. var sheetWidth = texture.Width / size.X; - var iconFrames = new(Texture, float)[dirValue][]; + var iconFrames = new (Texture, float)[dirValue][]; var counter = 0; for (var j = 0; j < iconFrames.Length; j++) { var delayList = delays[j]; - var directionFrames = new(Texture, float)[delayList.Length]; + var directionFrames = new (Texture, float)[delayList.Length]; for (var i = 0; i < delayList.Length; i++) { + if (!GameController.OnGodot) + { + directionFrames[i] = (new BlankTexture(), delayList[i]); + continue; + } var PosX = (counter % sheetWidth) * size.X; var PosY = (counter / sheetWidth) * size.Y; @@ -146,6 +151,7 @@ namespace SS14.Client.ResourceManagement directionFrames[i] = (new GodotTextureSource(atlasTexture), delayList[i]); counter++; } + iconFrames[j] = directionFrames; } @@ -186,14 +192,19 @@ namespace SS14.Client.ResourceManagement public RSILoadException() { } + public RSILoadException(string message) : base(message) { } + public RSILoadException(string message, Exception inner) : base(message, inner) { } + protected RSILoadException( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) : base(info, context) { } + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) + { + } } } diff --git a/SS14.Client/ResourceManagement/ResourceTypes/ShaderSourceResource.cs b/SS14.Client/ResourceManagement/ResourceTypes/ShaderSourceResource.cs index bc8eaa356..475041fa2 100644 --- a/SS14.Client/ResourceManagement/ResourceTypes/ShaderSourceResource.cs +++ b/SS14.Client/ResourceManagement/ResourceTypes/ShaderSourceResource.cs @@ -20,6 +20,10 @@ namespace SS14.Client.ResourceManagement.ResourceTypes public override void Load(IResourceCache cache, ResourcePath path) { + if (!GameController.OnGodot) + { + return; + } using (var stream = cache.ContentFileRead(path)) using (var reader = new StreamReader(stream, Encoding.UTF8)) { @@ -44,6 +48,10 @@ namespace SS14.Client.ResourceManagement.ResourceTypes private ShaderParamType DetectParamType(IDictionary dict) { + if (!GameController.OnGodot) + { + throw new NotImplementedException(); + } var type = (Godot.Variant.Type)dict["type"]; var hint = (Godot.PropertyHint)dict["hint"]; var hint_string = (string)dict["hint_string"]; diff --git a/SS14.Client/ResourceManagement/ResourceTypes/TextureResource.cs b/SS14.Client/ResourceManagement/ResourceTypes/TextureResource.cs index 2329dc8c1..5ebd133b6 100644 --- a/SS14.Client/ResourceManagement/ResourceTypes/TextureResource.cs +++ b/SS14.Client/ResourceManagement/ResourceTypes/TextureResource.cs @@ -14,6 +14,12 @@ namespace SS14.Client.ResourceManagement public override void Load(IResourceCache cache, ResourcePath path) { + if (!GameController.OnGodot) + { + Texture = new BlankTexture(); + return; + } + if (!cache.ContentFileExists(path)) { throw new FileNotFoundException("Content file does not exist for texture"); @@ -33,7 +39,7 @@ namespace SS14.Client.ResourceManagement } // Disable filter by default because pixel art. - godotTexture.SetFlags(godotTexture.GetFlags() & ~(int)Godot.Texture.FlagsEnum.Filter); + godotTexture.SetFlags(godotTexture.GetFlags() & ~(int) Godot.Texture.FlagsEnum.Filter); Texture = new GodotTextureSource(godotTexture); // Primarily for tracking down iCCP sRGB errors in the image files. Logger.DebugS("res.tex", $"Loaded texture {path}."); @@ -46,8 +52,10 @@ namespace SS14.Client.ResourceManagement public override void Dispose() { - godotTexture.Dispose(); - godotTexture = null; + if (GameController.OnGodot) + { + godotTexture.Dispose(); + } } } } diff --git a/SS14.Client/SS14.Client.csproj b/SS14.Client/SS14.Client.csproj index 4394520df..bdb84256a 100644 --- a/SS14.Client/SS14.Client.csproj +++ b/SS14.Client/SS14.Client.csproj @@ -6,7 +6,7 @@ Debug x64 {83429BD6-6358-4B18-BE51-401DF8EA2673} - Library + Exe Properties SS14.Client SS14.Client @@ -18,6 +18,7 @@ false 0649 7.2 + true true @@ -79,7 +80,7 @@ - + ..\SS14.Client.Godot\.mono\assemblies\GodotSharp.dll @@ -93,9 +94,10 @@ + + - @@ -163,13 +165,14 @@ - + + @@ -193,6 +196,8 @@ + + @@ -305,7 +310,7 @@ {59250baf-0000-0000-0000-000000000000} Lidgren.Network - + {8af31169-49b1-4a12-b8f4-2a0674a9e7cb} SS14.Client.Godot @@ -332,4 +337,4 @@ - \ No newline at end of file + diff --git a/SS14.Client/SceneTreeHolder.cs b/SS14.Client/SceneTreeHolder.cs index c9f9e0454..9ce598fe0 100644 --- a/SS14.Client/SceneTreeHolder.cs +++ b/SS14.Client/SceneTreeHolder.cs @@ -1,10 +1,6 @@ -using SS14.Client.Graphics; -using SS14.Client.Interfaces; +using SS14.Client.Interfaces; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using SS14.Client.Graphics; namespace SS14.Client { diff --git a/SS14.Client/State/States/MainMenu.cs b/SS14.Client/State/States/MainMenu.cs index e9c25ca4e..546ec5bde 100644 --- a/SS14.Client/State/States/MainMenu.cs +++ b/SS14.Client/State/States/MainMenu.cs @@ -13,6 +13,7 @@ using SS14.Shared.Log; using SS14.Client.Interfaces.State; using SS14.Client.UserInterface.Controls; using SS14.Client.UserInterface.CustomControls; +using SS14.Shared.Utility; namespace SS14.Client.State.States { @@ -29,7 +30,7 @@ namespace SS14.Client.State.States [Dependency] readonly IStateManager stateManager; - private Control MainMenuControl; + private MainMenuControl _mainMenuControl; private OptionsMenu OptionsMenu; @@ -41,12 +42,10 @@ namespace SS14.Client.State.States { IoCManager.InjectDependencies(this); - var scene = (Godot.PackedScene)Godot.ResourceLoader.Load("res://Scenes/MainMenu/MainMenu.tscn"); - MainMenuControl = Control.InstanceScene(scene); + _mainMenuControl = new MainMenuControl(); + userInterfaceManager.StateRoot.AddChild(_mainMenuControl); - userInterfaceManager.StateRoot.AddChild(MainMenuControl); - - var VBox = MainMenuControl.GetChild("VBoxContainer"); + var VBox = _mainMenuControl.GetChild("VBoxContainer"); VBox.GetChild