Skip to content

Commit 2dae72e

Browse files
committed
Add feature to cycle through recipes and item by clicking on left panel
1 parent b073d43 commit 2dae72e

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed

emscripten/shell_index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ <h3 class="app-name">Changelog</h3>
123123
"The current graph is automatically saved on exit",
124124
"Pins can't be locked inside a group node, but a full group node can be locked",
125125
"You can duplicate all selected nodes using Ctrl + D",
126+
"You can quickly find a given recipe in a graph by clicking on it on the left panel",
127+
"You can quickly find a given item in a graph by clicking on it on the left panel",
126128
];
127129

128130
function updateTip() {

ficsit-companion/include/app.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ class App
104104
void RenderControlsPopup();
105105
/// @brief React to app-specific key pressed
106106
void CustomKeyControl();
107+
/// @brief Focus the view on the next recipe with the corresponding name
108+
/// @param recipe Name of the recipe to search
109+
void FocusNextRecipe(const std::string& recipe);
110+
/// @brief Focus the view on the next item with the corresponding name
111+
/// @param item Name of the item to search
112+
void FocusNextItem(const std::string& item);
107113

108114
private:
109115
/// @brief Used in saved files to track when format change. Used to update files saved with previous versions
@@ -162,4 +168,11 @@ class App
162168
std::chrono::steady_clock::time_point last_time_interacted;
163169

164170
float error_time;
171+
172+
// Used to cycle through the nodes when clicking on the corresponding
173+
// element on the left panel
174+
std::string last_clicked_recipe;
175+
int next_clicked_recipe;
176+
std::string last_clicked_item;
177+
int next_clicked_item;
165178
};

ficsit-companion/src/app.cpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ App::App()
109109

110110
error_time = 0.0f;
111111

112+
last_clicked_recipe = "";
113+
next_clicked_recipe = 0;
114+
last_clicked_item = "";
115+
next_clicked_item = 0;
116+
112117
LoadSettings();
113118
}
114119

@@ -1989,6 +1994,10 @@ void App::RenderLeftPanel()
19891994
ImGui::Text("%sMW", recipe->building->variable_power ? "~" : "");
19901995
ImGui::SameLine();
19911996
recipe->Render();
1997+
if (ImGui::IsItemClicked())
1998+
{
1999+
FocusNextRecipe(recipe->name);
2000+
}
19922001
}
19932002

19942003
ImGui::Unindent();
@@ -2026,12 +2035,20 @@ void App::RenderLeftPanel()
20262035
p.RenderInputText("##sink_points", true, true, sink_points_width);
20272036
ImGui::SameLine();
20282037
ImGui::Image((void*)(intptr_t)item->icon_gl_index, ImVec2(ImGui::GetTextLineHeightWithSpacing(), ImGui::GetTextLineHeightWithSpacing()));
2038+
if (ImGui::IsItemClicked())
2039+
{
2040+
FocusNextItem(item->name);
2041+
}
20292042
ImGui::SameLine();
20302043
ImGui::TextUnformatted(item->name.c_str());
20312044
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
20322045
{
20332046
ImGui::SetTooltip("%s", item->name.c_str());
20342047
}
2048+
if (ImGui::IsItemClicked())
2049+
{
2050+
FocusNextItem(item->name);
2051+
}
20352052
}
20362053
ImGui::Unindent();
20372054
ImGui::TreePop();
@@ -2081,6 +2098,10 @@ void App::RenderLeftPanel()
20812098
ImGui::SameLine();
20822099

20832100
recipe->Render();
2101+
if (ImGui::IsItemClicked())
2102+
{
2103+
FocusNextRecipe(recipe->name);
2104+
}
20842105
}
20852106

20862107
ImGui::Unindent();
@@ -2121,8 +2142,16 @@ void App::RenderLeftPanel()
21212142
n.RenderInputText("##rate", true, true, rate_width);
21222143
ImGui::SameLine();
21232144
ImGui::Image((void*)(intptr_t)item->icon_gl_index, ImVec2(ImGui::GetTextLineHeightWithSpacing(), ImGui::GetTextLineHeightWithSpacing()));
2145+
if (ImGui::IsItemClicked())
2146+
{
2147+
FocusNextItem(item->name);
2148+
}
21242149
ImGui::SameLine();
21252150
ImGui::TextUnformatted(item->name.c_str());
2151+
if (ImGui::IsItemClicked())
2152+
{
2153+
FocusNextItem(item->name);
2154+
}
21262155
}
21272156

