1 /** 2 Clickable Logo. 3 4 Copyright: Copyright Auburn Sounds 2015-2017. 5 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 6 Authors: Guillaume Piolat 7 */ 8 module dplug.pbrwidgets.logo; 9 10 import std.math: exp, abs; 11 import dplug.gui.element; 12 import dplug.core.math; 13 import dplug.graphics; 14 import dplug.graphics.resizer; 15 16 class UILogo : UIElement 17 { 18 public: 19 nothrow: 20 @nogc: 21 22 /// Change this to point to your website 23 string targetURL = "http://example.com"; 24 25 @ScriptProperty float animationTimeConstant = 30.0f; 26 27 @ScriptProperty ubyte defaultEmissive = 0; // emissive where the logo isn't 28 29 // these are offset on top of defaultEmissive 30 @ScriptProperty ubyte emissiveOn = 40; 31 @ScriptProperty ubyte emissiveOff = 0; 32 33 /// Note: once called, the logo now own the diffuse image, and will destroy it. 34 this(UIContext context, OwnedImage!RGBA diffuseImage) 35 { 36 super(context, flagAnimated | flagPBR); 37 _diffuseImage = diffuseImage; 38 _animation = 0; 39 40 _diffuseImageResized = mallocNew!(OwnedImage!RGBA); 41 } 42 43 ~this() 44 { 45 if (_diffuseImage !is null) 46 { 47 destroyFree(_diffuseImage); 48 _diffuseImage = null; 49 } 50 if (_diffuseImageResized !is null) 51 { 52 destroyFree(_diffuseImageResized); 53 _diffuseImageResized = null; 54 } 55 } 56 57 override void reflow() 58 { 59 _diffuseImageResized.size(position.width, position.height); 60 ImageResizer* resizer = context.globalImageResizer; 61 resizer.resizeImageDiffuse(_diffuseImage.toRef(), _diffuseImageResized.toRef()); 62 } 63 64 override void onAnimate(double dt, double time) nothrow @nogc 65 { 66 float target = ( isDragged() || isMouseOver() ) ? 1 : 0; 67 68 float newAnimation = lerp(_animation, target, 1.0 - exp(-dt * animationTimeConstant)); 69 70 if (abs(newAnimation - _animation) > 0.001f) 71 { 72 _animation = newAnimation; 73 setDirtyWhole(); 74 } 75 } 76 77 override void onDrawPBR(ImageRef!RGBA diffuseMap, ImageRef!L16 depthMap, ImageRef!RGBA materialMap, box2i[] dirtyRects) nothrow @nogc 78 { 79 foreach(dirtyRect; dirtyRects) 80 { 81 ImageRef!RGBA croppedDiffuseIn = _diffuseImageResized.toRef().cropImageRef(dirtyRect); 82 ImageRef!RGBA croppedDiffuseOut = diffuseMap.cropImageRef(dirtyRect); 83 84 int w = dirtyRect.width; 85 int h = dirtyRect.height; 86 87 ubyte emissive = cast(ubyte)(0.5f + lerp!float(emissiveOff, emissiveOn, _animation)); 88 89 for(int j = 0; j < h; ++j) 90 { 91 RGBA[] input = croppedDiffuseIn.scanline(j); 92 RGBA[] output = croppedDiffuseOut.scanline(j); 93 94 for(int i = 0; i < w; ++i) 95 { 96 ubyte alpha = input[i].a; 97 RGBA color = blendColor(input[i], output[i], alpha); 98 99 // emissive has to be multiplied by alpha, and added to the default background emissive 100 color.a = cast(ubyte)( (128 + defaultEmissive * 256 + (emissive * color.a) ) >> 8); 101 output[i] = color; 102 } 103 } 104 } 105 } 106 107 override Click onMouseClick(int x, int y, int button, bool isDoubleClick, MouseState mstate) 108 { 109 browseNoGC(targetURL); 110 return Click.startDrag; 111 } 112 113 private: 114 float _animation; 115 OwnedImage!RGBA _diffuseImage; 116 OwnedImage!RGBA _diffuseImageResized; 117 }