diff --git a/README.md b/README.md index 0f1ad3e..1c25099 100755 --- a/README.md +++ b/README.md @@ -18,3 +18,6 @@ Note: this is lost when you close the terminal / console, so you have to run thi ### Windows _I don't have Windows so cannot provide any instructions - contributions by Windows users welcome !_ + +## Credits +* dsftxt2stg-lookup.py taken and modified from https://github.com/mherweg/d-laser-fgtools/library.txt diff --git a/dsf2stg_lookup.py b/dsf2stg_lookup.py new file mode 100755 index 0000000..2a44103 --- /dev/null +++ b/dsf2stg_lookup.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +lookup = { + "lib/airport/aircraft/corporate_biz/P180_avanti_ferrari.obj": {'path': 'Models/lib/citation.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/aircraft/corporate_biz/P180_avanti_white.obj": {'path': 'Models/lib/citation.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/aircraft/GA/Cessna_172.obj": {'path': 'CESSNA', 'alt-offset': 0, 'hdg-offset': 180}, + "lib/airport/aircraft/GA/KingAirC90B.obj": {'path': 'Models/Aircraft/Citation-II-Type1.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/aircraft/GA/Osprey_GP5.obj": {'path': 'Models/Aircraft/Zlin50xl_low_poly.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/aircraft/heavy_metal/747_United.obj": {'path': 'Models/Aircraft/B747.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/heavy_metal/MD-80_Alitalia.obj": {'path': 'Models/Aircraft/320austrian.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/heavy_metal/MD-80_Delta.obj": {'path': 'Models/Aircraft/737virgin.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/heavy_metal/MD-80_Scandinavian.obj": {'path': 'Models/Aircraft/320volare.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/regional_jet/CRJ100_Air_France.obj": {'path': 'Models/Aircraft/crj100af-obj.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/regional_jet/CRJ100_Austrian_Arrows.obj": {'path': 'Models/Aircraft/crj100af-obj.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/regional_jet/Dornier_328_jet_Cirrus_Airlines.obj": {'path': 'Models/Aircraft/D328_services.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/regional_jet/Dornier_328_jet_Welcome_Air.obj": {'path': 'Models/Aircraft/D328_services.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/regional_prop/ATR42-500_Air_Dolomiti.obj": {'path': 'Models/Aircraft/atr42-iberia.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/aircraft/regional_prop/ATR42-500_FedEx.obj": {'path': 'Models/Aircraft/bae-ootas-tnt.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/aircraft/regional_prop/ATR72-500_American_Eagle.obj": {'path': 'Models/Aircraft/ATR42.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/aircraft/regional_prop/ATR72-500_Lufthansa_Regional.obj": {'path': 'Models/Aircraft/fokker50_vlm.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/aircraft/regional_prop/Dornier_328_prop_Air_Alps.obj": {'path': 'Models/Aircraft/B1900_services.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Vintage_Airports/Control_Towers/Hangar_Tower.agp": {'path': 'Models/lib/vintage-tower-hangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Classic_Airports/Control_Towers/Classic_Tower_1.agp": {'path': 'Models/Airport/tower_small_airfield.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Classic_Airports/Control_Towers/Classic_Tower_2.agp": {'path': 'Models/Airport/tower_small_airfield.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Classic_Airports/Control_Towers/Classic_Tower_3.agp": {'path': 'Models/Airport/tower_small_airfield.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Classic_Airports/Control_Towers/Classic_Tower_4.agp": {'path': 'Models/Airport/tower_small_airfield.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Modern_Airports/Control_Towers/Modern_Tower_1.agp": {'path': 'Models/Airport/tower_small_airfield.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Modern_Airports/Control_Towers/Modern_Tower_3.agp": {'path': 'Models/Airport/tower_small_airfield.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Modern_Airports/Control_Towers/Modern_Tower_2.agp": {'path': 'Models/Airport/tower_small_airfield.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Fueling_Stations/2_horiz_tanks.agp": {'path': 'Models/lib/HorizTanks2.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Fueling_Stations/Covered_Station.agp": {'path': 'Models/Airport/FGRefuel02.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Common_Elements/Fueling_Stations/Small_Fuel_Station.obj": {'path': 'Models/Airport/Avgas_Pump.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Fuel_Storage/3_Tank_Array.agp": {'path': 'Models/Airport/GenericFuelStore3.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Fuel_Storage/Single_Tank_Large.obj": {'path': 'Models/Industrial/generic_tank_020m_grey.ac', 'alt-offset': -90, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Fuel_Storage/Single_Vert_Tank.agp": {'path': 'Models/Airport/GenericFuelStore1.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Fuel_Storage/Sing_Tank_Large.obj": {'path': 'Models/Airport/egkk_oil.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Fuel_Storage/Sing_Tank_Medium.obj": {'path': 'Models/Industrial/GenericStorageTank30m.ac', 'alt-offset': -92, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Fuel_Storage/Sing_Tank_Small.obj": {'path': 'Models/Industrial/generic_tank_005m_grey.ac', 'alt-offset': -95, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Hangars/FBO_Modern1.agp": {'path': 'Models/lib/fboModern1.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Lg_Maint_Blue.agp": {'path': 'Models/lib/LgMaint.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Lg_Maint_Brown.agp": {'path': 'Models/lib/LgMaint.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Lg_Maint_Gray.agp": {'path': 'Models/lib/LgMaint.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Lg_Maint_Orange.agp": {'path': 'Models/lib/LgMaint.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Long_Row_Beige.agp": {'path': 'Models/lib/LongRow.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Long_Row_Green.agp": {'path': 'Models/lib/LongRow.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Med_Blue_Hangar.agp": {'path': 'Models/lib/MedHangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Med_Brown_Hangar.agp": {'path': 'Models/lib/MedHangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Med_Gray_Hangar.agp": {'path': 'Models/lib/MedHangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Med_Orange_Hangar.agp": {'path': 'Models/lib/MedHangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Sm_Blue_Hangar.agp": {'path': 'Models/lib/SmHangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Sm_Brown_Hangar.agp": {'path': 'Models/lib/SmHangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Sm_Gray_Hangar.agp": {'path': 'Models/lib/SmHangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Hangars/Sm_Orange_Hangar.agp": {'path': 'Models/lib/SmHangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Lighting/com_DownLight.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Common_Elements/Lighting/com_Flood_20m.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Common_Elements/Lighting/com_Flood_36m.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Common_Elements/Lighting/Dir_Flood_Sm.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Lighting/Dir_Ramp_Lit_Med.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Common_Elements/Lighting/Dir_Ramp_Lit_Short.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Common_Elements/Lighting/Dir_Ramp_Lit_Tall.obj": {'path': 'Models/Airport/Apronlamp16m180deg.xml', 'alt-offset': 0, 'hdg-offset': 45}, + "lib/airport/Common_Elements/Lighting/Omni_Parking_Lit.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Common_Elements/Lighting/Opposing_Flood_Sm.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Common_Elements/Lighting/Ovrhd_Flood_Med.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Lighting/Ovrhd_Flood_Small.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Misc_Buildings/com_Office1.obj": {'path': 'Models/Commercial/OfficeBuilding74x18m.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Misc_Buildings/com_Office2.obj": {'path': 'Models/Commercial/OfficeBuilding74x18m.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Misc_Buildings/Fire_Station_Lg.agp": {'path': 'Models/lib/FireStationLg.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Misc_Buildings/Fire_Station_Sm.agp": {'path': 'Models/lib/cube16x10.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Misc_Buildings/Large_Office_1.agp": {'path': 'Models/lib/office112x50.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Misc_Buildings/Med_Office_1.agp": {'path': 'Models/lib/office65x50.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Misc_Buildings/Small_Office_1.agp": {'path': 'Models/lib/office32x25.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Misc_Buildings/Small_Office_2.agp": {'path': 'Models/lib/office40x25.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Misc_Buildings/Small_Office_3.agp": {'path': 'Models/lib/office32x25n.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Miscellaneous/Barrel_Trash_Can.obj": {'path': 'Models/StreetFurniture/Litter_Bin.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Blue_Dumpster.obj": {'path': 'Models/StreetFurniture/trash-container.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Blue_Dumpster_w_wall.obj": {'path': 'Models/StreetFurniture/trash-container.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/com_Const_Trailer.obj": {'path': 'Models/lib/office16x4n.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Miscellaneous/Const_Trailer.agp": {'path': 'Models/lib/office16x4n.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Miscellaneous/Flagpole.obj": {'path': 'Models/Misc/FlagpoleFG.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/One_Traffic_Cone.obj": {'path': 'Models/lib/cone.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Pad_Tansformer.obj": {'path': 'Models/Airport/switch_control_cabinet.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Picnic_Table.obj": {'path': 'Models/Misc/picnic_table.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Round_Trash_Can.obj": {'path': 'Models/StreetFurniture/Litter_Bin.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Sm_Propane_Tank.obj": {'path': 'Models/lib/propane-tank.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Miscellaneous/Square_Trash_Can.obj": {'path': 'Models/StreetFurniture/Litter_Bin.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Stack_of_Cones.obj": {'path': 'Models/lib/stack_of_cones.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Tree.obj": {'path': 'Models/Trees/platanus_acerifolia_15m.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/TreeTest.obj": {'path': 'Models/Trees/platanus_acerifolia_15m.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Miscellaneous/Water_Tank_Elev.obj": {'path': 'Models/lib/watertank3x1.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Parking/1_Space_Dual.obj": {'path': 'Models/lib/1space_dual.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/10_Spaces_dual.obj": {'path': 'Models/lib/10_spaces_dual.ac', 'alt-offset': 0, 'hdg-offset': 180}, + "lib/airport/Common_Elements/Parking/20_Spaces_dual.obj": {'path': 'Models/lib/20_spaces_dual.ac', 'alt-offset': 0, 'hdg-offset': 180}, + "lib/airport/Common_Elements/Parking/2_Spaces_Dual.obj": {'path': 'Models/lib/2_spaces_dual.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/2space_wStop.obj": {'path': 'Models/lib/2space_wStop.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/4_Spaces_Dual.obj": {'path': 'Models/lib/4_spaces_dual.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/4space_wStop.obj": {'path': 'Models/lib/4space_wStop.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/6space_wStop.obj": {'path': 'Models/lib/6space_wStop.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/Bollard.obj": {'path': 'Models/StreetFurniture/EDDI-cone.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Parking_Items/14_Single_Spaces.agp": {'path': 'Models/lib/cars14.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking_Items/7_Single_Spaces.agp": {'path': 'Models/lib/cars7.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking_Items/Row_of_Cars_10.agp": {'path': 'Models/lib/cars10.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking_Items/Row_of_Cars_2.agp": {'path': 'Models/lib/cars2.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking_Items/Row_of_Cars_4.agp": {'path': 'Models/lib/cars4.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking_Items/Row_of_Cars_6.agp": {'path': 'Models/lib/cars6.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/NoParkStripes.obj": {'path': 'Models/lib/NoParkStripes.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/Yellow_Triangle-1.obj": {'path': 'Models/lib/YellowTriangle1.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/Yellow_Triangle-2.obj": {'path': 'Models/lib/YellowTriangle2.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Vehicles/Cargo_Trailer.obj": {'path': 'Models/lib/trailer-fedex.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Vehicles/Cargo_Truck_Long.agp": {'path': 'Models/lib/trailer-ups.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Vehicles/Cargo_Truck.obj": {'path': 'Models/Transport/Norberttruck.xml', 'alt-offset': 0, 'hdg-offset': 270}, + "lib/airport/Common_Elements/vehicles/Large_Fuel_Truck.obj": {'path': 'Models/lib/fuel-truck.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/vehicles/Small_Fuel_Truck.obj": {'path': 'Models/lib/fuel-truck.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Water_Towers/1990.obj": {'path': 'Models/Airport/water-tower-150-red-white.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Water_Towers/com_WT_1930_fence.obj": {'path': 'Models/Airport/water-tower-150-red-white.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Water_Towers/com_WT_1930.obj": {'path': 'Models/Airport/water-tower-90-red-white.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Water_Towers/com_WT_1960.obj": {'path': 'Models/Airport/water-tower-90-red-white.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Water_Towers/com_WT_fence.obj": {'path': 'Models/Airport/water-tower-90-red-white.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Water_Towers/Water_Tower_1930.agp": {'path': 'Models/Airport/water-tower-90-red-white.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Common_Elements/Water_Towers/Water_Tower_1960.agp": {'path': 'Models/Airport/water-tower-90-red-white.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/landscape/apron_light.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/lights/slow/helipad_edge.obj": {'path': 'Models/Effects/GreenLight6000.xml', 'alt-offset': 0.5, 'hdg-offset': 0}, + "lib/airport/lights/slow/taxi_edge.obj": {'path': 'Models/Effects/taxilampblue.xml', 'alt-offset': 0.5, 'hdg-offset': 0}, + "lib/airport/lights/slow/rway_guard.obj": {'path': 'Models/lib/rw-guard-lights.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/250cm_Jetway_Group.agp": {'path': 'Models/Airport/Jetway/jetway.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/400cm_Jetway_2.agp": {'path': 'Models/Airport/Jetway/jetway.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/400cm_Jetway_3.agp": {'path': 'Models/Airport/Jetway/jetway.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/400cm_Jetway_Group.agp": {'path': 'Models/Airport/Jetway/jetway.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/500cm_Jetway_Group.agp": {'path': 'Models/Airport/Jetway/jetway.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/Belt_Loader.obj": {'path': 'Models/lib/belt_loader.ac', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Ramp_Equipment/Cargo_Container_1.obj": {'path': 'Models/lib/cargo-container1-HD.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Cargo_Container_6.obj": {'path': 'Models/lib/container6-HD.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Cargo_Dolly_1.obj": {'path': 'Models/lib/cargo-dolly1-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Cargo_Dolly_wPod.obj": {'path': 'Models/lib/CargoDollyWithContainer.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Cargo_Loader_1.obj": {'path': 'Models/lib/loader.ac', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Ramp_Equipment/Cargo_Palette_1.obj": {'path': 'Models/Airport/cargobox.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Cargo_Palette_2.obj": {'path': 'Models/Airport/cargoip.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Cargo_Palette_3.obj": {'path': 'Models/Airport/cargoim.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Cargo_Pallete_Pkng.agp": {'path': 'Models/lib/cargo-dolly-parking-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Cargo_Pod_Lot.agp": {'path': 'Models/lib/cargo_pod_lot.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Cargo_Pod_Pkng.obj": {'path': 'Models/lib/CargoPodPkng.ac', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Ramp_Equipment/GPU_1.obj": {'path': 'Models/Airport/Vehicle/generic-trailer-GPU.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Jetway_250cm.obj": {'path': 'Models/Airport/Jetway/jetway.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/Jetway_400cm.obj": {'path': 'Models/Airport/Jetway/jetway.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/Jetway_500cm.obj": {'path': 'Models/Airport/Jetway/jetway.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/JetWayEx_10m.obj": {'path': 'Models/lib/jetway_e10m.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/JetWayEx_12m.obj": {'path': 'Models/lib/jetway_e12m.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/JetWayEx_14m.obj": {'path': 'Models/lib/jetway_e14m.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/JetWayEx_16m.obj": {'path': 'Models/lib/jetway_e16m.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/JetWayEx_8m.obj": {'path': 'Models/lib/jetway_e8m.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/JetWayExt_4m.obj": {'path': 'Models/lib/jetway_e4m.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/JetWayWallBase.obj": {'path': 'Models/lib/JetWayWallBase.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Luggage_Cart.obj": {'path': 'Models/lib/luggage-cart-HD.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Luggage_Cart_Pkng.obj": {'path': 'Models/lib/LuggCartPkng.ac', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/airport/Ramp_Equipment/Luggage_Truck.obj": {'path': 'Models/lib/luggage-truck-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Cart_Group.obj": {'path': 'Models/lib/LuggCartGroup.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Train_3.obj": {'path': 'Models/lib/chariot3curve.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Train_Group.obj": {'path': 'Models/lib/caisses_group.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Train_Straight1.obj": {'path': 'Models/lib/luggage-truck-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Train_Straight2.obj": {'path': 'Models/lib/luggage-train-straight2-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Train_Straight3.obj": {'path': 'Models/lib/luggage-train-straight2-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Train_Straight4.obj": {'path': 'Models/lib/luggage-train-straight2-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Train_Straight5.obj": {'path': 'Models/lib/luggage-train-straight2-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Lugg_Train_Straight.obj": {'path': 'Models/lib/luggage-train-straight2-HD.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Ramp_Equipment/Ramp_Group_Medium.agp": {'path': 'Models/lib/RampGroup.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Ramp_Group_Narrow.agp": {'path': 'Models/lib/RampGroup.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Ramp_Group_Wide.agp": {'path': 'Models/lib/RampGroup.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Ramp_Parking.obj": {'path': 'Models/lib/RampParking.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Ramp_Parking_Stripe.obj": {'path': 'Models/lib/RampParkingStripe.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/airport/Ramp_Equipment/Uni_Jetway_250cm.obj": {'path': 'Models/Airport/Jetway/jetway-movable.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/Uni_Jetway_400cm.obj": {'path': 'Models/Airport/Jetway/jetway-movable.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Ramp_Equipment/Uni_Jetway_500cm.obj": {'path': 'Models/Airport/Jetway/jetway-movable.xml', 'alt-offset': 0, 'hdg-offset': 202}, + "lib/airport/Vintage_Airports/Hangars/Corrugated_Row.agp": {'path': 'Models/lib/hangar81x16.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Vintage_Airports/Terminals/Admin_Bldg.obj": {'path': 'Models/lib/admin31x12.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Vintage_Airports/Terminals/Admin_Bldg.agp": {'path': 'Models/lib/admin-with-cars.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/cars/car.obj": {'path': 'CAR', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/cars/car_or_truck.obj": {'path': 'CAR', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/cars/car_or_truck_static.obj": {'path': 'CAR', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/cars/car_static_invar.obj": {'path': 'CAR', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/cars/car_static.obj": {'path': 'CAR', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/forests/autogen_tree1.obj": {'path': 'Models/lib/deciduous-tree.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/forests/autogen_tree2.obj": {'path': 'Models/lib/deciduous-tree2.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/forests/autogen_tree3.obj": {'path': 'Models/lib/deciduous-tree3.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/forests/autogen_tree4.obj": {'path': 'Models/Trees/billboard-tree.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/forests/autogen_tree_any.obj": {'path': 'Models/Trees/billboard-tree.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/global_objects/CafeTbls2x2.obj": {'path': 'Models/Misc/picnic_table.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/global_objects/CafeTbls4x2.obj": {'path': 'Models/Misc/picnic_table.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/global_objects/DkGrpMed.obj": {'path': 'Models/Misc/picnic_table.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/global_objects/LawnGrpMed.obj": {'path': 'Models/Misc/picnic_table.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/global_objects/rubbish_bin.obj": {'path': 'Models/StreetFurniture/Litter_Bin.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/global_objects/vending_machine_X2.obj": {'path': 'Models/lib/vending-machine.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/global_objects/vending_machine.obj": {'path': 'Models/lib/2vending-machines.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/streetlights/AreaFloodHighMast.obj": {'path': 'Models/Airport/Apronlamp16m360deg.xml', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/streetlights/AreaFloodLrg.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/AreaFloodMed.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/AreaFloodShort.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/AreaFloodSml.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/HwyLt1BarMnt.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/HwyLt3BarMnt.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/HwyLt2GndMnt.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/HwyLt1GndMnt.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/ParkingLot.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/PrimaryLt1.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/ResLt1.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/ResLt1V1.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/ResLt1V2.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/ResLt2Dim.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/ResLt2.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/ResLt3.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/ResShort.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/RmpLt1BarMnt.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/RmpLt1GndMnt.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/RmpLt2BarMnt.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/streetlights/RmpLt2GndMnt.obj": {'path': 'Models/lib/lamp10m.xml', 'alt-offset': 0, 'hdg-offset': -90}, + "lib/g10/US/commercial/canopy_76.obj": {'path': 'Models/lib/canopy18x8.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/commercial/canopy_benzoil.obj": {'path': 'Models/lib/canopy17x14.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/commercial/canopy_bp_large.obj": {'path': 'Models/lib/canopy18x8.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/commercial/canopy_bp_small.obj": {'path': 'Models/lib/canopy38x8.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/commercial/canopy_ozgas.obj": {'path': 'Models/lib/canopy18x10.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/commercial/fuel_pump_76.obj": {'path': 'Models/Airport/Avgas_Pump.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/commercial/fuel_pump_benzoil.obj": {'path': 'Models/Airport/Avgas_Pump.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/commercial/fuel_pump_bp.obj": {'path': 'Models/Airport/Avgas_Pump.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/commercial/fuel_pump_ozgas.obj": {'path': 'Models/Airport/Avgas_Pump.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/TinShed10x30Lt.obj": {'path': 'Models/lib/hangarUL10x30.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/TinShed10x30Dk.obj": {'path': 'Models/lib/hangarUL10x30.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/TinShed10x50.obj": {'path': 'Models/lib/shed10x50.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/FactB10x30D.obj": {'path': 'Models/lib/hangarUL10x30.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/MineralsPile.obj": {'path': 'Models/lib/coal_pile.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/OilDrums.obj": {'path': 'Models/Misc/6barrels.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/industrial/light/SandBunker.obj": {'path': 'Models/lib/coal_pile.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/SiteOffice3x10.obj": {'path': 'Models/lib/office3x10.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/industrial/light/SiteOffice4x14.obj": {'path': 'Models/lib/office4x14.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/industrial/light/SiteOffice6x12.obj": {'path': 'Models/lib/office6x12.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/industrial/light/SiteOffice8x14.obj": {'path': 'Models/lib/office8x14.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/industrial/light/StorHut3x3.obj": {'path': 'Models/lib/transformer3x3.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/industrial/light/GateHut3x3.obj": {'path': 'Models/lib/transformer3x3.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/industrial/light/WoodShed8x10.obj": {'path': 'Models/lib/shed8x10.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/WoodShed8x20.obj": {'path': 'Models/lib/shed8x10.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/SecBarrier.obj": {'path': 'Models/lib/schranke.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/TrailerSnglShrtFlat.obj": {'path': 'Models/lib/office3x10.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/suburban/TrailerSnglShrtPtch.obj": {'path': 'Models/lib/office3x10.ac', 'alt-offset': 0, 'hdg-offset': 0}, + "lib/g10/US/suburban/B-RnchLH.obj": {'path': 'Models/lib/farm19x12.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/B-RnchLHGry.obj": {'path': 'Models/lib/farm19x12.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/dB-RnchLH.obj": {'path': 'Models/lib/farm19x12.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/dB-RnchLHGry.obj": {'path': 'Models/lib/farm19x12.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/Shed13x24.obj": {'path': 'Models/lib/industrial13x24.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/FactA15x22.obj": {'path': 'Models/lib/industrial15x22.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/Greenhse.obj": {'path': 'Models/lib/dGreenhse.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/dGreenhse.obj": {'path': 'Models/lib/dGreenhse.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/ships/SailBoat.obj": {'path': 'Models/Maritime/Civilian/red-sailing-boat.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/ships/OilRig.obj": {'path': 'Models/lib/OilRig.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/ships/OilPlatform.obj": {'path': 'Models/lib/OilPlatform.xml', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/lights/slow/MIRL_ww.obj": {'path': 'Models/lib/taxilight-HD-ww.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/1_CarStop.obj": {'path': 'Models/lib/1car-stop.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/2_Space_Dual.obj": {'path': 'Models/lib/2_spaces_dual.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/general_aviation/prop_a.obj": {'path': 'Models/lib/prop_a.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/cargo/prop_a.obj": {'path': 'Models/lib/prop_a.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/airliners/prop_a.obj": {'path': 'Models/lib/prop_a.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/TrailerSnglLong.obj": {'path': 'Models/lib/2container-office.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/TrailerDblLong.obj": {'path': 'Models/lib/4container-office.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Common_Elements/Parking/Handicap_Sign.obj": {'path': 'Models/lib/handicap-sign.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/lights/slow/MIRL_yy.obj": {'path': 'Models/lib/taxilight-HD-yy.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/lights/slow/MIRL_ry.obj": {'path': 'Models/lib/taxilight-HD-yy.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/lights/slow/MIRL_yw.obj": {'path': 'Models/lib/taxilight-HD-ww.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/Vintage_Airports/Hangars/Lg_Open_Ends.obj": {'path': 'Models/lib/large-hangar.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/StorSml2p0.obj": {'path': 'Models/lib/garages18x9.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/industrial/light/StorSml2p3.obj": {'path': 'Models/lib/garages22x9.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/GdnShed.obj": {'path': 'Models/lib/garden-shed.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/dGdnShed.obj": {'path': 'Models/lib/garden-shed.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/GrgSmlWht.obj": {'path': 'Models/lib/garage-small-white.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/g10/US/suburban/dGrgSmlWht.obj": {'path': 'Models/lib/garage-small-white.ac', 'alt-offset': 0, 'hdg-offset': 90}, + "lib/airport/aircraft/military/fighter_a.obj": {'path': 'Models/Aircraft/F-15-lowres.ac', 'alt-offset': 0, 'hdg-offset': 0}, +} + diff --git a/install.py b/install.py deleted file mode 100755 index 4621bf4..0000000 --- a/install.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 -#-*- coding:utf-8 -*- - -# Installer script for the main scripts and modules of fgtools -import os -import sys -import argparse -import shutil -import site - -from fgtools.utils import constants - -argp = argparse.ArgumentParser(description="install.py - installs the TerraGear tools so that they can be run like any other executable") - -argp.add_argument( - "-p", "--prefix", - help="Installation prefix (default: %(default)s)", - default=os.environ.get("FGTOOLSPREFIX", os.path.join(constants.HOME, ".local"))) -) - -argp.add_argument( - "--add-to-path", - help="whether to modify your $HOME/.profile file to have the folder containing the scripts in your path (default: %(default)s", - default="yes", - choices=["yes", "no"] -) - -args = argp.parse_args() - -SCRIPTDIR = os.path.dirname(os.path.abspath(__name__)) -BINDIR = os.path.join(args.prefix, "bin") -PYLIBDIR = os.path.join(args.prefix, "lib", "python3") - -print(f"Installing to {args.prefix}") - -print("Installing modules …") -shutil.copytree(os.path.join(SCRIPTDIR, constants.MODULE), PYLIBDIR) - -print("Installing scripts …") -for script in constants.SCRIPTS: - shutil.copy2(os.path.join(SCRIPTDIR, script), BINDIR) - -if not BINDIR in os.environ.get("PATH", "").split(os.pathsep): - if args.add_to_path: - print(f"Adding {BINDIR} to your $PATH …") - - if os.name == "posix": # Linux, MacOS - with open(os.path.join(constants.HOME, ".profile"), "a") as f: - f.write(f"export PATH=\"$PATH{os.pathsep}{BINDIR}\"") - else: # probably Windows - os.system(f"setx PATH \"%PATH%{os.pathsep}{BINDIR}\"") - else: - print(f"WARNING: {BINDIR} was not added to your $PATH - please do that manually") - -if not LIBDIR in os.environ.get("PYTHONPATH", "").split(os.pathsep): - print(f"Adding {LIBDIR} to your $PYTHONPATH …") - - if not os.path.isdir(site.USER_SITE): - os.mkdirs(site.USER_SITE) - - mode = "a" - if not os.path.isfile(os.path.join(site.USER_SITE, "sitecustomize.py")): - mode = "w" - - with open(os.path.join(site.USER_SITE, "sitecustomize.py"), mode) as f: - f.write(f"import site; site.addsitedir({LIBDIR})") diff --git a/scenery/dsftxt2stg.py b/scenery/dsftxt2stg.py new file mode 100755 index 0000000..21ae44f --- /dev/null +++ b/scenery/dsftxt2stg.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +import os +import argparse +import random +import sys + +from fgtools.dsf2stg_lookup import lookup +from fgtools import utils + +cars = [ + "hatchback_red.ac", + "hatchback_blue.ac", + "hatchback_black.ac", + "hatchback_black.ac", + "hatchback_silver.ac", + "hatchback_silver.ac", + "hatchback_green.ac", + "van_blue_dirty.ac", + "van_red.ac", + "van_silver.ac" +] + +cessnas = [ + "Cessna172.ac", + "Cessna172_blue.ac", + "Cessna172_green.ac", + "Cessna172_red.ac", + "Cessna172_sky.ac", + "Cessna172_yellow.ac", + "Cessna150_no_reg.ac" +] + + +def find_txt_files(path): + found = [] + for root, folders, files in os.walk(path): + for f in files: + if f.endswith(".txt"): + found.append(os.path.join(root, f)) + return found + +def parse_txt_file(path): + with open(path) as f: + content = list(map(str.strip, f.readlines())) + + objpaths = [] + for line in content: + if line.startswith("OBJECT_DEF"): + objpaths.append(line.split()[1]) + + objects = [] + for line in content: + if line.startswith("OBJECT "): + line = line.split() + objects.append({"path": objpaths[int(line[1])], "lon": float(line[2]), "lat": float(line[3]), "hdg": float(line[4])}) + + return objects + +def parse_txt_files(files): + objects = [] + total = len(files) + i = 1 + for f in files: + print(f"\rParsing DSF/TXT files … {i / total * 100:.1f}% ({i} of {total})", end="") + sys.stdout.flush() + objects += parse_txt_file(f) + i += 1 + print() + return objects + +def calc_object_elevs(objects, fgelev_pipe): + total = len(objects) + i = 1 + for o in objects: + print(f"\rCalculating object elevations … {i / total * 100:.1f}% ({i} of {total})", end="") + sys.stdout.flush() + fgelev_pipe.stdin.write(f"{o['path']} {o['lon']} {o['lat']}\n".encode("utf-8")) + fgelev_pipe.stdin.flush() + fgelevout = fgelev_pipe.stdout.readline().split() + if len(fgelevout) == 2: + o["alt"] = float(fgelevout[1]) + else: + print(f"\rReceived unusable output from FGElev: {fgelevout} for longitude {o['lon']} and latitude {o['lat']} - skipping object") + print(f"\rCalculating object elevations … {i / total * 100:.1f}% ({i} of {total})", end="") + i += 1 + print() + return objects + +def group_objects_by_tile(objects): + tiles = {} + for o in objects: + tile_index = utils.get_fg_tile_index(o["lon"], o["lat"]) + if not tile_index in tiles: + tiles[tile_index] = [] + tiles[tile_index].append(o) + + return tiles + +def write_stg_files(objects, output): + total = len(objects) + i = 1 + not_found_xpaths = [] + for tile_index in objects: + print(f"\rWriting STG files … {i / total * 100:.1f}% ({i} of {total})", end="") + sys.stdout.flush() + stgpath = os.path.join(output, utils.get_fg_tile_path(objects[tile_index][0]["lon"], objects[tile_index][0]["lat"]) + ".stg") + os.makedirs(os.path.join(*os.path.split(stgpath)[:-1]), exist_ok=True) + with open(stgpath, "w") as f: + for o in objects[tile_index]: + opath = lookup.get(o["path"], None) + if not opath: + if o["path"] not in not_found_xpaths: + print(f"\rNo FlightGear model found for XPlane model {o['path']} - skipping") + print(f"\rWriting STG files … {i / total * 100:.1f}% ({i} of {total})", end="") + not_found_xpaths.append(o["path"]) + continue + + opath = opath["path"] + + if opath == "CAR": + opath = "Models/Transport/" + random.choice(cars) + elif opath == "CESSNA": + opath = "Models/Aircraft/" + random.choice(cessnas) + + f.write(f"OBJECT_SHARED {opath} {o['lon']} {o['lat']} {o['alt'] + lookup[o['path']]['alt-offset']} {o['hdg'] + lookup[o['path']]['hdg-offset']}\n") + i += 1 + print() + +if __name__ == "__main__": + argp = argparse.ArgumentParser(description="Convert XPlane scenery DSF/TXT files to FlightGear scenery STG files") + + argp.add_argument( + "-i", "--input", + help="Input DSF/TXT file or directory containing such files", + required=True, + nargs="+" + ) + + argp.add_argument( + "-o", "--output", + help="Output directory to put produced STG files into", + required=True + ) + + argp.add_argument( + "-s", "--fgscenery", + help="Path to FlightGear scenery directories containing Terrain, more than one directory can be passed.", + nargs="+", + default=["~/TerraSync", "~/TerraSync/TerraSync", "TerraSync", "TerraSync/TerraSync"] + ) + + argp.add_argument( + "-d", "--fgdata", + help="Path to FlightGear data directory.", + default="~/fgdata" + ) + + argp.add_argument( + "-e", "--fgelev", + help="Name of / path to fgelev executable", + default="fgelev", + ) + + args = argp.parse_args() + + print("Searching for DSF/TXT files … ", end="") + sys.stdout.flush() + txt_files = [] + for i in args.input: + if os.path.isdir(i): + txt_files += find_txt_files(i) + elif os.path.isfile(i): + txt_files.append(i) + else: + print(f"\rInput file / directory {i} does not exist - skipping\nSearching for DSF/TXT files … ", end="") + print(f"done, found {len(txt_files)} files") + + objects = parse_txt_files(txt_files) + print("Connecting to fgelev … ", end="") + sys.stdout.flush() + fgelev_pipe = utils.make_fgelev_pipe(args.fgelev, args.fgscenery, args.fgdata) + print("done") + elev_objects = calc_object_elevs(objects, fgelev_pipe) + print("Grouping objects by tile … ", end="") + sys.stdout.flush() + stg_groups = group_objects_by_tile(elev_objects) + print("done") + write_stg_files(stg_groups, args.output) diff --git a/scenery/edit-stg.py b/scenery/edit-stg.py index f40a12a..0956d5e 100755 --- a/scenery/edit-stg.py +++ b/scenery/edit-stg.py @@ -7,22 +7,13 @@ import os import subprocess import time +from fgtools.utils import make_fgelev_pipe + class SkipReason: NotFound = 0 DirEmpty = 1 NoSTG = 2 -def make_fgelev_pipe(fgelev, fgscenery, fgdata): - env = os.environ.copy() - env["FG_SCENERY"] = os.pathsep.join(fgscenery) - env["FG_DATA"] = fgdata[0] - pipe = subprocess.Popen(args=[fgelev, "--expire", "1"], env={**env, **os.environ}, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - pipe.stdout.flush() - pipe.stdout.readline() - pipe.stdin.flush() - pipe.stdin.flush() - return pipe - def read_stg_file(path): result = [] offset = 0 @@ -191,7 +182,6 @@ def main(): argp.add_argument( "-d", "--fgdata", help="Path to FlightGear data directory.", - nargs=1, default="~/fgdata" ) diff --git a/utils/__init__.py b/utils/__init__.py index 4cc8134..f32c4ec 100755 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -2,6 +2,8 @@ #-*- coding:utf-8 -*- import math +import os +import subprocess def get_fg_tile_span(lat): if lat >= 89: @@ -31,9 +33,72 @@ def get_fg_tile_span(lat): else: return 12 -def get_fg_tile_index(lon, lat): - tile_width = get_fg_tile_span(lat) - x = math.floor((lon - math.floor(math.floor(lon / tile_width) * tile_width)) / tile_width) - y = trunc((lat - math.floor(lat)) + 8) +def get_fg_tile_index(dlon, dlat): + tile_width = get_fg_tile_span(dlat) + lon = math.floor(dlon) + lat = math.floor(dlat) + if tile_width <= 1: + x = math.floor((dlon - lon) / tile_width) + else: + lon = int(math.floor(lon / tile_width) * tile_width) + x = 0 + + if lat == 90: + lat = 89 + y = 7 + else: + y = math.floor((dlat - math.floor(dlat)) * 8) + return ((lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x + +def get_fg_tile_coords(index): + lon = index >> 14; + index -= lon << 14; + lon -= 180; + + lat = index >> 6; + index -= lat << 6; + lat -= 90; + + return lon, lat + +def get_fg_tile_path(lon, lat): + top_lon = int(lon / 10); + main_lon = int(lon); + if (lon < 0) and (top_lon * 10 != lon): + top_lon -= 1; + top_lon *= 10 + if top_lon >= 0: + hem = "e" + else: + hem = "w" + top_lon *= -1; + if main_lon < 0: + main_lon *= -1 + + top_lat = int(lat / 10) + main_lat = int(lat) + if (lat < 0) and (top_lat * 10 != lat): + top_lat -= 1 + top_lat *= 10 + if top_lat >= 0: + pole = "n" + else: + pole = "s" + top_lat *= -1 + if main_lat < 0: + main_lat *= -1 + + return f"{hem}{int(top_lon):03d}{pole}{int(top_lat):02d}/{hem}{int(main_lon):03d}{pole}{int(main_lat):02d}/{get_fg_tile_index(lon, lat)}" + +def make_fgelev_pipe(fgelev, fgscenery, fgdata): + env = os.environ.copy() + env["FG_SCENERY"] = os.pathsep.join(fgscenery) + env["FG_ROOT"] = fgdata + pipe = subprocess.Popen(args=[fgelev, "--expire", "1"], env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + pipe.stdout.flush() + pipe.stdout.readline() + pipe.stdin.flush() + pipe.stdin.flush() + return pipe diff --git a/utils/constants.py b/utils/constants.py index 63228d5..9e14e6c 100755 --- a/utils/constants.py +++ b/utils/constants.py @@ -5,8 +5,6 @@ import os import sys HOME = os.environ.get("HOME", os.path.expanduser("~")) -SCRIPTS = ["process-shapefiles.py", "process-elevations.py"] -MODULE = "tgtools" __version__ = (1, 0, 0) __versionstr__ = ".".join(map(str, __version__))