working puzzle editor?

This commit is contained in:
Asuro
2025-03-17 17:59:39 +01:00
parent 93bb1553be
commit ffd2e45d81
18 changed files with 203 additions and 47 deletions

Binary file not shown.

View File

@@ -78,7 +78,15 @@ void Transform::UpdateMatrix()
bx::mtxScale(scale.M, Scale.x, Scale.y, Scale.z); bx::mtxScale(scale.M, Scale.x, Scale.y, Scale.z);
Mat4 temp; Mat4 temp;
bx::mtxMul(temp.M, scale.M, Rotation.M); 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); bx::mtxInverse(MI.M, M.M);
} }

View File

@@ -227,6 +227,7 @@ struct Transform
Vec3 GetPosition(); Vec3 GetPosition();
const float* GetPtr(); const float* GetPtr();
void UpdateMatrix(); void UpdateMatrix();
void UpdateMatrixForCam();
}; };
struct SharedData; struct SharedData;

View File

@@ -152,13 +152,16 @@ namespace Game
{ {
Tests.Get(Tests.New()).Setup(); Tests.Get(Tests.New()).Setup();
} }
UIQuads.Count = 0;
PuzzleTiles.Count = 0;
for (int32_t i = 0; i < BX_COUNTOF(Puzzles); ++i) 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(); Puzzles[i].Setup();
} }
} }
LOG("Tiles: %u", PuzzleTiles.Count);
UpdatePlayerInputMode(); UpdatePlayerInputMode();
} }
@@ -170,9 +173,8 @@ namespace Game
// Input // Input
float delta = GetInstance().Time.Delta; float delta = GetInstance().Time.Delta;
delta = 1.0f / 144.0f;
constexpr float moveSpeed = 10.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 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); 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; auto& player = GetInstance().Player;
if (player.CameraM == CameraMode::Freefly) if (player.CameraM == CameraMode::Freefly)
{ {
player.FreeflyCamTransform.UpdateMatrix(); player.FreeflyCamTransform.UpdateMatrixForCam();
bgfx::setViewTransform(viewId, player.FreeflyCamTransform.M.M, proj); bgfx::setViewTransform(viewId, player.FreeflyCamTransform.M.M, proj);
} }
else else
{ {
player.PlayerCamTransform.UpdateMatrix(); player.PlayerCamTransform.UpdateMatrixForCam();
bgfx::setViewTransform(viewId, player.PlayerCamTransform.M.M, proj); bgfx::setViewTransform(viewId, player.PlayerCamTransform.M.M, proj);
} }
@@ -308,8 +310,12 @@ namespace Game
for (int32_t i = 0; i < Puzzle::Config::MaxCardsInPuzzle; ++i) for (int32_t i = 0; i < Puzzle::Config::MaxCardsInPuzzle; ++i)
{ {
TileHandles[i] = level.PuzzleTiles.New(); TileHandles[i] = level.PuzzleTiles.New();
auto& tile = level.PuzzleTiles.Get(TileHandles[i]);
tile.EData.MaterialHandle = 0;
UIPlacedCards[i] = level.UIQuads.New(); UIPlacedCards[i] = level.UIQuads.New();
} }
IsSetup = true;
LOG("finished setup!");
} }
void WorldPuzzle::Update() void WorldPuzzle::Update()
@@ -317,21 +323,31 @@ namespace Game
Transform& camTransform = GetInstance().Player.PlayerCamTransform; Transform& camTransform = GetInstance().Player.PlayerCamTransform;
Vec3 cameraPos = camTransform.GetPosition() * -1; Vec3 cameraPos = camTransform.GetPosition() * -1;
Level& level = GetInstance().GameLevel; Level& level = GetInstance().GameLevel;
auto& staticCards = Puzzle::GetStaticPuzzleData().Cards;
for (int8_t y = 0; y < Data.WidthTiles / Puzzle::Config::CardSize; ++y) for (int8_t y = 0; y < Data.WidthTiles / Puzzle::Config::CardSize; ++y)
{ {
for (int8_t x = 0; x < Data.WidthTiles / Puzzle::Config::CardSize; ++x) for (int8_t x = 0; x < Data.WidthTiles / Puzzle::Config::CardSize; ++x)
{ {
Generated::PlacedPuzzleCard& card = Data.PlacedCards[y * Puzzle::Config::MaxPuzzleSizeCards + 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]); 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]); 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}; Vec3 fw = {0, -1, 0};
// quad.EData.Transform.SetPosition(cameraPos + Vec3{0, -2, 0});
quad.EData.Transform.SetPosition({}); quad.EData.Transform.SetPosition({});
quad.EData.Transform.Rotation = camTransform.Rotation; quad.EData.Transform.Rotation = camTransform.Rotation;
} }

