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

📄 worldeditor.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
            if(mRedirectID)
               obj = Sim::findObject(mRedirectID);
            Con::executef(obj ? obj : this, 2, "onClick", buf);
         }


         mHitInfo = info;
         mHitObject = mHitInfo.obj;
         mHitOffset = info.pos - mSelected.getCentroid();
         mHitRotation = extractEuler(mHitObject->getTransform());
         mHitMousePos = event.mousePoint;
         mHitCentroid = mSelected.getCentroid();
      }
      else if(!mSelectionLocked)
      {
         if(!(event.modifier & SI_SHIFT))
            mSelected.clear();

         mDragSelect = true;
         mDragSelected.clear();
         mDragRect.set(Point2I(event.mousePoint), Point2I(0,0));
         mDragStart = event.mousePoint;
      }
   }

   mLastMouseEvent = event;
}

void WorldEditor::on3DMouseUp(const Gui3DMouseEvent & event)
{
   mMouseDown = false;
   mUsingAxisGizmo = false;

   // check if selecting objects....
   if(mDragSelect)
   {
      mDragSelect = false;

      // add all the objects from the drag selection into the normal selection
      clearSelection();

      for(U32 i = 0; i < mDragSelected.size(); i++)
      {
         Con::executef(this, 3, "onSelect", avar("%d", mDragSelected[i]->getId()));
         mSelected.addObject(mDragSelected[i]);
      }
      mDragSelected.clear();

      if(mSelected.size())
      {
         char buf[16];
         dSprintf(buf, sizeof(buf), "%d", mSelected[0]->getId());

         SimObject * obj = 0;
         if(mRedirectID)
            obj = Sim::findObject(mRedirectID);
         Con::executef(obj ? obj : this, 2, "onClick", buf);
      }

      mouseUnlock();
      return;
   }

   if (mHitInfo.obj)
      mHitInfo.obj->inspectPostApply();
   mHitInfo.obj = 0;

   //
   if(collideAxisGizmo(event))
      setCursor(HandCursor);
   else
   {
      CollisionInfo info;
      if(collide(event, info) && !objClassIgnored(info.obj))
      {
         setCursor(HandCursor);

//         if(!mMouseDragged && !mSelectionLocked)
//         {
//            if(event.modifier & SI_SHIFT)
//            {
//               if(mSelected.objInSet(info.obj))
//                  mSelected.removeObject(info.obj);
//               else
//                  mSelected.addObject(info.obj);
//            }
//            else
//            {
//               mSelected.clear();
//               mSelected.addObject(info.obj);
//            }
//         }

         mHitInfo = info;
      }
      else
         setCursor(ArrowCursor);
   }

   //
   mHitObject = mHitInfo.obj;
   mouseUnlock();
}

