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

📄 worldeditor.cc

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

      // If it's an interior we're going to need to relight the scene
      // since we've moved it, so notify script of this. Don't bother
      // ourselves with dynamic lit interiors, of course.
      InteriorInstance  *ii = dynamic_cast<InteriorInstance*>(clientObj);
      if(ii != NULL && ii->mUseGLLighting == false)
      {
         // Set it to be dynamically lit as well.
         ii->mDoSimpleDynamicRender = true;
         Con::executef( 1, "onNeedRelight" );
      }

      clientObj->setTransform(sel[i]->getTransform());
      clientObj->setScale(sel[i]->getScale());
   }
}

//------------------------------------------------------------------------------
// simple undo mechanism: bascially maintains stacks of state information
// from the selections (transform info only)
WorldEditor::SelectionState * WorldEditor::createUndo(Selection & sel)
{
   SelectionState * sState = new SelectionState;
   for(U32 i = 0; i < sel.size(); i++)
   {
      SelectionState::Entry entry;

      entry.mMatrix = sel[i]->getTransform();
      entry.mScale = sel[i]->getScale();
      entry.mObjId = sel[i]->getId();
      sState->mEntries.push_back(entry);
   }
   return(sState);
}

void WorldEditor::addUndo(Vector<SelectionState *> & list, SelectionState * sel)
{
   AssertFatal(sel, "WorldEditor::addUndo - invalid selection");
   list.push_front(sel);
   if(list.size() == mUndoLimit)
   {
      SelectionState * ss = list[list.size()-1];
      delete ss;
      list.pop_back();
   }
   setDirty();
}

bool WorldEditor::processUndo(Vector<SelectionState*> & src, Vector<SelectionState*> & dest)
{
   if(!src.size())
      return(false);

   SelectionState * task = src.front();
   src.pop_front();

   for(U32 i = 0; i < task->mEntries.size(); i++)
   {
      SceneObject * obj = static_cast<SceneObject*>(Sim::findObject(task->mEntries[i].mObjId));
      if(obj)
      {
         setClientObjInfo(obj, task->mEntries[i].mMatrix, task->mEntries[i].mScale);
         obj->setTransform(task->mEntries[i].mMatrix);
         obj->setScale(task->mEntries[i].mScale);
      }
   }

   addUndo(dest, task);
   mSelected.invalidateCentroid();

   return(true);
}

void WorldEditor::clearUndo(Vector<SelectionState *> & list)
{
   for(U32 i = 0; i < list.size(); i++)
      delete list[i];
   list.clear();
}

//------------------------------------------------------------------------------
// edit stuff
bool WorldEditor::deleteSelection(Selection & sel)
{
   if(sel.size())
      setDirty();

   while(sel.size())
      sel[0]->deleteObject();
   return(true);
}

bool WorldEditor::copySelection(Selection & sel)
{
   mStreamBufs.clear();

   for(U32 i = 0; i < sel.size(); i++)
   {
      // um.. can we say lame?
      mStreamBufs.increment();
      MemStream stream(2048, mStreamBufs.last(), false, true);
      stream.write(7, (void*)"return ");
      sel[i]->write(stream, 0);

      if(stream.getStatus() != Stream::Ok)
      {
         mStreamBufs.clear();
         return(false);
      }
   }
   return(true);
}

bool WorldEditor::pasteSelection()
{
   if(!mSelectionLocked)
      mSelected.clear();
   for(U32 i = 0; i < mStreamBufs.size(); i++)
   {
      const char * eval = Con::evaluate((const char *)mStreamBufs[i]);
      SceneObject * obj = dynamic_cast<SceneObject*>(Sim::findObject(eval));
      if(obj && !mSelectionLocked)
         mSelected.addObject(obj);
   }

   // drop it ...
   dropSelection(mSelected);
   return(true);
}

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

void WorldEditor::hideSelection(bool hide)
{
   // set server/client objects hide field
   for(U32 i = 0; i < mSelected.size(); i++)
   {
      // client
      SceneObject * clientObj = getClientObj(mSelected[i]);
      if(!clientObj)
         continue;

      clientObj->setHidden(hide);

      // server
      mSelected[i]->setHidden(hide);
   }
}

void WorldEditor::lockSelection(bool lock)
{
   //
   for(U32 i = 0; i < mSelected.size(); i++)
      mSelected[i]->setLocked(lock);
}

