mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-06-02 19:16:38 +00:00
Merge 6829ac2dd0 into 8407fa360c
This commit is contained in:
commit
903b2bd216
10 changed files with 497 additions and 124 deletions
|
|
@ -200,119 +200,141 @@ void SoundAsset::initPersistFields()
|
|||
docsURL;
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
addGroup("SoundSlots");
|
||||
addArray("slots", SFXPlayList::SFXPlaylistSettings::NUM_SLOTS);
|
||||
addProtectedField("soundFile", TypeAssetLooseFilePath, Offset(mSoundFile, SoundAsset),
|
||||
&_setSoundFile, &defaultProtectedGetFn, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, "Path to the sound file.");
|
||||
GROUP("SoundSlots")
|
||||
{
|
||||
ARRAY_BEGIN("slots", SFXPlayList::SFXPlaylistSettings::NUM_SLOTS)
|
||||
.showWhen(&slotVisible);
|
||||
|
||||
addField("replay", TYPEID< SFXPlayList::EReplayMode >(), Offset(mPlaylist.mSlots.mReplayMode, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Behavior when an already playing sound is encountered on this slot from a previous cycle.\n"
|
||||
"Each slot can have an arbitrary number of sounds playing on it from previous cycles. This field determines "
|
||||
"how SFXController will handle these sources.");
|
||||
addField("transitionIn", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionIn, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Behavior when moving into this slot.\n"
|
||||
"After the delayIn time has expired (if any), this slot determines what the controller "
|
||||
"will do before actually playing the slot.");
|
||||
addField("transitionOut", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionOut, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Behavior when moving out of this slot.\n"
|
||||
"After the #detailTimeOut has expired (if any), this slot determines what the controller "
|
||||
"will do before moving on to the next slot.");
|
||||
addFieldV("delayTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeIn.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Seconds to wait after moving into slot before #transitionIn.");
|
||||
addField("delayTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Bounds on randomization of #delayTimeIn.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
addFieldV("delayTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeOut.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Seconds to wait before moving out of slot after #transitionOut.");
|
||||
addField("delayTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Bounds on randomization of #delayTimeOut.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
addFieldV("fadeTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeIn.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Seconds to fade sound in (-1 to use the track's own fadeInTime.)\n"
|
||||
"@see SFXDescription::fadeTimeIn");
|
||||
addField("fadeTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Bounds on randomization of #fadeInTime.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
addFieldV("fadeTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeOut.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Seconds to fade sound out (-1 to use the track's own fadeOutTime.)\n"
|
||||
"@see SFXDescription::fadeTimeOut");
|
||||
addField("fadeTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Bounds on randomization of #fadeOutTime\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
addFieldV("referenceDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMinDistance.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"@c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description).\n"
|
||||
"@see SFXDescription::referenceDistance");
|
||||
addField("referenceDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMinDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Bounds on randomization of #referenceDistance.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
addFieldV("maxSlotDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMaxDistance.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"@c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description).\n"
|
||||
"@see SFXDescription::maxDistance");
|
||||
addField("maxSlotDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMaxDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Bounds on randomization of #maxDistance.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
addFieldV("volumeScale", TypeRangedF32, Offset(mPlaylist.mSlots.mVolumeScale.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Scale factor to apply to volume of sounds played on this list slot.\n"
|
||||
"This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will "
|
||||
"cause the track to play at half-volume.");
|
||||
addField("volumeScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mVolumeScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Bounds on randomization of #volumeScale.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
addFieldV("pitchScale", TypeRangedF32, Offset(mPlaylist.mSlots.mPitchScale.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Scale factor to apply to pitch of sounds played on this list slot.\n"
|
||||
"This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will "
|
||||
"cause the track to play at half its assigned speed.");
|
||||
addField("pitchScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mPitchScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Bounds on randomization of #pitchScale.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
addFieldV("repeatCount", TypeRangedS32, Offset(mPlaylist.mSlots.mRepeatCount, SoundAsset), &CommonValidators::PositiveInt, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Number of times to loop this slot.");
|
||||
addField("state", TypeSFXStateName, Offset(mPlaylist.mSlots.mState, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"State that must be active for this slot to play.\n\n"
|
||||
"@ref SFXPlayList_states");
|
||||
addField("stateMode", TYPEID< SFXPlayList::EStateMode >(), Offset(mPlaylist.mSlots.mStateMode, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS,
|
||||
"Behavior when assigned state is deactivated while slot is playing.\n\n"
|
||||
"@ref SFXPlayList_states");
|
||||
endArray("slots");
|
||||
endGroup("SoundSlots");
|
||||
ADD_FIELD("soundFile", TypeAssetLooseFilePath, Offset(mSoundFile, SoundAsset))
|
||||
.doc("Path to the sound file.")
|
||||
.onSet(&_setSoundFile);
|
||||
|
||||
addGroup("General Profile");
|
||||
addFieldV("pitchAdjust", TypeRangedF32, Offset(mProfileDesc.mPitch, SoundAsset), &CommonValidators::PositiveFloat, "Adjustment of the pitch value 1 is default.");
|
||||
addFieldV("volumeAdjust", TypeRangedF32, Offset(mProfileDesc.mVolume, SoundAsset), &CommonValidators::PositiveFloat, "Adjustment to the volume.");
|
||||
addField("is3D", TypeBool, Offset(mProfileDesc.mIs3D, SoundAsset), "Set this sound to 3D.");
|
||||
addField("isLooping", TypeBool, Offset(mProfileDesc.mIsLooping, SoundAsset), "Does this sound loop.");
|
||||
// if streaming, a default packet size should be chosen for all sounds.
|
||||
addField("isStreaming", TypeBool, Offset(mProfileDesc.mIsStreaming, SoundAsset), "Use streaming.");
|
||||
//....why?
|
||||
addField("useHardware", TypeBool, Offset(mProfileDesc.mUseHardware, SoundAsset), "Use hardware mixing for this sound.");
|
||||
addField("sourceGroup", TypeSFXSourceName, Offset(mProfileDesc.mSourceGroup, SoundAsset), "Group that sources playing with this description should be put into.");
|
||||
addField("preload", TypeBool, Offset(mPreload, SoundAsset), "Whether to preload sound data when the profile is added to system.");
|
||||
endGroup("General Profile");
|
||||
ADD_FIELD("replay", TYPEID< SFXPlayList::EReplayMode >(), Offset(mPlaylist.mSlots.mReplayMode, SoundAsset))
|
||||
.doc("Behavior when an already playing sound is encountered on this slot from a previous cycle.\n"
|
||||
"Each slot can have an arbitrary number of sounds playing on it from previous cycles. This field determines "
|
||||
"how SFXController will handle these sources.");
|
||||
|
||||
addGroup("Fading");
|
||||
addFieldV("fadeInTime", TypeRangedF32, Offset(mProfileDesc.mFadeInTime, SoundAsset), &CommonValidators::PositiveFloat, "Number of seconds to gradually fade in volume from zero when playback starts.");
|
||||
addFieldV("fadeOutTime", TypeRangedF32, Offset(mProfileDesc.mFadeOutTime, SoundAsset), &CommonValidators::PositiveFloat, "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused.");
|
||||
addField("fadeInEase", TypeEaseF, Offset(mProfileDesc.mFadeInEase, SoundAsset), "Easing curve for fade-in transition.");
|
||||
addField("fadeOutEase", TypeEaseF, Offset(mProfileDesc.mFadeOutEase, SoundAsset), "Easing curve for fade-out transition.");
|
||||
addField("fadeLoops", TypeBool, Offset(mProfileDesc.mFadeLoops, SoundAsset), "Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle.");
|
||||
endGroup("Fading");
|
||||
ADD_FIELD("transitionIn", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionIn, SoundAsset))
|
||||
.doc("Behavior when moving into this slot.\n"
|
||||
"After the delayIn time has expired (if any), this slot determines what the controller "
|
||||
"will do before actually playing the slot.");
|
||||
ADD_FIELD("transitionOut", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionOut, SoundAsset))
|
||||
.doc("Behavior when moving out of this slot.\n"
|
||||
"After the #detailTimeOut has expired (if any), this slot determines what the controller "
|
||||
"will do before moving on to the next slot.");
|
||||
ADD_FIELD("delayTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeIn.mValue, SoundAsset)).validate(&CommonValidators::PositiveFloat)
|
||||
.doc("Seconds to wait after moving into slot before #transitionIn.");
|
||||
ADD_FIELD("delayTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeIn.mVariance, SoundAsset))
|
||||
.doc("Bounds on randomization of #delayTimeIn.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
ADD_FIELD("delayTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeOut.mValue, SoundAsset)).validate(&CommonValidators::PositiveFloat)
|
||||
.doc("Seconds to wait before moving out of slot after #transitionOut.");
|
||||
ADD_FIELD("delayTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeOut.mVariance, SoundAsset))
|
||||
.doc("Bounds on randomization of #delayTimeOut.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
ADD_FIELD("fadeTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeIn.mValue, SoundAsset)).validate(&CommonValidators::PositiveFloat)
|
||||
.doc("Seconds to fade sound in (-1 to use the track's own fadeInTime.)\n"
|
||||
"@see SFXDescription::fadeTimeIn");
|
||||
ADD_FIELD("fadeTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeIn.mVariance, SoundAsset))
|
||||
.doc("Bounds on randomization of #fadeInTime.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
ADD_FIELD("fadeTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeOut.mValue, SoundAsset)).validate(&CommonValidators::PositiveFloat)
|
||||
.doc("Seconds to fade sound out (-1 to use the track's own fadeOutTime.)\n"
|
||||
"@see SFXDescription::fadeTimeOut");
|
||||
ADD_FIELD("fadeTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeOut.mVariance, SoundAsset))
|
||||
.doc("Bounds on randomization of #fadeOutTime\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
ADD_FIELD("referenceDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMinDistance.mValue, SoundAsset)).validate(&CommonValidators::PositiveFloat)
|
||||
.doc("@c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description).\n"
|
||||
"@see SFXDescription::referenceDistance");
|
||||
ADD_FIELD("referenceDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMinDistance.mVariance, SoundAsset))
|
||||
.doc("Bounds on randomization of #referenceDistance.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
ADD_FIELD("maxSlotDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMaxDistance.mValue, SoundAsset)).validate(&CommonValidators::PositiveFloat)
|
||||
.doc("@c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description).\n"
|
||||
"@see SFXDescription::maxDistance");
|
||||
ADD_FIELD("maxSlotDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMaxDistance.mVariance, SoundAsset))
|
||||
.doc("Bounds on randomization of #maxDistance.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
ADD_FIELD("volumeScale", TypeRangedF32, Offset(mPlaylist.mSlots.mVolumeScale.mValue, SoundAsset)).validate(&CommonValidators::PositiveFloat)
|
||||
.doc("Scale factor to apply to volume of sounds played on this list slot.\n"
|
||||
"This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will "
|
||||
"cause the track to play at half-volume.");
|
||||
ADD_FIELD("volumeScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mVolumeScale.mVariance, SoundAsset))
|
||||
.doc("Bounds on randomization of #volumeScale.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
ADD_FIELD("pitchScale", TypeRangedF32, Offset(mPlaylist.mSlots.mPitchScale.mValue, SoundAsset)).validate(&CommonValidators::PositiveFloat)
|
||||
.doc("Scale factor to apply to pitch of sounds played on this list slot.\n"
|
||||
"This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will "
|
||||
"cause the track to play at half its assigned speed.");
|
||||
ADD_FIELD("pitchScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mPitchScale.mVariance, SoundAsset))
|
||||
.doc("Bounds on randomization of #pitchScale.\n\n"
|
||||
"@ref SFXPlayList_randomization\n");
|
||||
ADD_FIELD("repeatCount", TypeRangedS32, Offset(mPlaylist.mSlots.mRepeatCount, SoundAsset)).validate(&CommonValidators::PositiveInt)
|
||||
.doc("Number of times to loop this slot.");
|
||||
ADD_FIELD("state", TypeSFXStateName, Offset(mPlaylist.mSlots.mState, SoundAsset))
|
||||
.doc("State that must be active for this slot to play.\n\n"
|
||||
"@ref SFXPlayList_states");
|
||||
ADD_FIELD("stateMode", TYPEID< SFXPlayList::EStateMode >(), Offset(mPlaylist.mSlots.mStateMode, SoundAsset))
|
||||
.doc("Behavior when assigned state is deactivated while slot is playing.\n\n"
|
||||
"@ref SFXPlayList_states");
|
||||
|
||||
addGroup("3D");
|
||||
addFieldV("minDistance", TypeRangedF32, Offset(mProfileDesc.mMinDistance, SoundAsset), &CommonValidators::PositiveFloat, "Minimum distance for sound.");
|
||||
addFieldV("maxDistance", TypeRangedF32, Offset(mProfileDesc.mMaxDistance, SoundAsset), &CommonValidators::PositiveFloat, "Max distance for sound.");
|
||||
addFieldV("coneInsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset), &CommonValidators::S32_PosDegreeRange, "Cone inside angle.");
|
||||
addFieldV("coneOutsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset), &CommonValidators::S32_PosDegreeRange, "Cone outside angle.");
|
||||
addFieldV("coneOutsideVolume", TypeRangedF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), &CommonValidators::NormalizedFloat, "Cone outside volume.");
|
||||
addFieldV("rolloffFactor", TypeRangedF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset), &CommonValidators::NegDefaultF32, "Rolloff factor.");
|
||||
addField("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset), "Randomization to the spacial position of the sound.");
|
||||
endGroup("3D");
|
||||
ARRAY_END("slots");
|
||||
}
|
||||
|
||||
addGroup("Playlist settings");
|
||||
addField("random", TYPEID< SFXPlayList::ERandomMode >(), Offset(mPlaylist.mRandomMode, SoundAsset), "Slot playback order randomization pattern.");
|
||||
addField("loopMode", TYPEID< SFXPlayList::ELoopMode >(), Offset(mPlaylist.mLoopMode, SoundAsset), "Behavior when description has looping enabled.");
|
||||
addFieldV("numSlotsToPlay", TypeRangedS32, Offset(mPlaylist.mNumSlotsToPlay, SoundAsset), &playlistSlotRange, "Number of slots to play.");
|
||||
addField("trace", TypeBool, Offset(mPlaylist.mTrace, SoundAsset), "Enable/disable execution tracing for this playlist (local only).");
|
||||
endGroup("Playlist settings");
|
||||
GROUP("General Profile")
|
||||
{
|
||||
ADD_FIELD("pitchAdjust", TypeRangedF32, Offset(mProfileDesc.mPitch, SoundAsset))
|
||||
.doc("Adjustment of the pitch value 1 is default.")
|
||||
.validate(&CommonValidators::PositiveFloat);
|
||||
|
||||
ADD_FIELD("volumeAdjust", TypeRangedF32, Offset(mProfileDesc.mVolume, SoundAsset))
|
||||
.doc("Adjustment to the volume.")
|
||||
.validate(&CommonValidators::PositiveFloat);
|
||||
|
||||
ADD_FIELD("is3D", TypeBool, Offset(mProfileDesc.mIs3D, SoundAsset)).doc("Set this sound to 3D.");
|
||||
ADD_FIELD("isLooping", TypeBool, Offset(mProfileDesc.mIsLooping, SoundAsset)).doc("Does this sound loop.");
|
||||
// if streaming, a default packet size should be chosen for all sounds.
|
||||
ADD_FIELD("isStreaming", TypeBool, Offset(mProfileDesc.mIsStreaming, SoundAsset)).doc("Use streaming.");
|
||||
//....why?
|
||||
ADD_FIELD("useHardware", TypeBool, Offset(mProfileDesc.mUseHardware, SoundAsset)).doc("Use hardware mixing for this sound.");
|
||||
ADD_FIELD("sourceGroup", TypeSFXSourceName, Offset(mProfileDesc.mSourceGroup, SoundAsset)).doc("Group that sources playing with this description should be put into.");
|
||||
ADD_FIELD("preload", TypeBool, Offset(mPreload, SoundAsset)).doc("Whether to preload sound data when the profile is added to system.");
|
||||
}
|
||||
|
||||
GROUP("Fading")
|
||||
{
|
||||
ADD_FIELD("fadeInTime", TypeRangedF32, Offset(mProfileDesc.mFadeInTime, SoundAsset))
|
||||
.validate(&CommonValidators::PositiveFloat)
|
||||
.doc("Number of seconds to gradually fade in volume from zero when playback starts.");
|
||||
|
||||
ADD_FIELD("fadeOutTime", TypeRangedF32, Offset(mProfileDesc.mFadeOutTime, SoundAsset))
|
||||
.validate(&CommonValidators::PositiveFloat)
|
||||
.doc("Number of seconds to gradually fade out volume down to zero when playback is stopped or paused.");
|
||||
|
||||
ADD_FIELD("fadeInEase", TypeEaseF, Offset(mProfileDesc.mFadeInEase, SoundAsset)).doc("Easing curve for fade-in transition.");
|
||||
ADD_FIELD("fadeOutEase", TypeEaseF, Offset(mProfileDesc.mFadeOutEase, SoundAsset)).doc("Easing curve for fade-out transition.");
|
||||
ADD_FIELD("fadeLoops", TypeBool, Offset(mProfileDesc.mFadeLoops, SoundAsset)).doc("Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle.");
|
||||
}
|
||||
|
||||
GROUP("3D")
|
||||
{
|
||||
ADD_FIELD("minDistance", TypeRangedF32, Offset(mProfileDesc.mMinDistance, SoundAsset)).validate(&CommonValidators::PositiveFloat).doc("Minimum distance for sound.");
|
||||
ADD_FIELD("maxDistance", TypeRangedF32, Offset(mProfileDesc.mMaxDistance, SoundAsset)).validate(&CommonValidators::PositiveFloat).doc("Max distance for sound.");
|
||||
ADD_FIELD("coneInsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset)).validate(&CommonValidators::S32_PosDegreeRange).doc("Cone inside angle.");
|
||||
ADD_FIELD("coneOutsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset)).validate(&CommonValidators::S32_PosDegreeRange).doc("Cone outside angle.");
|
||||
ADD_FIELD("coneOutsideVolume", TypeRangedF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset)).validate(&CommonValidators::NormalizedFloat).doc("Cone outside volume.");
|
||||
ADD_FIELD("rolloffFactor", TypeRangedF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset)).validate(&CommonValidators::NegDefaultF32).doc("Rolloff factor.");
|
||||
ADD_FIELD("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset)).doc("Randomization to the spacial position of the sound.");
|
||||
}
|
||||
|
||||
GROUP("Playlist settings")
|
||||
{
|
||||
ADD_FIELD("random", TYPEID< SFXPlayList::ERandomMode >(), Offset(mPlaylist.mRandomMode, SoundAsset)).doc("Slot playback order randomization pattern.");
|
||||
ADD_FIELD("loopMode", TYPEID< SFXPlayList::ELoopMode >(), Offset(mPlaylist.mLoopMode, SoundAsset)).doc("Behavior when description has looping enabled.");
|
||||
ADD_FIELD("numSlotsToPlay", TypeRangedS32, Offset(mPlaylist.mNumSlotsToPlay, SoundAsset)).validate(&playlistSlotRange).doc("Number of slots to play.");
|
||||
ADD_FIELD("trace", TypeBool, Offset(mPlaylist.mTrace, SoundAsset)).doc("Enable/disable execution tracing for this playlist (local only).");
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -462,6 +484,18 @@ bool SoundAsset::_setSoundFile(void* object, const char* index, const char* data
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SoundAsset::slotVisible(void* object, const char* index)
|
||||
{
|
||||
S32 idx = index ? dAtoi(index) : 0;
|
||||
if (idx == 0) return true;
|
||||
|
||||
SoundAsset* sa = static_cast<SoundAsset*>(object);
|
||||
if (!sa)
|
||||
return false;
|
||||
|
||||
return sa->mSoundFile[idx - 1] != NULL && sa->mSoundFile[idx - 1][0] != '\0';
|
||||
}
|
||||
|
||||
StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName)
|
||||
{
|
||||
if (fileName == StringTable->EmptyString())
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ public:
|
|||
DECLARE_CONOBJECT(SoundAsset);
|
||||
|
||||
static bool _setSoundFile(void* object, const char* index, const char* data);
|
||||
static bool slotVisible(void* object, const char* index);
|
||||
U32 load() override;
|
||||
inline StringTableEntry getSoundPath(const U32 slotId = 0) const { return mSoundPath[slotId]; };
|
||||
SFXProfile* getSfxProfile(const U32 slotId = 0) { return mSFXProfile[slotId]; }
|
||||
|
|
|
|||
|
|
@ -356,6 +356,83 @@ static char* suppressSpaces(const char* in_pname)
|
|||
return replacebuf;
|
||||
}
|
||||
|
||||
static U32 sg_currentArrayElementCount = 1;
|
||||
|
||||
void ConsoleObject::registerField(const char* name, U32 type, dsize_t offset, const FieldDescriptor& desc)
|
||||
{
|
||||
AbstractClassRep::Field f;
|
||||
|
||||
const bool isCollection = desc.isArrayBegin || desc.isArrayEnd || desc.isGroupBegin || desc.isGroupEnd;
|
||||
|
||||
if (isCollection)
|
||||
{
|
||||
char* pFieldNameBuf = suppressSpaces(name);
|
||||
if (desc.isGroupBegin)
|
||||
{
|
||||
// Append group begin type to fieldname.
|
||||
dStrcat(pFieldNameBuf, "_begingroup", 1024);
|
||||
f.type = AbstractClassRep::StartGroupFieldType;
|
||||
}
|
||||
|
||||
if (desc.isGroupEnd)
|
||||
{
|
||||
// Append group end type to fieldname.
|
||||
dStrcat(pFieldNameBuf, "_endgroup", 1024);
|
||||
f.type = AbstractClassRep::EndGroupFieldType;
|
||||
}
|
||||
|
||||
if (desc.isArrayBegin)
|
||||
{
|
||||
// Append array type to fieldname.
|
||||
dStrcat(pFieldNameBuf, "_beginarray", 1024);
|
||||
f.type = AbstractClassRep::StartArrayFieldType;
|
||||
}
|
||||
|
||||
if (desc.isArrayEnd)
|
||||
{
|
||||
// Append array end type to fieldname.
|
||||
dStrcat(pFieldNameBuf, "_endarray", 1024);
|
||||
f.type = AbstractClassRep::EndArrayFieldType;
|
||||
}
|
||||
|
||||
f.pFieldname = StringTable->insert(pFieldNameBuf);
|
||||
f.pGroupname = StringTable->insert(name);
|
||||
f.elementCount = desc.elementCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleBaseType* conType = ConsoleBaseType::getType(desc._type);
|
||||
AssertFatal(conType, avar("ConsoleObject::addProtectedField[%s] - invalid console type", name));
|
||||
f.pFieldname = StringTable->insert(name);
|
||||
f.type = desc._type;
|
||||
f.table = conType->getEnumTable();
|
||||
}
|
||||
|
||||
if (desc.isArrayBegin)
|
||||
sg_currentArrayElementCount = desc.elementCount;
|
||||
|
||||
if (desc.isArrayEnd)
|
||||
sg_currentArrayElementCount = 1;
|
||||
|
||||
if (desc.docs)
|
||||
f.pFieldDocs = desc.docs;
|
||||
|
||||
if (!isCollection)
|
||||
f.elementCount = desc.elementCount > 1 ? desc.elementCount : sg_currentArrayElementCount;
|
||||
|
||||
f.offset = desc._offset;
|
||||
f.validator = desc.validator;
|
||||
f.setDataFn = desc.setFn;
|
||||
f.getDataFn = desc.getFn;
|
||||
f.writeDataFn = desc.writeFn;
|
||||
f.visibilityFn = desc.visibilityFn;
|
||||
f.groupExpand = desc.isExpanded;
|
||||
f.networkMask = desc.networkMask;
|
||||
f.flag = desc.flags;
|
||||
|
||||
sg_tempFieldList.push_back(f);
|
||||
}
|
||||
|
||||
void ConsoleObject::addGroup(const char* in_pGroupname, const char* in_pGroupDocs)
|
||||
{
|
||||
// Remove spaces.
|
||||
|
|
@ -1130,3 +1207,23 @@ DefineEngineFunction(linkNamespaces, bool, ( String childNSName, String parentNS
|
|||
return true;
|
||||
}
|
||||
|
||||
FieldDescriptor::~FieldDescriptor()
|
||||
{
|
||||
if (!_active)
|
||||
return;
|
||||
|
||||
if (_name == NULL || _name[0] == '\0')
|
||||
return;
|
||||
|
||||
_active = false;
|
||||
|
||||
// if we are a collection, sanitize some properties.
|
||||
if (isGroupBegin || isGroupEnd || isArrayBegin || isArrayEnd)
|
||||
{
|
||||
elementCount = isArrayBegin ? elementCount : 0;
|
||||
validator = NULL;
|
||||
networkMask = 0;
|
||||
}
|
||||
|
||||
ConsoleObject::registerField(_name, _type, _offset, *this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -456,6 +456,11 @@ public:
|
|||
/// This is a function pointer typedef to support optional writing for fields.
|
||||
typedef bool(*WriteDataNotify)(void* obj, StringTableEntry pFieldName);
|
||||
|
||||
/// <summary>
|
||||
/// This is a function pointer typedef to support optional visibility of fields.
|
||||
/// </summary>
|
||||
typedef bool(*VisibilityNotify)(void* obj, const char* array);
|
||||
|
||||
/// These are special field type values used to mark
|
||||
/// groups and arrays in the field list.
|
||||
/// @see Field::type
|
||||
|
|
@ -517,27 +522,29 @@ public:
|
|||
setDataFn( NULL ),
|
||||
getDataFn( NULL ),
|
||||
writeDataFn(NULL),
|
||||
visibilityFn(NULL),
|
||||
networkMask(0)
|
||||
{
|
||||
doNotSubstitute = keepClearSubsOnly = false;
|
||||
}
|
||||
|
||||
StringTableEntry pFieldname; ///< Name of the field.
|
||||
const char* pGroupname; ///< Optionally filled field containing the group name.
|
||||
///
|
||||
/// This is filled when type is StartField or EndField
|
||||
StringTableEntry pFieldname; ///< Name of the field.
|
||||
const char* pGroupname; ///< Optionally filled field containing the group name.
|
||||
///
|
||||
/// This is filled when type is StartField or EndField
|
||||
|
||||
const char* pFieldDocs; ///< Documentation about this field; see consoleDoc.cc.
|
||||
bool groupExpand; ///< Flag to track expanded/not state of this group in the editor.
|
||||
U32 type; ///< A data type ID or one of the special custom fields. @see ACRFieldTypes
|
||||
U32 offset; ///< Memory offset from beginning of class for this field.
|
||||
S32 elementCount; ///< Number of elements, if this is an array.
|
||||
const EnumTable * table; ///< If this is an enum, this points to the table defining it.
|
||||
BitSet32 flag; ///< Stores various flags
|
||||
TypeValidator *validator; ///< Validator, if any.
|
||||
SetDataNotify setDataFn; ///< Set data notify Fn
|
||||
GetDataNotify getDataFn; ///< Get data notify Fn
|
||||
WriteDataNotify writeDataFn; ///< Function to determine whether data should be written or not.
|
||||
const char* pFieldDocs; ///< Documentation about this field; see consoleDoc.cc.
|
||||
bool groupExpand; ///< Flag to track expanded/not state of this group in the editor.
|
||||
U32 type; ///< A data type ID or one of the special custom fields. @see ACRFieldTypes
|
||||
U32 offset; ///< Memory offset from beginning of class for this field.
|
||||
S32 elementCount; ///< Number of elements, if this is an array.
|
||||
const EnumTable * table; ///< If this is an enum, this points to the table defining it.
|
||||
BitSet32 flag; ///< Stores various flags
|
||||
TypeValidator *validator; ///< Validator, if any.
|
||||
SetDataNotify setDataFn; ///< Set data notify Fn
|
||||
GetDataNotify getDataFn; ///< Get data notify Fn
|
||||
WriteDataNotify writeDataFn; ///< Function to determine whether data should be written or not.
|
||||
VisibilityNotify visibilityFn; ///< Function to determine this field is visibile or not.
|
||||
bool doNotSubstitute;
|
||||
bool keepClearSubsOnly;
|
||||
|
||||
|
|
@ -764,9 +771,173 @@ template< typename T > EnginePropertyTable& ConcreteAbstractClassRep< T >::smPro
|
|||
|
||||
//------------------------------------------------------------------------------
|
||||
// Forward declaration of this function so it can be used in the class
|
||||
bool defaultProtectedSetFn(void* object, const char* index, const char* data);
|
||||
const char *defaultProtectedGetFn( void *obj, const char *data );
|
||||
bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName);
|
||||
|
||||
struct FieldDescriptor {
|
||||
// Context for auto-registration
|
||||
const char* _name = NULL;
|
||||
U32 _type = 0;
|
||||
dsize_t _offset = 0;
|
||||
bool isExpanded = false;
|
||||
bool isGroupBegin = false;
|
||||
bool isGroupEnd = false;
|
||||
bool isArrayBegin = false;
|
||||
bool isArrayEnd = false;
|
||||
bool _active = true;
|
||||
|
||||
// Field properties
|
||||
const char* docs = NULL;
|
||||
AbstractClassRep::SetDataNotify setFn = &defaultProtectedSetFn;
|
||||
AbstractClassRep::GetDataNotify getFn = &defaultProtectedGetFn;
|
||||
AbstractClassRep::WriteDataNotify writeFn = &defaultProtectedWriteFn;
|
||||
TypeValidator* validator = NULL;
|
||||
U32 elementCount = 1;
|
||||
U32 flags = 0;
|
||||
U32 networkMask = 0;
|
||||
AbstractClassRep::VisibilityNotify visibilityFn = NULL;
|
||||
|
||||
// Add documentation to this field.
|
||||
FieldDescriptor& doc(const char* d) { docs = d; return *this; }
|
||||
// The number of elements for this field (U32 number)
|
||||
FieldDescriptor& elements(U32 n) { elementCount = n; return *this; }
|
||||
// The validator for this field.
|
||||
FieldDescriptor& validate(TypeValidator* v) { validator = v; return *this; }
|
||||
// The set data function.
|
||||
FieldDescriptor& onSet(AbstractClassRep::SetDataNotify fn) { setFn = fn; return *this; }
|
||||
// The get data function.
|
||||
FieldDescriptor& onGet(AbstractClassRep::GetDataNotify fn) { getFn = fn; return *this; }
|
||||
// The on write function
|
||||
FieldDescriptor& onWrite(AbstractClassRep::WriteDataNotify fn) { writeFn = fn; return *this; }
|
||||
// The visibility function
|
||||
FieldDescriptor& showWhen(AbstractClassRep::VisibilityNotify fn) { visibilityFn = fn; return *this; }
|
||||
// The network mask changes will trigger.
|
||||
FieldDescriptor& network(U32 mask) { networkMask = mask; return *this; }
|
||||
// The flags for this field.
|
||||
FieldDescriptor& withFlags(U32 f) { flags = f; return *this; }
|
||||
// This field marks the start of a group.
|
||||
FieldDescriptor& startGroup() { isGroupBegin = true; return *this; }
|
||||
// This field marks the end of a group.
|
||||
FieldDescriptor& endGroup() { isGroupEnd = true; return *this; }
|
||||
// This field marks the start of an array.
|
||||
FieldDescriptor& startArray() { isArrayBegin = true; return *this; }
|
||||
// This field marks the end of an array.
|
||||
FieldDescriptor& endArray() { isArrayEnd = true; return *this; }
|
||||
// This field should start expanded in the inspector.
|
||||
FieldDescriptor& expanded() { isExpanded = true; return *this; }
|
||||
|
||||
FieldDescriptor(const char* name, U32 type = 0, dsize_t offset = 0)
|
||||
: _name(name), _type(type), _offset(offset)
|
||||
{}
|
||||
|
||||
FieldDescriptor(const FieldDescriptor&) = delete;
|
||||
FieldDescriptor& operator=(const FieldDescriptor&) = delete;
|
||||
|
||||
FieldDescriptor(FieldDescriptor&& other) noexcept
|
||||
{
|
||||
moveFrom(std::move(other));
|
||||
}
|
||||
|
||||
FieldDescriptor& operator=(FieldDescriptor&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
moveFrom(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void moveFrom(FieldDescriptor&& other)
|
||||
{
|
||||
// transfer all data
|
||||
_name = other._name;
|
||||
_type = other._type;
|
||||
_offset = other._offset;
|
||||
|
||||
docs = other.docs;
|
||||
setFn = other.setFn;
|
||||
getFn = other.getFn;
|
||||
writeFn = other.writeFn;
|
||||
validator = other.validator;
|
||||
elementCount = other.elementCount;
|
||||
flags = other.flags;
|
||||
networkMask = other.networkMask;
|
||||
visibilityFn = other.visibilityFn;
|
||||
|
||||
isExpanded = other.isExpanded;
|
||||
isGroupBegin = other.isGroupBegin;
|
||||
isGroupEnd = other.isGroupEnd;
|
||||
isArrayBegin = other.isArrayBegin;
|
||||
isArrayEnd = other.isArrayEnd;
|
||||
|
||||
// transfer ownership of "registration responsibility"
|
||||
_active = other._active;
|
||||
|
||||
// CRITICAL: disable the source so its destructor does NOTHING
|
||||
other._active = false;
|
||||
}
|
||||
|
||||
~FieldDescriptor();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// Registers a standard field.
|
||||
/// Usage:
|
||||
/// FIELD("health", TypeS32, Offset(mHealth, Player)).doc("Player health");
|
||||
#define ADD_FIELD(name, type, offset) \
|
||||
FieldDescriptor(name, type, offset)
|
||||
|
||||
/// Field with fixed element count.
|
||||
/// Usage:
|
||||
/// FIELD_ARRAY("color", TypeColorF, Offset(mColor, GuiControl), 4);
|
||||
#define FIELD_ARRAY(name, type, offset, count) \
|
||||
FieldDescriptor(name, type, offset).elements(count)
|
||||
|
||||
/// Begins a field group in the inspector.
|
||||
/// All fields declared after this will belong to the group until GROUP_END().
|
||||
/// Usage:
|
||||
/// GROUP_BEGIN("Rendering").expanded();
|
||||
#define GROUP_BEGIN(name) \
|
||||
FieldDescriptor(name).startGroup()
|
||||
|
||||
/// Ends the current field group.
|
||||
/// Must match a preceding GROUP_BEGIN().
|
||||
/// Usage:
|
||||
/// GROUP_END("Rendering");
|
||||
#define GROUP_END(name) \
|
||||
FieldDescriptor(name).endGroup()
|
||||
|
||||
/// Begins an array block in the inspector.
|
||||
/// Usage:
|
||||
/// ARRAY_BEGIN("Waypoints");
|
||||
#define ARRAY_BEGIN(name, count) \
|
||||
FieldDescriptor(name).startArray().elements(count)
|
||||
|
||||
/// Ends an array block.
|
||||
/// Usage:
|
||||
/// ARRAY_END("Waypoints");
|
||||
#define ARRAY_END(name) \
|
||||
FieldDescriptor(name).endArray()
|
||||
|
||||
/// Declares a scoped inspector group.
|
||||
///
|
||||
/// Provides a structured grouping of fields in the inspector UI using a scoped
|
||||
/// block. Internally, this macro guarantees that a matching group end marker
|
||||
/// is emitted, preventing mismatched begin/end pairs.
|
||||
#define GROUP(name) \
|
||||
for (bool _once = true; _once; _once = false) \
|
||||
for (FieldDescriptor(name).startGroup(); _once; FieldDescriptor(name).endGroup(), _once = false)
|
||||
|
||||
/// Declares a scoped inspector array block.
|
||||
///
|
||||
/// Defines a logical array grouping in the inspector UI. Fields declared within
|
||||
/// the block are treated as elements of the array. Like GROUP, this macro
|
||||
/// ensures that the array begin/end markers are correctly paired using scoped
|
||||
/// execution.
|
||||
#define ARRAY(name, count) \
|
||||
for (bool _once = true; _once; _once = false) \
|
||||
for (FieldDescriptor(name).startArray().elements(count); _once; FieldDescriptor(name).endArray(), _once = false)
|
||||
|
||||
//=============================================================================
|
||||
// ConsoleObject.
|
||||
//=============================================================================
|
||||
|
|
@ -871,6 +1042,7 @@ public:
|
|||
|
||||
/// @name Fields
|
||||
/// @{
|
||||
static void registerField(const char* name, U32 type, dsize_t offset, const FieldDescriptor& desc);
|
||||
|
||||
/// Mark the beginning of a group of fields.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -785,6 +785,59 @@ void GuiInspector::refresh()
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::updateVisibility()
|
||||
{
|
||||
const U32 numTargets = getNumInspectObjects();
|
||||
|
||||
for (U32 i = 0; i < numTargets; i++)
|
||||
{
|
||||
|
||||
SimObject* target = getInspectObject(i);
|
||||
if (!target) return;
|
||||
|
||||
for (GuiInspectorGroup* group : mGroups)
|
||||
{
|
||||
const AbstractClassRep::Field* g = target->findField(group->getGroupName().c_str());
|
||||
|
||||
// if group has its own visibility function let it control it.
|
||||
bool group_visible = (!g || !g->visibilityFn) ? true : g->visibilityFn(target, "0");
|
||||
if (!group_visible)
|
||||
{
|
||||
group->setVisible(group_visible);
|
||||
return;
|
||||
}
|
||||
|
||||
bool anyVisible = false;
|
||||
for (GuiInspectorField* field : group->mChildren)
|
||||
{
|
||||
const AbstractClassRep::Field* f = field->getField();
|
||||
StringTableEntry idx = field->getArrayIndex();
|
||||
bool visible = (!f || !f->visibilityFn) ? true : f->visibilityFn(target, idx);
|
||||
|
||||
field->setVisible(visible);
|
||||
if (visible)
|
||||
anyVisible = true;
|
||||
}
|
||||
|
||||
// Per-array-element rollout visibility
|
||||
for (GuiInspectorGroup::ArrayElementEntry& elem : group->mArrayElements)
|
||||
{
|
||||
bool visible = false;
|
||||
if (!elem.arrayField || !elem.arrayField->visibilityFn || elem.elementIndex == 0)
|
||||
visible = true;
|
||||
|
||||
if (!visible)
|
||||
visible = elem.arrayField->visibilityFn(target, String::ToString(elem.elementIndex));
|
||||
|
||||
elem.rollout->setVisible(visible);
|
||||
if (visible) anyVisible = true;
|
||||
}
|
||||
|
||||
group->setVisible(anyVisible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiInspector::sendInspectPreApply()
|
||||
{
|
||||
const U32 numObjects = getNumInspectObjects();
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void updateVisibility();
|
||||
|
||||
S32 getComponentGroupTargetId() { return mComponentGroupTargetId; }
|
||||
void setComponentGroupTargetId(S32 compId) { mComponentGroupTargetId = compId; }
|
||||
|
||||
|
|
|
|||
|
|
@ -835,6 +835,8 @@ void GuiInspectorField::updateValue()
|
|||
}
|
||||
else
|
||||
setValue( getData() );
|
||||
|
||||
mInspector->updateVisibility();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ class GuiInspectorField : public GuiControl
|
|||
|
||||
///
|
||||
StringTableEntry getArrayIndex() const { return mFieldArrayIndex; }
|
||||
AbstractClassRep::Field* getField() const { return mField; }
|
||||
|
||||
/// Called from within setData to allow child classes
|
||||
/// to perform their own verification.
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ GuiInspectorGroup::GuiInspectorGroup( const String& groupName,
|
|||
|
||||
mChildren.clear();
|
||||
mMargin.set(0,0,4,0);
|
||||
VECTOR_SET_ASSOCIATION(mArrayElements);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -229,6 +230,7 @@ void GuiInspectorGroup::clearFields()
|
|||
// that we keep for our own convenience.
|
||||
mArrayCtrls.clear();
|
||||
mChildren.clear();
|
||||
mArrayElements.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -336,7 +338,7 @@ bool GuiInspectorGroup::inspectGroup()
|
|||
GuiControlProfile* elementRolloutProfile = dynamic_cast<GuiControlProfile*>(Sim::findObject("GuiInspectorRolloutProfile0"));
|
||||
|
||||
char buf[256];
|
||||
dSprintf(buf, 256, " [%i]", i);
|
||||
dSprintf(buf, 256, " [%i/%i]", i, field->elementCount);
|
||||
|
||||
elementRollout->setControlProfile(elementRolloutProfile);
|
||||
elementRollout->setCaption(buf);
|
||||
|
|
@ -349,6 +351,8 @@ bool GuiInspectorGroup::inspectGroup()
|
|||
elementRollout->instantCollapse();
|
||||
|
||||
arrayStack->addObject(elementRollout);
|
||||
|
||||
mArrayElements.push_back({ elementRollout, (S32)i, field });
|
||||
}
|
||||
|
||||
pArrayRollout = arrayRollout;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,13 @@ private:
|
|||
typedef GuiRolloutCtrl Parent;
|
||||
public:
|
||||
// Members
|
||||
struct ArrayElementEntry
|
||||
{
|
||||
GuiRolloutCtrl* rollout;
|
||||
S32 elementIndex;
|
||||
const AbstractClassRep::Field* arrayField; // the StartArrayFieldType field
|
||||
};
|
||||
Vector<ArrayElementEntry> mArrayElements;
|
||||
SimObjectPtr<GuiInspector> mParent;
|
||||
Vector<GuiInspectorField*> mChildren;
|
||||
GuiStackControl* mStack;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue