Jelajahi Sumber

Adds a notes object that only displays in the editor, useful for when working on maps.

Areloch 5 tahun lalu
induk
melakukan
4ffe6d2bb7

+ 163 - 0
Engine/source/T3D/notesObject.cpp

@@ -0,0 +1,163 @@
+#include "T3D/notesObject.h"
+
+#include "math/mathIO.h"
+#include "scene/sceneRenderState.h"
+#include "core/stream/bitStream.h"
+#include "materials/sceneData.h"
+#include "gfx/gfxDebugEvent.h"
+#include "gfx/gfxTransformSaver.h"
+#include "renderInstance/renderPassManager.h"
+#include "math\mathUtils.h"
+#include "gfx/gfxDrawUtil.h"
+
+IMPLEMENT_CO_NETOBJECT_V1(NotesObject);
+
+extern bool gEditingMission;
+
+//-----------------------------------------------------------------------------
+// Object setup and teardown
+//-----------------------------------------------------------------------------
+NotesObject::NotesObject()
+{
+   // Flag this object so that it will always
+   // be sent across the network to clients
+   mNetFlags.set(Ghostable | ScopeAlways);
+
+   // Set it as a "static" object
+   mTypeMask |= StaticObjectType | StaticShapeObjectType;
+
+   mShowArrow = true;
+   mArrowLength = 5;
+   mArrowRadius = 0.25;
+}
+
+NotesObject::~NotesObject()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Object Editing
+//-----------------------------------------------------------------------------
+void NotesObject::initPersistFields()
+{
+   Parent::initPersistFields();
+
+   addField("Note", TypeCommand, Offset(mNote, NotesObject), "");
+
+   addField("showArrow", TypeBool, Offset(mShowArrow, NotesObject), "");
+
+   addField("arrowColor", TypeColorF, Offset(mArrowColor, NotesObject), "");
+}
+
+void NotesObject::inspectPostApply()
+{
+   // Apply any transformations set in the editor
+   Parent::inspectPostApply();
+
+   if (isServerObject())
+   {
+      setMaskBits(-1);
+   }
+}
+
+bool NotesObject::onAdd()
+{
+   if (!Parent::onAdd())
+      return false;
+
+   // Set up a 1x1x1 bounding box
+   mObjBox.set(Point3F(-0.5f, -0.5f, -0.5f),
+      Point3F(0.5f, 0.5f, 0.5f));
+
+   resetWorldBox();
+
+   // Add this object to the scene
+   addToScene();
+
+   return true;
+}
+
+void NotesObject::onRemove()
+{
+   // Remove this object from the scene
+   removeFromScene();
+
+   Parent::onRemove();
+}
+
+void NotesObject::setTransform(const MatrixF& mat)
+{
+   // Let SceneObject handle all of the matrix manipulation
+   Parent::setTransform(mat);
+
+   // Dirty our network mask so that the new transform gets
+   // transmitted to the client object
+   setMaskBits(TransformMask);
+}
+
+U32 NotesObject::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
+{
+   // Allow the Parent to get a crack at writing its info
+   U32 retMask = Parent::packUpdate(conn, mask, stream);
+
+   // Write our transform information
+   //if (stream->writeFlag(mask & TransformMask))
+   {
+      mathWrite(*stream, getTransform());
+      mathWrite(*stream, getScale());
+      stream->write(mShowArrow);
+
+      stream->write(mArrowColor);
+   }
+
+   return retMask;
+}
+
+void NotesObject::unpackUpdate(NetConnection* conn, BitStream* stream)
+{
+   // Let the Parent read any info it sent
+   Parent::unpackUpdate(conn, stream);
+
+   //if (stream->readFlag())  // TransformMask
+   {
+      mathRead(*stream, &mObjToWorld);
+      mathRead(*stream, &mObjScale);
+
+      setTransform(mObjToWorld);
+
+      stream->read(&mShowArrow);
+      stream->read(&mArrowColor);
+   }
+}
+
+void NotesObject::prepRenderImage(SceneRenderState* state)
+{
+   if (!gEditingMission)
+      return;
+
+   ObjectRenderInst* ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
+   ri->renderDelegate.bind(this, &NotesObject::_render);
+   ri->type = RenderPassManager::RIT_Editor;
+   state->getRenderPass()->addInst(ri);
+}
+
+void NotesObject::_render(ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat)
+{
+   if (showArrow())
+   {
+      GFXStateBlockDesc desc;
+      desc.setBlend(true);
+      desc.setZReadWrite(true, false);
+
+      VectorF forwardVec = getTransform().getForwardVector();
+      forwardVec.normalize();
+
+       Point3F startPos = forwardVec * -(mArrowLength * 0.5) + getPosition();
+      Point3F endPos = forwardVec * (mArrowLength * 0.5) + getPosition();
+
+      ColorI arrowColor = mArrowColor.toColorI();
+      arrowColor.alpha = 128;
+
+      GFX->getDrawUtil()->drawArrow(desc, startPos, endPos, arrowColor, mArrowRadius);
+   }
+}

+ 103 - 0
Engine/source/T3D/notesObject.h

