1 /** 2 * Handles the creation and life cycle of UI objects and webview textures 3 */ 4 module dash.components.userinterface; 5 import dash, dash.utility.bindings.awesomium; 6 7 import std..string; 8 9 /** 10 * User interface objects handle drawing/updating an AwesomiumView over the screen 11 */ 12 class UserInterface 13 { 14 private: 15 uint _height; 16 uint _width; 17 mat4f _scaleMat; 18 AwesomiumView _view; 19 // TODO: Handle JS 20 21 public: 22 /// WebView to be drawn 23 mixin( Property!(_view, AccessModifier.Public) ); 24 /// Scale of the UI 25 mixin( Property!(_scaleMat, AccessModifier.Public) ); 26 27 /** 28 * Create UI object 29 * 30 * Params: 31 * w = Width (in pixels) of UI 32 * h = Height (in pixels) of UI 33 * filePath = Absolute file path to UI file 34 */ 35 this( uint w, uint h, string filePath ) 36 { 37 _scaleMat = mat4f.identity; 38 _scaleMat[0][0] = cast(float)w/2.0f; 39 _scaleMat[1][1] = cast(float)h/2.0f; 40 _height = h; 41 _width = w; 42 version(Windows) 43 { 44 _view = new AwesomiumView( w, h, filePath, null ); 45 } 46 tracef( "UI File: %s", filePath ); 47 } 48 49 /** 50 * Update UI view 51 */ 52 void update() 53 { 54 /// TODO: Check for mouse & keyboard input 55 version(Windows) 56 { 57 // Send mouse pos to awesomium 58 auto mousePos = Input.mousePos(); 59 awe_webview_inject_mouse_move( _view.webView, cast(int)mousePos.x,cast(int)( Graphics.height - mousePos.y ) ); 60 61 auto mouseUp = Mouse.isButtonUp(Mouse.Buttons.Left, true); 62 if( mouseUp ) awe_webview_inject_mouse_up( _view.webView, awe_mousebutton.AWE_MB_LEFT ); 63 64 _view.update(); 65 } 66 } 67 68 /** 69 * Cleanup UI memory 70 */ 71 void shutdown() 72 { 73 version(Windows) 74 // Try to clean up gl buffers 75 _view.shutdown(); 76 // Clean up mesh, material, and view 77 } 78 79 /* 80 * Call a JS Function on this UI 81 * 82 * Params: 83 * funcName = Name of the function to call 84 * args = Array of integer args to send to the function 85 * object = Name of the js object containing the function. Blank for global function. 86 */ 87 void callJSFunction( string funcName, int[] args, string object = "" ) 88 { 89 version(Windows) 90 { 91 // Convert params to awe_js objects 92 awe_string* funcStr = awe_string_create_from_ascii( funcName.toStringz(), funcName.length ); 93 awe_string* objectStr = awe_string_create_from_ascii( object.toStringz(), object.length ); 94 awe_string* frameStr = awe_string_create_from_ascii( "".toStringz(), 1 ); 95 96 // Build array of js ints 97 awe_jsvalue*[] jsArgs = new awe_jsvalue*[ args.length ]; 98 99 for( int i = 0; i < args.length; i++ ) 100 { 101 jsArgs[i] = awe_jsvalue_create_integer_value( args[i] ); 102 } 103 104 awe_jsarray* argArr = awe_jsarray_create( jsArgs.ptr, args.length ); 105 106 107 108 // Execute call 109 awe_webview_call_javascript_function( _view.webView, objectStr, funcStr, argArr, frameStr ); 110 111 112 // Clean up js objects 113 for( int i = 0; i < args.length; i++ ) 114 { 115 awe_jsvalue_destroy( jsArgs[i] ); 116 } 117 awe_jsarray_destroy( argArr ); 118 } 119 120 } 121 122 /** 123 * Initializes Awesomium singleton 124 */ 125 static void initializeAwesomium() 126 { 127 version( Windows ) 128 { 129 // Webcore setup 130 awe_webcore_initialize_default(); 131 string baseDir = Resources.UI; 132 awe_string* aweBaseDir = awe_string_create_from_ascii( baseDir.toStringz(), baseDir.length ); 133 awe_webcore_set_base_directory( aweBaseDir ); 134 awe_string_destroy( aweBaseDir ); 135 } 136 } 137 138 /** 139 * Updates Awesomium singleton 140 */ 141 static void updateAwesomium() 142 { 143 version( Windows ) 144 awe_webcore_update(); 145 } 146 147 /** 148 * Shutdowns Awesomium singleton 149 */ 150 static void shutdownAwesomium() 151 { 152 version( Windows ) 153 awe_webcore_shutdown(); 154 } 155 } 156 157 158 /** 159 * Creates an Awesomium web view texture 160 */ 161 class AwesomiumView : TextureAsset 162 { 163 private: 164 version( Windows ) 165 const(awe_renderbuffer)* renderBuffer; 166 167 public: 168 //package(dash): 169 version( Windows ) 170 awe_webview* webView; 171 ubyte[] glBuffer; 172 173 this( uint w, uint h, string filePath, GameObject owner, bool localFilePath = true ) 174 { 175 _width = w; 176 _height = h; 177 glBuffer = new ubyte[_width*_height*4]; 178 179 super( cast(ubyte*)null, internalResource ); 180 181 version( Windows ) 182 { 183 webView = awe_webcore_create_webview( _width, _height, false ); 184 webView.awe_webview_set_transparent( true ); 185 awe_string* urlString = awe_string_create_from_ascii( filePath.toStringz(), filePath.length ); 186 187 if ( localFilePath ) 188 webView.awe_webview_load_file( urlString, 189 awe_string_empty()); 190 else 191 webView.awe_webview_load_url( urlString, 192 awe_string_empty(), 193 awe_string_empty(), 194 awe_string_empty()); 195 196 // Wait for WebView to finish loading the page 197 // JK DON'T 198 //while(awe_webview_is_loading_page(cast(awe_webview*)webView)) 199 //awe_webcore_update(); 200 201 // Destroy our URL string 202 urlString.awe_string_destroy(); 203 } 204 } 205 206 override void update() 207 { 208 // No webview? No update. 209 version( Windows ) 210 if ( webView && webView.awe_webview_is_dirty() ) 211 { 212 renderBuffer = webView.awe_webview_render(); 213 214 // Ensure the buffer exists 215 if ( renderBuffer !is null ) { 216 217 renderBuffer.awe_renderbuffer_copy_to( glBuffer.ptr, awe_renderbuffer_get_rowspan( renderBuffer ), 4, false, true ); 218 219 updateBuffer( glBuffer.ptr ); 220 } 221 222 } 223 } 224 225 override void shutdown() 226 { 227 destroy( glBuffer ); 228 version( Windows ) 229 webView.awe_webview_destroy(); 230 } 231 }