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 throw new AssertError(msg, file, line); 29 } 30 31 /++ 32 The debug-mode Godot-D assert handler redirects assert messages to the Godot 33 error handlers (including Debugger tab in editor and system console). 34 35 Unlike the default D assert handler, this one doesn't terminate the program, 36 allowing the messages to remain in Godot's Debugger tab and matching how Godot 37 error macros behave. 38 +/ 39 nothrow 40 void godotAssertHandlerEditorDebug(string file, size_t line, string msg) 41 { 42 import core.exception; 43 import std.experimental.allocator.mallocator; 44 45 char[] buffer = cast(char[])Mallocator.instance.allocate(file.length + msg.length + 2); 46 scope(exit) Mallocator.instance.deallocate(cast(void[])buffer); 47 48 buffer[0..file.length] = file[]; 49 buffer[file.length] = '\0'; 50 buffer[file.length+1 .. $-1] = msg[]; 51 buffer[$-1] = '\0'; 52 53 _godot_api.godot_print_error(&buffer.ptr[file.length+1], "", buffer.ptr, cast(int)line); 54 55 version(assert) // any `assert(x)` gets compiled; usually a debug version 56 { 57 // TODO: if in Editor Debugger, debug_break like GDScript asserts 58 } 59 else // only `assert(0)`/`assert(false)` get compiled; usually a release version 60 { 61 // crash on always-false asserts 62 throw new AssertError(msg, file, line); 63 } 64 } 65 66 /** 67 Print to Godot's console and stdout. 68 69 Params: 70 args = any Godot-compatible types or strings 71 */ 72 void print(Args...)(Args args) 73 { 74 import godot.core.string, godot.core.variant; 75 76 String str; 77 static if(Args.length == 0) str = String(" "); 78 foreach(arg; args) 79 { 80 static if(is(typeof(arg) : String)) str ~= arg; 81 else static if(is(typeof(arg) : string)) str ~= String(arg); 82 else static if(Variant.compatibleToGodot!(typeof(arg))) str ~= Variant(arg).as!String; 83 else static assert(0, "Unable to print type "~typeof(arg).stringof); 84 } 85 _godot_api.godot_print(&str._godot_string); 86 } 87