1 /**
2 Grimoire
3 Copyright (c) 2017 Enalye
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising
7 from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute
11 it freely, subject to the following restrictions:
12 
13 	1. The origin of this software must not be misrepresented;
14 	   you must not claim that you wrote the original software.
15 	   If you use this software in a product, an acknowledgment
16 	   in the product documentation would be appreciated but
17 	   is not required.
18 
19 	2. Altered source versions must be plainly marked as such,
20 	   and must not be misrepresented as being the original software.
21 
22 	3. This notice may not be removed or altered from any source distribution.
23 */
24 
25 module ui.overlay;
26 
27 import std.algorithm.comparison: max;
28 
29 import core.all;
30 import render.all;
31 import common.all;
32 
33 import ui.widget;
34 import ui.label;
35 import ui.text;
36 
37 private {
38 	HintWindow _hintWindow;
39 	Hint _displayedHint;
40 	Widget[] _widgetsBackup;
41 	Widget[] _overlayWidgets;
42 	bool _isOverlay = false;
43 }
44 
45 Hint makeHint(string title, string text) {
46 	return new Hint(title, text);
47 }
48 
49 class Hint {
50 	string title, text;
51 
52 	this(string newTitle, string newText) {
53 		title = newTitle;
54 		text = newText;
55 	}
56 }
57 
58 void openHintWindow(Hint hint) {
59 	_displayedHint = hint;
60 }
61 
62 void initializeOverlay() {
63 	_hintWindow = new HintWindow;
64 	_displayedHint = null;
65 }
66 
67 bool isOverlay() {
68 	return _isOverlay;
69 }
70 
71 void setOverlay(Widget widget) {
72 	if(!_isOverlay) {
73 		_isOverlay = true;
74 		_widgetsBackup = getWidgets();
75 		removeWidgets();
76 	}
77 
78 	_overlayWidgets ~= widget;
79 	addWidget(widget);
80 }
81 
82 void stopOverlay() {
83 	if(!_isOverlay)
84 		throw new Exception("No overlay to stop");
85 	_isOverlay = false;
86 	setWidgets(_widgetsBackup);
87 	_widgetsBackup.length = 0L;
88 	_overlayWidgets.length = 0L;
89 }
90 
91 void processOverlayEvent(Event event) {
92 	if(event.type == EventType.Quit) {
93 		foreach(widget; _widgetsBackup)
94 			widget.onEvent(event);
95 	}
96 	foreach(widget; _overlayWidgets) {
97 		widget.isHovered = true;
98 		widget.hasFocus = true;
99 		widget.onEvent(event);
100 	}
101 }
102 
103 void processOverlayBack(float deltaTime) {
104 	foreach(widget; _widgetsBackup) {
105 		widget.update(deltaTime);	
106 		widget.draw();
107 	}
108 }
109 
110 void processOverlayFront(float deltaTime) {
111 	_hintWindow.hint = _displayedHint;
112 	_hintWindow.update(deltaTime);
113 	_hintWindow.draw();
114 }
115 
116 void endOverlay() {
117 	_displayedHint = null;
118 }
119 
120 private class HintWindow: Widget {
121 	private {
122 		bool _isRendered;
123 	}
124 	Label title;
125 	Text text;
126 
127 	@property void hint(Hint hint) {
128 		_isRendered = hint !is null;
129 		if(_isRendered) {
130 			title.text = hint.title;
131 			text.text = hint.text;
132 		}
133 	}
134 
135 	this() {
136 		title = new Label;
137 		text = new Text;
138 	}
139 
140 	override void onEvent(Event event) {}
141 
142 	override void update(float deltaTime) {
143 		if(!_isRendered)
144 			return;
145 		_size = Vec2f(max(title.size.x, text.size.x) + 25f, title.size.y + text.size.y);
146 		_position = getMousePos() + _size / 2f + Vec2f(20f, 10f);
147 		title.position = _position + Vec2f(0f, (title.size.y - _size.y) / 2f);
148 		text.position = _position + Vec2f(0f, title.size.y + (text.size.y - _size.y) / 2f);
149 	}
150 
151 	override void draw() {
152 		if(!_isRendered)
153 			return;
154 		drawFilledRect(_position - _size / 2f, _size, Color.white * .21f);
155 		drawFilledRect(_position - _size / 2f, Vec2f(_size.x, title.size.y), Color.white * .11f);
156 		title.draw();
157 		text.draw();
158 	}
159 }