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

📄 terraineditor.cc

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

#include "editor/terrainEditor.h"
#include "game/collisionTest.h"
#include "terrain/terrData.h"
#include "gui/core/guiCanvas.h"
#include "console/consoleTypes.h"
#include "editor/terrainActions.h"
#include "interior/interiorInstance.h"
#include "interior/interior.h"
#include "game/gameConnection.h"
#include "sim/netObject.h"
#include "core/frameAllocator.h"

IMPLEMENT_CONOBJECT(TerrainEditor);

Selection::Selection() :
   Vector<GridInfo>(__FILE__, __LINE__),
   mName(0),
   mUndoFlags(0),
   mHashListSize(1024)
{
   VECTOR_SET_ASSOCIATION(mHashLists);

   // clear the hash list
   mHashLists.setSize(mHashListSize);
   reset();
}

Selection::~Selection()
{
}

void Selection::reset()
{
   for(U32 i = 0; i < mHashListSize; i++)
      mHashLists[i] = -1;
   clear();
}

U32 Selection::getHashIndex(const Point2I & pos)
{
   Point2F pnt = Point2F(pos.x, pos.y) + Point2F(1.3f,3.5f);
   return( (U32)(mFloor(mHashLists.size() * mFmod(pnt.len() * 0.618f, 1))) );
}

S32 Selection::lookup(const Point2I & pos)
{
   U32 index = getHashIndex(pos);

   S32 entry = mHashLists[index];

   while(entry != -1)
   {
      if((*this)[entry].mGridPos == pos)
         return(entry);

      entry = (*this)[entry].mNext;
   }

   return(-1);
}

void Selection::insert(GridInfo & info)
{
   U32 index = getHashIndex(info.mGridPos);

   info.mNext = mHashLists[index];
   info.mPrev = -1;

   if(info.mNext != -1)
      (*this)[info.mNext].mPrev = size();

   mHashLists[index] = size();

   push_back(info);
}

bool Selection::remove(const GridInfo & info)
{
   U32 index = getHashIndex(info.mGridPos);

   S32 entry = mHashLists[index];

   if(entry == -1)
      return(false);

   // front?
   if((*this)[entry].mGridPos == info.mGridPos)
      mHashLists[index] = (*this)[entry].mNext;

   while(entry != -1)
   {
      if((*this)[entry].mGridPos == info.mGridPos)
      {
         if((*this)[entry].mPrev != -1)
            (*this)[(*this)[entry].mPrev].mNext = (*this)[entry].mNext;
         if((*this)[entry].mNext != -1)
            (*this)[(*this)[entry].mNext].mPrev = (*this)[entry].mPrev;

         // swap?
         if(entry != (size() - 1))
         {
            U32 last = size() - 1;

            (*this)[entry] = (*this)[size()-1];

            if((*this)[entry].mPrev != -1)
               (*this)[(*this)[entry].mPrev].mNext = entry;
            else
            {
               U32 idx = getHashIndex((*this)[entry].mGridPos);
               AssertFatal(mHashLists[idx] == ((*this).size() - 1), "doh");
               mHashLists[idx] = entry;
            }
            if((*this)[entry].mNext != -1)
               (*this)[(*this)[entry].mNext].mPrev = entry;
         }

         pop_back();
         return(true);
      }

      entry = (*this)[entry].mNext;
   }
   return(false);
}

// add unique grid info into the selection - test uniqueness by grid position
bool Selection::add(GridInfo & info)
{
   S32 index = lookup(info.mGridPos);
   if(index != -1)
      return(false);

   insert(info);
   return(true);
}

bool Selection::getInfo(Point2I pos, GridInfo & info)
{
   S32 index = lookup(pos);
   if(index == -1)
      return(false);

   info = (*this)[index];
   return(true);
}

bool Selection::setInfo(GridInfo & info)
{
   S32 index = lookup(info.mGridPos);
   if(index == -1)
      return(false);

   S32 next = (*this)[index].mNext;
   S32 prev = (*this)[index].mPrev;

   (*this)[index] = info;
   (*this)[index].mNext = next;
   (*this)[index].mPrev = prev;

   return(true);
}

F32 Selection::getAvgHeight()
{
   if(!size())
      return(0);

   F32 avg = 0.f;
   for(U32 i = 0; i < size(); i++)
      avg += (*this)[i].mHeight;

   return(avg / size());
}

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

Brush::Brush(TerrainEditor * editor) :
   mTerrainEditor(editor)
{
   mSize = mTerrainEditor->getBrushSize();
}

const Point2I & Brush::getPosition()
{
   return(mGridPos);
}

void Brush::setPosition(const Point3F & pos)
{
   Point2I gPos;
   mTerrainEditor->worldToGrid(pos, gPos);
   setPosition(gPos);
}

void Brush::setPosition(const Point2I & pos)
{
   mGridPos = pos;
   update();
}

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

