mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-11 22:54:34 +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
79
Engine/source/gui/editor/editorFunctions.cpp
Normal file
79
Engine/source/gui/editor/editorFunctions.cpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/editorFunctions.h"
|
||||
|
||||
#include "console/simObject.h"
|
||||
|
||||
|
||||
bool validateObjectName( const char *data, const SimObject *object )
|
||||
{
|
||||
if( !data || !data[ 0 ] )
|
||||
return true;
|
||||
|
||||
bool isValidId = true;
|
||||
if( !dIsalpha( data[ 0 ] ) && data[ 0 ] != '_' )
|
||||
isValidId = false;
|
||||
else
|
||||
{
|
||||
for( U32 i = 1; data[ i ] != '\0'; ++ i )
|
||||
{
|
||||
if( !dIsalnum( data[ i ] ) && data[ i ] != '_' )
|
||||
{
|
||||
isValidId = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !isValidId )
|
||||
{
|
||||
Platform::AlertOK( "Invalid Object Name", avar( "'%s' is not a valid "
|
||||
"object name. Please choose a name that begins with a letter or "
|
||||
"underscore and is otherwise comprised exclusively of letters, "
|
||||
"digits, and/or underscores.", data ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
SimObject *pTemp = NULL;
|
||||
if ( Sim::findObject( data, pTemp ) && pTemp != object )
|
||||
{
|
||||
const char* filename = pTemp->getFilename();
|
||||
if ( !filename || !filename[0] )
|
||||
filename = "an unknown file";
|
||||
|
||||
Platform::AlertOK( "Invalid Object Name", avar( "Object names must be unique, "
|
||||
"and there is an existing %s object with the name '%s' (defined in %s). "
|
||||
"Please choose another name.", pTemp->getClassName(), data, filename ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( AbstractClassRep::findClassRep( data ) )
|
||||
{
|
||||
Platform::AlertOK( "Invalid Object Name", avar( "'%s' is the name of an "
|
||||
"existing TorqueScript class. Please choose another name.", data ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
33
Engine/source/gui/editor/editorFunctions.h
Normal file
33
Engine/source/gui/editor/editorFunctions.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _EDITORFUNCTIONS_H_
|
||||
#define _EDITORFUNCTIONS_H_
|
||||
|
||||
class SimObject;
|
||||
|
||||
// Returns true if the passed name can be assigned to the passed object.
|
||||
// This is true if that name is not already in use and it is a valid identifier,
|
||||
// ( starts with a alpha character ).
|
||||
bool validateObjectName( const char *name, const SimObject *object );
|
||||
|
||||
#endif // _EDITORFUNCTIONS_H_
|
||||
705
Engine/source/gui/editor/guiDebugger.cpp
Normal file
705
Engine/source/gui/editor/guiDebugger.cpp
Normal file
|
|
@ -0,0 +1,705 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/guiDebugger.h"
|
||||
|
||||
#include "gui/core/guiCanvas.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "core/volume.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT(DbgFileView);
|
||||
|
||||
ConsoleDocClass( DbgFileView,
|
||||
"@brief Remnant from ancient script debugger (TGE days?)\n\n"
|
||||
"Possibly useful for an editor tooltip.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
static const char* itoa(S32 i)
|
||||
{
|
||||
static char buf[32];
|
||||
dSprintf(buf, sizeof(buf), "%d", i);
|
||||
return buf;
|
||||
}
|
||||
|
||||
DbgFileView::~DbgFileView()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
DbgFileView::DbgFileView()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mFileView);
|
||||
|
||||
mFileName = NULL;
|
||||
mPCFileName = NULL;
|
||||
mPCCurrentLine = -1;
|
||||
|
||||
mBlockStart = -1;
|
||||
mBlockEnd = -1;
|
||||
|
||||
mFindString[0] = '\0';
|
||||
mFindLineNumber = -1;
|
||||
|
||||
mSize.set(1, 0);
|
||||
}
|
||||
|
||||
ConsoleMethod(DbgFileView, setCurrentLine, void, 4, 4, "(int line, bool selected)"
|
||||
"Set the current highlighted line.")
|
||||
{
|
||||
object->setCurrentLine(dAtoi(argv[2]), dAtob(argv[3]));
|
||||
}
|
||||
|
||||
ConsoleMethod(DbgFileView, getCurrentLine, const char *, 2, 2, "()"
|
||||
"Get the currently executing file and line, if any.\n\n"
|
||||
"@returns A string containing the file, a tab, and then the line number."
|
||||
" Use getField() with this.")
|
||||
{
|
||||
S32 lineNum;
|
||||
const char *file = object->getCurrentLine(lineNum);
|
||||
char* ret = Con::getReturnBuffer(256);
|
||||
dSprintf(ret, sizeof(ret), "%s\t%d", file, lineNum);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ConsoleMethod(DbgFileView, open, bool, 3, 3, "(string filename)"
|
||||
"Open a file for viewing.\n\n"
|
||||
"@note This loads the file from the local system.")
|
||||
{
|
||||
return object->openFile(argv[2]);
|
||||
}
|
||||
|
||||
ConsoleMethod(DbgFileView, clearBreakPositions, void, 2, 2, "()"
|
||||
"Clear all break points in the current file.")
|
||||
{
|
||||
object->clearBreakPositions();
|
||||
}
|
||||
|
||||
ConsoleMethod(DbgFileView, setBreakPosition, void, 3, 3, "(int line)"
|
||||
"Set a breakpoint at the specified line.")
|
||||
{
|
||||
object->setBreakPosition(dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
ConsoleMethod(DbgFileView, setBreak, void, 3, 3, "(int line)"
|
||||
"Set a breakpoint at the specified line.")
|
||||
{
|
||||
object->setBreakPointStatus(dAtoi(argv[2]), true);
|
||||
}
|
||||
|
||||
ConsoleMethod(DbgFileView, removeBreak, void, 3, 3, "(int line)"
|
||||
"Remove a breakpoint from the specified line.")
|
||||
{
|
||||
object->setBreakPointStatus(dAtoi(argv[2]), false);
|
||||
}
|
||||
|
||||
ConsoleMethod(DbgFileView, findString, bool, 3, 3, "(string findThis)"
|
||||
"Find the specified string in the currently viewed file and "
|
||||
"scroll it into view.")
|
||||
{
|
||||
return object->findString(argv[2]);
|
||||
}
|
||||
|
||||
//this value is the offset used in the ::onRender() method...
|
||||
static S32 gFileXOffset = 44;
|
||||
|
||||
void DbgFileView::AdjustCellSize()
|
||||
{
|
||||
if (! bool(mFont))
|
||||
return;
|
||||
S32 maxWidth = 1;
|
||||
for (U32 i = 0; i < mFileView.size(); i++)
|
||||
{
|
||||
S32 cellWidth = gFileXOffset + mFont->getStrWidth((const UTF8 *)mFileView[i].text);
|
||||
maxWidth = getMax(maxWidth, cellWidth);
|
||||
}
|
||||
|
||||
mCellSize.set(maxWidth, mFont->getHeight() + 2);
|
||||
setSize(mSize);
|
||||
}
|
||||
|
||||
bool DbgFileView::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
|
||||
//clear the mouse over var
|
||||
mMouseOverVariable[0] = '\0';
|
||||
mbMouseDragging = false;
|
||||
|
||||
//adjust the cellwidth to the maximum line length
|
||||
AdjustCellSize();
|
||||
mSize.set(1, mFileView.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DbgFileView::addLine(const char *string, U32 strLen)
|
||||
{
|
||||
// first compute the size
|
||||
U32 size = 1; // for null
|
||||
for(U32 i = 0; i < strLen; i++)
|
||||
{
|
||||
if(string[i] == '\t')
|
||||
size += 3;
|
||||
else if(string[i] != '\r')
|
||||
size++;
|
||||
}
|
||||
FileLine fl;
|
||||
fl.breakPosition = false;
|
||||
fl.breakOnLine = false;
|
||||
if(size)
|
||||
{
|
||||
fl.text = (char *) dMalloc(size);
|
||||
|
||||
U32 dstIndex = 0;
|
||||
for(U32 i = 0; i < strLen; i++)
|
||||
{
|
||||
if(string[i] == '\t')
|
||||
{
|
||||
fl.text[dstIndex] = ' ';
|
||||
fl.text[dstIndex + 1] = ' ';
|
||||
fl.text[dstIndex + 2] = ' ';
|
||||
dstIndex += 3;
|
||||
}
|
||||
else if(string[i] != '\r')
|
||||
fl.text[dstIndex++] = string[i];
|
||||
}
|
||||
fl.text[dstIndex] = 0;
|
||||
}
|
||||
else
|
||||
fl.text = NULL;
|
||||
mFileView.push_back(fl);
|
||||
}
|
||||
|
||||
void DbgFileView::clear()
|
||||
{
|
||||
for(Vector<FileLine>::iterator i = mFileView.begin(); i != mFileView.end(); i++)
|
||||
dFree(i->text);
|
||||
mFileView.clear();
|
||||
}
|
||||
|
||||
bool DbgFileView::findString(const char *text)
|
||||
{
|
||||
//make sure we have a valid string to find
|
||||
if (!text || !text[0])
|
||||
return false;
|
||||
|
||||
//see which line we start searching from
|
||||
S32 curLine = 0;
|
||||
bool searchAgain = false;
|
||||
if (mFindLineNumber >= 0 && !dStricmp(mFindString, text))
|
||||
{
|
||||
searchAgain = true;
|
||||
curLine = mFindLineNumber;
|
||||
}
|
||||
else
|
||||
mFindLineNumber = -1;
|
||||
|
||||
//copy the search text
|
||||
dStrncpy(mFindString, text, 255);
|
||||
S32 length = dStrlen(mFindString);
|
||||
|
||||
//loop through looking for the next instance
|
||||
while (curLine < mFileView.size())
|
||||
{
|
||||
char *curText;
|
||||
if (curLine == mFindLineNumber && mBlockStart >= 0)
|
||||
curText = &mFileView[curLine].text[mBlockStart + 1];
|
||||
else
|
||||
curText = &mFileView[curLine].text[0];
|
||||
|
||||
//search for the string (the hard way... - apparently dStrupr is broken...
|
||||
char *found = NULL;
|
||||
char *curTextPtr = curText;
|
||||
while (*curTextPtr != '\0')
|
||||
{
|
||||
if (!dStrnicmp(mFindString, curTextPtr, length))
|
||||
{
|
||||
found = curTextPtr;
|
||||
break;
|
||||
}
|
||||
else
|
||||
curTextPtr++;
|
||||
}
|
||||
|
||||
//did we find it?
|
||||
if (found)
|
||||
{
|
||||
//scroll first
|
||||
mFindLineNumber = curLine;
|
||||
scrollToLine(mFindLineNumber + 1);
|
||||
|
||||
//then hilite
|
||||
mBlockStart = (S32)(found - &mFileView[curLine].text[0]);
|
||||
mBlockEnd = mBlockStart + length;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
curLine++;
|
||||
}
|
||||
|
||||
//didn't find anything - reset the vars for the next search
|
||||
mBlockStart = -1;
|
||||
mBlockEnd = -1;
|
||||
mFindLineNumber = -1;
|
||||
|
||||
setSelectedCell(Point2I(-1, -1));
|
||||
return false;
|
||||
}
|
||||
|
||||
void DbgFileView::setCurrentLine(S32 lineNumber, bool setCurrentLine)
|
||||
{
|
||||
//update the line number
|
||||
if (setCurrentLine)
|
||||
{
|
||||
mPCFileName = mFileName;
|
||||
mPCCurrentLine = lineNumber;
|
||||
mBlockStart = -1;
|
||||
mBlockEnd = -1;
|
||||
if (lineNumber >= 0)
|
||||
scrollToLine(mPCCurrentLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollToLine(lineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
const char* DbgFileView::getCurrentLine(S32 &lineNumber)
|
||||
{
|
||||
lineNumber = mPCCurrentLine;
|
||||
return mPCFileName;
|
||||
}
|
||||
|
||||
bool DbgFileView::openFile(const char *fileName)
|
||||
{
|
||||
if ((! fileName) || (! fileName[0]))
|
||||
return false;
|
||||
|
||||
StringTableEntry newFile = StringTable->insert(fileName);
|
||||
if (mFileName == newFile)
|
||||
return true;
|
||||
|
||||
void *data = NULL;
|
||||
U32 dataSize = 0;
|
||||
Torque::FS::ReadFile(fileName, data, dataSize, true);
|
||||
if(data == NULL)
|
||||
{
|
||||
Con::printf("DbgFileView: unable to open file %s.", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
//copy the file name
|
||||
mFileName = newFile;
|
||||
|
||||
//clear the old mFileView
|
||||
clear();
|
||||
setSize(Point2I(1, 0));
|
||||
|
||||
//begin reading and parsing at each '\n'
|
||||
char *parsePtr = (char *)data;
|
||||
for(;;) {
|
||||
char *tempPtr = dStrchr(parsePtr, '\n');
|
||||
if(tempPtr)
|
||||
addLine(parsePtr, tempPtr - parsePtr);
|
||||
else if(parsePtr[0])
|
||||
addLine(parsePtr, dStrlen(parsePtr));
|
||||
if(!tempPtr)
|
||||
break;
|
||||
parsePtr = tempPtr + 1;
|
||||
}
|
||||
//delete the buffer
|
||||
delete [] static_cast<char*>(data);
|
||||
|
||||
//set the file size
|
||||
AdjustCellSize();
|
||||
setSize(Point2I(1, mFileView.size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DbgFileView::scrollToLine(S32 lineNumber)
|
||||
{
|
||||
GuiControl *parent = getParent();
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
S32 yOffset = (lineNumber - 1) * mCellSize.y;
|
||||
|
||||
//see if the line is already visible
|
||||
if (! (yOffset + getPosition().y >= 0 && yOffset + getPosition().y < parent->getHeight() - mCellSize.y))
|
||||
{
|
||||
//reposition the control
|
||||
S32 newYOffset = getMin(0, getMax(parent->getHeight() - getHeight(), (mCellSize.y * 4) - yOffset));
|
||||
setPosition(Point2I(getPosition().x, newYOffset));
|
||||
}
|
||||
|
||||
//hilite the line
|
||||
cellSelected(Point2I(0, lineNumber - 1));
|
||||
}
|
||||
|
||||
S32 DbgFileView::findMouseOverChar(const char *text, S32 stringPosition)
|
||||
{
|
||||
static char tempBuf[512];
|
||||
char *bufPtr = &tempBuf[1];
|
||||
|
||||
// Handle the empty string correctly.
|
||||
if (text[0] == '\0') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copy the line's text into the scratch buffer.
|
||||
dStrncpy(tempBuf, text, 512);
|
||||
|
||||
// Make sure we have a null terminator.
|
||||
tempBuf[511] = '\0';
|
||||
|
||||
// Loop over the characters...
|
||||
bool found = false;
|
||||
bool finished = false;
|
||||
do {
|
||||
// Note the current character, then replace it with EOL.
|
||||
char c = *bufPtr;
|
||||
*bufPtr = '\0';
|
||||
// Is the resulting string long enough to include the current
|
||||
// mouse position?
|
||||
if ((S32)mFont->getStrWidth((const UTF8 *)tempBuf) > stringPosition) {
|
||||
// Yep.
|
||||
// Restore the character.
|
||||
*bufPtr = c;
|
||||
// Set bufPtr to point to the char under the mouse.
|
||||
bufPtr--;
|
||||
// Bail.
|
||||
found = true;
|
||||
finished = true;
|
||||
}
|
||||
else {
|
||||
// Nope.
|
||||
// Restore the character.
|
||||
*bufPtr = c;
|
||||
// Move on to the next character.
|
||||
bufPtr++;
|
||||
// Bail if EOL.
|
||||
if (*bufPtr == '\0') finished = true;
|
||||
}
|
||||
} while (!finished);
|
||||
|
||||
// Did we find a character under the mouse?
|
||||
if (found) {
|
||||
// If so, return its position.
|
||||
return bufPtr - tempBuf;
|
||||
}
|
||||
// If not, return -1.
|
||||
else return -1;
|
||||
}
|
||||
|
||||
bool DbgFileView::findMouseOverVariable()
|
||||
{
|
||||
GuiCanvas *root = getRoot();
|
||||
AssertFatal(root, "Unable to get the root Canvas.");
|
||||
|
||||
Point2I curMouse = root->getCursorPos();
|
||||
Point2I pt = globalToLocalCoord(curMouse);
|
||||
|
||||
//find out which cell was hit
|
||||
Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
|
||||
if(cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
S32 stringPosition = pt.x - gFileXOffset;
|
||||
char tempBuf[256], *varNamePtr = &tempBuf[1];
|
||||
dStrcpy(tempBuf, mFileView[cell.y].text);
|
||||
|
||||
//find the current mouse over char
|
||||
S32 charNum = findMouseOverChar(mFileView[cell.y].text, stringPosition);
|
||||
if (charNum >= 0)
|
||||
{
|
||||
varNamePtr = &tempBuf[charNum];
|
||||
}
|
||||
else
|
||||
{
|
||||
mMouseOverVariable[0] = '\0';
|
||||
mMouseOverValue[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
//now make sure we can go from the current cursor mPosition to the beginning of a var name
|
||||
bool found = false;
|
||||
while (varNamePtr >= &tempBuf[0])
|
||||
{
|
||||
if (*varNamePtr == '%' || *varNamePtr == '$')
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
else if ((dToupper(*varNamePtr) >= 'A' && dToupper(*varNamePtr) <= 'Z') ||
|
||||
(*varNamePtr >= '0' && *varNamePtr <= '9') || *varNamePtr == '_' || *varNamePtr == ':')
|
||||
{
|
||||
varNamePtr--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//mouse wasn't over a possible variable name
|
||||
if (! found)
|
||||
{
|
||||
mMouseOverVariable[0] = '\0';
|
||||
mMouseOverValue[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
//set the var char start positions
|
||||
mMouseVarStart = varNamePtr - tempBuf;
|
||||
|
||||
//now copy the (possible) var name into the buf
|
||||
char *tempPtr = &mMouseOverVariable[0];
|
||||
|
||||
//copy the leading '%' or '$'
|
||||
*tempPtr++ = *varNamePtr++;
|
||||
|
||||
//now copy letters and numbers until the end of the name
|
||||
while ((dToupper(*varNamePtr) >= 'A' && dToupper(*varNamePtr) <= 'Z') ||
|
||||
(*varNamePtr >= '0' && *varNamePtr <= '9') || *varNamePtr == '_' || *varNamePtr == ':')
|
||||
{
|
||||
*tempPtr++ = *varNamePtr++;
|
||||
}
|
||||
*tempPtr = '\0';
|
||||
|
||||
//set the var char end positions
|
||||
mMouseVarEnd = varNamePtr - tempBuf;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DbgFileView::clearBreakPositions()
|
||||
{
|
||||
for(Vector<FileLine>::iterator i = mFileView.begin(); i != mFileView.end(); i++)
|
||||
{
|
||||
i->breakPosition = false;
|
||||
i->breakOnLine = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DbgFileView::setBreakPosition(U32 line)
|
||||
{
|
||||
if(line > mFileView.size())
|
||||
return;
|
||||
mFileView[line-1].breakPosition = true;
|
||||
}
|
||||
|
||||
void DbgFileView::setBreakPointStatus(U32 line, bool set)
|
||||
{
|
||||
if(line > mFileView.size())
|
||||
return;
|
||||
mFileView[line-1].breakOnLine = set;
|
||||
}
|
||||
|
||||
void DbgFileView::onPreRender()
|
||||
{
|
||||
setUpdate();
|
||||
char oldVar[256];
|
||||
dStrcpy(oldVar, mMouseOverVariable);
|
||||
bool found = findMouseOverVariable();
|
||||
if (found && mPCCurrentLine >= 0)
|
||||
{
|
||||
//send the query only when the var changes
|
||||
if (dStricmp(oldVar, mMouseOverVariable))
|
||||
Con::executef("DbgSetCursorWatch", mMouseOverVariable);
|
||||
}
|
||||
else
|
||||
Con::executef("DbgSetCursorWatch", "");
|
||||
}
|
||||
|
||||
void DbgFileView::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
if (! mActive)
|
||||
{
|
||||
Parent::onMouseDown(event);
|
||||
return;
|
||||
}
|
||||
|
||||
Point2I pt = globalToLocalCoord(event.mousePoint);
|
||||
bool doubleClick = (event.mouseClickCount > 1);
|
||||
|
||||
//find out which cell was hit
|
||||
Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
|
||||
if(cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
//if we clicked on the breakpoint mark
|
||||
if (pt.x >= 0 && pt.x <= 12)
|
||||
{
|
||||
//toggle the break point
|
||||
if (mFileView[cell.y].breakPosition)
|
||||
{
|
||||
if (mFileView[cell.y].breakOnLine)
|
||||
Con::executef(this, "onRemoveBreakPoint", itoa(cell.y + 1));
|
||||
else
|
||||
Con::executef(this, "onSetBreakPoint", itoa(cell.y + 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Point2I prevSelected = mSelectedCell;
|
||||
Parent::onMouseDown(event);
|
||||
mBlockStart= -1;
|
||||
mBlockEnd = -1;
|
||||
|
||||
//open the file view
|
||||
if (mSelectedCell.y == prevSelected.y && doubleClick && mMouseOverVariable[0])
|
||||
{
|
||||
Con::executef(this, "onSetWatch", mMouseOverVariable);
|
||||
mBlockStart = mMouseVarStart;
|
||||
mBlockEnd = mMouseVarEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 stringPosition = pt.x - gFileXOffset;
|
||||
|
||||
//find which character we're over
|
||||
S32 charNum = findMouseOverChar(mFileView[mSelectedCell.y].text, stringPosition);
|
||||
if (charNum >= 0)
|
||||
{
|
||||
//lock the mouse
|
||||
mouseLock();
|
||||
setFirstResponder();
|
||||
|
||||
//set the block hilite start and end
|
||||
mbMouseDragging = true;
|
||||
mMouseDownChar = charNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Parent::onMouseDown(event);
|
||||
}
|
||||
}
|
||||
|
||||
void DbgFileView::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
if (mbMouseDragging)
|
||||
{
|
||||
Point2I pt = globalToLocalCoord(event.mousePoint);
|
||||
S32 stringPosition = pt.x - gFileXOffset;
|
||||
|
||||
//find which character we're over
|
||||
S32 charNum = findMouseOverChar(mFileView[mSelectedCell.y].text, stringPosition);
|
||||
if (charNum >= 0)
|
||||
{
|
||||
if (charNum < mMouseDownChar)
|
||||
{
|
||||
|
||||
mBlockEnd = mMouseDownChar + 1;
|
||||
mBlockStart = charNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
mBlockEnd = charNum + 1;
|
||||
mBlockStart = mMouseDownChar;
|
||||
}
|
||||
}
|
||||
|
||||
//otherwise, the cursor is past the end of the string
|
||||
else
|
||||
{
|
||||
mBlockStart = mMouseDownChar;
|
||||
mBlockEnd = dStrlen(mFileView[mSelectedCell.y].text) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DbgFileView::onMouseUp(const GuiEvent &)
|
||||
{
|
||||
//unlock the mouse
|
||||
mouseUnlock();
|
||||
|
||||
mbMouseDragging = false;
|
||||
}
|
||||
|
||||
void DbgFileView::onRenderCell(Point2I offset, Point2I cell, bool selected, bool)
|
||||
{
|
||||
Point2I cellOffset = offset;
|
||||
cellOffset.x += 4;
|
||||
|
||||
//draw the break point marks
|
||||
if (mFileView[cell.y].breakOnLine)
|
||||
{
|
||||
GFX->getDrawUtil()->setBitmapModulation(mProfile->mFontColorHL);
|
||||
GFX->getDrawUtil()->drawText(mFont, cellOffset, "#");
|
||||
}
|
||||
else if (mFileView[cell.y].breakPosition)
|
||||
{
|
||||
GFX->getDrawUtil()->setBitmapModulation(mProfile->mFontColor);
|
||||
GFX->getDrawUtil()->drawText(mFont, cellOffset, "-");
|
||||
}
|
||||
cellOffset.x += 8;
|
||||
|
||||
//draw in the "current line" indicator
|
||||
if (mFileName == mPCFileName && (cell.y + 1 == mPCCurrentLine))
|
||||
{
|
||||
GFX->getDrawUtil()->setBitmapModulation(mProfile->mFontColorHL);
|
||||
GFX->getDrawUtil()->drawText(mFont, cellOffset, "=>");
|
||||
}
|
||||
|
||||
//by this time, the cellOffset has been incremented by 44 - the value of gFileXOffset
|
||||
cellOffset.x += 32;
|
||||
|
||||
//hilite the line if selected
|
||||
if (selected)
|
||||
{
|
||||
if (mBlockStart == -1)
|
||||
{
|
||||
GFX->getDrawUtil()->drawRectFill(RectI(cellOffset.x - 2, cellOffset.y - 3,
|
||||
mCellSize.x + 4, mCellSize.y + 6), mProfile->mFillColorHL);
|
||||
}
|
||||
else if (mBlockStart >= 0 && mBlockEnd > mBlockStart && mBlockEnd <= S32(dStrlen(mFileView[cell.y].text) + 1))
|
||||
{
|
||||
S32 startPos, endPos;
|
||||
char tempBuf[256];
|
||||
dStrcpy(tempBuf, mFileView[cell.y].text);
|
||||
|
||||
//get the end coord
|
||||
tempBuf[mBlockEnd] = '\0';
|
||||
endPos = mFont->getStrWidth((const UTF8 *)tempBuf);
|
||||
|
||||
//get the start coord
|
||||
tempBuf[mBlockStart] = '\0';
|
||||
startPos = mFont->getStrWidth((const UTF8 *)tempBuf);
|
||||
|
||||
//draw the hilite
|
||||
GFX->getDrawUtil()->drawRectFill(RectI(cellOffset.x + startPos, cellOffset.y - 3, endPos - startPos + 2, mCellSize.y + 6), mProfile->mFillColorHL);
|
||||
}
|
||||
}
|
||||
|
||||
//draw the line of text
|
||||
GFX->getDrawUtil()->setBitmapModulation(mFileView[cell.y].breakOnLine ? mProfile->mFontColorHL : mProfile->mFontColor);
|
||||
GFX->getDrawUtil()->drawText(mFont, cellOffset, mFileView[cell.y].text);
|
||||
}
|
||||
101
Engine/source/gui/editor/guiDebugger.h
Normal file
101
Engine/source/gui/editor/guiDebugger.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIDEBUGGER_H_
|
||||
#define _GUIDEBUGGER_H_
|
||||
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#include "gui/core/guiArrayCtrl.h"
|
||||
#endif
|
||||
|
||||
class DbgFileView : public GuiArrayCtrl
|
||||
{
|
||||
private:
|
||||
|
||||
typedef GuiArrayCtrl Parent;
|
||||
|
||||
struct FileLine
|
||||
{
|
||||
bool breakPosition;
|
||||
bool breakOnLine;
|
||||
char *text;
|
||||
};
|
||||
|
||||
Vector<FileLine> mFileView;
|
||||
|
||||
StringTableEntry mFileName;
|
||||
|
||||
void AdjustCellSize();
|
||||
|
||||
//used to display the program counter
|
||||
StringTableEntry mPCFileName;
|
||||
S32 mPCCurrentLine;
|
||||
|
||||
//vars used to highlight the selected line segment for copying
|
||||
bool mbMouseDragging;
|
||||
S32 mMouseDownChar;
|
||||
S32 mBlockStart;
|
||||
S32 mBlockEnd;
|
||||
|
||||
char mMouseOverVariable[256];
|
||||
char mMouseOverValue[256];
|
||||
S32 findMouseOverChar(const char *text, S32 stringPosition);
|
||||
bool findMouseOverVariable();
|
||||
S32 mMouseVarStart;
|
||||
S32 mMouseVarEnd;
|
||||
|
||||
//find vars
|
||||
char mFindString[256];
|
||||
S32 mFindLineNumber;
|
||||
|
||||
public:
|
||||
|
||||
DbgFileView();
|
||||
~DbgFileView();
|
||||
|
||||
DECLARE_CONOBJECT(DbgFileView);
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
|
||||
bool onWake();
|
||||
|
||||
void clear();
|
||||
void clearBreakPositions();
|
||||
|
||||
void setCurrentLine(S32 lineNumber, bool setCurrentLine);
|
||||
const char *getCurrentLine(S32 &lineNumber);
|
||||
bool openFile(const char *fileName);
|
||||
void scrollToLine(S32 lineNumber);
|
||||
void setBreakPointStatus(U32 lineNumber, bool value);
|
||||
void setBreakPosition(U32 line);
|
||||
void addLine(const char *text, U32 textLen);
|
||||
|
||||
bool findString(const char *text);
|
||||
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
|
||||
void onPreRender();
|
||||
void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
|
||||
};
|
||||
|
||||
#endif //_GUI_DEBUGGER_H
|
||||
113
Engine/source/gui/editor/guiEaseViewCtrl.cpp
Normal file
113
Engine/source/gui/editor/guiEaseViewCtrl.cpp
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/guiEaseViewCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "math/mMath.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT( GuiEaseViewCtrl );
|
||||
|
||||
ConsoleDocClass( GuiEaseViewCtrl,
|
||||
"@brief Control to visualize an EaseF.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@see EaseF\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiEaseViewCtrl::GuiEaseViewCtrl()
|
||||
{
|
||||
mEase.set(Ease::In, Ease::Cubic);
|
||||
mAxisColor.set(1,1,1,1);
|
||||
mEaseColor.set(1,1,1,1);
|
||||
mEaseWidth = 4.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiEaseViewCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("ease", TypeEaseF, Offset( mEase, GuiEaseViewCtrl ) );
|
||||
addField("easeColor", TypeColorF, Offset( mEaseColor, GuiEaseViewCtrl ) );
|
||||
addField("easeWidth", TypeF32, Offset(mEaseWidth, GuiEaseViewCtrl ) );
|
||||
addField("axisColor", TypeColorF, Offset( mAxisColor, GuiEaseViewCtrl ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiEaseViewCtrl::onWake()
|
||||
{
|
||||
if (!Parent::onWake())
|
||||
return false;
|
||||
setActive(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiEaseViewCtrl::onSleep()
|
||||
{
|
||||
setActive(false);
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiEaseViewCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
const F32 W = getExtent().x;
|
||||
const F32 H = getExtent().y;
|
||||
const F32 plotW = W;
|
||||
const F32 plotH = H;
|
||||
const F32 zeroX = offset.x + 1.f;
|
||||
const F32 zeroY = offset.y;
|
||||
|
||||
// Draw axis.
|
||||
|
||||
GFX->getDrawUtil()->drawLine( zeroX, zeroY + 0.0f, zeroX, zeroY + plotH, mAxisColor );
|
||||
GFX->getDrawUtil()->drawLine( zeroX, zeroY + plotH, zeroX + plotW, zeroY + plotH, mAxisColor );
|
||||
|
||||
F32 numPoints = W;
|
||||
F32 lastX = zeroX;
|
||||
F32 lastY = zeroY + plotH;
|
||||
|
||||
// Draw curve.
|
||||
|
||||
for( int i = 1; i <= numPoints; ++ i )
|
||||
{
|
||||
F32 x = ( F32 ) i / ( F32 ) numPoints;
|
||||
F32 y = mEase.getValue( x, 0, 1, 1 );
|
||||
|
||||
x = zeroX + x * plotW;
|
||||
y = zeroY + plotH - y * plotH;
|
||||
|
||||
GFX->getDrawUtil()->drawLine( lastX, lastY, x, y, mEaseColor );
|
||||
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
}
|
||||
}
|
||||
63
Engine/source/gui/editor/guiEaseViewCtrl.h
Normal file
63
Engine/source/gui/editor/guiEaseViewCtrl.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIEASEVIEWCTRL_H_
|
||||
#define _GUIEASEVIEWCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
#ifndef _MEASE_H_
|
||||
#include "math/mEase.h"
|
||||
#endif
|
||||
|
||||
|
||||
/// Control to visualize an EaseF.
|
||||
class GuiEaseViewCtrl : public GuiControl
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
|
||||
EaseF mEase; // ease we are visualizing
|
||||
ColorF mAxisColor; // color to draw axis in
|
||||
ColorF mEaseColor; // color to draw ease in
|
||||
F32 mEaseWidth; // width of lines
|
||||
|
||||
public:
|
||||
|
||||
GuiEaseViewCtrl();
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void onRender( Point2I, const RectI &);
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT( GuiEaseViewCtrl );
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
DECLARE_DESCRIPTION( "Control that display an EaseF curve." );
|
||||
};
|
||||
|
||||
#endif // !_GUIEASEVIEWCTRL_H_
|
||||
2967
Engine/source/gui/editor/guiEditCtrl.cpp
Normal file
2967
Engine/source/gui/editor/guiEditCtrl.cpp
Normal file
File diff suppressed because it is too large
Load diff
339
Engine/source/gui/editor/guiEditCtrl.h
Normal file
339
Engine/source/gui/editor/guiEditCtrl.h
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIEDITCTRL_H_
|
||||
#define _GUIEDITCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
#ifndef _UNDO_H_
|
||||
#include "util/undo.h"
|
||||
#endif
|
||||
#ifndef _GFX_GFXDRAWER_H_
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#endif
|
||||
|
||||
|
||||
/// Native side of the GUI editor.
|
||||
class GuiEditCtrl : public GuiControl
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiControl Parent;
|
||||
friend class GuiEditorRuler;
|
||||
|
||||
enum Justification
|
||||
{
|
||||
JUSTIFY_LEFT,
|
||||
JUSTIFY_CENTER_VERTICAL,
|
||||
JUSTIFY_RIGHT,
|
||||
JUSTIFY_TOP,
|
||||
JUSTIFY_BOTTOM,
|
||||
SPACING_VERTICAL,
|
||||
SPACING_HORIZONTAL,
|
||||
JUSTIFY_CENTER_HORIZONTAL,
|
||||
};
|
||||
|
||||
enum guideAxis { GuideVertical, GuideHorizontal };
|
||||
|
||||
enum mouseModes { Selecting, MovingSelection, SizingSelection, DragSelecting, DragGuide, DragClone };
|
||||
enum sizingModes { sizingNone = 0, sizingLeft = 1, sizingRight = 2, sizingTop = 4, sizingBottom = 8 };
|
||||
|
||||
enum snappingAxis { SnapVertical, SnapHorizontal };
|
||||
enum snappingEdges { SnapEdgeMin, SnapEdgeMid, SnapEdgeMax };
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
NUT_SIZE = 4,
|
||||
MIN_GRID_SIZE = 3
|
||||
};
|
||||
|
||||
typedef Vector< GuiControl* > GuiControlVector;
|
||||
typedef SimObjectPtr< GuiControl > GuiControlPtr;
|
||||
|
||||
bool mDrawBorderLines;
|
||||
bool mDrawGuides;
|
||||
bool mFullBoxSelection;
|
||||
GuiControlVector mSelectedControls;
|
||||
GuiControlPtr mCurrentAddSet;
|
||||
GuiControlPtr mContentControl;
|
||||
Point2I mLastMousePos;
|
||||
Point2I mLastDragPos;
|
||||
Point2I mSelectionAnchor;
|
||||
Point2I mGridSnap;
|
||||
Point2I mDragBeginPoint;
|
||||
Vector<Point2I> mDragBeginPoints;
|
||||
bool mDragAddSelection;
|
||||
bool mDragMoveUndo;
|
||||
|
||||
// Guides.
|
||||
|
||||
bool mSnapToGuides; ///< If true, edge and center snapping will work against guides.
|
||||
bool mDragGuide[ 2 ];
|
||||
U32 mDragGuideIndex[ 2 ];///< Indices of the guide's being dragged in DragGuide mouse mode.
|
||||
Vector< U32 > mGuides[ 2 ]; ///< The guides defined on the current content control.
|
||||
|
||||
// Snapping
|
||||
|
||||
bool mSnapToControls; ///< If true, edge and center snapping will work against controls.
|
||||
bool mSnapToCanvas; ///< If true, edge and center snapping will work against canvas (= content control).
|
||||
bool mSnapToEdges; ///< If true, selection edges will snap to other control edges.
|
||||
bool mSnapToCenters; ///< If true, selection centers will snap to other control centers.
|
||||
S32 mSnapSensitivity; ///< Snap distance in pixels.
|
||||
|
||||
bool mSnapped[ 2 ]; ///< Snap flag for each axis. If true, we are currently snapped in a drag.
|
||||
S32 mSnapOffset[ 2 ]; ///< Reference point on snap line for each axis.
|
||||
GuiControlVector mSnapHits[ 2 ]; ///< Hit testing lists for each axis.
|
||||
snappingEdges mSnapEdge[ 2 ]; ///< Identification of edge being snapped for each axis.
|
||||
GuiControlPtr mSnapTargets[ 2 ]; ///< Controls providing the snap reference lines on each axis.
|
||||
|
||||
// Undo
|
||||
SimGroup* mTrash;
|
||||
SimSet* mSelectedSet;
|
||||
|
||||
// grid drawing
|
||||
GFXVertexBufferHandle<GFXVertexPC> mDots;
|
||||
GFXStateBlockRef mDotSB;
|
||||
|
||||
mouseModes mMouseDownMode;
|
||||
sizingModes mSizingMode;
|
||||
|
||||
static StringTableEntry smGuidesPropertyName[ 2 ];
|
||||
|
||||
// private methods
|
||||
void updateSelectedSet();
|
||||
|
||||
S32 findGuide( guideAxis axis, const Point2I& point, U32 tolerance = 0 );
|
||||
|
||||
RectI getSnapRegion( snappingAxis axis, const Point2I& center ) const;
|
||||
void findSnaps( snappingAxis axis, const Point2I& mousePoint, const RectI& minRegion, const RectI& midRegion, const RectI& maxRegion );
|
||||
void registerSnap( snappingAxis axis, const Point2I& mousePoint, const Point2I& point, snappingEdges edge, GuiControl* ctrl = NULL );
|
||||
|
||||
void doSnapping( const GuiEvent& event, const RectI& selectionBounds, Point2I& delta );
|
||||
void doGuideSnap( const GuiEvent& event, const RectI& selectionBounds, const RectI& selectionBoundsGlobal, Point2I& delta );
|
||||
void doControlSnap( const GuiEvent& event, const RectI& selectionBounds, const RectI& selectionBoundsGlobal, Point2I& delta );
|
||||
void doGridSnap( const GuiEvent& event, const RectI& selectionBounds, const RectI& selectionBoundsGlobal, Point2I& delta );
|
||||
void snapToGrid( Point2I& point );
|
||||
|
||||
void startDragMove( const Point2I& startPoint );
|
||||
void startDragRectangle( const Point2I& startPoint );
|
||||
void startDragClone( const Point2I& startPoint );
|
||||
void startMouseGuideDrag( guideAxis axis, U32 index, bool lockMouse = true );
|
||||
|
||||
void setMouseMode( mouseModes mode );
|
||||
|
||||
/// @name Callbacks
|
||||
/// @{
|
||||
|
||||
DECLARE_CALLBACK( void, onHierarchyChanged, () );
|
||||
DECLARE_CALLBACK( void, onDelete, () );
|
||||
DECLARE_CALLBACK( void, onPreEdit, ( SimSet* selection ) );
|
||||
DECLARE_CALLBACK( void, onPostEdit, ( SimSet* selection ) );
|
||||
DECLARE_CALLBACK( void, onClearSelected, () );
|
||||
DECLARE_CALLBACK( void, onSelect, ( GuiControl* control ) );
|
||||
DECLARE_CALLBACK( void, onAddSelected, ( GuiControl* control ) );
|
||||
DECLARE_CALLBACK( void, onRemoveSelected, ( GuiControl* control ) );
|
||||
DECLARE_CALLBACK( void, onPreSelectionNudged, ( SimSet* selection ) );
|
||||
DECLARE_CALLBACK( void, onPostSelectionNudged, ( SimSet* selection ) );
|
||||
DECLARE_CALLBACK( void, onSelectionMoved, ( GuiControl* control ) ); //FIXME: this should be a selection SimSet
|
||||
DECLARE_CALLBACK( void, onSelectionCloned, ( SimSet* selection ) );
|
||||
DECLARE_CALLBACK( void, onTrashSelection, ( SimSet* selection ) );
|
||||
DECLARE_CALLBACK( void, onAddNewCtrl, ( GuiControl* control ) );
|
||||
DECLARE_CALLBACK( void, onAddNewCtrlSet, ( SimSet* set ) );
|
||||
DECLARE_CALLBACK( void, onSelectionResized, ( GuiControl* control ) );
|
||||
DECLARE_CALLBACK( void, onFitIntoParent, ( bool width, bool height ) );
|
||||
DECLARE_CALLBACK( void, onMouseModeChange, () );
|
||||
DECLARE_CALLBACK( void, onControlInspectPreApply, ( GuiControl* control ) );
|
||||
DECLARE_CALLBACK( void, onControlInspectPostApply, ( GuiControl* control ) );
|
||||
|
||||
/// @}
|
||||
|
||||
static bool inNut( const Point2I &pt, S32 x, S32 y )
|
||||
{
|
||||
S32 dx = pt.x - x;
|
||||
S32 dy = pt.y - y;
|
||||
return dx <= NUT_SIZE && dx >= -NUT_SIZE && dy <= NUT_SIZE && dy >= -NUT_SIZE;
|
||||
}
|
||||
|
||||
static void drawCrossSection( U32 axis, S32 offset, const RectI& bounds, ColorI color, GFXDrawUtil* drawer )
|
||||
{
|
||||
Point2I start;
|
||||
Point2I end;
|
||||
|
||||
if( axis == 0 )
|
||||
{
|
||||
start.x = end.x = offset;
|
||||
start.y = bounds.point.y;
|
||||
end.y = bounds.point.y + bounds.extent.y - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
start.y = end.y = offset;
|
||||
start.x = bounds.point.x;
|
||||
end.x = bounds.point.x + bounds.extent.x - 1;
|
||||
}
|
||||
|
||||
drawer->drawLine( start, end, color );
|
||||
}
|
||||
|
||||
static void snapDelta( snappingAxis axis, snappingEdges edge, S32 offset, const RectI& bounds, Point2I& delta )
|
||||
{
|
||||
switch( axis )
|
||||
{
|
||||
case SnapVertical:
|
||||
switch( edge )
|
||||
{
|
||||
case SnapEdgeMin:
|
||||
delta.x = offset - bounds.point.x;
|
||||
break;
|
||||
|
||||
case SnapEdgeMid:
|
||||
delta.x = offset - bounds.point.x - bounds.extent.x / 2;
|
||||
break;
|
||||
|
||||
case SnapEdgeMax:
|
||||
delta.x = offset - bounds.point.x - bounds.extent.x + 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SnapHorizontal:
|
||||
switch( edge )
|
||||
{
|
||||
case SnapEdgeMin:
|
||||
delta.y = offset - bounds.point.y;
|
||||
break;
|
||||
|
||||
case SnapEdgeMid:
|
||||
delta.y = offset - bounds.point.y - bounds.extent.y / 2;
|
||||
break;
|
||||
|
||||
case SnapEdgeMax:
|
||||
delta.y = offset - bounds.point.y - bounds.extent.y + 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
GuiEditCtrl();
|
||||
|
||||
DECLARE_CONOBJECT(GuiEditCtrl);
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
DECLARE_DESCRIPTION( "Implements the framework for the GUI editor." );
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
GuiControl* getContentControl() const { return mContentControl; }
|
||||
void setContentControl(GuiControl *ctrl);
|
||||
void setEditMode(bool value);
|
||||
S32 getSizingHitKnobs(const Point2I &pt, const RectI &box);
|
||||
void getDragRect(RectI &b);
|
||||
void drawNut(const Point2I &nut, ColorI &outlineColor, ColorI &nutColor);
|
||||
void drawNuts(RectI &box, ColorI &outlineColor, ColorI &nutColor);
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
void addNewControl(GuiControl *ctrl);
|
||||
void setCurrentAddSet(GuiControl *ctrl, bool clearSelection = true);
|
||||
GuiControl* getCurrentAddSet();
|
||||
|
||||
// Selections.
|
||||
|
||||
void select( GuiControl *ctrl );
|
||||
bool selectionContains( GuiControl *ctrl );
|
||||
bool selectionContainsParentOf( GuiControl* ctrl );
|
||||
void setSelection( GuiControl *ctrl, bool inclusive = false );
|
||||
RectI getSelectionBounds() const;
|
||||
RectI getSelectionGlobalBounds() const;
|
||||
void canHitSelectedControls( bool state = true );
|
||||
void justifySelection( Justification j );
|
||||
void moveSelection( const Point2I &delta, bool callback = true );
|
||||
void moveAndSnapSelection( const Point2I &delta, bool callback = true );
|
||||
void saveSelection( const char *filename );
|
||||
void loadSelection( const char *filename );
|
||||
void addSelection( S32 id );
|
||||
void addSelection( GuiControl* ctrl );
|
||||
void removeSelection( S32 id );
|
||||
void removeSelection( GuiControl* ctrl );
|
||||
void deleteSelection();
|
||||
void clearSelection();
|
||||
void selectAll();
|
||||
void bringToFront();
|
||||
void pushToBack();
|
||||
void moveSelectionToCtrl( GuiControl* ctrl, bool callback = true );
|
||||
void addSelectControlsInRegion( const RectI& rect, U32 hitTestFlags = 0 );
|
||||
void addSelectControlAt( const Point2I& pos );
|
||||
void resizeControlsInSelectionBy( const Point2I& delta, U32 mode );
|
||||
void fitIntoParents( bool width = true, bool height = true );
|
||||
void selectParents( bool addToSelection = false );
|
||||
void selectChildren( bool addToSelection = false );
|
||||
void cloneSelection();
|
||||
U32 getNumSelected() const { return mSelectedControls.size(); }
|
||||
|
||||
// Guides.
|
||||
|
||||
U32 addGuide( guideAxis axis, U32 offset ) { U32 index = mGuides[ axis ].size(); mGuides[ axis ].push_back( offset ); return index; }
|
||||
void readGuides( guideAxis axis, GuiControl* ctrl );
|
||||
void writeGuides( guideAxis axis, GuiControl* ctrl );
|
||||
void clearGuides( guideAxis axis ) { mGuides[ axis ].clear(); }
|
||||
|
||||
// Undo Access.
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
|
||||
// When a control is changed by the inspector
|
||||
void controlInspectPreApply(GuiControl* object);
|
||||
void controlInspectPostApply(GuiControl* object);
|
||||
|
||||
// Sizing Cursors
|
||||
void getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent);
|
||||
|
||||
U32 getSelectionSize() const { return mSelectedControls.size(); }
|
||||
const Vector<GuiControl *>& getSelected() const { return mSelectedControls; }
|
||||
SimSet* getSelectedSet() { updateSelectedSet(); return mSelectedSet; }
|
||||
SimGroup* getTrash() { return mTrash; }
|
||||
GuiControl* getAddSet() const { return mCurrentAddSet; }; //JDD
|
||||
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onRightMouseDown(const GuiEvent &event);
|
||||
|
||||
mouseModes getMouseMode() const { return mMouseDownMode; }
|
||||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
|
||||
void setSnapToGrid(U32 gridsize);
|
||||
};
|
||||
|
||||
#endif //_GUI_EDIT_CTRL_H
|
||||
293
Engine/source/gui/editor/guiFilterCtrl.cpp
Normal file
293
Engine/source/gui/editor/guiFilterCtrl.cpp
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/guiFilterCtrl.h"
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "guiFilterCtrl.h"
|
||||
#include "math/mMath.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiFilterCtrl);
|
||||
|
||||
ConsoleDocClass( GuiFilterCtrl,
|
||||
"@brief A control that displays a Catmull-Rom spline through a number of control points.\n\n"
|
||||
"Currently editor use only, no real application without extension.\n\n "
|
||||
"@internal");
|
||||
|
||||
GuiFilterCtrl::GuiFilterCtrl()
|
||||
{
|
||||
mControlPointRequest = 7;
|
||||
mFilter.setSize(7);
|
||||
mShowIdentity = true;
|
||||
mIdentity.set( 0.0f, 1.0f );
|
||||
identity();
|
||||
mCurKnot = -1;
|
||||
}
|
||||
|
||||
void GuiFilterCtrl::initPersistFields()
|
||||
{
|
||||
addField("controlPoints", TypeS32, Offset(mControlPointRequest, GuiFilterCtrl),
|
||||
"Total number of control points in the spline curve." );
|
||||
addField("filter", TypeF32Vector, Offset(mFilter, GuiFilterCtrl),
|
||||
"Vector of control points." );
|
||||
addField("showIdentity", TypeBool, Offset(mShowIdentity, GuiFilterCtrl), "@internal" );
|
||||
addField("identity", TypePoint2F, Offset(mIdentity, GuiFilterCtrl), "@internal");
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiFilterCtrl, getValue, const char*, 2, 2, "Return a tuple containing all the values in the filter."
|
||||
"@internal")
|
||||
{
|
||||
TORQUE_UNUSED(argv);
|
||||
static char buffer[512];
|
||||
const Filter *filter = object->get();
|
||||
*buffer = 0;
|
||||
|
||||
for (U32 i=0; i < filter->size(); i++)
|
||||
{
|
||||
char value[32];
|
||||
dSprintf(value, 31, "%1.5f ", *(filter->begin()+i) );
|
||||
dStrcat(buffer, value);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiFilterCtrl, setValue, void, 3, 20, "(f1, f2, ...)"
|
||||
"Reset the filter to use the specified points, spread equidistantly across the domain."
|
||||
"@internal")
|
||||
{
|
||||
Filter filter;
|
||||
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
filter.set(argc, argv);
|
||||
object->set(filter);
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiFilterCtrl, identity, void, 2, 2, "Reset the filtering."
|
||||
"@internal")
|
||||
{
|
||||
object->identity();
|
||||
}
|
||||
|
||||
bool GuiFilterCtrl::onWake()
|
||||
{
|
||||
if (!Parent::onWake())
|
||||
return false;
|
||||
|
||||
if (U32(mControlPointRequest) != mFilter.size())
|
||||
{
|
||||
mFilter.setSize(mControlPointRequest);
|
||||
identity();
|
||||
}
|
||||
|
||||
mCurKnot = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GuiFilterCtrl::identity()
|
||||
{
|
||||
S32 size = mFilter.size()-1;
|
||||
for (U32 i=0; S32(i) <= size; i++)
|
||||
{
|
||||
F32 step = (F32)i/(F32)size;
|
||||
mFilter[i] = mLerp( mIdentity.x, mIdentity.y, step );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GuiFilterCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
mouseLock();
|
||||
setFirstResponder();
|
||||
|
||||
Point2I p = globalToLocalCoord(event.mousePoint);
|
||||
|
||||
// determine which knot (offset same as in onRender)
|
||||
F32 w = F32(getWidth()-4) / F32(mFilter.size()-1);
|
||||
F32 val = (F32(p.x) + (w / 2.f)) / w;
|
||||
mCurKnot = S32(val);
|
||||
|
||||
mFilter[mCurKnot] = 1.0f - F32(getMin(getMax(0, p.y), getHeight())/(F32)getHeight());
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
|
||||
void GuiFilterCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
if ( mCurKnot < 0 )
|
||||
return;
|
||||
|
||||
mouseLock();
|
||||
setFirstResponder();
|
||||
|
||||
Point2I p = globalToLocalCoord(event.mousePoint);
|
||||
mFilter[mCurKnot] = 1.0f - F32(getMin(getMax(0, p.y), getHeight())/(F32)getHeight());
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
void GuiFilterCtrl::onMouseUp(const GuiEvent &)
|
||||
{
|
||||
if ( mCurKnot < 0 )
|
||||
return;
|
||||
|
||||
mouseUnlock();
|
||||
execConsoleCallback();
|
||||
}
|
||||
|
||||
void GuiFilterCtrl::onPreRender()
|
||||
{
|
||||
if(U32(mControlPointRequest) != mFilter.size())
|
||||
{
|
||||
mFilter.setSize(mControlPointRequest);
|
||||
identity();
|
||||
setUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiFilterCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
Point2I pos = offset;
|
||||
Point2I ext = getExtent();
|
||||
|
||||
RectI r(pos, ext);
|
||||
GFX->getDrawUtil()->drawRectFill(r, ColorI(255,255,255));
|
||||
GFX->getDrawUtil()->drawRect(r, ColorI(0,0,0));
|
||||
|
||||
// shrink by 2 pixels
|
||||
pos.x += 2;
|
||||
pos.y += 2;
|
||||
ext.x -= 4;
|
||||
ext.y -= 4;
|
||||
|
||||
// draw the identity line
|
||||
if ( mShowIdentity )
|
||||
{
|
||||
GFX->getDrawUtil()->drawLine( pos.x, pos.y + ( ext.y * ( 1.0f - mIdentity.x ) ),
|
||||
pos.x + ext.x, pos.y + ( ext.y * ( 1.0f - mIdentity.y ) ),
|
||||
ColorF( 0.9f, 0.9f, 0.9f ) );
|
||||
}
|
||||
|
||||
// draw the curv
|
||||
GFXVertexBufferHandle<GFXVertexPC> verts(GFX, ext.x, GFXBufferTypeVolatile);
|
||||
|
||||
verts.lock();
|
||||
|
||||
F32 scale = 1.f / F32( ext.x );
|
||||
for ( U32 i = 0; i < ext.x; i++)
|
||||
{
|
||||
F32 index = F32(i) * scale;
|
||||
S32 y = (S32)(ext.y*(1.0f-mFilter.getValue(index)));
|
||||
|
||||
verts[i].point.set( (F32)(pos.x + i), (F32)(pos.y + y), 0.0f );
|
||||
verts[i].color = GFXVertexColor( ColorF( 0.4f, 0.4f, 0.4f ) );
|
||||
}
|
||||
|
||||
verts.unlock();
|
||||
|
||||
GFX->setVertexBuffer( verts );
|
||||
GFX->drawPrimitive( GFXLineStrip, 0, ext.x - 1 );
|
||||
|
||||
// draw the knots
|
||||
for (U32 k=0; k < mFilter.size(); k++)
|
||||
{
|
||||
RectI r;
|
||||
r.point.x = (S32)(((F32)ext.x/(F32)(mFilter.size()-1)*(F32)k));
|
||||
r.point.y = (S32)(ext.y - ((F32)ext.y * mFilter[k]));
|
||||
r.point += pos + Point2I(-2,-2);
|
||||
r.extent = Point2I(5,5);
|
||||
|
||||
GFX->getDrawUtil()->drawRectFill(r, ColorI(255,0,0));
|
||||
}
|
||||
|
||||
renderChildControls(offset, updateRect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void Filter::set(S32 argc, const char *argv[])
|
||||
{
|
||||
setSize(0);
|
||||
if (argc == 1)
|
||||
{ // in the form of one string "1.0 1.0 1.0"
|
||||
char list[1024];
|
||||
dStrcpy(list, *argv); // strtok modifies the string so we need to copy it
|
||||
char *value = dStrtok(list, " ");
|
||||
while (value)
|
||||
{
|
||||
push_back(dAtof(value));
|
||||
value = dStrtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // in the form of seperate strings "1.0" "1.0" "1.0"
|
||||
for (; argc ; argc--, argv++)
|
||||
push_back(dAtof(*argv));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
F32 Filter::getValue(F32 x) const
|
||||
{
|
||||
if (size() < 2)
|
||||
return 0.0f;
|
||||
|
||||
x = mClampF(x, 0.0f, 1.0f);
|
||||
x *= F32(size()-1);
|
||||
|
||||
F32 p0,p1,p2,p3;
|
||||
S32 i1 = (S32)mFloor(x);
|
||||
S32 i2 = i1+1;
|
||||
F32 dt = x - F32(i1);
|
||||
|
||||
p1 = *(begin()+i1);
|
||||
p2 = *(begin()+i2);
|
||||
|
||||
if (i1 == 0)
|
||||
p0 = p1 + (p1 - p2);
|
||||
else
|
||||
p0 = *(begin()+i1-1);
|
||||
|
||||
if (i2 == S32(size()-1))
|
||||
p3 = p2 + (p2 - p1);
|
||||
else
|
||||
p3 = *(begin()+i2+1);
|
||||
|
||||
return mClampF( mCatmullrom(dt, p0, p1, p2, p3), 0.0f, 1.0f );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
99
Engine/source/gui/editor/guiFilterCtrl.h
Normal file
99
Engine/source/gui/editor/guiFilterCtrl.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIFILTERCTRL_H_
|
||||
#define _GUIFILTERCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
|
||||
|
||||
class Filter: public Vector<F32>
|
||||
{
|
||||
public:
|
||||
Filter() : Vector<F32>(__FILE__, __LINE__) { }
|
||||
|
||||
void set(S32 argc, const char *argv[]);
|
||||
F32 getValue(F32 t) const;
|
||||
};
|
||||
|
||||
|
||||
class GuiFilterCtrl : public GuiControl
|
||||
{
|
||||
protected:
|
||||
|
||||
typedef GuiControl Parent;
|
||||
|
||||
S32 mControlPointRequest;
|
||||
|
||||
S32 mCurKnot;
|
||||
|
||||
Filter mFilter;
|
||||
|
||||
bool mShowIdentity;
|
||||
|
||||
Point2F mIdentity;
|
||||
|
||||
public:
|
||||
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiFilterCtrl);
|
||||
DECLARE_CATEGORY( "Gui Other" );
|
||||
DECLARE_DESCRIPTION( "A control that displays a Catmull-Rom spline through a number of control points\n"
|
||||
"and allows to edit the Y-coordinates of the control points to adjust the curve." );
|
||||
|
||||
GuiFilterCtrl();
|
||||
static void initPersistFields();
|
||||
|
||||
//Parental methods
|
||||
bool onWake();
|
||||
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &);
|
||||
|
||||
F32 getValue(S32 n);
|
||||
const Filter* get() { return &mFilter; }
|
||||
void set(const Filter &f);
|
||||
S32 getNumControlPoints() {return mFilter.size(); }
|
||||
void identity();
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect );
|
||||
};
|
||||
|
||||
|
||||
inline F32 GuiFilterCtrl::getValue(S32 n)
|
||||
{
|
||||
S32 index = getMin(getMax(n,0), (S32)mFilter.size()-1);
|
||||
return mFilter[index];
|
||||
}
|
||||
|
||||
|
||||
inline void GuiFilterCtrl::set(const Filter &f)
|
||||
{
|
||||
mControlPointRequest = f.size();
|
||||
mFilter = f;
|
||||
}
|
||||
|
||||
#endif
|
||||
430
Engine/source/gui/editor/guiGraphCtrl.cpp
Normal file
430
Engine/source/gui/editor/guiGraphCtrl.cpp
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/guiGraphCtrl.h"
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "gfx/primBuilder.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT( GuiGraphCtrl );
|
||||
|
||||
ConsoleDocClass( GuiGraphCtrl,
|
||||
"@brief A control that plots one or more curves in a chart.\n\n"
|
||||
|
||||
"Up to 6 individual curves can be plotted in the graph. Each plotted curve can have its own display style including its "
|
||||
"own charting style (#plotType) and color (#plotColor).\n\n"
|
||||
|
||||
"The data points on each curve can be added in one of two ways:\n\n"
|
||||
|
||||
"- Manually by calling addDatum(). This causes new data points to be added to the left end of the plotting curve.\n"
|
||||
"- Automatically by letting the graph plot the values of a variable over time. This is achieved by calling addAutoPlot "
|
||||
"and specifying the variable and update frequency.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"// Create a graph that plots a red polyline graph of the FPS counter in a 1 second (1000 milliseconds) interval.\n"
|
||||
"new GuiGraphCtrl( FPSGraph )\n"
|
||||
"{\n"
|
||||
" plotType[ 0 ] = \"PolyLine\";\n"
|
||||
" plotColor[ 0 ] = \"1 0 0\";\n"
|
||||
" plotVariable[ 0 ] = \"fps::real\";\n"
|
||||
" plotInterval[ 0 ] = 1000;\n"
|
||||
"};\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@note Each curve has a maximum number of 200 data points it can have at any one time. Adding more data points to a curve "
|
||||
"will cause older data points to be removed.\n\n"
|
||||
|
||||
"@ingroup GuiValues"
|
||||
);
|
||||
|
||||
ImplementEnumType( GuiGraphType,
|
||||
"The charting style of a single plotting curve in a GuiGraphCtrl.\n\n"
|
||||
"@ingroup GuiValues" )
|
||||
{ GuiGraphCtrl::Bar, "Bar", "Plot the curve as a bar chart." },
|
||||
{ GuiGraphCtrl::Filled, "Filled", "Plot a filled poly graph that connects the data points on the curve." },
|
||||
{ GuiGraphCtrl::Point, "Point", "Plot each data point on the curve as a single dot." },
|
||||
{ GuiGraphCtrl::Polyline , "PolyLine", "Plot straight lines through the data points of the curve." },
|
||||
EndImplementEnumType;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiGraphCtrl::GuiGraphCtrl()
|
||||
: mCenterY( 1.f )
|
||||
{
|
||||
dMemset( mAutoPlot, 0, sizeof( mAutoPlot ) );
|
||||
dMemset( mAutoPlotDelay, 0, sizeof( mAutoPlotDelay ) );
|
||||
dMemset( mGraphMax, 0, sizeof( mGraphMax ) );
|
||||
|
||||
for( S32 i = 0; i < MaxPlots; ++ i )
|
||||
{
|
||||
mGraphType[ i ] = Polyline;
|
||||
|
||||
VECTOR_SET_ASSOCIATION( mGraphData[ i ] );
|
||||
}
|
||||
|
||||
AssertWarn( MaxPlots == 6, "Only 6 plot colors initialized. Update following code if you change MaxPlots." );
|
||||
|
||||
mGraphColor[ 0 ] = ColorF( 1.0, 1.0, 1.0 );
|
||||
mGraphColor[ 1 ] = ColorF( 1.0, 0.0, 0.0 );
|
||||
mGraphColor[ 2 ] = ColorF( 0.0, 1.0, 0.0 );
|
||||
mGraphColor[ 3 ] = ColorF( 0.0, 0.0, 1.0 );
|
||||
mGraphColor[ 4 ] = ColorF( 0.0, 1.0, 1.0 );
|
||||
mGraphColor[ 5 ] = ColorF( 0.0, 0.0, 0.0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiGraphCtrl::initPersistFields()
|
||||
{
|
||||
addGroup( "Graph" );
|
||||
|
||||
addField( "centerY", TypeF32, Offset( mCenterY, GuiGraphCtrl ),
|
||||
"Ratio of where to place the center coordinate of the graph on the Y axis. 0.5=middle height of control.\n\n"
|
||||
"This allows to account for graphs that have only positive or only negative data points, for example." );
|
||||
|
||||
addField( "plotColor", TypeColorF, Offset( mGraphColor, GuiGraphCtrl ), MaxPlots,
|
||||
"Color to use for the plotting curves in the graph." );
|
||||
|
||||
addField( "plotType", TYPEID< GuiGraphType >(), Offset( mGraphType, GuiGraphCtrl ), MaxPlots,
|
||||
"Charting type of the plotting curves." );
|
||||
|
||||
addField( "plotVariable", TypeString, Offset( mAutoPlot, GuiGraphCtrl ), MaxPlots,
|
||||
"Name of the variable to automatically plot on the curves. If empty, auto-plotting "
|
||||
"is disabled for the respective curve." );
|
||||
|
||||
addField( "plotInterval", TypeS32, Offset( mAutoPlotDelay, GuiGraphCtrl ), MaxPlots,
|
||||
"Interval between auto-plots of #plotVariable for the respective curve (in milliseconds)." );
|
||||
|
||||
endGroup( "Graph" );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiGraphCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
if (mBlendSB.isNull())
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
|
||||
desc.setBlend(true, GFXBlendSrcColor, GFXBlendInvSrcColor);
|
||||
mBlendSB = GFX->createStateBlock(desc);
|
||||
|
||||
desc.setBlend(false, GFXBlendOne, GFXBlendZero);
|
||||
mSolidSB = GFX->createStateBlock(desc);
|
||||
|
||||
}
|
||||
|
||||
GFX->setStateBlock( mBlendSB );
|
||||
|
||||
GFX->getDrawUtil()->drawRectFill( updateRect, mProfile->mFillColor );
|
||||
|
||||
GFX->setStateBlock( mSolidSB );
|
||||
|
||||
const Point2I globalPos = getGlobalBounds().point;
|
||||
const F32 midPointY = F32( globalPos.y ) + F32( getExtent().y ) * mCenterY;
|
||||
|
||||
for( S32 k = 0; k < MaxPlots; ++ k )
|
||||
{
|
||||
// Check if there is an autoplot and the proper amount of time has passed, if so add datum.
|
||||
if( mAutoPlot[ k ] && mAutoPlotDelay[ k ] < (Sim::getCurrentTime() - mAutoPlotLastDisplay[ k ] ) )
|
||||
{
|
||||
mAutoPlotLastDisplay[ k ] = Sim::getCurrentTime();
|
||||
addDatum( k, Con::getFloatVariable( mAutoPlot[ k ] ) );
|
||||
}
|
||||
|
||||
// Nothing to graph
|
||||
if( mGraphData[ k ].size() == 0 )
|
||||
continue;
|
||||
|
||||
// Adjust scale to max value + 5% so we can see high values
|
||||
F32 Scale = F32( getExtent().y ) / F32( mGraphMax[ k ] * 1.05 );
|
||||
|
||||
const S32 numSamples = mGraphData[ k ].size();
|
||||
|
||||
switch( mGraphType[ k ] )
|
||||
{
|
||||
case Bar:
|
||||
{
|
||||
F32 prevOffset = 0;
|
||||
|
||||
for( S32 sample = 0; sample < numSamples; ++ sample )
|
||||
{
|
||||
PrimBuild::begin( GFXTriangleFan, 4 );
|
||||
PrimBuild::color( mGraphColor[ k ] );
|
||||
|
||||
F32 offset = F32( getExtent().x ) / F32( MaxDataPoints ) * F32( sample + 1 );
|
||||
|
||||
PrimBuild::vertex2f( globalPos.x + prevOffset,
|
||||
midPointY - ( getDatum( k, sample ) * Scale ) );
|
||||
|
||||
PrimBuild::vertex2f( globalPos.x + offset,
|
||||
midPointY - ( getDatum( k, sample ) * Scale ) );
|
||||
|
||||
PrimBuild::vertex2f( globalPos.x + offset,
|
||||
midPointY );
|
||||
|
||||
PrimBuild::vertex2f( globalPos.x + prevOffset,
|
||||
midPointY );
|
||||
|
||||
prevOffset = offset;
|
||||
|
||||
PrimBuild::end();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Filled:
|
||||
{
|
||||
PrimBuild::begin( GFXTriangleStrip, numSamples * 2 ); // Max size correct? -pw
|
||||
PrimBuild::color( mGraphColor[ k ] );
|
||||
|
||||
for( S32 sample = 0; sample < numSamples; ++ sample )
|
||||
{
|
||||
F32 offset = F32( getExtent().x ) / F32( MaxDataPoints - 1 ) * F32( sample );
|
||||
|
||||
PrimBuild::vertex2f( globalPos.x + offset,
|
||||
midPointY );
|
||||
|
||||
PrimBuild::vertex2f( globalPos.x + offset,
|
||||
midPointY - ( getDatum( k, sample ) * Scale ) );
|
||||
}
|
||||
|
||||
PrimBuild::end();
|
||||
break;
|
||||
}
|
||||
|
||||
case Point:
|
||||
case Polyline:
|
||||
{
|
||||
if( mGraphType[ k ] == Point )
|
||||
PrimBuild::begin( GFXPointList, numSamples ); // Max size correct? -pw
|
||||
else
|
||||
PrimBuild::begin( GFXLineStrip, numSamples );
|
||||
|
||||
PrimBuild::color( mGraphColor[ k ] );
|
||||
|
||||
for( S32 sample = 0; sample < numSamples; ++ sample )
|
||||
{
|
||||
F32 offset = F32( getExtent().x ) / F32( MaxDataPoints - 1 ) * F32( sample );
|
||||
|
||||
PrimBuild::vertex2f( globalPos.x + offset,
|
||||
midPointY - ( getDatum( k, sample ) * Scale ) );
|
||||
}
|
||||
|
||||
PrimBuild::end();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( mProfile->mBorder )
|
||||
{
|
||||
RectI rect( offset.x, offset.y, getWidth(), getHeight() );
|
||||
GFX->getDrawUtil()->drawRect( rect, mProfile->mBorderColor );
|
||||
}
|
||||
|
||||
renderChildControls( offset, updateRect );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiGraphCtrl::addDatum(S32 plotID, F32 v)
|
||||
{
|
||||
AssertFatal(plotID > -1 && plotID < MaxPlots, "Invalid plot specified!");
|
||||
|
||||
// Add the data and trim the vector...
|
||||
mGraphData[ plotID ].push_front( v );
|
||||
|
||||
if( mGraphData[ plotID ].size() > MaxDataPoints )
|
||||
mGraphData[ plotID ].pop_back();
|
||||
|
||||
// Keep record of maximum data value for scaling purposes.
|
||||
if( v > mGraphMax[ plotID ] )
|
||||
mGraphMax[ plotID ] = v;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
float GuiGraphCtrl::getDatum( int plotID, int sample)
|
||||
{
|
||||
AssertFatal(plotID > -1 && plotID < MaxPlots, "Invalid plot specified!");
|
||||
AssertFatal(sample > -1 && sample < MaxDataPoints, "Invalid sample specified!");
|
||||
return mGraphData[ plotID ][sample];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiGraphCtrl::addAutoPlot( S32 plotID, const char* variable, S32 update )
|
||||
{
|
||||
mAutoPlot[ plotID ] = StringTable->insert( variable );
|
||||
mAutoPlotDelay[ plotID ] = update;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiGraphCtrl::removeAutoPlot( S32 plotID )
|
||||
{
|
||||
mAutoPlot[ plotID ] = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiGraphCtrl::setGraphType( S32 plotID, GraphType graphType )
|
||||
{
|
||||
AssertFatal( plotID > -1 && plotID < MaxPlots, "Invalid plot specified!" );
|
||||
mGraphType[ plotID ] = graphType;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Console Methods.
|
||||
//=============================================================================
|
||||
// MARK: ---- Console Methods ----
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( GuiGraphCtrl, addDatum, void, ( S32 plotId, F32 value ),,
|
||||
"Add a data point to the plot's curve.\n\n"
|
||||
"@param plotId Index of the plotting curve to which to add the data point. Must be 0<=plotId<6.\n"
|
||||
"@param value Value of the data point to add to the curve.\n\n"
|
||||
"@note Data values are added to the @b left end of the plotting curve.\n\n"
|
||||
"@note A maximum number of 200 data points can be added to any single plotting curve at any one time. If "
|
||||
"this limit is exceeded, data points on the right end of the curve are culled." )
|
||||
{
|
||||
if( plotId > object->MaxPlots )
|
||||
{
|
||||
Con::errorf( "GuiGraphCtrl::addDatum - 'plotId' out of range: %i", plotId );
|
||||
return;
|
||||
}
|
||||
|
||||
object->addDatum( plotId, value );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( GuiGraphCtrl, getDatum, F32, ( S32 plotId, S32 index ),,
|
||||
"Get a data point on the given plotting curve.\n\n"
|
||||
"@param plotId Index of the plotting curve from which to fetch the data point. Must be 0<=plotId<6.\n"
|
||||
"@param index Index of the data point on the curve.\n"
|
||||
"@return The value of the data point or -1 if @a plotId or @a index are out of range." )
|
||||
{
|
||||
if( plotId > object->MaxPlots )
|
||||
{
|
||||
Con::errorf( "GuiGraphCtrl::getDatum - 'plotId' out of range: %i", plotId );
|
||||
return -1.f;
|
||||
}
|
||||
|
||||
if( index > object->MaxDataPoints)
|
||||
{
|
||||
Con::errorf( "GuiGraphCtrl::getDatum - Data point index out of range: %i", index );
|
||||
return -1.f;
|
||||
}
|
||||
|
||||
return object->getDatum( plotId, index );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( GuiGraphCtrl, addAutoPlot, void, ( S32 plotId, const char* variable, S32 updateFrequency ),,
|
||||
"Sets up the given plotting curve to automatically plot the value of the @a variable with a "
|
||||
"frequency of @a updateFrequency.\n"
|
||||
"@param plotId Index of the plotting curve. Must be 0<=plotId<6.\n"
|
||||
"@param variable Name of the global variable.\n"
|
||||
"@param updateFrequency Frequency with which to add new data points to the plotting curve (in milliseconds).\n"
|
||||
"@tsexample\n"
|
||||
"// Plot FPS counter at 1 second intervals.\n"
|
||||
"%graph.addAutoPlot( 0, \"fps::real\", 1000 );\n"
|
||||
"@endtsexample" )
|
||||
{
|
||||
if( plotId > object->MaxPlots )
|
||||
{
|
||||
Con::errorf( "GuiGraphCtrl::removeAutoPlot - 'plotId' out of range: %i", plotId );
|
||||
return;
|
||||
}
|
||||
|
||||
object->addAutoPlot( plotId, variable, updateFrequency );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( GuiGraphCtrl, removeAutoPlot, void, ( S32 plotId ),,
|
||||
"Stop automatic variable plotting for the given curve.\n"
|
||||
"@param plotId Index of the plotting curve. Must be 0<=plotId<6.\n" )
|
||||
{
|
||||
if( plotId > object->MaxPlots )
|
||||
{
|
||||
Con::errorf( "GuiGraphCtrl::removeAutoPlot - 'plotId' out of range: %i", plotId );
|
||||
return;
|
||||
}
|
||||
|
||||
object->removeAutoPlot( plotId );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( GuiGraphCtrl, setGraphType, void, ( S32 plotId, GuiGraphType graphType ),,
|
||||
"Change the charting type of the given plotting curve.\n"
|
||||
"@param plotId Index of the plotting curve. Must be 0<=plotId<6.\n"
|
||||
"@param graphType Charting type to use for the curve.\n"
|
||||
"@note Instead of calling this method, you can directly assign to #plotType." )
|
||||
{
|
||||
if( plotId > object->MaxPlots )
|
||||
{
|
||||
Con::errorf( "GuiGraphCtrl::setGraphType - 'plotId' out of range: %i", plotId );
|
||||
return;
|
||||
}
|
||||
|
||||
object->setGraphType( plotId, graphType );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiGraphCtrl, matchScale, void, 3, GuiGraphCtrl::MaxPlots + 2, "( int plotID1, int plotID2, ... ) "
|
||||
"Set the scale of all specified plots to the maximum scale among them.\n\n"
|
||||
"@param plotID1 Index of plotting curve.\n"
|
||||
"@param plotID2 Index of plotting curve." )
|
||||
{
|
||||
F32 max = 0;
|
||||
for( S32 i = 0; i < ( argc - 2 ); ++ i )
|
||||
{
|
||||
S32 plotID = dAtoi( argv[ 2 + i ] );
|
||||
if( plotID > object->MaxPlots )
|
||||
{
|
||||
Con::errorf( "GuiGraphCtrl::matchScale - Plot ID out of range: %i", plotID );
|
||||
return;
|
||||
}
|
||||
|
||||
max = getMax( object->getMax( plotID ), max );
|
||||
}
|
||||
|
||||
for( S32 i = 0; i < ( argc - 2 ); ++ i )
|
||||
object->setMax( dAtoi( argv[ 2 + i ] ), max );
|
||||
}
|
||||
88
Engine/source/gui/editor/guiGraphCtrl.h
Normal file
88
Engine/source/gui/editor/guiGraphCtrl.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIGRAPHCTRL_H_
|
||||
#define _GUIGRAPHCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiGraphCtrl : public GuiControl
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiControl Parent;
|
||||
|
||||
enum Constants
|
||||
{
|
||||
MaxPlots = 6,
|
||||
MaxDataPoints = 200
|
||||
};
|
||||
|
||||
enum GraphType {
|
||||
Point,
|
||||
Polyline,
|
||||
Filled,
|
||||
Bar
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
F32 mCenterY;
|
||||
StringTableEntry mAutoPlot[ MaxPlots ];
|
||||
U32 mAutoPlotDelay[ MaxPlots ];
|
||||
SimTime mAutoPlotLastDisplay[ MaxPlots ];
|
||||
ColorF mGraphColor[ MaxPlots ];
|
||||
Vector< F32 > mGraphData[ MaxPlots ];
|
||||
F32 mGraphMax[ MaxPlots ];
|
||||
GraphType mGraphType[ MaxPlots ];
|
||||
|
||||
GFXStateBlockRef mSolidSB;
|
||||
GFXStateBlockRef mBlendSB;
|
||||
|
||||
public:
|
||||
|
||||
GuiGraphCtrl();
|
||||
|
||||
void addDatum( S32 plotID, F32 v );
|
||||
F32 getDatum( S32 plotID, S32 samples );
|
||||
void addAutoPlot( S32 plotID, const char *variable, S32 update );
|
||||
void removeAutoPlot( S32 plotID);
|
||||
void setGraphType( S32 plotID, GraphType graphType );
|
||||
F32 getMax( S32 plotID ) const { return mGraphMax[ plotID ]; }
|
||||
void setMax( S32 plotID, F32 max ) { mGraphMax[ plotID ] = max; }
|
||||
|
||||
// GuiControl.
|
||||
virtual void onRender(Point2I offset, const RectI &updateRect);
|
||||
|
||||
DECLARE_CONOBJECT(GuiGraphCtrl);
|
||||
DECLARE_CATEGORY( "Gui Other" );
|
||||
DECLARE_DESCRIPTION( "A control that allows to plot curve graphs." );
|
||||
|
||||
static void initPersistFields();
|
||||
};
|
||||
|
||||
typedef GuiGraphCtrl::GraphType GuiGraphType;
|
||||
DefineEnumType( GuiGraphType );
|
||||
|
||||
#endif
|
||||
259
Engine/source/gui/editor/guiImageList.cpp
Normal file
259
Engine/source/gui/editor/guiImageList.cpp
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "gui/editor/guiImageList.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiImageList);
|
||||
|
||||
ConsoleDocClass( GuiImageList,
|
||||
"@brief GUI control which displays a list of images.\n\n"
|
||||
"Used to be a part of an old editor system for previous Torque systems. "
|
||||
"Doesn't appear to be used anymore, will most likely be deprecated.\n\n"
|
||||
"@ingroup GuiCore\n"
|
||||
"@internal");
|
||||
|
||||
GuiImageList::GuiImageList()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mTextures);
|
||||
mTextures.clear();
|
||||
mUniqueId = 0;
|
||||
}
|
||||
|
||||
U32 GuiImageList::Insert( const char* texturePath, GFXTextureProfile *Type )
|
||||
{
|
||||
TextureEntry *t = new TextureEntry;
|
||||
|
||||
if ( ! t ) return -1;
|
||||
|
||||
t->TexturePath = StringTable->insert(texturePath);
|
||||
if ( *t->TexturePath )
|
||||
{
|
||||
t->Handle = GFXTexHandle(t->TexturePath, Type, avar("%s() - t->Handle (line %d)", __FUNCTION__, __LINE__));
|
||||
|
||||
if ( t->Handle )
|
||||
{
|
||||
t->id = ++mUniqueId;
|
||||
|
||||
mTextures.push_back( t );
|
||||
|
||||
return t->id;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Free Texture Entry.
|
||||
delete t;
|
||||
|
||||
// Return Failure.
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
bool GuiImageList::Clear()
|
||||
{
|
||||
while ( mTextures.size() )
|
||||
FreeTextureEntry( mTextures[0] );
|
||||
mTextures.clear();
|
||||
|
||||
mUniqueId = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GuiImageList::FreeTextureEntry( U32 Index )
|
||||
{
|
||||
U32 Id = IndexFromId( Index );
|
||||
if ( Id != -1 )
|
||||
return FreeTextureEntry( mTextures[ Id ] );
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GuiImageList::FreeTextureEntry( PTextureEntry Entry )
|
||||
{
|
||||
if ( ! Entry )
|
||||
return false;
|
||||
|
||||
U32 id = IndexFromId( Entry->id );
|
||||
|
||||
delete Entry;
|
||||
|
||||
mTextures.erase ( id );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 GuiImageList::IndexFromId ( U32 Id )
|
||||
{
|
||||
if ( !mTextures.size() ) return -1;
|
||||
Vector<PTextureEntry>::iterator i = mTextures.begin();
|
||||
U32 j = 0;
|
||||
for ( ; i != mTextures.end(); i++ )
|
||||
{
|
||||
if ( i )
|
||||
{
|
||||
if ( (*i)->id == Id )
|
||||
return j;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
U32 GuiImageList::IndexFromPath ( const char* Path )
|
||||
{
|
||||
if ( !mTextures.size() ) return -1;
|
||||
Vector<PTextureEntry>::iterator i = mTextures.begin();
|
||||
for ( ; i != mTextures.end(); i++ )
|
||||
{
|
||||
if ( dStricmp( Path, (*i)->TexturePath ) == 0 )
|
||||
return (*i)->id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GuiImageList::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
DefineEngineMethod( GuiImageList, getImage, const char*, (int index),,
|
||||
"@brief Get a path to the texture at the specified index.\n\n"
|
||||
"@param index Index of the image in the list.\n"
|
||||
"@tsexample\n"
|
||||
"// Define the image index/n"
|
||||
"%index = \"5\";\n\n"
|
||||
"// Request the image path location from the control.\n"
|
||||
"%imagePath = %thisGuiImageList.getImage(%index);\n"
|
||||
"@endtsexample\n\n"
|
||||
"@return File path to the image map for the specified index.\n\n"
|
||||
"@see SimObject")
|
||||
{
|
||||
return object->GetTexturePath(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiImageList, clear, bool, (),,
|
||||
"@brief Clears the imagelist\n\n"
|
||||
"@tsexample\n"
|
||||
"// Inform the GuiImageList control to clear itself.\n"
|
||||
"%isFinished = %thisGuiImageList.clear();\n"
|
||||
"@endtsexample\n\n"
|
||||
"@return Returns true when finished.\n\n"
|
||||
"@see SimObject")
|
||||
{
|
||||
return object->Clear();
|
||||
}
|
||||
|
||||
DefineEngineMethod( GuiImageList, count, S32, (),,
|
||||
"@brief Gets the number of images in the list.\n\n"
|
||||
"@tsexample\n"
|
||||
"// Request the number of images from the GuiImageList control.\n"
|
||||
"%imageCount = %thisGuiImageList.count();\n"
|
||||
"@endtsexample\n\n"
|
||||
"@return Number of images in the control.\n\n"
|
||||
"@see SimObject")
|
||||
{
|
||||
return object->Count();
|
||||
}
|
||||
|
||||
DefineEngineMethod( GuiImageList, remove, bool, (int index),,
|
||||
"@brief Removes an image from the list by index.\n\n"
|
||||
"@param index Image index to remove.\n"
|
||||
"@tsexample\n"
|
||||
"// Define the image index.\n"
|
||||
"%imageIndex = \"4\";\n\n"
|
||||
"// Inform the GuiImageList control to remove the image at the defined index.\n"
|
||||
"%wasSuccessful = %thisGuiImageList.remove(%imageIndex);\n"
|
||||
"@endtsexample\n\n"
|
||||
"@return True if the operation was successful, false if it was not.\n\n"
|
||||
"@see SimObject")
|
||||
{
|
||||
return object->FreeTextureEntry( index );
|
||||
}
|
||||
|
||||
DefineEngineMethod( GuiImageList, getIndex, S32, (const char* imagePath),,
|
||||
"@brief Retrieves the imageindex of a specified texture in the list.\n\n"
|
||||
"@param imagePath Imagemap including filepath of image to search for\n"
|
||||
"@tsexample\n"
|
||||
"// Define the imagemap to search for\n"
|
||||
"%imagePath = \"./game/client/data/images/thisImage\";\n\n"
|
||||
"// Request the index entry for the defined imagemap\n"
|
||||
"%imageIndex = %thisGuiImageList.getIndex(%imagePath);\n"
|
||||
"@endtsexample\n\n"
|
||||
"@return Index of the imagemap matching the defined image path.\n\n"
|
||||
"@see SimObject")
|
||||
{
|
||||
return object->IndexFromPath( imagePath );
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiImageList, insert, S32, (const char* imagePath),,
|
||||
"@brief Insert an image into imagelist- returns the image index or -1 for failure.\n\n"
|
||||
"@param imagePath Imagemap, with path, to add to the list.\n"
|
||||
"@tsexample\n"
|
||||
"// Define the imagemap to add to the list\n"
|
||||
"%imagePath = \"./game/client/data/images/thisImage\";\n\n"
|
||||
"// Request the GuiImageList control to add the defined image to its list.\n"
|
||||
"%imageIndex = %thisGuiImageList.insert(%imagePath);\n"
|
||||
"@endtsexample\n\n"
|
||||
"@return The index of the newly inserted imagemap, or -1 if the insertion failed.\n\n"
|
||||
"@see SimObject")
|
||||
{
|
||||
return object->Insert( imagePath );
|
||||
}
|
||||
|
||||
GFXTexHandle GuiImageList::GetTextureHandle( U32 Index )
|
||||
{
|
||||
U32 ItemIndex = IndexFromId(Index);
|
||||
if ( ItemIndex != -1 )
|
||||
return mTextures[ItemIndex]->Handle;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
}
|
||||
GFXTexHandle GuiImageList::GetTextureHandle( const char* TexturePath )
|
||||
{
|
||||
Vector<PTextureEntry>::iterator i = mTextures.begin();
|
||||
for ( ; i != mTextures.end(); i++ )
|
||||
{
|
||||
if ( dStricmp( TexturePath, (*i)->TexturePath ) == 0 )
|
||||
return (*i)->Handle;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char *GuiImageList::GetTexturePath( U32 Index )
|
||||
{
|
||||
U32 ItemIndex = IndexFromId(Index);
|
||||
if ( ItemIndex != -1 )
|
||||
return mTextures[ItemIndex]->TexturePath;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
78
Engine/source/gui/editor/guiImageList.h
Normal file
78
Engine/source/gui/editor/guiImageList.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIIMAGELIST_H_
|
||||
#define _GUIIMAGELIST_H_
|
||||
|
||||
#include "console/simDatablock.h"
|
||||
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "gui/core/guiTypes.h"
|
||||
#endif
|
||||
|
||||
|
||||
class GuiImageList : public SimObject
|
||||
{
|
||||
private:
|
||||
typedef SimObject Parent;
|
||||
|
||||
public:
|
||||
typedef struct tag_TextureEntry
|
||||
{
|
||||
StringTableEntry TexturePath;
|
||||
GFXTexHandle Handle;
|
||||
U32 id;
|
||||
}TextureEntry,*PTextureEntry;
|
||||
|
||||
Vector<PTextureEntry> mTextures;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
U32 mUniqueId;
|
||||
|
||||
public:
|
||||
GuiImageList();
|
||||
|
||||
DECLARE_CONOBJECT(GuiImageList);
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
// Image managing functions
|
||||
bool Clear();
|
||||
inline U32 Count() { return (U32)mTextures.size(); };
|
||||
U32 Insert( const char* texturePath , GFXTextureProfile *Type = &GFXDefaultGUIProfile );
|
||||
|
||||
bool FreeTextureEntry( U32 Index );
|
||||
bool FreeTextureEntry( PTextureEntry Entry );
|
||||
|
||||
GFXTexHandle GetTextureHandle( U32 Index );
|
||||
GFXTexHandle GetTextureHandle( const char* TexturePath );
|
||||
|
||||
const char * GetTexturePath( U32 Index );
|
||||
|
||||
U32 IndexFromId ( U32 Id );
|
||||
U32 IndexFromPath ( const char* Path );
|
||||
|
||||
};
|
||||
|
||||
#endif //_GUIIMAGELISTCTRL_H_
|
||||
893
Engine/source/gui/editor/guiInspector.cpp
Normal file
893
Engine/source/gui/editor/guiInspector.cpp
Normal file
|
|
@ -0,0 +1,893 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/field.h"
|
||||
#include "gui/editor/inspector/group.h"
|
||||
#include "gui/buttons/guiIconButtonCtrl.h"
|
||||
#include "gui/editor/inspector/dynamicGroup.h"
|
||||
#include "gui/containers/guiScrollCtrl.h"
|
||||
#include "gui/editor/inspector/customField.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspector);
|
||||
|
||||
ConsoleDocClass( GuiInspector,
|
||||
"@brief A control that allows to edit the properties of one or more SimObjects.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
|
||||
//#define DEBUG_SPEW
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspector::GuiInspector()
|
||||
: mDividerPos( 0.35f ),
|
||||
mDividerMargin( 5 ),
|
||||
mOverDivider( false ),
|
||||
mMovingDivider( false ),
|
||||
mHLField( NULL ),
|
||||
mShowCustomFields( true )
|
||||
{
|
||||
mPadding = 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspector::~GuiInspector()
|
||||
{
|
||||
clearGroups();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::initPersistFields()
|
||||
{
|
||||
addGroup( "Inspector" );
|
||||
|
||||
addField( "dividerMargin", TypeS32, Offset( mDividerMargin, GuiInspector ) );
|
||||
|
||||
addField( "groupFilters", TypeRealString, Offset( mGroupFilters, GuiInspector ),
|
||||
"Specify groups that should be shown or not. Specifying 'shown' implicitly does 'not show' all other groups. Example string: +name -otherName" );
|
||||
|
||||
addField( "showCustomFields", TypeBool, Offset( mShowCustomFields, GuiInspector ),
|
||||
"If false the custom fields Name, Id, and Source Class will not be shown." );
|
||||
|
||||
endGroup( "Inspector" );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::onRemove()
|
||||
{
|
||||
clearGroups();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::onDeleteNotify( SimObject *object )
|
||||
{
|
||||
Parent::onDeleteNotify( object );
|
||||
|
||||
if( isInspectingObject( object ) )
|
||||
removeInspectObject( object );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::parentResized(const RectI &oldParentRect, const RectI &newParentRect)
|
||||
{
|
||||
GuiControl *parent = getParent();
|
||||
if ( parent && dynamic_cast<GuiScrollCtrl*>(parent) != NULL )
|
||||
{
|
||||
GuiScrollCtrl *scroll = dynamic_cast<GuiScrollCtrl*>(parent);
|
||||
setWidth( ( newParentRect.extent.x - ( scroll->scrollBarThickness() + 4 ) ) );
|
||||
}
|
||||
else
|
||||
Parent::parentResized(oldParentRect,newParentRect);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspector::resize( const Point2I &newPosition, const Point2I &newExtent )
|
||||
{
|
||||
//F32 dividerPerc = (F32)getWidth() / (F32)mDividerPos;
|
||||
|
||||
bool result = Parent::resize( newPosition, newExtent );
|
||||
|
||||
//mDividerPos = (F32)getWidth() * dividerPerc;
|
||||
|
||||
updateDivider();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiControl* GuiInspector::findHitControl( const Point2I &pt, S32 initialLayer )
|
||||
{
|
||||
if ( mOverDivider || mMovingDivider )
|
||||
return this;
|
||||
|
||||
return Parent::findHitControl( pt, initialLayer );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::getCursor( GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent )
|
||||
{
|
||||
GuiCanvas *pRoot = getRoot();
|
||||
if( !pRoot )
|
||||
return;
|
||||
|
||||
S32 desiredCursor = mOverDivider ? PlatformCursorController::curResizeVert : PlatformCursorController::curArrow;
|
||||
|
||||
// Bail if we're already at the desired cursor
|
||||
if ( pRoot->mCursorChanged == desiredCursor )
|
||||
return;
|
||||
|
||||
PlatformWindow *pWindow = static_cast<GuiCanvas*>(getRoot())->getPlatformWindow();
|
||||
AssertFatal(pWindow != NULL,"GuiControl without owning platform window! This should not be possible.");
|
||||
PlatformCursorController *pController = pWindow->getCursorController();
|
||||
AssertFatal(pController != NULL,"PlatformWindow without an owned CursorController!");
|
||||
|
||||
// Now change the cursor shape
|
||||
pController->popCursor();
|
||||
pController->pushCursor(desiredCursor);
|
||||
pRoot->mCursorChanged = desiredCursor;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::onMouseMove(const GuiEvent &event)
|
||||
{
|
||||
if ( collideDivider( globalToLocalCoord( event.mousePoint ) ) )
|
||||
mOverDivider = true;
|
||||
else
|
||||
mOverDivider = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
if ( mOverDivider )
|
||||
{
|
||||
mMovingDivider = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::onMouseUp(const GuiEvent &event)
|
||||
{
|
||||
mMovingDivider = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
if ( !mMovingDivider )
|
||||
return;
|
||||
|
||||
Point2I localPnt = globalToLocalCoord( event.mousePoint );
|
||||
|
||||
S32 inspectorWidth = getWidth();
|
||||
|
||||
// Distance from mouse/divider position in local space
|
||||
// to the right edge of the inspector
|
||||
mDividerPos = inspectorWidth - localPnt.x;
|
||||
mDividerPos = mClamp( mDividerPos, 0, inspectorWidth );
|
||||
|
||||
// Divide that by the inspectorWidth to get a percentage
|
||||
mDividerPos /= inspectorWidth;
|
||||
|
||||
updateDivider();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspectorGroup* GuiInspector::findExistentGroup( StringTableEntry groupName )
|
||||
{
|
||||
// If we have no groups, it couldn't possibly exist
|
||||
if( mGroups.empty() )
|
||||
return NULL;
|
||||
|
||||
// Attempt to find it in the group list
|
||||
Vector<GuiInspectorGroup*>::iterator i = mGroups.begin();
|
||||
|
||||
for( ; i != mGroups.end(); i++ )
|
||||
{
|
||||
if( dStricmp( (*i)->getGroupName(), groupName ) == 0 )
|
||||
return *i;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::updateFieldValue( StringTableEntry fieldName, StringTableEntry arrayIdx )
|
||||
{
|
||||
// We don't know which group contains the field of this name,
|
||||
// so ask each group in turn, and break when a group returns true
|
||||
// signifying it contained and updated that field.
|
||||
|
||||
Vector<GuiInspectorGroup*>::iterator groupIter = mGroups.begin();
|
||||
|
||||
for( ; groupIter != mGroups.end(); groupIter++ )
|
||||
{
|
||||
if ( (*groupIter)->updateFieldValue( fieldName, arrayIdx ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::clearGroups()
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspector] Clearing %i (%s)", getId(), getName() );
|
||||
#endif
|
||||
|
||||
// If we have no groups, there's nothing to clear!
|
||||
if( mGroups.empty() )
|
||||
return;
|
||||
|
||||
mHLField = NULL;
|
||||
|
||||
if( isMethod( "onClear" ) )
|
||||
Con::executef( this, "onClear" );
|
||||
|
||||
Vector<GuiInspectorGroup*>::iterator i = mGroups.begin();
|
||||
|
||||
freeze(true);
|
||||
|
||||
// Delete Groups
|
||||
for( ; i != mGroups.end(); i++ )
|
||||
{
|
||||
if((*i) && (*i)->isProperlyAdded())
|
||||
(*i)->deleteObject();
|
||||
}
|
||||
|
||||
mGroups.clear();
|
||||
|
||||
freeze(false);
|
||||
updatePanes();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspector::isInspectingObject( SimObject* object )
|
||||
{
|
||||
const U32 numTargets = mTargets.size();
|
||||
for( U32 i = 0; i < numTargets; ++ i )
|
||||
if( mTargets[ i ] == object )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::inspectObject( SimObject *object )
|
||||
{
|
||||
if( mTargets.size() > 1 || !isInspectingObject( object ) )
|
||||
clearInspectObjects();
|
||||
|
||||
addInspectObject( object );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::clearInspectObjects()
|
||||
{
|
||||
const U32 numTargets = mTargets.size();
|
||||
for( U32 i = 0; i < numTargets; ++ i )
|
||||
clearNotify( mTargets[ i ] );
|
||||
|
||||
clearGroups();
|
||||
mTargets.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::addInspectObject( SimObject* object, bool autoSync )
|
||||
{
|
||||
// If we are already inspecting the object, just update the groups.
|
||||
|
||||
if( isInspectingObject( object ) )
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspector] Refreshing view of %i:%s (%s)",
|
||||
object->getId(), object->getClassName(), object->getName() );
|
||||
#endif
|
||||
|
||||
Vector<GuiInspectorGroup*>::iterator i = mGroups.begin();
|
||||
for ( ; i != mGroups.end(); i++ )
|
||||
(*i)->updateAllFields();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspector] Adding %i:%s (%s) to inspect set",
|
||||
object->getId(), object->getClassName(), object->getName() );
|
||||
#endif
|
||||
|
||||
// Give users a chance to customize fields on this object
|
||||
if( object->isMethod("onDefineFieldTypes") )
|
||||
Con::executef( object, "onDefineFieldTypes" );
|
||||
|
||||
// Set Target
|
||||
mTargets.push_back( object );
|
||||
deleteNotify( object );
|
||||
|
||||
if( autoSync )
|
||||
refresh();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::removeInspectObject( SimObject* object )
|
||||
{
|
||||
const U32 numTargets = mTargets.size();
|
||||
for( U32 i = 0; i < numTargets; ++ i )
|
||||
if( mTargets[ i ] == object )
|
||||
{
|
||||
// Delete all inspector data *before* removing the target so that apply calls
|
||||
// triggered by edit controls losing focus will not find the inspect object
|
||||
// gone.
|
||||
|
||||
clearGroups();
|
||||
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspector] Removing %i:%s (%s) from inspect set",
|
||||
object->getId(), object->getClassName(), object->getName() );
|
||||
#endif
|
||||
|
||||
mTargets.erase( i );
|
||||
clearNotify( object );
|
||||
|
||||
// Refresh the inspector except if the system is going down.
|
||||
|
||||
if( !Sim::isShuttingDown() )
|
||||
refresh();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::setName( StringTableEntry newName )
|
||||
{
|
||||
if( mTargets.size() != 1 )
|
||||
return;
|
||||
|
||||
StringTableEntry name = StringTable->insert(newName);
|
||||
|
||||
// Only assign a new name if we provide one
|
||||
mTargets[ 0 ]->assignName(name);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspector::collideDivider( const Point2I &localPnt )
|
||||
{
|
||||
RectI divisorRect( getWidth() - getWidth() * mDividerPos - mDividerMargin, 0, mDividerMargin * 2, getHeight() );
|
||||
|
||||
if ( divisorRect.pointInRect( localPnt ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::updateDivider()
|
||||
{
|
||||
for ( U32 i = 0; i < mGroups.size(); i++ )
|
||||
for ( U32 j = 0; j < mGroups[i]->mChildren.size(); j++ )
|
||||
mGroups[i]->mChildren[j]->updateRects();
|
||||
|
||||
//setUpdate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::getDivider( S32 &pos, S32 &margin )
|
||||
{
|
||||
pos = (F32)getWidth() * mDividerPos;
|
||||
margin = mDividerMargin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::setHighlightField( GuiInspectorField *field )
|
||||
{
|
||||
if ( mHLField == field )
|
||||
return;
|
||||
|
||||
if ( mHLField.isValid() )
|
||||
mHLField->setHLEnabled( false );
|
||||
mHLField = field;
|
||||
|
||||
// We could have been passed a null field, meaning, set no field highlighted.
|
||||
if ( mHLField.isNull() )
|
||||
return;
|
||||
|
||||
mHLField->setHLEnabled( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspector::isGroupFiltered( const char *groupName ) const
|
||||
{
|
||||
// Internal and Ungrouped always filtered, we never show them.
|
||||
if ( dStricmp( groupName, "Internal" ) == 0 ||
|
||||
dStricmp( groupName, "Ungrouped" ) == 0 ||
|
||||
dStricmp( groupName, "AdvCoordManipulation" ) == 0)
|
||||
return true;
|
||||
|
||||
// Normal case, determine if filtered by looking at the mGroupFilters string.
|
||||
String searchStr;
|
||||
|
||||
// Is this group explicitly show? Does it immediately follow a + char.
|
||||
searchStr = String::ToString( "+%s", groupName );
|
||||
if ( mGroupFilters.find( searchStr ) != String::NPos )
|
||||
return false;
|
||||
|
||||
// Were there any other + characters, if so, we are implicitly hidden.
|
||||
if ( mGroupFilters.find( "+" ) != String::NPos )
|
||||
return true;
|
||||
|
||||
// Is this group explicitly hidden? Does it immediately follow a - char.
|
||||
searchStr = String::ToString( "-%s", groupName );
|
||||
if ( mGroupFilters.find( searchStr ) != String::NPos )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiInspector::isGroupExplicitlyFiltered( const char *groupName ) const
|
||||
{
|
||||
String searchStr;
|
||||
|
||||
searchStr = String::ToString( "-%s", groupName );
|
||||
|
||||
if ( mGroupFilters.find( searchStr ) != String::NPos )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::setObjectField( const char *fieldName, const char *data )
|
||||
{
|
||||
GuiInspectorField *field;
|
||||
|
||||
for ( S32 i = 0; i < mGroups.size(); i++ )
|
||||
{
|
||||
field = mGroups[i]->findField( fieldName );
|
||||
|
||||
if( field )
|
||||
{
|
||||
field->setData( data );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static SimObject *sgKeyObj = NULL;
|
||||
|
||||
bool findInspectors( GuiInspector *obj )
|
||||
{
|
||||
if ( obj->isAwake() && obj->isInspectingObject( sgKeyObj ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiInspector* GuiInspector::findByObject( SimObject *obj )
|
||||
{
|
||||
sgKeyObj = obj;
|
||||
|
||||
Vector< GuiInspector* > found;
|
||||
Sim::getGuiGroup()->findObjectByCallback( findInspectors, found );
|
||||
|
||||
if ( found.empty() )
|
||||
return NULL;
|
||||
|
||||
return found.first();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::refresh()
|
||||
{
|
||||
clearGroups();
|
||||
|
||||
// Remove any inspect object that happened to have
|
||||
// already been killed.
|
||||
|
||||
for( U32 i = 0; i < mTargets.size(); ++ i )
|
||||
if( !mTargets[ i ] )
|
||||
{
|
||||
mTargets.erase( i );
|
||||
-- i;
|
||||
}
|
||||
|
||||
if( !mTargets.size() )
|
||||
return;
|
||||
|
||||
// Special group for fields which should appear at the top of the
|
||||
// list outside of a rollout control.
|
||||
|
||||
GuiInspectorGroup *ungroup = NULL;
|
||||
if( mTargets.size() == 1 )
|
||||
{
|
||||
ungroup = new GuiInspectorGroup( "Ungrouped", this );
|
||||
ungroup->setHeaderHidden( true );
|
||||
ungroup->setCanCollapse( false );
|
||||
if( ungroup != NULL )
|
||||
{
|
||||
ungroup->registerObject();
|
||||
mGroups.push_back( ungroup );
|
||||
addObject( ungroup );
|
||||
}
|
||||
}
|
||||
|
||||
// Put the 'transform' group first
|
||||
GuiInspectorGroup *transform = new GuiInspectorGroup( "Transform", this );
|
||||
if( transform != NULL )
|
||||
{
|
||||
transform->registerObject();
|
||||
mGroups.push_back( transform );
|
||||
addObject( transform );
|
||||
}
|
||||
|
||||
// Always create the 'general' group (for fields without a group)
|
||||
GuiInspectorGroup *general = new GuiInspectorGroup( "General", this );
|
||||
if( general != NULL )
|
||||
{
|
||||
general->registerObject();
|
||||
mGroups.push_back( general );
|
||||
addObject( general );
|
||||
}
|
||||
|
||||
// Create the inspector groups for static fields.
|
||||
|
||||
for( TargetVector::iterator iter = mTargets.begin(); iter != mTargets.end(); ++ iter )
|
||||
{
|
||||
AbstractClassRep::FieldList &fieldList = ( *iter )->getModifiableFieldList();
|
||||
|
||||
// Iterate through, identifying the groups and create necessary GuiInspectorGroups
|
||||
for( AbstractClassRep::FieldList::iterator itr = fieldList.begin(); itr != fieldList.end(); itr++ )
|
||||
{
|
||||
if ( itr->type == AbstractClassRep::StartGroupFieldType )
|
||||
{
|
||||
GuiInspectorGroup* group = findExistentGroup( itr->pGroupname );
|
||||
|
||||
if( !group && !isGroupFiltered( itr->pGroupname ) )
|
||||
{
|
||||
GuiInspectorGroup *group = new GuiInspectorGroup( itr->pGroupname, this );
|
||||
if( group != NULL )
|
||||
{
|
||||
group->registerObject();
|
||||
if( !group->getNumFields() )
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiInspector] Removing empty group '%s'",
|
||||
group->getCaption().c_str() );
|
||||
#endif
|
||||
|
||||
// The group ended up having no fields. Remove it.
|
||||
group->deleteObject();
|
||||
}
|
||||
else
|
||||
{
|
||||
mGroups.push_back( group );
|
||||
addObject( group );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with dynamic fields
|
||||
if ( !isGroupFiltered( "Dynamic Fields" ) )
|
||||
{
|
||||
GuiInspectorGroup *dynGroup = new GuiInspectorDynamicGroup( "Dynamic Fields", this);
|
||||
if( dynGroup != NULL )
|
||||
{
|
||||
dynGroup->registerObject();
|
||||
mGroups.push_back( dynGroup );
|
||||
addObject( dynGroup );
|
||||
}
|
||||
}
|
||||
|
||||
if( mShowCustomFields && mTargets.size() == 1 )
|
||||
{
|
||||
SimObject* object = mTargets.first();
|
||||
|
||||
// Add the SimObjectID field to the ungrouped group.
|
||||
|
||||
GuiInspectorCustomField* field = new GuiInspectorCustomField();
|
||||
field->init( this, ungroup );
|
||||
|
||||
if( field->registerObject() )
|
||||
{
|
||||
ungroup->mChildren.push_back( field );
|
||||
ungroup->mStack->addObject( field );
|
||||
|
||||
static StringTableEntry sId = StringTable->insert( "id" );
|
||||
|
||||
field->setCaption( sId );
|
||||
field->setData( object->getIdString() );
|
||||
field->setDoc( "SimObjectId of this object. [Read Only]" );
|
||||
}
|
||||
else
|
||||
delete field;
|
||||
|
||||
// Add the Source Class field to the ungrouped group.
|
||||
|
||||
field = new GuiInspectorCustomField();
|
||||
field->init( this, ungroup );
|
||||
|
||||
if( field->registerObject() )
|
||||
{
|
||||
ungroup->mChildren.push_back( field );
|
||||
ungroup->mStack->addObject( field );
|
||||
|
||||
StringTableEntry sSourceClass = StringTable->insert( "Source Class", true );
|
||||
field->setCaption( sSourceClass );
|
||||
field->setData( object->getClassName() );
|
||||
|
||||
Namespace* ns = object->getClassRep()->getNameSpace();
|
||||
field->setToolTip( Con::getNamespaceList( ns ) );
|
||||
|
||||
field->setDoc( "Native class of this object. [Read Only]" );
|
||||
}
|
||||
else
|
||||
delete field;
|
||||
}
|
||||
|
||||
|
||||
// If the general group is still empty at this point ( or filtered ), kill it.
|
||||
if ( isGroupFiltered( "General" ) || general->mStack->size() == 0 )
|
||||
{
|
||||
for(S32 i=0; i<mGroups.size(); i++)
|
||||
{
|
||||
if ( mGroups[i] == general )
|
||||
{
|
||||
mGroups.erase(i);
|
||||
general->deleteObject();
|
||||
updatePanes();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If transform turns out to be empty or filtered, remove it
|
||||
if( isGroupFiltered( "Transform" ) || transform->mStack->size() == 0 )
|
||||
{
|
||||
for(S32 i=0; i<mGroups.size(); i++)
|
||||
{
|
||||
if ( mGroups[i] == transform )
|
||||
{
|
||||
mGroups.erase(i);
|
||||
transform->deleteObject();
|
||||
updatePanes();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If ungrouped is empty or explicitly filtered, remove it.
|
||||
if( ungroup && ( isGroupExplicitlyFiltered( "Ungrouped" ) || ungroup->getNumFields() == 0 ) )
|
||||
{
|
||||
for(S32 i=0; i<mGroups.size(); i++)
|
||||
{
|
||||
if ( mGroups[i] == ungroup )
|
||||
{
|
||||
mGroups.erase(i);
|
||||
ungroup->deleteObject();
|
||||
updatePanes();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the object cannot be renamed, deactivate the name field if we have it.
|
||||
|
||||
if( ungroup && getNumInspectObjects() == 1 && !getInspectObject()->isNameChangeAllowed() )
|
||||
{
|
||||
GuiInspectorField* nameField = ungroup->findField( "name" );
|
||||
if( nameField )
|
||||
nameField->setActive( false );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::sendInspectPreApply()
|
||||
{
|
||||
const U32 numObjects = getNumInspectObjects();
|
||||
for( U32 i = 0; i < numObjects; ++ i )
|
||||
getInspectObject( i )->inspectPreApply();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiInspector::sendInspectPostApply()
|
||||
{
|
||||
const U32 numObjects = getNumInspectObjects();
|
||||
for( U32 i = 0; i < numObjects; ++ i )
|
||||
getInspectObject( i )->inspectPostApply();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Console Methods.
|
||||
//=============================================================================
|
||||
// MARK: ---- Console Methods ----
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, inspect, void, 3, 3, "Inspect(Object)")
|
||||
{
|
||||
SimObject * target = Sim::findObject(argv[2]);
|
||||
if(!target)
|
||||
{
|
||||
if(dAtoi(argv[2]) > 0)
|
||||
Con::warnf("%s::inspect(): invalid object: %s", argv[0], argv[2]);
|
||||
|
||||
object->clearInspectObjects();
|
||||
return;
|
||||
}
|
||||
|
||||
object->inspectObject(target);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, addInspect, void, 3, 4, "( id object, (bool autoSync = true) ) - Add the object to the list of objects being inspected." )
|
||||
{
|
||||
SimObject* obj;
|
||||
if( !Sim::findObject( argv[ 2 ], obj ) )
|
||||
{
|
||||
Con::errorf( "%s::addInspect(): invalid object: %s", argv[ 0 ], argv[ 2 ] );
|
||||
return;
|
||||
}
|
||||
|
||||
if( argc > 3 )
|
||||
object->addInspectObject( obj, false );
|
||||
else
|
||||
object->addInspectObject( obj );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, removeInspect, void, 3, 3, "( id object ) - Remove the object from the list of objects being inspected." )
|
||||
{
|
||||
SimObject* obj;
|
||||
if( !Sim::findObject( argv[ 2 ], obj ) )
|
||||
{
|
||||
Con::errorf( "%s::removeInspect(): invalid object: %s", argv[ 0 ], argv[ 2 ] );
|
||||
return;
|
||||
}
|
||||
|
||||
object->removeInspectObject( obj );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, refresh, void, 2, 2, "Reinspect the currently selected object." )
|
||||
{
|
||||
if ( object->getNumInspectObjects() == 0 )
|
||||
return;
|
||||
|
||||
SimObject *target = object->getInspectObject();
|
||||
if ( target )
|
||||
object->inspectObject( target );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, getInspectObject, const char*, 2, 3, "getInspectObject( int index=0 ) - Returns currently inspected object" )
|
||||
{
|
||||
U32 index = 0;
|
||||
if( argc > 2 )
|
||||
index = dAtoi( argv[ 2 ] );
|
||||
|
||||
if( index >= object->getNumInspectObjects() )
|
||||
{
|
||||
Con::errorf( "GuiInspector::getInspectObject() - index out of range: %i", index );
|
||||
return "";
|
||||
}
|
||||
|
||||
return object->getInspectObject( index )->getIdString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, getNumInspectObjects, S32, 2, 2, "() - Return the number of objects currently being inspected." )
|
||||
{
|
||||
return object->getNumInspectObjects();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, setName, void, 3, 3, "setName(NewObjectName)")
|
||||
{
|
||||
object->setName(argv[2]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, apply, void, 2, 2, "apply() - Force application of inspected object's attributes" )
|
||||
{
|
||||
object->sendInspectPostApply();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod( GuiInspector, setObjectField, void, 4, 4,
|
||||
"setObjectField( fieldname, data ) - 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." )
|
||||
{
|
||||
object->setObjectField( argv[2], argv[3] );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleStaticMethod( GuiInspector, findByObject, S32, 2, 2,
|
||||
"findByObject( SimObject ) - returns the id of an awake inspector that is inspecting the passed object if one exists." )
|
||||
{
|
||||
SimObject *obj;
|
||||
if ( !Sim::findObject( argv[1], obj ) )
|
||||
return NULL;
|
||||
|
||||
obj = GuiInspector::findByObject( obj );
|
||||
|
||||
if ( !obj )
|
||||
return NULL;
|
||||
|
||||
return obj->getId();
|
||||
}
|
||||
155
Engine/source/gui/editor/guiInspector.h
Normal file
155
Engine/source/gui/editor/guiInspector.h
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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_H_
|
||||
#define _GUI_INSPECTOR_H_
|
||||
|
||||
#ifndef _GUISTACKCTRL_H_
|
||||
#include "gui/containers/guiStackCtrl.h"
|
||||
#endif
|
||||
|
||||
|
||||
class GuiInspectorGroup;
|
||||
class GuiInspectorField;
|
||||
class GuiInspectorDatablockField;
|
||||
|
||||
|
||||
/// A control that allows to edit the properties of one or more SimObjects.
|
||||
class GuiInspector : public GuiStackControl
|
||||
{
|
||||
typedef GuiStackControl Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspector();
|
||||
virtual ~GuiInspector();
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspector);
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
DECLARE_DESCRIPTION( "A control that allows to edit the properties of one or more SimObjects." );
|
||||
|
||||
// Console Object
|
||||
static void initPersistFields();
|
||||
|
||||
// SimObject
|
||||
virtual void onRemove();
|
||||
virtual void onDeleteNotify( SimObject *object );
|
||||
|
||||
// GuiControl
|
||||
virtual void parentResized( const RectI &oldParentRect, const RectI &newParentRect );
|
||||
virtual bool resize( const Point2I &newPosition, const Point2I &newExtent );
|
||||
virtual GuiControl* findHitControl( const Point2I &pt, S32 initialLayer );
|
||||
virtual void getCursor( GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent );
|
||||
virtual void onMouseMove( const GuiEvent &event );
|
||||
virtual void onMouseDown( const GuiEvent &event );
|
||||
virtual void onMouseUp( const GuiEvent &event );
|
||||
virtual void onMouseDragged( const GuiEvent &event );
|
||||
|
||||
// GuiInspector
|
||||
|
||||
/// Return true if "object" is in the inspection set of this inspector.
|
||||
bool isInspectingObject( SimObject* object );
|
||||
|
||||
/// Set the currently inspected object.
|
||||
virtual void inspectObject( SimObject *object );
|
||||
|
||||
/// Add another object to the set of currently inspected objects.
|
||||
virtual void addInspectObject( SimObject* object, bool autoSync = true );
|
||||
|
||||
/// Remove the given object from the set of inspected objects.
|
||||
virtual void removeInspectObject( SimObject* object );
|
||||
|
||||
/// Remove all objects from the inspection set.
|
||||
virtual void clearInspectObjects();
|
||||
|
||||
/// Get the currently inspected object
|
||||
SimObject* getInspectObject( U32 index = 0 ) { return mTargets[ index ]; }
|
||||
|
||||
/// Return the number of objects being inspected by this GuiInspector.
|
||||
U32 getNumInspectObjects() const { return mTargets.size(); }
|
||||
|
||||
/// Call inspectPreApply on all inspected objects.
|
||||
void sendInspectPreApply();
|
||||
|
||||
/// Call inspectPostApply on all inspected objects.
|
||||
void sendInspectPostApply();
|
||||
|
||||
/// Set the currently inspected object name
|
||||
/// @note Only valid in single-object mode.
|
||||
void setName( StringTableEntry newName );
|
||||
|
||||
/// Deletes all GuiInspectorGroups
|
||||
void clearGroups();
|
||||
|
||||
/// Returns true if the named group exists
|
||||
/// Helper for inspectObject
|
||||
GuiInspectorGroup* findExistentGroup( StringTableEntry groupName );
|
||||
|
||||
/// Should there be a GuiInspectorField associated with this fieldName,
|
||||
/// update it to reflect actual/current value of that field in the inspected object.
|
||||
/// Added to support UndoActions
|
||||
void updateFieldValue( StringTableEntry fieldName, const char* arrayIdx );
|
||||
|
||||
/// Divider position is interpreted as an offset
|
||||
/// from the right edge of the field control.
|
||||
/// Divider margin is an offset on both left and right
|
||||
/// sides of the divider in which it can be selected
|
||||
/// with the mouse.
|
||||
void getDivider( S32 &pos, S32 &margin );
|
||||
|
||||
void updateDivider();
|
||||
|
||||
bool collideDivider( const Point2I &localPnt );
|
||||
|
||||
void setHighlightField( GuiInspectorField *field );
|
||||
|
||||
// If returns true that group will not be inspected.
|
||||
bool isGroupFiltered( const char *groupName ) const;
|
||||
|
||||
// Returns true only if the group name follows a minus symbol in the filters.
|
||||
bool isGroupExplicitlyFiltered( const char *groupName ) const;
|
||||
|
||||
void setObjectField( const char *fieldName, const char *data );
|
||||
|
||||
static GuiInspector* findByObject( SimObject *obj );
|
||||
|
||||
protected:
|
||||
|
||||
typedef Vector< SimObjectPtr< SimObject > > TargetVector;
|
||||
|
||||
Vector<GuiInspectorGroup*> mGroups;
|
||||
|
||||
/// Objects being inspected by this GuiInspector.
|
||||
TargetVector mTargets;
|
||||
|
||||
F32 mDividerPos;
|
||||
S32 mDividerMargin;
|
||||
bool mOverDivider;
|
||||
bool mMovingDivider;
|
||||
SimObjectPtr<GuiInspectorField> mHLField;
|
||||
String mGroupFilters;
|
||||
bool mShowCustomFields;
|
||||
|
||||
void refresh();
|
||||
};
|
||||
|
||||
#endif
|
||||
1715
Engine/source/gui/editor/guiInspectorTypes.cpp
Normal file
1715
Engine/source/gui/editor/guiInspectorTypes.cpp
Normal file
File diff suppressed because it is too large
Load diff
580
Engine/source/gui/editor/guiInspectorTypes.h
Normal file
580
Engine/source/gui/editor/guiInspectorTypes.h
Normal file
|
|
@ -0,0 +1,580 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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_TYPES_H_
|
||||
#define _GUI_INSPECTOR_TYPES_H_
|
||||
|
||||
#ifndef _GUI_INSPECTOR_H_
|
||||
#include "gui/editor/guiInspector.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUI_INSPECTOR_FIELD_H_
|
||||
#include "gui/editor/inspector/field.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUICHECKBOXCTRL_H_
|
||||
#include "gui/buttons/guiCheckBoxCtrl.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUIBITMAPBUTTON_H_
|
||||
#include "gui/buttons/guiBitmapButtonCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiPopUpMenuCtrl;
|
||||
|
||||
/// A base class for other inspector field types which
|
||||
/// wish to display a popup/dropdown menu.
|
||||
class GuiInspectorTypeMenuBase : public GuiInspectorField
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorField Parent;
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeMenuBase);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual void setValue( StringTableEntry newValue );
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeEnum GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeEnum : public GuiInspectorTypeMenuBase
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorTypeMenuBase Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeEnum);
|
||||
static void consoleInit();
|
||||
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeCubemapName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeCubemapName : public GuiInspectorTypeMenuBase
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorTypeMenuBase Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeCubemapName);
|
||||
static void consoleInit();
|
||||
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// TypeMaterialName GuiInspectorField Class
|
||||
//--------------------------------------------------------------------------------
|
||||
class GuiBitmapButtonCtrl;
|
||||
|
||||
class GuiInspectorTypeMaterialName : public GuiInspectorField
|
||||
{
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeMaterialName();
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeMaterialName);
|
||||
static void consoleInit();
|
||||
|
||||
GuiBitmapButtonCtrl *mBrowseButton;
|
||||
RectI mBrowseRect;
|
||||
|
||||
GuiControl* construct(const char* command);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
class GuiInspectorTypeRegularMaterialName : public GuiInspectorTypeMaterialName
|
||||
{
|
||||
typedef GuiInspectorTypeMaterialName Parent;
|
||||
public:
|
||||
GuiInspectorTypeRegularMaterialName() {}
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeRegularMaterialName);
|
||||
static void consoleInit();
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// TypeTerrainMaterialIndex GuiInspectorField Class
|
||||
//--------------------------------------------------------------------------------
|
||||
class GuiInspectorTypeTerrainMaterialIndex : public GuiInspectorTypeMaterialName
|
||||
{
|
||||
typedef GuiInspectorTypeMaterialName Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeTerrainMaterialIndex() {}
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeTerrainMaterialIndex);
|
||||
static void consoleInit();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// TypeTerrainMaterialName GuiInspectorField Class
|
||||
//--------------------------------------------------------------------------------
|
||||
class GuiInspectorTypeTerrainMaterialName : public GuiInspectorTypeMaterialName
|
||||
{
|
||||
typedef GuiInspectorTypeMaterialName Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeTerrainMaterialName() {}
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeTerrainMaterialName);
|
||||
static void consoleInit();
|
||||
GuiControl* construct(const char* command);
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeGuiProfile Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeGuiProfile : public GuiInspectorTypeMenuBase
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorTypeMenuBase Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeGuiProfile);
|
||||
static void consoleInit();
|
||||
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeCheckBox Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeCheckBox : public GuiInspectorField
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorField Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeCheckBox);
|
||||
static void consoleInit();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual void setValue( StringTableEntry newValue );
|
||||
virtual const char* getValue();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeCommand GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeCommand : public GuiInspectorField
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorField Parent;
|
||||
StringTableEntry mTextEditorCommand;
|
||||
void _setCommand( GuiButtonCtrl *ctrl, StringTableEntry command );
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeCommand);
|
||||
GuiInspectorTypeCommand();
|
||||
static void consoleInit();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual void setValue( StringTableEntry data );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeFileName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeFileName : public GuiInspectorField
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorField Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeFileName);
|
||||
static void consoleInit();
|
||||
|
||||
SimObjectPtr<GuiButtonCtrl> mBrowseButton;
|
||||
RectI mBrowseRect;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
virtual bool updateRects();
|
||||
virtual void updateValue();
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeImageFileName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeImageFileName : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeImageFileName);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
bool renderTooltip( const Point2I &hoverPos, const Point2I &cursorPos, const char *tipText = NULL );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeRectUV GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeRectUV : public GuiInspectorField
|
||||
{
|
||||
typedef GuiInspectorField Parent;
|
||||
public:
|
||||
GuiBitmapButtonCtrl *mBrowseButton;
|
||||
RectI mBrowseRect;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeRectUV);
|
||||
GuiInspectorTypeRectUV();
|
||||
static void consoleInit();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeEaseF GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class GuiInspectorTypeEaseF : public GuiInspectorField
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
protected:
|
||||
|
||||
SimObjectPtr<GuiButtonCtrl> mBrowseButton;
|
||||
RectI mBrowseRect;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeEaseF();
|
||||
|
||||
DECLARE_CONOBJECT( GuiInspectorTypeEaseF );
|
||||
|
||||
static void consoleInit();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypePrefabFilename GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypePrefabFilename : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypePrefabFilename);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeShapeFilename GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeShapeFilename : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl *mShapeEdButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeShapeFilename);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeColor GuiInspectorField Class (Base for ColorI/ColorF)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class GuiSwatchButtonCtrl;
|
||||
|
||||
class GuiInspectorTypeColor : public GuiInspectorField
|
||||
{
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
protected:
|
||||
|
||||
/// Return the name of a function that will be used to convert the
|
||||
/// floating-point color of the swatch button to the form used by the
|
||||
/// data field.
|
||||
virtual const char* _getColorConversionFunction() const { return NULL; }
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeColor();
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeColor);
|
||||
|
||||
StringTableEntry mColorFunction;
|
||||
GuiSwatchButtonCtrl *mBrowseButton;
|
||||
RectI mBrowseRect;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeColorI GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeColorI : public GuiInspectorTypeColor
|
||||
{
|
||||
typedef GuiInspectorTypeColor Parent;
|
||||
|
||||
protected:
|
||||
|
||||
virtual const char* _getColorConversionFunction() const { return "ColorFloatToInt"; }
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeColorI();
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeColorI);
|
||||
|
||||
static void consoleInit();
|
||||
void setValue( StringTableEntry newValue );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeColorF GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeColorF : public GuiInspectorTypeColor
|
||||
{
|
||||
typedef GuiInspectorTypeColor Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeColorF();
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeColorF);
|
||||
|
||||
static void consoleInit();
|
||||
void setValue( StringTableEntry newValue );
|
||||
};
|
||||
|
||||
/* NOTE: Evidently this isn't used anywhere (or implemented) so i commented it out
|
||||
//------------------------------------------------------------------------------
|
||||
// TypeString GuiInspectorField class
|
||||
//------------------------------------------------------------------------------
|
||||
class GuiInspectorTypeString : public GuiInspectorField
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorField Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeString);
|
||||
static void consoleInit();
|
||||
|
||||
SimObjectPtr<GuiButtonCtrl> mBrowseButton;
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
virtual bool updateRects();
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TypeS32 GuiInspectorField class
|
||||
//------------------------------------------------------------------------------
|
||||
class GuiInspectorTypeS32 : public GuiInspectorField
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorField Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeS32);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual void setValue( StringTableEntry newValue );
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TypeBitMask32 GuiInspectorField class
|
||||
//------------------------------------------------------------------------------
|
||||
class GuiInspectorTypeBitMask32Helper;
|
||||
class GuiDynamicCtrlArrayControl;
|
||||
|
||||
class GuiInspectorTypeBitMask32 : public GuiInspectorField
|
||||
{
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeBitMask32();
|
||||
virtual ~GuiInspectorTypeBitMask32() {}
|
||||
|
||||
DECLARE_CONOBJECT( GuiInspectorTypeBitMask32 );
|
||||
|
||||
// ConsoleObject
|
||||
bool onAdd();
|
||||
static void consoleInit();
|
||||
|
||||
// GuiInspectorField
|
||||
virtual void childResized( GuiControl *child );
|
||||
virtual bool resize( const Point2I &newPosition, const Point2I &newExtent );
|
||||
virtual bool updateRects();
|
||||
virtual void updateData();
|
||||
virtual StringTableEntry getValue();
|
||||
virtual void setValue( StringTableEntry value );
|
||||
|
||||
protected:
|
||||
|
||||
GuiInspectorTypeBitMask32Helper *mHelper;
|
||||
GuiRolloutCtrl *mRollout;
|
||||
GuiDynamicCtrlArrayControl *mArrayCtrl;
|
||||
Vector<GuiInspectorField*> mChildren;
|
||||
};
|
||||
|
||||
class GuiInspectorTypeBitMask32Helper : public GuiInspectorField
|
||||
{
|
||||
typedef GuiInspectorField Parent;
|
||||
|
||||
public:
|
||||
|
||||
GuiInspectorTypeBitMask32Helper();
|
||||
|
||||
DECLARE_CONOBJECT( GuiInspectorTypeBitMask32Helper );
|
||||
|
||||
GuiBitmapButtonCtrl *mButton;
|
||||
GuiRolloutCtrl *mParentRollout;
|
||||
GuiInspectorTypeBitMask32 *mParentField;
|
||||
RectI mButtonRect;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Override able methods for custom edit fields
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool resize( const Point2I &newPosition, const Point2I &newExtent );
|
||||
virtual bool updateRects();
|
||||
virtual void setValue( StringTableEntry value );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeName : public GuiInspectorField
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorField Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeName);
|
||||
static void consoleInit();
|
||||
|
||||
virtual bool verifyData( StringTableEntry data );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeSFXParameterName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeSFXParameterName : public GuiInspectorTypeMenuBase
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorTypeMenuBase Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeSFXParameterName);
|
||||
static void consoleInit();
|
||||
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeSFXStateName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeSFXStateName : public GuiInspectorTypeMenuBase
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorTypeMenuBase Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeSFXStateName);
|
||||
static void consoleInit();
|
||||
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeSFXSourceName GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeSFXSourceName : public GuiInspectorTypeMenuBase
|
||||
{
|
||||
private:
|
||||
typedef GuiInspectorTypeMenuBase Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeSFXSourceName);
|
||||
static void consoleInit();
|
||||
|
||||
virtual void _populateMenu( GuiPopUpMenuCtrl *menu );
|
||||
};
|
||||
|
||||
|
||||
#endif // _GUI_INSPECTOR_TYPES_H_
|
||||
1943
Engine/source/gui/editor/guiMenuBar.cpp
Normal file
1943
Engine/source/gui/editor/guiMenuBar.cpp
Normal file
File diff suppressed because it is too large
Load diff
222
Engine/source/gui/editor/guiMenuBar.h
Normal file
222
Engine/source/gui/editor/guiMenuBar.h
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIMENUBAR_H_
|
||||
#define _GUIMENUBAR_H_
|
||||
|
||||
#ifndef _GUITEXTLISTCTRL_H_
|
||||
#include "gui/controls/guiTextListCtrl.h"
|
||||
#endif
|
||||
#ifndef _GUITICKCTRL_H_
|
||||
#include "gui/shiny/guiTickCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiMenuBar;
|
||||
class GuiMenuTextListCtrl;
|
||||
|
||||
class GuiMenuBackgroundCtrl : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
GuiMenuBar *mMenuBarCtrl;
|
||||
GuiMenuTextListCtrl *mTextList;
|
||||
public:
|
||||
GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseMove(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
};
|
||||
|
||||
class GuiSubmenuBackgroundCtrl : public GuiMenuBackgroundCtrl
|
||||
{
|
||||
typedef GuiMenuBackgroundCtrl Parent;
|
||||
|
||||
public:
|
||||
GuiSubmenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList);
|
||||
bool pointInControl(const Point2I & parentCoordPoint);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class GuiMenuTextListCtrl : public GuiTextListCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextListCtrl Parent;
|
||||
|
||||
protected:
|
||||
GuiMenuBar *mMenuBarCtrl;
|
||||
|
||||
public:
|
||||
bool isSubMenu; // Indicates that this text list is in a submenu
|
||||
|
||||
GuiMenuTextListCtrl(); // for inheritance
|
||||
GuiMenuTextListCtrl(GuiMenuBar *ctrl);
|
||||
|
||||
// GuiControl overloads:
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
|
||||
|
||||
virtual void onCellHighlighted(Point2I cell); // Added
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class GuiMenuBar : public GuiTickCtrl // Was: GuiControl
|
||||
{
|
||||
typedef GuiTickCtrl Parent; // Was: GuiControl Parent;
|
||||
public:
|
||||
|
||||
struct Menu;
|
||||
|
||||
struct MenuItem // an individual item in a pull-down menu
|
||||
{
|
||||
char *text; // the text of the menu item
|
||||
U32 id; // a script-assigned identifier
|
||||
char *accelerator; // the keyboard accelerator shortcut for the menu item
|
||||
U32 acceleratorIndex; // index of this accelerator
|
||||
bool enabled; // true if the menu item is selectable
|
||||
bool visible; // true if the menu item is visible
|
||||
S32 bitmapIndex; // index of the bitmap in the bitmap array
|
||||
S32 checkGroup; // the group index of the item visa vi check marks -
|
||||
// only one item in the group can be checked.
|
||||
MenuItem *nextMenuItem; // next menu item in the linked list
|
||||
|
||||
bool isSubmenu; // This menu item has a submenu that will be displayed
|
||||
MenuItem *firstSubmenuItem; // The first menu item in the submenu
|
||||
|
||||
Menu* submenuParentMenu; // For a submenu, this is the parent menu
|
||||
};
|
||||
|
||||
struct Menu
|
||||
{
|
||||
char *text;
|
||||
U32 id;
|
||||
RectI bounds;
|
||||
bool visible;
|
||||
|
||||
S32 bitmapIndex; // Index of the bitmap in the bitmap array (-1 = no bitmap)
|
||||
bool drawBitmapOnly; // Draw only the bitmap and not the text
|
||||
bool drawBorder; // Should a border be drawn around this menu (usually if we only have a bitmap, we don't want a border)
|
||||
|
||||
Menu *nextMenu;
|
||||
MenuItem *firstMenuItem;
|
||||
};
|
||||
|
||||
GuiMenuBackgroundCtrl *mBackground;
|
||||
GuiMenuTextListCtrl *mTextList;
|
||||
|
||||
GuiSubmenuBackgroundCtrl *mSubmenuBackground; // Background for a submenu
|
||||
GuiMenuTextListCtrl *mSubmenuTextList; // Text list for a submenu
|
||||
|
||||
Menu *menuList;
|
||||
Menu *mouseDownMenu;
|
||||
Menu *mouseOverMenu;
|
||||
|
||||
MenuItem* mouseDownSubmenu; // Stores the menu item that is a submenu that has been selected
|
||||
MenuItem* mouseOverSubmenu; // Stores the menu item that is a submenu that has been highlighted
|
||||
|
||||
bool menuBarDirty;
|
||||
U32 mCurAcceleratorIndex;
|
||||
Point2I maxBitmapSize;
|
||||
|
||||
S32 mCheckmarkBitmapIndex; // Index in the bitmap array to use for the check mark image
|
||||
|
||||
S32 mPadding;
|
||||
S32 mHorizontalMargin; // Left and right margin around the text of each menu
|
||||
S32 mVerticalMargin; // Top and bottom margin around the text of each menu
|
||||
S32 mBitmapMargin; // Margin between a menu's bitmap and text
|
||||
|
||||
// Used to keep track of the amount of ticks that the mouse is hovering
|
||||
// over a menu.
|
||||
S32 mMouseOverCounter;
|
||||
bool mCountMouseOver;
|
||||
S32 mMouseHoverAmount;
|
||||
|
||||
GuiMenuBar();
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
// internal menu handling functions
|
||||
// these are used by the script manipulation functions to add/remove/change menu items
|
||||
|
||||
void addMenu(const char *menuText, U32 menuId);
|
||||
Menu *findMenu(const char *menu); // takes either a menu text or a string id
|
||||
MenuItem *findMenuItem(Menu *menu, const char *menuItem); // takes either a menu text or a string id
|
||||
void removeMenu(Menu *menu);
|
||||
void removeMenuItem(Menu *menu, MenuItem *menuItem);
|
||||
void addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup);
|
||||
void clearMenuItems(Menu *menu);
|
||||
void clearMenus();
|
||||
|
||||
// Methods to deal with submenus
|
||||
MenuItem* findSubmenuItem(Menu *menu, const char *menuItem, const char *submenuItem);
|
||||
void addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup);
|
||||
void removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem);
|
||||
void clearSubmenuItems(MenuItem *menuitem);
|
||||
void onSubmenuAction(S32 selectionIndex, RectI bounds, Point2I cellSize);
|
||||
void closeSubmenu();
|
||||
void checkSubmenuMouseMove(const GuiEvent &event);
|
||||
MenuItem *findHitMenuItem(Point2I mousePoint);
|
||||
|
||||
void highlightedMenuItem(S32 selectionIndex, RectI bounds, Point2I cellSize); // Called whenever a menu item is highlighted by the mouse
|
||||
|
||||
// display/mouse functions
|
||||
|
||||
Menu *findHitMenu(Point2I mousePoint);
|
||||
|
||||
// Called when the GUI theme changes and a bitmap arrary may need updating
|
||||
// void onThemeChange();
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
|
||||
void checkMenuMouseMove(const GuiEvent &event);
|
||||
void onMouseMove(const GuiEvent &event);
|
||||
void onMouseLeave(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
|
||||
void onAction();
|
||||
void closeMenu();
|
||||
void buildAcceleratorMap();
|
||||
void acceleratorKeyPress(U32 index);
|
||||
|
||||
void menuItemSelected(Menu *menu, MenuItem *item);
|
||||
|
||||
// Added to support 'ticks'
|
||||
void processTick();
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT(GuiMenuBar);
|
||||
DECLARE_CALLBACK( void, onMouseInMenu, (bool hasLeftMenu));
|
||||
DECLARE_CALLBACK( void, onMenuSelect, (const char* menuId, const char* menuText));
|
||||
DECLARE_CALLBACK( void, onMenuItemSelect, ( const char* menuId, const char* menuText, const char* menuItemId, const char* menuItemText ));
|
||||
DECLARE_CALLBACK( void, onSubmenuSelect, ( const char* submenuId, const char* submenuText));
|
||||
};
|
||||
|
||||
#endif
|
||||
1453
Engine/source/gui/editor/guiParticleGraphCtrl.cpp
Normal file
1453
Engine/source/gui/editor/guiParticleGraphCtrl.cpp
Normal file
File diff suppressed because it is too large
Load diff
175
Engine/source/gui/editor/guiParticleGraphCtrl.h
Normal file
175
Engine/source/gui/editor/guiParticleGraphCtrl.h
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIPARTICLEGRAPHCTRL_H_
|
||||
#define _GUIPARTICLEGRAPHCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
#ifndef _STRINGTABLE_H_
|
||||
#include "core/stringTable.h"
|
||||
#endif
|
||||
|
||||
|
||||
class GuiParticleGraphCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
/// The color of the nuts.
|
||||
ColorI mNutColor;
|
||||
/// The outline color of the nuts.
|
||||
ColorI mOutlineColor;
|
||||
/// The rectangle size to check for clicks on nuts (default 8) which is RectI( pointClick - 4, pointClick - 4, 8, 8 )
|
||||
S32 mVertexClickSize;
|
||||
|
||||
Point2I findHitNut( Point2I hitPoint );
|
||||
|
||||
public:
|
||||
enum Constants {
|
||||
MaxPlots = 32,
|
||||
MaxDataPoints = 200
|
||||
};
|
||||
|
||||
enum GraphType {
|
||||
Point,
|
||||
Polyline,
|
||||
Filled,
|
||||
Bar
|
||||
};
|
||||
|
||||
struct PlotInfo
|
||||
{
|
||||
ColorF mGraphColor;
|
||||
Vector<Point2F> mGraphData;
|
||||
Vector<Point2F> mNutList;
|
||||
Point2F mGraphMax;
|
||||
Point2F mGraphMin;
|
||||
GraphType mGraphType;
|
||||
StringTableEntry mGraphName;
|
||||
bool mHidden;
|
||||
F32 mGraphScale;
|
||||
};
|
||||
|
||||
S32 mSelectedPlot;
|
||||
S32 mSelectedPoint;
|
||||
S32 mOriginalSelectedPoint;
|
||||
S32 mLastSelectedPoint;
|
||||
S32 mTooltipSelectedPlot;
|
||||
S32 mAddedPointIndex;
|
||||
bool mAutoMax;
|
||||
bool mAutoRemove;
|
||||
bool mRenderAllPoints;
|
||||
bool mPointWasAdded;
|
||||
bool mRenderGraphTooltip;
|
||||
bool mRenderNextGraphTooltip;
|
||||
bool mPointXMovementClamped;
|
||||
Point2F mAddedPoint;
|
||||
Point2F mLastMousePos;
|
||||
|
||||
Point2I mCursorPos;
|
||||
|
||||
PlotInfo mPlots[MaxPlots];
|
||||
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiParticleGraphCtrl);
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
|
||||
GuiParticleGraphCtrl();
|
||||
virtual ~GuiParticleGraphCtrl() { };
|
||||
|
||||
void onMouseMove(const GuiEvent &event);
|
||||
void onMouseDown( const GuiEvent &event );
|
||||
void onMouseUp( const GuiEvent &event );
|
||||
void onMouseDragged( const GuiEvent &event );
|
||||
void onRightMouseDown( const GuiEvent &event );
|
||||
void onRightMouseUp( const GuiEvent &event );
|
||||
void onRightMouseDragged( const GuiEvent &event );
|
||||
|
||||
//Parental methods
|
||||
bool onWake();
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
bool renderGraphTooltip(Point2I cursorPos, StringTableEntry tooltip);
|
||||
|
||||
// Graph interface
|
||||
S32 addPlotPoint(S32 plotID, Point2F v, bool setAdded = true);
|
||||
void insertPlotPoint(S32 plotID, S32 i, Point2F v);
|
||||
S32 changePlotPoint(S32 plotID, S32 i, Point2F v);
|
||||
S32 removePlotPoint(S32 plotID, S32 i);
|
||||
Point2F convertToGraphCoord(S32 plotID, Point2I v);
|
||||
|
||||
// Set Graph specific functions
|
||||
void setGraphType(S32 plotID, const char *graphType);
|
||||
void setSelectedPlot(S32 plotID);
|
||||
void setSelectedPoint(S32 point);
|
||||
void resetSelectedPoint();
|
||||
void setGraphHidden(S32 plotID, bool isHidden);
|
||||
|
||||
// Set Global Options
|
||||
void setAutoGraphMax(bool autoMax);
|
||||
void setAutoRemove(bool autoRemove);
|
||||
void setRenderAll(bool renderAll);
|
||||
void setRenderGraphTooltip(bool renderGraphTooltip);
|
||||
void setPointXMovementClamped(bool clamped);
|
||||
|
||||
// Get Functions
|
||||
Point2F getGraphExtent(S32 plotID);
|
||||
ColorF getGraphColor(S32 plotID);
|
||||
S32 getSelectedPlot();
|
||||
S32 getSelectedPoint();
|
||||
Point2F getPlotPoint(S32 plotID, S32 samples);
|
||||
S32 getPlotIndex(S32 plotID, F32 x, F32 y);
|
||||
Point2F getGraphMax(S32 plotID);
|
||||
Point2F getGraphMin(S32 plotID);
|
||||
|
||||
bool isExistingPoint(S32 plotID, S32 point);
|
||||
|
||||
StringTableEntry getGraphName(S32 plotID);
|
||||
|
||||
// Set Graph Min and MaxFunctions
|
||||
void setGraphMin(S32 plotID, Point2F graphMin);
|
||||
void setGraphMinX(S32 plotID, F32 graphMinX);
|
||||
void setGraphMinY(S32 plotID, F32 graphMinY);
|
||||
void setGraphMax(S32 plotID, Point2F graphMax);
|
||||
void setGraphMaxX(S32 plotID, F32 graphMaxX);
|
||||
void setGraphMaxY(S32 plotID, F32 graphMaxY);
|
||||
|
||||
// Other set functions for graphs
|
||||
void setGraphName(S32 plotID, StringTableEntry graphName);
|
||||
|
||||
|
||||
// Clear Functions
|
||||
void clearGraph(S32 plotID);
|
||||
void clearAllGraphs();
|
||||
|
||||
// Selection nuts.
|
||||
bool inNut( const Point2I &pt, S32 x, S32 y );
|
||||
void drawNut( const Point2I &nut, S32 size, ColorI &outlineColor, ColorI &nutColor );
|
||||
};
|
||||
|
||||
typedef GuiParticleGraphCtrl::GraphType GuiParticleGraphType;
|
||||
DefineEnumType( GuiParticleGraphType );
|
||||
|
||||
#endif
|
||||
318
Engine/source/gui/editor/guiRectHandles.cpp
Normal file
318
Engine/source/gui/editor/guiRectHandles.cpp
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
|
||||
#include "gui/editor/guiRectHandles.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiRectHandles);
|
||||
|
||||
ConsoleDocClass( GuiRectHandles,
|
||||
"@brief Draws a box with handles for the user to manipulate.\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GuiRectHandles::GuiRectHandles() : GuiControl()
|
||||
{
|
||||
mHandleRect.set(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
mHandleSize = 10;
|
||||
mUseCustomColor = false;
|
||||
mHandleColor.set(100,100,100);
|
||||
mHitHandle = 0;
|
||||
}
|
||||
|
||||
GuiRectHandles::~GuiRectHandles()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiRectHandles::initPersistFields()
|
||||
{
|
||||
addField("handleRect", TypeRectF, Offset(mHandleRect, GuiRectHandles), "RectF of handle's box." );
|
||||
addField("handleSize", TypeS32, Offset(mHandleSize, GuiRectHandles), "Size of handles in pixels." );
|
||||
addField("useCustomColor", TypeBool, Offset(mUseCustomColor, GuiRectHandles), "Use given custom color for handles." );
|
||||
addField("handleColor", TypeColorI, Offset(mHandleColor, GuiRectHandles), "Use given custom color for handles." );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void GuiRectHandles::onMouseUp(const GuiEvent &event)
|
||||
{
|
||||
mHitHandle = 0;
|
||||
}
|
||||
|
||||
void GuiRectHandles::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
// The handles range from 0-1, so scale to fit within the
|
||||
// control's bounds.
|
||||
const Point2I& extent = getExtent();
|
||||
Point2I pos(extent.x*mHandleRect.point.x, extent.y*mHandleRect.point.y);
|
||||
Point2I size(extent.x*mHandleRect.extent.x, extent.y*mHandleRect.extent.y);
|
||||
RectI box(pos, size);
|
||||
|
||||
Point2I localMousePoint = globalToLocalCoord(event.mousePoint);
|
||||
|
||||
// Check if mouse is within handle rect
|
||||
if(!box.pointInRect(localMousePoint))
|
||||
{
|
||||
mHitHandle = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Point2I normalizedMouse = localMousePoint - pos;
|
||||
Point2I halfSize = size / 2;
|
||||
S32 halfHandleSize = mHandleSize / 2;
|
||||
if(normalizedMouse.y < mHandleSize)
|
||||
{
|
||||
// Top handles
|
||||
if(normalizedMouse.x < mHandleSize)
|
||||
mHitHandle = 1;
|
||||
else if(normalizedMouse.x >= (size.x-mHandleSize))
|
||||
mHitHandle = 3;
|
||||
else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize))
|
||||
mHitHandle = 2;
|
||||
}
|
||||
else if(normalizedMouse.y >= (size.y-mHandleSize))
|
||||
{
|
||||
// Bottom handles
|
||||
if(normalizedMouse.x < mHandleSize)
|
||||
mHitHandle = 7;
|
||||
else if(normalizedMouse.x >= (size.x-mHandleSize))
|
||||
mHitHandle = 5;
|
||||
else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize))
|
||||
mHitHandle = 6;
|
||||
}
|
||||
else if(normalizedMouse.y >= (halfSize.y-halfHandleSize) && normalizedMouse.y < (halfSize.y+halfHandleSize))
|
||||
{
|
||||
// Middle handles
|
||||
if(normalizedMouse.x < mHandleSize)
|
||||
mHitHandle = 8;
|
||||
else if(normalizedMouse.x >= (size.x-mHandleSize))
|
||||
mHitHandle = 4;
|
||||
else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize))
|
||||
mHitHandle = 9;
|
||||
}
|
||||
|
||||
mHitPoint = localMousePoint;
|
||||
}
|
||||
|
||||
void GuiRectHandles::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
if(mHitHandle == 0)
|
||||
return;
|
||||
|
||||
// The handles range from 0-1, so scale to fit within the
|
||||
// control's bounds.
|
||||
const Point2I& extent = getExtent();
|
||||
|
||||
Point2I localMousePoint = globalToLocalCoord(event.mousePoint);
|
||||
|
||||
Point2I diffI = localMousePoint - mHitPoint;
|
||||
Point2F diffF(diffI.x/F32(extent.x), diffI.y/F32(extent.y));
|
||||
|
||||
RectF box(mHandleRect);
|
||||
bool postMoveExtentX = false;
|
||||
bool postMoveExtentY = false;
|
||||
bool keepExtent = false;
|
||||
|
||||
switch(mHitHandle)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
// Top left
|
||||
box.point += diffF;
|
||||
postMoveExtentX = true;
|
||||
postMoveExtentY = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
// Top middle
|
||||
box.point.y += diffF.y;
|
||||
postMoveExtentY = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
// Top right
|
||||
box.point.y += diffF.y;
|
||||
box.extent.x += diffF.x;
|
||||
postMoveExtentY = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
// Middle right
|
||||
box.extent.x += diffF.x;
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
// Bottom right
|
||||
box.extent += diffF;
|
||||
break;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
// Bottom middle
|
||||
box.extent.y += diffF.y;
|
||||
break;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
// Bottom left
|
||||
box.point.x += diffF.x;
|
||||
box.extent.y += diffF.y;
|
||||
postMoveExtentX = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
// Middle left
|
||||
box.point.x += diffF.x;
|
||||
postMoveExtentX = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 9:
|
||||
{
|
||||
// Centre
|
||||
box.point += diffF;
|
||||
keepExtent = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Position limits
|
||||
if(box.point.x < 0.0f)
|
||||
box.point.x = 0.0f;
|
||||
else if(box.point.x > 1.0f)
|
||||
box.point.x = 1.0f;
|
||||
|
||||
if(box.point.y < 0.0f)
|
||||
box.point.y = 0.0f;
|
||||
else if(box.point.y > 1.0f)
|
||||
box.point.y = 1.0f;
|
||||
|
||||
// Move any extent to counter a change in handle position. Do this
|
||||
// after the limits above to make sure the extent doesn't accidentally
|
||||
// grow when the position is clamped.
|
||||
if(postMoveExtentX)
|
||||
box.extent.x += mHandleRect.point.x - box.point.x;
|
||||
if(postMoveExtentY)
|
||||
box.extent.y += mHandleRect.point.y - box.point.y;
|
||||
|
||||
// Extent limits
|
||||
if(box.extent.x < 0.0f)
|
||||
box.extent.x = 0.0f;
|
||||
else if(box.extent.x > 1.0f)
|
||||
box.extent.x = 1.0f;
|
||||
if(box.point.x+box.extent.x > 1.0f)
|
||||
{
|
||||
if(keepExtent)
|
||||
box.point.x = 1.0f-box.extent.x;
|
||||
else
|
||||
box.extent.x = 1.0f-box.point.x;
|
||||
}
|
||||
|
||||
if(box.extent.y < 0.0f)
|
||||
box.extent.y = 0.0f;
|
||||
else if(box.extent.y > 1.0f)
|
||||
box.extent.y = 1.0f;
|
||||
if(box.point.y+box.extent.y > 1.0f)
|
||||
{
|
||||
if(keepExtent)
|
||||
box.point.y = 1.0f-box.extent.y;
|
||||
else
|
||||
box.extent.y = 1.0f-box.point.y;
|
||||
}
|
||||
|
||||
mHandleRect = box;
|
||||
mHitPoint = localMousePoint;
|
||||
|
||||
if( isMethod( "onHandleRectChange" ) )
|
||||
Con::executef(this, "onHandleRectChange" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiRectHandles::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
Parent::onRender( offset, updateRect );
|
||||
|
||||
ColorI handleColor = mProfile->mBorderColor;
|
||||
if(mUseCustomColor)
|
||||
handleColor = mHandleColor;
|
||||
|
||||
// The handles range from 0-1, so scale to fit within the
|
||||
// control's bounds.
|
||||
const Point2I& extent = getExtent();
|
||||
Point2I pos(extent.x*mHandleRect.point.x, extent.y*mHandleRect.point.y);
|
||||
Point2I size(extent.x*mHandleRect.extent.x, extent.y*mHandleRect.extent.y);
|
||||
RectI box(offset+pos, size);
|
||||
|
||||
// Draw border
|
||||
GFX->getDrawUtil()->drawRect(box, handleColor);
|
||||
|
||||
// Draw each handle
|
||||
Point2I handleSize(mHandleSize, mHandleSize);
|
||||
RectI handleRect(box.point, handleSize);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Upper left
|
||||
handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Upper right
|
||||
handleRect.point = Point2I(box.point.x, box.point.y+size.y-handleSize.y);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Lower left
|
||||
handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y+size.y-handleSize.y);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Lower right
|
||||
|
||||
Point2I halfSize = size / 2;
|
||||
Point2I halfHandleSize = handleSize / 2;
|
||||
handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Upper middle
|
||||
handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y+size.y-handleSize.y);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Lower middle
|
||||
handleRect.point = Point2I(box.point.x, box.point.y+halfSize.y-halfHandleSize.y);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Left middle
|
||||
handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y+halfSize.y-halfHandleSize.y);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Right middle
|
||||
|
||||
handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y+halfSize.y-halfHandleSize.y);
|
||||
GFX->getDrawUtil()->drawRectFill(handleRect, handleColor); // Middle
|
||||
|
||||
renderChildControls(offset, updateRect);
|
||||
}
|
||||
59
Engine/source/gui/editor/guiRectHandles.h
Normal file
59
Engine/source/gui/editor/guiRectHandles.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUIRECTHANDLES_H_
|
||||
#define _GUIRECTHANDLES_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiRectHandles : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
RectF mHandleRect;
|
||||
S32 mHandleSize;
|
||||
bool mUseCustomColor;
|
||||
ColorI mHandleColor;
|
||||
S32 mHitHandle; // 0 = none, 1-8 = clockwise circle starting upper left, 9 = centre
|
||||
Point2I mHitPoint;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiRectHandles);
|
||||
DECLARE_CATEGORY( "Gui Other" );
|
||||
DECLARE_DESCRIPTION( "Draws a box with handles for the user to manipulate.");
|
||||
|
||||
GuiRectHandles();
|
||||
virtual ~GuiRectHandles();
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
virtual void onMouseUp(const GuiEvent &event);
|
||||
virtual void onMouseDown(const GuiEvent &event);
|
||||
virtual void onMouseDragged(const GuiEvent &event);
|
||||
|
||||
virtual void onRender(Point2I offset, const RectI &updateRect);
|
||||
};
|
||||
|
||||
#endif
|
||||
142
Engine/source/gui/editor/guiSeparatorCtrl.cpp
Normal file
142
Engine/source/gui/editor/guiSeparatorCtrl.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/guiSeparatorCtrl.h"
|
||||
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gui/core/guiCanvas.h"
|
||||
#include "gui/core/guiDefaultControlRender.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiSeparatorCtrl);
|
||||
|
||||
ConsoleDocClass( GuiSeparatorCtrl,
|
||||
"@brief A control that renders a horizontal or vertical separator with "
|
||||
"an optional text label (horizontal only)\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"new GuiSeparatorCtrl()\n"
|
||||
"{\n"
|
||||
" profile = \"GuiDefaultProfile\";\n"
|
||||
" position = \"505 0\";\n"
|
||||
" extent = \"10 17\";\n"
|
||||
" minExtent = \"10 17\";\n"
|
||||
" canSave = \"1\";\n"
|
||||
" visible = \"1\";\n"
|
||||
" horizSizing = \"left\";\n"
|
||||
"};\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@ingroup GuiControls\n");
|
||||
|
||||
ImplementEnumType( GuiSeparatorType,
|
||||
"GuiSeparatorCtrl orientations\n\n"
|
||||
"@ingroup GuiControls" )
|
||||
{ GuiSeparatorCtrl::separatorTypeVertical, "Vertical" },
|
||||
{ GuiSeparatorCtrl::separatorTypeHorizontal,"Horizontal" }
|
||||
EndImplementEnumType;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GuiSeparatorCtrl::GuiSeparatorCtrl() : GuiControl()
|
||||
{
|
||||
mInvisible = false;
|
||||
mTextLeftMargin = 0;
|
||||
mMargin = 2;
|
||||
setExtent( 12, 35 );
|
||||
mSeparatorType = GuiSeparatorCtrl::separatorTypeVertical;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiSeparatorCtrl::initPersistFields()
|
||||
{
|
||||
addField("caption", TypeRealString, Offset(mText, GuiSeparatorCtrl),
|
||||
"Optional text label to display." );
|
||||
addField("type", TYPEID< separatorTypeOptions >(), Offset(mSeparatorType, GuiSeparatorCtrl),
|
||||
"Orientation of separator." );
|
||||
addField("borderMargin", TypeS32, Offset(mMargin, GuiSeparatorCtrl));
|
||||
addField("invisible", TypeBool, Offset(mInvisible, GuiSeparatorCtrl));// Nonsense. Should use GuiControl's visibility.
|
||||
addField("leftMargin", TypeS32, Offset(mTextLeftMargin, GuiSeparatorCtrl),
|
||||
"Left margin of text label." );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiSeparatorCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
Parent::onRender( offset, updateRect );
|
||||
|
||||
if( mInvisible )
|
||||
return;
|
||||
|
||||
if( mText.isNotEmpty() && mSeparatorType != separatorTypeVertical )
|
||||
{
|
||||
// If text is present and we have a left margin, then draw some separator, then the
|
||||
// text, and then the rest of the separator.
|
||||
|
||||
S32 posx = offset.x + mMargin;
|
||||
S32 fontheight = mProfile->mFont->getHeight();
|
||||
S32 seppos = (fontheight - 2) / 2 + offset.y;
|
||||
if( mTextLeftMargin > 0 )
|
||||
{
|
||||
RectI rect( Point2I( posx, seppos ), Point2I( mTextLeftMargin, 2 ) );
|
||||
renderSlightlyLoweredBox(rect, mProfile);
|
||||
posx += mTextLeftMargin;
|
||||
}
|
||||
|
||||
GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColor );
|
||||
posx = GFX->getDrawUtil()->drawText(mProfile->mFont, Point2I(posx,offset.y), mText, mProfile->mFontColors);
|
||||
|
||||
RectI rect( Point2I( posx, seppos ), Point2I( getWidth() - posx + offset.x, 2 ) );
|
||||
|
||||
// Space text and separator a bit apart at right end.
|
||||
|
||||
rect.point.x += 2;
|
||||
rect.extent.x -= 2;
|
||||
|
||||
if( rect.extent.x > 0 )
|
||||
renderSlightlyLoweredBox( rect, mProfile );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mSeparatorType == separatorTypeHorizontal )
|
||||
{
|
||||
S32 seppos = getHeight() / 2 + offset.y;
|
||||
RectI rect(Point2I(offset.x + mMargin ,seppos),Point2I(getWidth() - (mMargin * 2),2));
|
||||
renderSlightlyLoweredBox(rect, mProfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 seppos = getWidth() / 2 + offset.x;
|
||||
RectI rect(Point2I(seppos, offset.y + mMargin),Point2I(2, getHeight() - (mMargin * 2)));
|
||||
renderSlightlyLoweredBox(rect, mProfile);
|
||||
}
|
||||
}
|
||||
|
||||
renderChildControls(offset, updateRect);
|
||||
}
|
||||
|
||||
|
||||
67
Engine/source/gui/editor/guiSeparatorCtrl.h
Normal file
67
Engine/source/gui/editor/guiSeparatorCtrl.h
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.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef _GUISEPARATORCTRL_H_
|
||||
#define _GUISEPARATORCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
#ifndef _DYNAMIC_CONSOLETYPES_H_
|
||||
#include "console/dynamicTypes.h"
|
||||
#endif
|
||||
|
||||
|
||||
/// Renders a separator line with optional text.
|
||||
class GuiSeparatorCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
public:
|
||||
bool mInvisible;
|
||||
String mText;
|
||||
S32 mTextLeftMargin;
|
||||
S32 mMargin;
|
||||
S32 mSeparatorType;
|
||||
|
||||
enum separatorTypeOptions
|
||||
{
|
||||
separatorTypeVertical = 0, ///< Draw Vertical Separator
|
||||
separatorTypeHorizontal ///< Horizontal Separator
|
||||
};
|
||||
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiSeparatorCtrl);
|
||||
DECLARE_CATEGORY( "Gui Other" );
|
||||
DECLARE_DESCRIPTION( "A control that renders a horizontal or vertical separator with\n"
|
||||
"an optional text label (horizontal only). ");
|
||||
GuiSeparatorCtrl();
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
};
|
||||
|
||||
typedef GuiSeparatorCtrl::separatorTypeOptions GuiSeparatorType;
|
||||
DefineEnumType( GuiSeparatorType );
|
||||
|
||||
#endif
|
||||
1861
Engine/source/gui/editor/guiShapeEdPreview.cpp
Normal file
1861
Engine/source/gui/editor/guiShapeEdPreview.cpp
Normal file
File diff suppressed because it is too large
Load diff
262
Engine/source/gui/editor/guiShapeEdPreview.h
Normal file
262
Engine/source/gui/editor/guiShapeEdPreview.h
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GUISHAPEEDPREVIEW_H_
|
||||
#define _GUISHAPEEDPREVIEW_H_
|
||||
|
||||
#include "gui/worldEditor/editTSCtrl.h"
|
||||
#include "ts/tsShapeInstance.h"
|
||||
|
||||
class LightInfo;
|
||||
|
||||
class GuiShapeEdPreview : public EditTSCtrl
|
||||
{
|
||||
struct Thread
|
||||
{
|
||||
TSThread* key; //!< TSThread key
|
||||
String seqName; //!< Name of the sequence for this thread
|
||||
S32 direction; //!< Playback direction: -1 (reverse), 0 (paused), 1 (forward)
|
||||
bool pingpong; //!< Pingpong flag (auto-reverse direction at start/end)
|
||||
|
||||
Thread()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
key = NULL;
|
||||
direction = 1.0f;
|
||||
pingpong = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct MountedShape
|
||||
{
|
||||
enum eMountType
|
||||
{
|
||||
Object, //!< Mount origin of shape to target node
|
||||
Image, //!< Mount 'mountPoint' or origin of shape to target node
|
||||
Wheel, //!< Mount origin of shape to target node, ignore target node rotation
|
||||
};
|
||||
|
||||
TSShapeInstance* mShape; //!< The mounted shape instance
|
||||
S32 mNode; //!< Index of the node this shape is mounted to
|
||||
MatrixF mTransform; //!< Mount offset transform
|
||||
eMountType mType; //!< Type of mount
|
||||
Thread mThread; //!< Animation thread for the mounted shape
|
||||
|
||||
MountedShape() : mShape(0), mNode(-1), mTransform(true), mType(Object) { }
|
||||
~MountedShape() { delete mShape; }
|
||||
};
|
||||
|
||||
protected:
|
||||
typedef EditTSCtrl Parent;
|
||||
|
||||
// View and node selection
|
||||
bool mUsingAxisGizmo;
|
||||
bool mEditingSun; //!< True if editing the sun direction, false otherwise
|
||||
|
||||
S32 mGizmoDragID; //!< Used to track transform changes within a single gizmo drag action
|
||||
S32 mSelectedNode; //!< Index of the selected node
|
||||
S32 mHoverNode; //!< Index of the node the mouse is over
|
||||
Vector<Point3F> mProjectedNodes; //!< Projected screen positions of the model nodes
|
||||
|
||||
S32 mSelectedObject; //!< Name of the selected object
|
||||
S32 mSelectedObjDetail; //!< Detail mesh index of the selected object
|
||||
|
||||
// Camera
|
||||
EulerF mCameraRot;
|
||||
bool mRenderCameraAxes;
|
||||
Point3F mOrbitPos;
|
||||
F32 mOrbitDist;
|
||||
F32 mMoveSpeed;
|
||||
F32 mZoomSpeed;
|
||||
|
||||
// Current Detail
|
||||
bool mFixedDetail; //!< If false, the detail level will be determined based on camera distance
|
||||
S32 mCurrentDL; //!< Current detail level
|
||||
S32 mDetailSize; //!< Size of current detail level
|
||||
S32 mDetailPolys; //!< Number of polys (triangles) in current detail level
|
||||
F32 mPixelSize; //!< Current pixel size
|
||||
S32 mNumMaterials; //!< Number of materials in the current detail level
|
||||
S32 mNumDrawCalls; //!< Number of draw calls in the current detail level
|
||||
S32 mNumBones; //!< Number of bones in the current detail level (skins only)
|
||||
S32 mNumWeights; //!< Number of vertex weights in the current detail level (skins only)
|
||||
S32 mColMeshes; //!< Number of collision meshes
|
||||
S32 mColPolys; //!< Number of collision polygons (all meshes)
|
||||
|
||||
// Rendering
|
||||
Point2I mGridDimension; //!< Dimension of grid in perspective view (eg. 30x30)
|
||||
bool mRenderGhost;
|
||||
bool mRenderNodes;
|
||||
bool mRenderBounds;
|
||||
bool mRenderObjBox;
|
||||
bool mRenderColMeshes;
|
||||
bool mRenderMounts;
|
||||
TSShapeInstance* mModel;
|
||||
|
||||
LightInfo* mFakeSun;
|
||||
EulerF mSunRot;
|
||||
ColorI mSunDiffuseColor;
|
||||
ColorI mSunAmbientColor;
|
||||
|
||||
// Animation and playback control
|
||||
Vector<Thread> mThreads;
|
||||
F32 mTimeScale;
|
||||
S32 mActiveThread;
|
||||
S32 mLastRenderTime;
|
||||
|
||||
// Mounted objects
|
||||
Vector<MountedShape*> mMounts;
|
||||
|
||||
static bool setFieldCurrentDL( void *object, const char *index, const char *data );
|
||||
static bool setFieldSunDiffuse( void *object, const char *index, const char *data );
|
||||
static bool setFieldSunAmbient( void *object, const char *index, const char *data );
|
||||
static bool setFieldSunAngleX( void *object, const char *index, const char *data );
|
||||
static bool setFieldSunAngleZ( void *object, const char *index, const char *data );
|
||||
|
||||
static bool setFieldThreadPos( void *object, const char *index, const char *data );
|
||||
static bool setFieldThreadIn( void *object, const char *index, const char *data );
|
||||
static bool setFieldThreadOut( void *object, const char *index, const char *data );
|
||||
static bool setFieldThreadDir( void *object, const char *index, const char *data );
|
||||
static bool setFieldThreadPingPong( void *object, const char *index, const char *data );
|
||||
|
||||
static const char *getFieldThreadPos( void *object, const char *data );
|
||||
static const char *getFieldThreadIn( void *object, const char *data );
|
||||
static const char *getFieldThreadOut( void *object, const char *data );
|
||||
static const char *getFieldThreadDir( void *object, const char *data );
|
||||
static const char *getFieldThreadPingPong( void *object, const char *data );
|
||||
|
||||
// Generic mouse event handlers
|
||||
void handleMouseDown(const GuiEvent& event, GizmoMode mode);
|
||||
void handleMouseUp(const GuiEvent& event, GizmoMode mode);
|
||||
void handleMouseMove(const GuiEvent& event, GizmoMode mode);
|
||||
void handleMouseDragged(const GuiEvent& event, GizmoMode mode);
|
||||
|
||||
// Node picking
|
||||
S32 collideNode(const Gui3DMouseEvent& event) const;
|
||||
void updateProjectedNodePoints();
|
||||
|
||||
void updateSun();
|
||||
void updateDetailLevel(const SceneRenderState* state);
|
||||
void updateThreads(F32 delta);
|
||||
|
||||
// Rendering
|
||||
void renderGrid();
|
||||
void renderNodes() const;
|
||||
void renderNodeAxes(S32 index, const ColorF& nodeColor) const;
|
||||
void renderNodeName(S32 index, const ColorF& textColor) const;
|
||||
void renderSunDirection() const;
|
||||
void renderCollisionMeshes() const;
|
||||
|
||||
public:
|
||||
bool onWake();
|
||||
|
||||
void setDisplayType(S32 type);
|
||||
|
||||
/// @name Mouse event handlers
|
||||
///@{
|
||||
void onMouseDown(const GuiEvent& event) { handleMouseDown(event, NoneMode); }
|
||||
void onMouseUp(const GuiEvent& event) { handleMouseUp(event, NoneMode); }
|
||||
void onMouseMove(const GuiEvent& event) { handleMouseMove(event, NoneMode); }
|
||||
void onMouseDragged(const GuiEvent& event) { handleMouseDragged(event, NoneMode); }
|
||||
|
||||
void onMiddleMouseDown(const GuiEvent& event) { handleMouseDown(event, MoveMode); }
|
||||
void onMiddleMouseUp(const GuiEvent& event) { handleMouseUp(event, MoveMode); }
|
||||
void onMiddleMouseDragged(const GuiEvent& event) { handleMouseDragged(event, MoveMode); }
|
||||
|
||||
void onRightMouseDown(const GuiEvent& event) { handleMouseDown(event, RotateMode); }
|
||||
void onRightMouseUp(const GuiEvent& event) { handleMouseUp(event, RotateMode); }
|
||||
void onRightMouseDragged(const GuiEvent& event) { handleMouseDragged(event, RotateMode); }
|
||||
|
||||
void on3DMouseWheelUp(const Gui3DMouseEvent& event);
|
||||
void on3DMouseWheelDown(const Gui3DMouseEvent& event);
|
||||
///@}
|
||||
|
||||
// Setters/Getters
|
||||
TSShapeInstance* getModel() { return mModel; }
|
||||
|
||||
void setCurrentDetail(S32 dl);
|
||||
bool setObjectModel(const char * modelName);
|
||||
|
||||
/// @name Threads
|
||||
///@{
|
||||
void addThread();
|
||||
void removeThread(S32 slot);
|
||||
S32 getThreadCount() const { return mThreads.size(); }
|
||||
void setTimeScale(F32 scale);
|
||||
void setActiveThreadSequence(const char* seqName, F32 duration, F32 pos, bool play);
|
||||
void setThreadSequence(Thread& thread, TSShapeInstance* shape, const char * seqName, F32 duration=0.0f, F32 pos=0.0f, bool play=false);
|
||||
const char* getThreadSequence() const;
|
||||
void refreshThreadSequences();
|
||||
|
||||
DECLARE_CALLBACK( void, onThreadPosChanged, ( F32 pos, bool inTransition ) );
|
||||
///@}
|
||||
|
||||
/// @name Mounting
|
||||
///@{
|
||||
bool mountShape(const char* modelName, const char* nodeName, const char* mountType, S32 slot=-1);
|
||||
void setMountNode(S32 mountSlot, const char* nodeName);
|
||||
const char* getMountThreadSequence(S32 mountSlot) const;
|
||||
void setMountThreadSequence(S32 mountSlot, const char* seqName);
|
||||
F32 getMountThreadPos(S32 mountSlot) const;
|
||||
void setMountThreadPos(S32 mountSlot, F32 pos);
|
||||
F32 getMountThreadDir(S32 mountSlot) const;
|
||||
void setMountThreadDir(S32 mountSlot, F32 dir);
|
||||
void unmountShape(S32 mountSlot);
|
||||
void unmountAll();
|
||||
///@}
|
||||
|
||||
void refreshShape();
|
||||
void updateNodeTransforms();
|
||||
|
||||
void get3DCursor(GuiCursor *& cursor, bool& visible, const Gui3DMouseEvent& event_);
|
||||
|
||||
void fitToShape();
|
||||
void setOrbitPos( const Point3F& pos );
|
||||
|
||||
void exportToCollada( const String& path );
|
||||
|
||||
/// @name Rendering
|
||||
///@{
|
||||
bool getCameraTransform(MatrixF* cameraMatrix);
|
||||
void computeSceneBounds(Box3F& bounds);
|
||||
|
||||
bool getMeshHidden(const char* name) const;
|
||||
void setMeshHidden(const char* name, bool hidden);
|
||||
void setAllMeshesHidden(bool hidden);
|
||||
|
||||
void renderWorld(const RectI& updateRect);
|
||||
void renderGui(Point2I offset, const RectI& updateRect);
|
||||
///@}
|
||||
|
||||
DECLARE_CONOBJECT(GuiShapeEdPreview);
|
||||
DECLARE_CATEGORY( "Gui Editor" );
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
GuiShapeEdPreview();
|
||||
~GuiShapeEdPreview();
|
||||
};
|
||||
|
||||
#endif
|
||||
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