@@ -0,0 +1,103 @@
+#pragma once
+
+#ifndef _SCENEOBJECT_H_
+#include "scene/sceneObject.h"
+#endif
+#ifndef _GFXSTATEBLOCK_H_
+#include "gfx/gfxStateBlock.h"
+#endif
+#ifndef _GFXVERTEXBUFFER_H_
+#include "gfx/gfxVertexBuffer.h"
+#endif
+#ifndef _GFXPRIMITIVEBUFFER_H_
+#include "gfx/gfxPrimitiveBuffer.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// This class implements a basic SceneObject that can exist in the world at a
+// 3D position and render itself. Note that NotesObject handles its own
+// rendering by submitting itself as an ObjectRenderInst (see
+// renderInstance\renderPassmanager.h) along with a delegate for its render()
+// function. However, the preffered rendering method in the engine is to submit
+// a MeshRenderInst along with a Material, vertex buffer, primitive buffer, and
+// transform and allow the RenderMeshMgr handle the actual rendering. You can
+// see this implemented in RenderMeshExample.
+//-----------------------------------------------------------------------------
+
+class NotesObject : public SceneObject
+{
+   typedef SceneObject Parent;
+
+   String mNote;
+   bool mShowArrow;
+   F32 mArrowLength;
+   F32 mArrowRadius;
+
+   LinearColorF mArrowColor;
+
+   // Networking masks
+   // We need to implement at least one of these to allow
+   // the client version of the object to receive updates
+   // from the server version (like if it has been moved
+   // or edited)
+   enum MaskBits
+   {
+      TransformMask = Parent::NextFreeMask << 0,
+      NextFreeMask = Parent::NextFreeMask << 1
+   };
+
+   //--------------------------------------------------------------------------
+   // Rendering variables
+   //--------------------------------------------------------------------------
+   // Define our vertex format here so we don't have to
+   // change it in multiple spots later
+   typedef GFXVertexPCN VertexType;
+
+   // The handles for our StateBlocks
+   GFXStateBlockRef mNormalSB;
+   GFXStateBlockRef mReflectSB;
+
+   // The GFX vertex and primitive buffers
+   GFXVertexBufferHandle< VertexType > mVertexBuffer;
+
+public:
+   NotesObject();
+   virtual ~NotesObject();
+
+   // Declare this object as a ConsoleObject so that we can
+   // instantiate it into the world and network it
+   DECLARE_CONOBJECT(NotesObject);
+
+   //--------------------------------------------------------------------------
+   // Object Editing
+   // Since there is always a server and a client object in Torque and we
+   // actually edit the server object we need to implement some basic
+   // networking functions
+   //--------------------------------------------------------------------------
+   // Set up any fields that we want to be editable (like position)
+   static void initPersistFields();
+
+   void inspectPostApply();
+
+   // Handle when we are added to the scene and removed from the scene
+   bool onAdd();
+   void onRemove();
+
+   // Override this so that we can dirty the network flag when it is called
+   void setTransform(const MatrixF& mat);
+
+   // This function handles sending the relevant data from the server
+   // object to the client object
+   U32 packUpdate(NetConnection* conn, U32 mask, BitStream* stream);
+   // This function handles receiving relevant data from the server
+   // object and applying it to the client object
+   void unpackUpdate(NetConnection* conn, BitStream* stream);
+
+   // This is the function that allows this object to submit itself for rendering
+   void prepRenderImage(SceneRenderState* state);
+
+   void _render(ObjectRenderInst* ri, SceneRenderState* state, BaseMatInstance* overrideMat);
+
+   String getNote() { return mNote; }
+   bool showArrow() { return mShowArrow; }
+};

+ 32 - 0
Engine/source/gui/worldEditor/worldEditor.cpp

@@ -52,6 +52,7 @@
 #include "tools/editorTool.h"
 
 #include "T3D/Scene.h"
+#include <T3D\notesObject.h>
 
 IMPLEMENT_CONOBJECT( WorldEditor );
 
@@ -1709,6 +1710,37 @@ void WorldEditor::renderScreenObj( SceneObject *obj, const Point3F& projPos, con
 		  drawer->drawText(mProfile->mFont, pos, str);
 	  };
    }
+
+   NotesObject* noteObj = dynamic_cast<NotesObject*>(obj);
+   if (noteObj)
+   {
+      Point2I pos(sPos);
+
+      MatrixF cameraMat = mLastCameraQuery.cameraMatrix;
+
+      Point3F camPos = cameraMat.getPosition();
+      Point3F notePos = noteObj->getPosition();
+
+      VectorF distVec = notePos - camPos;
+      F32 dist = distVec.len();
+
+      F32 maxNoteDistance = 100;
+      F32 noteFadeStartDist = 50;
+
+      F32 fade = 1;
+
+      if(dist >= noteFadeStartDist)
+         fade = -((dist - noteFadeStartDist) / (maxNoteDistance - noteFadeStartDist));
+
+      if (dist >= maxNoteDistance)
+         return;
+
+      ColorI noteTextColor = mObjectTextColor;
+      noteTextColor.alpha = 255 * fade;
+
+      drawer->setBitmapModulation(noteTextColor);
+      drawer->drawText(mProfile->mFont, pos, noteObj->getNote().c_str());
+   }
 }
 
 //------------------------------------------------------------------------------

+ 5 - 0
Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui

@@ -1070,6 +1070,11 @@ function ObjectBuilderGui::buildObserverDropPoint(%this)
    %this.process();
 }
 
+function ObjectBuilderGui::buildNotesObject(%this)
+{
+   %this.objectClassName = "NotesObject";
+   %this.process();
+}
 //------------------------------------------------------------------------------
 // System
 //------------------------------------------------------------------------------

+ 1 - 0
Templates/BaseGame/game/tools/worldEditor/scripts/editors/creator.ed.cs

@@ -93,6 +93,7 @@ function EWCreatorWindow::init( %this )
       %this.registerMissionObject("NavMesh", "Navigation mesh");
       %this.registerMissionObject("NavPath", "Path");
       %this.registerMissionObject( "Entity",       "Entity" );
+      %this.registerMissionObject( "NotesObject",       "Note" );
       
    %this.endGroup();