Major Changes including Options menu, logic blocks, modding system, and more.

This commit is contained in:
2026-08-06 01:28:52 -04:00
parent c9ac4641a0
commit b58acff195
90 changed files with 4065 additions and 485 deletions

View File

@@ -39,7 +39,7 @@
<PackageReference Include="Arch" Version="2.1.0" />
<PackageReference Include="Arch.LowLevel" Version="1.1.5" />
<PackageReference Include="Arch.System" Version="1.1.0" />
<PackageReference Include="Chickensoft.GameTools" Version="3.1.18" />
<PackageReference Include="Chickensoft.GameTools" Version="3.1.27" />
<PackageReference Include="GodotHelper" Version="0.0.2" />
<!-- <PackageReference Include="LanguageExt.Core" Version="5.0.0-beta-77" /> -->
<PackageReference Include="MessagePack" Version="3.1.4" />
@@ -47,21 +47,23 @@
<PackageReference Include="NCalcSync" Version="5.12.0" />
<PackageReference Include="SharpYaml" Version="3.7.1" />
<PackageReference Include="SjkScripts" Version="1.0.17" />
<PackageReference Include="System.IO.Abstractions" Version="22.1.0" />
<PackageReference Include="System.IO.Abstractions" Version="22.1.1" />
<PackageReference Include="EnvironmentAbstractions" Version="5.0.0" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.6.0" PrivateAssets="all" OutputItemType="analyzer" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.3.54" />
<PackageReference Include="Chickensoft.AutoInject" Version="2.9.18" PrivateAssets="all" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.7.0" PrivateAssets="all" OutputItemType="analyzer" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="2.0.1" />
<PackageReference Include="Chickensoft.AutoInject" Version="2.13.15" PrivateAssets="all" />
<PackageReference Include="Chickensoft.Collections" Version="3.1.4" />
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.4.57" />
<PackageReference Include="Chickensoft.Introspection" Version="3.0.2" />
<PackageReference Include="Chickensoft.Introspection.Generator" Version="3.0.2" PrivateAssets="all" OutputItemType="analyzer" />
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="3.0.20" />
<PackageReference Include="Chickensoft.Introspection" Version="3.0.3" />
<PackageReference Include="Chickensoft.Introspection.Generator" Version="3.0.3" PrivateAssets="all" OutputItemType="analyzer" />
<PackageReference Include="Chickensoft.Serialization" Version="3.1.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.8.46" />
<PackageReference Include="Chickensoft.LogicBlocks" Version="5.20.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.20.0" PrivateAssets="all" OutputItemType="analyzer" />
<PackageReference Include="Chickensoft.UMLGenerator" Version="1.1.0" />
<PackageReference Include="Chickensoft.Sync" Version="2.2.0" />
<PackageReference Include="Chickensoft.Serialization.Godot" Version="0.9.1" />
<PackageReference Include="Chickensoft.LogicBlocks" Version="6.1.1" />
<PackageReference Include="Chickensoft.LogicBlocks.Auto" Version="6.1.1" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="6.1.1" PrivateAssets="all" OutputItemType="analyzer" />
<PackageReference Include="Chickensoft.UMLGenerator" Version="1.3.1" />
<PackageReference Include="Chickensoft.Sync" Version="2.4.1" />
<PackageReference Include="TrimKit.VirtualFileSystem" Version="1.8.1" />
<PackageReference Include="Utf8Json" Version="1.3.7" />
</ItemGroup>
<ItemGroup>
@@ -70,9 +72,9 @@
<ItemGroup Condition="'$(RunTests)' == 'true'">
<!-- Test dependencies go here! -->
<!-- Dependencies added here will not be included in release builds. -->
<PackageReference Include="Chickensoft.GoDotTest" Version="2.0.27" />
<PackageReference Include="Chickensoft.GoDotTest" Version="2.0.39" />
<!-- Used to drive test scenes when testing visual code -->
<PackageReference Include="Chickensoft.GodotTestDriver" Version="3.1.56" />
<PackageReference Include="Chickensoft.GodotTestDriver" Version="3.1.72" />
<!-- Bring your own assertion library for tests! -->
<!-- We're using Shouldly for this example, but you can use anything. -->
<PackageReference Include="Shouldly" Version="4.3.0" />

View File

@@ -1,8 +1,20 @@
using Godot;
using System;
using SJK.Math;
using Chickensoft.SaveFileBuilder;
using Chickensoft.Introspection;
using Chickensoft.Serialization;
public partial class RTSCamera : Node3D
[Meta, Id("save_data")]
public partial class SaveData
{
[Save("player_transform")]
public Transform3D Transform3D {get;set;}
[Save("player_camera")]
public Transform3D CameraTransform {get;set;}
}
public partial class RTSCamera : Node3D, ISaveable<SaveData>
{
[Export]
public Camera3D camera;
@@ -53,7 +65,7 @@ public partial class RTSCamera : Node3D
{
CancelUpdateFunc();
}
GD.PrintS(positionStartPos,positionOffsetPos,lastTransalation,LastMouseGroundPlanePositon,LastMousePostition,cameraTargetOffset,scrollAmount);
// GD.PrintS(positionStartPos,positionOffsetPos,lastTransalation,LastMouseGroundPlanePositon,LastMousePostition,cameraTargetOffset,scrollAmount);
Update_CurrentFunc();
Update_CameraScroll((float)delta);
LastMousePostition = GetViewport().GetMousePosition();
@@ -113,7 +125,7 @@ public partial class RTSCamera : Node3D
{
cameraTargetOffset += dir * scrollAmount;
}
DebugDraw3D.DrawArrow(Vector3.Zero,cameraTargetOffset);
// DebugDraw3D.DrawArrow(Vector3.Zero,cameraTargetOffset);
Vector3 lastCameraPosition = camera.Position;
camera.Position = camera.Position.Lerp(camera.Position + cameraTargetOffset, delta);
cameraTargetOffset -= camera.Position - lastCameraPosition;
@@ -153,6 +165,13 @@ public partial class RTSCamera : Node3D
);
LastMousePostition = hitpos = GetViewport().GetMousePosition();
}
public SaveData Save() => new(){Transform3D = Transform, CameraTransform = camera.Transform};
public void Load(in SaveData data)
{
Transform = data.Transform3D;
camera.Transform = data.CameraTransform;
}
}
public static partial class SJKMath

View File

@@ -20,7 +20,19 @@
"url": "https://github.com/DmitriySalnikov/godot_debug_draw_3d/releases/download/1.7.3/debug-draw-3d_1.7.3.zip/",
"source": "zip", // optional — this is the default
// "checkout": "master", // optional — this is the default
// "subfolder": "addons/debug_draw_3d" // optional — defaults to "/"
// "subfolder": "" // optional — defaults to "/"
},
"controller_icons": {
"url": "https://github.com/jembawls/controller_icons_csharp/releases/download/v3.1.6/controller_icons_csharp-3.1.6.zip",
"source": "zip", // optional — this is the default
// "checkout": "master", // optional — this is the default
"subfolder": "controller_icons_csharp-3.1.6/addons/controller_icons/" // optional — defaults to "/"
},
// "editor_theme_explorer": {
// "url": "https://github.com/YuriSizov/godot-editor-theme-explorer/releases/godot-editor-theme-explorer-2.1.1.zip",
// "source": "zip", // optional — this is the default
// // "checkout": "master", // optional — this is the default
// // "subfolder": "controller_icons_csharp-3.1.6/addons/controller_icons/" // optional — defaults to "/"
// },
}
}

1
mods/modA/mod.json Normal file
View File

@@ -0,0 +1 @@
"Hello"

1
mods/modB/mod.json Normal file
View File

@@ -0,0 +1 @@
"World"

View File

@@ -19,6 +19,10 @@ run/main_scene="res://src/Main.tscn"
config/features=PackedStringArray("4.6", "C#", "Mobile")
config/icon="res://icon.png"
[autoload]
ControllerIcons="*uid://cvqaxgmq6by3f"
[debug_draw_3d]
settings/addon_root_folder="res://addons/debug_draw_3d"
@@ -41,7 +45,7 @@ naming/scene_name_casing=1
[editor_plugins]
enabled=PackedStringArray("res://addons/imrp/plugin.cfg")
enabled=PackedStringArray("res://addons/controller_icons/plugin.cfg", "res://addons/explore-editor-theme/plugin.cfg", "res://addons/imrp/plugin.cfg")
[gui]
@@ -54,6 +58,7 @@ theme/default_theme_scale=2.0
move_forward={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null)
]
}
move_back={

474
src/App/App.cs Normal file
View File

@@ -0,0 +1,474 @@
namespace FoodFactory;
using Godot;
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.LogicBlocks.Auto;
using Chickensoft.LogicBlocks;
using System;
using System.Threading.Tasks;
using Chickensoft.UMLGenerator;
using System.Collections.Generic;
using System.Linq;
using FoodFactory.Modding;
using System.IO.Abstractions;
using Chickensoft.Sync.Primitives;
using Chickensoft.SaveFileBuilder;
using System.IO;
using System.Text.Json;
using Chickensoft.Serialization;
using Chickensoft.Collections;
using Chickensoft.Serialization.Godot;
using SJK.Functional;
// using Shouldly;
public interface IApp : ICanvasLayer, IProvide<IAppRepo>, IProvide<IOptionConfig>, IProvide<ISaveService>;
[Meta(typeof(IAutoNode))]
[ClassDiagram(UseVSCodePaths = true)]
public partial class App : CanvasLayer, IApp
{
public const string GAME_PATH = "res://src/Game/Game.tscn";
public override void _Notification(int what) => this.Notify(what);
[Node] public ISubViewport GameViewPort { get; private set; } = default!;
[Node] public Menu.IMainMenu MainMenu {get;set;} = default!;
[Node] public ICreateGameMenu CreateGameMenu {get;set;} = default!;
[Node] public ILoadingGameMenu LoadingGameMenu {get;set;} = default!;
[Node] public IOptionsMenu OptionsMenu {get;set;} = default!;
[Node] public IModMenu ModsMenu {get;set;} = default!;
public IGame Game { get; set; } = default!;
public IAppRepo AppRepo { get; set; } = default!;
public IOptionConfig OptionConfig { get; set; } = default!;
public IAppLogic AppLogic { get; set; } = default!;
public LogicBlock.Binding AppBinding { get; set; } = default!;
IAppRepo IProvide<IAppRepo>.Value() => AppRepo;
IOptionConfig IProvide<IOptionConfig>.Value() => OptionConfig;
private AutoChannel.Binding _binding;
private static JsonSerializerOptions _serializerOptions = new JsonSerializerOptions()
{
Converters = {
new SerializableTypeConverter(new Blackboard())
},
TypeInfoResolver = new SerializableTypeResolver(),
WriteIndented = true
};
public ISaveService SaveService { get; set; } = new SaveService(){
FilePath =Path.Join(OS.GetUserDataDir(), "saves", "game.json.gz"),
CurrentSave =
Chickensoft.SaveFileBuilder.SaveFile.CreateGZipJsonFile(
Path.Join(OS.GetUserDataDir(), "saves", "game.json.gz"),
// Create a standard JsonSerializerOptions with our introspective type
// resolver and the logic blocks converter.
_serializerOptions
)
};
private Dictionary<IOptionKey,Action<Variant>> _settingsBind = [];
public void BindSetting<[MustBeVariant] T>(IOptionKey<T> option, Action<T> action) => _settingsBind.Add(option, variant => action(variant.As<T>()));
public void Initialize()
{
GodotSerialization.Setup();
var fileSystem =new FileSystem();
AppRepo = new AppRepo()
{
ModManger = new ModManger()
{
AllMods = new AllMods("/home/ronnie/Documents/Godot/Projects/ChickenGameTest/mods", fileSystem),
Profiles = new ModProfiles()
}
};
AppRepo.ModManger.Profiles.Add(("base", [.. AppRepo.ModManger.AllMods.GetMods()]));
AppRepo.ModManger.Profiles.Add(("test", []));
// GD.Print(string.Join(',', AppRepo.ModManger.AllMods.GetMods()));
AppLogic = new AppLogic();
AppLogic.Set(AppRepo);
OptionConfig = new TestConfig();
((TestConfig)OptionConfig).OnSettingChanged += AppRepo.OnSettingChanged;
BindSetting(OptionConfig.SettingKeys.Video.RenderQuality, value => GameViewPort.Scaling3DScale = value);
BindSetting(OptionConfig.SettingKeys.Video.FullScreen, value => DisplayServer.WindowSetMode(value ? DisplayServer.WindowMode.Fullscreen : DisplayServer.WindowMode.Windowed));
_binding = AppRepo.AutoChannel.Bind();
_binding.On<IAppRepo.GameSettingChanged>((in setting) =>
{
GD.Print(setting);
if (_settingsBind.GetValue(setting.Setting).HasValue(out var action)){
action(setting.Value);
}
return;
if (setting.Setting is OptionKey<bool> key && key.Key == "FullScreen")
{
DisplayServer.WindowSetMode(setting.Value.As<bool>() ? DisplayServer.WindowMode.Fullscreen : DisplayServer.WindowMode.Windowed );
}
if (setting.Setting is OptionKey<float> key2 && key2.Key == "RenderQuality")
{
GameViewPort.Scaling3DScale = setting.Value.As<float>() / 100f;
}
});
_binding.On((in IAppRepo.GameExiting exiting) =>
{
AppLogic.Input(new AppLogicState.Input.EndGame(ExitGameReason.QuitToMenu));
});
MainMenu.NewGame += OnNewGame;
MainMenu.LastGame += () =>
{
var path = fileSystem.File.ReadAllText(Path.Combine(OS.GetUserDataDir(), "lastGame.txt"));
AppLogic.Input(new AppLogicState.Input.LoadGame());
OnLoadSaveGame(path);
};
MainMenu.LoadGame += OnLoadGame;
MainMenu.Options += OnOptions;
MainMenu.Exit += () => GetTree().Quit();
MainMenu.Mods += OnMods;
// =>
// {
// var vbox = new VBoxContainer();
// vbox.SetAnchorsPreset(Control.LayoutPreset.Center);
// foreach (var item in AppRepo.ModManger.AllMods.GetMods())
// {
// var b = new Button(){Text = item.ModName};
// b.Pressed += () =>
// {
// var p = AppRepo.ModManger.Profiles;
// if (p.Current.Contains(item))
// {
// p.Current.Remove(item);
// }
// else
// {
// p.Current.Add(item);
// }
// b.Text += "a";
// };
// vbox.AddChild(b);
// }
// MainMenu.AddChild(vbox);
// };
OptionsMenu.OnMenuExit += OnMenuExit;
CreateGameMenu.Exit += OnMenuExit;
CreateGameMenu.NewGame += OnNewGame;
CreateGameMenu.LevelSelected += (index) => GD.Print("selected ",index);
LoadingGameMenu.Exit += OnMenuExit;
LoadingGameMenu.LoadGame += index => OnLoadSaveGame(GetSaves()[index]);
MainMenu.SetLastGameVisible(fileSystem.File.Exists(Path.Combine(OS.GetUserDataDir(), "lastGame.txt")));
this.Provide();
}
private void OnLastGame()
{
AppLogic.Input(new AppLogicState.Input.LoadGame());
AppLogic.Input(new AppLogicState.Input.LoadSave());
}
private void OnMenuExit() => AppLogic.Input(new AppLogicState.Input.ExitMenu());
private void OnNewGame() => AppLogic.Input(new AppLogicState.Input.NewGame());
private void OnLoadGame() => AppLogic.Input(new AppLogicState.Input.LoadGame());
private void OnLoadSaveGame(string path)
{
SaveService.FilePath = path;
SaveService.CurrentSave = Chickensoft.SaveFileBuilder.SaveFile.CreateGZipJsonFile(
path,
_serializerOptions);
// Game.LoadExistingGame(GetSaves()[arg]);
GD.Print("save ", path, " loaded.");
AppLogic.Input(new AppLogicState.Input.LoadSave());
}
private void OnOptions() => AppLogic.Input(new AppLogicState.Input.Options());
private void OnMods() => AppLogic.Input(new AppLogicState.Input.Mods());
public void OnReady()
{
AppBinding = AppLogic.Bind();
AppBinding
.OnOutput((in AppLogicState.Output.ShowMainMenu _) =>
{
HideMenus();
MainMenu.Show();
//Fade In from black
})
.OnOutput((in AppLogicState.Output.StartLoadingSaveFile save) =>
{
Game.SaveFileLoaded += OnSaveFileLoaded;
Game.LoadGame();
})
.OnOutput((in AppLogicState.Output.RemoveExistingGame _) =>
{
GameViewPort.RemoveChildEx(Game);
Game.QueueFree();
Game = default!;
})
.OnOutput((in AppLogicState.Output.SetUpGameScene _) =>
{
Game = GD.Load<PackedScene>(GAME_PATH).Instantiate<Game>();
Game.Visible = false;
GameViewPort.AddChildEx(Game);
})
.OnOutput((in AppLogicState.Output.ShowGameCreationWindow _) =>
{
HideMenus();
CreateGameMenu.Initialize([.. GetLevels()]);
CreateGameMenu.Show();
})
.OnOutput((in AppLogicState.Output.ShowGameLoadingWindow _) =>
{
HideMenus();
LoadingGameMenu.Initialize(GetSaves());
LoadingGameMenu.Show();
})
.OnOutput((in AppLogicState.Output.ShowGame _) =>
{
HideMenus();
Game.Show();
})
.OnOutput((in AppLogicState.Output.QuitGame _) =>
{
GetTree().CallDeferred(SceneTree.MethodName.Quit);
})
.OnOutput((in AppLogicState.Output.ShowOptionMenu _) =>
{
HideMenus();
OptionsMenu.Show();
})
.OnOutput((in AppLogicState.Output.ShowModsMenu _) =>
{
HideMenus();
ModsMenu.Show();
})
;
AppLogic.Start<AppLogicState.MainMenu>();
}
private IReadOnlyList<string> GetSaves()
{
var fileSystem = new FileSystem();
var saves = fileSystem.Directory.EnumerateFiles(Path.Join(OS.GetUserDataDir(), "saves"));
return [.. saves];
}
private void OnSaveFileLoaded()
{
Game.SaveFileLoaded -= OnSaveFileLoaded;
AppLogic.Input(new AppLogicState.Input.SaveFileLoaded());
}
public void Setup()
{
}
public void OnExitTree()
{
AppLogic.Stop();
AppLogic.Dispose();
AppRepo.Dispose();
MainMenu.NewGame -= OnNewGame;
MainMenu.LoadGame -= OnLoadGame;
MainMenu.Options -= OnOptions;
MainMenu.Mods -= OnMods;
OptionsMenu.OnMenuExit -= OnMenuExit;
}
public void OnResolved()
{
}
public void HideMenus()
{
// Splash.Hide();
MainMenu.Hide();
CreateGameMenu.Hide();
LoadingGameMenu.Hide();
OptionsMenu.Hide();
ModsMenu.Hide();
}
public IEnumerable<LevelEntry> GetLevels()
{
yield return new LevelEntry("Level1", "res://assets/kenney_conveyor-kit/Sample.png");
yield return new LevelEntry("Level2", "res://assets/KayKit_Restaurant_Bits_1.0_FREE/sample.png");
yield return new LevelEntry("Level3", "res://assets/KayKit_Restaurant_Bits_1.0_FREE/contents.png");
}
public ISaveService Value() => SaveService;
// public override void _Ready()//=> new Test().TestECS();
// {
// // TestButton = GetNode<Button>("%TestButton");
// GD.Print(GameViewPort);
// }
// // public void OnTestButtonPressed() => ButtonPresses++;
// IGameLogic GameLogic = default!;
// LogicBlock.Binding GameLogicBinding = default!;
// Task task = default!;
// public void OnResolved()
// {
// // return;
// GD.Print("GLHF");
// GameLogic = new GameRootLogic();
// GameLogicBinding = GameLogic.Bind();
// GameLogicBinding
// .OnOutput((in GameRootLogicState.Output.QuitConfirmation _) => {
// var popup = new ConfirmationDialog();
// popup.Confirmed += () => GetTree().Quit();
// popup.Canceled += popup.QueueFree;
// popup.DialogText = "You sure you want to Quit";
// popup.OkButtonText = "Quit";
// popup.CancelButtonText = "Return to Menu";
// AddChild(popup);
// popup.PopupCentered();
// })
// .OnInput((in GameRootLogicState.Input.RequestQuit _) =>
// {
// }
// );
// // TestButton.ButtonUp += () => GameLogic.Input(new GameRootLogicState.Input.SaveRequested());
// GameLogic.Start<GameRootLogicState.MainMenu>();
// // GameLogic.Input(new GameLogicState.Input.Start());
// MainMenu.NewGame += () => GD.Print("New");
// MainMenu.LoadGame += () => GD.Print("Load");
// MainMenu.Options += () => GD.Print("Option");
// MainMenu.Mods += () => GD.Print("Mods");
// MainMenu.Exit += () => GameLogic.Input(new GameRootLogicState.Input.RequestQuit());
// }
}
// public interface IGameLogic : ILogicBlock
// {
// }
// [Meta]
// public partial class GameRootLogic : AutoBlock, IGameLogic
// {
// public GameRootLogic()
// {
// Preallocate<GameRootLogicState>();
// }
// }
// [Meta, StateDiagram]
// public abstract partial record GameRootLogicState : LogicBlockState
// {
// public static class Input
// {
// public readonly record struct Start;
// public readonly record struct Playing;
// public readonly record struct RequestQuit;
// // public readonly record struct SaveRequested;
// // public readonly record struct SaveCompleted;
// }
// public static class Output
// {
// // public readonly record struct StartSaving;
// public readonly record struct ShowMainMenu;
// public readonly record struct HideMainMenu;
// public readonly record struct QuitConfirmation;
// public readonly record struct Quit;
// }
// // [Meta]
// // public partial record Paused : GameRootLogicState, IGet<Input.SaveRequested>
// // {
// // public Paused()
// // {
// // this.OnEnter(() =>
// // {
// // GD.Print("enter paluse");
// // Output(new Output.ShowPauseMenu());
// // });
// // this.OnExit(()=>Output(new Output.HidePauseMenu()));
// // }
// // public Type On(in Input.SaveRequested input) => To<Saving>();
// // }
// // [Meta]
// // public partial record Saving : Paused, IGet<Input.SaveCompleted>
// // {
// // public Type On(in Input.SaveCompleted input) => To<MainMenu>();
// // public Saving()
// // {
// // this.OnEnter(
// // ()=>
// // {
// // GD.Print("enter save");
// // Output(new Output.StartSaving());
// // });
// // // this.OnExit(()=> Output(new Output.HidePauseMenu()));
// // }
// // }
// [Meta]
// public partial record MainMenu : GameRootLogicState, IGet<Input.RequestQuit>
// {
// public Type On(in Input.RequestQuit input) => To<ProcessQuit>();
// public MainMenu()
// {
// this.OnEnter(
// ()=>
// {
// GD.Print("enter menu");
// // Output(new Output.StartSaving());
// });
// // this.OnExit(()=> Output(new Output.HidePauseMenu()));
// }
// }
// [Meta]
// public partial record ProcessQuit : GameRootLogicState
// {
// public ProcessQuit()
// {
// this.OnEnter(
// ()=>
// {
// GD.Print("enter menu");
// Output(new Output.QuitConfirmation());
// });
// // this.OnExit(()=> Output(new Output.HidePauseMenu()));
// }
// }
// }

208
src/App/App.g.puml Normal file
View File

@@ -0,0 +1,208 @@
@startuml
package App-Type [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs]] {
class App {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs ScriptFile]]
[Properties]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:47 AppBinding]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:46 AppLogic]] - [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/AppLogic.cs Script]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:44 AppRepo]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:37 CreateGameMenu]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:42 Game]] - [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs Script]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:35 GameViewPort]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:38 LoadingGameMenu]] - [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs Script]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:36 MainMenu]] - [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs Script]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:40 ModsMenu]] - [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs Script]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:45 OptionConfig]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:39 OptionsMenu]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:59 SaveService]]
--
[Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:33 _Notification()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:70 BindSetting()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:299 GetLevels()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:252 GetSaves()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:288 HideMenus()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:72 Initialize()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:270 OnExitTree()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:165 OnLastGame()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:174 OnLoadGame()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:175 OnLoadSaveGame()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:172 OnMenuExit()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:187 OnMods()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:173 OnNewGame()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:186 OnOptions()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:189 OnReady()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:283 OnResolved()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:260 OnSaveFileLoaded()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:266 Setup()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/App.cs:306 Value()]]
}
class AppLogic {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/AppLogic.cs ScriptFile]]
[Constructors]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/App/AppLogic.cs:12 AppLogic]]()
}
package Game-Type [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs]] {
class Game {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs ScriptFile]]
[Properties]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:40 Environment]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:43 EquipmentTable]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:39 FileSystem]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:54 GameBinding]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:53 GameLogic]] - [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/GameLogicState.cs Script]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:48 OptionsMenu]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:47 PauseContainer]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:46 PauseMenu]] - [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs Script]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:49 PlayerCamera]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:38 SaveFile]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:41 SaveFilePath]]
--
[Interface Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:162 LoadGame()]]
[Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:33 _Notification()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:218 _UnhandledInput()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:169 HideMenus()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:71 Initialize()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:232 Load()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:233 LoadExistingGame()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:198 OnExitTree()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:103 OnReady()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:201 OnResolved()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:82 OnSaveButton()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:97 OpenOptions()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:85 PauseButtonPressed()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:84 QuitToDesktop()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:83 QuitToMainMenu()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:228 Save()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:143 SaveGame()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:155 SaveGame2()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/Game.cs:175 Setup()]]
}
class GameLogicState {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/GameLogicState.cs ScriptFile]]
[Constructors]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/Game/GameLogicState.cs:14 GameLogic]]()
}
class PauseMenu {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs ScriptFile]]
[Properties]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:29 BackToGameButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:30 OptionsButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:33 QuitToDesktopButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:32 QuitToMainMenuButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:31 SaveButton]]
--
[Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:27 _Notification()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:44 Initialize()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:79 OnExitTree()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:55 OnReady()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:84 OnResolved()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/PauseMenu/PauseMenu.cs:74 Setup()]]
}
Game::GameLogicState ---> GameLogicState
Game::PauseMenu ---> PauseMenu
}
class LoadingGameMenu {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs ScriptFile]]
[Properties]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:26 ExitButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:25 ItemList]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:24 LoadGameButton]]
--
[Interface Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:32 Initialize()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:36 Initialize()]]
[Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:22 _Notification()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:65 OnExitTree()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:56 OnGameLoad()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:63 OnItemSelected()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:49 OnReady()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:70 OnResolved()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/LoadingGameMenu.cs:45 Setup()]]
}
class MainMenu {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs ScriptFile]]
[Properties]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:29 ExitButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:24 LastGameButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:26 LoadGameButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:28 ModsButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:25 NewGameButton]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:27 OptionsButton]]
--
[Interface Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:70 SetLastGameVisible()]]
[Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:23 _Notification()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:39 Initialize()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:56 OnExitTree()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:47 OnReady()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:65 OnResolved()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/TitleMenu/MainMenu.cs:43 Setup()]]
}
package ModMenu-Type [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs]] {
class ModMenu {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs ScriptFile]]
[Properties]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:15 ModEntryScene]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:17 ModManger]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:18 ModsContainer]] - [[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs Script]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:19 ProfilesButton]]
--
[Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:74 _ExitTree()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:14 _Notification()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:26 OnModProfileSelected()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:20 OnResolved()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:32 OnVisibilityChanged()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ModMenu/ModMenu.cs:40 RefreshMods()]]
}
class ReOrderableContainer {
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs ScriptFile]]
[Properties]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:62 AutoScrollRange]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:61 AutoScrollSpeed]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:23 HoldDuration]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:64 IsDebugging]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:38 IsVertical]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:60 ScrollContainer]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:63 ScrollThreshold]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:25 Separation]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:24 Speed]]
--
[Methods]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:148 _Draw()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:95 _GuiInput()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:20 _Notification()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:115 _Process()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:319 AdjustChildRect()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:364 AdjustDropZoneRect()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:294 AdjustExpectedChildRect()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:404 AsIReOrderableContainer()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:405 GetVisibleChildren()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:238 HandleAutoScroll()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:207 HandleDraggingChildPos()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:159 HandleInput()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:267 OnExitTree()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:276 OnNodeAdded()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:80 OnReady()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:284 OnSortChildren()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:283 OnSortChildrenWrapper()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:175 OnStartDragging()]]
[[vscode://file//home/ronnie/Documents/Godot/Projects/ChickenGameTest/src/ReorderableContainer/ReOrderableContainer.cs:186 OnStopDragging()]]
}
ModMenu::ReOrderableContainer ---> ReOrderableContainer
}
App::AppLogic ---> AppLogic
App::Game ---> Game
App::LoadingGameMenu ---> LoadingGameMenu
App::MainMenu ---> MainMenu
App::ModMenu ---> ModMenu
}
@enduml

