diff --git a/src/platform/generic.nim b/src/platform/generic.nim index be693ba..d9fb18f 100644 --- a/src/platform/generic.nim +++ b/src/platform/generic.nim @@ -40,6 +40,7 @@ type Window* = ref object of RootObj import std/math import std/strformat import std/strutils +import std/unicode import ./gl import ../screen import ../util @@ -54,9 +55,20 @@ proc screen*(window: Window): Screen {.inline.} = proc `screen=`*(window: Window, screen1: Screen) {.inline.} = global_screen = screen1 +type MyouCallbacks = object + getdir: proc(app: pointer, buf: ptr char, len: int32, which: int8): int32 {.cdecl.} + getbundlefile: proc(app: pointer, buf: ptr char, len: int32, path: cstring): int32 {.cdecl,gcsafe.} + closeapp: proc(app: pointer) {.cdecl.} + +{.emit:"void *global_myou_app_pointer, *global_myou_app_callbacks;".} +var app_pointer {.importc:"global_myou_app_pointer".}: pointer +var callbacks0 {.importc:"global_myou_app_callbacks".}: pointer +template callbacks: untyped = cast[ptr MyouCallbacks](callbacks0) proc NimMain() {.importc.} -proc myouEngineCreate() {.exportc,cdecl,stackTrace:off.} = +proc myouEngineCreate(app: pointer, cbs: ptr MyouCallbacks) {.exportc,cdecl,stackTrace:off.} = + app_pointer = app + callbacks0 = cbs try: NimMain() echo "nimmain end" @@ -75,15 +87,21 @@ proc myouEngineOnPause() {.exportc,cdecl.} = proc myouEngineOnResume() {.exportc,cdecl.} = discard -proc myouEngineOnSurfaceCreated(w,h,r: int32) {.exportc,cdecl.} = +proc myouEngineOnSurfaceCreated(w,h,r: int32, scale: float32, top,right,bottom,left: float32) {.exportc,cdecl.} = assert global_screen != nil if global_screen != nil: global_screen.resize(w,h,r.int8) + global_screen.display_scale = scale + when not defined(myouUseFakeFrameInset): + global_screen.frame_inset = FrameInset(top: top*scale, right: right*scale, bottom: bottom*scale, left: left*scale) global_screen.engine.renderer.initialize() -proc myouEngineOnSurfaceChanged(w,h,r: int32) {.exportc,cdecl.} = +proc myouEngineOnSurfaceChanged(w,h,r: int32, scale: float32, top,right,bottom,left: float32) {.exportc,cdecl.} = if global_screen != nil: global_screen.resize(w,h,r.int8) + global_screen.display_scale = scale + when not defined(myouUseFakeFrameInset): + global_screen.frame_inset = FrameInset(top: top*scale, right: right*scale, bottom: bottom*scale, left: left*scale) proc make_window*(width, height: int32, title: string): Window = nil @@ -146,11 +164,16 @@ proc start_platform_main_loop*(engine1: MyouEngine, main_loop1: proc(self: MyouE engine = engine1 main_loop = main_loop1 -proc myouEngineOnFrame() {.exportc,cdecl.} = +type MyouEngineFrameResult = object + needsKeyboard: uint8 +var frame_result: MyouEngineFrameResult + +proc myouEngineOnFrame(): MyouEngineFrameResult {.exportc,cdecl.} = if engine == nil: return try: engine.main_loop() + return frame_result except Exception as e: for line in e.getStackTrace.split '\n': echo line @@ -168,5 +191,69 @@ proc platform_switch_screen*(screen: Screen): bool {.inline.} = discard proc myouSetKeyboardVisible*(show: bool) = - assert false, "TODO: myouSetKeyboardVisible in generic" + frame_result.needsKeyboard = show.uint8 + +proc myouGetDocumentsDir*(): string = + result.setLen 512 + let l = callbacks.getdir(app_pointer, result[0].addr, result.len.int32, 0) + result.setLen l + if result.startswith "file://": + result = result[7 .. ^1] + if result.endswith "/": + result.setlen(result.len - 1) + +proc myouGetCacheDir*(): string = + result.setLen 512 + let l = callbacks.getdir(app_pointer, result[0].addr, result.len.int32, 1) + result.setLen l + if result.startswith "file://": + result = result[7 .. ^1] + if result.endswith "/": + result.setlen(result.len - 1) + +proc myouGetTmpDir*(): string = + result.setLen 512 + let l = callbacks.getdir(app_pointer, result[0].addr, result.len.int32, 2) + result.setLen l + if result.startswith "file://": + result = result[7 .. ^1] + if result.endswith "/": + result.setlen(result.len - 1) + +proc myouGetBundledFilePath*(path: string): string {.gcsafe.} = + result.setLen 512 + let l = callbacks.getbundlefile(app_pointer, result[0].addr, result.len.int32, path.cstring) + result.setLen l + if result.startswith "file://": + result = result[7 .. ^1] + + +proc myouOnKeyEvent(keyCode: int32, mods: int32, pressed: int32) {.exportc,cdecl.} = + let key = cast[KeyCode](keyCode) + let shiftKey = (mods and (1 shl 17)).bool + let metaKey = (mods and (2 shl 17)).bool + let altKey = (mods and (4 shl 17)).bool + let ctrlKey = (mods and (8 shl 17)).bool + for cb in global_screen.key_callbacks: + cb(KeyEvent( + pressed: pressed != 0, + repeat: false, + shiftKey: shiftKey, ctrlKey: ctrlKey, altKey: altKey, metaKey: metaKey, + key: key, + )) + if global_screen.break_current_callbacks: + global_screen.break_current_callbacks = false + break + +proc myouOnCharEvent(str: cstring) {.exportc,cdecl.} = + for rune in ($str).toRunes: + let codepoint = cast[uint32](rune) + for cb in global_screen.char_callbacks: + cb(codepoint) + if global_screen.break_current_callbacks: + global_screen.break_current_callbacks = false + break + +proc myouCloseMobileApp*() = + callbacks.closeapp(app_pointer) diff --git a/src/platform/glfm_wrap.nim b/src/platform/glfm_wrap.nim index fc1088d..1d708e6 100644 --- a/src/platform/glfm_wrap.nim +++ b/src/platform/glfm_wrap.nim @@ -382,3 +382,4 @@ proc myouSetKeyboardVisible*(show: bool) = proc myouCloseMobileApp*() = ANativeActivity_finish(window.glfmAndroidGetActivity()) + quit()