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 }