84
src/App/App.tscn Normal file
View File

@@ -0,0 +1,84 @@
[gd_scene format=3 uid="uid://cywpu6lxdjhuu"]
[ext_resource type="Script" uid="uid://bcadf3uhcfy2" path="res://src/App/App.cs" id="1_tn3dc"]
[ext_resource type="PackedScene" uid="uid://nwt8o860iibl" path="res://src/TitleMenu/MainMenu.tscn" id="3_sb8ss"]
[ext_resource type="PackedScene" uid="uid://dkgrn8n1on4ec" path="res://src/TitleMenu/CreateGameMenu.tscn" id="4_qlumy"]
[ext_resource type="PackedScene" uid="uid://b7x2w61dwafxe" path="res://src/TitleMenu/LoadingGameMenu.tscn" id="5_sb8ss"]
[ext_resource type="PackedScene" uid="uid://bf3a5w3h1evaf" path="res://src/OptionsMenu/OptionMenu.tscn" id="6_6skpx"]
[ext_resource type="Script" uid="uid://c0qxjltjv53u7" path="res://addons/controller_icons/objects/ControllerIconTexture.cs" id="6_fj5p6"]
[ext_resource type="PackedScene" uid="uid://cgp6gntheq4g6" path="res://src/ModMenu/ModMenu.tscn" id="7_6skpx"]
[sub_resource type="Texture2D" id="Texture2D_6skpx"]
resource_local_to_scene = false
resource_name = ""
script = ExtResource("6_fj5p6")
path = "move_forward"
metadata/_custom_type_script = "uid://c0qxjltjv53u7"
[node name="App" type="CanvasLayer" unique_id=2068981625]
process_mode = 3
script = ExtResource("1_tn3dc")
[node name="GameSession" type="Control" parent="." unique_id=1185123368]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="SubViewportContainer" type="SubViewportContainer" parent="GameSession" unique_id=2046367171]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
stretch = true
[node name="GameViewPort" type="SubViewport" parent="GameSession/SubViewportContainer" unique_id=1388492347]
unique_name_in_owner = true
own_world_3d = true
handle_input_locally = false
size = Vector2i(720, 720)
render_target_update_mode = 4
[node name="CenterContainer" type="CenterContainer" parent="." unique_id=1905436581]
visible = false
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer" unique_id=1941107825]
layout_mode = 2
[node name="TestButton" type="Button" parent="CenterContainer/VBoxContainer" unique_id=1060152075]
unique_name_in_owner = true
layout_mode = 2
text = "Test Button"
[node name="OptionsMenu" parent="." unique_id=2143215493 instance=ExtResource("6_6skpx")]
unique_name_in_owner = true
visible = false
[node name="MainMenu" parent="." unique_id=869490384 instance=ExtResource("3_sb8ss")]
unique_name_in_owner = true
[node name="CreateGameMenu" parent="." unique_id=1233498611 instance=ExtResource("4_qlumy")]
unique_name_in_owner = true
visible = false
[node name="LoadingGameMenu" parent="." unique_id=1791717647 instance=ExtResource("5_sb8ss")]
unique_name_in_owner = true
visible = false
[node name="Sprite2D" type="Sprite2D" parent="." unique_id=1847137886]
texture = SubResource("Texture2D_6skpx")
[node name="ModsMenu" parent="." unique_id=1651472975 instance=ExtResource("7_6skpx")]
unique_name_in_owner = true
visible = false
[connection signal="pressed" from="CenterContainer/VBoxContainer/TestButton" to="." method="OnTestButtonPressed"]

17
src/App/AppLogic.cs Normal file
View File

@@ -0,0 +1,17 @@
namespace FoodFactory;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
using Chickensoft.LogicBlocks.Auto;
public interface IAppLogic : ILogicBlock;
[Meta]
public partial class AppLogic : AutoBlock, IAppLogic
{
public AppLogic()
{
Preallocate<AppLogicState>();
}
}

1
src/App/AppLogic.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://dugahjx2qt4fq

View File

@@ -0,0 +1,22 @@
namespace FoodFactory;
public abstract partial record AppLogicState
{
public static class Input
{
public readonly record struct ExitMenu;
public readonly record struct NewGame;
public readonly record struct LoadGame;
public readonly record struct LoadSave;
public readonly record struct Options;
public readonly record struct Mods;
public readonly record struct EndGame(ExitGameReason Reason = ExitGameReason.QuitToMenu);
public readonly record struct SaveFileLoaded;
}
}
public enum ExitGameReason
{
QuitToDesktop,
QuitToMenu,
}

View File

@@ -0,0 +1 @@
uid://cvvofc4v4vmr5

View File

@@ -0,0 +1,25 @@
namespace FoodFactory;
public abstract partial record AppLogicState
{
public static class Output
{
public readonly record struct StartLoadingSaveFile();
// public readonly record struct StartLoadingSaveFile(LoadGameArgs Save);
public readonly record struct SetUpGameScene;
public readonly record struct ShowGameCreationWindow;
// public readonly record struct HideGameCreationWindow;
public readonly record struct ShowMainMenu;
public readonly record struct ShowOptionMenu;
public readonly record struct ShowModsMenu;
// public readonly record struct ShowHideMenu;
public readonly record struct PlayGame;
public readonly record struct ShowGame;
// public readonly record struct HideGame;
public readonly record struct RemoveExistingGame;
public readonly record struct ShowGameLoadingWindow;
public readonly record struct QuitGame;
// public readonly record struct HideGameLoadingWindow;
}
}

View File

@@ -0,0 +1 @@
uid://chh4b4blwffef

7
src/App/AppLogicState.cs Normal file
View File

@@ -0,0 +1,7 @@
namespace FoodFactory;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
[Meta, StateDiagram]
public abstract partial record AppLogicState : LogicBlockState;

View File

@@ -0,0 +1 @@
uid://c1315dvv52mf0

View File

@@ -0,0 +1,35 @@
@startuml AppLogicState
state "AppLogicState" as FoodFactory_AppLogicState {
state "CreatingGame" as FoodFactory_AppLogicState_CreatingGame
state "InGame" as FoodFactory_AppLogicState_InGame
state "LeavingGame" as FoodFactory_AppLogicState_LeavingGame
state "LoadingGame" as FoodFactory_AppLogicState_LoadingGame
state "MainMenu" as FoodFactory_AppLogicState_MainMenu
state "ModsMenu" as FoodFactory_AppLogicState_ModsMenu
state "OptionMenu" as FoodFactory_AppLogicState_OptionMenu
}
FoodFactory_AppLogicState_CreatingGame --> FoodFactory_AppLogicState_InGame : NewGame
FoodFactory_AppLogicState_CreatingGame --> FoodFactory_AppLogicState_MainMenu : ExitMenu
FoodFactory_AppLogicState_InGame --> FoodFactory_AppLogicState_MainMenu : EndGame
FoodFactory_AppLogicState_LeavingGame --> FoodFactory_AppLogicState_MainMenu : EndGame
FoodFactory_AppLogicState_LoadingGame --> FoodFactory_AppLogicState_InGame : LoadSave
FoodFactory_AppLogicState_LoadingGame --> FoodFactory_AppLogicState_MainMenu : ExitMenu
FoodFactory_AppLogicState_MainMenu --> FoodFactory_AppLogicState_CreatingGame : NewGame
FoodFactory_AppLogicState_MainMenu --> FoodFactory_AppLogicState_LoadingGame : LoadGame
FoodFactory_AppLogicState_MainMenu --> FoodFactory_AppLogicState_ModsMenu : Mods
FoodFactory_AppLogicState_MainMenu --> FoodFactory_AppLogicState_OptionMenu : Options
FoodFactory_AppLogicState_ModsMenu --> FoodFactory_AppLogicState_MainMenu : ExitMenu
FoodFactory_AppLogicState_OptionMenu --> FoodFactory_AppLogicState_MainMenu : ExitMenu
FoodFactory_AppLogicState_CreatingGame : OnEnter → ShowGameCreationWindow
FoodFactory_AppLogicState_CreatingGame : OnNewGame → SetUpGameScene
FoodFactory_AppLogicState_InGame : OnEndGame → RemoveExistingGame
FoodFactory_AppLogicState_InGame : OnEnter → ShowGame
FoodFactory_AppLogicState_LeavingGame : OnEndGame → QuitGame, RemoveExistingGame
FoodFactory_AppLogicState_LoadingGame : OnEnter → ShowGameLoadingWindow
FoodFactory_AppLogicState_LoadingGame : OnLoadSave → SetUpGameScene, StartLoadingSaveFile
FoodFactory_AppLogicState_MainMenu : OnEnter → ShowMainMenu
FoodFactory_AppLogicState_ModsMenu : OnEnter → ShowModsMenu
FoodFactory_AppLogicState_OptionMenu : OnEnter → ShowOptionMenu
@enduml

59
src/App/AppRepo.cs Normal file
View File

