1 /*---------------------------------------------------------------------------*
2 
3   Copyright (C) 2010-2012 Nintendo.  All rights reserved.
4 
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law.  They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10 
11  *---------------------------------------------------------------------------*/
12 
13 ////////////////////////////////////////////////////
14 //
15 // Combo Box functions
16 //
17 ////////////////////////////////////////////////////
18 
19     // The numbers 0 through 20, just for simplicity
20 SubComboBasic<10> basicNums[] = {"0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",  "8",  "9",
21                                  "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
22                                  "20"};
23 SubCombo* basicNumList[] = {&basicNums[0],  &basicNums[1],  &basicNums[2],  &basicNums[3],  &basicNums[4],  &basicNums[5],  &basicNums[6],  &basicNums[7],  &basicNums[8],  &basicNums[9],
24                             &basicNums[10], &basicNums[11], &basicNums[12], &basicNums[13], &basicNums[14], &basicNums[15], &basicNums[16], &basicNums[17], &basicNums[18], &basicNums[19],
25                             &basicNums[20]};
26 
Add(const ComboBox & item)27 ComboBox* ComboBox::Add(const ComboBox& item)
28 {
29     ASSERT(item.count > 0 && "Combo boxes cannot be empty!");
30 
31     ComboBox* pItem = new ComboBox(item);
32     item.window->menuItems.push_back(pItem);
33     item.window->AddTabbing(pItem);
34     return pItem;
35 }
36 
37 	// Determines if the cursor is over this combo box
CursorOver()38 bool ComboBox::CursorOver()
39 {
40 	if (CursorColliding(this->x, this->y, this->width, this->height))
41 		return true;
42 
43 ////////////////////////////////////////////////////////////////////////////////////////////////////
44 	if (this->status < 2)
45 		return false;
46 
47 	if (this->bar.status == 2)
48 		return true;
49 
50 	int visibleCount = this->count - this->bar.pos;
51 	if (visibleCount > COMBOBOX_COUNT)
52 		visibleCount = COMBOBOX_COUNT;
53 
54     if (this->flipped)
55     {
56         if (CursorColliding(this->x, this->y + this->height / 2 + this->height * visibleCount / 2, this->width, this->height * visibleCount, true))
57             return true;
58     }
59     else
60     {
61         if (CursorColliding(this->x, this->y - this->height / 2 - this->height * visibleCount / 2, this->width, this->height * visibleCount, true))
62             return true;
63     }
64 
65 	return false;
66 }
67 
68 	// Updates the combo box
Update()69 bool ComboBox::Update()
70 {
71 	this->over = -1;
72 
73 	if (NegativeTriggered())
74     {
75         TabSubIndex() = -1;
76 		this->status = 0;
77     }
78 
79     float flipMul = 1.0;
80     if (this->flipped)
81         flipMul = -1.0;
82 
83 	if (this->status == 2)
84 	{
85         gIgnoreBounds = true;
86         this->bar.x = this->x + size.x / 2 - SCROLLBAR_WIDTH / 2;
87         this->bar.y = this->y - this->height * 5.5;
88         this->bar.count = this->count;
89 		this->bar.Update();
90         gIgnoreBounds = false;
91 
92 		float widthOffset = 0;
93 
94 		int visibleCount = this->count - this->bar.pos;
95 		if (visibleCount > COMBOBOX_COUNT)
96 			visibleCount = COMBOBOX_COUNT;
97 
98 		if (this->count > COMBOBOX_COUNT)
99 			widthOffset = this->bar.width / 2;
100 
101 			// Activate tabbing if we're in PAD mode
102 		if (!TabIndex() && UsingPad())
103 		{
104             this->bar.Reset();
105 
106 			TabIndex() = window->DummyTab();
107 			TabSubIndex() = 0;
108 
109 			while (TabIndex()->object != this)
110 				TabIndex() = TabIndex()->next;
111 		}
112 
113 			// Combo boxes deal specially with tabbing
114 		if (TabIndex())
115 		{
116 				// Tabbed away from us!
117 			if (TabIndex()->object != this)
118 			{
119 				this->status = 0;
120 				return true;
121 			}
122 
123 				// Just started
124 			if (TabSubIndex() == -1)
125 				TabSubIndex() = 0;
126 
127             bool downTriggered = false;
128             bool upTriggered = false;
129 
130             if (this->flipped)
131             {
132                 downTriggered = UpTriggered();
133                 upTriggered = DownTriggered();
134             }
135             else
136             {
137                 downTriggered = DownTriggered();
138                 upTriggered = UpTriggered();
139             }
140 
141 			if (downTriggered)
142 			{
143 				TabSubIndex() ++;
144 				if (TabSubIndex() > visibleCount - 1)
145 				{
146 					TabSubIndex() = visibleCount - 1;
147 
148 					this->bar.pos ++;
149 
150 					if (this->bar.pos > this->count - COMBOBOX_COUNT)
151 						this->bar.pos --;
152 				}
153 			}
154 
155 			if (upTriggered)
156 			{
157 				TabSubIndex() --;
158 				if (TabSubIndex() < 0)
159 				{
160 					TabSubIndex() = 0;
161 
162 					this->bar.pos --;
163 
164 					if (this->bar.pos < 0)
165 						this->bar.pos ++;
166 				}
167 			}
168 
169 			CursorY() = window->GetY() + this->y - (this->height + this->height * TabSubIndex()) * flipMul;
170 			CursorX() = window->GetX() + this->x - widthOffset;
171 		}
172 
173 			// See if we're over one of the choices
174 		this->over = -1;
175 		if (CursorColliding(this->x - widthOffset, this->y - (this->height / 2 + this->height * visibleCount / 2) * flipMul, this->width - widthOffset * 2, this->height * visibleCount, true))
176 		{
177 			int choice = (window->GetY() + this->y - (this->height / 2) * flipMul - CursorY()) / this->height * flipMul;
178 
179 			if (choice < 0)
180 				choice = 0;
181 
182 				// We've found our choice!
183 			if (choice < visibleCount)
184 			{
185 				this->over = this->bar.pos + 0.5 + choice;
186 
187 				if (PositiveTriggered())
188 				{
189 					this->pos = this->bar.pos + 0.5 + choice;
190 					this->status = 0;
191                     int old = *target;
192                     *target = this->pos;
193 
194 					TabSubIndex() = -1;
195 
196                     if (old != *target)
197                         this->func(this->funcExtra);
198 
199 					return false;
200 				}
201 			}
202 		}
203 
204 		if (CursorColliding(this->x, this->y - (this->height / 2 + this->height * visibleCount / 2) * flipMul, this->width, this->height * visibleCount, true))
205             return false;
206 
207 		if (PositiveTriggered())
208 			this->status = 0;
209 
210         if (this->CursorOver())
211             return false;
212 
213 		return true;
214 	}
215 
216         // Keep us up to date in case something changes!
217     this->pos = *target;
218 
219     this->bar.Reset();
220 
221 	int status;
222 
223 		// We don't care as much if the cursor isn't being triggered
224 	if (PositiveTriggered())
225 		status = 2;
226 	else
227 		status = 1;
228 
229 		// See if we just hit something
230 	if (CursorColliding(this->x, this->y, this->width, this->height))
231 		this->status = status;
232 	else
233 		this->status = 0;
234 
235     return (this->status == 0);
236 }
237 
238 	// Draws the combo box
Draw()239 void ComboBox::Draw()
240 {
241     float arrowWidth = this->height;
242 
243         // The main box itself
244 	if (this->status == 1)
245 	{
246 		DrawBox(CVec3(this->x, this->y, this->z + 0.003), size, CVec4(0.13, 0.13, 0.13));
247 		DrawBox(CVec3(this->x + this->width / 2 - arrowWidth / 2, this->y, this->z + 0.0035), CVec2(arrowWidth, this->height), CVec4(0.1, 0.1, 0.1));
248 	}
249 	else
250 	{
251 		DrawBox(CVec3(this->x, this->y, this->z + 0.003), size, CVec4(0.03, 0.03, 0.03));
252 		DrawBox(CVec3(this->x + this->width / 2 - arrowWidth / 2, this->y, this->z + 0.0035), CVec2(arrowWidth, this->height), CVec4(0.0, 0.0, 0.0));
253 	}
254 
255         // The "selected" text
256 	DrawText(this->data[*this->target]->GetName(), CVec3(this->x - arrowWidth / 2, this->y, this->z + 0.0032), CVec2(this->width - arrowWidth, this->height * 0.7), CVec4(1.0, 1.0, 1.0));
257 
258         // The arrow on the right
259 	DrawTexQuad(*GetTexture(CW_TEXTURE_COMBODOWNARROW), CVec3(this->x + this->width / 2 - arrowWidth / 2, this->y, this->z + 0.005), CVec2(arrowWidth / 2, this->height / 2), CVec4(0.8, 0.8, 0.8));
260 
261 		// If the combo box is selected...
262 	if (this->status == 2)
263 	{
264 		int count = COMBOBOX_COUNT;
265 		if (count > this->count)
266 			count = this->count;
267 
268 		float widthOffset = 0;
269 
270 		if (this->count > COMBOBOX_COUNT)
271 			widthOffset = this->bar.width / 2;
272 
273         this->flipped = false;
274         if (window->GetY() + this->y - this->height / 2 - this->height * count < -1.0 && window->GetY() + this->y + this->height / 2 + this->height * count < 1.0)
275             this->flipped = true;
276 
277         float flipMul = 1.0;
278         if (this->flipped)
279             flipMul = -1.0;
280 
281             // Draw regardless of depth
282         GX2SetDepthOnlyControl(GX2_ENABLE,
283                                GX2_ENABLE,
284                                GX2_COMPARE_ALWAYS);
285 
286 		DrawBox(CVec3(this->x, this->y - (this->height / 2 + this->height * count / 2) * flipMul, this->z + 0.02), CVec2(this->width, this->height * count), CVec4(0.0, 0.0, 0.0));
287 
288             // Draw normally again
289         GX2SetDepthOnlyControl(GX2_ENABLE,
290                                GX2_ENABLE,
291                                GX2_COMPARE_LESS);
292 
293 
294 		int position = this->bar.pos + 0.5;
295 
296 		float startY = this->y - this->height * flipMul;
297 
298 			// Draw a "highlight" if a choice is over or selected
299 		if (this->over >= position && this->over < position + COMBOBOX_COUNT)
300 			//DrawQuad(this->x, startY, this->z + 0.0205, this->width, this->height, 0.2, 0.2, 0.2);
301 			DrawQuad(CVec3(this->x - widthOffset, startY - (this->over - position) * this->height * flipMul, this->z + 0.0205), CVec2(this->width - widthOffset * 2, this->height), CVec4(0.2, 0.2, 0.2));
302 
303 		if (count > position + COMBOBOX_COUNT)
304 			count = position + COMBOBOX_COUNT;
305 
306 			// Draw only the elements we want to see!
307 		for (int i = 0; i < count; ++i)
308 		{
309 			DrawText(this->data[i + position]->GetName(), CVec3(this->x - this->bar.width / 2, startY, this->z + 0.021), CVec2(this->width - this->bar.width, this->height * 0.7), CVec4(1.0, 1.0, 1.0));
310 
311 			startY -= this->height * flipMul;
312 		}
313 
314         this->bar.count = this->count;
315         this->bar.x = this->x + size.x / 2 - SCROLLBAR_WIDTH / 2;
316         this->bar.y = this->y - this->height * 5.5 * flipMul;
317 		this->bar.Draw();
318 	}
319 }
320 
Reset()321 void ComboBox::Reset()
322 {
323     if (this->status > 0)
324         this->status = 0;
325 	this->bar.Reset();
326 }
327