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 }