//------------------------------------------------------------------------------------------ // Bone - TransformChanged (Default / Rigging Test / Modifier / AnimClip Modifier) // Rotate 값 직접 수정 (IK Range 확인) //------------------------------------------------------------------------------------------ public void TransformChanged_Rotate__Modifier_Rigging(float angle) { if (Editor.Select.MeshGroup == null || Editor.Select.Bone == null || Editor._boneGUIRenderMode != apEditor.BONE_RENDER_MODE.Render || Editor.Select.Modifier == null //<<Modifier가 null이면 안된다. ) { return; } if (!Editor.Select.IsRigEditTestPosing) { //TestPosing이 허용되지 않았다면 패스 return; } apBone bone = Editor.Select.Bone; apMeshGroup meshGroup = Editor.Select.MeshGroup; //apMeshGroup boneParentMeshGroup = bone._meshGroup;//Bone이 속한 MeshGroup. 다를 수 있다. apModifierBase modifier = Editor.Select.Modifier; //선택한 Modifier if (modifier.ModifierType != apModifierBase.MODIFIER_TYPE.Rigging) { //리깅 Modifier가 아니라면 패스 return; } if (bone._isIKAngleRange) { if (angle < bone._defaultMatrix._angleDeg + bone._IKAngleRange_Lower) { angle = bone._defaultMatrix._angleDeg + bone._IKAngleRange_Lower; } else if (angle > bone._defaultMatrix._angleDeg + bone._IKAngleRange_Upper) { angle = bone._defaultMatrix._angleDeg + bone._IKAngleRange_Upper; } } //직접 대입한다. bone._rigTestMatrix.SetRotate(angle); //bone.MakeWorldMatrix(true);//<<이전 //<BONE_EDIT> //if(bone._meshGroup != null) //{ // bone._meshGroup.UpdateBonesWorldMatrix();//<<변경 : 모든 본 동시에 갱신 //} //>Root MeshGroup에서 변경 if (meshGroup != null) { meshGroup.UpdateBonesWorldMatrix(); } bone.GUIUpdate(true); }
/// <summary> /// MeshGroup 메뉴 + Modifier 중 Rigging Modifier에서만 제어할 수 있다. /// Rigging 테스트를 위해 임시 WorldMatrix를 만들어서 움직인다. /// Rigging Modifier 활성할때마다 변수가 초기화됨. /// 자식 MeshGroup의 Bone도 제어 가능하다 (!) /// IK의 영향을 받지 않는다. /// </summary> /// <param name="deltaAngleW"></param> public void Rotate__Modifier_Rigging(float deltaAngleW, bool isFirstRotate) { if (Editor.Select.MeshGroup == null || Editor.Select.Bone == null || Editor._boneGUIRenderMode != apEditor.BONE_RENDER_MODE.Render || Editor.Select.Modifier == null || //<<Modifier가 null이면 안된다. deltaAngleW == 0.0f ) { return; } if (!Editor.Select.IsRigEditTestPosing) { //TestPosing이 허용되지 않았다면 패스 return; } apBone bone = Editor.Select.Bone; apMeshGroup meshGroup = Editor.Select.MeshGroup; //apMeshGroup boneParentMeshGroup = bone._meshGroup;//Bone이 속한 MeshGroup. 다를 수 있다. apModifierBase modifier = Editor.Select.Modifier; //선택한 Modifier if (modifier.ModifierType != apModifierBase.MODIFIER_TYPE.Rigging) { //리깅 Modifier가 아니라면 패스 return; } //Default Angle은 -180 ~ 180 범위 안에 들어간다. float nextAngle = bone._rigTestMatrix._angleDeg + deltaAngleW; if (nextAngle < -180.0f) { nextAngle += 360.0f; } if (nextAngle > 180.0f) { nextAngle -= 360.0f; } bone._rigTestMatrix.SetRotate(nextAngle); //bone.MakeWorldMatrix(true);//<<이전 : 단일 본 수정 //<BONE_EDIT> //if(bone._meshGroup != null) //{ // bone._meshGroup.UpdateBonesWorldMatrix();//변경 : 전체 본 수정 //} //>Root MeshGroup에서 변경 if (meshGroup != null) { meshGroup.UpdateBonesWorldMatrix(); } bone.GUIUpdate(true); }
/// <summary> /// MeshGroup 메뉴 + Modifier 중 Rigging Modifier에서만 제어할 수 있다. /// Rigging 테스트를 위해 임시 WorldMatrix를 만들어서 움직인다. /// Rigging Modifier 활성할때마다 변수가 초기화됨. /// 자식 MeshGroup의 Bone도 제어 가능하다 (!) /// IK의 영향을 받지 않는다. /// </summary> /// <param name="deltaScaleW"></param> public void Scale__Modifier_Rigging(Vector2 deltaScaleW, bool isFirstScale) { if (Editor.Select.MeshGroup == null || Editor.Select.Bone == null || Editor._boneGUIRenderMode != apEditor.BONE_RENDER_MODE.Render || Editor.Select.Modifier == null || //<<Modifier가 null이면 안된다. deltaScaleW.sqrMagnitude == 0.0f ) { return; } if (!Editor.Select.IsRigEditTestPosing) { //TestPosing이 허용되지 않았다면 패스 return; } apBone bone = Editor.Select.Bone; apMeshGroup meshGroup = Editor.Select.MeshGroup; //apMeshGroup boneParentMeshGroup = bone._meshGroup;//Bone이 속한 MeshGroup. 다를 수 있다. apModifierBase modifier = Editor.Select.Modifier; //선택한 Modifier if (modifier.ModifierType != apModifierBase.MODIFIER_TYPE.Rigging) { //리깅 Modifier가 아니라면 패스 return; } Vector3 prevScale = bone._rigTestMatrix._scale; Vector2 nextScale = new Vector2(prevScale.x + deltaScaleW.x, prevScale.y + deltaScaleW.y); bone._rigTestMatrix.SetScale(nextScale); //bone.MakeWorldMatrix(true);//<<이전 : 단일 본 갱신 //<BONE_EDIT> //if(bone._meshGroup != null) //{ // bone._meshGroup.UpdateBonesWorldMatrix();//<<변경 : 전체 본 갱신 //} //>Root MeshGroup에서 변경 if (meshGroup != null) { meshGroup.UpdateBonesWorldMatrix(); } bone.GUIUpdate(true); }
//------------------------------------------------------------------------------------------ // Bone - TransformChanged (Default / Rigging Test / Modifier / AnimClip Modifier) // Move 값 직접 수정. IK, Local Move 옵션에 따라 무시될 수 있다. // World 값이 아니라 Local 값을 수정한다. Local Move가 Lock이 걸린 경우엔 값이 적용되지 않는다. //------------------------------------------------------------------------------------------ public void TransformChanged_Position__Modifier_Rigging(Vector2 pos) { if (Editor.Select.MeshGroup == null || Editor.Select.Bone == null || Editor._boneGUIRenderMode != apEditor.BONE_RENDER_MODE.Render || Editor.Select.Modifier == null //<<Modifier가 null이면 안된다. ) { return; } apBone bone = Editor.Select.Bone; apMeshGroup meshGroup = Editor.Select.MeshGroup; //apMeshGroup boneParentMeshGroup = bone._meshGroup;//Bone이 속한 MeshGroup. 다를 수 있다. apModifierBase modifier = Editor.Select.Modifier; //선택한 Modifier if (modifier.ModifierType != apModifierBase.MODIFIER_TYPE.Rigging) { //리깅 Modifier가 아니라면 패스 return; } if (!Editor.Select.IsRigEditTestPosing) { //TestPosing이 허용되지 않았다면 패스 return; } //직접 대입하고 끝 bone._rigTestMatrix.SetPos(pos); //bone.MakeWorldMatrix(true);//<<이전 : 단일 본 변경 //<BONE_EDIT> //if(bone._meshGroup != null) //{ // bone._meshGroup.UpdateBonesWorldMatrix();//변경 : 전체 본 갱신 //} //>Root MeshGroup에서 변경 if (meshGroup != null) { meshGroup.UpdateBonesWorldMatrix(); } bone.GUIUpdate(true); }
/// <summary> /// MeshGroup 메뉴 + Modifier 중 Rigging Modifier에서만 제어할 수 있다. /// Rigging 테스트를 위해 임시 WorldMatrix를 만들어서 움직인다. /// Rigging Modifier 활성할때마다 변수가 초기화됨. /// 자식 MeshGroup의 Bone도 제어 가능하다 (!) /// Default와 달리 IK Lock이 걸려있으므로 IK 계산을 해야한다. /// </summary> /// <param name="curMouseGL"></param> /// <param name="curMousePosW"></param> /// <param name="deltaMoveW"></param> /// <param name="btnIndex"></param> /// <param name="isFirstMove"></param> public void Move__Modifier_Rigging(Vector2 curMouseGL, Vector2 curMousePosW, Vector2 deltaMoveW, int btnIndex, bool isFirstMove) { if (Editor.Select.MeshGroup == null || Editor.Select.Bone == null || Editor._boneGUIRenderMode != apEditor.BONE_RENDER_MODE.Render || Editor.Select.Modifier == null || //<<Modifier가 null이면 안된다. !Editor.Controller.IsMouseInGUI(curMouseGL) || deltaMoveW.sqrMagnitude == 0.0f ) { return; } apBone bone = Editor.Select.Bone; apMeshGroup meshGroup = Editor.Select.MeshGroup; //apMeshGroup boneParentMeshGroup = bone._meshGroup;//Bone이 속한 MeshGroup. 다를 수 있다. apModifierBase modifier = Editor.Select.Modifier; //선택한 Modifier if (modifier.ModifierType != apModifierBase.MODIFIER_TYPE.Rigging) { //리깅 Modifier가 아니라면 패스 return; } if (!Editor.Select.IsRigEditTestPosing) { //TestPosing이 허용되지 않았다면 패스 return; } _boneSelectPosW = curMousePosW; //Move로 제어 가능한 경우는 //1. IK Tail일 때 //2. Root Bone일때 (절대값) if (bone._isIKTail) { //Debug.Log("Request IK : " + _boneSelectPosW); float weight = 1.0f; //if (deltaMoveW.sqrMagnitude < 5.0f) //{ // //weight = 0.2f; //} if (bone != _prevSelected_TransformBone || isFirstMove) { _prevSelected_TransformBone = bone; _prevSelected_MousePosW = bone._worldMatrix._pos; } _prevSelected_MousePosW += deltaMoveW; Vector2 bonePosW = _prevSelected_MousePosW; //DeltaPos + 절대 위치 절충 //bool successIK = bone.RequestIK(_boneSelectPosW, weight, !isFirstSelectBone); //bool successIK = bone.RequestIK(_boneSelectPosW, weight, true); bool successIK = bone.RequestIK(bonePosW, weight, true); if (!successIK) { return; } apBone headBone = bone._IKHeaderBone; if (headBone != null) { apBone curBone = bone; //위로 올라가면서 IK 결과값을 Default에 적용하자 while (true) { float deltaAngle = curBone._IKRequestAngleResult; //float nextAngle = curBone._defaultMatrix._angleDeg + deltaAngle; float nextAngle = curBone._rigTestMatrix._angleDeg + deltaAngle; //Rig Test로 할 것 if (nextAngle < -180.0f) { nextAngle += 360.0f; } if (nextAngle > 180.0f) { nextAngle -= 360.0f; } //curBone._defaultMatrix.SetRotate(nextAngle); curBone._rigTestMatrix.SetRotate(nextAngle); curBone._isIKCalculated = false; curBone._IKRequestAngleResult = 0.0f; if (curBone == headBone) { break; } if (curBone._parentBone == null) { break; } curBone = curBone._parentBone; } //마지막으론 World Matrix 갱신 //headBone.MakeWorldMatrix(true);//<<이전 : 단일 본만 업데이트 //<BONE_EDIT> //if(headBone._meshGroup != null) //{ // headBone._meshGroup.UpdateBonesWorldMatrix();//<<변경 : 전체 본 업데이트 (IK 때문) //} //>Root MeshGroup에서 변경 if (meshGroup != null) { meshGroup.UpdateBonesWorldMatrix(); } headBone.GUIUpdate(true); } } else if (bone._parentBone == null || (bone._parentBone._IKNextChainedBone != bone)) { //수정 : Parent가 있지만 IK로 연결 안된 경우 / Parent가 없는 경우 2가지 모두 처리한다. apMatrix parentMatrix = null; if (bone._parentBone == null) { if (bone._renderUnit != null) { //Render Unit의 World Matrix를 참조하여 //로컬 값을 Default로 적용하자 parentMatrix = bone._renderUnit.WorldMatrixWrap; } } else { parentMatrix = bone._parentBone._worldMatrix; } apMatrix localMatrix = bone._localMatrix; apMatrix newWorldMatrix = new apMatrix(bone._worldMatrix); newWorldMatrix.SetPos(newWorldMatrix._pos + deltaMoveW); if (parentMatrix != null) { newWorldMatrix.RInverse(parentMatrix); } newWorldMatrix.Subtract(localMatrix); //이건 Add로 연산된거라 Subtract해야한다. //bone._defaultMatrix.SetPos(newWorldMatrix._pos); bone._rigTestMatrix.SetPos(newWorldMatrix._pos - bone._defaultMatrix._pos); //bone.MakeWorldMatrix(true);//이전 : 단일 본만 업데이트 //<BONE_EDIT> //if(bone._meshGroup != null) //{ // bone._meshGroup.UpdateBonesWorldMatrix();//변경 : 전체 본 업데이트 (IK 때문) //} //>Root MeshGroup에서 변경 if (meshGroup != null) { meshGroup.UpdateBonesWorldMatrix(); } bone.GUIUpdate(true); } }