void Brush::update()
{
   rebuild();
   // soft selection?
//   if(mTerrainEditor->mEnableSoftBrushes)
//   {
//      Gui3DMouseEvent event;
//      TerrainAction * action = mTerrainEditor->lookupAction("softSelect");
//      AssertFatal(action, "Brush::update: no 'softSelect' action found!");

      //
//      mTerrainEditor->setCurrentSel(this);
//      action->process(this, event, true, TerrainAction::Process);
//      mTerrainEditor->resetCurrentSel();
//   }
}

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

#ifdef TGE_RPG /// TGE_TerrainScene
void HLineBrush::rebuild()
{
   reset();
   Filter filter;
   filter.set(1, &mTerrainEditor->mSoftSelectFilter);
   //
   // mSize should always be odd.

   S32 centerX = (mSize.x - 1) / 2;
   //S32 centerY = (mSize.y - 1) / 2;

   F32 xFactorScale = F32(centerX) / (F32(centerX) + 0.5);

   for(S32 x = 0; x < mSize.x; x++)
   {
      GridInfo info;
      mTerrainEditor->getGridInfo(Point2I(mGridPos.x + x - centerX, mGridPos.y), info);
      if(mTerrainEditor->mEnableSoftBrushes && centerX != 0)
      {
         F32 xFactor = (mFabs(centerX - x) / F32(centerX)) * xFactorScale;
         info.mWeight = filter.getValue(xFactor);
      }
      push_back(info);
   }
}

void VLineBrush::rebuild()
{
   reset();
   Filter filter;
   filter.set(1, &mTerrainEditor->mSoftSelectFilter);
   //
   // mSize should always be odd.

   //S32 centerX = (mSize.x - 1) / 2;
   S32 centerY = (mSize.y - 1) / 2;

   F32 yFactorScale = F32(centerY) / (F32(centerY) + 0.5);

   for(S32 y = 0; y < mSize.y; y++)
   {
      GridInfo info;
      mTerrainEditor->getGridInfo(Point2I(mGridPos.x, mGridPos.y + y - centerY), info);
      if(mTerrainEditor->mEnableSoftBrushes &&  centerY != 0)
      {
         F32 yFactor = (mFabs(centerY - y) / F32(centerY)) * yFactorScale;
         info.mWeight = filter.getValue( yFactor);
      }
      push_back(info);
   }
}

#endif//#ifdef TGE_RPG /// TGE_TerrainScene


void BoxBrush::rebuild()
{
   reset();
   Filter filter;
   filter.set(1, &mTerrainEditor->mSoftSelectFilter);
   //
   // mSize should always be odd.

   S32 centerX = (mSize.x - 1) / 2;
   S32 centerY = (mSize.y - 1) / 2;

   F32 xFactorScale = F32(centerX) / (F32(centerX) + 0.5);
   F32 yFactorScale = F32(centerY) / (F32(centerY) + 0.5);

   for(S32 x = 0; x < mSize.x; x++)
   {
      for(S32 y = 0; y < mSize.y; y++)
      {
         GridInfo info;
         mTerrainEditor->getGridInfo(Point2I(mGridPos.x + x - centerX, mGridPos.y + y - centerY), info);
         if(mTerrainEditor->mEnableSoftBrushes && centerX != 0 && centerY != 0)
         {

            F32 xFactor = (mFabs(centerX - x) / F32(centerX)) * xFactorScale;
            F32 yFactor = (mFabs(centerY - y) / F32(centerY)) * yFactorScale;

            info.mWeight = filter.getValue(xFactor > yFactor ? xFactor : yFactor);
         }
         push_back(info);
      }
   }
}
//------------------------------------------------------------------------------

void EllipseBrush::rebuild()
{
   reset();
   Point3F center(F32(mSize.x - 1) / 2, F32(mSize.y - 1) / 2, 0);
   Filter filter;
   filter.set(1, &mTerrainEditor->mSoftSelectFilter);

   // a point is in a circle if:
   // x^2 + y^2 <= r^2
   // a point is in an ellipse if:
   // (ax)^2 + (by)^2 <= 1
   // where a = 1/halfEllipseWidth and b = 1/halfEllipseHeight

   // for a soft-selected ellipse,
   // the factor is simply the filtered: ((ax)^2 + (by)^2)

   F32 a = 1 / (F32(mSize.x) * 0.5);
   F32 b = 1 / (F32(mSize.y) * 0.5);

   for(U32 x = 0; x < mSize.x; x++)
   {
      for(U32 y = 0; y < mSize.y; y++)
      {
         F32 xp = center.x - x;
         F32 yp = center.y - y;

         F32 factor = (a * a * xp * xp) + (b * b * yp * yp);
         if(factor > 1)
            continue;

         GridInfo info;
         mTerrainEditor->getGridInfo(Point2I((S32)(mGridPos.x + x - center.x), (S32)(mGridPos.y + y - center.y)), info);
         if(mTerrainEditor->mEnableSoftBrushes)
            info.mWeight = filter.getValue(factor);

         push_back(info);
      }
   }
}

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

