/**************************************************************************** * Copyright (C) 2015 Dimok * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ #include #include #include /** * Constructor for the GuiButton class. */ GuiButton::GuiButton(float w, float h) { width = w; height = h; image = NULL; imageOver = NULL; imageHold = NULL; imageClick = NULL; icon = NULL; iconOver = NULL; for(int32_t i = 0; i < 4; i++) { label[i] = NULL; labelOver[i] = NULL; labelHold[i] = NULL; labelClick[i] = NULL; } for(int32_t i = 0; i < iMaxGuiTriggers; i++) { trigger[i] = NULL; } soundOver = NULL; soundHold = NULL; soundClick = NULL; clickedTrigger = NULL; heldTrigger = NULL; selectable = true; holdable = false; clickable = true; } /** * Destructor for the GuiButton class. */ GuiButton::~GuiButton() { } void GuiButton::setImage(GuiImage* img) { image = img; if(img) img->setParent(this); } void GuiButton::setImageOver(GuiImage* img) { imageOver = img; if(img) img->setParent(this); } void GuiButton::setImageHold(GuiImage* img) { imageHold = img; if(img) img->setParent(this); } void GuiButton::setImageClick(GuiImage* img) { imageClick = img; if(img) img->setParent(this); } void GuiButton::setIcon(GuiImage* img) { icon = img; if(img) img->setParent(this); } void GuiButton::setIconOver(GuiImage* img) { iconOver = img; if(img) img->setParent(this); } void GuiButton::setLabel(GuiText* txt, int32_t n) { label[n] = txt; if(txt) txt->setParent(this); } void GuiButton::setLabelOver(GuiText* txt, int32_t n) { labelOver[n] = txt; if(txt) txt->setParent(this); } void GuiButton::setLabelHold(GuiText* txt, int32_t n) { labelHold[n] = txt; if(txt) txt->setParent(this); } void GuiButton::setLabelClick(GuiText* txt, int32_t n) { labelClick[n] = txt; if(txt) txt->setParent(this); } void GuiButton::setSoundOver(GuiSound * snd) { soundOver = snd; } void GuiButton::setSoundHold(GuiSound * snd) { soundHold = snd; } void GuiButton::setSoundClick(GuiSound * snd) { soundClick = snd; } void GuiButton::setTrigger(GuiTrigger * t, int32_t idx) { if(idx >= 0 && idx < iMaxGuiTriggers) { trigger[idx] = t; } else { for(int32_t i = 0; i < iMaxGuiTriggers; i++) { if(!trigger[i]) { trigger[i] = t; break; } } } } void GuiButton::resetState(void) { clickedTrigger = NULL; heldTrigger = NULL; GuiElement::resetState(); } /** * Draw the button on screen */ void GuiButton::draw(CVideo *v) { if(!this->isVisible()) return; // draw image if((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && imageOver)) || (!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && imageOver))) imageOver->draw(v); else if(image) image->draw(v); if((isDrawOverOnlyWhenSelected() && (isStateSet(STATE_SELECTED) && iconOver)) || (!isDrawOverOnlyWhenSelected() && (isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && iconOver))) iconOver->draw(v); else if(icon) icon->draw(v); // draw text for(int32_t i = 0; i < 4; i++) { if(isStateSet(STATE_OVER | STATE_SELECTED | STATE_CLICKED | STATE_HELD) && labelOver[i]) labelOver[i]->draw(v); else if(label[i]) label[i]->draw(v); } } void GuiButton::update(GuiController * c) { if(!c || isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chanIdx)) return; else if(parentElement && (parentElement->isStateSet(STATE_DISABLED|STATE_HIDDEN|STATE_DISABLE_INPUT, c->chanIdx))) return; if(selectable) { if(c->data.validPointer && this->isInside(c->data.x, c->data.y)) { if(!isStateSet(STATE_OVER, c->chanIdx)) { setState(STATE_OVER, c->chanIdx); //if(this->isRumbleActive()) // this->rumble(t->chan); if(soundOver) soundOver->Play(); if(effectsOver && !effects) { // initiate effects effects = effectsOver; effectAmount = effectAmountOver; effectTarget = effectTargetOver; } pointedOn(this, c); } } else if(isStateSet(STATE_OVER, c->chanIdx)) { this->clearState(STATE_OVER, c->chanIdx); pointedOff(this, c); if(effectTarget == effectTargetOver && effectAmount == effectAmountOver) { // initiate effects (in reverse) effects = effectsOver; effectAmount = -effectAmountOver; effectTarget = 100; } } } for(int32_t i = 0; i < iMaxGuiTriggers; i++) { if(!trigger[i]) continue; // button triggers if(clickable) { int32_t isClicked = trigger[i]->clicked(c); if( !clickedTrigger && (isClicked != GuiTrigger::CLICKED_NONE) && (trigger[i]->isClickEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chanIdx) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) { if(soundClick) soundClick->Play(); clickedTrigger = trigger[i]; if(!isStateSet(STATE_CLICKED, c->chanIdx)) { if(isClicked == GuiTrigger::CLICKED_TOUCH) { setState(STATE_CLICKED_TOUCH, c->chanIdx); } else { setState(STATE_CLICKED, c->chanIdx); } } clicked(this, c, trigger[i]); } else if((isStateSet(STATE_CLICKED, c->chanIdx) || isStateSet(STATE_CLICKED_TOUCH, c->chanIdx)) && (clickedTrigger == trigger[i]) && !isStateSet(STATE_HELD, c->chanIdx) && !trigger[i]->held(c) && ((isClicked == GuiTrigger::CLICKED_NONE) || trigger[i]->released(c))) { if((isStateSet(STATE_CLICKED_TOUCH, c->chanIdx) && this->isInside(c->data.x, c->data.y)) || (isStateSet(STATE_CLICKED, c->chanIdx))) { clickedTrigger = NULL; clearState(STATE_CLICKED, c->chanIdx); released(this, c, trigger[i]); } } } if(holdable) { bool isHeld = trigger[i]->held(c); if( (!heldTrigger || heldTrigger == trigger[i]) && isHeld && (trigger[i]->isHoldEverywhere() || (isStateSet(STATE_SELECTED | STATE_OVER, c->chanIdx) && trigger[i]->isSelectionClickEverywhere()) || this->isInside(c->data.x, c->data.y))) { heldTrigger = trigger[i]; if(!isStateSet(STATE_HELD, c->chanIdx)) setState(STATE_HELD, c->chanIdx); held(this, c, trigger[i]); } else if(isStateSet(STATE_HELD, c->chanIdx) && (heldTrigger == trigger[i]) && (!isHeld || trigger[i]->released(c))) { //! click is removed at this point and converted to held if(clickedTrigger == trigger[i]) { clickedTrigger = NULL; clearState(STATE_CLICKED, c->chanIdx); } heldTrigger = NULL; clearState(STATE_HELD, c->chanIdx); released(this, c, trigger[i]); } } } }