53 #include <fmt/format.h>
57 # include <curl/curl.h>
58 # include <curl/easy.h>
61 #if defined(_MSC_VER) && defined(GetObject) // This MS Windows macro from <wingdi.h> (Windows Kit 8.1) clashes with RapidJSON
70 static size_t CurlWriteFunc(
void *ptr,
size_t size,
size_t nmemb, std::string* data)
72 data->append((
char*)ptr, size * nmemb);
85 Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(
"waypoints.json",
RGN_SAVEGAMES);
101 std::string url =
"https://raw.githubusercontent.com/RigsOfRods-Community/ai-waypoints/main/waypoints.json";
102 std::string response_payload;
103 long response_code = 0;
105 CURL *curl = curl_easy_init();
106 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
107 curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
109 curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
111 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
CurlWriteFunc);
112 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_payload);
114 CURLcode curl_result = curl_easy_perform(curl);
115 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
117 curl_easy_cleanup(curl);
120 if (curl_result != CURLE_OK || response_code != 200)
122 Ogre::LogManager::getSingleton().stream()
123 <<
"[RoR|Repository] Failed to download AI presets;"
124 <<
" Error: '" << curl_easy_strerror(curl_result) <<
"'; HTTP status code: " << response_code;
137 #endif // defined(USE_CURL)
160 int num_playable_actors = 0;
163 if (!actor->ar_hide_in_actor_list)
165 num_playable_actors++;
169 std::string sim_title =
_LC(
"TopMenubar",
"Simulation");
170 std::string actors_title =
fmt::format(
"{} ({})",
_LC(
"TopMenubar",
"Vehicles"), num_playable_actors);
171 std::string savegames_title =
_LC(
"TopMenubar",
"Saves");
172 std::string settings_title =
_LC(
"TopMenubar",
"Settings");
173 std::string tools_title =
_LC(
"TopMenubar",
"Tools");
174 std::string ai_title =
_LC(
"TopMenubar",
"Vehicle AI");
175 std::string tuning_title =
_LC(
"TopMenubar",
"Tuning");
177 int menubar_num_buttons = 5;
178 float menubar_content_width =
179 ImGui::CalcTextSize(sim_title.c_str()).x +
180 ImGui::CalcTextSize(actors_title.c_str()).x +
181 ImGui::CalcTextSize(savegames_title.c_str()).x +
182 ImGui::CalcTextSize(settings_title.c_str()).x +
183 ImGui::CalcTextSize(tools_title.c_str()).x;
187 menubar_num_buttons += 1;
188 menubar_content_width += ImGui::CalcTextSize(ai_title.c_str()).x;
193 menubar_num_buttons += 1;
194 menubar_content_width += ImGui::CalcTextSize(tuning_title.c_str()).x;
197 menubar_content_width +=
198 (ImGui::GetStyle().ItemSpacing.x * (menubar_num_buttons - 1)) +
199 (ImGui::GetStyle().FramePadding.x * (menubar_num_buttons * 2));
201 ImVec2 window_target_pos = ImVec2((ImGui::GetIO().DisplaySize.x/2.f) - (menubar_content_width / 2.f), theme.
screen_edge_padding.y);
211 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
214 int flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove
215 | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize;
216 ImGui::SetNextWindowContentSize(ImVec2(menubar_content_width, 0.f));
217 ImGui::SetNextWindowPos(window_target_pos);
218 ImGui::Begin(
"Top menubar",
nullptr, flags);
220 if (ImGui::IsWindowHovered())
226 ImVec2 window_pos = ImGui::GetWindowPos();
227 ImVec2 sim_cursor = ImGui::GetCursorPos();
228 ImGui::Button(sim_title.c_str());
235 ImVec2 tuning_cursor = ImVec2(0, 0);
239 tuning_cursor = ImGui::GetCursorPos();
240 ImGui::Button(tuning_title.c_str());
248 ImVec2 ai_cursor = ImVec2(0, 0);
252 ai_cursor = ImGui::GetCursorPos();
253 ImGui::Button(ai_title.c_str());
263 ImVec2 actors_cursor = ImGui::GetCursorPos();
264 ImGui::Button(actors_title.c_str());
273 ImVec2 savegames_cursor = ImGui::GetCursorPos();
274 ImGui::Button(savegames_title.c_str());
281 for (
int i = 0; i <= 9; i++)
291 ImVec2 settings_cursor = ImGui::GetCursorPos();
292 ImGui::Button(settings_title.c_str());
305 ImVec2 tools_cursor = ImGui::GetCursorPos();
306 ImGui::Button(tools_title.c_str());
312 ImVec2 topmenu_final_size = ImGui::GetWindowSize();
324 menu_pos.x = sim_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
325 ImGui::SetNextWindowPos(menu_pos);
326 if (ImGui::Begin(
_LC(
"TopMenubar",
"Sim menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
330 if (ImGui::Button(
_LC(
"TopMenubar",
"Get new vehicle")))
339 if (current_actor !=
nullptr)
341 if (ImGui::Button(
_LC(
"TopMenubar",
"Show vehicle description")))
348 if (ImGui::Button(
_LC(
"TopMenubar",
"Reload current vehicle")))
356 if (ImGui::Button(
_LC(
"TopMenubar",
"Remove current vehicle")))
364 if (ImGui::Button(
_LC(
"TopMenubar",
"Activate last spawned vehicle")))
372 if (ImGui::Button(
_LC(
"TopMenubar",
"Reload last spawned vehicle")))
380 if (ImGui::Button(
_LC(
"TopMenubar",
"Remove last spawned vehicle")))
389 if (ImGui::Button(
_LC(
"TopMenubar",
"Remove all vehicles")))
396 if (ImGui::Button(
_LC(
"TopMenubar",
" [!] Confirm removal")))
400 if (!actor->ar_hide_in_actor_list && !actor->isPreloadedWithTerrain() &&
408 ImGui::PopStyleColor();
411 if (ImGui::Button(
_LC(
"TopMenubar",
"Activate all vehicles")))
417 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Activated vehicles never sleep"), &force_trucks_active))
422 if (ImGui::Button(
_LC(
"TopMenubar",
"Send all vehicles to sleep")))
430 if (ImGui::Button(
_LC(
"TopMenubar",
"Reload current terrain")))
443 if (ImGui::Button(
_LC(
"TopMenubar",
"Back to menu")))
453 if (ImGui::Button(
_LC(
"TopMenubar",
"Exit")))
468 menu_pos.x = actors_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
469 ImGui::SetNextWindowPos(menu_pos);
470 if (ImGui::Begin(
_LC(
"TopMenubar",
"Actors menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
483 for (
auto& user: remote_users)
487 #endif // USE_SOCKETW
498 menu_pos.y = window_pos.y + savegames_cursor.y +
MENU_Y_OFFSET;
499 menu_pos.x = savegames_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
500 ImGui::SetNextWindowPos(menu_pos);
501 if (ImGui::Begin(
_LC(
"TopMenubar",
"Savegames"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
503 if (ImGui::Button(
_LC(
"TopMenubar",
"Quicksave")))
513 if (ImGui::Button(
_LC(
"TopMenubar",
"Quickload")))
524 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"(Save with CTRL+ALT+1..5)"));
525 for (
int i = 1; i <= 5; i++)
527 Ogre::String name =
_LC(
"TopMenubar",
"Empty Slot");
533 if (ImGui::Button(caption.c_str()))
541 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"(Load with ALT+1..5)"));
542 for (
int i = 1; i <= 5; i++)
548 if (ImGui::Button(caption.c_str()))
566 menu_pos.y = window_pos.y + settings_cursor.y +
MENU_Y_OFFSET;
567 menu_pos.x = settings_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
568 ImGui::SetNextWindowPos(menu_pos);
569 if (ImGui::Begin(
_LC(
"TopMenubar",
"Settings menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
571 ImGui::PushItemWidth(125.f);
575 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"Frames per second:"));
584 float slowmotion = std::min(
App::GetGameContext()->GetActorManager()->GetSimulationSpeed(), 1.0f);
585 if (ImGui::SliderFloat(
_LC(
"TopMenubar",
"Slow motion"), &slowmotion, 0.01f, 1.0f))
589 float timelapse = std::max(
App::GetGameContext()->GetActorManager()->GetSimulationSpeed(), 1.0f);
590 if (ImGui::SliderFloat(
_LC(
"TopMenubar",
"Time lapse"), &timelapse, 1.0f, 10.0f))
608 if (ImGui::SliderInt(
_LC(
"TopMenubar",
"FOV"), &fov, 10, 120))
616 if (ImGui::SliderInt(
_LC(
"TopMenubar",
"FOV"), &fov, 10, 120))
648 ImGui::PushID(
"waves");
658 if (current_actor !=
nullptr)
661 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"Vehicle control options:"));
671 ImGui::PopItemWidth();
682 menu_pos.x = tools_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
683 ImGui::SetNextWindowPos(menu_pos);
684 if (ImGui::Begin(
_LC(
"TopMenubar",
"Tools menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
686 if (ImGui::Button(
_LC(
"TopMenubar",
"Friction settings")))
692 if (ImGui::Button(
_LC(
"TopMenubar",
"Show console")))
698 if (ImGui::Button(
_LC(
"TopMenubar",
"Texture tool")))
704 if (ImGui::Button(
_LC(
"TopMenubar",
"Collisions debug")))
710 if (current_actor !=
nullptr)
712 if (ImGui::Button(
_LC(
"TopMenubar",
"Node / Beam utility")))
718 if (ImGui::Button(
_LC(
"TopMenubar",
"FlexBody debug")))
726 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"Pre-spawn diag. options:"));
729 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Node mass recalc. logging"), &diag_mass))
733 if (ImGui::IsItemHovered())
735 ImGui::BeginTooltip();
736 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Extra logging on runtime - mass recalculation"));
741 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Beam break logging"), &diag_break))
745 if (ImGui::IsItemHovered())
747 ImGui::BeginTooltip();
748 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Extra logging on runtime"));
753 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Beam deform. logging"), &diag_deform))
757 if (ImGui::IsItemHovered())
759 ImGui::BeginTooltip();
760 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Extra logging on runtime"));
765 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"Trigger logging"), &diag_trig))
769 if (ImGui::IsItemHovered())
771 ImGui::BeginTooltip();
772 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Extra logging on runtime - trigger beams activity"));
777 if (ImGui::Checkbox(
_LC(
"TopMenubar",
"VideoCamera direction marker"), &diag_vcam))
781 if (ImGui::IsItemHovered())
783 ImGui::BeginTooltip();
784 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Visual marker of VideoCameras direction"));
788 ImGui::PushItemWidth(125.f);
792 if (ImGui::IsItemHovered())
794 ImGui::BeginTooltip();
795 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"1 = Solid"));
796 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"2 = Wireframe"));
797 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"3 = Points"));
811 menu_pos.x = ai_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
812 ImGui::SetNextWindowPos(menu_pos);
813 if (ImGui::Begin(
_LC(
"TopMenubar",
"AI menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
815 if (ImGui::IsWindowHovered())
820 ImGui::PushItemWidth(125.f);
829 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
830 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
833 ImGui::InputInt(
_LC(
"TopMenubar",
"Vehicle count"), &
ai_num, 1, 100);
834 if (ImGui::IsItemHovered())
836 ImGui::BeginTooltip();
837 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Number of vehicles"));
843 ImGui::PopItemFlag();
844 ImGui::PopStyleVar();
849 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
850 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
855 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
856 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
859 ImGui::InputInt(
_LC(
"TopMenubar",
"Distance"), &
ai_distance, 1, 100);
860 if (ImGui::IsItemHovered())
862 ImGui::BeginTooltip();
863 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Following distance in meters"));
869 ImGui::PopItemFlag();
870 ImGui::PopStyleVar();
873 std::string label1 =
"Behind";
885 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
886 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
889 if (ImGui::BeginCombo(
"Position", label1.c_str()))
891 if (ImGui::Selectable(
"Behind"))
895 if (ImGui::Selectable(
"Parallel"))
901 if (ImGui::IsItemHovered())
903 ImGui::BeginTooltip();
904 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Positioning scheme"));
906 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Behind: Set vehicle behind vehicle, in line"));
907 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Parallel: Set vehicles in parallel, useful for certain scenarios like drag races"));
913 ImGui::PopItemFlag();
914 ImGui::PopStyleVar();
922 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
923 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
926 ImGui::InputInt(
_LC(
"TopMenubar",
"Repeat times"), &
ai_times, 1, 100);
927 if (ImGui::IsItemHovered())
929 ImGui::BeginTooltip();
930 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"How many times to loop the path"));
936 ImGui::PopItemFlag();
937 ImGui::PopStyleVar();
942 ImGui::PopItemFlag();
943 ImGui::PopStyleVar();
949 std::string label2 =
"Normal";
956 label2 =
"Drag Race";
969 if (actor->ar_driveable ==
AI)
971 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
972 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
977 if (ImGui::BeginCombo(
"Mode", label2.c_str()))
979 if (ImGui::Selectable(
"Normal"))
992 if (ImGui::Selectable(
"Race"))
1005 if (ImGui::Selectable(
"Drag Race"))
1022 if (ImGui::Selectable(
"Crash"))
1038 if (ImGui::Selectable(
"Chase"))
1053 if (ImGui::IsItemHovered())
1055 ImGui::BeginTooltip();
1056 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicle driving mode"));
1058 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Normal: Modify speed according to turns, other vehicles and character"));
1059 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Race: Always keep defined speed"));
1060 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Drag Race: Two vehicles performing a drag race"));
1061 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Crash: Two vehicles driving in opposite direction"));
1062 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Chase: Follow character and player vehicle"));
1063 ImGui::EndTooltip();
1068 if (actor->ar_driveable ==
AI)
1070 ImGui::PopItemFlag();
1071 ImGui::PopStyleVar();
1079 ImGui::InputInt(
_LC(
"TopMenubar",
"Speed"), &
ai_speed, 1, 100);
1080 if (ImGui::IsItemHovered())
1082 ImGui::BeginTooltip();
1083 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Speed in km/h for land vehicles or knots/s for boats"));
1084 ImGui::EndTooltip();
1090 ImGui::InputInt(
_LC(
"TopMenubar",
"Altitude"), &
ai_altitude, 1, 100);
1091 if (ImGui::IsItemHovered())
1093 ImGui::BeginTooltip();
1094 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Airplane maximum altitude in feet"));
1095 ImGui::EndTooltip();
1108 if (ImGui::IsItemHovered())
1110 ImGui::BeginTooltip();
1111 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicles, boats and airplanes"));
1112 ImGui::EndTooltip();
1117 ImGui::PushID(
"vehicle2");
1126 if (ImGui::IsItemHovered())
1128 ImGui::BeginTooltip();
1129 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicles, boats and airplanes"));
1130 ImGui::EndTooltip();
1139 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1140 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1145 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]);
1148 if (ImGui::Button(
_LC(
"TopMenubar",
"Start"), ImVec2(80, 0)))
1172 fmt::format(
_LC(
"TopMenubar",
"Select a preset, record or open survey map ({}) to set waypoints."),
1184 ImGui::PopStyleColor();
1189 if (ImGui::Button(
_LC(
"TopMenubar",
"Stop"), ImVec2(80, 0)))
1198 if (actor->ar_driveable ==
AI)
1207 ImGui::PopItemFlag();
1208 ImGui::PopStyleVar();
1213 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_Button]);
1214 std::string label =
"Record";
1217 label =
"Recording";
1218 ImGui::PushStyleColor(ImGuiCol_Button,
RED_TEXT);
1221 if (ImGui::Button(label.c_str(), ImVec2(80, 0)))
1234 ImGui::PopStyleColor();
1237 if (ImGui::CollapsingHeader(
_LC(
"TopMenubar",
"Presets")))
1241 int display_count = 0;
1242 for (
size_t i = 0; i < num_rows; i++)
1244 rapidjson::Value& j_row =
ai_presets_all[
static_cast<rapidjson::SizeType
>(i)];
1249 if (ImGui::Button(j_row[
"preset"].GetString(), ImVec2(250, 0)))
1253 for (
size_t i = 0; i < j_row[
"waypoints"].Size(); i++)
1255 float x = j_row[
"waypoints"][i][0].GetFloat();
1256 float y = j_row[
"waypoints"][i][1].GetFloat();
1257 float z = j_row[
"waypoints"][i][2].GetFloat();
1263 if (j_row[
"waypoints"][i].Size() == 4)
1265 speed = j_row[
"waypoints"][i][3].GetInt();
1271 waypoint.
speed = speed;
1283 float spinner_size = 8.f;
1284 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2.f) - spinner_size);
1289 ImGui::TextColored(
RED_TEXT,
"%s",
_LC(
"TopMenubar",
"Failed to fetch external presets."));
1290 if (ImGui::Button(
_LC(
"TopMenubar",
"Retry")))
1304 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"No presets found for this terrain :("));
1305 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Supported terrains:"));
1308 ImGui::BeginChild(
"terrains-scrolling", ImVec2(0.f, 200),
false);
1310 for (
size_t i = 0; i < num_rows; i++)
1312 rapidjson::Value& j_row_terrains =
ai_presets_all[
static_cast<rapidjson::SizeType
>(i)];
1313 if (j_row_terrains.HasMember(
"terrains"))
1315 for (
size_t i = 0; i < j_row_terrains[
"terrains"].Size(); i++)
1317 ImGui::Text(
"%s", j_row_terrains[
"terrains"][i].GetString());
1326 if (ImGui::CollapsingHeader(
_LC(
"TopMenubar",
"Waypoints")))
1330 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"No waypoints defined."));
1334 if (ImGui::Button(
_LC(
"TopMenubar",
"Export"), ImVec2(250, 0)))
1357 std::string json =
fmt::format(
"\n {{\n \"terrain\":\"{}\",\n \"preset\":\"Preset name\",\n \"waypoints\":\n [{}\n ]\n }}",
App::sim_terrain_name->getStr(), s);
1361 fmt::format(
_LC(
"TopMenubar",
"{} waypoints exported to RoR.log"),
1365 ImGui::BeginChild(
"waypoints-scrolling", ImVec2(0.f, 200),
false);
1370 ImGui::AlignTextToFramePadding();
1371 ImGui::Text(
"%d", i);
1373 if (ImGui::Button(
"teleport", ImVec2(60, 0)))
1375 Ogre::Vector3* payload =
new Ogre::Vector3(
ai_waypoints[i].position);
1378 if (ImGui::IsItemHovered())
1380 ImGui::BeginTooltip();
1382 ImGui::Text(
w.c_str());
1383 ImGui::EndTooltip();
1386 ImGui::SetNextItemWidth(90);
1392 ImGui::InputInt(
_LC(
"TopMenubar",
"speed"), &
ai_waypoints[i].speed, 1, 100);
1393 if (ImGui::IsItemHovered())
1395 ImGui::BeginTooltip();
1396 ImGui::Text(
_LC(
"TopMenubar",
"Set waypoint speed in km/h for land vehicles"));
1398 ImGui::Text(
_LC(
"TopMenubar",
"Value -1: Ignore, vehicle will use default speed"));
1399 ImGui::Text(
_LC(
"TopMenubar",
"Value >= 5: Override default speed"));
1400 ImGui::EndTooltip();
1409 ImGui::PopItemWidth();
1419 menu_pos.y = window_pos.y + tuning_cursor.y +
MENU_Y_OFFSET;
1420 menu_pos.x = tuning_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
1421 ImGui::SetNextWindowPos(menu_pos);
1422 if (ImGui::Begin(
_LC(
"TopMenubar",
"Tuning menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
1428 ImGui::Text(
"%s",
_LC(
"Tuning",
"You are on foot."));
1429 ImGui::Text(
"%s",
_LC(
"Tuning",
"Enter a vehicle to tune it."));
1430 ImGui::PopStyleColor();
1443 ImGui::AlignTextToFramePadding();
1464 std::string delbtn_text =
_LC(
"Tuning",
"Delete");
1465 float delbtn_w = ImGui::CalcTextSize(delbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1466 float delbtn_cursorx = ImGui::GetWindowContentRegionWidth() - delbtn_w;
1469 ImGui::SetCursorPosX(delbtn_cursorx);
1472 ImGui::PopStyleColor();
1483 ImGui::AlignTextToFramePadding();
1484 ImGui::TextDisabled(
_LC(
"Tuning",
"Working tuneup"));
1489 if (ImGui::Button(
_LC(
"Tuning",
"Save")))
1505 std::string cancelbtn_text =
_LC(
"Tuning",
"Cancel");
1506 float cancelbtn_w = ImGui::CalcTextSize(cancelbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1507 float cancelbtn_cursorx = ImGui::GetWindowContentRegionWidth() - cancelbtn_w;
1510 ImGui::SetCursorPosX(cancelbtn_cursorx);
1511 if (ImGui::SmallButton(
_LC(
"Tuning",
"Cancel")))
1517 else if (tuneup_def)
1520 if (ImGui::Button(
_LC(
"Tuning",
"Save as...")))
1529 ImGui::AlignTextToFramePadding();
1530 std::string resetbtn_text =
_LC(
"Tuning",
"Reset");
1531 float delbtn_w = ImGui::CalcTextSize(resetbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1532 float delbtn_cursorx = ImGui::GetWindowContentRegionWidth() - delbtn_w;
1535 ImGui::SetCursorPosX(delbtn_cursorx);
1538 ImGui::PopStyleColor();
1539 if (resetbtn_pressed)
1550 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
1552 if (ImGui::CollapsingHeader(addonparts_title.c_str()))
1558 ImGui::PushID(addonpart_entry->
fname.c_str());
1563 const ImVec2 checkbox_cursor = ImGui::GetCursorScreenPos();
1564 if (ImGui::Checkbox(addonpart_entry->
dname.c_str(), &used)
1565 && !conflict_w_hovered
1580 const float square_sz = ImGui::GetFrameHeight();
1581 const ImVec2 min = checkbox_cursor + ImGui::GetStyle().FramePadding*1.4f;
1582 const ImVec2 max = checkbox_cursor + (ImVec2(square_sz, square_sz) - ImGui::GetStyle().FramePadding*1.5f);
1583 const ImColor X_COLOR(0.5f, 0.48f, 0.45f);
1584 ImGui::GetWindowDrawList()->AddLine(min, max, X_COLOR, 4.f);
1585 ImGui::GetWindowDrawList()->AddLine(ImVec2(min.x, max.y), ImVec2(max.x, min.y), X_COLOR, 4.f);
1587 if (conflict_w_hovered)
1590 const float square_sz = ImGui::GetFrameHeight();
1591 const ImVec2 min = checkbox_cursor;
1592 const ImVec2 max = checkbox_cursor + ImVec2(square_sz + 0.5f, square_sz);
1593 const ImColor SQ_COLOR(0.7f, 0.1f, 0.f);
1594 ImGui::GetWindowDrawList()->AddRect(min, max, SQ_COLOR, 0.f, ImDrawCornerFlags_None, 3.f);
1597 if (ImGui::IsItemHovered())
1609 ImGui::AlignTextToFramePadding();
1610 std::string reloadbtn_text =
_LC(
"Tuning",
"Reload");
1611 const float reloadbtn_w = ImGui::CalcTextSize(reloadbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1613 ImGui::SetCursorPosX(reloadbtn_cursorx);
1614 const bool reloadbtn_pressed = ImGui::SmallButton(reloadbtn_text.c_str());
1615 if (reloadbtn_pressed)
1638 if (ImGui::Button(
_LC(
"Tuning",
"Browse all parts")))
1648 std::string props_title =
fmt::format(
_LC(
"Tuning",
"Props ({})"), total_props);
1649 if (ImGui::CollapsingHeader(props_title.c_str()))
1654 ImGui::PushID(p.pp_id);
1655 ImGui::AlignTextToFramePadding();
1668 if (p.pp_beacon_type ==
'L' || p.pp_beacon_type ==
'R' || p.pp_beacon_type ==
'w')
1671 ImGui::TextDisabled(
"(special!)");
1672 if (ImGui::IsItemHovered())
1674 ImGui::BeginTooltip();
1675 ImGui::Text(
"special prop - aerial nav light");
1676 ImGui::EndTooltip();
1679 else if (p.pp_wheel_mesh_obj)
1682 ImGui::TextDisabled(
"(special!)");
1683 if (ImGui::IsItemHovered())
1685 ImGui::BeginTooltip();
1686 ImGui::Text(
"special prop - dashboard + dirwheel");
1687 ImGui::EndTooltip();
1706 std::string flexbodies_title =
fmt::format(
_LC(
"Tuning",
"Flexbodies ({})"), total_flexbodies);
1707 if (ImGui::CollapsingHeader(flexbodies_title.c_str()))
1712 ImGui::PushID(flexbody->getID());
1713 ImGui::AlignTextToFramePadding();
1719 flexbody->getOrigMeshName(),
1737 std::string wheels_title =
fmt::format(
_LC(
"TopMenubar",
"Wheels ({})"), total_wheels);
1738 if (ImGui::CollapsingHeader(wheels_title.c_str()))
1740 for (
WheelID_t i = 0; i < total_wheels; i++)
1743 ImGui::AlignTextToFramePadding();
1751 ImGui::PushStyleColor(ImGuiCol_Border,
ORANGE_TEXT);
1752 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
1759 ImGui::TextDisabled(
"|");
1770 bool resetPressed =
false;
1776 resetPressed = ImGui::SmallButton(
_LC(
"Tuning",
"Reset"));
1777 ImGui::PopStyleColor();
1778 ImGui::PopStyleVar();
1779 ImGui::PopStyleColor();
1783 if (selected_side != active_side)
1792 else if (resetPressed)
1813 std::string flares_title =
fmt::format(
_LC(
"Tuning",
"Flares ({})"), total_flares);
1814 if (ImGui::CollapsingHeader(flares_title.c_str()))
1819 ImGui::PushID(flareid);
1820 ImGui::AlignTextToFramePadding();
1826 std::string flarename;
1830 flarename =
fmt::format(
"{} {}", (
char)flaretype, controlnumber);
1835 flarename =
fmt::format(
"{} {}", (
char)flaretype, linkname);
1862 std::string exhausts_title =
fmt::format(
_LC(
"Tuning",
"Exhausts ({})"), total_exhausts);
1863 if (ImGui::CollapsingHeader(exhausts_title.c_str()))
1868 ImGui::PushID(exhaustid);
1869 ImGui::AlignTextToFramePadding();
1893 std::string materials_title =
fmt::format(
_LC(
"Tuning",
"Managed Materials ({})"), total_materials);
1894 if (ImGui::CollapsingHeader(materials_title.c_str()))
1899 const std::string& material_name = mm_pair.first;
1900 ImGui::PushID(material_name.c_str());
1901 ImGui::AlignTextToFramePadding();
1936 ImGui::PopStyleColor(2);
1946 if (ImGui::IsMouseDown(1))
1957 ImVec2 box_min(0,0);
1958 ImVec2 box_max(ImGui::GetIO().DisplaySize.x, ImGui::GetStyle().WindowPadding.y +
PANEL_HOVERBOX_HEIGHT);
1959 ImVec2 mouse_pos = ImGui::GetIO().MousePos;
1960 const bool window_hovered ((mouse_pos.x >= box_min.x) && (mouse_pos.x <= box_max.x) &&
1961 (mouse_pos.y >= box_min.y) && (mouse_pos.y <= box_max.y));
1962 bool result = window_hovered;
1964 bool menu_hovered =
false;
1970 result |= menu_hovered;
1972 bool box_hovered =
false;
1977 result |= box_hovered;
1980 if (box_hovered && !menu_hovered)
1991 unsigned int num_actors_player = 0;
1994 if (actor->ar_net_source_id == user.
uniqueid)
1996 ++num_actors_player;
2003 ImVec4 player_gui_color(player_color.r, player_color.g, player_color.b, 1.f);
2004 ImGui::PushStyleColor(ImGuiCol_Text, player_gui_color);
2005 ImGui::Text(
"%s: %u (%s, Ver: %s, Lang: %s)",
2009 ImGui::PopStyleColor();
2010 #endif // USE_SOCKETW
2013 Ogre::TexturePtr tex1 =
FetchIcon(
"control_pause.png");
2014 Ogre::TexturePtr tex2 =
FetchIcon(
"control_play.png");
2018 if ((!actor->ar_hide_in_actor_list) && (actor->ar_net_source_id == user.
uniqueid))
2021 ImGui::PushID(
id.c_str());
2024 if (ImGui::ImageButton(
reinterpret_cast<ImTextureID
>(tex1->getHandle()), ImVec2(16, 16)))
2031 if (ImGui::ImageButton(
reinterpret_cast<ImTextureID
>(tex2->getHandle()), ImVec2(16, 16)))
2038 std::string text_buf_rem =
fmt::format(
" X ##[{}]", i);
2039 ImGui::PushStyleColor(ImGuiCol_Text,
RED_TEXT);
2040 if (ImGui::Button(text_buf_rem.c_str()))
2044 ImGui::PopStyleColor();
2050 if (ImGui::Button(actortext_buf.c_str()))
2060 std::vector<ActorPtr> actor_list;
2063 if (!actor->ar_hide_in_actor_list)
2065 actor_list.emplace_back(actor);
2068 if (actor_list.empty())
2071 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"None spawned yet"));
2072 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Use [Simulation] menu"));
2073 ImGui::PopStyleColor();
2081 std::string text_buf_rem =
fmt::format(
"X ##[{}]", i);
2082 ImGui::PushStyleColor(ImGuiCol_Text,
RED_TEXT);
2083 if (ImGui::Button(text_buf_rem.c_str()))
2087 ImGui::PopStyleColor();
2091 if (actor == player_actor)
2093 ImGui::PushStyleColor(ImGuiCol_Text,
GREEN_TEXT);
2095 else if (std::find(actor->ar_linked_actors.begin(), actor->ar_linked_actors.end(), player_actor) != actor->ar_linked_actors.end())
2097 ImGui::PushStyleColor(ImGuiCol_Text,
ORANGE_TEXT);
2101 ImGui::PushStyleColor(ImGuiCol_Text,
WHITE_TEXT);
2107 if (ImGui::Button(text_buf.c_str()))
2111 ImGui::PopStyleColor();
2128 float content_width = 0.f;
2130 std::string special_text;
2131 ImVec4 special_color = ImGui::GetStyle().Colors[ImGuiCol_Text];
2132 float special_text_centering_weight = 1.f;
2134 std::string special_text_b;
2135 std::string special_text_c;
2136 std::string special_text_d;
2137 ImVec4 special_color_c = ImVec4(0,0,0,0);
2144 special_text =
fmt::format(
_LC(
"TopMenubar",
"All physics paused, press {} to resume"),
2146 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2153 special_text =
fmt::format(
_LC(
"TopMenubar",
"Vehicle physics paused, press {} to resume"),
2155 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2160 content_width = 300;
2162 special_text =
_LC(
"TopMenubar",
"Replay");
2166 special_text =
fmt::format(
_LC(
"TopMenubar",
"Live repair mode, hit '{}' to stop"),
2168 content_width = 450;
2171 special_text_centering_weight = 0.7f;
2175 special_text =
fmt::format(
_LC(
"TopMenubar",
"Quick repair ('{}' for Live repair)"),
2177 content_width = 450;
2180 special_text_centering_weight = 0.7f;
2189 float distance = 0.0f;
2203 special_text_b =
fmt::format(
"{:.1f} {}", distance,
_LC(
"DirectionArrow",
"meter"));
2204 content_width = ImGui::CalcTextSize(special_text.c_str()).x + ImGui::CalcTextSize(special_text_b.c_str()).x;
2207 special_text_c =
fmt::format(
"{:02d}.{:02d}.{:02d}", (
int)(time) / 60, (
int)(time) % 60, (
int)(time * 100.0) % 100);
2209 special_color_c = (time_diff > 0.0f)
2216 special_text_d =
fmt::format(
"{:02d}.{:02d}.{:02d}", (
int)(best_time) / 60, (
int)(best_time) % 60, (
int)(best_time * 100.0) % 100);
2222 special_text =
fmt::format(
_LC(
"TopMenubar",
"Terrain editing mode, press {} to save and exit"),
2224 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2228 if (!special_text.empty())
2231 box_pos.y = top_offset;
2232 box_pos.x = (ImGui::GetIO().DisplaySize.x / 2) - ((content_width / 2) + ImGui::GetStyle().FramePadding.x);
2233 ImGui::SetNextWindowPos(box_pos);
2234 ImGui::SetNextWindowSize(ImVec2(0.f, 0.f));
2235 ImGui::SetNextWindowContentWidth(content_width);
2236 ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
2237 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse;
2238 ImGui::PushStyleColor(ImGuiCol_WindowBg,
App::GetGuiManager()->GetTheme().semitransparent_window_bg);
2239 if (ImGui::Begin(special_text.c_str(),
nullptr, flags))
2244 float text_w = ImGui::CalcTextSize(special_text.c_str()).x;
2245 ImGui::SetCursorPosX(((content_width / 2) - (text_w / 2)) * special_text_centering_weight);
2247 ImGui::TextColored(special_color,
"%s", special_text.c_str());
2257 float pbar_width = content_width - (ImGui::GetStyle().ItemSpacing.x + ImGui::CalcTextSize(special_text.c_str()).x);
2258 ImGui::ProgressBar(fraction, ImVec2(pbar_width, ImGui::GetTextLineHeight()), pbar_text.
ToCStr());
2266 int min = (int)time_sec / 60;
2267 str_pos = snprintf(str, 200,
"%dmin ", min);
2268 time_sec -= (float)min * 60.f;
2270 snprintf(str+str_pos, 200-str_pos,
"%.2fsec", time_sec);
2271 ImGui::TextDisabled(
"%s: %s",
_LC(
"TopMenubar",
"Time"), str);
2277 ImGui::Text(special_text_b.c_str());
2278 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2) - (ImGui::CalcTextSize(special_text_c.c_str()).x / 2));
2279 ImGui::TextColored(special_color_c,
"%s", special_text_c.c_str());
2282 text <<
"Best Time: " << special_text_d.c_str();
2283 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2) - (ImGui::CalcTextSize(text).
x / 2));
2285 if (!special_text_d.empty())
2287 ImGui::TextDisabled(text);
2294 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.f, 0.f));
2298 ImGui::ProgressBar(fraction, ImVec2(15.f, ImGui::GetTextLineHeight() / 2.f),
"");
2302 ImGui::PopStyleVar();
2304 const ImVec2 MINI_SPACING = ImVec2(2.f,0.f);
2305 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, MINI_SPACING);
2309 const float INDENT = 15.f;
2311 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Movement"));
2313 ImGui::SetColumnWidth(0, INDENT);
2314 ImGui::NextColumn();
2317 ImGui::NextColumn();
2320 ImGui::NextColumn();
2325 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Rotation"));
2327 ImGui::SetColumnWidth(0, INDENT);
2328 ImGui::NextColumn();
2333 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Modifiers"));
2335 ImGui::SetColumnWidth(0, INDENT);
2336 ImGui::SetColumnWidth(1, 125);
2337 ImGui::SetColumnWidth(2, 125);
2338 ImGui::NextColumn();
2345 ImGui::TextDisabled(
"%s (%s):",
_LC(
"LiveRepair",
"Reset mode"),
ToLocalizedString(resetmode).c_str());
2346 ImGui::Dummy(ImVec2(INDENT, 1.f));
2350 ImGui::PopStyleVar();
2352 const ImVec2 PAD = ImVec2(5, 5);
2360 ImGui::PopStyleColor(1);
2373 rapidjson::Document j_doc;
2384 if (!j_doc.IsArray())
2386 LOG(
fmt::format(
"[RoR|Terrain] AI presets file '{}' declared in '{}' has wrong format - the root element is not an array!",
2392 for (
const rapidjson::Value& j_bundled_preset: j_doc.GetArray())
2405 #if defined(USE_CURL)
2407 std::thread(std::move(task)).detach();
2409 #endif // defined(USE_CURL)
2422 rapidjson::Value preset_copy(bundled_preset,
ai_presets_all.GetAllocator());
2428 rapidjson::Value preset_copy(extern_preset,
ai_presets_all.GetAllocator());
2534 std::string protectchk_text =
_LC(
"Tuning",
"Protected");
2535 float protectchk_w = ImGui::CalcTextSize(protectchk_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
2536 float protectchk_cursorx = (ImGui::GetWindowContentRegionWidth() - protectchk_w) - 20.f;
2539 ImGui::SetCursorPosX(protectchk_cursorx);
2542 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
2543 bool chk_pressed = ImGui::Checkbox(protectchk_text.c_str(), &protectchk_value);
2544 ImGui::PopStyleVar(1);
2559 request->
mpr_type = (protectchk_value) ? request_type_set : request_type_reset;
2568 ImGui::GetWindowDrawList()->AddRect(
2569 ImGui::GetCursorScreenPos(),
2570 ImGui::GetCursorScreenPos() + ImGui::CalcTextSize(
"00") + ImGui::GetStyle().FramePadding*2,
2571 ImColor(ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]),
2572 ImGui::GetStyle().FrameRounding);
2573 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().FramePadding.x);
2574 ImGui::Text(
"%02d", subject_id);
2576 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().FramePadding.x);
2585 bool isEnabled = !is_unwanted && !is_force_removed;
2586 if (is_force_removed)
2588 ImGui::PushStyleColor(ImGuiCol_Border,
ORANGE_TEXT);
2589 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
2591 bool chkPressed = ImGui::Checkbox(name.c_str(), &isEnabled);
2592 bool resetPressed =
false;
2593 if (is_force_removed)
2597 resetPressed = ImGui::SmallButton(
_LC(
"Tuning",
"Reset"));
2598 ImGui::PopStyleColor();
2599 ImGui::PopStyleVar();
2600 ImGui::PopStyleColor();
2604 if (chkPressed && !isEnabled)
2619 else if ((chkPressed && isEnabled) || resetPressed)
2622 req->
mpr_type = request_type_reset;