123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "environment/timeOfDay.h"
- #include "console/consoleTypes.h"
- #include "core/stream/bitStream.h"
- #include "T3D/gameBase/gameConnection.h"
- #include "environment/sun.h"
- #include "console/engineAPI.h"
- TimeOfDayUpdateSignal TimeOfDay::smTimeOfDayUpdateSignal;
- IMPLEMENT_CO_NETOBJECT_V1(TimeOfDay);
- ConsoleDocClass( TimeOfDay,
- "@brief Environmental object that triggers a day/night cycle in level.\n\n"
- "@note TimeOfDay only works in Advanced Lighting with a Sub object or ScatterSky\n\n"
- "@tsexample\n"
- "new TimeOfDay(tod)\n"
- "{\n"
- " axisTilt = \"23.44\";\n"
- " dayLength = \"120\";\n"
- " startTime = \"0.15\";\n"
- " time = \"0.15\";\n"
- " play = \"0\";\n"
- " azimuthOverride = \"572.958\";\n"
- " dayScale = \"1\";\n"
- " nightScale = \"1.5\";\n"
- " position = \"598.399 550.652 196.297\";\n"
- " rotation = \"1 0 0 0\";\n"
- " scale = \"1 1 1\";\n"
- " canSave = \"1\";\n"
- " canSaveDynamicFields = \"1\";\n"
- "};\n"
- "@endtsexample\n\n"
- "@ingroup enviroMisc"
- );
- TimeOfDay::TimeOfDay()
- : mStartTimeOfDay( 0.5f ), // High noon
- mDayLen( 120.0f ), // 2 minutes
- mAxisTilt( 23.44f ), // 35 degree tilt
- mAzimuth( 0.0f ),
- mElevation( 0.0f ),
- mTimeOfDay( 0.0f ), // initialized to StartTimeOfDay in onAdd
- mDayScale( 1.0f ),
- mPlay( true ),
- mNightScale( 1.5f ),
- mAnimateTime( 0.0f ),
- mAnimateSpeed( 0.0f ),
- mAnimate( false )
- {
- mNetFlags.set( Ghostable | ScopeAlways );
- mTypeMask = EnvironmentObjectType;
- // Sets the sun vector directly overhead for lightmap generation
- // The value of mSunVector is grabbed by the terrain lighting stuff.
- /*
- F32 ele, azi;
- ele = azi = TORADIANS(90);
- MathUtils::getVectorFromAngles(mSunVector, azi, ele);
- */
- mPrevElevation = 0;
- mNextElevation = 0;
- mAzimuthOverride = 1.0f;
- _initColors();
- }
- TimeOfDay::~TimeOfDay()
- {
- }
- bool TimeOfDay::setTimeOfDay( void *object, const char *index, const char *data )
- {
- TimeOfDay *tod = static_cast<TimeOfDay*>(object);
- tod->setTimeOfDay( dAtof( data ) );
- return false;
- }
- bool TimeOfDay::setPlay( void *object, const char *index, const char *data )
- {
- TimeOfDay *tod = static_cast<TimeOfDay*>(object);
- tod->setPlay( dAtob( data ) );
- return false;
- }
- bool TimeOfDay::setDayLength( void *object, const char *index, const char *data )
- {
- TimeOfDay *tod = static_cast<TimeOfDay*>(object);
- F32 length = dAtof( data );
- if( length != 0 )
- tod->setDayLength( length );
- return false;
- }
- void TimeOfDay::initPersistFields()
- {
- addGroup( "TimeOfDay" );
- addField( "axisTilt", TypeF32, Offset( mAxisTilt, TimeOfDay ),
- "The angle in degrees between global equator and tropic." );
- addProtectedField( "dayLength", TypeF32, Offset( mDayLen, TimeOfDay ), &setDayLength, &defaultProtectedGetFn,
- "The length of a virtual day in real world seconds." );
- addField( "startTime", TypeF32, Offset( mStartTimeOfDay, TimeOfDay ),
- "" );
- addProtectedField( "time", TypeF32, Offset( mTimeOfDay, TimeOfDay ), &setTimeOfDay, &defaultProtectedGetFn, "Current time of day." );
- addProtectedField( "play", TypeBool, Offset( mPlay, TimeOfDay ), &setPlay, &defaultProtectedGetFn, "True when the TimeOfDay object is operating." );
- addField( "azimuthOverride", TypeF32, Offset( mAzimuthOverride, TimeOfDay ), "" );
- addField( "dayScale", TypeF32, Offset( mDayScale, TimeOfDay ), "Scalar applied to time that elapses while the sun is up." );
- addField( "nightScale", TypeF32, Offset( mNightScale, TimeOfDay ), "Scalar applied to time that elapses while the sun is down." );
- endGroup( "TimeOfDay" );
- Parent::initPersistFields();
- }
- void TimeOfDay::consoleInit()
- {
- Parent::consoleInit();
- //addVariable( "$TimeOfDay::currentTime", &TimeOfDay::smCurrentTime );
- //addVariable( "$TimeOfDay::timeScale", TypeF32, &TimeOfDay::smTimeScale );
- }
- void TimeOfDay::inspectPostApply()
- {
- _updatePosition();
- setMaskBits( OrbitMask );
- }
- void TimeOfDay::_onGhostAlwaysDone()
- {
- _updatePosition();
- }
- bool TimeOfDay::onAdd()
- {
- if ( !Parent::onAdd() )
- return false;
-
- // The server initializes to the specified starting values.
- // The client initializes itself to the server time from
- // unpackUpdate.
- if ( isServerObject() )
- {
- mTimeOfDay = mStartTimeOfDay;
- _updatePosition();
- }
- // We don't use a bounds.
- setGlobalBounds();
- resetWorldBox();
- addToScene();
- // Lets receive ghost events so we can resolve
- // the sun object.
- if ( isClientObject() )
- NetConnection::smGhostAlwaysDone.notify( this, &TimeOfDay::_onGhostAlwaysDone );
- if ( isServerObject() )
- Con::executef( this, "onAdd" );
- setProcessTick( true );
- return true;
- }
- void TimeOfDay::onRemove()
- {
- if ( isClientObject() )
- NetConnection::smGhostAlwaysDone.remove( this, &TimeOfDay::_onGhostAlwaysDone );
- removeFromScene();
- Parent::onRemove();
- }
- U32 TimeOfDay::packUpdate(NetConnection *conn, U32 mask, BitStream *stream )
- {
- U32 retMask = Parent::packUpdate( conn, mask, stream );
- if ( stream->writeFlag( mask & OrbitMask ) )
- {
- stream->write( mStartTimeOfDay );
- stream->write( mDayLen );
- stream->write( mTimeOfDay );
- stream->write( mAxisTilt );
- stream->write( mAzimuthOverride );
- stream->write( mDayScale );
- stream->write( mNightScale );
- stream->writeFlag( mPlay );
- }
- if ( stream->writeFlag( mask & AnimateMask ) )
- {
- stream->write( mAnimateTime );
- stream->write( mAnimateSpeed );
- }
- return retMask;
- }
- void TimeOfDay::unpackUpdate( NetConnection *conn, BitStream *stream )
- {
- Parent::unpackUpdate( conn, stream );
- if ( stream->readFlag() ) // OrbitMask
- {
- stream->read( &mStartTimeOfDay );
- stream->read( &mDayLen );
- stream->read( &mTimeOfDay );
- stream->read( &mAxisTilt );
- stream->read( &mAzimuthOverride );
- stream->read( &mDayScale );
- stream->read( &mNightScale );
- mPlay = stream->readFlag();
- _updatePosition();
- }
- if ( stream->readFlag() ) // AnimateMask
- {
- F32 time, speed;
- stream->read( &time );
- stream->read( &speed );
- if( isProperlyAdded() )
- animate( time, speed );
- }
- }
- void TimeOfDay::processTick( const Move *move )
- {
- if ( mAnimate )
- {
- F32 current = mTimeOfDay * 360.0f;
- F32 next = current + (mAnimateSpeed * TickSec);
- // Protect for wrap around.
- while ( next > 360.0f )
- next -= 360.0f;
- // Clamp to make sure we don't pass the target time.
- if ( next >= mAnimateTime )
- {
- next = mAnimateTime;
- mAnimate = false;
- }
- // Set the new time of day.
- mTimeOfDay = next / 360.0f;
- _updatePosition();
- _updateTimeEvents();
- if ( !mAnimate && isServerObject() )
- Con::executef( this, "onAnimateDone" );
- }
- else if ( mPlay )
- {
- F32 dt = TickSec;
- F32 current = mRadToDeg( mNextElevation );
- if ( current > 350.0f || ( 0.0f <= current && current < 190.0f ) )
- dt *= mDayScale;
- else
- dt *= mNightScale;
- mTimeOfDay += dt / mDayLen;
- // It could be possible for more than a full day to
- // pass in a single advance time, so I put this inside a loop
- // but timeEvents will not actually be called for the
- // skipped day.
- while ( mTimeOfDay > 1.0f )
- mTimeOfDay -= 1.0f;
- _updatePosition();
- _updateTimeEvents();
- }
- else
- _updatePosition();
- }
- void TimeOfDay::_updatePosition()
- {
- mPrevElevation = mNextElevation;
- if ( mFabs( mAzimuthOverride ) )
- {
- mElevation = mDegToRad( mTimeOfDay * 360.0f );
- mAzimuth = mAzimuthOverride;
- mNextElevation = mElevation; // already normalized
- }
- else
- {
- //// Full azimuth/elevation calculation.
- //// calculate sun decline and meridian angle (in radians)
- //F32 sunDecline = mSin( M_2PI * mTimeOfYear ) * mDegToRad( mAxisTilt );
- //F32 meridianAngle = mTimeOfDay * M_2PI - mDegToRad( mLongitude );
- //// calculate the elevation and azimuth (in radians)
- //mElevation = _calcElevation( mDegToRad( mLatitude ), sunDecline, meridianAngle );
- //mAzimuth = _calcAzimuth( mDegToRad( mLatitude ), sunDecline, meridianAngle );
- // Simplified azimuth/elevation calculation.
- // calculate sun decline and meridian angle (in radians)
- F32 sunDecline = mDegToRad( mAxisTilt );
- F32 meridianAngle = mTimeOfDay * M_2PI;
- // calculate the elevation and azimuth (in radians)
- mElevation = _calcElevation( 0.0f, sunDecline, meridianAngle );
- mAzimuth = _calcAzimuth( 0.0f, sunDecline, meridianAngle );
- // calculate 'normalized' elevation (0=sunrise, PI/2=zenith, PI=sunset, 3PI/4=nadir)
- F32 normElevation = M_PI_F * mElevation / ( 2 * _calcElevation( 0.0f, sunDecline, 0.0f ) );
- if ( mAzimuth > M_PI_F )
- normElevation = M_PI_F - normElevation;
- else if ( mElevation < 0 )
- normElevation = M_2PI_F + normElevation;
- mNextElevation = normElevation;
- }
- // Only the client updates the sun position!
- if ( isClientObject() )
- smTimeOfDayUpdateSignal.trigger( this, mTimeOfDay );
- }
- F32 TimeOfDay::_calcElevation( F32 lat, F32 dec, F32 mer )
- {
- return mAsin( mSin(lat) * mSin(dec) + mCos(lat) * mCos(dec) * mCos(mer) );
- }
- F32 TimeOfDay::_calcAzimuth( F32 lat, F32 dec, F32 mer )
- {
- // Add PI to normalize this from the range of -PI/2 to PI/2 to 0 to 2 * PI;
- return mAtan2( mSin(mer), mCos(mer) * mSin(lat) - mTan(dec) * mCos(lat) ) + M_PI_F;
- }
- void TimeOfDay::_getSunColor( LinearColorF *outColor ) const
- {
- const COLOR_TARGET *ct = NULL;
- F32 ele = mClampF( M_2PI_F - mNextElevation, 0.0f, M_PI_F );
- F32 phase = -1.0f;
- F32 div;
- if (!mColorTargets.size())
- {
- outColor->set(1.0f,1.0f,1.0f);
- return;
- }
- if (mColorTargets.size() == 1)
- {
- ct = &mColorTargets[0];
- outColor->set(ct->color.red, ct->color.green, ct->color.blue);
- return;
- }
- //simple check
- if ( mColorTargets[0].elevation != 0.0f )
- {
- AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians");
- outColor->set(1.0f, 1.0f, 1.0f);
- //mBandMod = 1.0f;
- //mCurrentBandColor = color;
- return;
- }
- if ( mColorTargets[mColorTargets.size()-1].elevation != M_PI_F )
- {
- AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI");
- outColor->set(1.0f, 1.0f, 1.0f);
- //mBandMod = 1.0f;
- //mCurrentBandColor = color;
- return;
- }
- //we need to find the phase and interp... also loop back around
- U32 count=0;
- for (;count < mColorTargets.size() - 1; count++)
- {
- const COLOR_TARGET *one = &mColorTargets[count];
- const COLOR_TARGET *two = &mColorTargets[count+1];
- if (ele >= one->elevation && ele <= two->elevation)
- {
- div = two->elevation - one->elevation;
-
- //catch bad input divide by zero
- if ( mFabs( div ) < 0.01f )
- div = 0.01f;
-
- phase = (ele - one->elevation) / div;
- outColor->interpolate( one->color, two->color, phase );
- //mCurrentBandColor.interpolate(one->bandColor, two->bandColor, phase);
- //mBandMod = one->bandMod * (1.0f - phase) + two->bandMod * phase;
- return;
- }
- }
- AssertFatal(0,"This isn't supposed to happen");
- }
- void TimeOfDay::_initColors()
- {
- // NOTE: The elevation targets represent distances
- // from PI/2 radians (strait up).
- LinearColorF c;
- LinearColorF bc;
- // e is for elevation
- F32 e = M_PI_F / 13.0f; // (semicircle in radians)/(number of color target entries);
- // Day
- c.set(1.0f,1.0f,1.0f);
- _addColorTarget(0, c, 1.0f, c); // High noon at equanox
- c.set(.9f,.9f,.9f);
- _addColorTarget(e * 1.0f, c, 1.0f, c);
- c.set(.9f,.9f,.9f);
- _addColorTarget(e * 2.0f, c, 1.0f, c);
- c.set(.8f,.75f,.75f);
- _addColorTarget(e * 3.0f, c, 1.0f, c);
- c.set(.7f,.65f,.65f);
- _addColorTarget(e * 4.0f, c, 1.0f, c);
- //Dawn and Dusk (3 entries)
- c.set(.7f,.65f,.65f);
- bc.set(.8f,.6f,.3f);
- _addColorTarget(e * 5.0f, c, 3.0f, bc);
- c.set(.65f,.54f,.4f);
- bc.set(.75f,.5f,.4f);
- _addColorTarget(e * 6.0f, c, 2.75f, bc);
- c.set(.55f,.45f,.25f);
- bc.set(.65f,.3f,.3f);
- _addColorTarget(e * 7.0f, c, 2.5f, bc);
- //NIGHT
- c.set(.3f,.3f,.3f);
- bc.set(.7f,.4f,.2f);
- _addColorTarget(e * 8.0f, c, 1.25f, bc);
- c.set(.25f,.25f,.3f);
- bc.set(.8f,.3f,.2f);
- _addColorTarget(e * 9.0f, c, 1.00f, bc);
- c.set(.25f,.25f,.4f);
- _addColorTarget(e * 10.0f, c, 1.0f, c);
- c.set(.2f,.2f,.35f);
- _addColorTarget(e * 11.0f, c, 1.0f, c);
- c.set(.15f,.15f,.2f);
- _addColorTarget(M_PI_F, c, 1.0f, c); // Midnight at equanox.
- }
- void TimeOfDay::_addColorTarget( F32 ele, const LinearColorF &color, F32 bandMod, const LinearColorF &bandColor )
- {
- COLOR_TARGET newTarget;
- newTarget.elevation = ele;
- newTarget.color = color;
- newTarget.bandMod = bandMod;
- newTarget.bandColor = bandColor;
- mColorTargets.push_back(newTarget);
- }
- void TimeOfDay::_updateTimeEvents()
- {
- if ( mTimeEvents.empty() )
- return;
- // Get the prev, next elevation in degrees since TimeOfDayEvent is specified
- // in degrees.
- F32 prevElevation = mRadToDeg( mPrevElevation );
- F32 nextElevation = mRadToDeg( mNextElevation );
- // If prevElevation is less than nextElevation then its the next day.
- // Unroll it so we can just loop forward in time and simplify our loop.
- if ( nextElevation < prevElevation )
- nextElevation += 360.0f;
- const U32 evtCount = mTimeEvents.size();
- // Find where in the event list we need to start...
- // The first timeEvent with elevation greater than our previous elevation.
-
- U32 start = 0;
- for ( ; start < evtCount; start++ )
- {
- if ( mTimeEvents[start].triggerElevation > prevElevation )
- break;
- }
- bool onNextDay = false;
- // Nothing between prevElevation and the end of the day...
- // Check between start of the day and nextElevation...
- if ( start == evtCount )
- {
- start = 0;
- for ( ; start < evtCount; start++ )
- {
- if ( mTimeEvents[start].triggerElevation <= nextElevation )
- {
- onNextDay = true;
- break;
- }
- }
- }
- // No events were hit...
- if ( start == evtCount )
- return;
- U32 itr = start;
- while ( true )
- {
- TimeOfDayEvent &timeEvent = mTimeEvents[itr];
-
- F32 elev = timeEvent.triggerElevation;
- if ( onNextDay )
- elev += 360.0f;
- // Hit an event that happens later after nextElevation so we
- // have checked everything within the range and are done.
- if ( elev > nextElevation )
- break;
- // If its not greater than the nextElevation it must be less, and if
- // we are here we already know its greater than prevElevation.
-
- AssertFatal( elev >= prevElevation && elev <= nextElevation, "TimeOfDay::_updateTimeEvents - Logical error in here!" );
- AssertFatal( !timeEvent.deleteMe, "TimeOfDay::_updateTimeEvents - tried to fire the same event twice!" );
- _onTimeEvent( timeEvent.identifier );
- if ( timeEvent.oneShot )
- timeEvent.deleteMe = true;
- // On to the next time event...
- itr++;
- // We hit the end of the day?
- if ( itr == evtCount )
- {
- // We are already on the next day so we have checked everything.
- if ( onNextDay )
- break;
- // Check events for the next day
- else
- {
- itr = 0;
- onNextDay = true;
- }
- }
- }
- // Cleanup one-shot events that fired...
- for ( S32 i = 0; i < mTimeEvents.size(); i++ )
- {
- if ( mTimeEvents[i].deleteMe )
- {
- // Don't use erase_fast, there are ordered.
- mTimeEvents.erase( i );
- i--;
- }
- }
- }
- void TimeOfDay::addTimeEvent( F32 triggerElevation, const UTF8 *identifier )
- {
- // Insert in ascending order of elevation.
- // Note that having more than one TimeEvent with the same triggerElevation
- // may cause undefined behavior.
- TimeOfDayEvent *pEvent = NULL;
-
- if ( mTimeEvents.empty() || mTimeEvents.last().triggerElevation <= triggerElevation )
- {
- mTimeEvents.increment();
- pEvent = &mTimeEvents.last();
- }
- else
- {
- for ( S32 i = 0; i < mTimeEvents.size(); i++ )
- {
- if ( mTimeEvents[i].triggerElevation > triggerElevation )
- {
- mTimeEvents.insert( i );
- pEvent = &mTimeEvents[i];
- break;
- }
- }
- }
- AssertFatal( pEvent, "TimeOfDay::addTimeEvent - could not find place to insert event." );
- pEvent->triggerElevation = triggerElevation;
- pEvent->identifier = identifier;
- pEvent->oneShot = false;
-
- pEvent->deleteMe = false;
- }
- void TimeOfDay::setTimeOfDay( F32 time )
- {
- mTimeOfDay = time;
- while ( mTimeOfDay > 1.0f )
- mTimeOfDay -= 1.0f;
- while ( mTimeOfDay < 0.0f )
- mTimeOfDay += 1.0f;
- _updatePosition();
- //if ( isServerObject() )
- _updateTimeEvents();
- setMaskBits( OrbitMask );
- }
- void TimeOfDay::_onTimeEvent( const String &identifier )
- {
- // Client doesn't do onTimeEvent callbacks.
- if ( isClientObject() )
- return;
- String strCurrentTime = String::ToString( "%g", mTimeOfDay );
- F32 elevation = mRadToDeg( mNextElevation );
- while( elevation < 0 )
- elevation += 360.0f;
- while( elevation > 360.0f )
- elevation -= 360.0f;
- String strCurrentElevation = String::ToString( "%g", elevation );
- Con::executef( this, "onTimeEvent", identifier.c_str(), strCurrentTime.c_str(), strCurrentElevation.c_str() );
- }
- void TimeOfDay::animate( F32 time, F32 speed )
- {
- // Stop any existing animation... this one
- // becomes the new one.
- mAnimate = false;
- // Set the target time to hit.
- mAnimateTime = mClamp(time, 0.0f, 360.0f);
- F32 current = mTimeOfDay * 360.0f;
- F32 target = mAnimateTime;
- if ( target < current )
- target += 360.0f;
- // If we're already at the current time then
- // we have nothing more to do... the animation is here.
- F32 dif = target - current;
- if ( mIsZero( dif ) )
- return;
- // Start playback.
- mAnimateSpeed = speed;
- mAnimate = true;
- if ( isServerObject() )
- {
- Con::executef( this, "onAnimateStart" );
- setMaskBits( AnimateMask );
- }
- }
- DefineEngineMethod( TimeOfDay, addTimeOfDayEvent, void, (F32 elevation, const char *identifier ),,
- "" )
- {
- object->addTimeEvent( elevation, identifier );
- }
- DefineEngineMethod( TimeOfDay, setTimeOfDay, void, ( F32 time ),,
- "" )
- {
- object->setTimeOfDay( time );
- }
- DefineEngineMethod( TimeOfDay, setPlay, void, ( bool enabled ),,
- "")
- {
- object->setPlay( enabled );
- }
- DefineEngineMethod( TimeOfDay, setDayLength, void, ( F32 seconds ),,
- "" )
- {
- if ( seconds > 0.0f )
- object->setDayLength( seconds );
- }
- DefineEngineMethod( TimeOfDay, animate, void, ( F32 elevation, F32 degreesPerSecond ),,
- "")
- {
- object->animate( elevation, degreesPerSecond );
- }
|