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 // If this version is enabled, you could press ENTER to 81 // reload the backgrounds. Do not ship this! 82 version(Dplug_EnterReloadBackgrounds) 83 { 84 override bool onKeyDown(Key key) 85 { 86 if (super.onKeyDown(key)) 87 return true; 88 89 if (key == Key.enter) 90 { 91 reloadImageAtRuntime(); 92 return true; 93 } 94 95 return false; 96 } 97 } 98 99 private: 100 OwnedImage!RGBA _backgroundImage, _backgroundImageResized; 101 102 /// Where pixel data is taken in the image, expressed in _background coordinates. 103 box2i _sourceRect; 104 105 /// Where it is deposited. Same size than _sourceRect. Expressed in _position coordinates. 106 box2i _destRect; 107 108 /// Offset from source to dest. 109 vec2i _offset; 110 111 /// Force resize of source image in order to display changes while editing files. 112 bool _forceResizeUpdate; 113 114 static immutable string backgroundPathAbs = absoluteGfxDirectory ~ backgroundPath; 115 116 final void loadBackgroundImageFromStaticData() 117 { 118 auto backgroundData = cast(ubyte[])(import(backgroundPath)); 119 loadBackgroundImage(backgroundData); 120 } 121 122 // Reloads image for UI development. 123 final void reloadImageAtRuntime() 124 { 125 // reading images with an absolute path since we don't know 126 // which is the current directory from the host 127 ubyte[] backgroundData = readFile(backgroundPathAbs); 128 129 if (backgroundData) 130 { 131 // Reload images from disk and update the UI 132 freeBackgroundImage(); 133 loadBackgroundImage(backgroundData); 134 _forceResizeUpdate = true; 135 setDirtyWhole(); 136 } 137 else 138 { 139 // Note: if you fail here, the absolute path you provided in your gui.d was incorrect. 140 // The background files cannot be loaded at runtime, and you have to fix your pathes. 141 assert(false); 142 } 143 144 freeSlice(backgroundData); 145 } 146 147 final void loadBackgroundImage(ubyte[] backgroundData) 148 { 149 _backgroundImage = loadOwnedImage(backgroundData); 150 } 151 152 void freeBackgroundImage() 153 { 154 if (_backgroundImage) 155 { 156 _backgroundImage.destroyFree(); 157 _backgroundImage = null; 158 } 159 } 160 }