📄 worldeditor.cc
字号:
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 + -