//public void SetLinkedKeyframes(apAnimKeyframe prevKeyframe, apAnimKeyframe nextKeyframe, bool isPrevDummyIndex, bool isNextDummyIndex) public void SetLinkedKeyframes(apAnimKeyframe prevKeyframe, apAnimKeyframe nextKeyframe, int prevFrameIndex, int nextFrameIndex) { _isActive = true; _prevLinkedKeyframe = prevKeyframe; _nextLinkedKeyframe = nextKeyframe; apAnimCurve prevCurveKey = null; apAnimCurve nextCurveKey = null; if (_prevLinkedKeyframe != null) { prevCurveKey = _prevLinkedKeyframe._curveKey; } if (_nextLinkedKeyframe != null) { nextCurveKey = _nextLinkedKeyframe._curveKey; } //_isLoopAsStart = false; //_isLoopAsEnd = false; //_loopFrameIndex = -1; //_curveKey.Set //_curveKey.SetLinkedCurveKey(prevCurveKey, nextCurveKey, isPrevDummyIndex, isNextDummyIndex); _curveKey.SetLinkedCurveKey(prevCurveKey, nextCurveKey, prevFrameIndex, nextFrameIndex); }
//----------------------------------------------------------------------------------- // Copy For Bake //----------------------------------------------------------------------------------- public void CopyFromTimelineLayer(apAnimTimelineLayer srcTimelineLayer) { _uniqueID = srcTimelineLayer._uniqueID; _keyframes.Clear(); for (int iKey = 0; iKey < srcTimelineLayer._keyframes.Count; iKey++) { apAnimKeyframe srcKeyframe = srcTimelineLayer._keyframes[iKey]; //Keyframe을 복사하자 apAnimKeyframe newKeyframe = new apAnimKeyframe(); newKeyframe.CopyFromKeyframe(srcKeyframe); _keyframes.Add(newKeyframe); } _linkModType = srcTimelineLayer._linkModType; _transformID = srcTimelineLayer._transformID; _boneID = srcTimelineLayer._boneID; _guiColor = srcTimelineLayer._guiColor; _guiLayerVisible = srcTimelineLayer._guiLayerVisible; _controlParamID = srcTimelineLayer._controlParamID; _linkType = srcTimelineLayer._linkType; }
//----------------------------------------------------------------------------------- // Copy For Bake //----------------------------------------------------------------------------------- public void CopyFromTimelineLayer(apAnimTimelineLayer srcTimelineLayer, apAnimClip parentAnimClip, apAnimTimeline parentTimeline) { _uniqueID = srcTimelineLayer._uniqueID; _parentTimeline = parentTimeline; _parentAnimClip = parentAnimClip; _keyframes.Clear(); for (int iKey = 0; iKey < srcTimelineLayer._keyframes.Count; iKey++) { apAnimKeyframe srcKeyframe = srcTimelineLayer._keyframes[iKey]; //Keyframe을 복사하자 apAnimKeyframe newKeyframe = new apAnimKeyframe(); newKeyframe.CopyFromKeyframe(srcKeyframe); _keyframes.Add(newKeyframe); } _linkModType = srcTimelineLayer._linkModType; _transformID = srcTimelineLayer._transformID; _boneID = srcTimelineLayer._boneID; _guiColor = srcTimelineLayer._guiColor; _guiLayerVisible = srcTimelineLayer._guiLayerVisible; _controlParamID = srcTimelineLayer._controlParamID; _linkType = srcTimelineLayer._linkType; //SortAndRefreshKeyframes(false, true);//<<추가 3.31 : 커브 복사 버그 수정 SortAndRefreshKeyframes(); //변경 19.5.20 }
// Get / Set //----------------------------------------------------------------------- //----------------------------------------------------------------------------------- // Copy For Bake //----------------------------------------------------------------------------------- public void CopyFromKeyframe(apAnimKeyframe srcKeyframe) { _uniqueID = srcKeyframe._uniqueID; _frameIndex = srcKeyframe._frameIndex; _curveKey = new apAnimCurve(srcKeyframe._curveKey, srcKeyframe._frameIndex); _isKeyValueSet = srcKeyframe._isKeyValueSet; _isActive = srcKeyframe._isActive; _isLoopAsStart = srcKeyframe._isLoopAsStart; _isLoopAsEnd = srcKeyframe._isLoopAsEnd; _loopFrameIndex = srcKeyframe._loopFrameIndex; _activeFrameIndexMin = srcKeyframe._activeFrameIndexMin; _activeFrameIndexMax = srcKeyframe._activeFrameIndexMax; _activeFrameIndexMin_Dummy = srcKeyframe._activeFrameIndexMin_Dummy; _activeFrameIndexMax_Dummy = srcKeyframe._activeFrameIndexMax_Dummy; _conSyncValue_Int = srcKeyframe._conSyncValue_Int; _conSyncValue_Float = srcKeyframe._conSyncValue_Float; _conSyncValue_Vector2 = srcKeyframe._conSyncValue_Vector2; }
// 실제로 연결된 데이터를 가져오자 //------------------------------------------------------------------------------- /// <summary> /// Animated Modifier 타입의 타임라인인 경우에, layer와 keyframe을 선택한 경우, /// 해당 데이터와 연동된 paramSet을 가져온다. (paramSet에는 ModMesh가 포함되어있다) /// </summary> /// <param name="targetLayer"></param> /// <param name="keyframe"></param> /// <returns></returns> public apModifierParamSet GetModifierParamSet(apAnimTimelineLayer targetLayer, apAnimKeyframe keyframe) { if (_linkType != apAnimClip.LINK_TYPE.AnimatedModifier || _linkedModifier == null) { return null; } if (targetLayer == null || !_layers.Contains(targetLayer) || keyframe == null) { return null; } apModifierParamSetGroup selectedParamSetGroup = _linkedModifier._paramSetGroup_controller.Find(delegate (apModifierParamSetGroup a) { return a._keyAnimTimelineLayer == targetLayer; }); if (selectedParamSetGroup == null) { return null; } return selectedParamSetGroup._paramSetList.Find(delegate (apModifierParamSet a) { return a.SyncKeyframe == keyframe; }); }
// Functions //--------------------------------------------------------- // Keyframe -> File public void SetAnimKeyframe(int unitID, apAnimKeyframe animKeyframe) { _unitID = unitID; _keyframeUniqueID = animKeyframe._uniqueID; _linkedKeyframe = animKeyframe; _frameIndex = animKeyframe._frameIndex; _isKeyValueSet = animKeyframe._isKeyValueSet; _isActive = animKeyframe._isActive; _isLoopAsStart = animKeyframe._isLoopAsStart; _isLoopAsEnd = animKeyframe._isLoopAsEnd; _loopFrameIndex = animKeyframe._loopFrameIndex; _activeFrameIndexMin = animKeyframe._activeFrameIndexMin; _activeFrameIndexMax = animKeyframe._activeFrameIndexMax; _activeFrameIndexMin_Dummy = animKeyframe._activeFrameIndexMin_Dummy; _activeFrameIndexMax_Dummy = animKeyframe._activeFrameIndexMax_Dummy; //Curve 정보 _curve_PrevTangentType = animKeyframe._curveKey._prevTangentType; _curve_PrevSmoothX = animKeyframe._curveKey._prevSmoothX; _curve_PrevSmoothY = animKeyframe._curveKey._prevSmoothY; _curve_NextTangentType = animKeyframe._curveKey._nextTangentType; _curve_NextSmoothX = animKeyframe._curveKey._nextSmoothX; _curve_NextSmoothY = animKeyframe._curveKey._nextSmoothY; //Control Param 타입이면 //Control Param의 어떤 값에 동기화되는가 _conSyncValue_Int = animKeyframe._conSyncValue_Int; _conSyncValue_Float = animKeyframe._conSyncValue_Float; _conSyncValue_Vector2 = animKeyframe._conSyncValue_Vector2; //Modifier Mesh 타입일때 _isModMeshType = animKeyframe._linkedModMesh_Editor != null; _isModBoneType = animKeyframe._linkedModBone_Editor != null; //>> Transform만 저장한다. _modTransformMatrix = new apMatrix(); _modMeshColor = Color.black; _modVisible = true; if (_isModMeshType) { _modTransformMatrix.SetMatrix(animKeyframe._linkedModMesh_Editor._transformMatrix); _modMeshColor = animKeyframe._linkedModMesh_Editor._meshColor; _modVisible = animKeyframe._linkedModMesh_Editor._isVisible; } else if (_isModBoneType) { _modTransformMatrix.SetMatrix(animKeyframe._linkedModBone_Editor._transformMatrix); } }
public void AddAnimKeyframe(apAnimKeyframe keyframe, bool isSelected) { _keyframes.Add(keyframe); if (!isSelected) { //하나라도 선택이 안되었다면 선택 안된걸로 처리 _isSelected = false; } }
public override bool Save(object target, string strParam) { base.Save(target, strParam); apAnimKeyframe keyframe = target as apAnimKeyframe; if (keyframe == null) { return(false); } _key_TimelineLayer = keyframe._parentTimelineLayer; if (_key_TimelineLayer == null) { return(false); } _animCurve = new apAnimCurve(keyframe._curveKey, keyframe._frameIndex); _isKeyValueSet = keyframe._isKeyValueSet; //_conSyncValue_Bool = keyframe._conSyncValue_Bool; _conSyncValue_Int = keyframe._conSyncValue_Int; _conSyncValue_Float = keyframe._conSyncValue_Float; _conSyncValue_Vector2 = keyframe._conSyncValue_Vector2; //_conSyncValue_Vector3 = keyframe._conSyncValue_Vector3; //_conSyncValue_Color = keyframe._conSyncValue_Color; _vertices.Clear(); _transformMatrix = new apMatrix(); _meshColor = new Color(0.5f, 0.5f, 0.5f, 1.0f); _isVisible = true; if (keyframe._linkedModMesh_Editor != null) { apModifiedMesh modMesh = keyframe._linkedModMesh_Editor; _vertices.Clear(); int nVert = modMesh._vertices.Count; for (int i = 0; i < nVert; i++) { apModifiedVertex modVert = modMesh._vertices[i]; _vertices.Add(new VertData(modVert._vertex, modVert._deltaPos)); } _transformMatrix = new apMatrix(modMesh._transformMatrix); _meshColor = modMesh._meshColor; _isVisible = modMesh._isVisible; } else if (keyframe._linkedModBone_Editor != null) { apModifiedBone modBone = keyframe._linkedModBone_Editor; _transformMatrix = new apMatrix(modBone._transformMatrix); } return(true); }
//-------------------------------------------------------------------- // 2. Keyframe //-------------------------------------------------------------------- public void Copy_Keyframe(apAnimKeyframe keyframe, string snapShotName) { _clipboard_Keyframe = new apSnapShotStackUnit(snapShotName); bool result = _clipboard_Keyframe.SetSnapShot_Keyframe(keyframe, "Clipboard"); if (!result) { _clipboard_Keyframe = null; //<<저장 불가능하다. } }
public override bool Load(object targetObj) { apAnimKeyframe keyframe = targetObj as apAnimKeyframe; if (keyframe == null) { return(false); } keyframe._curveKey = new apAnimCurve(_animCurve, keyframe._frameIndex); keyframe._isKeyValueSet = _isKeyValueSet; //keyframe._conSyncValue_Bool = _conSyncValue_Bool; keyframe._conSyncValue_Int = _conSyncValue_Int; keyframe._conSyncValue_Float = _conSyncValue_Float; keyframe._conSyncValue_Vector2 = _conSyncValue_Vector2; //keyframe._conSyncValue_Vector3 = _conSyncValue_Vector3; //keyframe._conSyncValue_Color = _conSyncValue_Color; if (keyframe._linkedModMesh_Editor != null) { apModifiedMesh modMesh = keyframe._linkedModMesh_Editor; VertData vertData = null; apModifiedVertex modVert = null; int nVert = _vertices.Count; for (int i = 0; i < nVert; i++) { vertData = _vertices[i]; modVert = modMesh._vertices.Find(delegate(apModifiedVertex a) { return(a._vertex == vertData._key_Vert); }); if (modVert != null) { modVert._deltaPos = vertData._deltaPos; } } modMesh._transformMatrix.SetMatrix(_transformMatrix); modMesh._meshColor = _meshColor; modMesh._isVisible = _isVisible; } else if (keyframe._linkedModBone_Editor != null) { apModifiedBone modBone = keyframe._linkedModBone_Editor; modBone._transformMatrix.SetMatrix(_transformMatrix); } return(true); }
public void SetInactive() { _isActive = false; _prevLinkedKeyframe = null; _nextLinkedKeyframe = null; _curveKey.SetLinkedCurveKey(null, null, _frameIndex, _frameIndex); _isLoopAsStart = false; _isLoopAsEnd = false; _loopFrameIndex = -1; }
public IEnumerator LinkParamSetGroupAsync(apOptParamSetGroup paramSetGroup, apPortrait portrait, apAsyncTimer asyncTimer) { _parentParamSetGroup = paramSetGroup; _syncKeyframe = null; if (_keyframeUniqueID >= 0) { //TODO //_syncKeyframe = if (paramSetGroup._keyAnimTimelineLayer != null) { _syncKeyframe = paramSetGroup._keyAnimTimelineLayer.GetKeyframeByID(_keyframeUniqueID); } } if (asyncTimer.IsYield()) { yield return(asyncTimer.WaitAndRestart()); } if (_isUseModMeshSet) { //19.5.23 : 새로운 버전 for (int i = 0; i < _meshSetData.Count; i++) { _meshSetData[i].Link(portrait); if (asyncTimer.IsYield()) { yield return(asyncTimer.WaitAndRestart()); } } } else { //이전 버전 for (int i = 0; i < _meshData.Count; i++) { _meshData[i].Link(portrait); if (asyncTimer.IsYield()) { yield return(asyncTimer.WaitAndRestart()); } } } //TODO : OptBone은 현재 Link할 객체가 없다. //필요하다면 Link를 여기에 추가해주자 }
// Show Window / Close Dialog //------------------------------------------------------------------------ public static object ShowDialog(apEditor editor, apPortrait portrait, apMeshGroup meshGroup, apModifierBase modifier, apModifiedMesh modMesh, apRenderUnit renderUnit, bool isAnimEdit, apAnimClip animClip, apAnimKeyframe keyframe) { CloseDialog(); if (editor == null || editor._portrait == null || meshGroup == null || modifier == null || modMesh == null) { return(null); } EditorWindow curWindow = EditorWindow.GetWindow(typeof(apDialog_ExtraOption), true, "Extra Properties", true); apDialog_ExtraOption curTool = curWindow as apDialog_ExtraOption; object loadKey = new object(); if (curTool != null && curTool != s_window) { int width = 400; int height = 620; if (isAnimEdit) { height = 715; } 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(editor, portrait, meshGroup, modifier, modMesh, renderUnit, isAnimEdit, animClip, keyframe); return(loadKey); } else { return(null); } }
// Set Calculated Value //-------------------------------------------------------------------- public void SetKeyframeResult(apAnimKeyframe keyframe, float weight) { //_weight = Mathf.Clamp01(_weight + weight); switch (_targetControlParam._valueType) { //case apControlParam.TYPE.Bool: // if(!_isCalculated) // { // //계산이 안되어있다면 -> Weight 상관없이 넣는다. // _value_Bool = keyframe._conSyncValue_Bool; // } // else // { // if(weight > 0.5f) // { // //Weight가 0.5 이상일때의 값을 넣는다. // _value_Bool = keyframe._conSyncValue_Bool; // } // } // break; case apControlParam.TYPE.Int: //_value_Int += (int)(keyframe._conSyncValue_Int * weight + 0.5f);//기존 : 버그 있다. _value_Int += (int)(keyframe._conSyncValue_Int * weight); //일단 이게 없어야 함 + Float형으로 바뀌었다. break; case apControlParam.TYPE.Float: _value_Float += keyframe._conSyncValue_Float * weight; break; case apControlParam.TYPE.Vector2: _value_Vec2 += keyframe._conSyncValue_Vector2 * weight; break; //case apControlParam.TYPE.Vector3: // _value_Vec3 += keyframe._conSyncValue_Vector3 * weight; // break; //case apControlParam.TYPE.Color: // _value_Color += keyframe._conSyncValue_Color * weight; // break; } _isCalculated = true; }
//-------------------------------------------------------------------- // 2.5. Keyframe 여러개 복사하기 //-------------------------------------------------------------------- //추가 3.29 : 타임라인 UI에서 키프레임들을 Ctrl+C로 복사하기 public void Copy_KeyframesOnTimelineUI(apAnimClip animClip, List <apAnimKeyframe> keyframes) { if (animClip == null || keyframes == null || keyframes.Count == 0) { _clipboard_AnimClipOfKeyframes = null; _clipboard_Keyframes = null; _copied_keyframes_StartFrame = -1; _copied_keyframes_EndFrame = -1; return; } _clipboard_AnimClipOfKeyframes = animClip; if (_clipboard_Keyframes == null) { _clipboard_Keyframes = new List <apSnapShotStackUnit>(); } else { _clipboard_Keyframes.Clear(); } _copied_keyframes_StartFrame = -1; _copied_keyframes_EndFrame = -1; apAnimKeyframe srcKeyframe = null; for (int i = 0; i < keyframes.Count; i++) { srcKeyframe = keyframes[i]; apSnapShotStackUnit newUnit = new apSnapShotStackUnit("Keyframe"); newUnit.SetSnapShot_Keyframe(srcKeyframe, "Clipboard"); _clipboard_Keyframes.Add(newUnit); if (i == 0) { _copied_keyframes_StartFrame = srcKeyframe._frameIndex; _copied_keyframes_EndFrame = srcKeyframe._frameIndex; } else { _copied_keyframes_StartFrame = Mathf.Min(_copied_keyframes_StartFrame, srcKeyframe._frameIndex); _copied_keyframes_EndFrame = Mathf.Max(_copied_keyframes_EndFrame, srcKeyframe._frameIndex); } } }
public bool IsPastable(apAnimKeyframe keyframe) { if (keyframe == null) { return(false); } if (_clipboard_Keyframe == null) { return(false); } //만약, 복사-붙여넣기 불가능한 객체이면 생략한다. bool isKeySync = _clipboard_Keyframe.IsKeySyncable(keyframe); if (!isKeySync) { return(false); } return(true); }
public bool Paste_Keyframe(apAnimKeyframe targetKeyframe) { if (targetKeyframe == null) { return(false); } if (_clipboard_Keyframe == null) { return(false); } //만약, 복사-붙여넣기 불가능한 객체이면 생략한다. bool isKeySync = _clipboard_Keyframe.IsKeySyncable(targetKeyframe); if (!isKeySync) { return(false); } return(_clipboard_Keyframe.Load(targetKeyframe)); }
// Functions //-------------------------------------------- public override bool IsKeySyncable(object target) { if (!(target is apAnimKeyframe)) { return(false); } apAnimKeyframe keyframe = target as apAnimKeyframe; if (keyframe == null) { return(false); } //Key가 같아야 한다. if (keyframe._parentTimelineLayer != _key_TimelineLayer) { return(false); } return(true); }
public void LinkParamSetGroup(apOptParamSetGroup paramSetGroup, apPortrait portrait) { _parentParamSetGroup = paramSetGroup; _syncKeyframe = null; if (_keyframeUniqueID >= 0) { //TODO //_syncKeyframe = if (paramSetGroup._keyAnimTimelineLayer != null) { _syncKeyframe = paramSetGroup._keyAnimTimelineLayer.GetKeyframeByID(_keyframeUniqueID); } } for (int i = 0; i < _meshData.Count; i++) { _meshData[i].Link(portrait); } //TODO : OptBone은 현재 Link할 객체가 없다. //필요하다면 Link를 여기에 추가해주자 }
//--------------------------------------------------- // 계산함수 - KeyFrame //--------------------------------------------------- private void CalculateWeight_KeyFrame() { if (_keyParamSetGroup == null || _keyParamSetGroup._keyAnimTimelineLayer == null) { return; } apAnimTimelineLayer timlineLayer = _keyParamSetGroup._keyAnimTimelineLayer; apOptCalculatedResultParam.OptParamKeyValueSet curParamKeyValue = null; //9.26 : 이거 수정해야한다. //Int형 프레임과 Float형 프레임을 둘다 사용한다. int curFrame = timlineLayer._parentAnimClip.CurFrame; float curFrameFloat = timlineLayer._parentAnimClip.CurFrameFloat; //<<이건 실수형 bool isLoop = timlineLayer._parentAnimClip.IsLoop; //apAnimKeyframe firstKeyframe = timlineLayer._firstKeyFrame; //apAnimKeyframe lastKeyframe = timlineLayer._lastKeyFrame; _totalWeight = 0.0f; apAnimKeyframe curKeyframe = null; apAnimKeyframe prevKeyframe = null; apAnimKeyframe nextKeyframe = null; //int indexOffsetA = 0; //int indexOffsetB = 0; int lengthFrames = timlineLayer._parentAnimClip.EndFrame - timlineLayer._parentAnimClip.StartFrame; int tmpCurFrameInt = 0; float tmpCurFrameFloat = 0; for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; curParamKeyValue._dist = -10.0f; curParamKeyValue._isCalculated = false; curParamKeyValue._weight = 0.0f; //추가 12.5 curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.NotCalculated; //유효하지 않은 키프레임이면 처리하지 않는다. if (curParamKeyValue._paramSet.SyncKeyframe == null || !curParamKeyValue._paramSet.SyncKeyframe._isActive) { //Debug.Log("[" + i + "] Not Active or Null Keyframe"); continue; } curKeyframe = curParamKeyValue._paramSet.SyncKeyframe; prevKeyframe = curParamKeyValue._paramSet.SyncKeyframe._prevLinkedKeyframe; nextKeyframe = curParamKeyValue._paramSet.SyncKeyframe._nextLinkedKeyframe; //1. 프레임이 같다. => 100% if (curFrame == curKeyframe._frameIndex || ((curKeyframe._isLoopAsStart || curKeyframe._isLoopAsEnd) && curFrame == curKeyframe._loopFrameIndex)) { curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //추가 12.5 : AnimKeyPos : 동일 프레임 curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.ExactKey; } //else if(curFrame >= curKeyframe._activeFrameIndexMin && // curFrame < curKeyframe._frameIndex) else if (curKeyframe.IsFrameIn(curFrame, apAnimKeyframe.LINKED_KEY.Prev)) { //범위 안에 들었다. [Prev - Cur] if (prevKeyframe != null) { tmpCurFrameInt = curFrame; if (tmpCurFrameInt > curKeyframe._frameIndex) { tmpCurFrameInt -= lengthFrames; } tmpCurFrameFloat = curFrameFloat; if (tmpCurFrameFloat > curKeyframe._frameIndex) { tmpCurFrameFloat -= lengthFrames; } //[중요] 재생 프레임 -> 보간 가중치 계산 코드 //_cal_itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrameInt, true);//기존 : Int _cal_itp = curKeyframe._curveKey.GetItp_Float(tmpCurFrameFloat, true, tmpCurFrameInt); //변경 : Float curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = _cal_itp; _totalWeight += _cal_itp; //추가 : Rotation Bias //Prev와 연결되었다면 Prev 설정을 적용한다. if (curKeyframe._prevRotationBiasMode != apAnimKeyframe.ROTATION_BIAS.None) { curParamKeyValue.SetAnimRotationBias(curKeyframe._prevRotationBiasMode, curKeyframe._prevRotationBiasCount); } //Debug.Log("[" + i + "] [Prev ~ Cur] " + itp); //Debug.Log("Prev ~ Next : " + itp); //추가 12.5 : AnimKeyPos - Next 프레임으로서 Prev 프레임과 보간이 된다. curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.NextKey; } else { //연결된게 없다면 이게 100% 가중치를 갖는다. curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] [Prev ?? ~ Cur] 1.0"); //추가 12.5 : AnimKeyPos - 동일 프레임 curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.ExactKey; } } //else if(curFrame > curKeyframe._frameIndex && // curFrame <= curKeyframe._activeFrameIndexMax) else if (curKeyframe.IsFrameIn(curFrame, apAnimKeyframe.LINKED_KEY.Next)) { //범위안에 들었다 [Cur - Next] if (nextKeyframe != null) { tmpCurFrameInt = curFrame; if (tmpCurFrameInt < curKeyframe._frameIndex) { tmpCurFrameInt += lengthFrames; } tmpCurFrameFloat = curFrameFloat; if (tmpCurFrameFloat < curKeyframe._frameIndex) { tmpCurFrameFloat += lengthFrames; } //[중요] 재생 프레임 -> 보간 가중치 계산 코드 //_cal_itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrameInt, false);//기존 _cal_itp = curKeyframe._curveKey.GetItp_Float(tmpCurFrameFloat, false, tmpCurFrameInt); //변경 : Float //itp = 1.0f - itp;//결과가 B에 맞추어지므로 여기서는 Reverse curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = _cal_itp; _totalWeight += _cal_itp; //Debug.Log("[" + i + "] [Cur ~ Next] " + itp); //추가 : Rotation Bias //Next와 연결되었다면 Next 설정을 적용한다. if (curKeyframe._nextRotationBiasMode != apAnimKeyframe.ROTATION_BIAS.None) { curParamKeyValue.SetAnimRotationBias(curKeyframe._nextRotationBiasMode, curKeyframe._nextRotationBiasCount); } //추가 12.5 : AnimKeyPos - Prev 프레임으로서 Next 프레임과 보간이 된다. curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.PrevKey; } else { //연결된게 없다면 이게 100% 가중치를 갖는다. curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] [Cur ~ Next ??] 1.0"); //추가 12.5 : AnimKeyPos - 동일 프레임 curParamKeyValue._animKeyPos = apOptCalculatedResultParam.AnimKeyPos.ExactKey; } } } if (_totalWeight > 0.0f) { //Debug.Log("Result --------------------------------"); for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; if (curParamKeyValue._isCalculated) { curParamKeyValue._weight /= _totalWeight; //Debug.Log("[" + curParamKeyValue._weight + "]"); } else { curParamKeyValue._weight = 0.0f; } } //Debug.Log("-------------------------------------"); } }
public override bool Load(object targetObj) { apAnimKeyframe keyframe = targetObj as apAnimKeyframe; if (keyframe == null) { return(false); } keyframe._curveKey = new apAnimCurve(_animCurve, keyframe._frameIndex); keyframe._isKeyValueSet = _isKeyValueSet; //keyframe._conSyncValue_Bool = _conSyncValue_Bool; keyframe._conSyncValue_Int = _conSyncValue_Int; keyframe._conSyncValue_Float = _conSyncValue_Float; keyframe._conSyncValue_Vector2 = _conSyncValue_Vector2; //keyframe._conSyncValue_Vector3 = _conSyncValue_Vector3; //keyframe._conSyncValue_Color = _conSyncValue_Color; if (keyframe._linkedModMesh_Editor != null) { apModifiedMesh modMesh = keyframe._linkedModMesh_Editor; VertData vertData = null; apModifiedVertex modVert = null; int nVert = _vertices.Count; for (int i = 0; i < nVert; i++) { vertData = _vertices[i]; modVert = modMesh._vertices.Find(delegate(apModifiedVertex a) { return(a._vertex == vertData._key_Vert); }); if (modVert != null) { modVert._deltaPos = vertData._deltaPos; } } modMesh._transformMatrix.SetMatrix(_transformMatrix); modMesh._meshColor = _meshColor; modMesh._isVisible = _isVisible; //추가 3.29 : ExtraProperty도 복사 modMesh._isExtraValueEnabled = _isExtraValueEnabled; if (modMesh._extraValue == null) { modMesh._extraValue = new apModifiedMesh.ExtraValue(); modMesh._extraValue.Init(); } if (_isExtraValueEnabled) { if (_extraValue != null) { modMesh._extraValue._isDepthChanged = _extraValue._isDepthChanged; modMesh._extraValue._deltaDepth = _extraValue._deltaDepth; modMesh._extraValue._isTextureChanged = _extraValue._isTextureChanged; modMesh._extraValue._linkedTextureData = _extraValue._linkedTextureData; modMesh._extraValue._textureDataID = _extraValue._textureDataID; modMesh._extraValue._weightCutout = _extraValue._weightCutout; modMesh._extraValue._weightCutout_AnimPrev = _extraValue._weightCutout_AnimPrev; modMesh._extraValue._weightCutout_AnimNext = _extraValue._weightCutout_AnimNext; } } else { modMesh._extraValue.Init(); } } else if (keyframe._linkedModBone_Editor != null) { apModifiedBone modBone = keyframe._linkedModBone_Editor; modBone._transformMatrix.SetMatrix(_transformMatrix); } return(true); }
public bool SetSnapShot_Keyframe(apAnimKeyframe keyframe, string strParam) { _snapShot = new apSnapShot_Keyframe(); return(_snapShot.Save(keyframe, strParam)); }
// Get / Set //-------------------------------------------------- public bool IsKeyframeContain(apAnimKeyframe keyframe) { return(_keyframes.Contains(keyframe)); }
// Functions //-------------------------------------------------- public int SortAndRefreshKeyframes(bool isPrintLog = false) { _keyframes.Sort(delegate(apAnimKeyframe a, apAnimKeyframe b) { return(a._frameIndex - b._frameIndex); }); int startFrame = _parentAnimClip.StartFrame; int endFrame = _parentAnimClip.EndFrame; int lengthFrame = endFrame - startFrame; bool isLoop = _parentAnimClip.IsLoop; _firstKeyFrame = null; _lastKeyFrame = null; _underStartKeyframe = null; _overEndKeyframe = null; apAnimKeyframe prevKey = null; apAnimKeyframe nextKey = null; apAnimKeyframe curKey = null; int nRefreshed = 0; if (_activeKeyframes == null) { _activeKeyframes = new List <apAnimKeyframe>(); } else { _activeKeyframes.Clear(); } for (int i = 0; i < _keyframes.Count; i++) { curKey = _keyframes[i]; //curKey._curveKey.SetLoopSize(lengthFrame); curKey._isActive = true; if (curKey._frameIndex < startFrame || curKey._frameIndex > endFrame) { //범위를 벗어났다. curKey.SetInactive(); continue; } curKey.SetDummyDisable(); //일단 더미 끈 상태로 처리 _activeKeyframes.Add(curKey); } if (isPrintLog) { Debug.Log("--------- Sort And Refresh [" + DisplayName + "] -----------"); } if (_activeKeyframes.Count > 0) { //1. 일단 루프 체크 및 더미 키 여부를 판단하자 if (isLoop) { //수정 : F/L은 무조건 0, n 에서 지정된다. //1)의 경우 (Start, End가 모두 지정된 경우)를 제외하고는 F, L은 모두 더미를 갖는다. // -----[Start]-------------------------[End]----------- //1) <First> <Last> (F/L 다르다 + 더미가 없다) //2) <<- <First> ~ [L:n] ->> (dummy) <<- (F가 L이 된다 (L이 더미)) //3) ->> (dummy) <<- [F:0] ~ <Last> ->> (L이 F가 된다 (F가 더미)) //4) <<->> [0:F:Dummy] ~ [n:L:Dummy] <<->> (F와 L이 다르다 (서로가 서로의 더미 프레임을 가진다) _firstKeyFrame = _activeKeyframes[0]; _lastKeyFrame = _activeKeyframes[_activeKeyframes.Count - 1]; if (_firstKeyFrame._frameIndex == startFrame && _lastKeyFrame._frameIndex == endFrame) { //딱히 뭐 없네용 } else { _firstKeyFrame.SetLoopFrame(true, _firstKeyFrame._frameIndex + lengthFrame); _lastKeyFrame.SetLoopFrame(false, _lastKeyFrame._frameIndex - lengthFrame); _underStartKeyframe = _lastKeyFrame; _overEndKeyframe = _firstKeyFrame; } #region [미사용 코드] //apAnimKeyframe keyA = _activeKeyframes[0]; //apAnimKeyframe keyB = _activeKeyframes[_activeKeyframes.Count - 1]; ////예외 (keyA와 keyB가 같다면) //if(keyA == keyB) //{ // _firstKeyFrame = keyA; // _lastKeyFrame = keyA; //} //else //{ // if(keyA._frameIndex == startFrame && keyB._frameIndex == endFrame) // { // //1) 둘다 각각 Start/End에 위치한다. => F/L 지정 후 더미 없음 // _firstKeyFrame = keyA; // _lastKeyFrame = keyB; // } // else if(keyA._frameIndex == startFrame && keyB._frameIndex != endFrame) // { // //2) Start에는 위치하지만 End는 비었다. => F 지정후 F의 더미가 L이 된다. // _firstKeyFrame = keyA; // keyA.SetDummy(true, keyA._frameIndex + lengthFrame); // _lastKeyFrame = keyA; // _overEndKeyframe = _firstKeyFrame; // } // else if(keyA._frameIndex != startFrame && keyB._frameIndex == endFrame) // { // //3) End에는 위치하지만 Start는 비었다. => L 지정후 L의 더미가 F가 된다. // _lastKeyFrame = keyB; // keyB.SetDummy(false, keyB._frameIndex - lengthFrame); // _firstKeyFrame = keyB; // _underStartKeyframe = _lastKeyFrame; // } // else//if(keyA._frameIndex != startFrame && keyB._frameIndex != endFrame) // { // //4) Start와 End에 모두 비었다. => 양쪽 모두 F/L이 되며, 서로 상대에 대해 Dummy가 된다. // _firstKeyFrame = keyA; // _lastKeyFrame = keyB; // keyA.SetDummy(true, keyA._frameIndex + lengthFrame); // keyB.SetDummy(false, keyB._frameIndex - lengthFrame); // _underStartKeyframe = _lastKeyFrame; // _overEndKeyframe = _firstKeyFrame; // } //} #endregion } else { //루프가 아니라면 //마지막 프레임이 마지막이다. _firstKeyFrame = _activeKeyframes[0]; _lastKeyFrame = _activeKeyframes[_activeKeyframes.Count - 1]; } //2. 활성화된 프레임들끼리 연결을 해주자 int iPrev = 0; //<<여기서 인덱스는 Frame값이 아니라 리스트의 인덱스이다. int iNext = 0; int iLast = _activeKeyframes.Count - 1; int prevFrameIndex = 0; int nextFrameIndex = 0; for (int i = 0; i < _activeKeyframes.Count; i++) { curKey = _activeKeyframes[i]; prevKey = null; nextKey = null; prevFrameIndex = curKey._frameIndex; nextFrameIndex = curKey._frameIndex; iPrev = i - 1; iNext = i + 1; if (iPrev < 0 && isLoop) { if (_underStartKeyframe != null) { iPrev = iLast; } } if (iPrev >= 0 && iPrev <= iLast) { prevKey = _activeKeyframes[iPrev]; ////예외가 하나 있다. ////[현재 = StartFrame] 일때 ////[Prev = EndFrame]이라면 두 프레임은 연결되지 않는다. (Loop에서 두 프레임은 같은걸로 친다) //if (curKey._frameIndex == startFrame && // prevKey._frameIndex == endFrame) //{ // prevKey = null; //} } if (iNext > iLast && isLoop) { if (_overEndKeyframe != null) { iNext = 0; } } if (iNext >= 0 && iNext <= iLast) { nextKey = _activeKeyframes[iNext]; ////예외가 하나 있다. ////[현재 = EndFrame] 일때 ////[Next = StartFrame]이라면 두 프레임은 연결되지 않는다. (Loop에서 두 프레임은 같은걸로 친다) //if (curKey._frameIndex == endFrame && // nextKey._frameIndex == startFrame) //{ // nextKey = null; //} } if (prevKey != null) { prevFrameIndex = prevKey._frameIndex; if (prevFrameIndex > curKey._frameIndex) { prevFrameIndex -= lengthFrame; } } if (nextKey != null) { nextFrameIndex = nextKey._frameIndex; if (nextFrameIndex < curKey._frameIndex) { nextFrameIndex += lengthFrame; } } //curKey.SetLinkedKeyframes(prevKey, nextKey, isPrevDummy, isNextDummy); //자기 자신으로 연결되지는 않는다. if (prevKey == curKey) { prevKey = null; } if (nextKey == curKey) { nextKey = null; } if (isPrintLog) { string strPrevKey = " X "; string strNextKey = " X "; if (prevKey != null) { strPrevKey = " " + prevKey._frameIndex + " "; } if (nextKey != null) { strNextKey = " " + nextKey._frameIndex + " "; } Debug.Log("Keyframe [" + curKey._frameIndex + "] Link (" + strPrevKey + ") <-> (" + strNextKey + ")"); } curKey.SetLinkedKeyframes(prevKey, nextKey, prevFrameIndex, nextFrameIndex); } #region [미사용 코드] //이제 lastFrame을 지정하자 //if (isLoop) //{ // //1. Loop 일때 // //1) 마지막 프레임이 EndFrame의 값을 가진다 -> EndFrame이 LastFrame이다. // //2) 마지막 프레임이 EndFrame의 값을 가지지 않는다 -> StartFrame이 LastFrame으로 반복(더미) 한다. // // // if(_activeKeyframes[iLast]._frameIndex == endFrame) // { // _lastKeyFrame = _activeKeyframes[iLast]; // } // else // { // _lastKeyFrame = _firstKeyFrame; // //더미프레임 처리를 하자 // _firstKeyFrame.SetDummy(endFrame); // } //} //else //{ // //2. Loop가 아닐때 // //무조건 마지막 프레임이 LastFrame이다. // _lastKeyFrame = _activeKeyframes[iLast]; //} #endregion //마지막으로 전체 CurveKeyCalculate를 하자 for (int i = 0; i < _activeKeyframes.Count; i++) { //+ frame영역을 정하자 curKey = _activeKeyframes[i]; if (curKey._prevLinkedKeyframe != null) { if (curKey._isLoopAsStart) { curKey._activeFrameIndexMin = curKey._prevLinkedKeyframe._loopFrameIndex; curKey._activeFrameIndexMin_Dummy = curKey._activeFrameIndexMin + lengthFrame; curKey._activeFrameIndexMax_Dummy = curKey._frameIndex + lengthFrame; } else { curKey._activeFrameIndexMin = curKey._prevLinkedKeyframe._frameIndex; } //if(curKey._activeFrameIndexMin > curKey._frameIndex) //{ // //Loop인가.. // curKey._activeFrameIndexMin -= lengthFrame; //} } else { if (curKey == _firstKeyFrame) { curKey._activeFrameIndexMin = startFrame - 10; } else { //? 연결이 안되어있다니? curKey._activeFrameIndexMin = curKey._frameIndex; } } if (curKey._nextLinkedKeyframe != null) { if (curKey._isLoopAsEnd) { curKey._activeFrameIndexMax = curKey._nextLinkedKeyframe._loopFrameIndex; curKey._activeFrameIndexMin_Dummy = curKey._frameIndex - lengthFrame; curKey._activeFrameIndexMax_Dummy = curKey._activeFrameIndexMax - lengthFrame; } else { curKey._activeFrameIndexMax = curKey._nextLinkedKeyframe._frameIndex; } //if(curKey._activeFrameIndexMax < curKey._frameIndex) //{ // //Loop인가.. // curKey._activeFrameIndexMax += lengthFrame; //} } else { if (curKey == _lastKeyFrame) { curKey._activeFrameIndexMax = endFrame + 10; } else { curKey._activeFrameIndexMax = curKey._frameIndex; } } _activeKeyframes[i].RefreshCurveKey(); nRefreshed++; //Debug.Log("Frame [" + curKey._frameIndex + "] ( " + curKey._activeFrameIndexMin + " ~ " + curKey._activeFrameIndexMax + " )"); } } if (isPrintLog) { Debug.Log("---------------------------------------------"); } return(nRefreshed); }
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); } } }
/// <summary> /// ParamSet간의 Weight를 계산한다. [Keyframe이 입력값인 경우] /// </summary> private void CalculateWeight_Keyframe() { if (_keyParamSetGroup == null || _keyParamSetGroup._keyAnimTimelineLayer == null) { return; } if (_keyParamSetGroup._keyAnimClip._isSelectedInEditor) { _keyParamSetGroup._layerWeight = 1.0f; } else { _keyParamSetGroup._layerWeight = 0.0f; } apAnimTimelineLayer timlineLayer = _keyParamSetGroup._keyAnimTimelineLayer; apCalculatedResultParam.ParamKeyValueSet curParamKeyValue = null; int curFrame = timlineLayer._parentAnimClip.CurFrame; bool isLoop = timlineLayer._parentAnimClip.IsLoop; apAnimKeyframe firstKeyframe = timlineLayer._firstKeyFrame; apAnimKeyframe lastKeyframe = timlineLayer._lastKeyFrame; //int firstFrame = -1; //int lastFrame = -1; //if(isLoop) //{ // if(firstKeyframe != null) // { // firstFrame = firstKeyframe._frameIndex; // } // if(lastKeyframe != null) // { // lastFrame = lastKeyframe._frameIndex; // } //} _totalWeight = 0.0f; apAnimKeyframe curKeyframe = null; apAnimKeyframe prevKeyframe = null; apAnimKeyframe nextKeyframe = null; //int indexOffsetA = 0; //int indexOffsetB = 0; int lengthFrames = timlineLayer._parentAnimClip.EndFrame - timlineLayer._parentAnimClip.StartFrame; int tmpCurFrame = 0; //Debug.Log("Calculated--------------------------------"); for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; curParamKeyValue._dist = -10.0f; curParamKeyValue._isCalculated = false; //유효하지 않은 키프레임이면 처리하지 않는다. if (curParamKeyValue._paramSet.SyncKeyframe == null || !curParamKeyValue._paramSet.SyncKeyframe._isActive || //!curParamKeyValue._isActive_InEditorExclusive !curParamKeyValue.IsActive ) { //Debug.Log("[" + i + "] Not Active or Null Keyframe"); continue; } curKeyframe = curParamKeyValue._paramSet.SyncKeyframe; prevKeyframe = curParamKeyValue._paramSet.SyncKeyframe._prevLinkedKeyframe; nextKeyframe = curParamKeyValue._paramSet.SyncKeyframe._nextLinkedKeyframe; //1. 프레임이 같다. => 100% if (curFrame == curKeyframe._frameIndex || ((curKeyframe._isLoopAsStart || curKeyframe._isLoopAsEnd) && curFrame == curKeyframe._loopFrameIndex)) { curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] <Exact Frame>"); } //else if(curFrame >= curKeyframe._activeFrameIndexMin && // curFrame < curKeyframe._frameIndex) else if (curKeyframe.IsFrameIn(curFrame, true)) { //범위 안에 들었다. [Prev - Cur] if (prevKeyframe != null) { //indexOffsetA = 0; //indexOffsetB = 0; //if(prevKeyframe._frameIndex > curKeyframe._frameIndex) //{ // //Loop인 경우 Prev가 더 클 수 있다. // indexOffsetA = -lengthFrames; //} tmpCurFrame = curFrame; if (tmpCurFrame > curKeyframe._frameIndex) { tmpCurFrame -= lengthFrames; } //float itp = apAnimCurve.GetCurvedRelativeInterpolation(prevKeyframe._curveKey, curKeyframe._curveKey, curFrame, curKeyframe._curveKey._isPrevKeyUseDummyIndex, false); //float itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, prevKeyframe._curveKey, tmpCurFrame, true); //>> 변경 float itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrame, true); curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = itp; _totalWeight += itp; //Debug.Log("[" + i + "] [Prev ~ Cur] " + itp); //Debug.Log("Prev ~ Next : " + itp); } else { //연결된게 없다면 이게 100% 가중치를 갖는다. curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] [Prev ?? ~ Cur] 1.0"); } } //else if(curFrame > curKeyframe._frameIndex && // curFrame <= curKeyframe._activeFrameIndexMax) else if (curKeyframe.IsFrameIn(curFrame, false)) { //범위안에 들었다 [Cur - Next] if (nextKeyframe != null) { //indexOffsetA = 0; //indexOffsetB = 0; //if(nextKeyframe._frameIndex < curKeyframe._frameIndex) //{ // //Loop인 경우 Next가 더 작을 수 있다. // indexOffsetB = lengthFrames; //} tmpCurFrame = curFrame; if (tmpCurFrame < curKeyframe._frameIndex) { tmpCurFrame += lengthFrames; } //float itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, nextKeyframe._curveKey, curFrame, false, curKeyframe._curveKey._isNextKeyUseDummyIndex); //float itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, nextKeyframe._curveKey, tmpCurFrame, false); //>> 변경 float itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrame, false); //itp = 1.0f - itp;//결과가 B에 맞추어지므로 여기서는 Reverse curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = itp; _totalWeight += itp; //Debug.Log("[" + i + "] [Cur ~ Next] " + itp); } else { //연결된게 없다면 이게 100% 가중치를 갖는다. curParamKeyValue._dist = 0.0f; curParamKeyValue._isCalculated = true; curParamKeyValue._weight = 1.0f; _totalWeight += 1.0f; //Debug.Log("[" + i + "] [Cur ~ Next ??] 1.0"); } } } if (_totalWeight > 0.0f) { //Debug.Log("Result --------------------------------"); float prevWeight = 0.0f; for (int i = 0; i < _subParamKeyValues.Count; i++) { curParamKeyValue = _subParamKeyValues[i]; if (curParamKeyValue._isCalculated) { curParamKeyValue._weight /= _totalWeight; //Debug.Log("[" + curParamKeyValue._weight + "]"); } else { curParamKeyValue._weight = 0.0f; } } //Debug.Log("-------------------------------------"); } }
/// <summary> /// [Editor] 업데이트 중 Control Param 제어 Timeline에 대해 업데이트 후 적용을 한다. /// [Runtime] isAdaptToWeight = false로 두고 나머지 처리를 한다. /// </summary> /// <param name="isAdaptToWeight1">[Editor]에서 Weight=1로 두고 적용을 한다</param> public void UpdateControlParam(bool isAdaptToWeight1, int optLayer = 0, float optWeight = 1.0f, apAnimPlayUnit.BLEND_METHOD optBlendMethod = apAnimPlayUnit.BLEND_METHOD.Interpolation) { if (_controlParamResult.Count == 0) { return; } for (int i = 0; i < _controlParamResult.Count; i++) { _controlParamResult[i].Init(); } apAnimTimeline timeline = null; apAnimTimelineLayer layer = null; int curFrame = CurFrame; float curFrameF = CurFrameFloat; //apAnimKeyframe firstKeyframe = null; //apAnimKeyframe lastKeyframe = null; apAnimKeyframe curKeyframe = null; apAnimKeyframe prevKeyframe = null; apAnimKeyframe nextKeyframe = null; int lengthFrames = _endFrame - _startFrame; int tmpCurFrame = 0; apAnimControlParamResult cpResult = null; for (int iTL = 0; iTL < _timelines.Count; iTL++) { timeline = _timelines[iTL]; if (timeline._linkType != LINK_TYPE.ControlParam) { continue; } for (int iL = 0; iL < timeline._layers.Count; iL++) { layer = timeline._layers[iL]; if (layer._linkedControlParam == null || layer._linkedControlParamResult == null) { continue; } cpResult = layer._linkedControlParamResult; //firstKeyframe = layer._firstKeyFrame; //lastKeyframe = layer._lastKeyFrame; for (int iK = 0; iK < layer._keyframes.Count; iK++) { curKeyframe = layer._keyframes[iK]; prevKeyframe = curKeyframe._prevLinkedKeyframe; nextKeyframe = curKeyframe._nextLinkedKeyframe; if (curFrame == curKeyframe._frameIndex || ((curKeyframe._isLoopAsStart || curKeyframe._isLoopAsEnd) && curKeyframe._loopFrameIndex == curFrame) ) { cpResult.SetKeyframeResult(curKeyframe, 1.0f); } else if (curKeyframe.IsFrameIn(curFrame, apAnimKeyframe.LINKED_KEY.Prev)) { //Prev - Cur 범위 안에 들었다. if (prevKeyframe != null) { //Prev 키가 있다면 tmpCurFrame = curFrame; if (tmpCurFrame > curKeyframe._frameIndex) { //한바퀴 돌았다면 tmpCurFrame -= lengthFrames; } //TODO : 여길 나중에 "정식 Curve로 변경"할 것 //float itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, prevKeyframe._curveKey, tmpCurFrame, true); //>> 변경 float itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrame, true); cpResult.SetKeyframeResult(curKeyframe, itp); } else { //Prev 키가 없다면 이게 100%다 cpResult.SetKeyframeResult(curKeyframe, 1.0f); } } else if (curKeyframe.IsFrameIn(curFrame, apAnimKeyframe.LINKED_KEY.Next)) { //Cur - Next 범위 안에 들었다. if (nextKeyframe != null) { //Next 키가 있다면 tmpCurFrame = curFrame; if (tmpCurFrame < curKeyframe._frameIndex) { //한바퀴 돌았다면 tmpCurFrame += lengthFrames; } //TODO : 여길 나중에 "정식 Curve로 변경"할 것 //float itp = apAnimCurve.GetCurvedRelativeInterpolation(curKeyframe._curveKey, nextKeyframe._curveKey, tmpCurFrame, false); //>> 변경 float itp = curKeyframe._curveKey.GetItp_Int(tmpCurFrame, false); cpResult.SetKeyframeResult(curKeyframe, itp); } else { //Prev 키가 없다면 이게 100%다 cpResult.SetKeyframeResult(curKeyframe, 1.0f); } } } } } //Control Param에 적용을 해야한다. if (isAdaptToWeight1) { //Editor인 경우 Weight 1로 강제한다. for (int i = 0; i < _controlParamResult.Count; i++) { _controlParamResult[i].AdaptToControlParam(); } } else { //Runtime인 경우 지정된 Weight, Layer로 처리한다. for (int i = 0; i < _controlParamResult.Count; i++) { //Debug.Log("AnimClip [" + _name + " > Control Param : " + _controlParamResult[i]._targetControlParam._keyName + " ]"); _controlParamResult[i].AdaptToControlParam_Opt(optWeight, optBlendMethod); } } }
// Init //------------------------------------------------------------------------------------------------ private void Init(apEditor editor, apPortrait portrait, apMeshGroup meshGroup, apModifierBase modifier, apModifiedMesh modMesh, apRenderUnit renderUnit, bool isAnimEdit, apAnimClip animClip, apAnimKeyframe keyframe) { _editor = editor; _portrait = portrait; _meshGroup = meshGroup; _modifier = modifier; _modMesh = modMesh; _renderUnit = modMesh._renderUnit; _isAnimEdit = isAnimEdit; _animClip = animClip; _keyframe = keyframe; _selectionType = _editor.Select.SelectionType; _targetDepth = renderUnit.GetDepth(); _img_DepthCursor = _editor.ImageSet.Get(apImageSet.PRESET.ExtraOption_DepthCursor); _img_DepthMidCursor = _editor.ImageSet.Get(apImageSet.PRESET.ExtraOption_DepthMidCursor); _img_MeshTF = _editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Mesh); _img_MeshGroupTF = _editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_MeshGroup); _subUnits_All.Clear(); apRenderUnit parentUnit = _renderUnit._parentRenderUnit; apRenderUnit curRenderUnit = null; for (int i = 0; i < _meshGroup._renderUnits_All.Count; i++) { curRenderUnit = _meshGroup._renderUnits_All[i]; //Parent가 같은 형제 렌더 유닛에 대해서만 처리한다. //단, MeshTransform일 때, Clipping Child는 생략한다. if (curRenderUnit._meshTransform != null && curRenderUnit._meshTransform._isClipping_Child) { continue; } if (curRenderUnit._parentRenderUnit != parentUnit) { continue; } SubUnit subUnit = new SubUnit(curRenderUnit, curRenderUnit._level, (curRenderUnit == _renderUnit), (curRenderUnit == _meshGroup._rootRenderUnit)); _subUnits_All.Add(subUnit); } _subUnits_All.Sort(delegate(SubUnit a, SubUnit b) { return(b._depth - a._depth); }); //여기서는 실제 Depth보다 상대적 Depth만 고려한다. int curDepth = 0; for (int i = _subUnits_All.Count - 1; i >= 0; i--) { _subUnits_All[i]._depth = curDepth; if (_subUnits_All[i]._isTarget) { _targetDepth = curDepth; } curDepth++; } //이미지를 바꿀 수 있는가 RefreshImagePreview(); }
// GUI //------------------------------------------------------------------------------------------------ private void OnGUI() { int width = (int)position.width; int height = (int)position.height; width -= 10; //만약 이 다이얼로그가 켜진 상태로 뭔가 바뀌었다면 종료 bool isClose = false; bool isMoveAnimKeyframe = false; bool isMoveAnimKeyframeToNext = false; if (_editor == null || _meshGroup == null || _modifier == null || _modMesh == null || _renderUnit == null) { //데이터가 없다. isClose = true; } else if (_editor.Select.SelectionType != _selectionType) { //선택 타입이 바뀌었다. isClose = true; } else { if (!_isAnimEdit) { //1. 일반 모디파이어 편집시 //- 현재 선택된 MeshGroup이 바뀌었다면 //- 현재 선택된 Modifier가 바뀌었다면 //- Modifier 메뉴가 아니라면 //- ExEditingMode가 꺼졌다면 //> 해제 if (_editor.Select.ExEditingMode == apSelection.EX_EDIT.None || _editor.Select.MeshGroup != _meshGroup || _editor.Select.Modifier != _modifier || _editor._meshGroupEditMode != apEditor.MESHGROUP_EDIT_MODE.Modifier) { isClose = true; } } else { //2. 애니메이션 편집 시 //- 현재 선택된 AnimationClip이 바뀌었다면 //- 현재 선택된 MeshGroup이 바뀌었다면 (AnimClip이 있을 때) //- AnimExEditingMode가 꺼졌다면 //- 재생 중이라면 //> 해제 if (_editor.Select.ExAnimEditingMode == apSelection.EX_EDIT.None || _editor.Select.AnimClip != _animClip || _animClip == null || _keyframe == null || _editor.Select.AnimClip._targetMeshGroup != _meshGroup || _editor.Select.IsAnimPlaying) { isClose = true; } } } if (isClose) { CloseDialog(); return; } //------------------------------------------------------------ //1. 선택된 객체 정보 //- RenderUnit 아이콘과 이름 //2. <애니메이션인 경우> //- 현재 키프레임과 키프레임 이동하기 //3. 가중치 //- [일반] Weight CutOut //- [Anim] Prev / Next CutOut // (구분선) //4. Depth //- 아이콘과 Chainging Depth 레이블 //- On / Off 버튼 //- Depth 증감과 리스트 (좌우에 배치) //5. Texture (RenderUnit이 MeshTransform인 경우) //- 현재 텍스쳐 //- 바뀔 텍스쳐 //- 텍스쳐 선택하기 버튼 //1. 선택된 객체 정보 //- RenderUnit 아이콘과 이름 //int iconSize = 25; GUIStyle guiStyle_TargetBox = new GUIStyle(GUI.skin.box); guiStyle_TargetBox.alignment = TextAnchor.MiddleCenter; Color prevColor = GUI.backgroundColor; // RenderUnit 이름 Texture2D iconRenderUnit = null; if (_renderUnit._meshTransform != null) { iconRenderUnit = _editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_Mesh); } else { iconRenderUnit = _editor.ImageSet.Get(apImageSet.PRESET.Hierarchy_MeshGroup); } GUI.backgroundColor = new Color(0.5f, 1.0f, 1.0f, 1.0f); GUILayout.Box(new GUIContent(" " + _renderUnit.Name, iconRenderUnit), guiStyle_TargetBox, GUILayout.Width(width), GUILayout.Height(30)); GUI.backgroundColor = prevColor; GUILayout.Space(5); //"Extra Property ON", "Extra Property OFF" if (apEditorUtil.ToggledButton_2Side(_editor.GetText(TEXT.ExtraOpt_ExtraPropertyOn), _editor.GetText(TEXT.ExtraOpt_ExtraPropertyOff), _modMesh._isExtraValueEnabled, true, width, 25)) { apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._isExtraValueEnabled = !_modMesh._isExtraValueEnabled; _meshGroup.RefreshModifierLink(); //<<옵션의 형태가 바뀌면 Modifier의 Link를 다시 해야한다. apEditorUtil.ReleaseGUIFocus(); } GUILayout.Space(5); if (_isAnimEdit) { GUILayout.Space(10); //2. <애니메이션인 경우> //- 현재 키프레임과 키프레임 이동하기 //"Target Frame" EditorGUILayout.LabelField(_editor.GetText(TEXT.ExtraOpt_TargetFrame)); int frameBtnSize = 20; int frameCurBtnWidth = 100; int frameMoveBtnWidth = (width - (10 + frameCurBtnWidth)) / 2; EditorGUILayout.BeginHorizontal(GUILayout.Width(width), GUILayout.Height(frameBtnSize)); GUILayout.Space(5); if (GUILayout.Button(_editor.ImageSet.Get(apImageSet.PRESET.Anim_MoveToPrevFrame), GUILayout.Width(frameMoveBtnWidth), GUILayout.Height(frameBtnSize))) { //이전 프레임으로 이동하기 isMoveAnimKeyframe = true; isMoveAnimKeyframeToNext = false; } if (GUILayout.Button(_keyframe._frameIndex.ToString(), GUILayout.Width(frameCurBtnWidth), GUILayout.Height(frameBtnSize))) { _animClip.SetFrame_Editor(_keyframe._frameIndex); _editor.SetRepaint(); } if (GUILayout.Button(_editor.ImageSet.Get(apImageSet.PRESET.Anim_MoveToNextFrame), GUILayout.Width(frameMoveBtnWidth), GUILayout.Height(frameBtnSize))) { //다음 프레임으로 이동하기 isMoveAnimKeyframe = true; isMoveAnimKeyframeToNext = true; } EditorGUILayout.EndHorizontal(); } GUILayout.Space(10); //3. 가중치 //- [일반] Weight CutOut //- [Anim] Prev / Next CutOut EditorGUILayout.LabelField(_editor.GetText(TEXT.ExtraOpt_WeightSettings)); //"Weight Settings" GUILayout.Space(5); if (!_isAnimEdit) { //일반이면 CutOut이 1개 float cutOut = EditorGUILayout.DelayedFloatField(_editor.GetText(TEXT.ExtraOpt_Offset), _modMesh._extraValue._weightCutout); //"Offset (0~1)" if (cutOut != _modMesh._extraValue._weightCutout) { cutOut = Mathf.Clamp01(cutOut); apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._extraValue._weightCutout = cutOut; apEditorUtil.ReleaseGUIFocus(); } } else { //애니메이션이면 CutOut이 2개 EditorGUILayout.LabelField(_editor.GetText(TEXT.ExtraOpt_Offset)); float animPrevCutOut = EditorGUILayout.DelayedFloatField(_editor.GetText(TEXT.ExtraOpt_OffsetPrevKeyframe), _modMesh._extraValue._weightCutout_AnimPrev); //"Prev Keyframe" float animNextCutOut = EditorGUILayout.DelayedFloatField(_editor.GetText(TEXT.ExtraOpt_OffsetNextKeyframe), _modMesh._extraValue._weightCutout_AnimNext); //"Next Keyframe" if (animPrevCutOut != _modMesh._extraValue._weightCutout_AnimPrev || animNextCutOut != _modMesh._extraValue._weightCutout_AnimNext ) { animPrevCutOut = Mathf.Clamp01(animPrevCutOut); animNextCutOut = Mathf.Clamp01(animNextCutOut); apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._extraValue._weightCutout_AnimPrev = animPrevCutOut; _modMesh._extraValue._weightCutout_AnimNext = animNextCutOut; apEditorUtil.ReleaseGUIFocus(); } } GUILayout.Space(10); apEditorUtil.GUI_DelimeterBoxH(width); GUILayout.Space(10); int tabBtnWidth = ((width - 10) / 2); int tabBtnHeight = 25; EditorGUILayout.BeginHorizontal(GUILayout.Width(width), GUILayout.Height(tabBtnHeight)); GUILayout.Space(5); if (apEditorUtil.ToggledButton(_editor.GetText(TEXT.ExtraOpt_Tab_Depth), _tab == TAB.Depth, tabBtnWidth, tabBtnHeight)) //"Depth" { _tab = TAB.Depth; } if (apEditorUtil.ToggledButton(_editor.GetText(TEXT.ExtraOpt_Tab_Image), _tab == TAB.Image, tabBtnWidth, tabBtnHeight)) //"Image" { _tab = TAB.Image; } EditorGUILayout.EndHorizontal(); GUILayout.Space(10); if (_tab == TAB.Depth) { //4. Depth //- 아이콘과 Chainging Depth 레이블 //- On / Off 버튼 //- Depth 증감과 리스트 (좌우에 배치) EditorGUILayout.LabelField(_editor.GetText(TEXT.ExtraOpt_ChangingDepth)); //"Changing Depth" GUILayout.Space(5); //"Depth Option ON", "Depth Option OFF" if (apEditorUtil.ToggledButton_2Side(_editor.GetText(TEXT.ExtraOpt_DepthOptOn), _editor.GetText(TEXT.ExtraOpt_DepthOptOff), _modMesh._extraValue._isDepthChanged, _modMesh._isExtraValueEnabled, width, 25)) { apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._extraValue._isDepthChanged = !_modMesh._extraValue._isDepthChanged; _meshGroup.RefreshModifierLink(); //<<Modifier Link를 다시 해야한다. _editor.SetRepaint(); } GUILayout.Space(5); bool isDepthAvailable = _modMesh._extraValue._isDepthChanged && _modMesh._isExtraValueEnabled; int depthListWidth_Left = 80; int depthListWidth_Right = width - (10 + depthListWidth_Left); int depthListWidth_RightInner = depthListWidth_Right - 20; int depthListHeight = 276; //int depthListHeight_LeftBtn = (depthListHeight - 40) / 2; int depthListHeight_LeftBtn = 40; int depthListHeight_LeftSpace = (depthListHeight - (40 + depthListHeight_LeftBtn * 2)) / 2; int depthListHeight_RightList = 20; //리스트 배경 Rect lastRect = GUILayoutUtility.GetLastRect(); if (!isDepthAvailable) { GUI.backgroundColor = new Color(1.0f, 0.6f, 0.6f, 1.0f); } GUI.Box(new Rect(5 + depthListWidth_Left + 8, lastRect.y + 8, depthListWidth_Right, depthListHeight), ""); if (!isDepthAvailable) { GUI.backgroundColor = prevColor; } EditorGUILayout.BeginHorizontal(GUILayout.Width(width), GUILayout.Height(depthListHeight)); GUILayout.Space(5); EditorGUILayout.BeginVertical(GUILayout.Width(depthListWidth_Left), GUILayout.Height(depthListHeight)); // Depth List의 왼쪽 // Depth 증감 버튼과 값 GUILayout.Space(depthListHeight_LeftSpace); Texture2D img_AddWeight = _editor.ImageSet.Get(apImageSet.PRESET.Rig_AddWeight); Texture2D img_SubtractWeight = _editor.ImageSet.Get(apImageSet.PRESET.Rig_SubtractWeight); //if (GUILayout.Button(, GUILayout.Width(depthListWidth_Left), GUILayout.Height(depthListHeight_LeftBtn))) if (apEditorUtil.ToggledButton(img_AddWeight, false, isDepthAvailable, depthListWidth_Left, depthListHeight_LeftBtn)) { //Depth 증가 apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._extraValue._deltaDepth++; _editor.SetRepaint(); apEditorUtil.ReleaseGUIFocus(); } //"Delta Depth" EditorGUILayout.LabelField(_editor.GetText(TEXT.ExtraOpt_DeltaDepth), GUILayout.Width(depthListWidth_Left)); int deltaDepth = EditorGUILayout.DelayedIntField(_modMesh._extraValue._deltaDepth, GUILayout.Width(depthListWidth_Left)); if (deltaDepth != _modMesh._extraValue._deltaDepth) { if (isDepthAvailable) { apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._extraValue._deltaDepth = deltaDepth; _editor.SetRepaint(); apEditorUtil.ReleaseGUIFocus(); } } //if (GUILayout.Button(_editor.ImageSet.Get(apImageSet.PRESET.Rig_SubtractWeight), GUILayout.Width(depthListWidth_Left), GUILayout.Height(depthListHeight_LeftBtn))) if (apEditorUtil.ToggledButton(img_SubtractWeight, false, isDepthAvailable, depthListWidth_Left, depthListHeight_LeftBtn)) { //Depth 감소 apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._extraValue._deltaDepth--; _editor.SetRepaint(); apEditorUtil.ReleaseGUIFocus(); } EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.Width(depthListWidth_Right), GUILayout.Height(depthListHeight)); // RenderUnit 리스트와 변환될 Depth 위치 _scrollList = EditorGUILayout.BeginScrollView(_scrollList, false, true, GUILayout.Width(depthListWidth_Right), GUILayout.Height(depthListHeight)); EditorGUILayout.BeginVertical(GUILayout.Width(depthListWidth_RightInner), GUILayout.Height(depthListHeight)); GUILayout.Space(5); SubUnit curSubUnit = null; //int cursorDepth = _renderUnit.GetDepth() + _modMesh._extraValue._deltaDepth; int cursorDepth = _targetDepth + _modMesh._extraValue._deltaDepth; //GUI Content 생성 [11.16 수정] if (_guiContent_DepthMidCursor == null) { _guiContent_DepthMidCursor = apGUIContentWrapper.Make(_img_DepthMidCursor); } if (_guiContent_DepthCursor == null) { _guiContent_DepthCursor = apGUIContentWrapper.Make(_img_DepthCursor); } if (_guiContent_MeshIcon == null) { _guiContent_MeshIcon = apGUIContentWrapper.Make(_img_MeshTF); } if (_guiContent_MeshGroupIcon == null) { _guiContent_MeshGroupIcon = apGUIContentWrapper.Make(_img_MeshGroupTF); } //이전 코드 //GUIContent guiContent_DepthMidCursor = new GUIContent(_img_DepthMidCursor); //GUIContent guiContent_DepthCursor = new GUIContent(_img_DepthCursor); //GUIContent guiContent_MeshIcon = new GUIContent(_img_MeshTF); //GUIContent guiContent_MeshGroupIcon = new GUIContent(_img_MeshGroupTF); int depthCursorSize = depthListHeight_RightList; for (int i = 0; i < _subUnits_All.Count; i++) { curSubUnit = _subUnits_All[i]; if (curSubUnit._isTarget) { //타겟이면 배경색을 그려주자 lastRect = GUILayoutUtility.GetLastRect(); if (EditorGUIUtility.isProSkin) { GUI.backgroundColor = new Color(0.0f, 1.0f, 1.0f, 1.0f); } else { GUI.backgroundColor = new Color(0.4f, 0.8f, 1.0f, 1.0f); } int yOffset = 6; if (i == 0) { yOffset = 7 - depthListHeight_RightList; } GUI.Box(new Rect(lastRect.x, lastRect.y + depthListHeight_RightList + yOffset, depthListWidth_RightInner + 10, depthListHeight_RightList), ""); GUI.backgroundColor = prevColor; } EditorGUILayout.BeginHorizontal(GUILayout.Width(depthListWidth_RightInner), GUILayout.Height(depthListHeight_RightList)); //TODO : Depth 커서 그려주기 //GUILayout.Space(20); DEPTH_CURSOR_TYPE depthCursorType = DEPTH_CURSOR_TYPE.None; if (!curSubUnit._isTarget) { if (cursorDepth != _targetDepth) { if (cursorDepth == curSubUnit._depth) { depthCursorType = DEPTH_CURSOR_TYPE.Target; } else { if (cursorDepth > _targetDepth) { //Depth가 증가했을 때 if (_targetDepth < curSubUnit._depth && curSubUnit._depth < cursorDepth) { depthCursorType = DEPTH_CURSOR_TYPE.Mid; } } else { //Depth가 감소했을 때 if (cursorDepth < curSubUnit._depth && curSubUnit._depth < _targetDepth) { depthCursorType = DEPTH_CURSOR_TYPE.Mid; } } } } } else { if (cursorDepth != _targetDepth) { depthCursorType = DEPTH_CURSOR_TYPE.Mid; } else { depthCursorType = DEPTH_CURSOR_TYPE.Target; } } GUILayout.Space(5); switch (depthCursorType) { case DEPTH_CURSOR_TYPE.None: GUILayout.Space(depthCursorSize + 4); break; case DEPTH_CURSOR_TYPE.Mid: EditorGUILayout.LabelField(_guiContent_DepthMidCursor.Content, GUILayout.Width(depthCursorSize), GUILayout.Height(depthCursorSize)); break; case DEPTH_CURSOR_TYPE.Target: EditorGUILayout.LabelField(_guiContent_DepthCursor.Content, GUILayout.Width(depthCursorSize), GUILayout.Height(depthCursorSize)); break; } EditorGUILayout.LabelField(curSubUnit._isMeshTransform ? _guiContent_MeshIcon.Content : _guiContent_MeshGroupIcon.Content, GUILayout.Width(depthCursorSize), GUILayout.Height(depthCursorSize)); EditorGUILayout.LabelField(curSubUnit._depth.ToString(), GUILayout.Width(20), GUILayout.Height(depthListHeight_RightList)); EditorGUILayout.LabelField(curSubUnit._name, GUILayout.Width(depthListWidth_RightInner - (24 + 5 + depthCursorSize + depthCursorSize + 20 + 8)), GUILayout.Height(depthListHeight_RightList) ); EditorGUILayout.EndHorizontal(); } GUILayout.Space(depthListHeight + 100); EditorGUILayout.EndVertical(); EditorGUILayout.EndScrollView(); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); } else { //5. Texture (RenderUnit이 MeshTransform인 경우) //- 현재 텍스쳐 //- 바뀔 텍스쳐 //- 텍스쳐 선택하기 버튼 //"Changing Image" EditorGUILayout.LabelField(_editor.GetText(TEXT.ExtraOpt_ChangingImage)); GUILayout.Space(5); //"Image Option ON", "Image Option OFF" if (apEditorUtil.ToggledButton_2Side(_editor.GetText(TEXT.ExtraOpt_ImageOptOn), _editor.GetText(TEXT.ExtraOpt_ImageOptOff), _modMesh._extraValue._isTextureChanged, _isImageChangable && _modMesh._isExtraValueEnabled, width, 25)) { apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._extraValue._isTextureChanged = !_modMesh._extraValue._isTextureChanged; _meshGroup.RefreshModifierLink(); //<<Modifier Link를 다시 해야한다. _editor.SetRepaint(); } GUILayout.Space(5); bool isTextureAvailable = _modMesh._extraValue._isTextureChanged && _isImageChangable && _modMesh._isExtraValueEnabled; int imageSlotSize = 170; int imageSlotSpaceSize = width - (imageSlotSize * 2 + 6 + 10); int imageSlotHeight = imageSlotSize + 50; Texture2D img_Src = null; Texture2D img_Dst = null; string strSrcName = "< None >"; string strDstName = "< None >"; if (_srcTexureData != null && _srcTexureData._image != null) { img_Src = _srcTexureData._image; strSrcName = _srcTexureData._name; } if (_dstTexureData != null && _dstTexureData._image != null) { img_Dst = _dstTexureData._image; strDstName = _dstTexureData._name; } GUIStyle guiStyle_ImageSlot = new GUIStyle(GUI.skin.box); guiStyle_ImageSlot.alignment = TextAnchor.MiddleCenter; GUIStyle guiStyle_ImageName = new GUIStyle(GUI.skin.label); guiStyle_ImageName.alignment = TextAnchor.MiddleCenter; EditorGUILayout.BeginHorizontal(GUILayout.Width(width), GUILayout.Height(imageSlotHeight)); GUILayout.Space(5); //이미지 슬롯 1 : 원래 이미지 EditorGUILayout.BeginVertical(GUILayout.Width(imageSlotSize), GUILayout.Height(imageSlotHeight)); //"Original" EditorGUILayout.LabelField(_editor.GetText(TEXT.ExtraOpt_SlotOriginal), GUILayout.Width(imageSlotSize)); GUILayout.Box(img_Src, guiStyle_ImageSlot, GUILayout.Width(imageSlotSize), GUILayout.Height(imageSlotSize)); GUILayout.Space(5); EditorGUILayout.LabelField(strSrcName, guiStyle_ImageName, GUILayout.Width(imageSlotSize)); EditorGUILayout.EndVertical(); GUILayout.Space(imageSlotSpaceSize); //이미지 슬롯 1 : 원래 이미지 EditorGUILayout.BeginVertical(GUILayout.Width(imageSlotSize), GUILayout.Height(imageSlotHeight)); //"Changed" EditorGUILayout.LabelField(_editor.GetText(TEXT.ExtraOpt_SlotChanged), GUILayout.Width(imageSlotSize)); GUILayout.Box(img_Dst, guiStyle_ImageSlot, GUILayout.Width(imageSlotSize), GUILayout.Height(imageSlotSize)); GUILayout.Space(5); EditorGUILayout.LabelField(strDstName, guiStyle_ImageName, GUILayout.Width(imageSlotSize)); EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); //"Set Image" if (apEditorUtil.ToggledButton(_editor.GetText(TEXT.ExtraOpt_SelectImage), false, isTextureAvailable, width, 30)) { //이미지 열기 열기 _loadKey_TextureSelect = apDialog_SelectTextureData.ShowDialog(_editor, null, OnTextureDataSelected); } //"Reset Image" if (GUILayout.Button(_editor.GetText(TEXT.ExtraOpt_ResetImage), GUILayout.Width(width), GUILayout.Height(20))) { apEditorUtil.SetRecord_Modifier(apUndoGroupData.ACTION.Modifier_SettingChanged, _editor, _modifier, _modMesh._extraValue, false); _modMesh._extraValue._textureDataID = -1; _modMesh._extraValue._linkedTextureData = null; RefreshImagePreview(); Repaint(); } } GUILayout.Space(10); apEditorUtil.GUI_DelimeterBoxH(width); GUILayout.Space(10); //"Close" if (GUILayout.Button(_editor.GetText(TEXT.Close), GUILayout.Height(30))) { isClose = true; } if (isClose) { CloseDialog(); } if (isMoveAnimKeyframe) { //키프레임 이동의 경우, //타임라인 레이어를 따라서 전,후로 이동한다. //이때 ModMesh가 아예 바뀌기 때문에 여기서 처리해야한다. if (_keyframe != null && _keyframe._parentTimelineLayer != null && _animClip != null) { apAnimKeyframe moveKeyframe = (isMoveAnimKeyframeToNext ? _keyframe._nextLinkedKeyframe : _keyframe._prevLinkedKeyframe); if (moveKeyframe != null && moveKeyframe._linkedModMesh_Editor != null) { _keyframe = moveKeyframe; _modMesh = _keyframe._linkedModMesh_Editor; _animClip.SetFrame_Editor(moveKeyframe._frameIndex); RefreshImagePreview(); apEditorUtil.ReleaseGUIFocus(); Repaint(); _editor.SetRepaint(); } } } }
public void LinkSyncKeyframe(apAnimKeyframe keyframe) { _keyframeUniqueID = keyframe._uniqueID; _syncKeyframe = keyframe; }