/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * 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 "twp/twp.h" #include "twp/actorswitcher.h" #include "twp/resmanager.h" #include "twp/util.h" #define DISABLE_ALPHA 0.f #define ENABLE_ALPHA 1.f #define INACTIVE_ALPHA 0.5f #define ACTOR_SEP 60.f #define MARGIN 30.f #define ANIM_DURATION 0.120f namespace Twp { ActorSwitcherSlot::ActorSwitcherSlot(const Common::String &icon_, const Color &back_, const Color &frame_, SelectFunc *selectFunc_, int id_) { icon = icon_; back = back_; frame = frame_; selectFunc = selectFunc_; id = id_; } void ActorSwitcherSlot::select() { if (selectFunc) { selectFunc(id); } } ActorSwitcher::ActorSwitcher() : Node("ActorSwitcher") { _alpha = ENABLE_ALPHA; } Math::Matrix4 ActorSwitcher::transform(const Math::Matrix4 &t, int index) { Math::Matrix4 trsf(t); float animPos = _mouseOver ? _animPos : 1.f; Math::Vector3d pos(SCREEN_WIDTH - MARGIN, SCREEN_HEIGHT - MARGIN - animPos * ACTOR_SEP * index, 0.f); Math::Vector2d s(2.f, 2.f); trsf.translate(pos); Twp::scale(trsf, s); return trsf; } float ActorSwitcher::getAlpha(size_t index) const { if (index == (_slots.size() - 1)) return ENABLE_ALPHA; if (_mode & asTemporaryUnselectable) return INACTIVE_ALPHA; if (_mode & asOn) return _mouseOver ? ENABLE_ALPHA : _alpha; return _mouseOver ? INACTIVE_ALPHA : DISABLE_ALPHA; } void ActorSwitcher::drawIcon(const Common::String &icon, const Color &backColor, const Color &frameColor, const Math::Matrix4 &trsf, int index) { SpriteSheet *gameSheet = g_twp->_resManager->spriteSheet("GameSheet"); Texture *texture = g_twp->_resManager->texture(gameSheet->meta.image); const SpriteSheetFrame &iconBackFrame = gameSheet->getFrame("icon_background"); const SpriteSheetFrame &iconActorFrame = gameSheet->getFrame(icon); const SpriteSheetFrame &iconFrame = gameSheet->getFrame("icon_frame"); Math::Matrix4 t = transform(trsf, index); float alpha = getAlpha(index); drawSprite(iconBackFrame, texture, Color::withAlpha(backColor, alpha), t); drawSprite(iconActorFrame, texture, Color::withAlpha(Color(), alpha), t); drawSprite(iconFrame, texture, Color::withAlpha(frameColor, alpha), t); } void ActorSwitcher::drawCore(const Math::Matrix4 &trsf) { if (_mouseOver) { for (size_t i = 0; i < _slots.size(); i++) { ActorSwitcherSlot &slot = _slots[i]; drawIcon(slot.icon, slot.back, slot.frame, trsf, i); } } else if (!_slots.empty()) { ActorSwitcherSlot &slot = _slots[0]; drawIcon(slot.icon, slot.back, slot.frame, trsf, 0); } } void ActorSwitcher::drawSprite(const SpriteSheetFrame &sf, Texture *texture, const Color &color, const Math::Matrix4 &trsf) { Math::Matrix4 t(trsf); Math::Vector3d pos(sf.spriteSourceSize.left - sf.sourceSize.getX() / 2.f, -sf.spriteSourceSize.height() - sf.spriteSourceSize.top + sf.sourceSize.getY() / 2.f, 0.f); t.translate(pos); g_twp->getGfx().drawSprite(sf.frame, *texture, color, t); } float ActorSwitcher::height() const { float n = _mouseOver ? _slots.size() : 1.0f; return n * ACTOR_SEP; } int ActorSwitcher::iconIndex(const Math::Vector2d &pos) const { float y = SCREEN_HEIGHT - pos.getY(); return _slots.size() - 1 - (int)((height() - y) / ACTOR_SEP); } Common::Rect ActorSwitcher::rect() const { float h = height(); return Common::Rect(Common::Point(SCREEN_WIDTH - ACTOR_SEP, SCREEN_HEIGHT - h), ACTOR_SEP, h); } void ActorSwitcher::update(const Common::Array &slots, float elapsed) { if (!_visible) return; _slots = slots; // update flash icon if ((_flash != 0) && ((_flash == -1) || (_flashElapsed < _flash))) { _flashElapsed = _flashElapsed + elapsed; _alpha = 0.6f + 0.4f * sin(M_PI * 2.f * _flashElapsed); } else { _flash = 0; _flashElapsed = 0.f; _alpha = INACTIVE_ALPHA; } // check if mouse is over actor icons or gear icon Math::Vector2d scrPos = g_twp->winToScreen(g_twp->_cursor.pos); bool oldMouseOver = _mouseOver; _mouseOver = !_down && rect().contains(scrPos.getX(), scrPos.getY()); // update anim _animElapsed = _animElapsed + elapsed; // stop anim or flash if necessary if (oldMouseOver != _mouseOver) { _animElapsed = 0.f; if (_mouseOver) _flash = 0; } // update anim pos _animPos = MIN(1.f, _animElapsed / ANIM_DURATION); // check if we select an actor or gear icon if (_mouseOver && (g_twp->_cursor.leftDown) && !_down) { _down = true; // check if we allow to select an actor size_t iconIdx = iconIndex(scrPos); if ((_mode == asOn) || (iconIdx == (_slots.size() - 1))) { if (_slots[iconIdx].selectFunc != nullptr) _slots[iconIdx].select(); } } if (!g_twp->_cursor.leftDown) _down = false; } } // namespace Twp