diff --git a/src/dependency/minidef/src/CppGen.cpp b/src/dependency/minidef/src/CppGen.cpp index 103a8a3..aabb65b 100644 --- a/src/dependency/minidef/src/CppGen.cpp +++ b/src/dependency/minidef/src/CppGen.cpp @@ -1,8 +1,10 @@ #include "CppGen.h" #include "Logging.h" #include "TypeDef.h" +#include "bx/string.h" #include +#include #include #include @@ -11,10 +13,15 @@ namespace WriteTemplates { - constexpr char FileHeader[] = + constexpr char FileHeaderStart[] = R"END(#pragma once #include "Def.h" +namespace Generated +{ +)END"; + constexpr char FileCppStart[] = R"END(#include "Generated.h" + namespace Generated { )END"; @@ -36,7 +43,7 @@ namespace Generated R"END( struct %s { static constexpr int32_t EntryCount = %u; - enum class Enum : %s + enum Enum : %s { )END"; @@ -62,8 +69,77 @@ namespace Generated constexpr char FileEnd[] = R"END(} )END"; + + constexpr char SaveFuncHeader1[] = + R"END( bool Save(const %s* obj, uint32_t count, Serializer& serializer); +)END"; + constexpr char SaveFuncBodyStart1[] = R"END( bool Save(const %s* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { +)END"; + constexpr char SaveFuncBodyType3[] = R"END( isOk = Save(%sobj[i].%s, %u, serializer) && isOk; +)END"; + constexpr char SaveFuncBodyEnum1[] = R"END( auto val = (%s)obj[i]; + isOk = Save(&val, 1, serializer) && isOk; +)END"; + constexpr char SaveFuncBodyEnd[] = R"END( } + return isOk; + } +)END"; } // namespace WriteTemplates +void CppFileWriter::InitBuffer(WriteBuffer& buf) +{ + if (buf.Data != nullptr) + { + LOG_ERROR(0, "Multiple writes not supported yet!"); + return; + } + buf.Data = + reinterpret_cast(VirtualAlloc(nullptr, BufferRequestSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)); + if (buf.Data == nullptr) + { + LOG_ERROR(0, "Failed to allocate write memory!"); + return; + } + buf.WrittenBytes = 0; +} + +bool CppFileWriter::WriteBufferToDisk(const bx::FilePath& path, const WriteBuffer& buf) +{ + bx::Error error; + bx::FileWriter writer; + + LOG(0, "Writing to %s", path.getCPtr()); + if (!writer.open(path, false, &error)) + { + LOG_ERROR(0, "Failed to open output file: %s", error.getMessage().getCPtr()); + return false; + } + + writer.write(buf.Data, buf.WrittenBytes, &error); + if (!error.isOk()) + { + LOG_ERROR(0, "Failed to write to output file: %s", error.getMessage().getCPtr()); + } + writer.close(); + LOG(0, "Finished writing!"); + return true; +} + +void CppFileWriter::WriteInternal(WriteBuffer& buf, const char* templateStr, va_list args) +{ + if (buf.Data == nullptr) + { + LOG_ERROR(0, "Wrote too early!"); + return; + } + + buf.WrittenBytes += bx::vsnprintf(&buf.Data[buf.WrittenBytes], BufferRequestSize, templateStr, args); +} + void CppFileWriter::PrintTypeName(char* buf, int32_t bufSize, const Def::FieldType& type, @@ -87,6 +163,7 @@ void CppFileWriter::PrintTypeName(char* buf, else if (type.FieldKind == Def::EFieldType::DefinedEnum) { bx::strCopy(buf, bufSize, definitions.Enums[type.TypeIdx].Name); + bx::strCat(buf, bufSize, "::Enum"); } } @@ -143,64 +220,75 @@ void CppFileWriter::WriteTypes(const Def::DefinitionFile& definitions) Write(WriteTemplates::StructEnd); } } +void CppFileWriter::WriteSaveMethods(const Def::DefinitionFile& definitions) +{ + char buf[64]{0}; + for (int32_t enumIdx = 0; enumIdx < definitions.EnumCount; ++enumIdx) + { + const Def::Enum& e = definitions.Enums[enumIdx]; + bx::snprintf(buf, sizeof(buf), "%s::Enum", e.Name); + Write(WriteTemplates::SaveFuncHeader1, buf); + + WriteCpp(WriteTemplates::SaveFuncBodyStart1, buf); + PrintTypeName(buf, sizeof(buf), e.EnumType, definitions); + WriteCpp(WriteTemplates::SaveFuncBodyEnum1, buf); + WriteCpp(WriteTemplates::SaveFuncBodyEnd); + } + for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx) + { + const Def::Type& t = definitions.Types[typeIdx]; + Write(WriteTemplates::SaveFuncHeader1, t.Name); + + WriteCpp(WriteTemplates::SaveFuncBodyStart1, t.Name); + for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx) + { + WriteCpp(WriteTemplates::SaveFuncBodyType3, + t.FieldArraySizes[fieldIdx] > 0 ? "" : "&", + t.FieldNames[fieldIdx], + bx::max(1, t.FieldArraySizes[fieldIdx])); + } + WriteCpp(WriteTemplates::SaveFuncBodyEnd); + } +} +void CppFileWriter::WriteLoadMethods(const Def::DefinitionFile& definitions) +{ +} void CppFileWriter::GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions) { - LOG(0, "Generating..."); + LOG(0, "Generating output files..."); - // Allocate write buffer - if (FileWriteBuffer != nullptr) - { - LOG_ERROR(0, "Multiple writes not supported yet!"); - return; - } - FileWriteBuffer = - reinterpret_cast(VirtualAlloc(nullptr, BufferRequestSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)); - if (FileWriteBuffer == nullptr) - { - LOG_ERROR(0, "Failed to allocate write memory!"); - return; - } - FileWriterWritten = 0; + InitBuffer(HeaderWrite); + InitBuffer(CppWrite); - // Write text to buffer - Write(WriteTemplates::FileHeader); + Write(WriteTemplates::FileHeaderStart); + WriteCpp(WriteTemplates::FileCppStart); WriteEnums(definitions); WriteTypes(definitions); + WriteSaveMethods(definitions); Write(WriteTemplates::FileEnd); + WriteCpp(WriteTemplates::FileEnd); - // Write buffer to disk - bx::Error error; - bx::FileWriter writer; - bx::FilePath writePath = outDir; // std::filesystem::create_directory(outDir.getCPtr()); - writePath.join("Generated.h"); - - LOG(0, "Writing to %s", writePath.getCPtr()); - if (!writer.open(writePath, false, &error)) - { - LOG_ERROR(0, "Failed to open output file: %s", error.getMessage().getCPtr()); - return; - } - - writer.write(FileWriteBuffer, FileWriterWritten, &error); - if (!error.isOk()) - { - LOG_ERROR(0, "Failed to write to output file: %s", error.getMessage().getCPtr()); - } - writer.close(); - LOG(0, "Finished writing!"); + bx::FilePath writePathHeader = outDir; + bx::FilePath writePathCpp = outDir; + writePathHeader.join("Generated.h"); + writePathCpp.join("Generated.cpp"); + WriteBufferToDisk(writePathHeader, HeaderWrite); + WriteBufferToDisk(writePathCpp, CppWrite); } -void CppFileWriter::Write(const char* Template, ...) +void CppFileWriter::Write(const char* templateStr, ...) { - if (FileWriteBuffer == nullptr) - { - LOG_ERROR(0, "Wrote too early!"); - return; - } - - va_list ArgList; - va_start(ArgList, Template); - FileWriterWritten += bx::vsnprintf(&FileWriteBuffer[FileWriterWritten], BufferRequestSize, Template, ArgList); - va_end(ArgList); + va_list args; + va_start(args, templateStr); + WriteInternal(HeaderWrite, templateStr, args); + va_end(args); +} + +void CppFileWriter::WriteCpp(const char* templateStr, ...) +{ + va_list args; + va_start(args, templateStr); + WriteInternal(CppWrite, templateStr, args); + va_end(args); } diff --git a/src/dependency/minidef/src/CppGen.h b/src/dependency/minidef/src/CppGen.h index d4db0b8..e9572b6 100644 --- a/src/dependency/minidef/src/CppGen.h +++ b/src/dependency/minidef/src/CppGen.h @@ -4,17 +4,30 @@ #include "bx/filepath.h" +struct WriteBuffer +{ + char* Data = nullptr; + uint64_t WrittenBytes = 0; +}; + struct CppFileWriter { private: static constexpr size_t BufferRequestSize = 1024 * 1024 * 1024; - char* FileWriteBuffer = nullptr; - uint64_t FileWriterWritten = 0; + WriteBuffer HeaderWrite; + WriteBuffer CppWrite; + void InitBuffer(WriteBuffer& buf); + bool WriteBufferToDisk(const bx::FilePath& path, const WriteBuffer& buf); + void WriteInternal(WriteBuffer& buf, const char* templateStr, va_list args); public: void PrintTypeName(char* buf, int32_t bufSize, const Def::FieldType& type, const Def::DefinitionFile& definitions); void WriteEnums(const Def::DefinitionFile& definitions); void WriteTypes(const Def::DefinitionFile& definitions); + void WriteSaveMethods(const Def::DefinitionFile& definitions); + void WriteLoadMethods(const Def::DefinitionFile& definitions); + void GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions); - void Write(const char* Template, ...); + void Write(const char* templateStr, ...); + void WriteCpp(const char* templateStr, ...); }; diff --git a/src/game/Level.cpp b/src/game/Level.cpp index fef01a5..9d46fcf 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -70,7 +70,7 @@ namespace Game needReset |= PuzzleTiles.Setup(storagePtr, needReset); needReset |= UIQuads.Setup(storagePtr, needReset); - PuzzleData.Setup(); + Generated::Setup(PuzzleData); if (Cubes.Count == 0) { @@ -255,7 +255,7 @@ namespace Game for (uint32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI) { - const Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; + const Generated::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; Level& level = GetInstance().GameLevel; TileHandles[cardI] = level.PuzzleTiles.New(); UIPlacedCards[cardI] = level.UIQuads.New(); @@ -283,9 +283,10 @@ namespace Game for (int32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI) { - Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; - if (!card.RefCard.IsValid()) continue; - const Puzzle::StaticPuzzleCard& cData = Puzzle::StaticPuzzleData::Get().GetCard(card.RefCard); + Generated::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; + if (!Generated::IsValid(card.RefCard)) continue; + const Generated::StaticPuzzleCard& cData = + Generated::GetCard(Generated::GetStaticPuzzleData(), card.RefCard); level.PuzzleTiles.Get(TileHandles[cardI]).EData.ModelHandle = cData.ModelHandle; auto& quad = level.UIQuads.Get(UIPlacedCards[cardI]); diff --git a/src/game/Level.h b/src/game/Level.h index 22fb859..6c5a023 100644 --- a/src/game/Level.h +++ b/src/game/Level.h @@ -128,7 +128,7 @@ namespace Game struct WorldPuzzle { static constexpr Vec2 WorldCardSize{10.0f, 10.0f}; - Puzzle::PuzzleData Data; + Generated::PuzzleData Data; Vec3 WorldPosition; PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle]; UIQuadEntityHandle UIPlacedCards[Puzzle::Config::MaxCardsInPuzzle]; @@ -146,7 +146,7 @@ namespace Game EntityManager UIQuads; public: - Puzzle::StaticPuzzleData PuzzleData; + Generated::StaticPuzzleData PuzzleData; WorldPuzzle Puzzles[1]; public: diff --git a/src/game/Puzzle.cpp b/src/game/Puzzle.cpp index f6b2585..6f65a33 100644 --- a/src/game/Puzzle.cpp +++ b/src/game/Puzzle.cpp @@ -9,73 +9,79 @@ namespace { - static constexpr Puzzle::PuzPos Dirs[4]{ + static constexpr Generated::PuzPos Dirs[4]{ {-1, 0}, {0, -1}, {0, 1}, {1, 0}, }; - Puzzle::StaticPuzzleData* StaticDataInstance = nullptr; + Generated::StaticPuzzleData* StaticDataInstance = nullptr; } // namespace -namespace Puzzle +namespace Generated { - void StaticPuzzleData::Setup() + void Setup(StaticPuzzleData& data) { - StaticDataInstance = this; + StaticDataInstance = &data; LOG("Setting up static puzzle data"); - for (int32_t i = 0; i < BX_COUNTOF(Cards); ++i) + for (int32_t i = 0; i < BX_COUNTOF(data.Cards); ++i) { - Cards[i].ModelHandle = Game::GameRendering::Get().GetModelHandleFromPath("models/w straight.glb"); + data.Cards[i].ModelHandle = Game::GameRendering::Get().GetModelHandleFromPath("models/w straight.glb"); } } - StaticPuzzleData& StaticPuzzleData::Get() + StaticPuzzleData& GetStaticPuzzleData() { assert(StaticDataInstance != nullptr); return *StaticDataInstance; } - const StaticPuzzleCard& StaticPuzzleData::GetCard(StaticPuzzleCardHandle H) const + const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H) { - assert(H.IsValid()); - return Cards[H.Idx]; + // assert(IsValid(H)); + return data.Cards[H.Idx]; } - bool PuzzleNode::HasElement(PuzzleElementType search) const + bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search) { - for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i) + for (int32_t i = 0; i < Puzzle::Config::MaxElementsPerTile; ++i) { - if (PlacedTypes[i] == search) return true; + if (node.PlacedTypes[i] == search) return true; } return false; } - bool PuzzleNode::IsEmpty() const + bool IsEmpty(const PuzzleNode& node) { - for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i) + for (int32_t i = 0; i < Puzzle::Config::MaxElementsPerTile; ++i) { - if (PlacedTypes[i] != PuzzleElementType::None) return false; + if (node.PlacedTypes[i] != PuzzleElementType::None) return false; } return true; } - uint8_t PuzzleCardStack::GetRemainingCount() + bool IsValid(StaticPuzzleCardHandle h) { - assert(MaxAvailableCount >= UsedCount); - return MaxAvailableCount - UsedCount; + return h.Idx != UINT16_MAX; } - const PuzzleNode& PuzzleData::GetNodeAt(PuzPos pos) const + uint8_t GetRemainingCount(const PuzzleCardStack& stack) { - assert(pos.X < Config::MaxPuzzleSizeCards && pos.Y < Config::MaxPuzzleSizeCards && pos.X >= 0 && pos.Y >= 0); - return PlacedNodes[pos.Y * Config::MaxPuzzleSizeCards + pos.X]; + assert(stack.MaxAvailableCount >= stack.UsedCount); + return stack.MaxAvailableCount - stack.UsedCount; } - PuzzleElementType PuzzleData::GetElementAt(ElemPos pos) const + const PuzzleNode& GetNodeAt(const PuzzleData& puz, PuzPos pos) { - assert(pos.ElemIdx < Config::MaxElementsPerTile); - const PuzzleNode& node = GetNodeAt(pos.Position); + assert(pos.X < Puzzle::Config::MaxPuzzleSizeCards && pos.Y < Puzzle::Config::MaxPuzzleSizeCards && pos.X >= 0 && + pos.Y >= 0); + return puz.PlacedNodes[pos.Y * Puzzle::Config::MaxPuzzleSizeCards + pos.X]; + } + + PuzzleElementType::Enum GetElementAt(const PuzzleData& puz, ElemPos pos) + { + assert(pos.ElemIdx < Puzzle::Config::MaxElementsPerTile); + const PuzzleNode& node = GetNodeAt(puz, pos.Position); return node.PlacedTypes[pos.ElemIdx]; } @@ -95,26 +101,26 @@ namespace Puzzle bool PuzzleSolver::IsExitSatisfied(const PuzzleData& puzzle, ElemPos pos) { - const PuzzleNode& goalNode = puzzle.GetNodeAt(pos.Position); - PuzzleElementType goalType = puzzle.GetElementAt(pos); + const PuzzleNode& goalNode = GetNodeAt(puzzle, pos.Position); + PuzzleElementType::Enum goalType = GetElementAt(puzzle, pos); uint32_t currentPositionQueueIdx = 0; uint32_t positionQueueCount = 0; - PuzPos positionQueue[Config::MaxTilesInPuzzle]; + PuzPos positionQueue[Puzzle::Config::MaxTilesInPuzzle]; positionQueue[0] = pos.Position; positionQueueCount++; while (positionQueueCount > 0) { - assert(currentPositionQueueIdx < Config::MaxTilesInPuzzle); + assert(currentPositionQueueIdx < Puzzle::Config::MaxTilesInPuzzle); PuzPos currentPos = positionQueue[currentPositionQueueIdx]; for (PuzPos dir : Dirs) { PuzPos nextPos = currentPos + dir; if (IsValidGoalConnection(puzzle, nextPos, currentPos, goalType)) { - const PuzzleNode& node = puzzle.GetNodeAt(nextPos); - for (PuzzleElementType e : node.PlacedTypes) + const PuzzleNode& node = GetNodeAt(puzzle, nextPos); + for (PuzzleElementType::Enum e : node.PlacedTypes) { if (IsValidSource(e, goalType)) { @@ -133,46 +139,50 @@ namespace Puzzle bool PuzzleSolver::IsValidGoalConnection(const PuzzleData& puzzle, PuzPos flowFrom, PuzPos flowTo, - PuzzleElementType goalType) + PuzzleElementType::Enum goalType) { - const PuzzleNode& from = puzzle.GetNodeAt(flowFrom); - const PuzzleNode& to = puzzle.GetNodeAt(flowTo); + const PuzzleNode& from = GetNodeAt(puzzle, flowFrom); + const PuzzleNode& to = GetNodeAt(puzzle, flowTo); if (goalType == PuzzleElementType::WaterGoal) { - return from.HasElement(PuzzleElementType::WaterIn) || from.HasElement(PuzzleElementType::WaterChannel) || - from.HasElement(PuzzleElementType::WaterGoal); + return HasElement(from, PuzzleElementType::WaterIn) || HasElement(from, PuzzleElementType::WaterChannel) || + HasElement(from, PuzzleElementType::WaterGoal); } else if (goalType == PuzzleElementType::ElectricGoal) { - return from.HasElement(PuzzleElementType::ElectricIn) || from.HasElement(PuzzleElementType::ElectricGoal) || - from.IsEmpty(); + return HasElement(from, PuzzleElementType::ElectricIn) || + HasElement(from, PuzzleElementType::ElectricGoal) || IsEmpty(from); } assert(false); return false; } - bool PuzzleSolver::IsValidSource(PuzzleElementType sourceType, PuzzleElementType goalType) + bool PuzzleSolver::IsValidSource(PuzzleElementType::Enum sourceType, PuzzleElementType::Enum goalType) { return (sourceType == PuzzleElementType::WaterIn && goalType == PuzzleElementType::WaterGoal) || (sourceType == PuzzleElementType::ElectricIn && goalType == PuzzleElementType::ElectricGoal); } - bool PuzzleData::RenderDebugUI() +} // namespace Generated + +namespace Generated +{ + bool RenderDebugUI(PuzzleData& obj) { bool dataChanged = false; bool isVisible = true; if (ImGui::Begin("Puzzle", &isVisible)) { - ImGui::Text("%s", PuzzleName); + ImGui::Text("%s", obj.PuzzleName); - int32_t W = S.WidthTiles; - int32_t H = S.HeightTiles; + int32_t W = obj.WidthTiles; + int32_t H = obj.HeightTiles; ImGui::PushID("width"); ImGui::SetNextItemWidth(40); - if (ImGui::DragInt("", &W, 0.3f, 0, Config::MaxPuzzleSizeTiles)) + if (ImGui::DragInt("", &W, 0.3f, 0, Puzzle::Config::MaxPuzzleSizeTiles)) { - S.WidthTiles = uint8_t(W); + obj.WidthTiles = uint8_t(W); dataChanged = true; } ImGui::PopID(); @@ -181,9 +191,9 @@ namespace Puzzle ImGui::SameLine(); ImGui::SetNextItemWidth(40); ImGui::PushID("height"); - if (ImGui::DragInt("", &H, 0.3f, 0, Config::MaxPuzzleSizeTiles)) + if (ImGui::DragInt("", &H, 0.3f, 0, Puzzle::Config::MaxPuzzleSizeTiles)) { - S.HeightTiles = uint8_t(H); + obj.HeightTiles = uint8_t(H); dataChanged = true; } ImGui::PopID(); @@ -193,10 +203,32 @@ namespace Puzzle if (dataChanged) { char path[128]{0}; - bx::snprintf(path, sizeof(path), "game/data/%s.pzl", PuzzleName); - SerializeStruct(&S, sizeof(S), path); + bx::snprintf(path, sizeof(path), "game/data/%s.pzl", obj.PuzzleName); + Serializer ser; + ser.Init(path); + if (Save(&obj, 1, ser)) + { + LOG("Saved to %s", path); + } + else + { + LOG_ERROR("Failed to save to %s", path); + } + ser.Finish(); } return isVisible; } -} // namespace Puzzle + + PuzPos operator+=(PuzPos lhs, const PuzPos& rhs) + { + lhs.X += rhs.X; + lhs.Y += rhs.Y; + return lhs; + } + PuzPos operator+(PuzPos lhs, const PuzPos& rhs) + { + lhs += rhs; + return lhs; + } +} // namespace Generated diff --git a/src/game/Puzzle.h b/src/game/Puzzle.h index 7803c68..9c730b1 100644 --- a/src/game/Puzzle.h +++ b/src/game/Puzzle.h @@ -19,125 +19,139 @@ namespace Puzzle static constexpr uint32_t MaxGoalPositions = 16; }; - struct PuzPos - { - int8_t X = 0; - int8_t Y = 0; + // struct PuzPos + // { + // int8_t X = 0; + // int8_t Y = 0; - PuzPos& operator+=(const PuzPos& rhs) - { - X += rhs.X; - Y += rhs.Y; - return *this; - } + // 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; - } - }; + // friend PuzPos operator+(PuzPos lhs, const PuzPos& rhs) + // { + // lhs += rhs; + // return lhs; + // } + // }; - struct ElemPos - { - PuzPos Position; - uint8_t ElemIdx = 0; - }; + // struct ElemPos + // { + // PuzPos Position; + // uint8_t ElemIdx = 0; + // }; - enum class PuzzleElementType : uint8_t - { - None, - WaterIn, - WaterGoal, - WaterChannel, - ElectricIn, - ElectricGoal, - Blocked, - Bridge, - }; + // enum class PuzzleElementType : uint8_t + // { + // None, + // WaterIn, + // WaterGoal, + // WaterChannel, + // ElectricIn, + // ElectricGoal, + // Blocked, + // Bridge, + // }; - struct PuzzleNode - { - PuzzleElementType PlacedTypes[Config::MaxElementsPerTile]{PuzzleElementType::None}; + // struct PuzzleNode + // { + // PuzzleElementType PlacedTypes[Config::MaxElementsPerTile]{PuzzleElementType::None}; - bool HasElement(PuzzleElementType search) const; - bool IsEmpty() const; - }; + // bool HasElement(PuzzleElementType search) const; + // bool IsEmpty() const; + // }; - struct StaticPuzzleCard - { - PuzzleNode Nodes[Config::NodesPerCard]; - uint16_t ModelHandle = 0; - }; + // struct StaticPuzzleCard + // { + // PuzzleNode Nodes[Config::NodesPerCard]; + // uint16_t ModelHandle = 0; + // }; - struct StaticPuzzleCardHandle - { - uint16_t Idx = UINT16_MAX; - bool IsValid() - { - return Idx != UINT16_MAX; - } - }; + // struct StaticPuzzleCardHandle + // { + // uint16_t Idx = UINT16_MAX; + // bool IsValid() + // { + // return Idx != UINT16_MAX; + // } + // }; - struct StaticPuzzleData - { - StaticPuzzleCard Cards[64]; + // struct StaticPuzzleData + // { + // StaticPuzzleCard Cards[64]; - void Setup(); - static StaticPuzzleData& Get(); - const StaticPuzzleCard& GetCard(StaticPuzzleCardHandle H) const; - }; + // 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 PlacedPuzzleCard + // { + // StaticPuzzleCardHandle RefCard; + // PuzPos Position; + // uint8_t Rotation = 0; + // bool IsLocked = false; + // }; - struct PuzzleCardStack - { - StaticPuzzleCardHandle RefCard; - uint8_t MaxAvailableCount = 0; - uint8_t UsedCount = 0; + // struct PuzzleCardStack + // { + // StaticPuzzleCardHandle RefCard; + // uint8_t MaxAvailableCount = 0; + // uint8_t UsedCount = 0; - uint8_t GetRemainingCount(); - }; + // uint8_t GetRemainingCount(); + // }; - struct PuzzleData - { - SER_HEADER(1, "PZZL"); - Generated::PuzzleData S; + // struct PuzzleData + // { + // uint32_t AvailableCardCount = 0; + // PuzzleCardStack AvailableCards[Config::MaxAvailableStacks]; + // uint32_t PlacedCardCount = 0; + // PlacedPuzzleCard PlacedCards[Config::MaxCardsInPuzzle]; - uint32_t AvailableCardCount = 0; - PuzzleCardStack AvailableCards[Config::MaxAvailableStacks]; - uint32_t PlacedCardCount = 0; - PlacedPuzzleCard PlacedCards[Config::MaxCardsInPuzzle]; + // // Indexed by board position + // PuzzleNode PlacedNodes[Config::MaxTilesInPuzzle]; - // Indexed by board position - PuzzleNode PlacedNodes[Config::MaxTilesInPuzzle]; + // uint32_t GoalPositionCount = 0; + // ElemPos GoalPositions[Config::MaxGoalPositions]; - uint32_t GoalPositionCount = 0; - ElemPos GoalPositions[Config::MaxGoalPositions]; + // const PuzzleNode& GetNodeAt(PuzPos pos) const; + // PuzzleElementType GetElementAt(ElemPos pos) const; - const PuzzleNode& GetNodeAt(PuzPos pos) const; - PuzzleElementType GetElementAt(ElemPos pos) const; + // char PuzzleName[32]{"Unnamed"}; + // bool RenderDebugUI(); + // }; +} // namespace Puzzle - char PuzzleName[32]{"Unnamed"}; - bool RenderDebugUI(); - }; +namespace Generated +{ + PuzPos operator+=(PuzPos lhs, const PuzPos& rhs); + PuzPos operator+(PuzPos lhs, const PuzPos& rhs); + + void Setup(StaticPuzzleData& data); + StaticPuzzleData& GetStaticPuzzleData(); + const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H); + bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search); + bool IsEmpty(const PuzzleNode& node); + bool IsValid(StaticPuzzleCardHandle h); + uint8_t GetRemainingCount(const PuzzleCardStack& stack); + const PuzzleNode& GetNodeAt(const PuzzleData& puz, PuzPos pos); + PuzzleElementType::Enum GetElementAt(const PuzzleData& puz, ElemPos pos); struct PuzzleSolver { - bool IsPuzzleSolved(const PuzzleData& puzzle); - bool IsExitSatisfied(const PuzzleData& puzzle, ElemPos pos); + bool IsPuzzleSolved(const Generated::PuzzleData& puzzle); + bool IsExitSatisfied(const Generated::PuzzleData& puzzle, ElemPos pos); // This assumes flowFrom is already verified to be connected. - bool IsValidGoalConnection(const PuzzleData& puzzle, + bool IsValidGoalConnection(const Generated::PuzzleData& puzzle, PuzPos flowFrom, PuzPos flowTo, - PuzzleElementType goalType); - bool IsValidSource(PuzzleElementType sourceType, PuzzleElementType goalType); + PuzzleElementType::Enum goalType); + bool IsValidSource(PuzzleElementType::Enum sourceType, PuzzleElementType::Enum goalType); }; -} // namespace Puzzle + bool RenderDebugUI(PuzzleData& obj); +} // namespace Generated diff --git a/src/game/mini.def b/src/game/mini.def index 667b1bb..d9c51bb 100644 --- a/src/game/mini.def +++ b/src/game/mini.def @@ -69,4 +69,5 @@ type PuzzleData PuzzleNode PlacedNodes Arr(1024) u32 GoalPositionCount ElemPos GoalPositions Arr(16) + str PuzzleName Arr(64) } diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index 2412779..5ff25da 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -511,6 +511,7 @@ namespace Game if (ImGui::Begin("Puzzles")) { ImGui::Text("List"); + ImGui::Separator(); for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) { auto& puzzleData = level.Puzzles[i].Data; @@ -524,10 +525,10 @@ namespace Game if (isSelected) { ImGui::PushID("edit field"); - ImGui::InputText("", puzzleData.PuzzleName, sizeof(Puzzle::PuzzleData::PuzzleName)); + ImGui::InputText("", puzzleData.PuzzleName, sizeof(Generated::PuzzleData::PuzzleName)); ImGui::PopID(); - if (!puzzleData.RenderDebugUI()) + if (!Generated::RenderDebugUI(puzzleData)) { debug.SelectedDebugLevel = UINT16_MAX; } @@ -540,13 +541,6 @@ namespace Game GetInstance().GameLevel.Update(); GetInstance().GameLevel.Render(MainViewID, Models, Materials); - // bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.1fs", GetInstance().Time.Now); - // for (int32_t i = 0; i < (int32_t)PerfCounterType::COUNT; ++i) - // { - // bgfx::dbgTextPrintf( - // 1, 2 + i, 0x0F, "%s Max: %.3fs", PerfCounterNames[i], shared.Window.PerfCounters[i].GetMax()); - // } - // Finish Frame imguiEndFrame(); diff --git a/src/gen/Def.h b/src/gen/Def.h index 8b14fbe..986ef05 100644 --- a/src/gen/Def.h +++ b/src/gen/Def.h @@ -1,2 +1,56 @@ #pragma once +#include #include + +#define SAVE_T(T) \ + inline bool Save(const T* obj, uint32_t count, Serializer& serializer) \ + { \ + bool isOk = true; \ + for (uint32_t i = 0; i < count; ++i) \ + { \ + isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk; \ + } \ + return isOk; \ + } + +namespace Generated +{ + struct Serializer + { + bx::Error Err; + bx::FilePath Path; + bx::FileWriter Writer; + + bool Init(const bx::FilePath& path) + { + Path = path; + Writer.open(path, false, &Err); + return Err.isOk(); + } + + bool Write(const void* data, uint32_t size) + { + Writer.write(data, size, &Err); + return Err.isOk(); + } + + void Finish() + { + Writer.close(); + } + }; + + SAVE_T(uint8_t) + SAVE_T(uint16_t) + SAVE_T(uint32_t) + SAVE_T(uint64_t) + SAVE_T(int8_t) + SAVE_T(int16_t) + SAVE_T(int32_t) + SAVE_T(int64_t) + SAVE_T(float) + SAVE_T(double) + SAVE_T(bool) + SAVE_T(char) + +} // namespace Generated diff --git a/src/gen/Generated.cpp b/src/gen/Generated.cpp new file mode 100644 index 0000000..1085cfd --- /dev/null +++ b/src/gen/Generated.cpp @@ -0,0 +1,113 @@ +#include "Generated.h" + +namespace Generated +{ + bool Save(const PuzzleElementType::Enum* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + auto val = (int32_t)obj[i]; + isOk = Save(&val, 1, serializer) && isOk; + } + return isOk; + } + bool Save(const PuzPos* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(&obj[i].X, 1, serializer) && isOk; + isOk = Save(&obj[i].Y, 1, serializer) && isOk; + } + return isOk; + } + bool Save(const ElemPos* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(&obj[i].Position, 1, serializer) && isOk; + isOk = Save(&obj[i].ElemIdx, 1, serializer) && isOk; + } + return isOk; + } + bool Save(const PuzzleNode* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(obj[i].PlacedTypes, 4, serializer) && isOk; + } + return isOk; + } + bool Save(const StaticPuzzleCard* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(obj[i].Nodes, 4, serializer) && isOk; + isOk = Save(&obj[i].ModelHandle, 1, serializer) && isOk; + } + return isOk; + } + bool Save(const StaticPuzzleCardHandle* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(&obj[i].Idx, 1, serializer) && isOk; + } + return isOk; + } + bool Save(const StaticPuzzleData* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(obj[i].Cards, 64, serializer) && isOk; + } + return isOk; + } + bool Save(const PuzzleCardStack* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(&obj[i].RefCard, 1, serializer) && isOk; + isOk = Save(&obj[i].MaxAvailableCount, 1, serializer) && isOk; + isOk = Save(&obj[i].UsedCount, 1, serializer) && isOk; + } + return isOk; + } + bool Save(const PlacedPuzzleCard* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(&obj[i].RefCard, 1, serializer) && isOk; + isOk = Save(&obj[i].Position, 1, serializer) && isOk; + isOk = Save(&obj[i].Rotation, 1, serializer) && isOk; + isOk = Save(&obj[i].IsLocked, 1, serializer) && isOk; + } + return isOk; + } + bool Save(const PuzzleData* obj, uint32_t count, Serializer& serializer) + { + bool isOk = true; + for (uint32_t i = 0; i < count; ++i) + { + isOk = Save(&obj[i].WidthTiles, 1, serializer) && isOk; + isOk = Save(&obj[i].HeightTiles, 1, serializer) && isOk; + isOk = Save(&obj[i].AvailableCardCount, 1, serializer) && isOk; + isOk = Save(obj[i].AvailableCards, 16, serializer) && isOk; + isOk = Save(&obj[i].PlacedCardCount, 1, serializer) && isOk; + isOk = Save(obj[i].PlacedCards, 256, serializer) && isOk; + isOk = Save(obj[i].PlacedNodes, 1024, serializer) && isOk; + isOk = Save(&obj[i].GoalPositionCount, 1, serializer) && isOk; + isOk = Save(obj[i].GoalPositions, 16, serializer) && isOk; + isOk = Save(obj[i].PuzzleName, 64, serializer) && isOk; + } + return isOk; + } +} diff --git a/src/gen/Generated.h b/src/gen/Generated.h index a3b3749..00c818b 100644 --- a/src/gen/Generated.h +++ b/src/gen/Generated.h @@ -6,7 +6,7 @@ namespace Generated struct PuzzleElementType { static constexpr int32_t EntryCount = 8; - enum class Enum : int32_t + enum Enum : int32_t { None, WaterIn, @@ -52,7 +52,7 @@ namespace Generated }; struct PuzzleNode { - PuzzleElementType PlacedTypes[4] = {}; + PuzzleElementType::Enum PlacedTypes[4] = {}; }; struct StaticPuzzleCard { @@ -91,5 +91,16 @@ namespace Generated PuzzleNode PlacedNodes[1024] = {}; uint32_t GoalPositionCount = {}; ElemPos GoalPositions[16] = {}; + char PuzzleName[64] = {}; }; + bool Save(const PuzzleElementType::Enum* obj, uint32_t count, Serializer& serializer); + bool Save(const PuzPos* obj, uint32_t count, Serializer& serializer); + bool Save(const ElemPos* obj, uint32_t count, Serializer& serializer); + bool Save(const PuzzleNode* obj, uint32_t count, Serializer& serializer); + bool Save(const StaticPuzzleCard* obj, uint32_t count, Serializer& serializer); + bool Save(const StaticPuzzleCardHandle* obj, uint32_t count, Serializer& serializer); + bool Save(const StaticPuzzleData* obj, uint32_t count, Serializer& serializer); + bool Save(const PuzzleCardStack* obj, uint32_t count, Serializer& serializer); + bool Save(const PlacedPuzzleCard* obj, uint32_t count, Serializer& serializer); + bool Save(const PuzzleData* obj, uint32_t count, Serializer& serializer); }