void GuiInspectorDynamicField::setData( const char* data, bool callbacks ) { if ( mDynField == NULL ) return; const U32 numTargets = mInspector->getNumInspectObjects(); if( callbacks && numTargets > 1 ) { mInspector->beginCompoundUndo_callback(); } // 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 ) { mInspector->onFieldRemoved_callback( target->getIdString(), mDynField->slotName ); } else { mInspector->onInspectorFieldModified_callback( target->getIdString(), mDynField->slotName,"(null)", oldData, data ); } } target->setDataField( mDynField->slotName, NULL, data ); // give the target a chance to validate target->inspectPostApply(); } } if( callbacks && numTargets > 1 ) { mInspector->endCompoundUndo_callback(); } // Force our edit to update updateValue(); }
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 ) { mInspector->onBeginCompoundEdit_callback(); } 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 ) { mInspector->onInspectorFieldModified_callback( 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 ) { mInspector->onEndCompoundEdit_callback(); } } // Force our edit to update updateValue(); }