1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-24 00:03:11 +01:00

Improve plugin API and type definitions

This commit is contained in:
Ted John
2021-01-28 19:55:04 +00:00
parent 4d8faee062
commit c2eb6d4153
4 changed files with 231 additions and 57 deletions

View File

@@ -990,7 +990,19 @@ declare global {
} }
type EntityType = type EntityType =
"car" | "duck" | "peep" | "steam_particle" | "money_effect" | "crashed_vehicle_particle" | "explosion_cloud" | "crash_splash" | "explosion_flare" | "jumping_fountain_water" | "balloon" | "jumping_fountain_snow"; "balloon" |
"car" |
"crash_splash" |
"crashed_vehicle_particle" |
"duck" |
"explosion_cloud" |
"explosion_flare" |
"jumping_fountain_snow" |
"jumping_fountain_water" |
"litter" |
"money_effect" |
"peep" |
"steam_particle";
/** /**
* Represents an object "entity" on the map that can typically moves and has a sub-tile coordinate. * Represents an object "entity" on the map that can typically moves and has a sub-tile coordinate.
@@ -1733,7 +1745,7 @@ declare global {
readonly windows: number; readonly windows: number;
readonly mainViewport: Viewport; readonly mainViewport: Viewport;
readonly tileSelection: TileSelection; readonly tileSelection: TileSelection;
readonly tool: Tool; readonly tool: Tool | null;
getWindow(id: number): Window; getWindow(id: number): Window;
getWindow(classification: string): Window; getWindow(classification: string): Window;
@@ -1754,6 +1766,19 @@ declare global {
*/ */
showTextInput(desc: TextInputDesc): void; showTextInput(desc: TextInputDesc): void;
/**
* Shows the window for loading or saving a file and calls the given callback when a file
* is selected.
* @param desc The parameters for the file browse window.
*/
showFileBrowse(desc: FileBrowseDesc): void;
/**
* Shows the scenario select window and calls the given callback when a scenario is
* selected.
*/
showScenarioSelect(desc: ScenarioSelectDesc): void;
/** /**
* Begins a new tool session. The cursor will change to the style specified by the * Begins a new tool session. The cursor will change to the style specified by the
* given tool descriptor and cursor events will be provided. * given tool descriptor and cursor events will be provided.
@@ -1794,6 +1819,59 @@ declare global {
callback: (value: string) => void; callback: (value: string) => void;
} }
/**
* Parameters for the file browse window.
*/
interface FileBrowseDesc {
/**
* Whether to browse a file for loading or saving. Saving will prompt the user
* before overwriting a file.
*/
type: 'load';
/**
* The type of file to browse for.
*/
fileType: 'game' | 'heightmap';
/**
* The pre-selected file to load by default if the user clicks OK.
*/
defaultPath?: string;
/**
* The function to call when the user has selected a file.
*/
callback: (path: string) => void;
}
/**
* Parameters for the scenario select window.
*/
interface ScenarioSelectDesc {
/**
* The function to call when the user has selected a scenario.
*/
callback: (scenario: ScenarioFile) => void;
}
/**
* Represents an installed scenario's path and metadata.
*/
interface ScenarioFile {
id: number;
category: 'beginner' | 'challenging' | 'expert' | 'real' | 'other' | 'dlc' | 'build_your_own';
sourceGame: 'rct1' | 'rct1_aa' | 'rct1_ll' | 'rct2' | 'rct2_ww' | 'rct2_tt' | 'real' | 'other';
path: string;
internalName: string;
name: string;
details: string;
highscore: {
name: string;
companyValue: number;
}
}
interface TileSelection { interface TileSelection {
range: MapRange; range: MapRange;
tiles: CoordsXY[]; tiles: CoordsXY[];
@@ -1821,11 +1899,11 @@ declare global {
id: string; id: string;
cursor?: CursorType; cursor?: CursorType;
onStart: () => void; onStart?: () => void;
onDown: (e: ToolEventArgs) => void; onDown?: (e: ToolEventArgs) => void;
onMove: (e: ToolEventArgs) => void; onMove?: (e: ToolEventArgs) => void;
onUp: (e: ToolEventArgs) => void; onUp?: (e: ToolEventArgs) => void;
onFinish: () => void; onFinish?: () => void;
} }
type CursorType = type CursorType =
@@ -1861,10 +1939,14 @@ declare global {
* Represents the type of a widget, e.g. button or label. * Represents the type of a widget, e.g. button or label.
*/ */
type WidgetType = type WidgetType =
"button" | "checkbox" | "colourpicker" | "dropdown" | "groupbox" | "label" | "listview" | "spinner" | "textbox" | "viewport"; "button" | "checkbox" | "colourpicker" | "dropdown" | "groupbox" |
"label" | "listview" | "spinner" | "textbox" | "viewport";
interface Widget { type Widget =
type: WidgetType; ButtonWidget | CheckboxWidget | ColourPickerWidget | DropdownWidget | GroupBoxWidget |
LabelWidget | ListView | SpinnerWidget | TextBoxWidget | ViewportWidget;
interface WidgetBase {
x: number; x: number;
y: number; y: number;
width: number; width: number;
@@ -1875,7 +1957,8 @@ declare global {
isVisible?: boolean; isVisible?: boolean;
} }
interface ButtonWidget extends Widget { interface ButtonWidget extends WidgetBase {
type: 'button';
/** /**
* Whether the button has a 3D border. * Whether the button has a 3D border.
* By default, text buttons have borders and image buttons do not but it can be overridden. * By default, text buttons have borders and image buttons do not but it can be overridden.
@@ -1884,29 +1967,37 @@ declare global {
image?: number; image?: number;
isPressed?: boolean; isPressed?: boolean;
text?: string; text?: string;
onClick: () => void; onClick?: () => void;
} }
interface CheckboxWidget extends Widget { interface CheckboxWidget extends WidgetBase {
text: string; type: 'checkbox';
isChecked: boolean; text?: string;
onChange: (isChecked: boolean) => void; isChecked?: boolean;
onChange?: (isChecked: boolean) => void;
} }
interface ColourPickerWidget extends Widget { interface ColourPickerWidget extends WidgetBase {
colour: number; type: 'colourpicker';
onChange: (colour: number) => void; colour?: number;
onChange?: (colour: number) => void;
} }
interface DropdownWidget extends Widget { interface DropdownWidget extends WidgetBase {
items: string[]; type: 'dropdown';
selectedIndex: number; items?: string[];
onChange: (index: number) => void; selectedIndex?: number;
onChange?: (index: number) => void;
} }
interface LabelWidget extends Widget { interface GroupBoxWidget extends WidgetBase {
text: string; type: 'groupbox';
onChange: (index: number) => void; }
interface LabelWidget extends WidgetBase {
type: 'label';
text?: string;
onChange?: (index: number) => void;
} }
type SortOrder = "none" | "ascending" | "descending"; type SortOrder = "none" | "ascending" | "descending";
@@ -1936,7 +2027,8 @@ declare global {
column: number; column: number;
} }
interface ListView extends Widget { interface ListView extends WidgetBase {
type: 'listview';
scrollbars?: ScrollbarType; scrollbars?: ScrollbarType;
isStriped?: boolean; isStriped?: boolean;
showColumnHeaders?: boolean; showColumnHeaders?: boolean;
@@ -1950,20 +2042,23 @@ declare global {
onClick?: (item: number, column: number) => void; onClick?: (item: number, column: number) => void;
} }
interface SpinnerWidget extends Widget { interface SpinnerWidget extends WidgetBase {
text: string; type: 'spinner';
onDecrement: () => void; text?: string;
onIncrement: () => void; onDecrement?: () => void;
onIncrement?: () => void;
} }
interface TextBoxWidget extends Widget { interface TextBoxWidget extends WidgetBase {
text: string; type: 'textbox';
maxLength: number; text?: string;
onChange: (text: string) => void; maxLength?: number;
onChange?: (text: string) => void;
} }
interface ViewportWidget extends Widget { interface ViewportWidget extends WidgetBase {
viewport: Viewport type: 'viewport';
viewport?: Viewport
} }
interface Window { interface Window {

View File

@@ -350,6 +350,7 @@ namespace OpenRCT2::Scripting
} }
} }
protected:
std::string text_get() const std::string text_get() const
{ {
if (IsCustomWindow()) if (IsCustomWindow())
@@ -362,6 +363,7 @@ namespace OpenRCT2::Scripting
} }
return ""; return "";
} }
void text_set(std::string value) void text_set(std::string value)
{ {
auto w = GetWindow(); auto w = GetWindow();
@@ -371,20 +373,6 @@ namespace OpenRCT2::Scripting
} }
} }
std::shared_ptr<ScViewport> viewport_get() const
{
auto w = GetWindow();
if (w != nullptr && IsCustomWindow())
{
auto widget = GetWidget();
if (widget != nullptr && widget->type == WindowWidgetType::Viewport)
{
return std::make_shared<ScViewport>(w->classification, w->number);
}
}
return {};
}
public: public:
static void Register(duk_context* ctx) static void Register(duk_context* ctx)
{ {
@@ -397,10 +385,6 @@ namespace OpenRCT2::Scripting
dukglue_register_property(ctx, &ScWidget::height_get, &ScWidget::height_set, "height"); dukglue_register_property(ctx, &ScWidget::height_get, &ScWidget::height_set, "height");
dukglue_register_property(ctx, &ScWidget::isDisabled_get, &ScWidget::isDisabled_set, "isDisabled"); dukglue_register_property(ctx, &ScWidget::isDisabled_get, &ScWidget::isDisabled_set, "isDisabled");
dukglue_register_property(ctx, &ScWidget::isVisible_get, &ScWidget::isVisible_set, "isVisible"); dukglue_register_property(ctx, &ScWidget::isVisible_get, &ScWidget::isVisible_set, "isVisible");
// No so common
dukglue_register_property(ctx, &ScWidget::text_get, &ScWidget::text_set, "text");
dukglue_register_property(ctx, &ScWidget::viewport_get, nullptr, "viewport");
} }
protected: protected:
@@ -641,6 +625,36 @@ namespace OpenRCT2::Scripting
} }
}; };
class ScGroupBoxWidget : public ScWidget
{
public:
ScGroupBoxWidget(rct_windowclass c, rct_windownumber n, rct_widgetindex widgetIndex)
: ScWidget(c, n, widgetIndex)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScWidget, ScGroupBoxWidget>(ctx);
dukglue_register_property(ctx, &ScGroupBoxWidget::text_get, &ScGroupBoxWidget::text_set, "text");
}
};
class ScLabelWidget : public ScWidget
{
public:
ScLabelWidget(rct_windowclass c, rct_windownumber n, rct_widgetindex widgetIndex)
: ScWidget(c, n, widgetIndex)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScWidget, ScLabelWidget>(ctx);
dukglue_register_property(ctx, &ScLabelWidget::text_get, &ScLabelWidget::text_set, "text");
}
};
class ScListViewWidget : public ScWidget class ScListViewWidget : public ScWidget
{ {
public: public:
@@ -832,6 +846,21 @@ namespace OpenRCT2::Scripting
} }
}; };
class ScSpinnerWidget : public ScWidget
{
public:
ScSpinnerWidget(rct_windowclass c, rct_windownumber n, rct_widgetindex widgetIndex)
: ScWidget(c, n, widgetIndex)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScWidget, ScSpinnerWidget>(ctx);
dukglue_register_property(ctx, &ScSpinnerWidget::text_get, &ScSpinnerWidget::text_set, "text");
}
};
class ScTextBoxWidget : public ScWidget class ScTextBoxWidget : public ScWidget
{ {
public: public:
@@ -867,6 +896,36 @@ namespace OpenRCT2::Scripting
} }
}; };
class ScViewportWidget : public ScWidget
{
public:
ScViewportWidget(rct_windowclass c, rct_windownumber n, rct_widgetindex widgetIndex)
: ScWidget(c, n, widgetIndex)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScWidget, ScViewportWidget>(ctx);
dukglue_register_property(ctx, &ScViewportWidget::viewport_get, nullptr, "viewport");
}
private:
std::shared_ptr<ScViewport> viewport_get() const
{
auto w = GetWindow();
if (w != nullptr && IsCustomWindow())
{
auto widget = GetWidget();
if (widget != nullptr && widget->type == WindowWidgetType::Viewport)
{
return std::make_shared<ScViewport>(w->classification, w->number);
}
}
return {};
}
};
inline DukValue ScWidget::ToDukValue(duk_context* ctx, rct_window* w, rct_widgetindex widgetIndex) inline DukValue ScWidget::ToDukValue(duk_context* ctx, rct_window* w, rct_widgetindex widgetIndex)
{ {
const auto& widget = w->widgets[widgetIndex]; const auto& widget = w->widgets[widgetIndex];
@@ -884,10 +943,18 @@ namespace OpenRCT2::Scripting
return GetObjectAsDukValue(ctx, std::make_shared<ScColourPickerWidget>(c, n, widgetIndex)); return GetObjectAsDukValue(ctx, std::make_shared<ScColourPickerWidget>(c, n, widgetIndex));
case WindowWidgetType::DropdownMenu: case WindowWidgetType::DropdownMenu:
return GetObjectAsDukValue(ctx, std::make_shared<ScDropdownWidget>(c, n, widgetIndex)); return GetObjectAsDukValue(ctx, std::make_shared<ScDropdownWidget>(c, n, widgetIndex));
case WindowWidgetType::Groupbox:
return GetObjectAsDukValue(ctx, std::make_shared<ScGroupBoxWidget>(c, n, widgetIndex));
case WindowWidgetType::Label:
return GetObjectAsDukValue(ctx, std::make_shared<ScLabelWidget>(c, n, widgetIndex));
case WindowWidgetType::Scroll: case WindowWidgetType::Scroll:
return GetObjectAsDukValue(ctx, std::make_shared<ScListViewWidget>(c, n, widgetIndex)); return GetObjectAsDukValue(ctx, std::make_shared<ScListViewWidget>(c, n, widgetIndex));
case WindowWidgetType::Spinner:
return GetObjectAsDukValue(ctx, std::make_shared<ScSpinnerWidget>(c, n, widgetIndex));
case WindowWidgetType::TextBox: case WindowWidgetType::TextBox:
return GetObjectAsDukValue(ctx, std::make_shared<ScTextBoxWidget>(c, n, widgetIndex)); return GetObjectAsDukValue(ctx, std::make_shared<ScTextBoxWidget>(c, n, widgetIndex));
case WindowWidgetType::Viewport:
return GetObjectAsDukValue(ctx, std::make_shared<ScViewportWidget>(c, n, widgetIndex));
default: default:
return GetObjectAsDukValue(ctx, std::make_shared<ScWidget>(c, n, widgetIndex)); return GetObjectAsDukValue(ctx, std::make_shared<ScWidget>(c, n, widgetIndex));
} }

View File

@@ -31,13 +31,18 @@ void UiScriptExtensions::Extend(ScriptEngine& scriptEngine)
ScTool::Register(ctx); ScTool::Register(ctx);
ScUi::Register(ctx); ScUi::Register(ctx);
ScViewport::Register(ctx); ScViewport::Register(ctx);
ScWidget::Register(ctx); ScWidget::Register(ctx);
ScButtonWidget::Register(ctx); ScButtonWidget::Register(ctx);
ScColourPickerWidget::Register(ctx); ScColourPickerWidget::Register(ctx);
ScCheckBoxWidget::Register(ctx); ScCheckBoxWidget::Register(ctx);
ScDropdownWidget::Register(ctx); ScDropdownWidget::Register(ctx);
ScGroupBoxWidget::Register(ctx);
ScLabelWidget::Register(ctx);
ScListViewWidget::Register(ctx); ScListViewWidget::Register(ctx);
ScSpinnerWidget::Register(ctx);
ScTextBoxWidget::Register(ctx); ScTextBoxWidget::Register(ctx);
ScViewportWidget::Register(ctx);
ScWindow::Register(ctx); ScWindow::Register(ctx);
InitialiseCustomMenuItems(scriptEngine); InitialiseCustomMenuItems(scriptEngine);

View File

@@ -717,10 +717,17 @@ DukValue ScriptEngine::ExecutePluginCall(
} }
void ScriptEngine::LogPluginInfo(const std::shared_ptr<Plugin>& plugin, std::string_view message) void ScriptEngine::LogPluginInfo(const std::shared_ptr<Plugin>& plugin, std::string_view message)
{
if (plugin == nullptr)
{
_console.WriteLine(std::string(message));
}
else
{ {
const auto& pluginName = plugin->GetMetadata().Name; const auto& pluginName = plugin->GetMetadata().Name;
_console.WriteLine("[" + pluginName + "] " + std::string(message)); _console.WriteLine("[" + pluginName + "] " + std::string(message));
} }
}
void ScriptEngine::AddNetworkPlugin(std::string_view code) void ScriptEngine::AddNetworkPlugin(std::string_view code)
{ {