Merge branch 'development' of https://github.com/GarageGames/Torque3D into PBR_ProbeArrayGLWIP

# Conflicts:
#	Engine/source/gfx/D3D11/gfxD3D11Device.cpp
#	Engine/source/lighting/lightManager.cpp
#	Templates/Full/game/levels/Empty Room.mis
#	Templates/Full/game/levels/Empty Terrain.mis
This commit is contained in:
AzaezelX 2019-05-01 23:18:31 -05:00
commit 97ec99f704
235 changed files with 7064 additions and 3090 deletions

View file

@ -72,7 +72,7 @@ GuiSwatchButtonCtrl::GuiSwatchButtonCtrl()
void GuiSwatchButtonCtrl::initPersistFields()
{
addField("color", TypeColorF, Offset(mSwatchColor, GuiSwatchButtonCtrl), "The foreground color of GuiSwatchButtonCtrl");
addField( "gridBitmap", TypeString, Offset( mGridBitmap, GuiSwatchButtonCtrl ), "The bitmap used for the transparent grid" );
addField( "gridBitmap", TypeRealString, Offset( mGridBitmap, GuiSwatchButtonCtrl ), "The bitmap used for the transparent grid" );
Parent::initPersistFields();
}

View file

@ -613,3 +613,25 @@ void GuiSplitContainer::onMouseDragged( const GuiEvent &event )
solvePanelConstraints(newDragPos, firstPanel, secondPanel, clientRect);
}
}
void GuiSplitContainer::setSplitPoint(Point2I splitPoint)
{
GuiContainer *firstPanel = dynamic_cast<GuiContainer*>(at(0));
GuiContainer *secondPanel = dynamic_cast<GuiContainer*>(at(1));
// This function will constrain the panels to their minExtents and update the mSplitPoint
if (firstPanel && secondPanel)
{
RectI clientRect = getClientRect();
solvePanelConstraints(splitPoint, firstPanel, secondPanel, clientRect);
layoutControls(clientRect);
}
}
DefineEngineMethod(GuiSplitContainer, setSplitPoint, void, (Point2I splitPoint), ,
"Set the position of the split handle.")
{
object->setSplitPoint(splitPoint);
}

View file

@ -87,6 +87,9 @@ public:
virtual void solvePanelConstraints(Point2I newDragPos, GuiContainer * firstPanel, GuiContainer * secondPanel, const RectI& clientRect);
virtual Point2I getMinExtent() const;
//Set the positin of the split handler
void setSplitPoint(Point2I splitPoint);
protected:
S32 mFixedPanel;

View file

