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