#include "../gen/Def.h" #include "Gen.h" #include "Global.h" #include "Instance.h" #include "Log.h" #include "Mesh.h" #include "Puzzle.h" #include "Tools.h" #include "bgfx/bgfx.h" #include "bx/filepath.h" #include "bx/string.h" #include "bx/timer.h" #include "rendering/Rendering.h" #include #include using namespace Gen; namespace { constexpr int32_t FrameTimeBufSize = 512; int64_t FrameTimes[FrameTimeBufSize]{0}; int32_t FrameTimeIdx = 0; } // namespace namespace Tools { const char* GetAssetPath(Gen::AssetHandle 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 "---"; } bool EntityDataSettings(Gen::SavedEntityRenderData& data) { ImGui::PushID(&data); bool changed = false; changed |= ModelDropdown(data.Model); changed |= MaterialDropdown(data.Material); changed |= TextureDropdown(data.Texture); changed |= TransformUI(data.TF); changed |= ImGui::Checkbox("Visible", &data.Visible); changed |= ImGui::ColorEdit4("Color 1", &data.BaseColor.x); changed |= ImGui::ColorEdit4("Color 2", &data.HighlightColor.x); ImGui::PopID(); return changed; } bool ModelDropdown(Gen::ModelHandle& modelHandle, const char* title) { bool changed = false; auto& R = Game::GameRendering::Get(); const char* assetName = GetAssetPath(modelHandle.Asset); if (ImGui::BeginCombo(title, assetName)) { for (int32_t i = 0; i < R.ModelCount; ++i) { if (ImGui::Selectable(GetAssetPath(R.Models[i].Handle.Asset), i == modelHandle.ModelIdx)) { modelHandle = R.Models[i].Handle; changed = true; } } ImGui::EndCombo(); } return changed; } bool TextureDropdown(Gen::TextureHandle& texHandle, const char* title) { bool changed = false; auto& R = Game::GameRendering::Get(); const char* name = GetAssetPath(texHandle.Asset); if (ImGui::BeginCombo(title, name)) { for (int32_t i = 0; i < R.MaxTextures; ++i) { if (!IsValid(R.Textures[i].TexHandle)) continue; ImGui::PushID(i); ImVec2 pos = ImGui::GetCursorScreenPos(); if (ImGui::Selectable("", i == texHandle.TextureIdx, ImGuiSelectableFlags_AllowOverlap, {0, 64})) { texHandle = R.Textures[i].TexHandle; changed = true; } ImGui::SetCursorScreenPos(pos); ImGui::Image(R.Textures[i].RenderHandle.idx, {64, 64}); ImGui::SameLine(); ImGui::Text("%s", GetAssetPath(R.Textures[i].TexHandle.Asset)); ImGui::PopID(); } ImGui::EndCombo(); } return changed; } bool MaterialDropdown(Gen::EMaterial::Enum& material) { bool changed = false; const char* selectedText = "---"; if (material < Gen::EMaterial::EntryCount) { selectedText = Gen::EMaterial::EntryNames[material]; } if (ImGui::BeginCombo("Material", selectedText)) { for (int32_t i = 0; i < Gen::EMaterial::EntryCount; ++i) { if (ImGui::Selectable(Gen::EMaterial::EntryNames[i], i == material)) { material = (Gen::EMaterial::Enum)i; changed = true; } } ImGui::EndCombo(); } return changed; } constexpr const char* UnitStrings[]{ "b", "kb", "mb", "gb", }; const char* GetUnitString(uint64_t byteCount, uint64_t& outCount) { outCount = byteCount; int32_t strIdx = 0; for (int32_t i = 0; i < BX_COUNTOF(UnitStrings); ++i) { if (outCount < 1024) break; ++strIdx; outCount /= 1024; } return UnitStrings[strIdx]; } void ProgressBar(const char* title, uint64_t current, uint64_t max) { ImGui::PushID(title); float percent = static_cast(current) / static_cast(max); ImVec2 startPos = ImGui::GetCursorScreenPos(); char content[128]{0}; uint64_t currentUnit = 0; const char* currentUnitStr = GetUnitString(current, currentUnit); uint64_t maxUnit = 0; const char* maxUnitStr = GetUnitString(max, maxUnit); bx::snprintf(content, sizeof(content), "%s: %u %s/%u %s (%.2f%%)", title, currentUnit, currentUnitStr, maxUnit, maxUnitStr, percent); ImGui::Text("%s", content); ImGui::PopID(); } bool TransformUI(Gen::Transform& transform) { bool changed = false; changed |= ImGui::DragFloat3("Pos", &transform.Position.x, 0.1f); Vec3 euler = EulerFromRotation(transform.Rotation); if (ImGui::DragFloat3("Rot", &euler.x, 0.1f)) { transform.Rotation = RotationFromEuler(euler); changed = true; } changed |= ImGui::DragFloat3("Scale", &transform.Scale.x, 0.01f); return changed; } void RenderLogUI() { auto& time = Game::GetInstance().Time; auto& debug = Game::GetInstance().DebugData; if (ImGui::Begin("Log")) { ImGui::Checkbox("Shorten File Names", &debug.ShortenLogFileNames); ImGui::BeginTable("tbl", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg); ImGui::TableSetupColumn("Time", ImGuiTableColumnFlags_NoResize); ImGui::TableSetupColumn("Log"); ImGui::TableSetupColumn("Line", ImGuiTableColumnFlags_NoResize); ImGui::TableSetupColumn("File", ImGuiTableColumnFlags_NoResize); ImGui::TableHeadersRow(); auto& logs = GetLogHistory(); int32_t lineCount = bx::min(100, LogInternal::LogHistorySize); for (int32_t i = 0; i < lineCount; ++i) { int32_t idx = logs.WriteIdx - i - 1; if (idx < 0) idx += LogInternal::LogHistorySize; const char* line = &logs.LogBuffer[idx * LogInternal::MaxLineSize]; if (line[0] != 0) { int64_t timeOffset = logs.WriteTime[idx] - time.StartTime; double writeTime = (double)timeOffset / bx::getHPFrequency(); uint32_t fileLine = logs.LineBuffer[idx]; const char* filePath = &logs.FileBuffer[idx * LogInternal::MaxLineSize]; const char* filePathRes = debug.ShortenLogFileNames ? bx::FilePath{filePath}.getFileName().getPtr() : filePath; ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("%.01f", writeTime); ImGui::TableNextColumn(); ImGui::Text("%s", line); ImGui::SetItemTooltip("%f\n%s%s:%u", writeTime, line, filePath, fileLine); ImGui::TableNextColumn(); ImGui::Text("%u", fileLine); ImGui::TableNextColumn(); ImGui::Text("%s", filePathRes); if (i > 0) ImGui::PopStyleColor(2); ImVec4 bgCol = {0.0f, 0.0f, 0.0f, 1.0f}; if (logs.WriteType[idx] == ELogType::Warn) bgCol = {0.2f, 0.2f, 0.0f, 1.0f}; else if (logs.WriteType[idx] == ELogType::Error) bgCol = {0.2f, 0.0f, 0.0f, 1.0f}; ImGui::PushStyleColor(ImGuiCol_TableRowBg, bgCol); ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, bgCol); } } ImGui::EndTable(); if (lineCount > 0) ImGui::PopStyleColor(2); } ImGui::End(); } void RenderRenderSettingsUI(Game::GameRendering& rendering) { auto& time = Game::GetInstance().Time; auto& shared = Game::GetShared(); auto& debug = Game::GetInstance().DebugData; auto& level = Game::GetInstance().GameLevel; auto& player = Game::GetInstance().Player; if (ImGui::Begin("Rendering")) { if (rendering.LastShaderLoadTime >= 0.0f) { ImGui::TextColored({0.2f, 0.9f, 0.2f, 1.0f}, "Shader loaded %.0f seconds ago", time.Now - rendering.LastShaderLoadTime); } else { ImGui::TextColored({0.9f, 0.2f, 0.2f, 1.0f}, "Shader load Failiure!"); } ImGui::SameLine(); if (ImGui::Button("Reload Level")) { level = {}; level.Setup(shared.Game); } ImGui::DragFloat3("Player Pos", &player.PlayerCamTransform.Position.x); ImGui::DragFloat3("Puz0 Pos", &level.Puzzles[0].WorldPosition.x); ImGui::SliderFloat("Mouse Sensitivity", &player.MouseSensitivity, 0.1f, 5.0f); ImGui::SliderFloat("Player Speed", &player.MovementSpeed, 1.0f, 30.0f); ImGui::Checkbox("Show ImGui Demo", &debug.ShowImguiDemo); ImGui::Checkbox("Show Stats", &debug.ShowStats); if (debug.ShowImguiDemo) ImGui::ShowDemoWindow(&debug.ShowImguiDemo); ImGui::Separator(); if (ImGui::TreeNodeEx("Entity Groups")) { ImGui::Checkbox("Cubes", &level.Cubes.IsEnabled); ImGui::Checkbox("Tests", &level.Tests.IsEnabled); ImGui::Checkbox("PuzzleTiles", &level.PuzzleTiles.IsEnabled); ImGui::Checkbox("UIQuads", &level.UIQuads.IsEnabled); ImGui::Checkbox("Level", &level.LevelEntities.IsEnabled); ImGui::TreePop(); } bool uiconfigChanged = false; if (ImGui::TreeNodeEx("Game Tablet")) { uiconfigChanged |= Tools::EntityDataSettings(player.Config.TabletBackgroundRenderData); ImGui::Separator(); ImGui::Text("Status"); uiconfigChanged |= Tools::EntityDataSettings(player.Config.TabletStatusRenderData); uiconfigChanged |= Tools::TextureDropdown(player.Config.TabletStatusSolvedTexture, "Solved Texture"); uiconfigChanged |= Tools::TextureDropdown(player.Config.TabletStatusNotSolvedTexture, "Not Solved Texture"); ImGui::Separator(); ImGui::Text("Reset"); uiconfigChanged |= Tools::EntityDataSettings(player.Config.TabletResetRenderData); ImGui::TreePop(); } if (ImGui::TreeNodeEx("Background Level")) { for (int32_t i = 0; i < BX_COUNTOF(player.Config.BackgroundLevelRenderData); ++i) { if (i > 0) ImGui::Separator(); uiconfigChanged |= Tools::EntityDataSettings(player.Config.BackgroundLevelRenderData[i]); } ImGui::TreePop(); } if (uiconfigChanged) { Serializer s; s.Init("game/data/static/uiconfig.dat", "UICO"); s.WriteT(player.Config); s.Finish(); level.PuzzleUI.Reset(); level.ReloadLevelEntities(); } if (ImGui::TreeNodeEx("Dithering")) { if (ImGui::Button("Dithergen")) { DitherGen(rendering.DitherTextures, rendering.DitherRecursion); } ImGui::SameLine(); ImGui::SliderInt("Recursion", &rendering.DitherRecursion, 1, 4); ImGui::Text("%ux%ux%u", rendering.DitherTextures.DitherTexWH, rendering.DitherTextures.DitherTexWH, rendering.DitherTextures.DitherTexDepth); if (!isValid(rendering.DitherTextures.PreviewTex)) { ImGui::Text("Invalid Texture"); } else { ImGui::Image( rendering.DitherTextures.PreviewTex.idx, {(float)rendering.DitherTextures.DitherTexWH, (float)rendering.DitherTextures.DitherTexWH * rendering.DitherTextures.DitherTexDepth}); } if (isValid(rendering.DitherTextures.RampTex)) { ImGui::Image(rendering.DitherTextures.RampTex.idx, {BX_COUNTOF(rendering.DitherTextures.BrightnessRamp), 8}); } ImGui::TreePop(); } if (ImGui::TreeNodeEx("Shader log")) { ImGui::TextWrapped("%s", Game::GetShared().Dev.ShaderLog); ImGui::TreePop(); } } ImGui::End(); } void RenderTexturesUI(Game::GameRendering& rendering) { if (ImGui::Begin("Textures")) { if (ImGui::Button("Reload")) { rendering.LoadTextures(); } for (int32_t i = 0; i < rendering.MaxTextures; ++i) { if (!isValid(rendering.Textures[i].RenderHandle)) continue; ImGui::Text("%i", i); float width = bx::min(ImGui::GetContentRegionAvail().x, rendering.Textures[i].Info.width); float height = bx::min(ImGui::GetContentRegionAvail().x, rendering.Textures[i].Info.height); ImGui::Image(rendering.Textures[i].RenderHandle.idx, {width, height}); } } ImGui::End(); } void RenderModelsUI(Game::GameRendering& rendering) { if (ImGui::Begin("Models")) { if (ImGui::Button("Reload")) { LoadModels(rendering.Models, rendering.ModelCount); } for (int32_t i = 0; i < rendering.ModelCount; ++i) { auto& mdl = rendering.Models[i]; if (bgfx::isValid(mdl.HeightMapTexture)) { ImGui::Text("%s", mdl.Name); ImGui::Image(mdl.HeightMapTexture.idx, ImVec2{(float)Game::HeightMap::Height, (float)Game::HeightMap::Width}); } else { ImGui::Text("Invalid Handle!"); } ImGui::Spacing(); } } ImGui::End(); } void RenderPuzzlesUI() { auto& debug = Game::GetInstance().DebugData; auto& level = Game::GetInstance().GameLevel; if (ImGui::Begin("Puzzles")) { char nameBuf[64]{0}; for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) { ImGui::PushID(i); auto& puzzleData = level.Puzzles[i].Data; bool isSelected = debug.SelectedDebugLevel == i; ImGui::PushID("selectable"); bx::snprintf(nameBuf, sizeof(nameBuf), "%u: %s", i, puzzleData.PuzzleName); if (ImGui::Selectable(nameBuf, isSelected)) { debug.SelectedDebugLevel = isSelected ? UINT16_MAX : i; } ImGui::DragFloat3("Pos", &level.Puzzles[i].WorldPosition.x); ImGui::PopID(); ImGui::PopID(); } } ImGui::End(); if (debug.SelectedDebugLevel < BX_COUNTOF(level.Puzzles)) { if (!Puzzle::RenderDebugUI(level.Puzzles[debug.SelectedDebugLevel].Data)) { debug.SelectedDebugLevel = UINT16_MAX; } } } void RenderCardsUI(Game::GameRendering& rendering) { auto& debug = Game::GetInstance().DebugData; if (ImGui::Begin("Cards")) { Gen::StaticPuzzleData& staticData = Puzzle::GetStaticPuzzleData(); if (ImGui::Button("Save")) { Puzzle::SaveStaticPuzzleData(); } ImGui::SameLine(); if (ImGui::Button("Reload")) { Puzzle::LoadStaticPuzzleData(); } ImGui::Separator(); ImGui::ColorEdit3("Disabled Tint", &staticData.Visuals.DisabledCardTint.x); ImGui::ColorEdit3("Tile Base Color", &staticData.Visuals.TileBaseColor.x); ImGui::ColorEdit3("Tile Dot Color", &staticData.Visuals.TileDotColor.x); for (int32_t i = 0; i < BX_COUNTOF(staticData.Cards); ++i) { ImGui::Separator(); Gen::StaticPuzzleCard& card = staticData.Cards[i]; ImGui::PushID(i); char cardName[64]{0}; bx::snprintf(cardName, sizeof(cardName), "%i", i); ImGui::Selectable(cardName); if (ImGui::BeginDragDropSource()) { Puzzle::DrawCard(card, debug.DebugCardRotation, ImGui::GetCursorScreenPos()); ImGui::SetDragDropPayload("cardtype", &i, sizeof(i)); ImGui::EndDragDropSource(); } Tools::ModelDropdown(card.BaseModelHandle); Tools::TextureDropdown(card.ModelTextureHandle, "World Texture"); Tools::TextureDropdown(card.BoardTextureHandle, "UI Texture"); if (IsValid(card.BaseModelHandle)) { auto& mdl = rendering.Models[card.BaseModelHandle.ModelIdx]; if (mdl.SocketCount > 0 && ImGui::TreeNodeEx("Slots")) { for (int32_t sIdx = 0; sIdx < mdl.SocketCount; ++sIdx) { Tools::ModelDropdown(card.Sockets[sIdx].Model, mdl.Sockets[sIdx].Name); int val = card.Sockets[sIdx].ConnectionDirection; ImGui::PushID(sIdx); if (ImGui::Combo("Connection Direction", &val, "North\0East\0South\0West\0")) { card.Sockets[sIdx].ConnectionDirection = val; } ImGui::PopID(); } ImGui::TreePop(); } } ImGui::Text("Card"); for (int8_t y = 0; y < Puzzle::Config::CardSize; ++y) { ImGui::PushID(y); for (int8_t x = 0; x < Puzzle::Config::CardSize; ++x) { if (x > 0) ImGui::SameLine(); ImGui::PushID(x); auto& node = Puzzle::EditCardNodeAt(card, 0, x, y); if (ImGui::Button(Gen::PuzzleElementType::ShortName[node], {26, 24})) { int32_t newVal = int32_t(node) + 1; if (newVal >= Gen::PuzzleElementType::EntryCount) { newVal = 0; } node = Gen::PuzzleElementType::Enum(newVal); } ImGui::PopID(); } ImGui::PopID(); } ImGui::PopID(); } } ImGui::End(); } void RenderEntitiesUI() { auto& level = Game::GetInstance().GameLevel; if (ImGui::Begin("Entities")) { if (ImGui::TreeNodeEx("UIQuads")) { ImGui::Text("Count: %u", level.UIQuads.Count); for (uint16_t i = 0; i < level.UIQuads.Count; ++i) { ImGui::Separator(); ImGui::PushID(i); ImGui::Text("%u", i); ImGui::SameLine(); auto& quad = level.UIQuads.Get({i}); ImGui::Checkbox("Visible", &quad.EData.Visible); TextureDropdown(quad.EData.TextureHandle); MaterialDropdown(quad.EData.MaterialHandle); ImGui::DragFloat3("Pos", &quad.EData.Transform.Position.x); ImGui::DragFloat3("UI Pos", &quad.UIPos.x); ImGui::Text("RenderID: %i", quad.EData.RenderID); ImGui::PopID(); } ImGui::TreePop(); } if (ImGui::TreeNodeEx("Level")) { ImGui::Text("Count: %u", level.LevelEntities.Count); for (uint16_t i = 0; i < level.LevelEntities.Count; ++i) { ImGui::Separator(); ImGui::PushID(i); ImGui::Text("%u", i); ImGui::SameLine(); auto& levelEnt = level.LevelEntities.Get({i}); ImGui::Checkbox("Visible", &levelEnt.EData.Visible); TextureDropdown(levelEnt.EData.TextureHandle); MaterialDropdown(levelEnt.EData.MaterialHandle); ImGui::DragFloat3("Pos", &levelEnt.EData.Transform.Position.x); ImGui::Text("RenderID: %i", levelEnt.EData.RenderID); ImGui::PopID(); } ImGui::TreePop(); } } ImGui::End(); } void RenderStatsUI() { auto& time = Game::GetInstance().Time; auto& debug = Game::GetInstance().DebugData; if (debug.ShowStats) { ImGui::SetNextWindowPos({0, 0}); if (ImGui::Begin("Stats", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize)) { if (Game::GetInstance().Player.CameraM == Game::CameraMode::Freefly) { ImGui::PushStyleColor(ImGuiCol_Text, {0.8f, 0.1f, 0.1f, 1.0f}); ImGui::Text("NOCLIP"); ImGui::PopStyleColor(); } ImGui::Text("Delta: %.01fms", time.Delta * 1000); ImGui::Text("FPS: %.0f", 1.0 / time.Delta); constexpr ImVec2 FpsPlotSize{200, 60}; if (ImGui::BeginChild("FpsPlot", FpsPlotSize, 0, ImGuiWindowFlags_NoInputs)) { auto& drawList = *ImGui::GetWindowDrawList(); ImVec2 pos = ImGui::GetWindowPos(); drawList.AddRectFilled(pos, {pos.x + FpsPlotSize.x, pos.y + FpsPlotSize.y}, 0x22222233); float scale = 1000.0f; for (int32_t i = 0; i < FrameTimeBufSize; ++i) { int32_t idx = FrameTimeIdx - i - 1; int32_t prevIdx = idx - 1; if (idx < 0) idx += FrameTimeBufSize; if (prevIdx < 0) prevIdx += FrameTimeBufSize; if (FrameTimes[idx] == 0 || FrameTimes[prevIdx] == 0) continue; int64_t frameTime = FrameTimes[idx] - FrameTimes[prevIdx]; double frameTimeSec = (double)frameTime / bx::getHPFrequency(); drawList.AddLine( {pos.x + (FpsPlotSize.x - i - 1), pos.y + FpsPlotSize.y}, {pos.x + (FpsPlotSize.x - i - 1), pos.y + FpsPlotSize.y - (float)frameTimeSec * scale}, 0xFFFFFFFF); } } ImGui::EndChild(); } ImGui::End(); } } void RenderDebugUI(Game::GameRendering& rendering) { if (!rendering.SetupData.UseImgui) return; ZoneScopedN("DebugUI"); auto& time = Game::GetInstance().Time; auto& shared = Game::GetShared(); auto& debug = Game::GetInstance().DebugData; auto& level = Game::GetInstance().GameLevel; auto& player = Game::GetInstance().Player; if (ImGui::Begin("Hilfe")) { if (ImGui::Button("Spiel Neustarten")) { player.PlayerCamTransform.Position = {0.0f, 3.0f, 0.0f}; for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) { Puzzle::ResetPuzzle(level.Puzzles[i].Data); } } ImGui::SameLine(); if (ImGui::Button("Zurück zum Anfang")) { player.PlayerCamTransform.Position = {0.0f, 3.0f, 0.0f}; } ImGui::Separator(); ImGui::Text("Anleitung:"); ImGui::Text("Bewege dich mit"); ImGui::SameLine(); ImGui::TextColored({1.0f, 0.6f, 0.6f, 1.0f}, "W, A, S, D"); ImGui::SameLine(); ImGui::Text("und schau dich um mit der"); ImGui::SameLine(); ImGui::TextColored({1.0f, 0.6f, 0.6f, 1.0f}, "Maus."); ImGui::Text("Drücke"); ImGui::SameLine(); ImGui::TextColored({1.0f, 0.6f, 0.6f, 1.0f}, "Leertaste"); ImGui::SameLine(); ImGui::Text("um den Spielplan zu öffnen."); ImGui::Text("Auf dem Spielplan kannst du Karten verschieben."); ImGui::Text("Mit"); ImGui::SameLine(); ImGui::TextColored({1.0f, 0.6f, 0.6f, 1.0f}, "Rechter Maustaste"); ImGui::SameLine(); ImGui::Text("kannst du Karten drehen."); ImGui::Text(""); ImGui::Text("Dein Ziel: Verbinde die Pumpe mit dem Abfluss, um das"); ImGui::Text("Tor zum nächsten Level zu öffnen!"); ImGui::Text(""); auto& inflowTexture = rendering.Textures[10]; auto& outflowTexture = rendering.Textures[9]; auto& connectionTexture = rendering.Textures[8]; ImGui::Text("Pumpe (Wasserquelle):"); ImGui::Image(inflowTexture.RenderHandle.idx, {64.0f, 64.0f}); ImGui::Text("Abfluss (Ziel):"); ImGui::Image(outflowTexture.RenderHandle.idx, {64.0f, 64.0f}); ImGui::Text("Verbindung:"); ImGui::Image(connectionTexture.RenderHandle.idx, {64.0f, 64.0f}); } ImGui::End(); if (rendering.UIVisible == Game::UIVisibilityState::Debug) { if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) { debug.DebugCardRotation++; if (debug.DebugCardRotation >= 4) debug.DebugCardRotation = 0; } if (ImGui::Begin("Debug")) { ImGui::Checkbox("ImGui Demo", &debug.ShowImguiDemo); ImGui::SliderFloat("Font Scale", &ImGui::GetIO().FontGlobalScale, 0.5f, 4.0f); ImGui::Checkbox("Break on ID", &debug.DebugBreakIDEnabled); ImGui::SameLine(); ImGui::PushID("@#$"); ImGui::InputInt("", &debug.DebugBreakID); ImGui::PopID(); ImGui::Separator(); ImGui::Text("Arenas"); ProgressBar("Permanent", shared.Game.PermanentArena.Used, shared.Game.PermanentArena.MaxSize); ProgressBar("Entity", shared.Game.EntityArena.Used, shared.Game.EntityArena.MaxSize); ProgressBar("Transient", shared.Game.TransientArena.Used, shared.Game.TransientArena.MaxSize); } ImGui::End(); RenderLogUI(); RenderRenderSettingsUI(rendering); RenderTexturesUI(rendering); RenderModelsUI(rendering); RenderPuzzlesUI(); RenderCardsUI(rendering); RenderEntitiesUI(); } RenderStatsUI(); } void MeasureFrameEnd() { FrameTimes[FrameTimeIdx] = bx::getHPCounter(); ++FrameTimeIdx; if (FrameTimeIdx >= FrameTimeBufSize) FrameTimeIdx = 0; } } // namespace Tools