ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

dialogpanel.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/ui/world/dialogpanel.h"
00024 
00025 #include "engines/stark/gfx/driver.h"
00026 
00027 #include "engines/stark/resources/speech.h"
00028 
00029 #include "engines/stark/services/services.h"
00030 #include "engines/stark/services/staticprovider.h"
00031 #include "engines/stark/services/dialogplayer.h"
00032 #include "engines/stark/services/settings.h"
00033 #include "engines/stark/services/userinterface.h"
00034 
00035 #include "engines/stark/ui/cursor.h"
00036 #include "engines/stark/ui/world/clicktext.h"
00037 
00038 #include "engines/stark/visual/image.h"
00039 #include "engines/stark/visual/text.h"
00040 
00041 namespace Stark {
00042 
00043 const Color DialogPanel::_aprilColor = Color(0xFF, 0xC0, 0x00);
00044 const Color DialogPanel::_otherColor = Color(0xFF, 0x40, 0x40);
00045 
00046 DialogPanel::DialogPanel(Gfx::Driver *gfx, Cursor *cursor) :
00047         Window(gfx, cursor),
00048         _subtitleVisual(nullptr),
00049         _currentSpeech(nullptr),
00050         _scrollUpArrowVisible(false),
00051         _scrollDownArrowVisible(false),
00052         _firstVisibleOption(0),
00053         _lastVisibleOption(0),
00054         _focusedOption(0),
00055         _acceptIdleMousePos(false) {
00056     _position = Common::Rect(Gfx::Driver::kOriginalWidth, Gfx::Driver::kBottomBorderHeight);
00057     _position.translate(0, Gfx::Driver::kTopBorderHeight + Gfx::Driver::kGameViewportHeight);
00058 
00059     _visible = true;
00060 
00061     _activeBackGroundTexture = StarkStaticProvider->getUIElement(StaticProvider::kTextBackgroundActive);
00062     _passiveBackGroundTexture = StarkStaticProvider->getUIElement(StaticProvider::kTextBackgroundPassive);
00063     _scrollUpArrowImage = StarkStaticProvider->getUIElement(StaticProvider::kTextScrollUpArrow);
00064     _scrollDownArrowImage = StarkStaticProvider->getUIElement(StaticProvider::kTextScrollDownArrow);
00065     _dialogOptionBullet = StarkStaticProvider->getUIImage(StaticProvider::kDialogOptionBullet);
00066 
00067     _scrollUpArrowRect = Common::Rect(_scrollUpArrowImage->getWidth(), _scrollUpArrowImage->getHeight());
00068     _scrollUpArrowRect.translate(0, _optionsTop);
00069 
00070     _scrollDownArrowRect = Common::Rect(_scrollDownArrowImage->getWidth(), _scrollDownArrowImage->getHeight());
00071     _scrollDownArrowRect.translate(0, _optionsTop + _optionsHeight - _scrollDownArrowImage->getHeight() - 9);
00072 }
00073 
00074 DialogPanel::~DialogPanel() {
00075     clearOptions();
00076     clearSubtitleVisual();
00077 }
00078 
00079 void DialogPanel::abortCurrentSpeech() {
00080     if (_currentSpeech) {
00081         _currentSpeech->stop();
00082         _currentSpeech = nullptr;
00083     }
00084 }
00085 
00086 void DialogPanel::clearSubtitleVisual() {
00087     delete _subtitleVisual;
00088     _subtitleVisual = nullptr;
00089 }
00090 
00091 void DialogPanel::clearOptions() {
00092     for (uint i = 0; i < _options.size(); i++) {
00093         delete _options[i];
00094     }
00095     _options.clear();
00096 }
00097 
00098 void DialogPanel::renderOptions() {
00099     uint32 pos = _optionsTop;
00100     for (uint i = _firstVisibleOption; i <= _lastVisibleOption; ++i) {
00101         _options[i]->setPosition(Common::Point(_optionsLeft, pos));
00102         _options[i]->render();
00103 
00104         _dialogOptionBullet->render(Common::Point(_optionsLeft - 13, pos + 3), false);
00105 
00106         pos += _options[i]->getHeight();
00107     }
00108 
00109     _scrollUpArrowVisible = _firstVisibleOption > 0;
00110     _scrollDownArrowVisible = _lastVisibleOption < _options.size() - 1;
00111 }
00112 
00113 void DialogPanel::renderScrollArrows() const {
00114     if (_scrollUpArrowVisible) {
00115         _scrollUpArrowImage->render(Common::Point(_scrollUpArrowRect.left, _scrollUpArrowRect.top), true);
00116     }
00117 
00118     if (_scrollDownArrowVisible) {
00119         _scrollDownArrowImage->render(Common::Point(_scrollDownArrowRect.left, _scrollDownArrowRect.top), true);
00120     }
00121 }
00122 
00123 void DialogPanel::onGameLoop() {
00124     // Clear completed speeches
00125     if (!_currentSpeech || !_currentSpeech->isPlaying()) {
00126         _currentSpeech = nullptr;
00127 
00128         clearSubtitleVisual();
00129 
00130         // Toggle subtitles on and off when requested
00131         if (StarkUserInterface->hasToggleSubtitleRequest()) {
00132             StarkUserInterface->performToggleSubtitle();
00133         }
00134     }
00135 
00136     // Update the dialog engine
00137     StarkDialogPlayer->update();
00138 
00139     // Check if a new speech can be played
00140     if (StarkDialogPlayer->isSpeechReady()) {
00141         _currentSpeech = StarkDialogPlayer->acquireReadySpeech();
00142         _currentSpeech->playSound();
00143         updateSubtitleVisual();
00144     }
00145 
00146     if (_options.empty() && StarkDialogPlayer->areOptionsAvailable()) {
00147         updateDialogOptions();
00148     }
00149 }
00150 
00151 void DialogPanel::onRender() {
00152     // Draw options if available
00153     if (!_options.empty()) {
00154         _activeBackGroundTexture->render(Common::Point(0, 0), false);
00155 
00156         renderOptions();
00157         renderScrollArrows();
00158     } else {
00159         _passiveBackGroundTexture->render(Common::Point(0, 0), false);
00160 
00161         // Draw subtitle if available
00162         if (_subtitleVisual && StarkSettings->getBoolSetting(Settings::kSubtitle)) {
00163             _subtitleVisual->render(Common::Point(_optionsLeft, _optionsTop));
00164         }
00165     }
00166 }
00167 
00168 void DialogPanel::updateSubtitleVisual() {
00169     clearSubtitleVisual();
00170 
00171     Color color = _otherColor;
00172     if (_currentSpeech->characterIsApril())
00173         color = _aprilColor;
00174 
00175     _subtitleVisual = new VisualText(_gfx);
00176     _subtitleVisual->setText(_currentSpeech->getPhrase());
00177     _subtitleVisual->setColor(color);
00178     _subtitleVisual->setFont(FontProvider::kBigFont);
00179     _subtitleVisual->setTargetWidth(600);
00180 }
00181 
00182 void DialogPanel::updateDialogOptions() {
00183     clearOptions();
00184 
00185     _firstVisibleOption = 0;
00186     _lastVisibleOption = 0;
00187     _focusedOption = 0;
00188     Common::Array<DialogPlayer::Option> options = StarkDialogPlayer->listOptions();
00189 
00190     for (uint i = 0; i < options.size(); i++) {
00191         _options.push_back(new ClickText(options[i]._caption, _aprilColor));
00192     }
00193 
00194     if (!_options.empty()) {
00195         updateLastVisibleOption();
00196         _options[_focusedOption]->setActive();
00197         _acceptIdleMousePos = true;
00198     }
00199 }
00200 
00201 void DialogPanel::onMouseMove(const Common::Point &pos) {
00202     static Common::Point prevPos;
00203 
00204     if (_subtitleVisual) {
00205         _cursor->setCursorType(Cursor::kDefault);
00206     } else if (!_options.empty()) {
00207         if (pos != prevPos || _acceptIdleMousePos) {
00208             for (uint i = _firstVisibleOption; i <= _lastVisibleOption; ++i) {
00209                 if (_options[i]->containsPoint(pos)) {
00210                     _options[_focusedOption]->setPassive();
00211                     _focusedOption = i;
00212                     _options[_focusedOption]->setActive();
00213 
00214                     _cursor->setCursorType(Cursor::kActive);
00215                     _acceptIdleMousePos = false;
00216 
00217                     prevPos = pos;
00218                     return;
00219                 }
00220             }
00221         }
00222         
00223         if (_options[_focusedOption]->containsPoint(pos)) {
00224             _cursor->setCursorType(Cursor::kActive);
00225         } else if (_scrollUpArrowVisible && _scrollUpArrowRect.contains(pos)) {
00226             _cursor->setCursorType(Cursor::kActive);
00227         } else if (_scrollDownArrowVisible && _scrollDownArrowRect.contains(pos)) {
00228             _cursor->setCursorType(Cursor::kActive);
00229         } else {
00230             _cursor->setCursorType(Cursor::kDefault);
00231         }
00232     } else {
00233         _cursor->setCursorType(Cursor::kDefault);
00234     }
00235 
00236     prevPos = pos;
00237 }
00238 
00239 void DialogPanel::onClick(const Common::Point &pos) {
00240     if (!_options.empty()) {
00241         if (_options[_focusedOption]->containsPoint(pos)) {
00242             selectFocusedOption();
00243         }
00244 
00245         if (_scrollUpArrowVisible && _scrollUpArrowRect.contains(pos)) {
00246             scrollUp();
00247         }
00248 
00249         if (_scrollDownArrowVisible && _scrollDownArrowRect.contains(pos)) {
00250             scrollDown();
00251         }
00252     }
00253 }
00254 
00255 void DialogPanel::onRightClick(const Common::Point &pos) {
00256     if (_currentSpeech && _currentSpeech->isPlaying()) {
00257         abortCurrentSpeech();
00258         clearSubtitleVisual();
00259     }
00260 }
00261 
00262 void DialogPanel::reset() {
00263     abortCurrentSpeech();
00264     clearSubtitleVisual();
00265     clearOptions();
00266 
00267     StarkDialogPlayer->reset();
00268 }
00269 
00270 void DialogPanel::scrollUp() {
00271     if (!_scrollUpArrowVisible) return;
00272 
00273     _lastVisibleOption = _firstVisibleOption;
00274     updateFirstVisibleOption();
00275 
00276     _options[_focusedOption]->setPassive();
00277     _focusedOption = _lastVisibleOption;
00278     _options[_focusedOption]->setActive();
00279 }
00280 
00281 void DialogPanel::scrollDown() {
00282     if (!_scrollDownArrowVisible) return;
00283 
00284     _firstVisibleOption = _lastVisibleOption;
00285     updateLastVisibleOption();
00286 
00287     _options[_focusedOption]->setPassive();
00288     _focusedOption = _firstVisibleOption;
00289     _options[_focusedOption]->setActive();
00290 }
00291 
00292 void DialogPanel::focusNextOption() {
00293     if (_options.empty() || _focusedOption == _options.size() - 1) return;
00294 
00295     _options[_focusedOption]->setPassive();
00296     ++_focusedOption;
00297     _options[_focusedOption]->setActive();
00298 
00299     if (_focusedOption > _lastVisibleOption) {
00300         _lastVisibleOption = _focusedOption;
00301         updateFirstVisibleOption();
00302     }
00303 }
00304 
00305 void DialogPanel::focusPrevOption() {
00306     if (_options.empty() || _focusedOption == 0) return;
00307 
00308     _options[_focusedOption]->setPassive();
00309     --_focusedOption;
00310     _options[_focusedOption]->setActive();
00311 
00312     if (_focusedOption < _firstVisibleOption) {
00313         _firstVisibleOption = _focusedOption;
00314         updateLastVisibleOption();
00315     }
00316 }
00317 
00318 void DialogPanel::selectFocusedOption() {
00319     if (_options.size() > 0) {
00320         StarkDialogPlayer->selectOption(_focusedOption);
00321         clearOptions();
00322     }
00323 }
00324 
00325 void DialogPanel::selectOption(uint index) {
00326     if (_options.size() <= index) return;
00327 
00328     StarkDialogPlayer->selectOption(index);
00329     clearOptions();
00330 }
00331 
00332 void DialogPanel::onScreenChanged() {
00333     if (_currentSpeech) {
00334         updateSubtitleVisual();
00335     } else {
00336         updateDialogOptions();
00337     }
00338 }
00339 
00340 void DialogPanel::updateFirstVisibleOption() {
00341     _firstVisibleOption = _lastVisibleOption;
00342     uint32 height = _optionsTop + _options[_lastVisibleOption]->getHeight();
00343 
00344     while (_firstVisibleOption > 0) {
00345         height += _options[_firstVisibleOption - 1]->getHeight();
00346         if (height <= _optionsHeight) {
00347             --_firstVisibleOption;
00348         } else {
00349             break;
00350         }
00351     }
00352 
00353     if (_firstVisibleOption == 0) {
00354         while (_lastVisibleOption < _options.size() - 1) {
00355             height += _options[_lastVisibleOption + 1]->getHeight();
00356             if (height <= _optionsHeight) {
00357                 ++_lastVisibleOption;
00358             } else {
00359                 break;
00360             }
00361         }
00362     }
00363 }
00364 
00365 void DialogPanel::updateLastVisibleOption() {
00366     _lastVisibleOption = _firstVisibleOption;
00367     uint32 height = _optionsTop + _options[_firstVisibleOption]->getHeight();
00368 
00369     while (_lastVisibleOption < _options.size() - 1) {
00370         height += _options[_lastVisibleOption + 1]->getHeight();
00371         if (height <= _optionsHeight) {
00372             ++_lastVisibleOption;
00373         } else {
00374             break;
00375         }
00376     }
00377 
00378     if (_lastVisibleOption == _options.size() - 1) {
00379         while (_firstVisibleOption > 0) {
00380             height += _options[_firstVisibleOption - 1]->getHeight();
00381             if (height <= _optionsHeight) {
00382                 --_firstVisibleOption;
00383             } else {
00384                 break;
00385             }
00386         }
00387     }
00388 }
00389 
00390 } // End of namespace Stark


Generated on Sat Feb 16 2019 05:00:49 for ResidualVM by doxygen 1.7.1
curved edge   curved edge