RigsofRods
Soft-body Physics Simulation
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 "Utils.h"
35 
36 #include <MyGUI.h>
37 #include <imgui.h>
38 #include <imgui_internal.h>
39 
40 using namespace RoR;
41 using namespace GUI;
42 
43 // MAIN SELECTOR WINDOW
44 // --------------------
45 // KEY CONTROLS
46 // tab: toggle search box focus (FIXME: currently, only focusing works)
47 // 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.
48 // arrow up/down: select prev/next entry. When already on top/bottom item, wrap to other end of the list.
49 // enter: activate highlighted entry
50 // SEARCHING
51 // The result list is sorted descending by 'score'.
52 // 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
53 // Syntax 'AREA:abcdef': searches (ignoring case) in AREA: 'guid'(guid string), 'author' (name/email), 'wheels' (string "WHEELCOUNTxPROPWHEELCOUNT"), 'file' (filename); returns string pos as score
54 
56 {
57  // Constructs `CacheEntryPtr` - doesn't compile without `#include CacheSystem.h` - not pretty if in header (even if auto-generated by C++).
58 }
59 
61 {
62  // Destructs `CacheEntryPtr` - doesn't compile without `#include CacheSystem.h` - not pretty if in header (even if auto-generated by C++).
63 }
64 
65 void MainSelector::Show(LoaderType type, std::string const& filter_guid, CacheEntryPtr advertised_entry)
66 {
67  m_loader_type = type;
70  m_search_string.clear();
71  m_filter_guid = filter_guid;
72  m_advertised_entry = advertised_entry;
74  if (m_selected_cid == 0)
76  this->UpdateDisplayLists();
78  {
80  }
82  {
84  }
85 }
86 
88 {
90 
91  ImGuiWindowFlags win_flags = ImGuiWindowFlags_NoCollapse;
92  ImGui::SetNextWindowPosCenter(ImGuiCond_FirstUseEver);
93  ImGui::SetNextWindowSize(ImVec2((ImGui::GetIO().DisplaySize.x / 1.4), (ImGui::GetIO().DisplaySize.y / 1.2)), ImGuiCond_FirstUseEver);
94  bool keep_open = true;
95  if (!ImGui::Begin(_LC("MainSelector", "Loader"), &keep_open, win_flags))
96  {
97  return;
98  }
99 
101 
102  // category keyboard control
103  const int num_categories = static_cast<int>(m_display_categories.size());
105  {
106  if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
107  {
108  m_selected_category = (m_selected_category + 1) % num_categories; // select next item and wrap around at bottom.
112  this->UpdateDisplayLists();
113  }
114  else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
115  {
116  m_selected_category = (m_selected_category > 0) ? (m_selected_category - 1) : (num_categories - 1); // select prev. item and wrap around on top
120  this->UpdateDisplayLists();
121  }
122  }
123 
124  // category combobox
125  ImGui::PushItemWidth(LEFT_PANE_WIDTH);
126  if (ImGui::Combo(
127  "##SelectorCategory", &m_selected_category,
129  {
133  this->UpdateDisplayLists();
134  }
135  ImGui::PopItemWidth();
136  ImGui::SameLine();
137 
138  // search box
139  const ImVec2 searchbox_cursor = ImGui::GetCursorPos();
140  const float searchbox_width = ImGui::GetWindowWidth() -
141  (LEFT_PANE_WIDTH + 2 * (ImGui::GetStyle().WindowPadding.x) + ImGui::GetStyle().ItemSpacing.x);
142 
143  if (m_kb_focused == true)
144  {
145  ImGui::SetKeyboardFocusHere();
146  m_kb_focused = false;
147  }
148 
149  if (!m_searchbox_was_active && (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Tab)) || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Slash))))
150  {
151  ImGui::SetKeyboardFocusHere();
152  }
153  ImGui::PushItemWidth(searchbox_width);
154  if (ImGui::InputText("##SelectorSearch", m_search_input.GetBuffer(), m_search_input.GetCapacity()))
155  {
156  m_selected_category = 0; // 'All'
158  this->UpdateSearchParams();
159  this->UpdateDisplayLists();
160  }
161  ImGui::PopItemWidth();
162  m_searchbox_was_active = ImGui::IsItemActive();
163  const ImVec2 separator_cursor = ImGui::GetCursorPos()
164  + ImVec2(0, ImGui::GetStyle().WindowPadding.y - ImGui::GetStyle().ItemSpacing.y);
165 
166  // advanced search hint
167  const char* searchbox_hint = "(?)";
168  ImGui::SetCursorPos(searchbox_cursor + ImVec2(searchbox_width - (ImGui::CalcTextSize(searchbox_hint).x + ImGui::GetStyle().FramePadding.x), ImGui::GetStyle().FramePadding.y));
169  ImGui::TextDisabled(searchbox_hint);
170  if (ImGui::IsItemHovered())
171  {
172  ImGui::BeginTooltip();
173  ImGui::TextDisabled("Fulltext search:");
174  ImGui::Text("~ partial name, filename, description, author name or e-mail");
175  ImGui::TextDisabled("Advanced search:");
176  ImGui::Text("guid: ~ partial GUID");
177  ImGui::Text("author: ~ partial author name or e-mail");
178  ImGui::Text("wheels: ~ wheel configuration (i.e. 4x4)");
179  ImGui::Text("file: ~ partial file name");
180  ImGui::EndTooltip();
181  }
182 
183  ImGui::SetCursorPos(separator_cursor);
184  ImGui::Separator();
185 
186  // left
187  ImGui::BeginChild("left pane", ImVec2(LEFT_PANE_WIDTH, 0), true);
188  const int num_entries = static_cast<int>(m_display_entries.size());
189  bool scroll_to_selected = false;
190  // Entry list: handle keyboard
191  if (m_selected_entry != -1) // -1 indicates empty entry-list
192  {
193  if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)))
194  {
195  m_selected_entry = (m_selected_entry + 1) % num_entries; // select next item and wrap around at bottom.
197  scroll_to_selected = true;
198  }
199  else if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)))
200  {
201  m_selected_entry = (m_selected_entry > 0) ? (m_selected_entry - 1) : (num_entries - 1); // select prev. item and wrap around on top
203  scroll_to_selected = true;
204  }
205  }
206  // Entry list: display
207  ImDrawList* drawlist = ImGui::GetWindowDrawList();
208  drawlist->ChannelsSplit(2); // 0=background selection indicator, 1=text
209  bool do_apply = false;
210  for (int i = 0; i < num_entries; ++i)
211  {
212  DisplayEntry& d_entry = m_display_entries[i];
213  bool is_selected = (i == m_selected_entry);
214 
215  // Draw text manually to enable coloring.
216  drawlist->ChannelsSetCurrent(1);
217  ImVec2 size = RoR::DrawColorMarkedText(drawlist, ImGui::GetCursorScreenPos(),
218  ImGui::GetStyle().Colors[ImGuiCol_Text],
219  /*override_alpha=*/1.f, /*wrap_width=*/-1.f,
220  d_entry.sde_entry->dname.c_str());
221 
222  ImGui::PushID(i);
223  drawlist->ChannelsSetCurrent(0);
224  ImVec2 mouse_area(LEFT_PANE_WIDTH, size.y); // Monitor the whole line (excess width gets clipped)
225  if (ImGui::Selectable("##dummy", &is_selected, 0, mouse_area)) // Use invisible label + size parameter.
226  {
227  m_selected_entry = i;
230  }
231  if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) // Left doubleclick
232  {
233  m_selected_entry = i;
236  do_apply = true;
237  }
238  if (is_selected && scroll_to_selected)
239  {
240  ImGui::SetScrollHere();
241  }
242  ImGui::PopID();
243  }
244 
245  if (do_apply)
246  {
247  this->Apply();
248  }
249  drawlist->ChannelsMerge();
250  ImGui::EndChild();
251  ImGui::SameLine();
252 
253  // right
254  ImGui::BeginGroup();
255 
256  ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us
257 
258  if (m_selected_entry != -1)
259  {
261 
262  // Preview image
263  if (!sd_entry.sde_entry->filecachename.empty())
264  {
265  ImVec2 cursor_pos = ImGui::GetCursorPos();
266  try
267  {
268  Ogre::TexturePtr preview_tex =
269  Ogre::TextureManager::getSingleton().load(
270  sd_entry.sde_entry->filecachename, Ogre::RGN_DEFAULT);
271  if (preview_tex)
272  {
273  // Scale the image
274  ImVec2 max_size = (ImGui::GetWindowSize() * PREVIEW_SIZE_RATIO);
275  ImVec2 size(preview_tex->getWidth(), preview_tex->getHeight());
276  size *= max_size.x / size.x; // Fit size along X
277  if (size.y > max_size.y) // Reduce size along Y if needed
278  {
279  size *= max_size.y / size.y;
280  }
281  // Draw the image
282  ImGui::SetCursorPos((cursor_pos + ImGui::GetWindowSize()) - size);
283  ImGui::Image(reinterpret_cast<ImTextureID>(preview_tex->getHandle()), size);
284  ImGui::SetCursorPos(cursor_pos);
285  }
286  }
287  catch(...)
288  {
289  // Invalid texture file - OGRE exception already logged
290  }
291  }
292 
293  // Title and description
295  ImGui::TextWrapped("%s", sd_entry.sde_entry->description.c_str());
296  ImGui::Separator();
297 
298  // Details
299  for (AuthorInfo const& author: sd_entry.sde_entry->authors)
300  {
301  ImGui::TextDisabled("%s", _LC("MainSelector", "Author(s): "));
302  ImGui::SameLine();
303  ImGui::TextColored(theme.value_blue_text_color, "%s [%s]", author.name.c_str(), author.type.c_str());
304  }
305  this->DrawAttrInt(_LC("MainSelector", "Version: "), sd_entry.sde_entry->version);
306  if (sd_entry.sde_entry->wheelcount > 0)
307  {
308  ImGui::Text("%s", _LC("MainSelector", "Wheels: "));
309  ImGui::SameLine();
310  ImGui::TextColored(theme.value_blue_text_color, "%dx%d", sd_entry.sde_entry->wheelcount, sd_entry.sde_entry->propwheelcount);
311  }
312  if (sd_entry.sde_entry->truckmass > 0)
313  {
314  ImGui::Text("%s", _LC("MainSelector", "Mass: "));
315  ImGui::SameLine();
316  ImGui::TextColored(theme.value_blue_text_color, "%.2f t", Round(sd_entry.sde_entry->truckmass / 1000.0f, 3));
317  }
318 
319  if (m_show_details)
320  {
321  if (sd_entry.sde_entry->loadmass > 0)
322  {
323  ImGui::Text("%s", _LC("MainSelector", "Load Mass: "));
324  ImGui::SameLine();
325  ImGui::TextColored(theme.value_blue_text_color, "%f.2 t", Round(sd_entry.sde_entry->loadmass / 1000.0f, 3));
326  }
327  this->DrawAttrInt(_LC("MainSelector", "Nodes: "), sd_entry.sde_entry->nodecount);
328  this->DrawAttrInt(_LC("MainSelector", "Beams: "), sd_entry.sde_entry->beamcount);
329  this->DrawAttrInt(_LC("MainSelector", "Shocks: "), sd_entry.sde_entry->shockcount);
330  this->DrawAttrInt(_LC("MainSelector", "Hydros: "), sd_entry.sde_entry->hydroscount);
331  this->DrawAttrInt(_LC("MainSelector", "SoundSources: "), sd_entry.sde_entry->soundsourcescount);
332  this->DrawAttrInt(_LC("MainSelector", "Commands: "), sd_entry.sde_entry->commandscount);
333  this->DrawAttrInt(_LC("MainSelector", "Rotators: "), sd_entry.sde_entry->rotatorscount);
334  this->DrawAttrInt(_LC("MainSelector", "Exhausts: "), sd_entry.sde_entry->exhaustscount);
335  this->DrawAttrInt(_LC("MainSelector", "Flares: "), sd_entry.sde_entry->flarescount);
336  this->DrawAttrInt(_LC("MainSelector", "Flexbodies: "), sd_entry.sde_entry->flexbodiescount);
337  this->DrawAttrInt(_LC("MainSelector", "Props: "), sd_entry.sde_entry->propscount);
338  this->DrawAttrInt(_LC("MainSelector", "Wings: "), sd_entry.sde_entry->wingscount);
339  if (sd_entry.sde_entry->hasSubmeshs)
340  {
341  ImGui::Text("%s", _LC("MainSelector", "Using Submeshs: "));
342  ImGui::SameLine();
343  ImGui::TextColored(theme.value_blue_text_color, "%s", sd_entry.sde_entry->hasSubmeshs ?_LC("MainSelector", "Yes") : _LC("MainSelector", "No"));
344  }
345  if (sd_entry.sde_entry->default_skin != "")
346  {
347  ImGui::Text("%s", _LC("MainSelector", "Default skin: "));
348  ImGui::SameLine();
349  ImGui::TextColored(theme.value_blue_text_color, "%s", sd_entry.sde_entry->default_skin.c_str());
350  }
351  this->DrawAttrFloat(_LC("MainSelector", "Torque: "), sd_entry.sde_entry->torque);
352  this->DrawAttrInt(_LC("MainSelector", "Transmission Gear Count: "), sd_entry.sde_entry->numgears);
353  if (sd_entry.sde_entry->minrpm > 0)
354  {
355  ImGui::Text("%s", _LC("MainSelector", "Engine RPM: "));
356  ImGui::SameLine();
357  ImGui::TextColored(theme.value_blue_text_color, "%f - %f", sd_entry.sde_entry->minrpm, sd_entry.sde_entry->maxrpm);
358  }
359  this->DrawAttrStr(_LC("MainSelector", "Unique ID: "), sd_entry.sde_entry->uniqueid);
360  this->DrawAttrStr(_LC("MainSelector", "GUID: "), sd_entry.sde_entry->guid);
361  this->DrawAttrInt(_LC("MainSelector", "Times used: "), sd_entry.sde_entry->usagecounter);
362  this->DrawAttrStr(_LC("MainSelector", "Date and Time modified: "), sd_entry.sde_filetime_str.ToCStr());
363  this->DrawAttrStr(_LC("MainSelector", "Date and Time installed: "), sd_entry.sde_addtime_str.ToCStr());
365  {
366  this->DrawAttrStr(_LC("MainSelector", "Vehicle Type: "), sd_entry.sde_driveable_str.ToCStr());
367  }
368 
369  this->DrawAttrSpecial(sd_entry.sde_entry->forwardcommands, _LC("MainSelector", "[forwards commands]"));
370  this->DrawAttrSpecial(sd_entry.sde_entry->importcommands, _LC("MainSelector", "[imports commands]"));
371  this->DrawAttrSpecial(sd_entry.sde_entry->rescuer, _LC("MainSelector", "[is rescuer]"));
372  this->DrawAttrSpecial(sd_entry.sde_entry->custom_particles, _LC("MainSelector", "[uses custom particles]"));
373  this->DrawAttrSpecial(sd_entry.sde_entry->fixescount > 0, _LC("MainSelector", "[has fixes]"));
374  // Engine type 't' (truck) is the default, do not display it
375  this->DrawAttrSpecial(sd_entry.sde_entry->enginetype == 'c', _LC("MainSelector", "[car engine]"));
376  this->DrawAttrSpecial(sd_entry.sde_entry->resource_bundle_type == "Zip", _LC("MainSelector", "[zip archive]"));
377  this->DrawAttrSpecial(sd_entry.sde_entry->resource_bundle_type == "FileSystem", _LC("MainSelector", "[unpacked in directory]"));
378 
379  if (!sd_entry.sde_entry->resource_bundle_path.empty())
380  {
381  ImGui::Text("%s", _LC("MainSelector", "Source: "));
382  ImGui::SameLine();
383  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color,
384  "%s", sd_entry.sde_entry->resource_bundle_path.c_str());
385  }
386  if (!sd_entry.sde_entry->fname.empty())
387  {
388  ImGui::Text("%s", _LC("MainSelector", "Filename: "));
389  ImGui::SameLine();
390  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color,
391  "%s", sd_entry.sde_entry->fname.c_str());
392  }
393  }
394  ImGui::Checkbox(_LC("MainSelector", "Show details"), &m_show_details);
395  }
396  ImGui::EndChild();
397 
398  ImGui::BeginChild("buttons");
399  if (m_selected_entry != -1)
400  {
402  if (sd_entry.sde_entry->sectionconfigs.size() > 0)
403  {
404  ImGui::PushItemWidth(ImGui::GetWindowWidth() / 2);
405  ImGui::Combo(_LC("MainSelector", "Configuration"), &m_selected_sectionconfig,
407  static_cast<int>(sd_entry.sde_entry->sectionconfigs.size()));
408  ImGui::SameLine();
409  }
410  ImGui::SameLine(ImGui::GetWindowWidth()-280);
411  if (ImGui::Button(_LC("MainSelector", "OK"), ImVec2(120.f, 0.0f)) ||
412  ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))
413  {
414  this->Apply();
415  }
416  }
417  ImGui::SameLine(ImGui::GetWindowWidth()-150);
418  if (ImGui::Button(_LC("MainSelector", "Cancel"), ImVec2(120.f, 0.0f)) || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape)))
419  {
420  this->Cancel();
421  }
422  ImGui::EndChild();
423 
424  ImGui::EndGroup();
425 
426  m_is_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
427 
428  ImGui::End();
429  if (!keep_open)
430  {
431  this->Cancel();
432  }
433 };
434 
435 template <typename T1, typename T2>
436 struct sort_cats
437 {
438  bool operator ()(std::pair<int, Ogre::String> const& a, std::pair<int, Ogre::String> const& b) const
439  {
440  if (a.first == CID_All)
441  return true;
442  if (b.first == CID_All)
443  return false;
444  if (a.first == CID_Fresh)
445  return true;
446  if (b.first == CID_Fresh)
447  return false;
448  return a.second < b.second;
449  }
450 };
451 
452 
454 {
455  m_display_categories.clear();
456  m_display_entries.clear();
457 
458  if (m_advertised_entry)
459  {
461  m_selected_entry = 0;
462  }
463 
464  // Find all relevant entries
465  CacheQuery query;
471 
472  App::GetCacheSystem()->Query(query);
473 
474  m_selected_entry = -1;
475  for (CacheQueryResult const& res: query.cqy_results)
476  {
477  if (res.cqr_entry != m_advertised_entry)
478  {
479  m_display_entries.push_back(res.cqr_entry);
480  m_selected_entry = 0;
481  }
482  }
483 
484  // Sort categories alphabetically
486  std::vector<std::pair<int, Ogre::String>> sorted_cats(cats.begin(), cats.end());
487  std::sort(sorted_cats.begin(), sorted_cats.end(), sort_cats<int, Ogre::String>());
488 
489  // Display used categories
490  for (auto itor: sorted_cats)
491  {
492  size_t usage = query.cqy_res_category_usage[itor.first];
493  if (usage > 0 || itor.first == CacheCategoryId::CID_Fresh) // HACK: Always include the "fresh" category
494  {
495  m_display_categories.emplace_back(itor.first, itor.second, usage);
496  }
497  }
498 }
499 
501 {
502  std::string input = m_search_input.ToCStr();
503 
504  if (input.find(":") == std::string::npos)
505  {
507  m_search_string = input;
508  }
509  else
510  {
511  Ogre::StringVector v = Ogre::StringUtil::split(input, ":");
512  if (v.size() < 2)
513  {
515  m_search_string = "";
516  }
517  else if (v[0] == "guid")
518  {
520  m_search_string = v[1];
521  }
522  else if (v[0] == "author")
523  {
525  m_search_string = v[1];
526  }
527  else if (v[0] == "wheels")
528  {
530  m_search_string = v[1];
531  }
532  else if (v[0] == "file")
533  {
535  m_search_string = v[1];
536  }
537  else
538  {
540  m_search_string = "";
541  }
542  }
543 }
544 
545 // Static helper
546 bool MainSelector::ScComboItemGetter(void* data, int idx, const char** out_text)
547 {
548  CacheEntryPtr* entry_ptr = static_cast<CacheEntryPtr*>(data);
549  if (out_text)
550  *out_text = (*entry_ptr)->sectionconfigs.at(idx).c_str();
551  return true;
552 }
553 
554 void MainSelector::DrawAttrInt(const char* title, int val) const
555 {
556  if (val > 0)
557  {
558  ImGui::Text("%s", title);
559  ImGui::SameLine();
560  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color, "%d", val);
561  }
562 }
563 
564 void MainSelector::DrawAttrFloat(const char* title, float val) const
565 {
566  if (val > 0)
567  {
568  ImGui::Text("%s", title);
569  ImGui::SameLine();
570  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color, "%f", val);
571  }
572 }
573 
574 void MainSelector::DrawAttrSpecial(bool val, const char* label) const
575 {
576  if (val)
577  {
578  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_red_text_color, "%s", label);
579  }
580 }
581 
582 void MainSelector::DrawAttrStr(const char* desc, std::string const& str) const
583 {
584  if (!str.empty())
585  {
586  ImGui::Text("%s", desc);
587  ImGui::SameLine();
588  ImGui::TextColored(App::GetGuiManager()->GetTheme().value_blue_text_color, "%s", str.c_str());
589  }
590 }
591 
593 {
594  m_selected_entry = -1;
596  m_searchbox_was_active = false;
597  m_loader_type = LT_None; // Hide window
598  m_kb_focused = true;
599  m_is_hovered = false;
600 }
601 
603 {
604  this->Close();
605 
606  if (App::app_state->getEnum<AppState>() == AppState::MAIN_MENU)
607  {
608  if (App::mp_state->getEnum<MpState>() == MpState::CONNECTED)
609  {
611  }
613  }
614  else if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
615  {
617  }
618 }
619 
621 {
622  ROR_ASSERT(m_selected_entry > -1); // Programmer error
624 
625  if (m_loader_type == LT_Terrain &&
626  App::app_state->getEnum<AppState>() == AppState::MAIN_MENU)
627  {
629  this->Close();
630  }
631  else if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
632  {
633  LoaderType type = m_loader_type;
634  std::string sectionconfig;
635  if (sd_entry.sde_entry->sectionconfigs.size() > 0)
636  {
637  sectionconfig = sd_entry.sde_entry->sectionconfigs[m_selected_sectionconfig];
638  }
639  this->Close();
640 
641  App::GetGameContext()->OnLoaderGuiApply(type, sd_entry.sde_entry, sectionconfig);
642  }
643 }
644 
645 // Static helper
646 bool MainSelector::CatComboItemGetter(void* data, int idx, const char** out_text)
647 {
648  DisplayCategoryVec* dc_vec = static_cast<DisplayCategoryVec*>(data);
649  if (out_text)
650  *out_text = dc_vec->at(idx).sdc_title.ToCStr();
651  return true;
652 }
653 
655  sde_entry(entry)
656 {
657  // Pre-format strings
658  if (sde_entry->filetime > 0)
659  {
660  sde_filetime_str = asctime(gmtime(&sde_entry->filetime));
661  }
662  if (sde_entry->addtimestamp > 0)
663  {
664  sde_addtime_str = asctime(gmtime(&sde_entry->addtimestamp));
665  }
666 
668 }
669 
670 MainSelector::DisplayCategory::DisplayCategory(int id, std::string const& name, size_t usage)
671  : sdc_category_id(id)
672 {
673  sdc_title << "(" << usage << ") " << _LC("ModCategory", name.c_str());
674 }
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:116
RoR::GUI::MainSelector::MainSelector
MainSelector()
Definition: GUI_MainSelector.cpp:55
RoR::GUI::MainSelector::Cancel
void Cancel()
Definition: GUI_MainSelector.cpp:602
RoR::CacheSystem::CategoryIdNameMap
std::map< int, Ogre::String > CategoryIdNameMap
Definition: CacheSystem.h:292
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:574
RoR::MpState::CONNECTED
@ CONNECTED
RoR::Str::GetBuffer
char * GetBuffer()
Definition: Str.h:48
RoR::CacheQuery::cqy_filter_category_id
int cqy_filter_category_id
Definition: CacheSystem.h:185
RoR::GUI::MainSelector::UpdateDisplayLists
void UpdateDisplayLists()
Definition: GUI_MainSelector.cpp:453
RoR::GUI::MainSelector::~MainSelector
~MainSelector()
Definition: GUI_MainSelector.cpp:60
RoR::GUIManager::GuiTheme
Definition: GUIManager.h:68
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:269
RoR::GUIManager::GuiTheme::value_blue_text_color
ImVec4 value_blue_text_color
Definition: GUIManager.h:75
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:188
RoR::LT_Skin
@ LT_Skin
Definition: Application.h:302
ContentManager.h
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
GUIUtils.h
RoR::GUI::MainSelector::DisplayCategory::DisplayCategory
DisplayCategory(int id, std::string const &name, size_t usage)
Definition: GUI_MainSelector.cpp:670
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:554
RoR::GameContext::OnLoaderGuiApply
void OnLoaderGuiApply(RoR::LoaderType type, CacheEntryPtr entry, std::string sectionconfig)
GUI callback.
Definition: GameContext.cpp:683
RoR::Round
Ogre::Real Round(Ogre::Real value, unsigned short ndigits=0)
Definition: Utils.cpp:98
RoR::CacheQuery
Definition: CacheSystem.h:182
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::GUI::MainSelector::m_display_categories
DisplayCategoryVec m_display_categories
Definition: GUI_MainSelector.h:89
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:65
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:168
RoR::GUI::MainSelector::DrawAttrFloat
void DrawAttrFloat(const char *desc, float val) const
Definition: GUI_MainSelector.cpp:564
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:646
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:192
RoR::GUIManager::GetTheme
GuiTheme & GetTheme()
Definition: GUIManager.h:154
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::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:327
RoR::CacheQueryResult
Definition: CacheSystem.h:162
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:65
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:500
RoR::CacheSearchMethod::FULLTEXT
@ FULLTEXT
Partial match in: name, filename, description, author name/mail.
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:289
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::CacheQuery::cqy_search_string
std::string cqy_search_string
Definition: CacheSystem.h:189
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:280
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::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:42
RoR::GUI::MainSelector::Apply
void Apply()
Definition: GUI_MainSelector.cpp:620
RoR::CID_Fresh
@ CID_Fresh
Definition: CacheSystem.h:157
RoR::LT_Terrain
@ LT_Terrain
Definition: Application.h:292
RoR::CacheSystem::ActorTypeToName
std::string ActorTypeToName(ActorType driveable)
Definition: CacheSystem.cpp:566
RoR::CacheEntry::numgears
int numgears
Definition: CacheSystem.h:140
RoR::GUI::MainSelector::DisplayEntry::DisplayEntry
DisplayEntry(CacheEntryPtr entry)
Definition: GUI_MainSelector.cpp:654
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:272
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:184
RoR::GameContext::OnLoaderGuiCancel
void OnLoaderGuiCancel()
GUI callback.
Definition: GameContext.cpp:667
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:291
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:592
RoR::GUI::MainSelector::ScComboItemGetter
static bool ScComboItemGetter(void *data, int idx, const char **out_text)
Definition: GUI_MainSelector.cpp:546
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:186
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:87
RoR::CacheEntry::hydroscount
int hydroscount
Definition: CacheSystem.h:114
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: CacheSystem.h:156
sort_cats
Definition: GUI_MainSelector.cpp:436
RoR::AuthorInfo::name
Ogre::String name
Definition: CacheSystem.h:51
RoR::CacheEntry::commandscount
int commandscount
Definition: CacheSystem.h:117
RoR::GUIManager::RequestGuiCaptureKeyboard
void RequestGuiCaptureKeyboard(bool val)
Pass true during frame to prevent input passing to application.
Definition: GUIManager.cpp:439
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:2090
RoR::GUI::MainSelector::DrawAttrStr
void DrawAttrStr(const char *desc, std::string const &str) const
Definition: GUI_MainSelector.cpp:582
RoR::GUIManager::GameMainMenu
GUI::GameMainMenu GameMainMenu
Definition: GUIManager.h:104
RoR::CacheQuery::cqy_results
std::vector< CacheQueryResult > cqy_results
Definition: CacheSystem.h:191
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