diff options
| author | Matthew Hoops | 2011-09-15 20:39:37 -0400 | 
|---|---|---|
| committer | Matthew Hoops | 2011-09-15 20:39:37 -0400 | 
| commit | 1ac6abaeff4813d75abd4ac58a13e22eaef2ab71 (patch) | |
| tree | ccc967c4c43cc10654805f9308879b878fe0e6dc | |
| parent | d3fde69770b5a3065fa3ae1da76e443d6d185147 (diff) | |
| download | scummvm-rg350-1ac6abaeff4813d75abd4ac58a13e22eaef2ab71.tar.gz scummvm-rg350-1ac6abaeff4813d75abd4ac58a13e22eaef2ab71.tar.bz2 scummvm-rg350-1ac6abaeff4813d75abd4ac58a13e22eaef2ab71.zip | |
PEGASUS: Stub off the base timebase code
This is not tested, and hopefully just works without anymore changes. I hate QuickTime :P
| -rw-r--r-- | engines/pegasus/elements.cpp | 121 | ||||
| -rw-r--r-- | engines/pegasus/elements.h | 59 | ||||
| -rw-r--r-- | engines/pegasus/pegasus.cpp | 8 | ||||
| -rw-r--r-- | engines/pegasus/pegasus.h | 7 | ||||
| -rwxr-xr-x | engines/pegasus/timers.cpp | 282 | ||||
| -rwxr-xr-x | engines/pegasus/timers.h | 166 | 
6 files changed, 643 insertions, 0 deletions
| diff --git a/engines/pegasus/elements.cpp b/engines/pegasus/elements.cpp index 132c19a02a..695a6e54b8 100644 --- a/engines/pegasus/elements.cpp +++ b/engines/pegasus/elements.cpp @@ -23,6 +23,9 @@   *   */ +#include "common/macresman.h" +#include "common/stream.h" +  #include "pegasus/elements.h"  #include "pegasus/graphics.h" @@ -238,4 +241,122 @@ void EnergyBar::calcLevelRect(Common::Rect &r) const {  	}  } +IdlerAnimation::IdlerAnimation(const tDisplayElementID id) : Animation(id) { +	_lastTime = 0xffffffff; +} + +void IdlerAnimation::startDisplaying() { +	if (!isDisplaying()) { +		Animation::startDisplaying(); +		startIdling(); +	} +} + +void IdlerAnimation::stopDisplaying() { +	if (isDisplaying()) { +		Animation::stopDisplaying(); +		stopIdling(); +	} +} + +void IdlerAnimation::useIdleTime() { +	uint32 currentTime = getTime(); + +	if (currentTime != _lastTime) { +		_lastTime = currentTime; +		timeChanged(_lastTime); +	} +} + +void IdlerAnimation::timeChanged(const TimeValue) { +	triggerRedraw(); +} + +FrameSequence::FrameSequence(const tDisplayElementID id) : IdlerAnimation(id) { +	_duration = 0; +	_currentFrameNum = 0; +	_resFork = new Common::MacResManager(); +} + +FrameSequence::~FrameSequence() { +	delete _resFork; +} + +void FrameSequence::useFileName(const Common::String &fileName) { +	_resFork->open(fileName); +} + +void FrameSequence::openFrameSequence() { +	if (!_resFork->hasResFork()) +		return; + +	Common::SeekableReadStream *res = _resFork->getResource(MKTAG('P', 'F', 'r', 'm'), 0x80); + +	if (!res) +		return; + +	uint32 scale = res->readUint32BE(); +	_bounds.top = res->readUint16BE(); +	_bounds.left = res->readUint16BE(); +	_bounds.bottom = res->readUint16BE(); +	_bounds.right = res->readUint16BE(); +	_numFrames = res->readUint16BE(); +	_duration = 0; + +	_frameTimes.clear(); +	for (uint32 i = 0; i < _numFrames; i++) { +		TimeValue time = res->readUint32BE(); +		_duration += time; +		_frameTimes.push_back(_duration); +	} + +	setScale(scale); +	setSegment(0, _duration); +	setTime(0); +	_currentFrameNum = 0; +	newFrame(_currentFrameNum); +	triggerRedraw(); + +	delete res; +} + +void FrameSequence::closeFrameSequence() { +	stop(); +	_resFork->close(); +	_duration = 0; +	_numFrames = 0; +	_frameTimes.clear(); +} + +void FrameSequence::timeChanged(const TimeValue time) { +	int16 frameNum = 0; +	for (int16 i = _numFrames - 1; i >= 0; i--) { +		if (_frameTimes[i] < time) { +			frameNum = i; +			break; +		} +	} + +	if (frameNum != _currentFrameNum) { +		_currentFrameNum = frameNum; +		newFrame(_currentFrameNum); +		triggerRedraw(); +	} +} + +void FrameSequence::setFrameNum(const int16 frameNum) { +	int16 f = CLIP<int>(frameNum, 0, _numFrames); + +	if (_currentFrameNum != f) { +		_currentFrameNum = f; +		setTime(_frameTimes[f]); +		newFrame(f); +		triggerRedraw(); +	} +} + +bool FrameSequence::isSequenceOpen() const { +	return _numFrames != 0; +} +  } // End of namespace Pegasus diff --git a/engines/pegasus/elements.h b/engines/pegasus/elements.h index 2fc7a3abd3..460b9a71d9 100644 --- a/engines/pegasus/elements.h +++ b/engines/pegasus/elements.h @@ -33,8 +33,13 @@  #include "graphics/surface.h"  #include "pegasus/pegasus.h" +#include "pegasus/timers.h"  #include "pegasus/util.h" +namespace Common { +	class MacResManager; +} +  namespace Pegasus {  class DisplayElement : public IDObject { @@ -134,6 +139,60 @@ protected:  	uint32 _barColor;  }; +class Animation : public DisplayElement, public DynamicElement { +public: +	Animation(const tDisplayElementID id) : DisplayElement(id) {} +}; + +class IdlerAnimation : public Animation, public Idler { +public: +	IdlerAnimation(const tDisplayElementID); +	 +	virtual void startDisplaying(); +	virtual void stopDisplaying(); +	 +	TimeValue getLastTime() const { return _lastTime; } + +protected: +	virtual void useIdleTime(); +	virtual void timeChanged(const TimeValue); +	 +	TimeValue _lastTime; +}; + +//	This class reads PICT resources and plays them like a movie. +//	Assumes there is a resource of type 'PFrm' describing the time values for each +//	PICT frame, as well as the total time in the movie. +//	Assumes that PICT frames begin at PICT 128 + +class FrameSequence : public IdlerAnimation { +public: +	FrameSequence(const tDisplayElementID); +	virtual ~FrameSequence(); + +	void useFileName(const Common::String &fileName); + +	virtual void openFrameSequence(); +	virtual void closeFrameSequence(); +	bool isSequenceOpen() const; +	 +	uint16 getNumFrames() const { return _numFrames; } +	virtual uint16 getFrameNum() const { return _currentFrameNum; } +	virtual void setFrameNum(const int16); + +protected:		 +	virtual void timeChanged(const TimeValue); +	virtual void newFrame(const uint16) {} + +	Common::MacResManager *_resFork; +	TimeValue _duration; + +	uint16 _numFrames; +	Common::Array<TimeValue> _frameTimes; + +	uint16 _currentFrameNum; +}; +  } // End of namespace Pegasus  #endif diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index 39eb7d50c4..dacc2a0a30 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -332,4 +332,12 @@ void PegasusEngine::giveIdleTime() {  		(*it)->useIdleTime();  } +void PegasusEngine::addTimeBase(TimeBase *timeBase) { +	_timeBases.push_back(timeBase); +} + +void PegasusEngine::removeTimeBase(TimeBase *timeBase) { +	_timeBases.remove(timeBase); +} +  } // End of namespace Pegasus diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h index 8ab891df9c..5074aaba09 100644 --- a/engines/pegasus/pegasus.h +++ b/engines/pegasus/pegasus.h @@ -50,6 +50,7 @@ class VideoManager;  class GraphicsManager;  class Idler;  class Cursor; +class TimeBase;  static const int kViewScreenOffset = 64; @@ -85,6 +86,9 @@ public:  	void addIdler(Idler *idler);  	void removeIdler(Idler *idler); +	void addTimeBase(TimeBase *timeBase); +	void removeTimeBase(TimeBase *timeBase); +  protected:  	Common::Error run(); @@ -141,6 +145,9 @@ private:  	// Items  	void createItems();  	void createItem(tItemID itemID, tNeighborhoodID neighborhoodID, tRoomID roomID, tDirectionConstant direction); + +	// TimeBases +	Common::List<TimeBase *> _timeBases;  };  } // End of namespace Pegasus diff --git a/engines/pegasus/timers.cpp b/engines/pegasus/timers.cpp index 5908854d13..fe487e90d2 100755 --- a/engines/pegasus/timers.cpp +++ b/engines/pegasus/timers.cpp @@ -24,6 +24,7 @@   */  #include "pegasus/pegasus.h" +#include "pegasus/notification.h"  #include "pegasus/timers.h"  namespace Pegasus { @@ -50,4 +51,285 @@ void Idler::stopIdling() {  	}  } +TimeBase::TimeBase(const TimeScale preferredScale) { +	_preferredScale = preferredScale; +	_callBackList = 0; +	_paused = false; +	_flags = 0; +	((PegasusEngine *)g_engine)->addTimeBase(this); +} + +TimeBase::~TimeBase() { +	if (_master) +		_master->_slaves.remove(this); + +	((PegasusEngine *)g_engine)->removeTimeBase(this); +	disposeAllCallBacks(); + +	// TODO: Remove slaves? Make them remove themselves? +} + +void TimeBase::setTime(const TimeValue time, const TimeScale scale) { +	// So, we're saying the *current* time from g_system->getMillis() is +	// what time/scale is. Which means we need to subtract time/scale from +	// the offset so that g_system->getMillis() - _currentOffset is +	// equal to time/scale. +	_timeOffset = g_system->getMillis() - time * 1000 / ((scale == 0) ? _preferredScale : scale); + +	// TODO: Also adjust the slaves' offsets (once we're actually using the +	// masters for calculating time) +} + +TimeValue TimeBase::getTime(const TimeScale scale) { +	if (_paused) +		return _pausedTime; + +	Common::Rational normalTime = Common::Rational((g_system->getMillis() - _timeOffset) * ((scale == 0) ? _preferredScale : scale), 1000); + +	// Adjust it according to our rate +	return (normalTime * getEffectiveRate()).toInt(); +} + +void TimeBase::setRate(const Common::Rational rate) { +	if (rate == 0) { +		_paused = false; +		_timeOffset = 0; +	} else if (_timeOffset != 0) { +		// Convert the time from the old rate to the new rate +		_timeOffset = g_system->getMillis() - (rate * (g_system->getMillis() - _timeOffset) / _rate).toInt(); +	} else { +		// TODO: Check this +		setTime(_startTime, _startScale); +	} + +	_rate = rate; +} + +Common::Rational TimeBase::getEffectiveRate() const { +	return _rate * ((_master == 0) ? 1 : _master->getEffectiveRate()); +} + +void TimeBase::start() { +	if (_paused) +		_pausedRate = 1; +	else +		setRate(1); +} + +void TimeBase::stop() { +	setRate(0); +	_paused = false; +} + +void TimeBase::pause() { +	if (isRunning() && !_paused) { +		_pausedRate = getRate(); +		stop(); +		_pausedTime = getTime(); +		_paused = true; +	} +} + +void TimeBase::resume() { +	if (_paused) { +		setRate(_pausedRate); +		_paused = false; +	} +} + +bool TimeBase::isRunning() { +	if (_paused && _pausedRate != 0) +		return true; + +	Common::Rational rate = getRate(); + +	if (rate == 0) +		return false; + +	if (getFlags() & kLoopTimeBase) +		return true; + +	if (rate > 0) +		return getTime() < getStop(); + +	return getTime() > getStart(); +} + +void TimeBase::setStart(const TimeValue startTime, const TimeScale scale) { +	_startTime = startTime; +	_startScale = (scale == 0) ? _preferredScale : scale; +} + +TimeValue TimeBase::getStart(const TimeScale scale) const { +	if (scale) +		return _startTime * scale / _startScale; + +	return _startTime * _preferredScale / _startScale; +} + +void TimeBase::setStop(const TimeValue stopTime, const TimeScale scale) { +	_stopTime = stopTime; +	_stopScale = (scale == 0) ? _preferredScale : scale; +} + +TimeValue TimeBase::getStop(const TimeScale scale) const { +	if (scale) +		return _stopTime * scale / _stopScale; + +	return _stopTime * _preferredScale / _stopScale; +} + +void TimeBase::setSegment(const TimeValue startTime, const TimeValue stopTime, const TimeScale scale) { +	setStart(startTime, scale); +	setStop(stopTime, scale); +} + +void TimeBase::getSegment(TimeValue &startTime, TimeValue &stopTime, const TimeScale scale) const { +	startTime = getStart(scale); +	stopTime = getStop(scale); +} + +TimeValue TimeBase::getDuration(const TimeScale scale) const { +	TimeValue startTime, stopTime; +	getSegment(startTime, stopTime, scale); +	return stopTime - startTime; +} + +void TimeBase::setMasterTimeBase(TimeBase *tb) { +	// TODO: We're just ignoring the master (except for effective rate) +	// for now to simplify things +	if (_master) +		_master->_slaves.remove(this); + +	_master = tb; + +	if (_master) +		_master->_slaves.push_back(this); +} + +void TimeBase::checkCallBacks() { +	uint32 time = getTime(); +	uint32 startTime = getStart(); +	uint32 stopTime = getStop(); + +	for (TimeBaseCallBack *runner = _callBackList; runner != 0; runner = runner->_nextCallBack) { +		if (runner->_type == kCallBackAtTime && runner->_trigger == kTriggerTimeFwd) { +			if (time >= (runner->_param2 * _preferredScale / runner->_param3) && getRate() > 0) +				runner->callBack(); +		} else if (runner->_type == kCallBackAtExtremes) { +			if (runner->_trigger == kTriggerAtStop) { +				if (time >= stopTime) +					runner->callBack(); +			} else if (runner->_trigger == kTriggerAtStart) { +				if (time <= startTime) +					runner->callBack(); +			} +		} +	} + +	if (getFlags() & kLoopTimeBase) { +		// Loop +		if (time >= startTime) +			setTime(stopTime); +		else if (time <= stopTime) +			setTime(startTime); +	} +} + +//	Protected functions only called by TimeBaseCallBack. + +void TimeBase::addCallBack(TimeBaseCallBack *callBack) { +	callBack->_nextCallBack = _callBackList; +	_callBackList = callBack; +} + +void TimeBase::removeCallBack(TimeBaseCallBack *callBack) {	 +	if (_callBackList == callBack) { +		_callBackList = callBack->_nextCallBack; +	} else { +		TimeBaseCallBack *runner, *prevRunner; +	 +		for (runner = _callBackList->_nextCallBack, prevRunner = _callBackList; runner != callBack; prevRunner = runner, runner = runner->_nextCallBack) +			; + +		prevRunner->_nextCallBack = runner->_nextCallBack; +	} + +	callBack->_nextCallBack = 0; +} + +void TimeBase::disposeAllCallBacks() { +	TimeBaseCallBack *nextRunner; +	 +	for (TimeBaseCallBack *runner = _callBackList; runner != 0; runner = nextRunner) { +		nextRunner = runner->_nextCallBack; +		runner->disposeCallBack(); +		runner->_nextCallBack = 0; +	} + +	_callBackList = 0; +} + +TimeBaseCallBack::TimeBaseCallBack() { +	_timeBase = 0; +	_nextCallBack = 0; +	_trigger = kTriggerNone; +	_type = kCallBackNone; +} + +TimeBaseCallBack::~TimeBaseCallBack() { +	releaseCallBack(); +} + +void TimeBaseCallBack::initCallBack(TimeBase *tb, CallBackType type) { +	releaseCallBack(); +	_timeBase = tb; +	_timeBase->addCallBack(this); +	_type = type; +} + +void TimeBaseCallBack::releaseCallBack() { +	if (_timeBase) +		_timeBase->removeCallBack(this); +	disposeCallBack(); +} + +void TimeBaseCallBack::disposeCallBack() { +	_timeBase = 0; +} + +void TimeBaseCallBack::scheduleCallBack(CallBackTrigger trigger, uint32 param2, uint32 param3) { +	// TODO: Rename param2/param3? +	_trigger = trigger; +	_param2 = param2; +	_param3 = param3; +} + +void TimeBaseCallBack::cancelCallBack() { +	_trigger = kTriggerNone; +} + +IdlerTimeBase::IdlerTimeBase() { +	_lastTime = 0xffffffff; +	startIdling(); +} + +void IdlerTimeBase::useIdleTime() {	 +	uint32 currentTime = getTime(); +	if (currentTime != _lastTime) { +		_lastTime = currentTime; +		timeChanged(_lastTime); +	} +} + +NotificationCallBack::NotificationCallBack() { +	_callBackFlag = 0; +	_notifier = 0; +} + +void NotificationCallBack::callBack() { +	if (_notifier) +		_notifier->setNotificationFlags(_callBackFlag, _callBackFlag); +} +  } // End of namespace Pegasus diff --git a/engines/pegasus/timers.h b/engines/pegasus/timers.h index e4bb41086f..9ce3093820 100755 --- a/engines/pegasus/timers.h +++ b/engines/pegasus/timers.h @@ -26,6 +26,10 @@  #ifndef PEGASUS_TIMERS_H  #define PEGASUS_TIMERS_H +#include "common/rational.h" + +#include "pegasus/constants.h" +  namespace Pegasus {  class Idler { @@ -45,6 +49,168 @@ protected:  	bool _isIdling;  }; +enum { +	kLoopTimeBase           = 1, +	kPalindromeLoopTimeBase = 2, +	kMaintainTimeBaseZero   = 4 +}; + +class TimeBaseCallBack; + +class TimeBase { +friend class TimeBaseCallBack; +public: +	TimeBase(const TimeScale = kDefaultTimeScale); +	virtual ~TimeBase(); +	 +	virtual void setTime(const TimeValue, const TimeScale = 0); +	virtual TimeValue getTime(const TimeScale = 0); +	 +	virtual void setScale(const TimeScale scale) { _preferredScale = scale; } +	virtual TimeScale getScale() const { return _preferredScale; } +	 +	virtual void setRate(const Common::Rational); +	virtual Common::Rational getRate() const { return _rate; } +	 +	virtual void start(); +	virtual void stop(); +	virtual bool isRunning(); +	 +	virtual void pause(); +	virtual void resume(); +	bool isPaused() const { return _paused; } +	 +	virtual void setFlags(const uint32 flags) { _flags = flags; } +	virtual uint32 getFlags() const { return _flags; } +	 +	virtual void setStart(const TimeValue, const TimeScale = 0); +	virtual TimeValue getStart(const TimeScale = 0) const; +	 +	virtual void setStop(const TimeValue, const TimeScale = 0); +	virtual TimeValue getStop(const TimeScale = 0) const; +	 +	virtual void setSegment(const TimeValue, const TimeValue, const TimeScale = 0); +	virtual void getSegment(TimeValue&, TimeValue&, const TimeScale = 0) const; +	 +	virtual TimeValue getDuration(const TimeScale = 0) const; + +	virtual void setMasterTimeBase(TimeBase *timeBase); +		 +	void disposeAllCallBacks(); + +	// ScummVM's API additions (to replace the need for actual timers) +	void checkCallBacks(); + +protected: +	void addCallBack(TimeBaseCallBack *); +	void removeCallBack(TimeBaseCallBack *); + +	TimeBase *_master; +	TimeScale _preferredScale; +	TimeBaseCallBack *_callBackList; +	Common::Rational _rate, _pausedRate; +	bool _paused; +	uint32 _startTime, _startScale; +	uint32 _stopTime, _stopScale; +	int32 _timeOffset; +	uint32 _flags; +	TimeValue _pausedTime; + +private: +	Common::Rational getEffectiveRate() const; + +	Common::List<TimeBase *> _slaves; +}; + +// Type passed to initCallBack() +enum CallBackType { +	kCallBackNone = 0, +	kCallBackAtTime = 1, +	kCallBackAtExtremes = 4 +}; + +// Trigger passed to scheduleCallBack() +enum CallBackTrigger { +	kTriggerNone = 0, + +	// AtTime flags +	kTriggerTimeFwd = 1, + +	// AtExtremes flags +	kTriggerAtStart = 1, +	kTriggerAtStop = 2 +}; + +class TimeBaseCallBack { +friend class TimeBase; + +public: +	TimeBaseCallBack(); +	virtual ~TimeBaseCallBack(); + +	void initCallBack(TimeBase *, CallBackType type); + +	void releaseCallBack(); + +	void scheduleCallBack(CallBackTrigger trigger, uint32 param2, uint32 param3); +	void cancelCallBack(); + +protected: +	virtual void callBack() = 0; + +	TimeBase *_timeBase; +	 +	// Owned and operated by TimeBase; +	TimeBaseCallBack *_nextCallBack; + +	// Our storage of the QuickTime timer crap +	CallBackType _type; +	CallBackTrigger _trigger; +	uint32 _param2, _param3; + +private: +	void disposeCallBack(); +}; + +class IdlerTimeBase : public Idler, public TimeBase { +public: +	IdlerTimeBase(); +	virtual ~IdlerTimeBase() { stopIdling(); } + +	TimeValue getLastTime() const { return _lastTime; } + +protected: +	virtual void useIdleTime(); +	virtual void timeChanged(const TimeValue) {} +	 +	TimeValue _lastTime; + +}; + +class Notification; + +class NotificationCallBack : public TimeBaseCallBack { +public: +	NotificationCallBack(); +	virtual ~NotificationCallBack() {} +	 +	void setNotification(Notification *notifier) { _notifier = notifier; } + +	void setCallBackFlag(const tNotificationFlags flag) { _callBackFlag = flag; } +	tNotificationFlags getCallBackFlag() const { return _callBackFlag; } +	 +protected: +	void callBack(); +	 +	Notification *_notifier; +	tNotificationFlags _callBackFlag; +}; + +class DynamicElement : public TimeBase { +public: +	TimeValue percentSeconds(const uint32 percent) { return getScale() * percent / 100; } +}; +  } // End of namespace Pegasus  #endif | 
