mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-13 07:34:45 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
129
Engine/source/gui/editor/inspector/customField.cpp
Normal file
129
Engine/source/gui/editor/inspector/customField.cpp
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "gui/editor/inspector/customField.h"
|
||||
#include "gui/editor/guiInspector.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorCustomField - Child class of GuiInspectorField
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT( GuiInspectorCustomField );
|
||||
|
||||
ConsoleDocClass( GuiInspectorCustomField,
|
||||
"@brief A control that allows to edit the custom properties (text) of one or more SimObjects.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
GuiInspectorCustomField::GuiInspectorCustomField( GuiInspector *inspector,
|
||||
GuiInspectorGroup* parent,
|
||||
SimFieldDictionary::Entry* field )
|
||||
{
|
||||
mInspector = inspector;
|
||||
mParent = parent;
|
||||
setBounds(0,0,100,20);
|
||||
}
|
||||
|
||||
GuiInspectorCustomField::GuiInspectorCustomField()
|
||||
{
|
||||
mInspector = NULL;
|
||||
mParent = NULL;
|
||||
}
|
||||
|
||||
void GuiInspectorCustomField::setData( const char* data, bool callbacks )
|
||||
{
|
||||
mCustomValue = data;
|
||||
|
||||
// Force our edit to update
|
||||
updateValue();
|
||||
}
|
||||
|
||||
const char* GuiInspectorCustomField::getData( U32 inspectObjectIndex )
|
||||
{
|
||||
return mCustomValue;
|
||||
}
|
||||
|
||||
void GuiInspectorCustomField::updateValue()
|
||||
{
|
||||
setValue( mCustomValue );
|
||||
}
|
||||
|
||||
void GuiInspectorCustomField::setDoc( const char* doc )
|
||||
{
|
||||
mDoc = StringTable->insert( doc, true );
|
||||
}
|
||||
|
||||
void GuiInspectorCustomField::setToolTip( StringTableEntry data )
|
||||
{
|
||||
static StringTableEntry sTooltipProfile = StringTable->insert( "tooltipProfile" );
|
||||
static StringTableEntry sHoverTime = StringTable->insert( "hovertime" );
|
||||
static StringTableEntry sTooltip = StringTable->insert( "tooltip" );
|
||||
|
||||
mEdit->setDataField( sTooltipProfile, NULL, "GuiToolTipProfile" );
|
||||
mEdit->setDataField( sHoverTime, NULL, "1000" );
|
||||
mEdit->setDataField( sTooltip, NULL, data );
|
||||
}
|
||||
|
||||
bool GuiInspectorCustomField::onAdd()
|
||||
{
|
||||
if( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiInspectorCustomField::setInspectorField( AbstractClassRep::Field *field,
|
||||
StringTableEntry caption,
|
||||
const char*arrayIndex )
|
||||
{
|
||||
// Override the base just to be sure it doesn't get called.
|
||||
// We don't use an AbstractClassRep::Field...
|
||||
|
||||
// mField = field;
|
||||
// mCaption = StringTable->EmptyString();
|
||||
// mRenameCtrl->setText( getFieldName() );
|
||||
}
|
||||
|
||||
GuiControl* GuiInspectorCustomField::constructEditControl()
|
||||
{
|
||||
GuiControl* retCtrl = new GuiTextCtrl();
|
||||
|
||||
static StringTableEntry sProfile = StringTable->insert( "profile" );
|
||||
retCtrl->setDataField( sProfile, NULL, "GuiInspectorTextEditProfile" );
|
||||
|
||||
// Register the object
|
||||
retCtrl->registerObject();
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
void GuiInspectorCustomField::setValue( const char* newValue )
|
||||
{
|
||||
GuiTextCtrl *ctrl = dynamic_cast<GuiTextCtrl*>( mEdit );
|
||||
if( ctrl != NULL )
|
||||
ctrl->setText( newValue );
|
||||
}
|
||||
|
||||
void GuiInspectorCustomField::_executeSelectedCallback()
|
||||
{
|
||||
Con::executef( mInspector, "onFieldSelected", mCaption, ConsoleBaseType::getType(TypeCaseString)->getTypeName(), mDoc );
|
||||
}
|
||||
69
Engine/source/gui/editor/inspector/customField.h
Normal file
69
Engine/source/gui/editor/inspector/customField.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_INSPECTOR_CUSTOMFIELD_H_
|
||||
#define _GUI_INSPECTOR_CUSTOMFIELD_H_
|
||||
|
||||
#include "console/simFieldDictionary.h"
|
||||
#include "gui/editor/inspector/field.h"
|
||||
|
||||
class GuiInspectorCustomField : public GuiInspectorField
|
||||
{
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorCustomField( GuiInspector *inspector, GuiInspectorGroup* parent, SimFieldDictionary::Entry* field );
|
||||
GuiInspectorCustomField();
|
||||
~GuiInspectorCustomField() {};
|
||||
|
||||
DECLARE_CONOBJECT( GuiInspectorCustomField );
|
||||
|
||||
virtual void setData( const char* data, bool callbacks = true );
|
||||
virtual const char* getData( U32 inspectObjectIndex = 0 );
|
||||
virtual void updateValue();
|
||||
virtual StringTableEntry getFieldName() { return StringTable->EmptyString(); }
|
||||
|
||||
virtual void setDoc( const char* doc );
|
||||
virtual void setToolTip( StringTableEntry data );
|
||||
|
||||
virtual bool onAdd();
|
||||
|
||||
virtual void setInspectorField( AbstractClassRep::Field *field,
|
||||
StringTableEntry caption = NULL,
|
||||
const char *arrayIndex = NULL );
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
|
||||
virtual void setValue( const char* newValue );
|
||||
|
||||
protected:
|
||||
|
||||
virtual void _executeSelectedCallback();
|
||||
|
||||
protected:
|
||||
|
||||
String mCustomValue;
|
||||
StringTableEntry mDoc;
|
||||
};
|
||||
|
||||
#endif // _GUI_INSPECTOR_DYNAMICFIELD_H_
|
||||
165
Engine/source/gui/editor/inspector/datablockField.cpp
Normal file
165
Engine/source/gui/editor/inspector/datablockField.cpp
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/simBase.h"
|
||||
#include "console/simDatablock.h"
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#include "gui/editor/inspector/datablockField.h"
|
||||
#include "gui/editor/inspector/group.h"
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
#include "gui/editor/inspector/datablockField.h"
|
||||
#include "sfx/sfxTypes.h"
|
||||
#include "sfx/sfxDescription.h"
|
||||
#include "sfx/sfxEnvironment.h"
|
||||
#include "sfx/sfxAmbience.h"
|
||||
#include "sfx/sfxTrack.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorDatablockField
|
||||
// Field construction for datablock types
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorDatablockField);
|
||||
|
||||
ConsoleDocClass( GuiInspectorDatablockField,
|
||||
"@brief Custom field type for datablock enumeration.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
|
||||
GuiInspectorDatablockField::GuiInspectorDatablockField( StringTableEntry className )
|
||||
{
|
||||
setClassName( className );
|
||||
}
|
||||
|
||||
void GuiInspectorDatablockField::setClassName( StringTableEntry className )
|
||||
{
|
||||
if( !className || !className[ 0 ] )
|
||||
mDesiredClass = NULL;
|
||||
else
|
||||
{
|
||||
mDesiredClass = AbstractClassRep::findClassRep( className );
|
||||
if( !mDesiredClass )
|
||||
Con::errorf( "GuiInspectorDatablockField::setClassName - no class '%s' found!", className );
|
||||
}
|
||||
}
|
||||
|
||||
void GuiInspectorDatablockField::_populateMenu( GuiPopUpMenuCtrl* menu )
|
||||
{
|
||||
menu->addScheme( 1, ColorI( 80, 0, 0, 255 ), ColorI( 80, 0, 0, 255 ), ColorI( 80, 0, 0, 255 ) ); // For client-only coloring.
|
||||
menu->addEntry( "", 0 ); // For unsetting.
|
||||
|
||||
SimSet* set = _getDatablockSet();
|
||||
U32 id = 1;
|
||||
|
||||
for( SimSet::iterator iter = set->begin(); iter != set->end(); ++ iter )
|
||||
{
|
||||
SimDataBlock* datablock = dynamic_cast< SimDataBlock* >( *iter );
|
||||
|
||||
// Skip non-datablocks if we somehow encounter them.
|
||||
if( !datablock )
|
||||
continue;
|
||||
|
||||
// Ok, now we have to figure inheritance info.
|
||||
if( datablock && ( !mDesiredClass || datablock->getClassRep()->isClass( mDesiredClass ) ) )
|
||||
menu->addEntry( datablock->getName(), id ++, datablock->isClientOnly() ? 1 : 0 );
|
||||
}
|
||||
|
||||
menu->sort();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeSFXDescriptionName
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeSFXDescriptionName);
|
||||
|
||||
ConsoleDocClass( GuiInspectorTypeSFXDescriptionName,
|
||||
"@brief Inspector field type for SFXDescriptionName\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeSFXDescriptionName::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType( TypeSFXDescriptionName )->setInspectorFieldType( "GuiInspectorTypeSFXDescriptionName" );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeSFXTrackName
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeSFXTrackName);
|
||||
|
||||
ConsoleDocClass( GuiInspectorTypeSFXTrackName,
|
||||
"@brief Inspector field type for SFXTrackName\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeSFXTrackName::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType( TypeSFXTrackName )->setInspectorFieldType( "GuiInspectorTypeSFXTrackName" );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeSFXEnvironmentName
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeSFXEnvironmentName);
|
||||
|
||||
ConsoleDocClass( GuiInspectorTypeSFXEnvironmentName,
|
||||
"@brief Inspector field type for SFXEnvironment\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeSFXEnvironmentName::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType( TypeSFXEnvironmentName )->setInspectorFieldType( "GuiInspectorTypeSFXEnvironmentName" );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeSFXAmbienceName
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeSFXAmbienceName);
|
||||
|
||||
ConsoleDocClass( GuiInspectorTypeSFXAmbienceName,
|
||||
"@brief Inspector field type for SFXAmbience\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeSFXAmbienceName::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType( TypeSFXAmbienceName )->setInspectorFieldType( "GuiInspectorTypeSFXAmbienceName" );
|
||||
}
|
||||
134
Engine/source/gui/editor/inspector/datablockField.h
Normal file
134
Engine/source/gui/editor/inspector/datablockField.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_INSPECTOR_DATABLOCKFIELD_H_
|
||||
#define _GUI_INSPECTOR_DATABLOCKFIELD_H_
|
||||
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorDatablockField - custom field type for datablock enumeration
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorDatablockField : public GuiInspectorTypeMenuBase
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiInspectorTypeMenuBase Parent;
|
||||
|
||||
protected:
|
||||
|
||||
AbstractClassRep *mDesiredClass;
|
||||
|
||||
virtual SimSet* _getDatablockSet() const { return Sim::getDataBlockGroup(); }
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl* menu );
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorDatablockField);
|
||||
|
||||
GuiInspectorDatablockField( StringTableEntry className );
|
||||
GuiInspectorDatablockField() { mDesiredClass = NULL; };
|
||||
|
||||
void setClassName( StringTableEntry className );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeSFXDescriptionName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeSFXDescriptionName : public GuiInspectorDatablockField
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiInspectorDatablockField Parent;
|
||||
|
||||
protected:
|
||||
|
||||
virtual SimSet* _getDatablockSet() const { return Sim::getSFXDescriptionSet(); }
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeSFXDescriptionName);
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeSFXTrackName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeSFXTrackName : public GuiInspectorDatablockField
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiInspectorDatablockField Parent;
|
||||
|
||||
protected:
|
||||
|
||||
virtual SimSet* _getDatablockSet() const { return Sim::getSFXTrackSet(); }
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeSFXTrackName);
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeSFXEnvironmentName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeSFXEnvironmentName : public GuiInspectorDatablockField
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiInspectorDatablockField Parent;
|
||||
|
||||
protected:
|
||||
|
||||
virtual SimSet* _getDatablockSet() const { return Sim::getSFXEnvironmentSet(); }
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeSFXEnvironmentName);
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeSFXAmbienceName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeSFXAmbienceName : public GuiInspectorDatablockField
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiInspectorDatablockField Parent;
|
||||
|
||||
protected:
|
||||
|
||||
virtual SimSet* _getDatablockSet() const { return Sim::getSFXAmbienceSet(); }
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeSFXAmbienceName);
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
321
Engine/source/gui/editor/inspector/dynamicField.cpp
Normal file
321
Engine/source/gui/editor/inspector/dynamicField.cpp
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "gui/editor/inspector/dynamicField.h"
|
||||
#include "gui/editor/inspector/dynamicGroup.h"
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorDynamicField - Child class of GuiInspectorField
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT( GuiInspectorDynamicField );
|
||||
|
||||
ConsoleDocClass( GuiInspectorDynamicField,
|
||||
"@brief Custom field type for dynamic variable modification on SimObjects.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
GuiInspectorDynamicField::GuiInspectorDynamicField( GuiInspector *inspector,
|
||||
GuiInspectorGroup* parent,
|
||||
SimFieldDictionary::Entry* field )
|
||||
: mRenameCtrl( NULL ),
|
||||
mDeleteButton( NULL )
|
||||
{
|
||||
mInspector = inspector;
|
||||
mParent = parent;
|
||||
mDynField = field;
|
||||
setBounds(0,0,100,20);
|
||||
}
|
||||
|
||||
void GuiInspectorDynamicField::setData( const char* data, bool callbacks )
|
||||
{
|
||||
if ( mDynField == NULL )
|
||||
return;
|
||||
|
||||
const U32 numTargets = mInspector->getNumInspectObjects();
|
||||
if( callbacks && numTargets > 1 )
|
||||
Con::executef( mInspector, "beginCompoundUndo" );
|
||||
|
||||
// Setting an empty string will kill the field.
|
||||
const bool isRemoval = !data[ 0 ];
|
||||
|
||||
for( U32 i = 0; i < numTargets; ++ i )
|
||||
{
|
||||
SimObject* target = mInspector->getInspectObject( i );
|
||||
|
||||
// Callback on the inspector when the field is modified
|
||||
// to allow creation of undo/redo actions.
|
||||
const char *oldData = target->getDataField( mDynField->slotName, NULL );
|
||||
if ( !oldData )
|
||||
oldData = "";
|
||||
if ( dStrcmp( oldData, data ) != 0 )
|
||||
{
|
||||
target->inspectPreApply();
|
||||
|
||||
if( callbacks )
|
||||
{
|
||||
if( isRemoval )
|
||||
Con::executef( mInspector, "onFieldRemoved", target->getIdString(), mDynField->slotName );
|
||||
else
|
||||
Con::executef( mInspector, "onInspectorFieldModified", target->getIdString(), mDynField->slotName, oldData, data );
|
||||
}
|
||||
|
||||
target->setDataField( mDynField->slotName, NULL, data );
|
||||
|
||||
// give the target a chance to validate
|
||||
target->inspectPostApply();
|
||||
}
|
||||
}
|
||||
|
||||
if( callbacks && numTargets > 1 )
|
||||
Con::executef( mInspector, "endCompoundUndo" );
|
||||
|
||||
// Force our edit to update
|
||||
updateValue();
|
||||
}
|
||||
|
||||
const char* GuiInspectorDynamicField::getData( U32 inspectObjectIndex )
|
||||
{
|
||||
if( mDynField == NULL )
|
||||
return "";
|
||||
|
||||
return mInspector->getInspectObject( inspectObjectIndex )->getDataField( mDynField->slotName, NULL );
|
||||
}
|
||||
|
||||
void GuiInspectorDynamicField::renameField( const char* newFieldName )
|
||||
{
|
||||
newFieldName = StringTable->insert( newFieldName );
|
||||
|
||||
if ( mDynField == NULL || mParent == NULL || mEdit == NULL )
|
||||
{
|
||||
Con::warnf("GuiInspectorDynamicField::renameField - No target object or dynamic field data found!" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !newFieldName )
|
||||
{
|
||||
Con::warnf("GuiInspectorDynamicField::renameField - Invalid field name specified!" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Only proceed if the name has changed
|
||||
if ( dStricmp( newFieldName, getFieldName() ) == 0 )
|
||||
return;
|
||||
|
||||
// Grab a pointer to our parent and cast it to GuiInspectorDynamicGroup
|
||||
GuiInspectorDynamicGroup *group = dynamic_cast<GuiInspectorDynamicGroup*>(mParent);
|
||||
if ( group == NULL )
|
||||
{
|
||||
Con::warnf("GuiInspectorDynamicField::renameField - Unable to locate GuiInspectorDynamicGroup parent!" );
|
||||
return;
|
||||
}
|
||||
|
||||
const U32 numTargets = mInspector->getNumInspectObjects();
|
||||
if( numTargets > 1 )
|
||||
Con::executef( mInspector, "onBeginCompoundEdit" );
|
||||
|
||||
const char* oldFieldName = getFieldName();
|
||||
SimFieldDictionary::Entry* newEntry = NULL;
|
||||
|
||||
for( U32 i = 0; i < numTargets; ++ i )
|
||||
{
|
||||
SimObject* target = mInspector->getInspectObject( i );
|
||||
|
||||
// Make sure the new field is not already defined as a static field
|
||||
// on the object.
|
||||
|
||||
if( target->isField( newFieldName ) )
|
||||
{
|
||||
// New field is already defined. If we can, let the scripts handle
|
||||
// the error. Otherwise, just emit an error on the console and proceed.
|
||||
|
||||
if( numTargets == 1 && mInspector->isMethod( "onFieldRenameAlreadyDefined" ) )
|
||||
Con::executef( mInspector, "onFieldRenameAlreadyDefined", target->getIdString(), oldFieldName, newFieldName );
|
||||
else
|
||||
Con::errorf( "GuiInspectorDynamicField::renameField - field '%s' is already defined on %i:%s (%s)",
|
||||
newFieldName, target->getId(), target->getClassName(), target->getName() );
|
||||
|
||||
// Reset the text entry.
|
||||
|
||||
if( mRenameCtrl )
|
||||
mRenameCtrl->setText( oldFieldName );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char currentValue[1024] = {0};
|
||||
// Grab our current dynamic field value (we use a temporary buffer as this gets corrupted upon Con::eval)
|
||||
dSprintf( currentValue, sizeof( currentValue ), "%s", target->getDataField( oldFieldName, NULL ) );
|
||||
|
||||
// Unset the old field and set the new field.
|
||||
|
||||
target->setDataField( oldFieldName, NULL, "" );
|
||||
target->setDataField( newFieldName, NULL, currentValue );
|
||||
|
||||
// Notify script.
|
||||
|
||||
Con::executef( mInspector, "onFieldRenamed", target->getIdString(), oldFieldName, newFieldName );
|
||||
|
||||
// Look up the new SimFieldDictionary entry.
|
||||
|
||||
if( !newEntry )
|
||||
{
|
||||
newEntry = target->getFieldDictionary()->findDynamicField( newFieldName );
|
||||
if( !newEntry )
|
||||
{
|
||||
Con::warnf( "GuiInspectorDynamicField::renameField - could not find new field '%s' on object %i:%s (%s)",
|
||||
newFieldName, target->getId(), target->getClassName(), target->getName() );
|
||||
}
|
||||
|
||||
mDynField = newEntry;
|
||||
}
|
||||
}
|
||||
|
||||
if( numTargets > 1 )
|
||||
Con::executef( mInspector, "onEndCompoundEdit" );
|
||||
|
||||
// Lastly we need to reassign our validate field for our value edit control
|
||||
char szBuffer[1024];
|
||||
dSprintf( szBuffer, sizeof( szBuffer ), "%d.apply(%d.getText());", getId(), mEdit->getId() );
|
||||
mEdit->setField("validate", szBuffer );
|
||||
|
||||
if( mDeleteButton )
|
||||
{
|
||||
dSprintf(szBuffer, sizeof( szBuffer ), "%d.apply("");%d.inspectGroup();", getId(), newFieldName, group->getId());
|
||||
mDeleteButton->setField("Command", szBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiInspectorDynamicField::onAdd()
|
||||
{
|
||||
if( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
//pushObjectToBack(mEdit);
|
||||
|
||||
// Create our renaming field
|
||||
mRenameCtrl = new GuiTextEditCtrl();
|
||||
mRenameCtrl->setDataField( StringTable->insert("profile"), NULL, "GuiInspectorDynamicFieldProfile" );
|
||||
|
||||
char szName[512];
|
||||
dSprintf( szName, 512, "IE_%s_%d_%s_Rename", mRenameCtrl->getClassName(), mInspector->getInspectObject()->getId(), getFieldName() );
|
||||
mRenameCtrl->registerObject( szName );
|
||||
|
||||
// Our command will evaluate to :
|
||||
//
|
||||
// if( (editCtrl).getText() !$= "" )
|
||||
// (field).renameField((editCtrl).getText());
|
||||
//
|
||||
char szBuffer[1024];
|
||||
dSprintf( szBuffer, sizeof( szBuffer ), "if( %d.getText() !$= \"\" ) %d.renameField(%d.getText());", mRenameCtrl->getId(), getId(), mRenameCtrl->getId() );
|
||||
mRenameCtrl->setText( getFieldName() );
|
||||
mRenameCtrl->setField("Validate", szBuffer );
|
||||
addObject( mRenameCtrl );
|
||||
|
||||
// Resize the name control to fit in our caption rect
|
||||
mRenameCtrl->resize( mCaptionRect.point, mCaptionRect.extent );
|
||||
|
||||
// Resize the value control to leave space for the delete button
|
||||
mEdit->resize( mValueRect.point, mValueRect.extent);
|
||||
|
||||
// Clear out any caption set from Parent::onAdd
|
||||
// since we are rendering the fieldname with our 'rename' control.
|
||||
mCaption = StringTable->insert( "" );
|
||||
|
||||
// Create delete button control
|
||||
mDeleteButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
SimObject* profilePtr = Sim::findObject("InspectorDynamicFieldButton");
|
||||
if( profilePtr != NULL )
|
||||
mDeleteButton->setControlProfile( dynamic_cast<GuiControlProfile*>(profilePtr) );
|
||||
|
||||
dSprintf( szBuffer, sizeof( szBuffer ),
|
||||
"%d.apply(\"\");%d.schedule(1,\"inspectGroup\");",
|
||||
getId(),
|
||||
mParent->getId() );
|
||||
|
||||
// FIXME Hardcoded image
|
||||
mDeleteButton->setField( "Bitmap", "tools/gui/images/iconDelete" );
|
||||
mDeleteButton->setField( "Text", "X" );
|
||||
mDeleteButton->setField( "Command", szBuffer );
|
||||
mDeleteButton->setSizing( horizResizeLeft, vertResizeCenter );
|
||||
mDeleteButton->resize(Point2I(getWidth() - 20,2), Point2I(16, 16));
|
||||
mDeleteButton->registerObject();
|
||||
|
||||
addObject(mDeleteButton);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GuiInspectorDynamicField::updateRects()
|
||||
{
|
||||
Point2I fieldExtent = getExtent();
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider( dividerPos, dividerMargin );
|
||||
|
||||
S32 editWidth = dividerPos - dividerMargin;
|
||||
|
||||
mEditCtrlRect.set( fieldExtent.x - dividerPos + dividerMargin, 1, editWidth, fieldExtent.y - 1 );
|
||||
mCaptionRect.set( 0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y );
|
||||
mValueRect.set( mEditCtrlRect.point, mEditCtrlRect.extent - Point2I( 20, 0 ) );
|
||||
mDeleteRect.set( fieldExtent.x - 20, 2, 16, fieldExtent.y - 4 );
|
||||
|
||||
// This is probably being called during Parent::onAdd
|
||||
// so our special controls haven't been created yet but are just about to
|
||||
// so we just need to calculate the extents.
|
||||
if ( mRenameCtrl == NULL )
|
||||
return false;
|
||||
|
||||
bool sized0 = mRenameCtrl->resize( mCaptionRect.point, mCaptionRect.extent );
|
||||
bool sized1 = mEdit->resize( mValueRect.point, mValueRect.extent );
|
||||
bool sized2 = mDeleteButton->resize(Point2I(getWidth() - 20,2), Point2I(16, 16));
|
||||
|
||||
return ( sized0 || sized1 || sized2 );
|
||||
}
|
||||
|
||||
void GuiInspectorDynamicField::setInspectorField( AbstractClassRep::Field *field,
|
||||
StringTableEntry caption,
|
||||
const char*arrayIndex )
|
||||
{
|
||||
// Override the base just to be sure it doesn't get called.
|
||||
// We don't use an AbstractClassRep::Field...
|
||||
|
||||
// mField = field;
|
||||
// mCaption = StringTable->EmptyString();
|
||||
// mRenameCtrl->setText( getFieldName() );
|
||||
}
|
||||
|
||||
void GuiInspectorDynamicField::_executeSelectedCallback()
|
||||
{
|
||||
ConsoleBaseType* type = mDynField->type;
|
||||
if ( type )
|
||||
Con::executef( mInspector, "onFieldSelected", mDynField->slotName, type->getTypeName() );
|
||||
else
|
||||
Con::executef( mInspector, "onFieldSelected", mDynField->slotName, "TypeDynamicField" );
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiInspectorDynamicField, renameField, void, 3,3, "field.renameField(newDynamicFieldName);" )
|
||||
{
|
||||
object->renameField( argv[ 2 ] );
|
||||
}
|
||||
72
Engine/source/gui/editor/inspector/dynamicField.h
Normal file
72
Engine/source/gui/editor/inspector/dynamicField.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_INSPECTOR_DYNAMICFIELD_H_
|
||||
#define _GUI_INSPECTOR_DYNAMICFIELD_H_
|
||||
|
||||
#include "console/simFieldDictionary.h"
|
||||
#include "gui/editor/inspector/field.h"
|
||||
|
||||
|
||||
class GuiInspectorDynamicField : public GuiInspectorField
|
||||
{
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorDynamicField( GuiInspector *inspector, GuiInspectorGroup* parent, SimFieldDictionary::Entry* field );
|
||||
GuiInspectorDynamicField() {};
|
||||
~GuiInspectorDynamicField() {};
|
||||
|
||||
DECLARE_CONOBJECT( GuiInspectorDynamicField );
|
||||
|
||||
virtual void setData( const char* data, bool callbacks = true );
|
||||
virtual const char* getData( U32 inspectObjectIndex = 0 );
|
||||
virtual StringTableEntry getFieldName() { return ( mDynField != NULL ) ? mDynField->slotName : StringTable->insert( "" ); }
|
||||
virtual StringTableEntry getRawFieldName() { return getFieldName(); }
|
||||
|
||||
virtual bool onAdd();
|
||||
|
||||
void renameField( const char* newFieldName );
|
||||
GuiControl* constructRenameControl();
|
||||
|
||||
virtual bool updateRects();
|
||||
virtual void setInspectorField( AbstractClassRep::Field *field,
|
||||
StringTableEntry caption = NULL,
|
||||
const char *arrayIndex = NULL );
|
||||
|
||||
protected:
|
||||
|
||||
virtual void _executeSelectedCallback();
|
||||
|
||||
protected:
|
||||
|
||||
/// Dynamic field dictionary entry for first target object only.
|
||||
SimFieldDictionary::Entry* mDynField;
|
||||
|
||||
SimObjectPtr<GuiTextEditCtrl> mRenameCtrl;
|
||||
GuiBitmapButtonCtrl* mDeleteButton;
|
||||
RectI mDeleteRect;
|
||||
RectI mValueRect;
|
||||
};
|
||||
|
||||
#endif // _GUI_INSPECTOR_DYNAMICFIELD_H_
|
||||
258
Engine/source/gui/editor/inspector/dynamicGroup.cpp
Normal file
258
Engine/source/gui/editor/inspector/dynamicGroup.cpp
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#include "gui/editor/inspector/dynamicGroup.h"
|
||||
#include "gui/editor/inspector/dynamicField.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorDynamicGroup);
|
||||
|
||||
ConsoleDocClass( GuiInspectorDynamicGroup,
|
||||
"@brief Used to inspect an object's FieldDictionary (dynamic fields) instead "
|
||||
"of regular persistent fields.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorDynamicGroup - add custom controls
|
||||
//-----------------------------------------------------------------------------
|
||||
bool GuiInspectorDynamicGroup::createContent()
|
||||
{
|
||||
if(!Parent::createContent())
|
||||
return false;
|
||||
|
||||
// encapsulate the button in a dummy control.
|
||||
GuiControl* shell = new GuiControl();
|
||||
shell->setDataField( StringTable->insert("profile"), NULL, "GuiTransparentProfile" );
|
||||
if( !shell->registerObject() )
|
||||
{
|
||||
delete shell;
|
||||
return false;
|
||||
}
|
||||
|
||||
// add a button that lets us add new dynamic fields.
|
||||
GuiBitmapButtonCtrl* addFieldBtn = new GuiBitmapButtonCtrl();
|
||||
{
|
||||
SimObject* profilePtr = Sim::findObject("InspectorDynamicFieldButton");
|
||||
if( profilePtr != NULL )
|
||||
addFieldBtn->setControlProfile( dynamic_cast<GuiControlProfile*>(profilePtr) );
|
||||
|
||||
// FIXME Hardcoded image
|
||||
addFieldBtn->setBitmap("tools/gui/images/iconAdd.png");
|
||||
|
||||
char commandBuf[64];
|
||||
dSprintf(commandBuf, 64, "%d.addDynamicField();", this->getId());
|
||||
addFieldBtn->setField("command", commandBuf);
|
||||
addFieldBtn->setSizing(horizResizeLeft,vertResizeCenter);
|
||||
//addFieldBtn->setField("buttonMargin", "2 2");
|
||||
addFieldBtn->resize(Point2I(getWidth() - 20,2), Point2I(16, 16));
|
||||
addFieldBtn->registerObject("zAddButton");
|
||||
}
|
||||
|
||||
shell->resize(Point2I(0,0), Point2I(getWidth(), 28));
|
||||
shell->addObject(addFieldBtn);
|
||||
|
||||
// save off the shell control, so we can push it to the bottom of the stack in inspectGroup()
|
||||
mAddCtrl = shell;
|
||||
mStack->addObject(shell);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct FieldEntry
|
||||
{
|
||||
SimFieldDictionary::Entry* mEntry;
|
||||
U32 mNumTargets;
|
||||
};
|
||||
|
||||
static S32 QSORT_CALLBACK compareEntries(const void* a,const void* b)
|
||||
{
|
||||
FieldEntry& fa = *((FieldEntry *)a);
|
||||
FieldEntry& fb = *((FieldEntry *)b);
|
||||
return dStrnatcmp(fa.mEntry->slotName, fb.mEntry->slotName);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorDynamicGroup - inspectGroup override
|
||||
//-----------------------------------------------------------------------------
|
||||
bool GuiInspectorDynamicGroup::inspectGroup()
|
||||
{
|
||||
// clear the first responder if it's set
|
||||
mStack->clearFirstResponder();
|
||||
|
||||
// Clearing the fields and recreating them will more than likely be more
|
||||
// efficient than looking up existent fields, updating them, and then iterating
|
||||
// over existent fields and making sure they still exist, if not, deleting them.
|
||||
clearFields();
|
||||
|
||||
// Create a vector of the fields
|
||||
Vector< FieldEntry > flist;
|
||||
|
||||
const U32 numTargets = mParent->getNumInspectObjects();
|
||||
for( U32 i = 0; i < numTargets; ++ i )
|
||||
{
|
||||
SimObject* target = mParent->getInspectObject( i );
|
||||
|
||||
// Then populate with fields
|
||||
SimFieldDictionary * fieldDictionary = target->getFieldDictionary();
|
||||
for(SimFieldDictionaryIterator ditr(fieldDictionary); *ditr; ++ditr)
|
||||
{
|
||||
if( i == 0 )
|
||||
{
|
||||
flist.increment();
|
||||
flist.last().mEntry = *ditr;
|
||||
flist.last().mNumTargets = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const U32 numFields = flist.size();
|
||||
for( U32 n = 0; n < numFields; ++ n )
|
||||
if( flist[ n ].mEntry->slotName == ( *ditr )->slotName )
|
||||
{
|
||||
flist[ n ].mNumTargets ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dQsort( flist.address(), flist.size(), sizeof( FieldEntry ), compareEntries );
|
||||
|
||||
for(U32 i = 0; i < flist.size(); i++)
|
||||
{
|
||||
if( flist[ i ].mNumTargets != numTargets )
|
||||
continue;
|
||||
|
||||
SimFieldDictionary::Entry* entry = flist[i].mEntry;
|
||||
|
||||
// Create a dynamic field inspector. Can't reuse typed GuiInspectorFields as
|
||||
// these rely on AbstractClassRep::Fields.
|
||||
GuiInspectorDynamicField *field = new GuiInspectorDynamicField( mParent, this, entry );
|
||||
|
||||
// Register the inspector field and add it to our lists
|
||||
if( field->registerObject() )
|
||||
{
|
||||
mChildren.push_back( field );
|
||||
mStack->addObject( field );
|
||||
}
|
||||
else
|
||||
delete field;
|
||||
}
|
||||
|
||||
mStack->pushObjectToBack(mAddCtrl);
|
||||
|
||||
setUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiInspectorDynamicGroup::updateAllFields()
|
||||
{
|
||||
// We overload this to just reinspect the group.
|
||||
inspectGroup();
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiInspectorDynamicGroup, inspectGroup, bool, 2, 2, "Refreshes the dynamic fields in the inspector.")
|
||||
{
|
||||
return object->inspectGroup();
|
||||
}
|
||||
|
||||
void GuiInspectorDynamicGroup::clearFields()
|
||||
{
|
||||
// save mAddCtrl
|
||||
Sim::getGuiGroup()->addObject(mAddCtrl);
|
||||
// delete everything else
|
||||
mStack->clear();
|
||||
// clear the mChildren list.
|
||||
mChildren.clear();
|
||||
// and restore.
|
||||
mStack->addObject(mAddCtrl);
|
||||
}
|
||||
|
||||
SimFieldDictionary::Entry* GuiInspectorDynamicGroup::findDynamicFieldInDictionary( StringTableEntry fieldName )
|
||||
{
|
||||
SimFieldDictionary * fieldDictionary = mParent->getInspectObject()->getFieldDictionary();
|
||||
|
||||
for(SimFieldDictionaryIterator ditr(fieldDictionary); *ditr; ++ditr)
|
||||
{
|
||||
SimFieldDictionary::Entry * entry = (*ditr);
|
||||
|
||||
if( entry->slotName == fieldName )
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GuiInspectorDynamicGroup::addDynamicField()
|
||||
{
|
||||
// We can't add a field without a target
|
||||
if( !mStack )
|
||||
{
|
||||
Con::warnf("GuiInspectorDynamicGroup::addDynamicField - no target SimObject to add a dynamic field to.");
|
||||
return;
|
||||
}
|
||||
|
||||
// find a field name that is not in use.
|
||||
// But we wont try more than 100 times to find an available field.
|
||||
U32 uid = 1;
|
||||
char buf[64] = "dynamicField";
|
||||
SimFieldDictionary::Entry* entry = findDynamicFieldInDictionary(buf);
|
||||
while(entry != NULL && uid < 100)
|
||||
{
|
||||
dSprintf(buf, sizeof(buf), "dynamicField%03d", uid++);
|
||||
entry = findDynamicFieldInDictionary(buf);
|
||||
}
|
||||
|
||||
const U32 numTargets = mParent->getNumInspectObjects();
|
||||
if( numTargets > 1 )
|
||||
Con::executef( mParent, "onBeginCompoundEdit" );
|
||||
|
||||
for( U32 i = 0; i < numTargets; ++ i )
|
||||
{
|
||||
SimObject* target = mParent->getInspectObject( i );
|
||||
|
||||
Con::evaluatef( "%d.dynamicField = \"defaultValue\";", target->getId(), buf );
|
||||
|
||||
// Notify script.
|
||||
|
||||
Con::executef( mParent, "onFieldAdded", target->getIdString(), buf );
|
||||
}
|
||||
|
||||
if( numTargets > 1 )
|
||||
Con::executef( mParent, "onEndCompoundEdit" );
|
||||
|
||||
// now we simply re-inspect the object, to see the new field.
|
||||
inspectGroup();
|
||||
instantExpand();
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiInspectorDynamicGroup, addDynamicField, void, 2, 2, "obj.addDynamicField();" )
|
||||
{
|
||||
object->addDynamicField();
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiInspectorDynamicGroup, removeDynamicField, void, 3, 3, "" )
|
||||
{
|
||||
}
|
||||
65
Engine/source/gui/editor/inspector/dynamicGroup.h
Normal file
65
Engine/source/gui/editor/inspector/dynamicGroup.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_INSPECTOR_DYNAMICGROUP_H_
|
||||
#define _GUI_INSPECTOR_DYNAMICGROUP_H_
|
||||
|
||||
#include "gui/editor/inspector/group.h"
|
||||
|
||||
#include "console/simFieldDictionary.h"
|
||||
|
||||
|
||||
class GuiInspectorDynamicGroup : public GuiInspectorGroup
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorGroup Parent;
|
||||
GuiControl* mAddCtrl;
|
||||
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorDynamicGroup);
|
||||
GuiInspectorDynamicGroup() { /*mNeedScroll=false;*/ };
|
||||
GuiInspectorDynamicGroup( StringTableEntry groupName, SimObjectPtr<GuiInspector> parent )
|
||||
: GuiInspectorGroup( groupName, parent) { /*mNeedScroll=false;*/};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// inspectGroup is overridden in GuiInspectorDynamicGroup to inspect an
|
||||
// objects FieldDictionary (dynamic fields) instead of regular persistent
|
||||
// fields.
|
||||
bool inspectGroup();
|
||||
virtual void updateAllFields();
|
||||
|
||||
// For scriptable dynamic field additions
|
||||
void addDynamicField();
|
||||
|
||||
// Clear our fields (delete them)
|
||||
void clearFields();
|
||||
|
||||
// Find an already existent field by name in the dictionary
|
||||
virtual SimFieldDictionary::Entry* findDynamicFieldInDictionary( StringTableEntry fieldName );
|
||||
protected:
|
||||
// create our inner controls when we add
|
||||
virtual bool createContent();
|
||||
|
||||
};
|
||||
|
||||
#endif // _GUI_INSPECTOR_DYNAMICGROUP_H_
|
||||
666
Engine/source/gui/editor/inspector/field.cpp
Normal file
666
Engine/source/gui/editor/inspector/field.cpp
Normal file
|
|
@ -0,0 +1,666 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "gui/editor/inspector/field.h"
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "math/mathTypes.h"
|
||||
#include "core/strings/stringUnit.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorField);
|
||||
|
||||
ConsoleDocClass( GuiInspectorField,
|
||||
"@brief The GuiInspectorField control is a representation of a single abstract "
|
||||
"field for a given ConsoleObject derived object.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorField::GuiInspectorField( GuiInspector* inspector,
|
||||
GuiInspectorGroup* parent,
|
||||
AbstractClassRep::Field* field )
|
||||
: mInspector( inspector ),
|
||||
mParent( parent ),
|
||||
mField( field ),
|
||||
mFieldArrayIndex( NULL ),
|
||||
mEdit( NULL )
|
||||
{
|
||||
if( field != NULL )
|
||||
mCaption = field->pFieldname;
|
||||
else
|
||||
mCaption = StringTable->EmptyString();
|
||||
|
||||
setCanSave( false );
|
||||
setBounds(0,0,100,18);
|
||||
|
||||
if( field )
|
||||
_setFieldDocs( field->pFieldDocs );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorField::GuiInspectorField()
|
||||
: mInspector( NULL ),
|
||||
mParent( NULL ),
|
||||
mEdit( NULL ),
|
||||
mField( NULL ),
|
||||
mFieldArrayIndex( NULL ),
|
||||
mCaption( StringTable->EmptyString() ),
|
||||
mHighlighted( false )
|
||||
{
|
||||
setCanSave( false );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorField::~GuiInspectorField()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::init( GuiInspector *inspector, GuiInspectorGroup *group )
|
||||
{
|
||||
mInspector = inspector;
|
||||
mParent = group;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspectorField::onAdd()
|
||||
{
|
||||
setInspectorProfile();
|
||||
|
||||
if ( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
if ( !mInspector )
|
||||
return false;
|
||||
|
||||
mEdit = constructEditControl();
|
||||
if ( mEdit == NULL )
|
||||
return false;
|
||||
|
||||
setBounds(0,0,100,18);
|
||||
|
||||
// Add our edit as a child
|
||||
addObject( mEdit );
|
||||
|
||||
// Calculate Caption and EditCtrl Rects
|
||||
updateRects();
|
||||
|
||||
// Force our editField to set it's value
|
||||
updateValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspectorField::resize( const Point2I &newPosition, const Point2I &newExtent )
|
||||
{
|
||||
if ( !Parent::resize( newPosition, newExtent ) )
|
||||
return false;
|
||||
|
||||
return updateRects();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::onRender( Point2I offset, const RectI &updateRect )
|
||||
{
|
||||
RectI ctrlRect(offset, getExtent());
|
||||
|
||||
// Render fillcolor...
|
||||
if ( mProfile->mOpaque )
|
||||
GFX->getDrawUtil()->drawRectFill(ctrlRect, mProfile->mFillColor);
|
||||
|
||||
// Render caption...
|
||||
if ( mCaption && mCaption[0] )
|
||||
{
|
||||
// Backup current ClipRect
|
||||
RectI clipBackup = GFX->getClipRect();
|
||||
|
||||
RectI clipRect = updateRect;
|
||||
|
||||
// The rect within this control in which our caption must fit.
|
||||
RectI rect( offset + mCaptionRect.point + mProfile->mTextOffset, mCaptionRect.extent + Point2I(1,1) - Point2I(5,0) );
|
||||
|
||||
// Now clipRect is the amount of our caption rect that is actually visible.
|
||||
bool hit = clipRect.intersect( rect );
|
||||
|
||||
if ( hit )
|
||||
{
|
||||
GFX->setClipRect( clipRect );
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
|
||||
// Backup modulation color
|
||||
ColorI currColor;
|
||||
drawer->getBitmapModulation( &currColor );
|
||||
|
||||
// Draw caption background...
|
||||
if( !isActive() )
|
||||
GFX->getDrawUtil()->drawRectFill( clipRect, mProfile->mFillColorNA );
|
||||
else if ( mHighlighted )
|
||||
GFX->getDrawUtil()->drawRectFill( clipRect, mProfile->mFillColorHL );
|
||||
|
||||
// Draw caption text...
|
||||
|
||||
drawer->setBitmapModulation( !isActive() ? mProfile->mFontColorNA : mHighlighted ? mProfile->mFontColorHL : mProfile->mFontColor );
|
||||
|
||||
// Clip text with '...' if too long to fit
|
||||
String clippedText( mCaption );
|
||||
clipText( clippedText, clipRect.extent.x );
|
||||
|
||||
renderJustifiedText( offset + mProfile->mTextOffset, getExtent(), clippedText );
|
||||
|
||||
// Restore modulation color
|
||||
drawer->setBitmapModulation( currColor );
|
||||
|
||||
// Restore previous ClipRect
|
||||
GFX->setClipRect( clipBackup );
|
||||
}
|
||||
}
|
||||
|
||||
// Render Children...
|
||||
renderChildControls(offset, updateRect);
|
||||
|
||||
// Render border...
|
||||
if ( mProfile->mBorder )
|
||||
renderBorder(ctrlRect, mProfile);
|
||||
|
||||
// Render divider...
|
||||
Point2I worldPnt = mEditCtrlRect.point + offset;
|
||||
GFX->getDrawUtil()->drawLine( worldPnt.x - 5,
|
||||
worldPnt.y,
|
||||
worldPnt.x - 5,
|
||||
worldPnt.y + getHeight(),
|
||||
!isActive() ? mProfile->mBorderColorNA : mHighlighted ? mProfile->mBorderColorHL : mProfile->mBorderColor );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::setFirstResponder( GuiControl *firstResponder )
|
||||
{
|
||||
Parent::setFirstResponder( firstResponder );
|
||||
|
||||
if ( firstResponder == this || firstResponder == mEdit )
|
||||
{
|
||||
mInspector->setHighlightField( this );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::onMouseDown( const GuiEvent &event )
|
||||
{
|
||||
if ( mCaptionRect.pointInRect( globalToLocalCoord( event.mousePoint ) ) )
|
||||
{
|
||||
if ( mEdit )
|
||||
//mEdit->onMouseDown( event );
|
||||
mInspector->setHighlightField( this );
|
||||
}
|
||||
else
|
||||
Parent::onMouseDown( event );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::onRightMouseUp( const GuiEvent &event )
|
||||
{
|
||||
if ( mCaptionRect.pointInRect( globalToLocalCoord( event.mousePoint ) ) )
|
||||
Con::executef( mInspector, "onFieldRightClick", getIdString() );
|
||||
else
|
||||
Parent::onMouseDown( event );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::setData( const char* data, bool callbacks )
|
||||
{
|
||||
if( mField == NULL )
|
||||
return;
|
||||
|
||||
if( verifyData( data ) )
|
||||
{
|
||||
String strData = data;
|
||||
const U32 numTargets = mInspector->getNumInspectObjects();
|
||||
|
||||
if( callbacks && numTargets > 1 )
|
||||
Con::executef( mInspector, "onBeginCompoundEdit" );
|
||||
|
||||
for( U32 i = 0; i < numTargets; ++ i )
|
||||
{
|
||||
SimObject* target = mInspector->getInspectObject( i );
|
||||
|
||||
String oldValue = target->getDataField( mField->pFieldname, mFieldArrayIndex);
|
||||
|
||||
// For numeric fields, allow input expressions.
|
||||
|
||||
String newValue = strData;
|
||||
S32 type= mField->type;
|
||||
if( type == TypeS8 || type == TypeS32 || type == TypeF32 )
|
||||
{
|
||||
char buffer[ 2048 ];
|
||||
expandEscape( buffer, newValue );
|
||||
newValue = Con::evaluatef( "%%f = \"%s\"; return ( %s );", oldValue.c_str(), buffer );
|
||||
}
|
||||
else if( type == TypeS32Vector
|
||||
|| type == TypeF32Vector
|
||||
|| type == TypeColorI
|
||||
|| type == TypeColorF
|
||||
|| type == TypePoint2I
|
||||
|| type == TypePoint2F
|
||||
|| type == TypePoint3F
|
||||
|| type == TypePoint4F
|
||||
|| type == TypeRectI
|
||||
|| type == TypeRectF
|
||||
|| type == TypeMatrixPosition
|
||||
|| type == TypeMatrixRotation
|
||||
|| type == TypeBox3F
|
||||
|| type == TypeRectUV )
|
||||
{
|
||||
//TODO: we should actually take strings into account and not chop things up between quotes
|
||||
|
||||
U32 numNewUnits = StringUnit::getUnitCount( newValue, " \t\n\r" );
|
||||
|
||||
StringBuilder strNew;
|
||||
bool isFirst = true;
|
||||
for( U32 n = 0; n < numNewUnits; ++ n )
|
||||
{
|
||||
char oldComponentVal[ 1024 ];
|
||||
StringUnit::getUnit( oldValue, n, " \t\n\r", oldComponentVal, sizeof( oldComponentVal ) );
|
||||
|
||||
char newComponentExpr[ 1024 ];
|
||||
StringUnit::getUnit( newValue, n, " \t\n\r", newComponentExpr, sizeof( newComponentExpr ) );
|
||||
|
||||
char buffer[ 2048 ];
|
||||
expandEscape( buffer, newComponentExpr );
|
||||
|
||||
const char* newComponentVal = Con::evaluatef( "%%f = \"%s\"; %%v = \"%s\"; return ( %s );",
|
||||
oldComponentVal, oldValue.c_str(), buffer );
|
||||
|
||||
if( !isFirst )
|
||||
strNew.append( ' ' );
|
||||
strNew.append( newComponentVal );
|
||||
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
newValue = strNew.end();
|
||||
}
|
||||
|
||||
target->inspectPreApply();
|
||||
|
||||
// Fire callback single-object undo.
|
||||
|
||||
if( callbacks )
|
||||
Con::executef( mInspector, "onInspectorFieldModified",
|
||||
target->getIdString(),
|
||||
mField->pFieldname,
|
||||
mFieldArrayIndex ? mFieldArrayIndex : "(null)",
|
||||
oldValue.c_str(),
|
||||
newValue.c_str() );
|
||||
|
||||
target->setDataField( mField->pFieldname, mFieldArrayIndex, newValue );
|
||||
|
||||
// Give the target a chance to validate.
|
||||
target->inspectPostApply();
|
||||
}
|
||||
|
||||
if( callbacks && numTargets > 1 )
|
||||
Con::executef( mInspector, "onEndCompoundEdit" );
|
||||
}
|
||||
|
||||
// Force our edit to update
|
||||
updateValue();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const char* GuiInspectorField::getData( U32 inspectObjectIndex )
|
||||
{
|
||||
if( mField == NULL )
|
||||
return "";
|
||||
|
||||
return mInspector->getInspectObject( inspectObjectIndex )->getDataField( mField->pFieldname, mFieldArrayIndex );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::resetData()
|
||||
{
|
||||
if( !mField )
|
||||
return;
|
||||
|
||||
SimObject* inspectObject = getInspector()->getInspectObject();
|
||||
|
||||
SimObject* tempObject = static_cast< SimObject* >( inspectObject->getClassRep()->create() );
|
||||
setData( tempObject->getDataField( mField->pFieldname, mFieldArrayIndex ) );
|
||||
delete tempObject;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::setInspectorField( AbstractClassRep::Field *field, StringTableEntry caption, const char*arrayIndex )
|
||||
{
|
||||
mField = field;
|
||||
|
||||
if ( arrayIndex != NULL )
|
||||
mFieldArrayIndex = StringTable->insert( arrayIndex );
|
||||
|
||||
if ( !caption || !caption[0] )
|
||||
mCaption = getFieldName();
|
||||
else
|
||||
mCaption = caption;
|
||||
|
||||
_setFieldDocs( mField->pFieldDocs );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
StringTableEntry GuiInspectorField::getRawFieldName()
|
||||
{
|
||||
if( !mField )
|
||||
return StringTable->EmptyString();
|
||||
|
||||
return mField->pFieldname;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
StringTableEntry GuiInspectorField::getFieldName()
|
||||
{
|
||||
// Sanity
|
||||
if ( mField == NULL )
|
||||
return StringTable->EmptyString();
|
||||
|
||||
// Array element?
|
||||
if( mFieldArrayIndex != NULL )
|
||||
{
|
||||
S32 frameTempSize = dStrlen( mField->pFieldname ) + 32;
|
||||
FrameTemp<char> valCopy( frameTempSize );
|
||||
dSprintf( (char *)valCopy, frameTempSize, "%s[%s]", mField->pFieldname, mFieldArrayIndex );
|
||||
|
||||
// Return formatted element
|
||||
return StringTable->insert( valCopy );
|
||||
}
|
||||
|
||||
// Plain field name.
|
||||
return mField->pFieldname;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
StringTableEntry GuiInspectorField::getFieldType()
|
||||
{
|
||||
if( !mField )
|
||||
return StringTable->EmptyString();
|
||||
|
||||
return ConsoleBaseType::getType( mField->type )->getTypeName();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiControl* GuiInspectorField::constructEditControl()
|
||||
{
|
||||
GuiControl* retCtrl = new GuiTextEditCtrl();
|
||||
|
||||
static StringTableEntry sProfile = StringTable->insert( "profile" );
|
||||
retCtrl->setDataField( sProfile, NULL, "GuiInspectorTextEditProfile" );
|
||||
|
||||
_registerEditControl( retCtrl );
|
||||
|
||||
char szBuffer[512];
|
||||
dSprintf( szBuffer, 512, "%d.apply(%d.getText());",getId(), retCtrl->getId() );
|
||||
|
||||
// Suffices to hook on to "validate" as regardless of whether we lose
|
||||
// focus through the user pressing enter or clicking away on another
|
||||
// keyboard control, we will see a validate call.
|
||||
|
||||
retCtrl->setField("validate", szBuffer );
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::setInspectorProfile()
|
||||
{
|
||||
GuiControlProfile *profile = NULL;
|
||||
|
||||
if( mInspector->getNumInspectObjects() > 1 )
|
||||
{
|
||||
if( !hasSameValueInAllObjects() )
|
||||
Sim::findObject( "GuiInspectorMultiFieldDifferentProfile", profile );
|
||||
else
|
||||
Sim::findObject( "GuiInspectorMultiFieldProfile", profile );
|
||||
}
|
||||
|
||||
if( !profile )
|
||||
Sim::findObject( "GuiInspectorFieldProfile", profile );
|
||||
|
||||
if( profile )
|
||||
setControlProfile( profile );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::setValue( StringTableEntry newValue )
|
||||
{
|
||||
GuiTextEditCtrl *ctrl = dynamic_cast<GuiTextEditCtrl*>( mEdit );
|
||||
if( ctrl != NULL )
|
||||
ctrl->setText( newValue );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspectorField::updateRects()
|
||||
{
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider( dividerPos, dividerMargin );
|
||||
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
S32 editWidth = dividerPos - dividerMargin;
|
||||
|
||||
mEditCtrlRect.set( fieldExtent.x - dividerPos + dividerMargin, 1, editWidth, fieldExtent.y - 1 );
|
||||
mCaptionRect.set( 0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y );
|
||||
|
||||
if ( !mEdit )
|
||||
return false;
|
||||
|
||||
return mEdit->resize( mEditCtrlRect.point, mEditCtrlRect.extent );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::updateValue()
|
||||
{
|
||||
if( mInspector->getNumInspectObjects() > 1 )
|
||||
{
|
||||
setInspectorProfile();
|
||||
|
||||
if( !hasSameValueInAllObjects() )
|
||||
setValue( StringTable->EmptyString() );
|
||||
else
|
||||
setValue( getData() );
|
||||
}
|
||||
else
|
||||
setValue( getData() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::setHLEnabled( bool enabled )
|
||||
{
|
||||
mHighlighted = enabled;
|
||||
if ( mHighlighted )
|
||||
{
|
||||
if ( mEdit && !mEdit->isFirstResponder() )
|
||||
{
|
||||
mEdit->setFirstResponder();
|
||||
GuiTextEditCtrl *edit = dynamic_cast<GuiTextEditCtrl*>( mEdit );
|
||||
if ( edit )
|
||||
{
|
||||
mouseUnlock();
|
||||
edit->mouseLock();
|
||||
edit->setCursorPos(0);
|
||||
}
|
||||
}
|
||||
_executeSelectedCallback();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspectorField::hasSameValueInAllObjects()
|
||||
{
|
||||
char value1[ 2048 ];
|
||||
|
||||
// Get field value from first object.
|
||||
|
||||
const char* data1 = getData( 0 );
|
||||
if( data1 )
|
||||
{
|
||||
dStrncpy( value1, data1, sizeof( value1 ) );
|
||||
value1[ sizeof( value1 ) - 1 ] = 0;
|
||||
}
|
||||
else
|
||||
value1[ 0 ] = 0;
|
||||
|
||||
// Check if all other objects have the same value.
|
||||
|
||||
const U32 numObjects = mInspector->getNumInspectObjects();
|
||||
for( U32 i = 1; i < numObjects; ++ i )
|
||||
{
|
||||
const char* value2 = getData( i );
|
||||
if( !value2 )
|
||||
value2 = "";
|
||||
|
||||
if( dStrcmp( value1, value2 ) != 0 )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::_executeSelectedCallback()
|
||||
{
|
||||
if( mField )
|
||||
Con::executef( mInspector, "onFieldSelected", mField->pFieldname, ConsoleBaseType::getType(mField->type)->getTypeName(), mFieldDocs.c_str() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::_registerEditControl( GuiControl *ctrl )
|
||||
{
|
||||
char szName[512];
|
||||
dSprintf( szName, 512, "IE_%s_%d_%s_Field", ctrl->getClassName(), mInspector->getInspectObject()->getId(), mCaption);
|
||||
|
||||
// Register the object
|
||||
ctrl->registerObject( szName );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorField::_setFieldDocs( StringTableEntry docs )
|
||||
{
|
||||
mFieldDocs = String();
|
||||
if( docs && docs[ 0 ] )
|
||||
{
|
||||
// Only accept first line of docs for brevity.
|
||||
|
||||
const char* newline = dStrchr( docs, '\n' );
|
||||
if( newline )
|
||||
mFieldDocs = String( docs, newline - docs );
|
||||
else
|
||||
mFieldDocs = docs;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Console Methods.
|
||||
//=============================================================================
|
||||
// MARK: ---- Console Methods ----
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspectorField, getInspector, S32, 2, 2, "() - Return the GuiInspector to which this field belongs." )
|
||||
{
|
||||
return object->getInspector()->getId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspectorField, getInspectedFieldName, const char*, 2, 2, "() - Return the name of the field edited by this inspector field." )
|
||||
{
|
||||
return object->getFieldName();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspectorField, getInspectedFieldType, const char*, 2, 2, "() - Return the type of the field edited by this inspector field." )
|
||||
{
|
||||
return object->getFieldType();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspectorField, apply, void, 3, 4, "( string newValue, bool callbacks=true ) - Set the field's value. Suppress callbacks for undo if callbacks=false." )
|
||||
{
|
||||
bool callbacks = true;
|
||||
if( argc > 3 )
|
||||
callbacks = dAtob( argv[ 3 ] );
|
||||
|
||||
object->setData( argv[ 2 ], callbacks );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspectorField, applyWithoutUndo, void, 3, 3, "() - Set field value without recording undo (same as 'apply( value, false )')." )
|
||||
{
|
||||
object->setData( argv[ 2 ], false );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspectorField, getData, const char*, 2, 2, "() - Return the value currently displayed on the field." )
|
||||
{
|
||||
return object->getData();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspectorField, reset, void, 2, 2, "() - Reset to default value." )
|
||||
{
|
||||
object->resetData();
|
||||
}
|
||||
194
Engine/source/gui/editor/inspector/field.h
Normal file
194
Engine/source/gui/editor/inspector/field.h
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_INSPECTOR_FIELD_H_
|
||||
#define _GUI_INSPECTOR_FIELD_H_
|
||||
|
||||
#include "gui/core/guiCanvas.h"
|
||||
#include "gui/shiny/guiTickCtrl.h"
|
||||
#include "gui/controls/guiTextEditCtrl.h"
|
||||
#include "gui/buttons/guiBitmapButtonCtrl.h"
|
||||
#include "gui/controls/guiPopUpCtrl.h"
|
||||
|
||||
#include "gui/containers/guiRolloutCtrl.h"
|
||||
|
||||
class GuiInspectorGroup;
|
||||
class GuiInspector;
|
||||
|
||||
|
||||
/// The GuiInspectorField control is a representation of a single abstract
|
||||
/// field for a given ConsoleObject derived object. It handles creation
|
||||
/// getting and setting of it's fields data and editing control.
|
||||
///
|
||||
/// Creation of custom edit controls is done through this class and is
|
||||
/// dependent upon the dynamic console type, which may be defined to be
|
||||
/// custom for different types.
|
||||
///
|
||||
/// @note GuiInspectorField controls must have a GuiInspectorGroup as their
|
||||
/// parent.
|
||||
class GuiInspectorField : public GuiControl
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiControl Parent;
|
||||
friend class GuiInspectorGroup;
|
||||
|
||||
protected:
|
||||
|
||||
/// The text to display as the field name.
|
||||
StringTableEntry mCaption;
|
||||
|
||||
/// The group to which this field belongs.
|
||||
GuiInspectorGroup* mParent;
|
||||
|
||||
/// The GuiInspector that the group is in to which this field belongs.
|
||||
GuiInspector* mInspector;
|
||||
|
||||
///
|
||||
AbstractClassRep::Field* mField;
|
||||
|
||||
///
|
||||
StringTableEntry mFieldArrayIndex;
|
||||
|
||||
///
|
||||
String mFieldDocs;
|
||||
|
||||
///
|
||||
GuiControl* mEdit;
|
||||
|
||||
///
|
||||
RectI mCaptionRect;
|
||||
|
||||
///
|
||||
RectI mEditCtrlRect;
|
||||
|
||||
///
|
||||
bool mHighlighted;
|
||||
|
||||
virtual void _registerEditControl( GuiControl *ctrl );
|
||||
virtual void _executeSelectedCallback();
|
||||
|
||||
void _setFieldDocs( StringTableEntry docs );
|
||||
|
||||
public:
|
||||
|
||||
explicit GuiInspectorField();
|
||||
|
||||
///
|
||||
GuiInspectorField( GuiInspector *inspector, GuiInspectorGroup* parent, AbstractClassRep::Field* field );
|
||||
|
||||
virtual ~GuiInspectorField();
|
||||
|
||||
///
|
||||
virtual void init( GuiInspector *inspector, GuiInspectorGroup *group );
|
||||
|
||||
///
|
||||
virtual void setInspectorField( AbstractClassRep::Field *field,
|
||||
StringTableEntry caption = NULL,
|
||||
const char *arrayIndex = NULL );
|
||||
|
||||
///
|
||||
virtual GuiControl* constructEditControl();
|
||||
|
||||
/// Chooses and sets the GuiControlProfile.
|
||||
virtual void setInspectorProfile();
|
||||
|
||||
/// Sets this control's caption text, usually set within setInspectorField,
|
||||
/// this is exposed in case someone wants to override the normal caption.
|
||||
virtual void setCaption( StringTableEntry caption ) { mCaption = caption; }
|
||||
|
||||
/// Returns pointer to this InspectorField's edit ctrl.
|
||||
virtual GuiControl* getEditCtrl() { return mEdit; }
|
||||
|
||||
/// Sets the value of this GuiInspectorField (not the actual field)
|
||||
/// This means the EditCtrl unless overridden.
|
||||
virtual void setValue( const char* newValue );
|
||||
|
||||
/// Get the currently value of this control (not the actual field)
|
||||
virtual const char* getValue() { return NULL; }
|
||||
|
||||
/// Update this controls value to reflect that of the inspected field.
|
||||
virtual void updateValue();
|
||||
|
||||
/// Return the name of the field being edited.
|
||||
virtual StringTableEntry getFieldName();
|
||||
|
||||
/// Return the name of the console type that this field uses.
|
||||
virtual StringTableEntry getFieldType();
|
||||
|
||||
/// Return the name without the array index that may potentially be present.
|
||||
virtual StringTableEntry getRawFieldName();
|
||||
|
||||
///
|
||||
StringTableEntry getArrayIndex() const { return mFieldArrayIndex; }
|
||||
|
||||
/// Called from within setData to allow child classes
|
||||
/// to perform their own verification.
|
||||
virtual bool verifyData( StringTableEntry data ) { return true; }
|
||||
|
||||
/// Set value of the field we are inspecting
|
||||
virtual void setData( const char* data, bool callbacks = true );
|
||||
|
||||
/// Reset the field value to its default value based on default-constructed objects.
|
||||
///
|
||||
/// @note If multiple objects are inspected, this will take the default value from
|
||||
/// the first object and set all fields to this value.
|
||||
virtual void resetData();
|
||||
|
||||
/// Get value of the field we are inspecting.
|
||||
///
|
||||
/// @note The string returned by this method may be a transient string allocated
|
||||
/// internally by the console. For any non-transient needs, this string has
|
||||
/// to be copied to locally owned memory.
|
||||
/// @note This method always returns the value of the field in the first
|
||||
/// inspected object.
|
||||
virtual const char* getData( U32 inspectObjectIndex = 0 );
|
||||
|
||||
/// Update the inspected field to match the value of this control.
|
||||
virtual void updateData() {};
|
||||
|
||||
///
|
||||
virtual bool updateRects();
|
||||
|
||||
///
|
||||
virtual void setHLEnabled( bool enabled );
|
||||
|
||||
/// Return true if all inspected objects have the same value for this
|
||||
/// field.
|
||||
bool hasSameValueInAllObjects();
|
||||
|
||||
/// Return the inspector object that this field belongs to.
|
||||
GuiInspector* getInspector() const { return mInspector; }
|
||||
|
||||
// GuiControl.
|
||||
virtual bool onAdd();
|
||||
virtual bool resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
virtual void onRender(Point2I offset, const RectI &updateRect);
|
||||
virtual void setFirstResponder( GuiControl *firstResponder );
|
||||
virtual void onMouseDown( const GuiEvent &event );
|
||||
virtual void onRightMouseUp( const GuiEvent &event );
|
||||
|
||||
DECLARE_CONOBJECT( GuiInspectorField );
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
};
|
||||
|
||||
#endif // _GUI_INSPECTOR_FIELD_H_
|
||||
567
Engine/source/gui/editor/inspector/group.cpp
Normal file
567
Engine/source/gui/editor/inspector/group.cpp
Normal file
|
|
@ -0,0 +1,567 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#include "gui/editor/inspector/group.h"
|
||||
#include "gui/editor/inspector/dynamicField.h"
|
||||
#include "gui/editor/inspector/datablockField.h"
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorGroup);
|
||||
|
||||
ConsoleDocClass( GuiInspectorGroup,
|
||||
"@brief The GuiInspectorGroup control is a helper control that the inspector "
|
||||
"makes use of which houses a collapsible pane type control for separating "
|
||||
"inspected objects fields into groups.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
//#define DEBUG_SPEW
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorGroup::GuiInspectorGroup()
|
||||
: mParent( NULL ),
|
||||
mStack(NULL)
|
||||
{
|
||||
setBounds(0,0,200,20);
|
||||
|
||||
mChildren.clear();
|
||||
|
||||
setCanSave( false );
|
||||
|
||||
// Make sure we receive our ticks.
|
||||
setProcessTicks();
|
||||
mMargin.set(0,0,5,0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorGroup::GuiInspectorGroup( const String& groupName,
|
||||
SimObjectPtr<GuiInspector> parent )
|
||||
: mParent( parent ),
|
||||
mStack(NULL)
|
||||
{
|
||||
|
||||
setBounds(0,0,200,20);
|
||||
|
||||
mCaption = groupName;
|
||||
setCanSave( false );
|
||||
|
||||
mChildren.clear();
|
||||
mMargin.set(0,0,4,0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorGroup::~GuiInspectorGroup()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspectorGroup::onAdd()
|
||||
{
|
||||
setDataField( StringTable->insert("profile"), NULL, "GuiInspectorGroupProfile" );
|
||||
|
||||
if( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
// Create our inner controls. Allow subclasses to provide other content.
|
||||
if(!createContent())
|
||||
return false;
|
||||
|
||||
inspectGroup();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspectorGroup::createContent()
|
||||
{
|
||||
// Create our field stack control
|
||||
mStack = new GuiStackControl();
|
||||
|
||||
// Prefer GuiTransperantProfile for the stack.
|
||||
mStack->setDataField( StringTable->insert("profile"), NULL, "GuiInspectorStackProfile" );
|
||||
if( !mStack->registerObject() )
|
||||
{
|
||||
SAFE_DELETE( mStack );
|
||||
return false;
|
||||
}
|
||||
|
||||
addObject( mStack );
|
||||
mStack->setField( "padding", "0" );
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorGroup::animateToContents()
|
||||
{
|
||||
calculateHeights();
|
||||
if(size() > 0)
|
||||
animateTo( mExpanded.extent.y );
|
||||
else
|
||||
animateTo( mHeader.extent.y );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorField* GuiInspectorGroup::constructField( S32 fieldType )
|
||||
{
|
||||
// See if we can construct a field of this type
|
||||
ConsoleBaseType *cbt = ConsoleBaseType::getType(fieldType);
|
||||
if( !cbt )
|
||||
return NULL;
|
||||
|
||||
// Alright, is it a datablock?
|
||||
if(cbt->isDatablock())
|
||||
{
|
||||
// Default to GameBaseData
|
||||
StringTableEntry typeClassName = cbt->getTypeClassName();
|
||||
|
||||
if( mParent->getNumInspectObjects() == 1 && !dStricmp(typeClassName, "GameBaseData") )
|
||||
{
|
||||
// Try and setup the classname based on the object type
|
||||
char className[256];
|
||||
dSprintf(className,256,"%sData", mParent->getInspectObject( 0 )->getClassName());
|
||||
// Walk the ACR list and find a matching class if any.
|
||||
AbstractClassRep *walk = AbstractClassRep::getClassList();
|
||||
while(walk)
|
||||
{
|
||||
if(!dStricmp(walk->getClassName(), className))
|
||||
break;
|
||||
|
||||
walk = walk->getNextClass();
|
||||
}
|
||||
|
||||
// We found a valid class
|
||||
if (walk)
|
||||
typeClassName = walk->getClassName();
|
||||
|
||||
}
|
||||
|
||||
|
||||
GuiInspectorDatablockField *dbFieldClass = new GuiInspectorDatablockField( typeClassName );
|
||||
if( dbFieldClass != NULL )
|
||||
{
|
||||
// return our new datablock field with correct datablock type enumeration info
|
||||
return dbFieldClass;
|
||||
}
|
||||
}
|
||||
|
||||
// Nope, not a datablock. So maybe it has a valid inspector field override we can use?
|
||||
if(!cbt->getInspectorFieldType())
|
||||
// Nothing, so bail.
|
||||
return NULL;
|
||||
|
||||
// Otherwise try to make it!
|
||||
ConsoleObject *co = create(cbt->getInspectorFieldType());
|
||||
GuiInspectorField *gif = dynamic_cast<GuiInspectorField*>(co);
|
||||
|
||||
if(!gif)
|
||||
{
|
||||
// Wasn't appropriate type, bail.
|
||||
delete co;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gif;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorField *GuiInspectorGroup::findField( const char *fieldName )
|
||||
{
|
||||
// If we don't have any field children we can't very well find one then can we?
|
||||
if( mChildren.empty() )
|
||||
return NULL;
|
||||
|
||||
Vector<GuiInspectorField*>::iterator i = mChildren.begin();
|
||||
|
||||
for( ; i != mChildren.end(); i++ )
|
||||
{
|
||||
if( (*i)->getFieldName() != NULL && dStricmp( (*i)->getFieldName(), fieldName ) == 0 )
|
||||
return (*i);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorGroup::clearFields()
|
||||
{
|
||||
// Deallocates all field related controls.
|
||||
mStack->clear();
|
||||
|
||||
// Then just cleanup our vectors which also point to children
|
||||
// that we keep for our own convenience.
|
||||
mArrayCtrls.clear();
|
||||
mChildren.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspectorGroup::inspectGroup()
|
||||
{
|
||||
// We can't inspect a group without a target!
|
||||
if( !mParent->getNumInspectObjects() )
|
||||
return false;
|
||||
|
||||
// to prevent crazy resizing, we'll just freeze our stack for a sec..
|
||||
mStack->freeze(true);
|
||||
|
||||
bool bNoGroup = false;
|
||||
|
||||
// Un-grouped fields are all sorted into the 'general' group
|
||||
if ( dStricmp( mCaption, "General" ) == 0 )
|
||||
bNoGroup = true;
|
||||
|
||||
// Just delete all fields and recreate them (like the dynamicGroup)
|
||||
// because that makes creating controls for array fields a lot easier
|
||||
clearFields();
|
||||
|
||||
bool bNewItems = false;
|
||||
bool bMakingArray = false;
|
||||
GuiStackControl *pArrayStack = NULL;
|
||||
GuiRolloutCtrl *pArrayRollout = NULL;
|
||||
bool bGrabItems = false;
|
||||
|
||||
AbstractClassRep* commonAncestorClass = findCommonAncestorClass();
|
||||
AbstractClassRep::FieldList& fieldList = commonAncestorClass->mFieldList;
|
||||
for( AbstractClassRep::FieldList::iterator itr = fieldList.begin();
|
||||
itr != fieldList.end(); ++ itr )
|
||||
{
|
||||
AbstractClassRep::Field* field = &( *itr );
|
||||
if( field->type == AbstractClassRep::StartGroupFieldType )
|
||||
{
|
||||
// If we're dealing with general fields, always set grabItems to true (to skip them)
|
||||
if( bNoGroup == true )
|
||||
bGrabItems = true;
|
||||
else if( dStricmp( field->pGroupname, mCaption ) == 0 )
|
||||
bGrabItems = true;
|
||||
continue;
|
||||
}
|
||||
else if ( field->type == AbstractClassRep::EndGroupFieldType )
|
||||
{
|
||||
// If we're dealing with general fields, always set grabItems to false (to grab them)
|
||||
if( bNoGroup == true )
|
||||
bGrabItems = false;
|
||||
else if( dStricmp( field->pGroupname, mCaption ) == 0 )
|
||||
bGrabItems = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip field if it has the HideInInspectors flag set.
|
||||
|
||||
if( field->flag.test( AbstractClassRep::FIELD_HideInInspectors ) )
|
||||
continue;
|
||||
|
||||
if( ( bGrabItems == true || ( bNoGroup == true && bGrabItems == false ) ) && itr->type != AbstractClassRep::DeprecatedFieldType )
|
||||
{
|
||||
if( bNoGroup == true && bGrabItems == true )
|
||||
continue;
|
||||
|
||||
if ( field->type == AbstractClassRep::StartArrayFieldType )
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspectorGroup] Beginning array '%s'",
|
||||
field->pFieldname );
|
||||
#endif
|
||||
|
||||
// Starting an array...
|
||||
// Create a rollout for the Array, give it the array's name.
|
||||
GuiRolloutCtrl *arrayRollout = new GuiRolloutCtrl();
|
||||
GuiControlProfile *arrayRolloutProfile = dynamic_cast<GuiControlProfile*>( Sim::findObject( "GuiInspectorRolloutProfile0" ) );
|
||||
|
||||
arrayRollout->setControlProfile(arrayRolloutProfile);
|
||||
//arrayRollout->mCaption = StringTable->insert( String::ToString( "%s (%i)", field->pGroupname, field->elementCount ) );
|
||||
arrayRollout->setCaption( field->pGroupname );
|
||||
//arrayRollout->setMargin( 14, 0, 0, 0 );
|
||||
arrayRollout->registerObject();
|
||||
|
||||
GuiStackControl *arrayStack = new GuiStackControl();
|
||||
arrayStack->registerObject();
|
||||
arrayStack->freeze(true);
|
||||
arrayRollout->addObject(arrayStack);
|
||||
|
||||
// Allocate a rollout for each element-count in the array
|
||||
// Give it the element count name.
|
||||
for ( U32 i = 0; i < field->elementCount; i++ )
|
||||
{
|
||||
GuiRolloutCtrl *elementRollout = new GuiRolloutCtrl();
|
||||
GuiControlProfile *elementRolloutProfile = dynamic_cast<GuiControlProfile*>( Sim::findObject( "GuiInspectorRolloutProfile0" ) );
|
||||
|
||||
char buf[256];
|
||||
dSprintf( buf, 256, " [%i]", i );
|
||||
|
||||
elementRollout->setControlProfile(elementRolloutProfile);
|
||||
elementRollout->setCaption(buf);
|
||||
//elementRollout->setMargin( 14, 0, 0, 0 );
|
||||
elementRollout->registerObject();
|
||||
|
||||
GuiStackControl *elementStack = new GuiStackControl();
|
||||
elementStack->registerObject();
|
||||
elementRollout->addObject(elementStack);
|
||||
elementRollout->instantCollapse();
|
||||
|
||||
arrayStack->addObject( elementRollout );
|
||||
}
|
||||
|
||||
pArrayRollout = arrayRollout;
|
||||
pArrayStack = arrayStack;
|
||||
arrayStack->freeze(false);
|
||||
pArrayRollout->instantCollapse();
|
||||
mStack->addObject(arrayRollout);
|
||||
|
||||
bMakingArray = true;
|
||||
continue;
|
||||
}
|
||||
else if ( field->type == AbstractClassRep::EndArrayFieldType )
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspectorGroup] Ending array '%s'",
|
||||
field->pFieldname );
|
||||
#endif
|
||||
|
||||
bMakingArray = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( bMakingArray )
|
||||
{
|
||||
// Add a GuiInspectorField for this field,
|
||||
// for every element in the array...
|
||||
for ( U32 i = 0; i < pArrayStack->size(); i++ )
|
||||
{
|
||||
FrameTemp<char> intToStr( 64 );
|
||||
dSprintf( intToStr, 64, "%d", i );
|
||||
|
||||
// The array stack should have a rollout for each element
|
||||
// as children...
|
||||
GuiRolloutCtrl *pRollout = dynamic_cast<GuiRolloutCtrl*>(pArrayStack->at(i));
|
||||
// And the each of those rollouts should have a stack for
|
||||
// fields...
|
||||
GuiStackControl *pStack = dynamic_cast<GuiStackControl*>(pRollout->at(0));
|
||||
|
||||
// And we add a new GuiInspectorField to each of those stacks...
|
||||
GuiInspectorField *fieldGui = constructField( field->type );
|
||||
if ( fieldGui == NULL )
|
||||
fieldGui = new GuiInspectorField();
|
||||
|
||||
fieldGui->init( mParent, this );
|
||||
StringTableEntry caption = field->pFieldname;
|
||||
fieldGui->setInspectorField( field, caption, intToStr );
|
||||
|
||||
if( fieldGui->registerObject() )
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspectorGroup] Adding array element '%s[%i]'",
|
||||
field->pFieldname, i );
|
||||
#endif
|
||||
|
||||
mChildren.push_back( fieldGui );
|
||||
pStack->addObject( fieldGui );
|
||||
}
|
||||
else
|
||||
delete fieldGui;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is weird, but it should work for now. - JDD
|
||||
// We are going to check to see if this item is an array
|
||||
// if so, we're going to construct a field for each array element
|
||||
if( field->elementCount > 1 )
|
||||
{
|
||||
// Make a rollout control for this array
|
||||
//
|
||||
GuiRolloutCtrl *rollout = new GuiRolloutCtrl();
|
||||
rollout->setDataField( StringTable->insert("profile"), NULL, "GuiInspectorRolloutProfile0" );
|
||||
rollout->setCaption(String::ToString( "%s (%i)", field->pFieldname, field->elementCount));
|
||||
rollout->setMargin( 14, 0, 0, 0 );
|
||||
rollout->registerObject();
|
||||
mArrayCtrls.push_back(rollout);
|
||||
|
||||
// Put a stack control within the rollout
|
||||
//
|
||||
GuiStackControl *stack = new GuiStackControl();
|
||||
stack->setDataField( StringTable->insert("profile"), NULL, "GuiInspectorStackProfile" );
|
||||
stack->registerObject();
|
||||
stack->freeze(true);
|
||||
rollout->addObject(stack);
|
||||
|
||||
mStack->addObject(rollout);
|
||||
|
||||
// Create each field and add it to the stack.
|
||||
//
|
||||
for (S32 nI = 0; nI < field->elementCount; nI++)
|
||||
{
|
||||
FrameTemp<char> intToStr( 64 );
|
||||
dSprintf( intToStr, 64, "%d", nI );
|
||||
|
||||
// Construct proper ValueName[nI] format which is "ValueName0" for index 0, etc.
|
||||
|
||||
String fieldName = String::ToString( "%s%d", field->pFieldname, nI );
|
||||
|
||||
// If the field already exists, just update it
|
||||
GuiInspectorField *fieldGui = findField( fieldName );
|
||||
if( fieldGui != NULL )
|
||||
{
|
||||
fieldGui->updateValue();
|
||||
continue;
|
||||
}
|
||||
|
||||
bNewItems = true;
|
||||
|
||||
fieldGui = constructField( field->type );
|
||||
if ( fieldGui == NULL )
|
||||
fieldGui = new GuiInspectorField();
|
||||
|
||||
fieldGui->init( mParent, this );
|
||||
StringTableEntry caption = StringTable->insert( String::ToString(" [%i]",nI) );
|
||||
fieldGui->setInspectorField( field, caption, intToStr );
|
||||
|
||||
if ( fieldGui->registerObject() )
|
||||
{
|
||||
mChildren.push_back( fieldGui );
|
||||
stack->addObject( fieldGui );
|
||||
}
|
||||
else
|
||||
delete fieldGui;
|
||||
}
|
||||
|
||||
stack->freeze(false);
|
||||
stack->updatePanes();
|
||||
rollout->instantCollapse();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the field already exists, just update it
|
||||
GuiInspectorField *fieldGui = findField( field->pFieldname );
|
||||
if ( fieldGui != NULL )
|
||||
{
|
||||
fieldGui->updateValue();
|
||||
continue;
|
||||
}
|
||||
|
||||
bNewItems = true;
|
||||
|
||||
fieldGui = constructField( field->type );
|
||||
if ( fieldGui == NULL )
|
||||
fieldGui = new GuiInspectorField();
|
||||
|
||||
fieldGui->init( mParent, this );
|
||||
fieldGui->setInspectorField( field );
|
||||
|
||||
if( fieldGui->registerObject() )
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspectorGroup] Adding field '%s'",
|
||||
field->pFieldname );
|
||||
#endif
|
||||
|
||||
mChildren.push_back( fieldGui );
|
||||
mStack->addObject( fieldGui );
|
||||
}
|
||||
else
|
||||
{
|
||||
SAFE_DELETE( fieldGui );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mStack->freeze(false);
|
||||
mStack->updatePanes();
|
||||
|
||||
// If we've no new items, there's no need to resize anything!
|
||||
if( bNewItems == false && !mChildren.empty() )
|
||||
return true;
|
||||
|
||||
sizeToContents();
|
||||
|
||||
setUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspectorGroup::updateFieldValue( StringTableEntry fieldName, StringTableEntry arrayIdx )
|
||||
{
|
||||
// Check if we contain a field of this name,
|
||||
// if so update its value and return true.
|
||||
Vector<GuiInspectorField*>::iterator iter = mChildren.begin();
|
||||
|
||||
if( arrayIdx == StringTable->EmptyString() )
|
||||
arrayIdx = NULL;
|
||||
|
||||
for( ; iter != mChildren.end(); iter++ )
|
||||
{
|
||||
GuiInspectorField *field = (*iter);
|
||||
if ( field->mField &&
|
||||
field->mField->pFieldname == fieldName &&
|
||||
field->mFieldArrayIndex == arrayIdx )
|
||||
{
|
||||
field->updateValue();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspectorGroup::updateAllFields()
|
||||
{
|
||||
Vector<GuiInspectorField*>::iterator iter = mChildren.begin();
|
||||
for( ; iter != mChildren.end(); iter++ )
|
||||
(*iter)->updateValue();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
AbstractClassRep* GuiInspectorGroup::findCommonAncestorClass()
|
||||
{
|
||||
AbstractClassRep* classRep = getInspector()->getInspectObject( 0 )->getClassRep();
|
||||
const U32 numInspectObjects = getInspector()->getNumInspectObjects();
|
||||
|
||||
for( U32 i = 1; i < numInspectObjects; ++ i )
|
||||
{
|
||||
SimObject* object = getInspector()->getInspectObject( i );
|
||||
while( !object->getClassRep()->isClass( classRep ) )
|
||||
{
|
||||
classRep = classRep->getParentClass();
|
||||
AssertFatal( classRep, "GuiInspectorGroup::findcommonAncestorClass - Walked above ConsoleObject!" );
|
||||
}
|
||||
}
|
||||
|
||||
return classRep;
|
||||
}
|
||||
87
Engine/source/gui/editor/inspector/group.h
Normal file
87
Engine/source/gui/editor/inspector/group.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_INSPECTOR_GROUP_H_
|
||||
#define _GUI_INSPECTOR_GROUP_H_
|
||||
|
||||
#include "gui/core/guiCanvas.h"
|
||||
#include "gui/controls/guiTextEditCtrl.h"
|
||||
#include "gui/buttons/guiBitmapButtonCtrl.h"
|
||||
#include "gui/containers/guiRolloutCtrl.h"
|
||||
|
||||
// Forward refs
|
||||
class GuiInspector;
|
||||
class GuiInspectorField;
|
||||
|
||||
|
||||
/// The GuiInspectorGroup control is a helper control that the inspector
|
||||
/// makes use of which houses a collapsible pane type control for separating
|
||||
/// inspected objects fields into groups. The content of the inspector is
|
||||
/// made up of zero or more GuiInspectorGroup controls inside of a GuiStackControl
|
||||
///
|
||||
class GuiInspectorGroup : public GuiRolloutCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiRolloutCtrl Parent;
|
||||
public:
|
||||
// Members
|
||||
SimObjectPtr<GuiInspector> mParent;
|
||||
Vector<GuiInspectorField*> mChildren;
|
||||
GuiStackControl* mStack;
|
||||
Vector<GuiRolloutCtrl*> mArrayCtrls;
|
||||
|
||||
// Constructor/Destructor/Conobject Declaration
|
||||
GuiInspectorGroup();
|
||||
GuiInspectorGroup( const String& groupName, SimObjectPtr<GuiInspector> parent );
|
||||
virtual ~GuiInspectorGroup();
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorGroup);
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
|
||||
virtual GuiInspectorField* constructField( S32 fieldType );
|
||||
virtual GuiInspectorField* findField( const char *fieldName );
|
||||
|
||||
// Publicly Accessible Information about this group
|
||||
const String& getGroupName() const { return mCaption; };
|
||||
SimObjectPtr<GuiInspector> getInspector() { return mParent; };
|
||||
|
||||
bool onAdd();
|
||||
virtual bool inspectGroup();
|
||||
|
||||
virtual void animateToContents();
|
||||
|
||||
void clearFields();
|
||||
|
||||
virtual bool updateFieldValue( StringTableEntry fieldName, const char *arrayIdx );
|
||||
virtual void updateAllFields();
|
||||
|
||||
U32 getNumFields() const { return mChildren.size(); }
|
||||
|
||||
protected:
|
||||
// overridable method that creates our inner controls.
|
||||
virtual bool createContent();
|
||||
|
||||
/// Determine the class that is a common ancestor to all inspected objects.
|
||||
AbstractClassRep* findCommonAncestorClass();
|
||||
};
|
||||
|
||||
#endif // _GUI_INSPECTOR_GROUP_H_
|
||||
120
Engine/source/gui/editor/inspector/variableField.cpp
Normal file
120
Engine/source/gui/editor/inspector/variableField.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "gui/editor/inspector/variableField.h"
|
||||
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorVariableField
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorVariableField);
|
||||
|
||||
ConsoleDocClass( GuiInspectorVariableField,
|
||||
"@brief Inspector support for variables in a GuiVariableInspector.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
GuiInspectorVariableField::GuiInspectorVariableField()
|
||||
{
|
||||
}
|
||||
|
||||
GuiInspectorVariableField::~GuiInspectorVariableField()
|
||||
{
|
||||
}
|
||||
|
||||
bool GuiInspectorVariableField::onAdd()
|
||||
{
|
||||
setInspectorProfile();
|
||||
|
||||
// Hack: skip our immediate parent
|
||||
if ( !Parent::Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
{
|
||||
GuiTextEditCtrl *edit = new GuiTextEditCtrl();
|
||||
|
||||
edit->setDataField( StringTable->insert("profile"), NULL, "GuiInspectorTextEditProfile" );
|
||||
|
||||
edit->registerObject();
|
||||
|
||||
char szBuffer[512];
|
||||
dSprintf( szBuffer, 512, "%d.apply(%d.getText());",getId(), edit->getId() );
|
||||
edit->setField("AltCommand", szBuffer );
|
||||
edit->setField("Validate", szBuffer );
|
||||
|
||||
mEdit = edit;
|
||||
}
|
||||
|
||||
setBounds(0,0,100,18);
|
||||
|
||||
// Add our edit as a child
|
||||
addObject( mEdit );
|
||||
|
||||
// Calculate Caption and EditCtrl Rects
|
||||
updateRects();
|
||||
|
||||
// Force our editField to set it's value
|
||||
updateValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiInspectorVariableField::setData( const char* data, bool callbacks )
|
||||
{
|
||||
if ( !mCaption || mCaption[0] == 0 )
|
||||
return;
|
||||
|
||||
Con::setVariable( mCaption, data );
|
||||
|
||||
// Force our edit to update
|
||||
updateValue();
|
||||
}
|
||||
|
||||
const char* GuiInspectorVariableField::getData( U32 inspectObjectIndex )
|
||||
{
|
||||
if ( !mCaption || mCaption[0] == 0 )
|
||||
return "";
|
||||
|
||||
return Con::getVariable( mCaption );
|
||||
}
|
||||
|
||||
void GuiInspectorVariableField::setValue( const char* newValue )
|
||||
{
|
||||
GuiTextEditCtrl *ctrl = dynamic_cast<GuiTextEditCtrl*>( mEdit );
|
||||
if( ctrl != NULL )
|
||||
ctrl->setText( newValue );
|
||||
}
|
||||
|
||||
void GuiInspectorVariableField::updateValue()
|
||||
{
|
||||
if ( !mCaption || mCaption[0] == 0 )
|
||||
return;
|
||||
|
||||
setValue( getData() );
|
||||
}
|
||||
62
Engine/source/gui/editor/inspector/variableField.h
Normal file
62
Engine/source/gui/editor/inspector/variableField.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_INSPECTOR_VARIABLEFIELD_H_
|
||||
#define _GUI_INSPECTOR_VARIABLEFIELD_H_
|
||||
|
||||
#ifndef _GUI_INSPECTOR_FIELD_H_
|
||||
#include "gui/editor/inspector/field.h"
|
||||
#endif
|
||||
|
||||
class GuiInspectorGroup;
|
||||
class GuiInspector;
|
||||
|
||||
|
||||
class GuiInspectorVariableField : public GuiInspectorField
|
||||
{
|
||||
friend class GuiInspectorField;
|
||||
|
||||
public:
|
||||
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
GuiInspectorVariableField();
|
||||
virtual ~GuiInspectorVariableField();
|
||||
|
||||
DECLARE_CONOBJECT( GuiInspectorVariableField );
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
|
||||
virtual bool onAdd();
|
||||
|
||||
|
||||
virtual void setValue( const char* newValue );
|
||||
virtual const char* getValue() { return NULL; }
|
||||
virtual void updateValue();
|
||||
virtual void setData( const char* data, bool callbacks = true );
|
||||
virtual const char* getData( U32 inspectObjectIndex = 0 );
|
||||
virtual void updateData() {};
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
#endif // _GUI_INSPECTOR_VARIABLEFIELD_H_
|
||||
109
Engine/source/gui/editor/inspector/variableGroup.cpp
Normal file
109
Engine/source/gui/editor/inspector/variableGroup.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform/platform.h"
|
||||
#include "gui/editor/inspector/variableGroup.h"
|
||||
#include "gui/editor/inspector/variableField.h"
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
#include "console/consoleInternal.h"
|
||||
|
||||
extern ExprEvalState gEvalState;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorVariableGroup
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorVariableGroup);
|
||||
|
||||
ConsoleDocClass( GuiInspectorVariableGroup,
|
||||
"@brief Inspector support for variable groups in a GuiVariableInspector.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
GuiInspectorVariableGroup::GuiInspectorVariableGroup()
|
||||
{
|
||||
}
|
||||
|
||||
GuiInspectorVariableGroup::~GuiInspectorVariableGroup()
|
||||
{
|
||||
}
|
||||
|
||||
GuiInspectorField* GuiInspectorVariableGroup::constructField( S32 fieldType )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool GuiInspectorVariableGroup::inspectGroup()
|
||||
{
|
||||
// to prevent crazy resizing, we'll just freeze our stack for a sec..
|
||||
mStack->freeze(true);
|
||||
|
||||
clearFields();
|
||||
|
||||
Vector<String> names;
|
||||
|
||||
gEvalState.globalVars.exportVariables( mSearchString, &names, NULL );
|
||||
|
||||
bool bNewItems = false;
|
||||
|
||||
for ( U32 i = 0; i < names.size(); i++ )
|
||||
{
|
||||
const String &varName = names[i];
|
||||
|
||||
// If the field already exists, just update it
|
||||
GuiInspectorVariableField *field = dynamic_cast<GuiInspectorVariableField*>( findField( varName ) );
|
||||
if ( field != NULL )
|
||||
{
|
||||
field->updateValue();
|
||||
continue;
|
||||
}
|
||||
|
||||
bNewItems = true;
|
||||
|
||||
field = new GuiInspectorVariableField();
|
||||
field->init( mParent, this );
|
||||
field->setInspectorField( NULL, StringTable->insert( varName ) );
|
||||
|
||||
if ( field->registerObject() )
|
||||
{
|
||||
mChildren.push_back( field );
|
||||
mStack->addObject( field );
|
||||
}
|
||||
else
|
||||
delete field;
|
||||
}
|
||||
|
||||
mStack->freeze(false);
|
||||
mStack->updatePanes();
|
||||
|
||||
// If we've no new items, there's no need to resize anything!
|
||||
if( bNewItems == false && !mChildren.empty() )
|
||||
return true;
|
||||
|
||||
sizeToContents();
|
||||
|
||||
setUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
55
Engine/source/gui/editor/inspector/variableGroup.h
Normal file
55
Engine/source/gui/editor/inspector/variableGroup.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_INSPECTOR_VARIABLEGROUP_H_
|
||||
#define _GUI_INSPECTOR_VARIABLEGROUP_H_
|
||||
|
||||
#ifndef _GUI_INSPECTOR_GROUP_H_
|
||||
#include "gui/editor/inspector/group.h"
|
||||
#endif
|
||||
|
||||
// Forward refs
|
||||
class GuiInspector;
|
||||
class GuiInspectorField;
|
||||
|
||||
class GuiInspectorVariableGroup : public GuiInspectorGroup
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiInspectorGroup Parent;
|
||||
|
||||
String mSearchString;
|
||||
|
||||
GuiInspectorVariableGroup();
|
||||
virtual ~GuiInspectorVariableGroup();
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorVariableGroup);
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
|
||||
virtual GuiInspectorField* constructField( S32 fieldType );
|
||||
|
||||
virtual bool inspectGroup();
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // _GUI_INSPECTOR_VARIABLEGROUP_H_
|
||||
67
Engine/source/gui/editor/inspector/variableInspector.cpp
Normal file
67
Engine/source/gui/editor/inspector/variableInspector.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "gui/editor/inspector/variableInspector.h"
|
||||
#include "gui/editor/inspector/variableGroup.h"
|
||||
|
||||
GuiVariableInspector::GuiVariableInspector()
|
||||
{
|
||||
}
|
||||
|
||||
GuiVariableInspector::~GuiVariableInspector()
|
||||
{
|
||||
}
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiVariableInspector);
|
||||
|
||||
ConsoleDocClass( GuiVariableInspector,
|
||||
"@brief GUI dedicated to variable viewing/manipulation\n\n"
|
||||
"Mostly used in console system, internal use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiVariableInspector::loadVars( String searchStr )
|
||||
{
|
||||
clearGroups();
|
||||
|
||||
GuiInspectorVariableGroup *group = new GuiInspectorVariableGroup();
|
||||
|
||||
group->setHeaderHidden( true );
|
||||
group->setCanCollapse( false );
|
||||
group->mParent = this;
|
||||
group->setCaption( "Global Variables" );
|
||||
group->mSearchString = searchStr;
|
||||
|
||||
if( group != NULL )
|
||||
{
|
||||
group->registerObject();
|
||||
mGroups.push_back( group );
|
||||
addObject( group );
|
||||
}
|
||||
|
||||
//group->inspectGroup();
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiVariableInspector, loadVars, void, 3, 3, "loadVars( searchString )" )
|
||||
{
|
||||
object->loadVars( argv[2] );
|
||||
}
|
||||
52
Engine/source/gui/editor/inspector/variableInspector.h
Normal file
52
Engine/source/gui/editor/inspector/variableInspector.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUI_VARIABLEINSPECTOR_H_
|
||||
#define _GUI_VARIABLEINSPECTOR_H_
|
||||
|
||||
#ifndef _GUI_INSPECTOR_H_
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#endif
|
||||
|
||||
|
||||
class GuiVariableInspector : public GuiInspector
|
||||
{
|
||||
typedef GuiInspector Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiVariableInspector();
|
||||
virtual ~GuiVariableInspector();
|
||||
|
||||
DECLARE_CONOBJECT( GuiVariableInspector );
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
|
||||
virtual void inspectObject( SimObject *object ) {}
|
||||
|
||||
virtual void loadVars( String searchString );
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
#endif // _GUI_VARIABLEINSPECTOR_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue