1 /++ 2 Integration with Godot editor's output and debugger tabs 3 +/ 4 module godot.d.output; 5 6 import godot.c, godot.core; 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 { 15 import core.exception; 16 import std.experimental.allocator.mallocator; 17 18 char[] buffer = cast(char[])Mallocator.instance.allocate(file.length + msg.length + 2); 19 scope(exit) 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.godot_print_error(&buffer.ptr[file.length+1], "", buffer.ptr, cast(int)line); 27 28 version(D_Exceptions) throw new AssertError(msg, file, line); 29 else 30 { 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 { 47 import core.exception; 48 import std.experimental.allocator.mallocator; 49 50 char[] buffer = cast(char[])Mallocator.instance.allocate(file.length + msg.length + 2); 51 scope(exit) 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.godot_print_error(&buffer.ptr[file.length+1], "", buffer.ptr, cast(int)line); 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) throw new AssertError(msg, file, line); 68 else 69 { 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) 83 { 84 import godot.core..string, godot.core.variant; 85 86 String str; 87 static if(Args.length == 0) str = String(" "); 88 foreach(arg; args) 89 { 90 static if(is(typeof(arg) : String)) str ~= arg; 91 else static if(is(typeof(arg) : string)) str ~= String(arg); 92 else static if(is(typeof(arg) : Variant)) str ~= arg.as!String; 93 else static if(Variant.compatibleToGodot!(typeof(arg))) str ~= Variant(arg).as!String; 94 else static assert(0, "Unable to print type "~typeof(arg).stringof); 95 } 96 _godot_api.godot_print(&str._godot_string); 97 } 98