diff --git a/assets/blender/plane.blend b/assets/blender/plane.blend new file mode 100644 index 0000000..95489f8 --- /dev/null +++ b/assets/blender/plane.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:981ced151e6b052264dc7081422e6a4c0afaa65fbd19de9aa3d4c9207a520510 +size 926632 diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 27d1d73..1840282 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -62,12 +62,13 @@ namespace Game void Level::Setup(GameData& data) { - Log("Level setup"); + LOG("Level setup"); void* storagePtr = data.EntityStorage; bool needReset = false; needReset |= Cubes.Setup(storagePtr, needReset); needReset |= Tests.Setup(storagePtr, needReset); needReset |= PuzzleTiles.Setup(storagePtr, needReset); + needReset |= UIQuads.Setup(storagePtr, needReset); PuzzleData.Setup(); @@ -77,20 +78,17 @@ namespace Game { for (uint32_t xx = 0; xx < 11; ++xx) { - Cube* c = Cubes.Get(Cubes.New()); - if (c) - { - c->TestX = xx; - c->TestY = yy; - c->Setup(); - } + Cube& c = Cubes.Get(Cubes.New()); + c.TestX = xx; + c.TestY = yy; + c.Setup(); } } Cubes.New(); // Floor } if (Tests.Count == 0) { - Tests.Get(Tests.New())->Setup(); + Tests.Get(Tests.New()).Setup(); } if (PuzzleTiles.Count == 0) { @@ -168,7 +166,7 @@ namespace Game // Cubes for (uint16_t i = 0; i < Cubes.Count; ++i) { - Cubes.Get({i})->Update(); + Cubes.Get({i}).Update(); } // Puzzle tiles @@ -258,16 +256,21 @@ namespace Game for (uint32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI) { const Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; - auto& tiles = GetInstance().GameLevel.PuzzleTiles; - TileHandles[cardI] = tiles.New(); + auto& level = GetInstance().GameLevel; + TileHandles[cardI] = level.PuzzleTiles.New(); + UIPlacedCards[cardI] = level.UIQuads.New(); + bx::Vec3 Pos = { WorldPosition.x + card.Position.X * WorldCardSize.x, WorldPosition.y, WorldPosition.z + card.Position.Y * WorldCardSize.y, }; - auto& tile = *tiles.Get(TileHandles[cardI]); + auto& tile = level.PuzzleTiles.Get(TileHandles[cardI]); tile.EData.Transform.Position = Pos; tile.EData.MaterialHandle = 0; + + auto& quad = level.UIQuads.Get(UIPlacedCards[cardI]); + // quad.EData.Transform.Position.something; } } @@ -278,7 +281,8 @@ namespace Game Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; if (!card.RefCard.IsValid()) continue; const Puzzle::StaticPuzzleCard& cData = Puzzle::StaticPuzzleData::Get().GetCard(card.RefCard); - GetInstance().GameLevel.PuzzleTiles.Get(TileHandles[cardI])->EData.ModelHandle = cData.ModelHandle; + GetInstance().GameLevel.PuzzleTiles.Get(TileHandles[cardI]).EData.ModelHandle = cData.ModelHandle; + GetInstance().GameLevel.UIQuads.Get(UIPlacedCards[cardI]).EData.Transform.Position = {0, 0, 0}; } } } // namespace Game diff --git a/src/game/Level.h b/src/game/Level.h index 2af702a..01b2df0 100644 --- a/src/game/Level.h +++ b/src/game/Level.h @@ -51,12 +51,25 @@ namespace Game EntityRenderData EData; }; - template class EntityManager + ENTITY_HANDLE(UIQuadEntityHandle); + struct UIQuadEntity + { + EntityRenderData EData; + }; + + class IEntityManager + { + public: + virtual bool Setup(void*& ptr, bool forceReset) = 0; + }; + + template class EntityManager : public IEntityManager { public: uint16_t Count = 0; T* Data = nullptr; uint32_t EntitySize = 0; + T InvalidObject{}; public: // Returns true if size changed @@ -78,12 +91,12 @@ namespace Game { if (Data == nullptr) { - Log("Accessed EntityManager before setup!"); + ERROR_ONCE("Accessed EntityManager before setup!"); return {}; } if (Count >= C) { - Log("Too many entities!"); + ERROR_ONCE("Too many entities!"); return {}; } Data[Count] = {}; @@ -93,22 +106,21 @@ namespace Game return H; } - T* Get(HandleT handle) + T& Get(HandleT handle) { if (handle.Idx > Count) { - Log("OOB Access!"); - return nullptr; + ERROR_ONCE("OOB Access!"); + return InvalidObject; } - return &Data[handle.Idx]; + return Data[handle.Idx]; } void Render(const Model* models, const Material* materials) { for (uint16_t i = 0; i < Count; ++i) { - T* c = Get({i}); - if (c) c->EData.Render(models, materials); + Get({i}).EData.Render(models, materials); } } }; @@ -119,6 +131,7 @@ namespace Game Puzzle::PuzzleData Data; Vec3 WorldPosition; PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle]; + UIQuadEntityHandle UIPlacedCards[Puzzle::Config::MaxCardsInPuzzle]; void Setup(); void Update(); @@ -130,6 +143,8 @@ namespace Game EntityManager Cubes; EntityManager Tests; EntityManager PuzzleTiles; + EntityManager UIQuads; + public: Puzzle::StaticPuzzleData PuzzleData; diff --git a/src/game/Log.cpp b/src/game/Log.cpp index 8a8319e..d32e0b6 100644 --- a/src/game/Log.cpp +++ b/src/game/Log.cpp @@ -1,16 +1,38 @@ #include "Log.h" +#include "bx/handlealloc.h" +#include "bx/hash.h" #include +#include + namespace { - char LineBuffer[1024]{0}; + char LineBuffer[1024]{0}; + char OutBuffer[1024]{0}; + bx::HandleHashMapT<1024> OnceMap; +} // namespace + +void Log(ELogType logType, const char* file, uint32_t line, const char* format, ...) +{ + va_list args; + va_start(args, format); + bx::snprintf(LineBuffer, sizeof(LineBuffer), "%s\n", format); + bx::vprintf(LineBuffer, args); + bx::vsnprintf(OutBuffer, sizeof(OutBuffer), LineBuffer, args); + va_end(args); + OutputDebugStringA(OutBuffer); } -void Log(const char *format, ...) +bool WasLogged(ELogType logType, const char* file, uint32_t line, const char* format) { - va_list args; - va_start(args, format); - bx::snprintf(LineBuffer, sizeof(LineBuffer), "%s\n", format); - bx::vprintf(LineBuffer, args); - va_end(args); + bx::HashCrc32 hasher; + hasher.begin(); + hasher.add(file); + hasher.add(line); + hasher.add(logType); + hasher.add(format); + uint32_t hash = hasher.end(); + if (OnceMap.find(hash) != bx::kInvalidHandle) return true; + OnceMap.insert(hash, {}); + return false; } diff --git a/src/game/Log.h b/src/game/Log.h index 4d56bc5..0c7332b 100644 --- a/src/game/Log.h +++ b/src/game/Log.h @@ -1,3 +1,31 @@ #pragma once +#include -void Log(const char *format, ...); +#define LOG(fmt, ...) Log(ELogType::Log, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define LOG_WARN(fmt, ...) Log(ELogType::Warn, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define LOG_ERROR(fmt, ...) Log(ELogType::Error, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define LOG_ONCE(fmt, ...) \ + if (!WasLogged(ELogType::Log, __FILE__, __LINE__, fmt)) \ + { \ + Log(ELogType::Log, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \ + } +#define WARN_ONCE(fmt, ...) \ + if (!WasLogged(ELogType::Warn, __FILE__, __LINE__, fmt)) \ + { \ + Log(ELogType::Warn, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \ + } +#define ERROR_ONCE(fmt, ...) \ + if (!WasLogged(ELogType::Error, __FILE__, __LINE__, fmt)) \ + { \ + Log(ELogType::Error, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \ + } + +enum class ELogType +{ + Log, + Warn, + Error, +}; + +void Log(ELogType logType, const char* file, uint32_t line, const char* format, ...); +bool WasLogged(ELogType logType, const char* file, uint32_t line, const char* format); diff --git a/src/game/Mesh.cpp b/src/game/Mesh.cpp index 40fd445..551be21 100644 --- a/src/game/Mesh.cpp +++ b/src/game/Mesh.cpp @@ -39,11 +39,16 @@ namespace Game loadSuccess = loader.LoadASCIIFromFile(&model, &err, &warn, path); } - if (!warn.empty()) Log("WARN: %s", warn.c_str()); - if (!err.empty()) Log("ERR: %s", err.c_str()); + if (!warn.empty()) LOG_WARN("WARN: %s", warn.c_str()); + if (!err.empty()) LOG_ERROR("ERR: %s", err.c_str()); if (!loadSuccess) { - Log("Model load failed!"); + LOG_ERROR("Model load failed!"); + return false; + } + if (model.meshes.empty() || model.meshes[0].primitives.empty()) + { + LOG_ERROR("Model is empty!"); return false; } @@ -93,7 +98,7 @@ namespace Game bx::DirectoryReader reader{}; if (!reader.open("models", &err) || !err.isOk()) { - Log("Failed to read models dir: %s", err.getMessage()); + LOG_ERROR("Failed to read models dir: %s", err.getMessage()); } bx::FileInfo info; int32_t modelFilePathCount = 0; @@ -105,7 +110,7 @@ namespace Game if (res == 0) break; // EOF if (res != sizeof(info)) { - Log("Dir iter error: %s", err.getMessage()); + LOG_ERROR("Dir iter error: %s", err.getMessage()); break; } const bx::StringView ext = info.filePath.getExt(); @@ -115,7 +120,7 @@ namespace Game { if (modelFilePathCount >= GameRendering::MaxModels) { - Log("Model limit reached!"); + LOG_ERROR("Model limit reached!"); break; } modelFilePaths[modelFilePathCount] = info.filePath; @@ -123,7 +128,7 @@ namespace Game modelFilePathCount++; } } - Log("Found %u models!", modelFilePathCount); + LOG("Found %u models!", modelFilePathCount); int32_t writeI = 0; for (int32_t i = 0; i < modelFilePathCount; ++i) @@ -138,7 +143,7 @@ namespace Game } else { - Log("Failed to load model: %s", fullPath.getCPtr()); + LOG_ERROR("Failed to load model: %s", fullPath.getCPtr()); } } outCount = writeI; diff --git a/src/game/Puzzle.cpp b/src/game/Puzzle.cpp index 5370dc3..371f9a7 100644 --- a/src/game/Puzzle.cpp +++ b/src/game/Puzzle.cpp @@ -22,7 +22,7 @@ namespace Puzzle void StaticPuzzleData::Setup() { StaticDataInstance = this; - Log("Setting up static puzzle data"); + LOG("Setting up static puzzle data"); for (int32_t i = 0; i < BX_COUNTOF(Cards); ++i) { Cards[i].ModelHandle = Game::GameRendering::Get().GetModelHandleFromPath("models/w straight.glb"); diff --git a/src/game/Setup.cpp b/src/game/Setup.cpp index 40e4542..97e0a67 100644 --- a/src/game/Setup.cpp +++ b/src/game/Setup.cpp @@ -22,27 +22,27 @@ namespace Game void Setup(SharedData& shared) { - Log("Game Setup Start!"); + LOG("Game Setup Start!"); if (shared.Game.PermanentStorage == nullptr) { - Log("Game memory not initialized!!"); + LOG_ERROR("Game memory not initialized!!"); return; } if (shared.Game.EntityStorage == nullptr) { - Log("Entity memory not initialized!"); + LOG_ERROR("Entity memory not initialized!"); return; } if (shared.Game.PermanentStorageSize < sizeof(GameInstance)) { - Log("Game memory too small! %u < %u", shared.Game.PermanentStorageSize, sizeof(GameInstance)); + LOG_ERROR("Game memory too small! %u < %u", shared.Game.PermanentStorageSize, sizeof(GameInstance)); return; } GameInstance& instance = *reinterpret_cast(shared.Game.PermanentStorage); if (sizeof(GameInstance) != instance.Size) { - Log("Game instance size changed, resetting!"); + LOG_ERROR("Game instance size changed, resetting!"); instance = {}; } instance.UsedScratchAmount = 0; @@ -81,7 +81,7 @@ namespace Game void Shutdown() { - Log("Shutdown"); + LOG("Shutdown"); SetupInstance.Rendering.Shutdown(); } } // namespace Game diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index fe50f69..5101198 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -96,12 +96,12 @@ namespace Game bx::strCat(buffer, sizeof(buffer), FILENAME); bx::strCat(buffer, sizeof(buffer), ".bin"); - Log("Loading shader at %s", buffer); + LOG("Loading shader at %s", buffer); const bgfx::Memory* mem = loadFile(buffer, true, 3); if (mem == nullptr) { - Log("Failed to load shader %s", FILENAME); + LOG_WARN("Failed to load shader %s", FILENAME); return {}; } return bgfx::createShader(mem); @@ -120,13 +120,13 @@ namespace Game const bgfx::Memory* data = loadFile(_filePath.getCPtr()); if (data == nullptr) { - Log("Failed to find image %s", _filePath.getCPtr()); + LOG_WARN("Failed to find image %s", _filePath.getCPtr()); return handle; } bimg::ImageContainer imageContainer; if (!bimg::imageParse(imageContainer, data->data, data->size, &err)) { - Log("Failed to load image %s", _filePath.getCPtr()); + LOG_WARN("Failed to load image %s", _filePath.getCPtr()); return handle; } if (NULL != _orientation) @@ -223,7 +223,7 @@ namespace Game if (BX_COUNTOF(DitherData::DitherTex) < texPixelCount) { - Log("Too many pixels: %llu", texPixelCount); + LOG_ERROR("Too many pixels: %llu", texPixelCount); return; } @@ -327,8 +327,8 @@ namespace Game void GameRendering::Setup() { - Log("--- RENDERING STARTUP ---"); - if (Instance != nullptr) Log("Warning, old rendering wasn't destroyed!"); + LOG("--- RENDERING STARTUP ---"); + if (Instance != nullptr) LOG_WARN("old rendering wasn't destroyed!"); Instance = this; SharedData& shared = GetShared(); @@ -345,15 +345,15 @@ namespace Game LastWidth = shared.Window.WindowWidth; LastHeight = shared.Window.WindowHeight; - Log("%i by %i", init.resolution.width, init.resolution.height); + LOG("%i by %i", init.resolution.width, init.resolution.height); if (!bgfx::init(init)) { - Log("BGFX setup failed!"); + LOG_ERROR("BGFX setup failed!"); } else { - Log("BGFX setup succeded!"); + LOG("BGFX setup succeded!"); } // bgfx::setDebug(BGFX_DEBUG_TEXT); bgfx::setViewClear(MainViewID, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x3399FFff, 1.0f, 0); @@ -371,7 +371,7 @@ namespace Game if (!ImGui_ImplSDL3_InitForOther(shared.Window.SDLWindow)) { - Log("Failed to set up imgui implementation!"); + LOG_ERROR("Failed to set up imgui implementation!"); return; } @@ -442,7 +442,7 @@ namespace Game } else { - Log("Failed to load shader!"); + LOG_WARN("Failed to load shader!"); LastShaderLoadTime = -1.0f; } } @@ -532,7 +532,7 @@ namespace Game void GameRendering::Shutdown() { - Log("--- RENDERING_SHUTDOWN ---"); + LOG("--- RENDERING_SHUTDOWN ---"); ImGui::SaveIniSettingsToDisk("imgui.ini"); const char* iniData = ImGui::SaveIniSettingsToMemory(reinterpret_cast(&GetInstance().ImguiIniSize)); assert(GetInstance().ImguiIniSize <= BX_COUNTOF(GameInstance::ImguiIni)); diff --git a/src/models/plane.glb b/src/models/plane.glb new file mode 100644 index 0000000..d3814f8 --- /dev/null +++ b/src/models/plane.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e47d024c30089d49d6836a129467c800065dcc3b392362c4a5688967c65d1919 +size 132