Compare commits

..

2 Commits

Author SHA1 Message Date
Asuro
155339917d static puzzle data! 2025-03-13 00:41:38 +01:00
Asuro
f3f994fd8b add hashes 2025-03-12 22:29:52 +01:00
21 changed files with 368 additions and 145 deletions

View File

@@ -26,9 +26,10 @@ namespace Generated
{ {
)END"; )END";
constexpr char StructHeader1[] = constexpr char StructHeader2[] =
R"END( struct %s R"END( struct %s
{ {
static constexpr uint32_t Hash = %u;
)END"; )END";
constexpr char StructField4[] = constexpr char StructField4[] =
@@ -39,9 +40,10 @@ namespace Generated
R"END( }; R"END( };
)END"; )END";
constexpr char EnumHeader3[] = constexpr char EnumHeader4[] =
R"END( struct %s R"END( struct %s
{ {
static constexpr uint32_t Hash = %u;
static constexpr int32_t EntryCount = %u; static constexpr int32_t EntryCount = %u;
enum Enum : %s enum Enum : %s
{ {
@@ -100,7 +102,7 @@ namespace Generated
)END"; )END";
constexpr char LoadFuncBodyType3[] = R"END( isOk = Load(%sobj[i].%s, %u, serializer) && isOk; constexpr char LoadFuncBodyType3[] = R"END( isOk = Load(%sobj[i].%s, %u, serializer) && isOk;
)END"; )END";
constexpr char LoadFuncBodyEnum1[] = R"END( auto val = (%s)obj[i]; constexpr char LoadFuncBodyEnum2[] = R"END( %s& val = (%s&)obj[i];
isOk = Load(&val, 1, serializer) && isOk; isOk = Load(&val, 1, serializer) && isOk;
)END"; )END";
constexpr char LoadFuncBodyEnd[] = R"END( } constexpr char LoadFuncBodyEnd[] = R"END( }
@@ -192,8 +194,11 @@ void CppFileWriter::WriteEnums(const Def::DefinitionFile& definitions)
{ {
const Def::Enum& e = definitions.Enums[enumIdx]; const Def::Enum& e = definitions.Enums[enumIdx];
Write( Write(WriteTemplates::EnumHeader4,
WriteTemplates::EnumHeader3, e.Name, e.EntryCount, Generated::KnownType::CName[(int32_t)e.EnumType.Native]); e.Name,
e.Hash,
e.EntryCount,
Generated::KnownType::CName[(int32_t)e.EnumType.Native]);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx) for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{ {
Write(WriteTemplates::EnumField1, e.EntryNames[entryIdx]); Write(WriteTemplates::EnumField1, e.EntryNames[entryIdx]);
@@ -223,7 +228,7 @@ void CppFileWriter::WriteTypes(const Def::DefinitionFile& definitions)
{ {
const Def::Type& t = definitions.Types[typeIdx]; const Def::Type& t = definitions.Types[typeIdx];
Write(WriteTemplates::StructHeader1, t.Name); Write(WriteTemplates::StructHeader2, t.Name, t.Hash);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx) for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{ {
char Type[64]{0}; char Type[64]{0};
@@ -234,7 +239,7 @@ void CppFileWriter::WriteTypes(const Def::DefinitionFile& definitions)
{ {
bx::snprintf(Array, sizeof(Array), "[%u]", ArraySize); bx::snprintf(Array, sizeof(Array), "[%u]", ArraySize);
} }
Write(WriteTemplates::StructField4, Type, t.FieldNames[fieldIdx], Array, t.FieldVaules[fieldIdx]); Write(WriteTemplates::StructField4, Type, t.FieldNames[fieldIdx], Array, t.FieldValues[fieldIdx]);
} }
Write(WriteTemplates::StructEnd); Write(WriteTemplates::StructEnd);
} }
@@ -257,7 +262,7 @@ void CppFileWriter::WriteSaveLoadMethods(const Def::DefinitionFile& definitions)
WriteCpp(WriteTemplates::SaveFuncBodyEnd); WriteCpp(WriteTemplates::SaveFuncBodyEnd);
WriteCpp(WriteTemplates::LoadFuncBodyStart1, nameBuf); WriteCpp(WriteTemplates::LoadFuncBodyStart1, nameBuf);
WriteCpp(WriteTemplates::LoadFuncBodyEnum1, fieldBuf); WriteCpp(WriteTemplates::LoadFuncBodyEnum2, fieldBuf, fieldBuf);
WriteCpp(WriteTemplates::LoadFuncBodyEnd); WriteCpp(WriteTemplates::LoadFuncBodyEnd);
} }
for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx) for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx)

View File

@@ -3,6 +3,8 @@
#include "Logging.h" #include "Logging.h"
#include "MiniDef.h" #include "MiniDef.h"
#include "TypeDef.h"
#include "bx/hash.h"
#include "bx/string.h" #include "bx/string.h"
#include <bx/filepath.h> #include <bx/filepath.h>
#include <ctype.h> #include <ctype.h>
@@ -165,7 +167,7 @@ Parser::Result Parser::HandleType()
Def::Type& t = Definitions.Types[Definitions.TypeCount]; Def::Type& t = Definitions.Types[Definitions.TypeCount];
for (int32_t i = 0; i < Def::MaxFields; ++i) for (int32_t i = 0; i < Def::MaxFields; ++i)
{ {
bx::strCopy(t.FieldVaules[i], sizeof(t.FieldVaules[i]), "{}"); bx::strCopy(t.FieldValues[i], sizeof(t.FieldValues[i]), "{}");
} }
CHECK(ReadName(t.Name)); CHECK(ReadName(t.Name));
@@ -203,11 +205,11 @@ Parser::Result Parser::HandleType()
CHECK(ExpectChar("(")); CHECK(ExpectChar("("));
CHECK(ExpectChar("\"")); CHECK(ExpectChar("\""));
int32_t Remaining = bx::min(GetRemaining(), (int32_t)BX_COUNTOF(Def::Type::FieldVaules[0])); int32_t Remaining = bx::min(GetRemaining(), (int32_t)BX_COUNTOF(Def::Type::FieldValues[0]));
for (int32_t i = 0; i < Remaining; ++i) for (int32_t i = 0; i < Remaining; ++i)
{ {
if (*ReadPtr != '\\' && CmpAdvance("\"", Res)) break; if (*ReadPtr != '\\' && CmpAdvance("\"", Res)) break;
t.FieldVaules[t.FieldCount][i] = *ReadPtr; t.FieldValues[t.FieldCount][i] = *ReadPtr;
ReadPtr++; ReadPtr++;
} }
if (Res != OK) return Res; if (Res != OK) return Res;
@@ -404,7 +406,7 @@ Parser::Result Parser::ReadOptionalEnumValues(Def::Enum& Enum, int32_t EntryIdx)
for (int32_t i = 0; i < Remaining; ++i) for (int32_t i = 0; i < Remaining; ++i)
{ {
if (CmpAdvance("\"", Res)) break; if (CmpAdvance("\"", Res)) break;
Enum.ExtraStringFields[extraIdx][EntryIdx][i] = *ReadPtr; Enum.ExtraStringFields[EntryIdx][extraIdx][i] = *ReadPtr;
ReadPtr++; ReadPtr++;
} }
if (Res != OK) return Res; if (Res != OK) return Res;
@@ -425,6 +427,59 @@ int32_t Parser::GetRemaining()
{ {
return &Buffer[BufferSize] - ReadPtr; return &Buffer[BufferSize] - ReadPtr;
} }
uint32_t Parser::CalculateTypeHash(const Def::Type& t)
{
bx::HashMurmur2A hash;
hash.begin();
for (int32_t i = 0; i < t.FieldCount; ++i)
{
hash.add(t.FieldNames[i]);
hash.add(t.FieldArraySizes[i]);
Def::EFieldType fieldType = t.FieldTypes[i].FieldKind;
if (fieldType == Def::EFieldType::Native)
{
hash.add(t.FieldTypes[i].Native);
}
else if (fieldType == Def::EFieldType::DefinedClass)
{
Def::Type& dependType = Definitions.Types[t.FieldTypes[i].TypeIdx];
if (dependType.Hash == 0)
{
CalculateTypeHash(dependType);
}
hash.add(dependType.Hash);
}
else if (fieldType == Def::EFieldType::DefinedEnum)
{
hash.add(Definitions.Enums[t.FieldTypes[i].TypeIdx].Hash);
}
else
{
LOG_ERROR(0, "TODO!");
}
}
return hash.end();
}
void Parser::CalculateHashes()
{
for (int32_t i = 0; i < Definitions.EnumCount; ++i)
{
Def::Enum& e = Definitions.Enums[i];
bx::HashMurmur2A hash;
hash.begin();
hash.add(e.EnumType.Native);
e.Hash = hash.end();
}
for (int32_t i = 0; i < Definitions.TypeCount; ++i)
{
Def::Type& t = Definitions.Types[i];
if (t.Hash == 0)
{
t.Hash = CalculateTypeHash(t);
}
}
}
Parser FileParser; Parser FileParser;
CppFileWriter Writer; CppFileWriter Writer;
@@ -460,6 +515,8 @@ int main(int argc, const char** argv)
return 1; return 1;
} }
LOG(0, "Finished parsing!"); LOG(0, "Finished parsing!");
FileParser.CalculateHashes();
Writer.GenerateCpp(outPath, FileParser.Definitions); Writer.GenerateCpp(outPath, FileParser.Definitions);
return 0; return 0;

View File

@@ -76,6 +76,7 @@ class Parser
public: public:
Result Parse(); Result Parse();
void CalculateHashes();
private: private:
int32_t GetRemaining(); int32_t GetRemaining();
@@ -94,6 +95,8 @@ class Parser
Result ReadTypeToken(); Result ReadTypeToken();
Result ReadOptionalEnumValues(Def::Enum& Enum, int32_t EntryIdx); Result ReadOptionalEnumValues(Def::Enum& Enum, int32_t EntryIdx);
uint32_t CalculateTypeHash(const Def::Type& t);
void ErrorLine() void ErrorLine()
{ {
char line[64]{0}; char line[64]{0};

View File

@@ -6,7 +6,7 @@ namespace Def
{ {
constexpr int32_t MaxNameLength = 64; constexpr int32_t MaxNameLength = 64;
constexpr int32_t MaxFields = 64; constexpr int32_t MaxFields = 64;
constexpr int32_t MaxExtraEnumFields = 1; constexpr int32_t MaxExtraEnumFields = 2;
enum class EFieldType enum class EFieldType
{ {
Native, Native,
@@ -26,8 +26,9 @@ namespace Def
FieldType FieldTypes[MaxFields]; FieldType FieldTypes[MaxFields];
char FieldNames[MaxFields][MaxNameLength]; char FieldNames[MaxFields][MaxNameLength];
uint32_t FieldArraySizes[MaxFields]{0}; uint32_t FieldArraySizes[MaxFields]{0};
char FieldVaules[MaxFields][128]{0}; char FieldValues[MaxFields][128]{0};
char Name[MaxNameLength]{0}; char Name[MaxNameLength]{0};
uint32_t Hash = 0;
}; };
struct Enum struct Enum
@@ -39,6 +40,7 @@ namespace Def
char ExtraStringFieldNames[MaxExtraEnumFields][MaxNameLength]; char ExtraStringFieldNames[MaxExtraEnumFields][MaxNameLength];
char ExtraStringFields[MaxFields][MaxExtraEnumFields][MaxNameLength]; char ExtraStringFields[MaxFields][MaxExtraEnumFields][MaxNameLength];
char Name[MaxNameLength]{0}; char Name[MaxNameLength]{0};
uint32_t Hash = 0;
}; };
struct DefinitionFile struct DefinitionFile

View File

@@ -43,6 +43,10 @@ namespace Game
uint16_t SelectedDebugLevel = UINT16_MAX; uint16_t SelectedDebugLevel = UINT16_MAX;
uint64_t ImguiIniSize = 0; uint64_t ImguiIniSize = 0;
char ImguiIni[4096]{0}; char ImguiIni[4096]{0};
static constexpr uint32_t MaxAssets = 128;
uint32_t AssetCount = 0;
uint32_t AssetHandles[MaxAssets]{0};
char AssetHandlePaths[MaxAssets][128];
}; };
struct GameInstance struct GameInstance

View File

@@ -74,7 +74,7 @@ namespace Game
needReset |= PuzzleTiles.Setup(storagePtr, needReset); needReset |= PuzzleTiles.Setup(storagePtr, needReset);
needReset |= UIQuads.Setup(storagePtr, needReset); needReset |= UIQuads.Setup(storagePtr, needReset);
Generated::Setup(PuzzleData); Generated::Setup();
bx::Error err; bx::Error err;
bx::DirectoryReader dirIter; bx::DirectoryReader dirIter;

View File

@@ -1,3 +1,4 @@
#include "Global.h"
#include "Log.h" #include "Log.h"
#include "Mesh.h" #include "Mesh.h"
#include "bx/bx.h" #include "bx/bx.h"
@@ -8,6 +9,8 @@
#include "bx/string.h" #include "bx/string.h"
#include "rendering/Rendering.h" #include "rendering/Rendering.h"
#include "Instance.h"
#define TINYGLTF_IMPLEMENTATION #define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION
@@ -139,6 +142,15 @@ namespace Game
if (LoadMesh(mod, fullPath.getCPtr(), modelFileIsBinary[i])) if (LoadMesh(mod, fullPath.getCPtr(), modelFileIsBinary[i]))
{ {
mod.AssetHandle = CrcPath(fullPath.getCPtr()); mod.AssetHandle = CrcPath(fullPath.getCPtr());
auto& inst = GetInstance();
if (inst.DebugData.AssetCount < inst.DebugData.MaxAssets)
{
inst.DebugData.AssetHandles[inst.DebugData.AssetCount] = mod.AssetHandle;
bx::strCopy(inst.DebugData.AssetHandlePaths[inst.DebugData.AssetCount],
sizeof(inst.DebugData.AssetHandlePaths[inst.DebugData.AssetCount]),
fullPath.getCPtr());
++inst.DebugData.AssetCount;
}
++writeI; ++writeI;
} }
else else

View File

@@ -1,10 +1,9 @@
#include "Log.h" #include "Log.h"
#include "Puzzle.h" #include "Puzzle.h"
#include "bx/string.h" #include "bx/string.h"
#include "imgui.h"
#include "rendering/Rendering.h"
#include "bx/bx.h" #include "bx/bx.h"
#include "imgui.h"
#include <cassert> #include <cassert>
namespace namespace
@@ -16,25 +15,43 @@ namespace
{1, 0}, {1, 0},
}; };
Generated::StaticPuzzleData* StaticDataInstance = nullptr; Generated::StaticPuzzleData StaticData;
} // namespace } // namespace
namespace Generated namespace Generated
{ {
void Setup(StaticPuzzleData& data) void Setup()
{ {
StaticDataInstance = &data;
LOG("Setting up static puzzle data"); LOG("Setting up static puzzle data");
for (int32_t i = 0; i < BX_COUNTOF(data.Cards); ++i) LoadStaticPuzzleData();
{
data.Cards[i].ModelHandle = Game::GameRendering::Get().GetModelHandleFromPath("models/w straight.glb");
}
} }
StaticPuzzleData& GetStaticPuzzleData() StaticPuzzleData& GetStaticPuzzleData()
{ {
assert(StaticDataInstance != nullptr); return StaticData;
return *StaticDataInstance; }
void LoadStaticPuzzleData()
{
Deserializer ser;
ser.Init("game/data/static/puzzle.dat");
if (ser.ReadT("SPUZ", StaticData))
{
LOG("Successfully loaded static puzzle data!");
}
ser.Finish();
}
void SaveStaticPuzzleData()
{
auto& data = GetStaticPuzzleData();
Serializer ser;
ser.Init("game/data/static/puzzle.dat");
if (ser.WriteT("SPUZ", GetStaticPuzzleData()))
{
LOG("Successfully saved static puzzle data!");
}
ser.Finish();
} }
const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H) const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H)
{ {
@@ -167,6 +184,18 @@ namespace Generated
namespace Generated namespace Generated
{ {
constexpr float UIPuzBoxSize = 26;
const char* GetShortNodeName(const PuzzleNode& node)
{
PuzzleElementType::Enum elemMax = PuzzleElementType::None;
for (int32_t i = 0; i < BX_COUNTOF(node.PlacedTypes); ++i)
{
if (node.PlacedTypes[i] > elemMax) elemMax = node.PlacedTypes[i];
}
return PuzzleElementType::ShortName[elemMax];
}
bool RenderDebugUI(PuzzleData& obj) bool RenderDebugUI(PuzzleData& obj)
{ {
bool dataChanged = false; bool dataChanged = false;
@@ -197,6 +226,47 @@ namespace Generated
dataChanged = true; dataChanged = true;
} }
ImGui::PopID(); ImGui::PopID();
ImVec2 puzCursorStart = ImGui::GetCursorScreenPos();
auto& drawList = *ImGui::GetWindowDrawList();
for (int32_t y = 0; y < obj.HeightTiles; ++y)
{
for (int32_t x = 0; x < obj.WidthTiles; ++x)
{
PuzzleNode& node = obj.PlacedNodes[Puzzle::Config::MaxPuzzleSizeTiles * y + x];
ImVec2 pos = ImVec2{puzCursorStart.x + x * UIPuzBoxSize + 5, puzCursorStart.y + y * UIPuzBoxSize};
ImGui::SetCursorScreenPos(pos);
ImGui::Text("%s", GetShortNodeName(node));
}
}
for (int32_t y = 0; y <= obj.HeightTiles; ++y)
{
ImVec2 linePos = {puzCursorStart.x, puzCursorStart.y + y * UIPuzBoxSize};
drawList.AddLine(linePos,
{linePos.x + obj.WidthTiles * UIPuzBoxSize, linePos.y},
y % Puzzle::Config::CardSize == 0 ? 0xFFFFFFFF : 0x11FFFFFF);
}
for (int32_t x = 0; x <= obj.WidthTiles; ++x)
{
ImVec2 linePos = {puzCursorStart.x + x * UIPuzBoxSize, puzCursorStart.y};
drawList.AddLine(linePos,
{linePos.x, linePos.y + obj.HeightTiles * UIPuzBoxSize},
x % Puzzle::Config::CardSize == 0 ? 0xFFFFFFFF : 0x11FFFFFF);
}
ImGui::Spacing();
ImGui::Spacing();
if (ImGui::TreeNodeEx("Available Cards", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
{
for (int32_t i = 0; i < obj.AvailableCardCount; ++i)
{
ImGui::Text("Card");
}
ImGui::TreePop();
}
} }
ImGui::End(); ImGui::End();

View File

@@ -18,112 +18,6 @@ namespace Puzzle
static constexpr uint32_t MaxAvailableStacks = 16; static constexpr uint32_t MaxAvailableStacks = 16;
static constexpr uint32_t MaxGoalPositions = 16; static constexpr uint32_t MaxGoalPositions = 16;
}; };
// struct PuzPos
// {
// int8_t X = 0;
// int8_t Y = 0;
// PuzPos& operator+=(const PuzPos& rhs)
// {
// X += rhs.X;
// Y += rhs.Y;
// return *this;
// }
// friend PuzPos operator+(PuzPos lhs, const PuzPos& rhs)
// {
// lhs += rhs;
// return lhs;
// }
// };
// struct ElemPos
// {
// PuzPos Position;
// uint8_t ElemIdx = 0;
// };
// enum class PuzzleElementType : uint8_t
// {
// None,
// WaterIn,
// WaterGoal,
// WaterChannel,
// ElectricIn,
// ElectricGoal,
// Blocked,
// Bridge,
// };
// struct PuzzleNode
// {
// PuzzleElementType PlacedTypes[Config::MaxElementsPerTile]{PuzzleElementType::None};
// bool HasElement(PuzzleElementType search) const;
// bool IsEmpty() const;
// };
// struct StaticPuzzleCard
// {
// PuzzleNode Nodes[Config::NodesPerCard];
// uint16_t ModelHandle = 0;
// };
// struct StaticPuzzleCardHandle
// {
// uint16_t Idx = UINT16_MAX;
// bool IsValid()
// {
// return Idx != UINT16_MAX;
// }
// };
// struct StaticPuzzleData
// {
// StaticPuzzleCard Cards[64];
// void Setup();
// static StaticPuzzleData& Get();
// const StaticPuzzleCard& GetCard(StaticPuzzleCardHandle H) const;
// };
// struct PlacedPuzzleCard
// {
// StaticPuzzleCardHandle RefCard;
// PuzPos Position;
// uint8_t Rotation = 0;
// bool IsLocked = false;
// };
// struct PuzzleCardStack
// {
// StaticPuzzleCardHandle RefCard;
// uint8_t MaxAvailableCount = 0;
// uint8_t UsedCount = 0;
// uint8_t GetRemainingCount();
// };
// struct PuzzleData
// {
// uint32_t AvailableCardCount = 0;
// PuzzleCardStack AvailableCards[Config::MaxAvailableStacks];
// uint32_t PlacedCardCount = 0;
// PlacedPuzzleCard PlacedCards[Config::MaxCardsInPuzzle];
// // Indexed by board position
// PuzzleNode PlacedNodes[Config::MaxTilesInPuzzle];
// uint32_t GoalPositionCount = 0;
// ElemPos GoalPositions[Config::MaxGoalPositions];
// const PuzzleNode& GetNodeAt(PuzPos pos) const;
// PuzzleElementType GetElementAt(ElemPos pos) const;
// char PuzzleName[32]{"Unnamed"};
// bool RenderDebugUI();
// };
} // namespace Puzzle } // namespace Puzzle
namespace Generated namespace Generated
@@ -131,8 +25,10 @@ namespace Generated
PuzPos operator+=(PuzPos lhs, const PuzPos& rhs); PuzPos operator+=(PuzPos lhs, const PuzPos& rhs);
PuzPos operator+(PuzPos lhs, const PuzPos& rhs); PuzPos operator+(PuzPos lhs, const PuzPos& rhs);
void Setup(StaticPuzzleData& data); void Setup();
StaticPuzzleData& GetStaticPuzzleData(); StaticPuzzleData& GetStaticPuzzleData();
void LoadStaticPuzzleData();
void SaveStaticPuzzleData();
const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H); const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H);
bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search); bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search);
bool IsEmpty(const PuzzleNode& node); bool IsEmpty(const PuzzleNode& node);

