1 /*---------------------------------------------------------------------------*
2
3 Copyright (C) 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