guiInspector.cpp
Engine/source/gui/editor/guiInspector.cpp
Public Functions
ConsoleDocClass(GuiInspector , "@brief A <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> that allows <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> edit the properties of one or more <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(GuiInspector , addInspect , void , (const char *simObject, bool autoSync) , (true) , "Add the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list of objects being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">inspected.\n</a>" "@param simObject <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the inspection." "@param autoSync Auto sync the values when they change." )
DefineEngineMethod(GuiInspector , apply , void , () , "Force application of inspected object's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">attributes.\n</a>" )
DefineEngineMethod(GuiInspector , findByObject , S32 , (SimObject *obj) , "Returns the <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of an awake inspector that is inspecting the passed object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> one <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exists\n</a>" "@param object <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> find away inspector for." "@return <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of an awake inspector that is inspecting the passed object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> one exists, else <a href="/coding/file/typesx86unix_8h/#typesx86unix_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a> or 0." )
DefineEngineMethod(GuiInspector , getInspectObject , const char * , (S32 index) , (0) , "Returns currently inspected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param index Index of object in inspection list you want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get." "@return object being inspected." )
DefineEngineMethod(GuiInspector , getNumInspectObjects , S32 , () , "Return the number of objects currently being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">inspected.\n</a>" "@return number of objects currently being inspected." )
DefineEngineMethod(GuiInspector , inspect , void , (const char *simObject) , ("") , "Inspect the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param simObject <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> inspect." )
DefineEngineMethod(GuiInspector , refresh , void , () , "Re-inspect the currently selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" )
DefineEngineMethod(GuiInspector , removeInspect , void , (const char *simObject) , "Remove the object from the list of objects being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">inspected.\n</a>" "@param simObject <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> remove from the inspection." )
DefineEngineMethod(GuiInspector , setName , void , (const char *newObjectName) , "Rename the object being inspected (first object in inspect list).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param newObjectName <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> name <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> object being inspected." )
DefineEngineMethod(GuiInspector , setObjectField , void , (const char *fieldname, const char *data) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> named fields <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> on the inspected object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it exists. This triggers all the usual callbacks that would occur <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the field had been changed through the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gui..\n</a>" "@param fieldname Field name on object we are inspecting we want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change." "@param data New <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given field." )
bool
findInspectors(GuiInspector * obj)
Detailed Description
Public Variables
SimObject * sgKeyObj
Public Functions
ConsoleDocClass(GuiInspector , "@brief A <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> that allows <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> edit the properties of one or more <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(GuiInspector , addInspect , void , (const char *simObject, bool autoSync) , (true) , "Add the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list of objects being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">inspected.\n</a>" "@param simObject <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the inspection." "@param autoSync Auto sync the values when they change." )
DefineEngineMethod(GuiInspector , apply , void , () , "Force application of inspected object's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">attributes.\n</a>" )
DefineEngineMethod(GuiInspector , findByObject , S32 , (SimObject *obj) , "Returns the <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of an awake inspector that is inspecting the passed object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> one <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exists\n</a>" "@param object <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> find away inspector for." "@return <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of an awake inspector that is inspecting the passed object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> one exists, else <a href="/coding/file/typesx86unix_8h/#typesx86unix_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a> or 0." )
DefineEngineMethod(GuiInspector , getInspectObject , const char * , (S32 index) , (0) , "Returns currently inspected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param index Index of object in inspection list you want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get." "@return object being inspected." )
DefineEngineMethod(GuiInspector , getNumInspectObjects , S32 , () , "Return the number of objects currently being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">inspected.\n</a>" "@return number of objects currently being inspected." )
DefineEngineMethod(GuiInspector , inspect , void , (const char *simObject) , ("") , "Inspect the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param simObject <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> inspect." )
DefineEngineMethod(GuiInspector , refresh , void , () , "Re-inspect the currently selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" )
DefineEngineMethod(GuiInspector , removeInspect , void , (const char *simObject) , "Remove the object from the list of objects being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">inspected.\n</a>" "@param simObject <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> remove from the inspection." )
DefineEngineMethod(GuiInspector , setName , void , (const char *newObjectName) , "Rename the object being inspected (first object in inspect list).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param newObjectName <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> name <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> object being inspected." )
DefineEngineMethod(GuiInspector , setObjectField , void , (const char *fieldname, const char *data) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> named fields <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> on the inspected object <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it exists. This triggers all the usual callbacks that would occur <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the field had been changed through the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gui..\n</a>" "@param fieldname Field name on object we are inspecting we want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change." "@param data New <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the given field." )
findInspectors(GuiInspector * obj)
IMPLEMENT_CONOBJECT(GuiInspector )
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 "console/engineAPI.h" 25#include "gui/editor/guiInspector.h" 26#include "gui/editor/inspector/field.h" 27#include "gui/editor/inspector/group.h" 28#include "gui/buttons/guiIconButtonCtrl.h" 29#include "gui/editor/inspector/dynamicGroup.h" 30#include "gui/containers/guiScrollCtrl.h" 31#include "gui/editor/inspector/customField.h" 32 33IMPLEMENT_CONOBJECT(GuiInspector); 34 35ConsoleDocClass( GuiInspector, 36 "@brief A control that allows to edit the properties of one or more SimObjects.\n\n" 37 "Editor use only.\n\n" 38 "@internal" 39); 40 41 42//#define DEBUG_SPEW 43 44 45//----------------------------------------------------------------------------- 46 47GuiInspector::GuiInspector() 48 : mDividerPos( 0.35f ), 49 mDividerMargin( 5 ), 50 mOverDivider( false ), 51 mMovingDivider( false ), 52 mHLField( NULL ), 53 mShowCustomFields( true ), 54 mComponentGroupTargetId(-1) 55{ 56 mPadding = 1; 57} 58 59//----------------------------------------------------------------------------- 60 61GuiInspector::~GuiInspector() 62{ 63 clearGroups(); 64} 65 66//----------------------------------------------------------------------------- 67 68void GuiInspector::initPersistFields() 69{ 70 addGroup( "Inspector" ); 71 72 addField( "dividerMargin", TypeS32, Offset( mDividerMargin, GuiInspector ) ); 73 74 addField( "groupFilters", TypeRealString, Offset( mGroupFilters, GuiInspector ), 75 "Specify groups that should be shown or not. Specifying 'shown' implicitly does 'not show' all other groups. Example string: +name -otherName" ); 76 77 addField( "showCustomFields", TypeBool, Offset( mShowCustomFields, GuiInspector ), 78 "If false the custom fields Name, Id, and Source Class will not be shown." ); 79 80 endGroup( "Inspector" ); 81 82 Parent::initPersistFields(); 83} 84 85//----------------------------------------------------------------------------- 86 87void GuiInspector::onRemove() 88{ 89 clearGroups(); 90 Parent::onRemove(); 91} 92 93//----------------------------------------------------------------------------- 94 95void GuiInspector::onDeleteNotify( SimObject *object ) 96{ 97 Parent::onDeleteNotify( object ); 98 99 if( isInspectingObject( object ) ) 100 removeInspectObject( object ); 101} 102 103//----------------------------------------------------------------------------- 104 105void GuiInspector::parentResized(const RectI &oldParentRect, const RectI &newParentRect) 106{ 107 GuiControl *parent = getParent(); 108 if ( parent && dynamic_cast<GuiScrollCtrl*>(parent) != NULL ) 109 { 110 GuiScrollCtrl *scroll = dynamic_cast<GuiScrollCtrl*>(parent); 111 setWidth( ( newParentRect.extent.x - ( scroll->scrollBarThickness() + 4 ) ) ); 112 } 113 else 114 Parent::parentResized(oldParentRect,newParentRect); 115} 116 117//----------------------------------------------------------------------------- 118 119bool GuiInspector::resize( const Point2I &newPosition, const Point2I &newExtent ) 120{ 121 //F32 dividerPerc = (F32)getWidth() / (F32)mDividerPos; 122 123 bool result = Parent::resize( newPosition, newExtent ); 124 125 //mDividerPos = (F32)getWidth() * dividerPerc; 126 127 updateDivider(); 128 129 return result; 130} 131 132//----------------------------------------------------------------------------- 133 134GuiControl* GuiInspector::findHitControl( const Point2I &pt, S32 initialLayer ) 135{ 136 if ( mOverDivider || mMovingDivider ) 137 return this; 138 139 return Parent::findHitControl( pt, initialLayer ); 140} 141 142//----------------------------------------------------------------------------- 143 144void GuiInspector::getCursor( GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent ) 145{ 146 GuiCanvas *pRoot = getRoot(); 147 if( !pRoot ) 148 return; 149 150 S32 desiredCursor = mOverDivider ? PlatformCursorController::curResizeVert : PlatformCursorController::curArrow; 151 152 // Bail if we're already at the desired cursor 153 if ( pRoot->mCursorChanged == desiredCursor ) 154 return; 155 156 PlatformWindow *pWindow = static_cast<GuiCanvas*>(getRoot())->getPlatformWindow(); 157 AssertFatal(pWindow != NULL,"GuiControl without owning platform window! This should not be possible."); 158 PlatformCursorController *pController = pWindow->getCursorController(); 159 AssertFatal(pController != NULL,"PlatformWindow without an owned CursorController!"); 160 161 // Now change the cursor shape 162 pController->popCursor(); 163 pController->pushCursor(desiredCursor); 164 pRoot->mCursorChanged = desiredCursor; 165} 166 167//----------------------------------------------------------------------------- 168 169void GuiInspector::onMouseMove(const GuiEvent &event) 170{ 171 if ( collideDivider( globalToLocalCoord( event.mousePoint ) ) ) 172 mOverDivider = true; 173 else 174 mOverDivider = false; 175} 176 177//----------------------------------------------------------------------------- 178 179void GuiInspector::onMouseDown(const GuiEvent &event) 180{ 181 if ( mOverDivider ) 182 { 183 mMovingDivider = true; 184 } 185} 186 187//----------------------------------------------------------------------------- 188 189void GuiInspector::onMouseUp(const GuiEvent &event) 190{ 191 mMovingDivider = false; 192} 193 194//----------------------------------------------------------------------------- 195 196void GuiInspector::onMouseDragged(const GuiEvent &event) 197{ 198 if ( !mMovingDivider ) 199 return; 200 201 Point2I localPnt = globalToLocalCoord( event.mousePoint ); 202 203 S32 inspectorWidth = getWidth(); 204 205 // Distance from mouse/divider position in local space 206 // to the right edge of the inspector 207 mDividerPos = inspectorWidth - localPnt.x; 208 mDividerPos = mClamp( mDividerPos, 0, inspectorWidth ); 209 210 // Divide that by the inspectorWidth to get a percentage 211 mDividerPos /= inspectorWidth; 212 213 updateDivider(); 214} 215 216//----------------------------------------------------------------------------- 217 218GuiInspectorGroup* GuiInspector::findExistentGroup( StringTableEntry groupName ) 219{ 220 // If we have no groups, it couldn't possibly exist 221 if( mGroups.empty() ) 222 return NULL; 223 224 // Attempt to find it in the group list 225 Vector<GuiInspectorGroup*>::iterator i = mGroups.begin(); 226 227 for( ; i != mGroups.end(); i++ ) 228 { 229 if( dStricmp( (*i)->getGroupName(), groupName ) == 0 ) 230 return *i; 231 } 232 233 return NULL; 234} 235 236S32 GuiInspector::findExistentGroupIndex(StringTableEntry groupName) 237{ 238 // If we have no groups, it couldn't possibly exist 239 if (mGroups.empty()) 240 return -1; 241 242 // Attempt to find it in the group list 243 Vector<GuiInspectorGroup*>::iterator i = mGroups.begin(); 244 245 S32 index = 0; 246 for (; i != mGroups.end(); i++) 247 { 248 if (dStricmp((*i)->getGroupName(), groupName) == 0) 249 return index; 250 251 index++; 252 } 253 254 return -1; 255} 256 257//----------------------------------------------------------------------------- 258 259void GuiInspector::updateFieldValue( StringTableEntry fieldName, StringTableEntry arrayIdx ) 260{ 261 // We don't know which group contains the field of this name, 262 // so ask each group in turn, and break when a group returns true 263 // signifying it contained and updated that field. 264 265 Vector<GuiInspectorGroup*>::iterator groupIter = mGroups.begin(); 266 267 for( ; groupIter != mGroups.end(); groupIter++ ) 268 { 269 if ( (*groupIter)->updateFieldValue( fieldName, arrayIdx ) ) 270 break; 271 } 272} 273 274//----------------------------------------------------------------------------- 275 276void GuiInspector::clearGroups() 277{ 278 #ifdef DEBUG_SPEW 279 Platform::outputDebugString( "[GuiInspector] Clearing %i (%s)", getId(), getName() ); 280 #endif 281 282 // If we have no groups, there's nothing to clear! 283 if( mGroups.empty() ) 284 return; 285 286 mHLField = NULL; 287 288 if( isMethod( "onClear" ) ) 289 Con::executef( this, "onClear" ); 290 291 Vector<GuiInspectorGroup*>::iterator i = mGroups.begin(); 292 293 freeze(true); 294 295 // Delete Groups 296 for( ; i != mGroups.end(); i++ ) 297 { 298 if((*i) && (*i)->isProperlyAdded()) 299 (*i)->deleteObject(); 300 } 301 302 mGroups.clear(); 303 304 freeze(false); 305 updatePanes(); 306} 307 308//----------------------------------------------------------------------------- 309 310bool GuiInspector::isInspectingObject( SimObject* object ) 311{ 312 const U32 numTargets = mTargets.size(); 313 for( U32 i = 0; i < numTargets; ++ i ) 314 if( mTargets[ i ] == object ) 315 return true; 316 317 return false; 318} 319 320//----------------------------------------------------------------------------- 321 322void GuiInspector::inspectObject( SimObject *object ) 323{ 324 if( mTargets.size() > 1 || !isInspectingObject( object ) ) 325 clearInspectObjects(); 326 327 addInspectObject( object ); 328} 329 330//----------------------------------------------------------------------------- 331 332void GuiInspector::clearInspectObjects() 333{ 334 const U32 numTargets = mTargets.size(); 335 for( U32 i = 0; i < numTargets; ++ i ) 336 clearNotify( mTargets[ i ] ); 337 338 clearGroups(); 339 mTargets.clear(); 340} 341 342//----------------------------------------------------------------------------- 343 344void GuiInspector::addInspectObject( SimObject* object, bool autoSync ) 345{ 346 // If we are already inspecting the object, just update the groups. 347 348 if( isInspectingObject( object ) ) 349 { 350 #ifdef DEBUG_SPEW 351 Platform::outputDebugString( "[GuiInspector] Refreshing view of %i:%s (%s)", 352 object->getId(), object->getClassName(), object->getName() ); 353 #endif 354 355 Vector<GuiInspectorGroup*>::iterator i = mGroups.begin(); 356 for ( ; i != mGroups.end(); i++ ) 357 (*i)->updateAllFields(); 358 359 return; 360 } 361 362 #ifdef DEBUG_SPEW 363 Platform::outputDebugString( "[GuiInspector] Adding %i:%s (%s) to inspect set", 364 object->getId(), object->getClassName(), object->getName() ); 365 #endif 366 367 // Give users a chance to customize fields on this object 368 if( object->isMethod("onDefineFieldTypes") ) 369 Con::executef( object, "onDefineFieldTypes" ); 370 371 // Set Target 372 mTargets.push_back( object ); 373 deleteNotify( object ); 374 375 if( autoSync ) 376 refresh(); 377} 378 379//----------------------------------------------------------------------------- 380 381void GuiInspector::removeInspectObject( SimObject* object ) 382{ 383 const U32 numTargets = mTargets.size(); 384 for( U32 i = 0; i < numTargets; ++ i ) 385 if( mTargets[ i ] == object ) 386 { 387 // Delete all inspector data *before* removing the target so that apply calls 388 // triggered by edit controls losing focus will not find the inspect object 389 // gone. 390 391 clearGroups(); 392 393 #ifdef DEBUG_SPEW 394 Platform::outputDebugString( "[GuiInspector] Removing %i:%s (%s) from inspect set", 395 object->getId(), object->getClassName(), object->getName() ); 396 #endif 397 398 mTargets.erase( i ); 399 clearNotify( object ); 400 401 // Refresh the inspector except if the system is going down. 402 403 if( !Sim::isShuttingDown() ) 404 refresh(); 405 406 return; 407 } 408} 409 410//----------------------------------------------------------------------------- 411 412void GuiInspector::setName( StringTableEntry newName ) 413{ 414 if( mTargets.size() != 1 ) 415 return; 416 417 StringTableEntry name = StringTable->insert(newName); 418 419 // Only assign a new name if we provide one 420 mTargets[ 0 ]->assignName(name); 421} 422 423//----------------------------------------------------------------------------- 424 425bool GuiInspector::collideDivider( const Point2I &localPnt ) 426{ 427 RectI divisorRect( getWidth() - getWidth() * mDividerPos - mDividerMargin, 0, mDividerMargin * 2, getHeight() ); 428 429 if ( divisorRect.pointInRect( localPnt ) ) 430 return true; 431 432 return false; 433} 434 435//----------------------------------------------------------------------------- 436 437void GuiInspector::updateDivider() 438{ 439 for ( U32 i = 0; i < mGroups.size(); i++ ) 440 for ( U32 j = 0; j < mGroups[i]->mChildren.size(); j++ ) 441 mGroups[i]->mChildren[j]->updateRects(); 442 443 //setUpdate(); 444} 445 446//----------------------------------------------------------------------------- 447 448void GuiInspector::getDivider( S32 &pos, S32 &margin ) 449{ 450 pos = (F32)getWidth() * mDividerPos; 451 margin = mDividerMargin; 452} 453 454//----------------------------------------------------------------------------- 455 456void GuiInspector::setHighlightField( GuiInspectorField *field ) 457{ 458 if ( mHLField == field ) 459 return; 460 461 if ( mHLField.isValid() ) 462 mHLField->setHLEnabled( false ); 463 mHLField = field; 464 465 // We could have been passed a null field, meaning, set no field highlighted. 466 if ( mHLField.isNull() ) 467 return; 468 469 mHLField->setHLEnabled( true ); 470} 471 472//----------------------------------------------------------------------------- 473 474bool GuiInspector::isGroupFiltered( const char *groupName ) const 475{ 476 // Internal and Ungrouped always filtered, we never show them. 477 if ( dStricmp( groupName, "Internal" ) == 0 || 478 dStricmp( groupName, "Ungrouped" ) == 0 || 479 dStricmp( groupName, "AdvCoordManipulation" ) == 0) 480 return true; 481 482 // Normal case, determine if filtered by looking at the mGroupFilters string. 483 String searchStr; 484 485 // Is this group explicitly show? Does it immediately follow a + char. 486 searchStr = String::ToString( "+%s", groupName ); 487 if ( mGroupFilters.find( searchStr ) != String::NPos ) 488 return false; 489 490 // Were there any other + characters, if so, we are implicitly hidden. 491 if ( mGroupFilters.find( "+" ) != String::NPos ) 492 return true; 493 494 // Is this group explicitly hidden? Does it immediately follow a - char. 495 searchStr = String::ToString( "-%s", groupName ); 496 if ( mGroupFilters.find( searchStr ) != String::NPos ) 497 return true; 498 499 return false; 500} 501 502//----------------------------------------------------------------------------- 503 504bool GuiInspector::isGroupExplicitlyFiltered( const char *groupName ) const 505{ 506 String searchStr; 507 508 searchStr = String::ToString( "-%s", groupName ); 509 510 if ( mGroupFilters.find( searchStr ) != String::NPos ) 511 return true; 512 513 return false; 514} 515 516//----------------------------------------------------------------------------- 517 518void GuiInspector::setObjectField( const char *fieldName, const char *data ) 519{ 520 GuiInspectorField *field; 521 522 for ( S32 i = 0; i < mGroups.size(); i++ ) 523 { 524 field = mGroups[i]->findField( fieldName ); 525 526 if( field ) 527 { 528 field->setData( data ); 529 return; 530 } 531 } 532} 533 534//----------------------------------------------------------------------------- 535 536static SimObject *sgKeyObj = NULL; 537 538bool findInspectors( GuiInspector *obj ) 539{ 540 if ( obj->isAwake() && obj->isInspectingObject( sgKeyObj ) ) 541 return true; 542 543 return false; 544} 545 546//----------------------------------------------------------------------------- 547 548GuiInspector* GuiInspector::findByObject( SimObject *obj ) 549{ 550 sgKeyObj = obj; 551 552 Vector< GuiInspector*> found; 553 Sim::getGuiGroup()->findObjectByCallback( findInspectors, found ); 554 555 if ( found.empty() ) 556 return NULL; 557 558 return found.first(); 559} 560 561//----------------------------------------------------------------------------- 562 563void GuiInspector::refresh() 564{ 565 clearGroups(); 566 567 // Remove any inspect object that happened to have 568 // already been killed. 569 570 for( U32 i = 0; i < mTargets.size(); ++ i ) 571 if( !mTargets[ i ] ) 572 { 573 mTargets.erase( i ); 574 -- i; 575 } 576 577 if( !mTargets.size() ) 578 return; 579 580 // Special group for fields which should appear at the top of the 581 // list outside of a rollout control. 582 583 GuiInspectorGroup *ungroup = NULL; 584 if( mTargets.size() == 1 ) 585 { 586 ungroup = new GuiInspectorGroup( "Ungrouped", this ); 587 ungroup->setHeaderHidden( true ); 588 ungroup->setCanCollapse( false ); 589 590 ungroup->registerObject(); 591 mGroups.push_back( ungroup ); 592 addObject( ungroup ); 593 } 594 595 // Put the 'transform' group first 596 GuiInspectorGroup *transform = new GuiInspectorGroup( "Transform", this ); 597 598 transform->registerObject(); 599 mGroups.push_back(transform); 600 addObject(transform); 601 602 // Always create the 'general' group (for fields without a group) 603 GuiInspectorGroup *general = new GuiInspectorGroup( "General", this ); 604 605 general->registerObject(); 606 mGroups.push_back(general); 607 addObject(general); 608 609 // Create the inspector groups for static fields. 610 611 for( TargetVector::iterator iter = mTargets.begin(); iter != mTargets.end(); ++ iter ) 612 { 613 AbstractClassRep::FieldList &fieldList = ( *iter )->getModifiableFieldList(); 614 615 // Iterate through, identifying the groups and create necessary GuiInspectorGroups 616 for( AbstractClassRep::FieldList::iterator itr = fieldList.begin(); itr != fieldList.end(); itr++ ) 617 { 618 if ( itr->type == AbstractClassRep::StartGroupFieldType ) 619 { 620 GuiInspectorGroup* group = findExistentGroup( itr->pGroupname ); 621 622 if( !group && !isGroupFiltered( itr->pGroupname ) ) 623 { 624 GuiInspectorGroup *newGroup = new GuiInspectorGroup( itr->pGroupname, this ); 625 626 newGroup->registerObject(); 627 if( !newGroup->getNumFields() ) 628 { 629 #ifdef DEBUG_SPEW 630 Platform::outputDebugString( "[GuiInspector] Removing empty group '%s'", 631 newGroup->getCaption().c_str() ); 632 #endif 633 634 // The group ended up having no fields. Remove it. 635 newGroup->deleteObject(); 636 } 637 else 638 { 639 mGroups.push_back(newGroup); 640 addObject(newGroup); 641 } 642 } 643 } 644 } 645 } 646 647 mTargets.first()->onInspect(this); 648 649 // Deal with dynamic fields 650 if ( !isGroupFiltered( "Dynamic Fields" ) ) 651 { 652 GuiInspectorGroup *dynGroup = new GuiInspectorDynamicGroup( "Dynamic Fields", this); 653 654 dynGroup->registerObject(); 655 mGroups.push_back( dynGroup ); 656 addObject( dynGroup ); 657 } 658 659 if( mShowCustomFields && mTargets.size() == 1 ) 660 { 661 SimObject* object = mTargets.first(); 662 663 // Add the SimObjectID field to the ungrouped group. 664 665 GuiInspectorCustomField* field = new GuiInspectorCustomField(); 666 field->init( this, ungroup ); 667 668 if( field->registerObject() ) 669 { 670 ungroup->mChildren.push_back( field ); 671 ungroup->mStack->addObject( field ); 672 673 static StringTableEntry sId = StringTable->insert( "id" ); 674 675 field->setCaption( sId ); 676 field->setData( object->getIdString() ); 677 field->setDoc( "SimObjectId of this object. [Read Only]" ); 678 } 679 else 680 delete field; 681 682 // Add the Source Class field to the ungrouped group. 683 684 field = new GuiInspectorCustomField(); 685 field->init( this, ungroup ); 686 687 if( field->registerObject() ) 688 { 689 ungroup->mChildren.push_back( field ); 690 ungroup->mStack->addObject( field ); 691 692 StringTableEntry sSourceClass = StringTable->insert( "Source Class", true ); 693 field->setCaption( sSourceClass ); 694 field->setData( object->getClassName() ); 695 696 Namespace* ns = object->getClassRep()->getNameSpace(); 697 field->setToolTip( Con::getNamespaceList( ns ) ); 698 699 field->setDoc( "Native class of this object. [Read Only]" ); 700 } 701 else 702 delete field; 703 } 704 705 706 // If the general group is still empty at this point ( or filtered ), kill it. 707 if ( isGroupFiltered( "General" ) || general->mStack->size() == 0 ) 708 { 709 for(S32 i=0; i<mGroups.size(); i++) 710 { 711 if ( mGroups[i] == general ) 712 { 713 mGroups.erase(i); 714 general->deleteObject(); 715 updatePanes(); 716 717 break; 718 } 719 } 720 } 721 722 // If transform turns out to be empty or filtered, remove it 723 if( isGroupFiltered( "Transform" ) || transform->mStack->size() == 0 ) 724 { 725 for(S32 i=0; i<mGroups.size(); i++) 726 { 727 if ( mGroups[i] == transform ) 728 { 729 mGroups.erase(i); 730 transform->deleteObject(); 731 updatePanes(); 732 733 break; 734 } 735 } 736 } 737 738 // If ungrouped is empty or explicitly filtered, remove it. 739 if( ungroup && ( isGroupExplicitlyFiltered( "Ungrouped" ) || ungroup->getNumFields() == 0 ) ) 740 { 741 for(S32 i=0; i<mGroups.size(); i++) 742 { 743 if ( mGroups[i] == ungroup ) 744 { 745 mGroups.erase(i); 746 ungroup->deleteObject(); 747 updatePanes(); 748 749 break; 750 } 751 } 752 } 753 754 // If the object cannot be renamed, deactivate the name field if we have it. 755 756 if( ungroup && getNumInspectObjects() == 1 && !getInspectObject()->isNameChangeAllowed() ) 757 { 758 GuiInspectorField* nameField = ungroup->findField( "name" ); 759 if( nameField ) 760 nameField->setActive( false ); 761 } 762} 763 764//----------------------------------------------------------------------------- 765 766void GuiInspector::sendInspectPreApply() 767{ 768 const U32 numObjects = getNumInspectObjects(); 769 for( U32 i = 0; i < numObjects; ++ i ) 770 getInspectObject( i )->inspectPreApply(); 771} 772 773//----------------------------------------------------------------------------- 774 775void GuiInspector::sendInspectPostApply() 776{ 777 const U32 numObjects = getNumInspectObjects(); 778 for( U32 i = 0; i < numObjects; ++ i ) 779 getInspectObject( i )->inspectPostApply(); 780} 781 782//============================================================================= 783// Console Methods. 784//============================================================================= 785// MARK: ---- Console Methods ---- 786 787//----------------------------------------------------------------------------- 788DefineEngineMethod( GuiInspector, inspect, void, (const char* simObject), (""), 789 "Inspect the given object.\n" 790 "@param simObject Object to inspect.") 791{ 792 SimObject * target = Sim::findObject(simObject); 793 if(!target) 794 { 795 if(dAtoi(simObject) > 0) 796 Con::warnf("%s::inspect(): invalid object: %s", object->getClassName(), simObject); 797 798 object->clearInspectObjects(); 799 return; 800 } 801 802 object->inspectObject(target); 803} 804 805//----------------------------------------------------------------------------- 806 807DefineEngineMethod( GuiInspector, addInspect, void, (const char* simObject, bool autoSync), (true), 808 "Add the object to the list of objects being inspected.\n" 809 "@param simObject Object to add to the inspection." 810 "@param autoSync Auto sync the values when they change.") 811{ 812 SimObject* obj; 813 if( !Sim::findObject( simObject, obj ) ) 814 { 815 Con::errorf( "%s::addInspect(): invalid object: %s", object->getClassName(), simObject ); 816 return; 817 } 818 819 object->addInspectObject( obj, autoSync ); 820} 821 822//----------------------------------------------------------------------------- 823 824DefineEngineMethod( GuiInspector, removeInspect, void, (const char* simObject), , 825 "Remove the object from the list of objects being inspected.\n" 826 "@param simObject Object to remove from the inspection.") 827{ 828 SimObject* obj; 829 if( !Sim::findObject( simObject, obj ) ) 830 { 831 Con::errorf( "%s::removeInspect(): invalid object: %s", object->getClassName(), simObject ); 832 return; 833 } 834 835 object->removeInspectObject( obj ); 836} 837 838//----------------------------------------------------------------------------- 839 840DefineEngineMethod( GuiInspector, refresh, void, (), , 841 "Re-inspect the currently selected object.\n") 842{ 843 if ( object->getNumInspectObjects() == 0 ) 844 return; 845 846 SimObject *target = object->getInspectObject(); 847 if ( target ) 848 object->inspectObject( target ); 849} 850 851//----------------------------------------------------------------------------- 852 853DefineEngineMethod( GuiInspector, getInspectObject, const char*, (S32 index), (0), 854 "Returns currently inspected object.\n" 855 "@param index Index of object in inspection list you want to get." 856 "@return object being inspected.") 857{ 858 859 if( index < 0 || index >= object->getNumInspectObjects() ) 860 { 861 Con::errorf( "GuiInspector::getInspectObject() - index out of range: %i", index ); 862 return ""; 863 } 864 865 return object->getInspectObject( index )->getIdString(); 866} 867 868//----------------------------------------------------------------------------- 869 870DefineEngineMethod( GuiInspector, getNumInspectObjects, S32, (), , 871 "Return the number of objects currently being inspected.\n" 872 "@return number of objects currently being inspected.") 873{ 874 return object->getNumInspectObjects(); 875} 876 877//----------------------------------------------------------------------------- 878 879DefineEngineMethod( GuiInspector, setName, void, (const char* newObjectName), , 880 "Rename the object being inspected (first object in inspect list).\n" 881 "@param newObjectName new name for object being inspected.") 882{ 883 object->setName(newObjectName); 884} 885 886//----------------------------------------------------------------------------- 887 888DefineEngineMethod( GuiInspector, apply, void, (), , 889 "Force application of inspected object's attributes.\n") 890{ 891 object->sendInspectPostApply(); 892} 893 894//----------------------------------------------------------------------------- 895 896DefineEngineMethod( GuiInspector, setObjectField, void, (const char* fieldname, const char* data ), , 897 "Set a named fields value on the inspected object if it exists. This triggers all the usual callbacks that would occur if the field had been changed through the gui..\n" 898 "@param fieldname Field name on object we are inspecting we want to change." 899 "@param data New Value for the given field.") 900{ 901 object->setObjectField( fieldname, data ); 902} 903 904//----------------------------------------------------------------------------- 905 906DefineEngineMethod( GuiInspector, findByObject, S32, (SimObject* obj), , 907 "Returns the id of an awake inspector that is inspecting the passed object if one exists\n" 908 "@param object Object to find away inspector for." 909 "@return id of an awake inspector that is inspecting the passed object if one exists, else NULL or 0.") 910{ 911 if ( !obj) 912 return NULL; 913 914 SimObject *inspector = GuiInspector::findByObject(obj); 915 916 if ( !inspector ) 917 return NULL; 918 919 return inspector->getId(); 920} 921