Torque3D Documentation / _generateds / dynamicField.cpp

dynamicField.cpp

Engine/source/gui/editor/inspector/dynamicField.cpp

More...

Public Functions

ConsoleDocClass(GuiInspectorDynamicField , "@brief Custom field type <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> dynamic variable modification on <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimObjects.\n\n</a>" "Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )
DefineEngineMethod(GuiInspectorDynamicField , renameField , void , (const char *newDynamicFieldName) , "field.renameField(newDynamicFieldName);" )

Detailed Description

Public Functions

ConsoleDocClass(GuiInspectorDynamicField , "@brief Custom field type <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> dynamic variable modification on <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SimObjects.\n\n</a>" "Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )

DefineEngineMethod(GuiInspectorDynamicField , renameField , void , (const char *newDynamicFieldName) , "field.renameField(newDynamicFieldName);" )

IMPLEMENT_CONOBJECT(GuiInspectorDynamicField )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "gui/editor/inspector/dynamicField.h"
 25#include "gui/editor/inspector/dynamicGroup.h"
 26#include "gui/editor/guiInspector.h"
 27#include "gui/buttons/guiIconButtonCtrl.h"
 28#include "console/engineAPI.h"
 29
 30//-----------------------------------------------------------------------------
 31// GuiInspectorDynamicField - Child class of GuiInspectorField 
 32//-----------------------------------------------------------------------------
 33IMPLEMENT_CONOBJECT( GuiInspectorDynamicField );
 34
 35ConsoleDocClass( GuiInspectorDynamicField,
 36   "@brief Custom field type for dynamic variable modification on SimObjects.\n\n"
 37   "Editor use only.\n\n"
 38   "@internal"
 39);
 40
 41GuiInspectorDynamicField::GuiInspectorDynamicField( GuiInspector *inspector,
 42                                                    GuiInspectorGroup* parent, 
 43                                                    SimFieldDictionary::Entry* field )
 44 : mRenameCtrl( NULL ),
 45   mDeleteButton( NULL )
 46{
 47   mInspector = inspector;
 48   mParent = parent;
 49   mDynField = field;
 50   setBounds(0,0,100,20);   
 51}
 52
 53void GuiInspectorDynamicField::setData( const char* data, bool callbacks )
 54{
 55   if ( mDynField == NULL )
 56      return;
 57   
 58   const U32 numTargets = mInspector->getNumInspectObjects();
 59   if( callbacks && numTargets > 1 )
 60      Con::executef( mInspector, "beginCompoundUndo" );
 61      
 62   // Setting an empty string will kill the field.
 63   const bool isRemoval = !data[ 0 ];
 64      
 65   for( U32 i = 0; i < numTargets; ++ i )
 66   {
 67      SimObject* target = mInspector->getInspectObject( i );
 68
 69      // Callback on the inspector when the field is modified
 70      // to allow creation of undo/redo actions.
 71      const char *oldData = target->getDataField( mDynField->slotName, NULL );
 72      if ( !oldData )
 73         oldData = "";
 74      if ( String::compare( oldData, data ) != 0 )
 75      {
 76         target->inspectPreApply();
 77         
 78         if( callbacks )
 79         {
 80            if( isRemoval )
 81               Con::executef( mInspector, "onFieldRemoved", target->getIdString(), mDynField->slotName );
 82            else
 83               Con::executef( mInspector, "onInspectorFieldModified", target->getIdString(), mDynField->slotName, oldData, data );
 84         }
 85
 86         target->setDataField( mDynField->slotName, NULL, data );
 87
 88         // give the target a chance to validate
 89         target->inspectPostApply();
 90      }
 91   }
 92   
 93   if( callbacks && numTargets > 1 )
 94      Con::executef( mInspector, "endCompoundUndo" );
 95
 96   // Force our edit to update
 97   updateValue();
 98}
 99
100const char* GuiInspectorDynamicField::getData( U32 inspectObjectIndex )
101{
102   if( mDynField == NULL )
103      return "";
104
105   return mInspector->getInspectObject( inspectObjectIndex )->getDataField( mDynField->slotName, NULL );
106}
107
108void GuiInspectorDynamicField::renameField( const char* newFieldName )
109{
110   newFieldName = StringTable->insert( newFieldName );
111   
112   if ( mDynField == NULL || mParent == NULL || mEdit == NULL )
113   {
114      Con::warnf("GuiInspectorDynamicField::renameField - No target object or dynamic field data found!" );
115      return;
116   }
117
118   if ( !newFieldName )
119   {
120      Con::warnf("GuiInspectorDynamicField::renameField - Invalid field name specified!" );
121      return;
122   }
123
124   // Only proceed if the name has changed
125   if ( dStricmp( newFieldName, getFieldName() ) == 0 )
126      return;
127      
128   // Grab a pointer to our parent and cast it to GuiInspectorDynamicGroup
129   GuiInspectorDynamicGroup *group = dynamic_cast<GuiInspectorDynamicGroup*>(mParent);
130   if ( group == NULL )
131   {
132      Con::warnf("GuiInspectorDynamicField::renameField - Unable to locate GuiInspectorDynamicGroup parent!" );
133      return;
134   }
135   
136   const U32 numTargets = mInspector->getNumInspectObjects();
137   if( numTargets > 1 )
138      Con::executef( mInspector, "onBeginCompoundEdit" );
139      
140   const char* oldFieldName = getFieldName();
141   SimFieldDictionary::Entry* newEntry = NULL;
142   
143   for( U32 i = 0; i < numTargets; ++ i )
144   {
145      SimObject* target = mInspector->getInspectObject( i );
146      
147      // Make sure the new field is not already defined as a static field
148      // on the object.
149      
150      if( target->isField( newFieldName ) )
151      {
152         // New field is already defined.  If we can, let the scripts handle
153         // the error.  Otherwise, just emit an error on the console and proceed.
154         
155         if( numTargets == 1 && mInspector->isMethod( "onFieldRenameAlreadyDefined" ) )
156            Con::executef( mInspector, "onFieldRenameAlreadyDefined", target->getIdString(), oldFieldName, newFieldName );
157         else
158            Con::errorf( "GuiInspectorDynamicField::renameField - field '%s' is already defined on %i:%s (%s)",
159               newFieldName, target->getId(), target->getClassName(), target->getName() );
160               
161         // Reset the text entry.
162               
163         if( mRenameCtrl )
164            mRenameCtrl->setText( oldFieldName );
165            
166         continue;
167      }
168      
169      char currentValue[1024] = {0};
170      // Grab our current dynamic field value (we use a temporary buffer as this gets corrupted upon Con::eval)
171      dSprintf( currentValue, sizeof( currentValue ), "%s", target->getDataField( oldFieldName, NULL ) );
172
173      // Unset the old field and set the new field.
174      
175      target->setDataField( oldFieldName, NULL, "" );
176      target->setDataField( newFieldName, NULL, currentValue );
177
178      // Notify script.
179      
180      Con::executef( mInspector, "onFieldRenamed", target->getIdString(), oldFieldName, newFieldName );
181      
182      // Look up the new SimFieldDictionary entry.
183      
184      if( !newEntry )
185      {
186         newEntry = target->getFieldDictionary()->findDynamicField( newFieldName );
187         if( !newEntry )
188         {
189            Con::warnf( "GuiInspectorDynamicField::renameField - could not find new field '%s' on object %i:%s (%s)",
190               newFieldName, target->getId(), target->getClassName(), target->getName() );
191         }
192         
193         mDynField = newEntry;
194      }
195   }
196
197   if( numTargets > 1 )
198      Con::executef( mInspector, "onEndCompoundEdit" );
199      
200   // Lastly we need to reassign our validate field for our value edit control
201   char szBuffer[1024];
202   dSprintf( szBuffer, sizeof( szBuffer ), "%d.apply(%d.getText());", getId(), mEdit->getId() );
203   mEdit->setField("validate", szBuffer );
204
205   if( mDeleteButton )
206   {
207      dSprintf(szBuffer, sizeof( szBuffer ), "%d.apply("");%d.inspectGroup();", getId(), newFieldName, group->getId());
208      mDeleteButton->setField("Command", szBuffer);
209   }
210}
211
212bool GuiInspectorDynamicField::onAdd()
213{
214   if( !Parent::onAdd() )
215      return false;
216
217   //pushObjectToBack(mEdit);
218
219   // Create our renaming field
220   mRenameCtrl = new GuiTextEditCtrl();
221   mRenameCtrl->setDataField( StringTable->insert("profile"), NULL, "GuiInspectorDynamicFieldProfile" );
222
223   char szName[512];
224   dSprintf( szName, 512, "IE_%s_%d_%s_Rename", mRenameCtrl->getClassName(), mInspector->getInspectObject()->getId(), getFieldName() );
225   mRenameCtrl->registerObject( szName );
226
227   // Our command will evaluate to :
228   //
229   //    if( (editCtrl).getText() !$= "" )
230   //       (field).renameField((editCtrl).getText());
231   //
232   char szBuffer[1024];
233   dSprintf( szBuffer, sizeof( szBuffer ), "if( %d.getText() !$= \"\" ) %d.renameField(%d.getText());", mRenameCtrl->getId(), getId(), mRenameCtrl->getId() );
234   mRenameCtrl->setText( getFieldName() );
235   mRenameCtrl->setField("Validate", szBuffer );
236   addObject( mRenameCtrl );
237
238   // Resize the name control to fit in our caption rect
239   mRenameCtrl->resize( mCaptionRect.point, mCaptionRect.extent );
240
241   // Resize the value control to leave space for the delete button
242   mEdit->resize( mValueRect.point, mValueRect.extent);
243
244   // Clear out any caption set from Parent::onAdd
245   // since we are rendering the fieldname with our 'rename' control.
246   mCaption = StringTable->insert( "" );
247
248   // Create delete button control
249   mDeleteButton = new GuiBitmapButtonCtrl();
250
251   SimObject* profilePtr = Sim::findObject("InspectorDynamicFieldButton");
252   if( profilePtr != NULL )
253      mDeleteButton->setControlProfile( dynamic_cast<GuiControlProfile*>(profilePtr) );
254
255   dSprintf( szBuffer, sizeof( szBuffer ),
256      "%d.apply(\"\");%d.schedule(1,\"inspectGroup\");",
257      getId(),
258      mParent->getId() );
259
260   // FIXME Hardcoded image
261   mDeleteButton->setField( "Bitmap", "tools/gui/images/iconDelete" );
262   mDeleteButton->setField( "Text", "X" );
263   mDeleteButton->setField( "Command", szBuffer );
264   mDeleteButton->setSizing( horizResizeLeft, vertResizeCenter );
265   mDeleteButton->resize(Point2I(getWidth() - 20,2), Point2I(16, 16));
266   mDeleteButton->registerObject();
267
268   addObject(mDeleteButton);
269
270   return true;
271}
272
273bool GuiInspectorDynamicField::updateRects()
274{   
275   Point2I fieldExtent = getExtent();   
276   S32 dividerPos, dividerMargin;
277   mInspector->getDivider( dividerPos, dividerMargin );
278
279   S32 editWidth = dividerPos - dividerMargin;
280
281   mEditCtrlRect.set( fieldExtent.x - dividerPos + dividerMargin, 1, editWidth, fieldExtent.y - 1 );
282   mCaptionRect.set( 0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y );
283   mValueRect.set( mEditCtrlRect.point, mEditCtrlRect.extent - Point2I( 20, 0 ) );
284   mDeleteRect.set( fieldExtent.x - 20, 2, 16, fieldExtent.y - 4 );
285
286   // This is probably being called during Parent::onAdd
287   // so our special controls haven't been created yet but are just about to
288   // so we just need to calculate the extents.
289   if ( mRenameCtrl == NULL )
290      return false;
291
292   bool sized0 = mRenameCtrl->resize( mCaptionRect.point, mCaptionRect.extent );
293   bool sized1 = mEdit->resize( mValueRect.point, mValueRect.extent );
294   bool sized2 = mDeleteButton->resize(Point2I(getWidth() - 20,2), Point2I(16, 16));
295
296   return ( sized0 || sized1 || sized2 );
297}
298
299void GuiInspectorDynamicField::setInspectorField( AbstractClassRep::Field *field, 
300                                                  StringTableEntry caption, 
301                                                  const char*arrayIndex ) 
302{
303   // Override the base just to be sure it doesn't get called.
304   // We don't use an AbstractClassRep::Field...
305
306//    mField = field; 
307//    mCaption = StringTable->EmptyString();
308//    mRenameCtrl->setText( getFieldName() );
309}
310
311void GuiInspectorDynamicField::_executeSelectedCallback()
312{
313   ConsoleBaseType* type = mDynField->type;
314   if ( type )
315      Con::executef( mInspector, "onFieldSelected", mDynField->slotName, type->getTypeName() );
316   else
317      Con::executef( mInspector, "onFieldSelected", mDynField->slotName, "TypeDynamicField" );
318}
319
320DefineEngineMethod( GuiInspectorDynamicField, renameField, void, (const char* newDynamicFieldName),, "field.renameField(newDynamicFieldName);" )
321{
322   object->renameField( newDynamicFieldName );
323}
324