/* 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. * * Additional copyright for this file: * Copyright (C) 1995-1997 Presto Studios, Inc. * * 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "pegasus/fader.h" #include "pegasus/util.h" namespace Pegasus { Fader::Fader() { _currentValue = 0; _currentFaderMove._numKnots = 0; } void Fader::setFaderValue(const uint32 newValue) { _currentValue = newValue; } bool Fader::initFaderMove(const FaderMoveSpec &spec) { bool faderMoves = false; uint32 value = 0; if (spec._numKnots > 0) { stopFader(); value = spec._knots[0].knotValue; TimeValue startTime = spec._knots[0].knotTime; if (startTime != 0xffffffff) { if (spec._numKnots > 1) { TimeValue stopTime = spec._knots[spec._numKnots - 1].knotTime; if (spec._faderScale > 0) { if (stopTime > startTime) { for (uint32 i = 1; i < spec._numKnots; ++i) { if (spec._knots[i - 1].knotValue != spec._knots[i].knotValue) { faderMoves = true; break; } } if (faderMoves) _currentFaderMove = spec; } else if (spec._knots[spec._numKnots - 1].knotValue != value) { value = spec._knots[spec._numKnots - 1].knotValue; } } } } } setFaderValue(value); return faderMoves; } void Fader::startFader(const FaderMoveSpec &spec) { if (initFaderMove(spec)) { setFlags(0); setScale(spec._faderScale); setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime); setTime(spec._knots[0].knotTime); start(); } } void Fader::startFaderSync(const FaderMoveSpec &spec) { if (initFaderMove(spec)) { setFlags(0); setScale(spec._faderScale); setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime); setTime(spec._knots[0].knotTime); start(); while (isFading()) useIdleTime(); // Once more, for good measure, to make sure that there are no boundary // condition problems. useIdleTime(); stopFader(); } } void Fader::loopFader(const FaderMoveSpec &spec) { if (initFaderMove(spec)) { setFlags(kLoopTimeBase); setScale(spec._faderScale); setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime); setTime(spec._knots[0].knotTime); start(); } } void Fader::stopFader() { stop(); } void Fader::pauseFader() { stopFader(); } void Fader::continueFader() { if (getTime() < getStop()) start(); } void Fader::timeChanged(const TimeValue newTime) { if (_currentFaderMove._numKnots != 0) { uint32 i; for (i = 0; i < _currentFaderMove._numKnots; i++) if (_currentFaderMove._knots[i].knotTime > newTime) break; uint32 newValue; if (i == 0) newValue = _currentFaderMove._knots[0].knotValue; else if (i == _currentFaderMove._numKnots) newValue = _currentFaderMove._knots[i - 1].knotValue; else newValue = linearInterp(_currentFaderMove._knots[i - 1].knotTime, _currentFaderMove._knots[i].knotTime, newTime, _currentFaderMove._knots[i - 1].knotValue, _currentFaderMove._knots[i].knotValue); if (newValue != _currentValue) setFaderValue(newValue); } } void FaderMoveSpec::makeOneKnotFaderSpec(const uint32 knotValue) { _numKnots = 1; _knots[0].knotTime = 0; _knots[0].knotValue = knotValue; } void FaderMoveSpec::makeTwoKnotFaderSpec(const TimeScale faderScale, const TimeValue time1, const uint32 value1, const TimeValue time2, const uint32 value2) { _numKnots = 2; _faderScale = faderScale; _knots[0].knotTime = time1; _knots[0].knotValue = value1; _knots[1].knotTime = time2; _knots[1].knotValue = value2; } void FaderMoveSpec::insertFaderKnot(const TimeValue knotTime, const uint32 knotValue) { if (_numKnots != kMaxFaderKnots) { uint32 index; for (index = 0; index < _numKnots; index++) { if (knotTime == _knots[index].knotTime) { _knots[index].knotValue = knotValue; return; } else if (knotTime < _knots[index].knotTime) { break; } } for (uint32 i = _numKnots; i > index; i--) _knots[i] = _knots[i - 1]; _knots[index].knotTime = knotTime; _knots[index].knotValue = knotValue; _numKnots++; } } void FaderAnimation::setFaderValue(const uint32 newValue) { if (getFaderValue() != newValue) { Fader::setFaderValue(newValue); triggerRedraw(); } } SoundFader::SoundFader() { _sound = 0; _masterVolume = 0xff; } void SoundFader::attachSound(Sound *sound) { if (!sound && isFading()) stopFader(); _sound = sound; } void SoundFader::setFaderValue(const uint32 newVolume) { if (_sound) _sound->setVolume((newVolume * _masterVolume) >> 8); _currentValue = newVolume; } void SoundFader::setMasterVolume(const uint16 masterVolume) { _masterVolume = masterVolume; setFaderValue(getFaderValue()); } } // End of namespace Pegasus