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

📄 terraineditor.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 4 页
字号:
}

void TerrainEditor::setCursor(GuiCursor * cursor)
{
   mCurrentCursor = cursor ? cursor : mDefaultCursor;
}


S32 TerrainEditor::getPaintMaterial()
{
   if(!mPaintMaterial)
      return -1;

   return getClientTerrain()->getMaterialAlphaIndex(mPaintMaterial);
}

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

TerrainBlock * TerrainEditor::getClientTerrain()
{
#ifdef TGE_RPGCLIENT2 /// TGE_RPGGhost
	return mTerrainBlock;
#else

   // do the client..
   NetConnection * toServer = NetConnection::getConnectionToServer();
   NetConnection * toClient = NetConnection::getLocalClientConnection();

   S32 index = toClient->getGhostIndex(mTerrainBlock);

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

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

bool TerrainEditor::gridToWorld(const Point2I & gPos, Point3F & wPos)
{
   const MatrixF & mat = mTerrainBlock->getTransform();
   Point3F origin;
   mat.getColumn(3, &origin);

#ifdef TGE_RPG /// TGE_TerrainScene
	if(mCurrentAction->isGridByBlock())
	{
		wPos.x = gPos.x * (float)mTerrainBlock->getSquareSize() + origin.x;
		wPos.y = gPos.y * (float)mTerrainBlock->getSquareSize() + origin.y;
	}
	else
	{
		wPos.x = mFloor(gPos.x) + origin.x;
		wPos.y = mFloor(gPos.y) + origin.y;
	}
#else
   wPos.x = gPos.x * (float)mTerrainBlock->getSquareSize() + origin.x;
   wPos.y = gPos.y * (float)mTerrainBlock->getSquareSize() + origin.y;
#endif
   wPos.z = getGridHeight(gPos);

   return(!(gPos.x >> TerrainBlock::BlockShift || gPos.y >> TerrainBlock::BlockShift));
}

bool TerrainEditor::worldToGrid(const Point3F & wPos, Point2I & gPos)
{
   const MatrixF & mat = mTerrainBlock->getTransform();
   Point3F origin;
   mat.getColumn(3, &origin);

#ifdef TGE_RPG /// TGE_TerrainScene

	if(mCurrentAction->isGridByBlock())
	{
		F32 squareSize = (F32) mTerrainBlock->getSquareSize();
		F32 halfSquareSize = squareSize / 2;
		gPos.x = (S32)mFloor((wPos.x - origin.x + halfSquareSize) / squareSize);
		gPos.y = (S32)mFloor((wPos.y - origin.y + halfSquareSize) / squareSize);
	}
	else
	{
		gPos.x = (S32)mFloor(wPos.x - origin.x);
		gPos.y = (S32)mFloor(wPos.y - origin.y);
	}
#else
	F32 squareSize = (F32) mTerrainBlock->getSquareSize();
	F32 halfSquareSize = squareSize / 2;
   float x = (wPos.x - origin.x + halfSquareSize) / squareSize;
   float y = (wPos.y - origin.y + halfSquareSize) / squareSize;
   gPos.x = (S32)mFloor(x);
   gPos.y = (S32)mFloor(y);
#endif


   return(!(gPos.x >> TerrainBlock::BlockShift || gPos.y >> TerrainBlock::BlockShift));
}

bool TerrainEditor::gridToCenter(const Point2I & gPos, Point2I & cPos)
{
#ifdef TGE_RPG /// TGE_TerrainScene
	if(mCurrentAction->isGridByBlock())
	{
		cPos.x = gPos.x & TerrainBlock::BlockMask;
		cPos.y = gPos.y & TerrainBlock::BlockMask;
	}
	else
	{
		F32 fMod = (F32) mTerrainBlock->getSquareSize() * TerrainBlock::BlockSize;
		cPos.x = mFmod(gPos.x,fMod);
		cPos.y = mFmod(gPos.y,fMod);
	}
#else
   cPos.x = gPos.x & TerrainBlock::BlockMask;
   cPos.y = gPos.y & TerrainBlock::BlockMask;
#endif

   return(!(gPos.x >> TerrainBlock::BlockShift || gPos.y >> TerrainBlock::BlockShift));
}

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

bool TerrainEditor::getGridInfo(const Point3F & wPos, GridInfo & info)
{
   Point2I gPos;
   worldToGrid(wPos, gPos);
   return getGridInfo(gPos, info);
}

bool TerrainEditor::getGridInfo(const Point2I & gPos, GridInfo & info)
{
   //
   info.mGridPos = gPos;
   info.mMaterial = getGridMaterial(gPos);
   info.mHeight = getGridHeight(gPos);
   info.mWeight = 1.f;
   info.mPrimarySelect = true;
   info.mMaterialChanged = false;

   Point2I cPos;
   gridToCenter(gPos, cPos);

   info.mMaterialGroup = mTerrainBlock->getBaseMaterial(cPos.x, cPos.y);
   mTerrainBlock->getMaterialAlpha(gPos, info.mMaterialAlpha);

   return(!(gPos.x >> TerrainBlock::BlockShift || gPos.y >> TerrainBlock::BlockShift));
}

void TerrainEditor::setGridInfo(const GridInfo & info)
{
#ifdef TGE_RPG /// TGE_TerrainScene
	setGridBlock(info.mGridPos, info.m_uSceneFlags);
#endif
	setGridHeight(info.mGridPos, info.mHeight);
   setGridMaterial(info.mGridPos, info.mMaterial);
   setGridMaterialGroup(info.mGridPos, info.mMaterialGroup);
   if(info.mMaterialChanged)
      mTerrainBlock->setMaterialAlpha(info.mGridPos, info.mMaterialAlpha);
}

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


void TerrainEditor::gridUpdateComplete()
{
   if(mGridUpdateMin.x <= mGridUpdateMax.x)
      mTerrainBlock->updateGrid(mGridUpdateMin, mGridUpdateMax);
   mGridUpdateMin.set(256,256);
   mGridUpdateMax.set(0,0);
}

void TerrainEditor::materialUpdateComplete()
{
   if(mGridUpdateMin.x <= mGridUpdateMax.x)
   {
      TerrainBlock * clientTerrain = getClientTerrain();
      clientTerrain->updateGridMaterials(mGridUpdateMin, mGridUpdateMax);
      mTerrainBlock->updateGrid(mGridUpdateMin, mGridUpdateMax);
   }
   mGridUpdateMin.set(256,256);
   mGridUpdateMax.set(0,0);
}

void TerrainEditor::setGridHeight(const Point2I & gPos, const F32 height)
{
   Point2I cPos;
   gridToCenter(gPos, cPos);
   if(cPos.x < mGridUpdateMin.x)
      mGridUpdateMin.x = cPos.x;
   if(cPos.y < mGridUpdateMin.y)
      mGridUpdateMin.y = cPos.y;
   if(cPos.x > mGridUpdateMax.x)
      mGridUpdateMax.x = cPos.x;
   if(cPos.y > mGridUpdateMax.y)
      mGridUpdateMax.y = cPos.y;

   mTerrainBlock->setHeight(cPos, height);
}

F32 TerrainEditor::getGridHeight(const Point2I & gPos)
{
   Point2I cPos;
   gridToCenter(gPos, cPos);
   return(fixedToFloat(mTerrainBlock->getHeight(cPos.x, cPos.y)));
}


#ifdef TGE_RPG /// TGE_TerrainScene
U32 TerrainEditor::getGridBlock(const Point2I & gPos)
{
   Point2I cPos;
   gridToCenter(gPos, cPos);
   return mTerrainBlock->getBlockAt(cPos.x, cPos.y);
}

void TerrainEditor::setGridBlock(const Point2I & gPos, const U32 uFlags)
{
   Point2I cPos;
   gridToCenter(gPos, cPos);
   if(cPos.x < mGridUpdateMin.x)
      mGridUpdateMin.x = cPos.x;
   if(cPos.y < mGridUpdateMin.y)
      mGridUpdateMin.y = cPos.y;
   if(cPos.x > mGridUpdateMax.x)
      mGridUpdateMax.x = cPos.x;
   if(cPos.y > mGridUpdateMax.y)
      mGridUpdateMax.y = cPos.y;

   Point3F ptPos;
	gridToWorld(cPos,ptPos);

   mTerrainBlock->setBlockAt(ptPos.x,ptPos.y,uFlags);
   //mTerrainBlock->setBlockAt(cPos.x,cPos.y,uFlags);
}
#endif


TerrainBlock::Material TerrainEditor::getGridMaterial(const Point2I & gPos)
{
   Point2I cPos;
   gridToCenter(gPos, cPos);
   return(*mTerrainBlock->getMaterial(cPos.x, cPos.y));
}

void TerrainEditor::setGridMaterial(const Point2I & gPos, const TerrainBlock::Material & material)
{
   Point2I cPos;
   gridToCenter(gPos, cPos);

   // check if empty has been altered...
   TerrainBlock::Material * mat = mTerrainBlock->getMaterial(cPos.x, cPos.y);

   if((mat->flags & TerrainBlock::Material::Empty) ^ (material.flags & TerrainBlock::Material::Empty))
      mRebuildEmpty = true;

   *mat = material;
}

U8 TerrainEditor::getGridMaterialGroup(const Point2I & gPos)
{
   Point2I cPos;
   gridToCenter(gPos, cPos);

   return(mTerrainBlock->getBaseMaterial(cPos.x, cPos.y));
}

// basematerials are shared through a resource... so work on client object
// so wont need to load textures....

void TerrainEditor::setGridMaterialGroup(const Point2I & gPos, const U8 group)
{
   Point2I cPos;
   gridToCenter(gPos, cPos);

   TerrainBlock * clientTerrain = getClientTerrain();

   clientTerrain->setBaseMaterial(cPos.x, cPos.y, group);
}

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

bool TerrainEditor::collide(const Gui3DMouseEvent & event, Point3F & pos)
{
   if(!mTerrainBlock)
      return(false);

   // call the terrain block's ray collision routine directly
   Point3F startPnt = event.pos;
   Point3F endPnt = event.pos + event.vec * 1000;
   Point3F tStartPnt, tEndPnt;

   mTerrainBlock->getTransform().mulP(startPnt, &tStartPnt);
   mTerrainBlock->getTransform().mulP(endPnt, &tEndPnt);

   RayInfo ri;
   if(mTerrainBlock->castRayI(tStartPnt, tEndPnt, &ri, true))
   {
      ri.point.interpolate(startPnt, endPnt, ri.t);
      pos = ri.point;
      return(true);
   }
   return(false);
}

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

void TerrainEditor::updateGuiInfo()
{
   char buf[128];

   // mouse num grids
   // mouse avg height
   // selection num grids
   // selection avg height
   dSprintf(buf, sizeof(buf), "%d %g %d %g",
      mMouseBrush->size(), mMouseBrush->getAvgHeight(),
      mDefaultSel.size(), mDefaultSel.getAvgHeight());
   Con::executef(this, 2, "onGuiUpdate", buf);
}

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

void TerrainEditor::renderScene(const RectI &)
{
   if(!mTerrainBlock)
      return;

   if(!mSelectionHidden)
      renderSelection(mDefaultSel, ColorF(1,0,0), ColorF(0,1,0), ColorF(0,0,1), ColorF(0,0,1), true, false);

   if(mRenderBrush && mMouseBrush->size())
      renderSelection(*mMouseBrush, ColorF(1,0,0), ColorF(0,1,0), ColorF(0,0,1), ColorF(0,0,1), false, true);

   if(mRenderBorder)
      renderBorder();
}

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

struct TerrVertex
{
   Point3F point;
   ColorI color;
};

void TerrainEditor::renderSelection( const Selection & sel, const ColorF & inColorFull, const ColorF & inColorNone, const ColorF & outColorFull, const ColorF & outColorNone, bool renderFill, bool renderFrame )
{
   Vector<TerrVertex> vertexBuffer;
   ColorF color;
   ColorI iColor;

   vertexBuffer.setSize(sel.size() * 4);

   if(mRenderVertexSelection)
   {
      for(U32 i = 0; i < sel.size(); i++)
      {
         Point3F wPos;
         bool center = gridToWorld(sel[i].mGridPos, wPos);

         if(center)
         {
            if(sel[i].mWeight < 0.f || sel[i].mWeight > 1.f)
               color = inColorFull;
            else
               color.interpolate(inColorNone, inColorFull, sel[i].mWeight);
         }
         else
         {
            if(sel[i].mWeight < 0.f || sel[i].mWeight > 1.f)
               color = outColorFull;
            else
               color.interpolate(outColorFull, outColorNone, sel[i].mWeight);
         }
         //
         iColor = color;

         TerrVertex *verts = &(vertexBuffer[i * 4]);

#ifdef TGE_RPG /// TGE_TerrainScene
			if(mCurrentAction->isGridByBlock())
			{
				verts[0].point = wPos + Point3F(-1, -1, 0);
				verts[0].color = iColor;
				verts[1].point = wPos + Point3F( 1, -1, 0);
				verts[1].color = iColor;
				verts[2].point = wPos + Point3F( 1,  1, 0);
				verts[2].color = iColor;
				verts[3].point = wPos + Point3F(-1,  1, 0);
				verts[3].color = iColor;
			}
			else
			{
				verts[0].point = wPos;
				verts[0].color = iColor;
				verts[1].point = wPos + Point3F(1, 0, 0);
				verts[1].color = iColor;
				verts[2].point = wPos + Point3F(1,  1, 0);
				verts[2].color = iColor;
				verts[3].point = wPos + Point3F(0,  1, 0);
				verts[3].color = iColor;
			}
#else
         verts[0].point = wPos + Point3F(-1, -1, 0);
         verts[0].color = iColor;
         verts[1].point = wPos + Point3F( 1, -1, 0);
         verts[1].color = iColor;
         verts[2].point = wPos + Point3F( 1,  1, 0);
         verts[2].color = iColor;
         verts[3].point = wPos + Point3F(-1,  1, 0);
         verts[3].color = iColor;
#endif
      }
   }
   else
   {
      // walk the points in the selection
      for(U32 i = 0; i < sel.size(); i++)
      {
         Point2I gPos = sel[i].mGridPos;

         TerrVertex *verts = &(vertexBuffer[i * 4]);

         bool center = gridToWorld(gPos,              verts[0].point);
         gridToWorld(Point2I(gPos.x + 1, gPos.y),     verts[1].point);
         gridToWorld(Point2I(gPos.x + 1, gPos.y + 1), verts[2].point);
         gridToWorld(Point2I(gPos.x, gPos.y + 1),     verts[3].point);

         if(center)
         {
            if(sel[i].mWeight < 0.f || sel[i].mWeight > 1.f)
               color = inColorFull;
            else
               color.interpolate(inColorNone, inColorFull, sel[i].mWeight);
         }
         else
         {
            if(sel[i].mWeight < 0.f || sel[i].mWeight > 1.f)
               color = outColorFull;
            else
               color.interpolate(outColorFull, outColorNone, sel[i].mWeight);
         }

         iColor = color;

         verts[0].color = iColor;
         verts[1].color = iColor;
         verts[2].color = iColor;
         verts[3].color = iColor;
      }
   }

   //
   glEnableClientState(GL_VERTEX_ARRAY);
   glVertexPointer(3, GL_FLOAT, sizeof(TerrVertex), &(vertexBuffer[0]));
   glEnableClientState(GL_COLOR_ARRAY);
   glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(TerrVertex), &(vertexBuffer[0].color));

#ifndef TORQUE_OS_MAC // line drawing crashes on mac under CVAs... !!!!TBD
   if (dglDoesSupportCompiledVertexArray())
        glLockArraysEXT(0, vertexBuffer.size());
#endif

   glDisable(GL_CULL_FACE);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);

   if(renderFill)
      glDrawArrays(GL_QUADS, 0, vertexBuffer.size());

   glDisable(GL_BLEND);

   if(renderFrame)
      for(U32 i = 0; i < sel.size(); i++)
         glDrawArrays(GL_LINE_LOOP, i * 4, 4);

