card dragging

This commit is contained in:
Asuro
2025-03-30 03:00:23 +02:00
parent e5076b0c3b
commit b006d14197
6 changed files with 76 additions and 48 deletions

View File

@@ -334,10 +334,9 @@ namespace Game
boardTransform.Rotation = camTransform.Rotation; boardTransform.Rotation = camTransform.Rotation;
Vec3 fw = {camTransform.M.M[8], camTransform.M.M[9], camTransform.M.M[10]}; Vec3 fw = {camTransform.M.M[8], camTransform.M.M[9], camTransform.M.M[10]};
Vec3 pos = cameraPos; Vec3 pos = cameraPos;
pos += fw * 10.0f; pos += fw * 1.0f;
boardTransform.SetPosition(pos); boardTransform.SetPosition(pos);
bool clicked = GetMouseButtonPressedNow(MouseButton::Left);
Vec2 mousePos = GetMousePos(); Vec2 mousePos = GetMousePos();
mousePos.x = mousePos.x / window.WindowWidth; mousePos.x = mousePos.x / window.WindowWidth;
mousePos.y = mousePos.y / window.WindowHeight; mousePos.y = mousePos.y / window.WindowHeight;
@@ -362,70 +361,90 @@ namespace Game
auto& tile = level.PuzzleTiles.Get(TileHandles[cardIdx]); auto& tile = level.PuzzleTiles.Get(TileHandles[cardIdx]);
auto& quad = level.UIQuads.Get(UIPlacedCards[cardIdx]); auto& quad = level.UIQuads.Get(UIPlacedCards[cardIdx]);
bool IsValid = Puzzle::IsValid(card.RefCard); bool isValid = Puzzle::IsValid(card.RefCard);
tile.EData.Visible = true; tile.EData.Visible = true;
tile.EData.ModelH = IsValid ? staticCards[card.RefCard.Idx].ModelHandle : staticCards[0].ModelHandle; tile.EData.ModelH = isValid ? staticCards[card.RefCard.Idx].ModelHandle : staticCards[0].ModelHandle;
Vec3 cardPos = { Vec3 cardPos = {
(float)card.Position.X * Puzzle::Config::CardScaleWorld, (float)card.Position.X * Puzzle::Config::CardScaleWorld,
-5.0f, -5.0f,
(float)card.Position.Y * Puzzle::Config::CardScaleWorld, (float)card.Position.Y * Puzzle::Config::CardScaleWorld,
}; };
if (!IsValid) if (!isValid)
{ {
cardPos = {x * Puzzle::Config::CardScaleWorld, -5.0f, y * Puzzle::Config::CardScaleWorld}; cardPos = {x * Puzzle::Config::CardScaleWorld, -5.0f, y * Puzzle::Config::CardScaleWorld};
} }
tile.EData.Transform.SetPosition(cardPos); tile.EData.Transform.SetPosition(cardPos);
bx::mtxRotateY(tile.EData.Transform.Rotation.M, card.Rotation * bx::kPi * 0.5f); bx::mtxRotateY(tile.EData.Transform.Rotation.M, card.Rotation * bx::kPi * 0.5f);
quad.EData.Visible = IsValid; quad.EData.Visible = isValid;
quad.EData.TextureHandle = quad.EData.TextureHandle =
IsValid ? staticCards[card.RefCard.Idx].BoardTextureHandle : Generated::TextureHandle{}; isValid ? staticCards[card.RefCard.Idx].BoardTextureHandle : Generated::TextureHandle{};
quad.EData.Transform = boardTransform; quad.EData.Transform = boardTransform;
quad.EData.Transform.TranslateLocal(Vec3{(float)card.Position.X, (float)card.Position.Y, 0.0f} * 3.0f); quad.EData.Transform.TranslateLocal(Vec3{(float)card.Position.X, (float)card.Position.Y, 0.0f} *
quad.EData.Transform.Scale = {1.0f, 1.0f, 1.0f}; UICardOffset);
// quad.EData.Transform.Scale = {0.1f, 0.1f, 0.1f}; quad.EData.Transform.Scale = {0.1f, 0.1f, 0.1f};
quad.EData.Transform.Rotate(Vec3{bx::kPi * 0.5f, 0.0f, bx::kPi}); quad.EData.Transform.Rotate(Vec3{bx::kPi * 0.5f, 0.0f, (1.0f + card.Rotation * 0.5f) * bx::kPi});
if (clicked && IsValid) Vec3 quadPosWorld = quad.EData.Transform.GetPosition();
Vec3 quadXWorld = quad.EData.Transform.LocalToGlobalPoint({1, 0, 0});
Vec3 quadZWorld = quad.EData.Transform.LocalToGlobalPoint({0, 0, 1});
Vec3 intersectPos;
if (RayPlaneIntersect(
camTransform.GetPosition(), mousePosWorld, quadPosWorld, quadXWorld, quadZWorld, intersectPos))
{ {
Vec3 quadPosWorld = quad.EData.Transform.GetPosition(); Vec3 quadSpaceIntersect = quad.EData.Transform.GlobalToLocalPoint(intersectPos);
Vec3 quadXWorld = quad.EData.Transform.LocalToGlobalPoint({1, 0, 0}); if (quadSpaceIntersect.x >= -1.0f && quadSpaceIntersect.x <= 1.0f &&
Vec3 quadYWorld = quad.EData.Transform.LocalToGlobalPoint({0, 0, 1}); quadSpaceIntersect.z >= -1.0f && quadSpaceIntersect.z <= 1.0f)
Vec3 intersectPos;
if (RayPlaneIntersect(camTransform.GetPosition(),
mousePosWorld,
quadPosWorld,
quadXWorld,
quadYWorld,
intersectPos))
{ {
Vec3 quadSpaceIntersect = quad.EData.Transform.GlobalToLocalPoint(intersectPos); if (isValid && !card.IsLocked && DraggedCard.X == -1 &&
if (quadSpaceIntersect.x >= -1.0f && quadSpaceIntersect.x <= 1.0f && GetMouseButtonPressedNow(MouseButton::Left))
quadSpaceIntersect.z >= -1.0f && quadSpaceIntersect.z <= 1.0f)
{ {
// LOG("---"); DraggedCard.X = x;
// LOG("%.03f %.03f: Click", mousePos.x, mousePos.y); DraggedCard.Y = y;
// LOG("%.03f %.03f %.03f: MouseCam", mousePosCam.x, mousePosCam.y, mousePosCam.z);
// LOG("%.03f %.03f %.03f: MouseWorld", mousePosWorld.x, mousePosWorld.y, mousePosWorld.z);
// LOG("%.03f %.03f %.03f: Player",
// camTransform.Position.x,
// camTransform.Position.y,
// camTransform.Position.z);
// LOG("%.03f %.03f %.03f: QuadWorld", quadPosWorld.x, quadPosWorld.y, quadPosWorld.z);
// LOG("%.03f %.03f %.03f: QuadX", quadXWorld.x, quadXWorld.y, quadXWorld.z);
// LOG("%.03f %.03f %.03f: QuadY", quadYWorld.x, quadYWorld.y, quadYWorld.z);
// LOG("%.03f %.03f %.03f: Intersect", intersectPos.x, intersectPos.y, intersectPos.z);
// LOG("%.03f %.03f %.03f: IntersectQ",
// quadSpaceIntersect.x,
// quadSpaceIntersect.y,
// quadSpaceIntersect.z);
LOG("Clicked %u %u", x, y);
} }
} }
} }
if (DraggedCard.X == x && DraggedCard.Y == y)
{
Vec3 dragPos = intersectPos;
dragPos -= fw * 0.01f;
quad.EData.Transform.SetPosition(dragPos);
Vec3 boardPos = boardTransform.GlobalToLocalPoint(intersectPos);
Vec3 boardTilePos = boardPos / UICardOffset;
int32_t xPos = (int32_t)bx::round(boardTilePos.x);
int32_t yPos = (int32_t)bx::round(boardTilePos.y);
Generated::PuzPos srcCardPos = {(int8_t)DraggedCard.X, (int8_t)DraggedCard.Y};
Generated::PlacedPuzzleCard& srcCard =
Data.PlacedCards[srcCardPos.Y * Puzzle::Config::MaxPuzzleSizeCards + srcCardPos.X];
if (GetMouseButtonPressedNow(MouseButton::Right))
{
srcCard.Rotation += 1;
if (srcCard.Rotation >= 4) srcCard.Rotation = 0;
}
if (!GetMouseButton(MouseButton::Left))
{
Generated::PuzPos targetCardPos = {(int8_t)xPos, (int8_t)yPos};
if (xPos >= 0 && xPos < Data.WidthTiles / Puzzle::Config::CardSize && yPos >= 0 &&
yPos < Data.HeightTiles / Puzzle::Config::CardSize)
{
Generated::PlacedPuzzleCard& targetCard =
Data.PlacedCards[yPos * Puzzle::Config::MaxPuzzleSizeCards + xPos];
bool canBeReplaced = !Puzzle::IsValid(targetCard.RefCard) || targetCard.RefCard.Idx == 0;
if (canBeReplaced && Puzzle::ReturnPlacedCard(Data, srcCardPos))
{
Puzzle::DragAvailableCardTo(Data, targetCardPos, 0, srcCard.Rotation);
}
}
DraggedCard.X = -1;
DraggedCard.Y = -1;
}
}
} }
} }
} }

