From cac2ef3330d1c53fee745fd7261728790055191f Mon Sep 17 00:00:00 2001 From: Till W Date: Sun, 25 May 2025 13:07:52 +0200 Subject: [PATCH] new puzzle tool --- src/game/Instance.h | 4 +- src/game/Puzzle.cpp | 156 ++++++++++++++++++-------------- src/game/Puzzle.h | 4 + src/game/Tools.cpp | 18 ++++ src/game/UI.cpp | 23 ++++- src/game/data/puzzles/0.pzl | 4 +- src/game/data/puzzles/1.pzl | 4 +- src/game/data/puzzles/2.pzl | 4 +- src/game/data/static/puzzle.dat | Bin 19041 -> 19084 bytes src/game/mini.def | 9 +- src/gen/Generated.cpp | 120 +++++++++++++++++------- src/gen/Generated.h | 51 +++++++++-- 12 files changed, 275 insertions(+), 122 deletions(-) diff --git a/src/game/Instance.h b/src/game/Instance.h index 3c1316d..6e775c9 100644 --- a/src/game/Instance.h +++ b/src/game/Instance.h @@ -52,10 +52,10 @@ namespace Game struct InstanceDebugData { - uint16_t SelectedDebugLevel = UINT16_MAX; + static constexpr uint32_t MaxAssets = 128; + uint16_t SelectedDebugLevel = 0; uint64_t ImguiIniSize = 0; char ImguiIni[4096]{0}; - static constexpr uint32_t MaxAssets = 128; uint32_t AssetCount = 0; Gen::AssetHandle AssetHandles[MaxAssets]{0}; char AssetHandlePaths[MaxAssets][128]; diff --git a/src/game/Puzzle.cpp b/src/game/Puzzle.cpp index b1f3fd0..9655807 100644 --- a/src/game/Puzzle.cpp +++ b/src/game/Puzzle.cpp @@ -22,6 +22,7 @@ namespace StaticPuzzleData StaticData; StaticPuzzleCard InvalidCard; + PlacedPuzzleCard InvalidPlacedCard; } // namespace namespace Puzzle @@ -104,6 +105,24 @@ namespace Puzzle return puz.BackgroundTiles[pos.Y * Puzzle::Config::MaxPuzzleSizeTiles + pos.X]; } + PuzzleElementType::Enum GetInitialNodeAt(const PuzzleData& puz, PuzPos pos) + { + assert(pos.X < Puzzle::Config::MaxPuzzleSizeTiles && pos.Y < Puzzle::Config::MaxPuzzleSizeTiles && pos.X >= 0 && + pos.Y >= 0); + int32_t cardIdxX = pos.X / Puzzle::Config::CardSize; + int32_t cardIdxY = pos.Y / Puzzle::Config::CardSize; + auto& card = puz.InitialPlacedCards[cardIdxY * Puzzle::Config::MaxPuzzleSizeCards + cardIdxX]; + int32_t offsetX = pos.X - (cardIdxX * Config::CardSize); + int32_t offsetY = pos.Y - (cardIdxY * Config::CardSize); + if (offsetX >= 0 && offsetX < Puzzle::Config::CardSize && offsetY >= 0 && offsetY < Puzzle::Config::CardSize && + IsValid(card.RefCard)) + { + PuzzleElementType::Enum cardVal = GetCardNodeAt(GetCard(card.RefCard), card.Rotation, offsetX, offsetY); + if (cardVal != PuzzleElementType::None) return cardVal; + } + return puz.BackgroundTiles[pos.Y * Puzzle::Config::MaxPuzzleSizeTiles + pos.X]; + } + PuzzleElementType::Enum GetCardNodeAt(const StaticPuzzleCard& card, uint8_t rotation, int8_t x, int8_t y) { assert(x >= 0 && x < Puzzle::Config::CardSize); @@ -288,12 +307,32 @@ namespace Puzzle bx::snprintf(buf, bufSize, "%s/%u.pzl", Puzzle::PuzzleFileDir, puzID); } + PlacedPuzzleCard& GetCardAt(PuzzleData& obj, PuzPos pos) + { + if (pos.X < 0 || pos.X >= Config::MaxPuzzleSizeCards || pos.Y < 0 || pos.Y >= Config::MaxPuzzleSizeCards) + { + LOG_ERROR("Invalid card access at %i %i!!", pos.X, pos.Y); + return InvalidPlacedCard; + } + return obj.PlacedCards[pos.Y * Config::MaxPuzzleSizeCards + pos.X]; + } + + PlacedPuzzleCard& GetInitialCardAt(PuzzleData& obj, PuzPos pos) + { + if (pos.X < 0 || pos.X >= Config::MaxPuzzleSizeCards || pos.Y < 0 || pos.Y >= Config::MaxPuzzleSizeCards) + { + LOG_ERROR("Invalid card access at %i %i!!", pos.X, pos.Y); + return InvalidPlacedCard; + } + return obj.InitialPlacedCards[pos.Y * Config::MaxPuzzleSizeCards + pos.X]; + } + bool ReturnPlacedCard(PuzzleData& obj, PuzPos targetPos) { - auto& placedCard = obj.PlacedCards[targetPos.Y * Config::MaxPuzzleSizeCards + targetPos.X]; + PlacedPuzzleCard& placedCard = GetCardAt(obj, targetPos); if (IsValid(placedCard.RefCard)) { - if (placedCard.IsLocked) + if (GetFlag(placedCard.Flags, PlacedPuzzleCardFlags::Locked)) { LOG_WARN("Card at %i %i is locked!", targetPos.X, targetPos.Y); return false; @@ -330,9 +369,9 @@ namespace Puzzle auto& draggedCard = obj.AvailableCards[availIdx]; draggedCard.UsedCount++; - auto& placedCard = obj.PlacedCards[targetPos.Y * Config::MaxPuzzleSizeCards + targetPos.X]; + PlacedPuzzleCard& placedCard = GetCardAt(obj, targetPos); placedCard.RefCard = draggedCard.RefCard; - placedCard.IsLocked = false; + placedCard.Flags = (PlacedPuzzleCardFlags::Enum)ClearFlags(placedCard.Flags, PlacedPuzzleCardFlags::Locked); placedCard.Position = targetPos; placedCard.Rotation = rotation; return true; @@ -340,9 +379,6 @@ namespace Puzzle bool RenderDebugUI(PuzzleData& obj) { - bool dataChanged = false; - uint8_t debugRot = Game::GetInstance().DebugData.DebugCardRotation; - bool isVisible = true; if (ImGui::Begin("Puzzle", &isVisible)) { @@ -356,17 +392,34 @@ namespace Puzzle return false; } ImGui::SameLine(); - if (ImGui::Button("Reload")) + if (ImGui::Button("Reset")) { - // TODO + ResetPuzzle(obj); } + ImGui::SameLine(); + if (ImGui::Button("Save")) + { + ResetPuzzle(obj); + char path[128]{0}; + WritePuzzleFilePath(path, sizeof(path), obj.ID); + Serializer ser; + if (ser.Init(path, "PZZL") && ser.WriteT(obj)) + { + LOG("Saved to %s", path); + } + else + { + LOG_ERROR("Failed to save to %s", path); + } + ser.Finish(); + } + int32_t val = obj.ID; if (ImGui::InputInt("ID", &val)) { obj.ID = val; - dataChanged = true; } - dataChanged = ImGui::InputText("Name", obj.PuzzleName, sizeof(obj.PuzzleName)) || dataChanged; + ImGui::InputText("Name", obj.PuzzleName, sizeof(obj.PuzzleName)); int32_t W = obj.WidthTiles; int32_t H = obj.HeightTiles; @@ -375,7 +428,6 @@ namespace Puzzle if (ImGui::DragInt("", &W, 0.3f, 0, Puzzle::Config::MaxPuzzleSizeTiles)) { obj.WidthTiles = uint8_t(W); - dataChanged = true; } ImGui::PopID(); ImGui::SameLine(); @@ -386,7 +438,6 @@ namespace Puzzle if (ImGui::DragInt("", &H, 0.3f, 0, Puzzle::Config::MaxPuzzleSizeTiles)) { obj.HeightTiles = uint8_t(H); - dataChanged = true; } ImGui::PopID(); @@ -401,7 +452,7 @@ namespace Puzzle { ImGui::PushID(x); PuzPos nodePos = {int8_t(x), int8_t(y)}; - auto node = GetNodeAt(obj, nodePos); + auto node = GetInitialNodeAt(obj, nodePos); if (node == PuzzleElementType::WaterGoal) { obj.GoalPositions[obj.GoalPositionCount] = nodePos; @@ -414,36 +465,29 @@ namespace Puzzle ImGui::SetCursorScreenPos(pos); if (x % Puzzle::Config::CardSize == 0 && y % Puzzle::Config::CardSize == 0) { - int32_t cardX = x / Config::CardSize; - int32_t cardY = y / Config::CardSize; - PuzPos cardPos = {int8_t(cardX), int8_t(cardY)}; - auto& placedCard = obj.PlacedCards[cardY * Config::MaxPuzzleSizeCards + cardX]; + PuzPos cardPos = {int8_t(x / Config::CardSize), int8_t(y / Config::CardSize)}; + PlacedPuzzleCard& placedCard = GetInitialCardAt(obj, cardPos); + bool isLocked = GetFlag(placedCard.Flags, PlacedPuzzleCardFlags::Locked); + ImGui::InvisibleButton("bn", {UIPuzBoxSize * 2, UIPuzBoxSize * 2}); if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { placedCard.Rotation += 1; if (placedCard.Rotation >= 4) placedCard.Rotation = 0; - dataChanged = true; } - if (ImGui::IsItemClicked(ImGuiMouseButton_Middle) && IsValid(placedCard.RefCard)) + if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) { - if (placedCard.IsLocked) + if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) { - placedCard.IsLocked = false; - placedCard.RefCard = {}; - dataChanged = true; + placedCard = {}; } else { - if (!ReturnPlacedCard(obj, cardPos)) - { - placedCard.IsLocked = false; - placedCard.RefCard = {}; - dataChanged = true; - } + placedCard.Flags = + (PlacedPuzzleCardFlags::Enum)(placedCard.Flags ^ PlacedPuzzleCardFlags::Locked); } } - if (!placedCard.IsLocked && IsValid(placedCard.RefCard)) + if (!isLocked && IsValid(placedCard.RefCard)) { ImVec2 s = {puzCursorStart.x + x * UIPuzBoxSize, puzCursorStart.y + y * UIPuzBoxSize}; drawList.AddRectFilled(s, @@ -458,17 +502,10 @@ namespace Puzzle uint32_t CardIdx = *reinterpret_cast(payload->Data); placedCard = {}; placedCard.RefCard = {(uint16_t)CardIdx}; - placedCard.Rotation = debugRot; + placedCard.Rotation = 0; placedCard.Position = cardPos; - placedCard.IsLocked = true; - dataChanged = true; - } - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("availcard", 0)) - { - DragAvailableCardTo(obj, - cardPos, - *(int32_t*)payload->Data, - Game::GetInstance().DebugData.DebugCardRotation); + placedCard.Flags = (PlacedPuzzleCardFlags::Enum)SetFlags(placedCard.Flags, + PlacedPuzzleCardFlags::Locked); } ImGui::EndDragDropTarget(); } @@ -534,7 +571,6 @@ namespace Puzzle obj.AvailableCardCount++; } } - dataChanged = true; } ImGui::EndDragDropTarget(); } @@ -547,14 +583,8 @@ namespace Puzzle ImGui::SetCursorScreenPos(localPos); ImGui::PushID(i); auto& card = obj.AvailableCards[i]; - DrawCard(GetCard(card.RefCard), debugRot, ImGui::GetCursorScreenPos()); + DrawCard(GetCard(card.RefCard), 0, ImGui::GetCursorScreenPos()); int displayCount = card.MaxAvailableCount - card.UsedCount; - if (displayCount > 0 && ImGui::BeginDragDropSource()) - { - ImGui::SetDragDropPayload("availcard", &i, sizeof(i)); - DrawCard(GetCard(card.RefCard), debugRot, ImGui::GetCursorScreenPos()); - ImGui::EndDragDropSource(); - } ImGui::SetCursorScreenPos({localPos.x, localPos.y + 55.0f}); ImGui::SetNextItemWidth(35); @@ -563,7 +593,6 @@ namespace Puzzle { int diff = displayCount - (card.MaxAvailableCount - card.UsedCount); card.MaxAvailableCount = bx::max(0, card.MaxAvailableCount + diff); - dataChanged = true; } ImGui::PopID(); ImGui::SameLine(0, 3); @@ -582,22 +611,17 @@ namespace Puzzle } ImGui::End(); - if (dataChanged) - { - char path[128]{0}; - WritePuzzleFilePath(path, sizeof(path), obj.ID); - Serializer ser; - if (ser.Init(path, "PZZL") && ser.WriteT(obj)) - { - LOG("Saved to %s", path); - } - else - { - LOG_ERROR("Failed to save to %s", path); - } - ser.Finish(); - } - return isVisible; } + void ResetPuzzle(PuzzleData& puz) + { + for (int32_t i = 0; i < puz.AvailableCardCount; ++i) + { + puz.AvailableCards[i].UsedCount = 0; + } + for (int32_t i = 0; i < BX_COUNTOF(puz.PlacedCards); ++i) + { + puz.PlacedCards[i] = puz.InitialPlacedCards[i]; + } + } } // namespace Puzzle diff --git a/src/game/Puzzle.h b/src/game/Puzzle.h index 08bc632..8177ff5 100644 --- a/src/game/Puzzle.h +++ b/src/game/Puzzle.h @@ -35,15 +35,19 @@ namespace Puzzle bool IsValid(StaticPuzzleCardHandle h); uint8_t GetRemainingCount(const PuzzleCardStack& stack); PuzzleElementType::Enum GetNodeAt(const PuzzleData& puz, PuzPos pos); + PuzzleElementType::Enum GetInitialNodeAt(const PuzzleData& puz, PuzPos pos); PuzzleElementType::Enum GetCardNodeAt(const StaticPuzzleCard& card, uint8_t rotation, int8_t x, int8_t y); PuzzleElementType::Enum& EditCardNodeAt(StaticPuzzleCard& card, uint8_t rotation, int8_t x, int8_t y); void DrawCard(const StaticPuzzleCard& card, uint8_t rotation, ImVec2 pos); void RotateCard(PlacedPuzzleCard& card); + PlacedPuzzleCard& GetCardAt(PuzzleData& obj, PuzPos pos); + PlacedPuzzleCard& GetInitialCardAt(PuzzleData& obj, PuzPos pos); // TODO: targetPos is of type CardPos bool ReturnPlacedCard(PuzzleData& obj, PuzPos targetPos); // TODO: targetPos is of type CardPos bool DragAvailableCardTo(PuzzleData& obj, PuzPos targetPos, int32_t availIdx, uint8_t rotation); + void ResetPuzzle(PuzzleData& puz); struct PuzzleSolver { diff --git a/src/game/Tools.cpp b/src/game/Tools.cpp index 6bf87ee..2711990 100644 --- a/src/game/Tools.cpp +++ b/src/game/Tools.cpp @@ -483,6 +483,7 @@ namespace Tools { ImGui::Checkbox("Arenas", &debug.ShowArenaUsage); ImGui::Checkbox("ImGui Demo", &debug.ShowImguiDemo); + ImGui::SliderFloat("Font Scale", &ImGui::GetIO().FontGlobalScale, 0.5f, 4.0f); } ImGui::End(); @@ -496,6 +497,23 @@ namespace Tools } ImGui::End(); } + + if (ImGui::Begin("Entities")) + { + ImGui::Text("UIQuads"); + for (uint16_t i = 0; i < level.UIQuads.Count; ++i) + { + ImGui::PushID(i); + auto& quad = level.UIQuads.Get({i}); + ImGui::Checkbox("Visible", &quad.EData.Visible); + TextureDropdown(quad.EData.TextureHandle); + MaterialDropdown(quad.EData.MaterialHandle); + ImGui::DragFloat3("Pos", &quad.EData.Transform.Position.x); + ImGui::DragFloat3("UI Pos", &quad.UIPos.x); + ImGui::PopID(); + } + } + ImGui::End(); } if (debug.ShowStats) { diff --git a/src/game/UI.cpp b/src/game/UI.cpp index 1fc09e6..7aa0379 100644 --- a/src/game/UI.cpp +++ b/src/game/UI.cpp @@ -6,6 +6,7 @@ #include "Instance.h" #include "Level.h" +#include "Puzzle.h" #include "bx/math.h" using namespace Gen; @@ -177,11 +178,22 @@ namespace Game } } + Vec3 CalcBoardOffset(const Gen::PuzzleData& puzData) + { + return Vec3{ + (float)(puzData.WidthTiles) / (2.0f * Puzzle::Config::CardSize), + (float)(puzData.HeightTiles) / (2.0f * Puzzle::Config::CardSize), + 0.0f, + } * + 2.0f * WorldPuzzleUI::UICardScale * WorldPuzzleUI::UICardScale; + } + void WorldPuzzleUI::UpdateBoardCards(Gen::PuzzleData& Data) { auto& level = GetInstance().GameLevel; auto& staticCards = Puzzle::GetStaticPuzzleData().Cards; Vec3 quadPlaneIntersectPos; + Vec3 boardOffset = CalcBoardOffset(Data); for (int8_t y = 0; y < Data.HeightTiles / Puzzle::Config::CardSize; ++y) { @@ -191,22 +203,24 @@ namespace Game int32_t cardIdx = y * Puzzle::Config::MaxPuzzleSizeCards + x; PlacedPuzzleCard& card = Data.PlacedCards[cardIdx]; bool isValid = Puzzle::IsValid(card.RefCard); + bool isLocked = GetFlag(card.Flags, PlacedPuzzleCardFlags::Locked); auto& quad = level.UIQuads.Get(UIPlacedCards[cardIdx]); quad.UIPos = Vec3{(float)card.Position.X, (float)card.Position.Y, 0.0f} * UICardOffset * UICardScale; + quad.UIPos -= boardOffset; quad.UIRot = card.Rotation * bx::kPi * 0.5f; UpdateQuad(level.UIQuads, UIPlacedCards[cardIdx]); quad.EData.Visible = isValid; quad.EData.TextureHandle = isValid ? staticCards[card.RefCard.Idx].BoardTextureHandle : Gen::TextureHandle{}; - quad.EData.DotColor = card.IsLocked ? Puzzle::GetStaticPuzzleData().Visuals.DisabledCardTint - : Vec4{1.0f, 1.0f, 1.0f, 1.0f}; + quad.EData.DotColor = + isLocked ? Puzzle::GetStaticPuzzleData().Visuals.DisabledCardTint : Vec4{1.0f, 1.0f, 1.0f, 1.0f}; quad.EData.Transform.Scale = {UICardScale, UICardScale, UICardScale}; if (isValid && IsQuadHovered(quad.EData.Transform, StaticData.MousePosWorld, quadPlaneIntersectPos)) { - if (!card.IsLocked && DraggedCard.X == -1 && DraggedAvailableCardIdx == UINT16_MAX) + if (!isLocked && DraggedCard.X == -1 && DraggedAvailableCardIdx == UINT16_MAX) { if (GetMouseButtonPressedNow(MouseButton::Left)) { @@ -318,8 +332,7 @@ namespace Game if (GetMouseButtonPressedNow(MouseButton::Left) && IsQuadHovered(resetQuad.EData.Transform, StaticData.MousePosWorld, hoverPosWorld)) { - LOG_WARN("TODO!"); - // TODO + Puzzle::ResetPuzzle(Data); } UpdateAvailableCards(Data); diff --git a/src/game/data/puzzles/0.pzl b/src/game/data/puzzles/0.pzl index cc24f96..88b8829 100644 --- a/src/game/data/puzzles/0.pzl +++ b/src/game/data/puzzles/0.pzl @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd485b73222de5ad4237a1307f9bb210c691253d0550e583a41b7512fae2af80 -size 10404 +oid sha256:8ecd11f17c4239e26afe510f994a9957182a26bd7f8b007dc11617973478ec3a +size 11416 diff --git a/src/game/data/puzzles/1.pzl b/src/game/data/puzzles/1.pzl index 4b0f284..34dfabd 100644 --- a/src/game/data/puzzles/1.pzl +++ b/src/game/data/puzzles/1.pzl @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d430919f99b555b5ab597eb6d0ba2ac2b64d43fcd81d78f225cdee35db0168c4 -size 10300 +oid sha256:0813471df56261f6f5e29e676efdddb939550f2f201e7aab48c1558d1173e86a +size 11416 diff --git a/src/game/data/puzzles/2.pzl b/src/game/data/puzzles/2.pzl index 1cd7844..86173c8 100644 --- a/src/game/data/puzzles/2.pzl +++ b/src/game/data/puzzles/2.pzl @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b14fed8c874d0ccdf49ac3dae26d4309a28b04d7f48fd1f2149e70802ac03e63 -size 10300 +oid sha256:def01a713150f726f958bcbde5d2a975f5c3f0ad1efab5d5702622a42c8f4598 +size 11416 diff --git a/src/game/data/static/puzzle.dat b/src/game/data/static/puzzle.dat index f971f4939e27935803f5d52e91269b56d4ef6dec..f7c6fc3c8aef5b665eeabe95e21e88f0aecf502d 100644 GIT binary patch delta 65 zcmaDjg|TNU;{-9rzK!Cw+>9)nr*i)lWp&F*OfQ~1OVNkjGcU6wGcjlKZN(J=e)%QA W`8j2&DIuv9C8b5Fo6D76sRIBR78w`- delta 43 zcmeB~%J^^!;{-9r8vHr*i)l(objBasePtr + WriteDestinations[j]); + auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); isOk = Load(fieldPtr, 1, serializer) && isOk; continue; } @@ -2105,6 +2142,7 @@ namespace Gen isOk = Save(&obj[i].AvailableCardCount, 1, serializer) && isOk; isOk = Save(obj[i].AvailableCards, 16, serializer) && isOk; isOk = Save(obj[i].PlacedCards, 256, serializer) && isOk; + isOk = Save(obj[i].InitialPlacedCards, 256, serializer) && isOk; isOk = Save(obj[i].BackgroundTiles, 1024, serializer) && isOk; isOk = Save(&obj[i].GoalPositionCount, 1, serializer) && isOk; isOk = Save(obj[i].GoalPositions, 16, serializer) && isOk; @@ -2131,6 +2169,7 @@ namespace Gen isOk = Load(&obj[i].AvailableCardCount, 1, serializer) && isOk; isOk = Load(obj[i].AvailableCards, 16, serializer) && isOk; isOk = Load(obj[i].PlacedCards, 256, serializer) && isOk; + isOk = Load(obj[i].InitialPlacedCards, 256, serializer) && isOk; isOk = Load(obj[i].BackgroundTiles, 1024, serializer) && isOk; isOk = Load(&obj[i].GoalPositionCount, 1, serializer) && isOk; isOk = Load(obj[i].GoalPositions, 16, serializer) && isOk; @@ -2141,6 +2180,7 @@ namespace Gen } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. + *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { @@ -2161,23 +2201,23 @@ namespace Gen { const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[i].Offset], matchedDef.MemberNameIndices[i].Size}; const char* memberTypeName = serializer.TypeBuf.Defs[matchedDef.ChildIndices[i]].Name; - if (bx::strCmp(memberName, "ID") == 0 && bx::strCmp(memberTypeName, "uint16_t") == 0) + if (bx::strCmp(memberName, "ID") == 0 && bx::strCmp(memberTypeName, "u16") == 0) { WriteDestinations[i] = offsetof(PuzzleData, ID); } - if (bx::strCmp(memberName, "PuzzleName") == 0 && bx::strCmp(memberTypeName, "char") == 0) + if (bx::strCmp(memberName, "PuzzleName") == 0 && bx::strCmp(memberTypeName, "str") == 0) { WriteDestinations[i] = offsetof(PuzzleData, PuzzleName); } - if (bx::strCmp(memberName, "WidthTiles") == 0 && bx::strCmp(memberTypeName, "uint8_t") == 0) + if (bx::strCmp(memberName, "WidthTiles") == 0 && bx::strCmp(memberTypeName, "u8") == 0) { WriteDestinations[i] = offsetof(PuzzleData, WidthTiles); } - if (bx::strCmp(memberName, "HeightTiles") == 0 && bx::strCmp(memberTypeName, "uint8_t") == 0) + if (bx::strCmp(memberName, "HeightTiles") == 0 && bx::strCmp(memberTypeName, "u8") == 0) { WriteDestinations[i] = offsetof(PuzzleData, HeightTiles); } - if (bx::strCmp(memberName, "AvailableCardCount") == 0 && bx::strCmp(memberTypeName, "uint32_t") == 0) + if (bx::strCmp(memberName, "AvailableCardCount") == 0 && bx::strCmp(memberTypeName, "u32") == 0) { WriteDestinations[i] = offsetof(PuzzleData, AvailableCardCount); } @@ -2189,11 +2229,15 @@ namespace Gen { WriteDestinations[i] = offsetof(PuzzleData, PlacedCards); } + if (bx::strCmp(memberName, "InitialPlacedCards") == 0 && bx::strCmp(memberTypeName, "PlacedPuzzleCard") == 0) + { + WriteDestinations[i] = offsetof(PuzzleData, InitialPlacedCards); + } if (bx::strCmp(memberName, "BackgroundTiles") == 0 && bx::strCmp(memberTypeName, "PuzzleElementType") == 0) { WriteDestinations[i] = offsetof(PuzzleData, BackgroundTiles); } - if (bx::strCmp(memberName, "GoalPositionCount") == 0 && bx::strCmp(memberTypeName, "uint32_t") == 0) + if (bx::strCmp(memberName, "GoalPositionCount") == 0 && bx::strCmp(memberTypeName, "u32") == 0) { WriteDestinations[i] = offsetof(PuzzleData, GoalPositionCount); } @@ -2263,6 +2307,12 @@ namespace Gen isOk = Load(fieldPtr, 256, serializer) && isOk; continue; } + if (bx::strCmp(memberName, "InitialPlacedCards") == 0) + { + auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); + isOk = Load(fieldPtr, 256, serializer) && isOk; + continue; + } if (bx::strCmp(memberName, "BackgroundTiles") == 0) { auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); @@ -2329,6 +2379,7 @@ namespace Gen } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. + *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { @@ -2373,7 +2424,7 @@ namespace Gen { WriteDestinations[i] = offsetof(SavedEntityRenderData, Model); } - if (bx::strCmp(memberName, "Visible") == 0 && bx::strCmp(memberTypeName, "bool") == 0) + if (bx::strCmp(memberName, "Visible") == 0 && bx::strCmp(memberTypeName, "b") == 0) { WriteDestinations[i] = offsetof(SavedEntityRenderData, Visible); } @@ -2483,6 +2534,7 @@ namespace Gen } // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. + *obj = {}; int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); if (nameMatchIdx < 0) { diff --git a/src/gen/Generated.h b/src/gen/Generated.h index f4bff64..f2e9d3d 100644 --- a/src/gen/Generated.h +++ b/src/gen/Generated.h @@ -54,10 +54,41 @@ namespace Gen "#", }; }; - struct EMaterial + struct PlacedPuzzleCardFlags { static constexpr uint16_t TypeIdx = 33; static constexpr int32_t EntryCount = 2; + enum Enum : uint8_t + { + None = 0, + Locked = 1 << 0, + }; + static constexpr char EntryNames[EntryCount][64] + { + "None", + "Locked", + }; + }; + inline PlacedPuzzleCardFlags::Enum operator| (const PlacedPuzzleCardFlags::Enum& a, const PlacedPuzzleCardFlags::Enum& b) + { + return a | b; + } + inline PlacedPuzzleCardFlags::Enum operator& (const PlacedPuzzleCardFlags::Enum& a, const PlacedPuzzleCardFlags::Enum& b) + { + return a & b; + } + inline PlacedPuzzleCardFlags::Enum operator|= (PlacedPuzzleCardFlags::Enum& a, const PlacedPuzzleCardFlags::Enum& b) + { + return a |= b; + } + inline PlacedPuzzleCardFlags::Enum operator&= (PlacedPuzzleCardFlags::Enum& a, const PlacedPuzzleCardFlags::Enum& b) + { + return a &= b; + } + struct EMaterial + { + static constexpr uint16_t TypeIdx = 34; + static constexpr int32_t EntryCount = 2; enum Enum : int32_t { Default, @@ -192,7 +223,7 @@ namespace Gen StaticPuzzleCardHandle RefCard = {}; PuzPos Position = {}; uint8_t Rotation = {}; - bool IsLocked = {}; + PlacedPuzzleCardFlags::Enum Flags = {}; }; struct PuzzleData { @@ -204,6 +235,7 @@ namespace Gen uint32_t AvailableCardCount = {}; PuzzleCardStack AvailableCards[16] = {}; PlacedPuzzleCard PlacedCards[256] = {}; + PlacedPuzzleCard InitialPlacedCards[256] = {}; PuzzleElementType::Enum BackgroundTiles[1024] = {}; uint32_t GoalPositionCount = {}; PuzPos GoalPositions[16] = {}; @@ -230,6 +262,8 @@ namespace Gen }; bool Save(const PuzzleElementType::Enum* obj, uint32_t count, Serializer& serializer); bool Load(PuzzleElementType::Enum* obj, uint32_t count, Deserializer& serializer); + bool Save(const PlacedPuzzleCardFlags::Enum* obj, uint32_t count, Serializer& serializer); + bool Load(PlacedPuzzleCardFlags::Enum* obj, uint32_t count, Deserializer& serializer); bool Save(const EMaterial::Enum* obj, uint32_t count, Serializer& serializer); bool Load(EMaterial::Enum* obj, uint32_t count, Deserializer& serializer); bool Save(const int8_t* obj, uint32_t count, Serializer& serializer); @@ -319,7 +353,7 @@ namespace Gen struct MetadataTable { - TypeDef TypeDefinitions[34] + TypeDef TypeDefinitions[35] { TypeDef{sizeof(int8_t), 0, "i8", 0, {}, {}, {}}, TypeDef{sizeof(int16_t), 1, "i16", 0, {}, {}, {}}, @@ -349,14 +383,15 @@ namespace Gen TypeDef{sizeof(PuzzleVisualSettings), 2302077481, "PuzzleVisualSettings", 4, {14, 14, 13, 14}, {0, 0, 0, 0}, {{223, 13}, {236, 12}, {248, 4}, {252, 16}}}, TypeDef{sizeof(StaticPuzzleData), 2637647137, "StaticPuzzleData", 2, {23, 25}, {64, 0}, {{268, 5}, {273, 7}}}, TypeDef{sizeof(PuzzleCardStack), 53538532, "PuzzleCardStack", 3, {24, 4, 4}, {0, 0, 0}, {{280, 7}, {287, 17}, {304, 9}}}, - TypeDef{sizeof(PlacedPuzzleCard), 3555575973, "PlacedPuzzleCard", 4, {24, 21, 4, 8}, {0, 0, 0, 0}, {{313, 7}, {320, 8}, {328, 8}, {336, 8}}}, - TypeDef{sizeof(PuzzleData), 3349686056, "PuzzleData", 10, {5, 11, 4, 4, 6, 27, 28, 32, 6, 21}, {0, 64, 0, 0, 0, 16, 256, 1024, 0, 16}, {{344, 2}, {346, 10}, {356, 10}, {366, 11}, {377, 18}, {395, 14}, {409, 11}, {420, 15}, {435, 17}, {452, 13}}}, - TypeDef{sizeof(SavedEntityRenderData), 3172756855, "SavedEntityRenderData", 7, {14, 14, 17, 33, 20, 19, 8}, {0, 0, 0, 0, 0, 0, 0}, {{465, 9}, {474, 14}, {488, 2}, {490, 8}, {498, 7}, {505, 5}, {510, 7}}}, - TypeDef{sizeof(SavedPlayerConfig), 3685229621, "SavedPlayerConfig", 5, {30, 30, 20, 20, 30}, {0, 0, 0, 0, 0}, {{517, 26}, {543, 22}, {565, 28}, {593, 25}, {618, 21}}}, + TypeDef{sizeof(PlacedPuzzleCard), 838818025, "PlacedPuzzleCard", 4, {24, 21, 4, 33}, {0, 0, 0, 0}, {{313, 7}, {320, 8}, {328, 8}, {336, 5}}}, + TypeDef{sizeof(PuzzleData), 1562434765, "PuzzleData", 11, {5, 11, 4, 4, 6, 27, 28, 28, 32, 6, 21}, {0, 64, 0, 0, 0, 16, 256, 256, 1024, 0, 16}, {{341, 2}, {343, 10}, {353, 10}, {363, 11}, {374, 18}, {392, 14}, {406, 11}, {417, 18}, {435, 15}, {450, 17}, {467, 13}}}, + TypeDef{sizeof(SavedEntityRenderData), 3172756855, "SavedEntityRenderData", 7, {14, 14, 17, 34, 20, 19, 8}, {0, 0, 0, 0, 0, 0, 0}, {{480, 9}, {489, 14}, {503, 2}, {505, 8}, {513, 7}, {520, 5}, {525, 7}}}, + TypeDef{sizeof(SavedPlayerConfig), 3685229621, "SavedPlayerConfig", 5, {30, 30, 20, 20, 30}, {0, 0, 0, 0, 0}, {{532, 26}, {558, 22}, {580, 28}, {608, 25}, {633, 21}}}, TypeDef{sizeof(PuzzleElementType::Enum), 2983807453, "PuzzleElementType", 0, {}, {}, {}}, + TypeDef{sizeof(PlacedPuzzleCardFlags::Enum), 2983807453, "PlacedPuzzleCardFlags", 0, {}, {}, {}}, TypeDef{sizeof(EMaterial::Enum), 2024002654, "EMaterial", 0, {}, {}, {}}, }; - char MemberNameBuffer[64*64*64]{"xyxyzxyzwMMMMIPositionRotationScaleIdxModelIdxAssetTextureIdxAssetXYModelConnectionDirectionElementsBaseModelHandleNorthCoverHandleEastCoverHandleSouthCoverHandleWestCoverHandleSocketsModelTextureHandleBoardTextureHandleIdxTileBaseColorTileDotColorTestDisabledCardTintCardsVisualsRefCardMaxAvailableCountUsedCountRefCardPositionRotationIsLockedIDPuzzleNameWidthTilesHeightTilesAvailableCardCountAvailableCardsPlacedCardsBackgroundTilesGoalPositionCountGoalPositionsBaseColorHighlightColorTFMaterialTextureModelVisibleTabletBackgroundRenderDataTabletStatusRenderDataTabletStatusNotSolvedTextureTabletStatusSolvedTextureTabletResetRenderData"}; + char MemberNameBuffer[64*64*64]{"xyxyzxyzwMMMMIPositionRotationScaleIdxModelIdxAssetTextureIdxAssetXYModelConnectionDirectionElementsBaseModelHandleNorthCoverHandleEastCoverHandleSouthCoverHandleWestCoverHandleSocketsModelTextureHandleBoardTextureHandleIdxTileBaseColorTileDotColorTestDisabledCardTintCardsVisualsRefCardMaxAvailableCountUsedCountRefCardPositionRotationFlagsIDPuzzleNameWidthTilesHeightTilesAvailableCardCountAvailableCardsPlacedCardsInitialPlacedCardsBackgroundTilesGoalPositionCountGoalPositionsBaseColorHighlightColorTFMaterialTextureModelVisibleTabletBackgroundRenderDataTabletStatusRenderDataTabletStatusNotSolvedTextureTabletStatusSolvedTextureTabletResetRenderData"}; }; constexpr MetadataTable Metadata;