diff --git a/ProffieOS.ino b/ProffieOS.ino index 701b422de..9ff43afee 100644 --- a/ProffieOS.ino +++ b/ProffieOS.ino @@ -638,6 +638,7 @@ class NoLED; #include "modes/bool_setting.h" #include "modes/color_menues.h" #include "modes/sorted_list_menues.h" +#include "modes/style_option_modes.h" BladeConfig* current_config = nullptr; class BladeBase* GetPrimaryBlade() { @@ -655,6 +656,17 @@ int GetBladeNumber(BladeBase *blade) { return 0; } +#define RETURN_BLADE_BY_NUMBER(N) case N: return current_config->blade##N; + +// 1 is first blade +BladeBase* GetBladeByNumber(int n) { + if (!current_config) return nullptr; + switch (n) { + ONCEPERBLADE(RETURN_BLADE_BY_NUMBER); + } + return nullptr; +} + const char* GetSaveDir() { if (!current_config) return ""; if (!current_config->save_dir) return ""; @@ -693,9 +705,9 @@ int prop_GetBulletCount() { } #endif -class Color16 GetColorArg(int blade, int arg) { return prop.GetColorArg(blade, arg); } -void SetArg(int blade, int arg, const char* argument) { prop.SetArg(blade, arg, argument); } -void SetColorArg(int blade, int arg, Color16 color) { prop.SetColorArg(blade, arg, color); } +const char* GetStyle(int blade) { return prop.GetStyle(blade); } +void SetStyle(int blade, LSPtr style); +void SetStyle(int blade, LSPtr style) { prop.SetStyle(blade, std::move(style)); } void SetFont(const char* font) { prop.SetFont(font); } void SetTrack(const char* track) { prop.SetTrack(track); } const char* GetFont() { return prop.GetFont(); } diff --git a/common/color.h b/common/color.h index 0ba20589a..9d396f5cd 100644 --- a/common/color.h +++ b/common/color.h @@ -40,6 +40,10 @@ class Color8 { enum Byteorder { NONE = 0, + R = 0x1, + G = 0x2, + B = 0x3, + // RGB colors BGR=0x321, BRG=0x312, @@ -80,11 +84,17 @@ class Color8 { }; static int num_bytes(int byteorder) { - return byteorder <= 0xfff ? 3 : 4; + return + byteorder <= 0xf ? 1 : + byteorder <= 0xfff ? 3 : + 4; } static constexpr int inline_num_bytes(int byteorder) __attribute__((always_inline)) { - return byteorder <= 0xfff ? 3 : 4; + return + byteorder <= 0xf ? 1 : + byteorder <= 0xfff ? 3 : + 4; } diff --git a/modes/color_menues.h b/modes/color_menues.h index 280e72f95..4ba744292 100644 --- a/modes/color_menues.h +++ b/modes/color_menues.h @@ -92,7 +92,7 @@ struct ColorBlueMode : public SPEC::GammaMode { template struct SaveColorMenuEntry : public MenuEntry { void say(int entry) override { - getSL->SaySave(); + getSL()->SaySave(); } void select(int entry) override { getPtr()->save(); diff --git a/modes/smooth_mode.h b/modes/smooth_mode.h index c7d19a3db..dd224504f 100644 --- a/modes/smooth_mode.h +++ b/modes/smooth_mode.h @@ -63,8 +63,6 @@ struct SmoothMode : public SPEC::SelectCancelMode { float last_angle_; }; -// TODO: Smooth mode without wraparound. - } // namespace mode #endif diff --git a/modes/style_argument_helpers.h b/modes/style_argument_helpers.h index e6b80fde4..6c61d5b52 100644 --- a/modes/style_argument_helpers.h +++ b/modes/style_argument_helpers.h @@ -1,15 +1,83 @@ #ifndef MODE_STYLE_ARGUMENT_HELPERS #define MODE_STYLE_ARGUMENT_HELPERS +const char* GetStyle(int blade); +void SetStyle(int blade, LSPtr style); + namespace mode { int menu_current_blade = 1; int menu_current_arg = 0; + +bool isTimeArg(int arg) { + switch (arg) { + case IGNITION_TIME_ARG: + case IGNITION_DELAY_ARG: + case RETRACTION_TIME_ARG: + case RETRACTION_DELAY_ARG: + return true; + } +} + +bool GetArg(int blade, int arg, char* argspace) { + return style_parser.GetArgument(GetStyle(blade), arg + 2, argspace); +} +void SetArg(int blade, int arg, const char* argument) { + SetStyle(blade, style_parser.SetArgument(GetStyle(blade), arg + 2, argument)); +} + +Color16 GetColorArg(int blade, int arg) { + char argspace[32]; + if (GetArg(blade, arg, argspace)) { + char* tmp; + int r = strtol(argspace, &tmp, 0); + int g = strtol(tmp+1, &tmp, 0); + int b = strtol(tmp+1, NULL, 0); + return Color16(r,g,b); + } + return Color16(65535,0,0); +} + +void SetColorArg(int blade, int arg, Color16 color) { + char tmp[32]; + itoa(color.r, tmp, 10); + strcat(tmp, ","); + itoa(color.g, tmp + strlen(tmp), 10); + strcat(tmp, ","); + itoa(color.b, tmp + strlen(tmp), 10); + + SetArg(blade, arg, tmp); +} + +int GetIntArg(int blade, int arg) { + char argspace[32]; + if (GetArg(blade, arg, argspace)) { + return strtol(argspace, nullptr, 0); + } + return -1; +} +void SetIntArg(int blade, int arg, int value) { + char tmp[32]; + itoa(value, tmp, 10); + SetArg(blade, arg, tmp); +} + +BladeStyle* GetCurrentBladeStyle() { + BladeBase* blade = GetBladeByNumber(menu_current_blade); + if (!blade) return nullptr; + return blade->current_style(); +} + +int GetMaxStyleArg() { + BladeStyle* style = GetCurrentBladeStyle(); + if (!style) return ARG_MAX_UNKNOWN; + return style->get_max_arg(menu_current_arg); +} + + } // namespace mode -Color16 GetColorArg(int blade, int arg); -void SetArg(int blade, int arg, const char* argument); -void SetColorArg(int blade, int arg, Color16 color); + #endif diff --git a/modes/style_option_modes.h b/modes/style_option_modes.h new file mode 100644 index 000000000..baa071f31 --- /dev/null +++ b/modes/style_option_modes.h @@ -0,0 +1,114 @@ +#ifndef MODES_STYLE_OPTION_MODES_H +#define MODES_STYLE_OPTION_MODES_H + +namespace mode { + +template +class SelectArgSmoothMode : public SPEC::SmoothMode { +public: + int get() override { return GetIntArg(menu_current_blade, menu_current_arg); } + int set(int x) { + value_ = x; + if (!getSL()->busy()) { + getSL()->SayWhole(x * 100 / 32768); + getSL()->SayPercent(); + } + } + + void select() override { + SPEC::SmoothMode::select(); + SetIntArg(menu_current_blade, menu_current_arg, value_); + popMode(); + } + +private: + int value_ = 0; +}; + +template +class SelectArgTime : public SPEC::SmoothMode { +public: + int get() override { return GetIntArg(menu_current_blade, menu_current_arg); } + float t(int x) { return powf(x / 32768.0f, 2.0) * 30.0; } + int set(int x) { + value_ = x; + if (!getSL()->busy()) { + getSL()->SayNumber(t(x), SAY_DECIMAL); + getSL()->SaySeconds(); + } + } + + void select() override { + SPEC::SmoothMode::select(); + SetIntArg(menu_current_blade, menu_current_arg, (int)(t(value_) * 1000)); + popMode(); + } + +private: + int value_ = 0; +}; + +template +class SelectArgNumber : public SPEC::MenuBase { +public: + void activate(bool onreturn) override { + SPEC::MenuBase::activate(onreturn); + if (!onreturn) { + int max = GetMaxStyleArg(); + if (max < 0) max = 32768; + max_ = max; + this->pos_ = GetIntArg(menu_current_blade, menu_current_arg); + // TODO: What if pos_ > max_ ? + } + } + void say() override { + getSL()->SayWhole(this->pos_); + } + uint16_t size() override { return max_; } + + void select() override { + SPEC::SmoothMode::select(); + SetIntArg(menu_current_blade, menu_current_arg, this->pos_); + popMode(); + } +private: + uint16_t max_; +}; + +template +class SelectArgMode : public SPEC::MenuBase { +public: + void activate(bool onreturn) override { + // TODO: Set pos_ to something reasonable? + arginfo_ = style_parser.GetArgInfo(GetStyle(menu_current_blade)); + SPEC::MenuBase::activate(onreturn); + } + int size() override { return arginfo_.used(); } + void say() override { + getSL()->SayArgument(getCurrentArgument()); + } + + void select() override { + menu_current_arg = getCurrentArgument(); + if (arginfo_.iscolor(menu_current_arg)) { + pushMode(); + } else { + int max_arg = GetMaxStyleArg(); + if (max_arg == 32768 || max_arg == 32767) { + pushMode(); + } else if (max_arg <= 0 && isTimeArg(menu_current_arg)) { + pushMode(); + } else { + pushMode(); + } + } + } + +protected: + int getCurrentArgument() { return arginfo_.nth(this->pos_); } + ArgInfo arginfo_; +}; + +} // namespace mode + +#endif diff --git a/props/prop_base.h b/props/prop_base.h index 52676b634..5269a5d92 100644 --- a/props/prop_base.h +++ b/props/prop_base.h @@ -1714,36 +1714,14 @@ class PropBase : CommandParser, Looper, protected SaberBase, public ModeInterfac } virtual bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) = 0; - - Color16 GetColorArg(int blade, int arg) { - char argspace[32]; - if (style_parser.GetArgument(current_preset_.GetStyle(blade), arg + 2, argspace)) { - char* tmp; - int r = strtol(argspace, &tmp, 0); - int g = strtol(tmp+1, &tmp, 0); - int b = strtol(tmp+1, NULL, 0); - return Color16(r,g,b); - } - return Color16(65535,0,0); + const char* GetStyle(int blade) { + return current_preset_.GetStyle(blade); } - - void SetArg(int blade, int arg, const char* argument) { - current_preset_.SetStyle(blade, style_parser.SetArgument(current_preset_.GetStyle(blade), arg + 2, argument)); - } - - void SetColorArg(int blade, int arg, Color16 color) { - char tmp[32]; - itoa(color.r, tmp, 10); - strcat(tmp, ","); - itoa(color.g, tmp + strlen(tmp), 10); - strcat(tmp, ","); - itoa(color.b, tmp + strlen(tmp), 10); - - SetArg(blade, arg, tmp); - + void SetStyle(int blade, LSPtr style) { + current_preset_.SetStyle(blade, std::move(style)); current_preset_.Save(); } - + void SetFont(const char* font) { current_preset_.font = mkstr(font); current_preset_.Save(); diff --git a/styles/get_arg_max.h b/styles/get_arg_max.h index ae7c1e771..0aa06c229 100644 --- a/styles/get_arg_max.h +++ b/styles/get_arg_max.h @@ -74,7 +74,6 @@ struct GetArgMaxT, REST...> { static const int value = combine_args(A, B); }; - template struct GetArgMax< SingleValueAdapter, IntSVF >>, ARG> { static const int value = MAX; }; diff --git a/styles/style_parser.h b/styles/style_parser.h index 0e2f64f5d..52880d876 100644 --- a/styles/style_parser.h +++ b/styles/style_parser.h @@ -210,6 +210,18 @@ class StyleParser : public CommandParser { return ap.nth(arg); } + // Returns the ArgInfo for this style. + ArgInfo GetArgInfo(const char* str) { + NamedStyle* style = FindStyle(str); + if (!style) return ArgInfo(); + GetUsedArgsParser ap(SkipWord(str)); + CurrentArgParser = ≈ + delete style->style_allocator->make(); + // Ignore the two "builtin" arguments + if (FirstWord(str, "builtin") && ap.used() <= 2) return ArgInfo(); + return ap.getArgInfo(); + } + // Get the Nth argument of a style string. // The output will be copied to |output|. // If the string itself doesn't contain that argument, the style