View File

@@ -19,6 +19,7 @@ namespace
}; };
Generated::StaticPuzzleData StaticData; Generated::StaticPuzzleData StaticData;
Generated::StaticPuzzleCard InvalidCard;
} // namespace } // namespace
namespace Puzzle namespace Puzzle
@@ -61,7 +62,11 @@ namespace Puzzle
} }
const StaticPuzzleCard& GetCard(StaticPuzzleCardHandle H) 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]; return GetStaticPuzzleData().Cards[H.Idx];
} }
@@ -83,22 +88,20 @@ namespace Puzzle
PuzzleElementType::Enum GetNodeAt(const PuzzleData& puz, PuzPos pos) 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); pos.Y >= 0);
// TODO: this is horrible int32_t cardIdxX = pos.X / Puzzle::Config::CardSize;
for (int32_t i = 0; i < puz.PlacedCardCount; ++i) int32_t cardIdxY = pos.Y / Puzzle::Config::CardSize;
{ auto& card = puz.PlacedCards[cardIdxY * Puzzle::Config::MaxPuzzleSizeCards + cardIdxX];
auto& card = puz.PlacedCards[i]; int32_t offsetX = pos.X - (cardIdxX * Config::CardSize);
int8_t offsetX = pos.X - card.Position.X; int32_t offsetY = pos.Y - (cardIdxY * Config::CardSize);
int8_t offsetY = pos.Y - card.Position.Y; if (offsetX >= 0 && offsetX < Puzzle::Config::CardSize && offsetY >= 0 && offsetY < Puzzle::Config::CardSize &&
if (offsetX >= 0 && offsetX < Puzzle::Config::CardSize && offsetY >= 0 && IsValid(card.RefCard))
offsetY < Puzzle::Config::CardSize)
{ {
PuzzleElementType::Enum cardVal = GetCardNodeAt(GetCard(card.RefCard), card.Rotation, offsetX, offsetY); PuzzleElementType::Enum cardVal = GetCardNodeAt(GetCard(card.RefCard), card.Rotation, offsetX, offsetY);
if (cardVal != PuzzleElementType::None) return cardVal; if (cardVal != PuzzleElementType::None) return cardVal;
} }
} return puz.BackgroundTiles[pos.Y * Puzzle::Config::MaxPuzzleSizeTiles + pos.X];
return puz.BackgroundTiles[pos.Y * Puzzle::Config::MaxPuzzleSizeCards + pos.X];
} }
PuzzleElementType::Enum GetCardNodeAt(const StaticPuzzleCard& card, uint8_t rotation, int8_t x, int8_t y) 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); 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 RenderDebugUI(PuzzleData& obj)
{ {
bool dataChanged = false; bool dataChanged = false;
uint8_t debugRot = Game::GetInstance().DebugData.DebugCardRotation;
bool isVisible = true; bool isVisible = true;
if (ImGui::Begin("Puzzle", &isVisible)) if (ImGui::Begin("Puzzle", &isVisible))
@@ -327,14 +379,61 @@ namespace Puzzle
ImGui::SetCursorScreenPos(pos); ImGui::SetCursorScreenPos(pos);
if (x % Puzzle::Config::CardSize == 0 && y % Puzzle::Config::CardSize == 0) 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}); 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 (ImGui::BeginDragDropTarget())
{ {
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("cardtype", 0)) if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("cardtype", 0))
{ {
uint32_t CardIdx = *reinterpret_cast<uint32_t*>(payload->Data); uint32_t CardIdx = *reinterpret_cast<uint32_t*>(payload->Data);
obj.PlacedCards[obj.PlacedCardCount].RefCard = {(uint16_t)CardIdx}; placedCard = {};
obj.PlacedCardCount++; 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(); ImGui::EndDragDropTarget();
} }
@@ -401,17 +500,42 @@ namespace Puzzle
} }
if (bAvailOpen) if (bAvailOpen)
{ {
uint8_t debugRot = Game::GetInstance().DebugData.DebugCardRotation; ImVec2 startPos = ImGui::GetCursorScreenPos();
for (uint32_t i = 0; i < obj.AvailableCardCount; ++i) 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]; auto& card = obj.AvailableCards[i];
DrawCard(GetCard(card.RefCard), debugRot, ImGui::GetCursorScreenPos()); 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)); ImGui::SetDragDropPayload("availcard", &i, sizeof(i));
DrawCard(GetCard(card.RefCard), debugRot, ImGui::GetCursorScreenPos()); DrawCard(GetCard(card.RefCard), debugRot, ImGui::GetCursorScreenPos());
ImGui::EndDragDropSource(); 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(); ImGui::TreePop();
} }