SelectionBrush::SelectionBrush(TerrainEditor * editor) :
   Brush(editor)
{
   //... grab the current selection
}

void SelectionBrush::rebuild()
{
   reset();
   //... move the selection
}

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

TerrainEditor::TerrainEditor() :
   mTerrainBlock(0),
   mMousePos(0,0,0),
   mMouseBrush(0),
   mInAction(false),
   mUndoLimit(20),
   mUndoSel(0),
   mRebuildEmpty(false),
   mRebuildTextures(false),
   mGridUpdateMin(255, 255),
   mGridUpdateMax(0, 0)
{
   VECTOR_SET_ASSOCIATION(mActions);
   VECTOR_SET_ASSOCIATION(mUndoList);
   VECTOR_SET_ASSOCIATION(mRedoList);
   VECTOR_SET_ASSOCIATION(mBaseMaterialInfos);

   //
   resetCurrentSel();

   //
   mBrushSize.set(1,1);
   mMouseBrush = new BoxBrush(this);
   mMouseDownSeq = 0;
   mIsDirty = false;
   mIsMissionDirty = false;
   mPaintMaterial = NULL;

   // add in all the actions here..
   mActions.push_back(new SelectAction(this));
   mActions.push_back(new SoftSelectAction(this));
   mActions.push_back(new OutlineSelectAction(this));
   mActions.push_back(new PaintMaterialAction(this));
   mActions.push_back(new RaiseHeightAction(this));
   mActions.push_back(new LowerHeightAction(this));
   mActions.push_back(new SetHeightAction(this));
   mActions.push_back(new SetEmptyAction(this));
   mActions.push_back(new ClearEmptyAction(this));
   mActions.push_back(new ScaleHeightAction(this));
   mActions.push_back(new BrushAdjustHeightAction(this));
   mActions.push_back(new AdjustHeightAction(this));
   mActions.push_back(new FlattenHeightAction(this));
   mActions.push_back(new SmoothHeightAction(this));
   mActions.push_back(new SetMaterialGroupAction(this));
   mActions.push_back(new SetModifiedAction(this));
   mActions.push_back(new ClearModifiedAction(this));
#ifdef TGE_RPG /// TGE_TerrainScene
   mActions.push_back(new SetBlockAction(this));
#endif

   // set the default action
   mCurrentAction = mActions[0];
   mRenderBrush = mCurrentAction->useMouseBrush();

   // persist data defaults
   mRenderBorder = true;
   mBorderHeight = 10;
   mBorderFillColor.set(0,255,0,20);
   mBorderFrameColor.set(0,255,0,128);
   mBorderLineMode = false;
   mSelectionHidden = false;
   mEnableSoftBrushes = false;
   mRenderVertexSelection = false;
   mProcessUsesBrush = false;
   mCurrentCursor = NULL;
   mCursorVisible = true;

   //
   mAdjustHeightVal = 10;
   mSetHeightVal = 100;
   mScaleVal = 1;
   mSmoothFactor = 0.1f;
   mMaterialGroup = 0;
   mSoftSelectRadius = 50.f;
   mAdjustHeightMouseScale = 0.1f;

   mSoftSelectDefaultFilter = StringTable->insert("1.000000 0.833333 0.666667 0.500000 0.333333 0.166667 0.000000");
   mSoftSelectFilter = mSoftSelectDefaultFilter;

#ifdef TGE_RPG /// TGE_TerrainScene
	m_uSceneFlag	= TerrainScene::BALK_WALK;
#endif
}

TerrainEditor::~TerrainEditor()
{
   // mouse
   delete mMouseBrush;

   // terrain actions
   U32 i;
   for(i = 0; i < mActions.size(); i++)
      delete mActions[i];

   // undo stuff
   clearUndo(mUndoList);
   clearUndo(mRedoList);
   delete mUndoSel;

   // base material infos
   for(i = 0; i < mBaseMaterialInfos.size(); i++)
      delete mBaseMaterialInfos[i];
}

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

TerrainAction * TerrainEditor::lookupAction(const char * name)
{
   for(U32 i = 0; i < mActions.size(); i++)
      if(!dStricmp(mActions[i]->getName(), name))
         return(mActions[i]);
   return(0);
}

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

bool TerrainEditor::onAdd()
{
   if(!Parent::onAdd())
      return(false);

   SimObject * obj = Sim::findObject("EditorArrowCursor");
   if(!obj)
   {
      Con::errorf(ConsoleLogEntry::General, "TerrainEditor::onAdd: failed to load cursor");
      return(false);
   }

   mDefaultCursor = dynamic_cast<GuiCursor*>(obj);

   return(true);
}

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

void TerrainEditor::onDeleteNotify(SimObject * object)
{
   Parent::onDeleteNotify(object);

   if(mTerrainBlock != dynamic_cast<TerrainBlock*>(object))
      return;

   mTerrainBlock = 0;

⌨️ 快捷键说明

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