@@ -0,0 +1,59 @@
namespace FoodFactory;
using System;
using Chickensoft.Sync.Primitives;
using FoodFactory.Modding;
using Godot;
using TrimKit.VirtualFileSystem;
public interface IAppRepo : IDisposable
{
readonly record struct GameEntering;
readonly record struct GameExiting;
readonly record struct GameSettingChanged(IOptionKey Setting, Variant Value);
void OnEnteringGame();
void OnExitGame();
void OnSettingChanged(IOptionKey setting, Variant value);
IAutoChannel AutoChannel { get; }
IModManger ModManger { get; }
}
public class AppRepo : IAppRepo
{
private readonly AutoChannel _autoChannel = new();
private bool _disposedValue;
public IAutoChannel AutoChannel => _autoChannel;
// private readonly IModManger _vFSManager;
public required IModManger ModManger {get;init;}
public void OnEnteringGame() => _autoChannel.Send(new IAppRepo.GameEntering());
public void OnExitGame() => _autoChannel.Send(new IAppRepo.GameExiting());
public void OnSettingChanged(IOptionKey setting, Variant value) => _autoChannel.Send(new IAppRepo.GameSettingChanged(setting, value));
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects)
_autoChannel.Dispose();
ModManger.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null
_disposedValue = true;
}
}
void IDisposable.Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}

1
src/App/AppRepo.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://cgp65d616yhl0

View File

@@ -0,0 +1,53 @@
namespace FoodFactory;
using System;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
public partial record AppLogicState
{
[Meta]
public partial record CreatingGame : AppLogicState, IGet<Input.ExitMenu>, IGet<Input.NewGame>
{
public CreatingGame()
{
this.OnEnter(() =>
{
Output(new Output.ShowGameCreationWindow());
});
}
public Type On(in Input.ExitMenu input) => To<MainMenu>();
public Type On(in Input.NewGame input)
{
Output(new Output.SetUpGameScene());
return To<InGame>();
}
}
[Meta]
public partial record OptionMenu : AppLogicState, IGet<Input.ExitMenu>
{
public OptionMenu()
{
this.OnEnter(() =>
{
Output(new Output.ShowOptionMenu());
});
}
public Type On(in Input.ExitMenu input) => To<MainMenu>();
}
[Meta]
public partial record ModsMenu : AppLogicState, IGet<Input.ExitMenu>
{
public ModsMenu()
{
this.OnEnter(() =>
{
Output(new Output.ShowModsMenu());
});
}
public Type On(in Input.ExitMenu input) => To<MainMenu>();
}
}

View File

@@ -0,0 +1 @@
uid://coo66h6424rhu

28
src/App/States/InGame.cs Normal file
View File

@@ -0,0 +1,28 @@
namespace FoodFactory;
using System;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
public partial record AppLogicState
{
[Meta]
public partial record InGame : AppLogicState, IGet<Input.EndGame>
{
public InGame()
{
this.OnEnter(() =>
{
Get<IAppRepo>().OnEnteringGame();
Output(new Output.ShowGame());
});
}
public Type On(in Input.EndGame input)
{
// return To<LeavingGame>();
Output(new Output.RemoveExistingGame());
return To<MainMenu>();
}
}
}

View File

@@ -0,0 +1 @@
uid://cqaqghb5xytb8

View File

@@ -0,0 +1,31 @@
namespace FoodFactory;
using System;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
public partial record AppLogicState
{
[Meta]
public partial record LeavingGame : AppLogicState, IGet<Input.EndGame>
{
public LeavingGame()
{
this.OnEnter(() =>
{
// Output(new Output.ShowGame());
});
}
public Type On(in Input.EndGame input){
Output(new Output.RemoveExistingGame());
if (input.Reason == ExitGameReason.QuitToDesktop)
{
Output(new Output.QuitGame());
}
return To<MainMenu>();
}
}
}

View File

@@ -0,0 +1 @@
uid://xumdrcvr86av

View File

@@ -0,0 +1,29 @@
namespace FoodFactory;
using System;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
public partial record AppLogicState
{
[Meta]
public partial record LoadingGame : AppLogicState, IGet<Input.ExitMenu>, IGet<Input.LoadSave>
{
public LoadingGame()
{
this.OnEnter(() =>
{
Output(new Output.ShowGameLoadingWindow());
});
}
public Type On(in Input.ExitMenu input) => To<MainMenu>();
public Type On(in Input.LoadSave input)
{
Output(new Output.SetUpGameScene());
Output(new Output.StartLoadingSaveFile());
return To<InGame>();
}
}
}

View File

@@ -0,0 +1 @@
uid://bovjntefvngmh

View File

@@ -0,0 +1,26 @@
namespace FoodFactory;
using System;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
public partial record AppLogicState
{
[Meta]
public partial record MainMenu : AppLogicState,
IGet<Input.NewGame>, IGet<Input.LoadGame>, IGet<Input.Options>, IGet<Input.Mods>
{
public MainMenu()
{
this.OnEnter(() =>
{
Output(new Output.ShowMainMenu());
});
}
public Type On(in Input.LoadGame input) => To<LoadingGame>();
public Type On(in Input.NewGame input) => To<CreatingGame>();
public Type On(in Input.Options input) => To<OptionMenu>();
public Type On(in Input.Mods input) => To<ModsMenu>();
}
}

View File

@@ -0,0 +1 @@
uid://c6qr7sej5f6vh

View File

@@ -1,15 +0,0 @@
namespace FoodFactory;
using Godot;
public partial class Game : Control
{
public Button TestButton { get; private set; } = default!;
public int ButtonPresses { get; private set; }
public override void _Ready()=> new Test().TestECS();
// => TestButton = GetNode<Button>("%TestButton");
public void OnTestButtonPressed() => ButtonPresses++;
}

8
src/Game.g.puml Normal file
View File

@@ -0,0 +1,8 @@
@startuml GameRootLogicState
state "GameRootLogicState" as FoodFactory_GameRootLogicState {
state "MainMenu" as FoodFactory_GameRootLogicState_MainMenu
state "ProcessQuit" as FoodFactory_GameRootLogicState_ProcessQuit
}
FoodFactory_GameRootLogicState_MainMenu --> FoodFactory_GameRootLogicState_ProcessQuit : RequestQuit
@enduml

View File

@@ -1,30 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://cywpu6lxdjhuu"]
[ext_resource type="Script" path="res://src/Game.cs" id="1_17mmo"]
[node name="Control" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_17mmo")
[node name="CenterContainer" type="CenterContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
layout_mode = 2
[node name="TestButton" type="Button" parent="CenterContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Test Button"
[connection signal="pressed" from="CenterContainer/VBoxContainer/TestButton" to="." method="OnTestButtonPressed"]

293
src/Game/Game.cs Normal file
View File

@@ -0,0 +1,293 @@
namespace FoodFactory;
using System;
using System.IO;
using System.IO.Abstractions;
using System.Text.Json;
using System.Threading.Tasks;
using Arch.Core;
using Chickensoft.AutoInject;
using Chickensoft.Collections;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
using Chickensoft.SaveFileBuilder;
using Chickensoft.Serialization;
using Chickensoft.Sync.Primitives;
using FoodFactory.Equipment;
using Godot;
public interface IGame : INode3D, IProvide<IGameRepo>, IProvide<EntityTable>, ISaveable<GameData>
{
event Game.SaveFileLoadedEventHandler SaveFileLoaded;
ValueTask LoadGame();
// void LoadExistingGame(LoadGameArgs args);
}
// public abstract record LoadGameArgs();
// public record LoadRecentGame : LoadGameArgs;
// public record LoadGameByName(string Name) : LoadGameArgs;
[Meta(typeof(IAutoNode))]
public partial class Game : Node3D, IGame
{
public override void _Notification(int what) => this.Notify(what);
public IGameRepo GameRepo = default!;
IGameRepo IProvide<IGameRepo>.Value() => GameRepo;
[Dependency] public IAppRepo AppRepo => this.DependOn<IAppRepo>();
[Dependency] public ISaveService SaveService => this.DependOn<ISaveService>();
public ISaveFile SaveFile => SaveService.CurrentSave;
public IFileSystem FileSystem {get;set;} = default!;
public IEnvironmentProvider Environment { get; set; } = default!;
public string SaveFilePath { get; set; } = $"{OS.GetUserDataDir()}/SaveFile.json";//default!;
public EntityTable EquipmentTable { get; set; } = default!;
EntityTable IProvide<EntityTable>.Value() => EquipmentTable;
[Node] public IPauseMenu PauseMenu { get; set; } = default!;
[Node] public INode3D PauseContainer { get; set; } = default!;
[Node] public IOptionsMenu OptionsMenu { get; set; } = default!;
[Node] public RTSCamera PlayerCamera { get; set; } = default!;
// public ISaveChunk<GameData> GameChunk { get; set; } = default!;
// ISaveChunk<GameData> IProvide<ISaveChunk<GameData>>.Value() => GameChunk;
public IGameLogic GameLogic {get;set;} = default!;
public LogicBlock.Binding GameBinding { get; set; } = default!;
private JsonSerializerOptions _options;
// public void LoadExistingGame(LoadGameArgs args)
// {
// switch (args)
// {
// case LoadGameByName name:
// break;
// case LoadRecentGame _:
// break;
// default:
// throw new NotSupportedException();
// }
// }
public void Initialize()
{
PauseMenu.OnResume += PauseButtonPressed;
PauseMenu.OnOptions += OpenOptions;
OptionsMenu.OnMenuExit += PauseButtonPressed;
PauseMenu.OnQuitToMainMenu += QuitToMainMenu;
PauseMenu.OnQuitToDesktop += QuitToDesktop;
PauseMenu.OnSave += OnSaveButton;
GameLogic = new GameLogic();
}
private void OnSaveButton() => GameLogic.Input(new GameLogicState.Input.SaveRequested());
private void QuitToMainMenu() => GameLogic.Input(new GameLogicState.Input.GotoMainMenu());
private void QuitToDesktop() => GameLogic.Input(new GameLogicState.Input.GotoDesktop());
private void PauseButtonPressed() => GameLogic.Input(new GameLogicState.Input.PauseButtonPressed());
// private void PauseGame() => GameLogic.Input(new GameLogicState.Input.PauseGame());
// if (GetTree().Paused)
// {
// PauseMenu.Show();
// }
// else
// {
// PauseMenu.Hide();
// }
// }
private void OpenOptions()
{
// GetParent().GetParent().GetParent().GetParent<App>().OptionsMenu.Show();
GameLogic.Input(new GameLogicState.Input.OpenOptionMenu());
}
public void OnReady()
{
GameBinding = GameLogic.Bind();
GameBinding.OnOutput((in GameLogicState.Output.SetPauseMode _) =>
{
GetTree().Paused = !GetTree().Paused;
}).OnOutput((in GameLogicState.Output.ShowOptionMenu _) =>
{
HideMenus();
OptionsMenu.Show();
})
// .OnOutput((in GameLogicState.Output.ShowOptionMenu _) =>
// {
// OptionsMenu.Hide();
// })
.OnOutput((in GameLogicState.Output.ShowPauseMenu _) =>
{
HideMenus();
PauseMenu.Show();
})
.OnOutput((in GameLogicState.Output.HideMenus _) => HideMenus())
.OnOutput((in GameLogicState.Output.StartSaving _) => SaveGame2())
.OnInput((in GameLogicState.Input.SaveCompleted _) => {
var path = Path.Combine(OS.GetUserDataDir(), "lastGame.txt");
File.WriteAllText(path,SaveService.FilePath);
})
// .OnOutput((in GameLogicState.Output.ExitPauseMenu _) =>
// {
// HideMenus();
// })
// .OnOutput((in GameLogicState.Output.HidePauseMenu _) =>
// {
// PauseMenu.Hide();
// })
;
GameLogic.Start<GameLogicState.Playing>();
}
private async ValueTask SaveGame()
{
GD.Print("started save");
try{
await SaveFile.SaveAsync(Save());
} catch (Exception ex)// Catches an silent error
{
throw;
}
GD.Print("Saved ");
GameLogic.Input(new GameLogicState.Input.SaveCompleted());
}
private void SaveGame2()
{
GD.Print("started save");
SaveFile.Save(Save());
GD.Print("Saved ");
GameLogic.Input(new GameLogicState.Input.SaveCompleted());
}
public async ValueTask LoadGame()
{
var data = await SaveFile.LoadAsync<GameData>();
Load(data);
EmitSignalSaveFileLoaded();
}
private void HideMenus()
{
OptionsMenu.Hide();
PauseMenu.Hide();
}
public void Setup()
{
GameRepo = new GameRepo();
GameLogic.Set(GameRepo);
GameLogic.Set(AppRepo);
FileSystem = new FileSystem();
// GameChunk = new SaveChunk<GameData>(
// (chunk) =>
// {
// var game_data = new GameData()
// {
// // LevelData = chunk.GetChunkSaveData<LevelData>()
// };
// return game_data;
// },
// onLoad: (chunk, data) =>{
// chunk.LoadChunkSaveData(data.LevelData);
// }
// );
}
public void OnExitTree()
{
}
public void OnResolved()
{
// SaveFile = new SaveFile<GameData>(GameChunk,
// async onSave =>
// {
// var data = JsonSerializer.Serialize(onSave, _options);
// await FileSystem.File.WriteAllTextAsync(SaveFilePath, data);
// },
// async () =>
// {
// var data = await FileSystem.File.ReadAllTextAsync(SaveFilePath);
// return JsonSerializer.Deserialize<GameData>(data, _options);
// }
// );
this.Provide();
}
public override void _UnhandledInput(InputEvent @event)
{
if (@event.IsActionReleased("ui_cancel"))
{
PauseButtonPressed();
// GameRepo.Pause();
// PauseMenu.Show();
}
}
public GameData Save() => new GameData()
{
PlayerCamera = PlayerCamera.Save()
};
public void Load(in GameData data) => PlayerCamera.Load(data.PlayerCamera);
public void LoadExistingGame()
{
LoadGame();
}
[Signal] public delegate void SaveFileLoadedEventHandler();
}
public interface IGameRepo
{
IAutoChannel AutoChannel { get; }
// IEquipmentManger EquipmentManger {get;}
IAutoValue<bool> IsPaused { get; }
IAutoValue<bool> IsMouseCaptured { get; }
void Pause();
void Resume();
}
public class GameRepo : IGameRepo
{
private readonly AutoChannel _autoChannel = new();
public IAutoChannel AutoChannel => _autoChannel;
private readonly AutoValue<bool> _isPaused;
public IAutoValue<bool> IsPaused => _isPaused;
private readonly AutoValue<bool> _isMouseCaptured;
public IAutoValue<bool> IsMouseCaptured => _isMouseCaptured;
public void Pause(){
_isPaused.Value = true;
_isMouseCaptured.Value = false;
}
public void Resume()
{
_isPaused.Value = false;
_isMouseCaptured.Value = true;
}
public GameRepo()
{
_isPaused = new(false);
_isMouseCaptured = new(false);
}
}
public interface IEquipmentManger
{
}
public class EquipmentTable : EntityTable<EquipmentId>
{
}
public interface ISaveService
{
string FilePath {get;set;}
ISaveFile CurrentSave { get; set;}
}
public sealed class SaveService : ISaveService
{
public required string FilePath {get;set;}
public required ISaveFile CurrentSave { get; set; }
}

1
src/Game/Game.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://bglv0u52nwcbi

37
src/Game/Game.tscn Normal file
View File

@@ -0,0 +1,37 @@
[gd_scene format=3 uid="uid://2cge61hbkepr"]
[ext_resource type="Script" uid="uid://bglv0u52nwcbi" path="res://src/Game/Game.cs" id="1_ggd3w"]
[ext_resource type="PackedScene" uid="uid://dr5gfg25sjr04" path="res://src/VoxelGrid/RtsController.tscn" id="1_i3df7"]
[ext_resource type="PackedScene" uid="uid://ermyaow1y331" path="res://src/PauseMenu/PauseMenu.tscn" id="3_5fh4b"]
[ext_resource type="PackedScene" uid="uid://bf3a5w3h1evaf" path="res://src/OptionsMenu/OptionMenu.tscn" id="4_0fb64"]
[sub_resource type="BoxMesh" id="BoxMesh_d3xpa"]
[node name="Game" type="Node3D" unique_id=241104626]
script = ExtResource("1_ggd3w")
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=927235587]
mesh = SubResource("BoxMesh_d3xpa")
[node name="EquipmentManger" type="Node3D" parent="." unique_id=949464651]
[node name="PauseContainer" type="Node3D" parent="." unique_id=96938972]
unique_name_in_owner = true
process_mode = 1
[node name="PlayerCamera" parent="PauseContainer" unique_id=1383983755 instance=ExtResource("1_i3df7")]
unique_name_in_owner = true
[node name="InGameUi" type="Control" parent="." unique_id=1695973023]
layout_mode = 3
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="PauseMenu" parent="." unique_id=1396653727 instance=ExtResource("3_5fh4b")]
unique_name_in_owner = true
visible = false
[node name="OptionsMenu" parent="." unique_id=2143215493 instance=ExtResource("4_0fb64")]
unique_name_in_owner = true
visible = false

141
src/Game/GameLogicState.cs Normal file
View File

@@ -0,0 +1,141 @@
using FoodFactory;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
using Chickensoft.LogicBlocks.Auto;
using System;
using Microsoft.Extensions.Options;
public interface IGameLogic : ILogicBlock;
[Meta]
public partial class GameLogic : AutoBlock, IGameLogic
{
public GameLogic()
{
Preallocate<GameLogicState>();
}
}
[Meta, StateDiagram]
public abstract partial record GameLogicState : LogicBlockState;
// [Meta]
public abstract partial record GameLogicState
{
[Meta]
public partial record Playing : GameLogicState, IGet<Input.PauseButtonPressed>
{
public Playing()
{
this.OnEnter(
() =>
{
Output(new Output.HideMenus());
}
);
}
public Type On(in Input.PauseButtonPressed input) => To<Paused>();
}
[Meta]
public partial record Paused : GameLogicState
, IGet<Input.PauseButtonPressed>
, IGet<Input.OpenOptionMenu>
, IGet<Input.SaveRequested>
, IGet<Input.GotoMainMenu>
{
public Paused()
{
this.OnEnter(
() =>
{
Get<IGameRepo>().Pause();
Output(new Output.ShowPauseMenu());
Output(new Output.SetPauseMode(true));
}
);
this.OnExit(() =>
{
Output(new Output.ExitPauseMenu());
// Output(new Output.HidePauseMenu());
Output(new Output.SetPauseMode(false));
});
}
public Type On(in Input.SaveRequested input) => To<Saving>();
public virtual Type On(in Input.PauseButtonPressed input) => To<Playing>();
public virtual Type On(in Input.GotoMainMenu input) => To<Quit>();
public virtual Type On(in Input.OpenOptionMenu input) => To<OptionsMenu>();
}
[Meta]
public partial record OptionsMenu : Paused
{
public OptionsMenu()
{
this.OnEnter(
() =>
{
Output(new Output.ShowOptionMenu());
}
);
// this.OnExit(() => Output(new Output.HideMenus()));
}
public override Type On(in Input.PauseButtonPressed input)
{
Output(new Output.ShowPauseMenu());
return To<Paused>();
}
public override Type On(in Input.OpenOptionMenu input) => ToSelf();
}
[Meta]
public partial record Saving : Paused
, IGet<Input.SaveCompleted>
{
public Saving()
{
this.OnEnter(() =>
{
Output(new Output.ShowPauseSaveOverlay());
Output(new Output.StartSaving());
});
}
public override Type On(in Input.PauseButtonPressed input) => ToSelf();
public Type On(in Input.SaveCompleted input) => To<Paused>();
public override Type On(in Input.OpenOptionMenu input) => ToSelf();
public override Type On(in Input.GotoMainMenu input) => ToSelf();
}
[Meta]
public partial record Quit : GameLogicState
{
public Quit()
{
this.OnEnter(
() => Get<IAppRepo>().OnExitGame()
);
}
}
public static class Input
{
public readonly record struct PauseGame;
public readonly record struct PauseButtonPressed;
public readonly record struct OpenOptionMenu;
public readonly record struct SaveRequested;
public readonly record struct SaveCompleted;
public readonly record struct GotoMainMenu;
public readonly record struct GotoDesktop;
}
public static class Output
{
public readonly record struct SetPauseMode(bool IsPaused);
public readonly record struct ShowPauseMenu;
// public readonly record struct HidePauseMenu;
public readonly record struct HideMenus;
public readonly record struct ExitPauseMenu;
public readonly record struct ShowOptionMenu;
// public readonly record struct HideOptionMenu;
public readonly record struct ShowPauseSaveOverlay;
public readonly record struct StartSaving();
}
}

View File

@@ -0,0 +1 @@
uid://dj8iyb644p25d

View File

@@ -0,0 +1,29 @@
@startuml GameLogicState
state "GameLogicState" as GameLogicState {
state "Paused" as GameLogicState_Paused {
state "OptionsMenu" as GameLogicState_OptionsMenu
state "Saving" as GameLogicState_Saving
}
state "Playing" as GameLogicState_Playing
state "Quit" as GameLogicState_Quit
}
GameLogicState_OptionsMenu --> GameLogicState_OptionsMenu : OpenOptionMenu
GameLogicState_OptionsMenu --> GameLogicState_Paused : PauseButtonPressed
GameLogicState_Paused --> GameLogicState_OptionsMenu : OpenOptionMenu
GameLogicState_Paused --> GameLogicState_Playing : PauseButtonPressed
GameLogicState_Paused --> GameLogicState_Quit : GotoMainMenu
GameLogicState_Paused --> GameLogicState_Saving : SaveRequested
GameLogicState_Playing --> GameLogicState_Paused : PauseButtonPressed
GameLogicState_Saving --> GameLogicState_Paused : SaveCompleted
GameLogicState_Saving --> GameLogicState_Saving : GotoMainMenu
GameLogicState_Saving --> GameLogicState_Saving : OpenOptionMenu
GameLogicState_Saving --> GameLogicState_Saving : PauseButtonPressed
GameLogicState_OptionsMenu : OnEnter → ShowOptionMenu
GameLogicState_OptionsMenu : OnPauseButtonPressed → ShowPauseMenu
GameLogicState_Paused : OnEnter → SetPauseMode, ShowPauseMenu
GameLogicState_Paused : OnExit → ExitPauseMenu, SetPauseMode
GameLogicState_Playing : OnEnter → HideMenus
GameLogicState_Saving : OnEnter → ShowPauseSaveOverlay, StartSaving
@enduml

View File

@@ -305,10 +305,13 @@ public record struct Handle(int Index, int Version);
[Meta, Id("game_data")]
public partial record GameData
{
[Save("world_data")]
public required World World { get; init; }
// [Save("equipments_data")]
// public required Dictionary<EquipmentId, EquipmentData> Equipments { get; init; }
[Save("player_camera")]
public required SaveData PlayerCamera {get;set;}
// [Save("world_data")]
// public required World World { get; init; }
// [Save("level_data")]
// public required LevelData LevelData { get; init; }
// public required EquipmentsData Equipments { get; init; }//TempTest /\
}
// [Meta, Id("equipments_data")]
@@ -323,6 +326,6 @@ public partial record GameData
public abstract partial record EquipmentData
{
[Save("guid_data")]
public required EquipmentId Id { get; init; }
// [Save("guid_data")]
// public required EquipmentId Id { get; init; }
}

0
src/Levels/Level.cs Normal file
View File

1
src/Levels/Level.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://c2r8pok0qhgyr

14
src/Levels/LevelData.cs Normal file
View File

@@ -0,0 +1,14 @@
namespace FoodFactory;
using System.Collections.Generic;
using Chickensoft.Introspection;
using Chickensoft.Serialization;
using FoodFactory.Equipment;
[Meta, Id("level_data")]
public partial record LevelData
{
[Save("equipment_data")]
public required Dictionary<EquipmentId, EquipmentData> Equipments { get; init; }
}

View File

@@ -0,0 +1 @@
uid://bstyh1fvqb3vq

View File

@@ -48,5 +48,5 @@ public partial class Main : Node2D
#endif
private void RunScene()
=> GetTree().ChangeSceneToFile("res://src/Game.tscn");
=> GetTree().ChangeSceneToFile("res://src/App/App.tscn");
}

