1 /++ 2 Integration with Godot editor's output and debugger tabs 3 +/ 4 module godot.api.output; 5 6 import godot.abi, godot; 7 8 /++ 9 The release-mode Godot-D assert handler redirects assert messages to the Godot 10 error handlers and terminates the program. 11 +/ 12 // nothrow 13 void godotAssertHandlerCrash(string file, size_t line, string msg) { 14 import core.exception; 15 import std.experimental.allocator.mallocator; 16 17 char[] buffer = cast(char[]) Mallocator.instance.allocate(file.length + msg.length + 2); 18 scope (exit) 19 Mallocator.instance.deallocate(cast(void[]) buffer); 20 21 buffer[0 .. file.length] = file[]; 22 buffer[file.length] = '\0'; 23 buffer[file.length + 1 .. $ - 1] = msg[]; 24 buffer[$ - 1] = '\0'; 25 26 _godot_api.print_error(&buffer.ptr[file.length + 1], "", buffer.ptr, cast(int) line, true); 27 28 version (D_Exceptions) 29 throw new AssertError(msg, file, line); 30 else { 31 assertHandler = null; 32 assert(0, msg); 33 } 34 } 35 36 /++ 37 The debug-mode Godot-D assert handler redirects assert messages to the Godot 38 error handlers (including Debugger tab in editor and system console). 39 40 Unlike the default D assert handler, this one doesn't terminate the program, 41 allowing the messages to remain in Godot's Debugger tab and matching how Godot 42 error macros behave. 43 +/ 44 // nothrow 45 void godotAssertHandlerEditorDebug(string file, size_t line, string msg) { 46 import core.exception; 47 import std.experimental.allocator.mallocator; 48 49 char[] buffer = cast(char[]) Mallocator.instance.allocate(file.length + msg.length + 2); 50 scope (exit) 51 Mallocator.instance.deallocate(cast(void[]) buffer); 52 53 buffer[0 .. file.length] = file[]; 54 buffer[file.length] = '\0'; 55 buffer[file.length + 1 .. $ - 1] = msg[]; 56 buffer[$ - 1] = '\0'; 57 58 _godot_api.print_error(&buffer.ptr[file.length + 1], "", buffer.ptr, cast(int) line, true); 59 60 //version(assert) // any `assert(x)` gets compiled; usually a debug version 61 //{ 62 // // TODO: if in Editor Debugger, debug_break like GDScript asserts 63 //} 64 //else // only `assert(0)`/`assert(false)` get compiled; usually a release version 65 { 66 // crash on always-false asserts 67 version (D_Exceptions) 68 throw new AssertError(msg, file, line); 69 else { 70 assertHandler = null; 71 assert(0, msg); 72 } 73 } 74 } 75 76 /** 77 Print to Godot's console and stdout. 78 79 Params: 80 args = any Godot-compatible types or strings 81 */ 82 void print(Args...)(Args args, string fn = __FUNCTION__, string f = __FILE__, int l = __LINE__) { 83 import godot.string, godot.variant; 84 85 String str; 86 static if (Args.length == 0) 87 str = String(" "); 88 foreach (arg; args) { 89 static if (is(typeof(arg) : String)) 90 str ~= arg; 91 else static if (is(typeof(arg) : NodePath)) 92 str ~= arg.str; 93 else static if (is(typeof(arg) : string)) 94 str ~= String(arg); 95 else static if (is(typeof(arg) : Variant)) 96 str ~= arg.as!String; 97 else static if (Variant.compatibleToGodot!(typeof(arg))) 98 str ~= Variant(arg).as!String; 99 else 100 static assert(0, "Unable to print type " ~ typeof(arg).stringof); 101 } 102 auto utfstr = str.utf8; 103 _godot_api.print_warning(cast(char*) utfstr.data, &fn[0], &f[0], l, true); 104 }