//------------------------------------------------------------------------------
// the centroid get's moved to the drop point...
void WorldEditor::dropSelection(Selection & sel)
{
   if(!sel.size())
      return;

   setDirty();

   Point3F centroid = mObjectsUseBoxCenter ? sel.getBoxCentroid() : sel.getCentroid();

   switch(mDropType)
   {
      case DropAtCentroid:
         // already there
         break;

      case DropAtOrigin:
      {
         sel.offset(Point3F(-centroid));
         break;
      }

      case DropAtCameraWithRot:
      {
         sel.offset(Point3F(smCamPos - centroid));
         sel.orient(smCamMatrix, centroid);
         break;
      }

      case DropAtCamera:
      {
         sel.offset(Point3F(smCamPos - centroid));
         break;
      }

      case DropBelowCamera:
      {
         Point3F offset = smCamPos - centroid;
         offset.z -= 15.f;
         sel.offset(offset);
         break;
      }

      case DropAtScreenCenter:
      {
         Gui3DMouseEvent event;
         event.pos = smCamPos;

         Point2I offset = localToGlobalCoord(Point2I(0,0));

         Point3F sp(offset.x + (getExtent().x / 2), offset.y + (getExtent().y / 2), 1);

         Point3F wp;
         unproject(sp, &wp);
         event.vec = wp - smCamPos;
         event.vec.normalizeSafe();

         // if fails to hit screen, then place at camera
         CollisionInfo info;
         if(collide(event, info))
            sel.offset(Point3F(info.pos - centroid));
         else
            sel.offset(Point3F(event.pos - centroid));

         break;
      }

      case DropToGround:
      {
         for(U32 i = 0; i < sel.size(); i++)
         {
            Point3F start;
            MatrixF mat = sel[i]->getTransform();
            mat.getColumn(3, &start);
            Point3F end = start;
            start.z = -2000.f;
            end.z = 2000.f;

            RayInfo ri;
            bool hit;
            if(mBoundingBoxCollision)
               hit = gServerContainer.collideBox(start, end, TerrainObjectType, &ri);
            else
               hit = gServerContainer.castRay(start, end, TerrainObjectType, &ri);

            if(hit)
            {
               mat.setColumn(3, ri.point);
               sel[i]->setTransform(mat);
            }
            else
               sel.offset(Point3F(smCamPos - centroid));
         }
         break;
      }
   }

   //
   updateClientTransforms(sel);
}

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

SceneObject * WorldEditor::getControlObject()
{
   GameConnection * connection = GameConnection::getLocalClientConnection();
   if(connection)
      return(dynamic_cast<SceneObject*>(connection->getControlObject()));
   return(0);
}

bool WorldEditor::collide(const Gui3DMouseEvent & event, CollisionInfo & info)
{
   // turn off the collsion with the control object
   SceneObject * controlObj = getControlObject();
   if(controlObj)
      controlObj->disableCollision();

   //
   Point3F startPnt = event.pos;
   Point3F endPnt = event.pos + event.vec * mProjectDistance;

   //
   RayInfo ri;
   bool hit;
   if(mBoundingBoxCollision)
      hit = gServerContainer.collideBox(startPnt, endPnt, 0xFFFFFFFF, &ri);
   else
      hit = gServerContainer.castRay(startPnt, endPnt, 0xFFFFFFFF, &ri);

   //
   if(hit)
   {
      info.pos = ri.point;
      info.obj = ri.object;
      info.normal = ri.normal;
      AssertFatal(info.obj, "WorldEditor::collide - client container returned non SceneObject");
   }

   if(controlObj)
      controlObj->enableCollision();
   return(hit);
}

//------------------------------------------------------------------------------
// main render functions

