From 5f19adcb439772c02cba6113285d2ea8b4b4f7fe Mon Sep 17 00:00:00 2001 From: milan Date: Sun, 13 Nov 2022 20:49:32 +0100 Subject: [PATCH] module state game objects --- .../Engine/Scripts/Editor/EngineEditor.cs | 31 ++++++--- .../Engine/Scripts/Engine.cs | 15 ++++- .../Engine/Scripts/Modules/DoorModule.cs | 16 +++-- .../Engine/Scripts/Modules/DoorState.cs | 66 +++++++++++++++++++ .../Engine/Scripts/Modules/DoorState.cs.meta | 3 + .../Engine/Scripts/Modules/Module.cs | 33 ++++++---- .../Engine/Scripts/Modules/ModuleState.cs | 11 ++++ .../Scripts/Modules/ModuleState.cs.meta | 3 + .../Engine/Scripts/Modules/PuzzleModule.cs | 46 +++---------- .../Engine/Scripts/Modules/PuzzleState.cs | 66 +++++++++++++++++++ .../Scripts/Modules/PuzzleState.cs.meta | 3 + .../Escape Room Engine/Engine/Scripts/Room.cs | 33 +++++++--- .../Engine/Scripts/Space.cs | 9 +-- 13 files changed, 251 insertions(+), 84 deletions(-) create mode 100644 Assets/Escape Room Engine/Engine/Scripts/Modules/DoorState.cs create mode 100644 Assets/Escape Room Engine/Engine/Scripts/Modules/DoorState.cs.meta create mode 100644 Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleState.cs create mode 100644 Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleState.cs.meta create mode 100644 Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleState.cs create mode 100644 Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleState.cs.meta diff --git a/Assets/Escape Room Engine/Engine/Scripts/Editor/EngineEditor.cs b/Assets/Escape Room Engine/Engine/Scripts/Editor/EngineEditor.cs index 3351bd5..30d7384 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Editor/EngineEditor.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Editor/EngineEditor.cs @@ -6,9 +6,10 @@ namespace Escape_Room_Engine.Engine.Scripts.Editor { public class EngineEditor : EditorWindow { - private Button _generateRoomButton, _skipCurrentRoomButton; + private bool _registeredUpdateEvent; + private Button _passToNextRoomButton, _skipCurrentRoomButton; - [MenuItem("Window/Engine/Engine Editor")] + [MenuItem("Window/Engine Editor")] public static void ShowEditor() { var window = GetWindow(); @@ -17,11 +18,11 @@ namespace Escape_Room_Engine.Engine.Scripts.Editor public void CreateGUI() { - _generateRoomButton = new Button(GenerateRoom) + _passToNextRoomButton = new Button(PassToNextRoom) { - text = "Generate Room" + text = "Pass To Next Room" }; - rootVisualElement.Add(_generateRoomButton); + rootVisualElement.Add(_passToNextRoomButton); _skipCurrentRoomButton = new Button(SkipCurrentRoom) { text = "Skip Current Room" @@ -32,12 +33,11 @@ namespace Escape_Room_Engine.Engine.Scripts.Editor UpdateUI(); } - private void GenerateRoom() + private void PassToNextRoom() { if (EditorApplication.isPlaying) { - Engine.DefaultEngine.HideOldestRoom(); - Engine.DefaultEngine.GenerateRoom(); + Engine.DefaultEngine.HidePreviousRoom(); UpdateUI(); } } @@ -53,7 +53,20 @@ namespace Escape_Room_Engine.Engine.Scripts.Editor private void UpdateUI() { - _generateRoomButton.SetEnabled(EditorApplication.isPlaying); + if (EditorApplication.isPlaying) + { + if (!_registeredUpdateEvent) + { + Engine.DefaultEngine.UpdateUIEvent += UpdateUI; + _registeredUpdateEvent = true; + } + } + else + { + _registeredUpdateEvent = false; + } + + _passToNextRoomButton.SetEnabled(EditorApplication.isPlaying && Engine.DefaultEngine.NumberOfRooms > 1); _skipCurrentRoomButton.SetEnabled(EditorApplication.isPlaying && Engine.DefaultEngine.NumberOfRooms > 0); } } diff --git a/Assets/Escape Room Engine/Engine/Scripts/Engine.cs b/Assets/Escape Room Engine/Engine/Scripts/Engine.cs index 9a76611..7109cb2 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Engine.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Engine.cs @@ -25,6 +25,9 @@ namespace Escape_Room_Engine.Engine.Scripts } private static Engine _foundEngine; + public delegate void UpdateUIHandler(); + public event UpdateUIHandler UpdateUIEvent; + [Required] public EngineConfiguration config; public int NumberOfRooms => _rooms.Count; @@ -38,6 +41,8 @@ namespace Escape_Room_Engine.Engine.Scripts _playSpaceOrigin = new GameObject("Play Space Origin"); _playSpaceOrigin.transform.SetParent(transform); _playSpaceOrigin.transform.localPosition = new Vector3(-config.playSpace.x / 2f, 0, -config.playSpace.y / 2f); + + GenerateRoom(); } public void GenerateRoom() @@ -53,6 +58,8 @@ namespace Escape_Room_Engine.Engine.Scripts GenerateSpace(room, entrance); // TODO: rooms with more than one space room.InstantiateRoom(_playSpaceOrigin.transform, (_rooms.Count - 1).ToString()); + + UpdateUI(); } private void GenerateSpace(Room room, Passage entrance) @@ -77,14 +84,16 @@ namespace Escape_Room_Engine.Engine.Scripts room.AddSpace(space, exit); } - public void HideOldestRoom() + public void HidePreviousRoom() { - if (NumberOfRooms > 0) + if (NumberOfRooms > 1) { - _rooms[NumberOfRooms - 1].roomObject.SetActive(false); + _rooms[NumberOfRooms - 2].roomObject.SetActive(false); } } + private void UpdateUI() => UpdateUIEvent?.Invoke(); + // ReSharper disable once SuggestBaseTypeForParameter // ReSharper disable once UnusedMember.Local private bool IsNotEmpty(List modules) => modules.Count > 0; diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorModule.cs b/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorModule.cs index c6ae82d..264a311 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorModule.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorModule.cs @@ -1,6 +1,5 @@ using System; using UnityEngine; -using LogType = Escape_Room_Engine.Engine.Scripts.Utilities.LogType; namespace Escape_Room_Engine.Engine.Scripts.Modules { @@ -14,19 +13,24 @@ namespace Escape_Room_Engine.Engine.Scripts.Modules { public bool IsEntrance => IsType((ModuleType)DoorType.Entrance); public bool IsExit => IsType((ModuleType)DoorType.Exit); - - private bool _unlocked; + internal new DoorState State { get; private set; } internal DoorModule(Space space, DoorModuleDescription description) : base(space, description) { srDimensions.Size = Vector2Int.one; // door always has size 1x1 } - internal void Unlock() + internal override void InstantiateModule(Transform parent) { - _unlocked = true; + base.InstantiateModule(parent); - Utilities.Logger.Log($"{this} has been unlocked", LogType.PuzzleFlow); + space.room.AddDoor(this); + } + + protected override void AddStateComponent() + { + State = moduleObject.AddComponent(); + State.SetModule(this); } public override string ToString() diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorState.cs b/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorState.cs new file mode 100644 index 0000000..be212d3 --- /dev/null +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorState.cs @@ -0,0 +1,66 @@ +using System; +using Escape_Room_Engine.Engine.Scripts.Utilities; +using NaughtyAttributes; + +namespace Escape_Room_Engine.Engine.Scripts.Modules +{ + public enum DoorEventType + { + Locked, Unlocked + } + + public delegate void DoorEventHandler(DoorModule source, DoorEventType e); + + public class DoorState : ModuleState + { + public event DoorEventHandler DoorEvent; + + private new DoorModule Module { get; set; } + public bool Unlocked + { + get => _unlocked; + private set + { + var type = + !_unlocked && value ? Some.Of(DoorEventType.Unlocked) + : _unlocked && !value ? Some.Of(DoorEventType.Locked) + : None.New(); + _unlocked = value; + type.Match(some: OnDoorEvent); + } + } + + private bool _unlocked; + + private void OnDoorEvent(DoorEventType type) + { + Logger.Log($"{Module} has been {type}", LogType.PuzzleFlow); + + DoorEvent?.Invoke(Module, type); + } + + public override void SetModule(Module module) + { + if (module is DoorModule doorModule) + { + Module = doorModule; + } + else + { + throw new Exception("Tried to set wrong type of module."); + } + } + + [Button(enabledMode: EButtonEnableMode.Playmode)] + internal void Unlock() + { + Unlocked = true; + } + + [Button(enabledMode: EButtonEnableMode.Playmode)] + internal void Lock() + { + Unlocked = false; + } + } +} \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorState.cs.meta b/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorState.cs.meta new file mode 100644 index 0000000..d51de0b --- /dev/null +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/DoorState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 696181e3eda449d49d4c1c88b07d7b05 +timeCreated: 1668337769 \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/Module.cs b/Assets/Escape Room Engine/Engine/Scripts/Modules/Module.cs index 1e6c03f..81e729c 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Modules/Module.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/Module.cs @@ -28,7 +28,8 @@ namespace Escape_Room_Engine.Engine.Scripts.Modules /// /// Get the room relative (RR) position of this module. /// - internal Vector2Int RrPosition => _space.ToRoomRelative(SrPosition); + internal Vector2Int RrPosition => space.ToRoomRelative(SrPosition); + internal ModuleState State { get; private set; } internal readonly ModuleDescription description; internal Orientation orientation; @@ -38,12 +39,13 @@ namespace Escape_Room_Engine.Engine.Scripts.Modules /// protected Dimensions srDimensions; - private GameObject _moduleObject, _orientationObject; - private readonly Space _space; + protected GameObject moduleObject; + protected readonly Space space; + private GameObject _orientationObject; internal Module(Space space, ModuleDescription description) { - _space = space; + this.space = space; this.description = description; } @@ -57,16 +59,16 @@ namespace Escape_Room_Engine.Engine.Scripts.Modules /// /// The room relative (RR) position of this module. Must be inside the space dimensions. /// If the position is not inside the space dimensions. - internal void PlaceRoomRelative(Vector2Int rrPosition) => Place(_space.ToSpaceRelative(rrPosition)); + internal void PlaceRoomRelative(Vector2Int rrPosition) => Place(space.ToSpaceRelative(rrPosition)); /// /// Place this module with a position relative to the space it is in. /// /// The space relative (SR) position of this module. Must be inside the space dimensions. /// If the position is not inside the space dimensions. internal void Place(Vector2Int srPosition) { - if (_space != null && !srPosition.IsInsideRelative(_space.rrDimensions)) + if (space != null && !srPosition.IsInsideRelative(space.rrDimensions)) { - throw new Exception($"Trying to place {this} at {srPosition}, which is outside space dimensions {_space.rrDimensions}."); + throw new Exception($"Trying to place {this} at {srPosition}, which is outside space dimensions {space.rrDimensions}."); } srDimensions.Position = srPosition; @@ -92,19 +94,26 @@ namespace Escape_Room_Engine.Engine.Scripts.Modules }; } - internal void InstantiateModule(Transform parent) + internal virtual void InstantiateModule(Transform parent) { - _moduleObject = new GameObject(ToString()); - _moduleObject.transform.SetParent(parent, false); - _moduleObject.transform.localPosition = new Vector3(srDimensions.x + .5f, 0, srDimensions.z + .5f); + moduleObject = new GameObject(ToString()); + moduleObject.transform.SetParent(parent, false); + moduleObject.transform.localPosition = new Vector3(srDimensions.x + .5f, 0, srDimensions.z + .5f); + AddStateComponent(); _orientationObject = new GameObject("Orientation"); - _orientationObject.transform.SetParent(_moduleObject.transform, false); + _orientationObject.transform.SetParent(moduleObject.transform, false); _orientationObject.transform.Rotate(Vector3.up, (float)orientation); Object.Instantiate(description.modulePrefab, _orientationObject.transform, false); } + protected virtual void AddStateComponent() + { + State = moduleObject.AddComponent(); + State.SetModule(this); + } + public override string ToString() { return $"Module ({string.Join(", ", description.types.ToList().ConvertAll(type => type.ToString()))})"; diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleState.cs b/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleState.cs new file mode 100644 index 0000000..8df075f --- /dev/null +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleState.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace Escape_Room_Engine.Engine.Scripts.Modules +{ + public class ModuleState : MonoBehaviour + { + public Module Module { get; protected set; } + + public virtual void SetModule(Module module) => Module = module; + } +} \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleState.cs.meta b/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleState.cs.meta new file mode 100644 index 0000000..ae77d3d --- /dev/null +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/ModuleState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: efdc32c450f7411385748449459a17b4 +timeCreated: 1668180361 \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleModule.cs b/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleModule.cs index 43a20ff..02a0849 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleModule.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleModule.cs @@ -1,57 +1,27 @@ -using Escape_Room_Engine.Engine.Scripts.Utilities; -using UnityEngine; -using Logger = Escape_Room_Engine.Engine.Scripts.Utilities.Logger; -using LogType = Escape_Room_Engine.Engine.Scripts.Utilities.LogType; +using UnityEngine; namespace Escape_Room_Engine.Engine.Scripts.Modules { - public enum PuzzleEventType - { - Reset, Solved - } - - public delegate void PuzzleEventHandler(PuzzleModule source, PuzzleEventType e); - public class PuzzleModule : Module { - internal event PuzzleEventHandler PuzzleEvent; - - internal bool Solved - { - get => _solved; - private set - { - var type = - !_solved && value ? Some.Of(PuzzleEventType.Solved) - : _solved && value ? Some.Of(PuzzleEventType.Reset) - : None.New(); - _solved = value; - type.Match(some: OnPuzzleEvent); - } - } - - private bool _solved; + internal new PuzzleState State { get; private set; } internal PuzzleModule(Space space, PuzzleModuleDescription description) : base(space, description) { srDimensions.Size = Vector2Int.one; // TODO: larger modules } - protected virtual void OnPuzzleEvent(PuzzleEventType type) + internal override void InstantiateModule(Transform parent) { - Logger.Log($"{this} has been {type}", LogType.PuzzleFlow); + base.InstantiateModule(parent); - PuzzleEvent?.Invoke(this, type); + space.room.AddPuzzle(this); } - public void Solve() + protected override void AddStateComponent() { - Solved = true; - } - - public override string ToString() - { - return $"Puzzle module ({(Solved ? "" : "not ")}solved)"; + State = moduleObject.AddComponent(); + State.SetModule(this); } } } \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleState.cs b/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleState.cs new file mode 100644 index 0000000..b605d6e --- /dev/null +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleState.cs @@ -0,0 +1,66 @@ +using System; +using Escape_Room_Engine.Engine.Scripts.Utilities; +using NaughtyAttributes; + +namespace Escape_Room_Engine.Engine.Scripts.Modules +{ + public enum PuzzleEventType + { + Restarted, Solved + } + + public delegate void PuzzleEventHandler(PuzzleModule source, PuzzleEventType e); + + public class PuzzleState : ModuleState + { + public event PuzzleEventHandler PuzzleEvent; + + private new PuzzleModule Module { get; set; } + public bool Solved + { + get => _solved; + private set + { + var type = + !_solved && value ? Some.Of(PuzzleEventType.Solved) + : _solved && !value ? Some.Of(PuzzleEventType.Restarted) + : None.New(); + _solved = value; + type.Match(some: OnPuzzleEvent); + } + } + + private bool _solved; + + private void OnPuzzleEvent(PuzzleEventType type) + { + Logger.Log($"{Module} has been {type}", LogType.PuzzleFlow); + + PuzzleEvent?.Invoke(Module, type); + } + + public override void SetModule(Module module) + { + if (module is PuzzleModule puzzleModule) + { + Module = puzzleModule; + } + else + { + throw new Exception("Tried to set wrong type of module."); + } + } + + [Button(enabledMode: EButtonEnableMode.Playmode)] + public void Solve() + { + Solved = true; + } + + [Button(enabledMode: EButtonEnableMode.Playmode)] + public void Restart() + { + Solved = false; + } + } +} \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleState.cs.meta b/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleState.cs.meta new file mode 100644 index 0000000..3006612 --- /dev/null +++ b/Assets/Escape Room Engine/Engine/Scripts/Modules/PuzzleState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 265ea1efb38042b282ea67c50ac3e878 +timeCreated: 1668180832 \ No newline at end of file diff --git a/Assets/Escape Room Engine/Engine/Scripts/Room.cs b/Assets/Escape Room Engine/Engine/Scripts/Room.cs index fc2d990..23261ac 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Room.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Room.cs @@ -14,6 +14,7 @@ namespace Escape_Room_Engine.Engine.Scripts private readonly List _spaces = new(); private readonly List _puzzles = new(); + private readonly List _doors = new(); internal Room(Passage entrance) { @@ -26,12 +27,6 @@ namespace Escape_Room_Engine.Engine.Scripts exit = spaceExit; } - internal void AddPuzzle(PuzzleModule puzzle) - { - _puzzles.Add(puzzle); - puzzle.PuzzleEvent += OnPuzzleEvent; - } - /// /// Solves all puzzles in this room. /// @@ -39,20 +34,40 @@ namespace Escape_Room_Engine.Engine.Scripts { Logger.Log($"Skipping {this}...", LogType.PuzzleFlow); - _puzzles.ForEach(puzzle => puzzle.Solve()); + _puzzles.ForEach(puzzle => puzzle.State.Solve()); + } + + internal void AddPuzzle(PuzzleModule puzzle) + { + _puzzles.Add(puzzle); + puzzle.State.PuzzleEvent += OnPuzzleEvent; } private void OnPuzzleEvent(PuzzleModule puzzle, PuzzleEventType type) { if (type == PuzzleEventType.Solved) { - if (_puzzles.All(p => p.Solved)) + if (_puzzles.All(p => p.State.Solved)) { - exit.fromOut.Unlock(); + exit.fromOut.State.Unlock(); } } } + internal void AddDoor(DoorModule door) + { + _doors.Add(door); + door.State.DoorEvent += OnDoorEvent; + } + + private void OnDoorEvent(DoorModule door, DoorEventType type) + { + if (type == DoorEventType.Unlocked && door.Equals(exit.fromOut)) + { + Engine.DefaultEngine.GenerateRoom(); + } + } + internal void InstantiateRoom(Transform parent, string name) { roomObject = new GameObject($"Room {name}"); diff --git a/Assets/Escape Room Engine/Engine/Scripts/Space.cs b/Assets/Escape Room Engine/Engine/Scripts/Space.cs index 60be555..35ea8ef 100644 --- a/Assets/Escape Room Engine/Engine/Scripts/Space.cs +++ b/Assets/Escape Room Engine/Engine/Scripts/Space.cs @@ -15,13 +15,13 @@ namespace Escape_Room_Engine.Engine.Scripts /// internal readonly Dimensions rrDimensions; internal List Modules { get; } = new(2); + internal readonly Room room; private GameObject _spaceObject, _spaceTiles; - private readonly Room _room; internal Space(Room room, Passage entrance) { - _room = room; + this.room = room; rrDimensions = GenerateSpaceDimensions( entrance, Engine.DefaultEngine.config.minRoomSize, @@ -36,11 +36,6 @@ namespace Escape_Room_Engine.Engine.Scripts internal void AddModule(Module module) { Modules.Add(module); - - if (module is PuzzleModule puzzleModule) - { - _room.AddPuzzle(puzzleModule); - } } internal bool AddModuleWithRequirements(Module module)