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.logo;
7 
8 import std.math;
9 import dplug.gui.element;
10 import dplug.core.math;
11 
12 class UILogo : UIElement
13 {
14 public:
15 nothrow:
16 @nogc:
17 
18     /// Change this to point to your website
19     string targetURL = "http://example.com";
20     float animationTimeConstant = 30.0f;
21     ubyte defaultEmissive = 0; // emissive where the logo isn't
22 
23     // these are offset on top of defaultEmissive
24     ubyte emissiveOn = 40;
25     ubyte emissiveOff = 0;
26 
27     /// Note: once called, the logo now own the diffuse image, and will destroy it.
28     this(UIContext context, OwnedImage!RGBA diffuseImage)
29     {
30         super(context);
31         _diffuseImage = diffuseImage;
32         _animation = 0;
33     }
34 
35     ~this()
36     {
37         _diffuseImage.destroyNoGC();
38     }
39 
40     override void onAnimate(double dt, double time) nothrow @nogc
41     {
42         float target = ( isDragged() || isMouseOver() ) ? 1 : 0;
43 
44         float newAnimation = lerp(_animation, target, 1.0 - exp(-dt * animationTimeConstant));
45 
46         if (abs(newAnimation - _animation) > 0.001f)
47         {
48             _animation = newAnimation;
49             setDirtyWhole();
50         }
51     }
52 
53     override void onDraw(ImageRef!RGBA diffuseMap, ImageRef!L16 depthMap, ImageRef!RGBA materialMap, box2i[] dirtyRects) nothrow @nogc
54     {
55         foreach(dirtyRect; dirtyRects)
56         {
57             auto croppedDiffuseIn = _diffuseImage.crop(dirtyRect);
58             auto croppedDiffuseOut = diffuseMap.crop(dirtyRect);
59 
60             int w = dirtyRect.width;
61             int h = dirtyRect.height;
62 
63             ubyte emissive = cast(ubyte)(0.5f + lerp!float(emissiveOff, emissiveOn, _animation));
64 
65             for(int j = 0; j < h; ++j)
66             {
67                 RGBA[] input = croppedDiffuseIn.scanline(j);
68                 RGBA[] output = croppedDiffuseOut.scanline(j);
69 
70                 for(int i = 0; i < w; ++i)
71                 {
72                     ubyte alpha = input[i].a;
73                     RGBA color = RGBA.op!q{.blend(a, b, c)}(input[i], output[i], alpha);
74 
75                     // emissive has to be multiplied by alpha, and added to the default background emissive
76                     color.a = cast(ubyte)( (128 + defaultEmissive * 256 + (emissive * color.a) ) >> 8);
77                     output[i] = color;
78                 }
79             }
80         }
81     }
82 
83     override bool onMouseClick(int x, int y, int button, bool isDoubleClick, MouseState mstate)
84     {
85         browseNoGC(targetURL);
86         return true;
87     }
88 
89 private:
90     float _animation;
91     OwnedImage!RGBA _diffuseImage;
92 }