⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 worldeditor.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "editor/worldEditor.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneState.h"
#include "sim/sceneObject.h"
#include "platform/event.h"
#include "gui/core/guiCanvas.h"
#include "game/gameConnection.h"
#include "core/memstream.h"
#include "collision/clippedPolyList.h"
#include "game/shapeBase.h"
#include "console/consoleInternal.h"
#include "game/sphere.h"
#include "sim/simPath.h"
#include "game/cameraSpline.h"
#include "interior/interiorInstance.h"
//#include "terrain/terrdata.h" /// TGE_Map

IMPLEMENT_CONOBJECT(WorldEditor);

// unnamed namespace for static data
namespace {

   static Point3F BoxPnts[] = {
      Point3F(0,0,0),
      Point3F(0,0,1),
      Point3F(0,1,0),
      Point3F(0,1,1),
      Point3F(1,0,0),
      Point3F(1,0,1),
      Point3F(1,1,0),
      Point3F(1,1,1)
   };

   static U32 BoxVerts[][4] = {
      {0,2,3,1},     // -x
      {7,6,4,5},     // +x
      {0,1,5,4},     // -y
      {3,2,6,7},     // +y
      {0,4,6,2},     // -z
      {3,7,5,1}      // +z
   };

   static Point3F BoxNormals[] = {
      Point3F(-1, 0, 0),
      Point3F( 1, 0, 0),
      Point3F( 0,-1, 0),
      Point3F( 0, 1, 0),
      Point3F( 0, 0,-1),
      Point3F( 0, 0, 1)
   };

   //
   U32 getBoxNormalIndex(const VectorF & normal)
   {
      const F32 * pNormal = ((const F32 *)normal);

      F32 max = 0;
      S32 index = -1;

      for(U32 i = 0; i < 3; i++)
         if(mFabs(pNormal[i]) >= mFabs(max))
         {
            max = pNormal[i];
            index = i*2;
         }

      AssertFatal(index >= 0, "Failed to get best normal");
      if(max > 0.f)
         index++;

      return(index);
   }

   //
   Point3F getBoundingBoxCenter(SceneObject * obj)
   {
      Box3F box = obj->getObjBox();
      MatrixF mat = obj->getTransform();
      VectorF scale = obj->getScale();

      Point3F center(0,0,0);
      Point3F projPnts[8];

      for(U32 i = 0; i < 8; i++)
      {
         Point3F pnt;
         pnt.set(BoxPnts[i].x ? box.max.x : box.min.x,
                 BoxPnts[i].y ? box.max.y : box.min.y,
                 BoxPnts[i].z ? box.max.z : box.min.z);

         // scale it
         pnt.convolve(scale);
         mat.mulP(pnt, &projPnts[i]);
         center += projPnts[i];
      }

      center /= 8;
      return(center);
   }

   //
   const char * parseObjectFormat(SimObject * obj, const char * format)
   {
      static char buf[1024];

      U32 curPos = 0;
      U32 len = dStrlen(format);

      for(U32 i = 0; i < len; i++)
      {
         if(format[i] == '$')
         {
            U32 j;
            for(j = i+1; j < len; j++)
               if(format[j] == '$')
                  break;

            if(j == len)
               break;

            char token[80];

            AssertFatal((j - i) < (sizeof(token) - 1), "token too long");
            dStrncpy(token, &format[i+1], (j - i - 1));
            token[j-i-1] = 0;

            U32 remaining = sizeof(buf) - curPos - 1;

            // look at the token
            if(!dStricmp(token, "id"))
               curPos += dSprintf(buf + curPos, remaining, "%d", obj->getId());
            else if(!dStricmp(token, "name"))
               curPos += dSprintf(buf + curPos, remaining, "%s", obj->getName());
            else if(!dStricmp(token, "class"))
               curPos += dSprintf(buf + curPos, remaining, "%s", obj->getClassName());
            else if(!dStricmp(token, "namespace") && obj->getNamespace())
               curPos += dSprintf(buf + curPos, remaining, "%s", obj->getNamespace()->mName);

            //
            i = j;
         }
         else
            buf[curPos++] = format[i];
      }

      buf[curPos] = 0;
      return(buf);
   }

