/// <summary> /// ParamSetGroup 내의 모든 ParamSet에서 MeshGroupTransform을 포함한 ModMesh를 모두 삭제한다. /// 주의 메세지를 꼭 출력할 것 /// </summary> /// <param name="meshGroupTransform"></param> public void RemoveModifierMeshes(apTransform_MeshGroup meshGroupTransform) { apModifierParamSet paramSet = null; for (int i = 0; i < _paramSetList.Count; i++) { paramSet = _paramSetList[i]; int nRemoved = paramSet._meshData.RemoveAll(delegate(apModifiedMesh a) { return(a.IsContains_MeshGroupTransform(_parentModifier._meshGroup, meshGroupTransform)); }); if (nRemoved > 0) { Debug.LogError("Remove ModMesh [RemoveModifierMeshes / MeshGroupTransform] : " + meshGroupTransform._nickName + " / " + nRemoved); } } }
public void RemoveModifierBones(apBone bone) { apModifierParamSet paramSet = null; for (int i = 0; i < _paramSetList.Count; i++) { paramSet = _paramSetList[i]; int nRemoved = paramSet._boneData.RemoveAll(delegate(apModifiedBone a) { return(a._bone == bone); }); if (nRemoved > 0) { Debug.LogError("Remove ModMesh [RemoveModifierBones] : " + bone._name + " / " + nRemoved); } } }
// Functions //------------------------------------------------- public void RemoveInvalidParamSet() { for (int i = 0; i < _paramSetList.Count; i++) { apModifierParamSet paramSet = _paramSetList[i]; int nRemoveModMesh = paramSet._meshData.RemoveAll(delegate(apModifiedMesh a) { if (a._meshGroupOfModifier == null) { return(true); } if (a._meshGroupOfTransform == null) { return(true); } if (a._transform_Mesh == null && a._transform_MeshGroup == null) { return(true); } return(false); }); if (nRemoveModMesh > 0) { Debug.LogError("RemoveInvalidParamSet : " + nRemoveModMesh); } //Debug.LogError("TODO : RemoveInvalidParamSet : 유효하지 않는 Bone을 결정해야한다."); paramSet._boneData.RemoveAll(delegate(apModifiedBone a) { //TODO : 유효하지 않는 Bone을 결정해야한다. return(false); }); } //_paramSetList.RemoveAll(delegate (apModifierParamSet a) //{ // bool isAnyData = false; // if(a._meshData.Count != 0) { isAnyData = true; } // if(a._boneData.Count != 0) { isAnyData = true; } // return !isAnyData;//데이터가 없다면 삭제 //}); }
private bool AddMeshGroupTransformToParamSet(apModifierParamSet paramSet, apTransform_MeshGroup meshGroupTransform) { //if(_parentModifier.ModifiedTargetType != apModifiedMesh.TARGET_TYPE.MeshGroupTransformOnly) //{ // return false; //} if (!_parentModifier.IsTarget_MeshGroupTransform) { return(false); } bool isExist = paramSet._meshData.Exists(delegate(apModifiedMesh a) { return(a.IsContains_MeshGroupTransform(_parentModifier._meshGroup, meshGroupTransform)); }); if (!isExist) { apRenderUnit targetRenderUnit = _parentModifier._meshGroup.GetRenderUnit(meshGroupTransform); if (targetRenderUnit != null) { apMeshGroup parentMeshGroupOfTransform = GetParentMeshGroupOfMeshGroupTransform(meshGroupTransform); if (parentMeshGroupOfTransform == null) { //Parent MeshGroup이 없네염 return(false); } apModifiedMesh modMesh = new apModifiedMesh(); modMesh.Init(_parentModifier._meshGroup._uniqueID, parentMeshGroupOfTransform._uniqueID, _parentModifier.ModifiedValueType); modMesh.SetTarget_MeshGroupTransform(meshGroupTransform._transformUniqueID, meshGroupTransform._meshColor2X_Default, meshGroupTransform._isVisible_Default); //modMesh.Init_MeshGroupTransform(_parentModifier._meshGroup._uniqueID, // meshGroupTransform._transformUniqueID); modMesh.Link_MeshGroupTransform(_parentModifier._meshGroup, parentMeshGroupOfTransform, meshGroupTransform, targetRenderUnit); paramSet._meshData.Add(modMesh); } } return(!isExist); }
public void Init(int uniqueID, int frameIndex) { _uniqueID = uniqueID; _frameIndex = frameIndex; _isLoopAsStart = false; _isLoopAsEnd = false; _loopFrameIndex = -1; //_conSyncValue_Bool = false; _conSyncValue_Int = 0; _conSyncValue_Float = 0.0f; _conSyncValue_Vector2 = Vector2.zero; //_conSyncValue_Vector3 = Vector3.zero; //_conSyncValue_Color = Color.black; _linkedParamSet_Editor = null; _linkedModMesh_Editor = null; _linkedModBone_Editor = null; }
private static object ShowDialog(FUNC_RETARGET_SINGLE_POSE_IMPORT_ANIM funcResult_Anim, FUNC_RETARGET_SINGLE_POSE_IMPORT_MOD funcResult_Mod, apEditor editor, apMeshGroup targetMeshGroup, apModifierBase targetModifier, apModifierParamSet targetParamSet, //<<일반 Modifier에서 작업하는 경우 apAnimClip targetAnimClip, apAnimTimeline targetAnimTimeline, int targetFrame //<<애니메이션에서 Pose를 여는 경우 ) { CloseDialog(); if (editor == null || editor._portrait == null || editor._portrait._controller == null) { return(null); } EditorWindow curWindow = EditorWindow.GetWindow(typeof(apDialog_RetargetSinglePoseImport), true, "Import Pose", true); apDialog_RetargetSinglePoseImport curTool = curWindow as apDialog_RetargetSinglePoseImport; object loadKey = new object(); if (curTool != null && curTool != s_window) { int width = 500; int height = 700; s_window = curTool; s_window.position = new Rect((editor.position.xMin + editor.position.xMax) / 2 - (width / 2), (editor.position.yMin + editor.position.yMax) / 2 - (height / 2), width, height); s_window.Init(funcResult_Anim, funcResult_Mod, editor, loadKey, targetMeshGroup, targetModifier, targetParamSet, targetAnimClip, targetAnimTimeline, targetFrame); return(loadKey); } else { return(null); } }
public bool RefreshSync() { if (_syncTransform_Mesh == null) { _syncTransform_Mesh = new List <apTransform_Mesh>(); } _syncTransform_Mesh.Clear(); if (_syncTransform_MeshGroup == null) { _syncTransform_MeshGroup = new List <apTransform_MeshGroup>(); } _syncTransform_MeshGroup.Clear(); if (_syncBone == null) { _syncBone = new List <apBone>(); } _syncBone.Clear(); //한번이라도 등장한 MeshTransform / MeshGroup Transform을 찾자 for (int i = 0; i < _paramSetList.Count; i++) { apModifierParamSet paramSet = _paramSetList[i]; for (int iModMesh = 0; iModMesh < paramSet._meshData.Count; iModMesh++) { apModifiedMesh modMesh = paramSet._meshData[iModMesh]; if (modMesh._transform_Mesh != null) { //수정 4.1 : Mesh가 없는 MeshTransform if (modMesh._transform_Mesh._mesh == null) { //Debug.Log("AnyPortrait : Mesh of [" + modMesh._transform_Mesh._nickName + "] is removed. Please check it."); } else { if (!_syncTransform_Mesh.Contains(modMesh._transform_Mesh)) { _syncTransform_Mesh.Add(modMesh._transform_Mesh); } } //이전 코드 //if (!_syncTransform_Mesh.Contains(modMesh._transform_Mesh)) //{ // _syncTransform_Mesh.Add(modMesh._transform_Mesh); //} } if (modMesh._transform_MeshGroup != null) { if (!_syncTransform_MeshGroup.Contains(modMesh._transform_MeshGroup)) { _syncTransform_MeshGroup.Add(modMesh._transform_MeshGroup); } } } for (int iModBone = 0; iModBone < paramSet._boneData.Count; iModBone++) { apModifiedBone modBone = paramSet._boneData[iModBone]; if (modBone._bone != null) { //>> 이건 Bone Set이 필요없다. if (modBone._meshGroup_Bone != null && modBone._meshGroup_Bone._boneList_All.Contains(modBone._bone) //해당 MeshGroup에 Bone이 존재하는가. ) { if (!_syncBone.Contains(modBone._bone)) { _syncBone.Add(modBone._bone); } } else { //Modifier로 등록되었지만 Bone이 삭제되었다면 여기로 들어온다. //Sync가 안됨 } } } } //동기화 전용 Sync Transform을 모든 ParamSet에 넣자 bool isAnyChanged = false; for (int iSync = 0; iSync < _syncTransform_Mesh.Count; iSync++) { apTransform_Mesh meshTransform = _syncTransform_Mesh[iSync]; //bool isAdd = _parentModifier.AddMeshTransformToAllParamSet(_parentModifier._meshGroup, meshTransform, false); for (int iParamSet = 0; iParamSet < _paramSetList.Count; iParamSet++) { bool isAdd = AddMeshTransformToParamSet(_paramSetList[iParamSet], meshTransform); if (isAdd) { isAnyChanged = true; } } } for (int iSync = 0; iSync < _syncTransform_MeshGroup.Count; iSync++) { apTransform_MeshGroup meshGroupTransform = _syncTransform_MeshGroup[iSync]; for (int iParamSet = 0; iParamSet < _paramSetList.Count; iParamSet++) { bool isAdd = AddMeshGroupTransformToParamSet(_paramSetList[iParamSet], meshGroupTransform); //bool isAdd = _parentModifier.AddMeshGroupTransformToAllParamSet(_parentModifier._meshGroup, meshGroupTransform, false); if (isAdd) { isAnyChanged = true; } } } for (int iSync = 0; iSync < _syncBone.Count; iSync++) { apBone bone = _syncBone[iSync]; apTransform_MeshGroup meshGroupTransform = null; if (_parentModifier._meshGroup == bone._meshGroup) { meshGroupTransform = _parentModifier._meshGroup._rootMeshGroupTransform; } else { meshGroupTransform = _parentModifier._meshGroup.FindChildMeshGroupTransform(bone._meshGroup); } for (int iParamSet = 0; iParamSet < _paramSetList.Count; iParamSet++) { //이전 //bool isAdd = AddBoneToParamSet(_paramSetList[iParamSet], bone._meshGroup._rootMeshGroupTransform, bone); //변경 : ChildMeshGroup의 Root MGTF로 설정하는 코드는 잘못되었다. bool isAdd = AddBoneToParamSet(_paramSetList[iParamSet], meshGroupTransform, bone); if (isAdd) { isAnyChanged = true; } } } //추가 : Sync시 WeightedVertex도 같이 처리해주자 // 동기화 안된건 자동 삭제 for (int i = 0; i < _calculatedWeightedVertexList.Count; i++) { _calculatedWeightedVertexList[i]._isSync = false; } for (int iSync = 0; iSync < _syncTransform_Mesh.Count; iSync++) { apTransform_Mesh meshTransform = _syncTransform_Mesh[iSync]; apModifierParamSetGroupVertWeight existWV = _calculatedWeightedVertexList.Find(delegate(apModifierParamSetGroupVertWeight a) { return(a._meshTransform_ID == meshTransform._transformUniqueID); }); if (existWV != null) { existWV._isSync = true; existWV.LinkMeshTransform(meshTransform); } else { //없다. 새로 만들자 apModifierParamSetGroupVertWeight newVW = new apModifierParamSetGroupVertWeight(meshTransform); newVW._isSync = true; _calculatedWeightedVertexList.Add(newVW); } } //동기화 되지 않은건 지운다. _calculatedWeightedVertexList.RemoveAll(delegate(apModifierParamSetGroupVertWeight a) { return(!a._isSync); }); return(isAnyChanged); }
//public void ClearParamSet() //{ // _paramSetList.Clear(); //} //public void AddParamSet(apModifierParamSet paramSet) //{ // _paramSetList.Add(paramSet); // RefreshSync(); //} public void SortParamSet() { if (_keyControlParam != null) { _paramSetList.Sort(delegate(apModifierParamSet a, apModifierParamSet b) { switch (_keyControlParam._valueType) { //case apControlParam.TYPE.Bool: // return 0; case apControlParam.TYPE.Int: return(a._conSyncValue_Int - b._conSyncValue_Int); case apControlParam.TYPE.Float: return((int)((a._conSyncValue_Float - b._conSyncValue_Float) * 1000.0f)); case apControlParam.TYPE.Vector2: if (Mathf.Abs(a._conSyncValue_Vector2.y - b._conSyncValue_Vector2.y) < 0.001f) { return((int)((a._conSyncValue_Vector2.x - b._conSyncValue_Vector2.x) * 1000.0f)); } else { return((int)((a._conSyncValue_Vector2.y - b._conSyncValue_Vector2.y) * 1000.0f)); } //case apControlParam.TYPE.Vector3: // if (Mathf.Abs(a._conSyncValue_Vector3.z - b._conSyncValue_Vector3.z) < 0.001f) // { // if (Mathf.Abs(a._conSyncValue_Vector3.y - b._conSyncValue_Vector3.y) < 0.001f) // { // return (int)((a._conSyncValue_Vector3.x - b._conSyncValue_Vector3.x) * 1000.0f); // } // else // { // return (int)((a._conSyncValue_Vector3.y - b._conSyncValue_Vector3.y) * 1000.0f); // } // } // else // { // return (int)((a._conSyncValue_Vector3.z - b._conSyncValue_Vector3.z) * 1000.0f); // } //case apControlParam.TYPE.Color: // return 0; } return(0); }); //추가 : ParamSet의 Dist 보간을 위해서 "보간 영역"을 설정해줘야 한다. float rangeBias = 1000.0f; for (int iParam = 0; iParam < _paramSetList.Count; iParam++) { apModifierParamSet paramSet = _paramSetList[iParam]; //일단 값 초기화 (영역 전체로 동기화를 하고 다른 값이 있으면 줄인다.) //if (_keyControlParam._isRange) //{ // switch (_keyControlParam._valueType) // { // case apControlParam.TYPE.Int: // paramSet._conSyncValueRange_Under = new Vector3(_keyControlParam._int_Min, 0.0f, 0.0f); // paramSet._conSyncValueRange_Over = new Vector3(_keyControlParam._int_Max, 0.0f, 0.0f); // break; // case apControlParam.TYPE.Float: // paramSet._conSyncValueRange_Under = new Vector3(_keyControlParam._float_Min, 0.0f, 0.0f); // paramSet._conSyncValueRange_Over = new Vector3(_keyControlParam._float_Max, 0.0f, 0.0f); // break; // case apControlParam.TYPE.Vector2: // paramSet._conSyncValueRange_Under = new Vector3(_keyControlParam._vec2_Min.x, _keyControlParam._vec2_Min.y, 0.0f); // paramSet._conSyncValueRange_Over = new Vector3(_keyControlParam._vec2_Max.x, _keyControlParam._vec2_Max.y, 0.0f); // break; // case apControlParam.TYPE.Vector3: // paramSet._conSyncValueRange_Under = _keyControlParam._vec3_Min; // paramSet._conSyncValueRange_Over = _keyControlParam._vec3_Max; // break; // } // //Bias를 가감해줘야 이후 Weight 계산시 Range 경계에서 적절한 값을 가진다. // paramSet._conSyncValueRange_Under -= Vector3.one * rangeBias; // paramSet._conSyncValueRange_Over += Vector3.one * rangeBias; //} //else //{ // paramSet._conSyncValueRange_Under = -(Vector3.one * 1000000.0f); // paramSet._conSyncValueRange_Over = (Vector3.one * 1000000.0f); //} switch (_keyControlParam._valueType) { case apControlParam.TYPE.Int: paramSet._conSyncValueRange_Under = new Vector3(_keyControlParam._int_Min, 0.0f, 0.0f); paramSet._conSyncValueRange_Over = new Vector3(_keyControlParam._int_Max, 0.0f, 0.0f); break; case apControlParam.TYPE.Float: paramSet._conSyncValueRange_Under = new Vector3(_keyControlParam._float_Min, 0.0f, 0.0f); paramSet._conSyncValueRange_Over = new Vector3(_keyControlParam._float_Max, 0.0f, 0.0f); break; case apControlParam.TYPE.Vector2: paramSet._conSyncValueRange_Under = new Vector3(_keyControlParam._vec2_Min.x, _keyControlParam._vec2_Min.y, 0.0f); paramSet._conSyncValueRange_Over = new Vector3(_keyControlParam._vec2_Max.x, _keyControlParam._vec2_Max.y, 0.0f); break; } //Bias를 가감해줘야 이후 Weight 계산시 Range 경계에서 적절한 값을 가진다. paramSet._conSyncValueRange_Under -= Vector2.one * rangeBias; paramSet._conSyncValueRange_Over += Vector2.one * rangeBias; //다른 값과 비교하여 Range를 정한다. //영역을 축소하는 방향으로 for (int iNext = 0; iNext < _paramSetList.Count; iNext++) { apModifierParamSet nextParamSet = _paramSetList[iNext]; if (nextParamSet == paramSet) { continue; } switch (_keyControlParam._valueType) { case apControlParam.TYPE.Int: { int nextValue_Int = nextParamSet._conSyncValue_Int; if (nextValue_Int <= paramSet._conSyncValue_Int) { //값이 작은 경우 + 영역보다 값이 큰 경우 if (nextValue_Int > paramSet._conSyncValueRange_Under.x) { paramSet._conSyncValueRange_Under.x = nextValue_Int; } } if (nextValue_Int >= paramSet._conSyncValue_Int) { //값이 큰 경우 + 영역보다 값이 작은 경우 if (nextValue_Int < paramSet._conSyncValueRange_Over.x) { paramSet._conSyncValueRange_Over.x = nextValue_Int; } } } break; case apControlParam.TYPE.Float: { float nextValue_float = nextParamSet._conSyncValue_Float; if (nextValue_float <= paramSet._conSyncValue_Float) { //값이 작은 경우 + 영역보다 값이 큰 경우 if (nextValue_float > paramSet._conSyncValueRange_Under.x) { paramSet._conSyncValueRange_Under.x = nextValue_float; } } if (nextValue_float >= paramSet._conSyncValue_Float) { //값이 큰 경우 + 영역보다 값이 작은 경우 if (nextValue_float < paramSet._conSyncValueRange_Over.x) { paramSet._conSyncValueRange_Over.x = nextValue_float; } } } break; case apControlParam.TYPE.Vector2: { Vector2 nextValue_Vec2 = nextParamSet._conSyncValue_Vector2; //X, Y에 대해서 값을 각각 처리한다. //X에 대해서 영역 처리할 땐 -> Y가 같은 경우에만 //Y에 대해서 영역 처리할 땐 -> X가 같은 경우에만 bool isXSame = Mathf.Abs(nextValue_Vec2.x - paramSet._conSyncValue_Vector2.x) < 0.01f; bool isYSame = Mathf.Abs(nextValue_Vec2.y - paramSet._conSyncValue_Vector2.y) < 0.01f; //Under - X if (nextValue_Vec2.x <= paramSet._conSyncValue_Vector2.x && isYSame) { //값이 작은 경우 + 영역보다 값이 큰 경우 if (nextValue_Vec2.x > paramSet._conSyncValueRange_Under.x) { paramSet._conSyncValueRange_Under.x = nextValue_Vec2.x; } } //Under - Y if (nextValue_Vec2.y <= paramSet._conSyncValue_Vector2.y && isXSame) { //값이 작은 경우 + 영역보다 값이 큰 경우 if (nextValue_Vec2.y > paramSet._conSyncValueRange_Under.y) { paramSet._conSyncValueRange_Under.y = nextValue_Vec2.y; } } //Over - X if (nextValue_Vec2.x >= paramSet._conSyncValue_Vector2.x && isYSame) { //값이 큰 경우 + 영역보다 값이 작은 경우 if (nextValue_Vec2.x < paramSet._conSyncValueRange_Over.x) { paramSet._conSyncValueRange_Over.x = nextValue_Vec2.x; } } //Over - Y if (nextValue_Vec2.y >= paramSet._conSyncValue_Vector2.y && isXSame) { //값이 큰 경우 + 영역보다 값이 작은 경우 if (nextValue_Vec2.y < paramSet._conSyncValueRange_Over.y) { paramSet._conSyncValueRange_Over.y = nextValue_Vec2.y; } } } break; //case apControlParam.TYPE.Vector3: // { // Vector3 nextValue_Vec3 = nextParamSet._conSyncValue_Vector3; // //X, Y에 대해서 값을 각각 처리한다. // //X에 대해서 영역 처리할 땐 -> Y가 같은 경우에만 // //Y에 대해서 영역 처리할 땐 -> X가 같은 경우에만 // //Z는 자유롭게 // bool isXSame = Mathf.Abs(nextValue_Vec3.x - paramSet._conSyncValue_Vector3.x) < 0.01f; // bool isYSame = Mathf.Abs(nextValue_Vec3.y - paramSet._conSyncValue_Vector3.y) < 0.01f; // //Under - X // if(nextValue_Vec3.x <= paramSet._conSyncValue_Vector3.x && isYSame) // { // //값이 작은 경우 + 영역보다 값이 큰 경우 // if(nextValue_Vec3.x > paramSet._conSyncValueRange_Under.x) // { // paramSet._conSyncValueRange_Under.x = nextValue_Vec3.x; // } // } // //Under - Y // if(nextValue_Vec3.y <= paramSet._conSyncValue_Vector3.y && isXSame) // { // //값이 작은 경우 + 영역보다 값이 큰 경우 // if(nextValue_Vec3.y > paramSet._conSyncValueRange_Under.y) // { // paramSet._conSyncValueRange_Under.y = nextValue_Vec3.y; // } // } // //Under - Z // if(nextValue_Vec3.z <= paramSet._conSyncValue_Vector3.z) // { // //값이 작은 경우 + 영역보다 값이 큰 경우 // if(nextValue_Vec3.z > paramSet._conSyncValueRange_Under.z) // { // paramSet._conSyncValueRange_Under.z = nextValue_Vec3.z; // } // } // //Over - X // if(nextValue_Vec3.x >= paramSet._conSyncValue_Vector3.x && isYSame) // { // //값이 큰 경우 + 영역보다 값이 작은 경우 // if(nextValue_Vec3.x < paramSet._conSyncValueRange_Over.x) // { // paramSet._conSyncValueRange_Over.x = nextValue_Vec3.x; // } // } // //Over - Y // if(nextValue_Vec3.y >= paramSet._conSyncValue_Vector3.y && isXSame) // { // //값이 큰 경우 + 영역보다 값이 작은 경우 // if(nextValue_Vec3.y < paramSet._conSyncValueRange_Over.y) // { // paramSet._conSyncValueRange_Over.y = nextValue_Vec3.y; // } // } // //Over - Z // if(nextValue_Vec3.z >= paramSet._conSyncValue_Vector3.z) // { // //값이 큰 경우 + 영역보다 값이 작은 경우 // if(nextValue_Vec3.z < paramSet._conSyncValueRange_Over.z) // { // paramSet._conSyncValueRange_Over.z = nextValue_Vec3.z; // } // } // } // break; } } } } }
public void Bake(apPortrait portrait, apOptModifierUnitBase parentModifier, apModifierParamSetGroup srcParamSetGroup, bool isAnimated) { _portrait = portrait; _parentModifier = parentModifier; _syncTarget = srcParamSetGroup._syncTarget; //_keyControlParamName = srcParamSetGroup._keyControlParamName; _keyControlParamID = srcParamSetGroup._keyControlParamID; _keyControlParam = null; //<<이건 링크로 해결하자 //애니메이션 값도 넣어주자 _keyAnimClipID = srcParamSetGroup._keyAnimClipID; _keyAnimTimelineID = srcParamSetGroup._keyAnimTimelineID; _keyAnimTimelineLayerID = srcParamSetGroup._keyAnimTimelineLayerID; _keyAnimClip = null; _keyAnimTimeline = null; _keyAnimTimelineLayer = null; _paramSetList.Clear(); for (int i = 0; i < srcParamSetGroup._paramSetList.Count; i++) { apModifierParamSet srcParamSet = srcParamSetGroup._paramSetList[i]; apOptParamSet optParamSet = new apOptParamSet(); optParamSet.LinkParamSetGroup(this, portrait); optParamSet.BakeModifierParamSet(srcParamSet, portrait); _paramSetList.Add(optParamSet); } _isEnabled = srcParamSetGroup._isEnabled; _layerIndex = srcParamSetGroup._layerIndex; _layerWeight = srcParamSetGroup._layerWeight; if (!isAnimated) { _blendMethod = srcParamSetGroup._blendMethod; } else { _blendMethod = apModifierParamSetGroup.BLEND_METHOD.Additive; //<<애니메이션에서는 Additive 강제 } _isColorPropertyEnabled = srcParamSetGroup._isColorPropertyEnabled; //<<추가. _calculatedWeightedVertexList.Clear(); for (int i = 0; i < srcParamSetGroup._calculatedWeightedVertexList.Count; i++) { apModifierParamSetGroupVertWeight srcWV = srcParamSetGroup._calculatedWeightedVertexList[i]; apOptParamSetGroupVertWeight optWV = new apOptParamSetGroupVertWeight(); optWV.Bake(srcWV); optWV.Link(portrait.GetOptTransform(optWV._meshTransform_ID)); //OptTransform을 연결한다. _calculatedWeightedVertexList.Add(optWV); } LinkPortrait(portrait, parentModifier); }
public void BakeModifierParamSet(apModifierParamSet srcParamSet, apPortrait portrait) { //switch (srcParamSet._syncTarget) //{ // case apModifierParamSet.SYNC_TARGET.Static: // _syncTarget = SYNC_TARGET.Static; // break; // case apModifierParamSet.SYNC_TARGET.Controller: // _syncTarget = SYNC_TARGET.Controller; // break; // case apModifierParamSet.SYNC_TARGET.KeyFrame: // _syncTarget = SYNC_TARGET.KeyFrame; // break; // default: // Debug.LogError("연동 에러 : ParamSet에 정의되지 않은 타입 : " + srcParamSet._syncTarget); // break; //} //_controlKeyName = srcParamSet._controlKeyName; //_conSyncValue_Bool = srcParamSet._conSyncValue_Bool; _conSyncValue_Int = srcParamSet._conSyncValue_Int; _conSyncValue_Float = srcParamSet._conSyncValue_Float; _conSyncValue_Vector2 = srcParamSet._conSyncValue_Vector2; //_conSyncValue_Vector3 = srcParamSet._conSyncValue_Vector3; //_conSyncValue_Color = srcParamSet._conSyncValue_Color; _keyframeUniqueID = srcParamSet._keyframeUniqueID; _syncKeyframe = null; _overlapWeight = srcParamSet._overlapWeight; //OverlapWeight를 집어넣자 _meshData.Clear(); _boneData.Clear(); //SrcModifier ParamSet의 ModMesh, ModBone을 Bake해주자 //Debug.LogError("TODO : Bone 데이터 연동"); for (int i = 0; i < srcParamSet._meshData.Count; i++) { apModifiedMesh srcModMesh = srcParamSet._meshData[i]; apOptModifiedMesh optModMesh = new apOptModifiedMesh(); bool isResult = optModMesh.Bake(srcModMesh, portrait); if (isResult) { _meshData.Add(optModMesh); } } //추가 : ModBone for (int i = 0; i < srcParamSet._boneData.Count; i++) { apModifiedBone srcModBone = srcParamSet._boneData[i]; apOptModifiedBone optModBone = new apOptModifiedBone(); bool isResult = optModBone.Bake(srcModBone, portrait); if (isResult) { _boneData.Add(optModBone); } } }
public void LinkModBone_Editor(apModifierParamSet paramSet, apModifiedBone modBone) { _linkedParamSet_Editor = paramSet; _linkedModMesh_Editor = null; _linkedModBone_Editor = modBone; }
/// <summary> /// ParamSet을 받아서 SubList와 연동한다. /// </summary> /// <param name="paramSet"></param> /// <param name="modifiedValue"></param> public void AddParamSetAndModifiedValue(apModifierParamSetGroup paramSetGroup, apModifierParamSet paramSet, apModifiedMesh modifiedMesh, apModifiedBone modifiedBone) { ParamKeyValueSet existSet = GetParamKeyValue(paramSet); if (existSet != null) { return; } //수정 : ModifiedBone을 넣어주자 //새로운 KeyValueSet을 만들어서 리스트에 추가하자 ParamKeyValueSet newKeyValueSet = null; if (modifiedMesh != null) { //ModMesh를 등록하는 경우 newKeyValueSet = new ParamKeyValueSet(paramSetGroup, paramSet, modifiedMesh); } else if (modifiedBone != null) { //ModBone을 등록하는 경우 newKeyValueSet = new ParamKeyValueSet(paramSetGroup, paramSet, modifiedBone); } _paramKeyValues.Add(newKeyValueSet); //Debug.LogError("Cur Param Key Value : " + _paramKeyValues.Count); apCalculatedResultParamSubList targetSubList = null; //같이 묶여서 작업할 SubList가 있는가 apCalculatedResultParamSubList existSubList = _subParamKeyValueList.Find(delegate(apCalculatedResultParamSubList a) { //return a._controlParam == paramSetGroup._keyControlParam; return(a._keyParamSetGroup == paramSetGroup); }); if (existSubList != null) { targetSubList = existSubList; } else { targetSubList = new apCalculatedResultParamSubList(this); targetSubList.SetParamSetGroup(paramSetGroup); //targetSubList.SetControlParam(paramSetGroup._keyControlParam); _subParamKeyValueList.Add(targetSubList); //Debug.LogError("AddParamSetAndModifiedMesh : Add New SubList"); } #region [미사용 코드] //switch (paramSetGroup._syncTarget) //{ // case apModifierParamSetGroup.SYNC_TARGET.Controller: // { // if (paramSetGroup._keyControlParam != null) // { // //같이 묶여서 작업할 SubList가 있는가 // apCalculatedResultParamSubList existSubList = _subParamKeyValueList.Find(delegate (apCalculatedResultParamSubList a) // { // return a._controlParam == paramSetGroup._keyControlParam; // }); // if (existSubList != null) // { // targetSubList = existSubList; // } // else // { // targetSubList = new apCalculatedResultParamSubList(this); // targetSubList.SetParamSetGroup(paramSetGroup); // //targetSubList.SetControlParam(paramSetGroup._keyControlParam); // _subParamKeyValueList.Add(targetSubList); // } // } // } // break; // case apModifierParamSetGroup.SYNC_TARGET.KeyFrame: // { // //...TODO // Debug.LogError("TODO : KeyFrame 타입의 CalculateResultParam의 SubList 처리할 것"); // //?? // } // break; // case apModifierParamSetGroup.SYNC_TARGET.Static: // { // //Static은 1개만 있다. // if(_subParamKeyValueList.Count == 0) // { // //새로 만들자. // targetSubList = new apCalculatedResultParamSubList(this); // targetSubList.SetStatic(); // _subParamKeyValueList.Add(targetSubList); // } // else // { // //있는거 사용하자 // targetSubList = _subParamKeyValueList[0]; // } // } // break; //} #endregion //해당 SubList에 위에서 만든 KeyValueSet을 추가하자 if (targetSubList != null) { //ParamKeyValueSet을 추가하자 targetSubList.AddParamKeyValueSet(newKeyValueSet); } }
public static object ShowDialog(FUNC_RETARGET_SINGLE_POSE_IMPORT_MOD funcResult_Mod, apEditor editor, apMeshGroup targetMeshGroup, apModifierBase targetModifier, apModifierParamSet targetParamSet) { return(ShowDialog(null, funcResult_Mod, editor, targetMeshGroup, targetModifier, targetParamSet, null, null, -1)); }
public bool RefreshSync() { if (_syncTransform_Mesh == null) { _syncTransform_Mesh = new List <apTransform_Mesh>(); } _syncTransform_Mesh.Clear(); if (_syncTransform_MeshGroup == null) { _syncTransform_MeshGroup = new List <apTransform_MeshGroup>(); } _syncTransform_MeshGroup.Clear(); if (_syncBone == null) { _syncBone = new List <apBone>(); } _syncBone.Clear(); //한번이라도 등장한 MeshTransform / MeshGroup Transform을 찾자 for (int i = 0; i < _paramSetList.Count; i++) { apModifierParamSet paramSet = _paramSetList[i]; for (int iModMesh = 0; iModMesh < paramSet._meshData.Count; iModMesh++) { apModifiedMesh modMesh = paramSet._meshData[iModMesh]; if (modMesh._transform_Mesh != null) { if (!_syncTransform_Mesh.Contains(modMesh._transform_Mesh)) { _syncTransform_Mesh.Add(modMesh._transform_Mesh); } } if (modMesh._transform_MeshGroup != null) { if (!_syncTransform_MeshGroup.Contains(modMesh._transform_MeshGroup)) { _syncTransform_MeshGroup.Add(modMesh._transform_MeshGroup); } } } for (int iModBone = 0; iModBone < paramSet._boneData.Count; iModBone++) { apModifiedBone modBone = paramSet._boneData[iModBone]; if (modBone._bone != null) { if (modBone._meshGroup_Bone != null && modBone._meshGroup_Bone._boneList_All.Contains(modBone._bone)) { if (!_syncBone.Contains(modBone._bone)) { _syncBone.Add(modBone._bone); } } else { //Modifier로 등록되었지만 Bone이 삭제되었다면 여기로 들어온다. //Sync가 안됨 } } } } //동기화 전용 Sync Transform을 모든 ParamSet에 넣자 bool isAnyChanged = false; for (int iSync = 0; iSync < _syncTransform_Mesh.Count; iSync++) { apTransform_Mesh meshTransform = _syncTransform_Mesh[iSync]; //bool isAdd = _parentModifier.AddMeshTransformToAllParamSet(_parentModifier._meshGroup, meshTransform, false); for (int iParamSet = 0; iParamSet < _paramSetList.Count; iParamSet++) { bool isAdd = AddMeshTransformToParamSet(_paramSetList[iParamSet], meshTransform); if (isAdd) { isAnyChanged = true; } } } for (int iSync = 0; iSync < _syncTransform_MeshGroup.Count; iSync++) { apTransform_MeshGroup meshGroupTransform = _syncTransform_MeshGroup[iSync]; for (int iParamSet = 0; iParamSet < _paramSetList.Count; iParamSet++) { bool isAdd = AddMeshGroupTransformToParamSet(_paramSetList[iParamSet], meshGroupTransform); //bool isAdd = _parentModifier.AddMeshGroupTransformToAllParamSet(_parentModifier._meshGroup, meshGroupTransform, false); if (isAdd) { isAnyChanged = true; } } } for (int iSync = 0; iSync < _syncBone.Count; iSync++) { apBone bone = _syncBone[iSync]; for (int iParamSet = 0; iParamSet < _paramSetList.Count; iParamSet++) { bool isAdd = AddBoneToParamSet(_paramSetList[iParamSet], bone._meshGroup._rootMeshGroupTransform, bone); if (isAdd) { isAnyChanged = true; } } } //추가 : Sync시 WeightedVertex도 같이 처리해주자 // 동기화 안된건 자동 삭제 for (int i = 0; i < _calculatedWeightedVertexList.Count; i++) { _calculatedWeightedVertexList[i]._isSync = false; } for (int iSync = 0; iSync < _syncTransform_Mesh.Count; iSync++) { apTransform_Mesh meshTransform = _syncTransform_Mesh[iSync]; apModifierParamSetGroupVertWeight existWV = _calculatedWeightedVertexList.Find(delegate(apModifierParamSetGroupVertWeight a) { return(a._meshTransform_ID == meshTransform._transformUniqueID); }); if (existWV != null) { existWV._isSync = true; existWV.LinkMeshTransform(meshTransform); } else { //없다. 새로 만들자 apModifierParamSetGroupVertWeight newVW = new apModifierParamSetGroupVertWeight(meshTransform); newVW._isSync = true; _calculatedWeightedVertexList.Add(newVW); } } //동기화 되지 않은건 지운다. _calculatedWeightedVertexList.RemoveAll(delegate(apModifierParamSetGroupVertWeight a) { return(!a._isSync); }); return(isAnyChanged); }
// 중요! //Mesh Transform / MeshGroup Transform을 각각의 ParamSet에 넣어준다. //Modifier 조건에 맞게 처리한다. private bool AddMeshTransformToParamSet(apModifierParamSet paramSet, apTransform_Mesh meshTransform) { //if(_parentModifier.ModifiedTargetType != apModifiedMesh.TARGET_TYPE.MeshTransformOnly && // _parentModifier.ModifiedTargetType != apModifiedMesh.TARGET_TYPE.VertexWithMeshTransform) //{ // //추가할 수 없다. // return false; //} if (!_parentModifier.IsTarget_MeshTransform) { return(false); } bool isExist = paramSet._meshData.Exists(delegate(apModifiedMesh a) { return(a.IsContains_MeshTransform(_parentModifier._meshGroup, meshTransform, meshTransform._mesh)); }); if (!isExist) { apRenderUnit targetRenderUnit = _parentModifier._meshGroup.GetRenderUnit(meshTransform); if (targetRenderUnit != null) { apMeshGroup parentMeshGroupOfTransform = GetParentMeshGroupOfMeshTransform(meshTransform); if (parentMeshGroupOfTransform == null) { //Parent MeshGroup이 없네염 return(false); } apModifiedMesh modMesh = new apModifiedMesh(); modMesh.Init(_parentModifier._meshGroup._uniqueID, parentMeshGroupOfTransform._uniqueID, _parentModifier.ModifiedValueType); modMesh.SetTarget_MeshTransform(meshTransform._transformUniqueID, meshTransform._mesh._uniqueID, meshTransform._meshColor2X_Default, meshTransform._isVisible_Default); modMesh.Link_MeshTransform(_parentModifier._meshGroup, parentMeshGroupOfTransform, meshTransform, targetRenderUnit, _portrait); #region [미사용 코드] 확장성 있는 코드로 변경했다. //if (_parentModifier.ModifiedTargetType == apModifiedMesh.TARGET_TYPE.VertexWithMeshTransform) //{ // modMesh.Init_VertexMorph(_parentModifier._meshGroup._uniqueID, // meshTransform._transformUniqueID, // meshTransform._mesh._uniqueID); // modMesh.Link_VertexMorph(_parentModifier._meshGroup, meshTransform, targetRenderUnit); //} //else if (_parentModifier.ModifiedTargetType == apModifiedMesh.TARGET_TYPE.MeshTransformOnly) //{ // modMesh.Init_MeshTransform(_parentModifier._meshGroup._uniqueID, // meshTransform._transformUniqueID, // meshTransform._mesh._uniqueID); // modMesh.Link_MeshTransform(_parentModifier._meshGroup, meshTransform, targetRenderUnit); //} #endregion paramSet._meshData.Add(modMesh); } } return(!isExist); }
public void LinkModifierStackToRenderUnitCalculateStack(bool isRoot = true, apMeshGroup rootMeshGroup = null) { //전체 Modifier중에서 RenderUnit을 포함한 Modifer를 찾는다. //그 중, RenderUnit에 대한것만 처리할 CalculateResultParam을 만들고 연동한다. //ResultParam을 RenderUnit의 CalculateStack에 넣는다. //Debug.Log("--------------------------------------------------------------"); //Debug.Log("LinkModifierStackToRenderUnitCalculateStack [" + _parentMeshGroup._name + "]"); //Debug.Log("--------------------------------------------------------------"); //수정 //각 ModMesh에서 계층적인 Link를 할 수 있도록 //RenderUnit을 매번 바꾸어주자 if (isRoot) { rootMeshGroup = _parentMeshGroup; //Modifier-ParamSetGroup-ParamSet + ModMesh가 "실제 RenderUnit"과 링크되지 않으므로 //Calculate Param을 만들기 전에 이 링크를 먼저 해주어야 한다. } //Modifier를 돌면서 ParamSet 데이터를 Calculated 데이터로 변환해서 옮긴다. for (int iMod = 0; iMod < _modifiers.Count; iMod++) { //Modifier ->.. apModifierBase modifier = _modifiers[iMod]; List <apModifierParamSetGroup> paramSetGroups = modifier._paramSetGroup_controller; for (int iGroup = 0; iGroup < paramSetGroups.Count; iGroup++) { //Modifier -> ParamSetGroup ->.. apModifierParamSetGroup paramSetGroup = paramSetGroups[iGroup]; List <apModifierParamSet> paramSets = paramSetGroup._paramSetList; for (int iParam = 0; iParam < paramSets.Count; iParam++) { //Modifier -> ParamSetGroup -> ParamSet ->... apModifierParamSet paramSet = paramSets[iParam]; List <apModifiedMesh> modMeshes = paramSet._meshData; List <apModifiedBone> modBones = paramSet._boneData; //1. Mod Mesh => Calculate Param으로 연결한다. for (int iModMesh = 0; iModMesh < modMeshes.Count; iModMesh++) { //[핵심] //Modifier -> ParamSetGroup -> ParamSet -> ModMeh //이제 이 ModMesh와 타겟 Transform을 연결하자. //연결할땐 Calculated 오브젝트를 만들어서 연결 apModifiedMesh modMesh = modMeshes[iModMesh]; #region [미사용 코드] //여기서 수정 //Root가 아닐때 > RenderUnit을 자체적으로 세팅할게 아니라, Root MeshGroup을 기준으로 RenderUnit을 찾자 //if(!isRoot) //{ // apRenderUnit recursiveRenderUnit = null; // if(modMesh._isMeshTransform) // { // recursiveRenderUnit = rootMeshGroup.GetRenderUnit(modMesh._transform_Mesh); // } // else // { // recursiveRenderUnit = rootMeshGroup.GetRenderUnit(modMesh._transform_MeshGroup); // } // if(recursiveRenderUnit != null) // { // //Debug.Log("Link ModStack -> Child Render Unit Changed [Modifier : " + modifier.DisplayName + "] / RenderUnit Name : " + recursiveRenderUnit.Name + " / is Changed : " + (modMesh._renderUnit != recursiveRenderUnit)); // //if(modMesh._renderUnit == null) // //{ // // Debug.LogError("기존 RenderUnit이 Null이다."); // //} // //else if(modMesh._renderUnit._meshGroup == null) // //{ // // Debug.LogError("기존 RenderUnit의 MeshGroup이 Null이다."); // //} // //else // //{ // // Debug.Log("[" + modMesh._renderUnit._meshGroup._name + " > " + rootMeshGroup._name + "]"); // //} // modMesh._renderUnit = recursiveRenderUnit; // } // else // { // Debug.LogError("Re Link Failed"); // } //} #endregion if (modMesh._renderUnit == null) { continue; } //이미 만든 Calculate Param이 있는지 확인 apCalculatedResultParam existParam = modifier.GetCalculatedResultParam(modMesh._renderUnit); //추가 : 만약 Calculated Param을 찾지 못했다면.. //Parent의 누군가가 이미 만들었을 수 있다! //Root Parent MeshGroup에 요청해서 한번 더 확인하자 //(Calculated Result Param을 공유할 수 있기 때문) if (existParam == null && rootMeshGroup != null) { //rootMeshGroup._modifierStack //?? 이거 해야하나 } apModifierParamSetGroupVertWeight weightedVertexData = null; if (modMesh._transform_Mesh != null) { weightedVertexData = paramSetGroup.GetWeightVertexData(modMesh._transform_Mesh); } if (existParam != null) { //Debug.Log("> ModMesh [" + iModMesh + "] : " + modMesh._transformUniqueID + "< Add >"); existParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, modMesh, null); existParam.LinkWeightedVertexData(weightedVertexData); //if(!isRoot) //{ // Debug.LogWarning("Child Modifier의 CalculateParam을 찾아서 적용 : " // + modifier.DisplayName + " / " + existParam._debugID + " / " + existParam._targetRenderUnit.Name); //} } else { //Debug.Log("> ModMesh [" + iModMesh + "] : " + modMesh._transformUniqueID + "< New >"); //새로 Calculate Param을 만들고.. apCalculatedResultParam newCalParam = new apCalculatedResultParam( modifier.CalculatedValueType, modifier.CalculatedSpace, modifier, modMesh._renderUnit, null, //<Bone은 없으닝께.. weightedVertexData ); newCalParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, modMesh, null); // Modifier에 등록하고 modifier._calculatedResultParams.Add(newCalParam); //RenderUnit에도 등록을 하자 modMesh._renderUnit._calculatedStack.AddCalculatedResultParam(newCalParam); //if(!isRoot) //{ // Debug.LogWarning("Child Modifier의 CalculateParam을 찾아서 적용 : " // + modifier.DisplayName + " / " + newCalParam._debugID + " / " + newCalParam._targetRenderUnit.Name); //} } //else //{ // Debug.LogError("Link Modifier Stack Error : No Render Unit (isRoot : " + isRoot + ")"); //} } //2. Mod Bone => Calculate Param으로 연결한다. for (int iModBone = 0; iModBone < modBones.Count; iModBone++) { apModifiedBone modBone = modBones[iModBone]; if (modBone._bone == null || modBone._renderUnit == null) { Debug.LogError("ModBone -> Calculate Link 실패 : [Bone : " + (modBone._bone != null) + ", RenderUnit : " + (modBone._renderUnit != null) + "]"); continue; } //이미 만든 Calculate Param이 있는지 확인 apCalculatedResultParam existParam = modifier.GetCalculatedResultParam_Bone(modBone._renderUnit, modBone._bone); if (existParam != null) { //이미 있다면 ModBone만 추가해주자 existParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, null, modBone); } else { //Debug.Log("Mod Bone -> Calculate Param 등록"); //새로 CalculateParam을 만들고 apCalculatedResultParam newCalParam = new apCalculatedResultParam( modifier.CalculatedValueType, modifier.CalculatedSpace, modifier, modBone._renderUnit, modBone._bone, null //WeightedVertex ); newCalParam.AddParamSetAndModifiedValue(paramSetGroup, paramSet, null, modBone); // Modifier에 등록하고 modifier._calculatedResultParams.Add(newCalParam); //RenderUnit에도 등록을 하자 modBone._renderUnit._calculatedStack.AddCalculatedResultParam(newCalParam); } } } } //SubList를 한번 정렬하자 for (int iCal = 0; iCal < modifier._calculatedResultParams.Count; iCal++) { modifier._calculatedResultParams[iCal].SortSubList(); } } //추가>> //하위 객체에 대해서도 Link를 자동으로 수행한다. //다 끝나고 Sort List <apTransform_MeshGroup> childMeshGroupTransforms = _parentMeshGroup._childMeshGroupTransforms; apTransform_MeshGroup childMeshGroup = null; if (childMeshGroupTransforms != null && childMeshGroupTransforms.Count > 0) { for (int i = 0; i < childMeshGroupTransforms.Count; i++) { childMeshGroup = childMeshGroupTransforms[i]; if (childMeshGroup._meshGroup != null && childMeshGroup._meshGroup != _parentMeshGroup) { childMeshGroup._meshGroup._modifierStack.LinkModifierStackToRenderUnitCalculateStack(false, rootMeshGroup); //<<여기서도 같이 수행 } } } if (isRoot) { //Debug.Log("Start Sort : " + _parentMeshGroup._name); //Root인 경우 //RenderUnit들을 검사하면서 Calculated Stack에 대해서 Sort를 해주자 List <apRenderUnit> renderUnits = _parentMeshGroup._renderUnits_All; for (int i = 0; i < renderUnits.Count; i++) { renderUnits[i]._calculatedStack.Sort(); } } }
public void BakeModifierParamSet(apModifierParamSet srcParamSet, apPortrait portrait, bool isUseModMeshSet) { _conSyncValue_Int = srcParamSet._conSyncValue_Int; _conSyncValue_Float = srcParamSet._conSyncValue_Float; _conSyncValue_Vector2 = srcParamSet._conSyncValue_Vector2; _keyframeUniqueID = srcParamSet._keyframeUniqueID; _syncKeyframe = null; _overlapWeight = srcParamSet._overlapWeight; //OverlapWeight를 집어넣자 _meshData.Clear(); _boneData.Clear(); //19.5.23 : meshSetData 추가 if (_meshSetData == null) { _meshSetData = new List <apOptModifiedMeshSet>(); } _meshSetData.Clear(); _isUseModMeshSet = isUseModMeshSet; //<<이 값이 1.1.7부터는 true가 된다. if (!_isUseModMeshSet) { //이전버전 //SrcModifier ParamSet의 ModMesh, ModBone을 Bake해주자 for (int i = 0; i < srcParamSet._meshData.Count; i++) { apModifiedMesh srcModMesh = srcParamSet._meshData[i]; apOptModifiedMesh optModMesh = new apOptModifiedMesh(); bool isResult = optModMesh.Bake(srcModMesh, portrait); if (isResult) { _meshData.Add(optModMesh); } } } else { //변경된 버전 : 19.5.23 (v.1.1.7) for (int i = 0; i < srcParamSet._meshData.Count; i++) { apModifiedMesh srcModMesh = srcParamSet._meshData[i]; apOptModifiedMeshSet optModMeshSet = new apOptModifiedMeshSet(); bool isResult = optModMeshSet.Bake( srcParamSet._parentParamSetGroup._parentModifier, srcParamSet._parentParamSetGroup, srcModMesh, portrait); if (isResult) { _meshSetData.Add(optModMeshSet); } } } //ModBone for (int i = 0; i < srcParamSet._boneData.Count; i++) { apModifiedBone srcModBone = srcParamSet._boneData[i]; apOptModifiedBone optModBone = new apOptModifiedBone(); bool isResult = optModBone.Bake(srcModBone, portrait); if (isResult) { _boneData.Add(optModBone); } } }