54 #include <fmt/format.h>
58 # include <curl/curl.h>
59 # include <curl/easy.h>
62 #if defined(_MSC_VER) && defined(GetObject) // This MS Windows macro from <wingdi.h> (Windows Kit 8.1) clashes with RapidJSON
71 static size_t CurlWriteFunc(
void *ptr,
size_t size,
size_t nmemb, std::string* data)
73 data->append((
char*)ptr, size * nmemb);
86 Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(
"waypoints.json",
RGN_SAVEGAMES);
102 std::string url =
"https://raw.githubusercontent.com/RigsOfRods-Community/ai-waypoints/main/waypoints.json";
103 std::string response_payload;
104 long response_code = 0;
106 CURL *curl = curl_easy_init();
107 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
108 curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
110 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
112 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
CurlWriteFunc);
113 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_payload);
115 CURLcode curl_result = curl_easy_perform(curl);
116 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
118 curl_easy_cleanup(curl);
121 if (curl_result != CURLE_OK || response_code != 200)
123 Ogre::LogManager::getSingleton().stream()
124 <<
"[RoR|Repository] Failed to download AI presets;"
125 <<
" Error: '" << curl_easy_strerror(curl_result) <<
"'; HTTP status code: " << response_code;
138 #endif // defined(USE_CURL)
161 int num_playable_actors = 0;
164 if (!actor->ar_hide_in_actor_list)
166 num_playable_actors++;
170 std::string sim_title =
_LC(
"TopMenubar",
"Simulation");
171 std::string actors_title =
fmt::format(
"{} ({})",
_LC(
"TopMenubar",
"Vehicles"), num_playable_actors);
172 std::string savegames_title =
_LC(
"TopMenubar",
"Saves");
173 std::string settings_title =
_LC(
"TopMenubar",
"Settings");
174 std::string tools_title =
_LC(
"TopMenubar",
"Tools");
175 std::string ai_title =
_LC(
"TopMenubar",
"Vehicle AI");
176 std::string tuning_title =
_LC(
"TopMenubar",
"Tuning");
178 int menubar_num_buttons = 5;
179 float menubar_content_width =
180 ImGui::CalcTextSize(sim_title.c_str()).x +
181 ImGui::CalcTextSize(actors_title.c_str()).x +
182 ImGui::CalcTextSize(savegames_title.c_str()).x +
183 ImGui::CalcTextSize(settings_title.c_str()).x +
184 ImGui::CalcTextSize(tools_title.c_str()).x;
188 menubar_num_buttons += 1;
189 menubar_content_width += ImGui::CalcTextSize(ai_title.c_str()).x;
194 menubar_num_buttons += 1;
195 menubar_content_width += ImGui::CalcTextSize(tuning_title.c_str()).x;
198 menubar_content_width +=
199 (ImGui::GetStyle().ItemSpacing.x * (menubar_num_buttons - 1)) +
200 (ImGui::GetStyle().FramePadding.x * (menubar_num_buttons * 2));
202 ImVec2 window_target_pos = ImVec2((ImGui::GetIO().DisplaySize.x/2.f) - (menubar_content_width / 2.f), theme.
screen_edge_padding.y);
212 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
215 int flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove
216 | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize;
217 ImGui::SetNextWindowContentSize(ImVec2(menubar_content_width, 0.f));
218 ImGui::SetNextWindowPos(window_target_pos);
219 ImGui::Begin(
"Top menubar",
nullptr, flags);
221 if (ImGui::IsWindowHovered())
227 ImVec2 window_pos = ImGui::GetWindowPos();
228 ImVec2 sim_cursor = ImGui::GetCursorPos();
229 ImGui::Button(sim_title.c_str());
236 ImVec2 tuning_cursor = ImVec2(0, 0);
240 tuning_cursor = ImGui::GetCursorPos();
241 ImGui::Button(tuning_title.c_str());
249 ImVec2 ai_cursor = ImVec2(0, 0);
253 ai_cursor = ImGui::GetCursorPos();
254 ImGui::Button(ai_title.c_str());
264 ImVec2 actors_cursor = ImGui::GetCursorPos();
265 ImGui::Button(actors_title.c_str());
274 ImVec2 savegames_cursor = ImGui::GetCursorPos();
275 ImGui::Button(savegames_title.c_str());
282 for (
int i = 0; i <= 9; i++)
292 ImVec2 settings_cursor = ImGui::GetCursorPos();
293 ImGui::Button(settings_title.c_str());
306 ImVec2 tools_cursor = ImGui::GetCursorPos();
307 ImGui::Button(tools_title.c_str());
313 ImVec2 topmenu_final_size = ImGui::GetWindowSize();
325 menu_pos.x = sim_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
326 ImGui::SetNextWindowPos(menu_pos);
327 if (ImGui::Begin(
_LC(
"TopMenubar",
"Sim menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
331 if (ImGui::Button(
_LC(
"TopMenubar",
"Get new vehicle")))
340 if (current_actor !=
nullptr)
342 if (ImGui::Button(
_LC(
"TopMenubar",
"Show vehicle description")))
349 if (ImGui::Button(
_LC(
"TopMenubar",
"Reload current vehicle")))
357 if (ImGui::Button(
_LC(
"TopMenubar",
"Remove current vehicle")))
365 if (ImGui::Button(
_LC(
"TopMenubar",
"Activate last spawned vehicle")))
373 if (ImGui::Button(
_LC(
"TopMenubar",
"Reload last spawned vehicle")))
381 if (ImGui::Button(
_LC(
"TopMenubar",
"Remove last spawned vehicle")))
390 if (ImGui::Button(
_LC(
"TopMenubar",
"Remove all vehicles")))
397 if (ImGui::Button(
_LC(
"TopMenubar",
" [!] Confirm removal")))
401 if (!actor->ar_hide_in_actor_list && !actor->isPreloadedWithTerrain() &&
409 ImGui::PopStyleColor();
412 if (ImGui::Button(
_LC(
"TopMenubar",
"Activate all vehicles")))
418 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Activated vehicles never sleep"), &force_trucks_active))
423 if (ImGui::Button(
_LC(
"TopMenubar",
"Send all vehicles to sleep")))
431 if (ImGui::Button(
_LC(
"TopMenubar",
"Reload current terrain")))
444 if (ImGui::Button(
_LC(
"TopMenubar",
"Back to menu")))
454 if (ImGui::Button(
_LC(
"TopMenubar",
"Exit")))
469 menu_pos.x = actors_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
470 ImGui::SetNextWindowPos(menu_pos);
471 if (ImGui::Begin(
_LC(
"TopMenubar",
"Actors menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
484 for (
auto& user: remote_users)
488 #endif // USE_SOCKETW
499 menu_pos.y = window_pos.y + savegames_cursor.y +
MENU_Y_OFFSET;
500 menu_pos.x = savegames_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
501 ImGui::SetNextWindowPos(menu_pos);
502 if (ImGui::Begin(
_LC(
"TopMenubar",
"Savegames"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
504 if (ImGui::Button(
_LC(
"TopMenubar",
"Quicksave")))
514 if (ImGui::Button(
_LC(
"TopMenubar",
"Quickload")))
525 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"(Save with CTRL+ALT+1..5)"));
526 for (
int i = 1; i <= 5; i++)
528 Ogre::String name =
_LC(
"TopMenubar",
"Empty Slot");
534 if (ImGui::Button(caption.c_str()))
542 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"(Load with ALT+1..5)"));
543 for (
int i = 1; i <= 5; i++)
549 if (ImGui::Button(caption.c_str()))
567 menu_pos.y = window_pos.y + settings_cursor.y +
MENU_Y_OFFSET;
568 menu_pos.x = settings_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
569 ImGui::SetNextWindowPos(menu_pos);
570 if (ImGui::Begin(
_LC(
"TopMenubar",
"Settings menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
574 ImGui::PushItemWidth(125.f);
580 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"Frames per second:"));
590 float slowmotion = std::min(
App::GetGameContext()->GetActorManager()->GetSimulationSpeed(), 1.0f);
591 if (ImGui::SliderFloat(
_LC(
"TopMenubar",
"Slow motion"), &slowmotion, 0.01f, 1.0f))
595 float timelapse = std::max(
App::GetGameContext()->GetActorManager()->GetSimulationSpeed(), 1.0f);
596 if (ImGui::SliderFloat(
_LC(
"TopMenubar",
"Time lapse"), &timelapse, 1.0f, 10.0f))
616 if (ImGui::SliderInt(
_LC(
"TopMenubar",
"FOV"), &fov, 10, 120))
624 if (ImGui::SliderInt(
_LC(
"TopMenubar",
"FOV"), &fov, 10, 120))
660 ImGui::PushID(
"waves");
671 if (current_actor !=
nullptr)
674 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"Vehicle control options:"));
686 ImGui::PopItemWidth();
697 menu_pos.x = tools_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
698 ImGui::SetNextWindowPos(menu_pos);
699 if (ImGui::Begin(
_LC(
"TopMenubar",
"Tools menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
701 if (ImGui::Button(
_LC(
"TopMenubar",
"Friction settings")))
707 if (ImGui::Button(
_LC(
"TopMenubar",
"Show console")))
713 if (ImGui::Button(
_LC(
"TopMenubar",
"Texture tool")))
719 if (ImGui::Button(
_LC(
"TopMenubar",
"Collisions debug")))
725 if (current_actor !=
nullptr)
727 if (ImGui::Button(
_LC(
"TopMenubar",
"Node / Beam utility")))
733 if (ImGui::Button(
_LC(
"TopMenubar",
"FlexBody debug")))
740 if (ImGui::Button(
_LC(
"TopMenubar",
"Browse gadgets ...")))
747 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"Pre-spawn diag. options:"));
750 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Node mass recalc. logging"), &diag_mass))
754 if (ImGui::IsItemHovered())
756 ImGui::BeginTooltip();
757 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Extra logging on runtime - mass recalculation"));
762 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Beam break logging"), &diag_break))
766 if (ImGui::IsItemHovered())
768 ImGui::BeginTooltip();
769 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Extra logging on runtime"));
774 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Beam deform. logging"), &diag_deform))
778 if (ImGui::IsItemHovered())
780 ImGui::BeginTooltip();
781 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Extra logging on runtime"));
786 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Trigger logging"), &diag_trig))
790 if (ImGui::IsItemHovered())
792 ImGui::BeginTooltip();
793 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Extra logging on runtime - trigger beams activity"));
798 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"VideoCamera direction marker"), &diag_vcam))
802 if (ImGui::IsItemHovered())
804 ImGui::BeginTooltip();
805 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Visual marker of VideoCameras direction"));
809 ImGui::PushItemWidth(125.f);
813 if (ImGui::IsItemHovered())
815 ImGui::BeginTooltip();
816 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"1 = Solid"));
817 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"2 = Wireframe"));
818 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"3 = Points"));
832 menu_pos.x = ai_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
833 ImGui::SetNextWindowPos(menu_pos);
834 if (ImGui::Begin(
_LC(
"TopMenubar",
"AI menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
836 if (ImGui::IsWindowHovered())
841 ImGui::PushItemWidth(125.f);
850 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
851 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
854 ImGui::InputInt(
_LC(
"TopMenubar",
"Vehicle count"), &
ai_num, 1, 100);
855 if (ImGui::IsItemHovered())
857 ImGui::BeginTooltip();
858 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Number of vehicles"));
864 ImGui::PopItemFlag();
865 ImGui::PopStyleVar();
870 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
871 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
876 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
877 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
880 ImGui::InputInt(
_LC(
"TopMenubar",
"Distance"), &
ai_distance, 1, 100);
881 if (ImGui::IsItemHovered())
883 ImGui::BeginTooltip();
884 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Following distance in meters"));
890 ImGui::PopItemFlag();
891 ImGui::PopStyleVar();
894 std::string label1 =
"Behind";
906 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
907 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
910 if (ImGui::BeginCombo(
"Position", label1.c_str()))
912 if (ImGui::Selectable(
"Behind"))
916 if (ImGui::Selectable(
"Parallel"))
922 if (ImGui::IsItemHovered())
924 ImGui::BeginTooltip();
925 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Positioning scheme"));
927 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Behind: Set vehicle behind vehicle, in line"));
928 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Parallel: Set vehicles in parallel, useful for certain scenarios like drag races"));
934 ImGui::PopItemFlag();
935 ImGui::PopStyleVar();
943 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
944 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
947 ImGui::InputInt(
_LC(
"TopMenubar",
"Repeat times"), &
ai_times, 1, 100);
948 if (ImGui::IsItemHovered())
950 ImGui::BeginTooltip();
951 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"How many times to loop the path"));
957 ImGui::PopItemFlag();
958 ImGui::PopStyleVar();
963 ImGui::PopItemFlag();
964 ImGui::PopStyleVar();
970 std::string label2 =
"Normal";
977 label2 =
"Drag Race";
990 if (actor->ar_driveable ==
AI)
992 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
993 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
998 if (ImGui::BeginCombo(
"Mode", label2.c_str()))
1000 if (ImGui::Selectable(
"Normal"))
1013 if (ImGui::Selectable(
"Race"))
1026 if (ImGui::Selectable(
"Drag Race"))
1043 if (ImGui::Selectable(
"Crash"))
1059 if (ImGui::Selectable(
"Chase"))
1074 if (ImGui::IsItemHovered())
1076 ImGui::BeginTooltip();
1077 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicle driving mode"));
1079 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Normal: Modify speed according to turns, other vehicles and character"));
1080 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Race: Always keep defined speed"));
1081 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Drag Race: Two vehicles performing a drag race"));
1082 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Crash: Two vehicles driving in opposite direction"));
1083 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Chase: Follow character and player vehicle"));
1084 ImGui::EndTooltip();
1089 if (actor->ar_driveable ==
AI)
1091 ImGui::PopItemFlag();
1092 ImGui::PopStyleVar();
1100 ImGui::InputInt(
_LC(
"TopMenubar",
"Speed"), &
ai_speed, 1, 100);
1101 if (ImGui::IsItemHovered())
1103 ImGui::BeginTooltip();
1104 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Speed in km/h for land vehicles or knots/s for boats"));
1105 ImGui::EndTooltip();
1111 ImGui::InputInt(
_LC(
"TopMenubar",
"Altitude"), &
ai_altitude, 1, 100);
1112 if (ImGui::IsItemHovered())
1114 ImGui::BeginTooltip();
1115 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Airplane maximum altitude in feet"));
1116 ImGui::EndTooltip();
1129 if (ImGui::IsItemHovered())
1131 ImGui::BeginTooltip();
1132 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicles, boats and airplanes"));
1133 ImGui::EndTooltip();
1138 ImGui::PushID(
"vehicle2");
1147 if (ImGui::IsItemHovered())
1149 ImGui::BeginTooltip();
1150 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicles, boats and airplanes"));
1151 ImGui::EndTooltip();
1160 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1161 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1166 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]);
1169 if (ImGui::Button(
_LC(
"TopMenubar",
"Start"), ImVec2(80, 0)))
1193 fmt::format(
_LC(
"TopMenubar",
"Select a preset, record or open survey map ({}) to set waypoints."),
1205 ImGui::PopStyleColor();
1210 if (ImGui::Button(
_LC(
"TopMenubar",
"Stop"), ImVec2(80, 0)))
1219 if (actor->ar_driveable ==
AI)
1228 ImGui::PopItemFlag();
1229 ImGui::PopStyleVar();
1234 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_Button]);
1235 std::string label =
"Record";
1238 label =
"Recording";
1239 ImGui::PushStyleColor(ImGuiCol_Button,
RED_TEXT);
1242 if (ImGui::Button(label.c_str(), ImVec2(80, 0)))
1255 ImGui::PopStyleColor();
1258 if (ImGui::CollapsingHeader(
_LC(
"TopMenubar",
"Presets")))
1262 int display_count = 0;
1263 for (
size_t i = 0; i < num_rows; i++)
1265 rapidjson::Value& j_row =
ai_presets_all[
static_cast<rapidjson::SizeType
>(i)];
1270 if (ImGui::Button(j_row[
"preset"].GetString(), ImVec2(250, 0)))
1274 for (
size_t i = 0; i < j_row[
"waypoints"].Size(); i++)
1276 float x = j_row[
"waypoints"][i][0].GetFloat();
1277 float y = j_row[
"waypoints"][i][1].GetFloat();
1278 float z = j_row[
"waypoints"][i][2].GetFloat();
1284 if (j_row[
"waypoints"][i].Size() == 4)
1286 speed = j_row[
"waypoints"][i][3].GetInt();
1292 waypoint.
speed = speed;
1304 float spinner_size = 8.f;
1305 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2.f) - spinner_size);
1310 ImGui::TextColored(
RED_TEXT,
"%s",
_LC(
"TopMenubar",
"Failed to fetch external presets."));
1311 if (ImGui::Button(
_LC(
"TopMenubar",
"Retry")))
1325 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"No presets found for this terrain :("));
1326 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Supported terrains:"));
1329 ImGui::BeginChild(
"terrains-scrolling", ImVec2(0.f, 200),
false);
1331 for (
size_t i = 0; i < num_rows; i++)
1333 rapidjson::Value& j_row_terrains =
ai_presets_all[
static_cast<rapidjson::SizeType
>(i)];
1334 if (j_row_terrains.HasMember(
"terrains"))
1336 for (
size_t i = 0; i < j_row_terrains[
"terrains"].Size(); i++)
1338 ImGui::Text(
"%s", j_row_terrains[
"terrains"][i].GetString());
1347 if (ImGui::CollapsingHeader(
_LC(
"TopMenubar",
"Waypoints")))
1351 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"No waypoints defined."));
1355 if (ImGui::Button(
_LC(
"TopMenubar",
"Export"), ImVec2(250, 0)))
1378 std::string json =
fmt::format(
"\n {{\n \"terrain\":\"{}\",\n \"preset\":\"Preset name\",\n \"waypoints\":\n [{}\n ]\n }}",
App::sim_terrain_name->getStr(), s);
1382 fmt::format(
_LC(
"TopMenubar",
"{} waypoints exported to RoR.log"),
1386 ImGui::BeginChild(
"waypoints-scrolling", ImVec2(0.f, 200),
false);
1391 ImGui::AlignTextToFramePadding();
1392 ImGui::Text(
"%d", i);
1394 if (ImGui::Button(
"teleport", ImVec2(60, 0)))
1396 Ogre::Vector3* payload =
new Ogre::Vector3(
ai_waypoints[i].position);
1399 if (ImGui::IsItemHovered())
1401 ImGui::BeginTooltip();
1403 ImGui::Text(
w.c_str());
1404 ImGui::EndTooltip();
1407 ImGui::SetNextItemWidth(90);
1413 ImGui::InputInt(
_LC(
"TopMenubar",
"speed"), &
ai_waypoints[i].speed, 1, 100);
1414 if (ImGui::IsItemHovered())
1416 ImGui::BeginTooltip();
1417 ImGui::Text(
_LC(
"TopMenubar",
"Set waypoint speed in km/h for land vehicles"));
1419 ImGui::Text(
_LC(
"TopMenubar",
"Value -1: Ignore, vehicle will use default speed"));
1420 ImGui::Text(
_LC(
"TopMenubar",
"Value >= 5: Override default speed"));
1421 ImGui::EndTooltip();
1430 ImGui::PopItemWidth();
1440 menu_pos.y = window_pos.y + tuning_cursor.y +
MENU_Y_OFFSET;
1441 menu_pos.x = tuning_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
1442 ImGui::SetNextWindowPos(menu_pos);
1443 if (ImGui::Begin(
_LC(
"TopMenubar",
"Tuning menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
1449 ImGui::Text(
"%s",
_LC(
"Tuning",
"You are on foot."));
1450 ImGui::Text(
"%s",
_LC(
"Tuning",
"Enter a vehicle to tune it."));
1451 ImGui::PopStyleColor();
1464 ImGui::AlignTextToFramePadding();
1485 std::string delbtn_text =
_LC(
"Tuning",
"Delete");
1486 float delbtn_w = ImGui::CalcTextSize(delbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1487 float delbtn_cursorx = ImGui::GetWindowContentRegionWidth() - delbtn_w;
1490 ImGui::SetCursorPosX(delbtn_cursorx);
1493 ImGui::PopStyleColor();
1504 ImGui::AlignTextToFramePadding();
1505 ImGui::TextDisabled(
_LC(
"Tuning",
"Working tuneup"));
1510 if (ImGui::Button(
_LC(
"Tuning",
"Save")))
1526 std::string cancelbtn_text =
_LC(
"Tuning",
"Cancel");
1527 float cancelbtn_w = ImGui::CalcTextSize(cancelbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1528 float cancelbtn_cursorx = ImGui::GetWindowContentRegionWidth() - cancelbtn_w;
1531 ImGui::SetCursorPosX(cancelbtn_cursorx);
1532 if (ImGui::SmallButton(
_LC(
"Tuning",
"Cancel")))
1538 else if (tuneup_def)
1541 if (ImGui::Button(
_LC(
"Tuning",
"Save as...")))
1550 ImGui::AlignTextToFramePadding();
1551 std::string resetbtn_text =
_LC(
"Tuning",
"Reset");
1552 float delbtn_w = ImGui::CalcTextSize(resetbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1553 float delbtn_cursorx = ImGui::GetWindowContentRegionWidth() - delbtn_w;
1556 ImGui::SetCursorPosX(delbtn_cursorx);
1559 ImGui::PopStyleColor();
1560 if (resetbtn_pressed)
1571 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
1573 if (ImGui::CollapsingHeader(addonparts_title.c_str()))
1579 ImGui::PushID(addonpart_entry->
fname.c_str());
1584 const ImVec2 checkbox_cursor = ImGui::GetCursorScreenPos();
1585 if (ImGui::Checkbox(addonpart_entry->
dname.c_str(), &used)
1586 && !conflict_w_hovered
1601 const float square_sz = ImGui::GetFrameHeight();
1602 const ImVec2 min = checkbox_cursor + ImGui::GetStyle().FramePadding*1.4f;
1603 const ImVec2 max = checkbox_cursor + (ImVec2(square_sz, square_sz) - ImGui::GetStyle().FramePadding*1.5f);
1604 const ImColor X_COLOR(0.5f, 0.48f, 0.45f);
1605 ImGui::GetWindowDrawList()->AddLine(min, max, X_COLOR, 4.f);
1606 ImGui::GetWindowDrawList()->AddLine(ImVec2(min.x, max.y), ImVec2(max.x, min.y), X_COLOR, 4.f);
1608 if (conflict_w_hovered)
1611 const float square_sz = ImGui::GetFrameHeight();
1612 const ImVec2 min = checkbox_cursor;
1613 const ImVec2 max = checkbox_cursor + ImVec2(square_sz + 0.5f, square_sz);
1614 const ImColor SQ_COLOR(0.7f, 0.1f, 0.f);
1615 ImGui::GetWindowDrawList()->AddRect(min, max, SQ_COLOR, 0.f, ImDrawCornerFlags_None, 3.f);
1618 if (ImGui::IsItemHovered())
1630 ImGui::AlignTextToFramePadding();
1631 std::string reloadbtn_text =
_LC(
"Tuning",
"Reload");
1632 const float reloadbtn_w = ImGui::CalcTextSize(reloadbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1634 ImGui::SetCursorPosX(reloadbtn_cursorx);
1635 const bool reloadbtn_pressed = ImGui::SmallButton(reloadbtn_text.c_str());
1636 if (reloadbtn_pressed)
1659 if (ImGui::Button(
_LC(
"Tuning",
"Browse all parts")))
1669 std::string props_title =
fmt::format(
_LC(
"Tuning",
"Props ({})"), total_props);
1670 if (ImGui::CollapsingHeader(props_title.c_str()))
1675 ImGui::PushID(p.pp_id);
1676 ImGui::AlignTextToFramePadding();
1689 if (p.pp_beacon_type ==
'L' || p.pp_beacon_type ==
'R' || p.pp_beacon_type ==
'w')
1692 ImGui::TextDisabled(
"(special!)");
1693 if (ImGui::IsItemHovered())
1695 ImGui::BeginTooltip();
1696 ImGui::Text(
"special prop - aerial nav light");
1697 ImGui::EndTooltip();
1700 else if (p.pp_wheel_mesh_obj)
1703 ImGui::TextDisabled(
"(special!)");
1704 if (ImGui::IsItemHovered())
1706 ImGui::BeginTooltip();
1707 ImGui::Text(
"special prop - dashboard + dirwheel");
1708 ImGui::EndTooltip();
1727 std::string flexbodies_title =
fmt::format(
_LC(
"Tuning",
"Flexbodies ({})"), total_flexbodies);
1728 if (ImGui::CollapsingHeader(flexbodies_title.c_str()))
1733 ImGui::PushID(flexbody->getID());
1734 ImGui::AlignTextToFramePadding();
1740 flexbody->getOrigMeshName(),
1758 std::string wheels_title =
fmt::format(
_LC(
"TopMenubar",
"Wheels ({})"), total_wheels);
1759 if (ImGui::CollapsingHeader(wheels_title.c_str()))
1761 for (
WheelID_t i = 0; i < total_wheels; i++)
1764 ImGui::AlignTextToFramePadding();
1772 ImGui::PushStyleColor(ImGuiCol_Border,
ORANGE_TEXT);
1773 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
1780 ImGui::TextDisabled(
"|");
1791 bool resetPressed =
false;
1797 resetPressed = ImGui::SmallButton(
_LC(
"Tuning",
"Reset"));
1798 ImGui::PopStyleColor();
1799 ImGui::PopStyleVar();
1800 ImGui::PopStyleColor();
1804 if (selected_side != active_side)
1813 else if (resetPressed)
1834 std::string flares_title =
fmt::format(
_LC(
"Tuning",
"Flares ({})"), total_flares);
1835 if (ImGui::CollapsingHeader(flares_title.c_str()))
1840 ImGui::PushID(flareid);
1841 ImGui::AlignTextToFramePadding();
1847 std::string flarename;
1851 flarename =
fmt::format(
"{} {}", (
char)flaretype, controlnumber);
1856 flarename =
fmt::format(
"{} {}", (
char)flaretype, linkname);
1883 std::string exhausts_title =
fmt::format(
_LC(
"Tuning",
"Exhausts ({})"), total_exhausts);
1884 if (ImGui::CollapsingHeader(exhausts_title.c_str()))
1887 for (
ExhaustID_t exhaustid = 0; exhaustid < (int)total_exhausts; exhaustid++)
1889 ImGui::PushID(exhaustid);
1890 ImGui::AlignTextToFramePadding();
1914 std::string materials_title =
fmt::format(
_LC(
"Tuning",
"Managed Materials ({})"), total_materials);
1915 if (ImGui::CollapsingHeader(materials_title.c_str()))
1920 const std::string& material_name = mm_pair.first;
1921 ImGui::PushID(material_name.c_str());
1922 ImGui::AlignTextToFramePadding();
1945 std::string videocameras_title =
fmt::format(
_LC(
"Tuning",
"Videocameras ({})"), total_videocameras);
1946 if (ImGui::CollapsingHeader(videocameras_title.c_str()))
1949 for (
VideoCameraID_t videocameraid = 0; videocameraid < (int)total_videocameras; videocameraid++)
1951 ImGui::PushID(videocameraid);
1952 ImGui::AlignTextToFramePadding();
1960 ImGui::Dummy(ImVec2(3, 3));
1969 ImGui::PushStyleColor(ImGuiCol_Border,
ORANGE_TEXT);
1970 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
1976 bool checkbox_pressed =
false;
1978 if ((is_mirror_flip || is_mirror_noflip))
1981 bool checkbox_checked = is_mirror_flip;
1982 checkbox_pressed = ImGui::Checkbox(
_LC(
"Tuning",
"Flipped"), &checkbox_checked);
2000 default: ImGui::TextDisabled(
_LC(
"Tuning",
"(Videocamera)"));
break;
2006 bool reset_pressed =
false;
2012 reset_pressed = ImGui::SmallButton(
_LC(
"Tuning",
"Reset"));
2013 ImGui::PopStyleColor();
2014 ImGui::PopStyleVar();
2015 ImGui::PopStyleColor();
2019 if (checkbox_pressed)
2028 else if (reset_pressed)
2056 ImGui::PopStyleColor(2);
2066 if (ImGui::IsMouseDown(1))
2077 ImVec2 box_min(0,0);
2078 ImVec2 box_max(ImGui::GetIO().DisplaySize.x, ImGui::GetStyle().WindowPadding.y +
PANEL_HOVERBOX_HEIGHT);
2079 ImVec2 mouse_pos = ImGui::GetIO().MousePos;
2080 const bool window_hovered ((mouse_pos.x >= box_min.x) && (mouse_pos.x <= box_max.x) &&
2081 (mouse_pos.y >= box_min.y) && (mouse_pos.y <= box_max.y));
2082 bool result = window_hovered;
2084 bool menu_hovered =
false;
2090 result |= menu_hovered;
2092 bool box_hovered =
false;
2097 result |= box_hovered;
2100 if (box_hovered && !menu_hovered)
2111 unsigned int num_actors_player = 0;
2114 if (actor->ar_net_source_id == user.
uniqueid)
2116 ++num_actors_player;
2123 ImVec4 player_gui_color(player_color.r, player_color.g, player_color.b, 1.f);
2124 ImGui::PushStyleColor(ImGuiCol_Text, player_gui_color);
2125 ImGui::Text(
"%s: %u (%s, Ver: %s, Lang: %s)",
2129 ImGui::PopStyleColor();
2130 #endif // USE_SOCKETW
2133 Ogre::TexturePtr tex1 =
FetchIcon(
"control_pause.png");
2134 Ogre::TexturePtr tex2 =
FetchIcon(
"control_play.png");
2138 if ((!actor->ar_hide_in_actor_list) && (actor->ar_net_source_id == user.
uniqueid))
2141 ImGui::PushID(
id.c_str());
2144 if (ImGui::ImageButton(
reinterpret_cast<ImTextureID
>(tex1->getHandle()), ImVec2(16, 16)))
2151 if (ImGui::ImageButton(
reinterpret_cast<ImTextureID
>(tex2->getHandle()), ImVec2(16, 16)))
2158 std::string text_buf_rem =
fmt::format(
" X ##[{}]", i);
2159 ImGui::PushStyleColor(ImGuiCol_Text,
RED_TEXT);
2160 if (ImGui::Button(text_buf_rem.c_str()))
2164 ImGui::PopStyleColor();
2170 if (ImGui::Button(actortext_buf.c_str()))
2180 std::vector<ActorPtr> actor_list;
2183 if (!actor->ar_hide_in_actor_list)
2185 actor_list.emplace_back(actor);
2188 if (actor_list.empty())
2191 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"None spawned yet"));
2192 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Use [Simulation] menu"));
2193 ImGui::PopStyleColor();
2201 std::string text_buf_rem =
fmt::format(
"X ##[{}]", i);
2202 ImGui::PushStyleColor(ImGuiCol_Text,
RED_TEXT);
2203 if (ImGui::Button(text_buf_rem.c_str()))
2207 ImGui::PopStyleColor();
2211 if (actor == player_actor)
2213 ImGui::PushStyleColor(ImGuiCol_Text,
GREEN_TEXT);
2215 else if (std::find(actor->ar_linked_actors.begin(), actor->ar_linked_actors.end(), player_actor) != actor->ar_linked_actors.end())
2217 ImGui::PushStyleColor(ImGuiCol_Text,
ORANGE_TEXT);
2221 ImGui::PushStyleColor(ImGuiCol_Text,
WHITE_TEXT);
2227 if (ImGui::Button(text_buf.c_str()))
2231 ImGui::PopStyleColor();
2248 float content_width = 0.f;
2250 std::string special_text;
2251 ImVec4 special_color = ImGui::GetStyle().Colors[ImGuiCol_Text];
2252 float special_text_centering_weight = 1.f;
2254 std::string special_text_b;
2255 std::string special_text_c;
2256 std::string special_text_d;
2257 ImVec4 special_color_c = ImVec4(0,0,0,0);
2264 special_text =
fmt::format(
_LC(
"TopMenubar",
"All physics paused, press {} to resume"),
2266 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2273 special_text =
fmt::format(
_LC(
"TopMenubar",
"Vehicle physics paused, press {} to resume"),
2275 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2280 content_width = 300;
2282 special_text =
_LC(
"TopMenubar",
"Replay");
2286 special_text =
fmt::format(
_LC(
"TopMenubar",
"Live repair mode, hit '{}' to stop"),
2288 content_width = 450;
2291 special_text_centering_weight = 0.7f;
2295 special_text =
fmt::format(
_LC(
"TopMenubar",
"Quick repair ('{}' for Live repair)"),
2297 content_width = 450;
2300 special_text_centering_weight = 0.7f;
2309 float distance = 0.0f;
2323 special_text_b =
fmt::format(
"{:.1f} {}", distance,
_LC(
"DirectionArrow",
"meter"));
2324 content_width = ImGui::CalcTextSize(special_text.c_str()).x + ImGui::CalcTextSize(special_text_b.c_str()).x;
2327 special_text_c =
fmt::format(
"{:02d}.{:02d}.{:02d}", (
int)(time) / 60, (
int)(time) % 60, (
int)(time * 100.0) % 100);
2329 special_color_c = (time_diff > 0.0f)
2336 special_text_d =
fmt::format(
"{:02d}.{:02d}.{:02d}", (
int)(best_time) / 60, (
int)(best_time) % 60, (
int)(best_time * 100.0) % 100);
2345 special_text =
fmt::format(
_LC(
"TopMenubar",
"Terrain editing mode, press {} to exit"),
2347 content_width = ImGui::CalcTextSize(special_text.c_str()).x + 25.f;
2352 special_text =
fmt::format(
_LC(
"TopMenubar",
"Terrain editing mode, press {} to save and exit"),
2354 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2359 if (!special_text.empty())
2362 box_pos.y = top_offset;
2363 box_pos.x = (ImGui::GetIO().DisplaySize.x / 2) - ((content_width / 2) + ImGui::GetStyle().FramePadding.x);
2364 ImGui::SetNextWindowPos(box_pos);
2365 ImGui::SetNextWindowSize(ImVec2(0.f, 0.f));
2366 ImGui::SetNextWindowContentWidth(content_width);
2367 ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
2368 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse;
2369 ImGui::PushStyleColor(ImGuiCol_WindowBg,
App::GetGuiManager()->GetTheme().semitransparent_window_bg);
2370 if (ImGui::Begin(special_text.c_str(),
nullptr, flags))
2375 float text_w = ImGui::CalcTextSize(special_text.c_str()).x;
2376 ImGui::SetCursorPosX(((content_width / 2) - (text_w / 2)) * special_text_centering_weight);
2378 ImGui::TextColored(special_color,
"%s", special_text.c_str());
2388 float pbar_width = content_width - (ImGui::GetStyle().ItemSpacing.x + ImGui::CalcTextSize(special_text.c_str()).x);
2389 ImGui::ProgressBar(fraction, ImVec2(pbar_width, ImGui::GetTextLineHeight()), pbar_text.
ToCStr());
2397 int min = (int)time_sec / 60;
2398 str_pos = snprintf(str, 200,
"%dmin ", min);
2399 time_sec -= (float)min * 60.f;
2401 snprintf(str+str_pos, 200-str_pos,
"%.2fsec", time_sec);
2402 ImGui::TextDisabled(
"%s: %s",
_LC(
"TopMenubar",
"Time"), str);
2408 ImGui::Text(special_text_b.c_str());
2409 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2) - (ImGui::CalcTextSize(special_text_c.c_str()).x / 2));
2410 ImGui::TextColored(special_color_c,
"%s", special_text_c.c_str());
2413 text <<
"Best Time: " << special_text_d.c_str();
2414 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2) - (ImGui::CalcTextSize(text).
x / 2));
2416 if (!special_text_d.empty())
2418 ImGui::TextDisabled(text);
2425 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.f, 0.f));
2429 ImGui::ProgressBar(fraction, ImVec2(15.f, ImGui::GetTextLineHeight() / 2.f),
"");
2433 ImGui::PopStyleVar();
2435 const ImVec2 MINI_SPACING = ImVec2(2.f,0.f);
2436 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, MINI_SPACING);
2440 const float INDENT = 15.f;
2442 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Movement"));
2444 ImGui::SetColumnWidth(0, INDENT);
2445 ImGui::NextColumn();
2448 ImGui::NextColumn();
2451 ImGui::NextColumn();
2456 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Rotation"));
2458 ImGui::SetColumnWidth(0, INDENT);
2459 ImGui::NextColumn();
2464 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Modifiers"));
2466 ImGui::SetColumnWidth(0, INDENT);
2467 ImGui::SetColumnWidth(1, 125);
2468 ImGui::SetColumnWidth(2, 125);
2469 ImGui::NextColumn();
2476 ImGui::TextDisabled(
"%s (%s):",
_LC(
"LiveRepair",
"Reset mode"),
ToLocalizedString(resetmode).c_str());
2477 ImGui::Dummy(ImVec2(INDENT, 1.f));
2481 ImGui::PopStyleVar();
2487 std::string lbl_readonly =
_LC(
"TopMenubar",
"This terrain is read only.");
2488 ImGui::SetCursorPosX(ImGui::GetCursorPosX()
2489 + (ImGui::GetWindowContentRegionWidth() / 2 - ImGui::CalcTextSize(lbl_readonly.c_str()).x/2));
2490 ImGui::TextDisabled(
"%s", lbl_readonly.c_str());
2492 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2, 0.2, 0.2, 1.0));
2493 std::string btn_import =
_LC(
"TopMenubar",
"Import as editable project.");
2494 ImGui::SetCursorPosX(ImGui::GetCursorPosX()
2495 + ((ImGui::GetWindowContentRegionWidth() / 2 - ImGui::CalcTextSize(btn_import.c_str()).x / 2) - ImGui::GetStyle().FramePadding.x));
2504 ImGui::PopStyleColor();
2506 const ImVec2 PAD = ImVec2(5, 5);
2514 ImGui::PopStyleColor(1);
2530 for (
const std::string& filename: terrain->
GetDef()->ai_presets_files)
2532 rapidjson::Document j_doc;
2543 if (!j_doc.IsArray())
2545 LOG(
fmt::format(
"[RoR|Terrain] AI presets file '{}' declared in '{}' has wrong format - the root element is not an array!",
2551 for (
const rapidjson::Value& j_bundled_preset: j_doc.GetArray())
2564 #if defined(USE_CURL)
2566 std::thread(std::move(task)).detach();
2568 #endif // defined(USE_CURL)
2581 rapidjson::Value preset_copy(bundled_preset,
ai_presets_all.GetAllocator());
2587 rapidjson::Value preset_copy(extern_preset,
ai_presets_all.GetAllocator());
2693 std::string protectchk_text =
_LC(
"Tuning",
"Protected");
2694 float protectchk_w = ImGui::CalcTextSize(protectchk_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
2695 float protectchk_cursorx = (ImGui::GetWindowContentRegionWidth() - protectchk_w) - 20.f;
2698 ImGui::SetCursorPosX(protectchk_cursorx);
2701 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
2702 bool chk_pressed = ImGui::Checkbox(protectchk_text.c_str(), &protectchk_value);
2703 ImGui::PopStyleVar(1);
2718 request->
mpr_type = (protectchk_value) ? request_type_set : request_type_reset;
2727 ImGui::GetWindowDrawList()->AddRect(
2728 ImGui::GetCursorScreenPos(),
2729 ImGui::GetCursorScreenPos() + ImGui::CalcTextSize(
"00") + ImGui::GetStyle().FramePadding*2,
2730 ImColor(ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]),
2731 ImGui::GetStyle().FrameRounding);
2732 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().FramePadding.x);
2733 ImGui::Text(
"%02d", subject_id);
2735 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().FramePadding.x);
2744 bool isEnabled = !is_unwanted && !is_force_removed;
2745 if (is_force_removed)
2747 ImGui::PushStyleColor(ImGuiCol_Border,
ORANGE_TEXT);
2748 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
2750 bool chkPressed = ImGui::Checkbox(name.c_str(), &isEnabled);
2751 bool resetPressed =
false;
2752 if (is_force_removed)
2756 resetPressed = ImGui::SmallButton(
_LC(
"Tuning",
"Reset"));
2757 ImGui::PopStyleColor();
2758 ImGui::PopStyleVar();
2759 ImGui::PopStyleColor();
2763 if (chkPressed && !isEnabled)
2778 else if ((chkPressed && isEnabled) || resetPressed)
2781 req->
mpr_type = request_type_reset;