RigsofRods
Soft-body Physics Simulation
GUI_SurveyMap.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-2020 Thomas Fischer
5  Copyright 2013-2023 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 
23 #include "GUI_SurveyMap.h"
24 
25 #include "AppContext.h"
26 #include "Actor.h"
27 #include "ContentManager.h"
28 #include "GameContext.h"
29 #include "GfxActor.h"
30 #include "GfxScene.h"
31 #include "GUIManager.h"
32 #include "GUI_MainSelector.h"
33 #include "GUIUtils.h"
34 #include "InputEngine.h"
35 #include "Language.h"
36 #include "OgreImGui.h"
38 #include "Terrain.h"
39 #include "TerrainObjectManager.h"
40 #include "Collisions.h"
41 
42 using namespace RoR;
43 using namespace GUI;
44 using namespace Ogre;
45 
47 {
48  // Check special cases
49  if ((mMapMode == SurveyMapMode::BIG &&
50  App::GetCameraManager()->GetCurrentBehavior() == CameraManager::CAMERA_BEHAVIOR_FREE) ||
52  {
53  mMapMode = SurveyMapMode::NONE;
54  return;
55  }
56 
57  // Handle input
58  if (App::GetInputEngine()->getEventBoolValueBounce(EV_SURVEY_MAP_TOGGLE_ICONS))
60 
61  if (mMapMode == SurveyMapMode::SMALL)
62  {
63  if (App::GetInputEngine()->getEventBoolValue(EV_SURVEY_MAP_ZOOM_IN))
64  {
65  setMapZoomRelative(+ImGui::GetIO().DeltaTime);
66  }
67  if (App::GetInputEngine()->getEventBoolValue(EV_SURVEY_MAP_ZOOM_OUT))
68  {
69  setMapZoomRelative(-ImGui::GetIO().DeltaTime);
70  }
71 
72  // Zoom in/out with mouse wheel also
73  if (mWindowMouseHovered)
74  {
75  setMapZoomRelative(ImGui::GetIO().MouseWheel*0.5f);
76  }
77  }
78 
79  // Calculate window position
80  Ogre::RenderWindow* rw = RoR::App::GetAppContext()->GetRenderWindow();
81  ImVec2 view_size(0, 0);
82  ImVec2 view_padding(8, 8);
83  if (mMapMode == SurveyMapMode::BIG)
84  {
85  view_padding.y = 40; // Extra space for hints
86  view_size.y = (rw->getWidth() * 0.55f) -
87  ((2 * App::GetGuiManager()->GetTheme().screen_edge_padding.y) + (2 * WINDOW_PADDING));
88  Vector3 terrn_size = App::GetGameContext()->GetTerrain()->getMaxTerrainSize(); // Y is 'up'!
89  if (!terrn_size.isZeroLength())
90  {
91  view_size.x = (view_size.y / terrn_size.z) * terrn_size.x;
92  }
93  else // Terrain has no heightmap
94  {
95  view_size.x = view_size.y;
96  }
97  }
98  else if (mMapMode == SurveyMapMode::SMALL)
99  {
100  view_size.y = rw->getWidth() * 0.2f;
101  view_size.x = view_size.y;
102  }
103 
104  // Open window
105  ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
106  ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(WINDOW_PADDING, WINDOW_PADDING));
107  ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, WINDOW_ROUNDING);
108  ImGui::SetNextWindowSize(ImVec2((view_size.x + view_padding.x), (view_size.y + view_padding.y)));
109 
111 
112  if (mMapMode == SurveyMapMode::BIG)
113  {
114  ImGui::PushStyleColor(ImGuiCol_WindowBg, theme.semitransparent_window_bg);
115  ImGui::SetNextWindowPosCenter();
116  }
117  else if (mMapMode == SurveyMapMode::SMALL)
118  {
119  ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0,0,0,0));
120  ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0,0,0,0));
121 
122  float x = ImGui::GetIO().DisplaySize.x -
123  (view_size.x + App::GetGuiManager()->GetTheme().screen_edge_padding.x);
124  ImGui::SetNextWindowPos(ImVec2(x, 100.f));
125  }
126  ImGui::Begin("SurveyMap", nullptr, flags);
127 
128  // Draw map texture
129  ImVec2 tl_screen_pos = ImGui::GetCursorScreenPos();
130  Ogre::Vector2 smallmap_center;
131  Ogre::Vector2 smallmap_size;
132  Ogre::Vector2 view_origin;
133  Ogre::Vector2 texcoords_top_left(0,0);
134  Ogre::Vector2 texcoords_bottom_right(1,1);
135  if (mMapMode == SurveyMapMode::BIG)
136  {
137  view_origin = mMapCenterOffset;
138  }
139  else if (mMapMode == SurveyMapMode::SMALL)
140  {
141  // Calc. view center
142  smallmap_size = mTerrainSize * (1.0f - mMapZoom);
143  Ogre::Vector2 player_map_pos;
145  if (actor)
146  {
147  auto& actor_data = actor->GetGfxActor()->GetSimDataBuffer();
148  player_map_pos = (Vector2(actor_data.simbuf_pos.x, actor_data.simbuf_pos.z));
149  }
150  else
151  {
152  auto& scene_data = App::GetGfxScene()->GetSimDataBuffer();
153  player_map_pos = (Vector2(scene_data.simbuf_character_pos.x, scene_data.simbuf_character_pos.z));
154  }
155 
156  smallmap_center.x = Math::Clamp(player_map_pos.x - mMapCenterOffset.x, smallmap_size.x / 2, mTerrainSize.x - smallmap_size.x / 2);
157  smallmap_center.y = Math::Clamp(player_map_pos.y - mMapCenterOffset.y, smallmap_size.y / 2, mTerrainSize.y - smallmap_size.y / 2);
158 
159  view_origin = ((smallmap_center + mMapCenterOffset) - smallmap_size / 2);
160 
161  texcoords_top_left = (smallmap_center - (smallmap_size/2)) / mTerrainSize;
162  texcoords_bottom_right = (smallmap_center + (smallmap_size/2)) / mTerrainSize;
163  }
164 
165  bool w_adj = false;
167  {
168  for (int i = 0; i < App::GetGuiManager()->TopMenubar.ai_waypoints.size(); i++)
169  {
170  ImVec2 cw_dist = this->CalcWaypointMapPos(tl_screen_pos, view_size, view_origin, i);
171  if (abs(cw_dist.x) <= 5 && abs(cw_dist.y) <= 5)
172  {
173  w_adj = true;
174  }
175  }
176  }
177 
178  ImGui::BeginChild("map", ImVec2(0.f, view_size.y), false);
179 
180  if (mMapMode == SurveyMapMode::BIG)
181  {
182  ImGui::Image(reinterpret_cast<ImTextureID>(mMapTexture->getHandle()), view_size);
183  }
184  else if (mMapMode == SurveyMapMode::SMALL)
185  {
186  ImDrawList* drawlist = ImGui::GetWindowDrawList();
187 
188  ImVec2 p_min = ImGui::GetCursorScreenPos();
189  ImVec2 p_max = ImVec2(p_min.x + view_size.x, p_min.y + view_size.y);
190  ImVec2 p_offset = ImVec2(5.f, 5.f);
191  ImVec2 _min(p_min + p_offset);
192  ImVec2 _max(p_max + p_offset);
193  ImVec2 uv_min(texcoords_top_left.x, texcoords_top_left.y);
194  ImVec2 uv_max(texcoords_bottom_right.x, texcoords_bottom_right.y);
195  m_circle_center =_min + ((_max-_min)/2);
196  m_circle_radius = view_size.x/2 - p_offset.x;
197 
198  // Outline
199  drawlist->AddCircle(ImVec2(p_min.x + view_size.x/2, p_min.y + view_size.y/2), view_size.x/2 - 2*p_offset.x, ImGui::GetColorU32(theme.semitransparent_window_bg), 96, 20);
200 
201  // The texture
202  drawlist->AddCircularImage(reinterpret_cast<ImTextureID>(mMapTexture->getHandle()), _min, _max, uv_min, uv_max, ImGui::GetColorU32(ImVec4(1,1,1,1)), m_circle_radius);
203 
204  // An invisible button so we can catch it below
205  ImGui::InvisibleButton("circle", view_size);
206  }
207 
208  if (ImGui::IsItemClicked(0) || ImGui::IsItemClicked(1)) // 0 = left click, 1 = right click
209  {
210  ImVec2 mouse_view_offset = (ImGui::GetMousePos() - tl_screen_pos) / view_size;
211  Vector2 mouse_map_pos;
212  if (mMapMode == SurveyMapMode::BIG)
213  {
214  mouse_map_pos = view_origin + Vector2(mouse_view_offset.x, mouse_view_offset.y) * mTerrainSize;
215  }
216  else if (mMapMode == SurveyMapMode::SMALL)
217  {
218  mouse_map_pos = view_origin + (Vector2(mouse_view_offset.x, mouse_view_offset.y) * smallmap_size);
219  }
220 
221  if (ImGui::IsItemClicked(1)) // Set AI waypoint
222  {
223  float y = App::GetGameContext()->GetTerrain()->GetCollisions()->getSurfaceHeight(mouse_map_pos.x, mouse_map_pos.y);
224  ai_events waypoint;
225  waypoint.position = Ogre::Vector3(mouse_map_pos.x, y, mouse_map_pos.y);
226  App::GetGuiManager()->TopMenubar.ai_waypoints.push_back(waypoint);
227  }
228  else if (!w_adj) // Teleport
229  {
230  Ogre::Vector3* payload = new Ogre::Vector3(mouse_map_pos.x, 0.f, mouse_map_pos.y);
232  }
233  }
234  else if (ImGui::IsItemClicked(2) && !w_adj) // 2 = middle click, clear AI waypoints
235  {
237  }
238  else if (ImGui::IsItemHovered())
239  {
240  // Draw teleport cursor
241  ImVec2 mouse_pos = ImGui::GetMousePos();
242  ImDrawList* drawlist = ImGui::GetWindowDrawList();
243  drawlist->AddCircleFilled(mouse_pos, 5, ImGui::GetColorU32(ImVec4(1,0,0,1)));
244  if (mMapMode == SurveyMapMode::SMALL)
245  {
246  const char* title = "Teleport/Waypoint";
247  ImVec2 text_pos(mouse_pos.x - (ImGui::CalcTextSize(title).x/2), mouse_pos.y - 25);
248  drawlist->AddText(text_pos, ImGui::GetColorU32(ImGui::GetStyle().Colors[ImGuiCol_Text]), title);
249  }
250  }
251 
252  // Draw AI waypoints
254  {
255  for (int i = 0; i < App::GetGuiManager()->TopMenubar.ai_waypoints.size(); i++)
256  {
257  ImVec2 cw_dist = this->DrawWaypoint(tl_screen_pos, view_size, view_origin, std::to_string(i), i);
258 
259  if (abs(cw_dist.x) <= 5 && abs(cw_dist.y) <= 5)
260  {
261  if (ImGui::IsMouseClicked(0))
262  {
263  mMouseClicked = true;
264  mWaypointNum = i;
265  }
266  else if (ImGui::IsMouseReleased(0))
267  {
268  mMouseClicked = false;
269  }
270  }
271 
272  if (mMouseClicked)
273  {
274  ImVec2 mouse_view_offset = (ImGui::GetMousePos() - tl_screen_pos) / view_size;
275  Vector2 mouse_map_pos;
276  if (mMapMode == SurveyMapMode::BIG)
277  {
278  mouse_map_pos = view_origin + Vector2(mouse_view_offset.x, mouse_view_offset.y) * mTerrainSize;
279  }
280  else if (mMapMode == SurveyMapMode::SMALL)
281  {
282  mouse_map_pos = view_origin + (Vector2(mouse_view_offset.x, mouse_view_offset.y) * smallmap_size);
283  }
284 
285  float y = App::GetGameContext()->GetTerrain()->GetCollisions()->getSurfaceHeight(mouse_map_pos.x, mouse_map_pos.y);
286  App::GetGuiManager()->TopMenubar.ai_waypoints[mWaypointNum].position = Ogre::Vector3(mouse_map_pos.x, y, mouse_map_pos.y);
287  }
288  else if (abs(cw_dist.x) <= 5 && abs(cw_dist.y) <= 5 && ImGui::IsItemClicked(2))
289  {
291  }
292  }
293  }
294 
295  if (App::gfx_surveymap_icons->getBool())
296  {
297  // Draw terrain object icons
298  for (SurveyMapEntity& e: App::GetGameContext()->GetTerrain()->getSurveyMapEntities())
299  {
301  bool visible = !((e.type == "checkpoint" && e.id != id) || (e.type == "racestart" && id != -1 && e.id != id));
302 
303  if ((visible) && (!App::gfx_declutter_map->getBool()))
304  {
305  this->CacheMapIcon(e);
306  this->DrawMapIcon(e, tl_screen_pos, view_size, view_origin);
307  }
308  }
309 
310  // Draw actor icons
311  for (GfxActor* gfx_actor: App::GetGfxScene()->GetGfxActors())
312  {
313  const char* type_str = this->getTypeByDriveable(gfx_actor->GetActor());
314  int truckstate = gfx_actor->GetActorState();
315  Str<100> fileName;
316 
317  if (truckstate == static_cast<int>(ActorState::LOCAL_SIMULATED))
318  fileName << "icon_" << type_str << "_activated.dds"; // green icon
319  else if (truckstate == static_cast<int>(ActorState::NETWORKED_OK))
320  fileName << "icon_" << type_str << "_networked.dds"; // blue icon
321  else
322  fileName << "icon_" << type_str << ".dds"; // gray icon
323 
324  auto& simbuf = gfx_actor->GetSimDataBuffer();
325 
326  // Update the surveymap icon entry
327  SurveyMapEntity& e = gfx_actor->getSurveyMapEntity();
328  e.pos = simbuf.simbuf_pos;
329  e.rot_angle = Ogre::Radian(simbuf.simbuf_rotation);
330  e.filename = fileName.ToCStr();
331 
332  // Update net player name
333  if (simbuf.simbuf_actor_state == ActorState::NETWORKED_OK)
334  {
335  e.caption = simbuf.simbuf_net_username;
336  e.caption_color = App::GetNetwork()->GetPlayerColor(simbuf.simbuf_net_colornum);
337  e.draw_caption = true;
338  }
339 
340  // Cache and draw icon
341  this->CacheMapIcon(e);
342  this->DrawMapIcon(e, tl_screen_pos, view_size, view_origin);
343  }
344 
345  // Draw character icons
346  for (GfxCharacter* gfx_character: App::GetGfxScene()->GetGfxCharacters())
347  {
348  auto& simbuf = gfx_character->xc_simbuf;
349  if (!simbuf.simbuf_actor_coupling)
350  {
351  // Update the surveymap icon entry
352  SurveyMapEntity& e = gfx_character->xc_surveymap_entity;
353  e.pos = simbuf.simbuf_character_pos;
354  e.rot_angle = simbuf.simbuf_character_rot;
355  e.filename = "icon_person_activated.dds"; // green icon
356 
357  // Update net player name
358  if (simbuf.simbuf_is_remote)
359  {
360  e.filename = "icon_person_networked.dds"; // blue icon
361  e.caption = simbuf.simbuf_net_username;
362  e.caption_color = App::GetNetwork()->GetPlayerColor(simbuf.simbuf_color_number);
363  e.draw_caption = true;
364  }
365 
366  // Cache and draw icon
367  this->CacheMapIcon(e);
368  this->DrawMapIcon(e, tl_screen_pos, view_size, view_origin);
369  }
370  }
371  }
372  ImGui::EndChild();
373 
374  // Bottom area
375  float orig_y = ImGui::GetCursorPosY();
376 
377  if (!m_icons_cached)
378  {
379  this->CacheIcons();
380  }
381 
382  ImGui::Image(reinterpret_cast<ImTextureID>(m_left_mouse_button->getHandle()), ImVec2(28, 24));
383  ImGui::SameLine();
384  ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().ItemSpacing.y);
385 
386  const char* text = "Teleport";
387  if (w_adj || mMouseClicked)
388  {
389  text = "Drag to adjust this waypoint";
390  }
391  ImGui::Text(text);
392 
393  ImGui::SameLine();
394  ImGui::SetCursorPosY(orig_y);
395  ImGui::Image(reinterpret_cast<ImTextureID>(m_right_mouse_button->getHandle()), ImVec2(28, 24));
396  ImGui::SameLine();
397  ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().ItemSpacing.y);
398 
399  text = "Set AI waypoint";
400  ImGui::Text(text);
401 
402  ImGui::SameLine();
403  ImGui::SetCursorPosY(orig_y);
404  ImGui::Image(reinterpret_cast<ImTextureID>(m_middle_mouse_button->getHandle()), ImVec2(28, 24));
405  ImGui::SameLine();
406  ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().ItemSpacing.y);
407 
408  text = "Remove all AI waypoints";
409  if (w_adj || mMouseClicked)
410  {
411  text = "Remove this waypoint";
412  }
413  ImGui::Text(text);
414 
415  ImGui::SameLine();
416  ImGui::SetCursorPosY(orig_y);
417  ImGui::Image(reinterpret_cast<ImTextureID>(m_middle_mouse_scroll_button->getHandle()), ImVec2(28, 24));
418  ImGui::SameLine();
419  ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().ItemSpacing.y);
420 
421  text = "Zoom mini map";
422  ImGui::Text(text);
423 
424  mWindowMouseHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
425 
426  ImGui::End();
427 
428  if (mMapMode == SurveyMapMode::BIG)
429  {
430  ImGui::PopStyleColor(1); // WindowBg
431  }
432  else if (mMapMode == SurveyMapMode::SMALL)
433  {
434  ImGui::PopStyleColor(2); // WindowBg, ChildBg
435  }
436 
437  ImGui::PopStyleVar(2); // WindowPadding, WindowRounding
438 }
439 
441 {
442  mMapCenterOffset = Ogre::Vector2::ZERO; // Reset, maybe new terrain was loaded
443  if (mMapTexture)
444  {
445  if (mMapTexture->getLoadingState() != Ogre::Resource::LoadingState::LOADSTATE_UNLOADED)
446  {
447  Ogre::TextureManager::getSingleton().unload(mMapTexture->getName(), mMapTexture->getGroup());
448  }
449  Ogre::TextureManager::getSingleton().remove(mMapTexture->getName(), mMapTexture->getGroup());
450  mMapTexture.setNull();
451  }
452  mMapZoom = 0.5f;
453  mMapMode = SurveyMapMode::NONE;
454 
455  AxisAlignedBox aab = App::GetGameContext()->GetTerrain()->getTerrainCollisionAAB();
456  Vector3 terrain_size = App::GetGameContext()->GetTerrain()->getMaxTerrainSize();
457  bool use_aab = App::GetGameContext()->GetTerrain()->isFlat() && std::min(aab.getSize().x, aab.getSize().z) > 50.0f;
458 
459  if (terrain_size.isZeroLength() || use_aab && (aab.getSize().length() < terrain_size.length()))
460  {
461  terrain_size = aab.getSize();
462  terrain_size.y = aab.getMaximum().y;
463  Vector3 offset = aab.getCenter() - terrain_size / 2;
464  mMapCenterOffset = Vector2(offset.x, offset.z);
465  }
466 
467  mTerrainSize = Vector2(terrain_size.x, terrain_size.z);
468  Ogre::Vector2 mMapCenter = mTerrainSize / 2;
469 
470  ConfigOptionMap ropts = App::GetAppContext()->GetOgreRoot()->getRenderSystem()->getConfigOptions();
471  int fsaa = StringConverter::parseInt(ropts["FSAA"].currentValue, 0);
472 
473  SurveyMapTextureCreator texCreatorStatic(terrain_size.y);
474  texCreatorStatic.init(4096, fsaa);
475  texCreatorStatic.update(mMapCenter + mMapCenterOffset, mTerrainSize);
476  mMapTexture = texCreatorStatic.convertTextureToStatic(
477  "SurveyMapStatic", App::GetGameContext()->GetTerrain()->getTerrainFileResourceGroup());
478 }
479 
480 
481 void SurveyMap::setMapZoom(float zoom)
482 {
483  zoom = Math::Clamp(zoom, 0.0f, std::max(0.0f, (mTerrainSize.x - 50.0f) / mTerrainSize.x));
484 
485  if (mMapZoom == zoom)
486  return;
487 
488  mMapZoom = zoom;
489 }
490 
492 {
493  setMapZoom(mMapZoom + 0.5f * delta * (1.0f - mMapZoom));
494 }
495 
496 
497 const char* SurveyMap::getTypeByDriveable(const ActorPtr& actor)
498 {
499  switch (actor->ar_driveable)
500  {
501  case NOT_DRIVEABLE:
502  return "load";
503  case TRUCK:
504  return "truck";
505  case AIRPLANE:
506  return "airplane";
507  case BOAT:
508  return "boat";
509  case MACHINE:
510  return "machine";
511  case AI:
512  return this->getAIType(actor);
513  default:
514  return "unknown";
515  }
516 }
517 
518 const char* SurveyMap::getAIType(const ActorPtr& actor)
519 {
520  if (actor->ar_engine)
521  {
522  return "truck";
523  }
524  else if (actor->ar_num_aeroengines > 0)
525  {
526  return "airplane";
527  }
528  else if (actor->ar_num_screwprops > 0)
529  {
530  return "boat";
531  }
532 
533  return "unknown";
534 }
535 
537 {
538  switch (mMapMode)
539  {
540  case SurveyMapMode::NONE: mMapLastMode = mMapMode = SurveyMapMode::SMALL; break;
541  case SurveyMapMode::SMALL: mMapLastMode = mMapMode = SurveyMapMode::BIG; break;
542  case SurveyMapMode::BIG: mMapMode = SurveyMapMode::NONE; break;
543  default:;
544  }
545 }
546 
548 {
549  mMapMode = (mMapMode == SurveyMapMode::NONE) ? mMapLastMode : SurveyMapMode::NONE;
550 }
551 
552 void SurveyMap::DrawMapIcon(const SurveyMapEntity& e, ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin)
553 {
554  Ogre::Vector2 terrn_size_adj = mTerrainSize;
555  if (mMapMode == SurveyMapMode::SMALL)
556  {
557  terrn_size_adj = mTerrainSize * (1.f - mMapZoom);
558  }
559 
560  ImVec2 img_pos;
561  img_pos.x = view_pos.x + ((e.pos.x - view_origin.x) / terrn_size_adj.x) * view_size.x;
562  img_pos.y = view_pos.y + ((e.pos.z - view_origin.y) / terrn_size_adj.y) * view_size.y;
563  float img_dist = (img_pos.x - m_circle_center.x) * (img_pos.x - m_circle_center.x) + (img_pos.y - m_circle_center.y) * (img_pos.y - m_circle_center.y);
564 
565  if (!e.cached_icon
566  || (mMapMode == SurveyMapMode::SMALL && img_dist > (m_circle_radius * m_circle_radius)*0.8))
567  {
568  return;
569  }
570 
571  DrawImageRotated(reinterpret_cast<ImTextureID>(e.cached_icon->getHandle()), img_pos,
572  ImVec2(e.cached_icon->getWidth(), e.cached_icon->getHeight()), e.rot_angle.valueRadians());
573 
574  if (e.draw_caption)
575  {
576  ImVec2 text_pos(img_pos.x - (ImGui::CalcTextSize(e.caption.c_str()).x/2), img_pos.y + 5);
577  ImVec4 text_color(e.caption_color.r, e.caption_color.g, e.caption_color.b, 1.f);
578  ImGui::GetWindowDrawList()->AddText(text_pos, ImColor(text_color), e.caption.c_str());
579  }
580  else
581  {
582  ImVec2 dist = ImGui::GetMousePos() - img_pos;
583  if (!e.caption.empty() && abs(dist.x) <= 5 && abs(dist.y) <= 5)
584  {
585  ImGui::BeginTooltip();
586  ImGui::Text("%s", e.caption.c_str());
587  ImGui::EndTooltip();
588  }
589  }
590 }
591 
592 ImVec2 SurveyMap::DrawWaypoint(ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin,
593  std::string const& caption, int idx)
594 {
595  Ogre::Vector2 terrn_size_adj = mTerrainSize;
596  if (mMapMode == SurveyMapMode::SMALL)
597  {
598  terrn_size_adj = mTerrainSize * (1.f - mMapZoom);
599  }
600 
601  ImVec2 wp_pos;
602  wp_pos.x = view_pos.x + ((App::GetGuiManager()->TopMenubar.ai_waypoints[idx].position.x - view_origin.x) / terrn_size_adj.x) * view_size.x;
603  wp_pos.y = view_pos.y + ((App::GetGuiManager()->TopMenubar.ai_waypoints[idx].position.z - view_origin.y) / terrn_size_adj.y) * view_size.y;
604 
605  float wp_dist = (wp_pos.x - m_circle_center.x) * (wp_pos.x - m_circle_center.x) + (wp_pos.y - m_circle_center.y) * (wp_pos.y - m_circle_center.y);
606  bool wp_draw = true;
607  if (mMapMode == SurveyMapMode::SMALL && wp_dist > (m_circle_radius * m_circle_radius)*0.8)
608  {
609  wp_draw = false;
610  }
611 
612  ImDrawList* drawlist = ImGui::GetWindowDrawList();
613  ImVec4 col = ImVec4(1,0,0,1);
614  ImVec2 dist = ImGui::GetMousePos() - wp_pos;
615  if (abs(dist.x) <= 5 && abs(dist.y) <= 5)
616  {
617  col = ImVec4(1,1,0,1);
618 
619  ImGui::BeginTooltip();
620  ImGui::Text("%s %s", "Waypoint", caption.c_str());
621  if (mMapMode == SurveyMapMode::BIG)
622  {
623  std::string wpos = "x:" + std::to_string(App::GetGuiManager()->TopMenubar.ai_waypoints[idx].position.x) + " y:" + std::to_string(App::GetGuiManager()->TopMenubar.ai_waypoints[idx].position.y) + " z:" + std::to_string(App::GetGuiManager()->TopMenubar.ai_waypoints[idx].position.z);
624  ImGui::TextDisabled("%s %s", "Position: ", wpos.c_str());
625  }
626  ImGui::EndTooltip();
627  }
628 
629  if (mMapMode == SurveyMapMode::BIG || (mMapMode == SurveyMapMode::SMALL && wp_draw))
630  {
631  drawlist->AddCircleFilled(wp_pos, 5, ImGui::GetColorU32(ImVec4(col)));
632  }
633 
634  if (App::GetGuiManager()->TopMenubar.ai_waypoints.size() >= 2 && idx != App::GetGuiManager()->TopMenubar.ai_waypoints.size() - 1)
635  {
636  ImVec2 next_wp_pos;
637  next_wp_pos.x = view_pos.x + ((App::GetGuiManager()->TopMenubar.ai_waypoints[idx+1].position.x - view_origin.x) / terrn_size_adj.x) * view_size.x;
638  next_wp_pos.y = view_pos.y + ((App::GetGuiManager()->TopMenubar.ai_waypoints[idx+1].position.z - view_origin.y) / terrn_size_adj.y) * view_size.y;
639 
640  float next_wp_dist = (next_wp_pos.x - m_circle_center.x) * (next_wp_pos.x - m_circle_center.x) + (next_wp_pos.y - m_circle_center.y) * (next_wp_pos.y - m_circle_center.y);
641  bool next_wp_draw = true;
642  if (mMapMode == SurveyMapMode::SMALL && next_wp_dist > (m_circle_radius * m_circle_radius)*0.8)
643  {
644  next_wp_draw = false;
645  }
646 
647  if (mMapMode == SurveyMapMode::BIG || (mMapMode == SurveyMapMode::SMALL && wp_draw && next_wp_draw))
648  {
649  drawlist->AddLine(wp_pos, next_wp_pos, ImGui::GetColorU32(ImVec4(1,0,0,1)));
650  }
651  }
652 
653  return ImGui::GetMousePos() - wp_pos;
654 }
655 
656 ImVec2 SurveyMap::CalcWaypointMapPos(ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin, int idx)
657 {
658  Ogre::Vector2 terrn_size_adj = mTerrainSize;
659  if (mMapMode == SurveyMapMode::SMALL)
660  {
661  terrn_size_adj = mTerrainSize * (1.f - mMapZoom);
662  }
663 
664  ImVec2 pos;
665  pos.x = view_pos.x + ((App::GetGuiManager()->TopMenubar.ai_waypoints[idx].position.x - view_origin.x) / terrn_size_adj.x) * view_size.x;
666  pos.y = view_pos.y + ((App::GetGuiManager()->TopMenubar.ai_waypoints[idx].position.z - view_origin.y) / terrn_size_adj.y) * view_size.y;
667 
668  return ImGui::GetMousePos() - pos;
669 }
670 
672 {
673  // Thanks WillM for the icons!
674 
675  m_left_mouse_button = FetchIcon("left-mouse-button.png");
676  m_middle_mouse_button = FetchIcon("middle-mouse-button.png");
677  m_middle_mouse_scroll_button = FetchIcon("middle-mouse-scroll-button.png");
678  m_right_mouse_button = FetchIcon("right-mouse-button.png");
679 
680  m_icons_cached = true;
681 }
682 
684 {
685  // Check if requested icon changed
686  if (e.cached_icon && e.cached_icon->getName() != e.filename)
687  e.cached_icon.setNull();
688 
689  // Check if valid icon is already loaded
690  if (e.cached_icon)
691  return;
692 
693  if (e.resource_group == "")
695 
696  if (e.filename != "")
697  {
698  try
699  {
700  e.cached_icon = Ogre::TextureManager::getSingleton().load(e.filename, e.resource_group);
701  }
702  catch (Ogre::FileNotFoundException)
703  {
704  // ignore silently and try loading substitute
705  }
706  }
707 
708  if (!e.cached_icon)
709  {
710  try
711  {
712  e.cached_icon = Ogre::TextureManager::getSingleton().load(
713  "icon_missing.dds", ContentManager::ResourcePack::TEXTURES.resource_group_name);
714  e.filename = "icon_missing.dds"; // Prevent constant reloading
715  }
716  catch (Ogre::FileNotFoundException)
717  {
718  return; // Draw nothing
719  }
720  }
721 }
GameContext.h
Game state manager and message-queue provider.
RoR::App::GetNetwork
Network * GetNetwork()
Definition: Application.cpp:284
RoR::SurveyMapEntity::rot_angle
Ogre::Radian rot_angle
world yaw in radians
Definition: SurveyMapEntity.h:49
RoR::SurveyMapTextureCreator::init
bool init(int res, int fsaa)
Definition: SurveyMapTextureCreator.cpp:54
ai_events::position
Ogre::Vector3 position
Definition: GUI_TopMenubar.h:39
y
float y
Definition: (ValueTypes) quaternion.h:6
RoR::RaceSystem::GetRaceId
int GetRaceId() const
Definition: RaceSystem.h:37
RoR::MACHINE
@ MACHINE
its a machine
Definition: SimData.h:96
RoR::FetchIcon
Ogre::TexturePtr FetchIcon(const char *name)
Definition: GUIUtils.cpp:344
RoR::TRUCK
@ TRUCK
its a truck (or other land vehicle)
Definition: SimData.h:93
RoR::SurveyMapEntity::caption
std::string caption
display caption
Definition: SurveyMapEntity.h:45
RoR::Terrain::getMaxTerrainSize
Ogre::Vector3 getMaxTerrainSize()
Definition: Terrain.cpp:496
RoR::GfxScene::GetSimDataBuffer
GameContextSB & GetSimDataBuffer()
Definition: GfxScene.h:61
RoR::GUIManager::GuiTheme
Definition: GUIManager.h:68
RoR::App::GetCameraManager
CameraManager * GetCameraManager()
Definition: Application.cpp:275
RoR::App::GetGuiManager
GUIManager * GetGuiManager()
Definition: Application.cpp:269
ContentManager.h
RoR::AppContext::GetRenderWindow
Ogre::RenderWindow * GetRenderWindow()
Definition: AppContext.h:67
RoR::GUI::SurveyMap::DrawMapIcon
void DrawMapIcon(const SurveyMapEntity &e, ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin)
Definition: GUI_SurveyMap.cpp:552
RoR::App::GetAppContext
AppContext * GetAppContext()
Definition: Application.cpp:266
RoR::Terrain::isFlat
bool isFlat()
Definition: Terrain.cpp:518
GUIUtils.h
RoR::CameraManager::CAMERA_BEHAVIOR_FREE
@ CAMERA_BEHAVIOR_FREE
Definition: CameraManager.h:52
RoR::CVar::getBool
bool getBool() const
Definition: CVar.h:98
RoR::Actor::ar_engine
EngineSim * ar_engine
Definition: Actor.h:379
RoR::SurveyMapEntity::filename
std::string filename
Requested icon, cached may be out of date.
Definition: SurveyMapEntity.h:46
RoR::GUI::SurveyMap::setMapZoomRelative
void setMapZoomRelative(float dt_sec)
Definition: GUI_SurveyMap.cpp:491
AppContext.h
System integration layer; inspired by OgreBites::ApplicationContext.
RoR::EV_SURVEY_MAP_ZOOM_IN
@ EV_SURVEY_MAP_ZOOM_IN
increase survey map scale
Definition: InputEngine.h:294
RoR::Actor::GetGfxActor
GfxActor * GetGfxActor()
Definition: Actor.h:269
RoR::GUI::TopMenubar::ai_waypoints
std::vector< ai_events > ai_waypoints
Definition: GUI_TopMenubar.h:68
RoR::ActorState::LOCAL_SIMULATED
@ LOCAL_SIMULATED
simulated (local) actor
RoR::Terrain::getTerrainCollisionAAB
Ogre::AxisAlignedBox getTerrainCollisionAAB()
Definition: Terrain.cpp:491
RoR::NOT_DRIVEABLE
@ NOT_DRIVEABLE
not drivable at all
Definition: SimData.h:92
Language.h
RoR::GUIManager::GuiTheme::semitransparent_window_bg
ImVec4 semitransparent_window_bg
Definition: GUIManager.h:81
RoR::GameContextSB::simbuf_player_actor
ActorPtr simbuf_player_actor
Definition: SimBuffers.h:201
TerrainObjectManager.h
OgreImGui.h
RefCountingObjectPtr< Actor >
RoR::GUI::SurveyMap::DrawWaypoint
ImVec2 DrawWaypoint(ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin, std::string const &caption, int idx)
Definition: GUI_SurveyMap.cpp:592
GUIManager.h
RoR::GUI::SurveyMap::CalcWaypointMapPos
ImVec2 CalcWaypointMapPos(ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin, int idx)
Definition: GUI_SurveyMap.cpp:656
Actor.h
RoR::GameContext::GetRaceSystem
RaceSystem & GetRaceSystem()
Definition: GameContext.h:168
GUI_SurveyMap.h
RoR::GUI::SurveyMap::Draw
void Draw()
Definition: GUI_SurveyMap.cpp:46
RoR::GUIManager::GetTheme
GuiTheme & GetTheme()
Definition: GUIManager.h:154
RoR::GUI::SurveyMap::ToggleMode
void ToggleMode()
Definition: GUI_SurveyMap.cpp:547
RoR::Actor::ar_num_aeroengines
int ar_num_aeroengines
Definition: Actor.h:330
RoR::Str
Wrapper for classic c-string (local buffer) Refresher: strlen() excludes '\0' terminator; strncat() A...
Definition: Str.h:35
RoR::SurveyMapTextureCreator::update
void update(Ogre::Vector2 center, Ogre::Vector2 size)
Definition: SurveyMapTextureCreator.cpp:87
GUI_MainSelector.h
RoR::GUI::SurveyMap::getTypeByDriveable
const char * getTypeByDriveable(const ActorPtr &actor)
Definition: GUI_SurveyMap.cpp:497
RoR::GUI::MainSelector::IsVisible
bool IsVisible()
Definition: GUI_MainSelector.h:48
RoR::GameContext::PushMessage
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
Definition: GameContext.cpp:65
RoR::ContentManager::ResourcePack::TEXTURES
static const ResourcePack TEXTURES
Definition: ContentManager.h:70
RoR::GfxCharacter
Definition: Character.h:99
RoR::Str::ToCStr
const char * ToCStr() const
Definition: Str.h:46
RoR::SurveyMapEntity::resource_group
std::string resource_group
if empty, defaults to TexturesRG
Definition: SurveyMapEntity.h:47
RoR::Terrain::GetCollisions
Collisions * GetCollisions()
Definition: Terrain.h:83
GfxScene.h
RoR::App::gfx_declutter_map
CVar * gfx_declutter_map
Definition: Application.cpp:231
RoR::GUI::TopMenubar
Definition: GUI_TopMenubar.h:46
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:280
RoR::AIRPLANE
@ AIRPLANE
its an airplane
Definition: SimData.h:94
RoR::EV_SURVEY_MAP_ZOOM_OUT
@ EV_SURVEY_MAP_ZOOM_OUT
decrease survey map scale
Definition: InputEngine.h:295
RoR::Actor::ar_num_screwprops
int ar_num_screwprops
Definition: Actor.h:332
RoR::SurveyMapEntity::draw_caption
bool draw_caption
By default, don't draw caption under icon, use the mouse tooltip.
Definition: SurveyMapEntity.h:52
RoR::Collisions::getSurfaceHeight
float getSurfaceHeight(float x, float z)
Definition: Collisions.cpp:671
RoR::SurveyMapTextureCreator
Definition: SurveyMapTextureCreator.h:28
RoR::GUI::SurveyMap::CreateTerrainTextures
void CreateTerrainTextures()
Definition: GUI_SurveyMap.cpp:440
RoR::EV_SURVEY_MAP_TOGGLE_ICONS
@ EV_SURVEY_MAP_TOGGLE_ICONS
toggle map icons
Definition: InputEngine.h:291
RoR::MSG_SIM_TELEPORT_PLAYER_REQUESTED
@ MSG_SIM_TELEPORT_PLAYER_REQUESTED
Payload = Ogre::Vector3* (owner)
Definition: Application.h:123
RoR::GUIManager::TopMenubar
GUI::TopMenubar TopMenubar
Definition: GUIManager.h:120
RoR::GUI::SurveyMap::CycleMode
void CycleMode()
Definition: GUI_SurveyMap.cpp:536
RoR::Network::GetPlayerColor
Ogre::ColourValue GetPlayerColor(int color_num)
Definition: Network.cpp:94
RoR::GUIManager::GuiTheme::screen_edge_padding
ImVec2 screen_edge_padding
Definition: GUIManager.h:85
RoR::GUI::MainSelector
Definition: GUI_MainSelector.h:38
SurveyMapTextureCreator.h
RoR::SurveyMapEntity::cached_icon
Ogre::TexturePtr cached_icon
Definition: SurveyMapEntity.h:51
RoR::GUI::SurveyMap::setMapZoom
void setMapZoom(float zoom)
Definition: GUI_SurveyMap.cpp:481
RoR::SurveyMapTextureCreator::convertTextureToStatic
Ogre::TexturePtr convertTextureToStatic(const std::string &texName, const std::string &rgName)
Definition: SurveyMapTextureCreator.cpp:120
RoR::GUI::SurveyMap::CacheIcons
void CacheIcons()
Definition: GUI_SurveyMap.cpp:671
ai_events
Definition: GUI_TopMenubar.h:37
RoR::Message
Unified game event system - all requests and state changes are reported using a message.
Definition: GameContext.h:51
RoR::Actor::ar_driveable
ActorType ar_driveable
Sim attr; marks vehicle type and features.
Definition: Actor.h:378
RoR::CVar::setVal
void setVal(T val)
Definition: CVar.h:72
RoR::ContentManager::ResourcePack::resource_group_name
const char * resource_group_name
Definition: ContentManager.h:73
RoR::SurveyMapEntity::pos
Ogre::Vector3 pos
world pos in meters
Definition: SurveyMapEntity.h:48
RoR::App::GetInputEngine
InputEngine * GetInputEngine()
Definition: Application.cpp:271
RoR::AppContext::GetOgreRoot
Ogre::Root * GetOgreRoot()
Definition: AppContext.h:65
Terrain.h
RoR::GfxActor
Definition: GfxActor.h:52
InputEngine.h
Handles controller inputs from player. Defines input events and binding mechanism,...
Ogre
Definition: ExtinguishableFireAffector.cpp:35
GfxActor.h
Manager for all visuals belonging to a single actor.
Collisions.h
RoR::GUI::SurveyMap::CacheMapIcon
void CacheMapIcon(SurveyMapEntity &e)
Definition: GUI_SurveyMap.cpp:683
RoR::BOAT
@ BOAT
its a boat
Definition: SimData.h:95
RoR::ActorState::NETWORKED_OK
@ NETWORKED_OK
not simulated (remote) actor
RoR::SurveyMapEntity
Definition: SurveyMapEntity.h:35
RoR::AI
@ AI
machine controlled by an Artificial Intelligence
Definition: SimData.h:97
RoR::GfxActor::GetSimDataBuffer
ActorSB & GetSimDataBuffer()
Definition: GfxActor.h:119
RoR
Definition: AppContext.h:36
RoR::GUI::SurveyMap::getAIType
const char * getAIType(const ActorPtr &actor)
Definition: GUI_SurveyMap.cpp:518
x
float x
Definition: (ValueTypes) quaternion.h:5
RoR::SurveyMapEntity::caption_color
Ogre::ColourValue caption_color
Definition: SurveyMapEntity.h:53
RoR::DrawImageRotated
void DrawImageRotated(ImTextureID tex_id, ImVec2 center, ImVec2 size, float angle)
Add rotated textured quad to ImDrawList, source: https://github.com/ocornut/imgui/issues/1982#issueco...
Definition: GUIUtils.cpp:175
RoR::App::GetGfxScene
GfxScene * GetGfxScene()
Definition: Application.cpp:276
RoR::App::gfx_surveymap_icons
CVar * gfx_surveymap_icons
Definition: Application.cpp:230
RoR::GameContext::GetTerrain
const TerrainPtr & GetTerrain()
Definition: GameContext.h:117