diff --git a/Engine/source/navigation/duDebugDrawTorque.cpp b/Engine/source/navigation/duDebugDrawTorque.cpp index a1e3f1c0d..8bcd5a48c 100644 --- a/Engine/source/navigation/duDebugDrawTorque.cpp +++ b/Engine/source/navigation/duDebugDrawTorque.cpp @@ -421,3 +421,25 @@ void duDebugDrawTorque::render(SceneRenderState* state) } } +void duDebugDrawTorque::immediateRender() +{ + for (U32 i = 0; i < mDrawCache.size(); ++i) + { + const CachedDraw& draw = mDrawCache[i]; + + GFX->setPrimitiveBuffer(draw.primitiveBuffer); + GFX->setStateBlockByDesc(draw.state); + GFX->setupGenericShaders(GFXDevice::GSColor); + GFX->setVertexBuffer(draw.buffer); + + GFX->drawIndexedPrimitive( + draw.primType, + 0, // start vertex + 0, // min vertex index + draw.vertexCount, // vertex count + 0, // start index + draw.primitiveCount // primitive count + ); + } +} + diff --git a/Engine/source/navigation/duDebugDrawTorque.h b/Engine/source/navigation/duDebugDrawTorque.h index 6ffcd378f..c18daf66e 100644 --- a/Engine/source/navigation/duDebugDrawTorque.h +++ b/Engine/source/navigation/duDebugDrawTorque.h @@ -105,6 +105,7 @@ public: void clearCache(); void render(SceneRenderState* state); + void immediateRender(); private: diff --git a/Engine/source/navigation/guiNavEditorCtrl.cpp b/Engine/source/navigation/guiNavEditorCtrl.cpp index c055acd5b..e825cefb2 100644 --- a/Engine/source/navigation/guiNavEditorCtrl.cpp +++ b/Engine/source/navigation/guiNavEditorCtrl.cpp @@ -323,51 +323,6 @@ void GuiNavEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event) 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 == mTestMode) { // Spawn new character @@ -471,35 +426,6 @@ void GuiNavEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event) 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; - } - } - if(mMode == mTestMode) { if(gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri)) diff --git a/Engine/source/navigation/navMesh.cpp b/Engine/source/navigation/navMesh.cpp index 13164d780..3d7e714c9 100644 --- a/Engine/source/navigation/navMesh.cpp +++ b/Engine/source/navigation/navMesh.cpp @@ -405,7 +405,7 @@ void NavMesh::setScale(const VectorF &scale) Parent::setScale(scale); } -S32 NavMesh::addLink(const Point3F &from, const Point3F &to, U32 flags) +S32 NavMesh::addLink(const Point3F &from, const Point3F &to, bool biDir, U32 flags) { Point3F rcFrom = DTStoRC(from), rcTo = DTStoRC(to); mLinkVerts.push_back(rcFrom.x); @@ -416,7 +416,7 @@ S32 NavMesh::addLink(const Point3F &from, const Point3F &to, U32 flags) mLinkVerts.push_back(rcTo.z); mLinksUnsynced.push_back(true); mLinkRads.push_back(mWalkableRadius); - mLinkDirs.push_back(0); + mLinkDirs.push_back(biDir ? 1 : 0); mLinkAreas.push_back(OffMeshArea); if (flags == 0) { Point3F dir = to - from; @@ -435,11 +435,11 @@ S32 NavMesh::addLink(const Point3F &from, const Point3F &to, U32 flags) return mLinkIDs.size() - 1; } -DefineEngineMethod(NavMesh, addLink, S32, (Point3F from, Point3F to, U32 flags), (0), +DefineEngineMethod(NavMesh, addLink, S32, (Point3F from, Point3F to, bool biDir, U32 flags), (0), "Add a link to this NavMesh between two points.\n\n" "") { - return object->addLink(from, to, flags); + return object->addLink(from, to, biDir, flags); } S32 NavMesh::getLink(const Point3F &pos) @@ -482,6 +482,23 @@ LinkData NavMesh::getLinkFlags(U32 idx) return LinkData(); } +bool NavMesh::getLinkDir(U32 idx) +{ + if (idx < mLinkIDs.size()) + { + return mLinkDirs[idx]; + } +} + +void NavMesh::setLinkDir(U32 idx, bool biDir) +{ + if (idx < mLinkIDs.size()) + { + mLinkDirs[idx] = biDir ? 1 : 0; + mLinksUnsynced[idx] = true; + } +} + DefineEngineMethod(NavMesh, getLinkFlags, S32, (U32 id),, "Get the flags set for a particular off-mesh link.") { @@ -1667,8 +1684,8 @@ void NavMesh::renderLinks(duDebugDraw &dd) { if(mBuilding) return; - dd.depthMask(true); dd.begin(DU_DRAW_LINES); + dd.depthMask(false); for(U32 i = 0; i < mLinkIDs.size(); i++) { U32 col = 0; @@ -1686,7 +1703,7 @@ void NavMesh::renderLinks(duDebugDraw &dd) s[0], s[1], s[2], e[0], e[1], e[2], 0.3f, - 0.0f, mLinkFlags[i] == DropFlag ? 0.0f : 0.4f, + (mLinkDirs[i]&1) ? 0.6f : 0.0f, mLinkFlags[i] == DropFlag ? 0.0f : 0.6f, col); if(!mDeleteLinks[i]) duAppendCircle(&dd, e[0], e[1], e[2], mLinkRads[i], col); diff --git a/Engine/source/navigation/navMesh.h b/Engine/source/navigation/navMesh.h index d81df419e..1e6d7376e 100644 --- a/Engine/source/navigation/navMesh.h +++ b/Engine/source/navigation/navMesh.h @@ -151,7 +151,7 @@ public: /// @{ /// Add an off-mesh link. - S32 addLink(const Point3F &from, const Point3F &to, U32 flags = 0); + S32 addLink(const Point3F &from, const Point3F &to, bool biDir, U32 flags = 0); /// Get the ID of the off-mesh link near the point. S32 getLink(const Point3F &pos); @@ -168,6 +168,10 @@ public: /// Get the flags used by a link. LinkData getLinkFlags(U32 idx); + bool getLinkDir(U32 idx); + + void setLinkDir(U32 idx, bool biDir); + /// Set flags used by a link. void setLinkFlags(U32 idx, const LinkData &d); diff --git a/Engine/source/navigation/navMeshTools/offMeshConnTool.cpp b/Engine/source/navigation/navMeshTools/offMeshConnTool.cpp new file mode 100644 index 000000000..088abdb26 --- /dev/null +++ b/Engine/source/navigation/navMeshTools/offMeshConnTool.cpp @@ -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); +} diff --git a/Engine/source/navigation/navMeshTools/offMeshConnTool.h b/Engine/source/navigation/navMeshTools/offMeshConnTool.h new file mode 100644 index 000000000..6e6732bdf --- /dev/null +++ b/Engine/source/navigation/navMeshTools/offMeshConnTool.h @@ -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 diff --git a/Engine/source/navigation/navMeshTools/tileTool.cpp b/Engine/source/navigation/navMeshTools/tileTool.cpp index 1ad3a4742..c77923832 100644 --- a/Engine/source/navigation/navMeshTools/tileTool.cpp +++ b/Engine/source/navigation/navMeshTools/tileTool.cpp @@ -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);