#pragma once #include "../engine/Shared.h" #include "Log.h" #include "Puzzle.h" #include "rendering/Rendering.h" #include #include #define ENTITY_HANDLE(X) \ struct X \ { \ uint16_t Idx = UINT16_MAX; \ }; \ inline bool IsValid(X h) \ { \ return h.Idx != UINT16_MAX; \ } namespace Game { struct EntityRenderData { Gen::Vec4 DotColor{1.0f, 1.0f, 1.0f, 1.0f}; Gen::Vec4 BaseColor{0.0f, 0.0f, 0.0f, 1.0f}; Gen::Transform Transform; Gen::EMaterial::Enum MaterialHandle = Gen::EMaterial::UI; Gen::TextureHandle TextureHandle; Gen::ModelHandle ModelH; bool Visible = true; void Render(const Model* models, const Material* materials, const Texture* textures); void LoadFromSaved(const Gen::SavedEntityRenderData& saved); }; ENTITY_HANDLE(CubeHandle); struct Cube { int32_t TestX = -1; int32_t TestY = -1; EntityRenderData EData; void Setup(); void Update(); }; ENTITY_HANDLE(TestEntityHandle); struct TestEntity { EntityRenderData EData; void Setup(); }; ENTITY_HANDLE(PuzzleTileEntityHandle); struct PuzzleTileEntity { EntityRenderData EData; }; ENTITY_HANDLE(PuzzleTileCoverHandle); struct PuzzleTileCover { EntityRenderData EData; }; ENTITY_HANDLE(UIQuadEntityHandle); struct UIQuadEntity { EntityRenderData EData; }; ENTITY_HANDLE(LevelEntityHandle); struct LevelEntity { EntityRenderData EData; }; class IEntityManager { public: virtual bool Setup(uint8_t*& ptr, bool forceReset) = 0; }; template class EntityManager : public IEntityManager { public: uint16_t Count = 0; T* Data = nullptr; uint32_t EntitySize = 0; T InvalidObject{}; bool IsEnabled = true; public: // Returns true if size changed bool Setup(uint8_t*& ptr, bool forceReset) { bool changed = false; if (EntitySize != sizeof(T) || forceReset) { Count = 0; changed = true; } EntitySize = sizeof(T); Data = reinterpret_cast(ptr); ptr += C * EntitySize; return changed; } HandleT New() { if (Data == nullptr) { ERROR_ONCE("Accessed EntityManager before setup!"); return {}; } if (Count >= C) { ERROR_ONCE("Too many entities!"); return {}; } Data[Count] = {}; HandleT H; H.Idx = Count; ++Count; return H; } T& Get(HandleT handle) { if (handle.Idx >= Count) { ERROR_ONCE("OOB Access!"); return InvalidObject; } return Data[handle.Idx]; } void Render(const Model* models, const Material* materials, const Texture* textures) { if (!IsEnabled) return; for (uint16_t i = 0; i < Count; ++i) { Get({i}).EData.Render(models, materials, textures); } } }; struct WorldPuzzle { static constexpr Gen::Vec2 WorldCardSize{10.0f, 10.0f}; static constexpr float UICardScale = 0.05f; static constexpr float UICardOffset = 2.1f * UICardScale; static constexpr int32_t UIAvailableCardMaxStackPreview = 3; Gen::PuzzleData Data; Gen::Vec3 WorldPosition; PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle]; PuzzleTileCoverHandle CoverHandles[Puzzle::Config::MaxCardsInPuzzle * Puzzle::Config::MaxCoversInTile]; UIQuadEntityHandle UIPlacedCards[Puzzle::Config::MaxCardsInPuzzle]; UIQuadEntityHandle UIAvailableCards[Puzzle::Config::MaxAvailableStacks * UIAvailableCardMaxStackPreview]; Gen::PuzPos DraggedCard{-1, -1}; uint16_t DraggedAvailableCardIdx = UINT16_MAX; bool IsSetup = false; bool IsActive = false; void Setup(); void Update(); }; class Level { public: EntityManager Cubes; EntityManager Tests; EntityManager PuzzleTiles; EntityManager PuzzleTileCovers; EntityManager UIQuads; EntityManager LevelEntities; CubeHandle PlayerOutsideViewCube; UIQuadEntityHandle TabletHandle; public: Gen::StaticPuzzleData PuzzleData; WorldPuzzle Puzzles[Puzzle::Config::MaxVisiblePuzzles]; public: void Setup(GameData& data); void Update(); void Render(uint16_t ViewID, const Model* models, const Material* materials, const Texture* textures); }; } // namespace Game