📄 guiinspector.cc
字号:
}
return NULL;
}
GuiInspectorDynamicField *GuiInspectorDynamicGroup::findDynamicField( StringTableEntry fieldName )
{
// We can't inspect a group without a target!
if( !mTarget || mChildren.empty() )
return false;
Vector<GuiInspectorField*>::iterator i = mChildren.begin();
for( ; i != mChildren.end(); i++ )
{
if( dStricmp( (*i)->getFieldName(), fieldName ) == 0 )
return dynamic_cast<GuiInspectorDynamicField*>(*i);
}
return NULL;
}
void GuiInspectorDynamicGroup::onRender(Point2I offset, const RectI &updateRect)
{
// Do normal rendering
Parent::onRender( offset, updateRect );
if( !mIsExpanded )
return;
// Calculate actual world bounds for rendering
RectI worldBounds( offset, mBounds.extent );
// Calculate rendering rectangle for the groups content
RectI contentRect( offset + mBarWidth, mBounds.extent - ( mBarWidth + Point2I(1,1) ));
U32 textXOffset = mFloor( (F32)( mBarWidth.x - mProfile->mFont->getHeight() ) / 2 ) + mProfile->mFont->getHeight();
RectI addFieldRect( offset + Point2I( textXOffset, mBarWidth.y + 4 ), Point2I(mBarWidth.x, mBounds.extent.y) );
// Backup Bitmap Modulation
ColorI currColor;
dglGetBitmapModulation( &currColor );
dglSetBitmapModulation( mProfile->mFontColor );
RectI clipRect = dglGetClipRect();
dglSetClipRect( updateRect );
// Draw Caption ( Vertically Centered )
dglDrawText( mProfile->mFont, addFieldRect.point, "Add Field" , &mProfile->mFontColor,9, -90.f );
dglSetClipRect( clipRect );
dglSetBitmapModulation( currColor );
}
void GuiInspectorDynamicGroup::onMouseDown( const GuiEvent &event )
{
Parent::onMouseDown( event );
// Calculate actual world bounds for rendering
RectI worldBounds( mBounds );
// Calculate rendering rectangle for the groups content
RectI contentRect( mBarWidth, mBounds.extent - ( mBarWidth + Point2I(1,1) ));
Point2I localPoint( globalToLocalCoord( event.mousePoint ) );
U32 textXOffset = mFloor( (F32)( mBarWidth.x - mProfile->mFont->getHeight() ) / 2 );
RectI addFieldRect( Point2I( textXOffset, mBarWidth.y + 4 ), Point2I( mBarWidth.x, mBounds.extent.y ) );
if( addFieldRect.pointInRect( localPoint ) )
{
addDynamicField();
}
}
S32 GuiInspectorDynamicGroup::getExpandedHeight()
{
if( mStack != NULL && mStack->size() > 0 )
return mStack->getHeight() + mBarWidth.y + 1;
else
return mBarWidth.y + 60;
}
void GuiInspectorDynamicGroup::addDynamicField()
{
// We can't add a field without a target
if( !mTarget || !mStack )
{
Con::warnf("GuiInspectorDynamicGroup::addDynamicField - no target SimObject to add a dynamic field to.");
return;
}
Con::evaluatef( "%d.%s = \"Default Value\";", mTarget->getId(), "NewDynamicField" );
SimFieldDictionary::Entry* entry = findDynamicFieldInDictionary( "NewDynamicField" );
if( entry == NULL )
{
Con::warnf("GuiInspectorDynamicGroup::addDynamicField - Unable to locate new dynamic field" );
return;
}
GuiInspectorDynamicField *field = findDynamicField( entry->slotName );
if( field != NULL )
{
Con::warnf("GuiInspectorDynamicGroup::addDynamicField - Dynamic Field already exists with name (%s)", entry->slotName );
return;
}
field = new GuiInspectorDynamicField( this, mTarget, entry );
if( field != NULL )
{
field->registerObject();
mChildren.push_back( field );
mStack->addObject( field );
}
animateTo( getExpandedHeight() );
}
ConsoleMethod( GuiInspectorDynamicGroup, addDynamicField, void, 2, 2, "obj.addDynamicField();" )
{
object->addDynamicField();
}
//////////////////////////////////////////////////////////////////////////
// GuiInspectorDynamicField - Child class of GuiInspectorField
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_CONOBJECT(GuiInspectorDynamicField);
GuiInspectorDynamicField::GuiInspectorDynamicField( GuiInspectorGroup* parent, SimObjectPtr<SimObject> target, SimFieldDictionary::Entry* field )
{
if( field != NULL )
mCaption = StringTable->insert( field->slotName );
else
mCaption = StringTable->insert( "" );
mParent = parent;
mTarget = target;
mDynField = field;
mBounds.set(0,0,100,20);
mRenameCtrl = NULL;
}
void GuiInspectorDynamicField::setData( StringTableEntry data )
{
if( mTarget == NULL || mDynField == NULL )
return;
char buf[1024];
const char * newValue = mEdit->getScriptValue();
dStrcpy( buf, newValue ? newValue : "" );
collapseEscape(buf);
mTarget->getFieldDictionary()->setFieldValue(mDynField->slotName, buf);
// Force our edit to update
updateValue( data );
}
StringTableEntry GuiInspectorDynamicField::getData()
{
if( mTarget == NULL || mDynField == NULL )
return "";
return mTarget->getFieldDictionary()->getFieldValue( mDynField->slotName );
}
void GuiInspectorDynamicField::renameField( StringTableEntry newFieldName )
{
if( mTarget == NULL || 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;
}
// Grab our current dynamic field value
StringTableEntry currentValue = getData();
// Create our new field with the value of our old field and the new fields name!
mTarget->setDataField( newFieldName, NULL, currentValue );
// Configure our field to grab data from the new dynamic field
SimFieldDictionary::Entry *newEntry = group->findDynamicFieldInDictionary( newFieldName );
if( newEntry == NULL )
{
Con::warnf("GuiInspectorDynamicField::renameField - Unable to find new field!" );
return;
}
// Set our old fields data to "" (which will effectively erase the field)
mTarget->setDataField( getFieldName(), NULL, "" );
// Assign our dynamic field pointer (where we retrieve field information from) to our new field pointer
mDynField = newEntry;
// Reassign the caption of the field (to match the new field name)
// Note : we use the getFieldName accessor which, since we have changed our field pointer
// will grab the slotName from the new field
mCaption = getFieldName();
// Lastly we need to reassign our Command and AltCommand fields for our value edit control
char szBuffer[512];
dSprintf( szBuffer, 512, "%d.%s = %d.getText();",mTarget->getId(), getFieldName(), mEdit->getId() );
mEdit->setField("AltCommand", szBuffer );
mEdit->setField("Validate", szBuffer );
}
ConsoleMethod( GuiInspectorDynamicField, renameField, void, 3,3, "field.renameField(newDynamicFieldName);" )
{
object->renameField( argv[2] );
}
bool GuiInspectorDynamicField::onAdd()
{
if( !Parent::onAdd() )
return false;
mRenameCtrl = constructRenameControl();
return true;
}
GuiControl* GuiInspectorDynamicField::constructRenameControl()
{
// Create our renaming field
GuiControl* retCtrl = new GuiTextEditCtrl();
// If we couldn't construct the control, bail!
if( retCtrl == NULL )
return retCtrl;
// Let's make it look pretty.
retCtrl->setField( "profile", "GuiInspectorTextEditProfile" );
// Don't forget to register ourselves
char szName[512];
dSprintf( szName, 512, "IE_%s_%d_%s_Rename", retCtrl->getClassName(), mTarget->getId(), getFieldName() );
retCtrl->registerObject( szName );
// Our command will evaluate to :
//
// if( (editCtrl).getText() !$= "" )
// (field).renameField((editCtrl).getText());
//
char szBuffer[512];
dSprintf( szBuffer, 512, "if( %d.getText() !$= \"\" ) %d.renameField(%d.getText());",retCtrl->getId(), getId(), retCtrl->getId() );
dynamic_cast<GuiTextEditCtrl*>(retCtrl)->setText( getFieldName() );
retCtrl->setField("AltCommand", szBuffer );
retCtrl->setField("Validate", szBuffer );
// Calculate Caption Rect (Adjust for 16 pixel wide delete button)
RectI captionRect( Point2I(mBounds.point.x + 16 ,0) , Point2I( mFloor( mBounds.extent.x * (F32)( (F32)GuiInspectorField::smCaptionWidth / 100.0 ) ) - 16 , mBounds.extent.y ) );
RectI deleteRect( Point2I( mBounds.point.x,2), Point2I( 16, mBounds.extent.y - 4));
addObject( retCtrl );
// Resize the edit control to fit in our caption rect (tricksy!)
retCtrl->resize( captionRect.point, captionRect.extent );
// Finally, add a delete button for this field
GuiButtonCtrl * delButt = new GuiBitmapButtonCtrl();
if( delButt != NULL )
{
dSprintf(szBuffer, 512, "%d.%s = \"\";%d.inspect(%d);", mTarget->getId(), getFieldName(), mParent->getContentCtrl()->getId(), mTarget->getId());
#ifdef TGE_RPG_UI /// TGE_RPG_UI
delButt->setField("profile", "GuiBitmapButtonProfile");
StringTableEntry pIconPath = Con::getVariable("$Theme::PathIcons");
delButt->setField("Bitmap", avar("%sinspector_delete",pIconPath));
#else
delButt->setField("Bitmap", "ui/icons/inspector_delete");
#endif
delButt->setField("Text", "X");
delButt->setField("Command", szBuffer);
delButt->registerObject();
delButt->resize( deleteRect.point,deleteRect.extent);
addObject(delButt);
}
return retCtrl;
}
void GuiInspectorDynamicField::resize( const Point2I &newPosition, const Point2I &newExtent )
{
Parent::resize( newPosition, newExtent );
// If we don't have a field rename control, bail!
if( mRenameCtrl == NULL )
return;
// Calculate Caption Rect
RectI captionRect( Point2I(mBounds.point.x + 16 ,0) , Point2I( mFloor( mBounds.extent.x * (F32)( (F32)GuiInspectorField::smCaptionWidth / 100.0 ) ) - 16, mBounds.extent.y ) );
// Resize the edit control to fit in our caption rect (tricksy!)
mRenameCtrl->resize( captionRect.point, captionRect.extent );
}
void GuiInspectorDynamicField::onRender(Point2I offset, const RectI &updateRect)
{
RectI worldRect( offset, mBounds.extent );
// Calculate Caption Rect
RectI captionRect( offset , Point2I( mFloor( mBounds.extent.x * (F32)( (F32)GuiInspectorField::smCaptionWidth / 100.0 ) ), mBounds.extent.y ) );
// Calculate Edit Field Rect
RectI editFieldRect( offset + Point2I( captionRect.extent.x + 1, 0 ) , Point2I( mBounds.extent.x - ( captionRect.extent.x + 5 ) , mBounds.extent.y ) );
// Calculate Y Offset to center vertically the caption
U32 captionYOffset = mFloor( (F32)( captionRect.extent.y - mProfile->mFont->getHeight() ) / 2 );
renderFilledBorder( captionRect, mProfile->mBorderColor, mProfile->mFillColor );
renderFilledBorder( editFieldRect, mProfile->mBorderColor, mProfile->mFillColor );
// Skip directly to GuiControl onRender (so we get child controls rendered, but no caption rendering from GuiInspectorField::onRender)
GuiControl::onRender( offset, updateRect );
}
//////////////////////////////////////////////////////////////////////////
// GuiInspectorDatablockField
// Field construction for datablock types
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_CONOBJECT(GuiInspectorDatablockField);
static S32 QSORT_CALLBACK stringCompare(const void *a,const void *b)
{
StringTableEntry sa = *(StringTableEntry*)a;
StringTableEntry sb = *(StringTableEntry*)b;
return(dStricmp(sb, sa));
}
GuiInspectorDatablockField::GuiInspectorDatablockField( StringTableEntry className )
{
setClassName(className);
};
void GuiInspectorDatablockField::setClassName( StringTableEntry className )
{
// Walk the ACR list and find a matching class if any.
AbstractClassRep *walk = AbstractClassRep::getClassList();
while(walk)
{
if(!dStricmp(walk->getClassName(), className))
{
// Match!
mDesiredClass = walk;
return;
}
walk = walk->getNextClass();
}
// No dice.
Con::warnf("GuiInspectorDatablockField::setClassName - no class '%s' found!", className);
return;
}
GuiControl* GuiInspectorDatablockField::constructEditControl()
{
GuiControl* retCtrl = new GuiPopUpMenuCtrl();
// If we couldn't construct the control, bail!
if( retCtrl == NULL )
return retCtrl;
GuiPopUpMenuCtrl *menu = dynamic_cast<GuiPopUpMenuCtrl*>(retCtrl);
// Let's make it look pretty.
retCtrl->setField( "profile", "InspectorTypeEnumProfile" );
menu->setField("text", getData());
registerEditControl( retCtrl );
// Configure it to update our value when the popup is closed
char szBuffer[512];
dSprintf( szBuffer, 512, "%d.%s = %d.getText();",mTarget->getId(), mField->pFieldname, menu->getId() );
menu->setField("Command", szBuffer );
Vector<StringTableEntry> entries;
SimDataBlockGroup * grp = Sim::getDataBlockGroup();
for(SimDataBlockGroup::iterator i = grp->begin(); i != grp->end(); i++)
{
SimDataBlock * datablock = dynamic_cast<SimDataBlock*>(*i);
// Skip non-datablocks if we somehow encounter them.
if(!datablock)
continue;
// Ok, now we have to figure inheritance info.
if( datablock && datablock->getClassRep()->isClass(mDesiredClass) )
entries.push_back(datablock->getName());
}
// sort the entries
dQsort(entries.address(), entries.size(), sizeof(StringTableEntry), stringCompare);
// add them to our enum
for(U32 j = 0; j < entries.size(); j++)
menu->addEntry(entries[j], 0);
return retCtrl;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -