Skip to content

Commit

Permalink
PEGASUS: Implement fader support
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Hoops committed Sep 16, 2011
1 parent 2ae8a97 commit da74436
Show file tree
Hide file tree
Showing 6 changed files with 352 additions and 16 deletions.
214 changes: 214 additions & 0 deletions engines/pegasus/fader.cpp
@@ -0,0 +1,214 @@
/* 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
130 changes: 130 additions & 0 deletions engines/pegasus/fader.h
@@ -0,0 +1,130 @@
/* 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.
*
*/

#ifndef PEGASUS_FADER_H
#define PEGASUS_FADER_H

#include "pegasus/elements.h"
#include "pegasus/timers.h"

namespace Pegasus {

class Fader;

class FaderMoveSpec {
friend class Fader;
public:
FaderMoveSpec() {
_faderScale = kDefaultTimeScale;
_numKnots = 0;
}

FaderMoveSpec(const TimeScale scale) {
_faderScale = scale;
_numKnots = 0;
}

void setFaderScale(const TimeScale scale) { _faderScale = scale; }
TimeScale getFaderScale() const { return _faderScale; }

void makeOneKnotFaderSpec(const uint32);
void makeTwoKnotFaderSpec(const TimeScale, const TimeValue, const uint32, const TimeValue, const uint32);

void insertFaderKnot(const TimeValue, const uint32);

uint32 getNumKnots() const { return _numKnots; }
uint32 getNthKnotTime(const uint32 index) const { return _knots[index].knotTime; }
uint32 getNthKnotValue(const uint32 index) const { return _knots[index].knotValue; }

protected:
struct FaderKnot {
TimeValue knotTime;
uint32 knotValue;
};

TimeScale _faderScale;
uint32 _numKnots;

static const uint32 kMaxFaderKnots = 20;
FaderKnot _knots[kMaxFaderKnots];
};

class Fader : private IdlerTimeBase {
public:
Fader();
virtual ~Fader() {}

virtual void setFaderValue(const uint32);
uint32 getFaderValue() const { return _currentValue; }
virtual void startFader(const FaderMoveSpec &);
virtual void startFaderSync(const FaderMoveSpec &);
virtual void loopFader(const FaderMoveSpec &);
virtual void stopFader();
virtual bool isFading() { return isRunning(); }

void pauseFader();
void continueFader();

void getCurrentFaderMove(FaderMoveSpec &spec) { spec = _currentFaderMove; }

protected:
bool initFaderMove(const FaderMoveSpec &);
virtual void timeChanged(const TimeValue);

uint32 _currentValue;
FaderMoveSpec _currentFaderMove;
};

class FaderAnimation : public DisplayElement, public Fader {
public:
FaderAnimation(const tDisplayElementID id) : DisplayElement(id) {}
virtual ~FaderAnimation() {}

void setFaderValue(const uint32);
};

class Sound;

class SoundFader : public Fader {
friend class Sound;
public:
SoundFader();
virtual ~SoundFader() {}

void setFaderValue(const uint32);

void setMasterVolume(const uint16);
uint16 getMasterVolume() const { return _masterVolume; }

protected:
void attachSound(Sound *);

Sound *_sound;
uint16 _masterVolume;
};

} // End of namespace Pegasus

#endif
1 change: 1 addition & 0 deletions engines/pegasus/module.mk
Expand Up @@ -6,6 +6,7 @@ MODULE_OBJS = \
cursor.o \
detection.o \
elements.o \
fader.o \
gamestate.o \
graphics.o \
hotspot.o \
Expand Down

0 comments on commit da74436

Please sign in to comment.