@ -0,0 +1,298 @@
//-----------------------------------------------------------------------------
// Gui3DProjectionCtrl
// Doppelganger Inc
// Orion Elenzil 200701
//
// This control is meant to be merely a container for other controls.
// What's neat is that it's easy to 'attach' this control to a point in world-space
// or, more interestingly, to an object such as a player.
//
// Usage:
// * Create the Gui3DProjectionControl - by default it will be at 0, 0, 0.
// * You can change where it's located by setting the field "offsetWorld".
// - note you can specify that right in the .gui file
// * You can attach it to any SceneObject by calling "setAttachedTo()".
//
// Behaviour:
// * If you're attaching it to a player, by default it will center on the player's head.
// * If you attach it to an object, by default it will delete itself if the object is deleted.
// * Doesn't occlude w/r/t 3D objects.
//
// Console Methods:
// * SetAttachedTo(SceneObject)
// * GetAttachedTo()
//
// Params:
// * pointWorld - read/write point in worldspace. read-only if attached to an object.
// * offsetObject - an offset in objectspace. default 0, 0, 0.
// * offsetWorld - an offset in worldspace. default 0, 0, 0.
// * offsetScreen - an offset in screenspace. default 0, 0.
// * hAlign - horizontal alignment. 0 = left, 1 = center, 2 = right. default center.
// * vAlign - vertical alignment. 0 = top, 1 = center, 2 = bottomt. default center.
// * useEyePoint - H & V usage of the eyePoint, if player object. default 0, 1. (ie - use only the vertical component)
// * autoDelete - self-delete when attachedTo object is deleted. default true.
//
// Todo:
// * occlusion - hide the control when its anchor point is occluded.
// * integrate w/ zbuffer - this would actually be a change to the whole GuiControl system.
// * allow attaching to arbitrary nodes in a skeleton.
// * avoid projection when the object is out of the frustum.
//
// oxe 20070111
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/consoleTypes.h"
#include "scene/sceneObject.h"
#include "T3D/player.h"
#include "gui/controls/gui3DProjectionCtrl.h"
IMPLEMENT_CONOBJECT(Gui3DProjectionCtrl);
//-----------------------------------------------------------------------------
Gui3DProjectionCtrl::Gui3DProjectionCtrl()
{
mTSCtrl = NULL;
mAttachedTo = NULL;
mAttachedToPlayer = NULL;
mAutoDelete = true;
mHAlign = center;
mVAlign = center;
mUseEyePoint.x = 0;
mUseEyePoint.y = 1;
mPtWorld .set(0, 0, 0);
mPtProj .set(0, 0);
mOffsetObject.set(0, 0, 0);
mOffsetWorld .set(0, 0, 0);
mOffsetScreen.set(0, 0);
}
void Gui3DProjectionCtrl::initPersistFields()
{
Parent::initPersistFields();
addGroup("3DProjection");
addField("pointWorld" , TypePoint3F , Offset(mPtWorld , Gui3DProjectionCtrl));
addField("offsetObject" , TypePoint3F , Offset(mOffsetObject , Gui3DProjectionCtrl));
addField("offsetWorld" , TypePoint3F , Offset(mOffsetWorld , Gui3DProjectionCtrl));
addField("offsetScreen" , TypePoint2I , Offset(mOffsetScreen , Gui3DProjectionCtrl));
addField("hAlign" , TypeS32 , Offset(mHAlign , Gui3DProjectionCtrl));
addField("vAlign" , TypeS32 , Offset(mVAlign , Gui3DProjectionCtrl));
addField("useEyePoint" , TypePoint2I , Offset(mUseEyePoint , Gui3DProjectionCtrl));
addField("autoDelete" , TypeBool , Offset(mAutoDelete , Gui3DProjectionCtrl));
endGroup("3DProjection");
}
void Gui3DProjectionCtrl::onRender(Point2I offset, const RectI &updateRect)
{
doPositioning();
doProjection();
doAlignment();
Parent::onRender(offset, updateRect);
}
void Gui3DProjectionCtrl::resizeDuringRender()
{
doPositioning();
doProjection ();
doAlignment ();
}
bool Gui3DProjectionCtrl::onWake()
{
// walk up the GUI tree until we find a GuiTSCtrl.
mTSCtrl = NULL;
GuiControl* walkCtrl = getParent();
AssertFatal(walkCtrl != NULL, "Gui3DProjectionCtrl::onWake() - NULL parent");
bool doMore = true;
while (doMore)
{
mTSCtrl = dynamic_cast<GuiTSCtrl*>(walkCtrl);
walkCtrl = walkCtrl->getParent();
doMore = (mTSCtrl == NULL) && (walkCtrl != NULL);
}
if (!mTSCtrl)
Con::errorf("Gui3DProjectionCtrl::onWake() - no TSCtrl parent");
return Parent::onWake();
}
void Gui3DProjectionCtrl::onSleep()
{
mTSCtrl = NULL;
return Parent::onSleep();
}
void Gui3DProjectionCtrl::onDeleteNotify(SimObject* obj)
{
// - SimSet assumes that obj is a member of THIS, which in our case ain't true.
// oxe 20070116 - the following doesn't compile on GCC.
// SimSet::Parent::onDeleteNotify(obj);
if (!obj)
{
Con::warnf("Gui3DProjectionCtrl::onDeleteNotify - got NULL");
return;
}
if (obj != mAttachedTo)
{
if (mAttachedTo != NULL)
Con::warnf("Gui3DProjectionCtrl::onDeleteNotify - got unexpected object: %d vs. %d", obj->getId(), mAttachedTo->getId());
return;
}
if (mAutoDelete)
this->deleteObject();
}
//-----------------------------------------------------------------------------
void Gui3DProjectionCtrl::doPositioning()
{
if (mAttachedTo == NULL)
return;
Point3F ptBase; // the regular position of the object.
Point3F ptEye; // the render position of the eye node, if a player object.
Point3F pt; // combination of ptBase and ptEye.
MatrixF mat; // utility
mAttachedTo->getRenderTransform().getColumn(3, &ptBase);
if (mAttachedToPlayer != NULL)
{
mAttachedToPlayer->getRenderEyeTransform(&mat);
mat.getColumn(3, &ptEye);
}
else
{
ptEye = ptBase;
}
// use some components from ptEye but other position from ptBase
pt = ptBase;
if (mUseEyePoint.x != 0)
{
pt.x = ptEye.x;
pt.y = ptEye.y;
}
if (mUseEyePoint.y != 0)
{
pt.z = ptEye.z;
}
// object-space offset
Point3F offsetObj;
QuatF quat(mAttachedTo->getRenderTransform());
quat.mulP(mOffsetObject, &offsetObj);
pt += offsetObj;
// world-space offset
pt += mOffsetWorld;
mPtWorld = pt;
}
void Gui3DProjectionCtrl::doProjection()
{
if (!mTSCtrl)
return;
Point3F pt;
if (!mTSCtrl->project(mPtWorld, &pt))
return;
mPtProj.x = (S32)(pt.x + 0.5f);
mPtProj.y = (S32)(pt.y + 0.5f);
}
void Gui3DProjectionCtrl::doAlignment()
{
// alignment
Point2I offsetAlign;
switch(mHAlign)
{
default:
case center:
offsetAlign.x = -getBounds().extent.x / 2;
break;
case min:
offsetAlign.x = 0;
break;
case max:
offsetAlign.x = -getBounds().extent.x;
break;
}
switch(mVAlign)
{
default:
case center:
offsetAlign.y = -getBounds().extent.y / 2;
break;
case min:
offsetAlign.y = 0;
break;
case max:
offsetAlign.y = -getBounds().extent.y;
break;
}
// projected point
mPtScreen = mPtProj;
// alignment offset
mPtScreen += offsetAlign;
// screen offset
mPtScreen += mOffsetScreen;
// setTrgPosition(mPtScreen);
RectI bounds = getBounds();
bounds.point = mPtScreen;
setBounds(bounds);
}
//-----------------------------------------------------------------------------
void Gui3DProjectionCtrl::setAttachedTo(SceneObject* obj)
{
if (obj == mAttachedTo)
return;
if (mAttachedTo)
clearNotify(mAttachedTo);
mAttachedTo = obj;
mAttachedToPlayer = dynamic_cast<Player*>(obj);
if (mAttachedTo)
deleteNotify(mAttachedTo);
}
DefineEngineMethod(Gui3DProjectionCtrl, setAttachedTo, void, (SceneObject* target), (nullAsType<SceneObject*>()), "(object)")
{
if(target)
object->setAttachedTo(target);
}
DefineEngineMethod(Gui3DProjectionCtrl, getAttachedTo, S32, (),, "()")
{
SceneObject* obj = object->getAttachedTo();
if (!obj)
return 0;
else
return obj->getId();
}

View file

