2014-11-28 08:42:10 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// 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.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2022-07-03 04:27:18 +00:00
|
|
|
#include "torqueConfig.h"
|
2022-06-13 17:38:08 +00:00
|
|
|
#ifdef TORQUE_TOOLS
|
2014-11-28 08:42:10 +00:00
|
|
|
#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"
|
2025-04-19 09:25:36 +00:00
|
|
|
#include "T3D/AI/AIController.h"
|
2025-07-27 18:32:52 +00:00
|
|
|
#include "navigation/navMeshTool.h"
|
2014-11-28 08:42:10 +00:00
|
|
|
|
|
|
|
|
IMPLEMENT_CONOBJECT(GuiNavEditorCtrl);
|
|
|
|
|
|
|
|
|
|
ConsoleDocClass(GuiNavEditorCtrl,
|
|
|
|
|
"@brief GUI tool that makes up the Navigation Editor\n\n"
|
|
|
|
|
"Editor use only.\n\n"
|
|
|
|
|
"@internal"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
GuiNavEditorCtrl::GuiNavEditorCtrl()
|
|
|
|
|
{
|
|
|
|
|
mIsDirty = false;
|
|
|
|
|
mStartDragMousePoint = InvalidMousePoint;
|
|
|
|
|
mMesh = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
{
|
2023-01-27 07:13:15 +00:00
|
|
|
docsURL;
|
2014-11-28 08:42:10 +00:00
|
|
|
addField("isDirty", TypeBool, Offset(mIsDirty, GuiNavEditorCtrl));
|
|
|
|
|
|
|
|
|
|
Parent::initPersistFields();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GuiNavEditorCtrl::onSleep()
|
|
|
|
|
{
|
|
|
|
|
Parent::onSleep();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GuiNavEditorCtrl::selectMesh(NavMesh *mesh)
|
|
|
|
|
{
|
|
|
|
|
mesh->setSelected(true);
|
|
|
|
|
mMesh = mesh;
|
2025-07-25 07:46:55 +00:00
|
|
|
|
|
|
|
|
if (mTool)
|
|
|
|
|
mTool->setActiveNavMesh(mMesh);
|
2014-11-28 08:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2025-07-23 14:08:29 +00:00
|
|
|
if (mTool)
|
|
|
|
|
mTool->on3DMouseDown(event);
|
2014-11-28 08:42:10 +00:00
|
|
|
|
|
|
|
|
mouseLock();
|
|
|
|
|
|
2025-07-23 14:08:29 +00:00
|
|
|
return;
|
2014-11-28 08:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GuiNavEditorCtrl::on3DMouseUp(const Gui3DMouseEvent & event)
|
|
|
|
|
{
|
|
|
|
|
// Keep the Gizmo up to date.
|
|
|
|
|
mGizmo->on3DMouseUp(event);
|
|
|
|
|
|
2025-07-23 14:08:29 +00:00
|
|
|
if (mTool)
|
|
|
|
|
mTool->on3DMouseUp(event);
|
|
|
|
|
|
2014-11-28 08:42:10 +00:00
|
|
|
mouseUnlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GuiNavEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event)
|
|
|
|
|
{
|
2025-07-23 14:08:29 +00:00
|
|
|
if (mTool)
|
|
|
|
|
mTool->on3DMouseMove(event);
|
|
|
|
|
|
|
|
|
|
return;
|
2014-11-28 08:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
{
|
2025-07-23 14:08:29 +00:00
|
|
|
if (mTool)
|
|
|
|
|
{
|
|
|
|
|
if (mTool->updateGuiInfo())
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-11-28 08:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GuiNavEditorCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|
|
|
|
{
|
|
|
|
|
PROFILE_SCOPE(GuiNavEditorCtrl_OnRender);
|
|
|
|
|
|
|
|
|
|
Parent::onRender(offset, updateRect);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2025-07-23 14:08:29 +00:00
|
|
|
if (mTool)
|
|
|
|
|
mTool->onRender3D();
|
|
|
|
|
|
2014-11-28 08:42:10 +00:00
|
|
|
duDebugDrawTorque d;
|
2025-07-26 09:48:49 +00:00
|
|
|
if (!mMesh.isNull())
|
|
|
|
|
{
|
2014-11-28 08:42:10 +00:00
|
|
|
mMesh->renderLinks(d);
|
2025-07-26 09:48:49 +00:00
|
|
|
d.immediateRender();
|
|
|
|
|
}
|
2014-11-28 08:42:10 +00:00
|
|
|
|
|
|
|
|
// 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::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);
|
|
|
|
|
}*/
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-23 14:08:29 +00:00
|
|
|
void GuiNavEditorCtrl::setActiveTool(NavMeshTool* tool)
|
|
|
|
|
{
|
|
|
|
|
if (mTool)
|
|
|
|
|
{
|
|
|
|
|
mTool->onDeactivated();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mTool = tool;
|
|
|
|
|
|
|
|
|
|
if (mTool)
|
|
|
|
|
{
|
2025-07-27 18:32:52 +00:00
|
|
|
mTool->setActiveEditor(this);
|
2025-07-23 14:08:29 +00:00
|
|
|
mTool->setActiveNavMesh(mMesh);
|
|
|
|
|
mTool->onActivated(mLastEvent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-24 13:25:02 +00:00
|
|
|
void GuiNavEditorCtrl::setDrawMode(S32 id)
|
|
|
|
|
{
|
|
|
|
|
if (mMesh.isNull())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
mMesh->setDrawMode((NavMesh::DrawMode)id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, setDrawMode, void, (S32 id), ,
|
|
|
|
|
"@brief Deselect whatever is currently selected in the editor.")
|
|
|
|
|
{
|
|
|
|
|
object->setDrawMode(id);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-23 14:08:29 +00:00
|
|
|
DefineEngineMethod(GuiNavEditorCtrl, setActiveTool, void, (const char* toolName), , "( NavMeshTool tool )")
|
|
|
|
|
{
|
|
|
|
|
NavMeshTool* tool = dynamic_cast<NavMeshTool*>(Sim::findObject(toolName));
|
|
|
|
|
object->setActiveTool(tool);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-13 17:38:08 +00:00
|
|
|
#endif
|