mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 12:44:46 +00:00
704 lines
19 KiB
C++
704 lines
19 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2014 Daniel Buckmaster
|
|
//
|
|
// 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 "torqueConfig.h"
|
|
#ifdef TORQUE_TOOLS
|
|
#include "platform/platform.h"
|
|
#include "guiNavEditorCtrl.h"
|
|
#include "duDebugDrawTorque.h"
|
|
#include "console/engineAPI.h"
|
|
|
|
#include "console/consoleTypes.h"
|
|
#include "math/util/frustum.h"
|
|
#include "math/mathUtils.h"
|
|
#include "gfx/primBuilder.h"
|
|
#include "gfx/gfxDrawUtil.h"
|
|
#include "scene/sceneRenderState.h"
|
|
#include "scene/sceneManager.h"
|
|
#include "gui/core/guiCanvas.h"
|
|
#include "gui/buttons/guiButtonCtrl.h"
|
|
#include "gui/worldEditor/undoActions.h"
|
|
#include "T3D/gameBase/gameConnection.h"
|
|
#include "T3D/AI/AIController.h"
|
|
|
|
IMPLEMENT_CONOBJECT(GuiNavEditorCtrl);
|
|
|
|
ConsoleDocClass(GuiNavEditorCtrl,
|
|
"@brief GUI tool that makes up the Navigation Editor\n\n"
|
|
"Editor use only.\n\n"
|
|
"@internal"
|
|
);
|
|
|
|
// Each of the mode names directly correlates with the Nav Editor's tool palette.
|
|
const String GuiNavEditorCtrl::mSelectMode = "SelectMode";
|
|
const String GuiNavEditorCtrl::mLinkMode = "LinkMode";
|
|
const String GuiNavEditorCtrl::mCoverMode = "CoverMode";
|
|
const String GuiNavEditorCtrl::mTileMode = "TileMode";
|
|
const String GuiNavEditorCtrl::mTestMode = "TestMode";
|
|
|
|
GuiNavEditorCtrl::GuiNavEditorCtrl()
|
|
{
|
|
mMode = mSelectMode;
|
|
mIsDirty = false;
|
|
mStartDragMousePoint = InvalidMousePoint;
|
|
mMesh = NULL;
|
|
mCurTile = mTile = -1;
|
|
mPlayer = mCurPlayer = NULL;
|
|
mSpawnClass = mSpawnDatablock = "";
|
|
mLinkStart = Point3F::Max;
|
|
mLink = mCurLink = -1;
|
|
}
|
|
|
|
GuiNavEditorCtrl::~GuiNavEditorCtrl()
|
|
{
|
|
}
|
|
|
|
void GuiNavEditorUndoAction::undo()
|
|
{
|
|
}
|
|
|
|
bool GuiNavEditorCtrl::onAdd()
|
|
{
|
|
if(!Parent::onAdd())
|
|
return false;
|
|
|
|
GFXStateBlockDesc desc;
|
|
desc.fillMode = GFXFillSolid;
|
|
desc.setBlend(false);
|
|
desc.setZReadWrite(false, false);
|
|
desc.setCullMode(GFXCullNone);
|
|
|
|
mZDisableSB = GFX->createStateBlock(desc);
|
|
|
|
desc.setZReadWrite(true, true);
|
|
mZEnableSB = GFX->createStateBlock(desc);
|
|
|
|
SceneManager::getPreRenderSignal().notify(this, &GuiNavEditorCtrl::_prepRenderImage);
|
|
|
|
return true;
|
|
}
|
|
|
|
void GuiNavEditorCtrl::initPersistFields()
|
|
{
|
|
docsURL;
|
|
addField("isDirty", TypeBool, Offset(mIsDirty, GuiNavEditorCtrl));
|
|
|
|
addField("spawnClass", TypeRealString, Offset(mSpawnClass, GuiNavEditorCtrl),
|
|
"Class of object to spawn in test mode.");
|
|
addField("spawnDatablock", TypeRealString, Offset(mSpawnDatablock, GuiNavEditorCtrl),
|
|
"Datablock to give new objects in test mode.");
|
|
|
|
Parent::initPersistFields();
|
|
}
|
|
|
|
void GuiNavEditorCtrl::onSleep()
|
|
{
|
|
Parent::onSleep();
|
|
|
|
//mMode = mSelectMode;
|
|
}
|
|
|
|
void GuiNavEditorCtrl::selectMesh(NavMesh *mesh)
|
|
{
|
|
mesh->setSelected(true);
|
|
mMesh = mesh;
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, selectMesh, void, (S32 id),,
|
|
"@brief Select a NavMesh object.")
|
|
{
|
|
NavMesh *obj;
|
|
if(Sim::findObject(id, obj))
|
|
object->selectMesh(obj);
|
|
}
|
|
|
|
S32 GuiNavEditorCtrl::getMeshId()
|
|
{
|
|
return mMesh.isNull() ? 0 : mMesh->getId();
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, getMesh, S32, (),,
|
|
"@brief Select a NavMesh object.")
|
|
{
|
|
return object->getMeshId();
|
|
}
|
|
|
|
S32 GuiNavEditorCtrl::getPlayerId()
|
|
{
|
|
return mPlayer.isNull() ? 0 : mPlayer->getId();
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, getPlayer, S32, (),,
|
|
"@brief Select a NavMesh object.")
|
|
{
|
|
return object->getPlayerId();
|
|
}
|
|
|
|
void GuiNavEditorCtrl::deselect()
|
|
{
|
|
if(!mMesh.isNull())
|
|
mMesh->setSelected(false);
|
|
mMesh = NULL;
|
|
mPlayer = mCurPlayer = NULL;
|
|
mCurTile = mTile = -1;
|
|
mLinkStart = Point3F::Max;
|
|
mLink = mCurLink = -1;
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, deselect, void, (),,
|
|
"@brief Deselect whatever is currently selected in the editor.")
|
|
{
|
|
object->deselect();
|
|
}
|
|
|
|
void GuiNavEditorCtrl::deleteLink()
|
|
{
|
|
if(!mMesh.isNull() && mLink != -1)
|
|
{
|
|
mMesh->selectLink(mLink, false);
|
|
mMesh->deleteLink(mLink);
|
|
mLink = -1;
|
|
Con::executef(this, "onLinkDeselected");
|
|
}
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, deleteLink, void, (),,
|
|
"@brief Delete the currently selected link.")
|
|
{
|
|
object->deleteLink();
|
|
}
|
|
|
|
void GuiNavEditorCtrl::setLinkFlags(const LinkData &d)
|
|
{
|
|
if(mMode == mLinkMode && !mMesh.isNull() && mLink != -1)
|
|
{
|
|
mMesh->setLinkFlags(mLink, d);
|
|
}
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, setLinkFlags, void, (U32 flags),,
|
|
"@Brief Set jump and drop properties of the selected link.")
|
|
{
|
|
object->setLinkFlags(LinkData(flags));
|
|
}
|
|
|
|
void GuiNavEditorCtrl::buildTile()
|
|
{
|
|
if(!mMesh.isNull() && mTile != -1)
|
|
mMesh->buildTile(mTile);
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, buildTile, void, (),,
|
|
"@brief Build the currently selected tile.")
|
|
{
|
|
object->buildTile();
|
|
}
|
|
|
|
void GuiNavEditorCtrl::spawnPlayer(const Point3F &pos)
|
|
{
|
|
SceneObject *obj = (SceneObject*)Sim::spawnObject(mSpawnClass, mSpawnDatablock);
|
|
if(obj)
|
|
{
|
|
MatrixF mat(true);
|
|
mat.setPosition(pos);
|
|
obj->setTransform(mat);
|
|
SimObject* cleanup = Sim::findObject("MissionCleanup");
|
|
if(cleanup)
|
|
{
|
|
SimGroup* missionCleanup = dynamic_cast<SimGroup*>(cleanup);
|
|
missionCleanup->addObject(obj);
|
|
}
|
|
mPlayer = obj;
|
|
#ifdef TORQUE_NAVIGATION_ENABLED
|
|
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(obj);
|
|
if (asAIPlayer) //try direct
|
|
{
|
|
Con::executef(this, "onPlayerSelected", Con::getIntArg(asAIPlayer->mLinkTypes.getFlags()));
|
|
}
|
|
else
|
|
{
|
|
ShapeBase* sbo = dynamic_cast<ShapeBase*>(obj);
|
|
if (sbo->getAIController())
|
|
{
|
|
if (sbo->getAIController()->mControllerData)
|
|
Con::executef(this, "onPlayerSelected", Con::getIntArg(sbo->getAIController()->mControllerData->mLinkTypes.getFlags()));
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
Con::executef(this, "onPlayerSelected");
|
|
#ifdef TORQUE_NAVIGATION_ENABLED
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, spawnPlayer, void, (),,
|
|
"@brief Spawn an AIPlayer at the centre of the screen.")
|
|
{
|
|
Point3F c;
|
|
if(object->get3DCentre(c))
|
|
object->spawnPlayer(c);
|
|
}
|
|
|
|
void GuiNavEditorCtrl::get3DCursor(GuiCursor *&cursor,
|
|
bool &visible,
|
|
const Gui3DMouseEvent &event_)
|
|
{
|
|
//cursor = mAddNodeCursor;
|
|
//visible = false;
|
|
|
|
cursor = NULL;
|
|
visible = false;
|
|
|
|
GuiCanvas *root = getRoot();
|
|
if(!root)
|
|
return;
|
|
|
|
S32 currCursor = PlatformCursorController::curArrow;
|
|
|
|
if(root->mCursorChanged == currCursor)
|
|
return;
|
|
|
|
PlatformWindow *window = root->getPlatformWindow();
|
|
PlatformCursorController *controller = window->getCursorController();
|
|
|
|
// We've already changed the cursor,
|
|
// so set it back before we change it again.
|
|
if(root->mCursorChanged != -1)
|
|
controller->popCursor();
|
|
|
|
// Now change the cursor shape
|
|
controller->pushCursor(currCursor);
|
|
root->mCursorChanged = currCursor;
|
|
}
|
|
|
|
bool GuiNavEditorCtrl::get3DCentre(Point3F &pos)
|
|
{
|
|
Point3F screen, start, end;
|
|
|
|
screen.set(getExtent().x / 2, getExtent().y / 2, 0);
|
|
unproject(screen, &start);
|
|
|
|
screen.z = 1.0f;
|
|
unproject(screen, &end);
|
|
|
|
RayInfo ri;
|
|
if(gServerContainer.castRay(start, end, StaticObjectType, &ri))
|
|
{
|
|
pos = ri.point;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void GuiNavEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
|
|
{
|
|
mGizmo->on3DMouseDown(event);
|
|
|
|
if(!isFirstResponder())
|
|
setFirstResponder();
|
|
|
|
mouseLock();
|
|
|
|
// Construct a LineSegment from the camera position to 1000 meters away in
|
|
// the direction clicked.
|
|
// If that segment hits the terrain, truncate the ray to only be that length.
|
|
|
|
Point3F startPnt = event.pos;
|
|
Point3F endPnt = event.pos + event.vec * 1000.0f;
|
|
|
|
RayInfo ri;
|
|
|
|
U8 keys = Input::getModifierKeys();
|
|
bool shift = keys & SI_LSHIFT;
|
|
bool ctrl = keys & SI_LCTRL;
|
|
|
|
if(mMode == mLinkMode && !mMesh.isNull())
|
|
{
|
|
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
|
{
|
|
U32 link = mMesh->getLink(ri.point);
|
|
if(link != -1)
|
|
{
|
|
if(mLink != -1)
|
|
mMesh->selectLink(mLink, false);
|
|
mMesh->selectLink(link, true, false);
|
|
mLink = link;
|
|
LinkData d = mMesh->getLinkFlags(mLink);
|
|
Con::executef(this, "onLinkSelected", Con::getIntArg(d.getFlags()));
|
|
}
|
|
else
|
|
{
|
|
if(mLink != -1)
|
|
{
|
|
mMesh->selectLink(mLink, false);
|
|
mLink = -1;
|
|
Con::executef(this, "onLinkDeselected");
|
|
}
|
|
else
|
|
{
|
|
if(mLinkStart != Point3F::Max)
|
|
{
|
|
mMesh->addLink(mLinkStart, ri.point);
|
|
if(!shift)
|
|
mLinkStart = Point3F::Max;
|
|
}
|
|
else
|
|
{
|
|
mLinkStart = ri.point;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mMesh->selectLink(mLink, false);
|
|
mLink = -1;
|
|
Con::executef(this, "onLinkDeselected");
|
|
}
|
|
}
|
|
|
|
if(mMode == mTileMode && !mMesh.isNull())
|
|
{
|
|
if(gServerContainer.castRay(startPnt, endPnt, StaticShapeObjectType, &ri))
|
|
{
|
|
mTile = mMesh->getTile(ri.point);
|
|
dd.clear();
|
|
mMesh->renderTileData(dd, mTile);
|
|
}
|
|
}
|
|
|
|
if(mMode == mTestMode)
|
|
{
|
|
// Spawn new character
|
|
if(ctrl)
|
|
{
|
|
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
|
spawnPlayer(ri.point);
|
|
}
|
|
// Deselect character
|
|
else if(shift)
|
|
{
|
|
mPlayer = NULL;
|
|
Con::executef(this, "onPlayerDeselected");
|
|
}
|
|
// Select/move character
|
|
else
|
|
{
|
|
if(gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
|
{
|
|
if(ri.object)
|
|
{
|
|
mPlayer = ri.object;
|
|
#ifdef TORQUE_NAVIGATION_ENABLED
|
|
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
|
if (asAIPlayer) //try direct
|
|
{
|
|
Con::executef(this, "onPlayerSelected", Con::getIntArg(asAIPlayer->mLinkTypes.getFlags()));
|
|
}
|
|
else
|
|
{
|
|
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
|
if (sbo->getAIController())
|
|
{
|
|
if (sbo->getAIController()->mControllerData)
|
|
Con::executef(this, "onPlayerSelected", Con::getIntArg(sbo->getAIController()->mControllerData->mLinkTypes.getFlags()));
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
Con::executef(this, "onPlayerSelected");
|
|
}
|
|
#ifdef TORQUE_NAVIGATION_ENABLED
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
else if (!mPlayer.isNull() && gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
|
{
|
|
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
|
if (asAIPlayer) //try direct
|
|
{
|
|
#ifdef TORQUE_NAVIGATION_ENABLED
|
|
asAIPlayer->setPathDestination(ri.point);
|
|
#else
|
|
asAIPlayer->setMoveDestination(ri.point,false);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
|
if (sbo->getAIController())
|
|
{
|
|
if (sbo->getAIController()->mControllerData)
|
|
sbo->getAIController()->getNav()->setPathDestination(ri.point, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiNavEditorCtrl::on3DMouseUp(const Gui3DMouseEvent & event)
|
|
{
|
|
// Keep the Gizmo up to date.
|
|
mGizmo->on3DMouseUp(event);
|
|
|
|
mouseUnlock();
|
|
}
|
|
|
|
void GuiNavEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event)
|
|
{
|
|
//if(mSelRiver != NULL && mSelNode != -1)
|
|
//mGizmo->on3DMouseMove(event);
|
|
|
|
Point3F startPnt = event.pos;
|
|
Point3F endPnt = event.pos + event.vec * 1000.0f;
|
|
|
|
RayInfo ri;
|
|
|
|
if(mMode == mLinkMode && !mMesh.isNull())
|
|
{
|
|
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
|
{
|
|
U32 link = mMesh->getLink(ri.point);
|
|
if(link != -1)
|
|
{
|
|
if(link != mLink)
|
|
{
|
|
if(mCurLink != -1)
|
|
mMesh->selectLink(mCurLink, false);
|
|
mMesh->selectLink(link, true, true);
|
|
}
|
|
mCurLink = link;
|
|
}
|
|
else
|
|
{
|
|
if(mCurLink != mLink)
|
|
mMesh->selectLink(mCurLink, false);
|
|
mCurLink = -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mMesh->selectLink(mCurLink, false);
|
|
mCurLink = -1;
|
|
}
|
|
}
|
|
|
|
// Select a tile from our current NavMesh.
|
|
if(mMode == mTileMode && !mMesh.isNull())
|
|
{
|
|
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
|
mCurTile = mMesh->getTile(ri.point);
|
|
else
|
|
mCurTile = -1;
|
|
}
|
|
|
|
if(mMode == mTestMode)
|
|
{
|
|
if(gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
|
mCurPlayer = ri.object;
|
|
else
|
|
mCurPlayer = NULL;
|
|
}
|
|
}
|
|
|
|
void GuiNavEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event)
|
|
{
|
|
mGizmo->on3DMouseDragged(event);
|
|
if(mGizmo->isDirty())
|
|
{
|
|
Point3F scale = mGizmo->getScale();
|
|
const MatrixF &mat = mGizmo->getTransform();
|
|
VectorF normal;
|
|
mat.getColumn(2, &normal);
|
|
|
|
//mSelRiver->setNode(pos, scale.x, scale.z, normal, mSelNode);
|
|
mIsDirty = true;
|
|
}
|
|
}
|
|
|
|
void GuiNavEditorCtrl::on3DMouseEnter(const Gui3DMouseEvent & event)
|
|
{
|
|
}
|
|
|
|
void GuiNavEditorCtrl::on3DMouseLeave(const Gui3DMouseEvent & event)
|
|
{
|
|
}
|
|
|
|
void GuiNavEditorCtrl::updateGuiInfo()
|
|
{
|
|
}
|
|
|
|
void GuiNavEditorCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|
{
|
|
PROFILE_SCOPE(GuiNavEditorCtrl_OnRender);
|
|
|
|
Parent::onRender(offset, updateRect);
|
|
return;
|
|
}
|
|
|
|
static void renderBoxOutline(const Box3F &box, const ColorI &col)
|
|
{
|
|
if(box != Box3F::Invalid)
|
|
{
|
|
GFXStateBlockDesc desc;
|
|
desc.setCullMode(GFXCullNone);
|
|
desc.setFillModeSolid();
|
|
desc.setZReadWrite(true, false);
|
|
desc.setBlend(true);
|
|
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 20));
|
|
desc.setFillModeWireframe();
|
|
desc.setBlend(false);
|
|
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 255));
|
|
}
|
|
}
|
|
|
|
void GuiNavEditorCtrl::renderScene(const RectI & updateRect)
|
|
{
|
|
GFX->setStateBlock(mZDisableSB);
|
|
|
|
// get the projected size...
|
|
GameConnection* connection = GameConnection::getConnectionToServer();
|
|
if(!connection)
|
|
return;
|
|
|
|
// Grab the camera's transform
|
|
MatrixF mat;
|
|
connection->getControlCameraTransform(0, &mat);
|
|
|
|
// Get the camera position
|
|
Point3F camPos;
|
|
mat.getColumn(3,&camPos);
|
|
|
|
if(mMode == mLinkMode)
|
|
{
|
|
if(mLinkStart != Point3F::Max)
|
|
{
|
|
GFXStateBlockDesc desc;
|
|
desc.setBlend(false);
|
|
desc.setZReadWrite(true ,true);
|
|
MatrixF linkMat(true);
|
|
linkMat.setPosition(mLinkStart);
|
|
Point3F scale(0.8f, 0.8f, 0.8f);
|
|
GFX->getDrawUtil()->drawTransform(desc, linkMat, &scale);
|
|
}
|
|
}
|
|
|
|
if(mMode == mTileMode && !mMesh.isNull())
|
|
{
|
|
renderBoxOutline(mMesh->getTileBox(mCurTile), ColorI::BLUE);
|
|
renderBoxOutline(mMesh->getTileBox(mTile), ColorI::GREEN);
|
|
if(Con::getBoolVariable("$Nav::Editor::renderVoxels", false)) dd.renderGroup(0);
|
|
if(Con::getBoolVariable("$Nav::Editor::renderInput", false))
|
|
{
|
|
dd.depthMask(false);
|
|
dd.renderGroup(1);
|
|
dd.depthMask(true);
|
|
}
|
|
}
|
|
|
|
if(mMode == mTestMode)
|
|
{
|
|
if(!mCurPlayer.isNull())
|
|
renderBoxOutline(mCurPlayer->getWorldBox(), ColorI::BLUE);
|
|
if(!mPlayer.isNull())
|
|
renderBoxOutline(mPlayer->getWorldBox(), ColorI::GREEN);
|
|
}
|
|
|
|
duDebugDrawTorque d;
|
|
if(!mMesh.isNull())
|
|
mMesh->renderLinks(d);
|
|
d.render();
|
|
|
|
// Now draw all the 2d stuff!
|
|
GFX->setClipRect(updateRect);
|
|
}
|
|
|
|
bool GuiNavEditorCtrl::getStaticPos(const Gui3DMouseEvent & event, Point3F &tpos)
|
|
{
|
|
// Find clicked point on the terrain
|
|
|
|
Point3F startPnt = event.pos;
|
|
Point3F endPnt = event.pos + event.vec * 1000.0f;
|
|
|
|
RayInfo ri;
|
|
bool hit;
|
|
|
|
hit = gServerContainer.castRay(startPnt, endPnt, StaticShapeObjectType, &ri);
|
|
tpos = ri.point;
|
|
|
|
return hit;
|
|
}
|
|
|
|
void GuiNavEditorCtrl::setMode(String mode, bool sourceShortcut = false)
|
|
{
|
|
mMode = mode;
|
|
Con::executef(this, "onModeSet", mode);
|
|
|
|
if(sourceShortcut)
|
|
Con::executef(this, "paletteSync", mode);
|
|
}
|
|
|
|
void GuiNavEditorCtrl::submitUndo(const UTF8 *name)
|
|
{
|
|
// Grab the mission editor undo manager.
|
|
UndoManager *undoMan = NULL;
|
|
if(!Sim::findObject("EUndoManager", undoMan))
|
|
{
|
|
Con::errorf("GuiNavEditorCtrl::submitUndo() - EUndoManager not found!");
|
|
return;
|
|
}
|
|
|
|
// Setup the action.
|
|
GuiNavEditorUndoAction *action = new GuiNavEditorUndoAction(name);
|
|
|
|
action->mNavEditor = this;
|
|
|
|
undoMan->addAction(action);
|
|
}
|
|
|
|
void GuiNavEditorCtrl::_prepRenderImage(SceneManager* sceneGraph, const SceneRenderState* state)
|
|
{
|
|
/*if(isAwake() && River::smEditorOpen && mSelRiver)
|
|
{
|
|
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
|
|
ri->type = RenderPassManager::RIT_Editor;
|
|
ri->renderDelegate.bind(this, &GuiNavEditorCtrl::_renderSelectedRiver);
|
|
ri->defaultKey = 100;
|
|
state->getRenderPass()->addInst(ri);
|
|
}*/
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, getMode, const char*, (), , "")
|
|
{
|
|
return object->getMode();
|
|
}
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, setMode, void, (String mode),, "setMode(String mode)")
|
|
{
|
|
object->setMode(mode);
|
|
}
|
|
#endif
|