35
src/ModMenu/ModEntry.cs Normal file
View File

@@ -0,0 +1,35 @@
namespace FoodFactory.Modding;
using System;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
public interface IModEntry : IHBoxContainer
{
event ModEntry.ToggleEventHandler Toggle;
ICheckButton EnableModButton { get; set; }
ITextureRect ModIcon { get; set; }
ILabel ModLabel { get; set; }
}
[Meta(typeof(IAutoNode))]
public partial class ModEntry : HBoxContainer, IModEntry
{
[Signal] public delegate void ToggleEventHandler(bool toggledOn);
public override void _Notification(int what) => this.Notify(what);
public ModInfo ModInfo { get; set; } = default!;
[Node] public ICheckButton EnableModButton { get; set; } = default!;
[Node] public ITextureRect ModIcon { get; set; } = default!;
[Node] public ILabel ModLabel { get; set; } = default!;
public override void _Ready()
{
EnableModButton.Toggled += EmitSignalToggle;
}
public override void _ExitTree()
{
base._ExitTree();
EnableModButton.Toggled -= EmitSignalToggle;
}
}

View File

@@ -0,0 +1 @@
uid://c44xdj2bx7jf2

21
src/ModMenu/ModEntry.tscn Normal file
View File

@@ -0,0 +1,21 @@
[gd_scene format=3 uid="uid://7254x1dwaxe2"]
[ext_resource type="Script" uid="uid://c44xdj2bx7jf2" path="res://src/ModMenu/ModEntry.cs" id="1_5igu7"]
[ext_resource type="Texture2D" uid="uid://cbkkfckoiohkh" path="res://assets/kenney_conveyor-kit/Previews/arrow.png" id="2_web80"]
[node name="ModEntry" type="HBoxContainer" unique_id=1826882444]
script = ExtResource("1_5igu7")
[node name="EnableModButton" type="CheckButton" parent="." unique_id=1221626892]
unique_name_in_owner = true
layout_mode = 2
[node name="ModLabel" type="Label" parent="." unique_id=1038432664]
unique_name_in_owner = true
layout_mode = 2
text = "ExampleMod"
[node name="ModIcon" type="TextureRect" parent="." unique_id=1688089757]
unique_name_in_owner = true
layout_mode = 2
texture = ExtResource("2_web80")

79
src/ModMenu/ModMenu.cs Normal file
View File

@@ -0,0 +1,79 @@
namespace FoodFactory.Modding;
using System;
using System.Linq;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
using GodotHelpers;
public interface IModMenu : IControl;
[Meta(typeof(IAutoNode))]
public partial class ModMenu : Control, IModMenu {
public override void _Notification(int what) => this.Notify(what);
[Export] public PackedScene ModEntryScene { get; set; } = default!;
[Dependency] public IAppRepo AppRepo => this.DependOn<IAppRepo>();
private IModManger ModManger => AppRepo.ModManger;
[Node] public ReOrderableContainer ModsContainer { get; set; } = default!;
[Node] public IOptionButton ProfilesButton { get; set; } = default!;
public void OnResolved()
{
VisibilityChanged += OnVisibilityChanged;
ProfilesButton.ItemSelected += OnModProfileSelected;
}
private void OnModProfileSelected(long index)
{
ModManger.Profiles.MakeCurrent((int)index);
RefreshMods();
}
public void OnVisibilityChanged()
{
if (Visible)
{
RefreshMods();
}
}
private void RefreshMods()
{
ModsContainer.QueueFreeChildren();
foreach (var mod in ModManger.AllMods.GetMods())
{
var scene = ModEntryScene.Instantiate<ModEntry>();
ModsContainer.AddChild(scene);
scene.ModLabel.Text = mod.ModName;
scene.EnableModButton.SetPressed(ModManger.Profiles.Current.Contains(mod));
scene.EnableModButton.Toggled += onToggled =>
{
if (onToggled){
ModManger.Profiles.Current.Add(mod);
}
else
{
ModManger.Profiles.Current.Remove(mod);
}
};
}
ProfilesButton.Clear();
foreach (var item in ModManger.Profiles)
{
ProfilesButton.AddItem(item.Name);
}
ProfilesButton.Selected = ModManger.Profiles.CurrentIndex;
}
public override void _ExitTree()
{
VisibilityChanged -= OnVisibilityChanged;
}
}

View File

@@ -0,0 +1 @@
uid://3i3jpgpj3o8c

105
src/ModMenu/ModMenu.tscn Normal file
View File

@@ -0,0 +1,105 @@
[gd_scene format=3 uid="uid://cgp6gntheq4g6"]
[ext_resource type="Script" uid="uid://3i3jpgpj3o8c" path="res://src/ModMenu/ModMenu.cs" id="1_gb6uv"]
[ext_resource type="PackedScene" uid="uid://7254x1dwaxe2" path="res://src/ModMenu/ModEntry.tscn" id="2_gb6uv"]
[ext_resource type="Script" uid="uid://dcarxou4fv5k" path="res://src/ReorderableContainer/ReOrderableContainer.cs" id="2_jor7m"]
[node name="ModMenu" type="Control" unique_id=1651472975]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_gb6uv")
ModEntryScene = ExtResource("2_gb6uv")
[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1940383295]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer" unique_id=727916029]
layout_mode = 2
[node name="TextEdit" type="TextEdit" parent="VBoxContainer/HBoxContainer" unique_id=158149286]
layout_mode = 2
size_flags_horizontal = 3
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer" unique_id=38532812]
layout_mode = 2
[node name="Button" type="Button" parent="VBoxContainer/HBoxContainer2" unique_id=69152890]
layout_mode = 2
[node name="HSplitContainer" type="HSplitContainer" parent="VBoxContainer" unique_id=1406486827]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HSplitContainer" unique_id=1819256880]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/HSplitContainer/VBoxContainer" unique_id=1968844436]
layout_mode = 2
[node name="VSplitContainer" type="VBoxContainer" parent="." unique_id=1045261877]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VSplitContainer" unique_id=212043614]
layout_mode = 2
[node name="LineEdit" type="LineEdit" parent="VSplitContainer/HBoxContainer" unique_id=103828017]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Search"
clear_button_enabled = true
[node name="HBoxContainer2" type="HBoxContainer" parent="VSplitContainer" unique_id=1597229027]
layout_mode = 2
[node name="Button" type="Button" parent="VSplitContainer/HBoxContainer2" unique_id=490993383]
layout_mode = 2
text = "Tag Filters"
[node name="ScrollContainer" type="ScrollContainer" parent="VSplitContainer" unique_id=268282062]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="ModsContainer" type="Container" parent="VSplitContainer/ScrollContainer" unique_id=474405826 node_paths=PackedStringArray("ScrollContainer")]
unique_name_in_owner = true
process_mode = 1
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
script = ExtResource("2_jor7m")
IsVertical = true
ScrollContainer = NodePath("..")
[node name="HBoxContainer3" type="HBoxContainer" parent="VSplitContainer" unique_id=1770191662]
layout_mode = 2
[node name="ProfilesButton" type="OptionButton" parent="VSplitContainer/HBoxContainer3" unique_id=1283538568]
unique_name_in_owner = true
layout_mode = 2
[node name="Button2" type="Button" parent="VSplitContainer/HBoxContainer3" unique_id=656433698]
layout_mode = 2
text = "Enable All"
[node name="Button3" type="Button" parent="VSplitContainer/HBoxContainer3" unique_id=1971172163]
layout_mode = 2
text = "Disable All"
[node name="BackButton" type="Button" parent="VSplitContainer/HBoxContainer3" unique_id=392421633]
layout_mode = 2
size_flags_horizontal = 10
text = "Back"

View File

@@ -0,0 +1,8 @@
namespace GodotHelpers.ChickenSoft;
using Chickensoft.GodotNodeInterfaces;
public static class NodeInterfaceExtension
{
public static void MoveChildEx(this INode parent, INode child, int index) => parent.MoveChild(((NodeAdapter)child).TargetObj, index);
}

View File

@@ -0,0 +1 @@
uid://evrj4m4bd0od

View File

@@ -0,0 +1,116 @@
namespace FoodFactory;
using System;
using System.Numerics;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
using Chickensoft.LogicBlocks.Auto;
using Godot;
public interface IOptionsMenu : IControl
{
event OptionMenu.OnMenuExitEventHandler OnMenuExit;
}
[Meta(typeof(IAutoNode))]
public partial class OptionMenu : Control, IOptionsMenu
{
[Signal] public delegate void OnMenuExitEventHandler();
public override void _Notification(int what) => this.Notify(what);
[Node] public IControl VideoVBox { get; set; } = default!;
[Node] public IButton BackButton { get; set; } = default!;
[Dependency] public IOptionConfig OptionsConfig => this.DependOn<IOptionConfig>();
// GameOptions OptionsConfig.SettingKeys = new();
public override void _Ready()
{
// foreach (var item in _gameOptions.Video.Master)
// {
// var control = new OptionControl();
// control.Initialize(item);
// }
BackButton.Pressed += EmitSignalOnMenuExit;
}
public override void _ExitTree()
{
BackButton.Pressed -= EmitSignalOnMenuExit;
}
public void Setup()
{
}
public void OnResolved()
{
ISettingsBuilder builder = new SettingBuilder(VideoVBox, OptionsConfig);
foreach (var item in OptionsConfig.SettingKeys.GetOptions())
{
item.Build(builder);
}
// OptionsConfig.SettingKeys.Audio.Master.Build(builder);
// OptionsConfig.SettingKeys.Video.FullScreen.Build(builder);
// OptionsConfig.SettingKeys.Video.RenderQuality.Build(builder);
}
public void Test<[MustBeVariant] T>(IOptionKey<T> key)
{
}
}
public interface ISettingsBuilder
{
void Build<[MustBeVariant] T>(IOptionKey<T> option);
void AddOption(Control control);
IOptionConfig OptionConfig { get; }
}
public record SettingBuilder(IControl Root, IOptionConfig OptionConfig) : ISettingsBuilder
{
// public IOptionConfig OptionConfig => throw new System.NotImplementedException();
public void AddOption(Control control) => Root.AddChild(control);
public void Build<[MustBeVariant] T>(IOptionKey<T> option) => option.Build(this);
}
public interface IOptionMenuLogic : ILogicBlock;
[Meta]
public partial class OptionMenuLogic : AutoBlock, IOptionMenuLogic
{
public OptionMenuLogic()
{
Preallocate<OptionMenuLogicState>();
}
}
[Meta, StateDiagram]
public abstract partial record OptionMenuLogicState : LogicBlockState
{
public partial record Menu : OptionMenuLogicState, IGet<Input.OpenMenu>
{
public Menu()
{
this.OnEnter(() =>
{
});
}
public Type On(in Input.OpenMenu input)
{
Output(new Output.ShowMenu());
return ToSelf();
}
}
public static class Input
{
public readonly record struct ApplySettings;
public readonly record struct Return;
public readonly record struct OpenMenu;
}
public static class Output
{
public readonly record struct OnApplySettings;
public readonly record struct ShowMenu;
public readonly record struct HideMenu;
}
}

View File

@@ -0,0 +1 @@
uid://c8qshqj0adwy6

View File

@@ -0,0 +1,9 @@
@startuml OptionMenuLogicState
state "OptionMenuLogicState" as FoodFactory_OptionMenuLogicState {
state "Menu" as FoodFactory_OptionMenuLogicState_Menu
}
FoodFactory_OptionMenuLogicState_Menu --> FoodFactory_OptionMenuLogicState_Menu : OpenMenu
FoodFactory_OptionMenuLogicState_Menu : OnOpenMenu → ShowMenu
@enduml

View File

@@ -0,0 +1,84 @@
[gd_scene format=3 uid="uid://bf3a5w3h1evaf"]
[ext_resource type="Script" uid="uid://c8qshqj0adwy6" path="res://src/OptionsMenu/OptionMenu.cs" id="1_exths"]
[node name="OptionMenu" type="Control" unique_id=2143215493]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
script = ExtResource("1_exths")
[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=291066975]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer" unique_id=1517779829]
layout_mode = 2
size_flags_vertical = 4
[node name="BackButton" type="Button" parent="VBoxContainer/HBoxContainer" unique_id=1823965564]
unique_name_in_owner = true
layout_mode = 2
text = "Back"
[node name="MenuButton" type="MenuButton" parent="VBoxContainer/HBoxContainer" unique_id=165771105]
layout_mode = 2
text = "Profials"
[node name="TabContainer" type="TabContainer" parent="VBoxContainer" unique_id=713184695]
layout_mode = 2
size_flags_vertical = 3
current_tab = 1
[node name="Game" type="Control" parent="VBoxContainer/TabContainer" unique_id=1603979791]
visible = false
layout_mode = 2
metadata/_tab_index = 0
[node name="Video" type="Control" parent="VBoxContainer/TabContainer" unique_id=129786204]
layout_mode = 2
metadata/_tab_index = 1
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer/TabContainer/Video" unique_id=604981526]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VideoVBox" type="VBoxContainer" parent="VBoxContainer/TabContainer/Video/ScrollContainer" unique_id=1912472141]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/TabContainer/Video/ScrollContainer/VideoVBox" unique_id=391821723]
layout_mode = 2
size_flags_horizontal = 4
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Video/ScrollContainer/VideoVBox/HBoxContainer" unique_id=1316771831]
layout_mode = 2
text = "hrsrdergs"
[node name="HSlider" type="HSlider" parent="VBoxContainer/TabContainer/Video/ScrollContainer/VideoVBox/HBoxContainer" unique_id=653575744]
custom_minimum_size = Vector2(200, 0)
layout_mode = 2
[node name="Input" type="Control" parent="VBoxContainer/TabContainer" unique_id=309533595]
visible = false
layout_mode = 2
metadata/_tab_index = 2
[node name="Control" type="Control" parent="VBoxContainer/TabContainer" unique_id=1803532027]
visible = false
layout_mode = 2
metadata/_tab_index = 3