void WorldEditor::renderSelectionWorldBox(Selection & sel)
{
   if(!mRenderSelectionBox)
      return;

   //
   if(!sel.size())
      return;

   // build the world bounds
   Box3F selBox = sel[0]->getWorldBox();

   U32 i;
   for(i = 1; i < sel.size(); i++)
   {
      const Box3F & wBox = sel[i]->getWorldBox();
      selBox.min.setMin(wBox.min);
      selBox.max.setMax(wBox.max);
   }

   //
   glDisable(GL_CULL_FACE);
   glColor4ub(mSelectionBoxColor.red, mSelectionBoxColor.green,
      mSelectionBoxColor.blue, mSelectionBoxColor.alpha);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   // create the box points
   Point3F projPnts[8];
   for(i = 0; i < 8; i++)
   {
      Point3F pnt;
      pnt.set(BoxPnts[i].x ? selBox.max.x : selBox.min.x,
              BoxPnts[i].y ? selBox.max.y : selBox.min.y,
              BoxPnts[i].z ? selBox.max.z : selBox.min.z);
      projPnts[i] = pnt;
   }

   // do the box
   for(U32 j = 0; j < 6; j++)
   {
      glBegin(GL_LINE_LOOP);
      for(U32 k = 0; k < 4; k++)
         glVertex3f(projPnts[BoxVerts[j][k]].x,
                    projPnts[BoxVerts[j][k]].y,
                    projPnts[BoxVerts[j][k]].z);
      glEnd();
   }
}

void WorldEditor::renderObjectBox(SceneObject * obj, const ColorI & col)
{
   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");

   glDisable(GL_CULL_FACE);
   glColor4ub(col.red, col.green, col.blue, col.alpha);

   // project the points...
   Box3F box = obj->getObjBox();
   MatrixF mat = obj->getTransform();
   VectorF scale = obj->getScale();

   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]);
   }

   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

   // do the box
   for(U32 j = 0; j < 6; j++)
   {
      glBegin(GL_LINE_LOOP);
      for(U32 k = 0; k < 4; k++)
         glVertex3f(projPnts[BoxVerts[j][k]].x,
                    projPnts[BoxVerts[j][k]].y,
                    projPnts[BoxVerts[j][k]].z);
      glEnd();
   }

//   // render the collision polys?
//   // jff - this is using the worldbox... use obj box? which sides?
//   if(mRenderBoxIntersect)
//   {
//      obj->disableCollision();
//      Box3F bBox = obj->getWorldBox();
//
//      bBox.min.z -= mProjectDistance;
//      bBox.max.z += mProjectDistance;
//
//      ClippedPolyList polyList;
//      polyList.mPlaneList.clear();
//      polyList.mNormal.set(0,0,0);
//      polyList.mPlaneList.setSize(4);
//      polyList.mPlaneList[0].set(bBox.min, VectorF(-1,0,0));
//      polyList.mPlaneList[1].set(bBox.max, VectorF(0,1,0));
//      polyList.mPlaneList[2].set(bBox.max, VectorF(1,0,0));
//      polyList.mPlaneList[3].set(bBox.min, VectorF(0,-1,0));
//
//      // build the poly list
//      if(gServerContainer.buildPolyList(bBox, -1, &polyList))
//      {
//         glEnable(GL_CULL_FACE);
//         glDisable(GL_DEPTH_TEST);
//         glVertexPointer(3,GL_FLOAT,sizeof(ClippedPolyList::Vertex), polyList.mVertexList.address());
//         glEnableClientState(GL_VERTEX_ARRAY);
//
//         glColor4ub(mBoxIntersectColor.red, mBoxIntersectColor.green, mBoxIntersectColor.blue, mBoxIntersectColor.alpha);
//
//         glEnable(GL_BLEND);
//         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//
//         // render em...
//         ClippedPolyList::Poly * p;
//         for (p = polyList.mPolyList.begin(); p < polyList.mPolyList.end(); p++) {
//            glDrawElements(GL_POLYGON,p->vertexCount,
//               GL_UNSIGNED_INT,&polyList.mIndexList[p->vertexStart]);
//         }
//
//         glDisableClientState(GL_VERTEX_ARRAY);
//         glEnable(GL_DEPTH_TEST);
//         glDisable(GL_CULL_FACE);
//      }
//      obj->enableCollision();
//   }

   dglSetCanonicalState();
   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
}

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

void WorldEditor::renderObjectFace(SceneObject * obj, const VectorF & normal, const ColorI & col)
{
   // get the normal index
   VectorF objNorm;
   obj->getWorldTransform().mulV(normal, &objNorm);

   U32 normI = getBoxNormalIndex(objNorm);

   //
   Box3F box = obj->getObjBox();
   MatrixF mat = obj->getTransform();
   VectorF scale = obj->getScale();

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

⌨️ 快捷键说明

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