From 5c2cb695e1d5a6d932b3005500fa04bde54770e4 Mon Sep 17 00:00:00 2001 From: Alexander Klingenbeck Date: Sun, 4 Jun 2023 13:41:18 +0200 Subject: [PATCH] Implement text reference params --- bindings/src/index.ts | 27 ++++++++++++++++++++++++- bindings/src/raylib-header.ts | 2 +- examples/lib.raylib.d.ts | 2 ++ examples/raygui/controls_test_suite.js | 4 ++-- generate-bindings.js | 28 ++++++++++++++++++++++++-- src/bindings/js_raylib_core.h | 21 +++++++++++++++++++ 6 files changed, 78 insertions(+), 6 deletions(-) diff --git a/bindings/src/index.ts b/bindings/src/index.ts index 6c9cb4b..1d06683 100644 --- a/bindings/src/index.ts +++ b/bindings/src/index.ts @@ -512,13 +512,38 @@ function main(){ } } } + const setOutParamString = (fun: RayLibFunction, index: number, indexLen: number) => { + const lenParam = fun!.params![indexLen] + lenParam.binding = { ignore: true } + const param = fun!.params![index] + param.binding = { + jsType: `{ ${param.name}: string }`, + customConverter: gen => { + gen.call("JS_GetPropertyStr", ["ctx","argv["+index+"]", '"'+param.name+'"'], { name: param.name+"_js", type: "JSValue" }) + gen.declare(param.name+"_len", "size_t"); + gen.call("JS_ToCStringLen",["ctx", "&"+param.name+"_len", param.name+"_js"], { name: param.name+"_val", type: "const char *" }) + gen.call("memcpy", ["(void *)textbuffer", param.name+"_val", param.name+"_len"]) + gen.statement("textbuffer["+param.name+"_len] = 0") + gen.declare(param.name, param.type, false, "textbuffer"); + gen.declare(lenParam.name, lenParam.type, false, "4096") + }, + customCleanup: gen => { + gen.jsCleanUpParameter("const char *", param.name + "_val") + gen.call("JS_SetPropertyStr", ["ctx", "argv["+index+"]", `"${param.name}"`, "JS_NewString(ctx,"+param.name+")"]) + } + } + + } + + core.definitions.declare("textbuffer[4096]", "char", true) setOutParam(getFunction(api.functions, "GuiDropdownBox")!, 2) setOutParam(getFunction(api.functions, "GuiSpinner")!, 2) setOutParam(getFunction(api.functions, "GuiValueBox")!, 2) setOutParam(getFunction(api.functions, "GuiListView")!, 2) ignore("GuiListViewEx") - ignore("GuiTextBox") + setOutParamString(getFunction(api.functions, "GuiTextBox")!, 1,2) + //ignore("GuiTextBox") ignore("GuiTextInputBox") //setOutParam(getFunction(api.functions, "GuiTextInputBox")!, 6) ignore("GuiTabBar") diff --git a/bindings/src/raylib-header.ts b/bindings/src/raylib-header.ts index a12fdaa..51511f5 100644 --- a/bindings/src/raylib-header.ts +++ b/bindings/src/raylib-header.ts @@ -43,7 +43,7 @@ export class RayLibHeader extends QuickJsHeader { // clean up parameters for (const param of api.params) { if(param.binding?.customCleanup) param.binding.customCleanup(fun) - fun.jsCleanUpParameter(param.type, param.name) + else fun.jsCleanUpParameter(param.type, param.name) } // return result if(api.returnType === "void"){ diff --git a/examples/lib.raylib.d.ts b/examples/lib.raylib.d.ts index 91786c2..cc2e668 100644 --- a/examples/lib.raylib.d.ts +++ b/examples/lib.raylib.d.ts @@ -1484,6 +1484,8 @@ declare function guiDropdownBox(bounds: Rectangle, text: string, active: { activ declare function guiSpinner(bounds: Rectangle, text: string, value: { value: number }, minValue: number, maxValue: number, editMode: boolean): boolean; /** Value Box control, updates input text with numbers */ declare function guiValueBox(bounds: Rectangle, text: string, value: { value: number }, minValue: number, maxValue: number, editMode: boolean): boolean; +/** Text Box control, updates input text */ +declare function guiTextBox(bounds: Rectangle, text: { text: string }, editMode: boolean): boolean; /** Slider control, returns selected value */ declare function guiSlider(bounds: Rectangle, textLeft: string, textRight: string, value: number, minValue: number, maxValue: number): number; /** Slider Bar control, returns selected value */ diff --git a/examples/raygui/controls_test_suite.js b/examples/raygui/controls_test_suite.js index 1db39d0..cba70ed 100644 --- a/examples/raygui/controls_test_suite.js +++ b/examples/raygui/controls_test_suite.js @@ -20,7 +20,7 @@ let spinnerEditMode = false; let valueBox002Value = { value: 0 }; let valueBoxEditMode = false; -let textBoxText = "Text box"; +let textBoxText = { text: "Text box" }; let textBoxEditMode = false; let listViewScrollIndex = { scrollIndex: 0 }; @@ -105,7 +105,7 @@ while (!exitWindow) // Detect window close button or ESC key if (guiSpinner(new Rectangle(25, 135, 125, 30), null, spinner001Value, 0, 100, spinnerEditMode)) spinnerEditMode = !spinnerEditMode; if (guiValueBox(new Rectangle(25, 175, 125, 30), null, valueBox002Value, 0, 100, valueBoxEditMode)) valueBoxEditMode = !valueBoxEditMode; guiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); - //if (guiTextBox(new Rectangle(25, 215, 125, 30), textBoxText, 64, textBoxEditMode)) textBoxEditMode = !textBoxEditMode; + if (guiTextBox(new Rectangle(25, 215, 125, 30), textBoxText, 64, textBoxEditMode)) textBoxEditMode = !textBoxEditMode; guiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); diff --git a/generate-bindings.js b/generate-bindings.js index 93807ad..772c307 100644 --- a/generate-bindings.js +++ b/generate-bindings.js @@ -678,7 +678,8 @@ class RayLibHeader extends quickjs_1.QuickJsHeader { for (const param of api.params) { if (param.binding?.customCleanup) param.binding.customCleanup(fun); - fun.jsCleanUpParameter(param.type, param.name); + else + fun.jsCleanUpParameter(param.type, param.name); } // return result if (api.returnType === "void") { @@ -1397,12 +1398,35 @@ function main() { } }; }; + const setOutParamString = (fun, index, indexLen) => { + const lenParam = fun.params[indexLen]; + lenParam.binding = { ignore: true }; + const param = fun.params[index]; + param.binding = { + jsType: `{ ${param.name}: string }`, + customConverter: gen => { + gen.call("JS_GetPropertyStr", ["ctx", "argv[" + index + "]", '"' + param.name + '"'], { name: param.name + "_js", type: "JSValue" }); + gen.declare(param.name + "_len", "size_t"); + gen.call("JS_ToCStringLen", ["ctx", "&" + param.name + "_len", param.name + "_js"], { name: param.name + "_val", type: "const char *" }); + gen.call("memcpy", ["(void *)textbuffer", param.name + "_val", param.name + "_len"]); + gen.statement("textbuffer[" + param.name + "_len] = 0"); + gen.declare(param.name, param.type, false, "textbuffer"); + gen.declare(lenParam.name, lenParam.type, false, "4096"); + }, + customCleanup: gen => { + gen.jsCleanUpParameter("const char *", param.name + "_val"); + gen.call("JS_SetPropertyStr", ["ctx", "argv[" + index + "]", `"${param.name}"`, "JS_NewString(ctx," + param.name + ")"]); + } + }; + }; + core.definitions.declare("textbuffer[4096]", "char", true); setOutParam(getFunction(api.functions, "GuiDropdownBox"), 2); setOutParam(getFunction(api.functions, "GuiSpinner"), 2); setOutParam(getFunction(api.functions, "GuiValueBox"), 2); setOutParam(getFunction(api.functions, "GuiListView"), 2); ignore("GuiListViewEx"); - ignore("GuiTextBox"); + setOutParamString(getFunction(api.functions, "GuiTextBox"), 1, 2); + //ignore("GuiTextBox") ignore("GuiTextInputBox"); //setOutParam(getFunction(api.functions, "GuiTextInputBox")!, 6) ignore("GuiTabBar"); diff --git a/src/bindings/js_raylib_core.h b/src/bindings/js_raylib_core.h index 8c8618c..cbca14f 100644 --- a/src/bindings/js_raylib_core.h +++ b/src/bindings/js_raylib_core.h @@ -19,6 +19,7 @@ #define countof(x) (sizeof(x) / sizeof((x)[0])) #endif +static char textbuffer[4096]; static JSClassID js_Vector2_class_id; static JSClassID js_Vector3_class_id; static JSClassID js_Vector4_class_id; @@ -8966,6 +8967,25 @@ static JSValue js_guiValueBox(JSContext * ctx, JSValueConst this_val, int argc, return ret; } +static JSValue js_guiTextBox(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { + Rectangle* bounds_ptr = (Rectangle*)JS_GetOpaque2(ctx, argv[0], js_Rectangle_class_id); + if(bounds_ptr == NULL) return JS_EXCEPTION; + Rectangle bounds = *bounds_ptr; + JSValue text_js = JS_GetPropertyStr(ctx, argv[1], "text"); + size_t text_len; + const char * text_val = JS_ToCStringLen(ctx, &text_len, text_js); + memcpy((void *)textbuffer, text_val, text_len); + textbuffer[text_len] = 0; + char * text = textbuffer; + int textSize = 4096; + bool editMode = JS_ToBool(ctx, argv[3]); + bool returnVal = GuiTextBox(bounds, text, textSize, editMode); + JS_FreeCString(ctx, text_val); + JS_SetPropertyStr(ctx, argv[1], "text", JS_NewString(ctx,text)); + JSValue ret = JS_NewBool(ctx, returnVal); + return ret; +} + static JSValue js_guiSlider(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { Rectangle* bounds_ptr = (Rectangle*)JS_GetOpaque2(ctx, argv[0], js_Rectangle_class_id); if(bounds_ptr == NULL) return JS_EXCEPTION; @@ -10219,6 +10239,7 @@ static const JSCFunctionListEntry js_raylib_core_funcs[] = { JS_CFUNC_DEF("guiDropdownBox",4,js_guiDropdownBox), JS_CFUNC_DEF("guiSpinner",6,js_guiSpinner), JS_CFUNC_DEF("guiValueBox",6,js_guiValueBox), + JS_CFUNC_DEF("guiTextBox",3,js_guiTextBox), JS_CFUNC_DEF("guiSlider",6,js_guiSlider), JS_CFUNC_DEF("guiSliderBar",6,js_guiSliderBar), JS_CFUNC_DEF("guiProgressBar",6,js_guiProgressBar),