View File

@@ -0,0 +1,264 @@
namespace FoodFactory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Reflection;
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
[Meta(typeof(IAutoNode))]
public partial class OptionControl : Control
{
public override void _Notification(int what) => this.Notify(what);
[Dependency] public IOptionConfig Config => this.DependOn<IOptionConfig>();
[Export] public Variant.Type Type { get; set; } = Variant.Type.Bool;
[Export] public string Section { get; set; } = "";
[Export] public string Key { get; set; } = "";
private IOptionKey _key;
public void Initialize()
{
// _key = new GameOptions().Video.Master;
}
public void Initialize(IOptionKey key)
{
_key = key;
}
public void OnReady()
{
}
public void Setup()
{
}
public void OnExitTree()
{
}
public void OnResolved()
{
return;
foreach (var item in GetChildren())
{
if (item is HSlider slider)
{
slider.Value = Config.GetValue(_key).As<float>();
slider.ValueChanged += v => Config.SetValue(_key, v);
// slider.Value = Config.GetValue<float>(Section, Key, 100);
// slider.ValueChanged += v => Config.SetValue(Section,Key,v);
}
}
}
}
public interface IOptionKey
{
// ControlType ControlType { get; }
Variant.Type VariantType { get; }
Variant VariantDefault { get; }
string Section { get; }
string Key { get; }
void Build(ISettingsBuilder builder);
}
public interface IOptionKey<[MustBeVariant] out T> : IOptionKey
{
T Default { get; }
// ControlType<T> ControlType { get; }
}
public sealed class OptionKey<[MustBeVariant] T>() : IOptionKey<T>
{
public required string Section { get; init; }
public required string Key { get; init; }
public required T Default { get; init; }
public required ControlType<T> ControlType { get; init; }
// public required Variant.Type VariantType { get; init; }
public Variant.Type VariantType => VariantDefault.VariantType;
public Variant VariantDefault => Variant.From(Default);
// ControlType IOptionKey.ControlType => ControlType;
public void Build(ISettingsBuilder builder) => ControlType.Build(builder, this);
}
//public abstract record ControlType;
public abstract record ControlType<[MustBeVariant] T>// : ControlType
{
public abstract void Build(
ISettingsBuilder builder,
IOptionKey<T> option);
}
// public record SpinBoxRangeControlType<[MustBeVariant] T>(T Min, T Max, T Step) : ControlType<T> where T : INumber<T>
// {
// }
public abstract record SliderRangeControlType<[MustBeVariant] T>(T Min, T Max, T Step) : ControlType<T> where T : INumber<T>;
public record SliderRangeControlTypeFloat(float Min, float Max, float Step) : SliderRangeControlType<float>(Min, Max, Step)
{
public override void Build(ISettingsBuilder builder, IOptionKey<float> option)
{
var hbox = new HBoxContainer
{
Alignment = BoxContainer.AlignmentMode.Center
};
hbox.AddChild(new Label() { Text = option.Key });
var slider = new HSlider
{
MinValue = Min,
MaxValue = Max,
Value = option.Default,
CustomMinimumSize = new Godot.Vector2(200, 0),
SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter
};
hbox.AddChild(slider);
slider.ValueChanged += v => builder.OptionConfig.SetValue(option, (int)v);
builder.AddOption(hbox);
}
}
public record SliderRangeControlTypeInt(int Min, int Max, int Step) : SliderRangeControlType<int>(Min, Max, Step)
{
public override void Build(ISettingsBuilder builder, IOptionKey<int> option)
{
var hbox = new HBoxContainer
{
Alignment = BoxContainer.AlignmentMode.Center
};
hbox.AddChild(new Label() { Text = option.Key });
var slider = new HSlider
{
MinValue = Min,
MaxValue = Max,
Value = option.Default,
CustomMinimumSize = new Godot.Vector2(200, 0),
SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter
};
hbox.AddChild(slider);
slider.ValueChanged += v => builder.OptionConfig.SetValue(option, v);
builder.AddOption(hbox);
}
}
public record ToggleControlType() : ControlType<bool>
{
public override void Build(ISettingsBuilder builder, IOptionKey<bool> option)
{
var hbox = new HBoxContainer
{
Alignment = BoxContainer.AlignmentMode.Center
};
hbox.AddChild(new Label() { Text = option.Key });
var button = new CheckBox
{
ButtonPressed = option.Default,
// CustomMinimumSize = new Godot.Vector2(200, 0),
// SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter
};
hbox.AddChild(button);
button.Toggled += v => builder.OptionConfig.SetValue(option, v);
builder.AddOption(hbox);
}
}
public record EnumToggleControl<TEnum>() : ControlType<int> where TEnum : struct, Enum
{
public override void Build(ISettingsBuilder builder, IOptionKey<int> option)
{
var hbox = new HBoxContainer
{
Alignment = BoxContainer.AlignmentMode.Center
};
hbox.AddChild(new Label() { Text = option.Key });
var buttonGroup = new ButtonGroup();
foreach (var @enum in Enum.GetValues<TEnum>())
{
var button = new Button
{
// ButtonPressed = option.Default,
ButtonGroup = buttonGroup,
ToggleMode = true,
Text = @enum.ToString(),
ButtonPressed = @enum.Equals(Enum.ToObject(typeof(TEnum), option.Default))
// CustomMinimumSize = new Godot.Vector2(200, 0),
// SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter
};
button.SetMeta(nameof(EnumToggleControl<>), @enum.ToString());
// if (@enum.Equals(Default))
// {
// button.ButtonPressed = true;
// }
hbox.AddChild(button);
}
buttonGroup.Pressed += v => builder.OptionConfig.SetValue(option, (int)(object)Enum.Parse<TEnum>(v.GetMeta(nameof(EnumToggleControl<>)).AsString()));
builder.AddOption(hbox);
}
}
// public record OptionButtonControlType<T>(params T[] Entries) : ControlType<T>;
public class GameOptions
{
public IEnumerable<IOptionKey> GetOptions() => [.. GetOptions<VideoOptions>(Video), .. GetOptions<AudionOptions>(Audio)];
protected IEnumerable<IOptionKey> GetOptions<T>(object obj)
=> typeof(T).
GetProperties(
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public).
Select(p => p.GetValue(obj)).Cast<IOptionKey>();
public VideoOptions Video {get ;} = new();
public class VideoOptions
{
public OptionKey<bool> FullScreen {get;}= new()
{
Section = nameof(VideoOptions),
Key = nameof(FullScreen),
Default = true,
ControlType = new ToggleControlType(),
};
public OptionKey<float> RenderQuality{get;} = new()
{
Section = nameof(VideoOptions),
Key = nameof(RenderQuality),
Default = 100,
ControlType = new SliderRangeControlTypeFloat(0,100,1)
};
// public IEnumerable<IOptionKey> GetOptions() => typeof(VideoOptions).GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).Select(p =>p.GetValue(null)).Cast<IOptionKey>();
}
public AudionOptions Audio {get;} = new();
public class AudionOptions
{
public OptionKey<float> Master {get;} = new()
{
Section = nameof(Video),
Key = nameof(Master),
Default = 100,
ControlType = new SliderRangeControlTypeFloat(0, 100, 1),
// VariantType = Variant.Type.Float
};
// public IEnumerable<IOptionKey> GetOptions() => typeof(AudionOptions).GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).Select(p =>p.GetValue(null)).Cast<IOptionKey>();
}
}
public enum TestRenderSetting
{
Low,
Medium,
High,
Custom,
}

View File

@@ -0,0 +1 @@
uid://b3lm1ipkmwjia

180
src/PauseMenu/PauseMenu.cs Normal file
View File

@@ -0,0 +1,180 @@
namespace FoodFactory;
using System;
using System.Collections.Generic;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
using Chickensoft.LogicBlocks.Auto;
using Chickensoft.Sync.Primitives;
using Chickensoft.UMLGenerator.Helpers;
using Godot;
public interface IPauseMenu : IControl, IProvide<IOptionConfig>
{
event PauseMenu.OnResumeEventHandler OnResume;
event PauseMenu.OnOptionsEventHandler OnOptions;
event PauseMenu.OnSaveEventHandler OnSave;
event PauseMenu.OnQuitToMainMenuEventHandler OnQuitToMainMenu;
event PauseMenu.OnQuitToDesktopEventHandler OnQuitToDesktop;
}
[Meta(typeof(IAutoNode))]
public partial class PauseMenu : Control, IPauseMenu
{
public override void _Notification(int what) => this.Notify(what);
[Node] IButton BackToGameButton { get; set; } = default!;
[Node] IButton OptionsButton { get; set; } = default!;
[Node] IButton SaveButton { get; set; } = default!;
[Node] IButton QuitToMainMenuButton { get; set; } = default!;
[Node] IButton QuitToDesktopButton { get; set; } = default!;
[Dependency] public IAppRepo AppRepo => this.DependOn<IAppRepo>();
// public TestConfig OptionConfig {get;set; } = default!;
[Dependency] public IOptionConfig OptionConfig => this.DependOn<IOptionConfig>();
IOptionConfig IProvide<IOptionConfig>.Value() => OptionConfig;
[Signal] public delegate void OnResumeEventHandler();
[Signal] public delegate void OnOptionsEventHandler();
[Signal] public delegate void OnSaveEventHandler();
[Signal] public delegate void OnQuitToDesktopEventHandler();
[Signal] public delegate void OnQuitToMainMenuEventHandler();
public void Initialize()
{
// var test = Variant.From("hello");
BackToGameButton.Pressed += EmitSignalOnResume;
OptionsButton.Pressed += EmitSignalOnOptions;
SaveButton.Pressed += EmitSignalOnSave;
QuitToDesktopButton.Pressed += EmitSignalOnQuitToDesktop;
QuitToMainMenuButton.Pressed += EmitSignalOnQuitToMainMenu;
}
public void OnReady()
{
var actions = InputMap.GetActions();
// var vbox = GetNode<VBoxContainer>("ScrollContainer/VBoxContainer");
// foreach (var item in actions)
// {
// var label = new Label(){Text = item};
// var b = new HBoxContainer();
// b.AddChild(label);
// var texture = new TextureRect();
// b.AddChild(texture);
// var icon = new ControllerIconTexture(){path = item};
// texture.Texture = icon;
// vbox.AddChild(b);
// }
SaveButton.Pressed += ()=>((TestConfig)OptionConfig).ConfigFile.Save("user://config.cfg");
}
public void Setup()
{
// OptionConfig = new TestConfig();
}
public void OnExitTree()
{
// OptionConfig.ConfigFile.Free();
}
public void OnResolved()
{
this.Provide();
}
}
public interface IOptionConfig
{
// Variant GetValue(string section, string key, Variant @default = default);
// T GetValue<[MustBeVariant] T>(string section, string key, T @default = default!);
Variant GetValue(IOptionKey key);
T GetValue<[MustBeVariant] T>(IOptionKey<T> key);
// void SetValue(string section, string key, Variant value);
// void SetValue<[MustBeVariant] T>(string section, string key, T value);
void SetValue(IOptionKey key, Variant value);
void SetValue<[MustBeVariant] T>(IOptionKey<T> key, T value);
GameOptions SettingKeys { get; }
}
public record TestConfig : IOptionConfig
{
public delegate void SettingChanged(IOptionKey key, Variant value);
// public delegate void SettingChanged<[MustBeVariant] in T>(IOptionKey<T> key, T old, T value);
public event SettingChanged? OnSettingChanged;
public ConfigFile ConfigFile;
private GameOptions _gameOptions = new();
public GameOptions SettingKeys => _gameOptions;
public TestConfig()
{
ConfigFile = new();
ConfigFile.Load("user://config.cfg");
}
// public Variant GetValue(string section, string key, Variant @default = default)
// {
// if (!ConfigFile.HasSectionKey(section, key))
// {
// return @default;
// }
// return ConfigFile.GetValue(section, key, @default);
// }
// public T GetValue<T>(string section, string key, T @default = default!)
// {
// if (!ConfigFile.HasSectionKey(section, key))
// {
// return @default;
// }
// return ConfigFile.GetValue(section, key).As<T>();
// }
// public void SetValue(string section, string key, Variant value) => ConfigFile.SetValue(section, key, value);
public Variant GetValue(IOptionKey key)
{
if (!ConfigFile.HasSectionKey(key.Section, key.Key))
{
return key.VariantDefault;
}
var setting = ConfigFile.GetValue(key.Section, key.Key);
if (setting.VariantType != key.VariantType)
{
throw new Exception($"Wrong Variant Type, setting has {setting.VariantType}, but the key has {key.VariantType}");
}
return ConfigFile.GetValue(key.Section, key.Key);
}
public T GetValue<[MustBeVariant] T>(IOptionKey<T> key)
{
if (!ConfigFile.HasSectionKey(key.Section, key.Key))
{
return key.Default;
}
return ConfigFile.GetValue(key.Section, key.Key).As<T>();
}
public void SetValue(IOptionKey key, Variant value)
{
if (key.VariantType != value.VariantType)
{
throw new Exception($"Wrong Variant Type, setting has {value.VariantType}, but the key has {key.VariantType}");
}
OnSettingChanged?.Invoke(key, value);
ConfigFile.SetValue(key.Section, key.Key, value);
}
public void SetValue<[MustBeVariant] T>(IOptionKey<T> key, T value)
{
var variant = Variant.From(value);
if (key.VariantType != variant.VariantType)
{
throw new Exception($"Wrong Variant Type, setting has {variant.VariantType}, but the key has {key.VariantType}");
}
OnSettingChanged?.Invoke(key, Variant.From(value));
ConfigFile.SetValue(key.Section, key.Key, variant);
}
}

View File

@@ -0,0 +1 @@
uid://bq1qbk2ca2rnd

View File

@@ -0,0 +1,15 @@
@startuml PauseMenuLogicState
state "PauseMenuLogicState" as FoodFactory_PauseMenuLogicState {
state "Hidden" as FoodFactory_PauseMenuLogicState_Hidden
state "MenuVisible" as FoodFactory_PauseMenuLogicState_MenuVisible {
state "Saving" as FoodFactory_PauseMenuLogicState_Saving
}
}
FoodFactory_PauseMenuLogicState_MenuVisible --> FoodFactory_PauseMenuLogicState_Hidden : ExitMenu
FoodFactory_PauseMenuLogicState_Saving --> FoodFactory_PauseMenuLogicState_Hidden : ExitMenu
FoodFactory_PauseMenuLogicState_Hidden : OnEnter → HideMenu
FoodFactory_PauseMenuLogicState_MenuVisible : OnEnter → ShowMenu
FoodFactory_PauseMenuLogicState_Saving : OnEnter → ShowMenu
@enduml

View File

@@ -0,0 +1,96 @@
[gd_scene format=3 uid="uid://ermyaow1y331"]
[ext_resource type="Script" uid="uid://bq1qbk2ca2rnd" path="res://src/PauseMenu/PauseMenu.cs" id="1_2ahbk"]
[ext_resource type="Script" uid="uid://b3lm1ipkmwjia" path="res://src/PauseMenu/OptionControl.cs" id="2_00y0h"]
[node name="PauseMenu" type="Control" unique_id=1396653727]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
script = ExtResource("1_2ahbk")
[node name="CenterContainer" type="CenterContainer" parent="." unique_id=721938240]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="PanelContainer" type="PanelContainer" parent="CenterContainer" unique_id=919834436]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/PanelContainer" unique_id=30079232]
layout_mode = 2
[node name="Label" type="Label" parent="CenterContainer/PanelContainer/VBoxContainer" unique_id=444034357]
layout_mode = 2
size_flags_horizontal = 4
text = "Paused"
[node name="BackToGameButton" type="Button" parent="CenterContainer/PanelContainer/VBoxContainer" unique_id=292081799]
unique_name_in_owner = true
layout_mode = 2
text = "Resume"
[node name="OptionsButton" type="Button" parent="CenterContainer/PanelContainer/VBoxContainer" unique_id=2029511532]
unique_name_in_owner = true
layout_mode = 2
text = "Options"
[node name="SaveButton" type="Button" parent="CenterContainer/PanelContainer/VBoxContainer" unique_id=665491856]
unique_name_in_owner = true
layout_mode = 2
text = "Save"
[node name="Label2" type="Label" parent="CenterContainer/PanelContainer/VBoxContainer" unique_id=1636926182]
layout_mode = 2
size_flags_horizontal = 4
text = "Exit To"
[node name="HBoxContainer" type="HBoxContainer" parent="CenterContainer/PanelContainer/VBoxContainer" unique_id=444158905]
layout_mode = 2
[node name="QuitToMainMenuButton" type="Button" parent="CenterContainer/PanelContainer/VBoxContainer/HBoxContainer" unique_id=758495631]
unique_name_in_owner = true
layout_mode = 2
text = "Menu"
[node name="QuitToDesktopButton" type="Button" parent="CenterContainer/PanelContainer/VBoxContainer/HBoxContainer" unique_id=369277644]
unique_name_in_owner = true
layout_mode = 2
text = "Desktop"
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/PanelContainer/VBoxContainer" unique_id=1815712922]
visible = false
layout_mode = 2
size_flags_horizontal = 3
[node name="FoldableContainer" type="FoldableContainer" parent="CenterContainer/PanelContainer/VBoxContainer/VBoxContainer" unique_id=1348631741]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/PanelContainer/VBoxContainer/VBoxContainer/FoldableContainer" unique_id=616148123]
layout_mode = 2
[node name="Label" type="Label" parent="CenterContainer/PanelContainer/VBoxContainer/VBoxContainer/FoldableContainer/VBoxContainer" unique_id=527284536]
layout_mode = 2
text = "Music"
[node name="Control" type="HBoxContainer" parent="CenterContainer/PanelContainer/VBoxContainer/VBoxContainer/FoldableContainer/VBoxContainer" unique_id=1675265249]
layout_mode = 2
script = ExtResource("2_00y0h")
Type = 4
Section = "hello"
Key = "world"
[node name="Label" type="Label" parent="CenterContainer/PanelContainer/VBoxContainer/VBoxContainer/FoldableContainer/VBoxContainer/Control" unique_id=642906436]
layout_mode = 2
text = "Test"
[node name="HSlider" type="HSlider" parent="CenterContainer/PanelContainer/VBoxContainer/VBoxContainer/FoldableContainer/VBoxContainer/Control" unique_id=925380166]
layout_mode = 2
size_flags_horizontal = 3

42
src/PrintHelper.cs Normal file
View File