View File

@@ -48,6 +48,7 @@ namespace Game
instance.UsedScratchAmount = 0; instance.UsedScratchAmount = 0;
SetShared(shared); SetShared(shared);
SetInstance(instance); SetInstance(instance);
Generated::LoadStaticPuzzleData();
SetupInstance.Rendering.Setup(); SetupInstance.Rendering.Setup();
instance.GameLevel.Setup(shared.Game); instance.GameLevel.Setup(shared.Game);
instance.IsInitialized = true; instance.IsInitialized = true;

39
src/game/Tools.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "Global.h"
#include "Instance.h"
#include "Tools.h"
#include "rendering/Rendering.h"
#include <imgui.h>
namespace Tools
{
const char* GetAssetPath(uint32_t assetHandle)
{
const auto& inst = Game::GetInstance();
for (int32_t j = 0; j < inst.DebugData.AssetCount; ++j)
{
if (inst.DebugData.AssetHandles[j] == assetHandle)
{
return inst.DebugData.AssetHandlePaths[j];
}
}
return "---";
}
void ModelDropdown(uint16_t& modelHandle)
{
auto& R = Game::GameRendering::Get();
const char* name = GetAssetPath(R.Models[modelHandle].AssetHandle);
if (ImGui::BeginCombo("Models", name))
{
for (int32_t i = 0; i < R.ModelCount; ++i)
{
if (ImGui::Selectable(GetAssetPath(R.Models[i].AssetHandle), i == modelHandle))
{
modelHandle = i;
}
}
ImGui::EndCombo();
}
}
} // namespace Tools

