Note: this repo is AI generated so use with caution!
GMTextEdit is a small GameMaker + Odin project that wraps Odin's core:text/edit
text editing primitives in a native extension for GameMaker.
The goal is to let GameMaker code create lightweight text editor states, send text input or editing commands to Odin, then read back the edited string, caret, selection, status, and clipboard state.
Windows uses a native DLL. Linux uses a native shared object. HTML5/GX uses a generated JavaScript extension that embeds the same Odin code compiled to WebAssembly, so the GML API stays the same across targets.
GMTextEdit/
GM/ GameMaker project
extensions/ext_gmtextedit GameMaker extension resource and packaged DLL/SO
plus generated GX/HTML5 JavaScript bridge
objects/ Example object that demonstrates editing text
rooms/Room1 Example room with the sample object
scripts/ Command/status enums for GameMaker
Odin/
textedit.odin Odin source for the DLL and test runner
textedit_wasm.odin JS/Wasm scratch-buffer bridge helpers
textedit_native_test.odin Native-only smoke tests and executable entry point
build.bat Windows build script
build_linux.sh Linux build script
build_gx.bat GX/HTML5 Wasm + JavaScript bridge build script
build_gx_bridge.ps1 Embeds the Wasm module into gmtextedit.js
build/ Build outputs
- GameMaker 2024 project format
- Odin compiler
- Windows/MSVC toolchain for the native DLL build in
build.bat - Linux x86_64 host/toolchain for the native SO build in
build_linux.sh - PowerShell for generating the GX/HTML5 JavaScript bridge
The GameMaker extension includes the Windows DLL:
GM/extensions/ext_gmtextedit/gmtextedit.dll
the Linux shared object:
GM/extensions/ext_gmtextedit/gmtextedit.so
and a generated JavaScript bridge for HTML5/GX:
GM/extensions/ext_gmtextedit/gmtextedit.js
macOS builds would need a matching shared library (.dylib) and GameMaker
extension metadata for that target.
Build and test the native Windows DLL, then regenerate the GX/HTML5 bridge:
Odin\build.batIf you only need the GX/HTML5 JavaScript bridge, run:
Odin\build_gx.batbuild_gx.bat compiles Odin/build/gmtextedit.wasm with Odin's js_wasm32
target, then embeds that Wasm payload into
GM/extensions/ext_gmtextedit/gmtextedit.js.
On Linux, build and test the native extension with:
Odin/build_linux.shPass build to skip running the native smoke tests:
Odin/build_linux.sh buildOpen the GameMaker project at:
GM/GMTextEdit.yyp
Room1 contains obj_gmtextedit_example, which:
- creates an editor state with
gmte_create - accepts typed input with
gmte_input_text - handles common edit/navigation commands with
gmte_command - draws the edited string
- displays caret, anchor, selection, clipboard, and error status values
- mirrors copied/cut text to the system clipboard and reads system clipboard text before paste
The example includes multiline text so Up/Down caret movement can be tested immediately.
The extension functions are documented in:
GM/extensions/ext_gmtextedit/ext_gmtextedit.yy
Main functions:
| Function | Purpose |
|---|---|
gmte_create(id, initial_text) |
Creates or resets an editor state. |
gmte_destroy(id) |
Destroys one editor state. |
gmte_destroy_all() |
Destroys every editor state. |
gmte_exists(id) |
Returns whether an editor exists. |
gmte_set_text(id, text) |
Replaces the editor text. |
gmte_get_text(id) |
Returns the current editor text. |
gmte_input_text(id, text) |
Inserts text at the caret or selection. |
gmte_command(id, command) |
Runs an edit/navigation command. |
gmte_set_selection(id, head, tail) |
Sets caret/selection byte indices. |
gmte_get_caret(id) |
Returns the caret byte index. |
gmte_get_anchor(id) |
Returns the selection anchor byte index. |
gmte_get_selection_start(id) |
Returns the lower selection byte index. |
gmte_get_selection_end(id) |
Returns the upper selection byte index. |
gmte_get_text_length(id) |
Returns text length in bytes. |
gmte_get_selected_text(id) |
Returns selected text. |
gmte_set_translate_by_grapheme(id, enabled) |
Toggles grapheme-aware left/right movement. |
gmte_clipboard_set(text) |
Sets the extension clipboard buffer. |
gmte_clipboard_get() |
Gets the extension clipboard buffer. |
gmte_last_status() |
Returns the last status code. |
gmte_last_error() |
Returns the last error message. |
GameMaker command constants live in:
GM/scripts/scr_gmtextedit_constants/scr_gmtextedit_constants.gml
They mirror Odin's core:text/edit.Command values:
gmte_command(editor_id, GMTE_Command.Left);
gmte_command(editor_id, GMTE_Command.Right);
gmte_command(editor_id, GMTE_Command.Up);
gmte_command(editor_id, GMTE_Command.Down);
gmte_command(editor_id, GMTE_Command.SelectAll);
gmte_command(editor_id, GMTE_Command.Paste);The numeric enum values are explicit because they are ABI constants shared with the Odin DLL.
- Selection and caret positions are byte indices, not GameMaker character indices.
- The extension stores text editor states by string id.
- The extension clipboard functions use an internal buffer. The included
GameMaker example mirrors Copy/Cut to the system clipboard when possible,
but keeps a local fallback clipboard for GX/browser builds where
clipboard_get_text()can return an empty string. - Up/Down and line-start/end movement are handled inside the Odin wrapper before dispatching to Odin's built-in text edit commands.