Torque3D Documentation / _generateds / sfxPlayList.cpp

sfxPlayList.cpp

Engine/source/sfx/sfxPlayList.cpp

More...

Public Defines

define
FOR_EACH_SLOT()       (   = 0;  < NUM_SLOTS; ++  )

Public Variables

Public Functions

ConsoleDocClass(SFXPlayList , "@brief A datablock describing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> playback pattern of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sounds.\n\n</a>" "Playlists allow <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> define intricate playback patterns of invidual tracks and thus allow the sound system <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be " "easily used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> playing multiple sounds in single <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">operations.\n\n</a>" "As playlists are % SFXTracks, they can thus be used anywhere in the engine where sound data can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">assigned.\n\n</a>" "Each playlist can hold <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> maximum of 16 tracks. Longer playlists may be constructed by cascading lists, i.e. " "by creating <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> playlist that references other <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playlists.\n\n</a>" "Processing of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single playlist slot progresses in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> fixed set of steps that are invariably " "iterated through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each slot(except the slot is assigned <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> state and its state is deactivated;in " "this case, the controller will <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a6d2c3c030982c7aa276480da4522ae0f">exit</a> out of the slot directly):\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "< ol >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >delayIn:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >Waits <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> set amount of time before processing the slot. This is 0 by default and " "is determined by the #delayTimeIn(seconds <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wait) and #delayTimeInVariance(bounds on randomization) " "properties.</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >#transitionIn:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >Decides what <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> do @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> before playing the slot. Defaults <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> @c None which makes " "this stage <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> no-operation. Alternatively, the slot can be configured <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wait <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> playback of other " "slots <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> finish(@c Wait and @c WaitAll) or <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> stop playback of other slots(@c Stop and @c StopAll). " "Note that @c Wait and @c Stop always refer <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> that was last started by the list.</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >play:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >< p > Finally, the #track attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the slot is played. However, this will only @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> start " "playback of the track and then immediately move on <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the next stage. It will @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> not wait <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the " "track <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> finish playing. Note also that depending on the @c replay setting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the slot, this " "stage may pick up <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> that is already playing on the slot rather than starting <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> one.</p > " "< p >Several slot properties(fade times, min/max distance, and volume/pitch scale) are used in this stage.</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >delayOut:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >Waits <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> set amount of time before transitioning out of the slot. This works the " "same as @c delayIn and is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 0 by default(i.e. no delay).</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >#transitionOut:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >Decides what <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> do @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> after playing the slot. This works like #transitionIn.</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "</ol >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "This is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> key difference <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> playlists in normal music players where upon reaching <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> certain slot, the slot " "will immediately play and the player then wait <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> playback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> finish before moving on <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the next <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slot.\n\n</a>" " @note Be aware that time limits set on slot delays are soft limits. The sound system updates sound sources in discrete " "(and equally system update frequency dependent) intervals which thus determines the granularity at which " "time-outs can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">handled.\n\n</a>" " @section SFXPlayList_randomization <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Randomization\n\n</a>" "For greater variety, many of the values <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> individual slots may be given <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> randomization limit that will " "trigger <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dynamic variance of the specified base <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n\n</a>" "Any given field @c xyz that may be randomized has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> corresponding field @c xyzVariance which is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> two-dimensional " "vector. The first number specifies the greatest <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> that may be subtracted from the given base <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a>(i.e. the @c xyz field) " "whereas the second number specifies the greatest <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> that may be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the base value. Between these two limits, " "<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> random number is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">generated.\n\n</a>" "The default variance settings of \"0 0\" will thus not allow <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add or subtract anything from the base <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> and " "effectively disable <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">randomization.\n\n</a>" "Randomization is re-evaluated on each cycle through <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">list.\n\n</a>" "@section SFXPlayList_states Playlists and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">States\n\n</a>" "A unique aspect of playlists is that they allow their playback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be tied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the changing set of active sound states. " "This feature enables playlists <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> basically connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> an extensible state machine that can be leveraged by the game " "code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> signal <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> multitude of different gameplay states with the audio system then automatically reacting <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> state " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transitions.\n\n</a>" "Playlists react <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> states in three <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ways:\n</a>" "- Before <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> controller starts processing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot it checks whether the slot is assigned <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> #state. If this is the " " case, the controller checks whether the particular state is active. If it is not, the entire slot is skipped. " "If it is, the controller goes on <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> process the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slot.\n</a>" "- If <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> controller is in one of the delay stages <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot that has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> #state assigned and the state is deactivated, " "the controller will stop the delay and skip any of the remaining processing stages <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slot.\n</a>" "- Once the play stage has been processed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot that has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> #state assigned, the slot 's #stateMode will determine " "what happens with the playing sound <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the slot 's state is deactivated <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a0e48c1f64b558d03d870367324920354">while</a> the sound is still <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playing.\n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "A simple example of how <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> make use of states in combination with playlists would be <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set up <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> playlist <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> background " "music that reacts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the mood of the current gameplay situation. For example, during combat, tenser music could play than " "during normal exploration. To set this up, different %SFXStates would represent different moods in the game and the " "background music playlist would have one slot set up <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each such mood. By making use of volume fades and the " " @c PauseWhenDeactivated # stateMode)
ImplementEnumType(SFXPlayListLoopMode , "Playlist behavior when description is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loop.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXDescription::isLooping\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::loopMode\n\n</a>" "@ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )
ImplementEnumType(SFXPlayListRandomMode , "Randomization pattern <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> apply <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> playlist slot playback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">order.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::random\n\n</a>" "@ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )
ImplementEnumType(SFXPlayListReplayMode , "Behavior when hitting the play stage of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot that is still playing from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previous <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">cycle.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::replay\n\n</a>" "@ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )
ImplementEnumType(SFXPlayListStateMode , "Reaction behavior when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> state is changed incompatibly on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot that has already started <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playing.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::stateMode\n\n</a>" "@ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )
ImplementEnumType(SFXPlayListTransitionMode , "Playlist behavior when transitioning in and out of invididual <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slots.\n\n</a>" "Transition behaviors apply when the playback controller starts processing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> playlist slot and when it ends processing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot. Using transition " " behaviors, playback can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">synchronized.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::transitionIn\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::transitionOut\n\n</a>" " @ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )

Detailed Description

Public Defines

FOR_EACH_SLOT()       (   = 0;  < NUM_SLOTS; ++  )

Public Variables

 EndImplementEnumType 

Public Functions

ConsoleDocClass(SFXPlayList , "@brief A datablock describing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> playback pattern of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sounds.\n\n</a>" "Playlists allow <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> define intricate playback patterns of invidual tracks and thus allow the sound system <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be " "easily used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> playing multiple sounds in single <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">operations.\n\n</a>" "As playlists are % SFXTracks, they can thus be used anywhere in the engine where sound data can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">assigned.\n\n</a>" "Each playlist can hold <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> maximum of 16 tracks. Longer playlists may be constructed by cascading lists, i.e. " "by creating <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> playlist that references other <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playlists.\n\n</a>" "Processing of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single playlist slot progresses in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> fixed set of steps that are invariably " "iterated through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each slot(except the slot is assigned <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> state and its state is deactivated;in " "this case, the controller will <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a6d2c3c030982c7aa276480da4522ae0f">exit</a> out of the slot directly):\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "< ol >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >delayIn:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >Waits <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> set amount of time before processing the slot. This is 0 by default and " "is determined by the #delayTimeIn(seconds <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wait) and #delayTimeInVariance(bounds on randomization) " "properties.</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >#transitionIn:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >Decides what <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> do @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> before playing the slot. Defaults <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> @c None which makes " "this stage <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> no-operation. Alternatively, the slot can be configured <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wait <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> playback of other " "slots <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> finish(@c Wait and @c WaitAll) or <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> stop playback of other slots(@c Stop and @c StopAll). " "Note that @c Wait and @c Stop always refer <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> that was last started by the list.</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >play:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >< p > Finally, the #track attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the slot is played. However, this will only @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> start " "playback of the track and then immediately move on <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the next stage. It will @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> not wait <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the " "track <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> finish playing. Note also that depending on the @c replay setting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the slot, this " "stage may pick up <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> that is already playing on the slot rather than starting <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> one.</p > " "< p >Several slot properties(fade times, min/max distance, and volume/pitch scale) are used in this stage.</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >delayOut:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >Waits <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> set amount of time before transitioning out of the slot. This works the " "same as @c delayIn and is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 0 by default(i.e. no delay).</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >#transitionOut:</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >< p >Decides what <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> do @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> after playing the slot. This works like #transitionIn.</p ></li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "</ol >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "This is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> key difference <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> playlists in normal music players where upon reaching <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> certain slot, the slot " "will immediately play and the player then wait <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> playback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> finish before moving on <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the next <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slot.\n\n</a>" " @note Be aware that time limits set on slot delays are soft limits. The sound system updates sound sources in discrete " "(and equally system update frequency dependent) intervals which thus determines the granularity at which " "time-outs can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">handled.\n\n</a>" " @section SFXPlayList_randomization <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Randomization\n\n</a>" "For greater variety, many of the values <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> individual slots may be given <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> randomization limit that will " "trigger <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dynamic variance of the specified base <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">value.\n\n</a>" "Any given field @c xyz that may be randomized has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> corresponding field @c xyzVariance which is <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> two-dimensional " "vector. The first number specifies the greatest <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> that may be subtracted from the given base <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a>(i.e. the @c xyz field) " "whereas the second number specifies the greatest <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> that may be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the base value. Between these two limits, " "<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> random number is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">generated.\n\n</a>" "The default variance settings of \"0 0\" will thus not allow <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add or subtract anything from the base <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> and " "effectively disable <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">randomization.\n\n</a>" "Randomization is re-evaluated on each cycle through <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">list.\n\n</a>" "@section SFXPlayList_states Playlists and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">States\n\n</a>" "A unique aspect of playlists is that they allow their playback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be tied <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the changing set of active sound states. " "This feature enables playlists <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> basically connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> an extensible state machine that can be leveraged by the game " "code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> signal <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> multitude of different gameplay states with the audio system then automatically reacting <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> state " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transitions.\n\n</a>" "Playlists react <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> states in three <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ways:\n</a>" "- Before <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> controller starts processing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot it checks whether the slot is assigned <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> #state. If this is the " " case, the controller checks whether the particular state is active. If it is not, the entire slot is skipped. " "If it is, the controller goes on <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> process the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slot.\n</a>" "- If <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> controller is in one of the delay stages <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot that has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> #state assigned and the state is deactivated, " "the controller will stop the delay and skip any of the remaining processing stages <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slot.\n</a>" "- Once the play stage has been processed <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot that has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> #state assigned, the slot 's #stateMode will determine " "what happens with the playing sound <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the slot 's state is deactivated <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a0e48c1f64b558d03d870367324920354">while</a> the sound is still <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playing.\n</a>" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "A simple example of how <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> make use of states in combination with playlists would be <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set up <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> playlist <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> background " "music that reacts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the mood of the current gameplay situation. For example, during combat, tenser music could play than " "during normal exploration. To set this up, different %SFXStates would represent different moods in the game and the " "background music playlist would have one slot set up <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> each such mood. By making use of volume fades and the " " @c PauseWhenDeactivated # stateMode)

IMPLEMENT_CO_DATABLOCK_V1(SFXPlayList )

ImplementEnumType(SFXPlayListLoopMode , "Playlist behavior when description is set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loop.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXDescription::isLooping\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::loopMode\n\n</a>" "@ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )

ImplementEnumType(SFXPlayListRandomMode , "Randomization pattern <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> apply <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> playlist slot playback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">order.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::random\n\n</a>" "@ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )

ImplementEnumType(SFXPlayListReplayMode , "Behavior when hitting the play stage of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot that is still playing from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> previous <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">cycle.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::replay\n\n</a>" "@ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )

ImplementEnumType(SFXPlayListStateMode , "Reaction behavior when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> state is changed incompatibly on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot that has already started <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">playing.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::stateMode\n\n</a>" "@ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )

ImplementEnumType(SFXPlayListTransitionMode , "Playlist behavior when transitioning in and out of invididual <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">slots.\n\n</a>" "Transition behaviors apply when the playback controller starts processing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> playlist slot and when it ends processing <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> slot. Using transition " " behaviors, playback can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">synchronized.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::transitionIn\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXPlayList::transitionOut\n\n</a>" " @ingroup <a href="/coding/file/sfxsystem_8h/#sfxsystem_8h_1a52e87f85ae30be82ffefd31b5c03e03d">SFX</a>" )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "sfx/sfxPlayList.h"
 25#include "sfx/sfxState.h"
 26#include "sfx/sfxTypes.h"
 27#include "core/stream/bitStream.h"
 28#include "math/mRandom.h"
 29#include "math/mathTypes.h"
 30
 31
 32IMPLEMENT_CO_DATABLOCK_V1( SFXPlayList );
 33
 34
 35ConsoleDocClass( SFXPlayList,
 36   "@brief A datablock describing a playback pattern of sounds.\n\n"
 37   
 38   "Playlists allow to define intricate playback patterns of invidual tracks and thus allow the sound system to be "
 39   "easily used for playing multiple sounds in single operations.\n\n"
 40   
 41   "As playlists are %SFXTracks, they can thus be used anywhere in the engine where sound data can be assigned.\n\n"
 42   
 43   "Each playlist can hold a maximum of 16 tracks.  Longer playlists may be constructed by cascading lists, i.e. "
 44   "by creating a playlist that references other playlists.\n\n"
 45      
 46   "Processing of a single playlist slot progresses in a fixed set of steps that are invariably "
 47   "iterated through for each slot (except the slot is assigned a state and its state is deactivated; in "
 48   "this case, the controller will exit out of the slot directly):\n\n"
 49   
 50   "<ol>\n"
 51      "<li><b>delayIn:</b><p>Waits a set amount of time before processing the slot. This is 0 by default and "
 52         "is determined by the #delayTimeIn (seconds to wait) and #delayTimeInVariance (bounds on randomization) "
 53         "properties.</p></li>\n"
 54      "<li><b>#transitionIn:</b><p>Decides what to do @b before playing the slot.  Defaults to @c None which makes "
 55         "this stage a no-operation.  Alternatively, the slot can be configured to wait for playback of other "
 56         "slots to finish (@c Wait and @c WaitAll) or to stop playback of other slots (@c Stop and @c StopAll). "
 57         "Note that @c Wait and @c Stop always refer to the source that was last started by the list.</p></li>\n"
 58      "<li><b>play:</b><p><p>Finally, the #track attached to the slot is played. However, this will only @b start "
 59         "playback of the track and then immediately move on to the next stage.  It will @b not wait for the "
 60         "track to finish playing.  Note also that depending on the @c replay setting for the slot, this "
 61         "stage may pick up a source that is already playing on the slot rather than starting a new one.</p> "
 62         "<p>Several slot properties (fade times, min/max distance, and volume/pitch scale) are used in this stage.</p></li>\n"
 63      "<li><b>delayOut:</b><p>Waits a set amount of time before transitioning out of the slot. This works the "
 64         "same as @c delayIn and is set to 0 by default (i.e. no delay).</p></li>\n"
 65      "<li><b>#transitionOut:</b><p>Decides what to do @b after playing the slot. This works like #transitionIn.</p></li>\n"
 66   "</ol>\n\n"
 67   
 68   "This is a key difference to playlists in normal music players where upon reaching a certain slot, the slot "
 69   "will immediately play and the player then wait for playback to finish before moving on to the next slot.\n\n"
 70      
 71   "@note Be aware that time limits set on slot delays are soft limits.  The sound system updates sound sources in discrete "
 72      "(and equally system update frequency dependent) intervals which thus determines the granularity at which "
 73      "time-outs can be handled.\n\n"
 74      
 75   "@section SFXPlayList_randomization Value Randomization\n\n"
 76   
 77   "For greater variety, many of the values for individual slots may be given a randomization limit that will "
 78   "trigger a dynamic variance of the specified base value.\n\n"
 79   
 80   "Any given field @c xyz that may be randomized has a corresponding field @c xyzVariance which is a two-dimensional "
 81   "vector.  The first number specifies the greatest value that may be subtracted from the given base value (i.e. the @c xyz field) "
 82   "whereas the second number specifies the greatest value that may be added to the base value.  Between these two limits, "
 83   "a random number is generated.\n\n"
 84   
 85   "The default variance settings of \"0 0\" will thus not allow to add or subtract anything from the base value and "
 86   "effectively disable randomization.\n\n"
 87      
 88   "Randomization is re-evaluated on each cycle through a list.\n\n"
 89
 90   "@section SFXPlayList_states Playlists and States\n\n"
 91   
 92   "A unique aspect of playlists is that they allow their playback to be tied to the changing set of active sound states. "
 93   "This feature enables playlists to basically connect to an extensible state machine that can be leveraged by the game "
 94   "code to signal a multitude of different gameplay states with the audio system then automatically reacting to state "
 95   "transitions.\n\n"
 96   
 97   "Playlists react to states in three ways:\n"
 98   
 99   "- Before a controller starts processing a slot it checks whether the slot is assigned a #state.  If this is the "
100      "case, the controller checks whether the particular state is active.  If it is not, the entire slot is skipped.  "
101      "If it is, the controller goes on to process the slot.\n"
102   "- If a controller is in one of the delay stages for a slot that has a #state assigned and the state is deactivated, "
103      "the controller will stop the delay and skip any of the remaining processing stages for the slot.\n"
104   "- Once the play stage has been processed for a slot that has a #state assigned, the slot's #stateMode will determine "
105      "what happens with the playing sound source if the slot's state is deactivated while the sound is still playing.\n"
106   "\n"
107   
108   "A simple example of how to make use of states in combination with playlists would be to set up a playlist for background "
109   "music that reacts to the mood of the current gameplay situation.  For example, during combat, tenser music could play than "
110   "during normal exploration.  To set this up, different %SFXStates would represent different moods in the game and the "
111   "background music playlist would have one slot set up for each such mood.  By making use of volume fades and the "
112   "@c PauseWhenDeactivated #stateMode, smooth transitions between the various audio tracks can be produced.\n\n"
113   
114   "@tsexample\n"
115   "// Create a play list from two SFXProfiles.\n"
116   "%playList = new SFXPlayList()\n"
117   "{\n"
118   "   // Use a looped description so the list playback will loop.\n"
119   "   description = AudioMusicLoop2D;\n"
120   "\n"
121   "   track[ 0 ] = Profile1;\n"
122   "   track[ 1 ] = Profile2;\n"
123   "};\n"
124   "\n"
125   "// Play the list.\n"
126   "sfxPlayOnce( %playList );\n"
127   "@endtsexample\n\n"
128
129   "@ref SFX_interactive\n\n"
130   
131   "@ingroup SFX"
132);
133
134
135ImplementEnumType( SFXPlayListLoopMode,
136   "Playlist behavior when description is set to loop.\n\n"
137   "@see SFXDescription::isLooping\n\n"
138   "@see SFXPlayList::loopMode\n\n"
139   "@ingroup SFX" )
140   { SFXPlayList::LOOP_All,                  "All",
141      "Loop over all slots, i.e. jump from last to first slot after all slots have played." },
142   { SFXPlayList::LOOP_Single,               "Single",
143      "Loop infinitely over the current slot.  Only useful in combination with either states or manual playlist control." },
144EndImplementEnumType;
145
146ImplementEnumType( SFXPlayListRandomMode,
147   "Randomization pattern to apply to playlist slot playback order.\n\n"
148   "@see SFXPlayList::random\n\n"
149   "@ingroup SFX" )
150   { SFXPlayList::RANDOM_NotRandom,          "NotRandom",
151      "Play slots in sequential order.  No randomization." },
152   { SFXPlayList::RANDOM_StrictRandom,       "StrictRandom",
153      "Play a strictly random selection of slots.\n\n"
154      "In this mode, a set of numSlotsToPlay random numbers between 0 and numSlotsToPlay-1 (inclusive), i.e. in the range of valid slot indices, is "
155      "generated and playlist slots are played back in the order of this list.  This allows the same slot to occur multiple times in a list and, "
156      "consequentially, allows for other slots to not appear at all in a given slot ordering." },
157   { SFXPlayList::RANDOM_OrderedRandom,      "OrderedRandom",
158      "Play all slots in the list in a random order.\n\n"
159      "In this mode, the @c numSlotsToPlay slots from the list with valid tracks assigned are put into a random order and played.  This guarantees "
160      "that each slots is played exactly once albeit at a random position in the total ordering." },
161EndImplementEnumType;
162
163ImplementEnumType( SFXPlayListTransitionMode,
164   "Playlist behavior when transitioning in and out of invididual slots.\n\n"
165   "Transition behaviors apply when the playback controller starts processing a playlist slot and when it ends processing a slot.  Using transition "
166   "behaviors, playback can be synchronized.\n\n"
167   "@see SFXPlayList::transitionIn\n\n"
168   "@see SFXPlayList::transitionOut\n\n"
169   "@ingroup SFX" )
170   { SFXPlayList::TRANSITION_None,           "None",
171      "No transition.  Immediately move on to processing the slot or immediately move on to the next slot." },
172   { SFXPlayList::TRANSITION_Wait,           "Wait",
173      "Wait for the sound source spawned last by this playlist to finish playing.  Then proceed." },
174   { SFXPlayList::TRANSITION_WaitAll,        "WaitAll",
175      "Wait for all sound sources currently spawned by the playlist to finish playing.  Then proceed." },
176   { SFXPlayList::TRANSITION_Stop,           "Stop",
177      "Stop the sound source spawned last by this playlist.  Then proceed." },
178   { SFXPlayList::TRANSITION_StopAll,        "StopAll",
179      "Stop all sound sources spawned by the playlist.  Then proceed." },
180EndImplementEnumType;
181
182ImplementEnumType( SFXPlayListReplayMode,
183   "Behavior when hitting the play stage of a slot that is still playing from a previous cycle.\n\n"
184   "@see SFXPlayList::replay\n\n"
185   "@ingroup SFX" )
186   { SFXPlayList::REPLAY_IgnorePlaying,      "IgnorePlaying",
187      "Ignore any sources that may already be playing on the slot and just create a new source." },
188   { SFXPlayList::REPLAY_RestartPlaying,     "RestartPlaying",
189      "Restart all sources that was last created for the slot." },
190   { SFXPlayList::REPLAY_KeepPlaying,        "KeepPlaying",
191      "Keep playing the current source(s) as if the source started last on the slot was created in this cycle.  For this, "
192      "the sources associated with the slot are brought to the top of the play stack." },
193   { SFXPlayList::REPLAY_StartNew,           "StartNew",
194      "Stop all sources currently playing on the slot and then create a new source." },
195   { SFXPlayList::REPLAY_SkipIfPlaying,      "SkipIfPlaying",
196      "If there are sources already playing on the slot, skip the play stage." },
197EndImplementEnumType;
198
199ImplementEnumType( SFXPlayListStateMode,
200   "Reaction behavior when a state is changed incompatibly on a slot that has already started playing.\n\n"
201   "@see SFXPlayList::stateMode\n\n"
202   "@ingroup SFX" )
203   { SFXPlayList::STATE_StopInactive,        "StopWhenDeactivated",
204      "Stop the sources playing on the slot when a state changes to a setting that is incompatible with "
205      "the slot's state setting." },
206   { SFXPlayList::STATE_PauseInactive,       "PauseWhenDeactivated",
207      "Pause all sources playing on the slot when a state changes to a setting that is incompatible with the "
208      "slot's state setting.\n\n"
209      "When the slot's state is reactivated again, the sources will resume playback." },
210   { SFXPlayList::STATE_IgnoreInactive,      "IgnoreWhenDeactivated",
211      "Ignore when a state changes to a setting incompatible with the slot's state setting and just keep "
212      "playing sources attached to the slot." },
213EndImplementEnumType;
214
215
216//-----------------------------------------------------------------------------
217
218SFXPlayList::SFXPlayList()
219   : mRandomMode( RANDOM_NotRandom ),
220     mLoopMode( LOOP_All ),
221     mTrace( false ),
222     mNumSlotsToPlay( NUM_SLOTS )
223{
224}
225
226//-----------------------------------------------------------------------------
227
228void SFXPlayList::initPersistFields()
229{
230   addGroup( "Sound" );
231   
232      addField( "random",           TYPEID< ERandomMode >(), Offset( mRandomMode, SFXPlayList ),
233         "Slot playback order randomization pattern.\n"
234         "By setting this field to something other than \"NotRandom\" to order in which slots of the "
235         "playlist are processed can be changed from sequential to a random pattern.  This allows to "
236         "to create more varied playback patterns.\n"
237         "Defaults to \"NotRandom\"." );
238      addField( "loopMode",         TYPEID< ELoopMode >(), Offset( mLoopMode, SFXPlayList ),
239         "Behavior when description has looping enabled.\n"
240         "The loop mode determines whether the list will loop over a single slot or loop over "
241         "all the entire list of slots being played.\n\n"
242         "@see SFXDescription::isLooping" );
243      addField( "numSlotsToPlay",   TypeS32,          Offset( mNumSlotsToPlay, SFXPlayList ),
244         "Number of slots to play.\n"
245         "Up to a maximum of 16, this field determines the number of slots that are taken from the "
246         "list for playback.  Only slots that have a valid #track assigned will be considered for "
247         "this." );
248   
249      addArray( "slots", NUM_SLOTS );
250      
251         addField( "track",                  TypeSFXTrackName, Offset( mSlots.mTrack, SFXPlayList ), NUM_SLOTS,
252            "Track to play in this slot.\n"
253            "This must be set for the slot to be considered for playback.  Other settings for a slot "
254            "will not take effect except this field is set." );
255         addField( "replay",                 TYPEID< EReplayMode >(), Offset( mSlots.mReplayMode, SFXPlayList ), NUM_SLOTS,
256            "Behavior when an already playing sound is encountered on this slot from a previous cycle.\n"
257            "Each slot can have an arbitrary number of sounds playing on it from previous cycles.  This field determines "
258            "how SFXController will handle these sources." );
259         addField( "transitionIn",           TYPEID< ETransitionMode >(), Offset( mSlots.mTransitionIn, SFXPlayList ), NUM_SLOTS,
260            "Behavior when moving into this slot.\n"
261            "After the delayIn time has expired (if any), this slot determines what the controller "
262            "will do before actually playing the slot." );
263         addField( "transitionOut",          TYPEID< ETransitionMode >(), Offset( mSlots.mTransitionOut, SFXPlayList ), NUM_SLOTS,
264            "Behavior when moving out of this slot.\n"
265            "After the #detailTimeOut has expired (if any), this slot determines what the controller "
266            "will do before moving on to the next slot." );
267         addField( "delayTimeIn",            TypeF32,          Offset( mSlots.mDelayTimeIn.mValue, SFXPlayList ), NUM_SLOTS,
268            "Seconds to wait after moving into slot before #transitionIn." );
269         addField( "delayTimeInVariance",    TypePoint2F,      Offset( mSlots.mDelayTimeIn.mVariance, SFXPlayList ), NUM_SLOTS,
270            "Bounds on randomization of #delayTimeIn.\n\n"
271            "@ref SFXPlayList_randomization\n" );
272         addField( "delayTimeOut",           TypeF32,          Offset( mSlots.mDelayTimeOut.mValue, SFXPlayList ), NUM_SLOTS,
273            "Seconds to wait before moving out of slot after #transitionOut." );
274         addField( "delayTimeOutVariance",   TypePoint2F,      Offset( mSlots.mDelayTimeOut.mVariance, SFXPlayList ), NUM_SLOTS,
275            "Bounds on randomization of #delayTimeOut.\n\n"
276            "@ref SFXPlayList_randomization\n" );
277         addField( "fadeTimeIn",             TypeF32,          Offset( mSlots.mFadeTimeIn.mValue, SFXPlayList ), NUM_SLOTS,
278            "Seconds to fade sound in (-1 to use the track's own fadeInTime.)\n"
279            "@see SFXDescription::fadeTimeIn" );
280         addField( "fadeTimeInVariance",     TypePoint2F,      Offset( mSlots.mFadeTimeIn.mVariance, SFXPlayList ), NUM_SLOTS,
281            "Bounds on randomization of #fadeInTime.\n\n"
282            "@ref SFXPlayList_randomization\n" );
283         addField( "fadeTimeOut",            TypeF32,          Offset( mSlots.mFadeTimeOut.mValue, SFXPlayList ), NUM_SLOTS,
284            "Seconds to fade sound out (-1 to use the track's own fadeOutTime.)\n"
285            "@see SFXDescription::fadeTimeOut" );
286         addField( "fadeTimeOutVariance",    TypePoint2F,      Offset( mSlots.mFadeTimeOut.mVariance, SFXPlayList ), NUM_SLOTS,
287            "Bounds on randomization of #fadeOutTime\n\n"
288            "@ref SFXPlayList_randomization\n" );
289         addField( "referenceDistance",      TypeF32,          Offset( mSlots.mMinDistance.mValue, SFXPlayList ), NUM_SLOTS,
290            "@c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description).\n"
291            "@see SFXDescription::referenceDistance" );
292         addField( "referenceDistanceVariance", TypePoint2F,   Offset( mSlots.mMinDistance.mVariance, SFXPlayList ), NUM_SLOTS,
293            "Bounds on randomization of #referenceDistance.\n\n"
294            "@ref SFXPlayList_randomization\n" );
295         addField( "maxDistance",            TypeF32,          Offset( mSlots.mMaxDistance.mValue, SFXPlayList ), NUM_SLOTS,
296            "@c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description).\n"
297            "@see SFXDescription::maxDistance" );
298         addField( "maxDistanceVariance",    TypePoint2F,      Offset( mSlots.mMaxDistance.mVariance, SFXPlayList ), NUM_SLOTS,
299            "Bounds on randomization of #maxDistance.\n\n"
300            "@ref SFXPlayList_randomization\n" );
301         addField( "volumeScale",            TypeF32,          Offset( mSlots.mVolumeScale.mValue, SFXPlayList ), NUM_SLOTS,
302            "Scale factor to apply to volume of sounds played on this list slot.\n"
303            "This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will "
304            "cause the track to play at half-volume." );
305         addField( "volumeScaleVariance",    TypePoint2F,      Offset( mSlots.mVolumeScale.mVariance, SFXPlayList ), NUM_SLOTS,
306            "Bounds on randomization of #volumeScale.\n\n"
307            "@ref SFXPlayList_randomization\n" );
308         addField( "pitchScale",             TypeF32,          Offset( mSlots.mPitchScale.mValue, SFXPlayList ), NUM_SLOTS,
309            "Scale factor to apply to pitch of sounds played on this list slot.\n"
310            "This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will "
311            "cause the track to play at half its assigned speed." );
312         addField( "pitchScaleVariance",     TypePoint2F,      Offset( mSlots.mPitchScale.mVariance, SFXPlayList ), NUM_SLOTS,
313            "Bounds on randomization of #pitchScale.\n\n"
314            "@ref SFXPlayList_randomization\n" );
315         addField( "repeatCount",            TypeS32,          Offset( mSlots.mRepeatCount, SFXPlayList ), NUM_SLOTS,
316            "Number of times to loop this slot." );
317         addField( "state",                  TypeSFXStateName, Offset( mSlots.mState, SFXPlayList ), NUM_SLOTS,
318            "State that must be active for this slot to play.\n\n"
319            "@ref SFXPlayList_states" );
320         addField( "stateMode",              TYPEID< EStateMode >(), Offset( mSlots.mStateMode, SFXPlayList ), NUM_SLOTS,
321            "Behavior when assigned state is deactivated while slot is playing.\n\n"
322            "@ref SFXPlayList_states" );
323   
324      endArray( "slots" );
325   
326   endGroup( "Sound" );
327   
328   addGroup( "Debug" );
329   
330      addField( "trace", TypeBool, Offset( mTrace, SFXPlayList ),
331         "Enable/disable execution tracing for this playlist (local only).\n"
332         "If this is true, SFXControllers attached to the list will automatically run in trace mode." );
333         
334   endGroup( "Debug" );
335
336   Parent::initPersistFields();
337}
338
339//-----------------------------------------------------------------------------
340
341bool SFXPlayList::preload( bool server, String& errorStr )
342{
343   if( !Parent::preload( server, errorStr ) )
344      return false;
345      
346   validate();
347      
348   // Resolve SFXTracks and SFXStates on client.
349      
350   if( !server )
351   {
352      for( U32 i = 0; i < NUM_SLOTS; ++ i )
353      {
354         if( !sfxResolve( &mSlots.mTrack[ i ], errorStr ) )
355            return false;
356            
357         if( !sfxResolve( &mSlots.mState[ i ], errorStr ) )
358            return false;
359      }
360   }
361      
362   return true;
363}
364
365//-----------------------------------------------------------------------------
366
367void SFXPlayList::packData( BitStream* stream )
368{
369   Parent::packData( stream );
370   
371   stream->writeInt( mRandomMode, NUM_RANDOM_MODE_BITS );
372   stream->writeInt( mLoopMode, NUM_LOOP_MODE_BITS );
373   stream->writeInt( mNumSlotsToPlay, NUM_SLOTS_TO_PLAY_BITS );
374   
375   #define FOR_EACH_SLOT \
376      for( U32 i = 0; i < NUM_SLOTS; ++ i )
377   
378   FOR_EACH_SLOT stream->writeInt( mSlots.mReplayMode[ i ], NUM_REPLAY_MODE_BITS );
379   FOR_EACH_SLOT stream->writeInt( mSlots.mTransitionIn[ i ], NUM_TRANSITION_MODE_BITS );
380   FOR_EACH_SLOT stream->writeInt( mSlots.mTransitionOut[ i ], NUM_TRANSITION_MODE_BITS );
381   FOR_EACH_SLOT stream->writeInt( mSlots.mStateMode[ i ], NUM_STATE_MODE_BITS );
382      
383   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mFadeTimeIn.mValue[ i ] != -1 ))
384      stream->write( mSlots.mFadeTimeIn.mValue[ i ] );
385   FOR_EACH_SLOT if (stream->writeFlag( mSlots.mFadeTimeIn.mVariance[ i ][ 0 ] > 0))
386      stream->write(mSlots.mFadeTimeIn.mVariance[ i ][ 0 ] );
387   FOR_EACH_SLOT if (stream->writeFlag( mSlots.mFadeTimeIn.mVariance[ i ][ 1 ] > 0))
388      stream->write(mSlots.mFadeTimeIn.mVariance[ i ][ 1 ] );
389   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mFadeTimeOut.mValue[ i ] != -1 ))
390      stream->write( mSlots.mFadeTimeOut.mValue[ i ] );
391   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mFadeTimeOut.mVariance[i][0] > 0))
392      stream->write(mSlots.mFadeTimeOut.mVariance[i][0]);
393   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mFadeTimeOut.mVariance[i][1] > 0))
394      stream->write(mSlots.mFadeTimeOut.mVariance[i][1]);
395   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mDelayTimeIn.mValue[ i ] > 0))
396      stream->write(mSlots.mDelayTimeIn.mValue[ i ] );
397   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mDelayTimeIn.mVariance[ i ][ 0 ] > 0))
398      stream->write(mSlots.mDelayTimeIn.mVariance[ i ][ 0 ] );
399   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mDelayTimeIn.mVariance[ i ][ 1 ] > 0))
400      stream->write(mSlots.mDelayTimeIn.mVariance[ i ][ 1 ] );
401   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mDelayTimeOut.mValue[ i ] > 0))
402      stream->write(mSlots.mDelayTimeOut.mValue[ i ] );
403   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mDelayTimeOut.mVariance[ i ][ 0 ] > 0))
404      stream->write(mSlots.mDelayTimeOut.mVariance[ i ][ 0 ] );
405   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mDelayTimeOut.mVariance[ i ][ 1 ] > 0))
406      stream->write(mSlots.mDelayTimeOut.mVariance[ i ][ 1 ] );
407   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mVolumeScale.mValue[ i ] != 1))
408      stream->write(mSlots.mVolumeScale.mValue[ i ] );
409   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mVolumeScale.mVariance[ i ][ 0 ] > 0))
410      stream->write(mSlots.mVolumeScale.mVariance[ i ][ 0 ] );
411   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mVolumeScale.mVariance[ i ][ 1 ] > 0))
412      stream->write(mSlots.mVolumeScale.mVariance[ i ][ 1 ] );
413   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mPitchScale.mValue[ i ] != 1))
414      stream->write(mSlots.mPitchScale.mValue[ i ] );
415   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mPitchScale.mVariance[ i ][ 0 ] > 0))
416      stream->write(mSlots.mPitchScale.mVariance[ i ][ 0 ] );
417   FOR_EACH_SLOT if (stream->writeFlag(mSlots.mPitchScale.mVariance[ i ][ 1 ] > 0))
418      stream->write(mSlots.mPitchScale.mVariance[ i ][ 1 ] );
419   FOR_EACH_SLOT if (stream->writeFlag( mSlots.mRepeatCount[ i ] > 0))
420      stream->write( mSlots.mRepeatCount[ i ] );
421      
422   FOR_EACH_SLOT sfxWrite( stream, mSlots.mState[ i ] );
423   FOR_EACH_SLOT sfxWrite( stream, mSlots.mTrack[ i ] );
424}
425
426//-----------------------------------------------------------------------------
427
428void SFXPlayList::unpackData( BitStream* stream )
429{
430   Parent::unpackData( stream );
431   
432   mRandomMode          = ( ERandomMode ) stream->readInt( NUM_RANDOM_MODE_BITS );
433   mLoopMode            = ( ELoopMode ) stream->readInt( NUM_LOOP_MODE_BITS );
434   mNumSlotsToPlay      = stream->readInt( NUM_SLOTS_TO_PLAY_BITS );
435   
436   FOR_EACH_SLOT mSlots.mReplayMode[ i ]     = ( EReplayMode ) stream->readInt( NUM_REPLAY_MODE_BITS );
437   FOR_EACH_SLOT mSlots.mTransitionIn[ i ]   = ( ETransitionMode ) stream->readInt( NUM_TRANSITION_MODE_BITS );
438   FOR_EACH_SLOT mSlots.mTransitionOut[ i ]  = ( ETransitionMode ) stream->readInt( NUM_TRANSITION_MODE_BITS );
439   FOR_EACH_SLOT mSlots.mStateMode[ i ]      = ( EStateMode ) stream->readInt( NUM_STATE_MODE_BITS );
440      
441   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mFadeTimeIn.mValue[ i ] );}
442   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mFadeTimeIn.mVariance[ i ][ 0 ] );}
443   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mFadeTimeIn.mVariance[ i ][ 1 ] );}
444   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mFadeTimeOut.mValue[ i ] );}
445   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mFadeTimeOut.mVariance[ i ][ 0 ] );}
446   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mFadeTimeOut.mVariance[ i ][ 1 ] );}
447   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mDelayTimeIn.mValue[ i ] );}
448   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mDelayTimeIn.mVariance[ i ][ 0 ] );}
449   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mDelayTimeIn.mVariance[ i ][ 1 ] );}
450   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mDelayTimeOut.mValue[ i ] );}
451   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mDelayTimeOut.mVariance[ i ][ 0 ] );}
452   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mDelayTimeOut.mVariance[ i ][ 1 ] );}
453   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mVolumeScale.mValue[ i ] );}
454   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mVolumeScale.mVariance[ i ][ 0 ] );}
455   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mVolumeScale.mVariance[ i ][ 1 ] );}
456   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mPitchScale.mValue[ i ] );}
457   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mPitchScale.mVariance[ i ][ 0 ] );}
458   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mPitchScale.mVariance[ i ][ 1 ] );}
459   FOR_EACH_SLOT if(stream->readFlag()){ stream->read( &mSlots.mRepeatCount[ i ] );}
460      
461   FOR_EACH_SLOT sfxRead( stream, &mSlots.mState[ i ] );
462   FOR_EACH_SLOT sfxRead( stream, &mSlots.mTrack[ i ] );
463   
464   #undef FOR_EACH_SLOT
465}
466
467//-----------------------------------------------------------------------------
468
469void SFXPlayList::inspectPostApply()
470{
471   Parent::inspectPostApply();
472   validate();
473}
474
475//-----------------------------------------------------------------------------
476
477void SFXPlayList::validate()
478{
479   if( mNumSlotsToPlay > NUM_SLOTS )
480      mNumSlotsToPlay = NUM_SLOTS;
481      
482   mSlots.mFadeTimeIn.validate();
483   mSlots.mFadeTimeOut.validate();
484   mSlots.mDelayTimeIn.validate();
485   mSlots.mDelayTimeOut.validate();
486   mSlots.mVolumeScale.validate();
487   mSlots.mPitchScale.validate();
488}
489