7
src/game/Tools.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <cstdint>
namespace Tools
{
void ModelDropdown(uint16_t& modelHandle);
} // namespace Tools

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

View File

@@ -3,6 +3,7 @@
#include "../Instance.h" #include "../Instance.h"
#include "../Log.h" #include "../Log.h"
#include "../Mesh.h" #include "../Mesh.h"
#include "../Tools.h"
#include "Rendering.h" #include "Rendering.h"
#include "SDL3/SDL_events.h" #include "SDL3/SDL_events.h"
@@ -515,6 +516,8 @@ namespace Game
for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i)
{ {
auto& puzzleData = level.Puzzles[i].Data; auto& puzzleData = level.Puzzles[i].Data;
if (puzzleData.PuzzleName[0] == 0) continue;
bool isSelected = debug.SelectedDebugLevel == i; bool isSelected = debug.SelectedDebugLevel == i;
ImGui::PushID("selectable"); ImGui::PushID("selectable");
if (ImGui::Selectable(puzzleData.PuzzleName, isSelected)) if (ImGui::Selectable(puzzleData.PuzzleName, isSelected))
@@ -525,6 +528,7 @@ namespace Game
if (isSelected) if (isSelected)
{ {
ImGui::PushID("edit field"); ImGui::PushID("edit field");
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
ImGui::InputText("", puzzleData.PuzzleName, sizeof(Generated::PuzzleData::PuzzleName)); ImGui::InputText("", puzzleData.PuzzleName, sizeof(Generated::PuzzleData::PuzzleName));
ImGui::PopID(); ImGui::PopID();
@@ -536,6 +540,53 @@ namespace Game
} }
} }
ImGui::End(); ImGui::End();
if (ImGui::Begin("Cards"))
{
Generated::StaticPuzzleData& staticData = Generated::GetStaticPuzzleData();
if (ImGui::Button("Save"))
{
Generated::SaveStaticPuzzleData();
}
ImGui::SameLine();
if (ImGui::Button("Reload"))
{
Generated::LoadStaticPuzzleData();
}
for (int32_t i = 0; i < BX_COUNTOF(staticData.Cards); ++i)
{
ImGui::Separator();
Generated::StaticPuzzleCard& card = staticData.Cards[i];
ImGui::PushID(i);
ImGui::Text("%i", i);
Tools::ModelDropdown(card.ModelHandle);
for (int32_t y = 0; y < Puzzle::Config::CardSize; ++y)
{
ImGui::PushID(y);
for (int32_t x = 0; x < Puzzle::Config::CardSize; ++x)
{
if (x > 0) ImGui::SameLine();
ImGui::PushID(x);
auto& node = card.Nodes[y * Puzzle::Config::CardSize + x];
if (ImGui::Button(Generated::PuzzleElementType::ShortName[node.PlacedTypes[0]], {26, 24}))
{
int32_t newVal = int32_t(node.PlacedTypes[0]) + 1;
if (newVal >= Generated::PuzzleElementType::EntryCount)
{
newVal = 0;
}
node.PlacedTypes[0] = Generated::PuzzleElementType::Enum(newVal);
}
ImGui::PopID();
}
ImGui::PopID();
}
ImGui::PopID();
}
}
ImGui::End();
} }
GetInstance().GameLevel.Update(); GetInstance().GameLevel.Update();

