Allow spinners to be clicked and held

This commit is contained in:
Ted John 2021-02-04 00:25:34 +00:00
parent c1b0df5de6
commit c2183989a5
7 changed files with 82 additions and 12 deletions

View file

@ -2125,8 +2125,16 @@ declare global {
interface SpinnerWidget extends WidgetBase {
type: 'spinner';
text?: string;
/**
* If true, the user can click and hold the decrement and increment
* button for repeated calls.
*/
isHoldable?: boolean;
onDecrement?: () => void;
onIncrement?: () => void;
onClick?: () => void;
}
interface TextBoxWidget extends WidgetBase {

View file

@ -856,6 +856,11 @@ bool WidgetIsDisabled(rct_window* w, rct_widgetindex widgetIndex)
return (w->disabled_widgets & (1LL << widgetIndex)) != 0;
}
bool WidgetIsHoldable(rct_window* w, rct_widgetindex widgetIndex)
{
return (w->hold_down_widgets & (1LL << widgetIndex)) != 0;
}
bool WidgetIsVisible(rct_window* w, rct_widgetindex widgetIndex)
{
return w->widgets[widgetIndex].IsVisible();
@ -1050,6 +1055,18 @@ void WidgetSetDisabled(rct_window* w, rct_widgetindex widgetIndex, bool value)
}
}
void WidgetSetHoldable(rct_window* w, rct_widgetindex widgetIndex, bool value)
{
if (value)
{
w->hold_down_widgets |= (1ULL << widgetIndex);
}
else
{
w->hold_down_widgets &= ~(1ULL << widgetIndex);
}
}
void WidgetSetVisible(rct_window* w, rct_widgetindex widgetIndex, bool value)
{
if (value)

View file

@ -77,6 +77,7 @@ namespace OpenRCT2::Ui::Windows
bool IsDisabled{};
bool IsVisible{};
bool IsPressed{};
bool IsHoldable{};
bool HasBorder{};
bool ShowColumnHeaders{};
bool IsStriped{};
@ -180,9 +181,11 @@ namespace OpenRCT2::Ui::Windows
}
else if (result.Type == "spinner")
{
result.IsHoldable = AsOrDefault(desc["isHoldable"], false);
result.Text = ProcessString(desc["text"]);
result.OnIncrement = desc["onIncrement"];
result.OnDecrement = desc["onDecrement"];
result.OnClick = desc["onClick"];
}
else if (result.Type == "textbox")
{
@ -564,8 +567,6 @@ namespace OpenRCT2::Ui::Windows
auto& scriptEngine = GetContext()->GetScriptEngine();
scriptEngine.ExecutePluginCall(info.Owner, widgetDesc->OnDraw, dukWidget, { dukG }, false);
}
// auto widgetDpi = dpi.Crop(
// { windowPos.x + widget.left, windowPos.y + widget.top }, { widget.width(), widget.height() });
}
}
else
@ -612,6 +613,14 @@ namespace OpenRCT2::Ui::Windows
args.push_back(DukValue::take_from_stack(ctx));
InvokeEventHandler(info.Owner, widgetDesc->OnChange, args);
}
else if (widgetDesc->Type == "spinner")
{
auto& widget = widgets[widgetIndex];
if (widget.text != STR_NUMERIC_DOWN && widget.text != STR_NUMERIC_UP)
{
InvokeEventHandler(info.Owner, widgetDesc->OnClick);
}
}
}
break;
}
@ -960,6 +969,10 @@ namespace OpenRCT2::Ui::Windows
{
disabled_widgets |= mask;
}
if (widgetFlags & WIDGET_FLAGS::IS_HOLDABLE)
{
hold_down_widgets |= mask;
}
}
widgetList.push_back({ WIDGETS_END });
@ -1110,6 +1123,8 @@ namespace OpenRCT2::Ui::Windows
widget.flags |= WIDGET_FLAGS::IS_ENABLED;
if (desc.IsDisabled)
widget.flags |= WIDGET_FLAGS::IS_DISABLED;
if (desc.IsHoldable)
widget.flags |= WIDGET_FLAGS::IS_HOLDABLE;
widgetList.push_back(widget);
// Add the increment button

View file

@ -887,8 +887,29 @@ namespace OpenRCT2::Scripting
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScWidget, ScSpinnerWidget>(ctx);
dukglue_register_property(ctx, &ScSpinnerWidget::isHoldable_get, &ScSpinnerWidget::isHoldable_set, "isHoldable");
dukglue_register_property(ctx, &ScSpinnerWidget::text_get, &ScSpinnerWidget::text_set, "text");
}
private:
int32_t isHoldable_get() const
{
auto w = GetWindow();
if (w != nullptr)
{
return WidgetIsHoldable(w, _widgetIndex);
}
return false;
}
void isHoldable_set(int32_t value)
{
auto w = GetWindow();
if (w != nullptr)
{
WidgetSetHoldable(w, _widgetIndex, value);
}
}
};
class ScTextBoxWidget : public ScWidget