@@ -0,0 +1,42 @@
namespace FoodFactory;
using System;
using System.Runtime.CompilerServices;
using System.Text;
using Godot;
public static class Log
{
// public static void PrintC<T>(T value, [CallerArgumentExpression(nameof(value))] string? name = null) => GD.Print($"{name}:{value}");
// public static void Print(Action<Dump> dump)
// {
// var d = new Dump();
// dump(d);
// GD.Print(d);
// }
}
public sealed class Dump
{
private readonly StringBuilder _sb = new();
public static Dump With<T>(
T value,
[CallerArgumentExpression(nameof(value))] string expr = "")
{
var dump = new Dump();
dump._sb.Append($"{expr}: {value}");
return dump;
}
public Dump And<T>(
T value,
[CallerArgumentExpression(nameof(value))] string expr = "")
{
_sb.Append($", {expr}: {value}");
return this;
}
public override string ToString() => _sb.ToString();
}

1
src/PrintHelper.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://c0aisokgmjlwh

View File

@@ -0,0 +1,406 @@
//https://github.com/FoolLin/ReorderableContainer
namespace FoodFactory;
using System;
using System.Collections.Generic;
using System.Linq;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
public interface IReOrderableContainer : IContainer
{
}
[Meta(typeof(IAutoNode))]
[Tool]
public partial class ReOrderableContainer : Container, IReOrderableContainer
{
public override void _Notification(int what) => this.Notify(what);
[Signal] public delegate void ReOrderedEventHandler(int from, int to);
[Export] public double HoldDuration { get; set; } = .5;
[Export(PropertyHint.Range, "3,30,0.01,or_greater,or_less")] public double Speed { get; set; } = 10;
[Export] public double Separation
{
get;
set
{
if (value == Separation || value < 0)
{
return;
}
field = value;
OnSortChildren();
}
}
[Export]
public bool IsVertical
{
get;
set
{
if (value == IsVertical)
{
return;
}
field = value;
if (IsVertical)
{
CustomMinimumSize = CustomMinimumSize with { X = 0 };
}
else
{
CustomMinimumSize = CustomMinimumSize with { Y = 0 };
}
OnSortChildren();
}
}
[Export] public ScrollContainer ScrollContainer { get; set; } = default!;
[Export] public double AutoScrollSpeed { get; set; } = 10;
[Export(PropertyHint.Range, "0,.5")] public double AutoScrollRange { get; set; } = .3;
[Export] public double ScrollThreshold { get; set; } = 30;
[Export] public bool IsDebugging { get; set; } = false;
private double _scrollStartingPoint = 0;
// private bool _isSmoothScroll = false;
private readonly List<Rect2> _dropZones = [];
private int _dropZoneIndex = -1;
private readonly List<Rect2> _expectChildRect = [];
protected Control? _focusChild = null;
protected bool _isPress = false;
protected bool _isHold = false;
private double _currentDuration = 0.0;
private bool _isUsingProcess = false;
private const int DROP_ZONE_EXTEND = 2000;
public void OnReady()
{
if (ScrollContainer is null && GetParent() is ScrollContainer)
{
ScrollContainer = GetParent<ScrollContainer>();
}
// if scroll_container != null and scroll_container.has_method("handle_overdrag"):
// _is_smooth_scroll = true
ProcessMode = ProcessModeEnum.Pausable;
AdjustExpectedChildRect();
SortChildren += OnSortChildrenWrapper;
// GetTree().NodeAdded += OnNodeAdded;
}
public override void _GuiInput(InputEvent @event)
{
if (@event is InputEventMouseButton eventMouseButton && eventMouseButton.ButtonIndex == MouseButton.Left)
{
GD.Print(string.Join(',',((IReOrderableContainer)this).GetChildren().Select(s => $"{s}, {s.Name}, {s.GetType()}, {(Control)s}")));
foreach (var child in ((IReOrderableContainer)this).GetChildren().OfType<Control>())
{
if (child.GetRect().HasPoint(GetLocalMousePosition()) && eventMouseButton.IsPressed())
{
_focusChild = child;
_isPress = true;
}
else if (!eventMouseButton.Pressed)
{
_isPress = false;
_isHold = false;
}
}
}
}
public override void _Process(double delta)
{
if (Engine.IsEditorHint())
{
return;
}
HandleInput(delta);
if ((_currentDuration >= HoldDuration) != _isHold)
{
_isHold = _currentDuration >= HoldDuration;
if (_isHold)
{
OnStartDragging();
}
}
if (_isHold)
{
HandleDraggingChildPos(delta);
if (ScrollContainer is not null)
{
HandleAutoScroll(delta);
}
}
else if (!_isHold && _dropZoneIndex != -1)
{
OnStopDragging();
}
if (_isUsingProcess)
{
OnSortChildren(delta);
}
QueueRedraw();
}
public override void _Draw()
{
var r = new Random(0);
foreach (var item in _dropZones)
{
// GD.Print(item);
DrawRect(item,new Color(r.NextSingle(),r.NextSingle(),r.NextSingle()));
}
base._Draw();
}
private void HandleInput(double delta)
{
if (ScrollContainer is not null && _isPress && !_isHold)
{
var scrollPoint = IsVertical ? ScrollContainer.ScrollVertical : ScrollContainer.ScrollHorizontal;
if (_currentDuration == 0)
{
_scrollStartingPoint = scrollPoint;
}
else
{
_isPress = Mathf.Abs(scrollPoint - _scrollStartingPoint) <= ScrollThreshold;
}
}
_currentDuration = _isPress ? _currentDuration + delta : 0;
}
private void OnStartDragging()
{
_isUsingProcess = true;
_focusChild?.ZIndex = 1;
// if _is_smooth_scroll:
// scroll_container.process_mode = Node.PROCESS_MODE_DISABLED
foreach (var child in GetVisibleChildren())
{
child.PropagateCall(Control.MethodName.SetMouseFilter, [Variant.From(MouseFilterEnum.Ignore)]);
}
}
private void OnStopDragging()
{
if (_focusChild is null)
{
return;
}
_focusChild.ZIndex = 0;
var focusChildIndex = _focusChild.GetIndex();
AsIReOrderableContainer().MoveChild(_focusChild, _dropZoneIndex);
EmitSignalReOrdered(focusChildIndex, _dropZoneIndex);
_focusChild = null;
GD.Print(_dropZoneIndex);
_dropZoneIndex = -1;
// if _is_smooth_scroll:
// scroll_container.pos = -Vector2(scroll_container.scroll_horizontal, scroll_container.scroll_vertical)
// scroll_container.process_mode = Node.PROCESS_MODE_INHERIT
foreach (var child in GetVisibleChildren())
{
child.PropagateCall(Control.MethodName.SetMouseFilter,[Variant.From(MouseFilterEnum.Pass)]);
}
}
public void HandleDraggingChildPos(double delta)
{
if (IsVertical)
{
var targetPos = GetLocalMousePosition().Y - (_focusChild.Size.Y/2);
_focusChild.Position = _focusChild.Position with {Y = Mathf.Lerp(_focusChild.Position.Y, targetPos, (float)(delta * Speed))};
}
else
{
var targetPos = GetLocalMousePosition().X - (_focusChild.Size.X/2);
_focusChild.Position = _focusChild.Position with {X = Mathf.Lerp(_focusChild.Position.X, targetPos, (float)(delta * Speed))};
}
var childCenterPos = _focusChild.GetRect().GetCenter();
for (int i = 0; i < _dropZones.Count; i++)
{
var dropZone = _dropZones[i];
GD.Print(Dump.With(i).And(_dropZones[i]).And(childCenterPos).And(dropZone.HasPoint(childCenterPos)).And(_dropZones.Count));
if (dropZone.HasPoint(childCenterPos))
{
_dropZoneIndex = i;
break;
}
else if (i == _dropZones.Count - 1)
{
_dropZoneIndex = -1;
}
// elif i == _drop_zones.size() - 1:
// _drop_zone_index = -1
}
}
public void HandleAutoScroll(double delta)
{
var mouseGPos = GetGlobalMousePosition();
var scrollGRect = ScrollContainer.GetGlobalRect();
var index = IsVertical ? 0 : 1;
var leftUpper = scrollGRect.Position[index] + (scrollGRect.Size[index] * AutoScrollRange);
var rightLower = scrollGRect.Position[index] + (scrollGRect.Size[index] * (1 - AutoScrollRange));
setScroll(
mouseGPos[index] switch
{
var i when leftUpper > i => scroll => useDelta((leftUpper - mouseGPos[index]) / (leftUpper - scrollGRect.Position[index])),
var i when rightLower < i => scroll => useDelta((mouseGPos[index] - rightLower) / (scrollGRect.Position[index] - rightLower)),
var i => scroll => (int)scroll
}
);
int useDelta(double d) => (int)(delta * AutoScrollSpeed * 150.0 * d);
void setScroll(Func<double, int> scroll)
{
if (IsVertical)
{
ScrollContainer.ScrollVertical = scroll(ScrollContainer.ScrollVertical);
}
else
{
ScrollContainer.ScrollHorizontal = scroll(ScrollContainer.ScrollHorizontal);
}
}
}
public void OnExitTree()
{
if (Engine.IsEditorHint())
{
return;
}
SortChildren -= OnSortChildrenWrapper;
// GetTree().NodeAdded -= OnNodeAdded;
}
private void OnNodeAdded(Node node)
{
if (node is Control control && !Engine.IsEditorHint())
{
control.MouseFilter = MouseFilterEnum.Pass;
}
}
private void OnSortChildrenWrapper() => OnSortChildren();
private void OnSortChildren(double delta = -1)
{
if (_isUsingProcess && delta == -1)
{
return;
}
AdjustExpectedChildRect();
AdjustChildRect(delta);
AdjustDropZoneRect();
}
private void AdjustExpectedChildRect()
{
_expectChildRect.Clear();
var endPoint = 0.0;
var i = 0;
var index = IsVertical ? 1 : 0;
foreach (var child in GetVisibleChildren())
{
var minSize = child.GetCombinedMinimumSize();
if (i == _dropZoneIndex)
{
endPoint += _focusChild.Size[index] + Separation;
}
_expectChildRect.Add(
new(
IsVertical
? new(0, (float)endPoint)
: new((float)endPoint, 0)
, IsVertical
? new(Size.X, minSize.Y)
: new(minSize.X, Size.Y)));
endPoint += minSize[index] + Separation;
i++;
}
}
private void AdjustChildRect(double delta = -1)
{
if (!GetVisibleChildren().Any())
{
return;
}
var isAnimating = false;
var endPoint = 0.0;
var children = GetVisibleChildren().ToArray();
for (int i = 0; i < children.Length; i++)
{
var child = children[i];
if (child.Position == _expectChildRect[i].Position && child.Size == _expectChildRect[i].Size)
{
continue;
}
if (_isUsingProcess)
{
isAnimating = true;
child.Position = child.Position.Lerp(_expectChildRect[i].Position, (float)(delta * Speed));
child.Size = _expectChildRect[i].Size;
if ((child.Position - _expectChildRect[i].Position).Length() <= 1)
{
child.Position = _expectChildRect[i].Position;
}
continue;
}
child.Position = _expectChildRect[i].Position;
child.Size = _expectChildRect[i].Size;
}
var lastChild = children[^1];
var index = IsVertical ? 0 : 1;
var newCustomSize =
_isUsingProcess && _dropZoneIndex == children.Length
? _expectChildRect[^1].End[index] + _focusChild.Size[index] + Separation
: !_isUsingProcess
?lastChild.GetRect().End[index]
:lastChild.CustomMinimumSize[index];
// lastChild.CustomMinimumSize = IsVertical?lastChild.CustomMinimumSize with { Y = (float)newCustomSize} :lastChild.CustomMinimumSize with { X = (float)newCustomSize};
if (!isAnimating && _focusChild is not null)
{
_isUsingProcess = false;
}
}
private void AdjustDropZoneRect()
{
_dropZones.Clear();
if (!GetVisibleChildren().Any())
{
return;
}
var children = GetVisibleChildren().ToArray();
var minSize = children.Max(child => child.GetMinimumSize()[IsVertical?0:1]);
if (_focusChild is not null)
{
minSize = Mathf.Max(minSize,_focusChild.GetMinimumSize()[IsVertical?0:1]);
}
for (int i = 0; i < children.Length; i++)
{
var child = children[i];
_dropZones.Add(i == 0 ?
new Rect2()
{
Position = child.Position - (IsVertical?new(0,DROP_ZONE_EXTEND):new(DROP_ZONE_EXTEND,0)),
End = IsVertical? new(minSize,child.GetRect().GetCenter().Y):new(child.GetRect().GetCenter().X,minSize)
}
:
new Rect2()
{
Position = IsVertical?new(children[i-1].Position.X,children[i-1].GetRect().GetCenter().Y) : new(children[i-1].GetRect().GetCenter().X,children[i-1].Position.Y),
End = IsVertical?new(minSize,child.GetRect().GetCenter().Y) : new(child.GetRect().GetCenter().X,minSize),
});
if (i == children.Length - 1)
{
_dropZones.Add(new Rect2()
{
Position = IsVertical?new(child.Position.X,child.GetRect().GetCenter().Y):new(child.GetRect().GetCenter().X,child.Position.Y),
End = IsVertical? new(minSize,child.GetRect().End.Y + DROP_ZONE_EXTEND):new(child.GetRect().End.X + DROP_ZONE_EXTEND, minSize)
});
}
}
}
private IReOrderableContainer AsIReOrderableContainer() => (IReOrderableContainer)this;
private IEnumerable<Control> GetVisibleChildren() => GetChildren().OfType<Control>().Where(child => child.Visible && !(child == _focusChild && _isHold));
}

View File

@@ -0,0 +1 @@
uid://dcarxou4fv5k

View File

@@ -0,0 +1,65 @@
namespace FoodFactory;
using System.Linq;
using Chickensoft.GodotNodeInterfaces;
using Godot;
public interface IReOrderableContainerFancy: IReOrderableContainer
{
}
public partial class ReOrderableContainerFancy : ReOrderableContainer, IReOrderableContainerFancy
{
public override void _GuiInput(InputEvent @event)
{
if (@event is InputEventMouseButton eventMouseButton && eventMouseButton.ButtonIndex == MouseButton.Left)
{
foreach (var child in (this as IReOrderableContainerFancy).GetChildren().OfType<Control>())
{
if (child is OrderableItem orderableItem)
{
if (orderableItem.DragHandel.GetRect().HasPoint(child.GetLocalMousePosition()) && eventMouseButton.IsPressed())
{
_focusChild = orderableItem;
_isPress = true;
}
else if (!eventMouseButton.Pressed)
{
_isPress = false;
_isHold = false;
}
}
else
{
if (child.GetRect().HasPoint(child.GetLocalMousePosition()) && eventMouseButton.IsPressed())
{
_focusChild = child;
_isPress = true;
}
else if (!eventMouseButton.Pressed)
{
_isPress = false;
_isHold = false;
}
}
}
}
}
}
public interface IOrderableItem : IControl
{
IControl DragHandel { get; }
}
public partial class OrderableItem : Control, IOrderableItem
{
[Export] public Control DragHandel { get; set; } = default!;
IControl IOrderableItem.DragHandel => (IControl)DragHandel;
public override void _Ready()
{
if (DragHandel is null)
{
DragHandel = this;
}
}
}

View File

@@ -0,0 +1 @@
uid://mb7j1wlyulw6

View File

@@ -0,0 +1,85 @@
namespace FoodFactory;
using System;
using System.Collections.Generic;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
public interface ICreateGameMenu : IControl
{
event CreateGameMenu.NewGameEventHandler NewGame;
event CreateGameMenu.ExitEventHandler Exit;
event CreateGameMenu.LevelSelectedEventHandler LevelSelected;
void Initialize(IReadOnlyList<LevelEntry> context);
}
public record LevelEntry(string Name, string ImagePath);
[Meta(typeof(IAutoNode))]
public partial class CreateGameMenu : Control, ICreateGameMenu
{
public override void _Notification(int what) => this.Notify(what);
[Node] public IButton NewGameButton { get; set; } = default!;
[Node] public IItemList ItemList { get; set; } = default!;
[Node] public IButton ExitButton { get; set; } = default!;
[Node] public ITextureRect TextureRect { get; set; } = default!;
[Signal] public delegate void NewGameEventHandler();
[Signal] public delegate void ExitEventHandler();
[Signal] public delegate void LevelSelectedEventHandler(long index);
private IReadOnlyList<LevelEntry> _createGameMenuContext = default!;
public void LoadLevels()
{
}
public void Initialize()
{
}
public void Setup()
{
}
public void OnReady()
{
NewGameButton.Pressed += EmitSignalNewGame;
ExitButton.Pressed += EmitSignalExit;
ItemList.ItemSelected += EmitSignalLevelSelected;
ItemList.ItemSelected += SetTexture;
}
private void SetTexture(long index)
{
var texture = GD.Load<Texture2D>(_createGameMenuContext[(int)index].ImagePath);
TextureRect.SetTexture(texture);
}
public void OnExitTree()
{
NewGameButton.Pressed -= EmitSignalNewGame;
ItemList.ItemSelected -= EmitSignalLevelSelected;
ExitButton.Pressed -= EmitSignalExit;
ItemList.ItemSelected -= SetTexture;
}
public void OnResolved()
{
}
public void Initialize(IReadOnlyList<LevelEntry> context)
{
_createGameMenuContext = context;
ItemList.Clear();
for (int i = 0; i < context.Count; i++)
{
ItemList.AddItem(context[i].Name);
}
}
}

View File

@@ -0,0 +1 @@
uid://b77y6vqplqeev

View File

@@ -0,0 +1 @@
uid://b77y6vqplqeev

View File