21282157
ImGui::SeparatorText("Outputs");
@@ -2151,8 +2180,16 @@ void App::RenderLeftPanel()
21512180
n.RenderInputText("##rate", true, true, rate_width);
21522181
ImGui::SameLine();
21532182
ImGui::Image((void*)(intptr_t)item->icon_gl_index, ImVec2(ImGui::GetTextLineHeightWithSpacing(), ImGui::GetTextLineHeightWithSpacing()));
2183+
if (ImGui::IsItemClicked())
2184+
{
2185+
FocusNextItem(item->name);
2186+
}
21542187
ImGui::SameLine();
21552188
ImGui::TextUnformatted(item->name.c_str());
2189+
if (ImGui::IsItemClicked())
2190+
{
2191+
FocusNextItem(item->name);
2192+
}
21562193
}
21572194

21582195
ImGui::SeparatorText("Intermediates");
@@ -2169,8 +2206,16 @@ void App::RenderLeftPanel()
21692206
n.RenderInputText("##rate", true, true, rate_width);
21702207
ImGui::SameLine();
21712208
ImGui::Image((void*)(intptr_t)item->icon_gl_index, ImVec2(ImGui::GetTextLineHeightWithSpacing(), ImGui::GetTextLineHeightWithSpacing()));
2209+
if (ImGui::IsItemClicked())
2210+
{
2211+
FocusNextItem(item->name);
2212+
}
21722213
ImGui::SameLine();
21732214
ImGui::TextUnformatted(item->name.c_str());
2215+
if (ImGui::IsItemClicked())
2216+
{
2217+
FocusNextItem(item->name);
2218+
}
21742219
}
21752220
}
21762221

@@ -3502,3 +3547,82 @@ void App::CustomKeyControl()
35023547
}
35033548
}
35043549
}
3550+
3551+
void App::FocusNextRecipe(const std::string& recipe)
3552+
{
3553+
if (recipe != last_clicked_recipe)
3554+
{
3555+
last_clicked_recipe = recipe;
3556+
next_clicked_recipe = 0;
3557+
}
3558+
3559+
// Get all matching nodes
3560+
std::vector<const Node*> matching_nodes;
3561+
for (const auto& n : nodes)
3562+
{
3563+
if (n->IsCraft() && static_cast<CraftNode*>(n.get())->recipe->name == recipe)
3564+
{
3565+
matching_nodes.push_back(n.get());
3566+
}
3567+
}
3568+
3569+
if (matching_nodes.size() == 0)
3570+
{
3571+
return;
3572+
}
3573+
3574+
ax::NodeEditor::SelectNode(matching_nodes[next_clicked_recipe % matching_nodes.size()]->id);
3575+
ax::NodeEditor::NavigateToSelection();
3576+
ax::NodeEditor::DeselectNode(matching_nodes[next_clicked_recipe % matching_nodes.size()]->id);
3577+
next_clicked_recipe = (next_clicked_recipe + 1) % matching_nodes.size();
3578+
}
3579+
3580+
void App::FocusNextItem(const std::string& item)
3581+
{
3582+
if (item != last_clicked_item)
3583+
{
3584+
last_clicked_item = item;
3585+
next_clicked_item = 0;
3586+
}
3587+
3588+
// Get all matching nodes
3589+
std::vector<const Node*> matching_nodes;
3590+
for (const auto& n : nodes)
3591+
{
3592+
bool has_item = false;
3593+
for (const auto& p : n->ins)
3594+
{
3595+
if (p->item != nullptr && p->item->name == item)
3596+
{
3597+
has_item = true;
3598+
break;
3599+
}
3600+
}
3601+
if (!has_item)
3602+
{
3603+
for (const auto& p : n->outs)
3604+
{
3605+
if (p->item != nullptr && p->item->name == item)
3606+
{
3607+
has_item = true;
3608+
break;
3609+
}
3610+
}
3611+
}
3612+
3613+
if (has_item)
3614+
{
3615+
matching_nodes.push_back(n.get());
3616+
}
3617+
}
3618+
3619+
if (matching_nodes.size() == 0)
3620+
{
3621+
return;
3622+
}
3623+
3624+
ax::NodeEditor::SelectNode(matching_nodes[next_clicked_item % matching_nodes.size()]->id);
3625+
ax::NodeEditor::NavigateToSelection();
3626+
ax::NodeEditor::DeselectNode(matching_nodes[next_clicked_item % matching_nodes.size()]->id);
3627+
next_clicked_item = (next_clicked_item + 1) % matching_nodes.size();
3628+
}

0 commit comments

Comments
 (0)