1 /** 2 Abstract base class for the game's main loop. 3 4 Copyright: 5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. 6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) 7 Copyright (c) 2017-2018 Godot-D contributors 8 9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License) 10 11 12 */ 13 module godot.mainloop; 14 import std.meta : AliasSeq, staticIndexOf; 15 import std.traits : Unqual; 16 import godot.d.traits; 17 import godot.core; 18 import godot.c; 19 import godot.d.bind; 20 import godot.d.reference; 21 import godot.globalenums; 22 import godot.object; 23 import godot.classdb; 24 import godot.inputevent; 25 /** 26 Abstract base class for the game's main loop. 27 28 $(D MainLoop) is the abstract base class for a Godot project's game loop. It is inherited by $(D SceneTree), which is the default game loop implementation used in Godot projects, though it is also possible to write and use one's own $(D MainLoop) subclass instead of the scene tree. 29 Upon the application start, a $(D MainLoop) implementation must be provided to the OS; otherwise, the application will exit. This happens automatically (and a $(D SceneTree) is created) unless a main $(D Script) is provided from the command line (with e.g. `godot -s my_loop.gd`, which should then be a $(D MainLoop) implementation. 30 Here is an example script implementing a simple $(D MainLoop): 31 32 33 extends MainLoop 34 35 var time_elapsed = 0 36 var keys_typed = [] 37 var quit = false 38 39 func _initialize(): 40 print("Initialized:") 41 print(" Starting time: %s" % str(time_elapsed)) 42 43 func _idle(delta): 44 time_elapsed += delta 45 # Return true to end the main loop. 46 return quit 47 48 func _input_event(event): 49 # Record keys. 50 if event is InputEventKey and event.pressed and !event.echo: 51 keys_typed.append(OS.get_scancode_string(event.scancode)) 52 # Quit on Escape press. 53 if event.scancode == KEY_ESCAPE: 54 quit = true 55 # Quit on any mouse click. 56 if event is InputEventMouseButton: 57 quit = true 58 59 func _finalize(): 60 print("Finalized:") 61 print(" End time: %s" % str(time_elapsed)) 62 print(" Keys typed: %s" % var2str(keys_typed)) 63 64 65 */ 66 @GodotBaseClass struct MainLoop 67 { 68 package(godot) enum string _GODOT_internal_name = "MainLoop"; 69 public: 70 @nogc nothrow: 71 union { /** */ godot_object _godot_object; /** */ GodotObject _GODOT_base; } 72 alias _GODOT_base this; 73 alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses); 74 package(godot) __gshared bool _classBindingInitialized = false; 75 package(godot) static struct GDNativeClassBinding 76 { 77 __gshared: 78 @GodotName("_drop_files") GodotMethod!(void, PoolStringArray, long) _dropFiles; 79 @GodotName("_finalize") GodotMethod!(void) _finalize; 80 @GodotName("_global_menu_action") GodotMethod!(void, Variant, Variant) _globalMenuAction; 81 @GodotName("_idle") GodotMethod!(bool, double) _idle; 82 @GodotName("_initialize") GodotMethod!(void) _initialize; 83 @GodotName("_input_event") GodotMethod!(void, InputEvent) _inputEvent; 84 @GodotName("_input_text") GodotMethod!(void, String) _inputText; 85 @GodotName("_iteration") GodotMethod!(bool, double) _iteration; 86 @GodotName("finish") GodotMethod!(void) finish; 87 @GodotName("idle") GodotMethod!(bool, double) idle; 88 @GodotName("init") GodotMethod!(void) _init; 89 @GodotName("input_event") GodotMethod!(void, InputEvent) inputEvent; 90 @GodotName("input_text") GodotMethod!(void, String) inputText; 91 @GodotName("iteration") GodotMethod!(bool, double) iteration; 92 } 93 /// 94 pragma(inline, true) bool opEquals(in MainLoop other) const 95 { return _godot_object.ptr is other._godot_object.ptr; } 96 /// 97 pragma(inline, true) typeof(null) opAssign(typeof(null) n) 98 { _godot_object.ptr = n; return null; } 99 /// 100 pragma(inline, true) bool opEquals(typeof(null) n) const 101 { return _godot_object.ptr is n; } 102 /// 103 size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; } 104 mixin baseCasts; 105 /// Construct a new instance of MainLoop. 106 /// Note: use `memnew!MainLoop` instead. 107 static MainLoop _new() 108 { 109 static godot_class_constructor constructor; 110 if(constructor is null) constructor = _godot_api.godot_get_class_constructor("MainLoop"); 111 if(constructor is null) return typeof(this).init; 112 return cast(MainLoop)(constructor()); 113 } 114 @disable new(size_t s); 115 /// 116 enum Constants : int 117 { 118 /** 119 Notification received from the OS when the mouse enters the game window. 120 Implemented on desktop and web platforms. 121 */ 122 notificationWmMouseEnter = 1002, 123 /** 124 Notification received from the OS when the mouse leaves the game window. 125 Implemented on desktop and web platforms. 126 */ 127 notificationWmMouseExit = 1003, 128 /** 129 Notification received from the OS when the game window is focused. 130 Implemented on all platforms. 131 */ 132 notificationWmFocusIn = 1004, 133 /** 134 Notification received from the OS when the game window is unfocused. 135 Implemented on all platforms. 136 */ 137 notificationWmFocusOut = 1005, 138 /** 139 Notification received from the OS when a quit request is sent (e.g. closing the window with a "Close" button or Alt+F4). 140 Implemented on desktop platforms. 141 */ 142 notificationWmQuitRequest = 1006, 143 /** 144 Notification received from the OS when a go back request is sent (e.g. pressing the "Back" button on Android). 145 Specific to the Android platform. 146 */ 147 notificationWmGoBackRequest = 1007, 148 /** 149 Notification received from the OS when an unfocus request is sent (e.g. another OS window wants to take the focus). 150 No supported platforms currently send this notification. 151 */ 152 notificationWmUnfocusRequest = 1008, 153 /** 154 Notification received from the OS when the application is exceeding its allocated memory. 155 Specific to the iOS platform. 156 */ 157 notificationOsMemoryWarning = 1009, 158 /** 159 Notification received when translations may have changed. Can be triggered by the user changing the locale. Can be used to respond to language changes, for example to change the UI strings on the fly. Useful when working with the built-in translation support, like $(D GodotObject.tr). 160 */ 161 notificationTranslationChanged = 1010, 162 /** 163 Notification received from the OS when a request for "About" information is sent. 164 Specific to the macOS platform. 165 */ 166 notificationWmAbout = 1011, 167 /** 168 Notification received from Godot's crash handler when the engine is about to crash. 169 Implemented on desktop platforms if the crash handler is enabled. 170 */ 171 notificationCrash = 1012, 172 /** 173 Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string). 174 Specific to the macOS platform. 175 */ 176 notificationOsImeUpdate = 1013, 177 /** 178 Notification received from the OS when the app is resumed. 179 Specific to the Android platform. 180 */ 181 notificationAppResumed = 1014, 182 /** 183 Notification received from the OS when the app is paused. 184 Specific to the Android platform. 185 */ 186 notificationAppPaused = 1015, 187 } 188 /** 189 Called when files are dragged from the OS file manager and dropped in the game window. The arguments are a list of file paths and the identifier of the screen where the drag originated. 190 */ 191 void _dropFiles(in PoolStringArray files, in long from_screen) 192 { 193 Array _GODOT_args = Array.make(); 194 _GODOT_args.append(files); 195 _GODOT_args.append(from_screen); 196 String _GODOT_method_name = String("_drop_files"); 197 this.callv(_GODOT_method_name, _GODOT_args); 198 } 199 /** 200 Called before the program exits. 201 */ 202 void _finalize() 203 { 204 Array _GODOT_args = Array.make(); 205 String _GODOT_method_name = String("_finalize"); 206 this.callv(_GODOT_method_name, _GODOT_args); 207 } 208 /** 209 Called when the user performs an action in the system global menu (e.g. the Mac OS menu bar). 210 */ 211 void _globalMenuAction(VariantArg0, VariantArg1)(in VariantArg0 id, in VariantArg1 meta) 212 { 213 Array _GODOT_args = Array.make(); 214 _GODOT_args.append(id); 215 _GODOT_args.append(meta); 216 String _GODOT_method_name = String("_global_menu_action"); 217 this.callv(_GODOT_method_name, _GODOT_args); 218 } 219 /** 220 Called each idle frame with the time since the last idle frame as argument (in seconds). Equivalent to $(D Node._process). 221 If implemented, the method must return a boolean value. `true` ends the main loop, while `false` lets it proceed to the next frame. 222 */ 223 bool _idle(in double delta) 224 { 225 Array _GODOT_args = Array.make(); 226 _GODOT_args.append(delta); 227 String _GODOT_method_name = String("_idle"); 228 return this.callv(_GODOT_method_name, _GODOT_args).as!(RefOrT!bool); 229 } 230 /** 231 Called once during initialization. 232 */ 233 void _initialize() 234 { 235 Array _GODOT_args = Array.make(); 236 String _GODOT_method_name = String("_initialize"); 237 this.callv(_GODOT_method_name, _GODOT_args); 238 } 239 /** 240 Called whenever an $(D InputEvent) is received by the main loop. 241 */ 242 void _inputEvent(InputEvent event) 243 { 244 Array _GODOT_args = Array.make(); 245 _GODOT_args.append(event); 246 String _GODOT_method_name = String("_input_event"); 247 this.callv(_GODOT_method_name, _GODOT_args); 248 } 249 /** 250 Deprecated callback, does not do anything. Use $(D _inputEvent) to parse text input. Will be removed in Godot 4.0. 251 */ 252 void _inputText(in String text) 253 { 254 Array _GODOT_args = Array.make(); 255 _GODOT_args.append(text); 256 String _GODOT_method_name = String("_input_text"); 257 this.callv(_GODOT_method_name, _GODOT_args); 258 } 259 /** 260 Called each physics frame with the time since the last physics frame as argument (`delta`, in seconds). Equivalent to $(D Node._physicsProcess). 261 If implemented, the method must return a boolean value. `true` ends the main loop, while `false` lets it proceed to the next frame. 262 */ 263 bool _iteration(in double delta) 264 { 265 Array _GODOT_args = Array.make(); 266 _GODOT_args.append(delta); 267 String _GODOT_method_name = String("_iteration"); 268 return this.callv(_GODOT_method_name, _GODOT_args).as!(RefOrT!bool); 269 } 270 /** 271 Should not be called manually, override $(D _finalize) instead. Will be removed in Godot 4.0. 272 */ 273 void finish() 274 { 275 checkClassBinding!(typeof(this))(); 276 ptrcall!(void)(GDNativeClassBinding.finish, _godot_object); 277 } 278 /** 279 Should not be called manually, override $(D _idle) instead. Will be removed in Godot 4.0. 280 */ 281 bool idle(in double delta) 282 { 283 checkClassBinding!(typeof(this))(); 284 return ptrcall!(bool)(GDNativeClassBinding.idle, _godot_object, delta); 285 } 286 /** 287 Should not be called manually, override $(D _initialize) instead. Will be removed in Godot 4.0. 288 */ 289 void _init() 290 { 291 checkClassBinding!(typeof(this))(); 292 ptrcall!(void)(GDNativeClassBinding._init, _godot_object); 293 } 294 /** 295 Should not be called manually, override $(D _inputEvent) instead. Will be removed in Godot 4.0. 296 */ 297 void inputEvent(InputEvent event) 298 { 299 checkClassBinding!(typeof(this))(); 300 ptrcall!(void)(GDNativeClassBinding.inputEvent, _godot_object, event); 301 } 302 /** 303 Should not be called manually, override $(D _inputText) instead. Will be removed in Godot 4.0. 304 */ 305 void inputText(in String text) 306 { 307 checkClassBinding!(typeof(this))(); 308 ptrcall!(void)(GDNativeClassBinding.inputText, _godot_object, text); 309 } 310 /** 311 Should not be called manually, override $(D _iteration) instead. Will be removed in Godot 4.0. 312 */ 313 bool iteration(in double delta) 314 { 315 checkClassBinding!(typeof(this))(); 316 return ptrcall!(bool)(GDNativeClassBinding.iteration, _godot_object, delta); 317 } 318 }