diff --git a/Engine/source/T3D/sfx/sfxEmitter.cpp b/Engine/source/T3D/sfx/sfxEmitter.cpp
index 961e3efb1..967da296a 100644
--- a/Engine/source/T3D/sfx/sfxEmitter.cpp
+++ b/Engine/source/T3D/sfx/sfxEmitter.cpp
@@ -89,6 +89,120 @@ ColorI SFXEmitter::smRenderColorOutsideVolume( 255, 0, 0, 255 );
ColorI SFXEmitter::smRenderColorRangeSphere( 200, 0, 0, 90 );
+
+//-----------------------------------------------------------------------------
+
+ConsoleType(SoundControls, TypeSoundControls, bool, "")
+
+ConsoleGetType(TypeSoundControls)
+{
+ return "";
+}
+ConsoleSetType(TypeSoundControls)
+{
+}
+
+IMPLEMENT_CONOBJECT(GuiInspectorTypeSoundControls);
+ConsoleDocClass(GuiInspectorTypeSoundControls,
+ "@brief Inspector field type for Controlling playback of sounds\n\n"
+ "Editor use only.\n\n"
+ "@internal"
+);
+
+void GuiInspectorTypeSoundControls::consoleInit()
+{
+ Parent::consoleInit();
+
+ ConsoleBaseType::getType(TypeSoundControls)->setInspectorFieldType("GuiInspectorTypeSoundControls");
+}
+
+GuiControl* GuiInspectorTypeSoundControls::constructEditControl()
+{
+ // Create base filename edit controls
+ GuiControl* retCtrl = Parent::constructEditControl();
+ if (retCtrl == NULL)
+ return retCtrl;
+
+ char szBuffer[512];
+
+ setDataField(StringTable->insert("targetObject"), NULL, mInspector->getInspectObject()->getIdString());
+
+ mPlayButton = new GuiBitmapButtonCtrl();
+ dSprintf(szBuffer, sizeof(szBuffer), "%d.play();", mInspector->getInspectObject()->getId());
+ mPlayButton->setField("Command", szBuffer);
+
+ mPlayButton->setBitmap(StringTable->insert("ToolsModule:playbutton_n_image"));
+
+ mPlayButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
+ mPlayButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+ mPlayButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+ mPlayButton->setDataField(StringTable->insert("tooltip"), NULL, "Play this sound emitter");
+
+ mPlayButton->registerObject();
+ addObject(mPlayButton);
+
+ mPauseButton = new GuiBitmapButtonCtrl();
+ dSprintf(szBuffer, sizeof(szBuffer), "%d.pause();", mInspector->getInspectObject()->getId());
+ mPauseButton->setField("Command", szBuffer);
+
+ mPauseButton->setBitmap(StringTable->insert("ToolsModule:pausebutton_n_image"));
+
+ mPauseButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
+ mPauseButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+ mPauseButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+ mPauseButton->setDataField(StringTable->insert("tooltip"), NULL, "Pause this sound emitter");
+
+ mPauseButton->registerObject();
+ addObject(mPauseButton);
+
+ mStopButton = new GuiBitmapButtonCtrl();
+ dSprintf(szBuffer, sizeof(szBuffer), "%d.stop();", mInspector->getInspectObject()->getId());
+ mStopButton->setField("Command", szBuffer);
+
+ mStopButton->setBitmap(StringTable->insert("ToolsModule:stopbutton_n_image"));
+
+ mStopButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
+ mStopButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
+ mStopButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
+ mStopButton->setDataField(StringTable->insert("tooltip"), NULL, "Stop this sound emitter");
+
+ mStopButton->registerObject();
+ addObject(mStopButton);
+
+ return retCtrl;
+}
+
+bool GuiInspectorTypeSoundControls::updateRects()
+{
+ S32 dividerPos, dividerMargin;
+ mInspector->getDivider(dividerPos, dividerMargin);
+ Point2I fieldExtent = getExtent();
+ Point2I fieldPos = getPosition();
+
+ bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
+
+ if (mPlayButton != NULL)
+ {
+ RectI shapeEdRect(2, 2, 16, 16);
+ resized |= mPlayButton->resize(shapeEdRect.point, shapeEdRect.extent);
+ }
+
+ if (mPauseButton != NULL)
+ {
+ RectI shapeEdRect(20, 2, 16, 16);
+ resized |= mPauseButton->resize(shapeEdRect.point, shapeEdRect.extent);
+ }
+
+ if (mStopButton != NULL)
+ {
+ RectI shapeEdRect(38, 2, 16, 16);
+ resized |= mStopButton->resize(shapeEdRect.point, shapeEdRect.extent);
+ }
+
+ return resized;
+}
+
+
//-----------------------------------------------------------------------------
SFXEmitter::SFXEmitter()
@@ -192,6 +306,8 @@ void SFXEmitter::initPersistFields()
addGroup( "Sound" );
+ addField("Controls", TypeSoundControls, 0, "");
+
addField( "playOnAdd", TypeBool, Offset( mPlayOnAdd, SFXEmitter ),
"Whether playback of the emitter's sound should start as soon as the emitter object is added to the level.\n"
"If this is true, the emitter will immediately start to play when the level is loaded." );
@@ -366,6 +482,7 @@ U32 SFXEmitter::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
// Write the source playback state.
stream->writeFlag( mask & SourcePlayMask );
+ stream->writeFlag( mask & SourcePauseMask );
stream->writeFlag( mask & SourceStopMask );
return retMask;
@@ -491,6 +608,8 @@ void SFXEmitter::unpackUpdate( NetConnection *conn, BitStream *stream )
// Check the source playback masks.
if ( stream->readFlag() ) // SourcePlayMask
play();
+ if (stream->readFlag()) //SourcePauseMask
+ pause();
if ( stream->readFlag() ) // SourceStopMask
stop();
}
@@ -1000,6 +1119,23 @@ void SFXEmitter::play()
//-----------------------------------------------------------------------------
+void SFXEmitter::pause()
+{
+ if (mSource)
+ mSource->pause();
+ else
+ {
+ // By clearing the playback masks first we
+ // ensure the last playback command called
+ // within a single tick is the one obeyed.
+ clearMaskBits(AllSourceMasks);
+
+ setMaskBits(SourcePauseMask);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
void SFXEmitter::stop()
{
if ( mSource )
@@ -1114,6 +1250,15 @@ DefineEngineMethod( SFXEmitter, play, void, (),,
//-----------------------------------------------------------------------------
+DefineEngineMethod(SFXEmitter, pause, void, (), ,
+ "Manually pause playback of the emitter's sound.\n"
+ "If this is called on the server-side object, the pause command will be related to all client-side ghosts.\n")
+{
+ object->pause();
+}
+
+//-----------------------------------------------------------------------------
+
DefineEngineMethod( SFXEmitter, stop, void, (),,
"Manually stop playback of the emitter's sound.\n"
"If this is called on the server-side object, the stop command will be related to all client-side ghosts.\n" )
@@ -1131,3 +1276,4 @@ DefineEngineMethod( SFXEmitter, getSource, SFXSource*, (),,
{
return object->getSource();
}
+
diff --git a/Engine/source/T3D/sfx/sfxEmitter.h b/Engine/source/T3D/sfx/sfxEmitter.h
index 103a92faf..067471820 100644
--- a/Engine/source/T3D/sfx/sfxEmitter.h
+++ b/Engine/source/T3D/sfx/sfxEmitter.h
@@ -41,6 +41,21 @@
class SFXSource;
class SFXTrack;
+DefineConsoleType(TypeSoundControls, bool)
+class GuiInspectorTypeSoundControls : public GuiInspectorField
+{
+ typedef GuiInspectorField Parent;
+public:
+ GuiBitmapButtonCtrl* mPlayButton;
+ GuiBitmapButtonCtrl* mPauseButton;
+ GuiBitmapButtonCtrl* mStopButton;
+
+ DECLARE_CONOBJECT(GuiInspectorTypeSoundControls);
+ static void consoleInit();
+
+ virtual GuiControl* constructEditControl();
+ virtual bool updateRects();
+};
//RDTODO: make 3D sound emitters yield their source when being culled
/// The SFXEmitter is used to place 2D or 3D sounds into a
@@ -69,7 +84,8 @@ class SFXEmitter : public SceneObject
DirtyUpdateMask = BIT(2),
SourcePlayMask = BIT(3),
- SourceStopMask = BIT(4),
+ SourcePauseMask = BIT(4),
+ SourceStopMask = BIT(5),
AllSourceMasks = SourcePlayMask | SourceStopMask,
};
@@ -219,6 +235,10 @@ class SFXEmitter : public SceneObject
/// the emitter source is not already playing.
void play();
+ /// Sends network event to pause playback if
+ /// the emitter source is already playing.
+ void pause();
+
/// Sends network event to stop emitter
/// playback on all ghosted clients.
void stop();
diff --git a/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_h.png b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_h.png
new file mode 100644
index 000000000..6a02d7d42
Binary files /dev/null and b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_h.png differ
diff --git a/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_h_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_h_image.asset.taml
new file mode 100644
index 000000000..7a643ed81
--- /dev/null
+++ b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_h_image.asset.taml
@@ -0,0 +1,8 @@
+
diff --git a/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_n.png b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_n.png
new file mode 100644
index 000000000..6fefd102b
Binary files /dev/null and b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_n.png differ
diff --git a/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_n_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_n_image.asset.taml
new file mode 100644
index 000000000..dc5c3ebb4
--- /dev/null
+++ b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/pausebutton_n_image.asset.taml
@@ -0,0 +1,8 @@
+
diff --git a/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_h.png b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_h.png
new file mode 100644
index 000000000..bcb3b3f89
Binary files /dev/null and b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_h.png differ
diff --git a/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_h_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_h_image.asset.taml
new file mode 100644
index 000000000..82f4dfbd3
--- /dev/null
+++ b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_h_image.asset.taml
@@ -0,0 +1,8 @@
+
diff --git a/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_n.png b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_n.png
new file mode 100644
index 000000000..c45cd993c
Binary files /dev/null and b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_n.png differ
diff --git a/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_n_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_n_image.asset.taml
new file mode 100644
index 000000000..11eed81f7
--- /dev/null
+++ b/Templates/BaseGame/game/tools/worldEditor/images/toolbar/stopbutton_n_image.asset.taml
@@ -0,0 +1,8 @@
+