1 /* 2 This is a template for creating GUI apps with PixelPerfectEngine's Concrete subsystem. 3 Contains the skeleton, that a GUI application needs. 4 Feel free to rename, or even completely change things! 5 */ 6 7 module guiapp; 8 9 //Imports that are mandatory for a minimum viable PPE Concrete GUI app 10 import pixelperfectengine.graphics.outputscreen; //Output screen import 11 import pixelperfectengine.graphics.layers; //Imports mandatory layer related things, especially the SpriteLayer 12 import pixelperfectengine.graphics.raster; //Imports the Raster class to handle one or more layers at once 13 import pixelperfectengine.concrete.window; //Imports everything needed for windowing (the Window class, elements, etc.). 14 import pixelperfectengine.system.input; //This gives us to read user inputs (mouse, keyboard, etc.) 15 import pixelperfectengine.system.systemutility; //It has the INIT_CONCRETE() function, important for setting and loading standards for Concrete. 16 import pixelperfectengine.system.file; //Bitmap file loading 17 import pixelperfectengine.system.common; //Has the initialzeSDL() function, needed for the engine to function as of now (might be replaced with INIT_IOTA() in the future) 18 import pixelperfectengine.system.timer; //Not mandatory, but a lack of timer.test() calls make certain GUI events not work. 19 20 import core.thread; //Imported due to the Thread.sleep() function, only needed for reduced raster refresh operations. 21 22 /// The main function of the application. 23 /// Feel free to add `string[] args` if needed! 24 int main() { 25 initialzeSDL(); //This function call initializes the SDL subsystem. Must be the first thing to be called for most things to work (graphics, input, etc) 26 INIT_CONCRETE(); //Initializes the Concrete subsystem of the engine. 27 SampleApp app = new SampleApp(); //Creates an instance of the class that contains the app instance. It is much easier to do things this way. 28 app.whereTheMagicHappens(); //Calls the main loop of the app. 29 return 0; //Everything went alright, return with value 0. 30 } 31 /// The class containing the basic application logic and classes that are needed for the app. 32 class SampleApp : InputListener, SystemEventListener { 33 Raster mainRaster; 34 OutputScreen outScrn; 35 SpriteLayer sprtL; 36 WindowHandler wh; 37 InputHandler ih; 38 //The next two are bitflags, can be unified into a single word to save on memory. 39 bool isRunning; 40 bool flipScreen; 41 /// Initializes every other things that wasn't initialized in other places. 42 public this() { 43 sprtL = new SpriteLayer(RenderingMode.Copy); //Creates a sprite layer to display the windows. 44 outScrn = new OutputScreen("Your app name here!",1696,960); //Creates an output window with the display size of 1696x960. 45 mainRaster = new Raster(848,480,outScrn,0); //Creates a raster with the size of 848x480. 46 mainRaster.addLayer(sprtL,0); //Adds the sprite layer to the raster. 47 mainRaster.loadPalette(loadPaletteFromFile("../system/concreteGUIE1.tga")); //Loads the default palette from a supplied file containing icons. 48 outScrn.setMainRaster(mainRaster); //Sets the main raster of the output screen. 49 //Load additional fonts, icons, etc. here 50 51 wh = new WindowHandler(1696,960,848,480,sprtL); //Creates a window handler for the sizes of the windowhandler and raster. 52 ih = new InputHandler(); //Initializes the input handler. 53 ih.inputListener = this; //Sets the input event output to this class. 54 ih.systemEventListener = this; //Sets the system event output to this class. 55 ih.mouseListener = wh; //Sets the mouse event output to the window handler. 56 WindowElement.inputHandler = ih; //Sets the input handler to be in charge of text input events, etc. 57 //Delete the next two lines if you want refresh on every frame! 58 WindowElement.onDraw = &rasterRefresh; //Sets the draw event output of the window elements to a function of this class. 59 Window.onDrawUpdate = &rasterRefresh; //Sets the draw event output of the windows to a function of this class. 60 isRunning = true; //Set isRunning to true, so the main loop will stay running. 61 62 //Add your initial windows to the window handler here! 63 } 64 /// Optional. 65 /// Reduces unneeded screen updates and thus the CPU usage, which might be useful for GUI applications, especially 66 /// on battery powered devices. 67 /// However, this can interfere with other things, like non-GUI related screen updates, input-latency, etc. 68 protected void rasterRefresh() { 69 flipScreen = true; 70 } 71 /// Function that contains the main loop 72 public void whereTheMagicHappens() { 73 mainRaster.refresh(); //Initial raster refresh, not needed if raster refresh is set to be updated on every frame 74 while(isRunning) { //The main loop 75 //Delete this if statement, if you want refresh on every frame! 76 if (flipScreen) { //This if statement is executed only when a draw function was called or a window was moved. 77 flipScreen = false; //sets boolean flipScreen to false once it's not needed. 78 mainRaster.refresh(); //Refreshes the screen by running refresh on all associated layers of the raster 79 } 80 //mainRaster.refresh(); //Uncomment this line, if you want refresh on every frame! 81 ih.test(); //Tests for input events, like keyboard, mouse, etc. 82 timer.test(); //Tests for expired timer events. 83 84 //Put additional things here you want to do on every loop! 85 86 Thread.sleep(dur!"msecs"(10)); //To avoid high CPU usage from frequent input checks. Remove this line if you want refresh on every frame! 87 } 88 89 //Put stuff here you want to do upon quitting your program. 90 91 } 92 /// Called when a key event have done by the user. 93 /// NOTE: Arguments will be changed once the move from SDL to iota is complete. 94 public void keyEvent(uint id, BindingCode code, uint timestamp, bool isPressed) { 95 96 } 97 /// Called when an axis event have done by the user. 98 /// NOTE: Arguments will be changed once the move from SDL to iota is complete. 99 public void axisEvent(uint id, BindingCode code, uint timestamp, float value) { 100 101 } 102 /// Called when the user exits from the application. 103 public void onQuit() { 104 isRunning = false; 105 } 106 /// Called when a controller is added to the system. 107 /// NOTE: Arguments will be changed once the move from SDL to iota is complete. 108 public void controllerAdded(uint id) { 109 110 } 111 /// Called when a controller is removed from the system. 112 /// Note: Arguments will be changed once the move from SDL to iota is complete. 113 public void controllerRemoved(uint id) { 114 115 } 116 }