Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
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"
40#include "Collisions.h"
41
42using namespace RoR;
43using namespace GUI;
44using namespace Ogre;
45
47{
48 // Check special cases
52 {
54 return;
55 }
56
57 // Handle input
58 if (App::GetInputEngine()->getEventBoolValueBounce(EV_SURVEY_MAP_TOGGLE_ICONS))
60
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
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);
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 }
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
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);
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
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;
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)));
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;
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
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
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.reset();
451 }
452 mMapZoom = 0.5f;
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
481void 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
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
518const 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 {
543 default:;
544 }
545}
546
551
552void SurveyMap::DrawMapIcon(const SurveyMapEntity& e, ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin)
553{
554 Ogre::Vector2 terrn_size_adj = mTerrainSize;
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
592ImVec2 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;
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;
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());
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
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
656ImVec2 SurveyMap::CalcWaypointMapPos(ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin, int idx)
657{
658 Ogre::Vector2 terrn_size_adj = mTerrainSize;
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.reset();
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}
System integration layer; inspired by OgreBites::ApplicationContext.
Game state manager and message-queue provider.
Manager for all visuals belonging to a single actor.
Handles controller inputs from player.
int ar_num_screwprops
Definition Actor.h:391
EnginePtr ar_engine
Definition Actor.h:432
GfxActor * GetGfxActor()
Definition Actor.h:309
int ar_num_aeroengines
Definition Actor.h:389
ActorType ar_driveable
Sim attr; marks vehicle type and features.
Definition Actor.h:431
Ogre::Root * GetOgreRoot()
Definition AppContext.h:65
Ogre::RenderWindow * GetRenderWindow()
Definition AppContext.h:67
bool getBool() const
Definition CVar.h:98
void setVal(T val)
Definition CVar.h:72
float getSurfaceHeight(float x, float z)
SurveyMapMode mMapMode
ImVec2 DrawWaypoint(ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin, std::string const &caption, int idx)
Ogre::Vector2 mMapCenterOffset
Ogre::TexturePtr m_right_mouse_button
SurveyMapMode mMapLastMode
void DrawMapIcon(const SurveyMapEntity &e, ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin)
Ogre::TexturePtr mMapTexture
void setMapZoom(float zoom)
Ogre::TexturePtr m_middle_mouse_scroll_button
const float WINDOW_ROUNDING
const float WINDOW_PADDING
Ogre::TexturePtr m_left_mouse_button
const char * getAIType(const ActorPtr &actor)
Ogre::TexturePtr m_middle_mouse_button
const char * getTypeByDriveable(const ActorPtr &actor)
Ogre::Vector2 mTerrainSize
void CacheMapIcon(SurveyMapEntity &e)
ImVec2 CalcWaypointMapPos(ImVec2 view_pos, ImVec2 view_size, Ogre::Vector2 view_origin, int idx)
void setMapZoomRelative(float dt)
std::vector< ai_events > ai_waypoints
GUI::TopMenubar TopMenubar
Definition GUIManager.h:133
GuiTheme & GetTheme()
Definition GUIManager.h:168
const TerrainPtr & GetTerrain()
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
RaceSystem & GetRaceSystem()
ActorSB & GetSimDataBuffer()
Definition GfxActor.h:128
GameContextSB & GetSimDataBuffer()
Definition GfxScene.h:80
std::vector< GfxActor * > & GetGfxActors()
Definition GfxScene.h:84
std::vector< GfxCharacter * > & GetGfxCharacters()
Definition GfxScene.h:85
Ogre::ColourValue GetPlayerColor(int color_num)
Definition Network.cpp:94
int GetRaceId() const
Definition RaceSystem.h:37
Wrapper for classic c-string (local buffer) Refresher: strlen() excludes '\0' terminator; strncat() A...
Definition Str.h:36
const char * ToCStr() const
Definition Str.h:46
Ogre::TexturePtr convertTextureToStatic(const std::string &texName, const std::string &rgName)
void update(Ogre::Vector2 center, Ogre::Vector2 size)
Ogre::Vector3 getMaxTerrainSize()
Definition Terrain.cpp:505
SurveyMapEntityVec & getSurveyMapEntities()
Definition Terrain.cpp:579
Collisions * GetCollisions()
Definition Terrain.h:86
bool isFlat()
Definition Terrain.cpp:527
Ogre::AxisAlignedBox getTerrainCollisionAAB()
Definition Terrain.cpp:500
@ MACHINE
its a machine
Definition SimData.h:88
@ TRUCK
its a truck (or other land vehicle)
Definition SimData.h:85
@ NOT_DRIVEABLE
not drivable at all
Definition SimData.h:84
@ BOAT
its a boat
Definition SimData.h:87
@ AIRPLANE
its an airplane
Definition SimData.h:86
@ AI
machine controlled by an Artificial Intelligence
Definition SimData.h:89
@ EV_SURVEY_MAP_ZOOM_OUT
decrease survey map scale
@ EV_SURVEY_MAP_TOGGLE_ICONS
toggle map icons
@ EV_SURVEY_MAP_ZOOM_IN
increase survey map scale
@ MSG_SIM_TELEPORT_PLAYER_REQUESTED
Payload = Ogre::Vector3* (owner)
@ LOCAL_SIMULATED
simulated (local) actor
@ NETWORKED_OK
not simulated (remote) actor
AppContext * GetAppContext()
InputEngine * GetInputEngine()
CameraManager * GetCameraManager()
GUIManager * GetGuiManager()
GameContext * GetGameContext()
GfxScene * GetGfxScene()
CVar * gfx_declutter_map
CVar * gfx_surveymap_icons
Network * GetNetwork()
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:201
Ogre::TexturePtr FetchIcon(const char *name)
Definition GUIUtils.cpp:372
static const ResourcePack TEXTURES
ActorPtr simbuf_player_actor
Definition SimBuffers.h:203
Unified game event system - all requests and state changes are reported using a message.
Definition GameContext.h:52
bool draw_caption
By default, don't draw caption under icon, use the mouse tooltip.
Ogre::Vector3 pos
world pos in meters
std::string caption
display caption
Ogre::ColourValue caption_color
std::string filename
Requested icon, cached may be out of date.
Ogre::TexturePtr cached_icon
Ogre::Radian rot_angle
world yaw in radians
std::string resource_group
if empty, defaults to TexturesRG
Ogre::Vector3 position