@@ -0,0 +1,101 @@
[gd_scene format=3 uid="uid://dkgrn8n1on4ec"]
[ext_resource type="Texture2D" uid="uid://vasmmctflj8t" path="res://assets/KayKit_Restaurant_Bits_1.0_FREE/sample.png" id="1_bjcgj"]
[ext_resource type="Script" uid="uid://b77y6vqplqeev" path="res://src/TitleMenu/CreateGameMenu.cs" id="1_tgp1f"]
[ext_resource type="Texture2D" uid="uid://cbkkfckoiohkh" path="res://assets/kenney_conveyor-kit/Previews/arrow.png" id="2_74aa3"]
[ext_resource type="Texture2D" uid="uid://44xceef8lwa1" path="res://assets/kenney_conveyor-kit/Previews/box-large.png" id="3_tgp1f"]
[node name="CreateGameMenu" type="Control" unique_id=1233498611]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_tgp1f")
[node name="VBoxContainer" type="VSplitContainer" parent="." unique_id=2020351108]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
split_offsets = PackedInt32Array(44)
split_offset = 44
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer" unique_id=1173131569]
layout_mode = 2
[node name="ExitButton" type="Button" parent="VBoxContainer/HBoxContainer" unique_id=548336592]
unique_name_in_owner = true
layout_mode = 2
text = "Back"
[node name="Title" type="Label" parent="VBoxContainer/HBoxContainer" unique_id=131542238]
layout_mode = 2
size_flags_horizontal = 6
text = "Create New Game"
horizontal_alignment = 1
[node name="TabContainer" type="TabContainer" parent="VBoxContainer" unique_id=559373496]
layout_mode = 2
current_tab = 0
[node name="Scenario" type="TabBar" parent="VBoxContainer/TabContainer" unique_id=671278362]
layout_mode = 2
metadata/_tab_index = 0
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/TabContainer/Scenario" unique_id=1613842078]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/TabContainer/Scenario/PanelContainer" unique_id=51747954]
layout_mode = 2
[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/TabContainer/Scenario/PanelContainer/VBoxContainer" unique_id=1298831420]
layout_mode = 2
[node name="TextureRect" type="TextureRect" parent="VBoxContainer/TabContainer/Scenario/PanelContainer/VBoxContainer/CenterContainer" unique_id=2081261267]
unique_name_in_owner = true
custom_minimum_size = Vector2(600, 0)
layout_mode = 2
size_flags_vertical = 3
texture = ExtResource("1_bjcgj")
expand_mode = 5
[node name="ItemList" type="ItemList" parent="VBoxContainer/TabContainer/Scenario/PanelContainer/VBoxContainer" unique_id=2047092385]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
item_count = 2
item_0/text = "Level One"
item_0/icon = ExtResource("2_74aa3")
item_1/text = "Level Two"
item_1/icon = ExtResource("3_tgp1f")
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/TabContainer/Scenario/PanelContainer/VBoxContainer" unique_id=119906153]
layout_mode = 2
size_flags_vertical = 8
[node name="LineEdit" type="LineEdit" parent="VBoxContainer/TabContainer/Scenario/PanelContainer/VBoxContainer/HBoxContainer" unique_id=736846967]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "CompanyName"
[node name="NewGameButton" type="Button" parent="VBoxContainer/TabContainer/Scenario/PanelContainer/VBoxContainer/HBoxContainer" unique_id=609544107]
unique_name_in_owner = true
layout_mode = 2
text = "New Game
"
[node name="Custom" type="TabBar" parent="VBoxContainer/TabContainer" unique_id=1103500564]
visible = false
layout_mode = 2
metadata/_tab_index = 1

View File

@@ -0,0 +1,74 @@
namespace FoodFactory;
using System;
using System.Collections.Generic;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
public interface ILoadingGameMenu : IControl
{
event LoadingGameMenu.LoadGameEventHandler LoadGame;
event LoadingGameMenu.ExitEventHandler Exit;
void Initialize(IReadOnlyList<string> context);
}
[Meta(typeof(IAutoNode))]
public partial class LoadingGameMenu : Control, ILoadingGameMenu{
public override void _Notification(int what) => this.Notify(what);
[Node] public IButton LoadGameButton { get; set; } = default!;
[Node] public IItemList ItemList { get; set; } = default!;
[Node] public IButton ExitButton { get; set; } = default!;
private IReadOnlyList<string> _createGameMenuContext = default!;
[Signal] public delegate void LoadGameEventHandler(int index);
[Signal] public delegate void ExitEventHandler();
public void Initialize()
{
}
public void Initialize(IReadOnlyList<string> context)
{
_createGameMenuContext = context;
ItemList.Clear();
for (int i = 0; i < context.Count; i++)
{
ItemList.AddItem(context[i]);
}
}
public void Setup()
{
}
public void OnReady()
{
LoadGameButton.Pressed += OnGameLoad;
ItemList.ItemSelected += OnItemSelected;
ExitButton.Pressed += EmitSignalExit;
}
private void OnGameLoad()
{
var indexs = ItemList.GetSelectedItems();
// var name = ItemList.GetItemText(indexs[0]);
// EmitSignalLoadGame(name);
EmitSignalLoadGame(indexs[0]);
}
private void OnItemSelected(long index) => EmitSignalLoadGame((int)index);
public void OnExitTree()
{
LoadGameButton.Pressed -= OnGameLoad;
ExitButton.Pressed -= EmitSignalExit;
}
public void OnResolved()
{
}
}

View File

@@ -0,0 +1 @@
uid://cq0iv164utrdh

View File

@@ -0,0 +1,81 @@
[gd_scene format=3 uid="uid://b7x2w61dwafxe"]
[ext_resource type="Script" uid="uid://cq0iv164utrdh" path="res://src/TitleMenu/LoadingGameMenu.cs" id="1_qfs4u"]
[ext_resource type="Texture2D" uid="uid://vasmmctflj8t" path="res://assets/KayKit_Restaurant_Bits_1.0_FREE/sample.png" id="2_s8dbj"]
[ext_resource type="Texture2D" uid="uid://cbkkfckoiohkh" path="res://assets/kenney_conveyor-kit/Previews/arrow.png" id="3_352do"]
[ext_resource type="Texture2D" uid="uid://44xceef8lwa1" path="res://assets/kenney_conveyor-kit/Previews/box-large.png" id="4_8epju"]
[node name="LoadGameMenu" type="Control" unique_id=1233498611]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_qfs4u")
[node name="PanelContainer" type="PanelContainer" parent="." unique_id=1613842078]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="VBoxContainer" type="VSplitContainer" parent="PanelContainer" unique_id=2020351108]
layout_mode = 2
split_offsets = PackedInt32Array(61)
split_offset = 61
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer" unique_id=1173131569]
layout_mode = 2
[node name="ExitButton" type="Button" parent="PanelContainer/VBoxContainer/HBoxContainer" unique_id=548336592]
unique_name_in_owner = true
layout_mode = 2
text = "Back"
[node name="Title" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer" unique_id=131542238]
layout_mode = 2
size_flags_horizontal = 6
text = "Load Game"
horizontal_alignment = 1
[node name="Button" type="Button" parent="PanelContainer/VBoxContainer/HBoxContainer" unique_id=271498422]
layout_mode = 2
text = "LoadFromFile"
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer" unique_id=51747954]
layout_mode = 2
[node name="CenterContainer" type="CenterContainer" parent="PanelContainer/VBoxContainer/VBoxContainer" unique_id=1298831420]
layout_mode = 2
[node name="TextureRect" type="TextureRect" parent="PanelContainer/VBoxContainer/VBoxContainer/CenterContainer" unique_id=2081261267]
custom_minimum_size = Vector2(600, 0)
layout_mode = 2
size_flags_vertical = 3
texture = ExtResource("2_s8dbj")
expand_mode = 5
[node name="ItemList" type="ItemList" parent="PanelContainer/VBoxContainer/VBoxContainer" unique_id=2047092385]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
item_count = 2
item_0/text = "Level One"
item_0/icon = ExtResource("3_352do")
item_1/text = "Level Two"
item_1/icon = ExtResource("4_8epju")
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer/VBoxContainer" unique_id=119906153]
layout_mode = 2
size_flags_vertical = 8
[node name="LoadGameButton" type="Button" parent="PanelContainer/VBoxContainer/VBoxContainer/HBoxContainer" unique_id=609544107]
unique_name_in_owner = true
layout_mode = 2
text = "Load Game
"

71
src/TitleMenu/MainMenu.cs Normal file
View File

@@ -0,0 +1,71 @@
namespace FoodFactory.Menu;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
public interface IMainMenu : IControl
{
event MainMenu.NewGameEventHandler NewGame;
event MainMenu.LastGameEventHandler LastGame;
void SetLastGameVisible(bool visible);
event MainMenu.LoadGameEventHandler LoadGame;
event MainMenu.OptionsEventHandler Options;
event MainMenu.ModsEventHandler Mods;
event MainMenu.ExitEventHandler Exit;
}
[Meta(typeof(IAutoNode))]
public partial class MainMenu : Control, IMainMenu
{
public override void _Notification(int what) => this.Notify(what);
[Node] public IButton LastGameButton { get; set; } = default!;
[Node] public IButton NewGameButton { get; set; } = default!;
[Node] public IButton LoadGameButton { get; set; } = default!;
[Node] public IButton OptionsButton { get; set; } = default!;
[Node] public IButton ModsButton { get; set; } = default!;
[Node] public IButton ExitButton { get; set; } = default!;
[Signal] public delegate void LastGameEventHandler();
[Signal] public delegate void NewGameEventHandler();
[Signal] public delegate void LoadGameEventHandler();
[Signal] public delegate void OptionsEventHandler();
[Signal] public delegate void ModsEventHandler();
[Signal] public delegate void ExitEventHandler();
public void Initialize()
{
}
public void Setup()
{
}
public void OnReady()
{
NewGameButton.Pressed += EmitSignalNewGame;
LastGameButton.Pressed += EmitSignalLastGame;
LoadGameButton.Pressed += EmitSignalLoadGame;
OptionsButton.Pressed += EmitSignalOptions;
ModsButton.Pressed += EmitSignalMods;
ExitButton.Pressed += EmitSignalExit;
}
public void OnExitTree()
{
NewGameButton.Pressed -= EmitSignalNewGame;
LastGameButton.Pressed -= EmitSignalLastGame;
LoadGameButton.Pressed -= EmitSignalLoadGame;
OptionsButton.Pressed -= EmitSignalOptions;
ModsButton.Pressed -= EmitSignalMods;
ExitButton.Pressed -= EmitSignalExit;
}
public void OnResolved()
{
}
public void SetLastGameVisible(bool visible) => LastGameButton.SetVisible(visible);
}

View File

@@ -0,0 +1 @@
uid://b15y3vees54pm

View File

@@ -0,0 +1,70 @@
[gd_scene format=3 uid="uid://nwt8o860iibl"]
[ext_resource type="Script" uid="uid://b15y3vees54pm" path="res://src/TitleMenu/MainMenu.cs" id="1_n52a4"]
[node name="MainMenu" type="Control" unique_id=869490384]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_n52a4")
[node name="VBoxContainer" type="VSplitContainer" parent="." unique_id=1896453495]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Title" type="Label" parent="VBoxContainer" unique_id=1325212057]
layout_mode = 2
size_flags_horizontal = 4
text = "Food Factory"
horizontal_alignment = 1
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer" unique_id=816832571]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/PanelContainer" unique_id=784552700]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
[node name="LastGameButton" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer" unique_id=1319799462]
unique_name_in_owner = true
layout_mode = 2
text = "Last Game
"
[node name="NewGameButton" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer" unique_id=1248735168]
unique_name_in_owner = true
layout_mode = 2
text = "New Game
"
[node name="LoadGameButton" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer" unique_id=87939676]
unique_name_in_owner = true
layout_mode = 2
text = "Load Game"
[node name="OptionsButton" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer" unique_id=422294180]
unique_name_in_owner = true
layout_mode = 2
text = "Options
"
[node name="ModsButton" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer" unique_id=1024632422]
unique_name_in_owner = true
layout_mode = 2
text = "Mods"
[node name="ExitButton" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer" unique_id=752681601]
unique_name_in_owner = true
layout_mode = 2
text = "Exit"

View File

@@ -0,0 +1,150 @@
namespace FoodFactory.Modding;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.IO.Compression;
using System.Linq;
using System.Numerics;
using TrimKit.VirtualFileSystem;
public interface IModManger : IDisposable
{
// VFSManager VFSManager { get; }
IModCatalog AllMods { get; }
ModProfiles Profiles { get; }
}
public interface IModCatalog
{
IEnumerable<ModInfo> GetMods();
}
public class ModProfiles : List<(string Name, LoadedMods Mods)>
{
private int _current = 0;
public int CurrentIndex => _current;
public LoadedMods Current => this[_current].Mods;
public void MakeCurrent(int index) => _current = index;
}
public class LoadedMods : List<ModInfo>, IModCatalog
{
public IEnumerable<ModInfo> GetMods() => this;
}
public class AllMods : IModCatalog
{
private readonly FilePath _modsRootFolder;
private readonly IFileSystem _fileSystem;
public AllMods(FilePath modsRootFolder, IFileSystem fileSystem)
{
_modsRootFolder = modsRootFolder;
_fileSystem = fileSystem;
}
public IEnumerable<ModInfo> GetMods()
{
var paths = _fileSystem.Directory.EnumerateDirectories(_modsRootFolder.Path);
foreach (var item in paths)
{
var info = TryGetModInfo(item);
if (info is null)
{
continue;
}
yield return info;
}
}
private ModInfo? TryGetModInfo(FilePath path)
{
foreach (var item in _fileSystem.Directory.GetFiles((string)path))
{
if (item.EndsWith("mod.json"))
{
using (var stream = _fileSystem.File.OpenText(item))
{
var info = new ModInfo(stream.ReadLine(), (string)path);
return info;
}
}
}
return null;
}
private ModInfo? TryGetModInfoFile(FilePath path)
{
throw new NotImplementedException();
if (!path.Path.EndsWith(".zip"))
{
return null;
}
// using (var stream = _fileSystem.File.OpenRead((string)path))
// using (var zip = new ZipArchive(stream, ZipArchiveMode.Read, false))
// {
// zip.Entries.Where()
// var info = new ModInfo(steam.ReadLine(), (string)path);
// return info;
// }
return null;
}
}
public sealed class ModManger : IModManger
{
private readonly VFSManager _vFSManager = new();
private bool _disposedValue;
public VFSManager VFSManager => _vFSManager;
public required IModCatalog AllMods { get; init; }
public required ModProfiles Profiles {get;init;}
private void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
_vFSManager.Dispose();
// TODO: dispose managed state (managed objects)
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null
_disposedValue = true;
}
}
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
// ~ModManger()
// {
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
// Dispose(disposing: false);
// }
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public void LoadMod(ModInfo modInfo)
{
_vFSManager.AddRootContainer((string)modInfo.FilePath);
// _vFSManager.
}
}
public record ModInfo(string ModName, FilePath FilePath)
{
// internal bool BaseGame { get; init; }
}
public readonly record struct FilePath(string Path) //:
// IAdditionOperators<FilePath,FilePath,FilePath>
{
// public static FilePath operator +(FilePath left, FilePath right) => new();
public static implicit operator FilePath(string path) => new(path);
public static explicit operator string(FilePath path) => path.Path;
}

View File

@@ -0,0 +1 @@
uid://c1weeb6ym0ufv

View File

@@ -0,0 +1,42 @@
[gd_scene format=3 uid="uid://cw6lqmgdppnvf"]
[ext_resource type="Script" uid="uid://opbkqoaa7x2n" path="res://src/Equipment/Balancer.cs" id="1_n5njw"]
[ext_resource type="Script" uid="uid://ee5aoxi8mjnw" path="res://src/Equipment/BeltPort.cs" id="2_5u1f8"]
[sub_resource type="BoxMesh" id="BoxMesh_2wkfx"]
size = Vector3(1, 1, 2)
[node name="Balancer" type="Node3D" unique_id=957436190]
script = ExtResource("1_n5njw")
[node name="Node3D" type="Node3D" parent="." unique_id=43944623]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("2_5u1f8")
Face = 4
Width = 1
Access = 2
[node name="Node3D3" type="Node3D" parent="." unique_id=296414815]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("2_5u1f8")
Face = 4
Width = 1
Access = 1
[node name="Node3D4" type="Node3D" parent="." unique_id=572337826]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 1)
script = ExtResource("2_5u1f8")
Face = 4
Width = 1
Access = 1
[node name="Node3D2" type="Node3D" parent="." unique_id=972888293]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 1)
script = ExtResource("2_5u1f8")
Face = 4
Width = 1
Access = 2
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1965393798]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.5)
mesh = SubResource("BoxMesh_2wkfx")

46
src/VoxelGrid/Slicer.tscn Normal file
View File

@@ -0,0 +1,46 @@
[gd_scene format=3 uid="uid://b5dlh57o6ke0m"]
[ext_resource type="Script" uid="uid://yec84plemjv1" path="res://src/Equipment/SlicerTest.cs" id="1_5d422"]
[ext_resource type="Script" uid="uid://ee5aoxi8mjnw" path="res://src/Equipment/BeltPort.cs" id="2_l6rs8"]
[ext_resource type="PackedScene" uid="uid://h00mq2srsbfa" path="res://assets/kenney_conveyor-kit/Models/GLB format/door.glb" id="3_h185v"]
[sub_resource type="Curve3D" id="Curve3D_mxaon"]
_data = {
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0.5, -0.5, 0, 0, 0, 0, 0, 0, 0, 0.5, 0),
"tilts": PackedFloat32Array(0, 0)
}
point_count = 2
[node name="Slicer" type="Node3D" unique_id=1687444994]
script = ExtResource("1_5d422")
[node name="Node3D4" type="Node3D" parent="." unique_id=954393339]
transform = Transform3D(-1, 0, 8.742277e-08, 0, 1, 0, -8.742277e-08, 0, -1, 0, 0, 0)
script = ExtResource("2_l6rs8")
Face = 4
Width = 1
Access = 1
PortName = "Input"
[node name="Path3D" type="Path3D" parent="Node3D4" unique_id=1897251283]
curve = SubResource("Curve3D_mxaon")
[node name="door3" parent="Node3D4" unique_id=1437027122 instance=ExtResource("3_h185v")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.870017e-08, 0, -0.6001501)
[node name="Node3D5" type="Node3D" parent="." unique_id=1324644847]
transform = Transform3D(1, 0, -1.7484555e-07, 0, 1, 0, 1.7484555e-07, 0, 1, 0, 0, 0)
script = ExtResource("2_l6rs8")
Face = 4
Width = 1
Access = 2
PortName = "OutPut"
[node name="Path3D2" type="Path3D" parent="Node3D5" unique_id=223109856]
curve = SubResource("Curve3D_mxaon")
[node name="door4" parent="Node3D5" unique_id=58698002 instance=ExtResource("3_h185v")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.9604645e-08, 0, -0.3998499)
[node name="door5" parent="Node3D5" unique_id=965836258 instance=ExtResource("3_h185v")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.9604645e-08, 0, -0.3998499)

View File

@@ -0,0 +1,27 @@
[gd_scene format=3 uid="uid://bbdtdqr4demip"]
[ext_resource type="Script" uid="uid://cnkblltup5guy" path="res://src/Equipment/OvenTest.cs" id="1_56ur6"]
[ext_resource type="Script" uid="uid://ee5aoxi8mjnw" path="res://src/Equipment/BeltPort.cs" id="2_p5qnq"]
[ext_resource type="PackedScene" uid="uid://bkg733oidira6" path="res://assets/KayKit_Restaurant_Bits_1.0_FREE/Assets/gltf/oven.gltf" id="3_8h2ny"]
[node name="OvenTest" type="Node3D" unique_id=1361096630]
script = ExtResource("1_56ur6")
[node name="Node3D2" type="Node3D" parent="." unique_id=1862798218]
transform = Transform3D(1.3113416e-07, 0, 1, 0, 1, 0, -1, 0, 1.3113416e-07, 0, 0, 0)
script = ExtResource("2_p5qnq")
Face = 4
Width = 1
Access = 1
PortName = "Input"
[node name="Node3D3" type="Node3D" parent="." unique_id=1445106382]
transform = Transform3D(-2.1855693e-07, 0, -1, 0, 1, 0, 1, 0, -2.1855693e-07, 0, 0, 0)
script = ExtResource("2_p5qnq")
Face = 4
Width = 1
Access = 2
PortName = "OutPut"
[node name="oven" parent="." unique_id=169939827 instance=ExtResource("3_8h2ny")]
transform = Transform3D(-2.1855694e-08, 0, -0.5, 0, 0.5, 0, 0.5, 0, -2.1855694e-08, 0, 0, 0)

