|
|
|
|
@@ -11,10 +11,12 @@
|
|
|
|
|
#include <SDL3/SDL_gpu.h>
|
|
|
|
|
#include <SDL3/SDL_error.h>
|
|
|
|
|
#include <SDL3/SDL_properties.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
// External globals
|
|
|
|
|
extern SDL_Window *global_window;
|
|
|
|
|
extern SDL_ThreadID main_thread;
|
|
|
|
|
// External function declarations
|
|
|
|
|
extern prosperon_rt *create_actor(int argc, char **argv, void (*hook)(JSContext *));
|
|
|
|
|
extern const char *register_actor(const char *id, prosperon_rt *rt, int main_thread);
|
|
|
|
|
|
|
|
|
|
// SDL Window free function
|
|
|
|
|
void SDL_Window_free(JSRuntime *rt, SDL_Window *w)
|
|
|
|
|
@@ -109,57 +111,235 @@ static inline rect renderer_worldrect_to_screen(renderer_ctx *ctx, rect r_world)
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Window creation function
|
|
|
|
|
#define JS_SDL_PROP(JS, VAL, SDLPROP, PROP) \
|
|
|
|
|
{ \
|
|
|
|
|
JSValue v = JS_GetPropertyStr(JS,VAL,#PROP); \
|
|
|
|
|
const char *str = JS_ToCString(JS, v); \
|
|
|
|
|
SDL_SetAppMetadataProperty(SDLPROP, str); \
|
|
|
|
|
JS_FreeCString(JS,str); \
|
|
|
|
|
JS_FreeValue(js,v); \
|
|
|
|
|
} \
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(os_engine_start,
|
|
|
|
|
if (!SDL_Init(SDL_INIT_VIDEO))
|
|
|
|
|
return JS_ThrowInternalError(js, "Unable to initialize video subsystem: %s", SDL_GetError());
|
|
|
|
|
|
|
|
|
|
if (SDL_GetCurrentThreadID() != main_thread)
|
|
|
|
|
return JS_ThrowInternalError(js, "This can only be called from the root actor.");
|
|
|
|
|
|
|
|
|
|
if (global_window)
|
|
|
|
|
return JS_ThrowReferenceError(js, "The engine was already started.");
|
|
|
|
|
|
|
|
|
|
JSValue p = argv[0];
|
|
|
|
|
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_NAME_STRING, name)
|
|
|
|
|
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_VERSION_STRING, version)
|
|
|
|
|
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_IDENTIFIER_STRING, identifier)
|
|
|
|
|
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_CREATOR_STRING, creator)
|
|
|
|
|
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_COPYRIGHT_STRING, copyright)
|
|
|
|
|
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_URL_STRING, url)
|
|
|
|
|
JS_SDL_PROP(js, p, SDL_PROP_APP_METADATA_TYPE_STRING, type)
|
|
|
|
|
// Window constructor function
|
|
|
|
|
static JSValue js_window_constructor(JSContext *js, JSValueConst new_target, int argc, JSValueConst *argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc < 1 || !JS_IsObject(argv[0]))
|
|
|
|
|
return JS_ThrowTypeError(js, "Window constructor requires an object argument");
|
|
|
|
|
|
|
|
|
|
const char *title;
|
|
|
|
|
JSValue title_val = JS_GetPropertyStr(js, argv[0], "title");
|
|
|
|
|
title = JS_ToCString(js, title_val);
|
|
|
|
|
JSValue opts = argv[0];
|
|
|
|
|
|
|
|
|
|
// Get basic properties (defaults are handled in JavaScript)
|
|
|
|
|
const char *title = NULL;
|
|
|
|
|
JSValue title_val = JS_GetPropertyStr(js, opts, "title");
|
|
|
|
|
if (!JS_IsUndefined(title_val) && !JS_IsNull(title_val)) {
|
|
|
|
|
title = JS_ToCString(js, title_val);
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, title_val);
|
|
|
|
|
|
|
|
|
|
JSValue width_val = JS_GetPropertyStr(js, argv[0], "width");
|
|
|
|
|
JSValue height_val = JS_GetPropertyStr(js, argv[0], "height");
|
|
|
|
|
int width = js2number(js, width_val);
|
|
|
|
|
int height = js2number(js, height_val);
|
|
|
|
|
if (!title) {
|
|
|
|
|
return JS_ThrowTypeError(js, "Window title is required");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int width = 640;
|
|
|
|
|
JSValue width_val = JS_GetPropertyStr(js, opts, "width");
|
|
|
|
|
if (!JS_IsUndefined(width_val) && !JS_IsNull(width_val)) {
|
|
|
|
|
width = js2number(js, width_val);
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, width_val);
|
|
|
|
|
|
|
|
|
|
int height = 480;
|
|
|
|
|
JSValue height_val = JS_GetPropertyStr(js, opts, "height");
|
|
|
|
|
if (!JS_IsUndefined(height_val) && !JS_IsNull(height_val)) {
|
|
|
|
|
height = js2number(js, height_val);
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, height_val);
|
|
|
|
|
|
|
|
|
|
SDL_Window *new = SDL_CreateWindow(title, width, height, SDL_WINDOW_RESIZABLE);
|
|
|
|
|
|
|
|
|
|
JS_FreeCString(js,title);
|
|
|
|
|
|
|
|
|
|
if (!new) return JS_ThrowReferenceError(js, "Couldn't open window: %s\n", SDL_GetError());
|
|
|
|
|
|
|
|
|
|
SDL_StartTextInput(new);
|
|
|
|
|
global_window = new;
|
|
|
|
|
return SDL_Window2js(js,new);
|
|
|
|
|
)
|
|
|
|
|
// Handle window position
|
|
|
|
|
int x = SDL_WINDOWPOS_UNDEFINED;
|
|
|
|
|
JSValue x_val = JS_GetPropertyStr(js, opts, "x");
|
|
|
|
|
if (!JS_IsUndefined(x_val)) {
|
|
|
|
|
if (JS_IsString(x_val)) {
|
|
|
|
|
const char *pos = JS_ToCString(js, x_val);
|
|
|
|
|
if (strcmp(pos, "centered") == 0) x = SDL_WINDOWPOS_CENTERED;
|
|
|
|
|
JS_FreeCString(js, pos);
|
|
|
|
|
} else {
|
|
|
|
|
x = js2number(js, x_val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, x_val);
|
|
|
|
|
|
|
|
|
|
int y = SDL_WINDOWPOS_UNDEFINED;
|
|
|
|
|
JSValue y_val = JS_GetPropertyStr(js, opts, "y");
|
|
|
|
|
if (!JS_IsUndefined(y_val)) {
|
|
|
|
|
if (JS_IsString(y_val)) {
|
|
|
|
|
const char *pos = JS_ToCString(js, y_val);
|
|
|
|
|
if (strcmp(pos, "centered") == 0) y = SDL_WINDOWPOS_CENTERED;
|
|
|
|
|
JS_FreeCString(js, pos);
|
|
|
|
|
} else {
|
|
|
|
|
y = js2number(js, y_val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, y_val);
|
|
|
|
|
|
|
|
|
|
// Build window flags
|
|
|
|
|
Uint64 flags = 0;
|
|
|
|
|
|
|
|
|
|
// Check boolean properties
|
|
|
|
|
JSValue resizable = JS_GetPropertyStr(js, opts, "resizable");
|
|
|
|
|
if (JS_ToBool(js, resizable)) flags |= SDL_WINDOW_RESIZABLE;
|
|
|
|
|
JS_FreeValue(js, resizable);
|
|
|
|
|
|
|
|
|
|
JSValue fullscreen = JS_GetPropertyStr(js, opts, "fullscreen");
|
|
|
|
|
if (JS_ToBool(js, fullscreen)) flags |= SDL_WINDOW_FULLSCREEN;
|
|
|
|
|
JS_FreeValue(js, fullscreen);
|
|
|
|
|
|
|
|
|
|
JSValue hidden = JS_GetPropertyStr(js, opts, "hidden");
|
|
|
|
|
if (JS_ToBool(js, hidden)) flags |= SDL_WINDOW_HIDDEN;
|
|
|
|
|
JS_FreeValue(js, hidden);
|
|
|
|
|
|
|
|
|
|
JSValue borderless = JS_GetPropertyStr(js, opts, "borderless");
|
|
|
|
|
if (JS_ToBool(js, borderless)) flags |= SDL_WINDOW_BORDERLESS;
|
|
|
|
|
JS_FreeValue(js, borderless);
|
|
|
|
|
|
|
|
|
|
JSValue always_on_top = JS_GetPropertyStr(js, opts, "alwaysOnTop");
|
|
|
|
|
if (JS_ToBool(js, always_on_top)) flags |= SDL_WINDOW_ALWAYS_ON_TOP;
|
|
|
|
|
JS_FreeValue(js, always_on_top);
|
|
|
|
|
|
|
|
|
|
JSValue minimized = JS_GetPropertyStr(js, opts, "minimized");
|
|
|
|
|
if (JS_ToBool(js, minimized)) flags |= SDL_WINDOW_MINIMIZED;
|
|
|
|
|
JS_FreeValue(js, minimized);
|
|
|
|
|
|
|
|
|
|
JSValue maximized = JS_GetPropertyStr(js, opts, "maximized");
|
|
|
|
|
if (JS_ToBool(js, maximized)) flags |= SDL_WINDOW_MAXIMIZED;
|
|
|
|
|
JS_FreeValue(js, maximized);
|
|
|
|
|
|
|
|
|
|
JSValue mouse_grabbed = JS_GetPropertyStr(js, opts, "mouseGrabbed");
|
|
|
|
|
if (JS_ToBool(js, mouse_grabbed)) flags |= SDL_WINDOW_MOUSE_GRABBED;
|
|
|
|
|
JS_FreeValue(js, mouse_grabbed);
|
|
|
|
|
|
|
|
|
|
JSValue keyboard_grabbed = JS_GetPropertyStr(js, opts, "keyboardGrabbed");
|
|
|
|
|
if (JS_ToBool(js, keyboard_grabbed)) flags |= SDL_WINDOW_KEYBOARD_GRABBED;
|
|
|
|
|
JS_FreeValue(js, keyboard_grabbed);
|
|
|
|
|
|
|
|
|
|
JSValue high_pixel_density = JS_GetPropertyStr(js, opts, "highPixelDensity");
|
|
|
|
|
if (JS_ToBool(js, high_pixel_density)) flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
|
|
|
|
JS_FreeValue(js, high_pixel_density);
|
|
|
|
|
|
|
|
|
|
JSValue transparent = JS_GetPropertyStr(js, opts, "transparent");
|
|
|
|
|
if (JS_ToBool(js, transparent)) flags |= SDL_WINDOW_TRANSPARENT;
|
|
|
|
|
JS_FreeValue(js, transparent);
|
|
|
|
|
|
|
|
|
|
JSValue not_focusable = JS_GetPropertyStr(js, opts, "notFocusable");
|
|
|
|
|
if (JS_ToBool(js, not_focusable)) flags |= SDL_WINDOW_NOT_FOCUSABLE;
|
|
|
|
|
JS_FreeValue(js, not_focusable);
|
|
|
|
|
|
|
|
|
|
// Special window types
|
|
|
|
|
JSValue utility = JS_GetPropertyStr(js, opts, "utility");
|
|
|
|
|
if (JS_ToBool(js, utility)) flags |= SDL_WINDOW_UTILITY;
|
|
|
|
|
JS_FreeValue(js, utility);
|
|
|
|
|
|
|
|
|
|
JSValue tooltip = JS_GetPropertyStr(js, opts, "tooltip");
|
|
|
|
|
if (JS_ToBool(js, tooltip)) flags |= SDL_WINDOW_TOOLTIP;
|
|
|
|
|
JS_FreeValue(js, tooltip);
|
|
|
|
|
|
|
|
|
|
JSValue popup_menu = JS_GetPropertyStr(js, opts, "popupMenu");
|
|
|
|
|
if (JS_ToBool(js, popup_menu)) flags |= SDL_WINDOW_POPUP_MENU;
|
|
|
|
|
JS_FreeValue(js, popup_menu);
|
|
|
|
|
|
|
|
|
|
// Graphics API flags
|
|
|
|
|
JSValue opengl = JS_GetPropertyStr(js, opts, "opengl");
|
|
|
|
|
if (JS_ToBool(js, opengl)) flags |= SDL_WINDOW_OPENGL;
|
|
|
|
|
JS_FreeValue(js, opengl);
|
|
|
|
|
|
|
|
|
|
JSValue vulkan = JS_GetPropertyStr(js, opts, "vulkan");
|
|
|
|
|
if (JS_ToBool(js, vulkan)) flags |= SDL_WINDOW_VULKAN;
|
|
|
|
|
JS_FreeValue(js, vulkan);
|
|
|
|
|
|
|
|
|
|
JSValue metal = JS_GetPropertyStr(js, opts, "metal");
|
|
|
|
|
if (JS_ToBool(js, metal)) flags |= SDL_WINDOW_METAL;
|
|
|
|
|
JS_FreeValue(js, metal);
|
|
|
|
|
|
|
|
|
|
// Handle parent window for tooltips, popups, etc
|
|
|
|
|
SDL_Window *parent = NULL;
|
|
|
|
|
JSValue parent_val = JS_GetPropertyStr(js, opts, "parent");
|
|
|
|
|
if (!JS_IsUndefined(parent_val)) {
|
|
|
|
|
parent = js2SDL_Window(js, parent_val);
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, parent_val);
|
|
|
|
|
|
|
|
|
|
// Create window with properties if we need special handling
|
|
|
|
|
SDL_Window *window = NULL;
|
|
|
|
|
|
|
|
|
|
if (parent || (flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU))) {
|
|
|
|
|
// Use SDL_CreateWindowWithProperties for advanced features
|
|
|
|
|
SDL_PropertiesID props = SDL_CreateProperties();
|
|
|
|
|
|
|
|
|
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width);
|
|
|
|
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height);
|
|
|
|
|
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title);
|
|
|
|
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x);
|
|
|
|
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y);
|
|
|
|
|
|
|
|
|
|
// Set boolean properties
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, flags & SDL_WINDOW_RESIZABLE);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, flags & SDL_WINDOW_FULLSCREEN);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN, flags & SDL_WINDOW_HIDDEN);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN, flags & SDL_WINDOW_BORDERLESS);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN, flags & SDL_WINDOW_ALWAYS_ON_TOP);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MINIMIZED_BOOLEAN, flags & SDL_WINDOW_MINIMIZED);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MAXIMIZED_BOOLEAN, flags & SDL_WINDOW_MAXIMIZED);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN, flags & SDL_WINDOW_MOUSE_GRABBED);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN, flags & SDL_WINDOW_TRANSPARENT);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, !(flags & SDL_WINDOW_NOT_FOCUSABLE));
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_UTILITY_BOOLEAN, flags & SDL_WINDOW_UTILITY);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN, flags & SDL_WINDOW_TOOLTIP);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN, flags & SDL_WINDOW_POPUP_MENU);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, flags & SDL_WINDOW_OPENGL);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_VULKAN_BOOLEAN, flags & SDL_WINDOW_VULKAN);
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_METAL_BOOLEAN, flags & SDL_WINDOW_METAL);
|
|
|
|
|
|
|
|
|
|
if (parent) {
|
|
|
|
|
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle modal property
|
|
|
|
|
JSValue modal = JS_GetPropertyStr(js, opts, "modal");
|
|
|
|
|
if (JS_ToBool(js, modal) && parent) {
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MODAL_BOOLEAN, 1);
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, modal);
|
|
|
|
|
|
|
|
|
|
// Handle external graphics context
|
|
|
|
|
JSValue external_graphics = JS_GetPropertyStr(js, opts, "externalGraphicsContext");
|
|
|
|
|
if (JS_ToBool(js, external_graphics)) {
|
|
|
|
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN, 1);
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, external_graphics);
|
|
|
|
|
|
|
|
|
|
window = SDL_CreateWindowWithProperties(props);
|
|
|
|
|
SDL_DestroyProperties(props);
|
|
|
|
|
} else {
|
|
|
|
|
// Use simpler API for basic windows
|
|
|
|
|
window = SDL_CreateWindow(title, width, height, flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Always free the title string since we allocated it
|
|
|
|
|
if (title) {
|
|
|
|
|
JS_FreeCString(js, title);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!window) {
|
|
|
|
|
return JS_ThrowReferenceError(js, "Failed to create window: %s", SDL_GetError());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set additional properties that can't be set during creation
|
|
|
|
|
JSValue opacity_val = JS_GetPropertyStr(js, opts, "opacity");
|
|
|
|
|
if (!JS_IsUndefined(opacity_val)) {
|
|
|
|
|
float opacity = js2number(js, opacity_val);
|
|
|
|
|
SDL_SetWindowOpacity(window, opacity);
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, opacity_val);
|
|
|
|
|
|
|
|
|
|
// Handle text input
|
|
|
|
|
JSValue text_input = JS_GetPropertyStr(js, opts, "textInput");
|
|
|
|
|
if (JS_ToBool(js, text_input)) {
|
|
|
|
|
SDL_StartTextInput(window);
|
|
|
|
|
}
|
|
|
|
|
JS_FreeValue(js, text_input);
|
|
|
|
|
|
|
|
|
|
return SDL_Window2js(js, window);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Window functions
|
|
|
|
|
JSC_SCALL(SDL_Window_make_renderer,
|
|
|
|
|
@@ -662,7 +842,7 @@ static const JSCFunctionListEntry js_renderer_ctx_funcs[] = {
|
|
|
|
|
extern SDL_ScaleMode js2SDL_ScaleMode(JSContext *js, JSValue v);
|
|
|
|
|
|
|
|
|
|
static const JSCFunctionListEntry js_sdl_video_funcs[] = {
|
|
|
|
|
MIST_FUNC_DEF(os, engine_start, 1),
|
|
|
|
|
// No regular functions, window is now a constructor
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
JSC_CCALL(texture_mode,
|
|
|
|
|
@@ -675,28 +855,64 @@ static const JSCFunctionListEntry js_SDL_Texture_funcs[] = {
|
|
|
|
|
MIST_FUNC_DEF(texture, mode, 1),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
JSValue js_sdl_video_use(JSContext *js) {
|
|
|
|
|
// In reality, this should return the ID of the ioactor. If it's not created yet,
|
|
|
|
|
// on any thread, it should be created. Then, the sdl_video_funcs need to be
|
|
|
|
|
// attached to it so it has access via prosperon.endowments.video
|
|
|
|
|
|
|
|
|
|
JSValue mod = JS_NewObject(js);
|
|
|
|
|
JS_SetPropertyFunctionList(js,mod,js_sdl_video_funcs,countof(js_sdl_video_funcs));
|
|
|
|
|
// Hook function to set up endowments for the video actor
|
|
|
|
|
static void video_actor_hook(JSContext *js) {
|
|
|
|
|
// Get prosperon object
|
|
|
|
|
JSValue prosperon = JS_GetPropertyStr(js, JS_GetGlobalObject(js), "prosperon");
|
|
|
|
|
JSValue c_types = JS_GetPropertyStr(js, prosperon, "c_types");
|
|
|
|
|
|
|
|
|
|
// Initialize classes
|
|
|
|
|
JSValue c_types = JS_GetPropertyStr(js, JS_GetGlobalObject(js), "c_types");
|
|
|
|
|
JSValue prosperon = JS_GetPropertyStr(js, JS_GetGlobalObject(js), "prosperon");
|
|
|
|
|
c_types = JS_GetPropertyStr(js, prosperon, "c_types");
|
|
|
|
|
JS_FreeValue(js, prosperon);
|
|
|
|
|
|
|
|
|
|
// add the singular ioactor address to the exported module
|
|
|
|
|
|
|
|
|
|
QJSCLASSPREP_FUNCS(SDL_Window)
|
|
|
|
|
QJSCLASSPREP_FUNCS(renderer_ctx)
|
|
|
|
|
QJSCLASSPREP_FUNCS(SDL_Texture)
|
|
|
|
|
|
|
|
|
|
JS_FreeValue(js, c_types);
|
|
|
|
|
|
|
|
|
|
return mod;
|
|
|
|
|
// Create window constructor
|
|
|
|
|
JSValue window_ctor = JS_NewCFunction2(js, js_window_constructor, "window", 1, JS_CFUNC_constructor, 0);
|
|
|
|
|
|
|
|
|
|
// Set prototype on constructor
|
|
|
|
|
JS_SetConstructor(js, window_ctor, SDL_Window_proto);
|
|
|
|
|
|
|
|
|
|
// Get or create endowments object
|
|
|
|
|
JSValue endowments = JS_GetPropertyStr(js, prosperon, "endowments");
|
|
|
|
|
if (JS_IsUndefined(endowments)) {
|
|
|
|
|
endowments = JS_NewObject(js);
|
|
|
|
|
JS_SetPropertyStr(js, prosperon, "endowments", JS_DupValue(js, endowments));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set window constructor in endowments
|
|
|
|
|
JS_SetPropertyStr(js, endowments, "window", window_ctor);
|
|
|
|
|
|
|
|
|
|
JS_FreeValue(js, endowments);
|
|
|
|
|
JS_FreeValue(js, prosperon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSValue js_sdl_video_use(JSContext *js) {
|
|
|
|
|
if (!SDL_Init(SDL_INIT_VIDEO))
|
|
|
|
|
return JS_ThrowInternalError(js, "Unable to initialize video subsystem: %s", SDL_GetError());
|
|
|
|
|
|
|
|
|
|
// Generate a unique ID for the video actor
|
|
|
|
|
char id[64];
|
|
|
|
|
snprintf(id, sizeof(id), "video_%d", SDL_GetTicks());
|
|
|
|
|
|
|
|
|
|
printf("id is %s\n", id);
|
|
|
|
|
|
|
|
|
|
// Prepare argv for create_actor
|
|
|
|
|
// We need to create the actor on the main thread
|
|
|
|
|
const char *argv[] = {
|
|
|
|
|
"./prosperon",
|
|
|
|
|
"spawn",
|
|
|
|
|
"--id", id,
|
|
|
|
|
"--program", "scripts/core/_sdl_video.js",
|
|
|
|
|
"--main", "1"
|
|
|
|
|
};
|
|
|
|
|
int argc = 8;
|
|
|
|
|
|
|
|
|
|
// Create the actor with the hook to set up endowments
|
|
|
|
|
prosperon_rt *rt = create_actor(argc, (char**)argv, video_actor_hook);
|
|
|
|
|
return JS_NewString(js,id);
|
|
|
|
|
JSValue ret = JS_NewObject(js);
|
|
|
|
|
JS_SetPropertyStr(js, ret, "id", JS_NewString(js,id));
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|