View File

@@ -96,7 +96,7 @@ namespace Game
UIVisibilityState UIVisible = UIVisibilityState::Game; UIVisibilityState UIVisible = UIVisibilityState::Game;
DitherData DitherTextures; DitherData DitherTextures;
private: public:
bgfx::UniformHandle DefaultSampler; bgfx::UniformHandle DefaultSampler;
Texture Textures[8]; Texture Textures[8];
Material Materials[8]; Material Materials[8];

View File

@@ -1,4 +1,7 @@
#pragma once #pragma once
#include "../game/Log.h"
#include "bx/string.h"
#include <bx/file.h> #include <bx/file.h>
#include <cstdint> #include <cstdint>
@@ -17,9 +20,23 @@ namespace Generated
return Err.isOk(); return Err.isOk();
} }
template <typename T> bool WriteT(const char* _4cc, const T& data)
{
if (!Write(_4cc, 4)) return false;
uint32_t hash = data.Hash;
if (!Write(&hash, sizeof(hash))) return false;
uint32_t size = sizeof(T);
if (!Write(&size, sizeof(size))) return false;
return Save(&data, 1, *this);
}
bool Write(const void* data, uint32_t size) bool Write(const void* data, uint32_t size)
{ {
Writer.write(data, size, &Err); Writer.write(data, size, &Err);
if (!Err.isOk()) LOG_ERROR("Write error: %s", Err.getMessage().getCPtr());
return Err.isOk(); return Err.isOk();
} }
@@ -45,9 +62,47 @@ namespace Generated
bool Read(void* data, uint32_t size) bool Read(void* data, uint32_t size)
{ {
Reader.read(data, size, &Err); Reader.read(data, size, &Err);
if (!Err.isOk()) LOG_ERROR("Read error: %s", Err.getMessage().getCPtr());
return Err.isOk(); return Err.isOk();
} }
template <typename T> bool ReadT(const char* _4cc, T& data)
{
char magic[5]{0};
if (!Read(magic, 4)) return false;
bx::StringView given{_4cc, 4};
bx::StringView loaded{magic, 4};
if (bx::strCmp(given, loaded) != 0)
{
LOG_ERROR("Magic mismatch! %s != %s", _4cc, magic);
return false;
}
uint32_t hash = 0;
if (!Read(&hash, sizeof(hash))) return false;
if (data.Hash != hash)
{
LOG_ERROR("Hash mismatch! %u != %u", data.Hash, hash);
return false;
}
uint32_t size = 0;
if (!Read(&size, sizeof(size))) return false;
if (sizeof(T) != size)
{
LOG_ERROR("Size mismatch! %u != %u", sizeof(T), size);
return false;
}
if (!Load(&data, 1, *this))
{
LOG_ERROR("Failed to load: %s", Err.getMessage().getCPtr());
return false;
}
return true;
}
void Finish() void Finish()
{ {
Reader.close(); Reader.close();

View File

@@ -17,7 +17,7 @@ namespace Generated
bool isOk = true; bool isOk = true;
for (uint32_t i = 0; i < count; ++i) for (uint32_t i = 0; i < count; ++i)
{ {
auto val = (int32_t)obj[i]; int32_t& val = (int32_t&)obj[i];
isOk = Load(&val, 1, serializer) && isOk; isOk = Load(&val, 1, serializer) && isOk;
} }
return isOk; return isOk;

View File

@@ -5,6 +5,7 @@ namespace Generated
{ {
struct PuzzleElementType struct PuzzleElementType
{ {
static constexpr uint32_t Hash = 2024002654;
static constexpr int32_t EntryCount = 8; static constexpr int32_t EntryCount = 8;
enum Enum : int32_t enum Enum : int32_t
{ {
@@ -39,42 +40,61 @@ namespace Generated
"Blocked", "Blocked",
"Bridge", "Bridge",
}; };
static constexpr char ShortName[EntryCount][64]
{
" ",
"~+",
"~-",
"~",
"e+",
"e-",
"B",
"#",
};
}; };
struct PuzPos struct PuzPos
{ {
static constexpr uint32_t Hash = 1834398141;
int8_t X = {}; int8_t X = {};
int8_t Y = {}; int8_t Y = {};
}; };
struct ElemPos struct ElemPos
{ {
static constexpr uint32_t Hash = 3966109730;
PuzPos Position = {}; PuzPos Position = {};
uint8_t ElemIdx = {}; uint8_t ElemIdx = {};
}; };
struct PuzzleNode struct PuzzleNode
{ {
static constexpr uint32_t Hash = 1417779061;
PuzzleElementType::Enum PlacedTypes[4] = {}; PuzzleElementType::Enum PlacedTypes[4] = {};
}; };
struct StaticPuzzleCard struct StaticPuzzleCard
{ {
static constexpr uint32_t Hash = 110653106;
PuzzleNode Nodes[4] = {}; PuzzleNode Nodes[4] = {};
uint16_t ModelHandle = {}; uint16_t ModelHandle = {};
}; };
struct StaticPuzzleCardHandle struct StaticPuzzleCardHandle
{ {
static constexpr uint32_t Hash = 1742502768;
uint16_t Idx = UINT16_MAX; uint16_t Idx = UINT16_MAX;
}; };
struct StaticPuzzleData struct StaticPuzzleData
{ {
static constexpr uint32_t Hash = 1881743597;
StaticPuzzleCard Cards[64] = {}; StaticPuzzleCard Cards[64] = {};
}; };
struct PuzzleCardStack struct PuzzleCardStack
{ {
static constexpr uint32_t Hash = 53538532;
StaticPuzzleCardHandle RefCard = {}; StaticPuzzleCardHandle RefCard = {};
uint8_t MaxAvailableCount = {}; uint8_t MaxAvailableCount = {};
uint8_t UsedCount = {}; uint8_t UsedCount = {};
}; };
struct PlacedPuzzleCard struct PlacedPuzzleCard
{ {
static constexpr uint32_t Hash = 3555575973;
StaticPuzzleCardHandle RefCard = {}; StaticPuzzleCardHandle RefCard = {};
PuzPos Position = {}; PuzPos Position = {};
uint8_t Rotation = {}; uint8_t Rotation = {};
@@ -82,6 +102,7 @@ namespace Generated
}; };
struct PuzzleData struct PuzzleData
{ {
static constexpr uint32_t Hash = 2015691597;
uint8_t WidthTiles = {}; uint8_t WidthTiles = {};
uint8_t HeightTiles = {}; uint8_t HeightTiles = {};
uint32_t AvailableCardCount = {}; uint32_t AvailableCardCount = {};