View File

@@ -136,10 +136,12 @@ namespace Game
struct WorldPuzzle struct WorldPuzzle
{ {
static constexpr Vec2 WorldCardSize{10.0f, 10.0f}; static constexpr Vec2 WorldCardSize{10.0f, 10.0f};
static constexpr float UICardOffset = 0.21f;
Generated::PuzzleData Data; Generated::PuzzleData Data;
Vec3 WorldPosition; Vec3 WorldPosition;
PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle]; PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle];
UIQuadEntityHandle UIPlacedCards[Puzzle::Config::MaxCardsInPuzzle]; UIQuadEntityHandle UIPlacedCards[Puzzle::Config::MaxCardsInPuzzle];
Generated::PuzPos DraggedCard{-1, -1};
bool IsSetup = false; bool IsSetup = false;
void Setup(); void Setup();

View File

@@ -277,13 +277,16 @@ 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) bool ReturnPlacedCard(PuzzleData& obj, PuzPos targetPos)
{ {
auto& placedCard = obj.PlacedCards[targetPos.Y * Config::MaxPuzzleSizeCards + targetPos.X]; auto& placedCard = obj.PlacedCards[targetPos.Y * Config::MaxPuzzleSizeCards + targetPos.X];
if (IsValid(placedCard.RefCard)) if (IsValid(placedCard.RefCard))
{ {
if (placedCard.IsLocked) return false; if (placedCard.IsLocked)
{
LOG_WARN("Card at %i %i is locked!", targetPos.X, targetPos.Y);
return false;
}
bool found = false; bool found = false;
for (int32_t i = 0; i < obj.AvailableCardCount; ++i) for (int32_t i = 0; i < obj.AvailableCardCount; ++i)
{ {
@@ -304,7 +307,6 @@ namespace Puzzle
return true; return true;
} }
// TODO: targetPos is of type CardPos
bool DragAvailableCardTo(PuzzleData& obj, PuzPos targetPos, int32_t availIdx, uint8_t rotation) bool DragAvailableCardTo(PuzzleData& obj, PuzPos targetPos, int32_t availIdx, uint8_t rotation)
{ {
if (availIdx >= obj.AvailableCardCount) if (availIdx >= obj.AvailableCardCount)

View File

@@ -2,7 +2,7 @@
#include <cstdint> #include <cstdint>
#include <imgui.h> #include <imgui.h>
#include "Gen.h" #include "Gen.h" // IWYU pragma: keep
namespace Puzzle namespace Puzzle
{ {
@@ -36,6 +36,11 @@ namespace Puzzle
PuzzleElementType::Enum& EditCardNodeAt(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 DrawCard(const StaticPuzzleCard& card, uint8_t rotation, ImVec2 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);
struct PuzzleSolver struct PuzzleSolver
{ {
bool IsPuzzleSolved(const Generated::PuzzleData& puzzle); bool IsPuzzleSolved(const Generated::PuzzleData& puzzle);

View File

@@ -6,7 +6,7 @@
#include "../Tools.h" #include "../Tools.h"
#include "Rendering.h" #include "Rendering.h"
#include "SDL3/SDL_events.h" #include "SDL3/SDL_events.h" // IWYU pragma: keep
#include "backends/imgui_impl_sdl3.h" #include "backends/imgui_impl_sdl3.h"
#include "bgfx/defines.h" #include "bgfx/defines.h"
#include "bx/bx.h" #include "bx/bx.h"

View File

@@ -4,7 +4,7 @@
#include <bx/string.h> #include <bx/string.h>
#include <cstdint> #include <cstdint>
#include "../Gen.h" #include "../Gen.h" // IWYU pragma: keep
#include "../Global.h" #include "../Global.h"
#include "Dither.h" #include "Dither.h"