void WorldEditor::on3DMouseDragged(const Gui3DMouseEvent & event)
{
   if(!mMouseDown)
      return;

   if(mNoMouseDrag)
      return;
   //
   if(!mMouseDragged)
   {
      if(!mUsingAxisGizmo)
      {
         // vert drag on new object.. reset hit offset
         if(bool(mHitObject) && !mSelected.objInSet(mHitObject))
         {
            if(!mSelectionLocked)
               mSelected.addObject(mHitObject);

            mHitOffset = mHitInfo.pos - mSelected.getCentroid();
         }
      }

      // create and add an undo state
      if(!mDragSelect)
      {
         addUndo(mUndoList, createUndo(mSelected));
         clearUndo(mRedoList);
      }

      mMouseDragged = true;
   }

   // update the drag selection
   if(mDragSelect)
   {
      // build the drag selection on the renderScene method - make sure no neg extent!
      mDragRect.point.x = (event.mousePoint.x < mDragStart.x) ? event.mousePoint.x : mDragStart.x;
      mDragRect.extent.x = (event.mousePoint.x > mDragStart.x) ? event.mousePoint.x - mDragStart.x : mDragStart.x - event.mousePoint.x;
      mDragRect.point.y = (event.mousePoint.y < mDragStart.y) ? event.mousePoint.y : mDragStart.y;
      mDragRect.extent.y = (event.mousePoint.y > mDragStart.y) ? event.mousePoint.y - mDragStart.y : mDragStart.y - event.mousePoint.y;
      return;
   }

   if(!mUsingAxisGizmo && (!bool(mHitObject) || !mSelected.objInSet(mHitObject)))
      return;

   // anything locked?
   for(U32 i = 0; i < mSelected.size(); i++)
      if(mSelected[i]->isLocked())
         return;

   // do stuff
   switch(mCurrentMode)
   {
      case Move:
      {
         setCursor(MoveCursor);

         // grabbed axis gizmo?
         if(mUsingAxisGizmo)
         {
            F32 offset;
            Point3F projPnt = mHitCentroid;;

            if( mAxisGizmoSelAxis != 2 ) {
               offset = ( event.mousePoint.x - mHitMousePos.x ) * mMouseMoveScale;

               Point3F cv, camVector, objVector;
               S32 col = ( mAxisGizmoSelAxis != 0 );

               smCamMatrix.getColumn( 1, &camVector );
               mSelected[0]->getTransform().getColumn( col, &objVector );

               mCross( objVector, camVector, &cv );
               if( cv.z < 0 )
                  offset *= -1;
            }
            else
               offset = ( event.mousePoint.y - mHitMousePos.y ) * mMouseMoveScale * -1;


            //for(S32 i = 0; i < 3; i++)
            //   if(i == mAxisGizmoSelAxis)
            //      ((F32*)projPnt)[i] += offset;
            ((F32*)projPnt)[mAxisGizmoSelAxis] += offset;

            //
            if((mSelected.size() == 1) && !(event.modifier & SI_SHIFT))
            {
               MatrixF mat = mSelected[0]->getTransform();
               Point3F offset;
               mat.mulV(projPnt - mHitCentroid, &offset);

               mSelected.offset(offset + mHitCentroid - mSelected.getCentroid());
            }
            else
            {
               // snap to the selected axis
               Point3F snap = snapPoint(projPnt);
               ((F32*)projPnt)[mAxisGizmoSelAxis] = ((F32*)snap)[mAxisGizmoSelAxis];
               mSelected.offset(projPnt - mSelected.getCentroid());
            }

            updateClientTransforms(mSelected);
         }
         else
         {
            // ctrl modifier movement?
            if(mUseVertMove)
            {
               if(mPlanarMovement)
               {
                  // do a projection onto the z axis
                  F64 pDist = mSqrt((event.pos.x - mHitInfo.pos.x) * (event.pos.x - mHitInfo.pos.x) +
                     (event.pos.y - mHitInfo.pos.y) * (event.pos.y - mHitInfo.pos.y));

                  Point3F vec(mHitInfo.pos.x - event.pos.x, mHitInfo.pos.y - event.pos.y, 0.f);
                  vec.normalizeSafe();

                  F64 projDist = mDot(event.vec, vec);
                  if(projDist == 0.f)
                     return;

                  F64 scale = pDist / projDist;
                  vec = event.pos + (event.vec * scale);

                  vec.x = mHitInfo.pos.x;
                  vec.y = mHitInfo.pos.y;
                  mSelected.offset(vec - mSelected.getCentroid() - mHitOffset);
                  updateClientTransforms(mSelected);
               }
               else
               {
                  // do a move on the z axis
                  F32 diff = mLastMouseEvent.mousePoint.x - event.mousePoint.x;
                  F32 offset = diff * mMouseMoveScale;
                  Point3F projPnt = mSelected.getCentroid();
                  projPnt.z += offset;

                  // snap just to z axis
                  Point3F snapped = snapPoint(projPnt);
                  projPnt.z = snapped.z;

                  mSelected.offset(projPnt - mSelected.getCentroid());
                  updateClientTransforms(mSelected);
               }
            }
            else
            {
               // move on XY plane
               if(mPlanarMovement)
               {
                  // on z
                  F32 cos = mDot(event.vec, Point3F(0,0,-1));
                  F32 a = event.pos.z - mHitInfo.pos.z;
                  if(cos != 0.f)
                  {
                     F32 c = a / cos;

                     Point3F projPnt = event.vec * c;
                     projPnt += event.pos;
                     projPnt -= mHitOffset;

                     //
                     F32 z = projPnt.z;
                     projPnt = snapPoint(projPnt);
                     projPnt.z = z;

                     mSelected.offset(projPnt - mSelected.getCentroid());
                     updateClientTransforms(mSelected);
                  }
               }
               else
               {
                  // offset the pnt of collision - no snapping involved
                  mSelected.disableCollision();

                  CollisionInfo info;
                  if(collide(event, info))
                  {
                     mSelected.offset(info.pos - mSelected.getCentroid() - mHitOffset);
                     updateClientTransforms(mSelected);
                  }

                  mSelected.enableCollision();
               }
            }
         }
         break;
      }

      case Scale:
      {
         setCursor(ScaleCursor);

         // can scale only single selections
         if(mSelected.size() > 1)
            break;

         if(mUsingAxisGizmo)
         {
            //
            F32 diff = mLastMouseEvent.mousePoint.x - event.mousePoint.x;

            // offset the correct axis
            EulerF curScale = ((SceneObject*)mSelected[0])->getScale();
            EulerF scale;

            F32 * pCurScale = ((F32*)curScale);
            F32 * pScale = ((F32*)scale);

            for(S32 i = 0; i < 3; i++)
            {
               if(i == mAxisGizmoSelAxis)
                  pScale[i] = 1.f + (diff * mMouseScaleScale);
               else
                  pScale[i] = 1.f;

               // clamp
               if(pCurScale[i] * pScale[i] < mMinScaleFactor)
                  pScale[i] = mMinScaleFactor / pCurScale[i];
               if(pCurScale[i] * pScale[i] > mMaxScaleFactor)
                  pScale[i] = mMaxScaleFactor / pCurScale[i];
            }

            mSelected.scale(scale);
            updateClientTransforms(mSelected);
         }
         else
         {
            if(!mBoundingBoxCollision)
            {
               // the hit normal is not useful, enable bounding box
               // collision and get the collided face/normal
               CollisionInfo info;

               mBoundingBoxCollision = true;
               bool hit = collide(event, info);
               mBoundingBoxCollision = false;

               // hit and the hit object?
               if(!hit || (info.obj != (SceneObject*)mHitObject))
                  break;

               mHitInfo = info;
            }

            VectorF normal;
            mCross(mHitInfo.normal, event.vec, &normal);

            VectorF planeNormal;
            mCross(mHitInfo.normal, normal, &planeNormal);

            PlaneF plane;
            plane.set(mHitInfo.pos, planeNormal);

            Point3F vecProj = event.pos + event.vec * mProjectDistance;
            F32 t = plane.intersect(event.pos, vecProj);
            if(t < 0.f || t > 1.f)
               break;

            Point3F pnt;
            pnt.interpolate(event.pos, vecProj, t);

            // figure out which axis we are working with, then
            // find the distance to the correct face on the bbox
            VectorF objNorm;
            const MatrixF & worldMat = mHitObject->getWorldTransform();
            worldMat.mulV(mHitInfo.normal, &objNorm);

            U32 normIndex = getBoxNormalIndex(objNorm);

            Box3F box = mHitObject->getObjBox();
            VectorF curScale = mHitObject->getScale();

            // scale and transform the bbox
            Point3F size = box.max - box.min;

            box.min.convolve(curScale);
            box.max.convolve(curScale);

            Box3F projBox;
            const MatrixF & objMat = mHitObject->getTransform();
            objMat.mulP(box.min, &projBox.min);
            objMat.mulP(box.max, &projBox.max);

            // if positive normal then grab max, else min
            Point3F boxPnt;
            Point3F offset;
            if(normIndex & 0x01)
            {
               boxPnt = projBox.max;
               worldMat.mulV(mSelected.getCentroid() - projBox.min, &offset);
            }
            else
            {
               boxPnt = projBox.min;
               worldMat.mulV(mSelected.getCentroid() - projBox.max, &offset);
            }

            plane.set(boxPnt, mHitInfo.normal);
            F32 dist = plane.distToPlane(pnt);

            // set the scale for the correct axis
            Point3F scale;
            F32 * pScale = ((F32*)scale);
            F32 * pSize = ((F32*)size);
            F32 * pCurScale = ((F32*)curScale);
            F32 * pOffset = ((F32*)offset);

            for(U32 i = 0; i < 3; i++)
            {
               if((normIndex >> 1) == i)
               {
                  // get the new scale
                  pScale[i] = (pSize[i] * pCurScale[i] + dist) / pSize[i];

                  // clamp
                  if(pScale[i] < mMinScaleFactor)
                     pScale[i] = mMinScaleFactor;
                  if(pScale[i] > mMaxScaleFactor)
                     pScale[i] = mMaxScaleFactor;

                  pOffset[i] = pScale[i] / pCurScale[i] * pOffset[i] - pOffset[i];
               }
               else
               {
                  pScale[i] = pCurScale[i];
                  pOffset[i] = 0;
               }
            }

            objMat.mulV(offset, &pnt);
            mSelected.offset(pnt);
            mHitObject->setScale(scale);
            updateClientTransforms(mSelected);
         }

         break;
      }

      case Rotate:
      {
         setCursor(RotateCursor);

         // default to z axis
         S32 axis = 2;
         if(mUsingAxisGizmo)
            axis = mAxisGizmoSelAxis;

         F32 angle = (event.mousePoint.x - mHitMousePos.x) * mMouseRotateScale;

         //
         if(mSnapRotations)
         {
            angle = mDegToRad(snapFloat(mRadToDeg(angle), mRotationSnap));
            if(mSelected.size() == 1)
               angle -= ((F32*)mHitRotation)[axis];
         }

         EulerF rot(0.f, 0.f, 0.f);
         ((F32*

⌨️ 快捷键说明

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