1 /** 2 Copyright: Guillaume Piolat 2015-2017. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 4 */ 5 module gui; 6 7 import core.stdc.stdlib; 8 9 import std.math; 10 11 import dplug.core; 12 import dplug.math; 13 import dplug.gui; 14 import dplug.pbrwidgets; 15 import dplug.client; 16 import dplug.flatwidgets; 17 import dplug.wren; 18 import leveldisplay; 19 import main; 20 21 //debug = voxelExport; 22 23 // Plugin GUI, based on PBRBackgroundGUI. 24 // If you don't want to use PBR, you not inherit from it. 25 class DistortGUI : PBRBackgroundGUI!("basecolor.jpg", "emissive.png", "material.png", 26 "depth.png", "skybox.jpg", 27 28 // In development, enter here the absolute path to the gfx directory. 29 // This allows to reload background images at debug-time with the press of ENTER. 30 `/home/myuser/my/path/to/Dplug/examples/distort/gfx/`) 31 { 32 public: 33 nothrow: 34 @nogc: 35 36 this(DistortClient client) 37 { 38 _client = client; 39 40 static immutable float[7] ratios = [0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f]; 41 super( makeSizeConstraintsDiscrete(620, 330, ratios) ); 42 43 // Note: PBRCompositor default lighting might change in a future version (increase of light to allow white plastics). 44 // So we keep the value. 45 PBRCompositor comp = cast(PBRCompositor)compositor; 46 comp.light1Color = vec3f(0.26, 0.24, 0.22f) * 0.98f; 47 comp.light2Dir = vec3f(-0.5f, 1.0f, 0.23f).normalized; 48 comp.light2Color = vec3f(0.36, 0.38f, 0.40) * 1.148; 49 comp.light3Dir = vec3f(0.0f, 1.0f, 0.1f).normalized; 50 comp.light3Color = vec3f(0.2f, 0.2f, 0.2f) * 0.84f; 51 comp.ambientLight = 0.042f; 52 comp.skyboxAmount = 0.56f; 53 54 // Sets the number of pixels recomputed around dirtied controls. 55 // This is a tradeoff between Emissive light accuracy and speed. 56 // This needs to be adjusted visually. 57 setUpdateMargin(30); 58 59 // All resources are bundled as a string import. 60 // You can avoid resource compilers that way. 61 // The only cost is that each resource is in each binary, this creates overhead with 62 _font = mallocNew!Font(cast(ubyte[])( import("VeraBd.ttf") )); 63 64 // Builds the UI hierarchy 65 // Meanwhile, we hardcode each position. 66 67 _knobImageData = loadKnobImage( import("imageknob.png") ); 68 addChild(_imageKnob = mallocNew!UIImageKnob(context(), _knobImageData, cast(FloatParameter) _client.param(paramBias))); 69 70 // Add procedural knobs 71 addChild(_driveKnob = mallocNew!UIKnob(context(), cast(FloatParameter) _client.param(paramDrive))); 72 73 // Add sliders 74 addChild(_inputSlider = mallocNew!UISlider(context(), cast(FloatParameter) _client.param(paramInput))); 75 76 addChild(_outputSlider = mallocNew!UISlider(context(), cast(FloatParameter) _client.param(paramOutput))); 77 78 // Add switch 79 addChild(_onOffSwitch = mallocNew!UIOnOffSwitch(context(), cast(BoolParameter) _client.param(paramOnOff))); 80 81 82 // Add bargraphs 83 addChild(_inputLevel = mallocNew!UILevelDisplay(context())); 84 addChild(_outputLevel = mallocNew!UILevelDisplay(context())); 85 86 // Add resizer corner 87 addChild(_resizer = mallocNew!UIWindowResizer(context())); 88 89 // Global color correction. 90 // Very useful at the end of the UI creating process. 91 // As the sole Raw-only widget it is always on top and doesn't need zOrder adjustment. 92 { 93 mat3x4!float colorCorrectionMatrix = mat3x4!float(- 0.07f, 1.0f , 1.15f, 0.03f, 94 + 0.01f, 0.93f, 1.16f, 0.08f, 95 + 0.0f , 1.0f , 1.10f, -0.01f); 96 addChild(_colorCorrection = mallocNew!UIColorCorrection(context())); 97 _colorCorrection.setLiftGammaGainContrastRGB(colorCorrectionMatrix); 98 } 99 100 // Enable all things Wren 101 mixin(fieldIdentifiersAreIDs!DistortGUI); // Each UIElement in this object receives its identifier as runtime ID, ie. _inputSlider receives ID "_inputSlider" 102 context.enableWrenSupport(); 103 //debug 104 // context.wrenSupport.addModuleFileWatch("plugin", `/my/absolute/path/to/plugin.wren`); // debug => live reload, enter absolute path here 105 //else 106 context.wrenSupport.addModuleSource("plugin", import("plugin.wren")); // no debug => static scripts 107 context.wrenSupport.registerScriptExports!DistortGUI; // Note: for now, only UIElement should be @ScriptExport 108 context.wrenSupport.callCreateUI(); 109 110 debug(voxelExport) 111 context.requestUIScreenshot(); // onScreenshot will be called at next render, can be called from anywhere 112 } 113 114 override void onAnimate(double dt, double time) 115 { 116 context.wrenSupport.callReflowWhenScriptsChange(dt); 117 } 118 119 ~this() 120 { 121 // Note: UI widgets are owned by the UI and don't need to be destroyed manually 122 // However some of the resources they consumed aren't owned by them, but borrowed. 123 _font.destroyFree(); 124 _knobImageData.destroyFree(); 125 context.disableWrenSupport(); 126 127 version(Dplug_ProfileUI) 128 { 129 writeFile(`/home/myuser/plugin-trace.json`, context.profiler.toBytes()); 130 browseNoGC("https://ui.perfetto.dev/"); // A webtool to read that trace 131 } 132 } 133 134 override void reflow() 135 { 136 super.reflow(); 137 context.wrenSupport.callReflow(); 138 } 139 140 void sendFeedbackToUI(float* inputRMS, float* outputRMS, int frames, float sampleRate) 141 { 142 _inputLevel.sendFeedbackToUI(inputRMS, frames, sampleRate); 143 _outputLevel.sendFeedbackToUI(outputRMS, frames, sampleRate); 144 } 145 146 debug(voxelExport) 147 { 148 // Show how to do a .qb export of final PBR render 149 override void onScreenshot(ImageRef!RGBA finalRender, 150 WindowPixelFormat pixelFormat, 151 ImageRef!RGBA diffuseMap, 152 ImageRef!L16 depthMap, 153 ImageRef!RGBA materialMap) 154 { 155 ubyte[] qb = encodeScreenshotAsQB(finalRender, pixelFormat, depthMap); // alternatively: encodeScreenshotAsPNG 156 if (qb) 157 { 158 writeFile(`/my/path/to/distort.qb`, qb); 159 free(qb.ptr); 160 } 161 } 162 } 163 164 private: 165 DistortClient _client; 166 167 // Resources 168 Font _font; 169 KnobImage _knobImageData; 170 171 // Widgets can be exported to Wren. This allow styling through a plugin.wren script. 172 @ScriptExport 173 { 174 UISlider _inputSlider; 175 UIKnob _driveKnob; 176 UISlider _outputSlider; 177 UIOnOffSwitch _onOffSwitch; 178 UILevelDisplay _inputLevel, _outputLevel; 179 UIColorCorrection _colorCorrection; 180 UIImageKnob _imageKnob; 181 UIWindowResizer _resizer; 182 } 183 } 184