   //
   F32 snapFloat(F32 val, F32 snap)
   {
      if(snap == 0.f)
         return(val);

      F32 a = mFmod(val, snap);

      if(mFabs(a) > (snap / 2))
         val < 0.f ? val -= snap : val += snap;

      return(val - a);
   }

   //
   EulerF extractEuler(const MatrixF & matrix)
   {
      const F32 * mat = (const F32*)matrix;

      EulerF r;
      r.x = mAsin(mat[MatrixF::idx(2,1)]);

      if(mCos(r.x) != 0.f)
      {
         r.y = mAtan(-mat[MatrixF::idx(2,0)], mat[MatrixF::idx(2,2)]);
         r.z = mAtan(-mat[MatrixF::idx(0,1)], mat[MatrixF::idx(1,1)]);
      }
      else
      {
         r.y = 0.f;
         r.z = mAtan(mat[MatrixF::idx(1,0)], mat[MatrixF::idx(0,0)]);
      }

      return(r);
   }
}

//------------------------------------------------------------------------------
// Class WorldEditor::Selection
//------------------------------------------------------------------------------

WorldEditor::Selection::Selection() :
   mCentroidValid(false),
   mAutoSelect(false)
{
   registerObject();
}

WorldEditor::Selection::~Selection()
{
   unregisterObject();
}

bool WorldEditor::Selection::objInSet(SceneObject * obj)
{
   for(U32 i = 0; i < mObjectList.size(); i++)
      if(mObjectList[i] == (SimObject*)obj)
         return(true);
   return(false);
}

bool WorldEditor::Selection::addObject(SceneObject * obj)
{
   if(objInSet(obj))
      return(false);

   mCentroidValid = false;

   mObjectList.pushBack(obj);
   deleteNotify(obj);

   if(mAutoSelect)
   {
      obj->setSelected(true);
      SceneObject * clientObj = WorldEditor::getClientObj(obj);
      if(clientObj)
         clientObj->setSelected(true);
   }

   return(true);
}

bool WorldEditor::Selection::removeObject(SceneObject * obj)
{
   if(!objInSet(obj))
      return(false);

   mCentroidValid = false;

   mObjectList.remove(obj);
   clearNotify(obj);

   if(mAutoSelect)
   {
      obj->setSelected(false);

      SceneObject * clientObj = WorldEditor::getClientObj(obj);
      if(clientObj)
         clientObj->setSelected(false);
   }

   return(true);
}

void WorldEditor::Selection::clear()
{
   while(mObjectList.size())
      removeObject((SceneObject*)mObjectList[0]);
}

void WorldEditor::Selection::onDeleteNotify(SimObject * obj)
{
   removeObject((SceneObject*)obj);
}

void WorldEditor::Selection::updateCentroid()
{
   if(mCentroidValid)
      return;

   mCentroidValid = true;

   //
   mCentroid.set(0,0,0);
   mBoxCentroid = mCentroid;

   if(!mObjectList.size())
      return;

   //
   for(U32 i = 0; i < mObjectList.size(); i++)
   {
      const MatrixF & mat = ((SceneObject*)mObjectList[i])->getTransform();
      Point3F wPos;
      mat.getColumn(3, &wPos);

      //
      mBoxCentroid += getBoundingBoxCenter((SceneObject*)mObjectList[i]);
      mCentroid += wPos;
   }

   mCentroid /= mObjectList.size();
   mBoxCentroid /= mObjectList.size();
}

const Point3F & WorldEditor::Selection::getCentroid()
{
   updateCentroid();
   return(mCentroid);
}

const Point3F & WorldEditor::Selection::getBoxCentroid()
{
   updateCentroid();
   return(mBoxCentroid);
}

void WorldEditor::Selection::enableCollision()
{
   for(U32 i = 0; i < mObjectList.size(); i++)
      ((SceneObject*)mObjectList[i])->enableCollision();
}

void WorldEditor::Selection::disableCollision()
{
   for(U32 i = 0; i < mObjectList.size(); i++)
      ((SceneObject*)mObjectList[i])->disableCollision();
}

//------------------------------------------------------------------------------

