1 /** 2 * Copyright: Copyright Auburn Sounds 2015 and later. 3 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 4 * Authors: Guillaume Piolat 5 */ 6 module dplug.gui.onoffswitch; 7 8 import std.math; 9 import dplug.core.math; 10 import dplug.graphics.drawex; 11 import dplug.gui.element; 12 import dplug.client.params; 13 14 class UIOnOffSwitch : UIElement, IParameterListener 15 { 16 public: 17 nothrow: 18 @nogc: 19 20 enum Orientation 21 { 22 vertical, 23 horizontal 24 } 25 26 RGBA diffuseOff = RGBA(230, 80, 43, 0); 27 RGBA diffuseOn = RGBA(230, 80, 43, 200); 28 RGBA material = RGBA(192, 10, 128, 255); 29 float animationTimeConstant = 10.0f; 30 ushort depthLow = 0; 31 ushort depthHigh = 30000; 32 ushort holeDepth = 0; 33 34 Orientation orientation = Orientation.vertical; 35 36 this(UIContext context, BoolParameter param) 37 { 38 super(context); 39 _param = param; 40 _param.addListener(this); 41 _animation = 0.0f; 42 } 43 44 ~this() 45 { 46 _param.removeListener(this); 47 } 48 49 override void onAnimate(double dt, double time) nothrow @nogc 50 { 51 float target = _param.valueAtomic() ? 1 : 0; 52 53 float newAnimation = lerp(_animation, target, 1.0 - exp(-dt * animationTimeConstant)); 54 55 if (abs(newAnimation - _animation) > 0.001f) 56 { 57 _animation = newAnimation; 58 setDirtyWhole(); 59 } 60 } 61 62 override void onDraw(ImageRef!RGBA diffuseMap, ImageRef!L16 depthMap, ImageRef!RGBA materialMap, box2i[] dirtyRects) nothrow @nogc 63 { 64 // dig a hole 65 depthMap.fill(L16(holeDepth)); 66 67 // The switch is in a subrect 68 int width = _position.width; 69 int height = _position.height; 70 float border = 0.1f; 71 box2i switchRect = box2i( cast(int)(0.5f + width * border), 72 cast(int)(0.5f + height * border), 73 cast(int)(0.5f + width * (1 - border)), 74 cast(int)(0.5f + height * (1 - border)) ); 75 76 ubyte red = cast(ubyte)(lerp!float(diffuseOff.r, diffuseOn.r, _animation)); 77 ubyte green = cast(ubyte)(lerp!float(diffuseOff.g, diffuseOn.g, _animation)); 78 ubyte blue = cast(ubyte)(lerp!float(diffuseOff.b, diffuseOn.b, _animation)); 79 int emissive = cast(ubyte)(lerp!float(diffuseOff.a, diffuseOn.a, _animation)); 80 81 if (isMouseOver || isDragged) 82 emissive += 40; 83 84 if (emissive > 255) 85 emissive = 255; 86 87 RGBA diffuseColor = RGBA(red, green, blue, cast(ubyte)emissive); 88 89 diffuseMap.crop(switchRect).fill(diffuseColor); 90 91 L16 depthA = L16(cast(short)(lerp!float(depthHigh, depthLow, _animation))); 92 L16 depthB = L16(cast(short)(lerp!float(depthLow, depthHigh, _animation))); 93 94 if (orientation == Orientation.vertical) 95 verticalSlope(depthMap, switchRect, depthA, depthB); 96 else 97 horizontalSlope(depthMap, switchRect, depthA, depthB); 98 99 materialMap.crop(switchRect).fill(material); 100 } 101 102 override bool onMouseClick(int x, int y, int button, bool isDoubleClick, MouseState mstate) 103 { 104 // double-click => set to default 105 _param.beginParamEdit(); 106 _param.setFromGUI(!_param.value()); 107 _param.endParamEdit(); 108 return true; 109 } 110 111 override void onMouseEnter() 112 { 113 setDirtyWhole(); 114 } 115 116 override void onMouseExit() 117 { 118 setDirtyWhole(); 119 } 120 121 override void onParameterChanged(Parameter sender) nothrow @nogc 122 { 123 setDirtyWhole(); 124 } 125 126 override void onBeginParameterEdit(Parameter sender) 127 { 128 } 129 130 override void onEndParameterEdit(Parameter sender) 131 { 132 } 133 134 protected: 135 136 /// The parameter this switch is linked with. 137 BoolParameter _param; 138 139 private: 140 float _animation; 141 }