@ -0,0 +1,77 @@
//-----------------------------------------------------------------------------
// Gui3DProjectionCtrl
// Doppelganger Inc
// Orion Elenzil 200701
//
//
//-----------------------------------------------------------------------------
#ifndef _GUI3DPROJECTIONCTRL_H_
#define _GUI3DPROJECTIONCTRL_H_
#include "gui/core/guiTypes.h"
#include "gui/core/guiControl.h"
#include "gui/3d/guiTSControl.h"
#include "scene/sceneObject.h"
#include "T3D/player.h"
class Gui3DProjectionCtrl : public GuiControl
{
//-----------------------------------------------------------------------------
// stock stuff
public:
Gui3DProjectionCtrl();
typedef GuiControl Parent;
DECLARE_CONOBJECT(Gui3DProjectionCtrl);
static void initPersistFields ();
//-----------------------------------------------------------------------------
// more interesting stuff
GuiTSCtrl* mTSCtrl; /// must be a child of one of these.
SimObjectPtr<SceneObject> mAttachedTo; /// optional object we're attached to.
SimObjectPtr<Player> mAttachedToPlayer; /// same pointer as mAttachedTo, but conveniently casted to player.
Point3F mPtWorld; /// the worldspace point which we're projecting
Point2I mPtProj; /// the screenspace projected point. - note there are further modifiers before
Point2I mPtScreen;
Point3F mOffsetObject; /// object-space offset applied first to the attached point to obtain mPtWorld.
Point3F mOffsetWorld; /// world-space offset applied second to the attached point to obtain mPtWorld.
Point2I mOffsetScreen; /// screen-space offset applied to mPtProj. note we still have centering, etc.
enum alignment
{
min = 0,
center = 1,
max = 2
};
alignment mHAlign; /// horizontal alignment
alignment mVAlign; /// horizontal alignment
bool mAutoDelete; /// optionally self-delete when mAttachedTo is deleted.
Point2I mUseEyePoint; /// optionally use the eye point. x != 0 -> horiz. y != 0 -> vert.
virtual void onRender (Point2I offset, const RectI &updateRect);
virtual void resizeDuringRender ();
virtual bool onWake ();
virtual void onSleep ();
virtual void onDeleteNotify (SimObject *object);
void doPositioning ();
void doProjection ();
void doAlignment ();
void setAttachedTo (SceneObject* obj);
SceneObject* getAttachedTo () { return mAttachedTo; }
void setWorldPt (Point3F& pt) { mPtWorld = pt; }
Point3F getWorldPt () { return mPtWorld; }
};
#endif //_GUI3DPROJECTIONCTRL_H_

View file

