1 /** 2 The root widget to inherit from for a flat UI. 3 4 Copyright: Guillaume Piolat 2015-2018. 5 Copyright: Ethan Reker 2017. 6 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 */ 8 module dplug.flatwidgets.flatbackgroundgui; 9 10 import dplug.math.box; 11 import dplug.core.nogc; 12 import dplug.core.file; 13 import dplug.graphics; 14 15 import dplug.core.nogc; 16 import dplug.gui.graphics; 17 import dplug.gui.element; 18 public import dplug.gui.sizeconstraints; 19 20 21 /// FlatBackgroundGUI provides a background that is loaded from a PNG or JPEG 22 /// image. The string for backgroundPath should be in "stringImportPaths" 23 /// specified in dub.json 24 class FlatBackgroundGUI(string backgroundPath, 25 string absoluteGfxDirectory = null // for UI development only 26 ) : GUIGraphics 27 { 28 public: 29 nothrow: 30 @nogc: 31 32 this(int width, int height) 33 { 34 this(makeSizeConstraintsFixed(width, height)); 35 } 36 37 this(SizeConstraints sizeConstraints) 38 { 39 super(sizeConstraints, flagRaw | flagAnimated); 40 _backgroundImageResized = mallocNew!(OwnedImage!RGBA)(); 41 loadBackgroundImageFromStaticData(); 42 } 43 44 ~this() 45 { 46 freeBackgroundImage(); 47 _backgroundImageResized.destroyFree(); 48 } 49 50 override void reflow() 51 { 52 } 53 54 override void onDrawRaw(ImageRef!RGBA rawMap, box2i[] dirtyRects) 55 { 56 // Resize resources to match actual size. 57 { 58 int W = position.width; 59 int H = position.height; 60 if (_forceResizeUpdate || _backgroundImageResized.w != W || _backgroundImageResized.h != H) 61 { 62 _backgroundImageResized.size(W, H); 63 ImageResizer resizer; 64 resizer.resizeImage_sRGBNoAlpha(_backgroundImage.toRef, _backgroundImageResized.toRef); 65 _forceResizeUpdate = false; 66 } 67 } 68 69 ImageRef!RGBA backgroundRef = _backgroundImageResized.toRef(); 70 71 foreach(dirtyRect; dirtyRects) 72 { 73 ImageRef!RGBA croppedRawIn = backgroundRef.cropImageRef(dirtyRect); 74 ImageRef!RGBA croppedRawOut = rawMap.cropImageRef(dirtyRect); 75 croppedRawIn.blitTo(croppedRawOut); 76 } 77 } 78 79 // Development purposes. 80 // In debug mode, pressing ENTER reload the backgrounds 81 debug 82 { 83 override bool onKeyDown(Key key) 84 { 85 if (super.onKeyDown(key)) 86 return true; 87 88 if (key == Key.enter) 89 { 90 reloadImageAtRuntime(); 91 return true; 92 } 93 94 return false; 95 } 96 } 97 98 private: 99 OwnedImage!RGBA _backgroundImage, _backgroundImageResized; 100 101 /// Where pixel data is taken in the image, expressed in _background coordinates. 102 box2i _sourceRect; 103 104 /// Where it is deposited. Same size than _sourceRect. Expressed in _position coordinates. 105 box2i _destRect; 106 107 /// Offset from source to dest. 108 vec2i _offset; 109 110 /// Force resize of source image in order to display changes while editing files. 111 bool _forceResizeUpdate; 112 113 static immutable string backgroundPathAbs = absoluteGfxDirectory ~ backgroundPath; 114 115 final void loadBackgroundImageFromStaticData() 116 { 117 auto backgroundData = cast(ubyte[])(import(backgroundPath)); 118 loadBackgroundImage(backgroundData); 119 } 120 121 // Reloads image for UI development. 122 final void reloadImageAtRuntime() 123 { 124 // reading images with an absolute path since we don't know 125 // which is the current directory from the host 126 ubyte[] backgroundData = readFile(backgroundPathAbs); 127 128 if (backgroundData) 129 { 130 // Reload images from disk and update the UI 131 freeBackgroundImage(); 132 loadBackgroundImage(backgroundData); 133 _forceResizeUpdate = true; 134 setDirtyWhole(); 135 } 136 else 137 { 138 // Note: if you fail here, the absolute path you provided in your gui.d was incorrect. 139 // The background files cannot be loaded at runtime, and you have to fix your pathes. 140 assert(false); 141 } 142 143 freeSlice(backgroundData); 144 } 145 146 final void loadBackgroundImage(ubyte[] backgroundData) 147 { 148 _backgroundImage = loadOwnedImage(backgroundData); 149 } 150 151 void freeBackgroundImage() 152 { 153 if (_backgroundImage) 154 { 155 _backgroundImage.destroyFree(); 156 _backgroundImage = null; 157 } 158 } 159 }