add sdl cursor support
This commit is contained in:
@@ -59,7 +59,8 @@ var resources = {
|
||||
window: {},
|
||||
renderer: {},
|
||||
texture: {},
|
||||
surface: {}
|
||||
surface: {},
|
||||
cursor: {}
|
||||
};
|
||||
|
||||
// ID counter for resource allocation
|
||||
@@ -93,6 +94,9 @@ $_.receiver(function(msg) {
|
||||
case 'surface':
|
||||
response = handle_surface(msg);
|
||||
break;
|
||||
case 'cursor':
|
||||
response = handle_cursor(msg);
|
||||
break;
|
||||
default:
|
||||
response = {error: "Unknown kind: " + msg.kind};
|
||||
}
|
||||
@@ -605,6 +609,39 @@ function handle_surface(msg) {
|
||||
}
|
||||
}
|
||||
|
||||
// Cursor operations
|
||||
function handle_cursor(msg) {
|
||||
switch (msg.op) {
|
||||
case 'create':
|
||||
var surf = new surface(msg.data)
|
||||
|
||||
var hotspot = msg.data.hotspot || [0, 0];
|
||||
var cursor = prosperon.endowments.createCursor(surf, hotspot);
|
||||
|
||||
var cursor_id = allocate_id();
|
||||
resources.cursor[cursor_id] = cursor;
|
||||
return {id: cursor_id};
|
||||
|
||||
case 'set':
|
||||
var cursor = null;
|
||||
if (msg.id && resources.cursor[msg.id]) {
|
||||
cursor = resources.cursor[msg.id];
|
||||
}
|
||||
prosperon.endowments.setCursor(cursor);
|
||||
return {success: true};
|
||||
|
||||
case 'destroy':
|
||||
if (!msg.id || !resources.cursor[msg.id]) {
|
||||
return {error: "Invalid cursor id: " + msg.id};
|
||||
}
|
||||
delete resources.cursor[msg.id];
|
||||
return {success: true};
|
||||
|
||||
default:
|
||||
return {error: "Unknown cursor operation: " + msg.op};
|
||||
}
|
||||
}
|
||||
|
||||
// Utility function to create window and renderer
|
||||
prosperon.endowments = prosperon.endowments || {};
|
||||
|
||||
|
||||
@@ -429,11 +429,6 @@ graphics.cull_sprites[prosperon.DOC] = `
|
||||
Filter an array of sprites to only those visible in the provided camera’s view.
|
||||
`
|
||||
|
||||
graphics.make_cursor[prosperon.DOC] = `
|
||||
:param opts: An object with {surface, hotx, hoty} or similar.
|
||||
:return: An SDL_Cursor object referencing the given surface for a custom mouse cursor.
|
||||
`
|
||||
|
||||
graphics.make_font[prosperon.DOC] = `
|
||||
:param data: TTF/OTF file data as an ArrayBuffer.
|
||||
:param size: Pixel size for rendering glyphs.
|
||||
|
||||
@@ -1199,19 +1199,6 @@ JSC_CCALL(os_make_aseprite,
|
||||
cute_aseprite_free(ase);
|
||||
)
|
||||
|
||||
|
||||
// TODO: Implement this correctly
|
||||
JSC_CCALL(os_make_cursor,
|
||||
/*if (SDL_GetCurrentThreadID() != main_thread)
|
||||
return JS_ThrowInternalError(js, "This can only be called from the root actor.");
|
||||
|
||||
SDL_Surface *s = js2SDL_Surface(js,argv[0]);
|
||||
HMM_Vec2 hot = js2vec2(js,argv[1]);
|
||||
SDL_Cursor *c = SDL_CreateColorCursor(s, hot.x, hot.y);
|
||||
if (!c) return JS_ThrowReferenceError(js,"couldn't make cursor: %s", SDL_GetError());
|
||||
return SDL_Cursor2js(js,c);*/
|
||||
)
|
||||
|
||||
JSC_CCALL(os_make_font,
|
||||
size_t len;
|
||||
void *data = JS_GetArrayBuffer(js,&len,argv[0]);
|
||||
@@ -1501,7 +1488,6 @@ static const JSCFunctionListEntry js_graphics_funcs[] = {
|
||||
MIST_FUNC_DEF(os, make_gif, 1),
|
||||
MIST_FUNC_DEF(os, make_aseprite, 1),
|
||||
MIST_FUNC_DEF(os, cull_sprites, 2),
|
||||
MIST_FUNC_DEF(os, make_cursor, 1),
|
||||
MIST_FUNC_DEF(os, make_font, 2),
|
||||
MIST_FUNC_DEF(os, make_line_prim, 5),
|
||||
MIST_FUNC_DEF(graphics, hsl_to_rgb, 3),
|
||||
|
||||
@@ -10,17 +10,11 @@ void SDL_Camera_free(JSRuntime *rt, SDL_Camera *cam)
|
||||
SDL_CloseCamera(cam);
|
||||
}
|
||||
|
||||
void SDL_Cursor_free(JSRuntime *rt, SDL_Cursor *c)
|
||||
{
|
||||
SDL_DestroyCursor(c);
|
||||
}
|
||||
|
||||
void SDL_AudioStream_free(JSRuntime *rt, SDL_AudioStream *st) {
|
||||
SDL_DestroyAudioStream(st);
|
||||
}
|
||||
|
||||
// Class definitions for SDL types
|
||||
QJSCLASS(SDL_Cursor,)
|
||||
QJSCLASS(SDL_Camera,)
|
||||
QJSCLASS(SDL_AudioStream,)
|
||||
|
||||
@@ -59,12 +53,6 @@ JSC_CCALL(input_mouse_show,
|
||||
SDL_HideCursor();
|
||||
)
|
||||
|
||||
JSC_CCALL(input_cursor_set,
|
||||
SDL_Cursor *c = js2SDL_Cursor(js,argv[0]);
|
||||
if (!SDL_SetCursor(c))
|
||||
return JS_ThrowReferenceError(js, "could not set cursor: %s", SDL_GetError());
|
||||
)
|
||||
|
||||
JSC_CCALL(input_keyname,
|
||||
return JS_NewString(js, SDL_GetKeyName(js2number(js,argv[0])));
|
||||
)
|
||||
@@ -97,7 +85,6 @@ JSC_CCALL(input_mousestate,
|
||||
static const JSCFunctionListEntry js_input_funcs[] = {
|
||||
MIST_FUNC_DEF(input, mouse_show, 1),
|
||||
MIST_FUNC_DEF(input, mouse_lock, 1),
|
||||
MIST_FUNC_DEF(input, cursor_set, 1),
|
||||
MIST_FUNC_DEF(input, keyname, 1),
|
||||
MIST_FUNC_DEF(input, keymod, 0),
|
||||
MIST_FUNC_DEF(input, mousestate, 0),
|
||||
@@ -109,7 +96,6 @@ JSValue js_input_use(JSContext *js) {
|
||||
|
||||
// Initialize SDL cursor class (no functions)
|
||||
JSValue c_types = JS_GetPropertyStr(js, JS_GetGlobalObject(js), "c_types");
|
||||
QJSCLASSPREP_NO_FUNCS(SDL_Cursor)
|
||||
JS_FreeValue(js, c_types);
|
||||
|
||||
return mod;
|
||||
|
||||
@@ -43,6 +43,13 @@ QJSCLASS(SDL_Texture,
|
||||
QJSCLASS(SDL_Renderer,)
|
||||
QJSCLASS(SDL_Window,)
|
||||
|
||||
void SDL_Cursor_free(JSRuntime *rt, SDL_Cursor *c)
|
||||
{
|
||||
SDL_DestroyCursor(c);
|
||||
}
|
||||
|
||||
QJSCLASS(SDL_Cursor,)
|
||||
|
||||
// External function declarations
|
||||
extern JSValue rect2js(JSContext *js, rect r);
|
||||
extern rect js2rect(JSContext *js, JSValue v);
|
||||
@@ -1555,6 +1562,29 @@ static const JSCFunctionListEntry js_sdl_video_funcs[] = {
|
||||
JS_PROP_INT32_DEF("BLENDMODE_MUL", SDL_BLENDMODE_MUL, JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
// Cursor creation function
|
||||
JSC_CCALL(sdl_create_cursor,
|
||||
SDL_Surface *surf = js2SDL_Surface(js, argv[0]);
|
||||
if (!surf) return JS_ThrowReferenceError(js, "Invalid surface");
|
||||
|
||||
HMM_Vec2 hot = {0, 0};
|
||||
if (argc > 1) hot = js2vec2(js, argv[1]);
|
||||
|
||||
SDL_Cursor *cursor = SDL_CreateColorCursor(surf, hot.x, hot.y);
|
||||
if (!cursor) return JS_ThrowReferenceError(js, "Failed to create cursor: %s", SDL_GetError());
|
||||
|
||||
return SDL_Cursor2js(js, cursor);
|
||||
)
|
||||
|
||||
// Set cursor function
|
||||
JSC_CCALL(sdl_set_cursor,
|
||||
SDL_Cursor *cursor = js2SDL_Cursor(js, argv[0]);
|
||||
|
||||
if (!cursor) return JS_ThrowReferenceError(js, "Invalid cursor");
|
||||
|
||||
SDL_SetCursor(cursor);
|
||||
)
|
||||
|
||||
// Texture getter/setter functions
|
||||
|
||||
// Alpha mod getter/setter
|
||||
@@ -1759,6 +1789,7 @@ static void video_actor_hook(JSContext *js) {
|
||||
QJSCLASSPREP_FUNCS(SDL_Window)
|
||||
QJSCLASSPREP_FUNCS(SDL_Renderer)
|
||||
QJSCLASSPREP_FUNCS(SDL_Texture)
|
||||
QJSCLASSPREP_NO_FUNCS(SDL_Cursor)
|
||||
|
||||
JS_FreeValue(js, c_types);
|
||||
|
||||
@@ -1789,6 +1820,12 @@ static void video_actor_hook(JSContext *js) {
|
||||
JS_SetPropertyStr(js, endowments, "createWindowAndRenderer",
|
||||
JS_NewCFunction(js, js_sdl_createWindowAndRenderer, "createWindowAndRenderer", 4));
|
||||
|
||||
// Add cursor functions
|
||||
JS_SetPropertyStr(js, endowments, "createCursor",
|
||||
JS_NewCFunction(js, js_sdl_create_cursor, "createCursor", 2));
|
||||
JS_SetPropertyStr(js, endowments, "setCursor",
|
||||
JS_NewCFunction(js, js_sdl_set_cursor, "setCursor", 1));
|
||||
|
||||
JS_FreeValue(js, endowments);
|
||||
JS_FreeValue(js, prosperon);
|
||||
}
|
||||
|
||||
@@ -56,13 +56,11 @@ function start_drawing() {
|
||||
var start_time = os.now();
|
||||
|
||||
// Load an image
|
||||
var bunny_image = null;
|
||||
try {
|
||||
bunny_image = graphics.texture('tests/bunny.png');
|
||||
} catch (e) {
|
||||
console.log("Failed to load bunny image:", e);
|
||||
console.log(e)
|
||||
}
|
||||
var bunny_image = graphics.texture('tests/bunny.png')
|
||||
|
||||
send(video_actor, {kind: "cursor", op: "create", data: bunny_image.cpu}, ({id}) => {
|
||||
send(video_actor, {kind:"cursor", op: "set", id})
|
||||
})
|
||||
|
||||
function draw_frame() {
|
||||
frame++;
|
||||
|
||||
Reference in New Issue
Block a user