@ -89,9 +89,6 @@ bool GuiConsole::onWake()
S32 GuiConsole::getMaxWidth(S32 startIndex, S32 endIndex)
{
//sanity check
U32 size;
ConsoleLogEntry *log;
if (startIndex < 0 || (U32)endIndex >= mFilteredLog.size() || startIndex > endIndex)
return 0;
@ -190,9 +187,6 @@ void GuiConsole::onPreRender()
void GuiConsole::onRenderCell(Point2I offset, Point2I cell, bool /*selected*/, bool /*mouseOver*/)
{
U32 size;
ConsoleLogEntry *log;
ConsoleLogEntry &entry = mFilteredLog[cell.y];
switch (entry.mLevel)
{
@ -210,9 +204,6 @@ void GuiConsole::onCellSelected( Point2I cell )
{
Parent::onCellSelected( cell );
U32 size;
ConsoleLogEntry* log;
ConsoleLogEntry& entry = mFilteredLog[cell.y];
onMessageSelected_callback( entry.mLevel, entry.mString );
}

View file

@ -631,7 +631,7 @@ DefineEngineMethod( GuiListBoxCtrl, addItem, S32, (const char* newItem, const ch
else if(elementCount == 1)
{
U32 objId = dAtoi( color );
return object->addItem( newItem, (void*)objId );
return object->addItem( newItem, (void*)(uintptr_t)objId );
}
else
{
@ -1523,7 +1523,7 @@ void GuiListBoxCtrl::_mirror()
if ( !found )
{
addItem( _makeMirrorItemName( curObj ), (void*)curId );
addItem( _makeMirrorItemName( curObj ), (void*)(uintptr_t)curId );
}
}
}

View file

@ -1241,6 +1241,9 @@ void GuiTextEditCtrl::onLoseFirstResponder()
root->disableKeyboardTranslation();
}
updateHistory(&mTextBuffer, true);
mHistoryDirty = false;
//execute the validate command
if( mValidateCommand.isNotEmpty() )
evaluate( mValidateCommand );

View file

@ -33,6 +33,7 @@
#include "gfx/gfxDrawUtil.h"
#include "gfx/primBuilder.h"
#include "console/engineAPI.h"
#include "gui/editor/guiPopupMenuCtrl.h"
// menu bar:
// basic idea - fixed height control bar at the top of a window, placed and sized in gui editor
@ -1113,6 +1114,13 @@ GuiMenuBar::GuiMenuBar()
void GuiMenuBar::onRemove()
{
GuiPopupMenuBackgroundCtrl* backgroundCtrl;
if (Sim::findObject("PopUpMenuControl", backgroundCtrl))
{
if (backgroundCtrl->mMenuBarCtrl == this)
backgroundCtrl->mMenuBarCtrl = nullptr;
}
Parent::onRemove();
}
@ -1472,11 +1480,11 @@ PopupMenu* GuiMenuBar::getMenu(U32 index)
return mMenuList[index].popupMenu;
}
PopupMenu* GuiMenuBar::findMenu(StringTableEntry barTitle)
PopupMenu* GuiMenuBar::findMenu(String barTitle)
{
for (U32 i = 0; i < mMenuList.size(); i++)
{
if (mMenuList[i].text == barTitle)
if (String::ToLower(mMenuList[i].text) == String::ToLower(barTitle))
return mMenuList[i].popupMenu;
}
@ -1521,8 +1529,7 @@ DefineEngineMethod(GuiMenuBar, insert, void, (SimObject* pObject, S32 pos), (nul
DefineEngineMethod(GuiMenuBar, findMenu, S32, (const char* barTitle), (""), "(barTitle)")
{
StringTableEntry barTitleStr = StringTable->insert(barTitle);
PopupMenu* menu = object->findMenu(barTitleStr);
PopupMenu* menu = object->findMenu(barTitle);
if (menu)
return menu->getId();

View file

@ -116,7 +116,7 @@ public:
U32 getMenuListCount() { return mMenuList.size(); }
PopupMenu* getMenu(U32 index);
PopupMenu* findMenu(StringTableEntry barTitle);
PopupMenu* findMenu(String barTitle);
DECLARE_CONOBJECT(GuiMenuBar);
DECLARE_CALLBACK( void, onMouseInMenu, ( bool hasLeftMenu ));

View file

@ -50,7 +50,9 @@ GuiInspectorField::GuiInspectorField( GuiInspector* inspector,
mField( field ),
mFieldArrayIndex( NULL ),
mEdit( NULL ),
mTargetObject(NULL)
mTargetObject(NULL),
mUseHeightOverride(false),
mHeightOverride(18)
{
if( field != NULL )
mCaption = field->pFieldname;
@ -77,7 +79,9 @@ GuiInspectorField::GuiInspectorField()
mTargetObject(NULL),
mVariableName(StringTable->EmptyString()),
mCallbackName(StringTable->EmptyString()),
mSpecialEditField(false)
mSpecialEditField(false),
mUseHeightOverride(false),
mHeightOverride(18)
{
setCanSave( false );
}
@ -112,7 +116,12 @@ bool GuiInspectorField::onAdd()
if ( mEdit == NULL )
return false;
setBounds(0,0,100,18);
S32 fieldHeight = 18;
if (mUseHeightOverride)
fieldHeight = mHeightOverride;
setBounds(0,0,100, fieldHeight);
// Add our edit as a child
addObject( mEdit );

View file

@ -84,6 +84,10 @@ class GuiInspectorField : public GuiControl
///
bool mHighlighted;
//These are so we can special-case our height for additional room on certain field-types
bool mUseHeightOverride;
U32 mHeightOverride;
//An override that lets us bypass inspector-dependent logic for setting/getting variables/fields
bool mSpecialEditField;
//An override to make sure this field is associated to an object that isn't expressly

View file

@ -133,9 +133,6 @@ bool GuiInspectorMountingGroup::inspectGroup()
clearFields();
bool bNewItems = false;
bool bMakingArray = false;
GuiStackControl *pArrayStack = NULL;
GuiRolloutCtrl *pArrayRollout = NULL;
bool bGrabItems = false;
AbstractClassRep* commonAncestorClass = findCommonAncestorClass();
@ -240,7 +237,6 @@ void GuiInspectorMountingGroup::updateAllFields()
void GuiInspectorMountingGroup::onMouseMove(const GuiEvent &event)
{
//mParent->mOverDivider = false;
bool test = false;
}
DefineEngineMethod(GuiInspectorMountingGroup, inspectGroup, bool, (),, "Refreshes the dynamic fields in the inspector.")

View file

@ -282,156 +282,159 @@ void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */)
if (owner == NULL)
return;
GuiControl* editorGui;
Sim::findObject("EditorGui", editorGui);
GuiPopupMenuBackgroundCtrl* backgroundCtrl;
Sim::findObject("PopUpMenuControl", backgroundCtrl);
if (editorGui)
GuiControlProfile* profile;
Sim::findObject("GuiMenubarProfile", profile);
if (!profile)
return;
if (mTextList == nullptr)
{
GuiPopupMenuBackgroundCtrl* backgroundCtrl;
Sim::findObject("PopUpMenuControl", backgroundCtrl);
mTextList = new GuiPopupMenuTextListCtrl();
mTextList->registerObject();
mTextList->setControlProfile(profile);
GuiControlProfile* profile;
Sim::findObject("GuiMenubarProfile", profile);
if (!profile)
return;
if (mTextList == nullptr)
{
mTextList = new GuiPopupMenuTextListCtrl();
mTextList->registerObject();
mTextList->setControlProfile(profile);
mTextList->mPopup = this;
mTextList->mMenuBar = getMenuBarCtrl();
}
if (!backgroundCtrl)
{
backgroundCtrl = new GuiPopupMenuBackgroundCtrl();
backgroundCtrl->registerObject("PopUpMenuControl");
}
if (!backgroundCtrl || !mTextList)
return;
if (!mIsSubmenu)
{
//if we're a 'parent' menu, then tell the background to clear out all existing other popups
backgroundCtrl->clearPopups();
}
//find out if we're doing a first-time add
S32 popupIndex = backgroundCtrl->findPopupMenu(this);
if (popupIndex == -1)
{
backgroundCtrl->addObject(mTextList);
backgroundCtrl->mPopups.push_back(this);
}
mTextList->mBackground = backgroundCtrl;
owner->pushDialogControl(backgroundCtrl, 10);
//Set the background control's menubar, if any, and if it's not already set
if(backgroundCtrl->mMenuBarCtrl == nullptr)
backgroundCtrl->mMenuBarCtrl = getMenuBarCtrl();
backgroundCtrl->setExtent(editorGui->getExtent());
mTextList->clear();
S32 textWidth = 0, width = 0;
S32 acceleratorWidth = 0;
GFont *font = profile->mFont;
Point2I maxBitmapSize = Point2I(0, 0);
S32 numBitmaps = profile->mBitmapArrayRects.size();
if (numBitmaps)
{
RectI *bitmapBounds = profile->mBitmapArrayRects.address();
for (S32 i = 0; i < numBitmaps; i++)
{
if (bitmapBounds[i].extent.x > maxBitmapSize.x)
maxBitmapSize.x = bitmapBounds[i].extent.x;
if (bitmapBounds[i].extent.y > maxBitmapSize.y)
maxBitmapSize.y = bitmapBounds[i].extent.y;
}
}
for (U32 i = 0; i < mMenuItems.size(); i++)
{
if (!mMenuItems[i].mVisible)
continue;
S32 iTextWidth = font->getStrWidth(mMenuItems[i].mText.c_str());
S32 iAcceleratorWidth = mMenuItems[i].mAccelerator ? font->getStrWidth(mMenuItems[i].mAccelerator) : 0;
if (iTextWidth > textWidth)
textWidth = iTextWidth;
if (iAcceleratorWidth > acceleratorWidth)
acceleratorWidth = iAcceleratorWidth;
}
width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
mTextList->setCellSize(Point2I(width, font->getHeight() + 2));
mTextList->clearColumnOffsets();
mTextList->addColumnOffset(-1); // add an empty column in for the bitmap index.
mTextList->addColumnOffset(maxBitmapSize.x + 1);
mTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
U32 entryCount = 0;
for (U32 i = 0; i < mMenuItems.size(); i++)
{
if (!mMenuItems[i].mVisible)
continue;
char buf[512];
// If this menu item is a submenu, then set the isSubmenu to 2 to indicate
// an arrow should be drawn. Otherwise set the isSubmenu normally.
char isSubmenu = 1;
if (mMenuItems[i].mIsSubmenu)
isSubmenu = 2;
char bitmapIndex = 1;
if (mMenuItems[i].mBitmapIndex >= 0 && (mMenuItems[i].mBitmapIndex * 3 <= profile->mBitmapArrayRects.size()))
bitmapIndex = mMenuItems[i].mBitmapIndex + 2;
dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, mMenuItems[i].mText.c_str(), mMenuItems[i].mAccelerator ? mMenuItems[i].mAccelerator : "");
mTextList->addEntry(entryCount, buf);
if (!mMenuItems[i].mEnabled)
mTextList->setEntryActive(entryCount, false);
entryCount++;
}
Point2I pos = Point2I::Zero;
if (x == -1 && y == -1)
pos = owner->getCursorPos();
else
pos = Point2I(x, y);
mTextList->setPosition(pos);
//nudge in if we'd overshoot the screen
S32 widthDiff = (mTextList->getPosition().x + mTextList->getExtent().x) - backgroundCtrl->getWidth();
if (widthDiff > 0)
{
Point2I popupPos = mTextList->getPosition();
mTextList->setPosition(popupPos.x - widthDiff, popupPos.y);
}
mTextList->setHidden(false);
mTextList->mPopup = this;
mTextList->mMenuBar = getMenuBarCtrl();
}
if (!backgroundCtrl)
{
backgroundCtrl = new GuiPopupMenuBackgroundCtrl();
backgroundCtrl->registerObject("PopUpMenuControl");
}
if (!backgroundCtrl || !mTextList)
return;
if (!mIsSubmenu)
{
//if we're a 'parent' menu, then tell the background to clear out all existing other popups
backgroundCtrl->clearPopups();
}
//find out if we're doing a first-time add
S32 popupIndex = backgroundCtrl->findPopupMenu(this);
if (popupIndex == -1)
{
backgroundCtrl->addObject(mTextList);
backgroundCtrl->mPopups.push_back(this);
}
mTextList->mBackground = backgroundCtrl;
owner->pushDialogControl(backgroundCtrl, 10);
//Set the background control's menubar, if any, and if it's not already set
if(backgroundCtrl->mMenuBarCtrl == nullptr)
backgroundCtrl->mMenuBarCtrl = getMenuBarCtrl();
backgroundCtrl->setExtent(owner->getExtent());
mTextList->clear();
S32 textWidth = 0, width = 0;
S32 acceleratorWidth = 0;
GFont *font = profile->mFont;
Point2I maxBitmapSize = Point2I(0, 0);
S32 numBitmaps = profile->mBitmapArrayRects.size();
if (numBitmaps)
{
RectI *bitmapBounds = profile->mBitmapArrayRects.address();
for (S32 i = 0; i < numBitmaps; i++)
{
if (bitmapBounds[i].extent.x > maxBitmapSize.x)
maxBitmapSize.x = bitmapBounds[i].extent.x;
if (bitmapBounds[i].extent.y > maxBitmapSize.y)
maxBitmapSize.y = bitmapBounds[i].extent.y;
}
}
for (U32 i = 0; i < mMenuItems.size(); i++)
{
if (!mMenuItems[i].mVisible)
continue;
S32 iTextWidth = font->getStrWidth(mMenuItems[i].mText.c_str());
S32 iAcceleratorWidth = mMenuItems[i].mAccelerator ? font->getStrWidth(mMenuItems[i].mAccelerator) : 0;
if (iTextWidth > textWidth)
textWidth = iTextWidth;
if (iAcceleratorWidth > acceleratorWidth)
acceleratorWidth = iAcceleratorWidth;
}
width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
mTextList->setCellSize(Point2I(width, font->getHeight() + 2));
mTextList->clearColumnOffsets();
mTextList->addColumnOffset(-1); // add an empty column in for the bitmap index.
mTextList->addColumnOffset(maxBitmapSize.x + 1);
mTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
U32 entryCount = 0;
for (U32 i = 0; i < mMenuItems.size(); i++)
{
if (!mMenuItems[i].mVisible)
continue;
char buf[512];
// If this menu item is a submenu, then set the isSubmenu to 2 to indicate
// an arrow should be drawn. Otherwise set the isSubmenu normally.
char isSubmenu = 1;
if (mMenuItems[i].mIsSubmenu)
isSubmenu = 2;
char bitmapIndex = 1;
if (mMenuItems[i].mBitmapIndex >= 0 && (mMenuItems[i].mBitmapIndex * 3 <= profile->mBitmapArrayRects.size()))
bitmapIndex = mMenuItems[i].mBitmapIndex + 2;
dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, mMenuItems[i].mText.c_str(), mMenuItems[i].mAccelerator ? mMenuItems[i].mAccelerator : "");
mTextList->addEntry(entryCount, buf);
if (!mMenuItems[i].mEnabled)
mTextList->setEntryActive(entryCount, false);
entryCount++;
}
Point2I pos = Point2I::Zero;
if (x == -1 && y == -1)
pos = owner->getCursorPos();
else
pos = Point2I(x, y);
mTextList->setPosition(pos);
//nudge in if we'd overshoot the screen
S32 widthDiff = (mTextList->getPosition().x + mTextList->getExtent().x) - backgroundCtrl->getWidth();
if (widthDiff > 0)
{
Point2I popupPos = mTextList->getPosition();
mTextList->setPosition(popupPos.x - widthDiff, popupPos.y);
}
//If we'd overshoot the screen vertically, just mirror the axis so we're above the mouse
S32 heightDiff = (mTextList->getPosition().y + mTextList->getExtent().y) - backgroundCtrl->getHeight();
if (heightDiff > 0)
{
Point2I popupPos = mTextList->getPosition();
mTextList->setPosition(popupPos.x, popupPos.y - mTextList->getExtent().y);
}
mTextList->setHidden(false);
}
void PopupMenu::hidePopup()

View file

@ -58,9 +58,25 @@ ConsoleDocClass( GuiInputCtrl,
//------------------------------------------------------------------------------
GuiInputCtrl::GuiInputCtrl()
: mSendAxisEvents(false),
mSendBreakEvents(false),
mSendModifierEvents(false)
{
}
//------------------------------------------------------------------------------
void GuiInputCtrl::initPersistFields()
{
addGroup("GuiInputCtrl");
addField("sendAxisEvents", TypeBool, Offset(mSendAxisEvents, GuiInputCtrl),
"If true, onAxisEvent callbacks will be sent for SI_AXIS Move events (Default false).");
addField("sendBreakEvents", TypeBool, Offset(mSendBreakEvents, GuiInputCtrl),
"If true, break events for all devices will generate callbacks (Default false).");
addField("sendModifierEvents", TypeBool, Offset(mSendModifierEvents, GuiInputCtrl),
"If true, Make events will be sent for modifier keys (Default false).");
endGroup("GuiInputCtrl");
Parent::initPersistFields();
}
@ -110,6 +126,8 @@ static bool isModifierKey( U16 keyCode )
case KEY_RALT:
case KEY_LSHIFT:
case KEY_RSHIFT:
case KEY_MAC_LOPT:
case KEY_MAC_ROPT:
return( true );
}
@ -117,33 +135,49 @@ static bool isModifierKey( U16 keyCode )
}
IMPLEMENT_CALLBACK( GuiInputCtrl, onInputEvent, void, (const char* device, const char* action, bool state ),
( device, action, state),
"@brief Callback that occurs when an input is triggered on this control\n\n"
"@param device The device type triggering the input, such as keyboard, mouse, etc\n"
"@param action The actual event occuring, such as a key or button\n"
"@param state True if the action is being pressed, false if it is being release\n\n"
);
( device, action, state),
"@brief Callback that occurs when an input is triggered on this control\n\n"
"@param device The device type triggering the input, such as keyboard, mouse, etc\n"
"@param action The actual event occuring, such as a key or button\n"
"@param state True if the action is being pressed, false if it is being release\n\n");
IMPLEMENT_CALLBACK(GuiInputCtrl, onAxisEvent, void, (const char* device, const char* action, F32 axisValue),
(device, action, axisValue),
"@brief Callback that occurs when an axis event is triggered on this control\n\n"
"@param device The device type triggering the input, such as mouse, joystick, gamepad, etc\n"
"@param action The ActionMap code for the axis\n"
"@param axisValue The current value of the axis\n\n");
//------------------------------------------------------------------------------
bool GuiInputCtrl::onInputEvent( const InputEventInfo &event )
{
// TODO - add POV support...
char deviceString[32];
if ( event.action == SI_MAKE )
{
if ( event.objType == SI_BUTTON
|| event.objType == SI_POV
|| ( ( event.objType == SI_KEY ) && !isModifierKey( event.objInst ) ) )
|| event.objType == SI_KEY )
{
char deviceString[32];
if ( !ActionMap::getDeviceName( event.deviceType, event.deviceInst, deviceString ) )
return( false );
return false;
const char* actionString = ActionMap::buildActionString( &event );
if ((event.objType == SI_KEY) && isModifierKey(event.objInst))
{
if (!mSendModifierEvents)
return false;
//Con::executef( this, "onInputEvent", deviceString, actionString, "1" );
onInputEvent_callback(deviceString, actionString, 1);
char keyString[32];
if (!ActionMap::getKeyString(event.objInst, keyString))
return false;
return( true );
onInputEvent_callback(deviceString, keyString, 1);
}
else
{
const char* actionString = ActionMap::buildActionString(&event);
onInputEvent_callback(deviceString, actionString, 1);
}
return true;
}
}
else if ( event.action == SI_BREAK )
@ -152,14 +186,36 @@ bool GuiInputCtrl::onInputEvent( const InputEventInfo &event )
{
char keyString[32];
if ( !ActionMap::getKeyString( event.objInst, keyString ) )
return( false );
return false;
//Con::executef( this, "onInputEvent", "keyboard", keyString, "0" );
onInputEvent_callback("keyboard", keyString, 0);
onInputEvent_callback("keyboard", keyString, 0);
return true;
}
else if (mSendBreakEvents)
{
if (!ActionMap::getDeviceName(event.deviceType, event.deviceInst, deviceString))
return false;
return( true );
const char* actionString = ActionMap::buildActionString(&event);
onInputEvent_callback(deviceString, actionString, 0);
return true;
}
}
else if (mSendAxisEvents && ((event.objType == SI_AXIS) || (event.objType == SI_INT) || (event.objType == SI_FLOAT)))
{
F32 fValue = event.fValue;
if (event.objType == SI_INT)
fValue = (F32)event.iValue;
return( false );
if (!ActionMap::getDeviceName(event.deviceType, event.deviceInst, deviceString))
return false;
const char* actionString = ActionMap::buildActionString(&event);
onAxisEvent_callback(deviceString, actionString, fValue);
return (event.deviceType != MouseDeviceType); // Don't consume mouse move events
}
return false;
}

