diff --git a/TLM/TLM/Lifecycle/TMPELifecycle.cs b/TLM/TLM/Lifecycle/TMPELifecycle.cs
index d016808fd..62e368593 100644
--- a/TLM/TLM/Lifecycle/TMPELifecycle.cs
+++ b/TLM/TLM/Lifecycle/TMPELifecycle.cs
@@ -172,8 +172,7 @@ internal void RegisterCustomManagers() {
RegisteredManagers.Add(ExtVehicleManager.Instance);
// Texture managers
- RegisteredManagers.Add(UI.Textures.RoadSignThemes.Instance);
- RegisteredManagers.Add(UI.Textures.JunctionRestrictions.Instance);
+ RegisteredManagers.Add(UI.Textures.RoadSignThemeManager.Instance);
RegisteredManagers.Add(UI.Textures.RoadUI.Instance);
RegisteredManagers.Add(UI.Textures.TrafficLightTextures.Instance);
diff --git a/TLM/TLM/Manager/Impl/OptionsManager.cs b/TLM/TLM/Manager/Impl/OptionsManager.cs
index 87e07d63e..4b6425282 100644
--- a/TLM/TLM/Manager/Impl/OptionsManager.cs
+++ b/TLM/TLM/Manager/Impl/OptionsManager.cs
@@ -330,7 +330,6 @@ internal static void RebuildMenu(bool languageChanged = false) {
}
if (languageChanged) {
- RoadUI.Instance.ReloadTexturesWithTranslation();
TrafficLightTextures.Instance.ReloadTexturesWithTranslation();
TMPELifecycle.Instance.TranslationDatabase.ReloadTutorialTranslations();
TMPELifecycle.Instance.TranslationDatabase.ReloadGuideTranslations();
diff --git a/TLM/TLM/Resources/JunctionRestrictions/crossing_allowed.png b/TLM/TLM/Resources/JunctionRestrictions/crossing_allowed.png
deleted file mode 100644
index 20709caea..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/crossing_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/crossing_forbidden.png b/TLM/TLM/Resources/JunctionRestrictions/crossing_forbidden.png
deleted file mode 100644
index e14500840..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/crossing_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/enterblocked_allowed.png b/TLM/TLM/Resources/JunctionRestrictions/enterblocked_allowed.png
deleted file mode 100644
index 99c0ec2ff..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/enterblocked_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/enterblocked_forbidden.png b/TLM/TLM/Resources/JunctionRestrictions/enterblocked_forbidden.png
deleted file mode 100644
index c5de78508..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/enterblocked_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/lanechange_allowed.png b/TLM/TLM/Resources/JunctionRestrictions/lanechange_allowed.png
deleted file mode 100644
index 4c18b0757..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/lanechange_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/lanechange_forbidden.png b/TLM/TLM/Resources/JunctionRestrictions/lanechange_forbidden.png
deleted file mode 100644
index 7e39dab40..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/lanechange_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/left_on_red_allowed.png b/TLM/TLM/Resources/JunctionRestrictions/left_on_red_allowed.png
deleted file mode 100644
index 689e452d5..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/left_on_red_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/left_on_red_forbidden.png b/TLM/TLM/Resources/JunctionRestrictions/left_on_red_forbidden.png
deleted file mode 100644
index 9d2e8e3ce..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/left_on_red_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/right_on_red_allowed.png b/TLM/TLM/Resources/JunctionRestrictions/right_on_red_allowed.png
deleted file mode 100644
index 58f35fa41..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/right_on_red_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/right_on_red_forbidden.png b/TLM/TLM/Resources/JunctionRestrictions/right_on_red_forbidden.png
deleted file mode 100644
index 700242fbe..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/right_on_red_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/uturn_allowed.png b/TLM/TLM/Resources/JunctionRestrictions/uturn_allowed.png
deleted file mode 100644
index 5c9b0a86f..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/uturn_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/JunctionRestrictions/uturn_forbidden.png b/TLM/TLM/Resources/JunctionRestrictions/uturn_forbidden.png
deleted file mode 100644
index d40349dac..000000000
Binary files a/TLM/TLM/Resources/JunctionRestrictions/uturn_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/RoadUI/parking_allowed.png b/TLM/TLM/Resources/RoadUI/parking_allowed.png
deleted file mode 100644
index 89dce008c..000000000
Binary files a/TLM/TLM/Resources/RoadUI/parking_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/RoadUI/parking_disallowed.png b/TLM/TLM/Resources/RoadUI/parking_disallowed.png
deleted file mode 100644
index ad3ec3051..000000000
Binary files a/TLM/TLM/Resources/RoadUI/parking_disallowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/RoadUI/sign_none.png b/TLM/TLM/Resources/RoadUI/sign_none.png
deleted file mode 100644
index 21ad93736..000000000
Binary files a/TLM/TLM/Resources/RoadUI/sign_none.png and /dev/null differ
diff --git a/TLM/TLM/Resources/RoadUI/sign_priority.png b/TLM/TLM/Resources/RoadUI/sign_priority.png
deleted file mode 100644
index 57befbfd1..000000000
Binary files a/TLM/TLM/Resources/RoadUI/sign_priority.png and /dev/null differ
diff --git a/TLM/TLM/Resources/RoadUI/sign_stop.png b/TLM/TLM/Resources/RoadUI/sign_stop.png
deleted file mode 100644
index 8b67c35be..000000000
Binary files a/TLM/TLM/Resources/RoadUI/sign_stop.png and /dev/null differ
diff --git a/TLM/TLM/Resources/RoadUI/sign_stop_zh.png b/TLM/TLM/Resources/RoadUI/sign_stop_zh.png
deleted file mode 100644
index d223dbd39..000000000
Binary files a/TLM/TLM/Resources/RoadUI/sign_stop_zh.png and /dev/null differ
diff --git a/TLM/TLM/Resources/RoadUI/sign_yield.png b/TLM/TLM/Resources/RoadUI/sign_yield.png
deleted file mode 100644
index f5f4960de..000000000
Binary files a/TLM/TLM/Resources/RoadUI/sign_yield.png and /dev/null differ
diff --git a/TLM/TLM/Resources/RoadUI/sign_yield_zh.png b/TLM/TLM/Resources/RoadUI/sign_yield_zh.png
deleted file mode 100644
index 7f6ef7e35..000000000
Binary files a/TLM/TLM/Resources/RoadUI/sign_yield_zh.png and /dev/null differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-Bus.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Bus.png
new file mode 100644
index 000000000..d1ab962b9
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Bus.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-CargoTrain.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-CargoTrain.png
new file mode 100644
index 000000000..8b9bd11d5
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-CargoTrain.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-Emergency.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Emergency.png
new file mode 100644
index 000000000..e8c3f04bc
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Emergency.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-EnterBlocked.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-EnterBlocked.png
new file mode 100644
index 000000000..0da02945b
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-EnterBlocked.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-LaneChange.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-LaneChange.png
new file mode 100644
index 000000000..f63217577
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-LaneChange.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-LeftOnRed.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-LeftOnRed.png
new file mode 100644
index 000000000..a467cca1a
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-LeftOnRed.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-PassengerTrain.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-PassengerTrain.png
new file mode 100644
index 000000000..df483d997
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-PassengerTrain.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-PedestrianCrossing.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-PedestrianCrossing.png
new file mode 100644
index 000000000..e6c4fa3a5
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-PedestrianCrossing.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-PersonalCar.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-PersonalCar.png
new file mode 100644
index 000000000..0bff55027
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-PersonalCar.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-RightOnRed.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-RightOnRed.png
new file mode 100644
index 000000000..3ceb1db34
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-RightOnRed.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-Service.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Service.png
new file mode 100644
index 000000000..2ddfdb665
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Service.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-Taxi.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Taxi.png
new file mode 100644
index 000000000..74ea063e0
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Taxi.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-Truck.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Truck.png
new file mode 100644
index 000000000..c2ecc4db9
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-Truck.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Allow-UTurn.png b/TLM/TLM/Resources/SignThemes/Fallback/Allow-UTurn.png
new file mode 100644
index 000000000..2c6b3ef18
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Allow-UTurn.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Fallback.svg b/TLM/TLM/Resources/SignThemes/Fallback/Fallback.svg
new file mode 100644
index 000000000..f81466c9a
--- /dev/null
+++ b/TLM/TLM/Resources/SignThemes/Fallback/Fallback.svg
@@ -0,0 +1,5082 @@
+
+
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/NoParking.png b/TLM/TLM/Resources/SignThemes/Fallback/NoParking.png
new file mode 100644
index 000000000..6ea9bdb4a
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/NoParking.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Parking.png b/TLM/TLM/Resources/SignThemes/Fallback/Parking.png
new file mode 100644
index 000000000..bd53febaf
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Parking.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/PriorityNone.png b/TLM/TLM/Resources/SignThemes/Fallback/PriorityNone.png
new file mode 100644
index 000000000..ab44a91db
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/PriorityNone.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/PriorityRightOfWay.png b/TLM/TLM/Resources/SignThemes/Fallback/PriorityRightOfWay.png
new file mode 100644
index 000000000..59550b83c
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/PriorityRightOfWay.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/PriorityStop.png b/TLM/TLM/Resources/SignThemes/Fallback/PriorityStop.png
new file mode 100644
index 000000000..4937305d9
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/PriorityStop.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/PriorityYield.png b/TLM/TLM/Resources/SignThemes/Fallback/PriorityYield.png
new file mode 100644
index 000000000..cb4f19ea2
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/PriorityYield.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/README.md b/TLM/TLM/Resources/SignThemes/Fallback/README.md
new file mode 100644
index 000000000..666d40724
--- /dev/null
+++ b/TLM/TLM/Resources/SignThemes/Fallback/README.md
@@ -0,0 +1,8 @@
+Fallback Road Signs Theme
+=========================
+
+This is an implicitly loaded road signs theme which is used as last resort when
+finding road signs.
+
+NOTE: Speed limit road signs do not query Fallback theme, it is assumed that
+any current theme would provide all necessary numbered road signs.
\ No newline at end of file
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Bus.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Bus.png
new file mode 100644
index 000000000..84b10e736
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Bus.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-CargoTrain.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-CargoTrain.png
new file mode 100644
index 000000000..827f11bf2
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-CargoTrain.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Emergency.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Emergency.png
new file mode 100644
index 000000000..5a0083e68
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Emergency.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-EnterBlocked.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-EnterBlocked.png
new file mode 100644
index 000000000..02e002c46
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-EnterBlocked.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-LaneChange.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-LaneChange.png
new file mode 100644
index 000000000..7352db33c
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-LaneChange.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-LeftOnRed.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-LeftOnRed.png
new file mode 100644
index 000000000..c05f5a1c9
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-LeftOnRed.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PassengerTrain.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PassengerTrain.png
new file mode 100644
index 000000000..66acfcef9
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PassengerTrain.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PedestrianCrossing.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PedestrianCrossing.png
new file mode 100644
index 000000000..a8d9de503
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PedestrianCrossing.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PersonalCar.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PersonalCar.png
new file mode 100644
index 000000000..cc3c57112
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-PersonalCar.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-RightOnRed.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-RightOnRed.png
new file mode 100644
index 000000000..c592cbade
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-RightOnRed.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Service.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Service.png
new file mode 100644
index 000000000..d644b50f2
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Service.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Taxi.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Taxi.png
new file mode 100644
index 000000000..f39bace38
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Taxi.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Truck.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Truck.png
new file mode 100644
index 000000000..77351f2db
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-Truck.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Fallback/Restrict-UTurn.png b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-UTurn.png
new file mode 100644
index 000000000..e8496c15a
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Fallback/Restrict-UTurn.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Brazil/Stop.png b/TLM/TLM/Resources/SignThemes/Kmph_Brazil/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Brazil/Stop.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Brazil/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Brazil/Yield.png b/TLM/TLM/Resources/SignThemes/Kmph_Brazil/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Brazil/Yield.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Brazil/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Canada/Stop.png b/TLM/TLM/Resources/SignThemes/Kmph_Canada/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Canada/Stop.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Canada/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Canada/Yield.png b/TLM/TLM/Resources/SignThemes/Kmph_Canada/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Canada/Yield.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Canada/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/0.png b/TLM/TLM/Resources/SignThemes/Kmph_China/0.png
new file mode 100644
index 000000000..520749a6d
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/0.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/10.png b/TLM/TLM/Resources/SignThemes/Kmph_China/10.png
new file mode 100644
index 000000000..f6f4c0186
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/10.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/100.png b/TLM/TLM/Resources/SignThemes/Kmph_China/100.png
new file mode 100644
index 000000000..0472a7baa
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/100.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/105.png b/TLM/TLM/Resources/SignThemes/Kmph_China/105.png
new file mode 100644
index 000000000..653306c45
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/105.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/110.png b/TLM/TLM/Resources/SignThemes/Kmph_China/110.png
new file mode 100644
index 000000000..042fa392c
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/110.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/115.png b/TLM/TLM/Resources/SignThemes/Kmph_China/115.png
new file mode 100644
index 000000000..68d08d092
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/115.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/120.png b/TLM/TLM/Resources/SignThemes/Kmph_China/120.png
new file mode 100644
index 000000000..ce6ac9000
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/120.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/125.png b/TLM/TLM/Resources/SignThemes/Kmph_China/125.png
new file mode 100644
index 000000000..0a7e05233
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/125.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/130.png b/TLM/TLM/Resources/SignThemes/Kmph_China/130.png
new file mode 100644
index 000000000..542bc512d
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/130.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/135.png b/TLM/TLM/Resources/SignThemes/Kmph_China/135.png
new file mode 100644
index 000000000..2a07f456b
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/135.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/140.png b/TLM/TLM/Resources/SignThemes/Kmph_China/140.png
new file mode 100644
index 000000000..07dc7333a
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/140.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/15.png b/TLM/TLM/Resources/SignThemes/Kmph_China/15.png
new file mode 100644
index 000000000..59ad38acf
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/15.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/20.png b/TLM/TLM/Resources/SignThemes/Kmph_China/20.png
new file mode 100644
index 000000000..67a4bc311
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/20.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/25.png b/TLM/TLM/Resources/SignThemes/Kmph_China/25.png
new file mode 100644
index 000000000..390063fd3
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/25.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/30.png b/TLM/TLM/Resources/SignThemes/Kmph_China/30.png
new file mode 100644
index 000000000..1a00e4e74
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/30.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/35.png b/TLM/TLM/Resources/SignThemes/Kmph_China/35.png
new file mode 100644
index 000000000..ab57b1f7d
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/35.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/40.png b/TLM/TLM/Resources/SignThemes/Kmph_China/40.png
new file mode 100644
index 000000000..a1504a33f
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/40.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/45.png b/TLM/TLM/Resources/SignThemes/Kmph_China/45.png
new file mode 100644
index 000000000..07158ba02
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/45.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/5.png b/TLM/TLM/Resources/SignThemes/Kmph_China/5.png
new file mode 100644
index 000000000..ebe5737e4
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/5.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/50.png b/TLM/TLM/Resources/SignThemes/Kmph_China/50.png
new file mode 100644
index 000000000..76a6a1393
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/50.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/55.png b/TLM/TLM/Resources/SignThemes/Kmph_China/55.png
new file mode 100644
index 000000000..def75145c
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/55.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/60.png b/TLM/TLM/Resources/SignThemes/Kmph_China/60.png
new file mode 100644
index 000000000..0abc25ec1
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/60.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/65.png b/TLM/TLM/Resources/SignThemes/Kmph_China/65.png
new file mode 100644
index 000000000..213aea34d
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/65.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/70.png b/TLM/TLM/Resources/SignThemes/Kmph_China/70.png
new file mode 100644
index 000000000..2935088a5
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/70.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/75.png b/TLM/TLM/Resources/SignThemes/Kmph_China/75.png
new file mode 100644
index 000000000..ad4fc0d59
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/75.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/80.png b/TLM/TLM/Resources/SignThemes/Kmph_China/80.png
new file mode 100644
index 000000000..358ac01d5
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/80.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/85.png b/TLM/TLM/Resources/SignThemes/Kmph_China/85.png
new file mode 100644
index 000000000..9bccac58e
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/85.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/90.png b/TLM/TLM/Resources/SignThemes/Kmph_China/90.png
new file mode 100644
index 000000000..f0193eae7
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/90.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/95.png b/TLM/TLM/Resources/SignThemes/Kmph_China/95.png
new file mode 100644
index 000000000..dc991719a
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/95.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Bus.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Bus.png
new file mode 100644
index 000000000..2cee62561
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Bus.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-CargoTrain.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-CargoTrain.png
new file mode 100644
index 000000000..4c3d44b4d
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-CargoTrain.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Emergency.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Emergency.png
new file mode 100644
index 000000000..c028cbb47
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Emergency.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-PassengerTrain.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-PassengerTrain.png
new file mode 100644
index 000000000..33af535e3
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-PassengerTrain.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-PersonalCar.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-PersonalCar.png
new file mode 100644
index 000000000..95eb1f7f7
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-PersonalCar.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Service.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Service.png
new file mode 100644
index 000000000..8ca6ac00f
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Service.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Taxi.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Taxi.png
new file mode 100644
index 000000000..eb717c7ba
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Taxi.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Truck.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Truck.png
new file mode 100644
index 000000000..92b68b061
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Allow-Truck.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/China.svg b/TLM/TLM/Resources/SignThemes/Kmph_China/China.svg
new file mode 100644
index 000000000..45686bff2
--- /dev/null
+++ b/TLM/TLM/Resources/SignThemes/Kmph_China/China.svg
@@ -0,0 +1,2939 @@
+
+
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/NoParking.png b/TLM/TLM/Resources/SignThemes/Kmph_China/NoParking.png
new file mode 100644
index 000000000..9d9d16502
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/NoParking.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Parking.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Parking.png
new file mode 100644
index 000000000..702799d77
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Parking.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/PriorityStop.png b/TLM/TLM/Resources/SignThemes/Kmph_China/PriorityStop.png
new file mode 100644
index 000000000..4c042f450
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/PriorityStop.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/PriorityYield.png b/TLM/TLM/Resources/SignThemes/Kmph_China/PriorityYield.png
new file mode 100644
index 000000000..e8a5458f5
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/PriorityYield.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Bus.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Bus.png
new file mode 100644
index 000000000..5a92652f8
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Bus.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-CargoTrain.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-CargoTrain.png
new file mode 100644
index 000000000..c22504bae
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-CargoTrain.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Emergency.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Emergency.png
new file mode 100644
index 000000000..ba0133a01
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Emergency.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-PassengerTrain.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-PassengerTrain.png
new file mode 100644
index 000000000..c4fbd5853
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-PassengerTrain.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-PersonalCar.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-PersonalCar.png
new file mode 100644
index 000000000..0b45eee82
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-PersonalCar.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Service.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Service.png
new file mode 100644
index 000000000..d74d06ebe
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Service.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Taxi.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Taxi.png
new file mode 100644
index 000000000..96c8c5308
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Taxi.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Truck.png b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Truck.png
new file mode 100644
index 000000000..6e94ed71a
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China/Restrict-Truck.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Allow-Emergency.png b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Allow-Emergency.png
new file mode 100644
index 000000000..dee7d0a00
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Allow-Emergency.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Allow-Taxi.png b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Allow-Taxi.png
new file mode 100644
index 000000000..16788ec99
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Allow-Taxi.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/PriorityYield.png b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/PriorityYield.png
new file mode 100644
index 000000000..ca60fb3dc
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/PriorityYield.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/README.md b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/README.md
new file mode 100644
index 000000000..066cfb97c
--- /dev/null
+++ b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/README.md
@@ -0,0 +1,7 @@
+Generic Chinese theme
+=====================
+
+Based on Mainland China theme and only replaces signs with text to have no text
+in them. Keeping the Stop 停 sign as it is fine in all/most Chinese dialects.
+
+Source file is located in Kmph_China/China.svg
\ No newline at end of file
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Restrict-Emergency.png b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Restrict-Emergency.png
new file mode 100644
index 000000000..7bfc69f0b
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Restrict-Emergency.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Restrict-Taxi.png b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Restrict-Taxi.png
new file mode 100644
index 000000000..5127c499b
Binary files /dev/null and b/TLM/TLM/Resources/SignThemes/Kmph_China_Generic/Restrict-Taxi.png differ
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_France/RightOfWay.png b/TLM/TLM/Resources/SignThemes/Kmph_France/PriorityRightOfWay.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_France/RightOfWay.png
rename to TLM/TLM/Resources/SignThemes/Kmph_France/PriorityRightOfWay.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_France/Stop.png b/TLM/TLM/Resources/SignThemes/Kmph_France/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_France/Stop.png
rename to TLM/TLM/Resources/SignThemes/Kmph_France/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_France/Yield.png b/TLM/TLM/Resources/SignThemes/Kmph_France/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_France/Yield.png
rename to TLM/TLM/Resources/SignThemes/Kmph_France/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Germany/RightOfWay.png b/TLM/TLM/Resources/SignThemes/Kmph_Germany/PriorityRightOfWay.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Germany/RightOfWay.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Germany/PriorityRightOfWay.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Germany/Stop.png b/TLM/TLM/Resources/SignThemes/Kmph_Germany/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Germany/Stop.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Germany/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Germany/Yield.png b/TLM/TLM/Resources/SignThemes/Kmph_Germany/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Germany/Yield.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Germany/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Indonesia/RightOfWay.png b/TLM/TLM/Resources/SignThemes/Kmph_Indonesia/PriorityRightOfWay.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Indonesia/RightOfWay.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Indonesia/PriorityRightOfWay.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Indonesia/Stop.png b/TLM/TLM/Resources/SignThemes/Kmph_Indonesia/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Indonesia/Stop.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Indonesia/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Indonesia/Yield.png b/TLM/TLM/Resources/SignThemes/Kmph_Indonesia/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Indonesia/Yield.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Indonesia/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Japan/Stop.png b/TLM/TLM/Resources/SignThemes/Kmph_Japan/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Japan/Stop.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Japan/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Japan/YIeld.png b/TLM/TLM/Resources/SignThemes/Kmph_Japan/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Japan/YIeld.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Japan/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_SouthKorea/Stop.png b/TLM/TLM/Resources/SignThemes/Kmph_SouthKorea/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_SouthKorea/Stop.png
rename to TLM/TLM/Resources/SignThemes/Kmph_SouthKorea/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_SouthKorea/Yield.png b/TLM/TLM/Resources/SignThemes/Kmph_SouthKorea/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_SouthKorea/Yield.png
rename to TLM/TLM/Resources/SignThemes/Kmph_SouthKorea/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Sweden/RightOfWay.png b/TLM/TLM/Resources/SignThemes/Kmph_Sweden/PriorityRightOfWay.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Sweden/RightOfWay.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Sweden/PriorityRightOfWay.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Sweden/Stop.png b/TLM/TLM/Resources/SignThemes/Kmph_Sweden/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Sweden/Stop.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Sweden/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/Kmph_Sweden/Yield.png b/TLM/TLM/Resources/SignThemes/Kmph_Sweden/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/Kmph_Sweden/Yield.png
rename to TLM/TLM/Resources/SignThemes/Kmph_Sweden/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/MPH_UK/Stop.png b/TLM/TLM/Resources/SignThemes/MPH_UK/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/MPH_UK/Stop.png
rename to TLM/TLM/Resources/SignThemes/MPH_UK/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/MPH_UK/Yield.png b/TLM/TLM/Resources/SignThemes/MPH_UK/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/MPH_UK/Yield.png
rename to TLM/TLM/Resources/SignThemes/MPH_UK/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/MPH_US/Stop.png b/TLM/TLM/Resources/SignThemes/MPH_US/PriorityStop.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/MPH_US/Stop.png
rename to TLM/TLM/Resources/SignThemes/MPH_US/PriorityStop.png
diff --git a/TLM/TLM/Resources/SignThemes/MPH_US/Yield.png b/TLM/TLM/Resources/SignThemes/MPH_US/PriorityYield.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/MPH_US/Yield.png
rename to TLM/TLM/Resources/SignThemes/MPH_US/PriorityYield.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/0.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/0.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/0.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/0.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/10.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/10.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/10.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/10.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/100.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/100.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/100.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/100.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/105.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/105.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/105.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/105.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/110.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/110.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/110.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/110.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/115.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/115.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/115.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/115.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/120.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/120.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/120.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/120.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/125.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/125.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/125.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/125.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/130.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/130.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/130.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/130.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/135.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/135.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/135.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/135.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/140.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/140.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/140.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/140.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/15.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/15.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/15.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/15.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/20.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/20.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/20.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/20.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/25.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/25.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/25.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/25.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/30.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/30.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/30.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/30.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/35.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/35.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/35.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/35.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/40.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/40.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/40.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/40.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/45.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/45.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/45.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/45.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/5.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/5.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/5.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/5.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/50.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/50.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/50.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/50.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/55.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/55.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/55.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/55.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/60.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/60.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/60.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/60.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/65.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/65.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/65.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/65.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/70.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/70.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/70.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/70.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/75.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/75.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/75.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/75.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/80.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/80.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/80.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/80.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/85.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/85.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/85.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/85.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/90.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/90.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/90.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/90.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/95.png b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/95.png
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/95.png
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/95.png
diff --git a/TLM/TLM/Resources/SignThemes/RoadDefaults/roadsigns-default.svg b/TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/roadsigns-default.svg
similarity index 100%
rename from TLM/TLM/Resources/SignThemes/RoadDefaults/roadsigns-default.svg
rename to TLM/TLM/Resources/SignThemes/SpeedLimitDefaults/roadsigns-default.svg
diff --git a/TLM/TLM/Resources/Translations/Options.csv b/TLM/TLM/Resources/Translations/Options.csv
index 07f071a0d..04caae7a5 100644
--- a/TLM/TLM/Resources/Translations/Options.csv
+++ b/TLM/TLM/Resources/Translations/Options.csv
@@ -154,11 +154,11 @@ Opsi ini hanya sekadar menambah realisme kepada game."
"VR.Option:No double crossings","Keine doppelten Übergänge","Remove widest crossing on transitions between two types of road","En una transición de segmento a segmento, solo los segmentos más pequeños muestran cruce peatonal","Dans une transition d'un segment à un autre, seul le plus petit segment aura un passage piéton","A szegmensek közötti átmenetnél csak a kisebb szegmens kap gyalogátkelőt.","Nessun doppio attraversamento","セグメント間の横断歩道が二重になるのを防止し、狭い道路側のみにする","구간이 바뀔 때 더 작은 구간에서만 교차로가 생성됩니다.","Geen dubbele kruisingen","Przejście dla pieszych tylko na węższym segmencie przy łączeniu segmentów różnej szerokości","Sem cruzamentos duplos","Без двойных пешеходных переходов","禁用雙重行人穿越道","禁用双方向人行横道","Remove widest crossing on transitions between two types of road","Çift kesişim olamaz","Заборонити подвійні пішохідні переходи","","Dvojité priechody pre chodcov nie sú možné","ไม่มีการข้ามสองครั้ง","","","ﺕﺎﻌﻃﺎﻘﺗ ﻰﻠﻋ ﻂﻘﻓ ﺮﻐﺻﻷﺍ ﺀﺰﺠﻟﺍ ﻞﺼﺤﻳ ، ﺀﺰﺟ ﻰﻟﺇ ﺀﺰﺟ ﻦﻣ ﻝﺎﻘﺘﻧﻻﺍ ﻲﻓ","Pada transisi ruas-ke-ruas, hanya ruas yang lebih kecil yang mendapatkan penyeberangan."
"VR.Option:Dedicated turning lanes","Dedizierte Abbiegespuren","Dedicated turning lanes","Carriles dedicados para girar","Voies dédiées pour tourner","Dedikált kanyarodósávok","Corsie di svolta dedicate","専用の右左折レーン","회전 전용 차선","Toegewijde lijn om terug te draaien","Dedykowane pasy do skrętu","","Выделенные полосы для поворота","專用轉向車道","专用转弯车道","Dedicated turning lanes","Dönüş şeritleri ayrılır","Виділені смуги для руху в різних напрямках","","Vyhradené odbočovacie pruhy","เลนเลี้ยวเฉพาะ","","","ةصصخملا ةراودلا تارمملا","Lajur belok khusus"
"General.Checkbox:Use UnifiedUI","UnifiedUI verwenden","Use UnifiedUI","Utilizar UnifiedUI","Utiliser 'UnifiedUI'","","Usa UnifiedUI","UnifiedUIを使用","UnifiedUI 사용","Gebruik UnifiedUI","Użyj UnifiedUI","","Использовать UnifiedUI","將主選單圖示加入 UnifiedUI 選單","使用 UnifiedUI","Use UnifiedUI","UnifiedUI kullan","Розмістити кнопку TM:PE в панелі UnifiedUI","","Použi UnifiedUI","ใช้ UnifiedUI","","","استخدام واجهة مستخدم موحدة","Gunakan UnifiedUI"
-"Keybind.SpeedLimits:Decrease selected speed","Ausgewählte Geschwindigkeit verringern","Decrease selected speed","Reducir la velocidad seleccionada","Diminuer la vitesse sélectionnée","","Riduci la velocità selezionata","選択した速度を下げる","선택한 속도 제한 감소","Verlaag geselecteerde snelheid","Zmniejsz wybraną prędkość","","Уменьшить выбранную скорость","收緊速限","降低目标车速","Decrease selected speed","","Зменшити обрану швидкість","","Znížiť zvolenú rýchlosť","","","","ﺓﺩﺪﺤﻤﻟﺍ ﺔﻋﺮﺴﻟﺍ ﺾﻔﺧ ","Kurangkan kecepatan"
-"Keybind.SpeedLimits:Increase selected speed","Ausgewählte Geschwindigkeit erhöhen","Increase selected speed","Aumentar la velocidad seleccionada","Augmenter la vitesse sélectionnée","","Aumenta la velocità selezionata","選択した速度を上げる","선택한 속도 제한 증가","Verhoog geselecteerde snelheid","Zwiększ wybraną prędkość","","Увеличить выбранную скорость","提高速限","提高目标车速","Increase selected speed","","Збільшити обрану швидкість","","Zvýšiť zvolenú rýchlosť","","","","ﺓﺩﺪﺤﻤﻟﺍ ﺔﻋﺮﺴﻟﺍ ﺓﺩﺎﻳﺯ","Tingkatkan kecepatan"
-"KeybindCategory:SpeedLimits","Geschwindigkeitsbegrenzungen","Speed Limits","Límites de velocidad","Limites de Vitesse","","Limiti di velocità","制限速度","속도 제한","Snelheidslimieten","Limity prędkości","","Ограничения скорости","速限","限速","Speed Limits","","Обмеження швидкості","","Rýchlostné obmedzenia","จำกัดความเร็ว","","","",""
-"General.Group:Localisation","Lokalisierung","Localization","Localización","Localisation","","General.Group:Localizzazione","言語設定","언어 설정","Lokalisatie","Lokalizacja","","Локализация","語言翻譯","本地化","Localisation","","","","Lokalizácia","ภาษาที่รองรับ","","","ﻊﻗﻮﻤﻟﺍ",""
-"General.Group:Interface","Interface","Interface","Interfaz","Interface","","General.Group:Interfaccia","インターフェース","인터페이스","Bediening","Interfejs","","Интерфейс","介面","接口","Interface","","","","Rozhranie","อินเตอร์เฟซ","","","ﻡﺪﺨﺘﺴﻤﻟﺍ ﻪﻬﺟﺍﻭ",""
-"General.Group:Compatibility","Kompatibilität","Compatibility","Compatibilidad","Compatibilités","","General.Group:Compatibilità","互換性","호환성","Compatibiliteit","Zgodność","","Совместимость","相容性","兼容性","Compatibility","","","","Kompatibilita","ความเข้ากันได้","","","ﻖﻓﺍﻮﺘﻟﺍ",""
-"General.Button:Help us translate on Crowdin","Hilf uns bei der Übersetzung auf Crowdin","Help us translate on Crowdin","Ayúdanos a traducir en Crowdin","Aidez-nous à traduire sur Crowdin","","Aiutaci a tradurre su Crowdin","Crowdinで翻訳を手伝ってください","Crowdin에서 번역을 도와주세요","Help ons vertalen op Crowdin","Pomóż w tłumaczeniu na Crowdin","","Помогите нам с переводом на Crowdin","提供翻譯協助","在 Crowdin 上帮助我们翻译","Help us translate on Crowdin","","","","Pomôžte s prekladom na Crowdin","ช่วยเราแปลใน Crowdin","","","",""
-"General.Button:View localisation guide","Übersetzungsleitfaden anzeigen","View localization guide","Ver guía de localización","Voir le guide des Localités","","Visualizza la guida alla localizzazione","ローカライズのガイドを表示","현지화 도움말 보기","Bekijk de lokalisatie handleiding","Zobacz przewodnik lokalizacji","","Руководство по локализации","關於多國語言翻譯","查看本地化指南","View localisation guide","","","","Zobraziť sprievodcu s lokalizáciou","ดูคู่มือการแปลเป็นภาษาท้องถิ่น","","","",""
+"Keybind.SpeedLimits:Decrease selected speed","Ausgewählte Geschwindigkeit verringern","Decrease selected speed","Reducir la velocidad seleccionada","Diminuer la vitesse sélectionnée","","Riduci la velocità selezionata","選択した速度を下げる","선택한 속도 제한 감소","Verlaag geselecteerde snelheid","Zmniejsz wybraną prędkość","","Уменьшить выбранную скорость","收緊速限","降低目标车速","Decrease selected speed","","Зменшити обрану швидкість","","Znížiť zvolenú rýchlosť","ลดขีดจำกัดความเร็ว","","","ﺓﺩﺪﺤﻤﻟﺍ ﺔﻋﺮﺴﻟﺍ ﺾﻔﺧ ","Kurangkan kecepatan"
+"Keybind.SpeedLimits:Increase selected speed","Ausgewählte Geschwindigkeit erhöhen","Increase selected speed","Aumentar la velocidad seleccionada","Augmenter la vitesse sélectionnée","","Aumenta la velocità selezionata","選択した速度を上げる","선택한 속도 제한 증가","Verhoog geselecteerde snelheid","Zwiększ wybraną prędkość","","Увеличить выбранную скорость","提高速限","提高目标车速","Increase selected speed","","Збільшити обрану швидкість","","Zvýšiť zvolenú rýchlosť","เพิ่มขีดจำกัดความเร็ว","","","ﺓﺩﺪﺤﻤﻟﺍ ﺔﻋﺮﺴﻟﺍ ﺓﺩﺎﻳﺯ","Tingkatkan kecepatan"
+"KeybindCategory:SpeedLimits","Geschwindigkeitsbegrenzungen","Speed Limits","Límites de velocidad","Limites de Vitesse","","Limiti di velocità","制限速度","속도 제한","Snelheidslimieten","Limity prędkości","","Ограничения скорости","速限","限速","Speed Limits","","Обмеження швидкості","","Rýchlostné obmedzenia","จำกัดความเร็ว","","","","Batas Kecepatan"
+"General.Group:Localisation","Lokalisierung","Localization","Localización","Localisation","","General.Group:Localizzazione","言語設定","언어 설정","Lokalisatie","Lokalizacja","","Локализация","語言翻譯","本地化","Localisation","","Локалізація","","Lokalizácia","ภาษาที่รองรับ","","","ﻊﻗﻮﻤﻟﺍ","Bahasa dan Lokalisasi"
+"General.Group:Interface","Interface","Interface","Interfaz","Interface","","General.Group:Interfaccia","インターフェース","인터페이스","Bediening","Interfejs","","Интерфейс","介面","接口","Interface","","Інтерфейс","","Rozhranie","อินเตอร์เฟซ","","","ﻡﺪﺨﺘﺴﻤﻟﺍ ﻪﻬﺟﺍﻭ","Tampilan"
+"General.Group:Compatibility","Kompatibilität","Compatibility","Compatibilidad","Compatibilités","","General.Group:Compatibilità","互換性","호환성","Compatibiliteit","Zgodność","","Совместимость","相容性","兼容性","Compatibility","","Сумісність","","Kompatibilita","ความเข้ากันได้","","","ﻖﻓﺍﻮﺘﻟﺍ","Kompatibilitas"
+"General.Button:Help us translate on Crowdin","Hilf uns bei der Übersetzung auf Crowdin","Help us translate on Crowdin","Ayúdanos a traducir en Crowdin","Aidez-nous à traduire sur Crowdin","","Aiutaci a tradurre su Crowdin","Crowdinで翻訳を手伝ってください","Crowdin에서 번역을 도와주세요","Help ons vertalen op Crowdin","Pomóż w tłumaczeniu na Crowdin","","Помогите нам с переводом на Crowdin","提供翻譯協助","在 Crowdin 上帮助我们翻译","Help us translate on Crowdin","","Допоможіть нам з перекладом на Crowdin","","Pomôžte s prekladom na Crowdin","ช่วยเราแปลใน Crowdin","","","","Bantu kami menerjemah di Crowdin"
+"General.Button:View localisation guide","Übersetzungsleitfaden anzeigen","View localization guide","Ver guía de localización","Voir le guide des Localités","","Visualizza la guida alla localizzazione","ローカライズのガイドを表示","현지화 도움말 보기","Bekijk de lokalisatie handleiding","Zobacz przewodnik lokalizacji","","Руководство по локализации","關於多國語言翻譯","查看本地化指南","View localisation guide","","Інструкції з локалізації","","Zobraziť sprievodcu s lokalizáciou","ดูคู่มือการแปลเป็นภาษาท้องถิ่น","","","","Lihat petunjuk lokalisasi"
diff --git a/TLM/TLM/Resources/Translations/SpeedLimits.csv b/TLM/TLM/Resources/Translations/SpeedLimits.csv
index 62fe3c1d8..4edb7876a 100644
--- a/TLM/TLM/Resources/Translations/SpeedLimits.csv
+++ b/TLM/TLM/Resources/Translations/SpeedLimits.csv
@@ -15,30 +15,32 @@
"Checkbox:Show lane-wise speed limits","Zeige spurweise Geschwindigkeitsbeschränkungen","Show lane-wise speed limits","Mostrar límite de velocidad en el carril","Afficher les limites de vitesse par voie","Mutassa meg a sáv szerinti sebességkorlátozásokat","Mostra i limiti di velocità per ogni corsia","車線毎の制限速度を表示する","차선별 속도 제한 표시","Toon rijstrookspecifieke snelheidslimieten","Pokaż limity prędkości dla pasów","Mostrar limites de velocidade por faixa.","Показывать ограничения по каждой полосе","顯示車道速限","显示各车道道路限速设置","Show lane-wise speed limits","Şerite göre azami hızları göster","Показувати обмеження в кожній смузі","Zobrazit limit rychlosti pro jízdní pruhy","Zobraziť obmedzenia rýchlostí pre jazdné pruhy","แสดงขีดจํากัดความเร็วที่ชาญฉลาดของเลน","","","ﺓﺭﺎﺤﻟﺍ ﺐﺴﺣ ﺔﻋﺮﺴﻟﺍ ﺩﻭﺪﺣ ﺽﺮﻋ","Perlihatkan batas kecepatan per lajur"
"Checkbox:Apply to entire road","Auf die gesamte Straße anwenden","Apply to entire road","Aplicar a toda la calle","Appliquer à toute la route","Alkalmazás a teljes útra","Applica a tutta la strada","道路全体に適用","도로 전체에 적용","Pas op het gehele weg toe","Zastosuj dla całej drogi","Aplica a toda a rua","Применить к целой дороге","套用到整個路段","应用至两个路口之间所有路段","Apply to entire road","Tüm yola uygula","Застосувати до всієї вулиці","Nastavit pro celou silnici","Použiť na celú cestu","ใช้กับถนนทั้งหมด","","","ﻖﻳﺮﻄﻟﺍ ﻞﻣﺎﻛ ﻰﻠﻋ ﻖﻴﺒﻄﺗ","Terapkan dari ujung ke ujung"
"Button:Default","Standard","Default","Predeterminado","Bouton : Défault","Alapbeállítás","Impostazione predefinita","デフォルト","기본값","Standaard","Domyślne","Padrão","По умолчанию","預設值","默认","Default","Varsayılan","По замовчанню","Výchozí","Predvolené","ค่าเริ่มต้น","","","ﻲﺿﺍﺮﺘﻓﻻﺍ","Standar"
-"Editing speed limit overrides for segments","Geschwindigkeitsbegrenzung für Segmente bearbeiten","Editing speed limit overrides for segments","","Modifier la limite de vitesse pour les segments","","Modificando le sovrascrizioni del limite di velocità per i segmenti","セグメントの制限速度を上書きする","구간 내 재구성한 제한 속도 편집 중","Bijwerken overschrijvingen van maximum snelheid voor segmenten","Edycja ograniczeń prędkości dla segmentów","","Редактирование ограничений для участков дороги","設定路段速限","覆盖当前区段限速","Editing speed limit overrides for segments","","Редагування обмежень для ділянок шляху","","","","","","ﺕﺎﻌﻃﺎﻘﺘﻠﻟ ﺔﻋﺮﺴﻟﺍ ﺩﻭﺪﺣ ﺮﻳﺮﺤﺗ",""
-"Editing default limits per road type","Bearbeite Standardlimits pro Straßentyp","Editing default limits per road type","Editando los límites según el tipo de carretera predeterminados","Modifier les limites par défaut par type de route","","Modificando i limiti predefiniti per tipo di strada","道路タイプごとのデフォルトの制限を編集する","도로 유형에 따른 기본 제한 속도 편집 중","Bijwerken standaard maxima per wegsoort","Edycja domyślnych ograniczeń prędkości dla wybranego rodzaju drogi","","Редактирование ограничений для всех дорог одного вида","設定各道路類型的預設速限","按道路类别设设置默认限速","Editing default limits per road type","","Редагування обмежень для типу дороги","","","","","","ﻖﻳﺮﻄﻟﺍ ﻉﻮﻧ ﺐﺴﺣ ﺔﻴﺿﺍﺮﺘﻓﻻﺍ ﺩﻭﺪﺤﻟﺍ ﻞﻳﺪﻌﺗ",""
-"Editing lane speed limit overrides","Geschwindigkeitsbegrenzung für Fahrspuren bearbeiten","Editing lane speed limit overrides","","Modification de la limite de vitesse des voies","","Modificando le sovrascrizioni del limite di velocità della corsia","車線速度制限のオーバーライドを編集する","차선 내 재구성한 제한 속도 편집 중","Bijwerken overschrijvingen van maximum snelheid per rijbaan","Edycja ograniczeń prędkości dla pasa","","Редактирование ограничений для полос движения","設定車道速限","覆盖车道限速","Editing lane speed limit overrides","","Редагування обмежень для смуги руху","","","","","","ﺕﺍﺭﺎﺤﻠﻟ ﺔﻋﺮﺴﻟﺍ ﺩﻭﺪﺣ ﺕﺍﺯﻭﺎﺠﺗ ﺮﻳﺮﺤﺗ",""
-"Tooltip:Default speed limits per road type","Standard Geschwindigkeitsbegrenzungen pro Straßentyp","Default speed limits per road type","Límites de velocidad predeterminados por tipo de carretera","Limites de vitesse par défaut par type de route","","Limiti di velocità predefiniti per tipo di strada","道路タイプごとのデフォルト制限速度","도로 유형에 따른 기본 제한 속도","Standaard maximum snelheid per wegsoort","Domyślne ograniczenia prędkości dla typu drogi","","Ограничения скорости по умолчанию для дорог этого типа","各道路類型的預設速限","每类道路的默认限速","Default speed limits per road type","","Обмеження для доріг одного типу","","","","","","ﻖﻳﺮﻄﻟﺍ ﻉﻮﻧ ﺐﺴﺣ ﺔﻴﺿﺍﺮﺘﻓﻻﺍ ﺩﻭﺪﺤﻟﺍ ﻞﻳﺪﻌﺗ",""
-"Tooltip:Edit segment speed limits","Bearbeiten der Geschwindigkeitsbegrenzung je Segment","Edit segment speed limits","Editar límites de velocidad del segmento","Modifier les limites de vitesse du segment","","Modifica limiti di velocità del segmento","セグメントの制限速度を編集","구간 내 속도 제한 편집","Bewerk maximum snelheid per segment","Edytuj ograniczenia prędkości dla segmentu","","Редактирование ограничения для участка дороги","設定路段速限","编辑区段限速","Edit segment speed limits","","Обмеження швидкості для ділянок шляху","","","","","","ﻊﻃﺎﻘﺘﻟﺍ ﺔﻋﺮﺳ ﺩﻭﺪﺣ ﺮﻳﺮﺤﺗ",""
-"Tooltip:Edit lane speed limits","Bearbeiten der Geschwindigkeitsbegrenzung je Fahrspur","Edit lane speed limits","Editar límites de velocidad del carril","Modifier la limite de vitesse de la voie","","Modifica limiti di velocità della corsia","レーンの制限速度を編集","차선 내 속도 제한 편집","Bewerk maximum snelheid per rijbaan","Edytuj ograniczenia prędkości pasa","","Редактирование ограничения по полосам движения","設定車道速限","编辑车道限速","Edit lane speed limits","","Обмеження швидкості для смуг руху","","","","","","ﻩﺭﺎﺤﻟﺍ ﺔﻋﺮﺳ ﺩﻭﺪﺣ ﺮﻳﺮﺤﺗ",""
-"Window.Title:Speed Limits","Geschwindigkeitsbegrenzung","Speed Limits","Límites de velocidad","Limites de vitesse","","Limiti di Velocità","制限速度","속도 제한","Maximum Snelheid","Ograniczenia prędkości","","Ограничения скорости","道路速度限制","行车速度限制","Speed Limits","","Обмеження швидкості","","Rýchlostné obmedzenia","จำกัดความเร็ว","","","ﺔﻋﺮﺴﻟﺍ ﺩﻭﺪﺣ",""
-"SpeedLimits.OSD:Select","Auswählen","Click road signs to set speed limit override","","Cliquez sur un panneau de vitesse pour assigner","","Seleziona","選択","도로의 표지판을 클릭하여 속도 제한 재구성","Selecteer","Kliknij na znak ograniczenia aby zmodyfikować limit","","Нажимайте на знаки, чтобы установить ограничения","點按號誌以設定速限","选择","Click road signs to set speed limit override","","Виберіть швидкість з палітри та задайте її для дороги","","","","","","ﺩﺪﺣ",""
-"UI.Key:Shift edit multiple","Gedrückt halten um mehrere Segmente zu ändern","Edit multiple segments between junctions","","Modifier tout le tronçon entre les jonctions","","Modifica multiplo","キーで複数を編集","[[Shift]]를 누른 채로 여러 항목 수정","Ingedrukt houden om meerdere segmenten tussen kruisingen te bewerken","Przytrzymaj, aby zmodyfikować wszystkie pomiędzy skrzyżowaniami","","Изменить несколько участков дороги в ряд","一併設定整個路口的路段","批量编辑","Edit multiple segments between junctions","","Змінити кілька ділянок підряд між перехрестями","","","","","","ﺩﺪﻌﺘﻣ ﺮﻳﺮﺤﺗ",""
-"UI.Key:Alt show overrides","Gedrückt halten um die Geschwindigkeitsbegrenzungen anzuzeigen","Hold to show overrides temporarily","","Maintenir Alt pour afficher les vitesses modifiées","","Mostra sovrascrizioni","キーでオーバーライドを表示","[[Alt]]를 누른 채로 있으면 재구성한 항목 표시","Ingedrukt houden om overschrijvingen te tonen","Przytrzymaj, aby pokazać zmodyfikowane ograniczenia","","Временно показать ограничения скорости","顯示特別速限","显示超速","Hold to show overrides temporarily","","Тимчасово показати задані гравцем обмеження швидкості","","","","","","ﺕﺍﺯﻭﺎﺠﺘﻟﺍ ﺽﺮﻋ",""
-"UI.Key:Alt show defaults","Gedrückt halten um die voreingestellten Geschwindigkeitsbegrenzungen anzuzeigen","Hold to show defaults for this road type","","Maintenir Alt pour afficher les vitesses par défaut","","Mostra predefiniti","キーでデフォルトを表示","[[Alt]]를 누른 채로 있으면 기본값이 적용된 항목 표시","Ingedrukt houden om standaardwaarden te tonen","Przytrzymaj, aby pokazać domyślne limity","","Временно показать скорость для всех дорог этого типа","顯示道路類型的預設速限","显示默认速度","Hold to show defaults for this road type","","Тимчасово показати швидкість для доріг цього типу","","","","","","ﺕﺎﺿﺍﺮﺘﻓﻻﺍ ﺭﺎﻬﻇﺇ",""
-"Palette.Text:Default","Auf Standard zurücksetzen","Reset to default","","Rétablir les valeurs par défaut","","Predefinito","デフォルト","기본값으로 초기화","Terugzetten naar standaardwaarden","Przywróć domyślną","","Сбросить","還原預設值","默认","Reset to default","","Скинути","","Predvolená","ค่าเริ่มต้น","","","ﻲﺿﺍﺮﺘﻓﻻﺍ",""
-"Palette.Text:Unlimited","Ohne Begrenzung","Unlimited","","Illimité","","Illimitato","無制限","무제한","Onbeperkt","Nieograniczona","","Без ограничения","無限制","无限制","Unlimited","","Без обмеження","","Neobmedzená","ไม่จำกัด","","","ﺩﻭﺪﺤﻣ ﺮﻴﻏ",""
-"UI.Key:PageUp/PageDown switch underground","[[Bild hoch]] / [[Bild runter]] um die unterirdische Ansicht umzuschalten","[[Page Up]] | [[Page Down]] To switch underground view","","[[Page Up]] | [[Page Down]] pour basculer vers la vue sous-terraine","","[[PageUp]] | [[PageDown]] interruttore sotterraneo","[[PageUp]] / [[PageDown]]で地下表示の切り替え","[[Page Up]] / [[Page Down]] 키를 눌러 지하 보기로 전환","[[Page Up]] | [[Page Down]] Schakel van/ naar ondergrondse weergave","[[Page Up]] / [[Page Down]] Aby przełączyć do widoku podziemnego","","[[Page Up]] | [[Page Down]] переключить вид дорог под землёй","[[PageUp]]/[[PageDown]] 切換地上/地下","[[PageUp]]/[[PageDown]] 切换地面/切换地下","[[Page Up]] | [[Page Down]] To switch underground view","","[[Page Up]] / [[Page Down]] Показати підземні шляхи","","","","","","ﺽﺭﻷﺍ ﺖﺤﺗ PageDown ﺡﺎﺘﻔﻣ",""
-"General.Dropdown:Road signs theme","Thema für Beschilderung","Road signs theme for speed limits","","Thème pour la Signalisation","","Tema segnali stradali","道路標識のテーマ","속도 제한 표지용 도로 표지판 테마","Stijl van de verkeersborden voor snelheid","Motyw znaków drogowych dla ograniczeń prędkości","","Выбранная тема дорожных знаков","速限路標風格","路标风格","Road signs theme for speed limits","","Обрана тема для дорожніх знаків","","","","","","ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ",""
-"RoadSignTheme:Kmph_Germany","Deutschland [km/h und MPH]","Germany [km/h]","","Allemagne [km/h et MPH]","","Germania [km/h e MPH]","ドイツの道路標識","독일식 (km/h & mph)","Duitsland [km/h en MPH]","Niemcy (km/h i mph)","","Германия (км/ч)","德式 (公里/小時 + 英哩/小時)","德国-km/h&mph","Germany [km/h]","","Германія (км/год)","","","","","","ﻞﻴﻤﻟﺍ ﻭﺍ ﻮﻠﻴﻜﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ",""
-"RoadSignTheme:MPH_UK","Vereinigtes Königreich (MPH)","United Kingdom [MPH]","","Royaume Uni [MPH]","","UK [MPH]","イギリスの道路標識","영국식 (mph만)","Verenigd Koninkrijk [MPH]","Zjednoczone Królestwo (tylko mph)","","Великобритания (мили/ч)","英式 (英哩/小時)","英国-MPH","United Kingdom [MPH]","","Велика Британія (милі/год)","","","","","","ﻂﻘﻓ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ UK",""
-"RoadSignTheme:MPH_US","Amerikanisch (MPH)","United States [MPH]","","États Unis [MPH]","","US [MPH]","アメリカの道路標識","미국식 (mph만)","Verenigde Staten [MPH]","Stany Zjednoczone (tylko mph)","","США (мили/ч)","美式 (英哩/小時)","美国-MPH","United States [MPH]","","Сполучені Штати (милі/год)","","","","","","ﻂﻘﻓ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ US",""
-"RoadSignTheme:Kmph_Canada","Kanadisch [nur km/h]","Canada [km/h]","","Canada [km/h]","","Canada [km/h]","カナダの道路標識","캐나다식 (km/h만)","Canada [km/h]","Kanada (tylko km/h)","","Канада (км/ч)","加拿大 (公里/小時)","加拿大-km/h","Canada [km/h]","","Канада (км/год)","","","","","","ﻂﻘﻓ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ CN",""
-"UI.Key:Unlimited; Default; Select","[[/]] | [[\]] Unbegrenzt; [[Entf]] | [[Zurück]] Standard; [[Alt+0]]..[[Alt+9]] Auswahl","[[Slash]] | [[Backslash]] Unlimited; [[Delete]] | [[Backspace]] Default; [[Alt+0]]..[[Alt+9]] Select","","[[Slash]] | [[Backslash]] Illimité; [[Delete]] | [[Backspace]] Par défaut; [[Alt+0]]..[[Alt+9]] Sélection","","[[/]] | [[\]] Illimitato; [[Delete]] | [[Backspace]] Predefinito; [[Alt+0]]..[[Alt+9]] Seleziona","[[Slash]] | [[Backslash]]無制限; [[Delete]] | [[Backspace]] デフォルト; [[Alt+0]]..[[Alt+9]] 選択","[[/]] | [[\]] 무제한; [[Delete]] | [[Backspace]] 기본값; [[Alt+0]]..[[Alt+9]] 속도 선택","[[Slash]] | [[Backslash]] Onbeperkt; [[Delete]] | [[Backspace]] Standaard; [[Alt+0]]..[[Alt+9]] Selecteer","[[/]] | [[\]] Nieograniczona; [[Delete]] | [[Backspace]] Domyślna; [[Alt+0]]..[[Alt+9]] Wybierz prędkość","","[[/]] | [[\]] Без ограничений; [[Delete]] | [[Backspace]] По умолчанию; [[Alt+0]]..[[Alt+9]] Выбрать скорость","[[Slash]] | [[Backslash]] 無限; [[Delete]] | [[Backspace]] 預設; [[Alt+0]]..[[Alt+9]] 設定","[[/]] | [[\]] 无限制; [[Delete]] | [[Backspace]] 默认; [[Alt+0]]...[[Alt+9]] 选择","[[Slash]] | [[Backslash]] Unlimited; [[Delete]] | [[Backspace]] Default; [[Alt+0]]..[[Alt+9]] Select","","[[/]] | [[\]] Без обмежень; [[Delete]] | [[Backspace]] Скинути як було; [[Alt+0]]..[[Alt+9]] Обрати швидкість","","[[/]] | [[\]] Neobmedzená; [[Delete]] | [[Backspace]] Predvolená; [[Alt+0]]..[[Alt+9]] Zvolená","","","","ﺓﺩﻭﺪﺤﻤﻟﺍ ﺮﻴﻏ ﺔﻴﺿﺍﺮﺘﻓﻻﺍ ﺔﻋﺮﺴﻟﺍ ﺪﻳﺪﺤﺘﻟ",""
-"UI.Key:Ctrl temporarily toggle between lanes and segments","Temporär zwischen Spuren und Segmenten umschalten","Temporarily toggle between lanes and segments","","Basculer temporairement entre Segments et Voies","","Attiva/disattiva temporaneamente tra corsie e segmenti","Ctrlキーでレーンとセグメントを一時的に切り替え","일시적으로 차선/구간 전환","Tijdelijk schakelen tussen rijbanen en segmenten","Przełącz między widokiem pasów ruchu, a segmentami","","Переключиться между сегментами и полосами движения","按下切換選擇車道/路段","临时切换车道/路段","Temporarily toggle between lanes and segments","","Перемикання між сегментами та смугами руху","","","","","","ﺕﺍﺭﺎﺤﻟﺍﻭ ﺕﺎﻃﺎﻘﺘﻟﺍ ﻦﻴﺑ ﻞﻳﺪﺒﺘﻠﻟ Ctrl ﺡﺎﺘﻔﻣ",""
-"RoadSignTheme:Kmph_Sweden","Schweden [km/h]","Sweden [km/h]","","Suède [km/h]","","Svezia [km/h]","スウェーデンの道路標識","스웨덴식 (km/h)","Zweden [km/h]","Szwecja (km/h)","","Швеция (км/ч)","瑞典 (公里/小時)","瑞典-Kmph","Sweden [km/h]","","Швеція (км/год)","","","","","","ﺪﻳﻮﺴﻟﺍ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ",""
-"RoadSignTheme:Kmph_Brazil","Brasilien [km/h]","Brazil [km/h]","","Brésil [km/h]","","Brasile [km/h]","ブラジルの道路標識","브라질식 (km/h)","Brazilië [km/h]","Brazylia (km/h)","","Бразилия (км/ч)","巴西 (公里/小時)","巴西-Kmph","Brazil [km/h]","","Бразилія (км/год)","","","","","","ﻞﻳﺯﺍﺮﺒﻟﺍ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ",""
-"RoadSignTheme:Kmph_France","Frankreich [km/h]","France [km/h]","","France [km/h]","","Francia [km/h]","フランスの道路標識","프랑스식 (km/h)","Frankrijk [km/h]","Francja (km/h)","","Франция (км/ч)","法式 (公里/小時)","法国-Kmph","France [km/h]","","Франція (км/год)","","","","","","ﺎﺴﻧﺮﻓ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ",""
-"RoadSignTheme:Kmph_Indonesia","Indonesien [km/h]","Indonesia [km/h]","","Indonésie [km/h]","","Indonesia [km/h]","インドネシアの道路標識","인도네시아식 (km/h)","Indonesië [km/h]","Indonezja (km/h)","","Индонезия (км/ч)","印尼 (公里/小時)","印尼-Kmph","Indonesia [km/h]","","Індонезія (км/год)","","","","","","ﺎﺴﺒﻧﻭﺪﻧﺍ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ",""
-"RoadSignTheme:Kmph_Japan","Japan [km/h]","Japan [km/h]","","Japon [km/h]","","Giappone [km/h]","日本の道路標識","일본식 (km/h)","Japan [km/h]","Japonia (km/h)","","Япония (км/ч)","日式 (公里/小時)","日本-Kmph","Japan [km/h]","","Японія (км/год)","","","","","","ﻥﺎﺑﺎﻴﻟﺍ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ",""
-"RoadSignTheme:Kmph_SouthKorea","Südkorea [km/h]","South Korea [km/h]","","Corée du Sud [km/h]","","SudCorea [km/h]","韓国の道路標識","한국식 (km/h)","Zuid Korea [km/h]","Korea Południowa (km/h)","","Южная Корея (км/ч)","南韓 (公里/小時)","韩国-Kmph","South Korea [km/h]","","Південна Корея (км/год)","","","","","","ﺝ ﺎﻳﺭﻮﻛ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ",""
+"Editing speed limit overrides for segments","Geschwindigkeitsbegrenzung für Segmente bearbeiten","Editing speed limit overrides for segments","Editar el límite de velocidad por segmentos","Modifier la limite de vitesse pour les segments","","Modificando le sovrascrizioni del limite di velocità per i segmenti","セグメントの制限速度を上書きする","구간 내 재구성한 제한 속도 편집 중","Bijwerken overschrijvingen van maximum snelheid voor segmenten","Edycja ograniczeń prędkości dla segmentów","Editar o limite de velocidade sobrescreve os seguimentos","Редактирование ограничений для участков дороги","設定路段速限","覆盖当前区段限速","Editing speed limit overrides for segments","","Редагування обмежень для ділянок шляху","","","แก้ไขการแทนที่ขีดจำกัดความเร็วสำหรับ segments","","","ﺕﺎﻌﻃﺎﻘﺘﻠﻟ ﺔﻋﺮﺴﻟﺍ ﺩﻭﺪﺣ ﺮﻳﺮﺤﺗ","Mengubah batas kecepatan untuk bagian jalan"
+"Editing default limits per road type","Bearbeite Standardlimits pro Straßentyp","Editing default limits per road type","Editando los límites según el tipo de carretera predeterminados","Modifier les limites par défaut par type de route","","Modificando i limiti predefiniti per tipo di strada","道路タイプごとのデフォルトの制限を編集する","도로 유형에 따른 기본 제한 속도 편집 중","Bijwerken standaard maxima per wegsoort","Edycja domyślnych ograniczeń prędkości dla wybranego rodzaju drogi","Editar os limites padrões por tipo de rodovia","Редактирование ограничений для всех дорог одного вида","設定各道路類型的預設速限","按道路类别设设置默认限速","Editing default limits per road type","","Редагування обмежень для типу дороги","","","แก้ไขขีดจำกัดความเร็วพื้นฐานตามประเภทถนน","","","ﻖﻳﺮﻄﻟﺍ ﻉﻮﻧ ﺐﺴﺣ ﺔﻴﺿﺍﺮﺘﻓﻻﺍ ﺩﻭﺪﺤﻟﺍ ﻞﻳﺪﻌﺗ","Mengubah batas standar beredasarkan jenis jalan"
+"Editing lane speed limit overrides","Geschwindigkeitsbegrenzung für Fahrspuren bearbeiten","Editing lane speed limit overrides","Editar el límite de velocidad por carriles","Modification de la limite de vitesse des voies","","Modificando le sovrascrizioni del limite di velocità della corsia","車線速度制限のオーバーライドを編集する","차선 내 재구성한 제한 속도 편집 중","Bijwerken overschrijvingen van maximum snelheid per rijbaan","Edycja ograniczeń prędkości dla pasa","Edição limites de velocidade de faixas sobscreve","Редактирование ограничений для полос движения","設定車道速限","覆盖车道限速","Editing lane speed limit overrides","","Редагування обмежень для смуги руху","","","แก้ไขการแทนที่ขีดจำกัดความเร็วของช่องจราจร","","","ﺕﺍﺭﺎﺤﻠﻟ ﺔﻋﺮﺴﻟﺍ ﺩﻭﺪﺣ ﺕﺍﺯﻭﺎﺠﺗ ﺮﻳﺮﺤﺗ","Mengubah batas kecepatan lajur"
+"Tooltip:Default speed limits per road type","Standard Geschwindigkeitsbegrenzungen pro Straßentyp","Default speed limits per road type","Límites de velocidad predeterminados por tipo de carretera","Limites de vitesse par défaut par type de route","","Limiti di velocità predefiniti per tipo di strada","道路タイプごとのデフォルト制限速度","도로 유형에 따른 기본 제한 속도","Standaard maximum snelheid per wegsoort","Domyślne ograniczenia prędkości dla typu drogi","Tooltip: Limites de velocidade padrão por tipo de rodovias","Ограничения скорости по умолчанию для дорог этого типа","各道路類型的預設速限","每类道路的默认限速","Default speed limits per road type","","Обмеження для доріг одного типу","","","ขีดจำกัดความเร็วพื้นฐานตามประเภทถนน","","","ﻖﻳﺮﻄﻟﺍ ﻉﻮﻧ ﺐﺴﺣ ﺔﻴﺿﺍﺮﺘﻓﻻﺍ ﺩﻭﺪﺤﻟﺍ ﻞﻳﺪﻌﺗ","Batas standar berdasarkan jenis jalan"
+"Tooltip:Edit segment speed limits","Bearbeiten der Geschwindigkeitsbegrenzung je Segment","Edit segment speed limits","Editar límites de velocidad del segmento","Modifier les limites de vitesse du segment","","Modifica limiti di velocità del segmento","セグメントの制限速度を編集","구간 내 속도 제한 편집","Bewerk maximum snelheid per segment","Edytuj ograniczenia prędkości dla segmentu","Dica: Editar limites de velocidade do seguimento","Редактирование ограничения для участка дороги","設定路段速限","编辑区段限速","Edit segment speed limits","","Обмеження швидкості для ділянок шляху","","","แก้ไขขีดจำกัดความเร็วของ segments","","","ﻊﻃﺎﻘﺘﻟﺍ ﺔﻋﺮﺳ ﺩﻭﺪﺣ ﺮﻳﺮﺤﺗ","Mengubah batas kecepatan bagian jalan"
+"Tooltip:Edit lane speed limits","Bearbeiten der Geschwindigkeitsbegrenzung je Fahrspur","Edit lane speed limits","Editar límites de velocidad del carril","Modifier la limite de vitesse de la voie","","Modifica limiti di velocità della corsia","レーンの制限速度を編集","차선 내 속도 제한 편집","Bewerk maximum snelheid per rijbaan","Edytuj ograniczenia prędkości pasa","Dica: Editar limites de velocidade da faixa","Редактирование ограничения по полосам движения","設定車道速限","编辑车道限速","Edit lane speed limits","","Обмеження швидкості для смуг руху","","","แก้ไขขีดจำกัดความเร็วของช่องจราจร","","","ﻩﺭﺎﺤﻟﺍ ﺔﻋﺮﺳ ﺩﻭﺪﺣ ﺮﻳﺮﺤﺗ","Mengubah batas kecepatan lajur"
+"Window.Title:Speed Limits","Geschwindigkeitsbegrenzung","Speed Limits","Límites de velocidad","Limites de vitesse","","Limiti di Velocità","制限速度","속도 제한","Maximum Snelheid","Ograniczenia prędkości","Window.Title:Limites de Velocidade","Ограничения скорости","道路速度限制","行车速度限制","Speed Limits","","Обмеження швидкості","","Rýchlostné obmedzenia","จำกัดความเร็ว","","","ﺔﻋﺮﺴﻟﺍ ﺩﻭﺪﺣ","Batas Kecepatan"
+"SpeedLimits.OSD:Select","Auswählen","Click road signs to set speed limit override","Haga clic en las señales de tráfico para modificar el límite de velocidad","Cliquez sur un panneau de vitesse pour assigner","","Seleziona","選択","도로의 표지판을 클릭하여 속도 제한 재구성","Selecteer","Kliknij na znak ograniczenia aby zmodyfikować limit","SpeedLimits.OSD:Selecionar","Нажимайте на знаки, чтобы установить ограничения","點按號誌以設定速限","选择","Click road signs to set speed limit override","","Виберіть швидкість з палітри та задайте її для дороги","","","คลิกที่ป้ายถนนเพื่อตั้งขีดจำกัดความเร็ว","","","ﺩﺪﺣ","Klik pada rambu untuk menyetel batas kecepatan"
+"UI.Key:Shift edit multiple","Gedrückt halten um mehrere Segmente zu ändern","Edit multiple segments between junctions","Editar varios segmentos entre dos cruces","Modifier tout le tronçon entre les jonctions","","Modifica multiplo","キーで複数を編集","[[Shift]]를 누른 채로 여러 항목 수정","Ingedrukt houden om meerdere segmenten tussen kruisingen te bewerken","Przytrzymaj, aby zmodyfikować wszystkie pomiędzy skrzyżowaniami","UI.Key:Editar múltiplos","Изменить несколько участков дороги в ряд","一併設定整個路口的路段","批量编辑","Edit multiple segments between junctions","","Змінити кілька ділянок підряд між перехрестями","","","แก้ไขหลาย segment ระหว่างทางแยก","","","ﺩﺪﻌﺘﻣ ﺮﻳﺮﺤﺗ","Mengubah beberapa bagian jalan di antara persimpangan"
+"UI.Key:Alt show overrides","Gedrückt halten um die Geschwindigkeitsbegrenzungen anzuzeigen","Hold to show overrides temporarily","Mantenga presionado para mostrar temporalmente lo modificado","Maintenir Alt pour afficher les vitesses modifiées","","Mostra sovrascrizioni","キーでオーバーライドを表示","[[Alt]]를 누른 채로 있으면 재구성한 항목 표시","Ingedrukt houden om overschrijvingen te tonen","Przytrzymaj, aby pokazać zmodyfikowane ograniczenia","UI.Key:Alt mostrar sobrescrições","Временно показать ограничения скорости","顯示特別速限","显示超速","Hold to show overrides temporarily","","Тимчасово показати задані гравцем обмеження швидкості","","","กดค้างเพื่อแสดงการแทนที่ชั่วคราว","","","ﺕﺍﺯﻭﺎﺠﺘﻟﺍ ﺽﺮﻋ","Tekan dan tahan untuk menampilkan batas kecepatan sebentar"
+"UI.Key:Alt show defaults","Gedrückt halten um die voreingestellten Geschwindigkeitsbegrenzungen anzuzeigen","Hold to show defaults for this road type","Mantén pulsado para mostrar los valores por defecto para este tipo de carretera","Maintenir Alt pour afficher les vitesses par défaut","","Mostra predefiniti","キーでデフォルトを表示","[[Alt]]를 누른 채로 있으면 기본값이 적용된 항목 표시","Ingedrukt houden om standaardwaarden te tonen","Przytrzymaj, aby pokazać domyślne limity","UI.Key:Alt mostrar padrões","Временно показать скорость для всех дорог этого типа","顯示道路類型的預設速限","显示默认速度","Hold to show defaults for this road type","","Тимчасово показати швидкість для доріг цього типу","","","กดค้างเพื่อแสดงค่าพื้นฐานของถนนประเภทนี้","","","ﺕﺎﺿﺍﺮﺘﻓﻻﺍ ﺭﺎﻬﻇﺇ","Tekan dan tahan untuk menampilkan standar untuk jenis jalan ini"
+"Palette.Text:Default","Auf Standard zurücksetzen","Reset to default","Predeterminado","Rétablir les valeurs par défaut","","Predefinito","デフォルト","기본값으로 초기화","Terugzetten naar standaardwaarden","Przywróć domyślną","Pallete.Text:Padrão","Сбросить","還原預設值","默认","Reset to default","","Скинути","","Predvolená","ค่าเริ่มต้น","","","ﻲﺿﺍﺮﺘﻓﻻﺍ","Kembalikan ke standar"
+"Palette.Text:Unlimited","Ohne Begrenzung","Unlimited","Sin límite","Illimité","","Illimitato","無制限","무제한","Onbeperkt","Nieograniczona","Palette.Text:Ilimitado","Без ограничения","無限制","无限制","Unlimited","","Без обмеження","","Neobmedzená","ไม่จำกัด","","","ﺩﻭﺪﺤﻣ ﺮﻴﻏ","Tidak terbatas"
+"UI.Key:PageUp/PageDown switch underground","[[Bild hoch]] / [[Bild runter]] um die unterirdische Ansicht umzuschalten","[[Page Up]] | [[Page Down]] To switch underground view","[[Page Up]] | [[Page Down]] Para cambiar a vista subterránea","[[Page Up]] | [[Page Down]] pour basculer vers la vue sous-terraine","","[[PageUp]] | [[PageDown]] interruttore sotterraneo","[[PageUp]] / [[PageDown]]で地下表示の切り替え","[[Page Up]] / [[Page Down]] 키를 눌러 지하 보기로 전환","[[Page Up]] | [[Page Down]] Schakel van/ naar ondergrondse weergave","[[Page Up]] / [[Page Down]] Aby przełączyć do widoku podziemnego","UI.Key:PageUp/PageDown trocar underground","[[Page Up]] | [[Page Down]] переключить вид дорог под землёй","[[PageUp]]/[[PageDown]] 切換地上/地下","[[PageUp]]/[[PageDown]] 切换地面/切换地下","[[Page Up]] | [[Page Down]] To switch underground view","","[[Page Up]] / [[Page Down]] Показати підземні шляхи","","","[[Page Up]] | [[Page Down]] เพื่อสลับมุมมองใต้ดิน","","","ﺽﺭﻷﺍ ﺖﺤﺗ PageDown ﺡﺎﺘﻔﻣ","[[Page Up]] | [[Page Down]] untuk mengubah ke mode bawah tanah"
+"General.Dropdown:Road signs theme","Thema für Beschilderung","Road signs theme for speed limits","Estilo de señales de tráfico para límites de velocidad","Thème pour la Signalisation","","Tema segnali stradali","道路標識のテーマ","속도 제한 표지용 도로 표지판 테마","Stijl van de verkeersborden voor snelheid","Motyw znaków drogowych dla ograniczeń prędkości","General.Dropdown:Road temas de sinais","Выбранная тема дорожных знаков","速限路標風格","路标风格","Road signs theme for speed limits","","Обрана тема для дорожніх знаків","","","ชุดรูปแบบของป้ายจราจรจำกัดความเร็ว","","","ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ","Tampilan rambu jalan untuk batas kecepatan"
+"RoadSignTheme:Kmph_Germany","Deutschland [km/h und MPH]","Germany [km/h]","Alemania [km/h]","Allemagne [km/h et MPH]","","Germania [km/h e MPH]","ドイツの道路標識","독일식 (km/h & mph)","Duitsland [km/h en MPH]","Niemcy (km/h i mph)","RoadSignTheme:Kmph_Alemanha","Германия (км/ч)","德式 (公里/小時 + 英哩/小時)","德国-km/h&mph","Germany [km/h]","","Германія (км/год)","","","เยอรมัน [กม./ชม.]","","","ﻞﻴﻤﻟﺍ ﻭﺍ ﻮﻠﻴﻜﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ","Jerman [km/j]"
+"RoadSignTheme:MPH_UK","Vereinigtes Königreich (MPH)","United Kingdom [MPH]","Reino Unido [MPH]","Royaume Uni [MPH]","","UK [MPH]","イギリスの道路標識","영국식 (mph만)","Verenigd Koninkrijk [MPH]","Zjednoczone Królestwo (tylko mph)","","Великобритания (мили/ч)","英式 (英哩/小時)","英国-MPH","United Kingdom [MPH]","","Велика Британія (милі/год)","","","สหราชอาณาจักร [ไมล์/ชม.]","","","ﻂﻘﻓ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ UK","Britania Raya [MPJ]"
+"RoadSignTheme:MPH_US","Amerikanisch (MPH)","United States [MPH]","EE. UU. [MPH]","États Unis [MPH]","","US [MPH]","アメリカの道路標識","미국식 (mph만)","Verenigde Staten [MPH]","Stany Zjednoczone (tylko mph)","","США (мили/ч)","美式 (英哩/小時)","美国-MPH","United States [MPH]","","Сполучені Штати (милі/год)","","","สหรัฐอเมริกา [ไมล์/ชม.]","","","ﻂﻘﻓ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ US","Amerika Serikat [MPJ]"
+"RoadSignTheme:Kmph_Canada","Kanadisch [nur km/h]","Canada [km/h]","Canadá [km/h]","Canada [km/h]","","Canada [km/h]","カナダの道路標識","캐나다식 (km/h만)","Canada [km/h]","Kanada (tylko km/h)","","Канада (км/ч)","加拿大 (公里/小時)","加拿大-km/h","Canada [km/h]","","Канада (км/год)","","","แคนาดา [กม./ชม.]","","","ﻂﻘﻓ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ CN","Kanada [km/j]"
+"UI.Key:Unlimited; Default; Select","[[/]] | [[\]] Unbegrenzt; [[Entf]] | [[Zurück]] Standard; [[Alt+0]]..[[Alt+9]] Auswahl","[[Slash]] | [[Backslash]] Unlimited; [[Delete]] | [[Backspace]] Default; [[Alt+0]]..[[Alt+9]] Select","[[Slash]] | [[Backslash]] Sin límite; [[Delete]] | [[Backspace]] Por defecto; [[Alt+0]]..[[Alt+9]] Seleccionado","[[Slash]] | [[Backslash]] Illimité; [[Delete]] | [[Backspace]] Par défaut; [[Alt+0]]..[[Alt+9]] Sélection","","[[/]] | [[\]] Illimitato; [[Delete]] | [[Backspace]] Predefinito; [[Alt+0]]..[[Alt+9]] Seleziona","[[Slash]] | [[Backslash]]無制限; [[Delete]] | [[Backspace]] デフォルト; [[Alt+0]]..[[Alt+9]] 選択","[[/]] | [[\]] 무제한; [[Delete]] | [[Backspace]] 기본값; [[Alt+0]]..[[Alt+9]] 속도 선택","[[Slash]] | [[Backslash]] Onbeperkt; [[Delete]] | [[Backspace]] Standaard; [[Alt+0]]..[[Alt+9]] Selecteer","[[/]] | [[\]] Nieograniczona; [[Delete]] | [[Backspace]] Domyślna; [[Alt+0]]..[[Alt+9]] Wybierz prędkość","","[[/]] | [[\]] Без ограничений; [[Delete]] | [[Backspace]] По умолчанию; [[Alt+0]]..[[Alt+9]] Выбрать скорость","[[Slash]] | [[Backslash]] 無限; [[Delete]] | [[Backspace]] 預設; [[Alt+0]]..[[Alt+9]] 設定","[[/]] | [[\]] 无限制; [[Delete]] | [[Backspace]] 默认; [[Alt+0]]...[[Alt+9]] 选择","[[Slash]] | [[Backslash]] Unlimited; [[Delete]] | [[Backspace]] Default; [[Alt+0]]..[[Alt+9]] Select","","[[/]] | [[\]] Без обмежень; [[Delete]] | [[Backspace]] Скинути як було; [[Alt+0]]..[[Alt+9]] Обрати швидкість","","[[/]] | [[\]] Neobmedzená; [[Delete]] | [[Backspace]] Predvolená; [[Alt+0]]..[[Alt+9]] Zvolená","[[Slash]] | [[Backslash]] ไม่จำกัด; [[Delete]] | [[Backspace]] ค่าพื้นฐาน; [[Alt+0]]..[[Alt+9]] เลือก","","","ﺓﺩﻭﺪﺤﻤﻟﺍ ﺮﻴﻏ ﺔﻴﺿﺍﺮﺘﻓﻻﺍ ﺔﻋﺮﺴﻟﺍ ﺪﻳﺪﺤﺘﻟ","[[Slash]] | [[Backslash]] Tidak terbatas; [[Delete]] | [[Backspace]] Standar; [[Alt+0]]..[[Alt+9]] Pilih"
+"UI.Key:Ctrl temporarily toggle between lanes and segments","Temporär zwischen Spuren und Segmenten umschalten","Temporarily toggle between lanes and segments","Alternar temporalmente entre carriles y segmentos","Basculer temporairement entre Segments et Voies","","Attiva/disattiva temporaneamente tra corsie e segmenti","Ctrlキーでレーンとセグメントを一時的に切り替え","일시적으로 차선/구간 전환","Tijdelijk schakelen tussen rijbanen en segmenten","Przełącz między widokiem pasów ruchu, a segmentami","","Переключиться между сегментами и полосами движения","按下切換選擇車道/路段","临时切换车道/路段","Temporarily toggle between lanes and segments","","Перемикання між сегментами та смугами руху","","","สลับระหว่างเลนและ segments ชั่วคราว","","","ﺕﺍﺭﺎﺤﻟﺍﻭ ﺕﺎﻃﺎﻘﺘﻟﺍ ﻦﻴﺑ ﻞﻳﺪﺒﺘﻠﻟ Ctrl ﺡﺎﺘﻔﻣ","Ubah mode setelan antara lajur dan bagian jalan"
+"RoadSignTheme:Kmph_Sweden","Schweden [km/h]","Sweden [km/h]","Suecia [km/h]","Suède [km/h]","","Svezia [km/h]","スウェーデンの道路標識","스웨덴식 (km/h)","Zweden [km/h]","Szwecja (km/h)","","Швеция (км/ч)","瑞典 (公里/小時)","瑞典-Kmph","Sweden [km/h]","","Швеція (км/год)","","","สวีเดน [กม./ชม.]","","","ﺪﻳﻮﺴﻟﺍ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ","Swedia [km/j]"
+"RoadSignTheme:Kmph_Brazil","Brasilien [km/h]","Brazil [km/h]","Brasil [km/h]","Brésil [km/h]","","Brasile [km/h]","ブラジルの道路標識","브라질식 (km/h)","Brazilië [km/h]","Brazylia (km/h)","","Бразилия (км/ч)","巴西 (公里/小時)","巴西-Kmph","Brazil [km/h]","","Бразилія (км/год)","","","บราซิล [กม./ชม.]","","","ﻞﻳﺯﺍﺮﺒﻟﺍ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ","Brasil [km/j]"
+"RoadSignTheme:Kmph_France","Frankreich [km/h]","France [km/h]","Francia [km/h]","France [km/h]","","Francia [km/h]","フランスの道路標識","프랑스식 (km/h)","Frankrijk [km/h]","Francja (km/h)","","Франция (км/ч)","法式 (公里/小時)","法国-Kmph","France [km/h]","","Франція (км/год)","","","ฝรั่งเศส [กม./ชม.]","","","ﺎﺴﻧﺮﻓ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ","Perancis [km/j]"
+"RoadSignTheme:Kmph_Indonesia","Indonesien [km/h]","Indonesia [km/h]","Indonesia [km/h]","Indonésie [km/h]","","Indonesia [km/h]","インドネシアの道路標識","인도네시아식 (km/h)","Indonesië [km/h]","Indonezja (km/h)","","Индонезия (км/ч)","印尼 (公里/小時)","印尼-Kmph","Indonesia [km/h]","","Індонезія (км/год)","","","อินโดนีเซีย [กม./ชม.]","","","ﺎﺴﺒﻧﻭﺪﻧﺍ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ","Indonesia [km/j]"
+"RoadSignTheme:Kmph_Japan","Japan [km/h]","Japan [km/h]","Japón [km/h]","Japon [km/h]","","Giappone [km/h]","日本の道路標識","일본식 (km/h)","Japan [km/h]","Japonia (km/h)","","Япония (км/ч)","日式 (公里/小時)","日本-Kmph","Japan [km/h]","","Японія (км/год)","","","ญี่ปุ่น [กม./ชม.]","","","ﻥﺎﺑﺎﻴﻟﺍ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ","Jepang [km/j]"
+"RoadSignTheme:Kmph_SouthKorea","Südkorea [km/h]","South Korea [km/h]","Corea del Sur [km/h]","Corée du Sud [km/h]","","SudCorea [km/h]","韓国の道路標識","한국식 (km/h)","Zuid Korea [km/h]","Korea Południowa (km/h)","","Южная Корея (км/ч)","南韓 (公里/小時)","韩国-Kmph","South Korea [km/h]","","Південна Корея (км/год)","","","เกาหลีใต้ [กม./ชม.]","","","ﺝ ﺎﻳﺭﻮﻛ ﻞﻴﻤﻟﺎﺑ ﻖﻳﺮﻄﻟﺍ ﺕﺎﺘﻓﻻ","Korea Selatan [km/j]"
+"RoadSignTheme:Kmph_China","China [km/h]","China (Mainland) [km/h]","China [km/h]","Chine [km/h]","","RoadSignTheme:Kmph_China","中国(本土用)の道路標識","중국식 (km/h)","","Chiny (km/h)","","Китай континентальный (км/ч)","中國大陸 (公里/小時)","中国-KMph","China (Mainland) [km/h]","","Китай континентальний (км/год)","","","","","","","Tiongkok [km/j]"
+"RoadSignTheme:Kmph_China_Generic","","China (Generic) [km/h]","China genérico [km/h]","","","","中国(一般的)の道路標識","중국식(공용) (km/h)","","Chiny (km/h ogólne, bez glifów)","","Китай (км/ч)","中式 (公里/小時)","中国(通用)-KMph","China (Generic) [km/h]","","Китай (км/год)","","","","","","",""
diff --git a/TLM/TLM/Resources/bus_allowed.png b/TLM/TLM/Resources/bus_allowed.png
deleted file mode 100644
index c846e43d0..000000000
Binary files a/TLM/TLM/Resources/bus_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/bus_forbidden.png b/TLM/TLM/Resources/bus_forbidden.png
deleted file mode 100644
index 15777e5c3..000000000
Binary files a/TLM/TLM/Resources/bus_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/cargotrain_allowed.png b/TLM/TLM/Resources/cargotrain_allowed.png
deleted file mode 100644
index a0a76d9ef..000000000
Binary files a/TLM/TLM/Resources/cargotrain_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/cargotrain_forbidden.png b/TLM/TLM/Resources/cargotrain_forbidden.png
deleted file mode 100644
index f00879e02..000000000
Binary files a/TLM/TLM/Resources/cargotrain_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/cargotruck_allowed.png b/TLM/TLM/Resources/cargotruck_allowed.png
deleted file mode 100644
index 86cac70d0..000000000
Binary files a/TLM/TLM/Resources/cargotruck_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/cargotruck_forbidden.png b/TLM/TLM/Resources/cargotruck_forbidden.png
deleted file mode 100644
index 93719b3b1..000000000
Binary files a/TLM/TLM/Resources/cargotruck_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/emergency_allowed.png b/TLM/TLM/Resources/emergency_allowed.png
deleted file mode 100644
index a9319fc4a..000000000
Binary files a/TLM/TLM/Resources/emergency_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/emergency_forbidden.png b/TLM/TLM/Resources/emergency_forbidden.png
deleted file mode 100644
index 2b589e48a..000000000
Binary files a/TLM/TLM/Resources/emergency_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/passengercar_allowed.png b/TLM/TLM/Resources/passengercar_allowed.png
deleted file mode 100644
index 868218ecf..000000000
Binary files a/TLM/TLM/Resources/passengercar_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/passengercar_forbidden.png b/TLM/TLM/Resources/passengercar_forbidden.png
deleted file mode 100644
index 89003e76a..000000000
Binary files a/TLM/TLM/Resources/passengercar_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/passengertrain_allowed.png b/TLM/TLM/Resources/passengertrain_allowed.png
deleted file mode 100644
index 443697fac..000000000
Binary files a/TLM/TLM/Resources/passengertrain_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/passengertrain_forbidden.png b/TLM/TLM/Resources/passengertrain_forbidden.png
deleted file mode 100644
index fc3fa5a14..000000000
Binary files a/TLM/TLM/Resources/passengertrain_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/service_allowed.png b/TLM/TLM/Resources/service_allowed.png
deleted file mode 100644
index dda54cfa6..000000000
Binary files a/TLM/TLM/Resources/service_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/service_forbidden.png b/TLM/TLM/Resources/service_forbidden.png
deleted file mode 100644
index d61f3b21a..000000000
Binary files a/TLM/TLM/Resources/service_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/Resources/taxi_allowed.png b/TLM/TLM/Resources/taxi_allowed.png
deleted file mode 100644
index 686418553..000000000
Binary files a/TLM/TLM/Resources/taxi_allowed.png and /dev/null differ
diff --git a/TLM/TLM/Resources/taxi_forbidden.png b/TLM/TLM/Resources/taxi_forbidden.png
deleted file mode 100644
index 7f1f06f55..000000000
Binary files a/TLM/TLM/Resources/taxi_forbidden.png and /dev/null differ
diff --git a/TLM/TLM/State/OptionsTabs/GeneralTab_LocalisationGroup.cs b/TLM/TLM/State/OptionsTabs/GeneralTab_LocalisationGroup.cs
index 05850c37c..8e4b6cdd9 100644
--- a/TLM/TLM/State/OptionsTabs/GeneralTab_LocalisationGroup.cs
+++ b/TLM/TLM/State/OptionsTabs/GeneralTab_LocalisationGroup.cs
@@ -79,10 +79,10 @@ private static void AddLanguageDropDown(UIHelperBase group) {
private static void AddRoadSignThemeDropDown(UIHelperBase group) {
Main mainConfig = GlobalConfig.Instance.Main;
- List themeNames = RoadSignThemes.Instance.ThemeNames;
+ List themeNames = RoadSignThemeManager.Instance.ThemeNames;
var themeOptions = themeNames.Select(TranslateThemeName).ToArray();
int selectedThemeIndex = themeNames.FindIndex(x => x == mainConfig.RoadSignTheme);
- int defaultSignsThemeIndex = RoadSignThemes.Instance.FindDefaultThemeIndex(mainConfig.DisplaySpeedLimitsMph);
+ int defaultSignsThemeIndex = RoadSignThemeManager.Instance.FindDefaultThemeIndex(mainConfig.DisplaySpeedLimitsMph);
_roadSignsThemeDropdown = group.AddDropdown(
text: TSpeedLimits("General.Dropdown:Road signs theme") + ":",
@@ -126,15 +126,15 @@ private static void OnLanguageChanged(int newLanguageIndex) {
private static void OnDisplaySpeedLimitsMphChanged(bool value) {
bool supportedByTheme = value
- ? RoadSignThemes.ActiveTheme.SupportsMph
- : RoadSignThemes.ActiveTheme.SupportsKmph;
+ ? RoadSignThemeManager.ActiveTheme.SupportsMph
+ : RoadSignThemeManager.ActiveTheme.SupportsKmph;
Main mainConfig = GlobalConfig.Instance.Main;
if (!supportedByTheme) {
// Reset to German road signs theme
- _roadSignsThemeDropdown.selectedIndex = RoadSignThemes.Instance.FindDefaultThemeIndex(value);
- mainConfig.RoadSignTheme = RoadSignThemes.Instance.GetDefaultThemeName(value);
+ _roadSignsThemeDropdown.selectedIndex = RoadSignThemeManager.Instance.FindDefaultThemeIndex(value);
+ mainConfig.RoadSignTheme = RoadSignThemeManager.Instance.GetDefaultThemeName(value);
Log.Info(
$"Display MPH changed to {value}, but was not supported by current theme, "
+ $"so theme was also reset to {mainConfig.RoadSignTheme}");
@@ -155,18 +155,18 @@ private static void OnRoadSignsThemeChanged(int newThemeIndex) {
return;
}
- var newTheme = RoadSignThemes.Instance.ThemeNames[newThemeIndex];
+ var newTheme = RoadSignThemeManager.Instance.ThemeNames[newThemeIndex];
Main mainConfig = GlobalConfig.Instance.Main;
- switch (RoadSignThemes.Instance.ChangeTheme(
+ switch (RoadSignThemeManager.Instance.ChangeTheme(
newTheme: newTheme,
mphEnabled: mainConfig.DisplaySpeedLimitsMph)) {
- case RoadSignThemes.ChangeThemeResult.Success:
+ case RoadSignThemeManager.ChangeThemeResult.Success:
Log.Info($"Road Sign theme changed to {newTheme}");
mainConfig.RoadSignTheme = newTheme;
break;
- case RoadSignThemes.ChangeThemeResult.ForceKmph:
+ case RoadSignThemeManager.ChangeThemeResult.ForceKmph:
mainConfig.DisplaySpeedLimitsMph = false;
DisplaySpeedLimitsMph.Value = false;
@@ -176,7 +176,7 @@ private static void OnRoadSignsThemeChanged(int newThemeIndex) {
ModUI.Instance.Events.DisplayMphChanged(false);
}
break;
- case RoadSignThemes.ChangeThemeResult.ForceMph:
+ case RoadSignThemeManager.ChangeThemeResult.ForceMph:
mainConfig.DisplaySpeedLimitsMph = true;
DisplaySpeedLimitsMph.Value = true;
diff --git a/TLM/TLM/TLM.csproj b/TLM/TLM/TLM.csproj
index 526584b33..c4792fb56 100644
--- a/TLM/TLM/TLM.csproj
+++ b/TLM/TLM/TLM.csproj
@@ -177,6 +177,7 @@
+
@@ -432,10 +433,9 @@
-
-
+
@@ -548,18 +548,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
@@ -574,17 +562,9 @@
-
-
-
-
-
-
-
-
@@ -830,36 +810,36 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -892,22 +872,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1054,61 +1018,37 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1142,8 +1082,6 @@
-
-
@@ -1158,6 +1096,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TLM/TLM/UI/Helpers/TrafficRulesOverlay.cs b/TLM/TLM/UI/Helpers/TrafficRulesOverlay.cs
index 781dd56e9..9de7bdf13 100644
--- a/TLM/TLM/UI/Helpers/TrafficRulesOverlay.cs
+++ b/TLM/TLM/UI/Helpers/TrafficRulesOverlay.cs
@@ -184,6 +184,7 @@ public bool DrawSignHandles(ushort nodeId,
Color guiColor = GUI.color;
// Vector3 nodePos = node.m_position;
IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;
+ var theme = RoadSignThemeManager.ActiveTheme;
for (int segmentIndex = 0; segmentIndex < Constants.MAX_SEGMENTS_OF_NODE; ++segmentIndex) {
ushort segmentId = node.GetSegment(segmentIndex);
@@ -244,9 +245,9 @@ public bool DrawSignHandles(ushort nodeId,
small: !configurable,
camPos: ref camPos,
guiColor: guiColor,
- signTexture: allowed
- ? JunctionRestrictions.Instance.LaneChangeAllowed
- : JunctionRestrictions.Instance.LaneChangeForbidden);
+ signTexture: theme.GetOtherRestriction(
+ RoadSignTheme.OtherRestriction.LaneChange,
+ allowed));
if (signHovered && this.handleClick_) {
isAnyHovered = true;
@@ -278,9 +279,9 @@ public bool DrawSignHandles(ushort nodeId,
small: !configurable,
camPos: ref camPos,
guiColor: guiColor,
- signTexture: allowed
- ? JunctionRestrictions.Instance.UturnAllowed
- : JunctionRestrictions.Instance.UturnForbidden);
+ signTexture: theme.GetOtherRestriction(
+ RoadSignTheme.OtherRestriction.UTurn,
+ allowed));
if (signHovered && this.handleClick_) {
isAnyHovered = true;
@@ -319,9 +320,9 @@ public bool DrawSignHandles(ushort nodeId,
small: !configurable,
camPos: ref camPos,
guiColor: guiColor,
- signTexture: allowed
- ? JunctionRestrictions.Instance.EnterBlockedJunctionAllowed
- : JunctionRestrictions.Instance.EnterBlockedJunctionForbidden);
+ signTexture: theme.GetOtherRestriction(
+ RoadSignTheme.OtherRestriction.EnterBlockedJunction,
+ allowed));
if (signHovered && this.handleClick_) {
isAnyHovered = true;
@@ -351,9 +352,9 @@ public bool DrawSignHandles(ushort nodeId,
small: !configurable,
camPos: ref camPos,
guiColor: guiColor,
- signTexture: allowed
- ? JunctionRestrictions.Instance.PedestrianCrossingAllowed
- : JunctionRestrictions.Instance.PedestrianCrossingForbidden);
+ signTexture: theme.GetOtherRestriction(
+ RoadSignTheme.OtherRestriction.Crossing,
+ allowed));
if (signHovered && this.handleClick_) {
isAnyHovered = true;
@@ -400,9 +401,9 @@ public bool DrawSignHandles(ushort nodeId,
small: !configurable,
camPos: ref camPos,
guiColor: guiColor,
- signTexture: allowed
- ? JunctionRestrictions.Instance.LeftOnRedAllowed
- : JunctionRestrictions.Instance.LeftOnRedForbidden);
+ signTexture: theme.GetOtherRestriction(
+ RoadSignTheme.OtherRestriction.LeftOnRed,
+ allowed));
if (signHovered && this.handleClick_) {
isAnyHovered = true;
@@ -441,9 +442,9 @@ public bool DrawSignHandles(ushort nodeId,
small: !configurable,
camPos: ref camPos,
guiColor: guiColor,
- signTexture: allowed
- ? JunctionRestrictions.Instance.RightOnRedAllowed
- : JunctionRestrictions.Instance.RightOnRedForbidden);
+ signTexture: theme.GetOtherRestriction(
+ RoadSignTheme.OtherRestriction.RightOnRed,
+ allowed));
if (signHovered && this.handleClick_) {
isAnyHovered = true;
diff --git a/TLM/TLM/UI/ModUI.cs b/TLM/TLM/UI/ModUI.cs
index 227ac4d46..c134c2e1f 100644
--- a/TLM/TLM/UI/ModUI.cs
+++ b/TLM/TLM/UI/ModUI.cs
@@ -242,7 +242,7 @@ public static void OnLevelLoaded() {
// Do not handle ChangeTheme result assuming that savegame always has the selected theme
// and MPH display in a consistent state
- RoadSignThemes.Instance.ChangeTheme(
+ RoadSignThemeManager.Instance.ChangeTheme(
newTheme: GlobalConfig.Instance.Main.RoadSignTheme,
mphEnabled: GlobalConfig.Instance.Main.DisplaySpeedLimitsMph);
}
diff --git a/TLM/TLM/UI/SubTools/LaneConnectorTool.cs b/TLM/TLM/UI/SubTools/LaneConnectorTool.cs
index 048bd9284..d2a15b891 100644
--- a/TLM/TLM/UI/SubTools/LaneConnectorTool.cs
+++ b/TLM/TLM/UI/SubTools/LaneConnectorTool.cs
@@ -32,7 +32,7 @@ public LaneConnectorTool(TrafficManagerTool mainTool)
CachedVisibleNodeIds = new GenericArrayCache(NetManager.MAX_NODE_COUNT);
LastCachedCamera = new CameraTransformValue();
nopeCursor_ = CursorUtil.CreateCursor(UIView.GetAView().defaultAtlas["Niet"]?.texture, new Vector2(45, 45));
- addCursor_ = CursorUtil.LoadCursorFromResource("LaneConnectionManager.add_cursor.png");
+ addCursor_ = CursorUtil.LoadCursorFromResource("LaneConnectionManager.add_cursor.png");
removeCursor_ = CursorUtil.LoadCursorFromResource("LaneConnectionManager.remove_cursor.png");
directionArrow_ = TextureResources.LoadDllResource("LaneConnectionManager.direction_arrow.png", new IntVector2(256, 256));
}
@@ -101,23 +101,23 @@ public enum StayInLaneMode {
private bool MultiMode => ShiftIsPressed;
private class LaneEnd {
- internal ushort SegmentId;
- internal ushort NodeId;
- internal bool StartNode;
- internal uint LaneId;
+ internal readonly List ConnectedLaneEnds = new List();
+ internal Color Color;
+ internal int InnerSimilarLaneIndex; // used for stay in lane.
+ internal bool IsBidirectional; // can be source AND/OR target of a lane connection.
internal bool IsSource;
internal bool IsTarget;
+ internal uint LaneId;
+
+ internal NetInfo.LaneType LaneType;
+ internal ushort NodeId;
+ internal NodeLaneMarker NodeMarker;
internal int OuterSimilarLaneIndex;
- internal int InnerSimilarLaneIndex; // used for stay in lane.
+ internal ushort SegmentId;
internal int SegmentIndex; // index accesable by NetNode.GetSegment(SegmentIndex);
- internal bool IsBidirectional; // can be source AND/OR target of a lane connection.
- internal readonly List ConnectedLaneEnds = new List();
- internal Color Color;
internal SegmentLaneMarker SegmentMarker;
- internal NodeLaneMarker NodeMarker;
-
- internal NetInfo.LaneType LaneType;
+ internal bool StartNode;
internal VehicleInfo.VehicleType VehicleType;
///
@@ -338,7 +338,7 @@ private void ShowOverlay(bool viewOnly, RenderManager.CameraInfo cameraInfo) {
cameraInfo: cameraInfo,
bezier: ref bezier,
color: this.selectedLaneEnd.Color,
- outlineColor: Color.black,
+ outlineColor: Color.black,
arrowColor: showArrow ? this.selectedLaneEnd.Color : default,
arrowOutlineColor: showArrow ? Color.black : default,
size: 0.18f, // Embolden
@@ -399,7 +399,7 @@ public override void RenderOverlay(RenderManager.CameraInfo cameraInfo) {
bezier: ref bezier,
color: fillColor,
outlineColor: Color.white,
- arrowColor: default,
+ arrowColor: default,
arrowOutlineColor: connected ? default : Color.white,
size: 0.18f, // Embolden
underground: true);
@@ -418,7 +418,7 @@ public override void RenderOverlay(RenderManager.CameraInfo cameraInfo) {
underground: true);
}
- OverrideCursor = connected ? removeCursor_ : addCursor_;
+ OverrideCursor = connected ? removeCursor_ : addCursor_;
}
}
diff --git a/TLM/TLM/UI/SubTools/ParkingRestrictionsTool.cs b/TLM/TLM/UI/SubTools/ParkingRestrictionsTool.cs
index aca54763a..8d10beb92 100644
--- a/TLM/TLM/UI/SubTools/ParkingRestrictionsTool.cs
+++ b/TLM/TLM/UI/SubTools/ParkingRestrictionsTool.cs
@@ -308,7 +308,7 @@ private NetInfo.Direction DrawParkingRestrictionHandles(ushort segmentId,
}
GUI.color = GUI.color.WithAlpha(TrafficManagerTool.OverlayAlpha);
- GUI.DrawTexture(boundingBox, RoadSignThemes.ActiveTheme.Parking(allowed));
+ GUI.DrawTexture(boundingBox, RoadSignThemeManager.ActiveTheme.Parking(allowed));
GUI.color = guiColor;
if (hoveredHandle && clicked && !IsCursorInPanel() &&
diff --git a/TLM/TLM/UI/SubTools/PrioritySigns/PrioritySignsTool.cs b/TLM/TLM/UI/SubTools/PrioritySigns/PrioritySignsTool.cs
index 8cdbe532b..4c0f89e6b 100644
--- a/TLM/TLM/UI/SubTools/PrioritySigns/PrioritySignsTool.cs
+++ b/TLM/TLM/UI/SubTools/PrioritySigns/PrioritySignsTool.cs
@@ -356,7 +356,7 @@ private void ShowGUI(bool viewOnly) {
}
if (Highlight.DrawGenericSquareOverlayTexture(
- texture: RoadSignThemes.ActiveTheme.Priority(sign),
+ texture: RoadSignThemeManager.ActiveTheme.Priority(sign),
camPos: camPos,
worldPos: signPos,
size: 90f,
diff --git a/TLM/TLM/UI/SubTools/SpeedLimits/Overlay/SignRenderer.cs b/TLM/TLM/UI/SubTools/SpeedLimits/Overlay/SignRenderer.cs
index f0ebd61a2..892d3fc05 100644
--- a/TLM/TLM/UI/SubTools/SpeedLimits/Overlay/SignRenderer.cs
+++ b/TLM/TLM/UI/SubTools/SpeedLimits/Overlay/SignRenderer.cs
@@ -41,27 +41,27 @@ public bool ContainsMouse(Vector2? mousePos) {
/// Draw large rect with the speed value or unlimited.
/// Show this speed.
public void DrawLargeTexture(SpeedValue? speedlimit,
- RoadSignThemes.RoadSignTheme theme) {
+ RoadSignTheme theme) {
Texture2D tex = speedlimit.HasValue
- ? theme.GetTexture(speedlimit.Value)
- : RoadSignThemes.Instance.NoOverride;
+ ? theme.SpeedLimitTexture(speedlimit.Value)
+ : RoadSignThemeManager.Instance.NoOverride;
GUI.DrawTexture(
position: this.screenRect_,
image: tex);
}
- public void DrawLargeTexture(Texture2D tex) {
- GUI.DrawTexture(
- position: this.screenRect_,
- image: tex);
- }
+ // public void DrawLargeTexture(Texture2D tex) {
+ // GUI.DrawTexture(
+ // position: this.screenRect_,
+ // image: tex);
+ // }
- internal static Texture2D ChooseTexture(SpeedValue? speedlimit,
- RoadSignThemes.RoadSignTheme theme) {
+ private static Texture2D ChooseTexture(SpeedValue? speedlimit,
+ RoadSignTheme theme) {
return speedlimit.HasValue
- ? theme.GetTexture(speedlimit.Value)
- : RoadSignThemes.Instance.NoOverride;
+ ? theme.SpeedLimitTexture(speedlimit.Value)
+ : RoadSignThemeManager.Instance.NoOverride;
}
/// Draws the small texture in the Bottom-Right corner.
@@ -87,7 +87,7 @@ public void DrawSmallTexture_BottomRight(Texture2D tex) {
public void DrawDefaultSpeedSubIcon(SpeedValue speed) {
Texture2D tex = SignRenderer.ChooseTexture(
speedlimit: speed,
- theme: RoadSignThemes.Instance.RoadDefaults);
+ theme: RoadSignThemeManager.Instance.SpeedLimitDefaults);
float size = this.screenRect_.height * 0.4f;
float half = size / 2;
diff --git a/TLM/TLM/UI/SubTools/SpeedLimits/Overlay/SpeedLimitsOverlay.cs b/TLM/TLM/UI/SubTools/SpeedLimits/Overlay/SpeedLimitsOverlay.cs
index 07f6b7a0e..8c9956e42 100644
--- a/TLM/TLM/UI/SubTools/SpeedLimits/Overlay/SpeedLimitsOverlay.cs
+++ b/TLM/TLM/UI/SubTools/SpeedLimits/Overlay/SpeedLimitsOverlay.cs
@@ -85,7 +85,7 @@ public bool IntersectsAnyUIRect(Rect testRect) {
/// and to carry drawing state between multiple calls without using class fields.
private class DrawEnv {
public Vector2 signsThemeAspectRatio_;
- public RoadSignThemes.RoadSignTheme largeSignsTextures_;
+ public RoadSignTheme largeSignsTextures_;
///
/// This is set to true if the user will see blue default signs, or the user is holding
@@ -347,15 +347,15 @@ public void ShowSigns_GUI(DrawArgs args) {
bool hover = false;
DrawEnv drawEnv = new DrawEnv {
- signsThemeAspectRatio_ = RoadSignThemes.ActiveTheme.GetAspectRatio(),
+ signsThemeAspectRatio_ = RoadSignThemeManager.ActiveTheme.GetAspectRatio(),
largeSignsTextures_ = args.ToolMode switch {
- SpeedlimitsToolMode.Segments => RoadSignThemes.ActiveTheme,
- SpeedlimitsToolMode.Lanes => RoadSignThemes.ActiveTheme,
+ SpeedlimitsToolMode.Segments => RoadSignThemeManager.ActiveTheme,
+ SpeedlimitsToolMode.Lanes => RoadSignThemeManager.ActiveTheme,
// Defaults can show normal textures if the user holds Alt
SpeedlimitsToolMode.Defaults => args.ToolMode == SpeedlimitsToolMode.Defaults
- ? RoadSignThemes.ActiveTheme
- : RoadSignThemes.Instance.RoadDefaults,
+ ? RoadSignThemeManager.ActiveTheme
+ : RoadSignThemeManager.Instance.SpeedLimitDefaults,
_ => throw new ArgumentOutOfRangeException(),
},
drawDefaults_ = args.ToolMode == SpeedlimitsToolMode.Defaults,
@@ -502,7 +502,7 @@ private bool DrawSpeedLimitHandles_SegmentCenter(
[NotNull] DrawArgs args)
{
Vector2 aspectRatio = drawEnv.drawDefaults_
- ? RoadSignThemes.DefaultSpeedlimitsAspectRatio()
+ ? RoadSignThemeManager.DefaultSpeedlimitsAspectRatio()
: drawEnv.signsThemeAspectRatio_;
// TODO: Replace formula in visibleScale and size to use Constants.OVERLAY_INTERACTIVE_SIGN_SIZE and OVERLAY_READONLY_SIGN_SIZE
@@ -537,10 +537,10 @@ private bool DrawSpeedLimitHandles_SegmentCenter(
//-------------------------------------
squareSignRenderer.Reset(
screenPos,
- size: size * RoadSignThemes.DefaultSpeedlimitsAspectRatio());
+ size: size * RoadSignThemeManager.DefaultSpeedlimitsAspectRatio());
squareSignRenderer.DrawLargeTexture(
speedlimit: defaultSpeedLimit,
- theme: RoadSignThemes.Instance.RoadDefaults);
+ theme: RoadSignThemeManager.Instance.SpeedLimitDefaults);
} else {
//-------------------------------------
// Draw override, if exists, otherwise draw circle and small blue default
@@ -653,7 +653,7 @@ private bool DrawSpeedLimitHandles_PerLane(
// Defaults have 1:1 ratio (square textures)
Vector2 largeRatio = drawEnv.drawDefaults_
- ? RoadSignThemes.DefaultSpeedlimitsAspectRatio()
+ ? RoadSignThemeManager.DefaultSpeedlimitsAspectRatio()
: drawEnv.signsThemeAspectRatio_;
// Signs are rendered in a grid starting from col 0
diff --git a/TLM/TLM/UI/SubTools/SpeedLimits/PaletteGenerator.cs b/TLM/TLM/UI/SubTools/SpeedLimits/PaletteGenerator.cs
index 250c7392e..e9c589a8d 100644
--- a/TLM/TLM/UI/SubTools/SpeedLimits/PaletteGenerator.cs
+++ b/TLM/TLM/UI/SubTools/SpeedLimits/PaletteGenerator.cs
@@ -19,17 +19,17 @@ public static List AllSpeedLimits(SpeedUnit unit) {
switch (unit) {
case SpeedUnit.Kmph:
- for (var km = RoadSignThemes.KMPH_STEP;
- km <= RoadSignThemes.UPPER_KMPH;
- km += RoadSignThemes.KMPH_STEP) {
+ for (var km = RoadSignThemeManager.KMPH_STEP;
+ km <= RoadSignThemeManager.UPPER_KMPH;
+ km += RoadSignThemeManager.KMPH_STEP) {
result.Add(SetSpeedLimitAction.SetOverride(SpeedValue.FromKmph(km)));
}
break;
case SpeedUnit.Mph:
- for(var mi = RoadSignThemes.MPH_STEP;
- mi <= RoadSignThemes.UPPER_MPH;
- mi += RoadSignThemes.MPH_STEP) {
+ for(var mi = RoadSignThemeManager.MPH_STEP;
+ mi <= RoadSignThemeManager.UPPER_MPH;
+ mi += RoadSignThemeManager.MPH_STEP) {
result.Add(SetSpeedLimitAction.SetOverride(SpeedValue.FromMph(mi)));
}
diff --git a/TLM/TLM/UI/SubTools/SpeedLimits/SpeedLimitsToolWindow.PalettePanel.cs b/TLM/TLM/UI/SubTools/SpeedLimits/SpeedLimitsToolWindow.PalettePanel.cs
index 1dc849a1a..b7c1e9c05 100644
--- a/TLM/TLM/UI/SubTools/SpeedLimits/SpeedLimitsToolWindow.PalettePanel.cs
+++ b/TLM/TLM/UI/SubTools/SpeedLimits/SpeedLimitsToolWindow.PalettePanel.cs
@@ -89,8 +89,8 @@ private SpeedLimitPaletteButton
: actionOnClick.GuardedValue.Override;
int speedInteger = showMph
- ? speedValue.ToMphRounded(RoadSignThemes.MPH_STEP).Mph
- : speedValue.ToKmphRounded(RoadSignThemes.KMPH_STEP).Kmph;
+ ? speedValue.ToMphRounded(RoadSignThemeManager.MPH_STEP).Mph
+ : speedValue.ToKmphRounded(RoadSignThemeManager.KMPH_STEP).Kmph;
//--------------------------------
// Create vertical combo:
@@ -220,7 +220,7 @@ public void TryDecreaseSpeed() {
int number = (int)(showMph
? this.parentTool_.SelectedAction.GuardedValue.Override.GetMph()
: this.parentTool_.SelectedAction.GuardedValue.Override.GetKmph());
- int step = showMph ? RoadSignThemes.MPH_STEP : RoadSignThemes.KMPH_STEP;
+ int step = showMph ? RoadSignThemeManager.MPH_STEP : RoadSignThemeManager.KMPH_STEP;
TryClick(number - step);
}
@@ -232,7 +232,7 @@ public void TryIncreaseSpeed() {
int number = (int)(showMph
? this.parentTool_.SelectedAction.GuardedValue.Override.GetMph()
: this.parentTool_.SelectedAction.GuardedValue.Override.GetKmph());
- int step = showMph ? RoadSignThemes.MPH_STEP : RoadSignThemes.KMPH_STEP;
+ int step = showMph ? RoadSignThemeManager.MPH_STEP : RoadSignThemeManager.KMPH_STEP;
TryClick(number + step);
}
}
diff --git a/TLM/TLM/UI/SubTools/VehicleRestrictionsTool.cs b/TLM/TLM/UI/SubTools/VehicleRestrictionsTool.cs
index ec4249432..11b252e04 100644
--- a/TLM/TLM/UI/SubTools/VehicleRestrictionsTool.cs
+++ b/TLM/TLM/UI/SubTools/VehicleRestrictionsTool.cs
@@ -17,8 +17,7 @@ namespace TrafficManager.UI.SubTools {
public class VehicleRestrictionsTool
: LegacySubTool,
- UI.MainMenu.IOnscreenDisplayProvider
- {
+ UI.MainMenu.IOnscreenDisplayProvider {
private static readonly ExtVehicleType[] RoadVehicleTypes = {
ExtVehicleType.PassengerCar,
ExtVehicleType.Bus,
@@ -33,33 +32,21 @@ public class VehicleRestrictionsTool
ExtVehicleType.CargoTrain,
};
+ private readonly GUI.WindowFunction _guiVehicleRestrictionsWindowDelegate;
+
private readonly float vehicleRestrictionsSignSize = 80f;
- private readonly GUI.WindowFunction _guiVehicleRestrictionsWindowDelegate;
+ private HashSet currentRestrictedSegmentIds;
private bool cursorInSecondaryPanel;
private bool overlayHandleHovered;
- private Color HighlightColor => MainTool.GetToolColor(false, false);
- private static bool RoadMode => ShiftIsPressed;
-
- private Rect windowRect = TrafficManagerTool.GetDefaultScreenPositionForRect(new Rect(0, 0, 620, 100));
-
- private HashSet currentRestrictedSegmentIds;
-
- private static string T(string m) => Translation.VehicleRestrictions.Get(m);
-
- private struct RenderData {
- internal ushort segmentId;
- internal uint laneId;
- internal byte laneIndex;
- internal NetInfo.Lane laneInfo;
- internal int SortedLaneIndex;
- internal bool GUIButtonHovered;
- }
private RenderData renderData_;
+ private Rect windowRect =
+ TrafficManagerTool.GetDefaultScreenPositionForRect(new Rect(0, 0, 620, 100));
+
public VehicleRestrictionsTool(TrafficManagerTool mainTool)
: base(mainTool) {
_guiVehicleRestrictionsWindowDelegate = GuiVehicleRestrictionsWindow;
@@ -67,6 +54,30 @@ public VehicleRestrictionsTool(TrafficManagerTool mainTool)
currentRestrictedSegmentIds = new HashSet();
}
+ private Color HighlightColor => MainTool.GetToolColor(false, false);
+ private static bool RoadMode => ShiftIsPressed;
+
+ public void UpdateOnscreenDisplayPanel() {
+ if (SelectedSegmentId == 0) {
+ // Select mode
+ var items = new List();
+ items.Add(new Label(localizedText: T("VR.OnscreenHint.Mode:Select segment")));
+ OnscreenDisplay.Display(items);
+ } else {
+ // Modify traffic light settings
+ var items = new List();
+ items.Add(new Label(localizedText: T("VR.OnscreenHint.Mode:Toggle restrictions")));
+ items.Add(
+ item: new Shortcut(
+ keybindSetting: KeybindSettingsBase.RestoreDefaultsKey,
+ localizedText: T("VR.Label:Revert to default")));
+ items.Add(OnscreenDisplay.RightClick_LeaveSegment());
+ OnscreenDisplay.Display(items);
+ }
+ }
+
+ private static string T(string m) => Translation.VehicleRestrictions.Get(m);
+
public override void OnActivate() {
base.OnActivate();
cursorInSecondaryPanel = false;
@@ -153,12 +164,12 @@ public override void OnToolGUI(Event e) {
GUI.color = GUI.color.WithAlpha(TrafficManagerTool.GetWindowAlpha());
windowRect = GUILayout.Window(
- 255,
- windowRect,
- _guiVehicleRestrictionsWindowDelegate,
- T("Dialog.Title:Vehicle restrictions"),
- WindowStyle,
- EmptyOptionsArray);
+ id: 255,
+ screenRect: windowRect,
+ func: _guiVehicleRestrictionsWindowDelegate,
+ text: T("Dialog.Title:Vehicle restrictions"),
+ style: WindowStyle,
+ options: EmptyOptionsArray);
cursorInSecondaryPanel = windowRect.Contains(Event.current.mousePosition);
GUI.color = oldColor;
// overlayHandleHovered = false;
@@ -188,17 +199,18 @@ private void RenderLaneOverlay(RenderManager.CameraInfo cameraInfo, uint laneId)
///
private void RenderRoadLane(RenderManager.CameraInfo cameraInfo) {
SegmentLaneTraverser.Traverse(
- renderData_.segmentId,
- SegmentTraverser.TraverseDirection.AnyDirection,
- SegmentTraverser.TraverseSide.AnySide,
- SegmentLaneTraverser.LaneStopCriterion.LaneCount,
- SegmentTraverser.SegmentStopCriterion.Junction,
- SpeedLimitManager.LANE_TYPES,
- SpeedLimitManager.VEHICLE_TYPES,
- data => {
+ initialSegmentId: renderData_.segmentId,
+ direction: SegmentTraverser.TraverseDirection.AnyDirection,
+ side: SegmentTraverser.TraverseSide.AnySide,
+ laneStopCrit: SegmentLaneTraverser.LaneStopCriterion.LaneCount,
+ segStopCrit: SegmentTraverser.SegmentStopCriterion.Junction,
+ laneTypeFilter: SpeedLimitManager.LANE_TYPES,
+ vehicleTypeFilter: SpeedLimitManager.VEHICLE_TYPES,
+ laneVisitor: data => {
if (renderData_.SortedLaneIndex == data.SortedLaneIndex) {
- RenderLaneOverlay(cameraInfo, data.CurLanePos.laneId);
+ RenderLaneOverlay(cameraInfo: cameraInfo, laneId: data.CurLanePos.laneId);
}
+
return true;
});
}
@@ -232,10 +244,10 @@ public override void RenderOverlay(RenderManager.CameraInfo cameraInfo) {
if (HoveredSegmentId != 0 && HoveredSegmentId != SelectedSegmentId &&
!overlayHandleHovered) {
NetTool.RenderOverlay(
- cameraInfo,
- ref HoveredSegmentId.ToSegment(),
- MainTool.GetToolColor(false, false),
- MainTool.GetToolColor(false, false));
+ cameraInfo: cameraInfo,
+ segment: ref HoveredSegmentId.ToSegment(),
+ importantColor: MainTool.GetToolColor(warning: false, error: false),
+ nonImportantColor: MainTool.GetToolColor(warning: false, error: false));
}
}
@@ -272,10 +284,10 @@ private void ShowSigns(bool viewOnly) {
// draw vehicle restrictions
if (DrawVehicleRestrictionHandles(
- segmentId,
- ref netSegment,
- viewOnly || segmentId != SelectedSegmentId,
- out bool updated)) {
+ segmentId: segmentId,
+ segment: ref netSegment,
+ viewOnly: viewOnly || segmentId != SelectedSegmentId,
+ stateUpdated: out bool updated)) {
handleHovered = true;
}
@@ -302,10 +314,11 @@ private void GuiVehicleRestrictionsWindow(int num) {
if (Input.GetKey(hotkey)) {
style.normal.background = style.active.background;
}
+
if (GUILayout.Button(
- T("Button:Allow all vehicles") + " [delete]",
- style,
- EmptyOptionsArray) || Input.GetKeyDown(hotkey)) {
+ T("Button:Allow all vehicles") + " [delete]",
+ style,
+ EmptyOptionsArray) || Input.GetKeyDown(hotkey)) {
AllVehiclesFunc(true);
if (RoadMode) {
ApplyRestrictionsToAllSegments();
@@ -324,8 +337,8 @@ private void GuiVehicleRestrictionsWindow(int num) {
}
if (GUILayout.Button(
- T("Button:Apply to entire road"),
- EmptyOptionsArray)) {
+ T("Button:Apply to entire road"),
+ EmptyOptionsArray)) {
ApplyRestrictionsToAllSegments();
}
@@ -350,8 +363,8 @@ private void AllVehiclesFunc(bool allow) {
NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];
ExtVehicleType allowedTypes = allow
- ? VehicleRestrictionsManager.EXT_VEHICLE_TYPES
- : ExtVehicleType.None;
+ ? VehicleRestrictionsManager.EXT_VEHICLE_TYPES
+ : ExtVehicleType.None;
VehicleRestrictionsManager.Instance.SetAllowedVehicleTypes(
SelectedSegmentId,
@@ -375,7 +388,7 @@ private void AllVehiclesFunc(bool allow) {
///
private void ApplyRestrictionsToAllSegments(
int? sortedLaneIndex = null,
- ExtVehicleType ?vehicleTypes = null) {
+ ExtVehicleType? vehicleTypes = null) {
NetManager netManager = Singleton.instance;
NetInfo selectedSegmentInfo = SelectedSegmentId.ToSegment().Info;
@@ -406,7 +419,8 @@ bool LaneVisitorFun(SegmentLaneVisitData data) {
selectedSegmentInfo,
selectedLaneIndex,
selectedLaneInfo,
- VehicleRestrictionsMode.Configured); ;
+ VehicleRestrictionsMode.Configured);
+
if (vehicleTypes != null) {
ExtVehicleType currentMask =
VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(
@@ -452,7 +466,6 @@ private bool DrawVehicleRestrictionHandles(ushort segmentId,
bool viewOnly,
out bool stateUpdated) {
stateUpdated = false;
- var vehicleRestrictionTextures = RoadUI.Instance.VehicleRestrictionTextures;
if (viewOnly && !Options.vehicleRestrictionsOverlay &&
MainTool.GetToolMode() != ToolMode.VehicleRestrictions) {
@@ -486,7 +499,7 @@ private bool DrawVehicleRestrictionHandles(ushort segmentId,
// if ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None)
// yu = -yu;
Vector3 xu = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized;
- float f = viewOnly ? 4f : 7f; // reserved sign size in game coordinates
+ float signSize = viewOnly ? 4f : 7f; // reserved sign size in game coordinates
int maxNumSigns = 0;
if (VehicleRestrictionsManager.Instance.IsRoadSegment(segmentInfo)) {
@@ -496,8 +509,8 @@ private bool DrawVehicleRestrictionHandles(ushort segmentId,
}
// Vector3 zero = center - 0.5f * (float)(numLanes + numDirections - 1) * f * (xu + yu); // "bottom left"
- Vector3 zero = center - (0.5f * (numLanes - 1 + numDirections - 1) * f * xu)
- - (0.5f * maxNumSigns * f * yu); // "bottom left"
+ Vector3 zero = center - (0.5f * (numLanes - 1 + numDirections - 1) * signSize * xu)
+ - (0.5f * maxNumSigns * signSize * yu); // "bottom left"
// if (!viewOnly)
// Log._Debug($"xu: {xu.ToString()} yu: {yu.ToString()} center: {center.ToString()}
@@ -507,9 +520,9 @@ private bool DrawVehicleRestrictionHandles(ushort segmentId,
Color guiColor = GUI.color; // TODO: Use OverlayHandleColorController
var sortedLanes = segment.GetSortedLanes(
- null,
- VehicleRestrictionsManager.LANE_TYPES,
- VehicleRestrictionsManager.VEHICLE_TYPES);
+ startNode: null,
+ laneTypeFilter: VehicleRestrictionsManager.LANE_TYPES,
+ vehicleTypeFilter: VehicleRestrictionsManager.VEHICLE_TYPES);
bool hovered = false;
HashSet directions = new HashSet();
@@ -550,45 +563,33 @@ private bool DrawVehicleRestrictionHandles(ushort segmentId,
VehicleRestrictionsMode.Configured);
uint y = 0;
-#if DEBUG_disabled_xxx
- Vector3 labelCenter = zero + f * (float)x * xu + f * (float)y * yu; // in game coordinates
-
- Vector3 labelScreenPos;
- bool visible = GeometryUtil.WorldToScreenPoint(labelCenter, out labelScreenPos);
- // BUGBUG: Using screen.height might be wrong, consider U.UIScaler.ScreenHeight (from UIView.fixedHeight)
- labelScreenPos.y = Screen.height - labelScreenPos.y;
- diff = labelCenter - camPos;
-
- var labelZoom = 1.0f / diff.magnitude * 100f;
- _counterStyle.fontSize = (int)(11f * labelZoom);
- _counterStyle.normal.textColor = new Color(1f, 1f, 0f);
-
- string labelStr = $"Idx {laneIndex}";
- Vector2 dim = _counterStyle.CalcSize(new GUIContent(labelStr));
- Rect labelRect = new Rect(labelScreenPos.x - dim.x / 2f, labelScreenPos.y, dim.x, dim.y);
- GUI.Label(labelRect, labelStr, _counterStyle);
-
- ++y;
-#endif
Color guiColor2 = GUI.color; // TODO: Use OverlayHandleColorController
GUI.color = GUI.color.WithAlpha(TrafficManagerTool.OverlayAlpha);
var gridRenderer = new Highlight.Grid(
gridOrigin: zero,
- cellWidth: f,
- cellHeight: f,
+ cellWidth: signSize,
+ cellHeight: signSize,
xu: xu,
yu: yu);
+ var theme = RoadSignThemeManager.ActiveTheme;
+
foreach (ExtVehicleType vehicleType in possibleVehicleTypes) {
- bool allowed = VehicleRestrictionsManager.Instance.IsAllowed(allowedTypes, vehicleType);
+ bool allowed =
+ VehicleRestrictionsManager.Instance.IsAllowed(allowedTypes, vehicleType);
if (allowed && viewOnly) {
continue; // do not draw allowed vehicles in view-only mode
}
+ Texture2D drawTex = theme.VehicleRestriction(vehicleType, allowed);
+ // if (drawTex == null) {
+ // drawTex = Texture2D.whiteTexture;
+ // }
+
bool hoveredHandle = gridRenderer.DrawGenericOverlayGridTexture(
- texture: vehicleRestrictionTextures[vehicleType][allowed],
+ texture: drawTex,
camPos: camPos,
x: x,
y: y,
@@ -606,7 +607,7 @@ private bool DrawVehicleRestrictionHandles(ushort segmentId,
renderData_.SortedLaneIndex = sortedLaneIndex;
}
- if (hoveredHandle && MainTool.CheckClicked() ) {
+ if (hoveredHandle && MainTool.CheckClicked()) {
// toggle vehicle restrictions
// Log._Debug($"Setting vehicle restrictions of segment {segmentId}, lane
// idx {laneIndex}, {vehicleType.ToString()} to {!allowed}");
@@ -639,23 +640,13 @@ private bool DrawVehicleRestrictionHandles(ushort segmentId,
return hovered;
}
- public void UpdateOnscreenDisplayPanel() {
- if (SelectedSegmentId == 0) {
- // Select mode
- var items = new List();
- items.Add(new Label(localizedText: T("VR.OnscreenHint.Mode:Select segment")));
- OnscreenDisplay.Display(items);
- } else {
- // Modify traffic light settings
- var items = new List();
- items.Add(new Label(localizedText: T("VR.OnscreenHint.Mode:Toggle restrictions")));
- items.Add(
- item: new Shortcut(
- keybindSetting: KeybindSettingsBase.RestoreDefaultsKey,
- localizedText: T("VR.Label:Revert to default")));
- items.Add(OnscreenDisplay.RightClick_LeaveSegment());
- OnscreenDisplay.Display(items);
- }
+ private struct RenderData {
+ internal ushort segmentId;
+ internal uint laneId;
+ internal byte laneIndex;
+ internal NetInfo.Lane laneInfo;
+ internal int SortedLaneIndex;
+ internal bool GUIButtonHovered;
}
}
-}
+}
\ No newline at end of file
diff --git a/TLM/TLM/UI/Textures/JunctionRestrictions.cs b/TLM/TLM/UI/Textures/JunctionRestrictions.cs
deleted file mode 100644
index c1ea21d37..000000000
--- a/TLM/TLM/UI/Textures/JunctionRestrictions.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-namespace TrafficManager.UI.Textures {
- using TrafficManager.Manager;
- using TrafficManager.Util;
- using UnityEngine;
- using static TextureResources;
-
- ///
- /// Textures for UI controlling crossings, junctions and nodes
- ///
- public class JunctionRestrictions : AbstractCustomManager {
- public static JunctionRestrictions Instance = new();
-
- public Texture2D LaneChangeForbidden;
- public Texture2D LaneChangeAllowed;
-
- public Texture2D UturnAllowed;
- public Texture2D UturnForbidden;
-
- public Texture2D RightOnRedForbidden;
- public Texture2D RightOnRedAllowed;
-
- public Texture2D LeftOnRedForbidden;
- public Texture2D LeftOnRedAllowed;
-
- public Texture2D EnterBlockedJunctionAllowed;
- public Texture2D EnterBlockedJunctionForbidden;
-
- public Texture2D PedestrianCrossingAllowed;
- public Texture2D PedestrianCrossingForbidden;
-
- /// Called by the lifecycle when textures are to be loaded.
- public override void OnLevelLoading() {
- IntVector2 size = new IntVector2(200);
-
- LaneChangeAllowed = LoadDllResource("JunctionRestrictions.lanechange_allowed.png", size);
- LaneChangeForbidden = LoadDllResource("JunctionRestrictions.lanechange_forbidden.png", size);
-
- UturnAllowed = LoadDllResource("JunctionRestrictions.uturn_allowed.png", size);
- UturnForbidden = LoadDllResource("JunctionRestrictions.uturn_forbidden.png", size);
-
- RightOnRedAllowed = LoadDllResource("JunctionRestrictions.right_on_red_allowed.png", size);
- RightOnRedForbidden = LoadDllResource("JunctionRestrictions.right_on_red_forbidden.png", size);
- LeftOnRedAllowed = LoadDllResource("JunctionRestrictions.left_on_red_allowed.png", size);
- LeftOnRedForbidden = LoadDllResource("JunctionRestrictions.left_on_red_forbidden.png", size);
-
- EnterBlockedJunctionAllowed = LoadDllResource("JunctionRestrictions.enterblocked_allowed.png", size);
- EnterBlockedJunctionForbidden = LoadDllResource("JunctionRestrictions.enterblocked_forbidden.png", size);
-
- PedestrianCrossingAllowed = LoadDllResource("JunctionRestrictions.crossing_allowed.png", size);
- PedestrianCrossingForbidden = LoadDllResource("JunctionRestrictions.crossing_forbidden.png", size);
-
- base.OnLevelLoading();
- }
-
- /// Called by the lifecycle when textures are to be unloaded.
- public override void OnLevelUnloading() {
- UnityEngine.Object.Destroy(LaneChangeAllowed);
- UnityEngine.Object.Destroy(LaneChangeForbidden);
-
- UnityEngine.Object.Destroy(UturnAllowed);
- UnityEngine.Object.Destroy(UturnForbidden);
-
- UnityEngine.Object.Destroy(RightOnRedAllowed);
- UnityEngine.Object.Destroy(RightOnRedForbidden);
- UnityEngine.Object.Destroy(LeftOnRedAllowed);
- UnityEngine.Object.Destroy(LeftOnRedForbidden);
-
- UnityEngine.Object.Destroy(EnterBlockedJunctionAllowed);
- UnityEngine.Object.Destroy(EnterBlockedJunctionForbidden);
-
- UnityEngine.Object.Destroy(PedestrianCrossingAllowed);
- UnityEngine.Object.Destroy(PedestrianCrossingForbidden);
-
- base.OnLevelUnloading();
- }
- }
-}
\ No newline at end of file
diff --git a/TLM/TLM/UI/Textures/RoadSignTheme.cs b/TLM/TLM/UI/Textures/RoadSignTheme.cs
new file mode 100644
index 000000000..4be225443
--- /dev/null
+++ b/TLM/TLM/UI/Textures/RoadSignTheme.cs
@@ -0,0 +1,386 @@
+namespace TrafficManager.UI.Textures {
+ using System;
+ using System.Collections.Generic;
+ using CSUtil.Commons;
+ using JetBrains.Annotations;
+ using TrafficManager.API.Traffic.Data;
+ using TrafficManager.API.Traffic.Enums;
+ using TrafficManager.State;
+ using TrafficManager.UI.SubTools;
+ using TrafficManager.Util;
+ using UnityEngine;
+ using Object = UnityEngine.Object;
+
+ ///
+ /// Defines one theme for road signs. All themes are accessible via, and stored in
+ /// .
+ ///
+ public class RoadSignTheme {
+ public enum OtherRestriction {
+ Crossing,
+ EnterBlockedJunction,
+ LaneChange,
+ LeftOnRed,
+ RightOnRed,
+ UTurn,
+ }
+
+ public readonly string Name;
+
+ // Kmph sign sets include range for MPH, but not all pictures are good to go with Kmph or Mph setting.
+ // For example Canadian signs have all values to show MPH, but make no sense because the sign says km/h.
+
+ /// Whether km/h signs range is supported from 5 to 140 step 5.
+ public readonly bool SupportsKmph;
+
+ /// Whether MPH signs range is supported from 5 to 90 step 5.
+ public readonly bool SupportsMph;
+
+ /// Speed limit signs from 5 to 140 km (from 5 to 90 mph) and zero for no limit.
+ public readonly Dictionary Textures = new();
+
+ /// Set to true if an attempt to find and load textures was made.
+ public bool AttemptedToLoad = false;
+
+ private bool HaveSpeedLimitSigns = false;
+
+ ///
+ /// Road signs for other restrictions such as pedestrian crossings, blocked junction, u-turn etc.
+ ///
+ private Dictionary otherRestrictions_ = new();
+
+ ///
+ /// This theme will be tried instead of the `Fallback` theme. Defaults to .
+ ///
+ private RoadSignTheme ParentTheme;
+
+ private Dictionary parking_ = new();
+
+ private string PathPrefix;
+
+ private Dictionary priority_ = new();
+
+ /// This list of required speed signs is used for loading.
+ private List SignValues = new();
+
+ private IntVector2 TextureSize;
+
+ ///
+ /// Road signs for restrictions per vehicle types. Not all vehicle types have an icon,
+ /// only those supported in
+ /// and .
+ ///
+ private Dictionary vehicleRestrictions_ = new();
+
+ public RoadSignTheme(string name,
+ bool supportsMph,
+ bool supportsKmph,
+ IntVector2 size,
+ string pathPrefix,
+ [CanBeNull]
+ RoadSignTheme parentTheme = null,
+ bool speedLimitSigns = true) {
+ Log._DebugIf(
+ this.TextureSize.x <= this.TextureSize.y,
+ () =>
+ $"Constructing a road sign theme {pathPrefix}: Portrait oriented size not supported");
+
+ this.Name = name;
+ this.SupportsMph = supportsMph;
+ this.SupportsKmph = supportsKmph;
+ this.PathPrefix = pathPrefix;
+ this.TextureSize = size;
+ this.ParentTheme = parentTheme;
+ this.HaveSpeedLimitSigns = speedLimitSigns;
+
+ if (supportsKmph) {
+ // Assumes that signs from 0 to 140 with step 5 exist, 0 denotes no-limit sign
+ for (var kmphValue = 0;
+ kmphValue <= RoadSignThemeManager.UPPER_KMPH;
+ kmphValue += RoadSignThemeManager.LOAD_KMPH_STEP) {
+ this.SignValues.Add(kmphValue);
+ }
+ } else if (supportsMph) {
+ for (var mphValue = 0;
+ mphValue <= RoadSignThemeManager.UPPER_MPH;
+ mphValue += RoadSignThemeManager.MPH_STEP) {
+ this.SignValues.Add(mphValue);
+ }
+ }
+ }
+
+ public Texture2D Priority(PriorityType p) =>
+ this.priority_.ContainsKey(p)
+ ? this.priority_[p]
+ : this.ParentTheme.Priority(p);
+
+ public Texture2D Parking(bool p) =>
+ this.parking_.ContainsKey(p)
+ ? this.parking_[p]
+ : this.ParentTheme.Parking(p);
+
+ public Texture2D VehicleRestriction(ExtVehicleType type, bool allow) {
+ if (allow) {
+ return this.vehicleRestrictions_.ContainsKey(type)
+ ? this.vehicleRestrictions_[type].allow
+ : this.ParentTheme.VehicleRestriction(type, allow: true);
+ }
+
+ return this.vehicleRestrictions_.ContainsKey(type)
+ ? this.vehicleRestrictions_[type].restrict
+ : this.ParentTheme.VehicleRestriction(type, allow: false);
+ }
+
+ ///
+ /// Returns road sign for other restrictions (pedestrian, blocked junction, u-turn etc).
+ ///
+ /// The restriction we need.
+ /// Allow or restrict.
+ public Texture2D GetOtherRestriction(OtherRestriction type, bool allow) {
+ if (allow) {
+ return this.otherRestrictions_.ContainsKey(type)
+ ? this.otherRestrictions_[type].allow
+ : this.ParentTheme.GetOtherRestriction(type, allow: true);
+ }
+
+ return this.otherRestrictions_.ContainsKey(type)
+ ? this.otherRestrictions_[type].restrict
+ : this.ParentTheme.GetOtherRestriction(type, allow: false);
+ }
+
+ public RoadSignTheme Load(bool whiteTexture = false) {
+ if (this.AttemptedToLoad) {
+ return this;
+ }
+
+ this.Textures.Clear();
+ this.AttemptedToLoad = true;
+
+ foreach (var speedLimit in this.SignValues) {
+ // Log._Debug($"Loading sign texture {this.PathPrefix}.{speedLimit}.png");
+ var resource = TextureResources.LoadDllResource(
+ resourceName: $"{this.PathPrefix}.{speedLimit}.png",
+ size: this.TextureSize,
+ mip: true,
+ logIfNotFound: false);
+ this.Textures.Add(speedLimit, resource ? resource : Texture2D.whiteTexture);
+ }
+
+ LoadPrioritySign(p: PriorityType.None, name: "PriorityNone", whiteTexture);
+ LoadPrioritySign(p: PriorityType.Main, name: "PriorityRightOfWay", whiteTexture);
+ LoadPrioritySign(p: PriorityType.Yield, name: "PriorityYield", whiteTexture);
+ LoadPrioritySign(p: PriorityType.Stop, name: "PriorityStop", whiteTexture);
+
+ LoadParkingSign(allow: true, name: "Parking", whiteTexture);
+ LoadParkingSign(allow: false, name: "NoParking", whiteTexture);
+
+ // Load Vehicle type restrictions
+ LoadVehicleRestrictionSign(ExtVehicleType.PassengerCar, "PersonalCar", whiteTexture);
+ LoadVehicleRestrictionSign(ExtVehicleType.Bus, "Bus", whiteTexture);
+ LoadVehicleRestrictionSign(ExtVehicleType.Taxi, "Taxi", whiteTexture);
+ LoadVehicleRestrictionSign(ExtVehicleType.CargoTruck, "Truck", whiteTexture);
+ LoadVehicleRestrictionSign(ExtVehicleType.Service, "Service", whiteTexture);
+ LoadVehicleRestrictionSign(ExtVehicleType.Emergency, "Emergency", whiteTexture);
+ LoadVehicleRestrictionSign(
+ ExtVehicleType.PassengerTrain,
+ "PassengerTrain",
+ whiteTexture);
+ LoadVehicleRestrictionSign(ExtVehicleType.CargoTrain, "CargoTrain", whiteTexture);
+
+ // Load other restrictions
+ LoadOtherRestrictionSign(OtherRestriction.Crossing, "PedestrianCrossing", whiteTexture);
+ LoadOtherRestrictionSign(
+ OtherRestriction.EnterBlockedJunction,
+ "EnterBlocked",
+ whiteTexture);
+ LoadOtherRestrictionSign(OtherRestriction.LaneChange, "LaneChange", whiteTexture);
+ LoadOtherRestrictionSign(OtherRestriction.LeftOnRed, "LeftOnRed", whiteTexture);
+ LoadOtherRestrictionSign(OtherRestriction.RightOnRed, "RightOnRed", whiteTexture);
+ LoadOtherRestrictionSign(OtherRestriction.UTurn, "UTurn", whiteTexture);
+
+ // Setup parent theme to be `Fallback` theme if ParentTheme is null
+ // For Fallback theme itself, keep it null.
+ if (this.ParentTheme == null
+ && !System.Object.ReferenceEquals(
+ this,
+ RoadSignThemeManager.Instance.FallbackTheme)) {
+ this.ParentTheme = RoadSignThemeManager.Instance.FallbackTheme;
+ }
+
+ this.ParentTheme?.Load(); // Reload parent theme if necessary
+
+ return this;
+ }
+
+ private void LoadPrioritySign(PriorityType p, string name, bool whiteTexture) {
+ var tex = TextureResources.LoadDllResource(
+ resourceName: $"{this.PathPrefix}.{name}.png",
+ size: new IntVector2(200),
+ mip: true,
+ logIfNotFound: false);
+
+ if (tex != null) {
+ this.priority_[p] = tex;
+ } else if (whiteTexture) {
+ this.priority_[p] = Texture2D.whiteTexture;
+ }
+ }
+
+ private void LoadParkingSign(bool allow, string name, bool whiteTexture) {
+ var tex = TextureResources.LoadDllResource(
+ resourceName: $"{this.PathPrefix}.{name}.png",
+ size: new IntVector2(200),
+ mip: true,
+ logIfNotFound: false);
+
+ if (tex != null) {
+ this.parking_[allow] = tex;
+ } else if (whiteTexture) {
+ this.parking_[allow] = Texture2D.whiteTexture;
+ }
+ }
+
+ ///
+ /// Generic function to load Allow-X and Restrict-X textures into either
+ /// or
+ ///
+ /// The key to store as.
+ /// The destination dictionary.
+ /// Name to append to either Allow- or Restrict-.
+ /// Create record even if resource is missing, using white texture.
+ /// Type of the key.
+ private void LoadRestrictionSignGeneric(
+ TIndex index,
+ Dictionary dict,
+ string name,
+ bool whiteTexture,
+ int sizeHint) {
+ var size = new IntVector2(sizeHint);
+ Texture2D allowTex = TextureResources.LoadDllResource(
+ resourceName: $"{this.PathPrefix}.Allow-{name}.png",
+ size: size,
+ mip: true,
+ logIfNotFound: false);
+ Texture2D restrictTex = TextureResources.LoadDllResource(
+ resourceName: $"{this.PathPrefix}.Restrict-{name}.png",
+ size: size,
+ mip: true,
+ logIfNotFound: false);
+ if (allowTex && restrictTex) {
+ var pairOfSigns = new AllowDisallowTexture {
+ allow = allowTex,
+ restrict = restrictTex,
+ };
+ dict[index] = pairOfSigns;
+ } else if (whiteTexture) {
+ var whiteBox = new AllowDisallowTexture {
+ allow = Texture2D.whiteTexture,
+ restrict = Texture2D.whiteTexture,
+ };
+ dict[index] = whiteBox;
+ }
+ }
+
+ private void LoadVehicleRestrictionSign(ExtVehicleType index,
+ string name,
+ bool whiteTexture) {
+ LoadRestrictionSignGeneric(index, this.vehicleRestrictions_, name, whiteTexture, 200);
+ }
+
+ private void LoadOtherRestrictionSign(OtherRestriction index,
+ string name,
+ bool whiteTexture) {
+ LoadRestrictionSignGeneric(index, this.otherRestrictions_, name, whiteTexture, 256);
+ }
+
+ private void DestroyTexture(Texture2D t) {
+ // Only destroy our textures, don't try to destroy UnityWhite
+ if (!System.Object.ReferenceEquals(t, Texture2D.whiteTexture)) {
+ UnityEngine.Object.Destroy(t);
+ }
+ }
+
+ public void Unload() {
+ this.ParentTheme?.Unload(); // Unload parent theme if necessary
+
+ // Speed limit textures
+ foreach (var texture in this.Textures) {
+ DestroyTexture(texture.Value);
+ }
+
+ this.Textures.Clear();
+
+ // Priority signs
+ foreach (var texture in this.priority_) {
+ DestroyTexture(texture.Value);
+ }
+
+ this.priority_.Clear();
+
+ // Parking signs
+ foreach (var texture in this.parking_) {
+ DestroyTexture(texture.Value);
+ }
+
+ this.parking_.Clear();
+
+ // Vehicle Restriction signs
+ foreach (var rs in this.vehicleRestrictions_) {
+ DestroyTexture(rs.Value.allow);
+ DestroyTexture(rs.Value.restrict);
+ }
+
+ this.parking_.Clear();
+
+ this.AttemptedToLoad = false;
+ }
+
+ ///
+ /// Assumes that signs can be square or vertical rectangle, no horizontal themes.
+ /// Aspect ratio value which scales width down to have height fully fit.
+ ///
+ public Vector2 GetAspectRatio() {
+ return new(this.TextureSize.x / (float)this.TextureSize.y, 1.0f);
+ }
+
+ ///
+ /// Given the speed, return a texture to render.
+ /// Does not use assuming that all speeds must be covered in a theme.
+ ///
+ /// Speed to display.
+ /// Texture to display.
+ public Texture2D SpeedLimitTexture(SpeedValue spd) {
+ if (!this.HaveSpeedLimitSigns) {
+ return this.ParentTheme.SpeedLimitTexture(spd);
+ }
+
+ // Round to nearest 5 MPH or nearest 5 km/h
+ bool mph = GlobalConfig.Instance.Main.DisplaySpeedLimitsMph;
+ ushort index = mph
+ ? spd.ToMphRounded(RoadSignThemeManager.MPH_STEP).Mph
+ : spd.ToKmphRounded(RoadSignThemeManager.KMPH_STEP).Kmph;
+
+ // Trim the index since 140 km/h / 90 MPH is the max sign we have
+ ushort upper = mph ? RoadSignThemeManager.UPPER_MPH : RoadSignThemeManager.UPPER_KMPH;
+
+ try {
+ // Show unlimited if the speed cannot be represented by the available sign textures
+ if (index == 0 || index > upper) {
+ return this.Textures[0];
+ }
+
+ // Trim from below to not go below index 5 (5 kmph or 5 mph)
+ ushort trimIndex = Math.Max((ushort)5, index);
+ return this.Textures[trimIndex];
+ }
+ catch (KeyNotFoundException) {
+ return RoadSignThemeManager.Instance.NoOverride;
+ }
+ }
+
+ public struct AllowDisallowTexture {
+ public Texture2D allow;
+ public Texture2D restrict;
+ }
+ }
+}
\ No newline at end of file
diff --git a/TLM/TLM/UI/Textures/RoadSignThemeManager.cs b/TLM/TLM/UI/Textures/RoadSignThemeManager.cs
new file mode 100644
index 000000000..0e0f8c2a7
--- /dev/null
+++ b/TLM/TLM/UI/Textures/RoadSignThemeManager.cs
@@ -0,0 +1,237 @@
+namespace TrafficManager.UI.Textures {
+ using static TextureResources;
+ using System.Collections.Generic;
+ using System.Linq;
+ using CSUtil.Commons;
+ using TrafficManager.Manager;
+ using TrafficManager.State;
+ using TrafficManager.State.ConfigData;
+ using TrafficManager.UI.SubTools.SpeedLimits;
+ using TrafficManager.Util;
+ using UnityEngine;
+
+ ///
+ /// Singleton which manages road signs themes dynamically loaded and freed as the user .
+ /// The textures are loaded when OnLevelLoaded event is fired from the .
+ ///
+ public class RoadSignThemeManager : AbstractCustomManager {
+ ///
+ /// Reports the success of theme change. ForceMph/ForceKmph require the caller to also
+ /// change display units because the currently selected display units are not supported.
+ ///
+ public enum ChangeThemeResult {
+ Success,
+ ForceMph,
+ ForceKmph,
+ }
+
+ // We have texture files for every 5 kmph but speed limits palette allows every 10. This is
+ // for more precise MPH display.
+ internal const ushort KMPH_STEP = 10;
+ internal const ushort UPPER_KMPH = 140;
+ internal const ushort LOAD_KMPH_STEP = 5;
+ internal const ushort UPPER_MPH = 90;
+ internal const ushort MPH_STEP = 5;
+
+ private const string FALLBACK_THEME = "Fallback";
+
+ private const string KMPH_BRAZIL_THEME = "Kmph_Brazil";
+ private const string KMPH_CANADA_THEME = "Kmph_Canada";
+ private const string KMPH_FRANCE_THEME = "Kmph_France";
+ private const string KMPH_GERMANY_THEME = "Kmph_Germany";
+ private const string KMPH_INDONESIA_THEME = "Kmph_Indonesia";
+ private const string KMPH_JAPAN_THEME = "Kmph_Japan";
+ private const string KMPH_SOUTHKOREA_THEME = "Kmph_SouthKorea";
+ private const string KMPH_SWEDEN_THEME = "Kmph_Sweden";
+ private const string KMPH_CHINA_THEME = "Kmph_China";
+ private const string KMPH_CHINA_GENERIC_THEME = "Kmph_China_Generic";
+ private const string MPH_UK_THEME = "MPH_UK";
+ private const string MPH_US_THEME = "MPH_US";
+
+ private const string DEFAULT_KMPH_THEME = KMPH_GERMANY_THEME;
+ private const string DEFAULT_MPH_THEME = MPH_UK_THEME;
+ public static RoadSignThemeManager Instance = new();
+
+ /// Fallback theme to use when a sign is not found in the user-selected theme.
+ public readonly RoadSignTheme FallbackTheme;
+
+ /// Green textures for road/lane default speed limits. Always loaded.
+ public readonly RoadSignTheme SpeedLimitDefaults;
+
+ /// Names from sorted.
+ internal readonly List ThemeNames = new();
+
+ public readonly Dictionary Themes = new();
+
+ private RoadSignTheme activeTheme_ = null;
+
+ public Texture2D Clear;
+
+ ///
+ /// Displayed in Override view for Speed Limits tool, when there's no override.
+ /// This is rather never displayed because there is always either override or default speed
+ /// limit value to show, but is still present for "safety".
+ ///
+ public Texture2D NoOverride;
+
+ private RoadSignThemeManager() {
+ SpeedLimitDefaults = new RoadSignTheme(
+ name: "Defaults",
+ supportsKmph: true,
+ supportsMph: true,
+ size: new IntVector2(200),
+ pathPrefix: "SignThemes.SpeedLimitDefaults");
+ FallbackTheme = new RoadSignTheme(
+ name: FALLBACK_THEME,
+ supportsKmph: true,
+ supportsMph: true,
+ size: new IntVector2(200),
+ pathPrefix: "SignThemes.Fallback");
+
+ RoadSignTheme NewTheme(string name,
+ SpeedUnit unit,
+ int height = 200,
+ RoadSignTheme parentTheme = null,
+ bool speedLimitSigns = true) {
+ var theme = new RoadSignTheme(
+ name: name,
+ supportsMph: unit == SpeedUnit.Mph,
+ supportsKmph: unit == SpeedUnit.Kmph,
+ size: new IntVector2(200, height),
+ pathPrefix: $"SignThemes.{name}",
+ parentTheme: parentTheme,
+ speedLimitSigns: speedLimitSigns);
+ Themes.Add(name, theme);
+ return theme;
+ }
+
+ NewTheme(name: MPH_UK_THEME, unit: SpeedUnit.Mph);
+ NewTheme(name: MPH_US_THEME, unit: SpeedUnit.Mph, height: 250);
+
+ NewTheme(name: KMPH_BRAZIL_THEME, unit: SpeedUnit.Kmph);
+ NewTheme(name: KMPH_CANADA_THEME, unit: SpeedUnit.Kmph, height: 250);
+ NewTheme(name: KMPH_FRANCE_THEME, unit: SpeedUnit.Kmph);
+ NewTheme(name: KMPH_GERMANY_THEME, unit: SpeedUnit.Kmph);
+ NewTheme(name: KMPH_INDONESIA_THEME, unit: SpeedUnit.Kmph);
+ NewTheme(name: KMPH_JAPAN_THEME, unit: SpeedUnit.Kmph);
+ NewTheme(name: KMPH_SOUTHKOREA_THEME, unit: SpeedUnit.Kmph);
+ NewTheme(name: KMPH_SWEDEN_THEME, unit: SpeedUnit.Kmph);
+
+ // "Mainland" theme defines road signs for mainland China, with chinese text
+ // "Generic" defines more generic signs without text and generic yield sign.
+ RoadSignTheme mainlandChina = NewTheme(
+ name: KMPH_CHINA_THEME,
+ unit: SpeedUnit.Kmph);
+ NewTheme(
+ name: KMPH_CHINA_GENERIC_THEME,
+ unit: SpeedUnit.Kmph,
+ parentTheme: mainlandChina,
+ speedLimitSigns: false);
+
+ ThemeNames = Themes.Keys.ToList();
+ ThemeNames.Sort();
+ }
+
+ public static RoadSignTheme ActiveTheme {
+ get {
+ if (Instance.activeTheme_ == null || !Instance.activeTheme_.AttemptedToLoad) {
+ Instance.activeTheme_ = Instance.LoadCurrentTheme();
+ }
+
+ return Instance.activeTheme_;
+ }
+ }
+
+ public string GetDefaultThemeName(bool mph) {
+ return mph ? DEFAULT_MPH_THEME : DEFAULT_KMPH_THEME;
+ }
+
+ public int FindDefaultThemeIndex(bool mph) {
+ if (mph) {
+ return ThemeNames.FindIndex(x => x == DEFAULT_MPH_THEME);
+ }
+
+ return ThemeNames.FindIndex(x => x == DEFAULT_KMPH_THEME);
+ }
+
+ private RoadSignTheme LoadCurrentTheme() {
+ Main confMain = GlobalConfig.Instance.Main;
+ string selectedThemeName = confMain.RoadSignTheme;
+
+ if (Themes.ContainsKey(selectedThemeName)) {
+ return Themes[selectedThemeName].Load();
+ }
+
+ bool confMainDisplaySpeedLimitsMph = confMain.DisplaySpeedLimitsMph;
+ string defaultTheme = GetDefaultThemeName(confMainDisplaySpeedLimitsMph);
+
+ confMain.RoadSignTheme = defaultTheme;
+ Log.Info($"Road Sign theme changed to default ({defaultTheme})");
+
+ return Themes[defaultTheme].Load();
+ }
+
+ public static Vector2 DefaultSpeedlimitsAspectRatio() => Vector2.one;
+
+ /// Called from Options General tab and attempts to change the theme.
+ /// New string key.
+ /// Whether config is set to showing MPH
+ /// False if the new theme doesn't support km/h and the settings require km/h.
+ /// Or false if the `newTheme` key isn't a valid theme name.
+ public ChangeThemeResult ChangeTheme(string newTheme, bool mphEnabled) {
+ if (!Themes.ContainsKey(newTheme)) {
+ var defaultTheme = GetDefaultThemeName(mphEnabled);
+ Log.Error(
+ $"Theme changing to {newTheme} but it isn't known to texture manager, so instead we change to {defaultTheme}");
+ newTheme = defaultTheme;
+ }
+
+ if (activeTheme_ != null && activeTheme_.Name != newTheme) {
+ activeTheme_.Unload();
+ activeTheme_ = Themes[newTheme];
+ activeTheme_.Load();
+
+ if (mphEnabled && !activeTheme_.SupportsMph) {
+ // Theme requires KM/H display to be on
+ return ChangeThemeResult.ForceKmph;
+ }
+
+ if (!mphEnabled && !activeTheme_.SupportsKmph) {
+ // Theme requires MPH display to be on
+ return ChangeThemeResult.ForceMph;
+ }
+ }
+
+ return ChangeThemeResult.Success;
+ }
+
+ /// Called by the lifecycle when textures are to be loaded.
+ public override void OnLevelLoading() {
+ SpeedLimitDefaults.Load();
+ FallbackTheme.Load(whiteTexture: true);
+
+ NoOverride = LoadDllResource(
+ resourceName: "SpeedLimits.NoOverride.png",
+ size: new IntVector2(200));
+ Clear = LoadDllResource(resourceName: "clear.png", size: new IntVector2(256));
+
+ base.OnLevelLoading();
+ }
+
+ /// Called by the lifecycle when textures are to be unloaded.
+ public override void OnLevelUnloading() {
+ // Let all themes know its time to unload, even the ones not loaded
+ SpeedLimitDefaults.Unload();
+ FallbackTheme.Unload();
+
+ foreach (var theme in Themes) {
+ theme.Value.Unload();
+ }
+
+ UnityEngine.Object.Destroy(Clear);
+ UnityEngine.Object.Destroy(NoOverride);
+
+ base.OnLevelUnloading();
+ }
+ }
+}
\ No newline at end of file
diff --git a/TLM/TLM/UI/Textures/RoadSignThemes.cs b/TLM/TLM/UI/Textures/RoadSignThemes.cs
deleted file mode 100644
index 25e749c71..000000000
--- a/TLM/TLM/UI/Textures/RoadSignThemes.cs
+++ /dev/null
@@ -1,405 +0,0 @@
-namespace TrafficManager.UI.Textures {
- using static TextureResources;
- using System.Collections.Generic;
- using System;
- using System.Linq;
- using CSUtil.Commons;
- using TrafficManager.API.Traffic.Data;
- using TrafficManager.API.Traffic.Enums;
- using TrafficManager.Manager;
- using TrafficManager.State;
- using TrafficManager.State.ConfigData;
- using TrafficManager.UI.SubTools.SpeedLimits;
- using TrafficManager.Util;
- using UnityEngine;
-
- ///
- /// Singleton which manages road signs themes dynamically loaded and freed as the user .
- /// The textures are loaded when OnLevelLoaded event is fired from the .
- ///
- public class RoadSignThemes : AbstractCustomManager {
- public static RoadSignThemes Instance = new();
-
- public class RoadSignTheme {
- private IntVector2 TextureSize;
-
- /// Speed limit signs from 5 to 140 km (from 5 to 90 mph) and zero for no limit.
- public readonly Dictionary Textures = new();
-
- private Dictionary priority_ = new();
-
- public Texture2D Priority(PriorityType p) => this.priority_.ContainsKey(p)
- ? this.priority_[p]
- : RoadUI.Instance.PrioritySignTextures[p];
-
- private Dictionary parking_ = new();
-
- public Texture2D Parking(bool p) => this.parking_.ContainsKey(p)
- ? this.parking_[p]
- : RoadUI.Instance.ParkingRestrictionTextures[p];
-
- /// This list of required speed signs is used for loading.
- private List SignValues = new();
-
- private string PathPrefix;
-
- // Kmph sign sets include range for MPH, but not all pictures are good to go with Kmph or Mph setting.
- // For example Canadian signs have all values to show MPH, but make no sense because the sign says km/h.
-
- /// Whether km/h signs range is supported from 5 to 140 step 5.
- public readonly bool SupportsKmph;
-
- /// Whether MPH signs range is supported from 5 to 90 step 5.
- public readonly bool SupportsMph;
-
- public readonly string Name;
-
- /// Set to true if an attempt to find and load textures was made.
- public bool AttemptedToLoad = false;
-
- public RoadSignTheme(string name,
- bool supportsMph,
- bool supportsKmph,
- IntVector2 size,
- string pathPrefix) {
- Log._DebugIf(
- this.TextureSize.x <= this.TextureSize.y,
- () =>
- $"Constructing a road sign theme {pathPrefix}: Portrait oriented size not supported");
-
- this.Name = name;
- this.SupportsMph = supportsMph;
- this.SupportsKmph = supportsKmph;
- this.PathPrefix = pathPrefix;
- this.TextureSize = size;
-
- if (supportsKmph) {
- // Assumes that signs from 0 to 140 with step 5 exist, 0 denotes no-limit sign
- for (var kmphValue = 0; kmphValue <= UPPER_KMPH; kmphValue += LOAD_KMPH_STEP) {
- this.SignValues.Add(kmphValue);
- }
- } else if (supportsMph) {
- for (var mphValue = 0; mphValue <= UPPER_MPH; mphValue += MPH_STEP) {
- this.SignValues.Add(mphValue);
- }
- }
- }
-
- public RoadSignTheme Load() {
- if (this.AttemptedToLoad) {
- return this;
- }
-
- this.Textures.Clear();
- this.AttemptedToLoad = true;
-
- foreach (var speedLimit in this.SignValues) {
- // Log._Debug($"Loading sign texture {this.PathPrefix}.{speedLimit}.png");
- var resource = LoadDllResource(
- resourceName: $"{this.PathPrefix}.{speedLimit}.png",
- size: this.TextureSize,
- mip: true);
- this.Textures.Add(
- speedLimit,
- resource ? resource : RoadSignThemes.Instance.Clear);
- }
-
- var squareSpecialSize = new IntVector2(200);
-
- LoadPrioritySign(
- PriorityType.Main,
- LoadDllResource(
- resourceName: $"{this.PathPrefix}.RightOfWay.png",
- size: squareSpecialSize,
- mip: true,
- failIfNotFound: false));
- LoadPrioritySign(
- PriorityType.Yield,
- LoadDllResource(
- resourceName: $"{this.PathPrefix}.Yield.png",
- size: squareSpecialSize,
- mip: true,
- failIfNotFound: false));
- LoadPrioritySign(
- PriorityType.Stop,
- LoadDllResource(
- resourceName: $"{this.PathPrefix}.Stop.png",
- size: squareSpecialSize,
- mip: true,
- failIfNotFound: false));
- LoadParkingSign(
- true,
- LoadDllResource(
- resourceName: $"{this.PathPrefix}.Parking.png",
- size: squareSpecialSize,
- mip: true,
- failIfNotFound: false));
- LoadParkingSign(
- false,
- LoadDllResource(
- resourceName: $"{this.PathPrefix}.NoParking.png",
- size: squareSpecialSize,
- mip: true,
- failIfNotFound: false));
-
- return this;
- }
-
- private void LoadPrioritySign(PriorityType p, Texture2D tex) {
- if (tex != null) {
- this.priority_[p] = tex;
- }
- }
-
- private void LoadParkingSign(bool allow, Texture2D tex) {
- if (tex != null) {
- this.parking_[allow] = tex;
- }
- }
-
- public void Unload() {
- foreach (var texture in this.Textures) {
- UnityEngine.Object.Destroy(texture.Value);
- }
-
- this.Textures.Clear();
-
- foreach (var texture in this.priority_) {
- UnityEngine.Object.Destroy(texture.Value);
- }
-
- this.priority_.Clear();
-
- foreach (var texture in this.parking_) {
- UnityEngine.Object.Destroy(texture.Value);
- }
-
- this.parking_.Clear();
-
- this.AttemptedToLoad = false;
- }
-
- ///
- /// Assumes that signs can be square or vertical rectangle, no horizontal themes.
- /// Aspect ratio value which scales width down to have height fully fit.
- ///
- public Vector2 GetAspectRatio() {
- return new(this.TextureSize.x / (float)this.TextureSize.y, 1.0f);
- }
-
- /// Given the speed, return a texture to render.
- /// Speed to display.
- /// Texture to display.
- public Texture2D GetTexture(SpeedValue spd) {
- // Round to nearest 5 MPH or nearest 5 km/h
- bool mph = GlobalConfig.Instance.Main.DisplaySpeedLimitsMph;
- ushort index = mph
- ? spd.ToMphRounded(MPH_STEP).Mph
- : spd.ToKmphRounded(KMPH_STEP).Kmph;
-
- // Trim the index since 140 km/h / 90 MPH is the max sign we have
- ushort upper = mph ? UPPER_MPH : UPPER_KMPH;
-
- try {
- // Show unlimited if the speed cannot be represented by the available sign textures
- if (index == 0 || index > upper) {
- return this.Textures[0];
- }
-
- // Trim from below to not go below index 5 (5 kmph or 5 mph)
- ushort trimIndex = Math.Max((ushort)5, index);
- return this.Textures[trimIndex];
- }
- catch (KeyNotFoundException) {
- return RoadSignThemes.Instance.NoOverride;
- }
- }
- }
-
- // We have texture files for every 5 kmph but speed limits palette allows every 10. This is
- // for more precise MPH display.
- internal const ushort KMPH_STEP = 10;
- internal const ushort UPPER_KMPH = 140;
- private const ushort LOAD_KMPH_STEP = 5;
- internal const ushort UPPER_MPH = 90;
- internal const ushort MPH_STEP = 5;
-
- ///
- /// Displayed in Override view for Speed Limits tool, when there's no override.
- /// This is rather never displayed because there is always either override or default speed
- /// limit value to show, but is still present for "safety".
- ///
- public Texture2D NoOverride;
-
- /// Blue textures for road/lane default speed limits. Always loaded.
- public readonly RoadSignTheme RoadDefaults;
-
- public Texture2D Clear;
-
- public readonly Dictionary Themes = new();
-
- private RoadSignTheme activeTheme_ = null;
-
- /// Names from sorted.
- internal readonly List ThemeNames = new();
-
- public static RoadSignTheme ActiveTheme {
- get {
- if (Instance.activeTheme_ == null || !Instance.activeTheme_.AttemptedToLoad) {
- Instance.activeTheme_ = Instance.LoadCurrentTheme();
- }
-
- return Instance.activeTheme_;
- }
- }
-
- private const string KMPH_BRAZIL_THEME = "Kmph_Brazil";
- private const string KMPH_CANADA_THEME = "Kmph_Canada";
- private const string KMPH_FRANCE_THEME = "Kmph_France";
- private const string KMPH_GERMANY_THEME = "Kmph_Germany";
- private const string KMPH_INDONESIA_THEME = "Kmph_Indonesia";
- private const string KMPH_JAPAN_THEME = "Kmph_Japan";
- private const string KMPH_SOUTHKOREA_THEME = "Kmph_SouthKorea";
- private const string KMPH_SWEDEN_THEME = "Kmph_Sweden";
- private const string MPH_UK_THEME = "MPH_UK";
- private const string MPH_US_THEME = "MPH_US";
-
- private const string DEFAULT_KMPH_THEME = KMPH_GERMANY_THEME;
- private const string DEFAULT_MPH_THEME = MPH_UK_THEME;
-
- public string GetDefaultThemeName(bool mph) {
- return mph ? DEFAULT_MPH_THEME : DEFAULT_KMPH_THEME;
- }
-
- public int FindDefaultThemeIndex(bool mph) {
- if (mph) {
- return ThemeNames.FindIndex(x => x == DEFAULT_MPH_THEME);
- }
-
- return ThemeNames.FindIndex(x => x == DEFAULT_KMPH_THEME);
- }
-
- private RoadSignTheme LoadCurrentTheme() {
- Main confMain = GlobalConfig.Instance.Main;
- string selectedThemeName = confMain.RoadSignTheme;
-
- if (Themes.ContainsKey(selectedThemeName)) {
- return Themes[selectedThemeName].Load();
- }
-
- bool confMainDisplaySpeedLimitsMph = confMain.DisplaySpeedLimitsMph;
- string defaultTheme = GetDefaultThemeName(confMainDisplaySpeedLimitsMph);
-
- confMain.RoadSignTheme = defaultTheme;
- Log.Info($"Road Sign theme changed to default ({defaultTheme})");
-
- return Themes[defaultTheme].Load();
- }
-
- private RoadSignThemes() {
- RoadDefaults = new RoadSignTheme(
- name: "Defaults",
- supportsKmph: true,
- supportsMph: true,
- size: new IntVector2(200),
- pathPrefix: "SignThemes.RoadDefaults");
-
- void NewTheme(string name, SpeedUnit unit, int height = 200) {
- Themes.Add(
- name,
- new RoadSignTheme(
- name: name,
- supportsKmph: unit == SpeedUnit.Kmph,
- supportsMph: unit == SpeedUnit.Mph,
- size: new IntVector2(200, height),
- pathPrefix: "SignThemes." + name));
- }
-
- NewTheme(name: MPH_UK_THEME, unit: SpeedUnit.Mph);
- NewTheme(name: MPH_US_THEME, unit: SpeedUnit.Mph, height: 250);
-
- NewTheme(name: KMPH_BRAZIL_THEME, unit: SpeedUnit.Kmph);
- NewTheme(name: KMPH_CANADA_THEME, unit: SpeedUnit.Kmph, height: 250);
- NewTheme(name: KMPH_FRANCE_THEME, unit: SpeedUnit.Kmph);
- NewTheme(name: KMPH_GERMANY_THEME, unit: SpeedUnit.Kmph);
- NewTheme(name: KMPH_INDONESIA_THEME, unit: SpeedUnit.Kmph);
- NewTheme(name: KMPH_JAPAN_THEME, unit: SpeedUnit.Kmph);
- NewTheme(name: KMPH_SOUTHKOREA_THEME, unit: SpeedUnit.Kmph);
- NewTheme(name: KMPH_SWEDEN_THEME, unit: SpeedUnit.Kmph);
-
- ThemeNames = Themes.Keys.ToList();
- ThemeNames.Sort();
- }
-
- public static Vector2 DefaultSpeedlimitsAspectRatio() => Vector2.one;
-
- ///
- /// Reports the success of theme change. ForceMph/ForceKmph require the caller to also
- /// change display units because the currently selected display units are not supported.
- ///
- public enum ChangeThemeResult {
- Success,
- ForceMph,
- ForceKmph,
- }
-
- /// Called from Options General tab and attempts to change the theme.
- /// New string key.
- /// Whether config is set to showing MPH
- /// False if the new theme doesn't support km/h and the settings require km/h.
- /// Or false if the `newTheme` key isn't a valid theme name.
- public ChangeThemeResult ChangeTheme(string newTheme, bool mphEnabled) {
- if (!Themes.ContainsKey(newTheme)) {
- var defaultTheme = GetDefaultThemeName(mphEnabled);
- Log.Error(
- $"Theme changing to {newTheme} but it isn't known to texture manager, so instead we change to {defaultTheme}");
- newTheme = defaultTheme;
- }
-
- if (activeTheme_ != null && activeTheme_.Name != newTheme) {
- activeTheme_.Unload();
- activeTheme_ = Themes[newTheme];
- activeTheme_.Load();
-
- if (mphEnabled && !activeTheme_.SupportsMph) {
- // Theme requires KM/H display to be on
- return ChangeThemeResult.ForceKmph;
- }
-
- if (!mphEnabled && !activeTheme_.SupportsKmph) {
- // Theme requires MPH display to be on
- return ChangeThemeResult.ForceMph;
- }
- }
-
- return ChangeThemeResult.Success;
- }
-
- /// Called by the lifecycle when textures are to be loaded.
- public override void OnLevelLoading() {
- RoadDefaults.Load();
-
- NoOverride = LoadDllResource(
- resourceName: "SpeedLimits.NoOverride.png",
- size: new IntVector2(200));
- Clear = LoadDllResource(resourceName: "clear.png", size: new IntVector2(256));
-
- base.OnLevelLoading();
- }
-
- /// Called by the lifecycle when textures are to be unloaded.
- public override void OnLevelUnloading() {
- // Let all themes know its time to unload, even the ones not loaded
- RoadDefaults.Unload();
-
- foreach (var theme in Themes) {
- theme.Value.Unload();
- }
-
- UnityEngine.Object.Destroy(Clear);
- UnityEngine.Object.Destroy(NoOverride);
-
- base.OnLevelUnloading();
- }
- }
-}
\ No newline at end of file
diff --git a/TLM/TLM/UI/Textures/RoadUI.cs b/TLM/TLM/UI/Textures/RoadUI.cs
index 1d9d108f9..4f461a094 100644
--- a/TLM/TLM/UI/Textures/RoadUI.cs
+++ b/TLM/TLM/UI/Textures/RoadUI.cs
@@ -14,90 +14,30 @@ namespace TrafficManager.UI.Textures {
public class RoadUI : AbstractCustomManager {
public static RoadUI Instance = new();
- [Obsolete("These are now available via RoadSignThemes.ActiveTheme.Priority(PriorityType p)")]
- public IDictionary PrioritySignTextures;
-
public Texture2D SignClear;
/// Smaller Arrow-Down sign to be rendered as half-size for underground nodes.
public Texture2D Underground;
- public IDictionary> VehicleRestrictionTextures;
public IDictionary VehicleInfoSignTextures;
- [Obsolete("These are now available via RoadSignThemes.ActiveTheme.Parking(bool)")]
- public IDictionary ParkingRestrictionTextures;
-
- public void ReloadTexturesWithTranslation() {
- IntVector2 size = new IntVector2(200);
- Texture2D stopTexture = PrioritySignTextures[PriorityType.Stop];
- if (stopTexture) {
- UnityEngine.GameObject.Destroy(stopTexture);
- }
-
- PrioritySignTextures[PriorityType.Stop] = LoadDllResource(Translation.GetTranslatedFileName("RoadUI.sign_stop.png"), size);
-
- Texture2D yieldTexture = PrioritySignTextures[PriorityType.Yield];
- if (yieldTexture) {
- UnityEngine.GameObject.Destroy(yieldTexture);
- }
-
- PrioritySignTextures[PriorityType.Yield] = LoadDllResource(Translation.GetTranslatedFileName("RoadUI.sign_yield.png"), size);
- }
-
public override void OnLevelLoading() {
- IntVector2 size = new IntVector2(200);
-
- // priority signs
- PrioritySignTextures = new Dictionary {
- [PriorityType.None] = LoadDllResource("RoadUI.sign_none.png", size),
- [PriorityType.Main] = LoadDllResource("RoadUI.sign_priority.png", size),
- [PriorityType.Stop] = LoadDllResource(Translation.GetTranslatedFileName("RoadUI.sign_stop.png"), size),
- [PriorityType.Yield] = LoadDllResource(Translation.GetTranslatedFileName("RoadUI.sign_yield.png"), size),
- };
-
// delete priority sign
SignClear = LoadDllResource("clear.png", new IntVector2(256));
// Arrow down for underground nodes, rendered half-size
Underground = LoadDllResource("Underground.png", new IntVector2(128), mip: true);
- VehicleRestrictionTextures =
- new Dictionary> {
- [ExtVehicleType.Bus] = new Dictionary(),
- [ExtVehicleType.CargoTrain] = new Dictionary(),
- [ExtVehicleType.CargoTruck] = new Dictionary(),
- [ExtVehicleType.Emergency] = new Dictionary(),
- [ExtVehicleType.PassengerCar] = new Dictionary(),
- [ExtVehicleType.PassengerTrain] = new Dictionary(),
- [ExtVehicleType.Service] = new Dictionary(),
- [ExtVehicleType.Taxi] = new Dictionary(),
- };
-
- foreach (KeyValuePair> e in
- VehicleRestrictionTextures) {
- foreach (bool b in new[] { false, true }) {
- string suffix = b ? "allowed" : "forbidden";
- e.Value[b] = LoadDllResource(
- resourceName: e.Key.ToString().ToLower() + "_" + suffix + ".png",
- size: size);
- }
- }
-
- ParkingRestrictionTextures = new Dictionary();
- ParkingRestrictionTextures[true] = LoadDllResource("RoadUI.parking_allowed.png", size);
- ParkingRestrictionTextures[false] = LoadDllResource("RoadUI.parking_disallowed.png", size);
-
IntVector2 signSize = new IntVector2(449, 411);
VehicleInfoSignTextures = new Dictionary {
- [ExtVehicleType.Bicycle] = LoadDllResource("RoadUI.bicycle_infosign.png", signSize),
- [ExtVehicleType.Bus] = LoadDllResource("RoadUI.bus_infosign.png", signSize),
- [ExtVehicleType.CargoTrain] = LoadDllResource("RoadUI.cargotrain_infosign.png", signSize),
- [ExtVehicleType.CargoTruck] = LoadDllResource("RoadUI.cargotruck_infosign.png", signSize),
- [ExtVehicleType.Emergency] = LoadDllResource("RoadUI.emergency_infosign.png", signSize),
- [ExtVehicleType.PassengerCar] = LoadDllResource("RoadUI.passengercar_infosign.png", signSize),
- [ExtVehicleType.PassengerTrain] = LoadDllResource("RoadUI.passengertrain_infosign.png", signSize),
+ [ExtVehicleType.Bicycle] = LoadDllResource("RoadUI.bicycle_infosign.png", signSize, true),
+ [ExtVehicleType.Bus] = LoadDllResource("RoadUI.bus_infosign.png", signSize, true),
+ [ExtVehicleType.CargoTrain] = LoadDllResource("RoadUI.cargotrain_infosign.png", signSize, true),
+ [ExtVehicleType.CargoTruck] = LoadDllResource("RoadUI.cargotruck_infosign.png", signSize, true),
+ [ExtVehicleType.Emergency] = LoadDllResource("RoadUI.emergency_infosign.png", signSize, true),
+ [ExtVehicleType.PassengerCar] = LoadDllResource("RoadUI.passengercar_infosign.png", signSize, true),
+ [ExtVehicleType.PassengerTrain] = LoadDllResource("RoadUI.passengertrain_infosign.png", signSize, true),
};
VehicleInfoSignTextures[ExtVehicleType.RailVehicle] = VehicleInfoSignTextures[ExtVehicleType.PassengerTrain];
VehicleInfoSignTextures[ExtVehicleType.Service] = LoadDllResource("RoadUI.service_infosign.png", signSize);
@@ -108,28 +48,11 @@ public override void OnLevelLoading() {
}
public override void OnLevelUnloading() {
- foreach (var t in PrioritySignTextures) {
- UnityEngine.Object.Destroy(t.Value);
- }
- PrioritySignTextures.Clear();
-
- foreach (var vrt in VehicleRestrictionTextures) {
- foreach (var t in vrt.Value) {
- UnityEngine.Object.Destroy(t.Value);
- }
- }
- VehicleRestrictionTextures.Clear();
-
foreach (var t in VehicleInfoSignTextures) {
UnityEngine.Object.Destroy(t.Value);
}
VehicleInfoSignTextures.Clear();
- foreach (var t in ParkingRestrictionTextures) {
- UnityEngine.Object.Destroy(t.Value);
- }
- ParkingRestrictionTextures.Clear();
-
UnityEngine.Object.Destroy(SignClear);
UnityEngine.Object.Destroy(Underground);
diff --git a/TLM/TLM/UI/Textures/TextureResources.cs b/TLM/TLM/UI/Textures/TextureResources.cs
index faeba3c19..f83dcf2a0 100644
--- a/TLM/TLM/UI/Textures/TextureResources.cs
+++ b/TLM/TLM/UI/Textures/TextureResources.cs
@@ -11,7 +11,7 @@ public static class TextureResources {
internal static Texture2D LoadDllResource(string resourceName,
IntVector2 size,
bool mip = false,
- bool failIfNotFound = true) {
+ bool logIfNotFound = true) {
#if DEBUG
bool debug = DebugSwitch.ResourceLoading.Get();
#endif
@@ -26,7 +26,7 @@ internal static Texture2D LoadDllResource(string resourceName,
myAssembly.GetManifestResourceStream(
"TrafficManager.Resources." + resourceName);
if (myStream == null) {
- if (failIfNotFound) {
+ if (logIfNotFound) {
throw new Exception($"Resource stream {resourceName} not found!");
}
@@ -45,16 +45,14 @@ internal static Texture2D LoadDllResource(string resourceName,
return texture;
}
catch (Exception e) {
- if (failIfNotFound) {
+ if (logIfNotFound) {
#if DEBUG
Log.Error($"Failed to load texture {resourceName}: " + e);
#else
Log.Warning($"Failed to load texture {resourceName}: " + e);
#endif
- } else {
- Log._Debug($"Resource {resourceName} failed to load (not an error)");
}
-
+ // If not found, silently return null
return null;
}
}