diff --git a/source/main/physics/ActorSpawner.cpp b/source/main/physics/ActorSpawner.cpp index df40728f66..6c3d5a01e7 100644 --- a/source/main/physics/ActorSpawner.cpp +++ b/source/main/physics/ActorSpawner.cpp @@ -3638,71 +3638,60 @@ void ActorSpawner::ProcessHydro(RigDef::Hydro & def) bool invisible = false; unsigned int hydro_flags = 0; - // Parse options - if (def.options.empty()) // Parse as if option 'n' (OPTION_n_NORMAL) was present + if (def.options == 0) { invisible = false; hydro_flags |= HYDRO_FLAG_DIR; } - else + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_i_INVISIBLE)) { - for (unsigned int i = 0; i < def.options.length(); ++i) - { - const char c = def.options[i]; - switch (c) - { - case RigDef::Hydro::OPTION_i_INVISIBLE: // i - invisible = true; - break; - case RigDef::Hydro::OPTION_n_NORMAL: // n - invisible = false; - hydro_flags |= HYDRO_FLAG_DIR; - break; - case RigDef::Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED: // 's': // speed changing hydro - hydro_flags |= HYDRO_FLAG_SPEED; - break; - case RigDef::Hydro::OPTION_a_INPUT_AILERON: // 'a': - hydro_flags |= HYDRO_FLAG_AILERON; - break; - case RigDef::Hydro::OPTION_r_INPUT_RUDDER: // 'r': - hydro_flags |= HYDRO_FLAG_RUDDER; - break; - case RigDef::Hydro::OPTION_e_INPUT_ELEVATOR: // 'e': - hydro_flags |= HYDRO_FLAG_ELEVATOR; - break; - case RigDef::Hydro::OPTION_u_INPUT_AILERON_ELEVATOR: // 'u': - hydro_flags |= (HYDRO_FLAG_AILERON | HYDRO_FLAG_ELEVATOR); - break; - case RigDef::Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR: // 'v': - hydro_flags |= (HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_ELEVATOR); - break; - case RigDef::Hydro::OPTION_x_INPUT_AILERON_RUDDER: // 'x': - hydro_flags |= (HYDRO_FLAG_AILERON | HYDRO_FLAG_RUDDER); - break; - case RigDef::Hydro::OPTION_y_INPUT_InvAILERON_RUDDER: // 'y': - hydro_flags |= (HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_RUDDER); - break; - case RigDef::Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER: // 'g': - hydro_flags |= (HYDRO_FLAG_ELEVATOR | HYDRO_FLAG_RUDDER); - break; - case RigDef::Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER: // 'h': - hydro_flags |= (HYDRO_FLAG_REV_ELEVATOR | HYDRO_FLAG_RUDDER); - break; - default: - this->AddMessage(Message::TYPE_WARNING, std::string("Ignoring invalid flag:") + c); - break; - } - - // NOTE: This is a quirk ported from v0.4.0.7 spawner (for compatibility) - // This code obviously belongs after the options-loop. - // However, since it's inside the loop, it only works correctly if the 'i' flag is last. - // - // ORIGINAL COMMENT: if you use the i flag on its own, add the direction to it - if (invisible && !hydro_flags) - { - hydro_flags |= HYDRO_FLAG_DIR; - } - } + invisible = true; + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED)) + { + hydro_flags |= HYDRO_FLAG_SPEED; + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_a_INPUT_AILERON)) + { + hydro_flags |= HYDRO_FLAG_AILERON; + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_r_INPUT_RUDDER)) + { + hydro_flags |= HYDRO_FLAG_RUDDER; + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_e_INPUT_ELEVATOR)) + { + hydro_flags |= HYDRO_FLAG_ELEVATOR; + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_u_INPUT_AILERON_ELEVATOR)) + { + hydro_flags |= (HYDRO_FLAG_AILERON | HYDRO_FLAG_ELEVATOR); + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR)) + { + hydro_flags |= (HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_ELEVATOR); + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_x_INPUT_AILERON_RUDDER)) + { + hydro_flags |= (HYDRO_FLAG_AILERON | HYDRO_FLAG_RUDDER); + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_y_INPUT_InvAILERON_RUDDER)) + { + hydro_flags |= (HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_RUDDER); + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER)) + { + hydro_flags |= (HYDRO_FLAG_ELEVATOR | HYDRO_FLAG_RUDDER); + } + if (BITMASK_IS_1(def.options, RigDef::Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER)) + { + hydro_flags |= (HYDRO_FLAG_REV_ELEVATOR | HYDRO_FLAG_RUDDER); + } + + // if you use the 'INVISIBLE' flag on its own, add the direction to it + if (invisible && !hydro_flags) + { + hydro_flags |= HYDRO_FLAG_DIR; } node_t & node_1 = GetNode(def.nodes[0]); diff --git a/source/main/resources/rig_def_fileformat/RigDef_File.h b/source/main/resources/rig_def_fileformat/RigDef_File.h index b5daace720..bde2bfb956 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_File.h +++ b/source/main/resources/rig_def_fileformat/RigDef_File.h @@ -274,6 +274,24 @@ enum class BeamOption: char s_SUPPORT = 's', }; +enum class HydroOption: char +{ + n_DUMMY = 'n', + i_INVISIBLE = 'i', + // Useful for trucks + s_DISABLE_ON_HIGH_SPEED = 's', + // Useful for planes: These can be used to control flight surfaces, or to create a thrust vectoring system. + a_INPUT_AILERON = 'a', + r_INPUT_RUDDER = 'r', + e_INPUT_ELEVATOR = 'e', + u_INPUT_AILERON_ELEVATOR = 'u', + v_INPUT_InvAILERON_ELEVATOR = 'v', + x_INPUT_AILERON_RUDDER = 'x', + y_INPUT_InvAILERON_RUDDER = 'y', + g_INPUT_ELEVATOR_RUDDER = 'g', + h_INPUT_InvELEVATOR_RUDDER = 'h', +}; + /* -------------------------------------------------------------------------- */ /* Utility */ /* -------------------------------------------------------------------------- */ @@ -1272,51 +1290,27 @@ struct SkeletonSettings struct Hydro { - Hydro(): - lenghtening_factor(0), - detacher_group(0) - {} - - static const char OPTION_n_NORMAL = 'n'; - static const char OPTION_i_INVISIBLE = 'i'; - - /* Useful for trucks */ - - static const char OPTION_s_DISABLE_ON_HIGH_SPEED = 's'; - - /* Useful for planes: These can be used to control flight surfaces, or to create a thrust vectoring system. */ - - static const char OPTION_a_INPUT_AILERON = 'a'; - static const char OPTION_r_INPUT_RUDDER = 'r'; - static const char OPTION_e_INPUT_ELEVATOR = 'e'; - static const char OPTION_u_INPUT_AILERON_ELEVATOR = 'u'; - static const char OPTION_v_INPUT_InvAILERON_ELEVATOR = 'v'; - static const char OPTION_x_INPUT_AILERON_RUDDER = 'x'; - static const char OPTION_y_INPUT_InvAILERON_RUDDER = 'y'; - static const char OPTION_g_INPUT_ELEVATOR_RUDDER = 'g'; - static const char OPTION_h_INPUT_InvELEVATOR_RUDDER = 'h'; - - inline bool HasFlag_a() { return options.find(RigDef::Hydro::OPTION_a_INPUT_AILERON) != std::string::npos; } - inline bool HasFlag_e() { return options.find(RigDef::Hydro::OPTION_e_INPUT_ELEVATOR) != std::string::npos; } - inline bool HasFlag_g() { return options.find(RigDef::Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER) != std::string::npos; } - inline bool HasFlag_h() { return options.find(RigDef::Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER) != std::string::npos; } - inline bool HasFlag_i() { return options.find(RigDef::Hydro::OPTION_i_INVISIBLE) != std::string::npos; } - inline bool HasFlag_r() { return options.find(RigDef::Hydro::OPTION_r_INPUT_RUDDER) != std::string::npos; } - inline bool HasFlag_s() { return options.find(RigDef::Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED) != std::string::npos; } - inline bool HasFlag_u() { return options.find(RigDef::Hydro::OPTION_u_INPUT_AILERON_ELEVATOR) != std::string::npos; } - inline bool HasFlag_v() { return options.find(RigDef::Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR) != std::string::npos; } - inline bool HasFlag_x() { return options.find(RigDef::Hydro::OPTION_x_INPUT_AILERON_RUDDER) != std::string::npos; } - inline bool HasFlag_y() { return options.find(RigDef::Hydro::OPTION_y_INPUT_InvAILERON_RUDDER) != std::string::npos; } - - inline void AddFlag(char flag) { options += flag; } + static const BitMask_t OPTION_i_INVISIBLE = BITMASK(1); + // Useful for trucks: + static const BitMask_t OPTION_s_DISABLE_ON_HIGH_SPEED = BITMASK(2); + // Useful for planes: These can be used to control flight surfaces, or to create a thrust vectoring system. + static const BitMask_t OPTION_a_INPUT_AILERON = BITMASK(3); + static const BitMask_t OPTION_r_INPUT_RUDDER = BITMASK(4); + static const BitMask_t OPTION_e_INPUT_ELEVATOR = BITMASK(5); + static const BitMask_t OPTION_u_INPUT_AILERON_ELEVATOR = BITMASK(6); + static const BitMask_t OPTION_v_INPUT_InvAILERON_ELEVATOR = BITMASK(7); + static const BitMask_t OPTION_x_INPUT_AILERON_RUDDER = BITMASK(8); + static const BitMask_t OPTION_y_INPUT_InvAILERON_RUDDER = BITMASK(9); + static const BitMask_t OPTION_g_INPUT_ELEVATOR_RUDDER = BITMASK(10); + static const BitMask_t OPTION_h_INPUT_InvELEVATOR_RUDDER = BITMASK(11); Node::Ref nodes[2]; - float lenghtening_factor; - std::string options; + float lenghtening_factor = 0.f; + BitMask_t options = 0; Inertia inertia; std::shared_ptr inertia_defaults; std::shared_ptr beam_defaults; - int detacher_group; + int detacher_group = 0; }; /* -------------------------------------------------------------------------- */ diff --git a/source/main/resources/rig_def_fileformat/RigDef_Parser.cpp b/source/main/resources/rig_def_fileformat/RigDef_Parser.cpp index 45251dfa9e..839e5182f5 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Parser.cpp +++ b/source/main/resources/rig_def_fileformat/RigDef_Parser.cpp @@ -2611,7 +2611,7 @@ void Parser::ParseHydros() hydro.nodes[1] = this->GetArgNodeRef(1); hydro.lenghtening_factor = this->GetArgFloat (2); - if (m_num_args > 3) { hydro.options = this->GetArgStr(3); } + if (m_num_args > 3) { hydro.options = this->GetArgHydroOptions(3); } this->ParseOptionalInertia(hydro.inertia, 4); @@ -3268,6 +3268,35 @@ BitMask_t Parser::GetArgBeamOptions(int index) return ret; } +BitMask_t Parser::GetArgHydroOptions (int index) +{ + BitMask_t ret = 0; + for (char c: this->GetArgStr(index)) + { + switch (c) + { + case (char)HydroOption::i_INVISIBLE : ret |= Hydro::OPTION_i_INVISIBLE ; break; + case (char)HydroOption::s_DISABLE_ON_HIGH_SPEED : ret |= Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED ; break; + case (char)HydroOption::a_INPUT_AILERON : ret |= Hydro::OPTION_a_INPUT_AILERON ; break; + case (char)HydroOption::r_INPUT_RUDDER : ret |= Hydro::OPTION_r_INPUT_RUDDER ; break; + case (char)HydroOption::e_INPUT_ELEVATOR : ret |= Hydro::OPTION_e_INPUT_ELEVATOR ; break; + case (char)HydroOption::u_INPUT_AILERON_ELEVATOR : ret |= Hydro::OPTION_u_INPUT_AILERON_ELEVATOR ; break; + case (char)HydroOption::v_INPUT_InvAILERON_ELEVATOR: ret |= Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR; break; + case (char)HydroOption::x_INPUT_AILERON_RUDDER : ret |= Hydro::OPTION_x_INPUT_AILERON_RUDDER ; break; + case (char)HydroOption::y_INPUT_InvAILERON_RUDDER : ret |= Hydro::OPTION_y_INPUT_InvAILERON_RUDDER ; break; + case (char)HydroOption::g_INPUT_ELEVATOR_RUDDER : ret |= Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER ; break; + case (char)HydroOption::h_INPUT_InvELEVATOR_RUDDER : ret |= Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER ; break; + + case (char)HydroOption::n_DUMMY: break; + + default: + this->LogMessage(Console::CONSOLE_SYSTEM_WARNING, + fmt::format("ignoring invalid option '{}'", c)); + } + } + return ret; +} + int Parser::TokenizeCurrentLine() { int cur_arg = 0; diff --git a/source/main/resources/rig_def_fileformat/RigDef_Parser.h b/source/main/resources/rig_def_fileformat/RigDef_Parser.h index 0570b445a1..3b6c3cd392 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Parser.h +++ b/source/main/resources/rig_def_fileformat/RigDef_Parser.h @@ -213,6 +213,7 @@ class Parser BitMask_t GetArgCabOptions (int index); BitMask_t GetArgTriggerOptions(int index); BitMask_t GetArgBeamOptions (int index); + BitMask_t GetArgHydroOptions (int index); float ParseArgFloat (const char* str); int ParseArgInt (const char* str); diff --git a/source/main/resources/rig_def_fileformat/RigDef_Serializer.cpp b/source/main/resources/rig_def_fileformat/RigDef_Serializer.cpp index c740241354..66cb45f951 100644 --- a/source/main/resources/rig_def_fileformat/RigDef_Serializer.cpp +++ b/source/main/resources/rig_def_fileformat/RigDef_Serializer.cpp @@ -2076,14 +2076,20 @@ void Serializer::ProcessHydro(Hydro & def) << std::setw(m_node_id_width) << def.nodes[1].ToString() << ", "; m_stream << std::setw(m_float_width) << def.lenghtening_factor << ", "; - if (def.options.empty()) - { - m_stream << "n"; // Placeholder, does nothing - } - else - { - m_stream << def.options; - } + + // Options + if (BITMASK_IS_1(def.options, Hydro::OPTION_i_INVISIBLE )) m_stream << (char)HydroOption::i_INVISIBLE ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_s_DISABLE_ON_HIGH_SPEED )) m_stream << (char)HydroOption::s_DISABLE_ON_HIGH_SPEED ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_a_INPUT_AILERON )) m_stream << (char)HydroOption::a_INPUT_AILERON ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_r_INPUT_RUDDER )) m_stream << (char)HydroOption::r_INPUT_RUDDER ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_e_INPUT_ELEVATOR )) m_stream << (char)HydroOption::e_INPUT_ELEVATOR ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_u_INPUT_AILERON_ELEVATOR )) m_stream << (char)HydroOption::u_INPUT_AILERON_ELEVATOR ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_v_INPUT_InvAILERON_ELEVATOR)) m_stream << (char)HydroOption::v_INPUT_InvAILERON_ELEVATOR; + if (BITMASK_IS_1(def.options, Hydro::OPTION_x_INPUT_AILERON_RUDDER )) m_stream << (char)HydroOption::x_INPUT_AILERON_RUDDER ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_y_INPUT_InvAILERON_RUDDER )) m_stream << (char)HydroOption::y_INPUT_InvAILERON_RUDDER ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_g_INPUT_ELEVATOR_RUDDER )) m_stream << (char)HydroOption::g_INPUT_ELEVATOR_RUDDER ; + if (BITMASK_IS_1(def.options, Hydro::OPTION_h_INPUT_InvELEVATOR_RUDDER )) m_stream << (char)HydroOption::h_INPUT_InvELEVATOR_RUDDER ; + if (def.options == 0) m_stream << (char)HydroOption::n_DUMMY; m_stream << ", "; // Inertia