From ffd2e45d81d96c82a8b9f8de04fd25c437f6b1f3 Mon Sep 17 00:00:00 2001 From: Asuro Date: Mon, 17 Mar 2025 17:59:39 +0100 Subject: [PATCH] working puzzle editor? --- assets/blender/Channels.blend | 4 +- src/game/Global.cpp | 10 +- src/game/Global.h | 1 + src/game/Level.cpp | 38 ++++-- src/game/Puzzle.cpp | 160 ++++++++++++++++++++--- src/game/Puzzle.h | 1 + src/game/compiled-shaders/dx11/frag.bin | 2 +- src/game/compiled-shaders/glsl/frag.bin | 4 +- src/game/compiled-shaders/spirv/frag.bin | 2 +- src/game/data/puzzles/0.pzl | 4 +- src/game/data/static/puzzle.dat | Bin 1164 -> 1164 bytes src/game/mini.def | 4 +- src/game/shaders/frag.sc | 4 +- src/gen/Generated.h | 4 +- src/models/ConcretePlane.glb | 4 +- src/models/w corner bridge.glb | 3 + src/models/w corner long.glb | 2 +- src/models/w+ corner short.glb | 3 + 18 files changed, 203 insertions(+), 47 deletions(-) create mode 100644 src/models/w corner bridge.glb create mode 100644 src/models/w+ corner short.glb diff --git a/assets/blender/Channels.blend b/assets/blender/Channels.blend index 581fae0..72becb4 100644 --- a/assets/blender/Channels.blend +++ b/assets/blender/Channels.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0fd27bb60cdba42d3e3ce713ae86d9f27548ef031b4e6af68fb5aa7344584335 -size 1125796 +oid sha256:de23fbb69db831bb505606fc7f14825a6b8e036a42a6170f1b85104818d7c33e +size 1127016 diff --git a/src/game/Global.cpp b/src/game/Global.cpp index 0bae8c0..ab48921 100644 --- a/src/game/Global.cpp +++ b/src/game/Global.cpp @@ -78,7 +78,15 @@ void Transform::UpdateMatrix() bx::mtxScale(scale.M, Scale.x, Scale.y, Scale.z); Mat4 temp; bx::mtxMul(temp.M, scale.M, Rotation.M); - bx::mtxMul(M.M, pos.M, temp.M); + bx::mtxMul(M.M, temp.M, pos.M); + bx::mtxInverse(MI.M, M.M); +} + +void Transform::UpdateMatrixForCam() +{ + Mat4 pos; + bx::mtxTranslate(pos.M, Position.x, Position.y, Position.z); + bx::mtxMul(M.M, pos.M, Rotation.M); bx::mtxInverse(MI.M, M.M); } diff --git a/src/game/Global.h b/src/game/Global.h index 49016b6..e7b545c 100644 --- a/src/game/Global.h +++ b/src/game/Global.h @@ -227,6 +227,7 @@ struct Transform Vec3 GetPosition(); const float* GetPtr(); void UpdateMatrix(); + void UpdateMatrixForCam(); }; struct SharedData; diff --git a/src/game/Level.cpp b/src/game/Level.cpp index e1f4346..0d9e181 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -152,13 +152,16 @@ namespace Game { Tests.Get(Tests.New()).Setup(); } + UIQuads.Count = 0; + PuzzleTiles.Count = 0; for (int32_t i = 0; i < BX_COUNTOF(Puzzles); ++i) { - if (Puzzles[i].Data.ID != UINT16_MAX && !Puzzles[i].IsSetup) + if (Puzzles[i].Data.ID != UINT16_MAX) { Puzzles[i].Setup(); } } + LOG("Tiles: %u", PuzzleTiles.Count); UpdatePlayerInputMode(); } @@ -170,9 +173,8 @@ namespace Game // Input float delta = GetInstance().Time.Delta; - delta = 1.0f / 144.0f; constexpr float moveSpeed = 10.0f; - constexpr float rotSpeed = 0.6f; + constexpr float rotSpeed = 1.6f; float forwardInput = (GetKey(ScanCode::W) ? 1.0f : 0.0f) + (GetKey(ScanCode::S) ? -1.0f : 0.0f); float rightInput = (GetKey(ScanCode::D) ? 1.0f : 0.0f) + (GetKey(ScanCode::A) ? -1.0f : 0.0f); @@ -256,12 +258,12 @@ namespace Game auto& player = GetInstance().Player; if (player.CameraM == CameraMode::Freefly) { - player.FreeflyCamTransform.UpdateMatrix(); + player.FreeflyCamTransform.UpdateMatrixForCam(); bgfx::setViewTransform(viewId, player.FreeflyCamTransform.M.M, proj); } else { - player.PlayerCamTransform.UpdateMatrix(); + player.PlayerCamTransform.UpdateMatrixForCam(); bgfx::setViewTransform(viewId, player.PlayerCamTransform.M.M, proj); } @@ -308,8 +310,12 @@ namespace Game for (int32_t i = 0; i < Puzzle::Config::MaxCardsInPuzzle; ++i) { TileHandles[i] = level.PuzzleTiles.New(); + auto& tile = level.PuzzleTiles.Get(TileHandles[i]); + tile.EData.MaterialHandle = 0; UIPlacedCards[i] = level.UIQuads.New(); } + IsSetup = true; + LOG("finished setup!"); } void WorldPuzzle::Update() @@ -317,21 +323,31 @@ namespace Game Transform& camTransform = GetInstance().Player.PlayerCamTransform; Vec3 cameraPos = camTransform.GetPosition() * -1; Level& level = GetInstance().GameLevel; + auto& staticCards = Puzzle::GetStaticPuzzleData().Cards; for (int8_t y = 0; y < Data.WidthTiles / Puzzle::Config::CardSize; ++y) { for (int8_t x = 0; x < Data.WidthTiles / Puzzle::Config::CardSize; ++x) { Generated::PlacedPuzzleCard& card = Data.PlacedCards[y * Puzzle::Config::MaxPuzzleSizeCards + x]; - if (!Puzzle::IsValid(card.RefCard)) - const Generated::StaticPuzzleCard& cData = Puzzle::GetCard(card.RefCard); auto& tile = level.PuzzleTiles.Get(TileHandles[y * Puzzle::Config::MaxPuzzleSizeCards + x]); - tile.EData.ModelHandle = Puzzle::GetStaticPuzzleData().Cards[card.RefCard.Idx].ModelHandle; - tile.EData.Transform.SetPosition({(float)card.Position.X, (float)card.Position.Y, 0.0f}); - auto& quad = level.UIQuads.Get(UIPlacedCards[y * Puzzle::Config::MaxPuzzleSizeCards + x]); + + bool IsValid = Puzzle::IsValid(card.RefCard); + tile.EData.Visible = true; + quad.EData.Visible = IsValid; + + // const Generated::StaticPuzzleCard& cData = Puzzle::GetCard(card.RefCard); + tile.EData.ModelHandle = + IsValid ? staticCards[card.RefCard.Idx].ModelHandle : staticCards[0].ModelHandle; + tile.EData.Transform.SetPosition({ + (float)card.Position.X * Puzzle::Config::CardScaleWorld, + -5.0f, + (float)card.Position.Y * Puzzle::Config::CardScaleWorld, + }); + bx::mtxRotateY(tile.EData.Transform.Rotation.M, card.Rotation * bx::kPi * 0.5f); + Vec3 fw = {0, -1, 0}; - // quad.EData.Transform.SetPosition(cameraPos + Vec3{0, -2, 0}); quad.EData.Transform.SetPosition({}); quad.EData.Transform.Rotation = camTransform.Rotation; } diff --git a/src/game/Puzzle.cpp b/src/game/Puzzle.cpp index 66deed9..680aa85 100644 --- a/src/game/Puzzle.cpp +++ b/src/game/Puzzle.cpp @@ -19,6 +19,7 @@ namespace }; Generated::StaticPuzzleData StaticData; + Generated::StaticPuzzleCard InvalidCard; } // namespace namespace Puzzle @@ -61,7 +62,11 @@ namespace Puzzle } const StaticPuzzleCard& GetCard(StaticPuzzleCardHandle H) { - assert(IsValid(H)); + if (H.Idx == UINT16_MAX) + { + LOG_ERROR("Invalid static card handle!"); + return InvalidCard; + } return GetStaticPuzzleData().Cards[H.Idx]; } @@ -83,22 +88,20 @@ namespace Puzzle PuzzleElementType::Enum GetNodeAt(const PuzzleData& puz, PuzPos pos) { - assert(pos.X < Puzzle::Config::MaxPuzzleSizeCards && pos.Y < Puzzle::Config::MaxPuzzleSizeCards && pos.X >= 0 && + assert(pos.X < Puzzle::Config::MaxPuzzleSizeTiles && pos.Y < Puzzle::Config::MaxPuzzleSizeTiles && pos.X >= 0 && pos.Y >= 0); - // TODO: this is horrible - for (int32_t i = 0; i < puz.PlacedCardCount; ++i) + int32_t cardIdxX = pos.X / Puzzle::Config::CardSize; + int32_t cardIdxY = pos.Y / Puzzle::Config::CardSize; + auto& card = puz.PlacedCards[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)) { - auto& card = puz.PlacedCards[i]; - int8_t offsetX = pos.X - card.Position.X; - int8_t offsetY = pos.Y - card.Position.Y; - if (offsetX >= 0 && offsetX < Puzzle::Config::CardSize && offsetY >= 0 && - offsetY < Puzzle::Config::CardSize) - { - PuzzleElementType::Enum cardVal = GetCardNodeAt(GetCard(card.RefCard), card.Rotation, offsetX, offsetY); - if (cardVal != PuzzleElementType::None) return cardVal; - } + PuzzleElementType::Enum cardVal = GetCardNodeAt(GetCard(card.RefCard), card.Rotation, offsetX, offsetY); + if (cardVal != PuzzleElementType::None) return cardVal; } - return puz.BackgroundTiles[pos.Y * Puzzle::Config::MaxPuzzleSizeCards + pos.X]; + 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) @@ -260,9 +263,58 @@ namespace Puzzle bx::snprintf(buf, bufSize, "%s/%u.pzl", Puzzle::PuzzleFileDir, puzID); } + // TODO: targetPos is of type CardPos + bool ReturnPlacedCard(PuzzleData& obj, PuzPos targetPos) + { + auto& placedCard = obj.PlacedCards[targetPos.Y * Config::MaxPuzzleSizeCards + targetPos.X]; + if (IsValid(placedCard.RefCard)) + { + if (placedCard.IsLocked) return false; + bool found = false; + for (int32_t i = 0; i < obj.AvailableCardCount; ++i) + { + if (obj.AvailableCards[i].RefCard.Idx == placedCard.RefCard.Idx && obj.AvailableCards[i].UsedCount > 0) + { + obj.AvailableCards[i].UsedCount--; + found = true; + break; + } + } + if (!found) + { + LOG_ERROR("Failed to find available card to return placed card of type %u to!", placedCard.RefCard.Idx); + return false; + } + placedCard.RefCard = {}; + } + return true; + } + + // TODO: targetPos is of type CardPos + bool DragAvailableCardTo(PuzzleData& obj, PuzPos targetPos, int32_t availIdx, uint8_t rotation) + { + if (availIdx >= obj.AvailableCardCount) + { + LOG_ERROR("Invalid drag with avail idx %i!", availIdx); + return false; + } + if (!ReturnPlacedCard(obj, targetPos)) return false; + + auto& draggedCard = obj.AvailableCards[availIdx]; + draggedCard.UsedCount++; + + auto& placedCard = obj.PlacedCards[targetPos.Y * Config::MaxPuzzleSizeCards + targetPos.X]; + placedCard.RefCard = draggedCard.RefCard; + placedCard.IsLocked = false; + placedCard.Position = targetPos; + placedCard.Rotation = rotation; + return true; + } + bool RenderDebugUI(PuzzleData& obj) { bool dataChanged = false; + uint8_t debugRot = Game::GetInstance().DebugData.DebugCardRotation; bool isVisible = true; if (ImGui::Begin("Puzzle", &isVisible)) @@ -327,14 +379,61 @@ 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]; 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 (placedCard.IsLocked) + { + placedCard.IsLocked = false; + placedCard.RefCard = {}; + dataChanged = true; + } + else + { + if (!ReturnPlacedCard(obj, cardPos)) + { + placedCard.IsLocked = false; + placedCard.RefCard = {}; + dataChanged = true; + } + } + } + if (!placedCard.IsLocked && IsValid(placedCard.RefCard)) + { + ImVec2 s = {puzCursorStart.x + x * UIPuzBoxSize, puzCursorStart.y + y * UIPuzBoxSize}; + drawList.AddRectFilled(s, + {s.x + UIPuzBoxSize * Puzzle::Config::CardSize, + s.y + UIPuzBoxSize * Puzzle::Config::CardSize}, + 0x33FFFFFF); + } if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("cardtype", 0)) { uint32_t CardIdx = *reinterpret_cast(payload->Data); - obj.PlacedCards[obj.PlacedCardCount].RefCard = {(uint16_t)CardIdx}; - obj.PlacedCardCount++; + placedCard = {}; + placedCard.RefCard = {(uint16_t)CardIdx}; + placedCard.Rotation = debugRot; + 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); } ImGui::EndDragDropTarget(); } @@ -401,17 +500,42 @@ namespace Puzzle } if (bAvailOpen) { - uint8_t debugRot = Game::GetInstance().DebugData.DebugCardRotation; + ImVec2 startPos = ImGui::GetCursorScreenPos(); for (uint32_t i = 0; i < obj.AvailableCardCount; ++i) { + ImVec2 localPos = {startPos.x + i * 60.0f, startPos.y}; + ImGui::SetCursorScreenPos(localPos); + ImGui::PushID(i); auto& card = obj.AvailableCards[i]; DrawCard(GetCard(card.RefCard), debugRot, ImGui::GetCursorScreenPos()); - if (ImGui::BeginDragDropSource()) + 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); + ImGui::PushID("carc"); + if (ImGui::DragInt("", &displayCount, 0.25f)) + { + int diff = displayCount - (card.MaxAvailableCount - card.UsedCount); + card.MaxAvailableCount = bx::max(0, card.MaxAvailableCount + diff); + dataChanged = true; + } + ImGui::PopID(); + ImGui::SameLine(0, 3); + if (ImGui::Button("x")) + { + if (i < obj.AvailableCardCount - 1) + { + obj.AvailableCards[i] = obj.AvailableCards[obj.AvailableCardCount - 1]; + } + obj.AvailableCardCount--; + } + ImGui::PopID(); } ImGui::TreePop(); } diff --git a/src/game/Puzzle.h b/src/game/Puzzle.h index cf18d5d..299e937 100644 --- a/src/game/Puzzle.h +++ b/src/game/Puzzle.h @@ -22,6 +22,7 @@ namespace Puzzle static constexpr uint32_t MaxTilesInPuzzle = MaxPuzzleSizeTiles * MaxPuzzleSizeTiles; static constexpr uint32_t MaxAvailableStacks = 16; static constexpr uint32_t MaxGoalPositions = 16; + static constexpr float CardScaleWorld = 10.0f; }; void Setup(); diff --git a/src/game/compiled-shaders/dx11/frag.bin b/src/game/compiled-shaders/dx11/frag.bin index 8167e08..c560bda 100644 --- a/src/game/compiled-shaders/dx11/frag.bin +++ b/src/game/compiled-shaders/dx11/frag.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c2953a0e0de93277cbf340eff51557bb8a322b36255df693cebd8d175a5b003 +oid sha256:60bb6c5e7379dee6a39f40577f8f838929f010a321a2d9ec104791aef63f6a7b size 3900 diff --git a/src/game/compiled-shaders/glsl/frag.bin b/src/game/compiled-shaders/glsl/frag.bin index 8fbb81c..705a83e 100644 --- a/src/game/compiled-shaders/glsl/frag.bin +++ b/src/game/compiled-shaders/glsl/frag.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:484b68fb533a5395db797f26c2a650228096c03d661d841b8eeb1e5f989b0fda -size 13317 +oid sha256:85a99cbada51961bbc111a17f67f8c9dd5c582ac890cb9a0b2e0087d3e038c2b +size 13315 diff --git a/src/game/compiled-shaders/spirv/frag.bin b/src/game/compiled-shaders/spirv/frag.bin index 221f818..7106766 100644 --- a/src/game/compiled-shaders/spirv/frag.bin +++ b/src/game/compiled-shaders/spirv/frag.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15289052836fd4c95c9ce84d4a0ec6a5ec33ec1679709a9d53d51cf7d2105182 +oid sha256:56e998b9752a86a9b1b15ea3341535b104c4368692d9ab38407d98ad5beac262 size 4430 diff --git a/src/game/data/puzzles/0.pzl b/src/game/data/puzzles/0.pzl index 074df81..ab1e767 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:2162216c620c252d35d2a0339f07dd729b6aa1665eec7477245f39afcc76fc65 -size 5820 +oid sha256:b6c70072903838f61c24ad449706759d1e1b1820fc79b5499bb9b9d3e46a3cc3 +size 5816 diff --git a/src/game/data/static/puzzle.dat b/src/game/data/static/puzzle.dat index d555fea32fd81f9b56abf517e6b5819500e42fa8..1af579930c28a9a046296be786588e9f78bae49c 100644 GIT binary patch literal 1164 zcmWFz2#vDxNZ!xD%76hF8JMABFq#uA0^)%%NRk~a0%E~12LmIN2~)!h7lBGJ@W2>I oG!v8!)5XmI6M;%FaKRWzG)OfFvqQz$p!6s;8UmvsFtkDd0CFn>bN~PV delta 15 XcmeC-?BSfC$H=kq;%?@N4;BFcDia1p diff --git a/src/game/mini.def b/src/game/mini.def index b68cab9..d080d1d 100644 --- a/src/game/mini.def +++ b/src/game/mini.def @@ -48,10 +48,10 @@ enum PuzzleElementType(u8) { None GameName("Empty") ShortName(" ") WaterIn GameName("Water Source") ShortName("~+") - WaterGoal GameName("Water Goal") ShortName("~-") + WaterGoal GameName("Water Goal") ShortName("~!") WaterChannel GameName("Water Channel") ShortName("~") ElectricIn GameName("Electricity Source") ShortName("e+") - ElectricGoal GameName("Electricity Goal") ShortName("e-") + ElectricGoal GameName("Electricity Goal") ShortName("e!") Blocked GameName("Blocked") ShortName("B") Bridge GameName("Bridge") ShortName("#") } diff --git a/src/game/shaders/frag.sc b/src/game/shaders/frag.sc index 38eeb20..e656233 100644 --- a/src/game/shaders/frag.sc +++ b/src/game/shaders/frag.sc @@ -32,7 +32,7 @@ vec3 desaturate(vec3 color) float dither(float brightness, vec2 inputUv) { - float globalScale = 8.0; + float globalScale = 8; // constants float xRes = u_texInfo.z; @@ -77,7 +77,7 @@ float dither(float brightness, vec2 inputUv) float pattern = texture3D(s_ditherSampler, vec3(uv, subLayer)).r; - float contrast = 8 * scaleExp * brightnessSpacingMultiplier * 0.1; + float contrast = 2 * scaleExp * brightnessSpacingMultiplier * 0.1; contrast *= pow(freq.y / freq.x, 1.0); float baseVal = lerp(0.5, brightness, saturate(1.05 / (1 + contrast))); float threshold = 1 - brightnessCurve + 0.6; diff --git a/src/gen/Generated.h b/src/gen/Generated.h index 4d118da..6037b2f 100644 --- a/src/gen/Generated.h +++ b/src/gen/Generated.h @@ -44,10 +44,10 @@ namespace Generated { " ", "~+", - "~-", + "~!", "~", "e+", - "e-", + "e!", "B", "#", }; diff --git a/src/models/ConcretePlane.glb b/src/models/ConcretePlane.glb index b071319..ce10076 100644 --- a/src/models/ConcretePlane.glb +++ b/src/models/ConcretePlane.glb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c5759a2e563ef4260920f50dfac9c057cb1e0ad69b0994bd420f1123b40eeae -size 1464 +oid sha256:fb7691da04448da3169880b4df7c051b86145e1514678ca91c7e6af512e1793d +size 1440 diff --git a/src/models/w corner bridge.glb b/src/models/w corner bridge.glb new file mode 100644 index 0000000..c1e996c --- /dev/null +++ b/src/models/w corner bridge.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:569a59aae2f7a64cc85a24178c36507c51d8d3553836ba93e125b8fb17c9a17a +size 7632 diff --git a/src/models/w corner long.glb b/src/models/w corner long.glb index 45d56fd..525352d 100644 --- a/src/models/w corner long.glb +++ b/src/models/w corner long.glb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e0c3968772ea80a7de6cfecd5b083c25e874bc87960356ec5a987ac0ef4db62 +oid sha256:ecc10aa2d8b086057e076cfb54a2bf8064a79cc750418cacc57b64fedf9dc529 size 2896 diff --git a/src/models/w+ corner short.glb b/src/models/w+ corner short.glb new file mode 100644 index 0000000..79c40ff --- /dev/null +++ b/src/models/w+ corner short.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25328a270cb3ac28f73b1a462dfdb8c8eabd99a559a17108ae6fba82f357f7b2 +size 11608