diff --git a/Makefile.lin64 b/Makefile.lin64 index 75c8963..ee5f309 100644 --- a/Makefile.lin64 +++ b/Makefile.lin64 @@ -9,11 +9,14 @@ TARGET_XP12=$(OBJDIR)/openSAM.xpl TARGET_XP11=$(OBJDIR)/openSAM.xpl_xp11 HEADERS=$(wildcard *.h) -SOURCES=openSAM.c os_dgs.c os_jw.c os_ui.c os_anim.c sam_xml.c log_msg.c read_wav.c -OBJECTS=$(addprefix $(OBJDIR)/, $(SOURCES:.c=.o)) +SOURCES=openSAM.cpp os_dgs.cpp os_jw.cpp os_ui.cpp os_anim.cpp sam_xml.cpp log_msg.cpp read_wav.cpp +OBJECTS:=$(addprefix $(OBJDIR)/, $(SOURCES:.cpp=.o)) OBJECTS_XP12=$(OBJECTS) $(OBJDIR)/os_sound.o OBJECTS_XP11=$(OBJECTS) $(OBJDIR)/os_sound_xp11.o +CXX=g++ +LD=g++ + CFLAGS=-DVERSION=\"$(VERSION)\" \ -Wall -Wextra -Wno-format-overflow -Wno-format-truncation \ -I$(SDK)/CHeaders/XPLM -I$(SDK)/CHeaders/Widgets -O2 -fPIC -DLIN=1 -fno-stack-protector @@ -24,8 +27,8 @@ LIBS=-lexpat all: $(TARGET_XP12) $(TARGET_XP11) $(shell [ -d $(OBJDIR) ] || mkdir $(OBJDIR)) -$(OBJDIR)/%.o: %.c version.mak - $(CC) $(CFLAGS) -o $@ -c $< +$(OBJDIR)/%.o: %.cpp version.mak + $(CXX) $(CFLAGS) -o $@ -c $< $(TARGET_XP12): $(OBJECTS_XP12) $(CC) -o $(TARGET_XP12) $(LNFLAGS) $(OBJECTS_XP12) $(LIBS) diff --git a/Makefile.mac64 b/Makefile.mac64 index 3911822..87678d0 100644 --- a/Makefile.mac64 +++ b/Makefile.mac64 @@ -14,19 +14,19 @@ TARGET_XP12=$(OBJDIR)/openSAM.xpl TARGET_XP11=$(OBJDIR)/openSAM.xpl_xp11 HEADERS=$(wildcard *.h) -SOURCES=openSAM.c os_dgs.c os_jw.c os_ui.c os_anim.c sam_xml.c log_msg.c read_wav.c -OBJECTS_XP12_arm=$(addprefix $(OBJDIR)/, $(SOURCES:.c=.o_arm)) $(OBJDIR)/os_sound.o_arm +SOURCES=openSAM.cpp os_dgs.cpp os_jw.cpp os_ui.cpp os_anim.cpp sam_xml.cpp log_msg.cpp read_wav.cpp +OBJECTS_XP12_arm=$(addprefix $(OBJDIR)/, $(SOURCES:.cpp=.o_arm)) $(OBJDIR)/os_sound.o_arm OBJECTS_XP12_x86=$(OBJECTS_XP12_arm:.o_arm=.o_x86) -OBJECTS_XP11_arm=$(addprefix $(OBJDIR)/, $(SOURCES:.c=.o_arm)) $(OBJDIR)/os_sound_xp11.o_arm +OBJECTS_XP11_arm=$(addprefix $(OBJDIR)/, $(SOURCES:.cpp=.o_arm)) $(OBJDIR)/os_sound_xp11.o_arm OBJECTS_XP11_x86=$(OBJECTS_XP11_arm:.o_arm=.o_x86) -CCx=clang -target x86_64-apple-macos11 -CCa=clang -target arm64-apple-macos11 +CCx=clang++ -target x86_64-apple-macos11 +CCa=clang++ -target arm64-apple-macos11 DEFS= -DAPL=1 -fPIC -fno-stack-protector -fvisibility=hidden -ffast-math -DNDEBUG -Wno-deprecated-declarations -CFLAGS+=-O2 -Wall -I$(SDK)/CHeaders/XPLM -I$(SDK)/CHeaders/Widgets -DVERSION=\"$(VERSION)\" $(DEFS) +CFLAGS+=-std=c++17 -O2 -Wall -I$(SDK)/CHeaders/XPLM -I$(SDK)/CHeaders/Widgets -DVERSION=\"$(VERSION)\" $(DEFS) LNFLAGS+=-dynamiclib -shared -rdynamic -fvisibility=hidden -Wl,-exported_symbols_list -Wl,linkscript.mac @@ -42,10 +42,10 @@ LIBS+=/opt/local/lib/libexpat.a all: $(TARGET_XP12) $(TARGET_XP11) $(shell [ -d $(OBJDIR) ] || mkdir $(OBJDIR)) -$(OBJDIR)/%.o_arm: %.c version.mak +$(OBJDIR)/%.o_arm: %.cpp version.mak $(CCa) $(CFLAGS) -o $@ -c $< -$(OBJDIR)/%.o_x86: %.c version.mak +$(OBJDIR)/%.o_x86: %.cpp version.mak $(CCx) $(CFLAGS) -o $@ -c $< $(TARGET_XP12)_arm: $(OBJECTS_XP12_arm) diff --git a/Makefile.mgw64 b/Makefile.mgw64 index db4155c..5b465ae 100644 --- a/Makefile.mgw64 +++ b/Makefile.mgw64 @@ -11,32 +11,32 @@ TARGET_XP12=$(OBJDIR)/openSAM.xpl TARGET_XP11=$(OBJDIR)/openSAM.xpl_xp11 HEADERS=$(wildcard *.h) -SOURCES=openSAM.c os_dgs.c os_jw.c os_ui.c os_anim.c sam_xml.c log_msg.c read_wav.c -OBJECTS:=$(addprefix $(OBJDIR)/, $(SOURCES:.c=.o)) +SOURCES=openSAM.cpp os_dgs.cpp os_jw.cpp os_ui.cpp os_anim.cpp sam_xml.cpp log_msg.cpp read_wav.cpp +OBJECTS:=$(addprefix $(OBJDIR)/, $(SOURCES:.cpp=.o)) OBJECTS_XP12=$(OBJECTS) $(OBJDIR)/os_sound.o OBJECTS_XP11=$(OBJECTS) $(OBJDIR)/os_sound_xp11.o # all sources to the dep files -SOURCES_DEP=$(SOURCES) os_sound.c os_sound_xp11.c -DEPFILES=$(SOURCES_DEP:%.c=$(DEPDIR)/%.d) +SOURCES_DEP=$(SOURCES) os_sound.cpp os_sound_xp11.cpp +DEPFILES=$(SOURCES_DEP:%.cpp=$(DEPDIR)/%.d) DEPDIR := $(OBJDIR)/.deps DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d -CC=gcc -LD=gcc +CXX=g++ +LD=g++ CFLAGS+=-DVERSION=\"$(VERSION)\" -g0 -O2 -Wextra -Wall -fdiagnostics-color -Wno-format-overflow -Wno-format-truncation \ -DWINDOWS -DWIN32 -DIBM=1 \ -I$(SDK)/CHeaders/XPLM -I$(SDK)/CHeaders/Widgets -I$(OPENAL) -COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) -c +COMPILE.cpp = $(CXX) $(DEPFLAGS) $(CFLAGS) -c LDFLAGS=-shared -static-libgcc -static -lpthread LIBS=-L$(SDK)/Libraries/Win -lXPLM_64 -lXPWidgets_64 -l:libexpat.a -$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d version.mak | $(DEPDIR) - $(COMPILE.c) -o $@ $< +$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d version.mak | $(DEPDIR) + $(COMPILE.cpp) -o $@ $< install: install_xp12 install_xp11 @@ -64,7 +64,7 @@ install_xp11: $(TARGET_XP11) clean: rm -f ./$(OBJDIR)/* sam_xml_test.exe -sam_xml_test.exe: sam_xml_test.c sam_xml.c log_msg.c $(HEADERS) - $(CC) -Wall -fdiagnostics-color -Wno-format-overflow -I$(SDK)/CHeaders/XPLM -DIBM=1 \ +sam_xml_test.exe: sam_xml_test.cpp sam_xml.cpp log_msg.cpp $(HEADERS) + $(CXX) -Wall -fdiagnostics-color -Wno-format-overflow -I$(SDK)/CHeaders/XPLM -DIBM=1 \ -DWINDOWS -DWIN32 -DLOCAL_DEBUGSTRING -o sam_xml_test.exe \ - sam_xml_test.c sam_xml.c log_msg.c -l:libexpat.a + sam_xml_test.cpp sam_xml.cpp log_msg.cpp -l:libexpat.a diff --git a/Makefile.osxcross b/Makefile.osxcross index 1601abf..16a8fb9 100644 --- a/Makefile.osxcross +++ b/Makefile.osxcross @@ -12,15 +12,15 @@ OBJDIR=./OBJ_osx TARGET_XP12=$(OBJDIR)/openSAM.xpl TARGET_XP11=$(OBJDIR)/openSAM.xpl_xp11 HEADERS=$(wildcard *.h) -SOURCES=openSAM.c os_dgs.c os_jw.c os_ui.c os_anim.c sam_xml.c log_msg.c read_wav.c -OBJECTS_XP12_arm=$(addprefix $(OBJDIR)/, $(SOURCES:.c=.o_arm)) $(OBJDIR)/os_sound.o_arm +SOURCES=openSAM.cpp os_dgs.cpp os_jw.cpp os_ui.cpp os_anim.cpp sam_xml.cpp log_msg.cpp read_wav.cpp +OBJECTS_XP12_arm=$(addprefix $(OBJDIR)/, $(SOURCES:.cpp=.o_arm)) $(OBJDIR)/os_sound.o_arm OBJECTS_XP12_x86=$(OBJECTS_XP12_arm:.o_arm=.o_x86) -OBJECTS_XP11_arm=$(addprefix $(OBJDIR)/, $(SOURCES:.c=.o_arm)) $(OBJDIR)/os_sound_xp11.o_arm +OBJECTS_XP11_arm=$(addprefix $(OBJDIR)/, $(SOURCES:.cpp=.o_arm)) $(OBJDIR)/os_sound_xp11.o_arm OBJECTS_XP11_x86=$(OBJECTS_XP11_arm:.o_arm=.o_x86) -CCx=o64-clang -mmacosx-version-min=12.0 -CCa=oa64-clang -mmacosx-version-min=12.0 +CCx=o64-clang++ -mmacosx-version-min=12.0 +CCa=oa64-clang++ -mmacosx-version-min=12.0 DEFS= -DAPL=1 -fPIC -fno-stack-protector -fvisibility=hidden -ffast-math -DNDEBUG @@ -42,10 +42,10 @@ LIBS+= all: $(TARGET_XP12) $(TARGET_XP11) $(shell [ -d $(OBJDIR) ] || mkdir $(OBJDIR)) -$(OBJDIR)/%.o_arm: %.c version.mak +$(OBJDIR)/%.o_arm: %.cpp version.mak $(CCa) $(CFLAGS) -o $@ -c $< -$(OBJDIR)/%.o_x86: %.c version.mak +$(OBJDIR)/%.o_x86: %.cpp version.mak $(CCx) $(CFLAGS) -o $@ -c $< $(TARGET_XP12)_arm: $(OBJECTS_XP12_arm) diff --git a/log_msg.c b/log_msg.cpp similarity index 95% rename from log_msg.c rename to log_msg.cpp index 15b8731..bbff7ef 100644 --- a/log_msg.c +++ b/log_msg.cpp @@ -20,9 +20,9 @@ */ -#include -#include -#include +#include +#include +#include #ifdef LOCAL_DEBUGSTRING void diff --git a/openSAM.c b/openSAM.cpp similarity index 91% rename from openSAM.c rename to openSAM.cpp index bfe8c43..84377c4 100644 --- a/openSAM.c +++ b/openSAM.cpp @@ -20,12 +20,11 @@ */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "openSAM.h" #include "os_dgs.h" @@ -76,9 +75,8 @@ */ static int init_done, init_fail; -static char xp_dir[512]; -static char pref_path[512]; -static const char *psep; +static std::string xp_dir; +static std::string pref_path; static XPLMMenuID seasons_menu; static int auto_item, season_item[4]; static int auto_season; @@ -112,8 +110,8 @@ int auto_select_jws; float parked_x, parked_z; int parked_ngen; -float now; // current timestamp -char base_dir[512]; // base directory of openSAM +float now; // current timestamp +std::string base_dir; // base directory of openSAM int beacon_state, beacon_last_pos; // beacon state, last switch_pos, ts of last switch actions float beacon_off_ts, beacon_on_ts; @@ -132,14 +130,14 @@ unsigned long long stat_sc_far_skip, stat_far_skip, stat_near_skip, stat_acc_called, stat_jw_match, stat_dgs_acc, stat_dgs_acc_last, stat_anim_acc_called, stat_auto_drf_called; -XPLMProbeInfo_t probeinfo = {.structSize = sizeof(XPLMProbeInfo_t)}; +XPLMProbeInfo_t probeinfo; XPLMProbeRef probe_ref; XPLMMenuID anim_menu; static void save_pref() { - FILE *f = fopen(pref_path, "w"); + FILE *f = fopen(pref_path.c_str(), "w"); if (NULL == f) return; @@ -160,7 +158,7 @@ load_pref() season = 1; auto_select_jws = 1; - FILE *f = fopen(pref_path, "r"); + FILE *f = fopen(pref_path.c_str(), "r"); if (NULL == f) return; @@ -315,7 +313,7 @@ flight_loop_cb(float inElapsedSinceLastCall, anim_next_ts = now + anim_loop_delay; } - return MIN(anim_loop_delay, MIN(jw_loop_delay, dgs_loop_delay)); + return std::min(anim_loop_delay, std::min(jw_loop_delay, dgs_loop_delay)); } // set season according to date @@ -387,34 +385,27 @@ menu_cb(void *menu_ref, void *item_ref) save_pref(); } -static int -find_icao_in_file(const char *acf_icao, const char *dir, const char *fn, - char *line, int len) +static bool +find_icao_in_file(const char *acf_icao, const std::string& fn, std::string& line) { - char fn_full[512]; - snprintf(fn_full, sizeof(fn_full) - 1, "%s%s", dir, fn); - - int res = 0; - FILE *f = fopen(fn_full, "r"); - line[len-1] = '\0'; - if (f) { - log_msg("check whether acf '%s' is in file %s", acf_icao, fn_full); - while (fgets(line, len-1, f)) { - char *cptr = strchr(line, '\r'); - if (cptr) - *cptr = '\0'; - cptr = strchr(line, '\n'); - if (cptr) - *cptr = '\0'; - - if (line == strstr(line, acf_icao)) { - log_msg("found acf %s in %s", acf_icao, fn); - res = 1; + bool res = false; + std::ifstream f(fn); + if (f.is_open()) { + log_msg("check whether acf '%s' is in file %s", acf_icao, fn.c_str()); + + while (std::getline(f, line)) { + size_t i = line.find('\r'); + if (i != std::string::npos) + line.resize(i); + + if (line.find(acf_icao) == 0) { + log_msg("found acf %s in %s", acf_icao, fn.c_str()); + res = true; break; } } - fclose(f); + f.close(); } return res; @@ -426,6 +417,7 @@ XPluginStart(char *out_name, char *out_sig, char *out_desc) { log_msg("Startup " VERSION); + probeinfo.structSize = sizeof(XPLMProbeInfo_t); strcpy(out_name, "openSAM " VERSION); strcpy(out_sig, "openSAM.hotbso"); strcpy(out_desc, "A plugin that emulates SAM"); @@ -434,24 +426,17 @@ XPluginStart(char *out_name, char *out_sig, char *out_desc) XPLMEnableFeature("XPLM_USE_NATIVE_PATHS", 1); XPLMEnableFeature("XPLM_USE_NATIVE_WIDGET_WINDOWS", 1); - XPLMGetSystemPath(xp_dir); - psep = XPLMGetDirectorySeparator(); + char buffer[2048]; + XPLMGetSystemPath(buffer); + xp_dir = std::string(buffer); // set pref path - XPLMGetPrefsPath(pref_path); - XPLMExtractFileAndPath(pref_path); - strcat(pref_path, psep); - strcat(pref_path, "openSAM.prf"); + XPLMGetPrefsPath(buffer); + XPLMExtractFileAndPath(buffer); + pref_path = std::string(buffer) + "/openSAM.prf"; // get my base dir - XPLMGetPluginInfo(XPLMGetMyID(), NULL, base_dir, NULL, NULL); - char *cptr = strrchr(base_dir, '/'); - if (cptr) - *cptr = '\0'; - - cptr = strrchr(base_dir, '/'); - if (cptr) - *(cptr + 1) = '\0'; // keep / + base_dir = xp_dir + "Resources/plugins/openSAM/"; date_day_dr = XPLMFindDataRef("sim/time/local_date_days"); @@ -492,10 +477,13 @@ XPluginStart(char *out_name, char *out_sig, char *out_desc) load_pref(); - if (!collect_sam_xml(xp_dir)) + SceneryPacks scp(xp_dir); + if (! scp.valid) { + log_msg("Error collecting scenery_packs.ini!"); + } else if (!collect_sam_xml(scp)) log_msg("Error collecting sam.xml files!"); - log_msg("%d sceneries with sam jetways found", n_sceneries); + log_msg("%d sceneries with sam jetways found", (int)sceneries.size()); // if commands or dataref accessors are already registered it's to late to // fail XPluginStart as the dll is unloaded and X-Plane crashes @@ -658,13 +646,13 @@ XPluginReceiveMessage(XPLMPluginID in_from, long in_msg, void *in_param) return; // check whether acf is listed in exception files - char line[200]; - if (find_icao_in_file(acf_icao, base_dir, "acf_use_engine_running.txt", line, sizeof(line))) { + std::string line; line.reserve(200); + if (find_icao_in_file(acf_icao, base_dir + "acf_use_engine_running.txt", line)) { use_engine_running = 1; log_msg("found"); } - if (find_icao_in_file(acf_icao, base_dir, "acf_dont_connect_jetway.txt", line, sizeof(line))) { + if (find_icao_in_file(acf_icao, base_dir + "acf_dont_connect_jetway.txt", line)) { dont_connect_jetway = 1; log_msg("found"); } @@ -682,11 +670,10 @@ XPluginReceiveMessage(XPLMPluginID in_from, long in_msg, void *in_param) // check for a second door, seems to be not available by dataref // data in the acf file is often bogus, so check our own config file first - line[sizeof(line) - 1] = '\0'; - if (find_icao_in_file(acf_icao, base_dir, "acf_door_position.txt", line, sizeof(line))) { + if (find_icao_in_file(acf_icao, base_dir + "acf_door_position.txt", line)) { int d; float x, y, z; - if (4 == sscanf(line + 4, "%d %f %f %f", &d, &x, &y, &z)) { + if (4 == sscanf(line.c_str() + 4, "%d %f %f %f", &d, &x, &y, &z)) { if (d == 2) { // only door 2 for now d--; door_info[d].x = x; @@ -769,7 +756,7 @@ XPluginReceiveMessage(XPLMPluginID in_from, long in_msg, void *in_param) log_msg("A321 detected, checking door config"); char path[512]; - strcpy(path, xp_dir); + strcpy(path, xp_dir.c_str()); int len = strlen(path); int n = XPLMGetDatab(acf_livery_path, path + len, 0, sizeof(path) - len - 50); path[len + n] = '\0'; diff --git a/openSAM.h b/openSAM.h index 8b71a41..0157a94 100644 --- a/openSAM.h +++ b/openSAM.h @@ -20,7 +20,9 @@ */ -#include +#include +#include +#include #define XPLM200 #define XPLM210 @@ -43,32 +45,56 @@ static const float D2R = M_PI/180.0; static const float F2M = 0.3048; // 1 ft [m] static const float LAT_2_M = 111120; // 1° lat in m -typedef struct _sam_jw sam_jw_t; -typedef struct _sam_dgs sam_dgs_t; -typedef struct _stand stand_t; -typedef struct _sam_obj sam_obj_t; -typedef struct _sam_anim sam_anim_t; +// forwards +class Stand; +class SamObj; +class SamAnim; +class SamJw; +class SceneryPacks; + +static float RA(float angle); + +class Scenery { + public: + // Not copyable or movable + Scenery(const Scenery&) = delete; + Scenery& operator=(const Scenery&) = delete; -typedef struct _scenery { char name[52]; - sam_jw_t *sam_jws; - int n_sam_jws; + std::vector sam_jws; + std::vector stands; + std::vector sam_objs; + std::vector sam_anims; - stand_t *stands; - int n_stands; + float bb_lat_min, bb_lat_max, bb_lon_min, bb_lon_max; /* bounding box for FAR_SKIP */ - sam_obj_t *sam_objs; - int n_sam_objs; + Scenery() { + sam_jws.reserve(100); stands.reserve(100); + sam_objs.reserve(50); sam_anims.reserve(50); + } - sam_anim_t *sam_anims; - int n_sam_anims; + auto in_bbox(float lat, float lon) -> bool { + return (lat >= bb_lat_min && lat <= bb_lat_max + && RA(lon - bb_lon_min) >= 0 && RA(lon - bb_lon_max) <= 0); + } +}; - float bb_lat_min, bb_lat_max, bb_lon_min, bb_lon_max; /* bounding box for FAR_SKIP */ -} scenery_t; +extern std::vector sceneries; + +// a poor man's factory for creating sceneries +extern int collect_sam_xml(const SceneryPacks &scp); -extern scenery_t *sceneries; -extern int n_sceneries; +class SceneryPacks { + public: + bool valid; + std::string openSAM_Library_path; + std::string SAM_Library_path; + + std::vector sc_paths; + + SceneryPacks(const std::string& xp_dir); +}; typedef struct door_info_ { float x, y, z; @@ -81,7 +107,7 @@ extern door_info_t door_info[MAX_DOOR]; extern float plane_nw_z, plane_mw_z, plane_cg_z; // z value of plane's 0 to fw, mw and cg extern char acf_icao[]; -extern char base_dir[512]; // base directory of openSAM +extern std::string base_dir; // base directory of openSAM extern int use_engine_running; // instead of beacon, e.g. MD11 extern int dont_connect_jetway; // e.g. for ZIBO with own ground service extern int is_helicopter; @@ -123,23 +149,11 @@ extern XPLMProbeRef probe_ref; // functions extern void log_msg(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -extern int collect_sam_xml(const char *xp_dir); extern int check_beacon(void); extern int check_teleportation(void); extern void toggle_ui(void); -/* helpers */ -#define MAX(a,b) \ - ({ __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a > _b ? _a : _b; }) - -#define MIN(a,b) \ - ({ __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a < _b ? _a : _b; }) - #define BETWEEN(x ,a ,b) ((a) <= (x) && (x) <= (b)) static inline diff --git a/os_anim.c b/os_anim.cpp similarity index 87% rename from os_anim.c rename to os_anim.cpp index a8d099f..a34a618 100644 --- a/os_anim.c +++ b/os_anim.cpp @@ -20,12 +20,9 @@ */ -#include -#include -#include -#include -#include -#include +#include +#include +#include #include "openSAM.h" #include "os_anim.h" @@ -33,9 +30,9 @@ static const float SAM_2_OBJ_MAX = 2.5; // m, max delta between coords in sam.xml and object static const float SAM_2_OBJ_HDG_MAX = 5; // °, likewise for heading -static scenery_t *cur_sc; // the current scenery determined by dref access -static float cur_sc_ts = -100.0f; // timestamp of selection of cur_sc -static scenery_t *menu_sc; // the scenery the menu is built of +static Scenery* cur_sc; // the current scenery determined by dref access +static float cur_sc_ts = -100.0f; // timestamp of selection of cur_sc +static Scenery* menu_sc; // the scenery the menu is built of // // Accessor for the "sam/..." custom animation datarefs @@ -66,13 +63,12 @@ anim_acc(void *ref) int drf_idx = (uint64_t)ref; - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) { - for (int i = 0; i < sc->n_sam_anims; i++) { - sam_anim_t *anim = &sc->sam_anims[i]; + for (auto sc : sceneries) { + for (auto anim : sc->sam_anims) { if (drf_idx != anim->drf_idx) continue; - sam_obj_t *obj = &sc->sam_objs[anim->obj_idx]; + SamObj *obj = sc->sam_objs[anim->obj_idx]; if (fabsf(RA(obj->heading - obj_psi)) > SAM_2_OBJ_HDG_MAX) continue; @@ -92,7 +88,7 @@ anim_acc(void *ref) continue; } - sam_drf_t *drf = &sam_drfs[drf_idx]; + SamDrf *drf = sam_drfs[drf_idx]; //log_msg("acc %s called, %s %s", drf->name, anim->label, anim->title); if (now > cur_sc_ts + 20.0f) { // avoid high freq flicker @@ -140,7 +136,7 @@ auto_drf_acc(void *ref) { stat_auto_drf_called++; - const sam_drf_t *drf = (const sam_drf_t *)ref; + const SamDrf *drf = (const SamDrf *)ref; float t = XPLMGetDataf(total_running_time_sec_dr); @@ -169,7 +165,7 @@ anim_menu_cb(void *menu_ref, void *item_ref) return; unsigned int idx = (uint64_t)item_ref; - sam_anim_t *anim = &menu_sc->sam_anims[idx]; + SamAnim *anim = menu_sc->sam_anims[idx]; log_msg("anim_menu_cb: label: %s, menu_item: %d", anim->label, anim->menu_item); now = XPLMGetDataf(total_running_time_sec_dr); @@ -187,7 +183,7 @@ anim_menu_cb(void *menu_ref, void *item_ref) } if (reverse) { - sam_drf_t *drf = &sam_drfs[anim->drf_idx]; + SamDrf *drf = sam_drfs[anim->drf_idx]; float t_rel = now - anim->start_ts; float dt = drf->t[drf->n_tv - 1] - t_rel; anim->start_ts = now - dt; @@ -196,13 +192,13 @@ anim_menu_cb(void *menu_ref, void *item_ref) } static void -build_menu(scenery_t *sc) +build_menu(Scenery* sc) { log_msg("build menu for scenery %s", sc->name); XPLMClearAllMenuItems(anim_menu); - for (int i = 0; i < sc->n_sam_anims; i++) { - sam_anim_t *anim = &sc->sam_anims[i]; + for (unsigned i = 0; i < sc->sam_anims.size(); i++) { + SamAnim *anim = sc->sam_anims[i]; XPLMMenuCheck chk = (anim->state == ANIM_OFF || anim->state == ANIM_ON_2_OFF) ? xplm_Menu_Unchecked : xplm_Menu_Checked; @@ -241,8 +237,8 @@ anim_state_machine(void) int anim_init() { - for (int i = 0; i < n_sam_drfs; i++) { - const sam_drf_t *drf = &sam_drfs[i]; + for (unsigned i = 0; i < sam_drfs.size(); i++) { + const SamDrf *drf = sam_drfs[i]; if (drf->autoplay) XPLMRegisterDataAccessor(drf->name, xplmType_Float, 0, NULL, NULL, auto_drf_acc, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/os_anim.h b/os_anim.h index 296da44..fd59a30 100644 --- a/os_anim.h +++ b/os_anim.h @@ -20,10 +20,12 @@ */ -#include +#include +#include #define DRF_MAX_ANIM 10 -typedef struct _sam_drf { +class SamDrf { + public: char name[60]; int n_tv; @@ -32,9 +34,10 @@ typedef struct _sam_drf { float s[DRF_MAX_ANIM]; // s[i] = slope for (i-1, i) bool autoplay, randomize_phase, augment_wind_speed; -} sam_drf_t; +}; -struct _sam_obj { +class SamObj { + public: char id[30]; float latitude, longitude, elevation, heading; @@ -50,7 +53,8 @@ typedef enum _ANIM_STATE { ANIM_ON } anim_state_t; -struct _sam_anim { +class SamAnim { + public: char label[40]; char title[40]; @@ -63,8 +67,7 @@ struct _sam_anim { int menu_item; }; -extern sam_drf_t *sam_drfs; -extern int n_sam_drfs; +extern std::vector sam_drfs; extern int anim_init(void); extern float anim_state_machine(void); diff --git a/os_dgs.c b/os_dgs.cpp similarity index 88% rename from os_dgs.c rename to os_dgs.cpp index cbd9efa..75b38fd 100644 --- a/os_dgs.c +++ b/os_dgs.cpp @@ -21,10 +21,8 @@ */ -#include -#include -#include -#include +#include +#include #include "openSAM.h" #include "os_dgs.h" @@ -70,7 +68,7 @@ static float azimuth, distance; float plane_nw_z, plane_mw_z, plane_cg_z; // z value of plane's 0 to fw, mw and cg -static stand_t *nearest_stand; +static Stand *nearest_stand; static float nearest_stand_ts; // timestamp of last find_nearest_stand() // track the max local z (= closest to stand) of dgs objs for nearest_stand static float max_dgs_z_l, max_dgs_z_l_ts; @@ -191,7 +189,7 @@ static float last_dgs_z; // xform lat,lon into the active global frame void -xform_to_ref_frame(stand_t *stand) +xform_to_ref_frame(Stand *stand) { if (stand->ref_gen < ref_gen) { XPLMWorldToLocal(stand->lat, stand->lon, XPLMGetDataf(plane_elevation_dr), @@ -205,7 +203,7 @@ xform_to_ref_frame(stand_t *stand) // xform global coordinates into the stand frame void -global_2_stand(const stand_t * stand, float x, float z, float *x_l, float *z_l) +global_2_stand(const Stand * stand, float x, float z, float *x_l, float *z_l) { float dx = x - stand->stand_x; float dz = z - stand->stand_z; @@ -348,7 +346,7 @@ read_sam1_icao_acc(XPLMDataRef ref, int *values, int ofs, int n) if (n <= 0 || ofs < 0 || ofs >= 4) return 0; - n = MIN(n, 4 - ofs); + n = std::min(n, 4 - ofs); for (int i = 0; i < n; i++) { char c = acf_icao[ofs + i]; @@ -365,7 +363,7 @@ static void find_nearest_stand() { double dist = 1.0E10; - stand_t *min_stand = NULL; + Stand *min_stand = NULL; float plane_lat = XPLMGetDataf(plane_lat_dr); float plane_lon = XPLMGetDataf(plane_lon_dr); @@ -375,14 +373,14 @@ find_nearest_stand() float plane_hdgt = XPLMGetDataf(plane_true_psi_dr); - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) { + for (auto sc : sceneries) { // cheap check against bounding box if (plane_lat < sc->bb_lat_min || plane_lat > sc->bb_lat_max || RA(plane_lon - sc->bb_lon_min) < 0 || RA(plane_lon - sc->bb_lon_max) > 0) { continue; } - for (stand_t *stand = sc->stands; stand < sc->stands + sc->n_stands; stand++) { + for (auto stand : sc->stands) { // heading in local system float local_hdgt = RA(plane_hdgt - stand->hdgt); @@ -598,80 +596,82 @@ dgs_state_machine() } break; - case TRACK: - if (!beacon_on) { // don't get stuck in TRACK - new_state = DONE; - break; - } + case TRACK: { + if (!beacon_on) { // don't get stuck in TRACK + new_state = DONE; + break; + } - if (locgood) { - new_state = GOOD; - break; - } + if (locgood) { + new_state = GOOD; + break; + } - if (nw_z < -GOOD_Z) { - new_state = BAD; - break; - } + if (nw_z < -GOOD_Z) { + new_state = BAD; + break; + } - if ((distance > CAP_Z) || (fabsf(azimuth_nw) > CAP_A)) { - new_state = ENGAGED; // moving away from current gate - break; - } + if ((distance > CAP_Z) || (fabsf(azimuth_nw) > CAP_A)) { + new_state = ENGAGED; // moving away from current gate + break; + } - status = 1; // plane id - if (distance > AZI_Z || fabsf(azimuth_nw) > AZI_A) { - track=1; // lead-in only - break; - } + status = 1; // plane id + if (distance > AZI_Z || fabsf(azimuth_nw) > AZI_A) { + track=1; // lead-in only + break; + } - // compute distance and guidance commands - azimuth = clampf(azimuth, -AZI_A, AZI_A); - float req_hdgt = -3.5f * azimuth; // to track back to centerline - float d_hdgt = req_hdgt - local_hdgt; // degrees to turn - - if (now > update_stand_log_ts + 2.0f) - log_msg("is_marshaller: %d, azimuth: %0.1f, mw: (%0.1f, %0.1f), nw: (%0.1f, %0.1f), ref: (%0.1f, %0.1f), " - "x: %0.1f, local_hdgt: %0.1f, d_hdgt: %0.1f", - is_marshaller, azimuth, mw_x, mw_z, nw_x, nw_z, - x_dr, z_dr, - local_x, local_hdgt, d_hdgt); - - if (d_hdgt < -1.5) - lr = 2; - else if (d_hdgt > 1.5) - lr = 1; - - // xform azimuth to values required by OBJ - azimuth = clampf(azimuth, -AZI_DISP_A, AZI_DISP_A) * 4.0 / AZI_DISP_A; - azimuth=((float)((int)(azimuth * 2))) / 2; // round to 0.5 increments - - if (distance <= REM_Z/2) { - track = 3; - loop_delay = 0.03; - } else // azimuth only - track = 2; - - if (! phase180) { // no wild oscillation - lr = lr_prev; - - // sync transition with Marshaller's arm movement - if (is_marshaller && track == 3 && track_prev == 2) { - track = track_prev; - distance = distance_prev; + // compute distance and guidance commands + azimuth = clampf(azimuth, -AZI_A, AZI_A); + float req_hdgt = -3.5f * azimuth; // to track back to centerline + float d_hdgt = req_hdgt - local_hdgt; // degrees to turn + + if (now > update_stand_log_ts + 2.0f) + log_msg("is_marshaller: %d, azimuth: %0.1f, mw: (%0.1f, %0.1f), nw: (%0.1f, %0.1f), ref: (%0.1f, %0.1f), " + "x: %0.1f, local_hdgt: %0.1f, d_hdgt: %0.1f", + is_marshaller, azimuth, mw_x, mw_z, nw_x, nw_z, + x_dr, z_dr, + local_x, local_hdgt, d_hdgt); + + if (d_hdgt < -1.5) + lr = 2; + else if (d_hdgt > 1.5) + lr = 1; + + // xform azimuth to values required by OBJ + azimuth = clampf(azimuth, -AZI_DISP_A, AZI_DISP_A) * 4.0 / AZI_DISP_A; + azimuth=((float)((int)(azimuth * 2))) / 2; // round to 0.5 increments + + if (distance <= REM_Z/2) { + track = 3; + loop_delay = 0.03; + } else // azimuth only + track = 2; + + if (! phase180) { // no wild oscillation + lr = lr_prev; + + // sync transition with Marshaller's arm movement + if (is_marshaller && track == 3 && track_prev == 2) { + track = track_prev; + distance = distance_prev; + } } } break; - case GOOD: - // @stop position*/ - status = 2; lr = 3; + case GOOD: { + // @stop position*/ + status = 2; lr = 3; - int parkbrake_set = (XPLMGetDataf(parkbrake_dr) > 0.5f); - if (!locgood) - new_state = TRACK; - else if (parkbrake_set || !beacon_on) - new_state = PARKED; + int parkbrake_set = (XPLMGetDataf(parkbrake_dr) > 0.5f); + if (!locgood) + new_state = TRACK; + else if (parkbrake_set || !beacon_on) + new_state = PARKED; + } break; case BAD: @@ -753,7 +753,7 @@ dgs_state_machine() // translate into compatible SAM1 values sam1_lateral = -x_dr; - sam1_longitudinal = MIN(z_dr, 30.0f); + sam1_longitudinal = std::min(z_dr, 30.0f); switch (state) { case ENGAGED: @@ -786,7 +786,8 @@ dgs_state_machine() } if (is_marshaller && BETWEEN(state, ENGAGED, PARKED)) { - XPLMDrawInfo_t drawinfo = {.structSize = sizeof(XPLMDrawInfo_t)}; + XPLMDrawInfo_t drawinfo = {}; + drawinfo.structSize = sizeof(XPLMDrawInfo_t); drawinfo.heading = marshaller_psi; drawinfo.pitch = drawinfo.roll = 0.0; diff --git a/os_dgs.h b/os_dgs.h index cc8c5de..d111ac1 100644 --- a/os_dgs.h +++ b/os_dgs.h @@ -20,7 +20,8 @@ */ -struct _stand { +class Stand { + public: float lat, lon, hdgt; // from apt.dat unsigned int ref_gen; // only valid if this matches the generation of the ref frame @@ -35,6 +36,6 @@ extern float dgs_state_machine(void); extern void dgs_set_active(void); extern void dgs_set_inactive(void); -extern void xform_to_ref_frame(stand_t *stand); -extern void global_2_stand(const stand_t * stand, float x, float z, float *x_l, float *z_l); +extern void xform_to_ref_frame(Stand* stand); +extern void global_2_stand(const Stand* stand, float x, float z, float *x_l, float *z_l); diff --git a/os_jw.c b/os_jw.cpp similarity index 63% rename from os_jw.c rename to os_jw.cpp index c5a1113..58c0ee1 100644 --- a/os_jw.c +++ b/os_jw.cpp @@ -20,12 +20,11 @@ */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "openSAM.h" #include "os_jw.h" @@ -77,15 +76,13 @@ static const char *dr_name_jw[] = { }; int n_active_jw; -jw_ctx_t active_jw[MAX_DOOR]; +JwCtrl active_jw[MAX_DOOR]; -jw_ctx_t nearest_jw[MAX_NEAREST]; +JwCtrl nearest_jw[MAX_NEAREST]; int n_nearest; // zero config jw structures -static sam_jw_t zc_jws[150]; // static for now -static int zc_max_jws = 150; -static int zc_n_jws; +static std::vectorzc_jws; static unsigned int zc_ref_gen; // change of ref_gen invalidates the whole list static int dock_requested, undock_requested, toggle_requested; @@ -93,78 +90,70 @@ static float plane_x, plane_y, plane_z, plane_psi, sin_psi, cos_psi; XPLMCommandRef dock_cmdr, undock_cmdr, toggle_cmdr, toggle_ui_cmdr; - -// set wheels height -static inline void -jw_set_wheels(sam_jw_t *jw) -{ - jw->wheels = tanf(jw->rotate3 * D2R) * (jw->wheelPos + jw->extent); -} - // // fill in values for a library jetway // -static void -fill_library_values(sam_jw_t *jw) +auto SamJw::fill_library_values(int id) -> void { - int id = jw->library_id; + if (library_id) + return; + if (!BETWEEN(id, 1, MAX_SAM3_LIB_JW)) { - log_msg("sanity check failed for jw: '%s', id: %d", jw->name, id); + log_msg("sanity check failed for jw: '%s', id: %d", name, id); return; } - log_msg("filling in library data for '%s', id: %d", jw->name, id); + library_id = id; + + log_msg("filling in library data for '%s', id: %d", name, id); - sam_jw_t *ljw = &sam3_lib_jw[id]; + const SamJw *ljw = &sam3_lib_jw[id]; - jw->height = ljw->height; - jw->wheelPos = ljw->wheelPos; - jw->cabinPos = ljw->cabinPos; - jw->cabinLength = ljw->cabinLength; + height = ljw->height; + wheelPos = ljw->wheelPos; + cabinPos = ljw->cabinPos; + cabinLength = ljw->cabinLength; - jw->wheelDiameter = ljw->wheelDiameter; - jw->wheelDistance = ljw->wheelDistance; + wheelDiameter = ljw->wheelDiameter; + wheelDistance = ljw->wheelDistance; - jw->minRot1 = ljw->minRot1; - jw->maxRot1 = ljw->maxRot1; + minRot1 = ljw->minRot1; + maxRot1 = ljw->maxRot1; - jw->minRot2 = ljw->minRot2; - jw->maxRot2 = ljw->maxRot2; + minRot2 = ljw->minRot2; + maxRot2 = ljw->maxRot2; - jw->minRot3 = ljw->minRot3; - jw->maxRot3 = ljw->maxRot3; + minRot3 = ljw->minRot3; + maxRot3 = ljw->maxRot3; - jw->minExtent = ljw->minExtent; - jw->maxExtent = ljw->maxExtent; + minExtent = ljw->minExtent; + maxExtent = ljw->maxExtent; - jw->minWheels = ljw->minWheels; - jw->maxWheels = ljw->maxWheels; + minWheels = ljw->minWheels; + maxWheels = ljw->maxWheels; } // // find the stand the jetway belongs to // -static stand_t * -find_stand_for_jw(sam_jw_t *jw) +auto SamJw::find_stand() -> Stand* { float dist = 1.0E10; - stand_t *min_stand = NULL; + Stand *min_stand = nullptr; float plane_lat = XPLMGetDataf(plane_lat_dr); float plane_lon = XPLMGetDataf(plane_lon_dr); - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) { + for (auto sc : sceneries) { // cheap check against bounding box - if (plane_lat < sc->bb_lat_min || plane_lat > sc->bb_lat_max - || RA(plane_lon - sc->bb_lon_min) < 0 || RA(plane_lon - sc->bb_lon_max) > 0) { + if (! sc->in_bbox(plane_lat, plane_lon)) continue; - } - for (stand_t *stand = sc->stands; stand < sc->stands + sc->n_stands; stand++) { - xform_to_ref_frame(stand); + for (auto s : sc->stands) { + xform_to_ref_frame(s); float local_x, local_z; - global_2_stand(stand, jw->x, jw->z, &local_x, &local_z); + global_2_stand(s, x, z, &local_x, &local_z); if (local_x > 2.0f) // on the right continue; @@ -173,31 +162,28 @@ find_stand_for_jw(sam_jw_t *jw) if (d < dist) { //log_msg("new min: %s, z: %2.1f, x: %2.1f",stand->id, local_z, local_x); dist = d; - min_stand = stand; + min_stand = s; } } } - return min_stand; + stand = min_stand; + return stand; } // // configure a zc library jetway // -static sam_jw_t * +static SamJw * configure_zc_jw(int id, float obj_x, float obj_z, float obj_y, float obj_psi) { - if (zc_n_jws == zc_max_jws) - return NULL; - // library jetways may be in view from very far away when stand information is not // yet available. We won't see details anyway. if (len2f(obj_x - XPLMGetDataf(plane_x_dr), obj_z - XPLMGetDataf(plane_z_dr)) > 0.5f * FAR_SKIP || fabsf(obj_y - XPLMGetDataf(plane_y_dr)) > 1000.0f) - return NULL; + return nullptr; - sam_jw_t *jw = &zc_jws[zc_n_jws++]; - *jw = (sam_jw_t){0}; + SamJw *jw = new SamJw(); jw->obj_ref_gen = ref_gen; jw->x = obj_x; jw->z = obj_z; @@ -205,10 +191,9 @@ configure_zc_jw(int id, float obj_x, float obj_z, float obj_y, float obj_psi) jw->psi = obj_psi; jw->is_zc_jw = 1; strcpy(jw->name, "zc_"); - jw->library_id = id; - fill_library_values(jw); + jw->fill_library_values(id); - stand_t *stand = jw->stand = find_stand_for_jw(jw); + Stand *stand = jw->find_stand(); if (stand) { // delta = cabin points perpendicular to stand float delta = RA((stand->hdgt + 90.0f) - jw->psi); @@ -226,7 +211,10 @@ configure_zc_jw(int id, float obj_x, float obj_z, float obj_y, float obj_psi) jw->rotate2 = jw->initialRot2; jw->rotate3 = jw->initialRot3; jw->extent = jw->initialExtent; - jw_set_wheels(jw); + jw->set_wheels(); + + zc_jws.push_back(jw); + log_msg("added to zc table stand: '%s', global: x: %5.3f, z: %5.3f, y: %5.3f, psi: %4.1f, initialRot2: %0.1f", stand ? stand->id : "", jw->x, jw->z, jw->y, jw->psi, jw->initialRot2); return jw; @@ -250,7 +238,10 @@ check_ref_frame_shift() if (zc_ref_gen < ref_gen) { // from a different frame = stale data log_msg("zc_jws deleted"); - zc_n_jws = 0; + for (auto jw : zc_jws) + delete(jw); + + zc_jws.resize(0); // keep the allocation zc_ref_gen = ref_gen; } } @@ -281,20 +272,19 @@ jw_anim_acc(void *ref) check_ref_frame_shift(); uint64_t ctx = (uint64_t)ref; - dr_code_t drc = ctx & 0xffffffff; + dr_code_t drc = (dr_code_t)(ctx & 0xffffffff); int id = ctx >> 32; - sam_jw_t *jw = NULL; + SamJw *jw = nullptr; - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) { + for (auto sc : sceneries) { // cheap check against bounding box - if (lat < sc->bb_lat_min || lat > sc->bb_lat_max - || RA(lon - sc->bb_lon_min) < 0 || RA(lon - sc->bb_lon_max) > 0) { + if (! sc->in_bbox(lat, lon)) { stat_sc_far_skip++; continue; } - for (sam_jw_t *jw_ = sc->sam_jws; jw_ < sc->sam_jws + sc->n_sam_jws; jw_++) { + for (auto jw_ : sc->sam_jws) { // cheap check against bounding box if (lat < jw_->bb_lat_min || lat > jw_->bb_lat_max || RA(lon - jw_->bb_lon_min) < 0 || RA(lon - jw_->bb_lon_max) > 0) { @@ -358,7 +348,7 @@ jw_anim_acc(void *ref) // no match of custom jw // check against the zero config table - for (sam_jw_t *jw_ = zc_jws; jw_ < zc_jws + zc_n_jws; jw_++) { + for (auto jw_ : zc_jws) { if (obj_x == jw_->x && obj_z == jw_->z && obj_y == jw_->y) { stat_jw_match++; jw = jw_; @@ -368,19 +358,18 @@ jw_anim_acc(void *ref) stat_near_skip++; } - if (NULL == jw && BETWEEN(id, 1, MAX_SAM3_LIB_JW)) // unconfigured library jetway + if (nullptr == jw && BETWEEN(id, 1, MAX_SAM3_LIB_JW)) // unconfigured library jetway jw = configure_zc_jw(id, obj_x, obj_z, obj_y, obj_psi); - if (NULL == jw) // still unconfigured -> bad luck + if (nullptr == jw) // still unconfigured -> bad luck return 0.0f; out: switch (drc) { case DR_ROTATE1: // a one shot event on first access - if (id > 0 && 0 == jw->library_id) { - jw->library_id = id; - fill_library_values(jw); + if (id > 0) { + jw->fill_library_values(id); } return jw->rotate1; break; @@ -450,16 +439,16 @@ jw_door_status_acc(XPLMDataRef ref, int *values, int ofs, int n) { UNUSED(ref); - if (values == NULL) + if (values == nullptr) return MAX_DOOR; if (n <= 0 || ofs < 0 || ofs >= MAX_DOOR) return 0; - n = MIN(n, MAX_DOOR - ofs); + n = std::min(n, MAX_DOOR - ofs); for (int i = 0; i < n; i++) { - jw_ctx_t *ajw = &active_jw[ofs + i]; + JwCtrl *ajw = &active_jw[ofs + i]; values[i] = (ajw->jw && ajw->state == AJW_DOCKED) ? 1 : 0; } @@ -469,29 +458,17 @@ jw_door_status_acc(XPLMDataRef ref, int *values, int ofs, int n) static void reset_jetways() { - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) - for (sam_jw_t *jw = sc->sam_jws; jw < sc->sam_jws + sc->n_sam_jws; jw++) { - jw->rotate1 = jw->initialRot1; - jw->rotate2 = jw->initialRot2; - jw->rotate3 = jw->initialRot3; - jw->extent = jw->initialExtent; - jw_set_wheels(jw); - jw->warnlight = 0; - } + for (auto sc : sceneries) + for (auto jw : sc->sam_jws) + jw->reset(); - for (sam_jw_t *jw = zc_jws; jw < zc_jws + zc_n_jws; jw++) { - jw->rotate1 = jw->initialRot1; - jw->rotate2 = jw->initialRot2; - jw->rotate3 = jw->initialRot3; - jw->extent = jw->initialExtent; - jw_set_wheels(jw); - jw->warnlight = 0; - } + for (auto jw : zc_jws) + jw->reset(); for (int i = 0; i < n_door; i++) { - jw_ctx_t *ajw = &active_jw[i]; + JwCtrl *ajw = &active_jw[i]; if (ajw->jw) - alert_off(ajw); + ajw->alert_off(); } state = IDLE; @@ -507,117 +484,110 @@ jw_auto_mode_change() reset_jetways(); // an animation might be ongoing } -// convert tunnel end at (cabin_x, cabin_z) to dataref values; rot2, rot3 can be NULL -static inline void -jw_xy_to_sam_dr(const jw_ctx_t *ajw, float cabin_x, float cabin_z, - float *rot1, float *extent, float *rot2, float *rot3) +// convert tunnel end at (cabin_x, cabin_z) to dataref values; rot2, rot3 can be nullptr +auto +JwCtrl::xz_to_sam_dr(float cabin_x, float cabin_z, + float& rot1, float& extent, float *rot2, float *rot3) -> void { - const sam_jw_t *jw = ajw->jw; - - float dist = len2f(cabin_x - ajw->x, cabin_z - ajw->z); + float dist = len2f(cabin_x - x, cabin_z - z); - float rot1_d = atan2(cabin_z - ajw->z, cabin_x - ajw->x) / D2R; // door frame - *rot1 = RA(rot1_d + 90.0f - ajw->psi); - *extent = dist - jw->cabinPos; + float rot1_d = atan2(cabin_z - z, cabin_x - x) / D2R; // door frame + rot1 = RA(rot1_d + 90.0f - psi); + extent = dist - jw->cabinPos; // angle 0° door frame -> hdgt -> jw frame -> diff to rot1 - float r2 = RA(0.0f + 90.0f - ajw->psi - *rot1); + float r2 = RA(0.0f + 90.0f - psi - rot1); if (rot2) *rot2 = r2; if (rot3) { float net_length = dist + jw->cabinLength * cosf(r2 * D2R); - *rot3 = -atan2f(ajw->y, net_length) / D2R; + *rot3 = -atan2f(y, net_length) / D2R; } } // // fill in geometry data related to specific door // -static void -jw_ctx_for_door(jw_ctx_t *ajw, const door_info_t *door_info) +auto +JwCtrl::setup_for_door(const door_info_t *door_info) -> void { - sam_jw_t *jw = ajw->jw; - // rotate into plane local frame float dx = jw->x - plane_x; float dz = jw->z - plane_z; - ajw->x = cos_psi * dx + sin_psi * dz; - ajw->z = -sin_psi * dx + cos_psi * dz; - ajw->psi = RA(jw->psi - plane_psi); + x = cos_psi * dx + sin_psi * dz; + z = -sin_psi * dx + cos_psi * dz; + psi = RA(jw->psi - plane_psi); // xlate into door local frame - ajw->x -= door_info->x; - ajw->z -= door_info->z; + x -= door_info->x; + z -= door_info->z; - float rot1_d = RA((jw->initialRot1 + ajw->psi) - 90.0f); // door frame - ajw->cabin_x = ajw->x + (jw->extent + jw->cabinPos) * cosf(rot1_d * D2R); - ajw->cabin_z = ajw->z + (jw->extent + jw->cabinPos) * sinf(rot1_d * D2R); + float rot1_d = RA((jw->initialRot1 + psi) - 90.0f); // door frame + cabin_x = x + (jw->extent + jw->cabinPos) * cosf(rot1_d * D2R); + cabin_z = z + (jw->extent + jw->cabinPos) * sinf(rot1_d * D2R); - ajw->tgt_x = -jw->cabinLength; + door_x = -jw->cabinLength; // tgt z = 0.0 - ajw->y = (jw->y + jw->height) - (plane_y + door_info->y); + y = (jw->y + jw->height) - (plane_y + door_info->y); - jw_xy_to_sam_dr(ajw, ajw->tgt_x, 0.0f, &ajw->tgt_rot1, &ajw->tgt_extent, &ajw->tgt_rot2, &ajw->tgt_rot3); + xz_to_sam_dr(door_x, 0.0f, door_rot1, door_extent, &door_rot2, &door_rot3); float r = jw->initialExtent + jw->cabinPos; - ajw->parked_x = ajw->x + r * cosf(rot1_d * D2R); - ajw->parked_z = ajw->z + r * sinf(rot1_d * D2R); + parked_x = x + r * cosf(rot1_d * D2R); + parked_z = z + r * sinf(rot1_d * D2R); - ajw->ap_x = ajw->tgt_x - JW_ALIGN_DIST; + ap_x = door_x - JW_ALIGN_DIST; - jw_set_wheels(jw); + jw->set_wheels(); } // a fuzzy comparator for jetway by door number -static int -njw_compar(const void *a_, const void *b_) +bool +operator<(const JwCtrl& a, const JwCtrl& b) { - const jw_ctx_t *a = a_; - const jw_ctx_t *b = b_; - // height goes first - if (a->jw->height < b->jw->height - 1.0f) - return -1; + if (a.jw->height < b.jw->height - 1.0f) + return true; - if (a->jw->height > b->jw->height + 1.0f) - return 1; + if (a.jw->height > b.jw->height + 1.0f) + return false; // then z - if (a->z < b->z - 0.5f) - return -1; + if (a.z < b.z - 0.5f) + return true; - if (a->z > b->z + 0.5f) - return 1; + if (a.z > b.z + 0.5f) + return false; // then x, further left (= towards -x) is higher - if (a->x < b->x) - return 1; + if (a.x < b.x) + return false; - if (a->x > b->x) - return -1; + if (a.x > b.x) + return true; - return 0; + return true; } // filter list of jetways jw[] for candidates and add them to nearest_jw[] static void -filter_candidates(sam_jw_t *jw, int n_jw, const door_info_t *door_info, float *dist_threshold) +filter_candidates(std::vector &jws, const door_info_t *door_info, float *dist_threshold) { // Unfortunately maxExtent in sam.xml can be bogus (e.g. FlyTampa EKCH) // So we find the nearest jetways on the left and do some heuristics - for (;n_jw-- > 0; jw++) { + for (auto jw : jws) { if (jw->obj_ref_gen < ref_gen) // not visible -> not dockable continue; log_msg("%s door %d, global: x: %5.3f, z: %5.3f, y: %5.3f, psi: %4.1f", jw->name, jw->door, jw->x, jw->z, jw->y, jw->psi); - jw_ctx_t tentative_njw = {0}; - jw_ctx_t *njw = &tentative_njw; + JwCtrl tentative_njw = {}; + JwCtrl *njw = &tentative_njw; njw->jw = jw; - jw_ctx_for_door(njw, door_info); + njw->setup_for_door(door_info); if (njw->x > 1.0f || BETWEEN(RA(njw->psi + jw->initialRot1), -130.0f, 20.0f) || // on the right side or pointing away njw->x < -80.0f || fabsf(njw->z) > 80.0f) { // or far away @@ -630,12 +600,12 @@ filter_candidates(sam_jw_t *jw, int n_jw, const door_info_t *door_info, float *d if (njw->z > *dist_threshold) continue; - if (!(BETWEEN(njw->tgt_rot1, jw->minRot1, jw->maxRot1) && BETWEEN(njw->tgt_rot2, jw->minRot2, jw->maxRot2) - && BETWEEN(njw->tgt_extent, jw->minExtent, jw->maxExtent))) { + if (!(BETWEEN(njw->door_rot1, jw->minRot1, jw->maxRot1) && BETWEEN(njw->door_rot2, jw->minRot2, jw->maxRot2) + && BETWEEN(njw->door_extent, jw->minExtent, jw->maxExtent))) { log_msg("jw: %s for door %d, rot1: %0.1f, rot2: %0.1f, rot3: %0.1f, extent: %0.1f", - jw->name, jw->door, njw->tgt_rot1, njw->tgt_rot2, njw->tgt_rot3, njw->tgt_extent); + jw->name, jw->door, njw->door_rot1, njw->door_rot2, njw->door_rot3, njw->door_extent); log_msg(" does not fulfil min max criteria in sam.xml"); - float extra_extent = njw->tgt_extent - jw->maxExtent; + float extra_extent = njw->door_extent - jw->maxExtent; if (extra_extent < 10.0f) { log_msg(" as extra extent of %0.1f m < 10.0 m we take it as a soft match", extra_extent); njw->soft_match = 1; @@ -647,13 +617,13 @@ filter_candidates(sam_jw_t *jw, int n_jw, const door_info_t *door_info, float *d log_msg("--> candidate %s, lib_id: %d, door %d, door frame: x: %5.3f, z: %5.3f, y: %5.3f, psi: %4.1f, " "rot1: %0.1f, extent: %.1f", jw->name, jw->library_id, jw->door, - njw->x, njw->z, njw->y, njw->psi, njw->tgt_rot1, njw->tgt_extent); + njw->x, njw->z, njw->y, njw->psi, njw->door_rot1, njw->door_extent); nearest_jw[n_nearest] = *njw; n_nearest++; // if full, sort by dist and trim down to NEAR_JW_LIMIT if (n_nearest == MAX_NEAREST) { - qsort(nearest_jw, MAX_NEAREST, sizeof(jw_ctx_t), njw_compar); + std::sort(nearest_jw, nearest_jw + MAX_NEAREST); n_nearest = NEAR_JW_LIMIT; *dist_threshold = nearest_jw[NEAR_JW_LIMIT - 1].z; } @@ -691,22 +661,23 @@ find_nearest_jws() float dist_threshold = 1.0E10f; // custom jws - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) - filter_candidates(sc->sam_jws, sc->n_sam_jws, &avg_di, &dist_threshold); + for (auto sc : sceneries) + filter_candidates(sc->sam_jws, &avg_di, &dist_threshold); // and zero config jetways - filter_candidates(zc_jws, zc_n_jws, &avg_di, &dist_threshold); + filter_candidates(zc_jws, &avg_di, &dist_threshold); if (n_nearest > 1) { // final sort + trim down to limit - qsort(nearest_jw, n_nearest, sizeof(jw_ctx_t), njw_compar); - n_nearest = MIN(n_nearest, NEAR_JW_LIMIT); + n_nearest = std::min(n_nearest, MAX_NEAREST); // required to keep the compiler happy + std::sort(nearest_jw, nearest_jw + n_nearest); + n_nearest = std::min(n_nearest, NEAR_JW_LIMIT); // required to keep the compiler happy } // fake names for zc jetways for (int i = 0; i < n_nearest; i++) { - sam_jw_t *jw = nearest_jw[i].jw; + SamJw *jw = nearest_jw[i].jw; if (jw->is_zc_jw) { - stand_t *stand = jw->stand; + Stand *stand = jw->stand; if (stand) { // stand->id can be eveything from "A11" to "A11 - Terminal 1 (cat C)" char buf[sizeof(stand->id)]; @@ -745,12 +716,12 @@ int jw_collision_check(int i, int j) // A B C // if the solutions for s, t are in [0,1] there is collision - const jw_ctx_t *njw1 = &nearest_jw[i]; - const jw_ctx_t *njw2 = &nearest_jw[j]; + const JwCtrl *njw1 = &nearest_jw[i]; + const JwCtrl *njw2 = &nearest_jw[j]; // x, z in the door frame - float A1 = njw1->tgt_x - njw1->x; - float A2 = - njw1->z; // tgt_z is 0 in the door frame + float A1 = njw1->door_x - njw1->x; + float A2 = - njw1->z; // door_z is 0 in the door frame float B1 = -(njw2->parked_x - njw2->x); float B2 = -(njw2->parked_z - njw2->z); @@ -814,12 +785,10 @@ select_jws() log_msg("Oh no, no active jetways left in select_jws()!"); } -static int -rotate_wheel_base(jw_ctx_t *ajw, float dt) +auto +JwCtrl::rotate_wheel_base(float dt) -> bool { - sam_jw_t *jw = ajw->jw; - - float delta_rot = RA(ajw->wb_rot - jw->wheelrotatec); + float delta_rot = RA(wb_rot - jw->wheelrotatec); // optimize rotation if (delta_rot > 90.0f) @@ -828,11 +797,11 @@ rotate_wheel_base(jw_ctx_t *ajw, float dt) delta_rot += 180.0f; //log_msg("wb_rot: %0.2f, delta_rot: %0.2f, wheelrotatec: %0.2f", - // ajw->wb_rot, delta_rot, jw->wheelrotatec); + // wb_rot, delta_rot, jw->wheelrotatec); // wheel base rotation - int must_wait = 0; + bool done = true; float d_rot; if (fabsf(delta_rot) > 2.0f) { d_rot = dt * JW_TURN_SPEED; @@ -842,7 +811,7 @@ rotate_wheel_base(jw_ctx_t *ajw, float dt) jw->wheelrotatec += d_rot; - must_wait = 1; // must wait + done = false; // must wait } else { d_rot = delta_rot; jw->wheelrotatec += delta_rot; @@ -852,71 +821,62 @@ rotate_wheel_base(jw_ctx_t *ajw, float dt) jw->wheelrotatel += da_rot; jw->wheelrotater -= da_rot; - return must_wait; + return done; } // rotation1 + extend -static void -rotate_1_extend(jw_ctx_t *ajw, float cabin_x, float cabin_z) +auto +JwCtrl::rotate_1_extend() -> void { - sam_jw_t *jw = ajw->jw; - - jw_xy_to_sam_dr(ajw, cabin_x, cabin_z, &jw->rotate1, &jw->extent, NULL, NULL); - jw_set_wheels(jw); + xz_to_sam_dr(cabin_x, cabin_z, jw->rotate1, jw->extent, nullptr, nullptr); + jw->set_wheels(); } // rotation 3 -// return 1 when done -static int -rotate_3(jw_ctx_t *ajw, float tgt_rot3, float dt) +auto +JwCtrl::rotate_3(float rot3, float dt) -> bool { - sam_jw_t *jw = ajw->jw; - - if (fabsf(jw->rotate3 - tgt_rot3) > 0.1) { + if (fabsf(jw->rotate3 - rot3) > 0.1) { float d_rot3 = (dt * JW_HEIGHT_SPEED / (jw->cabinPos + jw->extent)) / D2R; // strictly it's atan - if (jw->rotate3 >= tgt_rot3) - jw->rotate3 = MAX(jw->rotate3 - d_rot3, tgt_rot3); + if (jw->rotate3 >= rot3) + jw->rotate3 = std::max(jw->rotate3 - d_rot3, rot3); else - jw->rotate3 = MIN(jw->rotate3 + d_rot3, tgt_rot3); + jw->rotate3 = std::min(jw->rotate3 + d_rot3, rot3); } - jw_set_wheels(jw); + jw->set_wheels(); - if (fabsf(jw->rotate3 - tgt_rot3) > 0.1f) + if (fabsf(jw->rotate3 - rot3) > 0.1f) return 0; - jw->rotate3 = tgt_rot3; + jw->rotate3 = rot3; return 1; } // rotation 2 -// return 1 when done -static int -rotate_2(jw_ctx_t *ajw, float tgt_rot2, float dt) { - sam_jw_t *jw = ajw->jw; - - if (fabsf(jw->rotate2 - tgt_rot2) > 0.5) { +auto +JwCtrl::rotate_2(float rot2, float dt) -> bool +{ + if (fabsf(jw->rotate2 - rot2) > 0.5) { float d_rot2 = dt * JW_TURN_SPEED; - if (jw->rotate2 >= tgt_rot2) - jw->rotate2 = MAX(jw->rotate2 - d_rot2, tgt_rot2); + if (jw->rotate2 >= rot2) + jw->rotate2 = std::max(jw->rotate2 - d_rot2, rot2); else - jw->rotate2 = MIN(jw->rotate2 + d_rot2, tgt_rot2); - return fabsf(jw->rotate2 - tgt_rot2) <= 0.5; + jw->rotate2 = std::min(jw->rotate2 + d_rot2, rot2); + return fabsf(jw->rotate2 - rot2) <= 0.5; } - jw->rotate2 = tgt_rot2; - return 1; + jw->rotate2 = rot2; + return true; } // animate wheels for straight driving -static void -animate_wheels(jw_ctx_t *ajw, float ds) +auto +JwCtrl::animate_wheels(float ds) -> void { - sam_jw_t *jw = ajw->jw; - - if (fabsf(RA(ajw->wb_rot - jw->wheelrotatec)) > 90.0f) + if (fabsf(RA(wb_rot - jw->wheelrotatec)) > 90.0f) ds = -ds; - //log_msg("wb_rot: %0.2f, wheelrotatec: %0.2f, ds: 0.3f", ajw->wb_rot, jw->wheelrotatec, ds); + //log_msg("wb_rot: %0.2f, wheelrotatec: %0.2f, ds: 0.3f", wb_rot, jw->wheelrotatec, ds); float da_ds = (ds / jw->wheelDiameter) / D2R; @@ -926,293 +886,288 @@ animate_wheels(jw_ctx_t *ajw, float ds) // drive jetway to the door // return 1 when done -static int -dock_drive(jw_ctx_t *ajw) +auto +JwCtrl::dock_drive() -> bool { - sam_jw_t *jw = ajw->jw; - - if (ajw->state == AJW_DOCKED) - return 1; + if (state == AJW_DOCKED) + return true; - if (now < ajw->start_ts) - return 0; + if (now < start_ts) + return false; // guard against a hung animation - if (now > ajw->timeout) { + if (now > timeout) { log_msg("dock_drive() timeout!"); - ajw->state = AJW_DOCKED; - jw->rotate1 = ajw->tgt_rot1; - jw->rotate2 = ajw->tgt_rot2; - jw->rotate3 = ajw->tgt_rot3; - jw->extent = ajw->tgt_extent; + state = AJW_DOCKED; + jw->rotate1 = door_rot1; + jw->rotate2 = door_rot2; + jw->rotate3 = door_rot3; + jw->extent = door_extent; jw->warnlight = 0; - alert_off(ajw); - return 1; // -> done + alert_off(); + return true; // -> done } - float dt = now - ajw->last_step_ts; - ajw->last_step_ts = now; + float dt = now - last_step_ts; + last_step_ts = now; - float rot1_d = RA((jw->rotate1 + ajw->psi) - 90.0f); // door frame + float rot1_d = RA((jw->rotate1 + psi) - 90.0f); // door frame - //float wheel_x = ajw->x + (jw->extent + jw->wheelPos) * cosf(rot1_d * D2R); - //float wheel_z = ajw->z + (jw->extent + jw->wheelPos) * sinf(rot1_d * D2R); + //float wheel_x = x + (jw->extent + jw->wheelPos) * cosf(rot1_d * D2R); + //float wheel_z = z + (jw->extent + jw->wheelPos) * sinf(rot1_d * D2R); - if (ajw->state == AJW_TO_AP) { - if (ajw->wait_wb_rot) { + if (state == AJW_TO_AP) { + if (wait_wb_rot) { //log_msg("AJW_TO_AP: waiting for wb rotation"); - if (rotate_wheel_base(ajw, dt)) - return 0; - ajw->wait_wb_rot = 0; + if (! rotate_wheel_base(dt)) + return false; + wait_wb_rot = false; } - float tgt_x = ajw->ap_x; + float tgt_x = ap_x; - float eps = MAX(2.0f * dt * JW_DRIVE_SPEED, 0.1f); - //log_msg("eps: %0.3f, %0.3f, %0.3f", eps, fabs(tgt_x - ajw->cabin_x), fabs(ajw->cabin_z)); - if (fabs(tgt_x - ajw->cabin_x) < eps && fabs(ajw->cabin_z) < eps) { - ajw->state = AJW_AT_AP; + float eps = std::max(2.0f * dt * JW_DRIVE_SPEED, 0.1f); + //log_msg("eps: %0.3f, %0.3f, %0.3f", eps, fabs(tgt_x - cabin_x), fabs(cabin_z)); + if (fabs(tgt_x - cabin_x) < eps && fabs(cabin_z) < eps) { + state = AJW_AT_AP; log_msg("align point reached reached"); - return 0; + return false; } double ds = dt * JW_DRIVE_SPEED; // Well, the wheels are somewhat behind the cabin so this is only approximate // but doesn't make much of a difference. - double drive_angle = atan2(-ajw->cabin_z, tgt_x - ajw->cabin_x) / D2R; + double drive_angle = atan2(-cabin_z, tgt_x - cabin_x) / D2R; // wb_rot is drive_angle in the 'tunnel frame' - float wb_rot = RA(drive_angle - rot1_d); + float wb_rot_ = RA(drive_angle - rot1_d); // avoid compression of jetway - if (jw->extent <= jw->minExtent && wb_rot < -90.0f) { - wb_rot = -90.0f; + if (jw->extent <= jw->minExtent && wb_rot_ < -90.0f) { + wb_rot_ = -90.0f; drive_angle = RA(rot1_d + -90.0f); } - ajw->wb_rot = wb_rot; - ajw->cabin_x += cos(drive_angle * D2R) * ds; - ajw->cabin_z += sin(drive_angle * D2R) * ds; + wb_rot = wb_rot_; + cabin_x += cos(drive_angle * D2R) * ds; + cabin_z += sin(drive_angle * D2R) * ds; - //log_msg("to ap: rot1_d: %.2f, ajw->cabin_x: %0.3f, ajw->cabin_z: %0.3f, drive_angle: %0.2f, wb_rot: %0.2f", - // rot1_d, ajw->cabin_x, ajw->cabin_z, drive_angle, ajw->wb_rot); + //log_msg("to ap: rot1_d: %.2f, cabin_x: %0.3f, cabin_z: %0.3f, drive_angle: %0.2f, wb_rot: %0.2f", + // rot1_d, cabin_x, cabin_z, drive_angle, wb_rot); - if (rotate_wheel_base(ajw, dt)) { - ajw->wait_wb_rot = 1; - return 0; + if (! rotate_wheel_base(dt)) { + wait_wb_rot = true; + return false; } - ajw->wait_wb_rot = 0; + wait_wb_rot = false; // rotation2 - float tgt_rot2 = ajw->tgt_rot2; - if (ajw->cabin_x < (tgt_x - 1.0f) || ajw->cabin_z < -2.0f) { - float angle_to_door = atan2f(-ajw->cabin_z, ajw->tgt_x - ajw->cabin_x) / D2R; - tgt_rot2 = RA(angle_to_door + 90.0f - ajw->psi - jw->rotate1); // point to door + float tgt_rot2 = door_rot2; + if (cabin_x < (tgt_x - 1.0f) || cabin_z < -2.0f) { + float angle_to_door = atan2f(-cabin_z, door_x - cabin_x) / D2R; + tgt_rot2 = RA(angle_to_door + 90.0f - psi - jw->rotate1); // point to door } - //log_msg("jw->rotate2: %0.1f, ajw->tgt_rot2: %0.1f, tgt_rot2: %0.1f", jw->rotate2, ajw->tgt_rot2, tgt_rot2); + //log_msg("jw->rotate2: %0.1f, tgt_rot2: %0.1f, tgt_rot2: %0.1f", jw->rotate2, tgt_rot2, tgt_rot2); - rotate_2(ajw, tgt_rot2, dt); - rotate_1_extend(ajw, ajw->cabin_x, ajw->cabin_z); - rotate_3(ajw, ajw->tgt_rot3, dt); - animate_wheels(ajw, ds); + rotate_2(tgt_rot2, dt); + rotate_1_extend(); + rotate_3(door_rot3, dt); + animate_wheels(ds); } - if (ajw->state == AJW_AT_AP) { + if (state == AJW_AT_AP) { // use the time to rotate the wheel base towards the door - ajw->wb_rot = RA(-rot1_d); - rotate_wheel_base(ajw, dt); + wb_rot = RA(-rot1_d); + rotate_wheel_base(dt); // rotation 2 + 3 must be at target now - if (rotate_2(ajw, ajw->tgt_rot2, dt) && rotate_3(ajw, ajw->tgt_rot3, dt)) - ajw->state = AJW_TO_DOOR; + if (rotate_2(door_rot2, dt) && rotate_3(door_rot3, dt)) + state = AJW_TO_DOOR; } - if (ajw->state == AJW_TO_DOOR) { - if (ajw->wait_wb_rot) { + if (state == AJW_TO_DOOR) { + if (wait_wb_rot) { // log_msg("AJW_TO_AP: waiting for wb rotation"); - if (rotate_wheel_base(ajw, dt)) - return 0; - ajw->wait_wb_rot = 0; + if (! rotate_wheel_base(dt)) + return false; + wait_wb_rot = false; } - float tgt_x = ajw->tgt_x; + double tgt_x = door_x; - ajw->cabin_x = MIN(ajw->cabin_x, tgt_x); // dont drive beyond the target point + cabin_x = std::min(cabin_x, tgt_x); // dont drive beyond the target point - //log_msg("to door: rot1_d: %.2f, ajw->cabin_x: %0.3f, ajw->cabin_z: %0.3f", rot1_d, ajw->cabin_x, ajw->cabin_z); + //log_msg("to door: rot1_d: %.2f, cabin_x: %0.3f, cabin_z: %0.3f", rot1_d, cabin_x, cabin_z); // ramp down speed when approaching the plane float drive_speed = JW_DRIVE_SPEED; - if (ajw->cabin_x >= (ajw->tgt_x - 0.8f)) - drive_speed = JW_DRIVE_SPEED * (0.1f + 0.9f * MAX(0.0f, (ajw->tgt_x - ajw->cabin_x) / 0.8f)); + if (cabin_x >= (tgt_x - 0.8f)) + drive_speed = JW_DRIVE_SPEED * (0.1f + 0.9f * std::max(0.0f, float((tgt_x - cabin_x)) / 0.8f)); float ds = dt * drive_speed; - ajw->cabin_x += ds; - //log_msg("ajw->cabin_x: %0.3f, ajw->cabin_z: %0.3f", ajw->cabin_x, ajw->cabin_z); + cabin_x += ds; + //log_msg("cabin_x: %0.3f, cabin_z: %0.3f", cabin_x, cabin_z); - ajw->wb_rot = RA(-rot1_d); - if (rotate_wheel_base(ajw, dt)) { - ajw->wait_wb_rot = 1; - return 0; + wb_rot = RA(-rot1_d); + if (! rotate_wheel_base(dt)) { + wait_wb_rot = true; + return false; } - ajw->wait_wb_rot = 0; + wait_wb_rot = false; - rotate_1_extend(ajw, ajw->cabin_x, ajw->cabin_z); - animate_wheels(ajw, ds); + rotate_1_extend(); + animate_wheels(ds); - float eps = MAX(2.0f * dt * JW_DRIVE_SPEED, 0.05f); - //log_msg("eps: %0.3f, d_x: %0.3f", eps, fabs(tgt_x - ajw->cabin_x)); - if (fabs(tgt_x - ajw->cabin_x) < eps) { - ajw->state = AJW_DOCKED; + float eps = std::max(2.0f * dt * JW_DRIVE_SPEED, 0.05f); + //log_msg("eps: %0.3f, d_x: %0.3f", eps, fabs(tgt_x - cabin_x)); + if (fabs(tgt_x - cabin_x) < eps) { + state = AJW_DOCKED; log_msg("door reached"); jw->warnlight = 0; - alert_off(ajw); - return 1; // done + alert_off(); + return true; // done } } - alert_setpos(ajw); - return 0; + alert_setpos(); + return false; } // drive jetway to parked position -// return 1 when done -static float -undock_drive(jw_ctx_t *ajw) +auto +JwCtrl::undock_drive() -> bool { - sam_jw_t *jw = ajw->jw; - - if (ajw->state == AJW_PARKED) + if (state == AJW_PARKED) return 1; - if (now < ajw->start_ts) + if (now < start_ts) return 0; // guard against a hung animation - if (now > ajw->timeout) { + if (now > timeout) { log_msg("undock_drive() timeout!"); - ajw->state = AJW_PARKED; + state = AJW_PARKED; jw->rotate1 = jw->initialRot1; jw->rotate2 = jw->initialRot2; jw->rotate3 = jw->initialRot3; jw->extent = jw->initialExtent; jw->warnlight = 0; - alert_off(ajw); + alert_off(); return 1; // -> done } - float dt = now - ajw->last_step_ts; - ajw->last_step_ts = now; + float dt = now - last_step_ts; + last_step_ts = now; - float rot1_d = RA((jw->rotate1 + ajw->psi) - 90.0f); // door frame + float rot1_d = RA((jw->rotate1 + psi) - 90.0f); // door frame - //float wheel_x = ajw->x + (jw->extent + jw->wheelPos) * cosf(rot1_d * D2R); - //float wheel_z = ajw->z + (jw->extent + jw->wheelPos) * sinf(rot1_d * D2R); + //float wheel_x = x + (jw->extent + jw->wheelPos) * cosf(rot1_d * D2R); + //float wheel_z = z + (jw->extent + jw->wheelPos) * sinf(rot1_d * D2R); - if (ajw->state == AJW_TO_AP) { - if (ajw->wait_wb_rot) { + if (state == AJW_TO_AP) { + if (wait_wb_rot) { //log_msg("AJW_TO_AP: waiting for wb rotation"); - if (rotate_wheel_base(ajw, dt)) { + if (! rotate_wheel_base(dt)) { return 0; } - ajw->wait_wb_rot = 0; + wait_wb_rot = false; } - float tgt_x = ajw->ap_x; + float tgt_x = ap_x; - float eps = MAX(2.0f * dt * JW_DRIVE_SPEED, 0.1f); - //log_msg("eps: %0.3f, %0.3f, %0.3f", eps, fabs(tgt_x - ajw->cabin_x), fabs(ajw->cabin_z)); - if (fabs(tgt_x - ajw->cabin_x) < eps && fabs(ajw->cabin_z) < eps) { - ajw->state = AJW_AT_AP; + float eps = std::max(2.0f * dt * JW_DRIVE_SPEED, 0.1f); + //log_msg("eps: %0.3f, %0.3f, %0.3f", eps, fabs(tgt_x - cabin_x), fabs(cabin_z)); + if (fabs(tgt_x - cabin_x) < eps && fabs(cabin_z) < eps) { + state = AJW_AT_AP; log_msg("align point reached reached"); return 0; } double ds = dt * 0.5 * JW_DRIVE_SPEED; - double drive_angle = atan2(-ajw->cabin_z, tgt_x - ajw->cabin_x) / D2R; + double drive_angle = atan2(-cabin_z, tgt_x - cabin_x) / D2R; - ajw->cabin_x += cos(drive_angle * D2R) * ds; - ajw->cabin_z += sin(drive_angle * D2R) * ds; - //log_msg("to ap: rot1_d: %.2f, ajw->cabin_x: %0.3f, ajw->cabin_z: %0.3f, wheel_x: %0.3f, wheel_z: %0.3f, drive_angle: %0.2f", - // rot1_d, ajw->cabin_x, ajw->cabin_z, wheel_x, wheel_z, drive_angle); + cabin_x += cos(drive_angle * D2R) * ds; + cabin_z += sin(drive_angle * D2R) * ds; + //log_msg("to ap: rot1_d: %.2f, cabin_x: %0.3f, cabin_z: %0.3f, wheel_x: %0.3f, wheel_z: %0.3f, drive_angle: %0.2f", + // rot1_d, cabin_x, cabin_z, wheel_x, wheel_z, drive_angle); - ajw->wb_rot = RA(drive_angle - rot1_d); - if (rotate_wheel_base(ajw, dt)) { - ajw->wait_wb_rot = 1; + wb_rot = RA(drive_angle - rot1_d); + if (! rotate_wheel_base(dt)) { + wait_wb_rot = true; return 0; } - ajw->wait_wb_rot = 0; + wait_wb_rot = false; - rotate_1_extend(ajw, ajw->cabin_x, ajw->cabin_z); - animate_wheels(ajw, ds); + rotate_1_extend(); + animate_wheels(ds); } - if (ajw->state == AJW_AT_AP) { + if (state == AJW_AT_AP) { // nothing for now - ajw->state = AJW_TO_PARK; + state = AJW_TO_PARK; } - if (ajw->state == AJW_TO_PARK) { - if (ajw->wait_wb_rot) { + if (state == AJW_TO_PARK) { + if (wait_wb_rot) { // log_msg("AJW_TO_AP: waiting for wb rotation"); - if (rotate_wheel_base(ajw, dt)) { + if (! rotate_wheel_base(dt)) { return 0; } - ajw->wait_wb_rot = 0; + wait_wb_rot = false; } - float tgt_x = ajw->parked_x; - float tgt_z = ajw->parked_z; + float tgt_x = parked_x; + float tgt_z = parked_z; - //log_msg("to park: rot1_d: %.2f, ajw->cabin_x: %0.3f, ajw->cabin_z: %0.3f, wheel_x: %0.3f, wheel_z: %0.3f", - // rot1_d, ajw->cabin_x, ajw->cabin_z, wheel_x, wheel_z); + //log_msg("to park: rot1_d: %.2f, cabin_x: %0.3f, cabin_z: %0.3f, wheel_x: %0.3f, wheel_z: %0.3f", + // rot1_d, cabin_x, cabin_z, wheel_x, wheel_z); double ds = dt * JW_DRIVE_SPEED; - double drive_angle = atan2(tgt_z - ajw->cabin_z, tgt_x - ajw->cabin_x) / D2R; + double drive_angle = atan2(tgt_z - cabin_z, tgt_x - cabin_x) / D2R; // wb_rot is drive_angle in the 'tunnel frame' - float wb_rot = RA(drive_angle - rot1_d); + float wb_rot_ = RA(drive_angle - rot1_d); // avoid compression of jetway - if (jw->extent <= jw->minExtent && wb_rot > 90.0f) { - wb_rot = 90.0f; + if (jw->extent <= jw->minExtent && wb_rot_ > 90.0f) { + wb_rot_ = 90.0f; drive_angle = RA(rot1_d + 90.0f); } - ajw->wb_rot = wb_rot; + wb_rot = wb_rot_; - ajw->cabin_x += cos(drive_angle * D2R) * ds; - ajw->cabin_z += sin(drive_angle * D2R) * ds; - //log_msg("to parked: rot1_d: %.2f, ajw->cabin_x: %0.3f, ajw->cabin_z: %0.3f, wheel_x: %0.3f, wheel_z: %0.3f, drive_angle: %0.2f", - // rot1_d, ajw->cabin_x, ajw->cabin_z, wheel_x, wheel_z, drive_angle); + cabin_x += cos(drive_angle * D2R) * ds; + cabin_z += sin(drive_angle * D2R) * ds; + //log_msg("to parked: rot1_d: %.2f, cabin_x: %0.3f, cabin_z: %0.3f, wheel_x: %0.3f, wheel_z: %0.3f, drive_angle: %0.2f", + // rot1_d, cabin_x, cabin_z, wheel_x, wheel_z, drive_angle); - if (rotate_wheel_base(ajw, dt)) { - ajw->wait_wb_rot = 1; + if (! rotate_wheel_base(dt)) { + wait_wb_rot = true; return 0; } - ajw->wait_wb_rot = 0; + wait_wb_rot = false; - rotate_2(ajw, jw->initialRot2, dt); - rotate_3(ajw, jw->initialRot3, dt); - rotate_1_extend(ajw, ajw->cabin_x, ajw->cabin_z); - animate_wheels(ajw, ds); + rotate_2(jw->initialRot2, dt); + rotate_3(jw->initialRot3, dt); + rotate_1_extend(); + animate_wheels(ds); - float eps = MAX(2.0f * dt * JW_DRIVE_SPEED, 0.1f); - //log_msg("eps: %0.3f, %0.3f, %0.3f", eps, fabs(tgt_x - ajw->cabin_x), fabs(tgt_z - ajw->cabin_z)); - if (fabs(tgt_x - ajw->cabin_x) < eps && fabs(tgt_z -ajw->cabin_z) < eps) { - ajw->state = AJW_PARKED; + float eps = std::max(2.0f * dt * JW_DRIVE_SPEED, 0.1f); + //log_msg("eps: %0.3f, %0.3f, %0.3f", eps, fabs(tgt_x - cabin_x), fabs(tgt_z - cabin_z)); + if (fabs(tgt_x - cabin_x) < eps && fabs(tgt_z -cabin_z) < eps) { + state = AJW_PARKED; jw->warnlight = 0; - alert_off(ajw); + alert_off(); log_msg("park position reached"); return 1; // done } } - alert_setpos(ajw); + alert_setpos(); return 0; } @@ -1266,21 +1221,22 @@ jw_state_machine() } break; - case PARKED: - // find airport I'm on now to ease debugging - lat = XPLMGetDataf(plane_lat_dr); - lon = XPLMGetDataf(plane_lon_dr); - XPLMNavRef ref = XPLMFindNavAid(NULL, NULL, &lat, &lon, NULL, xplm_Nav_Airport); - if (XPLM_NAV_NOT_FOUND != ref) { - XPLMGetNavAidInfo(ref, NULL, NULL, NULL, NULL, NULL, NULL, airport_id, - NULL, NULL); - log_msg("parked on airport: %s, lat,lon: %0.5f,%0.5f", airport_id, lat, lon); - } + case PARKED: { + // find airport I'm on now to ease debugging + lat = XPLMGetDataf(plane_lat_dr); + lon = XPLMGetDataf(plane_lon_dr); + XPLMNavRef ref = XPLMFindNavAid(NULL, NULL, &lat, &lon, NULL, xplm_Nav_Airport); + if (XPLM_NAV_NOT_FOUND != ref) { + XPLMGetNavAidInfo(ref, NULL, NULL, NULL, NULL, NULL, NULL, airport_id, + NULL, NULL); + log_msg("parked on airport: %s, lat,lon: %0.5f,%0.5f", airport_id, lat, lon); + } - if (find_nearest_jws()) - new_state = SELECT_JWS; - else - new_state = CANT_DOCK; + if (find_nearest_jws()) + new_state = SELECT_JWS; + else + new_state = CANT_DOCK; + } break; case SELECT_JWS: @@ -1300,16 +1256,16 @@ jw_state_machine() // or wait for GUI selection if (n_active_jw) { for (int i = 0; i < n_door; i++) { - jw_ctx_t *ajw = &active_jw[i]; - sam_jw_t *jw = ajw->jw; + JwCtrl *ajw = &active_jw[i]; + SamJw *jw = ajw->jw; - if (NULL == jw) + if (nullptr == jw) continue; log_msg("setting up active jw for door: %d", i); - jw_ctx_for_door(ajw, &door_info[i]); + ajw->setup_for_door(&door_info[i]); if (i == 0) // slightly slant towards the nose cone for door LF1 - ajw->tgt_rot2 += 3.0f; + ajw->door_rot2 += 3.0f; } new_state = CAN_DOCK; @@ -1326,8 +1282,8 @@ jw_state_machine() log_msg("docking requested"); int active_door = 0; for (int i = 0; i < n_door; i++) { - jw_ctx_t *ajw = &active_jw[i]; - if (NULL == ajw->jw) + JwCtrl *ajw = &active_jw[i]; + if (nullptr == ajw->jw) continue; ajw->state = AJW_TO_AP; @@ -1335,7 +1291,7 @@ jw_state_machine() ajw->start_ts = now + active_door * 5.0f; ajw->last_step_ts = ajw->start_ts; ajw->timeout = ajw->start_ts + JW_ANIM_TIMEOUT; - alert_on(ajw); + ajw->alert_on(); ajw->jw->warnlight = 1; active_door++; } @@ -1354,11 +1310,12 @@ jw_state_machine() case DOCKING: n_done = 0; for (int i = 0; i < n_door; i++) { - jw_ctx_t *ajw = &active_jw[i]; - if (NULL == ajw->jw) + JwCtrl *ajw = &active_jw[i]; + if (nullptr == ajw->jw) continue; - n_done += dock_drive(ajw); + if (ajw->dock_drive()) + n_done++; } if (n_done == n_active_jw) { @@ -1386,8 +1343,8 @@ jw_state_machine() log_msg("undocking requested"); int active_door = n_door; for (int i = 0; i < n_door; i++) { - jw_ctx_t *ajw = &active_jw[i]; - if (NULL == ajw->jw) + JwCtrl *ajw = &active_jw[i]; + if (nullptr == ajw->jw) continue; active_door--; @@ -1396,7 +1353,7 @@ jw_state_machine() ajw->start_ts = now + active_door * 5.0f; ajw->last_step_ts = ajw->start_ts; ajw->timeout = ajw->start_ts + JW_ANIM_TIMEOUT; - alert_on(ajw); + ajw->alert_on(); ajw->jw->warnlight = 1; } @@ -1411,10 +1368,11 @@ jw_state_machine() case UNDOCKING: n_done = 0; for (int i = 0; i < n_door; i++) { - jw_ctx_t *ajw = &active_jw[i]; - if (NULL == ajw->jw) + JwCtrl *ajw = &active_jw[i]; + if (nullptr == ajw->jw) continue; - n_done += undock_drive(&active_jw[i]); + if (ajw->undock_drive()) + n_done++; } if (n_done == n_active_jw) @@ -1490,10 +1448,7 @@ int jw_init() { // load alert sound - char fn[sizeof(base_dir) + 100]; - strcpy(fn, base_dir); - strcat(fn, "sound/alert.wav"); - read_wav(fn, &alert); + read_wav(base_dir + "sound/alert.wav", &alert); if (alert.data) log_msg("alert sound loaded, channels: %d, bit_rate: %d, size: %d", alert.num_channels, alert.sample_rate, alert.size); @@ -1505,6 +1460,8 @@ jw_init() if (!sound_init()) return 0; + zc_jws.reserve(150); + dock_cmdr = XPLMCreateCommand("openSAM/dock_jwy", "Dock jetway"); XPLMRegisterCommandHandler(dock_cmdr, cmd_dock_jw_cb, 0, &dock_requested); @@ -1520,7 +1477,7 @@ jw_init() XPLMRegisterCommandHandler(xp12_toggle_cmdr, cmd_xp12_dock_jw_cb, 1, NULL); // create the jetway animation datarefs - for (dr_code_t drc = DR_ROTATE1; drc < N_JW_DR; drc++) { + for (int drc = DR_ROTATE1; drc < N_JW_DR; drc++) { char name[100]; name[99] = '\0'; snprintf(name, sizeof(name) - 1, "sam/jetway/%s", dr_name_jw[drc]); diff --git a/os_jw.h b/os_jw.h index 519d1d0..9946b89 100644 --- a/os_jw.h +++ b/os_jw.h @@ -22,9 +22,10 @@ static const float FAR_SKIP = 5000; // (m) don't consider jetways farther away -struct _sam_jw { +class SamJw { + public: int is_zc_jw; // is a zero config jw - stand_t *stand; // back pointer to stand for zc jetways + Stand* stand; // back pointer to stand for zc jetways // local x,z computed from the xml's lat/lon float xml_x, xml_y, xml_z; @@ -53,12 +54,30 @@ struct _sam_jw { int door; // 0 = LF1 or default, 1 = LF2 float bb_lat_min, bb_lat_max, bb_lon_min, bb_lon_max; // bounding box for FAR_SKIP + + + // set wheels height + auto set_wheels() -> void { + wheels = tanf(rotate3 * D2R) * (wheelPos + extent); + } + + auto reset() -> void { + rotate1 = initialRot1; + rotate2 = initialRot2; + rotate3 = initialRot3; + extent = initialExtent; + set_wheels(); + warnlight = 0; + } + + auto fill_library_values(int id) -> void; + auto find_stand() -> Stand*; }; // fortunately SAM3 is abandoned so this will never change 8-) #define MAX_SAM3_LIB_JW 27 // index is 0..27 -extern sam_jw_t sam3_lib_jw[]; +extern SamJw sam3_lib_jw[]; extern int jw_init(void); extern float jw_state_machine(); diff --git a/os_jw_impl.h b/os_jw_impl.h index 6927a60..93991f3 100644 --- a/os_jw_impl.h +++ b/os_jw_impl.h @@ -37,8 +37,10 @@ typedef enum ajw_status_e { AJW_TO_PARK } ajw_status_t; -typedef struct jw_ctx_ { - sam_jw_t *jw; // == NULL means empty +// jetway controller +class JwCtrl { + public: + SamJw *jw; // == NULL means empty ajw_status_t state; // in door local coordinates @@ -47,13 +49,13 @@ typedef struct jw_ctx_ { int soft_match; // does not really fulfill matching criteria // target cabin position with corresponding dref values - float tgt_x, tgt_rot1, tgt_rot2, tgt_rot3, tgt_extent; + float door_x, door_rot1, door_rot2, door_rot3, door_extent; float ap_x; // alignment point abeam door float parked_x, parked_z; double cabin_x, cabin_z; - int wait_wb_rot; // waiting for wheel base rotation + bool wait_wb_rot; // waiting for wheel base rotation float wb_rot; // to this angle float start_ts; // actually start operation if now > start_ts @@ -61,21 +63,53 @@ typedef struct jw_ctx_ { float timeout; // so we don't get stuck FMOD_CHANNEL *alert_chn; -} jw_ctx_t; + + auto setup_for_door(const door_info_t *door_info) -> void; + + // convert tunnel end at (cabin_x, cabin_z) to dataref values; rot2, rot3 are optional + auto xz_to_sam_dr(float cabin_x, float cabin_z, + float& rot1, float& extent, float *rot2, float *rot3) -> void; + + // + // animation + // + private: + auto rotate_1_extend() -> void; + + // rotation 2/3 to angle, return true when done + auto rotate_2(float rot2, float dt) -> bool; + auto rotate_3(float rot3, float dt) -> bool; + + auto rotate_wheel_base(float dt) -> bool; + + auto animate_wheels(float ds) -> void; + + public: + // drive jetway, return true when done + auto dock_drive() -> bool; + auto undock_drive() -> bool; + + // sound stuff + auto alert_on() -> void; + auto alert_off()-> void; + auto alert_setpos() -> void; + + friend bool operator<(const JwCtrl&, const JwCtrl&); +}; #define NEAR_JW_LIMIT 3 // max # of jetways we consider for docking #define MAX_NEAREST 10 // max # jetways / door we consider as nearest extern int n_active_jw; -extern jw_ctx_t active_jw[MAX_DOOR]; +extern JwCtrl active_jw[MAX_DOOR]; -extern jw_ctx_t nearest_jw[MAX_NEAREST]; +extern JwCtrl nearest_jw[MAX_NEAREST]; extern int n_nearest; extern void jw_auto_mode_change(void); // from os_read_wav.c -extern void read_wav(const char *fname, sound_t *sound); +extern void read_wav(const std::string& fname, sound_t *sound); // from os_ui.c extern int ui_unlocked; // the ui is unlocked for jw_selection @@ -84,6 +118,3 @@ extern void update_ui(int only_if_visible); // from os_sound.c extern sound_t alert; extern int sound_init(void); -extern void alert_on(jw_ctx_t *ajw); -extern void alert_off(jw_ctx_t *ajw); -extern void alert_setpos(jw_ctx_t *ajw); diff --git a/os_sound.c b/os_sound.cpp similarity index 71% rename from os_sound.c rename to os_sound.cpp index 4a32f60..8a6e279 100644 --- a/os_sound.c +++ b/os_sound.cpp @@ -20,7 +20,7 @@ */ -#include +#include #include "openSAM.h" #include "os_jw.h" @@ -39,38 +39,33 @@ alert_complete(void *ref, FMOD_RESULT status) { UNUSED(status); - jw_ctx_t *ajw = ref; + JwCtrl *ajw = (JwCtrl *)ref; ajw->alert_chn = NULL; } -void -alert_on(jw_ctx_t *ajw) +auto JwCtrl::alert_on() -> void { - if (ajw->alert_chn) + if (alert_chn) return; - ajw->alert_chn = XPLMPlayPCMOnBus(alert.data, alert.size, FMOD_SOUND_FORMAT_PCM16, + alert_chn = XPLMPlayPCMOnBus(alert.data, alert.size, FMOD_SOUND_FORMAT_PCM16, alert.sample_rate, alert.num_channels, 1, xplm_AudioExteriorUnprocessed, - alert_complete, ajw); + alert_complete, this); - alert_setpos(ajw); - XPLMSetAudioFadeDistance(ajw->alert_chn, 20.0f, 150.0f ); - XPLMSetAudioVolume(ajw->alert_chn, 1.3f); + alert_setpos(); + XPLMSetAudioFadeDistance(alert_chn, 20.0f, 150.0f ); + XPLMSetAudioVolume(alert_chn, 1.3f); } -void -alert_off(jw_ctx_t *ajw) +auto JwCtrl::alert_off() -> void { - if (ajw->alert_chn) - XPLMStopAudio(ajw->alert_chn); - ajw->alert_chn = NULL; + if (alert_chn) + XPLMStopAudio(alert_chn); + alert_chn = NULL; } -void -alert_setpos(jw_ctx_t *ajw) +auto JwCtrl::alert_setpos() -> void { - const sam_jw_t *jw = ajw->jw; - static FMOD_VECTOR vel = {0.0f, 0.0f, 0.0f}; FMOD_VECTOR pos; @@ -78,5 +73,5 @@ alert_setpos(jw_ctx_t *ajw) pos.x = jw->x + (jw->extent + jw->cabinPos) * cosf(rot1 * D2R); pos.y = jw->y + jw->height; pos.z = jw->z + (jw->extent + jw->cabinPos) * sinf(rot1 * D2R); - XPLMSetAudioPosition(ajw->alert_chn, &pos, &vel); + XPLMSetAudioPosition(alert_chn, &pos, &vel); } diff --git a/os_sound_xp11.c b/os_sound_xp11.cpp similarity index 95% rename from os_sound_xp11.c rename to os_sound_xp11.cpp index 76ed0b5..79ef95e 100644 --- a/os_sound_xp11.c +++ b/os_sound_xp11.cpp @@ -41,7 +41,7 @@ sound_t alert; static ALuint snd_src; static ALuint snd_buffer; -static const ALfloat zero[3]; +static const ALfloat zero[3] = {}; static int paused; static XPLMDataRef audio_dr, paused_dr, view_external_dr; @@ -94,19 +94,18 @@ sound_init() return 1; } void -alert_on(jw_ctx_t *ajw) +JwCtrl::alert_on() { if (0 == snd_src) return; - alert_setpos(ajw); + alert_setpos(); alSourcePlay(snd_src); } void -alert_off(jw_ctx_t *ajw) +JwCtrl::alert_off() { - UNUSED(ajw); if (0 == snd_src) return; @@ -114,13 +113,11 @@ alert_off(jw_ctx_t *ajw) } void -alert_setpos(jw_ctx_t *ajw) +JwCtrl::alert_setpos() { if (0 == snd_src) return; - const sam_jw_t *jw = ajw->jw; - // Pause sound while sim is paused if (XPLMGetDatai(paused_dr)) { if (!paused) diff --git a/os_ui.c b/os_ui.cpp similarity index 99% rename from os_ui.c rename to os_ui.cpp index cb12957..cfa7831 100644 --- a/os_ui.c +++ b/os_ui.cpp @@ -203,8 +203,8 @@ update_ui(int only_if_visible) if (ui_unlocked && !auto_select_jws) { for (int i = 0; i < n_door; i++) for (int j = 0; j < n_nearest; j++) { - jw_ctx_t *njw = &nearest_jw[j]; - sam_jw_t *jw = njw->jw; + JwCtrl *njw = &nearest_jw[j]; + SamJw *jw = njw->jw; if (NULL == jw) // should never happen continue; diff --git a/read_wav.c b/read_wav.cpp similarity index 93% rename from read_wav.c rename to read_wav.cpp index 5447cd9..452a0bf 100644 --- a/read_wav.c +++ b/read_wav.cpp @@ -57,13 +57,13 @@ typedef struct WAV_HEADER // file than the ones supplied here. // void -read_wav(const char *fname, sound_t *sound) +read_wav(const std::string& fname, sound_t *sound) { memset(sound, 0, sizeof(sound_t)); - FILE *f = fopen(fname, "rb"); + FILE *f = fopen(fname.c_str(), "rb"); if (NULL == f) { - log_msg("can't open wav %s", fname); + log_msg("can't open wav %s", fname.c_str()); return; } @@ -117,6 +117,6 @@ read_wav(const char *fname, sound_t *sound) } fclose (f); - log_msg("can't find data chunk in %s", fname); + log_msg("can't find data chunk in %s", fname.c_str()); return; } diff --git a/sam_xml.c b/sam_xml.cpp similarity index 50% rename from sam_xml.c rename to sam_xml.cpp index e767ee9..56e37cd 100644 --- a/sam_xml.c +++ b/sam_xml.cpp @@ -20,13 +20,15 @@ */ -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include +#include +#include #include @@ -48,24 +50,15 @@ typedef struct _expat_ctx { bool in_objects; bool in_gui; - scenery_t *sc; - - int max_sam_jws; - int max_sam_objs; - int max_sam_anims; - int max_sam_drfs; - - sam_drf_t *cur_dataref; + Scenery* sc; + SamDrf *cur_dataref; } expat_ctx_t; -scenery_t *sceneries; -int n_sceneries; -static int max_sceneries; +std::vector sceneries; -sam_jw_t sam3_lib_jw[MAX_SAM3_LIB_JW + 1]; +SamJw sam3_lib_jw[MAX_SAM3_LIB_JW + 1]; -sam_drf_t *sam_drfs; -int n_sam_drfs; +std::vector sam_drfs; static const int BUFSIZE = 4096; @@ -106,9 +99,9 @@ lookup_attr(const XML_Char **attr, const char *name) { } static void -get_jw_attrs(const XML_Char **attr, sam_jw_t *sam_jw) +get_jw_attrs(const XML_Char **attr, SamJw *sam_jw) { - *sam_jw = (sam_jw_t){0}; + *sam_jw = (SamJw){}; GET_INT_ATTR(sam_jw, id) GET_STR_ATTR(sam_jw, name) @@ -150,18 +143,18 @@ get_jw_attrs(const XML_Char **attr, sam_jw_t *sam_jw) static int lookup_drf(const char *name) { - for (int i = 0; i < n_sam_drfs; i++) - if (0 == strcmp(sam_drfs[i].name, name)) + for (unsigned int i = 0; i < sam_drfs.size(); i++) + if (0 == strcmp(sam_drfs[i]->name, name)) return i; return -1; } static int -lookup_obj(const scenery_t *sc, const char *id) +lookup_obj(const Scenery* sc, const char *id) { - for (int i = 0; i < sc->n_sam_objs; i++) - if (0 == strcmp(sc->sam_objs[i].id, id)) + for (unsigned int i = 0; i < sc->sam_objs.size(); i++) + if (0 == strcmp(sc->sam_objs[i]->id, id)) return i; return -1; @@ -170,7 +163,7 @@ lookup_obj(const scenery_t *sc, const char *id) // expat's callbacks static void XMLCALL start_element(void *user_data, const XML_Char *name, const XML_Char **attr) { - expat_ctx_t *ctx = user_data; + expat_ctx_t *ctx = (expat_ctx_t *)user_data; if (0 == strcmp(name, "scenery")) { GET_STR_ATTR(ctx->sc, name); @@ -188,22 +181,15 @@ start_element(void *user_data, const XML_Char *name, const XML_Char **attr) { } if (ctx->in_jetways && (0 == strcmp(name, "jetway"))) { - scenery_t *sc = ctx->sc; - - if (sc->n_sam_jws == ctx->max_sam_jws) { - ctx->max_sam_jws += 100; - sc->sam_jws = realloc(sc->sam_jws, ctx->max_sam_jws * sizeof(sam_jw_t)); - if (sc->sam_jws == NULL) - goto oom; - } - - get_jw_attrs(attr, &sc->sam_jws[sc->n_sam_jws]); - sc->n_sam_jws++; + Scenery* sc = ctx->sc; + SamJw *jw = new SamJw(); + get_jw_attrs(attr, jw); + sc->sam_jws.push_back(jw); return; } if (ctx->in_sets && (0 == strcmp(name, "set"))) { - sam_jw_t sam_jw; + SamJw sam_jw; get_jw_attrs(attr, &sam_jw); if (!BETWEEN(sam_jw.id, 1, MAX_SAM3_LIB_JW)) { log_msg("invalid library jw '%s', %d", sam_jw.name, sam_jw.id); @@ -222,41 +208,34 @@ start_element(void *user_data, const XML_Char *name, const XML_Char **attr) { if (ctx->in_datarefs && (0 == strcmp(name, "dataref"))) { ctx->in_dataref = true; - ctx->cur_dataref = NULL; //for (int i = 0; attr[i]; i += 2) // log_msg("dataref %s, %s", attr[i], attr[i+1]); - if (n_sam_drfs == ctx->max_sam_drfs) { - ctx->max_sam_drfs += 100; - sam_drfs = realloc(sam_drfs, ctx->max_sam_drfs * sizeof(sam_drf_t)); - if (sam_drfs == NULL) - goto oom; - } - - ctx->cur_dataref = &sam_drfs[n_sam_drfs]; - *(ctx->cur_dataref) = (sam_drf_t){0}; + auto drf = new SamDrf(); + ctx->cur_dataref = drf; - GET_STR_ATTR(ctx->cur_dataref, name); - if (ctx->cur_dataref->name[0] == '\0') { + GET_STR_ATTR(drf, name); + if (drf->name[0] == '\0') { log_msg("name attribute not found for dataref"); ctx->cur_dataref = NULL; + return; } - if (lookup_drf(ctx->cur_dataref->name) >= 0) { - log_msg("duplicate definition for dataref '%s', ingnored", ctx->cur_dataref->name); + if (lookup_drf(drf->name) >= 0) { + log_msg("duplicate definition for dataref '%s', ingnored", drf->name); ctx->cur_dataref = NULL; + return; } - if (ctx->cur_dataref) { - GET_BOOL_ATTR(ctx->cur_dataref, autoplay); - GET_BOOL_ATTR(ctx->cur_dataref, randomize_phase); - GET_BOOL_ATTR(ctx->cur_dataref, augment_wind_speed); - } + GET_BOOL_ATTR(drf, autoplay); + GET_BOOL_ATTR(drf, randomize_phase); + GET_BOOL_ATTR(drf, augment_wind_speed); + sam_drfs.push_back(drf); return; } if (ctx->in_dataref && ctx->cur_dataref && (0 == strcmp(name, "animation"))) { - sam_drf_t *d = ctx->cur_dataref; + SamDrf *d = ctx->cur_dataref; if (d->n_tv == DRF_MAX_ANIM) { log_msg("animation table overflow for %s", d->name); return; @@ -291,24 +270,15 @@ start_element(void *user_data, const XML_Char *name, const XML_Char **attr) { } if (ctx->in_objects && (0 == strcmp(name, "instance"))) { - scenery_t *sc = ctx->sc; + Scenery* sc = ctx->sc; - if (sc->n_sam_objs == ctx->max_sam_objs) { - ctx->max_sam_objs += 100; - sc->sam_objs = realloc(sc->sam_objs, ctx->max_sam_objs * sizeof(sam_obj_t)); - if (sc->sam_objs == NULL) - goto oom; - } - - sam_obj_t *obj = &sc->sam_objs[sc->n_sam_objs]; - - *obj = (sam_obj_t){0}; + SamObj *obj = new SamObj(); GET_STR_ATTR(obj, id); GET_FLOAT_ATTR(obj, latitude); GET_FLOAT_ATTR(obj, longitude); GET_FLOAT_ATTR(obj, elevation); GET_FLOAT_ATTR(obj, heading); - sc->n_sam_objs++; + sc->sam_objs.push_back(obj); return; } @@ -319,18 +289,9 @@ start_element(void *user_data, const XML_Char *name, const XML_Char **attr) { } if (ctx->in_gui && (0 == strcmp(name, "checkbox"))) { - scenery_t *sc = ctx->sc; - - if (sc->n_sam_anims == ctx->max_sam_anims) { - ctx->max_sam_anims += 100; - sc->sam_anims = realloc(sc->sam_anims, ctx->max_sam_anims * sizeof(sam_anim_t)); - if (sc->sam_anims == NULL) - goto oom; - } + Scenery* sc = ctx->sc; - sam_anim_t *anim = &sc->sam_anims[sc->n_sam_anims]; - - *anim = (sam_anim_t){0}; + SamAnim *anim = new SamAnim(); GET_STR_ATTR(anim, label); GET_STR_ATTR(anim, title); @@ -345,24 +306,20 @@ start_element(void *user_data, const XML_Char *name, const XML_Char **attr) { anim->drf_idx = lookup_drf(name); if (anim->obj_idx >= 0 && anim->drf_idx >= 0) - sc->n_sam_anims++; - else + sc->sam_anims.push_back(anim); + else { + delete(anim); log_msg("dataref of object not found for checkbox entry"); - + } return; } return; - - oom: - log_msg("Can't allocate memory"); - XML_StopParser(ctx->parser, XML_FALSE); - return; } static void XMLCALL end_element(void *user_data, const XML_Char *name) { - expat_ctx_t *ctx = user_data; + expat_ctx_t *ctx = (expat_ctx_t *)user_data; if (0 == strcmp(name, "jetways")) ctx->in_jetways = false; @@ -375,12 +332,8 @@ end_element(void *user_data, const XML_Char *name) { else if (0 == strcmp(name, "dataref")) { ctx->in_dataref = false; - if (ctx->cur_dataref) { - if (ctx->cur_dataref->n_tv >= 2) // sanity check - n_sam_drfs++; - else - log_msg("too few animation entries for %s", ctx->cur_dataref->name); - } + if (ctx->cur_dataref && ctx->cur_dataref->n_tv < 2) // sanity check + log_msg("too few animation entries for %s", ctx->cur_dataref->name); } else if (0 == strcmp(name, "objects")) @@ -391,11 +344,14 @@ end_element(void *user_data, const XML_Char *name) { } static int -parse_sam_xml(int fd, scenery_t *sc) +parse_sam_xml(const std::string& fn, Scenery* sc) { - *sc = (scenery_t){0}; - int rc = 0; + int fd = open(fn.c_str(), O_RDONLY|O_BINARY); + if (fd < 0) + return 0; + + log_msg("Processing '%s'", fn.c_str()); XML_Parser parser = XML_ParserCreate(NULL); if (NULL == parser) goto out; @@ -430,6 +386,7 @@ parse_sam_xml(int fd, scenery_t *sc) rc = 1; out: + close(fd); if (parser) XML_ParserFree(parser); parser = NULL; @@ -437,242 +394,158 @@ parse_sam_xml(int fd, scenery_t *sc) } // go through apt.dat and collect stand information from 1300 lines -static int -parse_apt_dat(FILE *f, scenery_t *sc) +static bool +parse_apt_dat(const std::string& fn, Scenery* sc) { - char line[2000]; // can be quite long + std::ifstream apt(fn); + if (apt.fail()) + return false; - int max_stands = 0; + log_msg("Processing '%s'", fn.c_str()); - while (fgets(line, sizeof(line) - 1, f)) { - char *cptr = strchr(line, '\r'); - if (cptr) - *cptr = '\0'; + std::string line; + line.reserve(2000); // can be quite long - cptr = strchr(line, '\n'); - if (cptr) - *cptr = '\0'; + while (std::getline(apt, line)) { + size_t i = line.find('\r'); + if (i != std::string::npos) + line.resize(i); - if (line == strstr(line, "1300 ")) { + if (line.find("1300 ") == 0) { //log_msg("%s", line); - if (sc->n_stands == max_stands) { - max_stands += 100; - sc->stands = realloc(sc->stands, max_stands * sizeof(stand_t)); - if (sc->stands == NULL) { - log_msg("Can't allocate memory"); - return 0; - } - } - stand_t *stand = &sc->stands[sc->n_stands]; - *stand = (stand_t){0}; + line.erase(0, 5); + Stand *stand = new Stand(); int len; - int n = sscanf(line + 5, "%f %f %f %*s %*s %n", + int n = sscanf(line.c_str(), "%f %f %f %*s %*s %n", &stand->lat, &stand->lon, &stand->hdgt, &len); if (3 == n) { - strncpy(stand->id, line + 5 + len, sizeof(stand->id) - 1); + strncpy(stand->id, line.c_str() + len, sizeof(stand->id) - 1); //log_msg("%d %d, %f %f %f '%s'", n, len, stand->lat, stand->lon, stand->hdgt, stand->id); stand->hdgt = RA(stand->hdgt); stand->sin_hdgt = sinf(D2R * stand->hdgt); stand->cos_hdgt = cosf(D2R * stand->hdgt); - sc->n_stands++; + sc->stands.push_back(stand); + } else { + delete(stand); } } } - return 1; + apt.close(); + return true; } -// make a complete filename for ../sam.xml from a line of scenery_packs.ini -static int -mk_sam_fn(const char *xp_dir, char *line, char *fn, int fn_size) +// SceneryPacks contructor +SceneryPacks::SceneryPacks(const std::string& xp_dir) { - char *cptr = strchr(line, '\r'); - if (cptr) - *cptr = '\0'; + std::string scpi_name(xp_dir + "/Custom Scenery/scenery_packs.ini"); - cptr = strchr(line, '\n'); - if (cptr) - *cptr = '\0'; + std::ifstream scpi(scpi_name); + if (scpi.fail()) { + log_msg("Can't open '%s'", scpi_name.c_str()); + return; + } - cptr = strstr(line, "SCENERY_PACK "); - if (NULL == cptr) - return 0; - char *scenery_path = cptr + 13; - int is_absolute = (scenery_path[0] == '/' || strchr(scenery_path, ':')); + sc_paths.reserve(500); + std::string line; - fn[0] = '\0'; + while (std::getline(scpi, line)) { + size_t i; + if ((i = line.find('\r')) != std::string::npos) + line.resize(i); - if (is_absolute) { - strncpy(fn, scenery_path, fn_size - 100); - } else { - strncpy(fn, xp_dir, fn_size - 100); - strcat(fn, "/"); - strncat(fn, scenery_path, fn_size - 100); - } + if (line.find("SCENERY_PACK ") != 0 || line.find("*GLOBAL_AIRPORTS*") != std::string::npos) + continue; - strcat(fn, "sam.xml"); + // autoortho pretends every file exists but + // reads give errors + if (line.find("/z_ao_") != std::string::npos) + continue; - // posixify - for (cptr = fn; *cptr; cptr++) - if (*cptr == '\\') - *cptr = '/'; + line.erase(0, 13); + std::string sc_path; + bool is_absolute = (line[0] == '/' || line.find(':') != std::string::npos); + if (is_absolute) + sc_path = line; + else + sc_path = xp_dir + "/" + line; - return 1; -} + // posixify + for (unsigned i = 0; i < sc_path.size(); i++) + if (sc_path[i] == '\\') + sc_path[i] = '/'; + + if (sc_path.find("/openSAM_Library/") != std::string::npos) { + openSAM_Library_path = sc_path; + continue; + } + + if (sc_path.find("/SAM_Library/") != std::string::npos) { + SAM_Library_path = sc_path; + continue; + } -#define REALLOC_CHECK(ptr, n, type) \ -if (ptr) { \ - ptr = realloc(ptr, (n) * sizeof(type)); \ - if ((n) > 0 && NULL == ptr) { \ - log_msg("out of memory " #ptr); \ - return 0; \ - } \ + sc_paths.push_back(sc_path); + } + + scpi.close(); + sc_paths.shrink_to_fit(); + if (openSAM_Library_path.size() == 0) { + log_msg("openSAM_Library is not installed!"); + valid = false; + return; + } + + valid = true; } // collect sam.xml from all sceneries int -collect_sam_xml(const char *xp_dir) +collect_sam_xml(const SceneryPacks &scp) { - char line[1000]; - line[sizeof(line) - 1] = '\0'; - strncpy(line, xp_dir, sizeof(line) - 200); - strcat(line, "/Custom Scenery/scenery_packs.ini"); - - FILE *scp = fopen(line, "r"); - if (NULL == scp) { - log_msg("Can't open '%s'", line); + // drefs from openSAM_Library must come first + Scenery dummy; + if (!parse_sam_xml(scp.openSAM_Library_path + "sam.xml", &dummy)) return 0; - } - max_sceneries = 100; - sceneries = realloc(sceneries, max_sceneries * sizeof(scenery_t)); - if (sceneries == NULL) { - log_msg("Can't allocate memory"); - fclose(scp); - return 0; + if (scp.SAM_Library_path.size() > 0) { + Scenery dummy; + if (!parse_sam_xml(scp.SAM_Library_path + "libraryjetways.xml", &dummy)) + return 0; } - // sam's default datarefs must be defined first, so we need 2 passes - // openSAM_Library only - while (fgets(line, sizeof(line) - 100, scp)) { - char fn[2000]; - if (!mk_sam_fn(xp_dir, line, fn, sizeof(fn))) + for (auto sc_path : scp.sc_paths) { + Scenery* sc = new Scenery(); + if (!parse_sam_xml(sc_path + "sam.xml", sc)) { + delete(sc); continue; - - if (NULL == strstr(fn, "/openSAM_Library/")) - continue; - - //log_msg("Trying '%s'", fn); - int fd = open(fn, O_RDONLY|O_BINARY); - if (fd > 0) { - log_msg("Processing '%s'", fn); - - scenery_t *sc = &sceneries[n_sceneries]; - int rc = parse_sam_xml(fd, sc); - close(fd); - if (!rc) { - fclose(scp); - return 0; - } - break; } - } - // second pass, everything but openSAM_Library - rewind(scp); - while (fgets(line, sizeof(line) - 100, scp)) { - char fn[2000]; - if (!mk_sam_fn(xp_dir, line, fn, sizeof(fn))) - continue; + // read stands from apt.dat + parse_apt_dat(sc_path + "Earth nav data/apt.dat", sc); - if (strstr(fn, "/openSAM_Library/")) - continue; - - // autoortho pretends every file exists but - // reads give errors - if (strstr(fn, "/z_ao_")) + // don't save empty sceneries + if (sc->sam_jws.size() == 0 && sc->stands.size() == 0 && sc->sam_anims.size() == 0) { + delete(sc); continue; - - char *path_end = strrchr(fn, '/'); - - //log_msg("Trying '%s'", fn); - int fd = open(fn, O_RDONLY|O_BINARY); - if (fd > 0) { - log_msg("Processing '%s'", fn); - - if (n_sceneries == max_sceneries) { - max_sceneries += 100; - sceneries = realloc(sceneries, max_sceneries * sizeof(scenery_t)); - if (sceneries == NULL) { - log_msg("Can't allocate memory"); - fclose(scp); close(fd); - return 0; - } - } - - scenery_t *sc = &sceneries[n_sceneries]; - - int rc = parse_sam_xml(fd, sc); - close(fd); - if (rc) { - // read stands from apt.dat - strcpy(path_end, "/Earth nav data/apt.dat"); - - //log_msg("Trying '%s'", fn); - FILE *f = fopen(fn, "r"); - if (f) { - log_msg("Processing '%s'", fn); - rc = parse_apt_dat(f, sc); - fclose(f); - if (!rc) { - fclose(scp); - return 0; - } - } - - // don't save empty sceneries - if (sc->n_sam_jws > 0 || sc->n_stands > 0 || sc->n_sam_anims > 0) - n_sceneries++; - } } - strcpy(path_end, "/libraryjetways.xml"); - //log_msg("Trying '%s'", fn); - fd = open(fn, O_RDONLY|O_BINARY); - if (fd > 0) { - log_msg("Processing '%s'", fn); - scenery_t dummy; - int rc = parse_sam_xml(fd, &dummy); - close(fd); - if (!rc) - return 0; - } - } - - fclose(scp); - - REALLOC_CHECK(sceneries, n_sceneries, scenery_t); - REALLOC_CHECK(sam_drfs, n_sam_drfs, sam_drf_t); - - static const float far_skip_dlat = FAR_SKIP / LAT_2_M; - - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) { + static const float far_skip_dlat = FAR_SKIP / LAT_2_M; // shrink to actual - - REALLOC_CHECK(sc->sam_jws, sc->n_sam_jws, sam_jw_t); - REALLOC_CHECK(sc->stands, sc->n_stands, stand_t); - REALLOC_CHECK(sc->sam_anims, sc->n_sam_anims, sam_anim_t); - REALLOC_CHECK(sc->sam_objs, sc->n_sam_objs, sam_obj_t); + sc->sam_jws.shrink_to_fit(); + sc->stands.shrink_to_fit(); + sc->sam_anims.shrink_to_fit(); + sc->sam_objs.shrink_to_fit(); // compute the bounding boxes sc->bb_lat_min = sc->bb_lon_min = 1000.0f; sc->bb_lat_max = sc->bb_lon_max = -1000.0f; - for (sam_jw_t *jw = sc->sam_jws; jw < sc->sam_jws + sc->n_sam_jws; jw++) { + for (auto jw : sc->sam_jws) { jw->bb_lat_min = jw->latitude - far_skip_dlat; jw->bb_lat_max = jw->latitude + far_skip_dlat; @@ -680,26 +553,31 @@ collect_sam_xml(const char *xp_dir) jw->bb_lon_min = RA(jw->longitude - far_skip_dlon); jw->bb_lon_max = RA(jw->longitude + far_skip_dlon); - sc->bb_lat_min = MIN(sc->bb_lat_min, jw->bb_lat_min); - sc->bb_lat_max = MAX(sc->bb_lat_max, jw->bb_lat_max); + sc->bb_lat_min = std::min(sc->bb_lat_min, jw->bb_lat_min); + sc->bb_lat_max = std::max(sc->bb_lat_max, jw->bb_lat_max); - sc->bb_lon_min = MIN(sc->bb_lon_min, jw->bb_lon_min); - sc->bb_lon_max = MAX(sc->bb_lon_max, jw->bb_lon_max); + sc->bb_lon_min = std::min(sc->bb_lon_min, jw->bb_lon_min); + sc->bb_lon_max = std::max(sc->bb_lon_max, jw->bb_lon_max); } - for (stand_t *stand = sc->stands; stand < sc->stands + sc->n_stands; stand++) { + for (auto stand : sc->stands) { float far_skip_dlon = far_skip_dlat / cosf(stand->lat * D2R); - sc->bb_lat_min = MIN(sc->bb_lat_min, stand->lat - far_skip_dlat); - sc->bb_lat_max = MAX(sc->bb_lat_max, stand->lat + far_skip_dlat); + sc->bb_lat_min = std::min(sc->bb_lat_min, stand->lat - far_skip_dlat); + sc->bb_lat_max = std::max(sc->bb_lat_max, stand->lat + far_skip_dlat); - sc->bb_lon_min = MIN(sc->bb_lon_min, stand->lon - far_skip_dlon); - sc->bb_lon_max = MAX(sc->bb_lon_max, stand->lon + far_skip_dlon); + sc->bb_lon_min = std::min(sc->bb_lon_min, stand->lon - far_skip_dlon); + sc->bb_lon_max = std::max(sc->bb_lon_max, stand->lon + far_skip_dlon); } // don't consider objects as these may be far away (e.g. Aerosoft LSZH) + + sceneries.push_back(sc); } + sceneries.shrink_to_fit(); + sam_drfs.shrink_to_fit(); + return 1; } diff --git a/sam_xml_test.c b/sam_xml_test.cpp similarity index 61% rename from sam_xml_test.c rename to sam_xml_test.cpp index e45765f..9c2a7ad 100644 --- a/sam_xml_test.c +++ b/sam_xml_test.cpp @@ -20,10 +20,11 @@ */ -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "openSAM.h" #include "os_dgs.h" @@ -33,19 +34,26 @@ int main(int argc, char **argv) { - if (!collect_sam_xml("E:/X-Plane-12")) { + std::cout << "sam_xml_test starting\n"; + + SceneryPacks scp("E:/X-Plane-12"); + if (! scp.valid) { + log_msg("%s", "Can't create SceneryPacks"); + return 1; + } + + if (!collect_sam_xml(scp)) { log_msg("Error reading sam.xml files"); exit(2); } - printf("\n%d sceneries collected\n", n_sceneries); + printf("\n%d sceneries collected\n", (int)sceneries.size()); - printf("%d datarefs collected\n", n_sam_drfs); + printf("%d datarefs collected\n", (int)sam_drfs.size()); - for (int i = 0; i < n_sam_drfs; i++) { - sam_drf_t *drf = &sam_drfs[i]; - printf("%2d: %s, auto_play: %d, randomize_phase: %d, augment_wind_speed: %d\n", - i, drf->name, drf->autoplay, drf->randomize_phase, drf->augment_wind_speed); + for (auto drf : sam_drfs) { + printf("%s, auto_play: %d, randomize_phase: %d, augment_wind_speed: %d\n", + drf->name, drf->autoplay, drf->randomize_phase, drf->augment_wind_speed); for (int j = 0; j < drf->n_tv; j++) printf(" t: %6.2f, v: %6.2f\n", drf->t[j], drf->v[j]); @@ -53,27 +61,23 @@ main(int argc, char **argv) { puts(""); } - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) { + for (auto sc : sceneries) { printf("%s: %d jetways, %d stands collected, bbox: %0.3f,%0.3f -> %0.3f, %0.3f\n", - sc->name, sc->n_sam_jws, sc->n_stands, + sc->name, (int)sc->sam_jws.size(), (int)sc->stands.size(), sc->bb_lat_min, sc->bb_lon_min, sc->bb_lat_max, sc->bb_lon_max); puts("\nObjects"); - for (int i = 0; i < sc->n_sam_objs; i++) { - sam_obj_t *obj = &sc->sam_objs[i]; - printf("%2d: %s %5.6f %5.6f %5.6f %5.6f\n", i, obj->id, obj->latitude, obj->longitude, + for (auto obj : sc->sam_objs) + printf("%s %5.6f %5.6f %5.6f %5.6f\n", obj->id, obj->latitude, obj->longitude, obj->elevation, obj->heading); - } puts("\nAnimations"); - for (int i = 0; i < sc->n_sam_anims; i++) { - sam_anim_t *anim = &sc->sam_anims[i]; + for (auto anim : sc->sam_anims) printf("'%s' '%s', obj: '%s', drf: '%s'\n", anim->label, anim->title, - sc->sam_objs[anim->obj_idx].id, sam_drfs[anim->drf_idx].name); - } + sc->sam_objs[anim->obj_idx]->id, sam_drfs[anim->drf_idx]->name); puts("\nJetways"); - for (sam_jw_t *jw = sc->sam_jws; jw < sc->sam_jws + sc->n_sam_jws; jw++) { + for (auto jw : sc->sam_jws) { printf("%s %5.6f %5.6f door: %d\n", jw->name, jw->latitude, jw->longitude, jw->door); } puts("\n"); @@ -81,21 +85,21 @@ main(int argc, char **argv) { puts("Library jetways"); for (int i = 0; i <= MAX_SAM3_LIB_JW; i++) { - sam_jw_t *jw = &sam3_lib_jw[i]; + SamJw *jw = &sam3_lib_jw[i]; if (jw->id == 0) continue; log_msg("%d; %s height: %0.2f, cabinPos: %0.2f", jw->id, jw->name, jw->height, jw->cabinPos); } puts("Ramps"); - for (scenery_t *sc = sceneries; sc < sceneries + n_sceneries; sc++) { + for (auto sc : sceneries) { printf("%s\n", sc->name); - for (stand_t *stand = sc->stands; stand < sc->stands + sc->n_stands; stand++) { + for (auto stand : sc->stands) { log_msg("%-40s %5.6f, %5.6f %6.2f", stand->id, stand->lat, stand->lon, stand->hdgt); } puts("\n"); } - return (1); + return (0); } diff --git a/version.mak b/version.mak index 69f97d9..df3f71a 100644 --- a/version.mak +++ b/version.mak @@ -1 +1 @@ -VERSION=2.00-beta-1 +VERSION=3.00-dev