/* 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 "common/config-manager.h" #include "twp/twp.h" #include "twp/hud.h" namespace Twp { Verb::Verb() = default; Verb::Verb(VerbId verbId, const Common::String &img, const Common::String &f, const Common::String &t, const Common::String &k, int fl) : id(verbId), image(img), fun(f), text(t), key(k), flags(fl) { } VerbUiColors::VerbUiColors() = default; VerbUiColors::VerbUiColors(Color s, Color vbNormal, Color vbNormalTint, Color vbHiglight, Color vbHiglightTint, Color dlgNormal, Color dlgHighlt, Color invFrame, Color inventoryBack, Color retroNml, Color retroHighlt) : sentence(s), verbNormal(vbNormal), verbNormalTint(vbNormalTint), verbHighlight(vbHiglight), verbHighlightTint(vbHiglightTint), dialogNormal(dlgNormal), dialogHighlight(dlgHighlt), inventoryFrame(invFrame), inventoryBackground(inventoryBack), retroNormal(retroNml), retroHighlight(retroHighlt) { } ActorSlot::ActorSlot() = default; HudShader::HudShader() = default; void HudShader::init() { const char *v_source = R"( attribute vec2 a_position; attribute vec4 a_color; attribute vec2 a_texCoords; uniform vec4 u_shadowColor; uniform vec4 u_normalColor; uniform vec4 u_highlightColor; uniform vec2 u_ranges; uniform mat4 u_transform; varying vec4 v_color; varying vec2 v_texCoords; varying vec4 v_shadowColor; varying vec4 v_normalColor; varying vec4 v_highlightColor; varying vec2 v_ranges; void main() { gl_Position = u_transform * vec4(a_position, 0.0, 1.0); v_color = a_color; v_texCoords = a_texCoords; v_shadowColor = u_shadowColor; v_normalColor = u_normalColor; v_highlightColor = u_highlightColor; v_ranges = u_ranges; })"; const char* f_source = R"( varying vec4 v_color; varying vec2 v_texCoords; varying vec4 v_shadowColor; varying vec4 v_normalColor; varying vec4 v_highlightColor; varying vec2 v_ranges; uniform sampler2D u_texture; void main() { float shadows = v_ranges.x; float highlights = v_ranges.y; vec4 texColor = texture2D(u_texture, v_texCoords); if (texColor.g <= shadows) { texColor *= v_shadowColor; } else if (texColor.g >= highlights) { texColor *= v_highlightColor; } else { texColor *= v_normalColor; } texColor *= v_color; gl_FragColor = texColor; })"; Shader::init("hud", v_source, f_source); } HudShader::~HudShader() = default; void HudShader::applyUniforms() { setUniform("u_ranges", Math::Vector2d(0.8f, 0.8f)); setUniform4("u_shadowColor", _shadowColor); setUniform4("u_normalColor", _normalColor); setUniform4("u_highlightColor", _highlightColor); } Hud::Hud() : Node("hud") { _zOrder = 100; for (auto &_actorSlot : _actorSlots) { ActorSlot *slot = &_actorSlot; slot->actor = nullptr; } } void Hud::init() { _shader.init(); } ActorSlot *Hud::actorSlot(Common::SharedPtr actor) { for (auto &_actorSlot : _actorSlots) { ActorSlot *slot = &_actorSlot; if (slot->actor == actor) { return slot; } } return nullptr; } void Hud::drawSprite(const SpriteSheetFrame &sf, Texture *texture, Color color, Math::Matrix4 trsf) { Math::Vector3d pos(sf.spriteSourceSize.left, -sf.spriteSourceSize.height() - sf.spriteSourceSize.top + sf.sourceSize.getY(), 0.f); trsf.translate(pos); g_twp->getGfx().drawSprite(sf.frame, *texture, color, trsf); } void Hud::drawCore(Math::Matrix4 trsf) { ActorSlot *slot = actorSlot(_actor); if (!slot) return; // draw HUD background SpriteSheet *gameSheet = g_twp->_resManager.spriteSheet("GameSheet"); bool classic = ConfMan.getBool("hudSentence"); const SpriteSheetFrame &backingFrame = gameSheet->getFrame(classic ? "ui_backing_tall" : "ui_backing"); Texture *gameTexture = g_twp->_resManager.texture(gameSheet->meta.image); float alpha = 0.33f; // prefs(UiBackingAlpha); g_twp->getGfx().drawSprite(backingFrame.frame, *gameTexture, Color(0, 0, 0, alpha * getAlpha()), trsf); bool verbHlt = ConfMan.getBool("invertVerbHighlight"); Color verbHighlight = verbHlt ? Color() : slot->verbUiColors.verbHighlight; Color verbColor = verbHlt ? slot->verbUiColors.verbHighlight : Color(); // draw actor's verbs SpriteSheet *verbSheet = g_twp->_resManager.spriteSheet("VerbSheet"); Texture *verbTexture = g_twp->_resManager.texture(verbSheet->meta.image); Common::String lang = ConfMan.get("language"); bool retroVerbs = ConfMan.getBool("retroVerbs"); Common::String verbSuffix = retroVerbs ? "_retro" : ""; Shader *saveShader = g_twp->getGfx().getShader(); g_twp->getGfx().use(&_shader); _shader._shadowColor = slot->verbUiColors.verbNormalTint; _shader._normalColor = slot->verbUiColors.verbHighlight; _shader._highlightColor = slot->verbUiColors.verbHighlightTint; bool isOver = false; for (int i = 1; i < 22; i++) { const Verb &verb = slot->verbs[i]; if (verb.image.size() > 0) { const SpriteSheetFrame &verbFrame = verbSheet->getFrame(Common::String::format("%s%s_%s", verb.image.c_str(), verbSuffix.c_str(), lang.c_str())); bool over = verbFrame.spriteSourceSize.contains(_mousePos.getX(), _mousePos.getY()); if (over) isOver = true; Color color = (over || (verb.id.id == _defaultVerbId)) ? verbHighlight : verbColor; if (_mouseClick && over) { _verb = verb; } drawSprite(verbFrame, verbTexture, Color::withAlpha(color, getAlpha()), trsf); } } g_twp->getGfx().use(saveShader); _over = isOver; } void Hud::update(float elapsed, Math::Vector2d pos, Common::SharedPtr hotspot, bool mouseClick) { _mousePos = Math::Vector2d(pos.getX(), SCREEN_HEIGHT - pos.getY()); _defaultVerbId = !hotspot ? 0 : hotspot->defaultVerbId(); _mouseClick = mouseClick; _fadeTime += elapsed; if (_fadeTime > 2.f) { _fadeTime = 2.f; if (!_fadeIn) { setVisible(false); } } if (_fadeIn) { float alpha = MIN(_fadeTime, 2.0f) / 2.0f; setAlpha(alpha); } else { float alpha = MAX(2.0f - _fadeTime, 0.0f) / 2.0f; setAlpha(alpha); } } void Hud::setVisible(bool visible) { if (_fadeIn != visible) { _fadeIn = visible; if (visible) { Node::setVisible(visible); } _fadeTime = 0; } } } // namespace Twp