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"));
801 if (current_actor !=
nullptr)
805 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"Live diagnostic views:"));
810 if (current_actor !=
nullptr)
839 if ((current_actor !=
nullptr) && (debug_view_type !=
static_cast<int>(current_actor->
GetGfxActor()->
GetDebugView())))
852 if (debug_view_type >= 2)
869 menu_pos.x = ai_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
870 ImGui::SetNextWindowPos(menu_pos);
871 if (ImGui::Begin(
_LC(
"TopMenubar",
"AI menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
873 if (ImGui::IsWindowHovered())
878 ImGui::PushItemWidth(125.f);
887 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
888 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
891 ImGui::InputInt(
_LC(
"TopMenubar",
"Vehicle count"), &
ai_num, 1, 100);
892 if (ImGui::IsItemHovered())
894 ImGui::BeginTooltip();
895 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Number of vehicles"));
901 ImGui::PopItemFlag();
902 ImGui::PopStyleVar();
907 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
908 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
913 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
914 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
917 ImGui::InputInt(
_LC(
"TopMenubar",
"Distance"), &
ai_distance, 1, 100);
918 if (ImGui::IsItemHovered())
920 ImGui::BeginTooltip();
921 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Following distance in meters"));
927 ImGui::PopItemFlag();
928 ImGui::PopStyleVar();
931 std::string label1 =
"Behind";
943 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
944 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
947 if (ImGui::BeginCombo(
"Position", label1.c_str()))
949 if (ImGui::Selectable(
"Behind"))
953 if (ImGui::Selectable(
"Parallel"))
959 if (ImGui::IsItemHovered())
961 ImGui::BeginTooltip();
962 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Positioning scheme"));
964 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Behind: Set vehicle behind vehicle, in line"));
965 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Parallel: Set vehicles in parallel, useful for certain scenarios like drag races"));
971 ImGui::PopItemFlag();
972 ImGui::PopStyleVar();
980 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
981 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
984 ImGui::InputInt(
_LC(
"TopMenubar",
"Repeat times"), &
ai_times, 1, 100);
985 if (ImGui::IsItemHovered())
987 ImGui::BeginTooltip();
988 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"How many times to loop the path"));
994 ImGui::PopItemFlag();
995 ImGui::PopStyleVar();
1000 ImGui::PopItemFlag();
1001 ImGui::PopStyleVar();
1005 ImGui::TextColored(
GRAY_HINT_TEXT,
"%s",
_LC(
"TopMenubar",
"Vehicle options:"));
1007 std::string label2 =
"Normal";
1014 label2 =
"Drag Race";
1027 if (actor->ar_driveable ==
AI)
1029 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1030 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1035 if (ImGui::BeginCombo(
"Mode", label2.c_str()))
1037 if (ImGui::Selectable(
"Normal"))
1050 if (ImGui::Selectable(
"Race"))
1063 if (ImGui::Selectable(
"Drag Race"))
1080 if (ImGui::Selectable(
"Crash"))
1096 if (ImGui::Selectable(
"Chase"))
1111 if (ImGui::IsItemHovered())
1113 ImGui::BeginTooltip();
1114 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicle driving mode"));
1116 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Normal: Modify speed according to turns, other vehicles and character"));
1117 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Race: Always keep defined speed"));
1118 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Drag Race: Two vehicles performing a drag race"));
1119 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Crash: Two vehicles driving in opposite direction"));
1120 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Chase: Follow character and player vehicle"));
1121 ImGui::EndTooltip();
1126 if (actor->ar_driveable ==
AI)
1128 ImGui::PopItemFlag();
1129 ImGui::PopStyleVar();
1137 ImGui::InputInt(
_LC(
"TopMenubar",
"Speed"), &
ai_speed, 1, 100);
1138 if (ImGui::IsItemHovered())
1140 ImGui::BeginTooltip();
1141 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Speed in km/h for land vehicles or knots/s for boats"));
1142 ImGui::EndTooltip();
1148 ImGui::InputInt(
_LC(
"TopMenubar",
"Altitude"), &
ai_altitude, 1, 100);
1149 if (ImGui::IsItemHovered())
1151 ImGui::BeginTooltip();
1152 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Airplane maximum altitude in feet"));
1153 ImGui::EndTooltip();
1166 if (ImGui::IsItemHovered())
1168 ImGui::BeginTooltip();
1169 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicles, boats and airplanes"));
1170 ImGui::EndTooltip();
1175 ImGui::PushID(
"vehicle2");
1184 if (ImGui::IsItemHovered())
1186 ImGui::BeginTooltip();
1187 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Land vehicles, boats and airplanes"));
1188 ImGui::EndTooltip();
1197 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1198 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1203 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]);
1206 if (ImGui::Button(
_LC(
"TopMenubar",
"Start"), ImVec2(80, 0)))
1230 fmt::format(
_LC(
"TopMenubar",
"Select a preset, record or open survey map ({}) to set waypoints."),
1242 ImGui::PopStyleColor();
1247 if (ImGui::Button(
_LC(
"TopMenubar",
"Stop"), ImVec2(80, 0)))
1256 if (actor->ar_driveable ==
AI)
1265 ImGui::PopItemFlag();
1266 ImGui::PopStyleVar();
1271 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_Button]);
1272 std::string label =
"Record";
1275 label =
"Recording";
1276 ImGui::PushStyleColor(ImGuiCol_Button,
RED_TEXT);
1279 if (ImGui::Button(label.c_str(), ImVec2(80, 0)))
1292 ImGui::PopStyleColor();
1295 if (ImGui::CollapsingHeader(
_LC(
"TopMenubar",
"Presets")))
1299 int display_count = 0;
1300 for (
size_t i = 0; i < num_rows; i++)
1302 rapidjson::Value& j_row =
ai_presets_all[
static_cast<rapidjson::SizeType
>(i)];
1307 if (ImGui::Button(j_row[
"preset"].GetString(), ImVec2(250, 0)))
1311 for (
size_t i = 0; i < j_row[
"waypoints"].Size(); i++)
1313 float x = j_row[
"waypoints"][i][0].GetFloat();
1314 float y = j_row[
"waypoints"][i][1].GetFloat();
1315 float z = j_row[
"waypoints"][i][2].GetFloat();
1321 if (j_row[
"waypoints"][i].Size() == 4)
1323 speed = j_row[
"waypoints"][i][3].GetInt();
1329 waypoint.
speed = speed;
1341 float spinner_size = 8.f;
1342 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2.f) - spinner_size);
1347 ImGui::TextColored(
RED_TEXT,
"%s",
_LC(
"TopMenubar",
"Failed to fetch external presets."));
1348 if (ImGui::Button(
_LC(
"TopMenubar",
"Retry")))
1362 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"No presets found for this terrain :("));
1363 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Supported terrains:"));
1366 ImGui::BeginChild(
"terrains-scrolling", ImVec2(0.f, 200),
false);
1368 for (
size_t i = 0; i < num_rows; i++)
1370 rapidjson::Value& j_row_terrains =
ai_presets_all[
static_cast<rapidjson::SizeType
>(i)];
1371 if (j_row_terrains.HasMember(
"terrains"))
1373 for (
size_t i = 0; i < j_row_terrains[
"terrains"].Size(); i++)
1375 ImGui::Text(
"%s", j_row_terrains[
"terrains"][i].GetString());
1384 if (ImGui::CollapsingHeader(
_LC(
"TopMenubar",
"Waypoints")))
1388 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"No waypoints defined."));
1392 if (ImGui::Button(
_LC(
"TopMenubar",
"Export"), ImVec2(250, 0)))
1415 std::string json =
fmt::format(
"\n {{\n \"terrain\":\"{}\",\n \"preset\":\"Preset name\",\n \"waypoints\":\n [{}\n ]\n }}",
App::sim_terrain_name->getStr(), s);
1419 fmt::format(
_LC(
"TopMenubar",
"{} waypoints exported to RoR.log"),
1423 ImGui::BeginChild(
"waypoints-scrolling", ImVec2(0.f, 200),
false);
1428 ImGui::AlignTextToFramePadding();
1429 ImGui::Text(
"%d", i);
1431 if (ImGui::Button(
"teleport", ImVec2(60, 0)))
1433 Ogre::Vector3* payload =
new Ogre::Vector3(
ai_waypoints[i].position);
1436 if (ImGui::IsItemHovered())
1438 ImGui::BeginTooltip();
1440 ImGui::Text(
w.c_str());
1441 ImGui::EndTooltip();
1444 ImGui::SetNextItemWidth(90);
1450 ImGui::InputInt(
_LC(
"TopMenubar",
"speed"), &
ai_waypoints[i].speed, 1, 100);
1451 if (ImGui::IsItemHovered())
1453 ImGui::BeginTooltip();
1454 ImGui::Text(
_LC(
"TopMenubar",
"Set waypoint speed in km/h for land vehicles"));
1456 ImGui::Text(
_LC(
"TopMenubar",
"Value -1: Ignore, vehicle will use default speed"));
1457 ImGui::Text(
_LC(
"TopMenubar",
"Value >= 5: Override default speed"));
1458 ImGui::EndTooltip();
1467 ImGui::PopItemWidth();
1477 menu_pos.y = window_pos.y + tuning_cursor.y +
MENU_Y_OFFSET;
1478 menu_pos.x = tuning_cursor.x + window_pos.x - ImGui::GetStyle().WindowPadding.x;
1479 ImGui::SetNextWindowPos(menu_pos);
1480 if (ImGui::Begin(
_LC(
"TopMenubar",
"Tuning menu"),
nullptr,
static_cast<ImGuiWindowFlags_
>(flags)))
1486 ImGui::Text(
"%s",
_LC(
"Tuning",
"You are on foot."));
1487 ImGui::Text(
"%s",
_LC(
"Tuning",
"Enter a vehicle to tune it."));
1488 ImGui::PopStyleColor();
1501 ImGui::AlignTextToFramePadding();
1522 std::string delbtn_text =
_LC(
"Tuning",
"Delete");
1523 float delbtn_w = ImGui::CalcTextSize(delbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1524 float delbtn_cursorx = ImGui::GetWindowContentRegionWidth() - delbtn_w;
1527 ImGui::SetCursorPosX(delbtn_cursorx);
1530 ImGui::PopStyleColor();
1541 ImGui::AlignTextToFramePadding();
1542 ImGui::TextDisabled(
_LC(
"Tuning",
"Working tuneup"));
1547 if (ImGui::Button(
_LC(
"Tuning",
"Save")))
1563 std::string cancelbtn_text =
_LC(
"Tuning",
"Cancel");
1564 float cancelbtn_w = ImGui::CalcTextSize(cancelbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1565 float cancelbtn_cursorx = ImGui::GetWindowContentRegionWidth() - cancelbtn_w;
1568 ImGui::SetCursorPosX(cancelbtn_cursorx);
1569 if (ImGui::SmallButton(
_LC(
"Tuning",
"Cancel")))
1575 else if (tuneup_def)
1578 if (ImGui::Button(
_LC(
"Tuning",
"Save as...")))
1587 ImGui::AlignTextToFramePadding();
1588 std::string resetbtn_text =
_LC(
"Tuning",
"Reset");
1589 float delbtn_w = ImGui::CalcTextSize(resetbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1590 float delbtn_cursorx = ImGui::GetWindowContentRegionWidth() - delbtn_w;
1593 ImGui::SetCursorPosX(delbtn_cursorx);
1596 ImGui::PopStyleColor();
1597 if (resetbtn_pressed)
1608 ImGui::SetNextItemOpen(
true, ImGuiCond_FirstUseEver);
1610 if (ImGui::CollapsingHeader(addonparts_title.c_str()))
1616 ImGui::PushID(addonpart_entry->
fname.c_str());
1621 const ImVec2 checkbox_cursor = ImGui::GetCursorScreenPos();
1622 if (ImGui::Checkbox(addonpart_entry->
dname.c_str(), &used)
1623 && !conflict_w_hovered
1638 const float square_sz = ImGui::GetFrameHeight();
1639 const ImVec2 min = checkbox_cursor + ImGui::GetStyle().FramePadding*1.4f;
1640 const ImVec2 max = checkbox_cursor + (ImVec2(square_sz, square_sz) - ImGui::GetStyle().FramePadding*1.5f);
1641 const ImColor X_COLOR(0.5f, 0.48f, 0.45f);
1642 ImGui::GetWindowDrawList()->AddLine(min, max, X_COLOR, 4.f);
1643 ImGui::GetWindowDrawList()->AddLine(ImVec2(min.x, max.y), ImVec2(max.x, min.y), X_COLOR, 4.f);
1645 if (conflict_w_hovered)
1648 const float square_sz = ImGui::GetFrameHeight();
1649 const ImVec2 min = checkbox_cursor;
1650 const ImVec2 max = checkbox_cursor + ImVec2(square_sz + 0.5f, square_sz);
1651 const ImColor SQ_COLOR(0.7f, 0.1f, 0.f);
1652 ImGui::GetWindowDrawList()->AddRect(min, max, SQ_COLOR, 0.f, ImDrawCornerFlags_None, 3.f);
1655 if (ImGui::IsItemHovered())
1667 ImGui::AlignTextToFramePadding();
1668 std::string reloadbtn_text =
_LC(
"Tuning",
"Reload");
1669 const float reloadbtn_w = ImGui::CalcTextSize(reloadbtn_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
1671 ImGui::SetCursorPosX(reloadbtn_cursorx);
1672 const bool reloadbtn_pressed = ImGui::SmallButton(reloadbtn_text.c_str());
1673 if (reloadbtn_pressed)
1696 if (ImGui::Button(
_LC(
"Tuning",
"Browse all parts")))
1706 std::string props_title =
fmt::format(
_LC(
"Tuning",
"Props ({})"), total_props);
1707 if (ImGui::CollapsingHeader(props_title.c_str()))
1712 ImGui::PushID(p.pp_id);
1713 ImGui::AlignTextToFramePadding();
1726 if (p.pp_beacon_type ==
'L' || p.pp_beacon_type ==
'R' || p.pp_beacon_type ==
'w')
1729 ImGui::TextDisabled(
"(special!)");
1730 if (ImGui::IsItemHovered())
1732 ImGui::BeginTooltip();
1733 ImGui::Text(
"special prop - aerial nav light");
1734 ImGui::EndTooltip();
1737 else if (p.pp_wheel_mesh_obj)
1740 ImGui::TextDisabled(
"(special!)");
1741 if (ImGui::IsItemHovered())
1743 ImGui::BeginTooltip();
1744 ImGui::Text(
"special prop - dashboard + dirwheel");
1745 ImGui::EndTooltip();
1764 std::string flexbodies_title =
fmt::format(
_LC(
"Tuning",
"Flexbodies ({})"), total_flexbodies);
1765 if (ImGui::CollapsingHeader(flexbodies_title.c_str()))
1770 ImGui::PushID(flexbody->getID());
1771 ImGui::AlignTextToFramePadding();
1777 flexbody->getOrigMeshName(),
1795 std::string wheels_title =
fmt::format(
_LC(
"TopMenubar",
"Wheels ({})"), total_wheels);
1796 if (ImGui::CollapsingHeader(wheels_title.c_str()))
1798 for (
WheelID_t i = 0; i < total_wheels; i++)
1801 ImGui::AlignTextToFramePadding();
1809 ImGui::PushStyleColor(ImGuiCol_Border,
ORANGE_TEXT);
1810 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
1817 ImGui::TextDisabled(
"|");
1828 bool resetPressed =
false;
1834 resetPressed = ImGui::SmallButton(
_LC(
"Tuning",
"Reset"));
1835 ImGui::PopStyleColor();
1836 ImGui::PopStyleVar();
1837 ImGui::PopStyleColor();
1841 if (selected_side != active_side)
1850 else if (resetPressed)
1871 std::string flares_title =
fmt::format(
_LC(
"Tuning",
"Flares ({})"), total_flares);
1872 if (ImGui::CollapsingHeader(flares_title.c_str()))
1877 ImGui::PushID(flareid);
1878 ImGui::AlignTextToFramePadding();
1884 std::string flarename;
1888 flarename =
fmt::format(
"{} {}", (
char)flaretype, controlnumber);
1893 flarename =
fmt::format(
"{} {}", (
char)flaretype, linkname);
1920 std::string exhausts_title =
fmt::format(
_LC(
"Tuning",
"Exhausts ({})"), total_exhausts);
1921 if (ImGui::CollapsingHeader(exhausts_title.c_str()))
1926 ImGui::PushID(exhaustid);
1927 ImGui::AlignTextToFramePadding();
1951 std::string materials_title =
fmt::format(
_LC(
"Tuning",
"Managed Materials ({})"), total_materials);
1952 if (ImGui::CollapsingHeader(materials_title.c_str()))
1957 const std::string& material_name = mm_pair.first;
1958 ImGui::PushID(material_name.c_str());
1959 ImGui::AlignTextToFramePadding();
1994 ImGui::PopStyleColor(2);
2004 if (ImGui::IsMouseDown(1))
2015 ImVec2 box_min(0,0);
2016 ImVec2 box_max(ImGui::GetIO().DisplaySize.x, ImGui::GetStyle().WindowPadding.y +
PANEL_HOVERBOX_HEIGHT);
2017 ImVec2 mouse_pos = ImGui::GetIO().MousePos;
2018 const bool window_hovered ((mouse_pos.x >= box_min.x) && (mouse_pos.x <= box_max.x) &&
2019 (mouse_pos.y >= box_min.y) && (mouse_pos.y <= box_max.y));
2020 bool result = window_hovered;
2022 bool menu_hovered =
false;
2028 result |= menu_hovered;
2030 bool box_hovered =
false;
2035 result |= box_hovered;
2038 if (box_hovered && !menu_hovered)
2049 unsigned int num_actors_player = 0;
2052 if (actor->ar_net_source_id == user.
uniqueid)
2054 ++num_actors_player;
2061 ImVec4 player_gui_color(player_color.r, player_color.g, player_color.b, 1.f);
2062 ImGui::PushStyleColor(ImGuiCol_Text, player_gui_color);
2063 ImGui::Text(
"%s: %u (%s, Ver: %s, Lang: %s)",
2067 ImGui::PopStyleColor();
2068 #endif // USE_SOCKETW
2071 Ogre::TexturePtr tex1 =
FetchIcon(
"control_pause.png");
2072 Ogre::TexturePtr tex2 =
FetchIcon(
"control_play.png");
2076 if ((!actor->ar_hide_in_actor_list) && (actor->ar_net_source_id == user.
uniqueid))
2079 ImGui::PushID(
id.c_str());
2082 if (ImGui::ImageButton(
reinterpret_cast<ImTextureID
>(tex1->getHandle()), ImVec2(16, 16)))
2089 if (ImGui::ImageButton(
reinterpret_cast<ImTextureID
>(tex2->getHandle()), ImVec2(16, 16)))
2096 std::string text_buf_rem =
fmt::format(
" X ##[{}]", i);
2097 ImGui::PushStyleColor(ImGuiCol_Text,
RED_TEXT);
2098 if (ImGui::Button(text_buf_rem.c_str()))
2102 ImGui::PopStyleColor();
2108 if (ImGui::Button(actortext_buf.c_str()))
2118 std::vector<ActorPtr> actor_list;
2121 if (!actor->ar_hide_in_actor_list)
2123 actor_list.emplace_back(actor);
2126 if (actor_list.empty())
2129 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"None spawned yet"));
2130 ImGui::Text(
"%s",
_LC(
"TopMenubar",
"Use [Simulation] menu"));
2131 ImGui::PopStyleColor();
2139 std::string text_buf_rem =
fmt::format(
"X ##[{}]", i);
2140 ImGui::PushStyleColor(ImGuiCol_Text,
RED_TEXT);
2141 if (ImGui::Button(text_buf_rem.c_str()))
2145 ImGui::PopStyleColor();
2149 if (actor == player_actor)
2151 ImGui::PushStyleColor(ImGuiCol_Text,
GREEN_TEXT);
2153 else if (std::find(actor->ar_linked_actors.begin(), actor->ar_linked_actors.end(), player_actor) != actor->ar_linked_actors.end())
2155 ImGui::PushStyleColor(ImGuiCol_Text,
ORANGE_TEXT);
2159 ImGui::PushStyleColor(ImGuiCol_Text,
WHITE_TEXT);
2165 if (ImGui::Button(text_buf.c_str()))
2169 ImGui::PopStyleColor();
2186 float content_width = 0.f;
2188 std::string special_text;
2189 ImVec4 special_color = ImGui::GetStyle().Colors[ImGuiCol_Text];
2190 float special_text_centering_weight = 1.f;
2192 std::string special_text_b;
2193 std::string special_text_c;
2194 std::string special_text_d;
2195 ImVec4 special_color_c = ImVec4(0,0,0,0);
2202 special_text =
fmt::format(
_LC(
"TopMenubar",
"All physics paused, press {} to resume"),
2204 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2211 special_text =
fmt::format(
_LC(
"TopMenubar",
"Vehicle physics paused, press {} to resume"),
2213 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2218 content_width = 300;
2220 special_text =
_LC(
"TopMenubar",
"Replay");
2224 special_text =
fmt::format(
_LC(
"TopMenubar",
"Live repair mode, hit '{}' to stop"),
2226 content_width = 450;
2229 special_text_centering_weight = 0.7f;
2233 special_text =
fmt::format(
_LC(
"TopMenubar",
"Quick repair ('{}' for Live repair)"),
2235 content_width = 450;
2238 special_text_centering_weight = 0.7f;
2247 float distance = 0.0f;
2261 special_text_b =
fmt::format(
"{:.1f} {}", distance,
_LC(
"DirectionArrow",
"meter"));
2262 content_width = ImGui::CalcTextSize(special_text.c_str()).x + ImGui::CalcTextSize(special_text_b.c_str()).x;
2265 special_text_c =
fmt::format(
"{:02d}.{:02d}.{:02d}", (
int)(time) / 60, (
int)(time) % 60, (
int)(time * 100.0) % 100);
2267 special_color_c = (time_diff > 0.0f)
2274 special_text_d =
fmt::format(
"{:02d}.{:02d}.{:02d}", (
int)(best_time) / 60, (
int)(best_time) % 60, (
int)(best_time * 100.0) % 100);
2280 special_text =
fmt::format(
_LC(
"TopMenubar",
"Terrain editing mode, press {} to save and exit"),
2282 content_width = ImGui::CalcTextSize(special_text.c_str()).x;
2286 if (!special_text.empty())
2289 box_pos.y = top_offset;
2290 box_pos.x = (ImGui::GetIO().DisplaySize.x / 2) - ((content_width / 2) + ImGui::GetStyle().FramePadding.x);
2291 ImGui::SetNextWindowPos(box_pos);
2292 ImGui::SetNextWindowSize(ImVec2(0.f, 0.f));
2293 ImGui::SetNextWindowContentWidth(content_width);
2294 ImGuiWindowFlags flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
2295 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse;
2296 ImGui::PushStyleColor(ImGuiCol_WindowBg,
App::GetGuiManager()->GetTheme().semitransparent_window_bg);
2297 if (ImGui::Begin(special_text.c_str(),
nullptr, flags))
2302 float text_w = ImGui::CalcTextSize(special_text.c_str()).x;
2303 ImGui::SetCursorPosX(((content_width / 2) - (text_w / 2)) * special_text_centering_weight);
2305 ImGui::TextColored(special_color,
"%s", special_text.c_str());
2315 float pbar_width = content_width - (ImGui::GetStyle().ItemSpacing.x + ImGui::CalcTextSize(special_text.c_str()).x);
2316 ImGui::ProgressBar(fraction, ImVec2(pbar_width, ImGui::GetTextLineHeight()), pbar_text.
ToCStr());
2324 int min = (int)time_sec / 60;
2325 str_pos = snprintf(str, 200,
"%dmin ", min);
2326 time_sec -= (float)min * 60.f;
2328 snprintf(str+str_pos, 200-str_pos,
"%.2fsec", time_sec);
2329 ImGui::TextDisabled(
"%s: %s",
_LC(
"TopMenubar",
"Time"), str);
2335 ImGui::Text(special_text_b.c_str());
2336 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2) - (ImGui::CalcTextSize(special_text_c.c_str()).x / 2));
2337 ImGui::TextColored(special_color_c,
"%s", special_text_c.c_str());
2340 text <<
"Best Time: " << special_text_d.c_str();
2341 ImGui::SetCursorPosX((ImGui::GetWindowSize().
x / 2) - (ImGui::CalcTextSize(text).
x / 2));
2343 if (!special_text_d.empty())
2345 ImGui::TextDisabled(text);
2352 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.f, 0.f));
2356 ImGui::ProgressBar(fraction, ImVec2(15.f, ImGui::GetTextLineHeight() / 2.f),
"");
2360 ImGui::PopStyleVar();
2362 const ImVec2 MINI_SPACING = ImVec2(2.f,0.f);
2363 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, MINI_SPACING);
2367 const float INDENT = 15.f;
2369 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Movement"));
2371 ImGui::SetColumnWidth(0, INDENT);
2372 ImGui::NextColumn();
2375 ImGui::NextColumn();
2378 ImGui::NextColumn();
2383 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Rotation"));
2385 ImGui::SetColumnWidth(0, INDENT);
2386 ImGui::NextColumn();
2391 ImGui::TextDisabled(
"%s:",
_LC(
"LiveRepair",
"Modifiers"));
2393 ImGui::SetColumnWidth(0, INDENT);
2394 ImGui::SetColumnWidth(1, 125);
2395 ImGui::SetColumnWidth(2, 125);
2396 ImGui::NextColumn();
2403 ImGui::TextDisabled(
"%s (%s):",
_LC(
"LiveRepair",
"Reset mode"),
ToLocalizedString(resetmode).c_str());
2404 ImGui::Dummy(ImVec2(INDENT, 1.f));
2408 ImGui::PopStyleVar();
2410 const ImVec2 PAD = ImVec2(5, 5);
2418 ImGui::PopStyleColor(1);
2431 rapidjson::Document j_doc;
2442 if (!j_doc.IsArray())
2444 LOG(
fmt::format(
"[RoR|Terrain] AI presets file '{}' declared in '{}' has wrong format - the root element is not an array!",
2450 for (
const rapidjson::Value& j_bundled_preset: j_doc.GetArray())
2463 #if defined(USE_CURL)
2465 std::thread(std::move(task)).detach();
2467 #endif // defined(USE_CURL)
2480 rapidjson::Value preset_copy(bundled_preset,
ai_presets_all.GetAllocator());
2486 rapidjson::Value preset_copy(extern_preset,
ai_presets_all.GetAllocator());
2592 std::string protectchk_text =
_LC(
"Tuning",
"Protected");
2593 float protectchk_w = ImGui::CalcTextSize(protectchk_text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2;
2594 float protectchk_cursorx = (ImGui::GetWindowContentRegionWidth() - protectchk_w) - 20.f;
2597 ImGui::SetCursorPosX(protectchk_cursorx);
2600 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
2601 bool chk_pressed = ImGui::Checkbox(protectchk_text.c_str(), &protectchk_value);
2602 ImGui::PopStyleVar(1);
2617 request->
mpr_type = (protectchk_value) ? request_type_set : request_type_reset;
2626 ImGui::GetWindowDrawList()->AddRect(
2627 ImGui::GetCursorScreenPos(),
2628 ImGui::GetCursorScreenPos() + ImGui::CalcTextSize(
"00") + ImGui::GetStyle().FramePadding*2,
2629 ImColor(ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]),
2630 ImGui::GetStyle().FrameRounding);
2631 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().FramePadding.x);
2632 ImGui::Text(
"%02d", subject_id);
2634 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().FramePadding.x);
2643 bool isEnabled = !is_unwanted && !is_force_removed;
2644 if (is_force_removed)
2646 ImGui::PushStyleColor(ImGuiCol_Border,
ORANGE_TEXT);
2647 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
2649 bool chkPressed = ImGui::Checkbox(name.c_str(), &isEnabled);
2650 bool resetPressed =
false;
2651 if (is_force_removed)
2655 resetPressed = ImGui::SmallButton(
_LC(
"Tuning",
"Reset"));
2656 ImGui::PopStyleColor();
2657 ImGui::PopStyleVar();
2658 ImGui::PopStyleColor();
2662 if (chkPressed && !isEnabled)
2677 else if ((chkPressed && isEnabled) || resetPressed)
2680 req->
mpr_type = request_type_reset;