#ifndef TORQUE_OS_MAC // line drawing crashes on mac under CVAs...
   if (dglDoesSupportCompiledVertexArray())
      glUnlockArraysEXT();
#endif
   glDisableClientState(GL_VERTEX_ARRAY);
   glDisableClientState(GL_COLOR_ARRAY);
}

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

void TerrainEditor::renderBorder()
{
   glDisable(GL_CULL_FACE);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   Point2I pos(0,0);
   Point2I dir[4] = {
      Point2I(1,0),
      Point2I(0,1),
      Point2I(-1,0),
      Point2I(0,-1)
   };

   //
   if(mBorderLineMode)
   {
      glColor4ub(mBorderFrameColor.red, mBorderFrameColor.green, mBorderFrameColor.blue, mBorderFrameColor.alpha);
      glBegin(GL_LINE_STRIP);
      for(U32 i = 0; i < 4; i++)
      {
         for(U32 j = 0; j < TerrainBlock::BlockSize; j++)
         {
            Point3F wPos;
            gridToWorld(pos, wPos);
            glVertex3f(wPos.x, wPos.y, wPos.z);
            pos += dir[i];
         }
      }

      Point3F wPos;
      gridToWorld(Point2I(0,0),  wPos);
      glVertex3f(wPos.x, wPos.y, wPos.z);
      glEnd();

⌨️ 快捷键说明

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