off mesh connection tool

Adds off mesh connection tool
upgrade functionality to allow setting the direction to be bi-directional
added immediate draw to duDebugDrawtorque so we can draw offmesh connections
This commit is contained in:
marauder2k7 2025-07-24 23:43:35 +01:00
parent de1642c33e
commit 2df2cb5c15
8 changed files with 287 additions and 87 deletions

View file

@ -0,0 +1,189 @@
#include "offMeshConnTool.h"
#include "navigation/guiNavEditorCtrl.h"
#include "console/consoleTypes.h"
#include "gfx/gfxDrawUtil.h"
#include "scene/sceneManager.h"
#include "math/mathUtils.h"
IMPLEMENT_CONOBJECT(OffMeshConnectionTool);
void OffMeshConnectionTool::onActivated(const Gui3DMouseEvent& evt)
{
Con::executef(this, "onActivated");
}
void OffMeshConnectionTool::onDeactivated()
{
Con::executef(this, "onDeactivated");
}
void OffMeshConnectionTool::on3DMouseDown(const Gui3DMouseEvent& evt)
{
if (mNavMesh.isNull())
return;
Point3F startPnt = evt.pos;
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
RayInfo ri;
bool shift = evt.modifier & SI_LSHIFT;
bool ctrl = evt.modifier & SI_LCTRL;
if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
{
U32 link = mNavMesh->getLink(ri.point);
if (link != -1)
{
if (mLink != -1)
mNavMesh->selectLink(mLink, false);
mNavMesh->selectLink(link, true, false);
mLink = link;
if (ctrl)
{
mNavMesh->selectLink(mLink, false);
mNavMesh->deleteLink(mLink);
mLink = -1;
Con::executef(this, "onLinkDeselected");
return;
}
else
{
LinkData d = mNavMesh->getLinkFlags(mLink);
bool biDir = mNavMesh->getLinkDir(mLink);
Con::executef(this, "onLinkSelected", Con::getIntArg(d.getFlags()), Con::getBoolArg(biDir));
}
}
else
{
if (mLink != -1)
{
mNavMesh->selectLink(mLink, false);
mLink = -1;
Con::executef(this, "onLinkDeselected");
}
if (mLinkStart != Point3F::Max)
{
mLink = mNavMesh->addLink(mLinkStart, ri.point, mBiDir);
mNavMesh->selectLink(mLink, true, false);
mLinkStart = Point3F::Max;
Con::executef(this, "onLinkSelected", Con::getIntArg(mLinkCache.getFlags()), Con::getBoolArg(mBiDir));
}
else
{
mLinkStart = ri.point;
}
}
}
else
{
if (mLink != -1)
{
mNavMesh->selectLink(mLink, false);
mLink = -1;
Con::executef(this, "onLinkDeselected");
}
}
}
void OffMeshConnectionTool::on3DMouseMove(const Gui3DMouseEvent& evt)
{
if (mNavMesh.isNull())
return;
Point3F startPnt = evt.pos;
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
RayInfo ri;
if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
{
U32 link = mNavMesh->getLink(ri.point);
if (link != -1)
{
if (link != mLink)
{
if (mCurLink != -1)
mNavMesh->selectLink(mCurLink, false);
mNavMesh->selectLink(link, true, true);
}
mCurLink = link;
}
else
{
if (mCurLink != mLink)
mNavMesh->selectLink(mCurLink, false);
mCurLink = -1;
}
}
else
{
mNavMesh->selectLink(mCurLink, false);
mCurLink = -1;
}
}
void OffMeshConnectionTool::onRender3D()
{
if (mNavMesh.isNull())
return;
duDebugDrawTorque dd;
if (mLinkStart != Point3F::Max)
{
Point3F rcFrom = DTStoRC(mLinkStart);
dd.begin(DU_DRAW_LINES);
dd.depthMask(false);
duAppendCircle(&dd, rcFrom.x, rcFrom.y, rcFrom.z, mNavMesh->mWalkableRadius, duRGBA(0, 255, 0, 255));
dd.end();
}
mNavMesh->renderLinks(dd);
dd.immediateRender();
}
bool OffMeshConnectionTool::updateGuiInfo()
{
SimObject* statusbar;
Sim::findObject("EditorGuiStatusBar", statusbar);
GuiTextCtrl* selectionBar;
Sim::findObject("EWorldEditorStatusBarSelection", selectionBar);
String text;
text = "LMB To Select Link. CTRL+LMB To Delete Link";
if (statusbar)
Con::executef(statusbar, "setInfo", text.c_str());
if (mLink != -1)
text = String::ToString("Selected Link: %d", mLink);
else
text = "";
if (selectionBar)
selectionBar->setText(text);
return true;
}
void OffMeshConnectionTool::setLinkProperties(const LinkData& d, bool biDir)
{
if (!mNavMesh.isNull() && mLink != -1)
{
mNavMesh->setLinkFlags(mLink, d);
mNavMesh->setLinkDir(mLink, biDir);
}
mLinkCache = d;
mBiDir = biDir;
}
DefineEngineMethod(OffMeshConnectionTool, setLinkProperties, void, (U32 flags, bool biDir), ,
"@Brief Set properties of the selected link.")
{
object->setLinkProperties(LinkData(flags), biDir);
}

View file

@ -0,0 +1,44 @@
#ifndef _OFFMESHCONNTOOL_H_
#define _OFFMESHCONNTOOL_H_
#ifndef _NAVMESH_TOOL_H_
#include "navigation/navMeshTool.h"
#endif
class OffMeshConnectionTool : public NavMeshTool
{
typedef NavMeshTool Parent;
bool mStartPosSet;
bool mBiDir;
S32 mLink;
S32 mCurLink;
Point3F mLinkStart;
LinkData mLinkCache;
public:
DECLARE_CONOBJECT(OffMeshConnectionTool);
OffMeshConnectionTool() {
mStartPosSet = false;
mBiDir = false;
mLink = -1;
mCurLink = -1;
mLinkStart = Point3F::Max;
mLinkCache = LinkData(0);
}
virtual ~OffMeshConnectionTool() {}
void onActivated(const Gui3DMouseEvent& evt) override;
void onDeactivated() override;
void on3DMouseDown(const Gui3DMouseEvent& evt) override;
void on3DMouseMove(const Gui3DMouseEvent& evt) override;
void onRender3D() override;
bool updateGuiInfo() override;
void setLinkProperties(const LinkData& d, bool biDir);
};
#endif

View file

@ -69,9 +69,6 @@ void TileTool::onRender3D()
if (mNavMesh.isNull())
return;
// Optional: Draw all tile bounds as overlays
//mNavMesh->renderTilesOverlay(DebugDraw::get()->getDD());
if(mCurTile != -1)
renderBoxOutline(mNavMesh->getTileBox(mCurTile), ColorI::BLUE);
@ -87,8 +84,8 @@ void TileTool::buildTile()
bool TileTool::updateGuiInfo()
{
GuiTextCtrl* statusbar;
Sim::findObject("EWorldEditorStatusBarInfo", statusbar);
SimObject* statusbar;
Sim::findObject("EditorGuiStatusBar", statusbar);
GuiTextCtrl* selectionBar;
Sim::findObject("EWorldEditorStatusBarSelection", selectionBar);
@ -98,7 +95,7 @@ bool TileTool::updateGuiInfo()
text = "LMB To select NavMesh Tile";
if (statusbar)
statusbar->setText(text);
Con::executef(statusbar, "setInfo", text.c_str());
if (mSelTile != -1)
text = String::ToString("Selected Tile: %d", mSelTile);