View File

@@ -57,8 +57,8 @@ IProvide<IItemRenderer>,
IProvide<IRecipes>,
IProvide<IBlueprintManger>,
IProvide<World>,
IProvide<IFoodFactoryApi>,
IProvide<ISaveChunk<GameData>>
IProvide<IFoodFactoryApi>//,
// IProvide<ISaveChunk<GameData>>
{
public override void _Notification(int what) => this.Notify(what);
@@ -74,7 +74,7 @@ IProvide<ISaveChunk<GameData>>
IRecipes IProvide<IRecipes>.Value() => _recipes;
private IItemRenderer _itemRenderer = default!;
IItemRenderer IProvide<IItemRenderer>.Value() => _itemRenderer;
public ISaveChunk<GameData> Value() => SaveFile.Root;
// public ISaveChunk<GameData> Value() => SaveFile.Root;
public static string SavePath => $"{OS.GetUserDataDir()}/SaveFile.json";
JsonSerializerOptions _options;
public void Setup()
@@ -89,47 +89,47 @@ IProvide<ISaveChunk<GameData>>
var test = "gg";
GD.Print(SavePath);
SaveFile = new SaveFile<GameData>(
new SaveChunk<GameData>(
onSave: (chunk) =>
{
// SaveFile = new SaveFile<GameData>(
// new SaveChunk<GameData>(
// onSave: (chunk) =>
// {
var gameData = new GameData()
{
World = _world,
// Equipments = chunk.GetChunkSaveData<EquipmentsData>()
};
return gameData;
},
onLoad: (chunk, data) =>
{
World.Destroy(_world);
_world = data.World;
// chunk.LoadChunkSaveData(data.Equipments);
}
),
onSave: async data =>
{
// var gameData = new GameData()
// {
// World = _world,
// // Equipments = chunk.GetChunkSaveData<EquipmentsData>()
// };
// return gameData;
// },
// onLoad: (chunk, data) =>
// {
// World.Destroy(_world);
// _world = data.World;
// // chunk.LoadChunkSaveData(data.Equipments);
// }
// ),
// onSave: async data =>
// {
var yaml = JsonSerializer.Serialize(data, _options);
GD.Print(SavePath);
await File.WriteAllTextAsync(SavePath, yaml);
},
onLoad: async () =>
{
if (!File.Exists(SavePath))
{
GD.PushWarning("Save does nto exist");
return null;
}
// var yaml = JsonSerializer.Serialize(data, _options);
// GD.Print(SavePath);
// await File.WriteAllTextAsync(SavePath, yaml);
// },
// onLoad: async () =>
// {
// if (!File.Exists(SavePath))
// {
// GD.PushWarning("Save does nto exist");
// return null;
// }
var data = JsonSerializer.Deserialize<GameData>(await File.ReadAllTextAsync(SavePath), _options);
return data;
}
);
// var data = JsonSerializer.Deserialize<GameData>(await File.ReadAllTextAsync(SavePath), _options);
// return data;
// }
// );
}
public ISaveFile<GameData> SaveFile { get; set; } = default!;
// public ISaveFile<GameData> SaveFile { get; set; } = default!;
Group<float> _systems;
public override void _Ready()
{
@@ -190,12 +190,12 @@ IProvide<ISaveChunk<GameData>>
}
if (@event.IsActionPressed("ui_right"))
{
SaveFile.Save();
// SaveFile.Save();
}
if (@event.IsActionPressed("ui_left"))
{
SaveFile.Load();
// SaveFile.Load();
}
}
public override void _ExitTree()

View File

@@ -1,29 +1,10 @@
[gd_scene format=3 uid="uid://dfacxkkkc0v10"]
[ext_resource type="Script" uid="uid://dcrb286hmpli" path="res://src/VoxelGrid/VoxelGridNode.cs" id="1_tsdpe"]
[ext_resource type="Script" uid="uid://cnkblltup5guy" path="res://src/Equipment/OvenTest.cs" id="3_r7dgx"]
[ext_resource type="PackedScene" uid="uid://bktqs1lw6go4" path="res://src/VoxelGrid/ItemSpawner.tscn" id="5_mxaon"]
[ext_resource type="PackedScene" uid="uid://bkg733oidira6" path="res://assets/KayKit_Restaurant_Bits_1.0_FREE/Assets/gltf/oven.gltf" id="5_ujjjs"]
[ext_resource type="PackedScene" uid="uid://h00mq2srsbfa" path="res://assets/kenney_conveyor-kit/Models/GLB format/door.glb" id="5_wk2t5"]
[ext_resource type="Script" uid="uid://ee5aoxi8mjnw" path="res://src/Equipment/BeltPort.cs" id="6_2wkfx"]
[ext_resource type="PackedScene" uid="uid://c4h7mwnfrdesg" path="res://src/Conveyors/ConveyorBeltStraight/ConveyorBeltStraight.tscn" id="6_mxaon"]
[ext_resource type="Script" uid="uid://opbkqoaa7x2n" path="res://src/Equipment/Balancer.cs" id="7_2wkfx"]
[ext_resource type="Script" uid="uid://yec84plemjv1" path="res://src/Equipment/SlicerTest.cs" id="8_2lg7i"]
[ext_resource type="Script" uid="uid://culjdbwllmsyk" path="res://src/Equipment/StackerTest.cs" id="8_e2skk"]
[ext_resource type="PackedScene" uid="uid://dr5gfg25sjr04" path="res://src/VoxelGrid/RtsController.tscn" id="11_21ota"]
[ext_resource type="Script" uid="uid://0yvk53xc1dix" path="res://src/VoxelGrid/ItemPlacerTest.cs" id="12_6whqj"]
[ext_resource type="Resource" uid="uid://cus0vfrtgh0uh" path="res://src/VoxelGrid/test_equipment.tres" id="13_njjff"]
[sub_resource type="BoxMesh" id="BoxMesh_2wkfx"]
size = Vector3(1, 1, 2)
[sub_resource type="Curve3D" id="Curve3D_mxaon"]
_data = {
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0.5, -0.5, 0, 0, 0, 0, 0, 0, 0, 0.5, 0),
"tilts": PackedFloat32Array(0, 0)
}
point_count = 2
[sub_resource type="BoxMesh" id="BoxMesh_6whqj"]
size = Vector3(25, 1, 25)
@@ -33,325 +14,6 @@ size = Vector3(25, 1, 25)
[node name="VoxelGridNode" type="Node3D" unique_id=825696340]
script = ExtResource("1_tsdpe")
[node name="ConveyorBeltStraight5" parent="." unique_id=975225936 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 1, 0, 0)
[node name="ConveyorBeltStraight14" parent="." unique_id=1045608025 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 0, 0, 0)
[node name="ConveyorBeltStraight7" parent="." unique_id=1602707514 instance=ExtResource("6_mxaon")]
transform = Transform3D(-1, 0, -8.742277e-08, 0, 1, 0, 8.742277e-08, 0, -1, 1, 0, 1)
[node name="ConveyorBeltStraight8" parent="." unique_id=1032197109 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 1, 0, 2)
[node name="ConveyorBeltStraight24" parent="." unique_id=574723066 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 1, 0, 6)
[node name="ConveyorBeltStraight25" parent="." unique_id=1584944068 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 0, 0, 6)
[node name="ConveyorBeltStraight13" parent="." unique_id=490179430 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 2)
[node name="ConveyorBeltStraight20" parent="." unique_id=1684880263 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 4, 0, 2)
[node name="ConveyorBeltStraight15" parent="." unique_id=1971663524 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 3)
[node name="ConveyorBeltStraight23" parent="." unique_id=830278017 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 4, 0, 3)
[node name="ConveyorBeltStraight9" parent="." unique_id=1449572266 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 1)
[node name="ConveyorBeltStraight44" parent="." unique_id=27021356 instance=ExtResource("6_mxaon")]
transform = Transform3D(-1, 0, -8.742277e-08, 0, 1, 0, 8.742277e-08, 0, -1, 3, 0, 0)
[node name="ConveyorBeltStraight26" parent="." unique_id=181268712 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 5)
[node name="ConveyorBeltStraight27" parent="." unique_id=1546024538 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 6)
[node name="ConveyorBeltStraight42" parent="." unique_id=2038052188 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 4, 0, 6)
[node name="ConveyorBeltStraight43" parent="." unique_id=131250040 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 3, 0, 6)
[node name="ConveyorBeltStraight28" parent="." unique_id=1945842047 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 4)
[node name="ConveyorBeltStraight29" parent="." unique_id=116753972 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 8)
[node name="ConveyorBeltStraight30" parent="." unique_id=903050872 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 9)
[node name="ConveyorBeltStraight31" parent="." unique_id=848458617 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 7)
[node name="ConveyorBeltStraight32" parent="." unique_id=889036013 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 8)
[node name="ConveyorBeltStraight33" parent="." unique_id=992629708 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 9)
[node name="ConveyorBeltStraight34" parent="." unique_id=795974742 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 7, 0, 9)
[node name="ConveyorBeltStraight35" parent="." unique_id=601890089 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 5)
[node name="ConveyorBeltStraight36" parent="." unique_id=2134741630 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 7, 0, 4)
[node name="ConveyorBeltStraight37" parent="." unique_id=196786809 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 4)
[node name="ConveyorBeltStraight10" parent="." unique_id=68139731 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 4, 0, 1)
[node name="ConveyorBeltStraight11" parent="." unique_id=358641682 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 5, 0, 1)
[node name="ConveyorBeltStraight12" parent="." unique_id=310565328 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 6, 0, 1)
[node name="ConveyorBeltStraight17" parent="." unique_id=111805683 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, 1)
[node name="ConveyorBeltStraight21" parent="." unique_id=764425478 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, 2)
[node name="ConveyorBeltStraight22" parent="." unique_id=1089887693 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, 3)
[node name="ConveyorBeltStraight18" parent="." unique_id=971476244 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, 0)
[node name="ConveyorBeltStraight19" parent="." unique_id=1940918727 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 8, 0, -3)
[node name="ConveyorBeltStraight40" parent="." unique_id=1578916497 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 8, 0, -2)
[node name="ConveyorBeltStraight41" parent="." unique_id=1562444632 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 8, 0, -4)
[node name="ConveyorBeltStraight38" parent="." unique_id=1520289120 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, -3)
[node name="ConveyorBeltStraight39" parent="." unique_id=44974977 instance=ExtResource("6_mxaon")]
transform = Transform3D(1, 0, 1.7484555e-07, 0, 1, 0, -1.7484555e-07, 0, 1, 7, 0, -4)
[node name="ConveyorBeltStraight16" parent="." unique_id=1178816500 instance=ExtResource("6_mxaon")]
transform = Transform3D(1.3113416e-07, 0, -1, 0, 1, 0, 1, 0, 1.3113416e-07, 0, 0, 1)
[node name="OvenTest" type="Node3D" parent="." unique_id=824176002]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0)
script = ExtResource("3_r7dgx")
[node name="Node3D2" type="Node3D" parent="OvenTest" unique_id=1815100025]
transform = Transform3D(1.3113416e-07, 0, 1, 0, 1, 0, -1, 0, 1.3113416e-07, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 1
PortName = "Input"
[node name="Node3D3" type="Node3D" parent="OvenTest" unique_id=1033202746]
transform = Transform3D(-2.1855693e-07, 0, -1, 0, 1, 0, 1, 0, -2.1855693e-07, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 2
PortName = "OutPut"
[node name="oven" parent="OvenTest" unique_id=169939827 instance=ExtResource("5_ujjjs")]
transform = Transform3D(-2.1855694e-08, 0, -0.5, 0, 0.5, 0, 0.5, 0, -2.1855694e-08, 0, 0, 0)
[node name="ItemSpawner" parent="." unique_id=966349707 instance=ExtResource("5_mxaon")]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -1.0023941, 0, 0.0019463301)
ItemName = "raw_potato"
[node name="ItemSpawner2" parent="." unique_id=405829395 instance=ExtResource("5_mxaon")]
transform = Transform3D(3.059797e-07, 0, -1, 0, 1, 0, 1, 0, 3.059797e-07, -1, 0, 1)
ItemName = "raw_onion"
[node name="ItemSpawner3" parent="." unique_id=422927887 instance=ExtResource("5_mxaon")]
transform = Transform3D(3.059797e-07, 0, -1, 0, 1, 0, 1, 0, 3.059797e-07, -1, 0, 6)
ItemName = "raw_red_onion"
[node name="Balancer" type="Node3D" parent="." unique_id=619243985]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 2)
script = ExtResource("7_2wkfx")
[node name="Node3D" type="Node3D" parent="Balancer" unique_id=793236513]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 2
[node name="Node3D3" type="Node3D" parent="Balancer" unique_id=1846433120]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 1
[node name="Node3D4" type="Node3D" parent="Balancer" unique_id=1579207766]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 1)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 1
[node name="Node3D2" type="Node3D" parent="Balancer" unique_id=717100096]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 1)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 2
[node name="MeshInstance3D" type="MeshInstance3D" parent="Balancer" unique_id=383290173]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.5)
mesh = SubResource("BoxMesh_2wkfx")
[node name="Balancer3" type="Node3D" parent="." unique_id=457806568]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 2)
script = ExtResource("7_2wkfx")
[node name="Node3D" type="Node3D" parent="Balancer3" unique_id=1019210964]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 2
[node name="Node3D3" type="Node3D" parent="Balancer3" unique_id=1520385636]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 1
[node name="Node3D4" type="Node3D" parent="Balancer3" unique_id=2034092939]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 1)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 1
[node name="Node3D2" type="Node3D" parent="Balancer3" unique_id=1013256336]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 1)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 2
[node name="MeshInstance3D" type="MeshInstance3D" parent="Balancer3" unique_id=920267076]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.5)
mesh = SubResource("BoxMesh_2wkfx")
[node name="Balancer2" type="Node3D" parent="." unique_id=620786657]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 6)
script = ExtResource("8_e2skk")
[node name="Node3D" type="Node3D" parent="Balancer2" unique_id=1570745328]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 3
PortName = "OutPut"
[node name="Node3D3" type="Node3D" parent="Balancer2" unique_id=1793642533]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 3
PortName = "Input"
[node name="MeshInstance3D" type="MeshInstance3D" parent="Balancer2" unique_id=1733942784]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.5)
mesh = SubResource("BoxMesh_2wkfx")
[node name="Balancer8" type="Node3D" parent="." unique_id=1783081047]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 7, 0, -1)
script = ExtResource("7_2wkfx")
[node name="Node3D" type="Node3D" parent="Balancer8" unique_id=1818940385]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 2
[node name="Node3D3" type="Node3D" parent="Balancer8" unique_id=51764402]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 1
[node name="Node3D4" type="Node3D" parent="Balancer8" unique_id=233486636]
transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 1)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 1
[node name="Node3D2" type="Node3D" parent="Balancer8" unique_id=1446214840]
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, 0, 0, 1)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 2
[node name="MeshInstance3D" type="MeshInstance3D" parent="Balancer8" unique_id=556689065]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0.5)
mesh = SubResource("BoxMesh_2wkfx")
[node name="Slicer" type="Node3D" parent="." unique_id=566544377]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 0, -2)
script = ExtResource("8_2lg7i")
[node name="Node3D4" type="Node3D" parent="Slicer" unique_id=1206144064]
transform = Transform3D(-1, 0, 8.742277e-08, 0, 1, 0, -8.742277e-08, 0, -1, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 1
PortName = "Input"
[node name="Path3D" type="Path3D" parent="Slicer/Node3D4" unique_id=894348025]
curve = SubResource("Curve3D_mxaon")
[node name="door3" parent="Slicer/Node3D4" unique_id=1024066398 instance=ExtResource("5_wk2t5")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.870017e-08, 0, -0.6001501)
[node name="Node3D5" type="Node3D" parent="Slicer" unique_id=1113082191]
transform = Transform3D(1, 0, -1.7484555e-07, 0, 1, 0, 1.7484555e-07, 0, 1, 0, 0, 0)
script = ExtResource("6_2wkfx")
Face = 4
Width = 1
Access = 2
PortName = "OutPut"
[node name="Path3D2" type="Path3D" parent="Slicer/Node3D5" unique_id=1352328131]
curve = SubResource("Curve3D_mxaon")
[node name="door4" parent="Slicer/Node3D5" unique_id=1411233670 instance=ExtResource("5_wk2t5")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.9604645e-08, 0, -0.3998499)
[node name="door5" parent="Slicer/Node3D5" unique_id=770270315 instance=ExtResource("5_wk2t5")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.9604645e-08, 0, -0.3998499)
[node name="RTS" parent="." unique_id=1383983755 instance=ExtResource("11_21ota")]
[node name="Node" type="Node" parent="RTS" unique_id=1499015368]

34
test/src/App/AppTest.cs Normal file
View File

@@ -0,0 +1,34 @@
// namespace FoodFactory;
// using System.Threading.Tasks;
// using Chickensoft.GoDotTest;
// using Chickensoft.GodotTestDriver;
// using Chickensoft.GodotTestDriver.Drivers;
// using Godot;
// using Shouldly;
// public class GameTest : TestClass
// {
// private App _game = default!;
// private Fixture _fixture = default!;
// public GameTest(Node testScene) : base(testScene) { }
// [SetupAll]
// public async Task Setup()
// {
// _fixture = new Fixture(TestScene.GetTree());
// _game = await _fixture.LoadAndAddScene<App>();
// }
// [CleanupAll]
// public void Cleanup() => _fixture.Cleanup();
// [Test]
// public void TestButtonUpdatesCounter()
// {
// var buttonDriver = new ButtonDriver(() => _game.TestButton);
// buttonDriver.ClickCenter();
// _game.ButtonPresses.ShouldBe(1);
// }
// }

View File

@@ -1,34 +0,0 @@
namespace FoodFactory;
using System.Threading.Tasks;
using Chickensoft.GoDotTest;
using Chickensoft.GodotTestDriver;
using Chickensoft.GodotTestDriver.Drivers;
using Godot;
using Shouldly;
public class GameTest : TestClass
{
private Game _game = default!;
private Fixture _fixture = default!;
public GameTest(Node testScene) : base(testScene) { }
[SetupAll]
public async Task Setup()
{
_fixture = new Fixture(TestScene.GetTree());
_game = await _fixture.LoadAndAddScene<Game>();
}
[CleanupAll]
public void Cleanup() => _fixture.Cleanup();
[Test]
public void TestButtonUpdatesCounter()
{
var buttonDriver = new ButtonDriver(() => _game.TestButton);
buttonDriver.ClickCenter();
_game.ButtonPresses.ShouldBe(1);
}
}