diff --git a/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.cpp index 67ebfb03c..a738e755f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.cpp @@ -32,24 +32,8 @@ struct ExpressionTable { bool CombineAdult = false; }; -struct LogicTrackerCheck { - struct Region { - std::string RegionName; - RandomizerRegion RandomizerRegion; - ExpressionTable ExpressionTable; - - bool ChildDayAccess = false; - bool ChildNightAccess = false; - bool AdultDayAccess = false; - bool AdultNightAccess = false; - }; - - std::string CheckName; - std::vector Regions; -}; - -struct LogicTrackerRegion { - struct Entrance { +struct LogicTrackerNode { + struct Connection { std::string ParentName; RandomizerRegion ParentRandomizerRegion; ExpressionTable ExpressionTable; @@ -60,10 +44,15 @@ struct LogicTrackerRegion { bool AdultNightAccess = false; }; - std::string RegionName; - std::vector Entrances; + std::string NodeName; + std::vector Connections; + int NodeId; }; +bool expandingNode = false; +int expandNodeId = -1; +std::vector nodes; + static ExpressionTable::ExpressionRow CreateExpressionRows(const std::shared_ptr& expression) { ExpressionTable::ExpressionRow row; row.Expression = expression; @@ -85,7 +74,6 @@ enum class AgeTime { AdultNight }; - static void PopulateExpressionValues(ExpressionTable::ExpressionRow& row, const ExpressionEvaluation& eval, AgeTime ageTime) { if (ageTime == AgeTime::ChildDay) { @@ -121,161 +109,162 @@ static std::tuple CalculateCombines(const ExpressionTable::Exp return {combineAll, combineChild, combineAdult}; } -bool expandCheck = false; -std::unique_ptr logicTrackerCheck; - void LogicTrackerWindow::ShowRandomizerCheck(RandomizerCheck randomizerCheck) { const auto& location = Rando::StaticData::GetLocation(randomizerCheck); - - logicTrackerCheck = std::make_unique(); - logicTrackerCheck->CheckName = location->GetName(); - //for (const auto& region : areaTable) { + nodes.clear(); + + LogicTrackerNode node; + node.NodeName = location->GetName(); + node.NodeId = nodes.size(); + for (int randomizerRegion = RR_NONE; randomizerRegion < RR_MAX; ++randomizerRegion) { const auto& region = areaTable[randomizerRegion]; for (const auto& locationAccess : region.locations) { if (locationAccess.GetLocation() == randomizerCheck) { - LogicTrackerCheck::Region regionAgeTime; - regionAgeTime.RegionName = region.regionName; - regionAgeTime.RandomizerRegion = RandomizerRegion(randomizerRegion); - regionAgeTime.ExpressionTable.Root = CreateExpressionRows(LogicExpression::Parse(locationAccess.GetConditionStr())); - regionAgeTime.ChildDayAccess = region.childDay; - regionAgeTime.ChildNightAccess = region.childNight; - regionAgeTime.AdultDayAccess = region.adultDay; - regionAgeTime.AdultNightAccess = region.adultNight; + LogicTrackerNode::Connection connection; + connection.ParentName = region.regionName; + connection.ParentRandomizerRegion = RandomizerRegion(randomizerRegion); + connection.ExpressionTable.Root = CreateExpressionRows(LogicExpression::Parse(locationAccess.GetConditionStr())); + connection.ChildDayAccess = region.childDay; + connection.ChildNightAccess = region.childNight; + connection.AdultDayAccess = region.adultDay; + connection.AdultNightAccess = region.adultNight; - if (regionAgeTime.ChildDayAccess) { + if (connection.ChildDayAccess) { logic->IsChild = true; logic->AtDay = true; - const auto& eval = EvaluateExpression(regionAgeTime.ExpressionTable.Root.Expression); - PopulateExpressionValues(regionAgeTime.ExpressionTable.Root, eval, AgeTime::ChildDay); + const auto& eval = EvaluateExpression(connection.ExpressionTable.Root.Expression); + PopulateExpressionValues(connection.ExpressionTable.Root, eval, AgeTime::ChildDay); logic->IsChild = false; logic->AtDay = false; } - if (regionAgeTime.ChildNightAccess) { + if (connection.ChildNightAccess) { logic->IsChild = true; logic->AtNight = true; - const auto& eval = EvaluateExpression(regionAgeTime.ExpressionTable.Root.Expression); - PopulateExpressionValues(regionAgeTime.ExpressionTable.Root, eval, AgeTime::ChildNight); + const auto& eval = EvaluateExpression(connection.ExpressionTable.Root.Expression); + PopulateExpressionValues(connection.ExpressionTable.Root, eval, AgeTime::ChildNight); logic->IsChild = false; logic->AtNight = false; } - if (regionAgeTime.AdultDayAccess) { + if (connection.AdultDayAccess) { logic->IsAdult = true; logic->AtDay = true; - const auto& eval = EvaluateExpression(regionAgeTime.ExpressionTable.Root.Expression); - PopulateExpressionValues(regionAgeTime.ExpressionTable.Root, eval, AgeTime::AdultDay); + const auto& eval = EvaluateExpression(connection.ExpressionTable.Root.Expression); + PopulateExpressionValues(connection.ExpressionTable.Root, eval, AgeTime::AdultDay); logic->IsAdult = false; logic->AtDay = false; } - if (regionAgeTime.AdultNightAccess) { + if (connection.AdultNightAccess) { logic->IsAdult = true; logic->AtNight = true; - const auto& eval = EvaluateExpression(regionAgeTime.ExpressionTable.Root.Expression); - PopulateExpressionValues(regionAgeTime.ExpressionTable.Root, eval, AgeTime::AdultNight); + const auto& eval = EvaluateExpression(connection.ExpressionTable.Root.Expression); + PopulateExpressionValues(connection.ExpressionTable.Root, eval, AgeTime::AdultNight); logic->IsAdult = false; logic->AtNight = false; } - auto [combineAll, combineChild, combineAdult] = CalculateCombines(regionAgeTime.ExpressionTable.Root); - regionAgeTime.ExpressionTable.CombineAll = combineAll; - regionAgeTime.ExpressionTable.CombineChild = combineChild; - regionAgeTime.ExpressionTable.CombineAdult = combineAdult; + auto [combineAll, combineChild, combineAdult] = CalculateCombines(connection.ExpressionTable.Root); + connection.ExpressionTable.CombineAll = combineAll; + connection.ExpressionTable.CombineChild = combineChild; + connection.ExpressionTable.CombineAdult = combineAdult; - logicTrackerCheck->Regions.emplace_back(std::move(regionAgeTime)); + node.Connections.emplace_back(std::move(connection)); } } } + nodes.emplace_back(std::move(node)); + auto window = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Logic Tracker"); window->Show(); ImGui::SetWindowFocus(window->GetName().c_str()); - expandCheck = true; + expandNodeId = node.NodeId; } -bool expandRegion = false; -std::unique_ptr logicTrackerRegion; - void LogicTrackerWindow::ShowRandomizerRegion(RandomizerRegion randomizerRegion) { const auto& region = RegionTable(randomizerRegion); - logicTrackerRegion = std::make_unique(); - logicTrackerRegion->RegionName = region->regionName; + LogicTrackerNode node; + node.NodeName = region->regionName; + node.NodeId = nodes.size(); for (const auto& entrance : region->entrances) { const auto& parentRegion = entrance->GetParentRegion(); - LogicTrackerRegion::Entrance entranceAgeTime; - entranceAgeTime.ParentName = parentRegion->regionName; - entranceAgeTime.ParentRandomizerRegion = entrance->GetParentRegionKey(); - entranceAgeTime.ExpressionTable.Root = + LogicTrackerNode::Connection connection; + connection.ParentName = parentRegion->regionName; + connection.ParentRandomizerRegion = entrance->GetParentRegionKey(); + connection.ExpressionTable.Root = CreateExpressionRows(LogicExpression::Parse(entrance->GetConditionStr())); - entranceAgeTime.ChildDayAccess = parentRegion->childDay; - entranceAgeTime.ChildNightAccess = parentRegion->childNight; - entranceAgeTime.AdultDayAccess = parentRegion->adultDay; - entranceAgeTime.AdultNightAccess = parentRegion->adultNight; + connection.ChildDayAccess = parentRegion->childDay; + connection.ChildNightAccess = parentRegion->childNight; + connection.AdultDayAccess = parentRegion->adultDay; + connection.AdultNightAccess = parentRegion->adultNight; - if (entranceAgeTime.ChildDayAccess) { + if (connection.ChildDayAccess) { logic->IsChild = true; logic->AtDay = true; - const auto& eval = EvaluateExpression(entranceAgeTime.ExpressionTable.Root.Expression); - PopulateExpressionValues(entranceAgeTime.ExpressionTable.Root, eval, AgeTime::ChildDay); + const auto& eval = EvaluateExpression(connection.ExpressionTable.Root.Expression); + PopulateExpressionValues(connection.ExpressionTable.Root, eval, AgeTime::ChildDay); logic->IsChild = false; logic->AtDay = false; } - if (entranceAgeTime.ChildNightAccess) { + if (connection.ChildNightAccess) { logic->IsChild = true; logic->AtNight = true; - const auto& eval = EvaluateExpression(entranceAgeTime.ExpressionTable.Root.Expression); - PopulateExpressionValues(entranceAgeTime.ExpressionTable.Root, eval, AgeTime::ChildNight); + const auto& eval = EvaluateExpression(connection.ExpressionTable.Root.Expression); + PopulateExpressionValues(connection.ExpressionTable.Root, eval, AgeTime::ChildNight); logic->IsChild = false; logic->AtNight = false; } - if (entranceAgeTime.AdultDayAccess) { + if (connection.AdultDayAccess) { logic->IsAdult = true; logic->AtDay = true; - const auto& eval = EvaluateExpression(entranceAgeTime.ExpressionTable.Root.Expression); - PopulateExpressionValues(entranceAgeTime.ExpressionTable.Root, eval, AgeTime::AdultDay); + const auto& eval = EvaluateExpression(connection.ExpressionTable.Root.Expression); + PopulateExpressionValues(connection.ExpressionTable.Root, eval, AgeTime::AdultDay); logic->IsAdult = false; logic->AtDay = false; } - if (entranceAgeTime.AdultNightAccess) { + if (connection.AdultNightAccess) { logic->IsAdult = true; logic->AtNight = true; - const auto& eval = EvaluateExpression(entranceAgeTime.ExpressionTable.Root.Expression); - PopulateExpressionValues(entranceAgeTime.ExpressionTable.Root, eval, AgeTime::AdultNight); + const auto& eval = EvaluateExpression(connection.ExpressionTable.Root.Expression); + PopulateExpressionValues(connection.ExpressionTable.Root, eval, AgeTime::AdultNight); logic->IsAdult = false; logic->AtNight = false; } - auto [combineAll, combineChild, combineAdult] = CalculateCombines(entranceAgeTime.ExpressionTable.Root); - entranceAgeTime.ExpressionTable.CombineAll = combineAll; - entranceAgeTime.ExpressionTable.CombineChild = combineChild; - entranceAgeTime.ExpressionTable.CombineAdult = combineAdult; + auto [combineAll, combineChild, combineAdult] = CalculateCombines(connection.ExpressionTable.Root); + connection.ExpressionTable.CombineAll = combineAll; + connection.ExpressionTable.CombineChild = combineChild; + connection.ExpressionTable.CombineAdult = combineAdult; - logicTrackerRegion->Entrances.emplace_back(std::move(entranceAgeTime)); + node.Connections.emplace_back(std::move(connection)); } + nodes.emplace_back(std::move(node)); + auto window = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Logic Tracker"); window->Show(); ImGui::SetWindowFocus(window->GetName().c_str()); - expandRegion = true; + expandNodeId = node.NodeId; } static std::string ToString(const std::optional& value) { @@ -459,12 +448,9 @@ static void DrawExpressionTable(ExpressionTable& table) { ImGui::EndTable(); } -static void DrawCheckRegion(LogicTrackerCheck::Region& region) { - ImGui::SeparatorText(("Region: " + region.RegionName).c_str()); - - ImGui::TextUnformatted("Region Access:"); - - if (ImGui::BeginTable(("Region Access: " + region.RegionName).c_str(), 4, +static void DrawNodeConnection(LogicTrackerNode& node, LogicTrackerNode::Connection& connection) { + ImGui::TextUnformatted("Parent Access:"); + if (ImGui::BeginTable(("##" + connection.ParentName).c_str(), 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoHostExtendX)) { ImGui::TableSetupColumn("Child Day", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("Child Night", ImGuiTableColumnFlags_WidthFixed); @@ -473,111 +459,72 @@ static void DrawCheckRegion(LogicTrackerCheck::Region& region) { ImGui::TableHeadersRow(); ImGui::TableNextRow(); - + ImGui::PushFont(OTRGlobals::Instance->fontMono); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(region.ChildDayAccess ? "true" : "false"); ImGui::TableNextColumn(); - ImGui::TextUnformatted(region.ChildNightAccess ? "true" : "false"); + ImGui::TextUnformatted(connection.ChildDayAccess ? "true" : "false"); ImGui::TableNextColumn(); - ImGui::TextUnformatted(region.AdultDayAccess ? "true" : "false"); + ImGui::TextUnformatted(connection.ChildNightAccess ? "true" : "false"); ImGui::TableNextColumn(); - ImGui::TextUnformatted(region.AdultNightAccess ? "true" : "false"); + ImGui::TextUnformatted(connection.AdultDayAccess ? "true" : "false"); + + ImGui::TableNextColumn(); + ImGui::TextUnformatted(connection.AdultNightAccess ? "true" : "false"); + ImGui::PopFont(); ImGui::EndTable(); } - ImGui::SameLine(); - if (ImGui::Button(("Show Entrance Logic##" + region.RegionName).c_str())) { - LogicTrackerWindow::ShowRandomizerRegion(region.RandomizerRegion); + if (connection.ParentRandomizerRegion != RR_NONE) { + ImGui::SameLine(); + if (ImGui::Button(("Show Region Logic##" + connection.ParentName).c_str())) { + while (nodes.back().NodeId > node.NodeId) { + nodes.pop_back(); + } + + LogicTrackerWindow::ShowRandomizerRegion(connection.ParentRandomizerRegion); + } } - ImGui::Dummy(ImVec2(0.0f, 10.0f)); - - ImGui::TextUnformatted("Check Access:"); - DrawExpressionTable(region.ExpressionTable); + ImGui::TextUnformatted("Node Access:"); + DrawExpressionTable(connection.ExpressionTable); } -static void DrawCheck() { - if (expandCheck) { - expandCheck = false; - ImGui::SetNextItemOpen(true, ImGuiCond_Always); +static void DrawNode(LogicTrackerNode& node) { + if (expandingNode) { + ImGui::SetNextItemOpen(expandNodeId == node.NodeId, ImGuiCond_Always); } - if (ImGui::CollapsingHeader(("Check: " + (logicTrackerCheck != nullptr ? logicTrackerCheck->CheckName : "")).c_str(), ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_SpanFullWidth)) { - if (logicTrackerCheck->Regions.empty()) { - ImGui::Text("No regions found for this check."); - return; - } - for (auto& region : logicTrackerCheck->Regions) { - DrawCheckRegion(region); - ImGui::Dummy(ImVec2(0.0f, 20.0f)); - } - } -} - -static void DrawRegionEntrance(LogicTrackerRegion::Entrance& entrance) { - ImGui::SeparatorText(("Entrance: " + entrance.ParentName).c_str()); - ImGui::TextUnformatted("Entrance Access:"); - if (ImGui::BeginTable(("Entrance Access: " + entrance.ParentName).c_str(), 4, - ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoHostExtendX)) { - ImGui::TableSetupColumn("Child Day", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("Child Night", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("Adult Day", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("Adult Night", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableHeadersRow(); - - ImGui::TableNextRow(); - - ImGui::PushFont(OTRGlobals::Instance->fontMono); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(entrance.ChildDayAccess ? "true" : "false"); - - ImGui::TableNextColumn(); - ImGui::TextUnformatted(entrance.ChildNightAccess ? "true" : "false"); - - ImGui::TableNextColumn(); - ImGui::TextUnformatted(entrance.AdultDayAccess ? "true" : "false"); - - ImGui::TableNextColumn(); - ImGui::TextUnformatted(entrance.AdultNightAccess ? "true" : "false"); - ImGui::PopFont(); - - ImGui::EndTable(); - } - - ImGui::SameLine(); - if (ImGui::Button(("Show Region Logic##" + entrance.ParentName).c_str())) { - LogicTrackerWindow::ShowRandomizerRegion(entrance.ParentRandomizerRegion); - } - - ImGui::Dummy(ImVec2(0.0f, 10.0f)); - DrawExpressionTable(entrance.ExpressionTable); -} - -static void DrawRegion() { - if (expandRegion) { - expandRegion = false; - ImGui::SetNextItemOpen(true, ImGuiCond_Always); - } - if (ImGui::CollapsingHeader(("Region: " + (logicTrackerRegion != nullptr ? logicTrackerRegion->RegionName : "")).c_str(), ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_SpanFullWidth)) { - if (logicTrackerRegion->Entrances.empty()) { - ImGui::Text("No entrances found for this region."); - return; - } - for (auto& entrance : logicTrackerRegion->Entrances) { - DrawRegionEntrance(entrance); - ImGui::Dummy(ImVec2(0.0f, 20.0f)); + + if (ImGui::CollapsingHeader(node.NodeName.c_str(), + ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_SpanFullWidth)) { + ImGui::Indent(25.0f); + for (int i = 0; i < node.Connections.size(); i++) { + if (ImGui::CollapsingHeader(node.Connections[i].ParentName.c_str(), ImGuiTreeNodeFlags_AllowOverlap | + ImGuiTreeNodeFlags_SpanAvailWidth)) { + DrawNodeConnection(node, node.Connections[i]); + } } + ImGui::Unindent(25.0f); } } void LogicTrackerWindow::DrawElement() { - DrawCheck(); - DrawRegion(); + if (expandNodeId != -1) { + expandingNode = true; + } + + for (LogicTrackerNode& node : nodes) { + DrawNode(node); + } + + if (expandingNode) { + expandNodeId = -1; + expandingNode = false; + } } void LogicTrackerWindow::InitElement() {