/*---------------------------------------------------------------------------* Copyright (C) Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ //////////////////////////////////////////////////// // // Combo Box functions // //////////////////////////////////////////////////// // The numbers 0 through 20, just for simplicity SubComboBasic<10> basicNums[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"}; SubCombo* basicNumList[] = {&basicNums[0], &basicNums[1], &basicNums[2], &basicNums[3], &basicNums[4], &basicNums[5], &basicNums[6], &basicNums[7], &basicNums[8], &basicNums[9], &basicNums[10], &basicNums[11], &basicNums[12], &basicNums[13], &basicNums[14], &basicNums[15], &basicNums[16], &basicNums[17], &basicNums[18], &basicNums[19], &basicNums[20]}; ComboBox* ComboBox::Add(const ComboBox& item) { ASSERT(item.count > 0 && "Combo boxes cannot be empty!"); ComboBox* pItem = new ComboBox(item); item.window->menuItems.push_back(pItem); item.window->AddTabbing(pItem); return pItem; } // Determines if the cursor is over this combo box bool ComboBox::CursorOver() { if (CursorColliding(this->x, this->y, this->width, this->height)) return true; //////////////////////////////////////////////////////////////////////////////////////////////////// if (this->status < 2) return false; if (this->bar.status == 2) return true; int visibleCount = this->count - this->bar.pos; if (visibleCount > COMBOBOX_COUNT) visibleCount = COMBOBOX_COUNT; if (this->flipped) { if (CursorColliding(this->x, this->y + this->height / 2 + this->height * visibleCount / 2, this->width, this->height * visibleCount, true)) return true; } else { if (CursorColliding(this->x, this->y - this->height / 2 - this->height * visibleCount / 2, this->width, this->height * visibleCount, true)) return true; } return false; } // Updates the combo box bool ComboBox::Update() { this->over = -1; if (NegativeTriggered()) { TabSubIndex() = -1; this->status = 0; } float flipMul = 1.0; if (this->flipped) flipMul = -1.0; if (this->status == 2) { gIgnoreBounds = true; this->bar.x = this->x + size.x / 2 - SCROLLBAR_WIDTH / 2; this->bar.y = this->y - this->height * 5.5; this->bar.count = this->count; this->bar.Update(); gIgnoreBounds = false; float widthOffset = 0; int visibleCount = this->count - this->bar.pos; if (visibleCount > COMBOBOX_COUNT) visibleCount = COMBOBOX_COUNT; if (this->count > COMBOBOX_COUNT) widthOffset = this->bar.width / 2; // Activate tabbing if we're in PAD mode if (!TabIndex() && UsingPad()) { this->bar.Reset(); TabIndex() = window->DummyTab(); TabSubIndex() = 0; while (TabIndex()->object != this) TabIndex() = TabIndex()->next; } // Combo boxes deal specially with tabbing if (TabIndex()) { // Tabbed away from us! if (TabIndex()->object != this) { this->status = 0; return true; } // Just started if (TabSubIndex() == -1) TabSubIndex() = 0; bool downTriggered = false; bool upTriggered = false; if (this->flipped) { downTriggered = UpTriggered(); upTriggered = DownTriggered(); } else { downTriggered = DownTriggered(); upTriggered = UpTriggered(); } if (downTriggered) { TabSubIndex() ++; if (TabSubIndex() > visibleCount - 1) { TabSubIndex() = visibleCount - 1; this->bar.pos ++; if (this->bar.pos > this->count - COMBOBOX_COUNT) this->bar.pos --; } } if (upTriggered) { TabSubIndex() --; if (TabSubIndex() < 0) { TabSubIndex() = 0; this->bar.pos --; if (this->bar.pos < 0) this->bar.pos ++; } } CursorY() = window->GetY() + this->y - (this->height + this->height * TabSubIndex()) * flipMul; CursorX() = window->GetX() + this->x - widthOffset; } // See if we're over one of the choices this->over = -1; if (CursorColliding(this->x - widthOffset, this->y - (this->height / 2 + this->height * visibleCount / 2) * flipMul, this->width - widthOffset * 2, this->height * visibleCount, true)) { int choice = (window->GetY() + this->y - (this->height / 2) * flipMul - CursorY()) / this->height * flipMul; if (choice < 0) choice = 0; // We've found our choice! if (choice < visibleCount) { this->over = this->bar.pos + 0.5 + choice; if (PositiveTriggered()) { this->pos = this->bar.pos + 0.5 + choice; this->status = 0; int old = *target; *target = this->pos; TabSubIndex() = -1; if (old != *target) this->func(this->funcExtra); return false; } } } if (CursorColliding(this->x, this->y - (this->height / 2 + this->height * visibleCount / 2) * flipMul, this->width, this->height * visibleCount, true)) return false; if (PositiveTriggered()) this->status = 0; if (this->CursorOver()) return false; return true; } // Keep us up to date in case something changes! this->pos = *target; this->bar.Reset(); int status; // We don't care as much if the cursor isn't being triggered if (PositiveTriggered()) status = 2; else status = 1; // See if we just hit something if (CursorColliding(this->x, this->y, this->width, this->height)) this->status = status; else this->status = 0; return (this->status == 0); } // Draws the combo box void ComboBox::Draw() { float arrowWidth = this->height; // The main box itself if (this->status == 1) { DrawBox(CVec3(this->x, this->y, this->z + 0.003), size, CVec4(0.13, 0.13, 0.13)); 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)); } else { DrawBox(CVec3(this->x, this->y, this->z + 0.003), size, CVec4(0.03, 0.03, 0.03)); 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)); } // The "selected" text 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)); // The arrow on the right 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)); // If the combo box is selected... if (this->status == 2) { int count = COMBOBOX_COUNT; if (count > this->count) count = this->count; float widthOffset = 0; if (this->count > COMBOBOX_COUNT) widthOffset = this->bar.width / 2; this->flipped = false; 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) this->flipped = true; float flipMul = 1.0; if (this->flipped) flipMul = -1.0; // Draw regardless of depth GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_ALWAYS); 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)); // Draw normally again GX2SetDepthOnlyControl(GX2_ENABLE, GX2_ENABLE, GX2_COMPARE_LESS); int position = this->bar.pos + 0.5; float startY = this->y - this->height * flipMul; // Draw a "highlight" if a choice is over or selected if (this->over >= position && this->over < position + COMBOBOX_COUNT) //DrawQuad(this->x, startY, this->z + 0.0205, this->width, this->height, 0.2, 0.2, 0.2); 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)); if (count > position + COMBOBOX_COUNT) count = position + COMBOBOX_COUNT; // Draw only the elements we want to see! for (int i = 0; i < count; ++i) { 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)); startY -= this->height * flipMul; } this->bar.count = this->count; this->bar.x = this->x + size.x / 2 - SCROLLBAR_WIDTH / 2; this->bar.y = this->y - this->height * 5.5 * flipMul; this->bar.Draw(); } } void ComboBox::Reset() { if (this->status > 0) this->status = 0; this->bar.Reset(); }