View file

@ -32,23 +32,31 @@
/// to script. This is useful for implementing custom keyboard handling code.
class GuiInputCtrl : public GuiMouseEventCtrl
{
public:
protected:
bool mSendAxisEvents;
bool mSendBreakEvents;
bool mSendModifierEvents;
typedef GuiMouseEventCtrl Parent;
// GuiControl.
virtual bool onWake();
virtual void onSleep();
public:
virtual bool onInputEvent( const InputEventInfo &event );
static void initPersistFields();
typedef GuiMouseEventCtrl Parent;
DECLARE_CONOBJECT(GuiInputCtrl);
DECLARE_CATEGORY( "Gui Other Script" );
DECLARE_DESCRIPTION( "A control that locks the mouse and reports all keyboard input events to script." );
GuiInputCtrl();
DECLARE_CALLBACK( void, onInputEvent, ( const char* device, const char* action, bool state ));
// GuiControl.
virtual bool onWake();
virtual void onSleep();
virtual bool onInputEvent( const InputEventInfo &event );
static void initPersistFields();
DECLARE_CONOBJECT(GuiInputCtrl);
DECLARE_CATEGORY( "Gui Other Script" );
DECLARE_DESCRIPTION( "A control that locks the mouse and reports all input events to script." );
DECLARE_CALLBACK( void, onInputEvent, ( const char* device, const char* action, bool state ));
DECLARE_CALLBACK(void, onAxisEvent, (const char* device, const char* action, F32 axisValue));
};
#endif // _GUI_INPUTCTRL_H

