diff --git a/src/game/Instance.h b/src/game/Instance.h index 283edcd..3c1316d 100644 --- a/src/game/Instance.h +++ b/src/game/Instance.h @@ -32,12 +32,6 @@ namespace Game int64_t StartTime = 0; }; - // TODO: move to generated data and save - struct SavedPlayerConfig - { - Gen::SavedEntityRenderData TabletRenderData; - }; - struct PlayerData { Gen::Transform PlayerCamTransform; @@ -53,7 +47,7 @@ namespace Game InteractionMode InteractionM = InteractionMode::Walk; float MouseSensitivity = 1.0f; float MovementSpeed = 10.0f; - SavedPlayerConfig Config; + Gen::SavedPlayerConfig Config; }; struct InstanceDebugData diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 3fd2a77..499e297 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -195,7 +195,7 @@ namespace Game { Deserializer d; d.Init("game/data/static/uiconfig.dat", "UICO"); - d.ReadT(GetInstance().Player.Config.TabletRenderData); + d.ReadT(GetInstance().Player.Config); d.Finish(); } } @@ -271,7 +271,7 @@ namespace Game if (IsValid(TabletHandle)) { auto& tablet = UIQuads.Get(TabletHandle); - tablet.EData.LoadFromSaved(player.Config.TabletRenderData); + tablet.EData.LoadFromSaved(player.Config.TabletBackgroundRenderData); UpdateMatrix(player.PlayerCamTransform); tablet.EData.Transform.Rotation = player.PlayerCamTransform.Rotation; Rotate(tablet.EData.Transform, {0.5f * bx::kPi, 0.0f, 0.0f}); @@ -382,6 +382,7 @@ namespace Game quad.EData.MaterialHandle = EMaterial::UI; quad.EData.ModelH = GameRendering::Get().GetModelHandleFromPath("models/plane.glb"); } + SolvedQuad = level.UIQuads.New(); IsSetup = true; LOG("finished setup!"); } @@ -450,6 +451,21 @@ namespace Game Vec3 mousePosWorld = GetMousePosWorld(); + Puzzle::PuzzleSolver solver; + EntityRenderData solvedData; + solvedData.LoadFromSaved(GetInstance().Player.Config.TabletStatusRenderData); + auto& solvedQuad = level.UIQuads.Get(SolvedQuad); + solvedQuad.EData = solvedData; + solvedQuad.EData.Visible = IsActive; + solvedQuad.EData.TextureHandle = solver.IsPuzzleSolved(Data) + ? GetInstance().Player.Config.TabletStatusSolvedTexture + : solvedData.TextureHandle; + solvedQuad.EData.Transform.Position = tileOriginTransform.Position; + solvedQuad.EData.Transform.Rotation = camTransform.Rotation; + solvedQuad.EData.Transform.Scale = solvedData.Transform.Scale; + TranslateLocal(solvedQuad.EData.Transform, solvedData.Transform.Position); + Rotate(solvedQuad.EData.Transform, Vec3{bx::kPi * 0.5f, 0.0f, (1.0f - 0 * 0.5f) * bx::kPi}); + // Available Cards for (int32_t i = 0; i < Puzzle::Config::MaxAvailableStacks; ++i) { diff --git a/src/game/Level.h b/src/game/Level.h index 6405550..854269d 100644 --- a/src/game/Level.h +++ b/src/game/Level.h @@ -157,6 +157,7 @@ namespace Game PuzzleTileCoverHandle CoverHandles[Puzzle::Config::MaxCardsInPuzzle * Puzzle::Config::MaxCoversInTile]; UIQuadEntityHandle UIPlacedCards[Puzzle::Config::MaxCardsInPuzzle]; UIQuadEntityHandle UIAvailableCards[Puzzle::Config::MaxAvailableStacks * UIAvailableCardMaxStackPreview]; + UIQuadEntityHandle SolvedQuad; Gen::PuzPos DraggedCard{-1, -1}; uint16_t DraggedAvailableCardIdx = UINT16_MAX; bool IsSetup = false; diff --git a/src/game/Puzzle.cpp b/src/game/Puzzle.cpp index 37324c0..b1f3fd0 100644 --- a/src/game/Puzzle.cpp +++ b/src/game/Puzzle.cpp @@ -240,7 +240,7 @@ namespace Puzzle return from == PuzzleElementType::ElectricIn || from == PuzzleElementType::ElectricGoal || from == PuzzleElementType::None; } - assert(false); + // assert(false); return false; } bool PuzzleSolver::IsValidSource(PuzzleElementType::Enum sourceType, PuzzleElementType::Enum goalType) diff --git a/src/game/Tools.cpp b/src/game/Tools.cpp index 33871e3..700df18 100644 --- a/src/game/Tools.cpp +++ b/src/game/Tools.cpp @@ -39,6 +39,7 @@ namespace Tools bool EntityDataSettings(Gen::SavedEntityRenderData& data) { + ImGui::PushID(&data); bool changed = false; changed |= ModelDropdown(data.Model); changed |= MaterialDropdown(data.Material); @@ -47,6 +48,7 @@ namespace Tools changed |= ImGui::Checkbox("Visible", &data.Visible); changed |= ImGui::ColorEdit4("Color 1", &data.BaseColor.x); changed |= ImGui::ColorEdit4("Color 2", &data.HighlightColor.x); + ImGui::PopID(); return changed; } @@ -299,11 +301,16 @@ namespace Tools ImGui::Separator(); ImGui::Text("Game Tablet"); - if (Tools::EntityDataSettings(player.Config.TabletRenderData)) + bool bTabletChanged = false; + bTabletChanged |= Tools::EntityDataSettings(player.Config.TabletBackgroundRenderData); + ImGui::Text("Status"); + bTabletChanged |= Tools::EntityDataSettings(player.Config.TabletStatusRenderData); + bTabletChanged |= Tools::TextureDropdown(player.Config.TabletStatusSolvedTexture); + if (bTabletChanged) { Serializer s; s.Init("game/data/static/uiconfig.dat", "UICO"); - s.WriteT(player.Config.TabletRenderData); + s.WriteT(player.Config); s.Finish(); } diff --git a/src/game/data/puzzles/0.pzl b/src/game/data/puzzles/0.pzl index 78cb6c9..cc24f96 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:deda5ca16e6d732fb41bbdc7cec4dd2932389f3d66b8c9f69d93771a3972b22e -size 10312 +oid sha256:dd485b73222de5ad4237a1307f9bb210c691253d0550e583a41b7512fae2af80 +size 10404 diff --git a/src/game/data/static/puzzle.dat b/src/game/data/static/puzzle.dat index bcea19f..7108a9c 100644 Binary files a/src/game/data/static/puzzle.dat and b/src/game/data/static/puzzle.dat differ diff --git a/src/game/data/static/uiconfig.dat b/src/game/data/static/uiconfig.dat index b332890..c8c989c 100644 Binary files a/src/game/data/static/uiconfig.dat and b/src/game/data/static/uiconfig.dat differ diff --git a/src/game/mini.def b/src/game/mini.def index b876714..c5cb55f 100644 --- a/src/game/mini.def +++ b/src/game/mini.def @@ -165,3 +165,10 @@ type SavedEntityRenderData ModelHandle Model b Visible } + +type SavedPlayerConfig +{ + SavedEntityRenderData TabletBackgroundRenderData + SavedEntityRenderData TabletStatusRenderData + TextureHandle TabletStatusSolvedTexture +} diff --git a/src/gen/Generated.cpp b/src/gen/Generated.cpp index 2761ee2..b92bd25 100644 --- a/src/gen/Generated.cpp +++ b/src/gen/Generated.cpp @@ -2445,4 +2445,114 @@ namespace Gen assert(isOk); return isOk; } + bool Save(const SavedPlayerConfig* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(&obj[i].TabletBackgroundRenderData, 1, serializer) && isOk; + isOk = Save(&obj[i].TabletStatusRenderData, 1, serializer) && isOk; + isOk = Save(&obj[i].TabletStatusSolvedTexture, 1, serializer) && isOk; + } + return isOk; + } + bool Load(SavedPlayerConfig* obj, uint32_t count, Deserializer& serializer) + { + const char* typeName = Meta::Metadata.TypeDefinitions[SavedPlayerConfig::TypeIdx].Name; + + // Quick match + int32_t matchedHashIdx = + serializer.TypeBuf.FindHash(Meta::Metadata.TypeDefinitions[SavedPlayerConfig::TypeIdx].Hash); + if (matchedHashIdx >= 0) + { + assert(bx::strCmp(serializer.TypeBuf.Defs[matchedHashIdx].Name, typeName) == 0); + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Load(&obj[i].TabletBackgroundRenderData, 1, serializer) && isOk; + isOk = Load(&obj[i].TabletStatusRenderData, 1, serializer) && isOk; + isOk = Load(&obj[i].TabletStatusSolvedTexture, 1, serializer) && isOk; + } + // if we're not ok here, something went really wrong + assert(isOk); + return isOk; + } + + // Failed to resolve hash, the type definition chaned since the file was saved! try to match by name. + int32_t nameMatchIdx = serializer.TypeBuf.FindDefByName(typeName); + if (nameMatchIdx < 0) + { + // Name match failed, caller has to handle this and potentially skip some bytes + return false; + } + + // Successfully matched name, but we need to follow the definition of the file now! + const Meta::TypeDef& matchedDef = serializer.TypeBuf.Defs[nameMatchIdx]; + + // Figure out new member mapping + uint64_t WriteDestinations[64]; + for (int32_t i = 0; i < BX_COUNTOF(WriteDestinations); ++i) + { + WriteDestinations[i] = UINT64_MAX; + } + for (uint32_t i = 0; i < matchedDef.ChildCount; ++i) + { + 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, "TabletBackgroundRenderData") == 0 && bx::strCmp(memberTypeName, "SavedEntityRenderData") == 0) + { + WriteDestinations[i] = offsetof(SavedPlayerConfig, TabletBackgroundRenderData); + } + if (bx::strCmp(memberName, "TabletStatusRenderData") == 0 && bx::strCmp(memberTypeName, "SavedEntityRenderData") == 0) + { + WriteDestinations[i] = offsetof(SavedPlayerConfig, TabletStatusRenderData); + } + if (bx::strCmp(memberName, "TabletStatusSolvedTexture") == 0 && bx::strCmp(memberTypeName, "TextureHandle") == 0) + { + WriteDestinations[i] = offsetof(SavedPlayerConfig, TabletStatusSolvedTexture); + } + } + + // Start reading in file order, skipping things that we don't know by name and type + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + uint8_t* objBasePtr = reinterpret_cast(&obj[i]); + + for (uint32_t j = 0; j < matchedDef.ChildCount; ++j) + { + const Meta::TypeDef& childDef = serializer.TypeBuf.Defs[matchedDef.ChildIndices[j]]; + const bx::StringView memberName = {&serializer.MemberNameBuf[matchedDef.MemberNameIndices[j].Offset], matchedDef.MemberNameIndices[j].Size}; + if (WriteDestinations[j] == UINT64_MAX) + { + // Unknown member name or type changed + uint16_t count = bx::max(1, matchedDef.ChildArraySizes[matchedDef.ChildIndices[j]]); + serializer.Skip(childDef.Size * count); + continue; + } + + if (bx::strCmp(memberName, "TabletBackgroundRenderData") == 0) + { + auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); + isOk = Load(fieldPtr, 1, serializer) && isOk; + continue; + } + if (bx::strCmp(memberName, "TabletStatusRenderData") == 0) + { + auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); + isOk = Load(fieldPtr, 1, serializer) && isOk; + continue; + } + if (bx::strCmp(memberName, "TabletStatusSolvedTexture") == 0) + { + auto* fieldPtr = reinterpret_cast(objBasePtr + WriteDestinations[j]); + isOk = Load(fieldPtr, 1, serializer) && isOk; + continue; + } + assert(false); + } + } + assert(isOk); + return isOk; + } } diff --git a/src/gen/Generated.h b/src/gen/Generated.h index 155c407..5b6452a 100644 --- a/src/gen/Generated.h +++ b/src/gen/Generated.h @@ -7,7 +7,7 @@ namespace Gen struct Deserializer; struct PuzzleElementType { - static constexpr uint16_t TypeIdx = 31; + static constexpr uint16_t TypeIdx = 32; static constexpr int32_t EntryCount = 8; enum Enum : uint8_t { @@ -56,7 +56,7 @@ namespace Gen }; struct EMaterial { - static constexpr uint16_t TypeIdx = 32; + static constexpr uint16_t TypeIdx = 33; static constexpr int32_t EntryCount = 2; enum Enum : int32_t { @@ -219,6 +219,13 @@ namespace Gen ModelHandle Model = {}; bool Visible = {}; }; + struct SavedPlayerConfig + { + static constexpr uint16_t TypeIdx = 31; + SavedEntityRenderData TabletBackgroundRenderData = {}; + SavedEntityRenderData TabletStatusRenderData = {}; + TextureHandle TabletStatusSolvedTexture = {}; + }; bool Save(const PuzzleElementType::Enum* obj, uint32_t count, Serializer& serializer); bool Load(PuzzleElementType::Enum* obj, uint32_t count, Deserializer& serializer); bool Save(const EMaterial::Enum* obj, uint32_t count, Serializer& serializer); @@ -285,6 +292,8 @@ namespace Gen bool Load(PuzzleData* obj, uint32_t count, Deserializer& serializer); bool Save(const SavedEntityRenderData* obj, uint32_t count, Serializer& serializer); bool Load(SavedEntityRenderData* obj, uint32_t count, Deserializer& serializer); + bool Save(const SavedPlayerConfig* obj, uint32_t count, Serializer& serializer); + bool Load(SavedPlayerConfig* obj, uint32_t count, Deserializer& serializer); namespace Meta { constexpr uint16_t CurrentMetaVersion = 1; @@ -308,7 +317,7 @@ namespace Gen struct MetadataTable { - TypeDef TypeDefinitions[33] + TypeDef TypeDefinitions[34] { TypeDef{sizeof(int8_t), 0, "i8", 0, {}, {}, {}}, TypeDef{sizeof(int16_t), 1, "i16", 0, {}, {}, {}}, @@ -333,18 +342,19 @@ namespace Gen TypeDef{sizeof(TextureHandle), 1633273761, "TextureHandle", 2, {5, 18}, {0, 0}, {{51, 10}, {61, 5}}}, TypeDef{sizeof(PuzPos), 1834398141, "PuzPos", 2, {0, 0}, {0, 0}, {{66, 1}, {67, 1}}}, TypeDef{sizeof(CardSocket), 2168907571, "CardSocket", 2, {19, 4}, {0, 0}, {{68, 5}, {73, 19}}}, - TypeDef{sizeof(StaticPuzzleCard), 537913399, "StaticPuzzleCard", 9, {31, 19, 19, 19, 19, 19, 22, 20, 20}, {4, 0, 0, 0, 0, 0, 16, 0, 0}, {{92, 8}, {100, 15}, {115, 16}, {131, 15}, {146, 16}, {162, 15}, {177, 7}, {184, 18}, {202, 18}}}, + TypeDef{sizeof(StaticPuzzleCard), 537913399, "StaticPuzzleCard", 9, {32, 19, 19, 19, 19, 19, 22, 20, 20}, {4, 0, 0, 0, 0, 0, 16, 0, 0}, {{92, 8}, {100, 15}, {115, 16}, {131, 15}, {146, 16}, {162, 15}, {177, 7}, {184, 18}, {202, 18}}}, TypeDef{sizeof(StaticPuzzleCardHandle), 1742502768, "StaticPuzzleCardHandle", 1, {5}, {0}, {{220, 3}}}, 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, 31, 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, 32, 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(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), 692059165, "SavedPlayerConfig", 3, {30, 30, 20}, {0, 0, 0}, {{517, 26}, {543, 22}, {565, 25}}}, TypeDef{sizeof(PuzzleElementType::Enum), 2983807453, "PuzzleElementType", 0, {}, {}, {}}, TypeDef{sizeof(EMaterial::Enum), 2024002654, "EMaterial", 0, {}, {}, {}}, }; - char MemberNameBuffer[64*64*64]{"xyxyzxyzwMMMMIPositionRotationScaleIdxModelIdxAssetTextureIdxAssetXYModelConnectionDirectionElementsBaseModelHandleNorthCoverHandleEastCoverHandleSouthCoverHandleWestCoverHandleSocketsModelTextureHandleBoardTextureHandleIdxTileBaseColorTileDotColorTestDisabledCardTintCardsVisualsRefCardMaxAvailableCountUsedCountRefCardPositionRotationIsLockedIDPuzzleNameWidthTilesHeightTilesAvailableCardCountAvailableCardsPlacedCardsBackgroundTilesGoalPositionCountGoalPositionsBaseColorHighlightColorTFMaterialTextureModelVisible"}; + char MemberNameBuffer[64*64*64]{"xyxyzxyzwMMMMIPositionRotationScaleIdxModelIdxAssetTextureIdxAssetXYModelConnectionDirectionElementsBaseModelHandleNorthCoverHandleEastCoverHandleSouthCoverHandleWestCoverHandleSocketsModelTextureHandleBoardTextureHandleIdxTileBaseColorTileDotColorTestDisabledCardTintCardsVisualsRefCardMaxAvailableCountUsedCountRefCardPositionRotationIsLockedIDPuzzleNameWidthTilesHeightTilesAvailableCardCountAvailableCardsPlacedCardsBackgroundTilesGoalPositionCountGoalPositionsBaseColorHighlightColorTFMaterialTextureModelVisibleTabletBackgroundRenderDataTabletStatusRenderDataTabletStatusSolvedTexture"}; }; constexpr MetadataTable Metadata;