View File

@@ -22,6 +22,7 @@ namespace Puzzle
static constexpr uint32_t MaxTilesInPuzzle = MaxPuzzleSizeTiles * MaxPuzzleSizeTiles; static constexpr uint32_t MaxTilesInPuzzle = MaxPuzzleSizeTiles * MaxPuzzleSizeTiles;
static constexpr uint32_t MaxAvailableStacks = 16; static constexpr uint32_t MaxAvailableStacks = 16;
static constexpr uint32_t MaxGoalPositions = 16; static constexpr uint32_t MaxGoalPositions = 16;
static constexpr float CardScaleWorld = 10.0f;
}; };
void Setup(); void Setup();

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -48,10 +48,10 @@ enum PuzzleElementType(u8)
{ {
None GameName("Empty") ShortName(" ") None GameName("Empty") ShortName(" ")
WaterIn GameName("Water Source") ShortName("~+") WaterIn GameName("Water Source") ShortName("~+")
WaterGoal GameName("Water Goal") ShortName("~-") WaterGoal GameName("Water Goal") ShortName("~!")
WaterChannel GameName("Water Channel") ShortName("~") WaterChannel GameName("Water Channel") ShortName("~")
ElectricIn GameName("Electricity Source") ShortName("e+") ElectricIn GameName("Electricity Source") ShortName("e+")
ElectricGoal GameName("Electricity Goal") ShortName("e-") ElectricGoal GameName("Electricity Goal") ShortName("e!")
Blocked GameName("Blocked") ShortName("B") Blocked GameName("Blocked") ShortName("B")
Bridge GameName("Bridge") ShortName("#") Bridge GameName("Bridge") ShortName("#")
} }

View File

@@ -32,7 +32,7 @@ vec3 desaturate(vec3 color)
float dither(float brightness, vec2 inputUv) float dither(float brightness, vec2 inputUv)
{ {
float globalScale = 8.0; float globalScale = 8;
// constants // constants
float xRes = u_texInfo.z; 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 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); contrast *= pow(freq.y / freq.x, 1.0);
float baseVal = lerp(0.5, brightness, saturate(1.05 / (1 + contrast))); float baseVal = lerp(0.5, brightness, saturate(1.05 / (1 + contrast)));
float threshold = 1 - brightnessCurve + 0.6; float threshold = 1 - brightnessCurve + 0.6;

View File

@@ -44,10 +44,10 @@ namespace Generated
{ {
" ", " ",
"~+", "~+",
"~-", "~!",
"~", "~",
"e+", "e+",
"e-", "e!",
"B", "B",
"#", "#",
}; };

Binary file not shown.

BIN
src/models/w corner bridge.glb LFS Normal file

Binary file not shown.

Binary file not shown.

BIN
src/models/w+ corner short.glb LFS Normal file

Binary file not shown.