View file

@ -138,6 +138,7 @@ void WidgetDraw(rct_drawpixelinfo* dpi, rct_window* w, rct_widgetindex widgetInd
bool WidgetIsEnabled(rct_window* w, rct_widgetindex widgetIndex);
bool WidgetIsDisabled(rct_window* w, rct_widgetindex widgetIndex);
bool WidgetIsHoldable(rct_window* w, rct_widgetindex widgetIndex);
bool WidgetIsVisible(rct_window* w, rct_widgetindex widgetIndex);
bool WidgetIsPressed(rct_window* w, rct_widgetindex widgetIndex);
bool WidgetIsHighlighted(rct_window* w, rct_widgetindex widgetIndex);
@ -148,6 +149,7 @@ void WidgetScrollGetPart(
void WidgetSetEnabled(rct_window* w, rct_widgetindex widgetIndex, bool enabled);
void WidgetSetDisabled(rct_window* w, rct_widgetindex widgetIndex, bool value);
void WidgetSetHoldable(rct_window* w, rct_widgetindex widgetIndex, bool value);
void WidgetSetVisible(rct_window* w, rct_widgetindex widgetIndex, bool value);
void WidgetSetCheckboxValue(rct_window* w, rct_widgetindex widgetIndex, int32_t value);

View file

@ -77,6 +77,7 @@ namespace WIDGET_FLAGS
const WidgetFlags IS_DISABLED = 1 << 3;
const WidgetFlags TOOLTIP_IS_STRING = 1 << 4;
const WidgetFlags IS_HIDDEN = 1 << 5;
const WidgetFlags IS_HOLDABLE = 1 << 6;
} // namespace WIDGET_FLAGS
enum class WindowWidgetType : uint8_t;

View file

@ -73,8 +73,14 @@ private:
_ss << "\n" << std::string(_indent, ' ');
}
void Stringify(const DukValue& val, bool canStartWithNewLine)
void Stringify(const DukValue& val, bool canStartWithNewLine, int32_t nestLevel)
{
if (nestLevel >= 8)
{
_ss << "[...]";
return;
}
switch (val.type())
{
case DukValue::Type::UNDEFINED:
@ -99,11 +105,11 @@ private:
}
else if (val.is_array())
{
StringifyArray(val, canStartWithNewLine);
StringifyArray(val, canStartWithNewLine, nestLevel);
}
else
{
StringifyObject(val, canStartWithNewLine);
StringifyObject(val, canStartWithNewLine, nestLevel);
}
break;
case DukValue::Type::BUFFER:
@ -118,7 +124,7 @@ private:
}
}
void StringifyArray(const DukValue& val, bool canStartWithNewLine)
void StringifyArray(const DukValue& val, bool canStartWithNewLine, int32_t nestLevel)
{
constexpr auto maxItemsToShow = 4;
@ -139,7 +145,7 @@ private:
{
_ss << ", ";
}
Stringify(DukValue::take_from_stack(_context), false);
Stringify(DukValue::take_from_stack(_context), false, nestLevel + 1);
}
}
_ss << " ]";
@ -177,7 +183,7 @@ private:
{
if (duk_get_prop_index(_context, -1, i))
{
Stringify(DukValue::take_from_stack(_context), false);
Stringify(DukValue::take_from_stack(_context), false, nestLevel + 1);
}
}
}
@ -191,7 +197,7 @@ private:
duk_pop(_context);
}
void StringifyObject(const DukValue& val, bool canStartWithNewLine)
void StringifyObject(const DukValue& val, bool canStartWithNewLine, int32_t nestLevel)
{
auto numEnumerables = GetNumEnumerablesOnObject(val);
if (numEnumerables == 0)
@ -222,7 +228,7 @@ private:
// For some reason the key was not a string
_ss << "?: ";
}
Stringify(value, true);
Stringify(value, true, nestLevel + 1);
index++;
}
duk_pop_2(_context);
@ -261,7 +267,7 @@ private:
// For some reason the key was not a string
_ss << "?: ";
}
Stringify(value, true);
Stringify(value, true, nestLevel + 1);
index++;
}
duk_pop_2(_context);
@ -343,7 +349,7 @@ public:
static std::string StringifyExpression(const DukValue& val)
{
ExpressionStringifier instance(val.context());
instance.Stringify(val, false);
instance.Stringify(val, false, 0);
return instance._ss.str();
}
};