View file

@ -38,6 +38,7 @@
#include "scene/sceneRenderState.h"
#include "renderInstance/renderBinManager.h"
#include "T3D/Scene.h"
IMPLEMENT_CONOBJECT(EditTSCtrl);
ConsoleDocClass( EditTSCtrl,
@ -795,15 +796,15 @@ void EditTSCtrl::_renderScene( ObjectRenderInst*, SceneRenderState *state, BaseM
GFXTransformSaver saver;
// render through console callbacks
SimSet * missionGroup = static_cast<SimSet*>(Sim::findObject("MissionGroup"));
if(missionGroup)
Scene* scene = Scene::getRootScene();
if(scene)
{
mConsoleRendering = true;
// [ rene, 27-Jan-10 ] This calls onEditorRender on the server objects instead
// of on the client objects which seems a bit questionable to me.
for(SimSetIterator itr(missionGroup); *itr; ++itr)
for(SimSetIterator itr(scene); *itr; ++itr)
{
SceneObject* object = dynamic_cast< SceneObject* >( *itr );
if( object && object->isRenderEnabled() && !object->isHidden() )

View file

@ -51,6 +51,8 @@
#include "T3D/portal.h"
#include "math/mPolyhedron.impl.h"
#include "T3D/Scene.h"
IMPLEMENT_CONOBJECT( GuiConvexEditorCtrl );
ConsoleDocClass( GuiConvexEditorCtrl,
@ -121,12 +123,12 @@ bool GuiConvexEditorCtrl::onWake()
if ( !Parent::onWake() )
return false;
SimGroup *missionGroup;
if ( !Sim::findObject( "MissionGroup", missionGroup ) )
Scene* scene = Scene::getRootScene();
if ( !scene )
return true;
SimGroup::iterator itr = missionGroup->begin();
for ( ; itr != missionGroup->end(); itr++ )
SimGroup::iterator itr = scene->begin();
for ( ; itr != scene->end(); itr++ )
{
if ( dStrcmp( (*itr)->getClassName(), "ConvexShape" ) == 0 )
{
@ -166,8 +168,8 @@ void GuiConvexEditorCtrl::setVisible( bool val )
mSavedGizmoFlags = -1;
}
SimGroup* misGroup;
if (Sim::findObject("MissionGroup", misGroup))
Scene* scene = Scene::getRootScene();
if (scene != nullptr)
{
//Make our proxy objects "real" again
for (U32 i = 0; i < mProxyObjects.size(); ++i)
@ -178,13 +180,13 @@ void GuiConvexEditorCtrl::setVisible( bool val )
AbstractClassRep* classRep = AbstractClassRep::findClassRep(mProxyObjects[i].targetObjectClass);
if (!classRep)
{
Con::errorf("WorldEditor::createPolyhedralObject - No such class: %s", mProxyObjects[i].targetObjectClass);
Con::errorf("WorldEditor::createPolyhedralObject - No such class: %s", mProxyObjects[i].targetObjectClass.c_str());
continue;
}
SceneObject* polyObj = createPolyhedralObject(mProxyObjects[i].targetObjectClass.c_str(), mProxyObjects[i].shapeProxy);
misGroup->addObject(polyObj);
scene->addObject(polyObj);
//Now, remove the convex proxy
mProxyObjects[i].shapeProxy->deleteObject();
@ -222,19 +224,19 @@ void GuiConvexEditorCtrl::setVisible( bool val )
updateGizmoPos();
mSavedGizmoFlags = mGizmoProfile->flags;
SimGroup* misGroup;
if (Sim::findObject("MissionGroup", misGroup))
Scene* scene = Scene::getRootScene();
if (scene != nullptr)
{
for (U32 c = 0; c < misGroup->size(); ++c)
for (U32 c = 0; c < scene->size(); ++c)
{
bool isTrigger = (misGroup->at(c)->getClassName() == StringTable->insert("Trigger"));
bool isZone = (misGroup->at(c)->getClassName() == StringTable->insert("Zone"));
bool isPortal = (misGroup->at(c)->getClassName() == StringTable->insert("Portal"));
bool isOccluder = (misGroup->at(c)->getClassName() == StringTable->insert("OcclusionVolume"));
bool isTrigger = (scene->at(c)->getClassName() == StringTable->insert("Trigger"));
bool isZone = (scene->at(c)->getClassName() == StringTable->insert("Zone"));
bool isPortal = (scene->at(c)->getClassName() == StringTable->insert("Portal"));
bool isOccluder = (scene->at(c)->getClassName() == StringTable->insert("OcclusionVolume"));
if (isZone || isPortal || isOccluder)
{
SceneObject* sceneObj = static_cast<SceneObject*>(misGroup->at(c));
SceneObject* sceneObj = static_cast<SceneObject*>(scene->at(c));
if (!sceneObj)
{
Con::errorf("WorldEditor::createConvexShapeFrom - Invalid object");
@ -1350,9 +1352,9 @@ void GuiConvexEditorCtrl::setupShape( ConvexShape *shape )
shape->registerObject();
updateShape( shape );
SimGroup *group;
if ( Sim::findObject( "missionGroup", group ) )
group->addObject( shape );
Scene* scene = Scene::getRootScene();
if ( scene )
scene->addObject( shape );
}
void GuiConvexEditorCtrl::updateShape( ConvexShape *shape, S32 offsetFace )
@ -1929,10 +1931,8 @@ ConvexEditorTool::EventResult ConvexEditorCreateTool::on3DMouseUp( const Gui3DMo
}
else if ( mStage == 0 )
{
SimGroup *mg;
Sim::findObject( "MissionGroup", mg );
mg->addObject( mNewConvex );
SimGroup *scene = Scene::getRootScene();
scene->addObject( mNewConvex );
mStage = -1;
@ -2128,9 +2128,9 @@ ConvexShape* ConvexEditorCreateTool::extrudeShapeFromFace( ConvexShape *inShape,
newShape->registerObject();
mEditor->updateShape( newShape );
SimGroup *group;
if ( Sim::findObject( "missionGroup", group ) )
group->addObject( newShape );
Scene* scene = Scene::getRootScene();
if ( scene )
scene->addObject( newShape );
return newShape;
}
@ -2513,4 +2513,4 @@ if (convex)
DefineEngineMethod( GuiConvexEditorCtrl, splitSelectedFace, void, (), , "" )
{
object->splitSelectedFace();
}
}

View file

@ -36,7 +36,7 @@
#include "gui/worldEditor/terrainActions.h"
#include "terrain/terrMaterial.h"
#include "T3D/Scene.h"
IMPLEMENT_CONOBJECT(TerrainEditor);
@ -2405,10 +2405,10 @@ void TerrainEditor::reorderMaterial( S32 index, S32 orderPos )
DefineEngineMethod( TerrainEditor, attachTerrain, void, (const char * terrain), (""), "(TerrainBlock terrain)")
{
SimSet * missionGroup = dynamic_cast<SimSet*>(Sim::findObject("MissionGroup"));
if (!missionGroup)
Scene* scene = Scene::getRootScene();
if (!scene)
{
Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::attach: no mission group found");
Con::errorf(ConsoleLogEntry::Script, "TerrainEditor::attach: no scene found");
return;
}
@ -2417,7 +2417,7 @@ DefineEngineMethod( TerrainEditor, attachTerrain, void, (const char * terrain),
// attach to first found terrainBlock
if (dStrcmp (terrain,"")==0)
{
for(SimSetIterator itr(missionGroup); *itr; ++itr)
for(SimSetIterator itr(scene); *itr; ++itr)
{
TerrainBlock* terrBlock = dynamic_cast<TerrainBlock*>(*itr);

View file

@ -51,6 +51,8 @@
#include "tools/editorTool.h"
#include "T3D/Scene.h"
IMPLEMENT_CONOBJECT( WorldEditor );
ConsoleDocClass( WorldEditor,
@ -455,19 +457,20 @@ bool WorldEditor::pasteSelection( bool dropSel )
return false;
}
SimGroup *missionGroup = NULL;
SimGroup *targetGroup = NULL;
if( isMethod( "getNewObjectGroup" ) )
{
const char* targetGroupName = Con::executef( this, "getNewObjectGroup" );
if( targetGroupName && targetGroupName[ 0 ] && !Sim::findObject( targetGroupName, missionGroup ) )
if( targetGroupName && targetGroupName[ 0 ] && !Sim::findObject( targetGroupName, targetGroup) )
Con::errorf( "WorldEditor::pasteSelection() - no SimGroup called '%s'", targetGroupName );
}
if( !missionGroup )
if( !targetGroup)
{
if( !Sim::findObject( "MissionGroup", missionGroup ) )
targetGroup = Scene::getRootScene();
if( !targetGroup)
{
Con::errorf( "WorldEditor::pasteSelection() - MissionGroup not found" );
Con::errorf( "WorldEditor::pasteSelection() - Scene not found" );
return false;
}
}
@ -481,8 +484,8 @@ bool WorldEditor::pasteSelection( bool dropSel )
if ( !obj )
continue;
if ( missionGroup )
missionGroup->addObject( obj );
if (targetGroup)
targetGroup->addObject( obj );
action->addObject( obj );
@ -594,7 +597,7 @@ void WorldEditor::hideObject(SceneObject* serverObj, bool hide)
void WorldEditor::hideSelection(bool hide)
{
SimGroup* pGroup = dynamic_cast<SimGroup*>(Sim::findObject("MissionGroup"));
Scene* scene = Scene::getRootScene();
// set server/client objects hide field
for(U32 i = 0; i < mSelected->size(); i++)
@ -605,7 +608,7 @@ void WorldEditor::hideSelection(bool hide)
// Prevent non-mission group objects (i.e. Player) from being hidden.
// Otherwise it is difficult to show them again.
if(!serverObj->isChildOfGroup(pGroup))
if(!serverObj->isChildOfGroup(scene))
continue;
hideObject(serverObj, hide);
@ -2437,7 +2440,7 @@ void WorldEditor::renderScene( const RectI &updateRect )
}
// Render the paths
renderPaths(Sim::findObject("MissionGroup"));
renderPaths(Scene::getRootScene());
// walk selected
Selection* selection = getActiveSelectionSet();
@ -3653,10 +3656,10 @@ void WorldEditor::makeSelectionPrefab( const char *filename )
return;
}
SimGroup *missionGroup;
if ( !Sim::findObject( "MissionGroup", missionGroup ) )
Scene* scene = Scene::getRootScene();
if ( !scene)
{
Con::errorf( "WorldEditor::makeSelectionPrefab - Could not find MissionGroup." );
Con::errorf( "WorldEditor::makeSelectionPrefab - Could not find root Scene." );
return;
}
@ -3746,7 +3749,7 @@ void WorldEditor::makeSelectionPrefab( const char *filename )
fabMat.inverse();
fab->setTransform( fabMat );
fab->registerObject();
missionGroup->addObject( fab );
scene->addObject( fab );
// Select it, mark level as dirty.
clearSelection();
@ -3812,10 +3815,10 @@ void WorldEditor::makeSelectionAMesh(const char *filename)
return;
}
SimGroup *missionGroup;
if (!Sim::findObject("MissionGroup", missionGroup))
Scene* scene = Scene::getRootScene();
if (!scene)
{
Con::errorf("WorldEditor::makeSelectionAMesh - Could not find MissionGroup.");
Con::errorf("WorldEditor::makeSelectionAMesh - Could not find root Scene.");
return;
}
@ -3877,8 +3880,6 @@ void WorldEditor::makeSelectionAMesh(const char *filename)
fabMat.inverse();
MatrixF objMat;
SimObject *obj = NULL;
SceneObject *sObj = NULL;
Vector< SceneObject* > objectList;
@ -3967,7 +3968,7 @@ void WorldEditor::makeSelectionAMesh(const char *filename)
fabMat.inverse();
ts->setTransform(fabMat);
ts->registerObject();
missionGroup->addObject(ts);
scene->addObject(ts);
// Select it, mark level as dirty.
clearSelection();