//----------------------------------------------------------------------------
void FMODSound::SetVelocity (const AVector &velocity)
{
    FMOD_VECTOR vec;
    vec.x = velocity.X();
    vec.y = velocity.Y();
    vec.z = velocity.Z();

    if (mChannel)
        mChannel->set3DAttributes(0, &vec);
}
//----------------------------------------------------------------------------
void Soundable::UpdateWorldData(double applicationTime, double elapsedTime)
{
	Movable::UpdateWorldData(applicationTime, elapsedTime);

	if (mSound)
		mSound->SetPosition(WorldTransform.GetTranslate());

	const APoint &listenPos = SoundSystem::GetSingleton().GetListenerPos();

	if (!Is3D())
	{
		AVector dir = WorldTransform.GetTranslate() - listenPos;

		if (!mDistanceUseX)
			dir.X() = 0.0f;

		if (!mDistanceUseY)
			dir.Y() = 0.0f;

		if (!mDistanceUseZ)
			dir.Z() = 0.0f;

		float dist = dir.Length();

		SoundableController *sCtrl = DynamicCast<SoundableController>(GetEffectableController());
		const SoundableObject *sObj = sCtrl->GetSoundableObject();
		if (sObj)
		{
			float curVolume = sObj->Volume;
			float volume = curVolume;

			if (dist < mMinDistance)
			{
				volume = curVolume;
			}
			else if (mMinDistance<=dist && dist<=mMaxDistance)
			{
				float range = mMaxDistance - mMinDistance;
				if (range <= 0.0f)
					range = 0.0f;

				volume = curVolume * (1.0f - (dist - mMinDistance)/range);
			}
			else if (dist > mMaxDistance)
			{
				volume = 0.0f;
			}

			if (mSound)
			{
				mSound->SetVolume(volume);
			}
		}
	}
}
//----------------------------------------------------------------------------
bool PushTransformController::Update(double applicationTime, 
	double elapsedTime1)
{
	if (!Controller::Update(applicationTime, elapsedTime1))
		return false;

	if (mVelocity == AVector::ZERO)
		return true;

	float elapsedTime = (float)elapsedTime1;

	AVector velocityDis = mVelocity*elapsedTime;
	AVector movedDis;

	if (IsXY())
	{
		movedDis.X() = velocityDis.X();
		movedDis.Y() = velocityDis.Y();
	}
	else
	{
		movedDis.X() = velocityDis.X();
		movedDis.Z() = velocityDis.Z();
	}

	OnMoving(movedDis);
	
	// 减小速度
	AVector vecTemp = mVelocity;
	float vecLength = vecTemp.Normalize();
	vecLength -= mFriction * elapsedTime;
	if (vecLength <= 0.0f)
	{
		SetVelocity(AVector::ZERO);
	}
	else
	{
		SetVelocity(vecTemp * vecLength);
	}

	return true;
}
//----------------------------------------------------------------------------
AVector InputPushTransformController::GetSmallTransDir()
{
	Movable *movable = DynamicCast<Movable>(mObject);
	if (!movable)
		AVector::ZERO;

	APoint curPos = movable->LocalTransform.GetTranslate();

	AVector moveDir = AVector::ZERO;
	if (curPos.X() < mMinPosSmall.X())
	{
		moveDir.X() = mMinPosSmall.X() - curPos.X();
	}

	if (curPos.Y() < mMinPosSmall.Y())
	{
		moveDir.Y() = mMinPosSmall.Y() - curPos.Y();
	}

	if (curPos.Z() < mMinPosSmall.Z())
	{
		moveDir.Z() = mMinPosSmall.Z() - curPos.Z();
	}

	if (curPos.X()>mMaxPosSmall.X())
	{
		moveDir.X() = mMaxPosSmall.X() - curPos.X();
	}

	if (curPos.Y() > mMaxPosSmall.Y())
	{
		moveDir.Y() = mMaxPosSmall.Y() - curPos.Y();
	}

	if (curPos.Z() > mMaxPosSmall.Z())
	{
		moveDir.Z() = mMaxPosSmall.Z() - curPos.Z();
	}

	return moveDir;
}
//----------------------------------------------------------------------------
int FramesMesh::_GetDirIndex(const AVector &dir)
{
	AVector animVec = dir;
	animVec.Normalize();

	AVector up = AVector::UNIT_Y;
	float dotVal = up.Dot(animVec);

	float rad = Mathf::ACos(dotVal);
	float degree = Mathf::RAD_TO_DEG * rad;
	bool isRight = (dir.X() > 0.0f);

	if (0 <= degree && degree < 22.5f)
	{
		return 0;
	}
	else if (22.5f <= degree && degree < 67.5f)
	{
		if (isRight)
			return 1;
		else
			return 7;
	}
	else if (67.5 <= degree && degree < 112.5f)
	{
		if (isRight)
			return 2;
		else
			return 6;
	}
	else if (112.5f <= degree && degree < 157.5f)
	{
		if (isRight)
			return 3;
		else
			return 5;
	}
	else if (157.5f <= degree && degree <= 180.0f)
	{
		return 4;
	}

	return 0;
}
//----------------------------------------------------------------------------
void EditRenderView_Scene::OnMotion(const APoint &pos)
{
	if (!IsEnable()) return;

	APoint curPos = pos;
	APoint lastPos = mLastMousePoint;
	AVector delta = curPos - lastPos;
	mLastMousePoint = curPos;

	if (delta == AVector::ZERO) return;

	Edit::EditType et = PX2_EDIT.GetEditType();

	if (et == Edit::ET_TERRAIN)
	{
		_UpdateBrushPos(pos);
	}

	if (mIsMiddleDown || mIsRightDown)
	{
		float speedVal = 3.0f;

		if (VT_PERSPECTIVE == mViewType)
		{
			if (PX2_EDIT.IsAltDown)
			{
				_RolateCamera(delta.X()*mPixelToWorld.first*speedVal*0.25f, -delta.Z()*mPixelToWorld.second*speedVal*0.25f);
			}
			else if (PX2_EDIT.IsCtrlDown)
			{
				Movable *mov = DynamicCast<Movable>(PX2_SELECTION.GetFirstObject());
				if (mov)
				{
					_RoundCamera(delta.X()*speedVal*0.02f, -delta.Z()*speedVal*0.02f);
				}
				else
				{
					_PanCamera(-delta.X()*mPixelToWorld.first*speedVal, delta.Z()*mPixelToWorld.second*speedVal);
				}
			}
			else if (PX2_EDIT.IsShiftDown)
			{
				_ZoomCamera(-delta.Z()*mPixelToWorld.second*PX2_EDIT.GetCameraMoveSpeed());
			}
			else
			{
				_PanCamera(-delta.X()*mPixelToWorld.first*speedVal, delta.Z()*mPixelToWorld.second*speedVal);
			}
		}
		else
		{
			_PanCamera(delta.X()*mPixelToWorld.first, delta.Z()*mPixelToWorld.second);
		}
	}
	else if (mIsLeftDown)
	{
		PX2_EDIT.GetTerrainEdit()->Apply(false);
	}

	Edit::EditMode em = PX2_EDIT.GetEditMode();
	if ((Edit::EM_TRANSLATE == em || Edit::EM_ROLATE == em || Edit::EM_SCALE == em))
	{
		if (mSceneNodeCtrl)
			mSceneNodeCtrl->OnMotion(mIsLeftDown, mRenderStepCtrl, curPos, lastPos);

		if (mIsLeftDown)
		{
			mIsSelectMovableTransChanged = true;
		}
	}
}
//----------------------------------------------------------------------------
void SizeNode::UpdateLayout(Movable *parent)
{
	Movable *par = parent;
	if (!par) return;

	SizeNode *parNode = DynamicCast<SizeNode>(par);

	// parent pvoit决定了从那一点作为原点,计算当前Frame原点位置
	// 例如
	// (0.0f, 0.0f)是左下角
	// (0.5f, 0.5f)是中心点	
	Sizef parentSize;
	AVector parentLeftBottomOffset;
	if (parNode)
	{
		parentSize = parNode->GetSize();
		parentLeftBottomOffset = parNode->LeftBottomCornerOffset;
	}

	APoint localPos = LocalTransform.GetTranslate();
	Sizef localSize = GetSize();

	APoint newPos;
	Sizef newSize = localSize;
	if (parNode)
	{
		float width = 0.0f;
		float height = 0.0f;

		bool isHEqual = (mAnchorHor[0] == mAnchorHor[1]);
		bool isVEqual = (mAnchorVer[0] == mAnchorVer[1]);

		if (isHEqual)
		{
			width = localSize.Width;
			newPos.X() = parentLeftBottomOffset.X() +
				parentSize.Width * mAnchorHor[0] + mAnchorParamHor[0];
		}
		else
		{
			// 如果是范围,直接取中心点,作为原点
			width = parentSize.Width * (mAnchorHor[1] - mAnchorHor[0]) - mAnchorParamHor[0] + mAnchorParamHor[1];
			newPos.X() = parentLeftBottomOffset.X() + parentSize.Width*mAnchorHor[0] + mAnchorParamHor[0] + width / 2.0f;
		}

		if (isVEqual)
		{
			height = localSize.Height;
			newPos.Z() = parentLeftBottomOffset.Z() +
				parentSize.Height * mAnchorVer[0] + mAnchorParamVer[0];
		}
		else
		{
			// 如果是范围,直接取中心点,作为原点
			height = parentSize.Height * (mAnchorVer[1] - mAnchorVer[0]) - mAnchorParamVer[0] + mAnchorParamVer[1];
			newPos.Z() = parentLeftBottomOffset.Z() + parentSize.Height*mAnchorVer[0] + mAnchorParamVer[0] + height / 2.0f;
		}

		newSize = Sizef(width, height);
	}

	newPos.Y() = localPos.Y();
	LocalTransform.SetTranslate(newPos);

	if (newSize != localSize)
	{
		SetSize(newSize);
	}
}
//----------------------------------------------------------------------------
void BeamEmitterController::EmitABeam (float ctrlTime)
{
	BeamEmitter *emitter = (BeamEmitter*)mObject;
	ModulesUpdateEffectable(ctrlTime);

	Camera *cam = Renderer::GetDefaultRenderer()->GetCamera();
	const AVector &camD = cam->GetDVector();

	Effectable::FaceType faceType = emitter->GetFaceType();
	BeamEmitter::WaveType waveTypeUp = emitter->GetWaveTypeUp();
	BeamEmitter::WaveType waveTypeExtend = emitter->GetWaveTypeExtend();
	int numLowFre = emitter->GetNumLowFrequency();
	int numHighFre = emitter->GetNumHighFrequency();
	const Float2 &lowFreRangeUp = emitter->GetLowFrequencyRangeUp();
	const Float2 &lowFreRangeExtend = emitter->GetLowFrequencyRangeExtend();
	const Float2 &hightFreRangeUp = emitter->GetHighFrequencyRangeUp();
	const Float2 &hightFreRangeExtend = emitter->GetHighFrequencyRangeExtend();
	APoint emitStartPos = emitter->GetEmitStartPos();
	const APoint &emitEndPos = emitter->GetEmitEndPos();

	if (emitter->IsStartPosUseLocal() && !emitter->IsLocal())
	{
		emitStartPos = emitter->WorldTransform * emitStartPos;
	}

	BeamObject obj;
	obj.StartPos = emitStartPos;
	obj.EndPos = emitEndPos;

	AVector dirVec = emitEndPos - emitStartPos;
	if (dirVec == AVector::ZERO)
	{
		dirVec.X() = 0.01f;
	}
	AVector dir = dirVec;
	dir.Normalize();

	AVector toMeDir;
	if (Effectable::FT_X == faceType)
	{
		toMeDir = AVector::UNIT_X;
	}
	else if (Effectable::FT_NX == faceType)
	{
		toMeDir = -AVector::UNIT_X;
	}
	else if (Effectable::FT_Y == faceType)
	{
		toMeDir = AVector::UNIT_Y;
	}
	else if (Effectable::FT_NY == faceType)
	{
		toMeDir = -AVector::UNIT_Y;
	}
	else if (Effectable::FT_Z == faceType)
	{
		toMeDir = AVector::UNIT_Z;
	}
	else if (Effectable::FT_NZ == faceType)
	{
		toMeDir = -AVector::UNIT_Z;
	}
	else if (Effectable::FT_CAMERA == faceType || 
		Effectable::FT_SPEEDDIR==faceType || 
		Effectable::FT_FREE==faceType)
	{
		toMeDir = -camD;
	}

	AVector upDir = toMeDir.Cross(dir);
	upDir.Normalize();
	AVector toMeExtendDir = dir.Cross(upDir);
	toMeExtendDir.Normalize();

	int numLowFreNumPoints = numLowFre+1;

	std::vector<float> upLFs, toMeLFs;

	if (BeamEmitter::WT_RANDOM==waveTypeUp || BeamEmitter::WT_LINE==waveTypeUp)
	{
		GernerateLFPoints(upLFs, numLowFreNumPoints, waveTypeUp, lowFreRangeUp[0], lowFreRangeUp[1]);
	}
	else
	{
	}

	if (BeamEmitter::WT_RANDOM==waveTypeExtend || BeamEmitter::WT_LINE==waveTypeExtend)
	{
		GernerateLFPoints(toMeLFs, numLowFreNumPoints, waveTypeExtend, lowFreRangeExtend[0], lowFreRangeExtend[1]);
	}
	else
	{
	}

	APoint lastPoint;
	for (int i=0; i<numLowFreNumPoints; i++)
	{
		APoint lPos = emitStartPos + dirVec * (i/(float)(numLowFreNumPoints-1));
		APoint lPoint = lPos + upDir*upLFs[i] + toMeExtendDir * toMeLFs[i];

		if (0 != i)
		{
			for (int k=1; k<numHighFre; k++)
			{
				AVector hVec = lPoint - lastPoint;
				APoint hPoint = lastPoint + hVec * (k/(float)numHighFre);
				hPoint += upDir * Mathf::IntervalRandom(hightFreRangeUp[0], hightFreRangeUp[1]);
				hPoint += toMeExtendDir * Mathf::IntervalRandom(hightFreRangeExtend[0], hightFreRangeExtend[1]);

				obj.Points.push_back(hPoint);
			}
		}

		obj.Points.push_back(lPoint);

		lastPoint = lPoint;
	}

	OnNewAEffectObject(&obj);

	ModulesUpdateEffectObject(&obj);

	mBeamObjects.push_back(obj);
}
//----------------------------------------------------------------------------
void WindowApplication3::RotateTrackBall (float x0, float y0, float x1,
        float y1)
{
	if ((x0 == x1 && y0 == y1) || !mCamera)
	{
		// Nothing to rotate.
		return;
	}

	// Get the first vector on the sphere.
	float length = Mathf::Sqrt(x0*x0 + y0*y0), invLength, z0, z1;
	if (length > 1.0f)
	{
		// Outside the unit disk, project onto it.
		invLength = 1.0f/length;
		x0 *= invLength;
		y0 *= invLength;
		z0 = 0.0f;
	}
	else
	{
		// Compute point (x0,y0,z0) on negative unit hemisphere.
		z0 = 1.0f - x0*x0 - y0*y0;
		z0 = (z0 <= 0.0f ? 0.0f : Mathf::Sqrt(z0));
	}
	z0 *= -1.0f;

	// Use camera world coordinates, order is (D,U,R), so point is (z,y,x).
	AVector vec0(z0, y0, x0);

	// Get the second vector on the sphere.
	length = Mathf::Sqrt(x1*x1 + y1*y1);
	if (length > 1.0f)
	{
		// Outside unit disk, project onto it.
		invLength = 1.0f/length;
		x1 *= invLength;
		y1 *= invLength;
		z1 = 0.0f;
	}
	else
	{
		// Compute point (x1,y1,z1) on negative unit hemisphere.
		z1 = 1.0f - x1*x1 - y1*y1;
		z1 = (z1 <= 0.0f ? 0.0f : Mathf::Sqrt(z1));
	}
	z1 *= -1.0f;

	// Use camera world coordinates, order is (D,U,R), so point is (z,y,x).
	AVector vec1(z1, y1, x1);

	// Create axis and angle for the rotation.
	AVector axis = vec0.Cross(vec1);
	float dot = vec0.Dot(vec1);
	float angle;
	if (axis.Normalize() > Mathf::ZERO_TOLERANCE)
	{
		angle = Mathf::ACos(dot);
	}
	else  // Vectors are parallel.
	{
		if (dot < 0.0f)
		{
			// Rotated pi radians.
			invLength = Mathf::InvSqrt(x0*x0 + y0*y0);
			axis.X() = y0*invLength;
			axis.Y() = -x0*invLength;
			axis.Z() = 0.0f;
			angle = Mathf::PI;
		}
		else
		{
			// Rotation by zero radians.
			axis = AVector::UNIT_X;
			angle = 0.0f;
		}
	}

	// Compute the world rotation matrix implied by trackball motion.  The
	// axis vector was computed in camera coordinates.  It must be converted
	// to world coordinates.  Once again, I use the camera ordering (D,U,R).
	AVector worldAxis =
	    axis.X()*mCamera->GetDVector() +
	    axis.Y()*mCamera->GetUVector() +
	    axis.Z()*mCamera->GetRVector();

	HMatrix trackRotate(worldAxis, angle);

	// Compute the new local rotation.  If the object is the root of the
	// scene, the new rotation is simply the *incremental rotation* of the
	// trackball applied *after* the object has been rotated by its old
	// local rotation.  If the object is not the root of the scene, you have
	// to convert the incremental rotation by a change of basis in the
	// parent's coordinate space.
	const Spatial* parent = mMotionObject->GetParent();
	HMatrix localRot;
	if (parent)
	{
		const HMatrix& parWorRotate = parent->WorldTransform.GetRotate();
		localRot = parWorRotate.TransposeTimes(trackRotate) * parWorRotate *
		           mSaveRotate;
	}
	else
	{
		localRot = trackRotate*mSaveRotate;
	}
	localRot.Orthonormalize();
	mMotionObject->LocalTransform.SetRotate(localRot);
}
//----------------------------------------------------------------------------
void EditRenderView_TimeLine::OnMotion(const APoint &pos)
{
	AVector diff = pos - mLastMousePoint;
	if (AVector::ZERO == diff) return;

	float movedX = -diff.X() / mPixelOverCamIn;
	float movedZ = -diff.Z() / mPixelOverCamOut;
	Rectf rect(0, 0, mLeftWidth, mSize.Height);
	bool leftContain = rect.IsInsize(Float2(pos.X(), pos.Z()));

	bool isCtrlDown = PX2_EDIT.IsCtrlDown;
	CurveCtrl *selectedCtrl = PX2_EDIT.GetTimeLineEdit()->GetSelectedCurveCtrl();

	if (isCtrlDown && !leftContain && selectedCtrl && mIsLeftDown)
	{
		Camera *camera = mRenderStep->GetCamera();

		const APoint &outVal = selectedCtrl->GetOutVal();
		Vector2f posInViewPort = mUIViewGrid->PointWorldToViewPort(outVal);

		float xDiss = pos.X() - posInViewPort.X();
		float zDiss = pos.Z() - posInViewPort.Y();
		float xDissReal = xDiss / mPixelOverCamIn;
		float zDissReal = zDiss / mPixelOverCamOut;

		AVector arrive = AVector(-xDissReal, 0.0f, -zDissReal);
		arrive.Normalize();
		AVector leave = AVector(xDissReal, 0.0f, zDissReal);
		leave.Normalize();

		if (CurveCtrl::SM_ARRIVE == selectedCtrl->GetSelectMode())
		{
			if (xDiss < 0.0f)
			{
				selectedCtrl->SetArriveTangent(arrive);

				InterpCurveMode mode = selectedCtrl->GetInterpCurveMode();
				if (ICM_CURVE_AUTO == mode || ICM_CURVE_AUTOCLAMPED == mode)
				{
					selectedCtrl->SetInterpCurveMode(ICM_CURVE_USER);
					//UnToggleAllInterps();
					//ToggleInterp(ICM_CURVE_USER);
				}
			}
		}
		else if (CurveCtrl::SM_LEAVE == selectedCtrl->GetSelectMode())
		{
			if (xDiss > 0.0f)
			{
				selectedCtrl->SetLeaveTangent(leave);

				InterpCurveMode mode = selectedCtrl->GetInterpCurveMode();
				if (ICM_CURVE_AUTO == mode || ICM_CURVE_AUTOCLAMPED == mode)
				{
					selectedCtrl->SetInterpCurveMode(ICM_CURVE_USER);
					//UnToggleAllInterps();
					//ToggleInterp(ICM_CURVE_USER);
				}
			}
		}
		else if (CurveCtrl::SM_CENTER == selectedCtrl->GetSelectMode())
		{
			APoint camPos = camera->GetPosition();
			Vector2f camScreenPos = mUIViewGrid->PointWorldToViewPort(camPos);
			float xDissCam = pos.X() - camScreenPos.X();
			float zDissCam = pos.Z() - camScreenPos.Y();
			float xDissCamReal = xDissCam / mPixelOverCamIn;
			float zDissCamReal = zDissCam / mPixelOverCamOut;
			APoint pointPos = camPos + AVector(xDissCamReal, 0.0f, zDissCamReal);
			pointPos.Y() = 0.0f;

			selectedCtrl->SetInVal(pointPos.X()); // ctrl may changed

			selectedCtrl = PX2_EDIT.GetTimeLineEdit()->GetSelectedCurveCtrl(); // ctrl may changed, can it again
			if (selectedCtrl) selectedCtrl->SetOutVal(pointPos);
		}
	}

	bool doMovCal = false;

	if (mIsMiddleDown && !leftContain)
		doMovCal = true;

	if (mIsRightDown && !leftContain)
		doMovCal = true;

	if (doMovCal)
	{
		if (MM_PAN == mMoveMode)
		{
			APoint pos = mUIViewGrid->GetCameraNode()->LocalTransform.GetTranslate();
			pos += AVector(movedX, 0.0f, movedZ);
			mUIViewGrid->GetCameraNode()->LocalTransform.SetTranslate(pos);
			mUIViewGrid->GetCameraNode()->Update(GetTimeInSeconds(), 0.0f);

			_RefreshGrid(false);
		}
		else if (MM_ZOOM == mMoveMode)
		{
		}
	}

	mLastMousePoint = pos;
}
//----------------------------------------------------------------------------
void EU_CanvasStage::OnMotion(const APoint &worldPos)
{
	if (!IsEnable())
		return;

	const Rectf &rectWorld = GetWorldRect();
	if (!rectWorld.IsInsize(worldPos.X(), worldPos.Z()))
		return;

	UICanvas::OnMotion(worldPos);

	if (!Project::GetSingletonPtr()) return;
	if (!PX2_PROJ.GetScene()) return;

	if (mMoveDelta == AVector::ZERO) return;

	Edit::EditType et = PX2_EDIT.GetEditType();
	if (et == Edit::ET_TERRAIN)
	{
		APoint viewPortPos = WorldPosToViewPortPos(worldPos);
		_UpdateBrushPos(viewPortPos);
	}

	APoint curViewPortPos = WorldPosToViewPortPos(mCurPickPos);
	APoint lastViewPortPos = WorldPosToViewPortPos(mLastPickPos);

	AVector delta = mMoveDelta;
	float speedVal = 0.01f;

	SceneNodeCtrl::DragType dt = mSceneNodeCtrl->GetDragType();
	if (dt == SceneNodeCtrl::DT_NONE)
	{
		if (AVector::ZERO != delta && (mIsRightPressed || mIsMiddlePressed))
		{
			SetCameraDraging(true);
		}
	}
	else
	{
		SetCameraDraging(false);
	}

	if (IsCameraDraging())
	{
		if (VT_PERSPECTIVE == mViewType)
		{
			if (PX2_EDIT.IsAltDown)
			{
				if (mIsLeftPressed)
				{
					Movable *mov = DynamicCast<Movable>(PX2_SELECTM_E->GetFirstObject());
					if (mov)
					{
						_RoundCamera(delta.X()*speedVal*0.02f, -delta.Z()*speedVal*0.02f);
					}
					else
					{
						_PanCamera(delta.X()*mPixelToWorld.first*speedVal, delta.Z()*mPixelToWorld.second*speedVal);
					}
				}
				else if (mIsRightPressed)
				{
					_ZoomCamera(-delta.Z()*mPixelToWorld.second*PX2_EDIT.GetCameraMoveSpeed()*speedVal);
				}
			}
			else
			{
				if (mIsRightPressed)
				{
					_RolateCamera(delta.X()*mPixelToWorld.first*speedVal*0.25f, -delta.Z()*mPixelToWorld.second*speedVal);
				}
				else if (mIsMiddlePressed)
				{
					_PanCamera(-delta.X()*mPixelToWorld.first*speedVal, delta.Z()*mPixelToWorld.second*speedVal);
				}
			}
		}
		else
		{
			_PanCamera(-delta.X()*mPixelToWorld.first, delta.Z()*mPixelToWorld.second*speedVal);
		}
	}
	else
	{
		if (mIsLeftPressed)
		{
			PX2_EDIT.GetTerrainEdit()->Apply(false);
		}

		Edit::EditMode em = PX2_EDIT.GetEditMode();
		if ((Edit::EM_TRANSLATE == em || Edit::EM_ROTATE == em || Edit::EM_SCALE == em))
		{
			Camera *camera = mSceneNodeCtrlCanvas->GetOverCamera();

			if (mSceneNodeCtrl)
				mSceneNodeCtrl->OnMotion(mIsLeftPressed, camera, 
				curViewPortPos, lastViewPortPos, GetSize());

			if (mIsLeftPressed)
			{
				mIsSelectMovableTransChanged = true;
			}
		}
	}
}
//----------------------------------------------------------------------------
bool InputPushTransformController::Update(double applicationTime, 
	double elapsedTime1)
{
	if (!Controller::Update(applicationTime, elapsedTime1))
		return false;

	float elapsedTime = (float)elapsedTime1;

	if (mIsPressedValid)
	{
		mSampingTiming += elapsedTime;
		if (mSampingTiming >= 0.03f)
		{
			AVector deltaVec = mCurTouchPos - mLastSamplePos;
			mLastSamplePos = mCurTouchPos;

			mTouchMoveSpeed = deltaVec / 0.03f;

			mSampingTiming = 0.0f;
		}
	}

	if (!IsSmallTransScope())
	{
		// 减小速度
		AVector vecTemp = mVelocity;
		float vecLength = vecTemp.Normalize();
		vecLength -= mFriction * elapsedTime;
		if (vecLength <= 0.0f)
		{
			SetVelocity(AVector::ZERO);
		}
		else
		{
			SetVelocity(vecTemp * vecLength);
		}
	}
	else
	{
		if (!mIsPressedValid) // 没有按下
		{
			if (0.0f == mSideMoveLength)
				mSideMoveLength = 1.0f;

			AVector smallDir = GetSmallTransDir();
			if (AVector::ZERO != smallDir)
			{
				float moveDirLength = smallDir.Normalize();
				float adjuge = moveDirLength / mSideMoveLength;

				mVelocity += smallDir * mFriction * adjuge * adjuge * elapsedTime;
			}
		}
		else
		{
			mVelocity = AVector::ZERO;
		}
	}

	AVector velocityDis = mVelocity*elapsedTime;

	AVector movedDis;
	if (IsXY())
	{
		movedDis.X() = velocityDis.X();
		movedDis.Y() = velocityDis.Y();
	}
	else
	{
		movedDis.X() = velocityDis.X();
		movedDis.Z() = velocityDis.Z();
	}

	AVector beforeSmallDir = GetSmallTransDir();

	OnMoving(movedDis);

	if (IsSmallTransScope())
	{
		AVector smallDir = GetSmallTransDir();
		if (smallDir == AVector::ZERO && beforeSmallDir != AVector::ZERO)
		{
			SetVelocity(AVector::ZERO);
		}
	}

	return true;
}
//----------------------------------------------------------------------------
void InputPushTransformController::OnEvent(Event *event)
{
	if (!Active) return;
	if (!IsPlaying()) return;

	Movable *mov = DynamicCast<Movable>(GetControlledable());
	if (!mov) return;

	if (InputEventSpace::IsEqual(event, InputEventSpace::LevelView))
	{
		mIsPressedValid = false;
	}
	else if (InputEventSpace::IsEqual(event, InputEventSpace::MousePressed) ||
		InputEventSpace::IsEqual(event,InputEventSpace::TouchPressed))
	{
		InputEventData data = event->GetData<InputEventData>();

		mIsPressedValid = true;
		mSampingTiming = 0.0f;

		mPressedTime = (float)Time::GetTimeInSeconds();
		mPressedPos = data.MTPos;

		if (mConvertCallback)
		{
			mConvertCallback(mPressedPos, (int)data.MTPos.X(), (int)data.MTPos.Z());
		}

		mCurTouchPos = mPressedPos;
		mLastTouchPos = mCurTouchPos;
		mLastSamplePos = mCurTouchPos;

		SetVelocity(AVector::ZERO);
	}
	else if (InputEventSpace::IsEqual(event, InputEventSpace::MouseReleased) ||
		InputEventSpace::IsEqual(event, InputEventSpace::TouchReleased))
	{
		InputEventData data = event->GetData<InputEventData>();

		mSampingTiming = 0.0f;

		if (!mIsPressedValid) return;

		mIsPressedValid = false;

		mReleasedTime = (float)Time::GetTimeInSeconds();
		mReleasedPos = data.MTPos;

		if (mConvertCallback)
		{
			mConvertCallback(mPressedPos, (int)data.MTPos.X(), (int)data.MTPos.Z());
		}

		float deltaTime = mReleasedTime - mPressedTime;
		if (deltaTime <= 0.0f) deltaTime = 1.0f;

		//AVector speed = mReleasedPos - mPressedPos;
		//speed /= deltaTime;
		AVector speed = mTouchMoveSpeed;
		float judge = 0.0f;
		if (mLockDir != AVector::ZERO)
		{
			judge = mLockDir.Dot(speed);
		}
		else
		{
			judge = speed.Length();
		}
		judge = Mathf::FAbs(judge);

		if (judge >= mPushTriggerSpeed)
		{
			if (mLockDir != AVector::ZERO)
			{
				speed.X() *= mLockDir.X();
				speed.Y() *= mLockDir.Y();
				speed.Z() *= mLockDir.Z();
			}

			SetReleaseVelocity(speed * judge);
		}

		if (IsSmallTransScope() && GetSmallTransDir() != AVector::ZERO)
		{
			SetReleaseVelocity(AVector::ZERO);
		}
	}
	else if (InputEventSpace::IsEqual(event, InputEventSpace::MouseMoved) ||
		InputEventSpace::IsEqual(event, InputEventSpace::TouchMoved))
	{
		InputEventData data = event->GetData<InputEventData>();

		if (!mIsPressedValid) return;

		mCurTouchPos = data.MTPos;

		if (mConvertCallback)
		{
			mConvertCallback(mPressedPos, (int)data.MTPos.X(), (int)data.MTPos.Z());
		}

		AVector moveDis = mCurTouchPos - mLastTouchPos;

		APoint pos = mov->LocalTransform.GetTranslate();
		pos += moveDis;
		TransScope(pos);
		mov->LocalTransform.SetTranslate(pos);

		mLastTouchPos = mCurTouchPos;
	}
	else if (InputEventSpace::IsEqual(event, InputEventSpace::TouchCancelled))
	{
		mIsPressedValid = false;
	}
}
//----------------------------------------------------------------------------
void SceneNodeCtrl::OnMotion(bool leftDown, RenderStep *renderStep,
	PX2::APoint posNow, PX2::APoint posBefore)
{
	PX2_UNUSED(leftDown);
	PX2_UNUSED(renderStep);

	Renderer *renderer = renderStep->GetRenderer();
	Camera *camera = renderStep->GetCamera();

	// 光标移动更新
	if (DT_NONE == mDragType)
	{
		GeoObjFactory factory;

		DragType dt = GetDragType(renderStep, posNow);
		Movable *ctrlMov = 0;
		Float4 colorYellowAlpha = Float4(1.0f, 1.0f, 0.0f, 0.3f);

		if (DT_X == dt)
		{
			ctrlMov = GetCurrentCtrlX();
			factory.UpdateCtrlColor(renderer, ctrlMov, Float4::YELLOW);
		}
		else if (DT_Y == dt)
		{
			ctrlMov = GetCurrentCtrlY();
			factory.UpdateCtrlColor(renderer, ctrlMov, Float4::YELLOW);
		}
		else if (DT_Z == dt)
		{
			ctrlMov = GetCurrentCtrlZ();
			factory.UpdateCtrlColor(renderer, ctrlMov, Float4::YELLOW);
		}
		else if (DT_XY == dt)
		{
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXY(), colorYellowAlpha);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlYZ(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXZ(), Float4::ZERO);
		}
		else if (DT_YZ == dt)
		{
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlYZ(), colorYellowAlpha);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXY(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXZ(), Float4::ZERO);
		}
		else if (DT_XZ == dt)
		{
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXZ(), colorYellowAlpha);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXY(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlYZ(), Float4::ZERO);
		}
		else if (DT_XYZ == dt)
		{
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXYZ(), Float4::YELLOW);
		}
		else if (DT_NONE == dt)
		{
			factory.UpdateCtrlColor(renderer, GetCurrentCtrlX(), Float4::RED);
			factory.UpdateCtrlColor(renderer, GetCurrentCtrlY(), Float4::GREEN);
			factory.UpdateCtrlColor(renderer, GetCurrentCtrlZ(), Float4::BLUE);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXY(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlYZ(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXZ(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXYZ(), Float4::WHITE);
		}

		if (DT_NONE == dt)
		{
			Event *ent = EditEventSpace::CreateEventX(EditEventSpace::SceneNodeDrag);
			ent->SetData<int>(0);
			EventWorld::GetSingleton().BroadcastingLocalEvent(ent);
		}
		else
		{
			Event *ent = EditEventSpace::CreateEventX(EditEventSpace::SceneNodeDrag);
			ent->SetData<int>(1);
			EventWorld::GetSingleton().BroadcastingLocalEvent(ent);
		}
	}

	if (DT_NONE == mDragType) return;
	else
	{
		Event *ent = EditEventSpace::CreateEventX(EditEventSpace::SceneNodeDrag);
		ent->SetData<int>(1);
		EventWorld::GetSingleton().BroadcastingLocalEvent(ent);
	}

	int numObjs = PX2_SELECTION.GetNumObjects();
	if (0 == numObjs) 
		return;

	// get pickPoint with the plane
	TriMesh *meshHelp = PX2_GR.GetXYPlane();
	if (DT_X == mDragType)
	{
		if (LT_PERSPECTIVE == mLookType || LT_TOP == mLookType)
			meshHelp = PX2_GR.GetXYPlane();
		else if (LT_FRONT == mLookType)
			meshHelp = PX2_GR.GetXZPlane();
	}
	else if (DT_Y == mDragType)
	{
		meshHelp = PX2_GR.GetXYPlane();
	}
	else if (DT_Z == mDragType)
	{
		AVector cameraDir = camera->GetDVector();
		cameraDir.Normalize();
		float dotVal = Mathf::FAbs(cameraDir.Dot(AVector::UNIT_X));
		if (dotVal > 0.7f)
		{
			meshHelp = PX2_GR.GetYZPlane();
		}
		else
		{
			meshHelp = PX2_GR.GetXZPlane();
		}
	}
	else if (DT_XY == mDragType)
	{
		meshHelp = PX2_GR.GetXYPlane();
	}
	else if (DT_YZ == mDragType)
	{
		meshHelp = PX2_GR.GetYZPlane();
	}
	else if (DT_XZ == mDragType)
	{
		meshHelp = PX2_GR.GetXZPlane();
	}
	else if (DT_XYZ == mDragType)
	{
		meshHelp = PX2_GR.GetXYPlane();
	}
	meshHelp->WorldTransform.SetTranslate(GetPosition());

	// get pick ray
	APoint rayOrigin_Now;
	AVector rayDir_Now;
	renderStep->GetPickRay(posNow.X(), posNow.Z(), rayOrigin_Now, rayDir_Now);

	APoint rayOrigin_Before;
	AVector rayDir_Before;
	renderStep->GetPickRay(posBefore.X(), posBefore.Z(), rayOrigin_Before, rayDir_Before);

	// pick
	Picker pickerNow;
	pickerNow.Execute(meshHelp, rayOrigin_Now, rayDir_Now, 0.0f, Mathf::MAX_REAL);
	float lengthNow = pickerNow.GetClosestToZero().T;
	APoint positionNow(rayOrigin_Now + rayDir_Now*lengthNow);

	Picker pickerOrigin;
	pickerOrigin.Execute(meshHelp, rayOrigin_Before, rayDir_Before, 0.0f, Mathf::MAX_REAL);
	float lengthBefore = pickerOrigin.GetClosestToZero().T;
	APoint positionBefore(rayOrigin_Before + rayDir_Before*lengthBefore);

	if (pickerNow.Records.empty() || pickerOrigin.Records.empty()) return;

	AVector transMoved = positionNow - positionBefore;
	AVector transDir = transMoved;
	transDir.Normalize();

	float transValue = 0.0f;
	float transValue1 = 0.0f;
	AVector transVec;
	AVector rolateVec;

	AVector dirX = mDirX;
	AVector dirY = mDirY;
	AVector dirZ = mDirZ;

	if (DT_X == mDragType)
	{
		transValue = transMoved.Dot(dirX);
		transVec = dirX * transValue;

		rolateVec.X() = transMoved.Length() *(1.0f - Mathf::FAbs(transDir.Dot(dirX)));

		AVector vec = transDir.Cross(dirX);
		rolateVec.X() *= Mathf::Sign(vec.Z());
	}
	else if (DT_Y == mDragType)
	{
		transValue = transMoved.Dot(dirY);
		transVec = dirY * transValue;

		rolateVec.Y() = transMoved.Length() *(1.0f - Mathf::FAbs(transDir.Dot(dirY)));

		AVector vec = transDir.Cross(dirY);
		rolateVec.Y() *= Mathf::Sign(vec.Z());
	}
	else if (DT_Z == mDragType)
	{
		transValue = transMoved.Dot(dirZ);
		transVec = dirZ * transValue;

		rolateVec.Z() = transMoved.Length() *(1.0f - Mathf::FAbs(transDir.Dot(dirZ)));

		rolateVec.Z() *= Mathf::Sign(posNow.X() - posBefore.X());
	}
	else if (DT_XY == mDragType)
	{
		transValue = transMoved.Dot(dirX);
		transValue1 = transMoved.Dot(dirY);
		transVec = dirX * transValue + dirY * transValue1;
	}
	else if (DT_YZ == mDragType)
	{
		transValue = transMoved.Dot(dirY);
		transValue1 = transMoved.Dot(dirZ);
		transVec = dirY * transValue + dirZ * transValue1;
	}
	else if (DT_XZ == mDragType)
	{
		transValue = transMoved.Dot(dirX);
		transValue1 = transMoved.Dot(dirZ);
		transVec = dirX * transValue + dirZ * transValue1;
	}
	else if (DT_XYZ == mDragType)
	{
		float transValue0 = Mathf::FAbs(transMoved.Dot(dirX));
		float transValue1 = Mathf::FAbs(transMoved.Dot(dirY));
		float transValue2 = Mathf::FAbs(transMoved.Dot(dirZ));

		float trans = (transValue0 + transValue1 + transValue2) / 3.0f;
		trans *= Mathf::Sign(transMoved.Y());

		transVec = AVector(trans, trans, trans);
	}

	if (CT_SCALE == mCtrlType)
		transVec *= 0.5f;

	HMatrix parentMat = mParentRotateMat.Inverse();
	transVec = parentMat * transVec;

	if (CT_TRANSLATE == mCtrlType)
	{
		PX2_SELECTION.Translate(transVec);

		UpdateCtrlTrans();
	}
	else if (CT_ROLATE == mCtrlType)
	{
		PX2_SELECTION.AddRolate(rolateVec);
	}
	else if (CT_SCALE == mCtrlType)
	{
		if (DT_XYZ == mDragType)
			PX2_SELECTION.AddScale(transVec);
	}

	Object *obj = PX2_SELECTION.GetFirstObject();
	if (obj)
	{
		Event *ent = EditEventSpace::CreateEventX(
			EditEventSpace::ObjectTransformChanged);
		ent->SetData<Object*>(obj);
		EventWorld::GetSingleton().BroadcastingLocalEvent(ent);
	}

	mCtrlsGroup->Update(Time::GetTimeInSeconds(), false);
}