void WorldEditor::Selection::offset(const Point3F & offset)
{
   for(U32 i = 0; i < mObjectList.size(); i++)
   {
      MatrixF mat = ((SceneObject*)mObjectList[i])->getTransform();
      Point3F wPos;
      mat.getColumn(3, &wPos);

      // adjust
      wPos += offset;
      mat.setColumn(3, wPos);
      ((SceneObject*)mObjectList[i])->setTransform(mat);
   }

   mCentroidValid = false;
}

void WorldEditor::Selection::orient(const MatrixF & rot, const Point3F & center)
{
   // Orient all the selected objects to the given rotation
   for(U32 i = 0; i < size(); i++) 
   {
      MatrixF mat = rot;
      mat.setPosition(((SceneObject*)mObjectList[i])->getPosition());
      ((SceneObject*)mObjectList[i])->setTransform(mat);
   }

   mCentroidValid = false;
}

void WorldEditor::Selection::rotate(const EulerF & rot, const Point3F & center)
{
   // single selections will rotate around own axis, multiple about world
   if(mObjectList.size() == 1)
   {
      MatrixF mat = ((SceneObject*)mObjectList[0])->getTransform();

      Point3F pos;
      mat.getColumn(3, &pos);

      // get offset in obj space
      Point3F offset = pos - center;
      MatrixF wMat = ((SceneObject*)mObjectList[0])->getWorldTransform();
      wMat.mulV(offset);

      //
      MatrixF transform(EulerF(0,0,0), -offset);
      transform.mul(MatrixF(rot));
      transform.mul(MatrixF(EulerF(0,0,0), offset));
      mat.mul(transform);

      ((SceneObject*)mObjectList[0])->setTransform(mat);
   }
   else
   {
      for(U32 i = 0; i < size(); i++)
      {
         MatrixF mat = ((SceneObject*)mObjectList[i])->getTransform();

         Point3F pos;
         mat.getColumn(3, &pos);

         // get offset in obj space
         Point3F offset = pos - center;

         MatrixF transform(rot);
         Point3F wOffset;
         transform.mulV(offset, &wOffset);

         MatrixF wMat = ((SceneObject*)mObjectList[i])->getWorldTransform();
         wMat.mulV(offset);

         //
         transform.set(EulerF(0,0,0), -offset);

         mat.setColumn(3, Point3F(0,0,0));
         wMat.setColumn(3, Point3F(0,0,0));

         transform.mul(wMat);
         transform.mul(MatrixF(rot));
         transform.mul(mat);
         mat.mul(transform);

         mat.normalize();
         mat.setColumn(3, wOffset + center);

         ((SceneObject*)mObjectList[i])->setTransform(mat);
      }
   }

   mCentroidValid = false;
}

void WorldEditor::Selection::scale(const VectorF & scale)
{
   for(U32 i = 0; i < mObjectList.size(); i++)
   {
      VectorF current = ((SceneObject*)mObjectList[i])->getScale();
      current.convolve(scale);
      ((SceneObject*)mObjectList[i])->setScale(current);
   }

   mCentroidValid = false;
}

//------------------------------------------------------------------------------

SceneObject * WorldEditor::getClientObj(SceneObject * obj)
{
#ifdef TGE_RPGCLIENT2 /// TGE_RPGGhost
	return obj;
#else
   AssertFatal(obj->isServerObject(), "WorldEditor::getClientObj: not a server object!");

   NetConnection * toServer = NetConnection::getConnectionToServer();
   NetConnection * toClient = NetConnection::getLocalClientConnection();

   S32 index = toClient->getGhostIndex(obj);
   if(index == -1)
      return(0);

   return(dynamic_cast<SceneObject*>(toServer->resolveGhost(index)));
#endif
}

void WorldEditor::setClientObjInfo(SceneObject * obj, const MatrixF & mat, const VectorF & scale)
{
   SceneObject * clientObj = getClientObj(obj);
   if(!clientObj)
      return;

   clientObj->setTransform(mat);
   clientObj->setScale(scale);
}

void WorldEditor::updateClientTransforms(Selection & sel)
{
   for(U32 i = 0; i < sel.size(); i++)
   {
      SceneObject * clientObj = getClientObj(sel[i]);
      if(!clientObj)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -