RigsofRods
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
GUI_MainSelector.cpp
Go to the documentation of this file.
1 /*
2  This source file is part of Rigs of Rods
3  Copyright 2005-2012 Pierre-Michel Ricordel
4  Copyright 2007-2012 Thomas Fischer
5  Copyright 2013-2019 Petr Ohlidal
6 
7  For more information, see http://www.rigsofrods.org/
8 
9  Rigs of Rods is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License version 3, as
11  published by the Free Software Foundation.
12 
13  Rigs of Rods is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "GUI_MainSelector.h"
23 
24 #include "Application.h"
25 #include "ActorManager.h"
26 #include "CacheSystem.h"
27 #include "ContentManager.h"
28 #include "GameContext.h"
29 #include "GUIManager.h"
30 #include "GUIUtils.h"
31 #include "GUI_LoadingWindow.h"
32 #include "InputEngine.h"
33 #include "Language.h"
34 #include "ScriptEngine.h"
35 #include "Utils.h"
36 
37 #include <MyGUI.h>
38 #include <imgui.h>
39 #include <imgui_internal.h>
40 
41 using namespace RoR;
42 using namespace GUI;
43 
44 // MAIN SELECTOR WINDOW
45 // --------------------
46 // KEY CONTROLS
47 // tab: toggle search box focus (FIXME: currently, only focusing works)
48 // arrow left/right: if search box is not in focus, select previous(left) or next(right) category in "categories" combobox, wrap around when at either end.
49 // arrow up/down: select prev/next entry. When already on top/bottom item, wrap to other end of the list.
50 // enter: activate highlighted entry
51 // SEARCHING
52 // The result list is sorted descending by 'score'.
53 // Syntax 'abcdef': searches fulltext (ingoring case) in: name, filename, description, author name/mail (in this order, with descending rank) and returns rank+string pos as score
54 // Syntax 'AREA:abcdef': searches (ignoring case) in AREA: 'guid'(guid string), 'author' (name/email), 'wheels' (string "WHEELCOUNTxPROPWHEELCOUNT"), 'file' (filename); returns string pos as score
55 
57 {
58  // Constructs `CacheEntryPtr` - doesn't compile without `#include CacheSystem.h` - not pretty if in header (even if auto-generated by C++).
59 }
60 
62 {
63  // Destructs `CacheEntryPtr` - doesn't compile without `#include CacheSystem.h` - not pretty if in header (even if auto-generated by C++).
64 }
65 
66 void MainSelector::Show(LoaderType type, std::string const& filter_guid, CacheEntryPtr advertised_entry)
67 {
68  m_loader_type = type;
71  m_search_string.clear();
72  m_filter_guid = filter_guid;
73  m_advertised_entry = advertised_entry;
75  if (m_selected_cid == 0)
77  this->UpdateDisplayLists();
79  {
81  }
83  {
85  }
86 }
87 
89 {
91 
92  ImGuiWindowFlags win_flags = ImGuiWindowFlags_NoCollapse;
93  ImGui::SetNextWindowPosCenter(ImGuiCond_FirstUseEver);
94  ImGui::SetNextWindowSize(ImVec2((ImGui::GetIO().DisplaySize.x / 1.4), (ImGui::GetIO().DisplaySize.y / 1.2)), ImGuiCond_FirstUseEver);
95  bool keep_open = true;
96  if (!ImGui::Begin(_LC("MainSelector", "Loader"), &keep_open, win_flags))
97  {
98  return;
99  }
100 
102 
103  // category keyboard control
104  const int num_categories = static_cast<int>(m_display_categories.size());
106  {
107  if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
108  {
109  m_selected_category = (m_selected_category + 1) % num_categories; // select next item and wrap around at bottom.
113  this->UpdateDisplayLists();
114  }
115  else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
116  {
117  m_selected_category = (m_selected_category > 0) ? (m_selected_category - 1) : (num_categories - 1); // select prev. item and wrap around on top
121  this->UpdateDisplayLists();
122  }
123  }
124 
125  // category combobox
126  ImGui::PushItemWidth(LEFT_PANE_WIDTH);
127  if (ImGui::Combo(
128  "##SelectorCategory", &m_selected_category,
130  {
134  this->UpdateDisplayLists();
135  }
136  ImGui::PopItemWidth();
137  ImGui::SameLine();
138 
139  // search box
140  const ImVec2 searchbox_cursor = ImGui::GetCursorPos();
141  const float searchbox_width = ImGui::GetWindowWidth() -
142  (LEFT_PANE_WIDTH + 2 * (ImGui::GetStyle().WindowPadding.x) + ImGui::GetStyle().ItemSpacing.x);
143 
144  if (m_kb_focused == true)
145  {
146  ImGui::SetKeyboardFocusHere();
147  m_kb_focused = false;
148  }
149 
150  if (!m_searchbox_was_active && (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Tab)) || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Slash))))
151  {
152  ImGui::SetKeyboardFocusHere();
153  }
154  ImGui::PushItemWidth(searchbox_width);
155  if (ImGui::InputText("##SelectorSearch", m_search_input.GetBuffer(), m_search_input.GetCapacity()))
156  {
157  m_selected_category = 0; // 'All'
159  this->UpdateSearchParams();
160  this->UpdateDisplayLists();
161  }
162  ImGui::PopItemWidth();
163  m_searchbox_was_active = ImGui::IsItemActive();
164  const ImVec2 separator_cursor = ImGui::GetCursorPos()
165  + ImVec2(0, ImGui::GetStyle().WindowPadding.y - ImGui::GetStyle().ItemSpacing.y);
166 
167  // advanced search hint
168  const char* searchbox_hint = "(?)";
169  ImGui::SetCursorPos(searchbox_cursor + ImVec2(searchbox_width - (ImGui::CalcTextSize(searchbox_hint).x + ImGui::GetStyle().FramePadding.x), ImGui::GetStyle().FramePadding.y));
170  ImGui::TextDisabled(searchbox_hint);
171  if (ImGui::IsItemHovered())
172  {
173  ImGui::BeginTooltip();
174  ImGui::TextDisabled("Fulltext search:");
175  ImGui::Text("~ partial name, filename, description, author name or e-mail");
176  ImGui::TextDisabled("Advanced search:");
177  ImGui::Text("guid: ~ partial GUID");
178  ImGui::Text("author: ~ partial author name or e-mail");
179  ImGui::Text("wheels: ~ wheel configuration (i.e. 4x4)");
180  ImGui::Text("file: ~ partial file name");
181  ImGui::EndTooltip();
182  }
183 
184  ImGui::SetCursorPos(separator_cursor);
185  ImGui::Separator();
186 
187  // left
188  ImGui::BeginChild("left pane", ImVec2(LEFT_PANE_WIDTH, 0), true);
189  const int num_entries = static_cast<int>(m_display_entries.size());
190  bool scroll_to_selected = false;
191  // Entry list: handle keyboard
192  if (m_selected_entry != -1) // -1 indicates empty entry-list
193  {
194  if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)))
195  {
196  m_selected_entry = (m_selected_entry + 1) % num_entries; // select next item and wrap around at bottom.
198  scroll_to_selected = true;
199  }
200  else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)))
201  {
202  m_selected_entry = (m_selected_entry > 0) ? (m_selected_entry - 1) : (num_entries - 1); // select prev. item and wrap around on top
204  scroll_to_selected = true;
205  }
206  }
207  // Entry list: display
208  ImDrawList* drawlist = ImGui::GetWindowDrawList();
209  drawlist->ChannelsSplit(2); // 0=background selection indicator, 1=text
210  bool do_apply = false;
211  for (int i = 0; i < num_entries; ++i)
212  {
213  DisplayEntry& d_entry = m_display_entries[i];
214  bool is_selected = (i == m_selected_entry);
215 
216  // Draw text manually to enable coloring.
217  drawlist->ChannelsSetCurrent(1);
218  ImVec2 size = RoR::DrawColorMarkedText(drawlist, ImGui::GetCursorScreenPos(),
219  ImGui::GetStyle().Colors[ImGuiCol_Text],
220  /*override_alpha=*/1.f, /*wrap_width=*/-1.f,
221  d_entry.sde_entry->dname.c_str());
222 
223  ImGui::PushID(i);
224  drawlist->ChannelsSetCurrent(0);
225  ImVec2 mouse_area(LEFT_PANE_WIDTH, size.y); // Monitor the whole line (excess width gets clipped)
226  if (ImGui::Selectable("##dummy", &is_selected, 0, mouse_area)) // Use invisible label + size parameter.
227  {
228  m_selected_entry = i;
231  }
232  if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) // Left doubleclick
233  {
234  m_selected_entry = i;
237  do_apply = true;
238  }
239  if (is_selected && scroll_to_selected)
240  {
241  ImGui::SetScrollHere();
242  }
243  ImGui::PopID();
244  }
245 
246  if (do_apply)
247  {
248  this->Apply();
249  }
250  drawlist->ChannelsMerge();
251  ImGui::EndChild();
252  ImGui::SameLine();
253 
254  // right
255  ImGui::BeginGroup();
256 
257  ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us
258 
259  if (m_selected_entry != -1)
260  {
262 
263  // Preview image
264  if (!sd_entry.sde_entry->filecachename.empty())
265  {
266  ImVec2 cursor_pos = ImGui::GetCursorPos();
267  try
268  {
269  Ogre::TexturePtr preview_tex =
270  Ogre::TextureManager::getSingleton().load(
271  sd_entry.sde_entry->filecachename, Ogre::RGN_DEFAULT);
272  if (preview_tex)
273  {
274  // Scale the image (for dashboards only shrink but don't enlarge so players see actual in-game size).
275  ImVec2 max_size = (ImGui::GetWindowSize() * PREVIEW_SIZE_RATIO);
276  ImVec2 size(preview_tex->getWidth(), preview_tex->getHeight());
277  if (m_loader_type != LT_DashBoard || size.x > max_size.x)
278  {
279  size *= max_size.x / size.x; // Fit size along X
280  if (size.y > max_size.y) // Reduce size along Y if needed
281  {
282  size *= max_size.y / size.y;
283  }
284  }
285  // Draw the image
286  ImGui::SetCursorPos((cursor_pos + ImGui::GetWindowSize()) - size);
287  ImGui::Image(reinterpret_cast<ImTextureID>(preview_tex->getHandle()), size);
288  ImGui::SetCursorPos(cursor_pos);
289  }
290  }
291  catch(...)
292  {
293  // Invalid texture file - OGRE exception already logged
294  }
295  }
296 
297  // Title and description
299  ImGui::TextWrapped("%s", sd_entry.sde_entry->description.c_str());
300  ImGui::Separator();
301 
302  // Details
303  for (AuthorInfo const& author: sd_entry.sde_entry->authors)
304  {
305  ImGui::TextDisabled("%s", _LC("MainSelector", "Author(s): "));
306  ImGui::SameLine();
307  ImGui::TextColored(theme.value_blue_text_color, "%s [%s]", author.name.c_str(), author.type.c_str());
308  }
309  this->DrawAttrInt(_LC("MainSelector", "Version: "), sd_entry.sde_entry->version);
310  if (sd_entry.sde_entry->wheelcount > 0)
311  {
312  ImGui::Text("%s", _LC("MainSelector", "Wheels: "));
313  ImGui::SameLine();
314  ImGui::TextColored(theme.value_blue_text_color, "%dx%d", sd_entry.sde_entry->wheelcount, sd_entry.sde_entry->propwheelcount);
315  }
316  if (sd_entry.sde_entry->truckmass > 0)
317  {
318  ImGui::Text("%s", _LC("MainSelector", "Mass: "));
319  ImGui::SameLine();
320  ImGui::TextColored(theme.value_blue_text_color, "%.2f t", Round(sd_entry.sde_entry->truckmass / 1000.0f, 3));
321  }
322 
323  if (m_show_details)
324  {
325  if (sd_entry.sde_entry->loadmass > 0)
326  {
327  ImGui::Text("%s", _LC("MainSelector", "Load Mass: "));
328  ImGui::SameLine();
329  ImGui::TextColored(theme.value_blue_text_color, "%f.2 t", Round(sd_entry.sde_entry->loadmass / 1000.0f, 3));
330  }
331  this->DrawAttrInt(_LC("MainSelector", "Nodes: "), sd_entry.sde_entry->nodecount);
332  this->DrawAttrInt(_LC("MainSelector", "Beams: "), sd_entry.sde_entry->beamcount);
333  this->DrawAttrInt(_LC("MainSelector", "Shocks: "), sd_entry.sde_entry->shockcount);
334  this->DrawAttrInt(_LC("MainSelector", "Hydros: "), sd_entry.sde_entry->hydroscount);
335  this->DrawAttrInt(_LC("MainSelector", "SoundSources: "), sd_entry.sde_entry->soundsourcescount);
336  this->DrawAttrInt(_LC("MainSelector", "Commands: "), sd_entry.sde_entry->commandscount);
337  this->DrawAttrInt(_LC("MainSelector", "Rotators: "), sd_entry.sde_entry->rotatorscount);
338  this->DrawAttrInt(_LC("MainSelector", "Exhausts: "), sd_entry.sde_entry->exhaustscount);
339  this->DrawAttrInt(_LC("MainSelector", "Flares: "), sd_entry.sde_entry->flarescount);
340  this->DrawAttrInt(_LC("MainSelector", "Flexbodies: "), sd_entry.sde_entry->flexbodiescount);
341  this->DrawAttrInt(_LC("MainSelector", "Props: "), sd_entry.sde_entry->propscount);
342  this->DrawAttrInt(_LC("MainSelector", "Wings: "), sd_entry.sde_entry->wingscount);
343  if (sd_entry.sde_entry->hasSubmeshs)
344  {
345  ImGui::Text("%s", _LC("MainSelector", "Using Submeshs: "));
346  ImGui::SameLine();
347  ImGui::TextColored(theme.value_blue_text_color, "%s", sd_entry.sde_entry->hasSubmeshs ?_LC("MainSelector", "Yes") : _LC("MainSelector", "No"));
348  }
349  if (sd_entry.sde_entry->default_skin != "")
350  {
351  ImGui::Text("%s", _LC("MainSelector", "Default skin: "));
352  ImGui::SameLine();
353  ImGui::TextColored(theme.value_blue_text_color, "%s", sd_entry.sde_entry->default_skin.c_str());
354  }
355  this->DrawAttrFloat(_LC("MainSelector", "Torque: "), sd_entry.sde_entry->torque);
356  this->DrawAttrInt(_LC("MainSelector", "Transmission Gear Count: "), sd_entry.sde_entry->numgears);
357  if (sd_entry.sde_entry->minrpm > 0)
358  {
359  ImGui::Text("%s", _LC("MainSelector", "Engine RPM: "));
360  ImGui::SameLine();
361  ImGui::TextColored(theme.value_blue_text_color, "%f - %f", sd_entry.sde_entry->minrpm, sd_entry.sde_entry->maxrpm);
362  }
363  this->DrawAttrStr(_LC("MainSelector", "Unique ID: "), sd_entry.sde_entry->uniqueid);
364  this->DrawAttrStr(_LC("MainSelector", "GUID: "), sd_entry.sde_entry->guid);
365  this->DrawAttrInt(_LC("MainSelector", "Times used: "), sd_entry.sde_entry->usagecounter);
366  this->DrawAttrStr(_LC("MainSelector", "Date and Time modified: "), sd_entry.sde_filetime_str.ToCStr());
367  this->DrawAttrStr(_LC("MainSelector", "Date and Time installed: "), sd_entry.sde_addtime_str.ToCStr());
369  {
370  this->DrawAttrStr(_LC("MainSelector", "Vehicle Type: "), sd_entry.sde_driveable_str.ToCStr());
371  }
372 
373  this->DrawAttrSpecial(sd_entry.sde_entry->forwardcommands, _LC("MainSelector", "[forwards commands]"));
374  this->DrawAttrSpecial(sd_entry.sde_entry->importcommands, _LC("MainSelector", "[imports commands]"));
375  this->DrawAttrSpecial(sd_entry.sde_entry->rescuer, _LC("MainSelector", "[is rescuer]"));
376  this->DrawAttrSpecial(sd_entry.sde_entry->custom_particles, _LC("MainSelector", "[uses custom particles]"));
377  this->DrawAttrSpecial(sd_entry.sde_entry->fixescount > 0, _LC("MainSelector", "[has fixes]"));
378  // Engine type 't' (truck) is the default, do not display it
379  this->DrawAttrSpecial(sd_entry.sde_entry->enginetype == 'c', _LC("MainSelector", "[car engine]"));
380  this->DrawAttrSpecial(sd_entry.sde_entry->resource_bundle_type == "Zip", _LC("MainSelector", "[zip archive]"));
381  this->DrawAttrSpecial(sd_entry.sde_entry->resource_bundle_type == "FileSystem", _LC("MainSelector", "[unpacked in directory]"));
382 
383  if (!sd_entry.sde_entry->resource_bundle_path.empty())
384  {
385  ImGui::Text("%s", _LC("MainSelector", "Source: "));
386  ImGui::SameLine();
387  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color,
388  "%s", sd_entry.sde_entry->resource_bundle_path.c_str());
389  }
390  if (!sd_entry.sde_entry->fname.empty())
391  {
392  ImGui::Text("%s", _LC("MainSelector", "Filename: "));
393  ImGui::SameLine();
394  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color,
395  "%s", sd_entry.sde_entry->fname.c_str());
396  }
397  }
398  ImGui::Checkbox(_LC("MainSelector", "Show details"), &m_show_details);
399  }
400  ImGui::EndChild();
401 
402  ImGui::BeginChild("buttons");
403  if (m_selected_entry != -1)
404  {
406  if (sd_entry.sde_entry->sectionconfigs.size() > 0)
407  {
408  ImGui::PushItemWidth(ImGui::GetWindowWidth() / 2);
409  ImGui::Combo(_LC("MainSelector", "Configuration"), &m_selected_sectionconfig,
411  static_cast<int>(sd_entry.sde_entry->sectionconfigs.size()));
412  ImGui::SameLine();
413  }
414  ImGui::SameLine(ImGui::GetWindowWidth()-280);
415  if (ImGui::Button(_LC("MainSelector", "OK"), ImVec2(120.f, 0.0f)) ||
416  ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))
417  {
418  this->Apply();
419  }
420  }
421  ImGui::SameLine(ImGui::GetWindowWidth()-150);
422  if (ImGui::Button(_LC("MainSelector", "Cancel"), ImVec2(120.f, 0.0f)) || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape)))
423  {
424  this->Cancel();
425  }
426  ImGui::EndChild();
427 
428  ImGui::EndGroup();
429 
430  m_is_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
431 
432  ImGui::End();
433  if (!keep_open)
434  {
435  this->Cancel();
436  }
437 };
438 
439 template <typename T1, typename T2>
440 struct sort_cats
441 {
442  bool operator ()(std::pair<int, Ogre::String> const& a, std::pair<int, Ogre::String> const& b) const
443  {
444  if (a.first == CID_All)
445  return true;
446  if (b.first == CID_All)
447  return false;
448  if (a.first == CID_Fresh)
449  return true;
450  if (b.first == CID_Fresh)
451  return false;
452  return a.second < b.second;
453  }
454 };
455 
456 
458 {
459  m_display_categories.clear();
460  m_display_entries.clear();
461 
462  if (m_advertised_entry)
463  {
465  m_selected_entry = 0;
466  }
467 
468  // Find all relevant entries
469  CacheQuery query;
475  if (m_loader_type == LT_DashBoard) // HACK for dashboards
476  {
478  }
479 
480  App::GetCacheSystem()->Query(query);
481 
482  m_selected_entry = -1;
483  for (CacheQueryResult const& res: query.cqy_results)
484  {
485  if (res.cqr_entry != m_advertised_entry)
486  {
487  m_display_entries.push_back(res.cqr_entry);
488  m_selected_entry = 0;
489  }
490  }
491 
492  // Sort categories alphabetically
494  std::vector<std::pair<int, Ogre::String>> sorted_cats(cats.begin(), cats.end());
495  std::sort(sorted_cats.begin(), sorted_cats.end(), sort_cats<int, Ogre::String>());
496 
497  // Display used categories
498  for (auto itor: sorted_cats)
499  {
500  size_t usage = query.cqy_res_category_usage[itor.first];
501  if (usage > 0 || itor.first == CacheCategoryId::CID_Fresh) // HACK: Always include the "fresh" category
502  {
503  m_display_categories.emplace_back(itor.first, itor.second, usage);
504  }
505  }
506 }
507 
509 {
510  std::string input = m_search_input.ToCStr();
511 
512  if (input.find(":") == std::string::npos)
513  {
515  m_search_string = input;
516  }
517  else
518  {
519  Ogre::StringVector v = Ogre::StringUtil::split(input, ":");
520  if (v.size() < 2)
521  {
523  m_search_string = "";
524  }
525  else if (v[0] == "guid")
526  {
528  m_search_string = v[1];
529  }
530  else if (v[0] == "author")
531  {
533  m_search_string = v[1];
534  }
535  else if (v[0] == "wheels")
536  {
538  m_search_string = v[1];
539  }
540  else if (v[0] == "file")
541  {
543  m_search_string = v[1];
544  }
545  else
546  {
548  m_search_string = "";
549  }
550  }
551 }
552 
553 // Static helper
554 bool MainSelector::ScComboItemGetter(void* data, int idx, const char** out_text)
555 {
556  CacheEntryPtr* entry_ptr = static_cast<CacheEntryPtr*>(data);
557  if (out_text)
558  *out_text = (*entry_ptr)->sectionconfigs.at(idx).c_str();
559  return true;
560 }
561 
562 void MainSelector::DrawAttrInt(const char* title, int val) const
563 {
564  if (val > 0)
565  {
566  ImGui::Text("%s", title);
567  ImGui::SameLine();
568  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color, "%d", val);
569  }
570 }
571 
572 void MainSelector::DrawAttrFloat(const char* title, float val) const
573 {
574  if (val > 0)
575  {
576  ImGui::Text("%s", title);
577  ImGui::SameLine();
578  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color, "%f", val);
579  }
580 }
581 
582 void MainSelector::DrawAttrSpecial(bool val, const char* label) const
583 {
584  if (val)
585  {
586  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_red_text_color, "%s", label);
587  }
588 }
589 
590 void MainSelector::DrawAttrStr(const char* desc, std::string const& str) const
591 {
592  if (!str.empty())
593  {
594  ImGui::Text("%s", desc);
595  ImGui::SameLine();
596  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color, "%s", str.c_str());
597  }
598 }
599 
601 {
602  m_selected_entry = -1;
604  m_searchbox_was_active = false;
605  m_loader_type = LT_None; // Hide window
606  m_kb_focused = true;
607  m_is_hovered = false;
608 }
609 
611 {
612  this->Close();
613 
614  if (App::app_state->getEnum<AppState>() == AppState::MAIN_MENU)
615  {
616  if (App::mp_state->getEnum<MpState>() == MpState::CONNECTED)
617  {
619  }
621  }
622  else if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
623  {
625  }
626 }
627 
629 {
630  ROR_ASSERT(m_selected_entry > -1); // Programmer error
632 
633  if (m_loader_type == LT_Gadget)
634  {
635  auto request = new LoadScriptRequest();
636  request->lsr_filename = sd_entry.sde_entry->fname;
637  request->lsr_category = ScriptCategory::GADGET;
639  this->Close();
640  }
641  else if (m_loader_type == LT_Terrain &&
642  App::app_state->getEnum<AppState>() == AppState::MAIN_MENU)
643  {
645  this->Close();
646  }
647  else if (m_loader_type == LT_DashBoard &&
648  App::app_state->getEnum<AppState>() == AppState::MAIN_MENU)
649  {
651  {
652  case CID_DashboardsTruck:
654  break;
655  case CID_DashboardsBoat:
657  break;
658  default:
659  LOG(fmt::format("[RoR|GameSettings] INTERNAL ERROR - Unrecognized dashboard type being selected ({})!",
661  break;
662  }
664  this->Close();
665  }
666  else if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
667  {
668  LoaderType type = m_loader_type;
669  std::string sectionconfig;
670  if (sd_entry.sde_entry->sectionconfigs.size() > 0)
671  {
672  sectionconfig = sd_entry.sde_entry->sectionconfigs[m_selected_sectionconfig];
673  }
674  this->Close();
675 
676  App::GetGameContext()->OnLoaderGuiApply(type, sd_entry.sde_entry, sectionconfig);
677  }
678 }
679 
680 // Static helper
681 bool MainSelector::CatComboItemGetter(void* data, int idx, const char** out_text)
682 {
683  DisplayCategoryVec* dc_vec = static_cast<DisplayCategoryVec*>(data);
684  if (out_text)
685  *out_text = dc_vec->at(idx).sdc_title.ToCStr();
686  return true;
687 }
688 
690  sde_entry(entry)
691 {
692  // Pre-format strings
693  if (sde_entry->filetime > 0)
694  {
695  sde_filetime_str = asctime(gmtime(&sde_entry->filetime));
696  }
697  if (sde_entry->addtimestamp > 0)
698  {
699  sde_addtime_str = asctime(gmtime(&sde_entry->addtimestamp));
700  }
701 
703 }
704 
705 MainSelector::DisplayCategory::DisplayCategory(int id, std::string const& name, size_t usage)
706  : sdc_category_id(id)
707 {
708  sdc_title << "(" << usage << ") " << _LC("ModCategory", name.c_str());
709 }
ROR_ASSERT
#define ROR_ASSERT(_EXPR)
Definition: Application.h:40
GameContext.h
Game state manager and message-queue provider.
RoR::CacheEntry::resource_bundle_type
std::string resource_bundle_type
Archive type recognized by OGRE resource system: 'FileSystem' or 'Zip'.
Definition: CacheSystem.h:80
RoR::MSG_SIM_LOAD_TERRN_REQUESTED
@ MSG_SIM_LOAD_TERRN_REQUESTED
Definition: Application.h:118
RoR::GUI::MainSelector::MainSelector
MainSelector()
Definition: GUI_MainSelector.cpp:56
RoR::GUI::MainSelector::Cancel
void Cancel()
Definition: GUI_MainSelector.cpp:610
RoR::CacheSystem::CategoryIdNameMap
std::map< int, Ogre::String > CategoryIdNameMap
Definition: CacheSystem.h:281
RoR::CacheEntry::dname
Ogre::String dname
name parsed from the file
Definition: CacheSystem.h:70
RoR::CacheSearchMethod::GUID
@ GUID
Partial match in: guid.
RoR::ImTextWrappedColorMarked
void ImTextWrappedColorMarked(std::string const &text)
Prints multiline text with '#rrggbb' color markers. Behaves like ImGui::Text* functions.
Definition: GUIUtils.cpp:246
RoR::GUI::MainSelector::PREVIEW_SIZE_RATIO
const float PREVIEW_SIZE_RATIO
Definition: GUI_MainSelector.h:42
RoR::GUI::MainSelector::DrawAttrSpecial
void DrawAttrSpecial(bool val, const char *label) const
Definition: GUI_MainSelector.cpp:582
RoR::MpState::CONNECTED
@ CONNECTED
RoR::CID_DashboardsTruck
@ CID_DashboardsTruck
Definition: Application.h:482
RoR::Str::GetBuffer
char * GetBuffer()
Definition: Str.h:48
RoR::CacheQuery::cqy_filter_category_id
int cqy_filter_category_id
Definition: CacheSystem.h:170
RoR::GUI::MainSelector::UpdateDisplayLists
void UpdateDisplayLists()
Definition: GUI_MainSelector.cpp:457
RoR::GUI::MainSelector::~MainSelector
~MainSelector()
Definition: GUI_MainSelector.cpp:61
RoR::GUIManager::GuiTheme
Definition: GUIManager.h:79
RoR::GUI::MainSelector::DisplayEntry::sde_filetime_str
Str< 50 > sde_filetime_str
Definition: GUI_MainSelector.h:68
RoR::App::GetGuiManager
GUIManager * GetGuiManager()
Definition: Application.cpp:285
RoR::GUIManager::GuiTheme::value_blue_text_color
ImVec4 value_blue_text_color
Definition: GUIManager.h:86
RoR::AuthorInfo::type
Ogre::String type
Definition: CacheSystem.h:50
RoR::CacheEntry::version
int version
file's version
Definition: CacheSystem.h:78
RoR::GUI::MainSelector::m_selected_sectionconfig
int m_selected_sectionconfig
Definition: GUI_MainSelector.h:103
RoR::AppState::MAIN_MENU
@ MAIN_MENU
RoR::CacheQuery::cqy_search_method
CacheSearchMethod cqy_search_method
Definition: CacheSystem.h:173
RoR::LT_Skin
@ LT_Skin
Definition: Application.h:468
ContentManager.h
RoR::GUI::GameSettings::default_dash_being_selected
CacheCategoryId default_dash_being_selected
Definition: GUI_GameSettings.h:36
RoR::DrawColorMarkedText
ImVec2 DrawColorMarkedText(ImDrawList *drawlist, ImVec2 text_cursor, ImVec4 default_color, float override_alpha, float wrap_width, std::string const &line)
Draw multiline text with '#rrggbb' color markers. Returns total text size.
Definition: GUIUtils.cpp:204
format
Truck file format(technical spec)
GUIUtils.h
RoR::GUI::MainSelector::DisplayCategory::DisplayCategory
DisplayCategory(int id, std::string const &name, size_t usage)
Definition: GUI_MainSelector.cpp:705
RoR::CacheEntry::driveable
ActorType driveable
Definition: CacheSystem.h:139
RoR::CacheEntry::importcommands
bool importcommands
Definition: CacheSystem.h:136
RoR::Str::GetCapacity
size_t GetCapacity() const
Definition: Str.h:49
RoR::CacheSearchMethod::FILENAME
@ FILENAME
Partial match in file name.
RoR::GUI::MainSelector::m_selected_entry
int m_selected_entry
Definition: GUI_MainSelector.h:102
RoR::GUI::MainSelector::DrawAttrInt
void DrawAttrInt(const char *desc, int val) const
Definition: GUI_MainSelector.cpp:562
RoR::GameContext::OnLoaderGuiApply
void OnLoaderGuiApply(RoR::LoaderType type, CacheEntryPtr entry, std::string sectionconfig)
GUI callback.
Definition: GameContext.cpp:704
RoR::Round
Ogre::Real Round(Ogre::Real value, unsigned short ndigits=0)
Definition: Utils.cpp:101
RoR::CacheQuery
Definition: CacheSystem.h:167
RoR::App::ui_default_boat_dash
CVar * ui_default_boat_dash
string; name of the '.dashboard' file in modcache.
Definition: Application.cpp:279
RoR::GUI::MainSelector::m_selected_cid
int m_selected_cid
Category ID.
Definition: GUI_MainSelector.h:101
RoR::CacheEntry::propwheelcount
int propwheelcount
Definition: CacheSystem.h:116
RoR::CacheEntry::hasSubmeshs
bool hasSubmeshs
Definition: CacheSystem.h:109
RoR::MSG_APP_LOAD_SCRIPT_REQUESTED
@ MSG_APP_LOAD_SCRIPT_REQUESTED
Payload = RoR::LoadScriptRequest* (owner)
Definition: Application.h:92
RoR::GUIManager::GameSettings
GUI::GameSettings GameSettings
Definition: GUIManager.h:119
RoR::GUI::MainSelector::m_display_categories
DisplayCategoryVec m_display_categories
Definition: GUI_MainSelector.h:89
RoR::CID_None
@ CID_None
Definition: Application.h:479
RoR::CacheEntry::sectionconfigs
std::vector< Ogre::String > sectionconfigs
Definition: CacheSystem.h:142
Utils.h
RoR::GUI::MainSelector::Show
void Show(LoaderType type, std::string const &filter_guid="", CacheEntryPtr advertised_entry=nullptr)
Definition: GUI_MainSelector.cpp:66
RoR::GUI::MainSelector::m_selected_category
int m_selected_category
Combobox position (uses display list)
Definition: GUI_MainSelector.h:100
RoR::GUI::MainSelector::LEFT_PANE_WIDTH
const float LEFT_PANE_WIDTH
Definition: GUI_MainSelector.h:41
RoR::CacheEntry::enginetype
char enginetype
Definition: CacheSystem.h:141
Language.h
RoR::CacheEntry::minrpm
float minrpm
Definition: CacheSystem.h:130
RoR::CacheEntry::description
Ogre::String description
Definition: CacheSystem.h:105
RoR::CacheQueryResult::cqr_entry
CacheEntryPtr cqr_entry
Definition: CacheSystem.h:153
RoR::GUI::MainSelector::DrawAttrFloat
void DrawAttrFloat(const char *desc, float val) const
Definition: GUI_MainSelector.cpp:572
RefCountingObjectPtr< CacheEntry >
GUIManager.h
ActorManager.h
RoR::CacheEntry::forwardcommands
bool forwardcommands
Definition: CacheSystem.h:135
RoR::CacheSearchMethod::NONE
@ NONE
Ignore the search string and find all.
RoR::CacheEntry::beamcount
int beamcount
Definition: CacheSystem.h:111
RoR::GUI::MainSelector::DisplayEntry
Definition: GUI_MainSelector.h:63
RoR::GUI::MainSelector::DisplayCategoryVec
std::vector< DisplayCategory > DisplayCategoryVec
Definition: GUI_MainSelector.h:73
RoR::CacheEntry::shockcount
int shockcount
Definition: CacheSystem.h:112
RoR::App::mp_state
CVar * mp_state
Definition: Application.cpp:115
RoR::GUI::MainSelector::m_is_hovered
bool m_is_hovered
Definition: GUI_MainSelector.h:98
RoR::GUI::MainSelector::CatComboItemGetter
static bool CatComboItemGetter(void *data, int idx, const char **out_text)
Definition: GUI_MainSelector.cpp:681
RoR::CacheQuery::cqy_res_category_usage
std::map< int, size_t > cqy_res_category_usage
Total usage (ignores search params + category filter)
Definition: CacheSystem.h:177
RoR::GUIManager::GetTheme
GuiTheme & GetTheme()
Definition: GUIManager.h:168
RoR::CacheSearchMethod::AUTHORS
@ AUTHORS
Partial match in: author name/email.
RoR::CacheEntry::rotatorscount
int rotatorscount
Definition: CacheSystem.h:123
RoR::CacheEntry::soundsourcescount
int soundsourcescount
Definition: CacheSystem.h:126
RoR::App::ui_default_truck_dash
CVar * ui_default_truck_dash
string; name of the '.dashboard' file in modcache.
Definition: Application.cpp:278
RoR::CacheEntry::torque
float torque
Definition: CacheSystem.h:132
RoR::CacheEntry::authors
std::vector< AuthorInfo > authors
authors
Definition: CacheSystem.h:86
GUI_LoadingWindow.h
RoR::CacheEntry::filecachename
Ogre::String filecachename
preview image filename
Definition: CacheSystem.h:87
CacheSystem.h
A database of user-installed content alias 'mods' (vehicles, terrains...)
RoR::CacheEntry::propscount
int propscount
Definition: CacheSystem.h:119
GUI_MainSelector.h
RoR::GUI::MainSelector::m_advertised_entry
CacheEntryPtr m_advertised_entry
Always shown on top, even if not existing in modcache (i.e. dummy default skin)
Definition: GUI_MainSelector.h:97
RoR::CacheSystem::GetCategories
const CategoryIdNameMap & GetCategories() const
Definition: CacheSystem.h:316
RoR::CacheQueryResult
Definition: CacheSystem.h:147
ScriptEngine.h
RoR::CacheEntry::addtimestamp
std::time_t addtimestamp
timestamp when this file was added to the cache
Definition: CacheSystem.h:75
RoR::GameContext::PushMessage
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
Definition: GameContext.cpp:66
RoR::App::app_state
CVar * app_state
Definition: Application.cpp:79
RoR::Str::ToCStr
const char * ToCStr() const
Definition: Str.h:46
RoR::GUI::MainSelector::UpdateSearchParams
void UpdateSearchParams()
Definition: GUI_MainSelector.cpp:508
RoR::CacheSearchMethod::FULLTEXT
@ FULLTEXT
Partial match in: name, filename, description, author name/mail.
RoR::LT_Gadget
@ LT_Gadget
Definition: Application.h:474
RoR::GUI::MainSelector::m_show_details
bool m_show_details
Definition: GUI_MainSelector.h:95
RoR::CacheSearchMethod::WHEELS
@ WHEELS
Wheel configuration, i.e. 4x4.
RoR::LoaderType
LoaderType
< Search mode for ModCache::Query() & Operation mode for GUI::MainSelector
Definition: Application.h:455
RoR::GUI::MainSelector::m_last_selected_entry
std::map< LoaderType, int > m_last_selected_entry
Stores the last manually selected entry index for each loader type.
Definition: GUI_MainSelector.h:107
RoR::CacheEntry::rescuer
bool rescuer
Definition: CacheSystem.h:137
Application.h
Central state/object manager and communications hub.
RoR::LT_DashBoard
@ LT_DashBoard
Definition: Application.h:473
RoR::CacheQuery::cqy_search_string
std::string cqy_search_string
Definition: CacheSystem.h:174
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:296
RoR::GUIManager::RequestGuiCaptureKeyboard
void RequestGuiCaptureKeyboard(bool val)
Pass true during frame to prevent input passing to application.
Definition: GUIManager.cpp:464
RoR::AppState::SIMULATION
@ SIMULATION
RoR::CacheEntry::uniqueid
Ogre::String uniqueid
file's unique id
Definition: CacheSystem.h:76
RoR::GUI::MainSelector::m_search_method
CacheSearchMethod m_search_method
Definition: GUI_MainSelector.h:91
RoR::LoadScriptRequest
Definition: ScriptEngine.h:92
RoR::AuthorInfo
Definition: CacheSystem.h:47
RoR::GUI::GameMainMenu::SetVisible
void SetVisible(bool v)
Definition: GUI_GameMainMenu.h:43
RoR::CacheEntry::loadmass
float loadmass
Definition: CacheSystem.h:129
RoR::CacheEntry::fixescount
int fixescount
Definition: CacheSystem.h:113
_LC
#define _LC(ctx, str)
Definition: Language.h:38
RoR::GUI::MainSelector::Apply
void Apply()
Definition: GUI_MainSelector.cpp:628
RoR::CID_Fresh
@ CID_Fresh
Definition: Application.h:495
RoR::LT_Terrain
@ LT_Terrain
Definition: Application.h:458
RoR::CacheSystem::ActorTypeToName
std::string ActorTypeToName(ActorType driveable)
Definition: CacheSystem.cpp:569
RoR::CacheEntry::numgears
int numgears
Definition: CacheSystem.h:140
RoR::GUI::MainSelector::DisplayEntry::DisplayEntry
DisplayEntry(CacheEntryPtr entry)
Definition: GUI_MainSelector.cpp:689
RoR::GUI::MainSelector::DisplayEntry::sde_driveable_str
Str< 50 > sde_driveable_str
Definition: GUI_MainSelector.h:70
RoR::App::GetCacheSystem
CacheSystem * GetCacheSystem()
Definition: Application.cpp:288
RoR::CID_DashboardsBoat
@ CID_DashboardsBoat
Definition: Application.h:483
RoR::CacheEntry::usagecounter
int usagecounter
how much it was used already
Definition: CacheSystem.h:85
RoR::CacheQuery::cqy_filter_type
RoR::LoaderType cqy_filter_type
Definition: CacheSystem.h:169
RoR::GameContext::OnLoaderGuiCancel
void OnLoaderGuiCancel()
GUI callback.
Definition: GameContext.cpp:688
RoR::Message
Unified game event system - all requests and state changes are reported using a message.
Definition: GameContext.h:51
RoR::CacheEntry::wheelcount
int wheelcount
Definition: CacheSystem.h:115
RoR::LT_None
@ LT_None
Definition: Application.h:457
RoR::CacheEntry::nodecount
int nodecount
Definition: CacheSystem.h:110
RoR::GUI::MainSelector::m_filter_guid
std::string m_filter_guid
Used for skins.
Definition: GUI_MainSelector.h:93
RoR::CacheEntry::resource_bundle_path
std::string resource_bundle_path
Path of ZIP or directory which contains the media. Shared between CacheEntries, loaded only once.
Definition: CacheSystem.h:81
RoR::CacheEntry::flexbodiescount
int flexbodiescount
Definition: CacheSystem.h:125
RoR::CacheEntry::wingscount
int wingscount
Definition: CacheSystem.h:120
RoR::GUI::MainSelector::m_last_selected_cid
std::map< LoaderType, int > m_last_selected_cid
Last selected category-ID for each loader type.
Definition: GUI_MainSelector.h:106
RoR::CacheEntry::exhaustscount
int exhaustscount
Definition: CacheSystem.h:124
RoR::GUI::MainSelector::Close
void Close()
Definition: GUI_MainSelector.cpp:600
RoR::GUI::MainSelector::ScComboItemGetter
static bool ScComboItemGetter(void *data, int idx, const char **out_text)
Definition: GUI_MainSelector.cpp:554
RoR::CacheEntry::truckmass
float truckmass
Definition: CacheSystem.h:128
RoR::GUI::MainSelector::m_kb_focused
bool m_kb_focused
Definition: GUI_MainSelector.h:50
RoR::CacheEntry::maxrpm
float maxrpm
Definition: CacheSystem.h:131
InputEngine.h
Handles controller inputs from player. Defines input events and binding mechanism,...
RoR::CacheQuery::cqy_filter_guid
std::string cqy_filter_guid
Exact match (case-insensitive); leave empty to disable.
Definition: CacheSystem.h:171
RoR::GUI::MainSelector::DisplayEntry::sde_entry
CacheEntryPtr sde_entry
Definition: GUI_MainSelector.h:67
RoR::GUI::MainSelector::m_display_entries
DisplayEntryVec m_display_entries
Definition: GUI_MainSelector.h:90
RoR::GUI::MainSelector::Draw
void Draw()
Definition: GUI_MainSelector.cpp:88
RoR::CacheEntry::hydroscount
int hydroscount
Definition: CacheSystem.h:114
RoR::ScriptCategory::GADGET
@ GADGET
Associated with a .gadget mod file, launched via UI or any method given below for CUSTOM scripts (use...
RoR::GUI::MainSelector::m_loader_type
LoaderType m_loader_type
Definition: GUI_MainSelector.h:88
RoR::GUI::MainSelector::m_searchbox_was_active
bool m_searchbox_was_active
Definition: GUI_MainSelector.h:96
RoR::GUI::MainSelector::m_last_selected_category
std::map< LoaderType, int > m_last_selected_category
Last category-combobox position for each loader type.
Definition: GUI_MainSelector.h:105
RoR::CacheEntry::filetime
std::time_t filetime
filetime
Definition: CacheSystem.h:83
RoR::GUI::MainSelector::DisplayCategory::sdc_title
Str< 200 > sdc_title
Definition: GUI_MainSelector.h:60
RoR::GUI::MainSelector::m_search_input
Str< 500 > m_search_input
Definition: GUI_MainSelector.h:94
RoR::CacheEntry::custom_particles
bool custom_particles
Definition: CacheSystem.h:134
RoR::GUI::MainSelector::m_search_string
std::string m_search_string
Definition: GUI_MainSelector.h:92
RoR::CID_All
@ CID_All
Definition: Application.h:494
sort_cats
Definition: GUI_MainSelector.cpp:440
RoR::AuthorInfo::name
Ogre::String name
Definition: CacheSystem.h:51
RoR::CacheEntry::commandscount
int commandscount
Definition: CacheSystem.h:117
RoR
Definition: AppContext.h:36
RoR::Str::Clear
Str & Clear()
Definition: Str.h:54
x
float x
Definition: (ValueTypes) quaternion.h:5
RoR::CacheSystem::Query
size_t Query(CacheQuery &query)
Definition: CacheSystem.cpp:2294
RoR::GUI::GameSettings
Definition: GUI_GameSettings.h:28
RoR::CVar::setStr
void setStr(std::string const &str)
Definition: CVar.h:83
RoR::GUI::MainSelector::DrawAttrStr
void DrawAttrStr(const char *desc, std::string const &str) const
Definition: GUI_MainSelector.cpp:590
RoR::GUIManager::GameMainMenu
GUI::GameMainMenu GameMainMenu
Definition: GUIManager.h:117
RoR::CacheQuery::cqy_results
std::vector< CacheQueryResult > cqy_results
Definition: CacheSystem.h:176
RoR::CacheEntry::default_skin
std::string default_skin
Definition: CacheSystem.h:107
RoR::CacheEntry::guid
Ogre::String guid
global unique id; Type "addonpart" leaves this empty and uses addonpart_guids; Always lowercase.
Definition: CacheSystem.h:77
RoR::MSG_NET_DISCONNECT_REQUESTED
@ MSG_NET_DISCONNECT_REQUESTED
Definition: Application.h:103
RoR::CacheEntry::flarescount
int flarescount
Definition: CacheSystem.h:118
RoR::GUI::MainSelector::DisplayEntry::sde_addtime_str
Str< 50 > sde_addtime_str
Definition: GUI_MainSelector.h:69
RoR::CacheEntry::fname
Ogre::String fname
filename
Definition: CacheSystem.h:67