// Init //------------------------------------------------------------------------ public void Init(apEditor editor, object loadKey, apBone targetBone, apMeshGroup targetMeshGroup, REQUEST_TYPE requestType, FUNC_SELECT_LINKED_BONE funcResult) { _editor = editor; _loadKey = loadKey; _funcResult = funcResult; _targetBone = targetBone; _targetMeshGroup = targetMeshGroup; _requestType = requestType; _selectedBoneUnit = null; _boneUnits.Clear(); _boneUnits_Root.Clear(); List <apBone> exclusiveBones = new List <apBone>(); //None 유닛 선택 //Parent에서만 가능 //추가 : IKController에서도 가능 if (_requestType == REQUEST_TYPE.ChangeParent || _requestType == REQUEST_TYPE.SelectIKLookAtControllerEffector || _requestType == REQUEST_TYPE.SelectIKLookAtControllerStartBone || _requestType == REQUEST_TYPE.SelectIKPositionControllerEffector || _requestType == REQUEST_TYPE.Mirror) { BoneUnit nullUnit = new BoneUnit(null, true, false, null, 0); _boneUnits.Add(nullUnit); _boneUnits_Root.Add(nullUnit); } //기존 Rootqnxj 순회하는 방식으로 리스트를 만들되, //"제외"되는 것들을 음영처리하자 //별도의 Unit 필요 //모두 None Unit이 있다. switch (_requestType) { case REQUEST_TYPE.AttachChild: //Parent 중 하나를 Child로 둬선 안된다. (Loop 발생) case REQUEST_TYPE.ChangeParent: { //전체 Bone 중에서 //- 자기 자신 제외 //- Parent 제외 exclusiveBones.Add(_targetBone); if (_targetBone._parentBone != null) { exclusiveBones.Add(_targetBone._parentBone); if (_requestType == REQUEST_TYPE.AttachChild) { //재귀적인 Parent 제외 AddExclusiveBoneRecursive(exclusiveBones, _targetBone._parentBone, false); } } for (int iChild = 0; iChild < _targetBone._childBones.Count; iChild++) { apBone childBone = _targetBone._childBones[iChild]; if (childBone != null) { exclusiveBones.Add(childBone); } if (_requestType == REQUEST_TYPE.ChangeParent) { //재귀적인 Child 제외 AddExclusiveBoneRecursive(exclusiveBones, childBone, true); } } //BoneUnit을 넣자 for (int i = 0; i < _targetMeshGroup._boneList_Root.Count; i++) { AddBoneUnitRecursive(_targetMeshGroup._boneList_Root[i], exclusiveBones, _targetBone, null); } } break; case REQUEST_TYPE.SelectIKTarget: { //<재귀적인 Child 중에서> //-자기 자신 제외 exclusiveBones.Add(_targetBone); for (int iChild = 0; iChild < _targetBone._childBones.Count; iChild++) { apBone childBone = _targetBone._childBones[iChild]; if (childBone != null) { AddBoneUnitRecursive(childBone, exclusiveBones, _targetBone, null); } } } break; case REQUEST_TYPE.SelectIKLookAtControllerEffector: case REQUEST_TYPE.SelectIKPositionControllerEffector: { //IK Controller의 Effector를 결정할때 //-자기 자신 제외 //-자신의 IK Header가 있다면, IK Header의 모든 Child 제외 (무한 움직임을 보일 것이므로) //-자기 바로 위의 Parent 제외 //-자신의 모든 Child 제외 (chain 상관없이) exclusiveBones.Add(_targetBone); if (_targetBone._parentBone != null) { exclusiveBones.Add(_targetBone._parentBone); } if (_targetBone._IKHeaderBone != null) { //IKHeader로부터 모든 Chained은 삭제 exclusiveBones.Add(_targetBone._IKHeaderBone); List <apBone> chainedChildBonesFromIKHeader = _targetBone._IKHeaderBone.GetAllChildBones(); if (chainedChildBonesFromIKHeader != null) { for (int i = 0; i < chainedChildBonesFromIKHeader.Count; i++) { exclusiveBones.Add(chainedChildBonesFromIKHeader[i]); } } } List <apBone> childBones = _targetBone.GetAllChildBones(); if (childBones != null) { for (int i = 0; i < childBones.Count; i++) { if (!exclusiveBones.Contains(childBones[i])) { exclusiveBones.Add(childBones[i]); } } } //그외 모든 본을 추가한다. //BoneUnit을 넣자 for (int i = 0; i < _targetMeshGroup._boneList_Root.Count; i++) { AddBoneUnitRecursive(_targetMeshGroup._boneList_Root[i], exclusiveBones, _targetBone, null); } } break; case REQUEST_TYPE.SelectIKLookAtControllerStartBone: { //IK LookAt Controller의 EndBone을 결정할 때 //-자기 자신을 제외한 Chained의 모든 자식 본들만 선택가능 //List<apBone> childChainedBones = _targetBone.GetAllChainedChildBones(); //if(childChainedBones.Contains(_targetBone)) //{ // childChainedBones.Remove(_targetBone); //} //for (int iChild = 0; iChild < _targetBone._childBones.Count; iChild++) //{ // apBone childBone = _targetBone._childBones[iChild]; // if (childBone != null) // { // AddBoneUnitRecursive(childBone, exclusiveBones, childChainedBones, _targetBone, null); // } //} //수정 : StartBone을 결정한다. //-자기 자신을 제외한 Chained의 모든 부모 본들만 선택 가능 List <apBone> parentChainedBones = _targetBone.GetAllChainedParentBones(); if (parentChainedBones != null) { if (parentChainedBones.Contains(_targetBone)) { parentChainedBones.Remove(_targetBone); } //가장 첫 루트 본에서 BoneUnit을 만들자 apBone parentRootBone = parentChainedBones[parentChainedBones.Count - 1]; //<<리스트 마지막이 가장 Parent이다. if (parentRootBone != null) { AddBoneUnitRecursive(parentRootBone, exclusiveBones, parentChainedBones, _targetBone, null); } } //for (int iChild = 0; iChild < _targetBone._childBones.Count; iChild++) //{ // apBone childBone = _targetBone._childBones[iChild]; // if (childBone != null) // { // AddBoneUnitRecursive(childBone, exclusiveBones, childChainedBones, _targetBone, null); // } //} } break; case REQUEST_TYPE.Mirror: { //Mirror Bone 선택 //자신의 Parent 본들과 자식 본들은 선택 불가. 그 외에는 모두 가능 exclusiveBones.Add(_targetBone); AddExclusiveBoneRecursive(exclusiveBones, _targetBone, true); AddExclusiveBoneRecursive(exclusiveBones, _targetBone, false); //그외 모든 본을 추가한다. //BoneUnit을 넣자 for (int i = 0; i < _targetMeshGroup._boneList_Root.Count; i++) { AddBoneUnitRecursive(_targetMeshGroup._boneList_Root[i], exclusiveBones, _targetBone, null); } } break; } _isSearched = false; _strSearchKeyword = ""; _boneUnits_Root.Sort(delegate(BoneUnit a, BoneUnit b) { if (a._bone == null && b._bone == null) { return(0); } if (a._bone == null) { return(-1); } else if (b._bone == null) { return(1); } return(string.Compare(a._name, b._name)); }); }
// Functions //--------------------------------------------------- /// <summary> /// 선택된 Bone들이 유효한 것들인지 체크한다. /// RefreshSubChainedBones()함수를 포함한다. /// </summary> public void CheckValidation() { if (_effectorBone != null) { //Effector 본이 존재할 때 //Effector 본은 //- 자기 자신 제외 //- 자신의 IK Header가 있다면, IK Header의 모든 Child 제외 //- Parent 제외 //- 자신의 모든 Child 제외 (Chain 상관없이) //위 조건을 만족해야한다. List <apBone> exBones = new List <apBone>(); exBones.Add(_parentBone); if (_parentBone._IKHeaderBone != null) { List <apBone> childBonesOfIKHeader = _parentBone._IKHeaderBone.GetAllChildBones(); if (childBonesOfIKHeader != null) { for (int i = 0; i < childBonesOfIKHeader.Count; i++) { exBones.Add(childBonesOfIKHeader[i]); } } } if (_parentBone._parentBone != null) { exBones.Add(_parentBone._parentBone); } List <apBone> childBones = _parentBone.GetAllChildBones(); if (childBones != null) { for (int i = 0; i < childBones.Count; i++) { exBones.Add(childBones[i]); } } if (exBones.Contains(_effectorBone)) { //선택될 수 없는 EffectBone이다. Debug.LogError("유효하지 않은 Position Controller Effector Bone이다."); _effectorBoneID = -1; _effectorBone = null; } } #region [미사용 코드] //if(_startBone != null) //{ // //EndBone이 존재할 때 // //EndBone 조건 // //-자기 자신을 제외한 Chained의 모든 자식 본들만 선택가능 // //EndBone -> Start Bone으로 변경 // //Start Bone이 Parent Bone 중에 하나여야 하며, Chain으로 연결된 상태여야 한다. // // // List<apBone> parentBones = _parentBone.GetAllChainedParentBones(); // if(parentBones == null) // { // _startBoneID = -1; // _startBone = null; // } // else if(!parentBones.Contains(_startBone)) // { // _startBoneID = -1; // _startBone = null; // } // //TODO // //List<apBone> childChainedBones = _parentBone.GetAllChainedChildBones(); // //if(childChainedBones == null) // //{ // // //리스트가 사라졌다. // // _endBoneID = -1; // // _endBone = null; // //} // //else if(!childChainedBones.Contains(_endBone)) // //{ // // //선택될 수 없는 EndBone이다. // // Debug.LogError("유효하지 않은 Position Controller End Bone ID이다."); // // _endBoneID = -1; // // _endBone = null; // //} //} //RefreshSubChainedBones(); #endregion }