mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-19 19:35:26 +00:00
Update of Particle Editor to standardize it up and utilize inspectors rather than adhoc guis
This commit is contained in:
parent
1f5a4267ac
commit
12ebebff46
31 changed files with 5091 additions and 6095 deletions
|
|
@ -351,7 +351,7 @@ public:
|
|||
|
||||
#define INITPERSISTFIELD_IMAGEASSET(name, consoleClass, docs) \
|
||||
addProtectedField(assetText(name, Asset), TypeImageAssetPtr, Offset(m##name##Asset, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, asset docs.)); \
|
||||
addProtectedField(assetText(name, File), TypeFilename, Offset(m##name##File, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, file docs.));
|
||||
addProtectedField(assetText(name, File), TypeFilename, Offset(m##name##File, consoleClass), _set##name##Data, &defaultProtectedGetFn, assetDoc(name, file docs.), AbstractClassRep::FIELD_HideInInspectors);
|
||||
|
||||
|
||||
#define DECLARE_IMAGEASSET_ARRAY(className, name, profile, max) \
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "math/mRandom.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "particleInspectors.h"
|
||||
|
||||
IMPLEMENT_CO_DATABLOCK_V1( ParticleData );
|
||||
|
||||
|
|
@ -814,3 +815,313 @@ void ParticleData::onPerformSubstitutions()
|
|||
}
|
||||
|
||||
DEF_ASSET_BINDS_REFACTOR(ParticleData, Texture);
|
||||
|
||||
ConsoleType(stringList, TypeParticleList, Vector<StringTableEntry>, "")
|
||||
|
||||
ConsoleGetType(TypeParticleList)
|
||||
{
|
||||
Vector<StringTableEntry>* vec = (Vector<StringTableEntry> *)dptr;
|
||||
S32 buffSize = (vec->size() * 15) + 16;
|
||||
char* returnBuffer = Con::getReturnBuffer(buffSize);
|
||||
S32 maxReturn = buffSize;
|
||||
returnBuffer[0] = '\0';
|
||||
S32 returnLeng = 0;
|
||||
for (Vector<const char*>::iterator itr = vec->begin(); itr != vec->end(); itr++)
|
||||
{
|
||||
// concatenate the next value onto the return string
|
||||
dSprintf(returnBuffer + returnLeng, maxReturn - returnLeng, "%s ", *itr);
|
||||
// update the length of the return string (so far)
|
||||
returnLeng = dStrlen(returnBuffer);
|
||||
}
|
||||
// trim off that last extra space
|
||||
if (returnLeng > 0 && returnBuffer[returnLeng - 1] == ' ')
|
||||
returnBuffer[returnLeng - 1] = '\0';
|
||||
return returnBuffer;
|
||||
}
|
||||
|
||||
ConsoleSetType(TypeParticleList)
|
||||
{
|
||||
Vector<StringTableEntry>* vec = (Vector<StringTableEntry> *)dptr;
|
||||
// we assume the vector should be cleared first (not just appending)
|
||||
vec->clear();
|
||||
S32 numUnits = 0;
|
||||
if (argc == 1)
|
||||
{
|
||||
const char* values = argv[0];
|
||||
numUnits = StringUnit::getUnitCount(values, " ");
|
||||
|
||||
if (numUnits > 1)
|
||||
bool dafgdf = true;
|
||||
|
||||
for (U32 i = 0; i < numUnits; i++)
|
||||
{
|
||||
const char* value = StringUnit::getUnit(values, i, " ");
|
||||
|
||||
vec->push_back(StringTable->insert(value));
|
||||
}
|
||||
}
|
||||
else if (argc > 1)
|
||||
{
|
||||
for (S32 i = 0; i < argc; i++)
|
||||
vec->push_back(StringTable->insert(argv[i]));
|
||||
}
|
||||
else
|
||||
Con::printf("TypeParticleList must be set as { a, b, c, ... } or \"a b c ...\"");
|
||||
|
||||
if (numUnits > 1)
|
||||
{
|
||||
for (U32 x = 0; x < numUnits; x++)
|
||||
{
|
||||
Vector<const char*> testVec = *vec;
|
||||
String test = testVec[x];
|
||||
Con::printf("TypeParticleList vec results: %s", testVec[x]);
|
||||
}
|
||||
}
|
||||
bool test = false;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeExpandableIdList
|
||||
//-----------------------------------------------------------------------------
|
||||
/**/IMPLEMENT_CONOBJECT(GuiInspectorTypeParticleDataList);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeParticleDataList,
|
||||
"@brief Inspector field type for ParticleData lists\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
GuiControl* GuiInspectorTypeParticleDataList::constructEditControl()
|
||||
{
|
||||
mStack = new GuiStackControl();
|
||||
|
||||
if (mStack == NULL)
|
||||
return mStack;
|
||||
|
||||
mStack->registerObject();
|
||||
mStack->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiDefaultProfile");
|
||||
mStack->setPadding(3);
|
||||
|
||||
mNewParticleBtn = new GuiIconButtonCtrl();
|
||||
mNewParticleBtn->registerObject();
|
||||
mNewParticleBtn->_setBitmap(StringTable->insert("ToolsModule:iconAdd_image"));
|
||||
mNewParticleBtn->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiDefaultProfile");
|
||||
mNewParticleBtn->setHorizSizing(horizResizeRight);
|
||||
mNewParticleBtn->mMakeIconSquare = true;
|
||||
mNewParticleBtn->mFitBitmapToButton = true;
|
||||
mNewParticleBtn->setExtent(20, 20);
|
||||
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "ParticleEditor.addParticleSlot(%s, %s);",
|
||||
mNewParticleBtn->getIdString(), mInspector->getInspectObject()->getIdString());
|
||||
mNewParticleBtn->setField("Command", szBuffer);
|
||||
|
||||
GuiContainer* newBtnCtnr = new GuiContainer();
|
||||
newBtnCtnr->registerObject();
|
||||
newBtnCtnr->addObject(mNewParticleBtn);
|
||||
newBtnCtnr->setHorizSizing(horizResizeWidth);
|
||||
|
||||
mStack->addObject(newBtnCtnr);
|
||||
|
||||
//Particle 0
|
||||
mParticleSlot0Ctrl = _buildParticleEntryField(0);
|
||||
|
||||
mStack->addObject(mParticleSlot0Ctrl);
|
||||
|
||||
//Now the non-default entries if we already have some
|
||||
Parent::updateValue();
|
||||
const char* data = getData();
|
||||
|
||||
if (data != nullptr && !String::isEmpty(data))
|
||||
{
|
||||
U32 particlesCount = StringUnit::getUnitCount(data, " ");
|
||||
for (U32 i=1; i < particlesCount; i++)
|
||||
{
|
||||
GuiControl* particleSlotCtrl = _buildParticleEntryField(i);
|
||||
mStack->addObject(particleSlotCtrl);
|
||||
}
|
||||
}
|
||||
|
||||
_registerEditControl(mStack);
|
||||
|
||||
//constructEditControlChildren(retCtrl, getWidth());
|
||||
|
||||
//retCtrl->addObject(mScriptValue);
|
||||
|
||||
/*char szBuffer[512];
|
||||
dSprintf(szBuffer, 512, "setClipboard(%d.getText());", mScriptValue->getId());
|
||||
mCopyButton->setField("Command", szBuffer);
|
||||
addObject(mCopyButton);*/
|
||||
|
||||
mUseHeightOverride = true;
|
||||
mHeightOverride = (mStack->getCount() * 23) + 6;
|
||||
|
||||
return mStack;
|
||||
}
|
||||
|
||||
GuiControl* GuiInspectorTypeParticleDataList::_buildParticleEntryField(const S32& index)
|
||||
{
|
||||
Point2I editPos = mStack->getPosition();
|
||||
Point2I editExtent = mStack->getExtent();
|
||||
|
||||
//Particle 0
|
||||
GuiControl* particleSlotCtrl = new GuiControl();
|
||||
particleSlotCtrl->registerObject();
|
||||
particleSlotCtrl->setExtent(editExtent.x, 18);
|
||||
particleSlotCtrl->setHorizSizing(horizResizeWidth);
|
||||
|
||||
GuiButtonCtrl* listBtn = new GuiButtonCtrl();
|
||||
listBtn->registerObject();
|
||||
listBtn->setHorizSizing(horizResizeLeft);
|
||||
listBtn->setInternalName("particleDropdown");
|
||||
listBtn->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiButtonProfile");
|
||||
listBtn->setExtent(editExtent.x - 40, 18);
|
||||
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "ParticleEditor.changeParticleSlot(%s, %s, %d);",
|
||||
listBtn->getIdString(), mInspector->getInspectObject()->getIdString(), index);
|
||||
listBtn->setField("Command", szBuffer);
|
||||
|
||||
if (mField && index != -1)
|
||||
{
|
||||
Parent::updateValue();
|
||||
const char* data = getData();
|
||||
|
||||
if (data != nullptr && !String::isEmpty(data))
|
||||
{
|
||||
const char* particleSlotData = StringUnit::getUnit(data, index, " ");
|
||||
listBtn->setText(particleSlotData);
|
||||
}
|
||||
}
|
||||
|
||||
particleSlotCtrl->addObject(listBtn);
|
||||
|
||||
GuiButtonCtrl* editSlotBtn = new GuiIconButtonCtrl();
|
||||
editSlotBtn->registerObject();
|
||||
editSlotBtn->setText(StringTable->insert("..."));
|
||||
editSlotBtn->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiButtonProfile");
|
||||
editSlotBtn->setHorizSizing(horizResizeRight);
|
||||
editSlotBtn->setInternalName("editBtn");
|
||||
editSlotBtn->setPosition(editExtent.x - 40, 0);
|
||||
editSlotBtn->setExtent(20, 20);
|
||||
|
||||
char cmdBuffer[512];
|
||||
dSprintf(cmdBuffer, sizeof(cmdBuffer), "ParticleEditor.editParticleSlot(%s, %s, %d);",
|
||||
this->getIdString(), mInspector->getInspectObject()->getIdString(), index);
|
||||
editSlotBtn->setField("Command", cmdBuffer);
|
||||
|
||||
particleSlotCtrl->addObject(editSlotBtn);
|
||||
|
||||
if (index != 0)
|
||||
{
|
||||
GuiIconButtonCtrl* deleteSlotBtn = new GuiIconButtonCtrl();
|
||||
deleteSlotBtn->registerObject();
|
||||
deleteSlotBtn->_setBitmap(StringTable->insert("ToolsModule:iconCancel_image"));
|
||||
deleteSlotBtn->setDataField(StringTable->insert("profile"), NULL, "ToolsGuiDefaultProfile");
|
||||
deleteSlotBtn->setHorizSizing(horizResizeRight);
|
||||
deleteSlotBtn->setInternalName("deleteBtn");
|
||||
deleteSlotBtn->mMakeIconSquare = true;
|
||||
deleteSlotBtn->mFitBitmapToButton = true;
|
||||
deleteSlotBtn->setPosition(editExtent.x - 20, 0);
|
||||
deleteSlotBtn->setExtent(20, 20);
|
||||
|
||||
char cmdBuffer[512];
|
||||
dSprintf(cmdBuffer, sizeof(cmdBuffer), "ParticleEditor.clearParticleSlot(%s, %s, %d);",
|
||||
this->getIdString(), mInspector->getInspectObject()->getIdString(), index);
|
||||
deleteSlotBtn->setField("Command", cmdBuffer);
|
||||
|
||||
particleSlotCtrl->addObject(deleteSlotBtn);
|
||||
}
|
||||
|
||||
return particleSlotCtrl;
|
||||
}
|
||||
|
||||
void GuiInspectorTypeParticleDataList::_populateMenu(GuiPopUpMenuCtrlEx* menu)
|
||||
{
|
||||
// Check whether we should show profiles from the editor category.
|
||||
|
||||
const bool showEditorProfiles = Con::getBoolVariable("$pref::GuiEditor::showEditorProfiles", false);
|
||||
|
||||
// Add the control profiles to the menu.
|
||||
|
||||
SimGroup* grp = Sim::getGuiDataGroup();
|
||||
SimSetIterator iter(grp);
|
||||
for (; *iter; ++iter)
|
||||
{
|
||||
GuiControlProfile* profile = dynamic_cast<GuiControlProfile*>(*iter);
|
||||
if (!profile)
|
||||
continue;
|
||||
|
||||
if (!showEditorProfiles && profile->mCategory.compare("Editor", 0, String::NoCase) == 0)
|
||||
continue;
|
||||
|
||||
menu->addEntry(profile->getName(), profile->getId());
|
||||
}
|
||||
|
||||
menu->sort();
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeParticleDataList::updateRects()
|
||||
{
|
||||
S32 rowSize = 18;
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider(dividerPos, dividerMargin);
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
|
||||
|
||||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin, fieldExtent.y);
|
||||
S32 cellWidth = mCeil((dividerPos - dividerMargin - 29));
|
||||
|
||||
mNewParticleBtn->resize(Point2I(mEditCtrlRect.extent.x - 20, 0), Point2I(20, 20));
|
||||
|
||||
//Particle Slot 0 is mandatory
|
||||
auto c = mStack->getCount();
|
||||
for (U32 i=0; i < mStack->getCount(); i++)
|
||||
{
|
||||
GuiControl* slot = static_cast<GuiControl*>(mStack->getObject(i));
|
||||
|
||||
slot->resize(Point2I(0, 0), Point2I(mEditCtrlRect.extent.x, rowSize));
|
||||
|
||||
GuiControl* dropdown = dynamic_cast<GuiControl*>(slot->findObjectByInternalName(StringTable->insert("particleDropdown")));
|
||||
if (dropdown)
|
||||
{
|
||||
dropdown->setPosition(0, 0);
|
||||
dropdown->setExtent(mEditCtrlRect.extent.x - 40, 20);
|
||||
}
|
||||
|
||||
GuiControl* editBtn = dynamic_cast<GuiControl*>(slot->findObjectByInternalName(StringTable->insert("editBtn")));
|
||||
if (editBtn)
|
||||
{
|
||||
editBtn->setPosition(mEditCtrlRect.extent.x - 40, 0);
|
||||
editBtn->setExtent(20, 20);
|
||||
}
|
||||
|
||||
GuiControl* deleteBtn = dynamic_cast<GuiControl*>(slot->findObjectByInternalName(StringTable->insert("deleteBtn")));
|
||||
if (deleteBtn)
|
||||
{
|
||||
deleteBtn->setPosition(mEditCtrlRect.extent.x - 20, 0);
|
||||
deleteBtn->setExtent(20, 20);
|
||||
}
|
||||
}
|
||||
|
||||
mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
|
||||
mHeightOverride = (mStack->getCount() * 23) + 6;
|
||||
|
||||
//mCopyButton->resize(Point2I(mProfile->mTextOffset.x, rowSize + 3), Point2I(45, 15));
|
||||
//mPasteButton->resize(Point2I(mProfile->mTextOffset.x, rowSize + rowSize + 6), Point2I(45, 15));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GuiInspectorTypeParticleDataList::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType(TypeParticleList)->setInspectorFieldType("GuiInspectorTypeParticleDataList");
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
#pragma once
|
||||
|
||||
#ifndef _PARTICLE_H_
|
||||
#define _PARTICLE_H_
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "T3D/gameBase/gameProcess.h"
|
||||
#include "lighting/lightInfo.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "particleInspectors.h"
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
#include "afx/util/afxParticlePool.h"
|
||||
|
|
@ -145,7 +146,6 @@ ParticleEmitterData::ParticleEmitterData()
|
|||
ribbonParticles = false;
|
||||
useEmitterSizes = false;
|
||||
useEmitterColors = false;
|
||||
particleString = NULL;
|
||||
partListInitSize = 0;
|
||||
|
||||
// These members added for support of user defined blend factors
|
||||
|
|
@ -265,7 +265,7 @@ void ParticleEmitterData::initPersistFields()
|
|||
addField( "ribbonParticles", TYPEID< bool >(), Offset(ribbonParticles, ParticleEmitterData),
|
||||
"If true, particles are rendered as a continous ribbon." );
|
||||
|
||||
addField( "particles", TYPEID< StringTableEntry >(), Offset(particleString, ParticleEmitterData),
|
||||
addField( "particles", TypeParticleList, Offset(particleString, ParticleEmitterData),
|
||||
"@brief List of space or TAB delimited ParticleData datablock names.\n\n"
|
||||
"A random one of these datablocks is selected each time a particle is "
|
||||
"emitted." );
|
||||
|
|
@ -605,21 +605,11 @@ bool ParticleEmitterData::onAdd()
|
|||
softnessDistance = 0.0f;
|
||||
}
|
||||
|
||||
if (particleString == NULL && dataBlockIds.size() == 0)
|
||||
if (particleString.empty() && dataBlockIds.size() == 0)
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleEmitterData(%s) no particleString, invalid datablock", getName());
|
||||
return false;
|
||||
}
|
||||
if (particleString && particleString[0] == '\0')
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleEmitterData(%s) no particleString, invalid datablock", getName());
|
||||
return false;
|
||||
}
|
||||
if (particleString && dStrlen(particleString) > 255)
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "ParticleEmitterData(%s) particle string too long [> 255 chars]", getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if( lifetimeMS < 0 )
|
||||
{
|
||||
|
|
@ -635,40 +625,18 @@ bool ParticleEmitterData::onAdd()
|
|||
|
||||
// load the particle datablocks...
|
||||
//
|
||||
if( particleString != NULL )
|
||||
if( !particleString.empty() )
|
||||
{
|
||||
// particleString is once again a list of particle datablocks so it
|
||||
// must be parsed to extract the particle references.
|
||||
|
||||
// First we parse particleString into a list of particle name tokens
|
||||
Vector<char*> dataBlocks(__FILE__, __LINE__);
|
||||
dsize_t tokLen = dStrlen(particleString) + 1;
|
||||
char* tokCopy = new char[tokLen];
|
||||
dStrcpy(tokCopy, particleString, tokLen);
|
||||
|
||||
char* currTok = dStrtok(tokCopy, " \t");
|
||||
while (currTok != NULL)
|
||||
{
|
||||
dataBlocks.push_back(currTok);
|
||||
currTok = dStrtok(NULL, " \t");
|
||||
}
|
||||
if (dataBlocks.size() == 0)
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleEmitterData(%s) invalid particles string. No datablocks found", getName());
|
||||
delete [] tokCopy;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now we convert the particle name tokens into particle datablocks and IDs
|
||||
particleDataBlocks.clear();
|
||||
dataBlockIds.clear();
|
||||
|
||||
for (U32 i = 0; i < dataBlocks.size(); i++)
|
||||
for (U32 i = 0; i < particleString.size(); i++)
|
||||
{
|
||||
ParticleData* pData = NULL;
|
||||
if (Sim::findObject(dataBlocks[i], pData) == false)
|
||||
if (Sim::findObject(particleString[i], pData) == false)
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleEmitterData(%s) unable to find particle datablock: %s", getName(), dataBlocks[i]);
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleEmitterData(%s) unable to find particle datablock: %s", getName(), particleString[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -677,9 +645,6 @@ bool ParticleEmitterData::onAdd()
|
|||
}
|
||||
}
|
||||
|
||||
// cleanup
|
||||
delete [] tokCopy;
|
||||
|
||||
// check that we actually found some particle datablocks
|
||||
if (particleDataBlocks.size() == 0)
|
||||
{
|
||||
|
|
@ -2570,26 +2535,12 @@ bool ParticleEmitterData::reload()
|
|||
dataBlockIds.clear();
|
||||
particleDataBlocks.clear();
|
||||
|
||||
// Parse out particle string.
|
||||
|
||||
U32 numUnits = 0;
|
||||
if( particleString )
|
||||
numUnits = StringUnit::getUnitCount( particleString, " \t" );
|
||||
if( !particleString || !particleString[ 0 ] || !numUnits )
|
||||
for( U32 i = 0; i < particleString.size(); ++ i )
|
||||
{
|
||||
Con::errorf( "ParticleEmitterData(%s) has an empty particles string.", getName() );
|
||||
mReloadSignal.trigger();
|
||||
return false;
|
||||
}
|
||||
|
||||
for( U32 i = 0; i < numUnits; ++ i )
|
||||
{
|
||||
const char* dbName = StringUnit::getUnit( particleString, i, " \t" );
|
||||
|
||||
ParticleData* data = NULL;
|
||||
if( !Sim::findObject( dbName, data ) )
|
||||
if( !Sim::findObject(particleString[i], data))
|
||||
{
|
||||
Con::errorf( ConsoleLogEntry::General, "ParticleEmitterData(%s) unable to find particle datablock: %s", getName(), dbName );
|
||||
Con::errorf( ConsoleLogEntry::General, "ParticleEmitterData(%s) unable to find particle datablock: %s", getName(), particleString[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class ParticleEmitterData : public GameBaseData
|
|||
bool alignParticles; ///< Particles always face along a particular axis
|
||||
Point3F alignDirection; ///< The direction aligned particles should face
|
||||
|
||||
StringTableEntry particleString; ///< Used to load particle data directly from a string
|
||||
Vector<StringTableEntry> particleString; ///< Used to load particle data directly from a string
|
||||
|
||||
Vector<ParticleData*> particleDataBlocks; ///< Particle Datablocks
|
||||
Vector<U32> dataBlockIds; ///< Datablock IDs (parellel array to particleDataBlocks)
|
||||
|
|
|
|||
40
Engine/source/T3D/fx/particleInspectors.h
Normal file
40
Engine/source/T3D/fx/particleInspectors.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
#ifdef TORQUE_TOOLS
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
#endif
|
||||
|
||||
#include "gui/containers/guiStackCtrl.h"
|
||||
#include "gui/controls/guiPopUpCtrlEx.h"
|
||||
#include "gui/editor/inspector/field.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeParticleList
|
||||
//-----------------------------------------------------------------------------
|
||||
DefineConsoleType(TypeParticleList, Vector<const char*>)
|
||||
|
||||
|
||||
#ifdef TORQUE_TOOLS
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeGuiProfile Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeParticleDataList : public GuiInspectorField
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
GuiStackControl* mStack;
|
||||
GuiIconButtonCtrl* mNewParticleBtn;
|
||||
GuiControl* mParticleSlot0Ctrl;
|
||||
Vector<GuiControl*> mParticleSlotList;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeParticleDataList);
|
||||
static void consoleInit();
|
||||
|
||||
GuiControl* constructEditControl() override;
|
||||
bool updateRects() override;
|
||||
|
||||
void _populateMenu(GuiPopUpMenuCtrlEx* menu);
|
||||
GuiControl* _buildParticleEntryField(const S32& index);
|
||||
};
|
||||
#endif
|
||||
|
|
@ -387,3 +387,8 @@ void GuiStackControl::childResized(GuiControl *child)
|
|||
{
|
||||
updatePanes();
|
||||
}
|
||||
|
||||
void GuiStackControl::setPadding(const U32& padding)
|
||||
{
|
||||
mPadding = padding;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ public:
|
|||
|
||||
bool reOrder(SimObject* obj, SimObject* target = 0) override;
|
||||
|
||||
void setPadding(const U32& padding);
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT(GuiStackControl);
|
||||
|
|
|
|||
|
|
@ -781,6 +781,30 @@ void GuiInspectorGroup::hideInspectorField(StringTableEntry fieldName, bool setH
|
|||
field->flag.clear(AbstractClassRep::FIELD_HideInInspectors);
|
||||
}
|
||||
|
||||
void GuiInspectorGroup::replaceInspectorField(StringTableEntry fieldName, GuiInspectorField* replacementField)
|
||||
{
|
||||
for (U32 i = 0; i < mStack->size(); i++)
|
||||
{
|
||||
GuiInspectorField* field = dynamic_cast<GuiInspectorField*>(mStack->getObject(i));
|
||||
|
||||
if (field == nullptr)
|
||||
continue;
|
||||
|
||||
if (field->getFieldName() == fieldName || field->getSpecialEditVariableName() == fieldName)
|
||||
{
|
||||
//ensure we match up to the internals
|
||||
replacementField->mField = field->mField;
|
||||
|
||||
mStack->addObject(replacementField);
|
||||
mStack->reOrder(replacementField, field);
|
||||
|
||||
mStack->removeObject(field);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorGroup, createInspectorField, GuiInspectorField*, (), , "createInspectorField()")
|
||||
{
|
||||
return object->createInspectorField();
|
||||
|
|
@ -828,6 +852,16 @@ DefineEngineMethod(GuiInspectorGroup, hideField, void, (const char* fieldName, b
|
|||
object->hideInspectorField(StringTable->insert(fieldName), setHidden);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorGroup, replaceField, void, (const char* fieldName, GuiInspectorField* field), (nullAsType<GuiInspectorField*>()),
|
||||
"Removes a Inspector field to this group of a given name.\n"
|
||||
"@param fieldName The name of the field to be removed.")
|
||||
{
|
||||
if (dStrEqual(fieldName, ""))
|
||||
return;
|
||||
|
||||
object->replaceInspectorField(StringTable->insert(fieldName), field);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiInspectorGroup, setForcedArrayIndex, void, (S32 arrayIndex), (-1),
|
||||
"Sets the ForcedArrayIndex for the group. Used to force presentation of arrayed fields to only show a specific field index."
|
||||
"@param arrayIndex The specific field index for arrayed fields to show. Use -1 or blank arg to go back to normal behavior.")
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ public:
|
|||
void addInspectorField(GuiInspectorField* field);
|
||||
void removeInspectorField(StringTableEntry name);
|
||||
void hideInspectorField(StringTableEntry fieldName, bool setHidden);
|
||||
void replaceInspectorField(StringTableEntry fieldName, GuiInspectorField* replacementField);
|
||||
|
||||
void setForcedArrayIndex(const S32& arrayIndex = -1)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue