private void WriteTracksAsIs(AnimationClip clipAnimation, BinaryWriter writer) { var positionAdapter = new Vector3AnimationCurveAdapter("m_LocalPosition", Vector3.zero); var rotationAdapter = new QuaternionAnimationCurveAdapter("m_LocalRotation"); var eulerAnglesRawAdapter = new EulerAnglesAnimationCurveAdapter("localEulerAnglesRaw"); var scaleAdapter = new Vector3AnimationCurveAdapter("m_LocalScale", Vector3.one); var allAdapters = new IAnimationCurveAdapter[] { positionAdapter, rotationAdapter, scaleAdapter, eulerAnglesRawAdapter }; var allBindings = AnimationUtility.GetCurveBindings(clipAnimation); var bindingGroups = allBindings.Where(_ => allAdapters.Any(a => a.HasProperty(_.propertyName))) .GroupBy(_ => _.path) .OrderBy(_ => _.Key.Length).ToArray(); var timeStep = 1.0f / clipAnimation.frameRate; var numKeyFrames = 1 + (int)(clipAnimation.length * clipAnimation.frameRate); var numTracks = (uint)bindingGroups.Length; writer.Write(numTracks); foreach (var group in bindingGroups) { foreach (var adapter in allAdapters) { adapter.PickTracks(clipAnimation, group); } var boneName = group.Key; boneName = boneName.Substring(boneName.LastIndexOf('/') + 1); WriteStringSZ(writer, boneName); IAnimationCurveAdapter <Vector3> position = null; if (positionAdapter.HasTracks) { position = positionAdapter; } var rotation = new IAnimationCurveAdapter <Quaternion>[] { rotationAdapter, eulerAnglesRawAdapter }.FirstOrDefault( _ => _.HasTracks); IAnimationCurveAdapter <Vector3> scale = null; if (scaleAdapter.HasTracks) { scale = scaleAdapter; } byte trackMask = 0; if (position != null) { trackMask |= 1; } if (rotation != null) { trackMask |= 2; } if (scale != null) { trackMask |= 4; } writer.Write(trackMask); writer.Write(numKeyFrames); for (var frame = 0; frame < numKeyFrames; ++frame) { var t = frame * timeStep; writer.Write(t); if ((trackMask & 1) != 0) { var pos = position.Evaluate(t); Write(writer, pos); } if ((trackMask & 2) != 0) { var rot = rotation.Evaluate(t); Write(writer, rot); } if ((trackMask & 4) != 0) { var scaleV = scale.Evaluate(t); Write(writer, scaleV); } } } }
void UpdatePath(string oldPath, string newPath) { if (paths[newPath] != null) { throw new UnityException("Path " + newPath + " already exists in that animation!"); } AssetDatabase.StartAssetEditing(); for (int iCurrentClip = 0; iCurrentClip < animationClips.Count; iCurrentClip++) { AnimationClip animationClip = animationClips[iCurrentClip]; Undo.RecordObject(animationClip, "Animation Hierarchy Change"); //recreating all curves one by one //to maintain proper order in the editor - //slower than just removing old curve //and adding a corrected one, but it's more //user-friendly for (int iCurrentPath = 0; iCurrentPath < pathsKeys.Count; iCurrentPath++) { string path = pathsKeys[iCurrentPath] as string; ArrayList curves = (ArrayList)paths[path]; for (int i = 0; i < curves.Count; i++) { EditorCurveBinding binding = (EditorCurveBinding)curves[i]; AnimationCurve curve = AnimationUtility.GetEditorCurve(animationClip, binding); ObjectReferenceKeyframe[] objectReferenceCurve = AnimationUtility.GetObjectReferenceCurve(animationClip, binding); if (curve != null) { AnimationUtility.SetEditorCurve(animationClip, binding, null); } else { AnimationUtility.SetObjectReferenceCurve(animationClip, binding, null); } if (path == oldPath) { binding.path = newPath; } if (curve != null) { AnimationUtility.SetEditorCurve(animationClip, binding, curve); } else { AnimationUtility.SetObjectReferenceCurve(animationClip, binding, objectReferenceCurve); } float fChunk = 1f / animationClips.Count; float fProgress = (iCurrentClip * fChunk) + fChunk * ((float)iCurrentPath / (float)pathsKeys.Count); EditorUtility.DisplayProgressBar( "Animation Hierarchy Progress", "How far along the animation editing has progressed.", fProgress); } } } AssetDatabase.StopAssetEditing(); EditorUtility.ClearProgressBar(); FillModel(); this.Repaint(); }
private static void ExportSkeletonAnimationClipData(GameObject source, BabylonSkeleton skeleton, SkinnedMeshRenderer skinnedMesh, BabylonMesh babylonMesh, UnityEditor.AnimationState animationState, ref List <AnimationClip> states, ref UnityMetaData metaData, Animator animator) { ExporterWindow.ReportProgress(1, "Exporting skeleton clips: " + skinnedMesh.name); //string sourceId = GetID(source); int frameRate = 0; int firstClipEnd = 0; int totalFrameCount = 0; Transform[] bones = skinnedMesh.bones; List <string> stateNameCache = new List <string>(); if (!AnimationMode.InAnimationMode()) { AnimationMode.StartAnimationMode(); } //var anims = new List<BabylonAnimation>(); //var pxkeys = new List<BabylonAnimationKey>(); float playbackSpeed = (animationState != null) ? animationState.playbackSpeed : 1.0f; float clampFeetPositions = (animationState != null) ? animationState.clampFeetPositions : 0.0f; BabylonAnimationBaking bakeRootTransforms = (animationState != null) ? animationState.bakeRootTransforms : BabylonAnimationBaking.GameBlend; foreach (var bone in skeleton.bones) { int frameOffest = 0; var keys = new List <BabylonAnimationKey>(); Transform transform = bones.Single(b => b.name == bone.name); foreach (var state in states) { if (state == null) { continue; } AnimationClip clip = state as AnimationClip; if (frameRate <= 0) { frameRate = (int)clip.frameRate; } var frameTime = 1.0f / frameRate; int clipFrameCount = (int)(clip.length * frameRate); if (firstClipEnd <= 0) { firstClipEnd = (clipFrameCount - 1); } var settings = AnimationUtility.GetAnimationClipSettings(clip); BabylonLoopBehavior behavior = (settings.loopTime) ? BabylonLoopBehavior.Cycle : BabylonLoopBehavior.Constant; if (settings.loopTime && settings.loopBlend) { behavior = BabylonLoopBehavior.Relative; } ExporterWindow.ReportProgress(1, "Sampling: " + babylonMesh.name + " - " + bone.name + " - " + clip.name); // Set Animation State Meta Data if (!stateNameCache.Contains(clip.name)) { stateNameCache.Add(clip.name); // Animation Clip Information Dictionary <string, object> animStateInfo = new Dictionary <string, object>(); animStateInfo.Add("type", "skeleton"); animStateInfo.Add("name", clip.name); animStateInfo.Add("start", frameOffest); animStateInfo.Add("stop", (frameOffest + clipFrameCount - 1)); animStateInfo.Add("rate", frameRate); animStateInfo.Add("behavior", (int)behavior); animStateInfo.Add("playback", playbackSpeed); metaData.animationClips.Add(animStateInfo); } AnimationMode.BeginSampling(); for (var i = 0; i < clipFrameCount; i++) { Matrix4x4 local; int frameIndex = (i + frameOffest); float originalPX = transform.localPosition.x; float originalPY = transform.localPosition.y; float originalPZ = transform.localPosition.z; float originalRY = transform.localRotation.eulerAngles.y; clip.SampleAnimation(source, i * frameTime); if (transform == skinnedMesh.rootBone) { float positionX = transform.localPosition.x; float positionY = transform.localPosition.y; float positionZ = transform.localPosition.z; Quaternion rotationQT = transform.localRotation; if (settings.loopBlendOrientation || settings.keepOriginalOrientation) { if (settings.keepOriginalOrientation) { // Original Rotation - ??? rotationQT = Quaternion.Euler(rotationQT.eulerAngles.x, originalRY, rotationQT.eulerAngles.z); } else { // Body Orientation - ??? rotationQT = Quaternion.Euler(rotationQT.eulerAngles.x, settings.orientationOffsetY, rotationQT.eulerAngles.z); } } if (settings.loopBlendPositionY || settings.keepOriginalPositionY) { if (settings.keepOriginalPositionY) { // Original Position Y positionY = originalPY; } else if (settings.heightFromFeet) { // Feet Position Y positionY = (settings.level + clampFeetPositions); } else { // Center Of Mass positionY = 0.0f; } } if (settings.loopBlendPositionXZ || settings.keepOriginalPositionXZ) { if (settings.keepOriginalPositionXZ) { // Original Position XZ positionX = originalPX; positionZ = originalPZ; } else { // Center Of Mass positionX = 0.0f; positionZ = 0.0f; } } if (bakeRootTransforms == BabylonAnimationBaking.GameBlend) { positionX = 0.0f; positionZ = 0.0f; } local = Matrix4x4.TRS(new Vector3(positionX, positionY, positionZ), rotationQT, transform.localScale); } else { // DEPRECIATED: local = (transform.parent.localToWorldMatrix.inverse * transform.localToWorldMatrix); local = Matrix4x4.TRS(transform.localPosition, transform.localRotation, transform.localScale); } float[] matrix = new[] { local[0, 0], local[1, 0], local[2, 0], local[3, 0], local[0, 1], local[1, 1], local[2, 1], local[3, 1], local[0, 2], local[1, 2], local[2, 2], local[3, 2], local[0, 3], local[1, 3], local[2, 3], local[3, 3] }; var key = new BabylonAnimationKey { frame = frameIndex, values = matrix }; keys.Add(key); } AnimationMode.EndSampling(); frameOffest += clipFrameCount; totalFrameCount += clipFrameCount; } var babylonAnimation = new BabylonAnimation { name = bone.name + "Animation", property = "_matrix", dataType = (int)BabylonAnimation.DataType.Matrix, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, enableBlending = false, blendingSpeed = 0.0f, framePerSecond = frameRate, keys = keys.ToArray() }; bone.animation = babylonAnimation; } if (AnimationMode.InAnimationMode()) { AnimationMode.StopAnimationMode(); } /* * // * // TODO: Format Custom Curve Keys * // * string property = "none"; * if (pxkeys.Count > 0) * { * property = "metadata.state.animPosition.x"; * anims.Add(new BabylonAnimation * { * dataType = (int)BabylonAnimation.DataType.Float, * name = property + " animation", * keys = pxkeys.ToArray(), * framePerSecond = frameRate, * enableBlending = false, * blendingSpeed = 0.0f, * loopBehavior = (int)BabylonAnimation.LoopBehavior.Cycle, * property = property * }); * } * // * // Cache Babylon Animation Keys * // * if (anims.Count > 0) * { * List<BabylonAnimation> sourceAnimiamtions = null; * if (SceneBuilder.AnimationCurveKeys.ContainsKey(sourceId)) { * sourceAnimiamtions = SceneBuilder.AnimationCurveKeys[sourceId]; * } else { * sourceAnimiamtions = new List<BabylonAnimation>(); * SceneBuilder.AnimationCurveKeys.Add(sourceId, sourceAnimiamtions); * } * foreach (var anim in anims) { * sourceAnimiamtions.Add(anim); * } * } */ }
public GameObject GenerateUnityObject(StaticMeshData playable, Context ctx) { int frameStart = playable.AbsoluteTimeOffset - playable.TrimIn; int frameLength = playable.GetFrameCount(ctx.fps) + playable.TrimIn + playable.TrimOut; var playableObj = MakePlayableBaseObject(playable, ref ctx, frameStart / ctx.fps, frameLength / ctx.fps); var transformAnchor = new GameObject("TransformAnchor"); transformAnchor.transform.SetParent(playableObj.transform, false); var pathForName = AnimationUtility.CalculateTransformPath(transformAnchor.transform, ctx.rootTransform); List <Material> materials = new List <Material>(); int matIndex = 0; foreach (var matData in playable.Materials) { var mat = MeshUtils.MaterialFromData(matData, baseMaterial); mat.name = pathForName + "_material" + (matIndex++).ToString(); ctx.ctx.AddObjectToAsset(mat.name, mat); if (mat.mainTexture) { ctx.ctx.AddObjectToAsset(mat.name + "_diffuse", mat.mainTexture); } materials.Add(mat); m_Materials.Add(new SerializableIdentifier(mat)); } int partIndex = 0; foreach (var part in playable.Frames) { var partObj = new GameObject("MeshPart"); var mf = partObj.AddComponent <MeshFilter>(); var mr = partObj.AddComponent <MeshRenderer>(); partObj.transform.SetParent(transformAnchor.transform, false); part.Transform.ApplyTo(partObj.transform); mr.sharedMaterial = materials[part.MaterialIndex]; mf.sharedMesh = MeshUtils.MeshFromData(part); mf.sharedMesh.name = pathForName + "_mesh" + (partIndex).ToString(); ctx.ctx.AddObjectToAsset(mf.sharedMesh.name, mf.sharedMesh); totalVertices += mf.sharedMesh.vertexCount; } var groupTrack = ctx.parentTimeline.CreateTrack <GroupTrack>(null, playable.displayName); ctx.ctx.AddObjectToAsset(pathForName + "_GroupTrack", groupTrack); double clipDuration = 1.0 / stage.fps; if (playable.InstanceMap.Count > 1) { var animTrack = ctx.parentTimeline.CreateTrack <AnimationTrack>(groupTrack, pathForName + "_TransformTrack"); ctx.director.SetGenericBinding(animTrack, ctx.animator); ctx.ctx.AddObjectToAsset(pathForName + "_TransformTrack", animTrack); var animationClip = MakeAnimationClip(playable.InstanceMap, null, AnimationUtility.CalculateTransformPath(transformAnchor.transform, ctx.parentTransform)); animationClip.name = pathForName + "_animation"; ctx.ctx.AddObjectToAsset(pathForName + "_animation", animationClip); var timelineClip = animTrack.CreateClip(animationClip); timelineClip.start = playable.TrimIn; timelineClip.displayName = playable.displayName; typeof(TimelineClip).GetProperty("preExtrapolationMode").SetValue(timelineClip, LOOP_MAPPING[playable.LoopIn], null); typeof(TimelineClip).GetProperty("postExtrapolationMode").SetValue(timelineClip, LOOP_MAPPING[playable.LoopOut], null); clipDuration = timelineClip.duration; ctx.ctx.AddObjectToAsset(pathForName + "_asset", timelineClip.asset); } else { playable.InstanceMap[0].ApplyTo(transformAnchor.transform); } /* * var activeTrack = ctx.parentTimeline.CreateTrack<ActivationTrack>(groupTrack, pathForName + "_Activation"); * ctx.ctx.AddObjectToAsset(pathForName + "_Activation", activeTrack); * * ctx.director.SetGenericBinding(activeTrack, playableObj); * * var clip = activeTrack.CreateDefaultClip(); * clip.start = playable.LoopIn != AnimVR.LoopType.OneShot ? 0 : playable.TrimIn; * clip.duration = playable.LoopOut != AnimVR.LoopType.OneShot ? ctx.parentTimeline.fixedDuration - clip.start : (playable.TrimIn - clip.start) + clipDuration; * * ctx.ctx.AddObjectToAsset(pathForName + "_activeAsset", clip.asset);*/ return(playableObj); }
public AnimationClip MakeAnimationClip(List <SerializableTransform> frames, List <float> times, string path) { var xCurve = new AnimationCurve(); var yCurve = new AnimationCurve(); var zCurve = new AnimationCurve(); var rotXCurve = new AnimationCurve(); var rotYCurve = new AnimationCurve(); var rotZCurve = new AnimationCurve(); var rotWCurve = new AnimationCurve(); var scaleXCurve = new AnimationCurve(); var scaleYCurve = new AnimationCurve(); var scaleZCurve = new AnimationCurve(); for (int i = 0; i < frames.Count; i++) { var frame = frames[i]; var time = times != null ? times[i] : (i / stage.fps); xCurve.AddKey(new Keyframe(time, frame.pos.x)); //, float.NegativeInfinity, float.PositiveInfinity)); yCurve.AddKey(new Keyframe(time, frame.pos.y)); //, float.NegativeInfinity, float.PositiveInfinity)); zCurve.AddKey(new Keyframe(time, frame.pos.z)); //, float.NegativeInfinity, float.PositiveInfinity)); rotXCurve.AddKey(new Keyframe(time, frame.rot.x)); //, float.NegativeInfinity, float.PositiveInfinity)); rotYCurve.AddKey(new Keyframe(time, frame.rot.y)); //, float.NegativeInfinity, float.PositiveInfinity)); rotZCurve.AddKey(new Keyframe(time, frame.rot.z)); //, float.NegativeInfinity, float.PositiveInfinity)); rotWCurve.AddKey(new Keyframe(time, frame.rot.w)); //, float.NegativeInfinity, float.PositiveInfinity)); scaleXCurve.AddKey(new Keyframe(time, frame.scl.x)); //, float.NegativeInfinity, float.PositiveInfinity)); scaleYCurve.AddKey(new Keyframe(time, frame.scl.y)); //, float.NegativeInfinity, float.PositiveInfinity)); scaleZCurve.AddKey(new Keyframe(time, frame.scl.z)); //, float.NegativeInfinity, float.PositiveInfinity)); AnimationUtility.SetKeyBroken(xCurve, i, true); AnimationUtility.SetKeyBroken(yCurve, i, true); AnimationUtility.SetKeyBroken(zCurve, i, true); AnimationUtility.SetKeyBroken(scaleXCurve, i, true); AnimationUtility.SetKeyBroken(scaleYCurve, i, true); AnimationUtility.SetKeyBroken(scaleZCurve, i, true); AnimationUtility.SetKeyBroken(rotXCurve, i, true); AnimationUtility.SetKeyBroken(rotYCurve, i, true); AnimationUtility.SetKeyBroken(rotZCurve, i, true); AnimationUtility.SetKeyBroken(rotWCurve, i, true); AnimationUtility.SetKeyLeftTangentMode(xCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(yCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(zCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(rotXCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(rotYCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(rotZCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(rotWCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(scaleXCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(scaleYCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyLeftTangentMode(scaleZCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(xCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(yCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(zCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(rotXCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(rotYCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(rotZCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(rotWCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(scaleXCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(scaleYCurve, i, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(scaleZCurve, i, AnimationUtility.TangentMode.Constant); } var animationClip = new AnimationClip(); #pragma warning disable CS0618 // Type or member is obsolete AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localPosition.x", xCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localPosition.y", yCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localPosition.z", zCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localRotation.x", rotXCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localRotation.y", rotYCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localRotation.z", rotZCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localRotation.w", rotWCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localScale.x", scaleXCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localScale.y", scaleYCurve); AnimationUtility.SetEditorCurve(animationClip, path, typeof(Transform), "localScale.z", scaleZCurve); #pragma warning restore CS0618 // Type or member is obsolete animationClip.frameRate = stage.fps; return(animationClip); }
/// <summary> /// make the AnimEvent and EventGO to be matched /// maybe not one-one match, multiple animEvent could match same EventGO /// </summary> private void _MatchEventGOAndAnimEvent() { ////////////////////////////////////////////////// // 1. for each AnimEvent, if there is not a corresponding eventGO, create it; // 2. for each eventGO, if there is not a corresponding AnimEvent, the delete the eventGO ////////////////////////////////////////////////// //if( _IsAnimEventPopupOpen() ) //{ // return; //don't execute matching if the AnimEventPopup is open //} // create a Dictionary for eventGO for (int idx = 0; idx < m_evtGoRoot.childCount; ++idx) { Transform ctr = m_evtGoRoot.GetChild(idx); m_evtGORefDict[ctr] = false; } // get the AnimEvent list AnimationEvent[] events = AnimationUtility.GetAnimationEvents(m_CurClip); // step 1 for (int idx = 0; idx < events.Length; ++idx) { AnimationEvent evt = events[idx]; string goName = evt.stringParameter; string funcName = evt.functionName; if (goName == null) { Dbg.LogWarn("CCEditor._MatchEventGOAndAnimEvent: found an event not specifying the GOName, at time: {0}", evt.time); ArrayUtility.RemoveAt(ref events, idx); --idx; } Transform oneTr = m_evtGoRoot.Find(goName); if (null == oneTr) { //create the go GameObject newEvtGO = new GameObject(goName); Misc.AddChild(m_evtGoRoot, newEvtGO); Dbg.Log("Sync AnimEvent with EventGO: create EventGO for: {0}", goName); //add component according to the funcName, the init-work should be executed by the MB's awake() or start() //CC_EvtActions newAct = newEvtGO.AddComponent("CC_" + funcName) as CC_EvtActions; //Dbg.Assert(m_CC != null, "CCEditor._MatchEventGOAndAnimEvent: failed to get CutsceneController"); //newAct.CC = m_CC; string tpName = "MH.CC_" + funcName; Type tp = RCall.GetTypeFromString(tpName); Dbg.Assert(tp != null, "CCEditor._MatchEventGOAndAnimEvent: failed to get type from string: {0}", tpName); CC_EvtActions newAct = newEvtGO.AddComponent(tp) as CC_EvtActions; Dbg.Assert(m_CC != null, "CCEditor._MatchEventGOAndAnimEvent: failed to get CutsceneController"); newAct.CC = m_CC; } else { m_evtGORefDict[oneTr] = true; //this event go is ref-ed, don't delete it } } // step 2 for (var ie = m_evtGORefDict.GetEnumerator(); ie.MoveNext();) { var pr = ie.Current; bool inUse = pr.Value; if (!inUse) { Transform tr = pr.Key; Dbg.Log("Sync AnimEvent with EventGO: delete EventGO: {0}", tr.name); GameObject.DestroyImmediate(tr.gameObject); } } m_evtGORefDict.Clear(); //clear the tmp data }
public GameObject MakePlayableBaseObject(PlayableData playable, ref Context ctx, float start, float duration) { start += ctx.frameOffset / ctx.fps; var hackyStart = Mathf.Max(0, start); var clipIn = hackyStart - start; start = hackyStart; var playableObj = new GameObject(playable.displayName ?? "Layer"); playableObj.transform.parent = ctx.parentTransform; playableObj.transform.localPosition = playable.transform.pos.V3; playableObj.transform.localRotation = playable.transform.rot.Q; playableObj.transform.localScale = playable.transform.scl.V3; playableObj.SetActive(playable.isVisible); var path = AnimationUtility.CalculateTransformPath(playableObj.transform, ctx.rootTransform); var director = playableObj.AddComponent <PlayableDirector>(); var timelineAsset = TimelineAsset.CreateInstance <TimelineAsset>(); timelineAsset.name = path + "_Timeline"; timelineAsset.editorSettings.fps = stage.fps; timelineAsset.durationMode = TimelineAsset.DurationMode.FixedLength; timelineAsset.fixedDuration = playable.TrimLoopOut == AnimVR.TrimLoopType.Infinity ? duration : 1000000; ctx.ctx.AddObjectToAsset(timelineAsset.name, timelineAsset); director.extrapolationMode = playable.TrimLoopOut == AnimVR.TrimLoopType.OneShot ? DirectorWrapMode.None : playable.TrimLoopOut == AnimVR.TrimLoopType.Loop ? DirectorWrapMode.Loop : playable.TrimLoopOut == AnimVR.TrimLoopType.Hold ? DirectorWrapMode.Hold : DirectorWrapMode.Hold; director.playableAsset = timelineAsset; ctx.animator = playableObj.AddComponent <Animator>(); var controlTrack = ctx.parentTimeline.CreateTrack <AnimVR.Timeline.AnimControlTrack>(null, playableObj.name); ctx.ctx.AddObjectToAsset(path + "_Control", controlTrack); var controlClip = controlTrack.CreateDefaultClip(); controlClip.displayName = playableObj.name; controlClip.start = start == 0 ? start : (start - 0.000001); controlClip.duration = (start == 0 ? -0.000001 : 0) + duration - clipIn; controlClip.clipIn = clipIn; controlClip.blendInCurveMode = controlClip.blendOutCurveMode = TimelineClip.BlendCurveMode.Manual; controlClip.mixInCurve = AnimationCurve.Linear(0, 0, 1, 1); controlClip.mixOutCurve = AnimationCurve.Linear(0, 1, 1, 0); controlClip.easeInDuration = playable.TrimLoopIn == AnimVR.TrimLoopType.Infinity || playable.FadeIn < 0.01f ? 0 : playable.FadeIn / ctx.fps; controlClip.easeOutDuration = playable.TrimLoopOut == AnimVR.TrimLoopType.Infinity || playable.FadeOut < 0.01f ? 0 : playable.FadeOut / ctx.fps; typeof(TimelineClip).GetProperty("preExtrapolationMode").SetValue(controlClip, TRIM_LOOP_MAPPING[playable.TrimLoopIn], null); typeof(TimelineClip).GetProperty("postExtrapolationMode").SetValue(controlClip, TRIM_LOOP_MAPPING[playable.TrimLoopOut], null); var controlAsset = controlClip.asset as AnimVR.Timeline.AnimControlPlayableAsset; controlAsset.name = playable.name; ctx.director.SetGenericBinding(controlAsset, playableObj); ctx.ctx.AddObjectToAsset(path + "_ControlAsset", controlAsset); ctx.parentTimeline = timelineAsset; ctx.director = director; ctx.parentTransform = playableObj.transform; return(playableObj); }
public override void Serialize(SerializedAssets serializedAssets, object[] serializeOptions, NodeBase objNode, List <Action <NodeBase> > postSerializeActions) { //Make sure this is always 36 characters long. this.referenceID = this.rootNode.GenerateID(); #if UNITY_EDITOR string assetPath = AssetDatabase.GetAssetPath(animationClip); NodeBase animationNode = CheckSharedAnimationClip(this.rootNode, assetPath); if (animationNode != null) { UInt32 animationID = animationNode.GetReferenceID(); ComponentNode componentNode = new ComponentNode(PCFResourceType.ANIMATIONCLIPREFERENCE, referenceID, null, typeof(UnityEngine.AnimationClip).Name.ToString()); objNode.AddChildNode(componentNode); byte[] bytes = BitConverter.GetBytes(animationID); JObject metaData = new JObject(); metaData["fieldName"] = this.fieldName; AssetResource resource = new AssetResource(false); byte[] metaDataBuffer = System.Text.Encoding.UTF8.GetBytes(metaData.ToString(Formatting.None)); resource.Serialize(referenceID, MetaDataType.JSON, metaDataBuffer, bytes); serializedAssets.AddResource(referenceID, PCFResourceType.ANIMATIONCLIPREFERENCE, resource); this.pointedID = animationID; } else { ComponentNode componentNode = new ComponentNode(PCFResourceType.ANIMATIONCLIP, referenceID, assetPath, typeof(UnityEngine.AnimationClip).Name.ToString()); objNode.AddChildNode(componentNode); EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(animationClip); AnimationCurve initialCurve = AnimationUtility.GetEditorCurve(animationClip, curveBindings[0]); SerializedAnimationClip serializedAnimationClip = new SerializedAnimationClip(); serializedAnimationClip.PostWrapMode = (int)initialCurve.postWrapMode; serializedAnimationClip.PreWrapMode = (int)initialCurve.preWrapMode; for (int i = 0; i < curveBindings.Length; i++) { string propertyName = curveBindings[i].propertyName; AnimationCurve animCurve = AnimationUtility.GetEditorCurve(animationClip, curveBindings[i]); SerializedAnimationKeyFrame[] serializedKeyFrames = new SerializedAnimationKeyFrame[animCurve.keys.Length]; for (int j = 0; j < animCurve.keys.Length; j++) { serializedKeyFrames[j] = new SerializedAnimationKeyFrame(); serializedKeyFrames[j].InTagent = animCurve.keys[j].inTangent; serializedKeyFrames[j].OutTangent = animCurve.keys[j].outTangent; serializedKeyFrames[j].Time = animCurve.keys[j].time; serializedKeyFrames[j].Value = animCurve.keys[j].value; } serializedAnimationClip.AddChannel(AnimationClipUtils.GetAnimationClipChannelName(propertyName), serializedKeyFrames); } JObject metaData = new JObject(); metaData["name"] = animationClip.name; metaData["frameRate"] = animationClip.frameRate; metaData["wrapMode"] = (int)animationClip.wrapMode; metaData["legacy"] = animationClip.legacy; metaData["fieldName"] = this.fieldName; byte[] data = ProtocolBufferSerializer.SerializeAnimationClipData(serializedAnimationClip); AssetResource resource = new AssetResource(false); byte[] metaDataBuffer = System.Text.Encoding.UTF8.GetBytes(metaData.ToString(Formatting.None)); resource.Serialize(referenceID, MetaDataType.JSON, metaDataBuffer, data); serializedAssets.AddResource(referenceID, PCFResourceType.ANIMATIONCLIP, resource); //Nodes store their resource when serializing componentNode.SetSerializer(this); //Make sure caller can get the actual material referenceID when serializing its metadata. this.pointedID = this.referenceID; } #endif }
//Creates the animation public AnimationClip CreateClip(Object obj, string clipName, int startFrame, int endFrame, float frameRate, float timeBetween, bool pingPong) { string path = AssetDatabase.GetAssetPath(obj); Object[] sprites = AssetDatabase.LoadAllAssetsAtPath(path); int frameCount = endFrame - startFrame + 1; float frameLength = 1f / timeBetween; AnimationClip clip = new AnimationClip(); clip.frameRate = frameRate; EditorCurveBinding curveBinding = new EditorCurveBinding(); curveBinding.type = typeof(SpriteRenderer); curveBinding.propertyName = "m_Sprite"; ObjectReferenceKeyframe[] keyFrames; if (!pingPong) { keyFrames = new ObjectReferenceKeyframe[frameCount + 1]; } else { keyFrames = new ObjectReferenceKeyframe[frameCount * 2 + 1]; } int frameNumber = 0; for (int i = startFrame; i < endFrame + 1; i++, frameNumber++) { ObjectReferenceKeyframe tempKeyFrame = new ObjectReferenceKeyframe(); tempKeyFrame.time = frameNumber * frameLength; tempKeyFrame.value = sprites[i]; keyFrames[frameNumber] = tempKeyFrame; } //sets up ping pong behaviour if (pingPong) { for (int i = endFrame; i >= startFrame; i--, frameNumber++) { ObjectReferenceKeyframe tempKeyFrame = new ObjectReferenceKeyframe(); tempKeyFrame.time = frameNumber * frameLength; tempKeyFrame.value = sprites[i]; keyFrames[frameNumber] = tempKeyFrame; } } ObjectReferenceKeyframe lastSprite = new ObjectReferenceKeyframe(); lastSprite.time = frameNumber * frameLength; lastSprite.value = sprites[startFrame]; keyFrames[frameNumber] = lastSprite; clip.name = clipName; AnimationUtility.SetObjectReferenceCurve(clip, curveBinding, keyFrames); //Creates the animation asset inside of the Animations folder AssetDatabase.CreateAsset(clip, ("Assets/" + clipName + ".anim")); return(clip); }
static MotionDataInAsset buildMotionData(AnimationClip[] animationClips) { return(new MotionDataInAsset { Motions = queryMotions(animationClips).ToArray() }); IEnumerable <MotionDataUnit> queryMotions(AnimationClip[] clips) => // アニメーションクリップを列挙 from clip in clips select new MotionDataUnit { MotionName = clip.name, LocalAABB = clip.localBounds, WrapMode = clip.wrapMode, TimeLength = clip.length, Sections = buildSections(clip).ToArray() }; IEnumerable <SectionDataUnit> buildSections(AnimationClip clip) => // 全プロパティストリームを列挙( .x .y などの要素レベルの binding ) from binding in AnimationUtility.GetCurveBindings(clip) where !binding.path.StartsWith("_") // セクションでグループ化( m_LocalPosition など)&ソート group binding by Path.GetFileNameWithoutExtension(binding.propertyName) into section_group orderby section_group.Key select new SectionDataUnit { SectionName = section_group.Key, Streams = queryKeyStreams(clip, section_group).ToArray() }; IEnumerable <StreamDataUnit> queryKeyStreams(AnimationClip clip, IGrouping <string, EditorCurveBinding> section_group) => // ストリームでグループ化&ソート from binding in section_group group binding by binding.path into stream_group orderby stream_group.Key select new StreamDataUnit { StreamPath = stream_group.Key, keys = queryKeys(clip, stream_group).ToArray() }; IEnumerable <KeyDataUnit> queryKeys(AnimationClip clip, IGrouping <string, EditorCurveBinding> stream_group) => // キーを列挙 from stream in stream_group from keyframe in AnimationUtility.GetEditorCurve(clip, stream).keys select(element : Path.GetExtension(stream.propertyName)[1], keyFrame : keyframe) into keyBind // 時間でグループ化&ソート group keyBind by keyBind.keyFrame.time into time_group orderby time_group.Key // 要素で辞書化し、添え字アクセスできるようにする。 let elements = time_group.ToDictionary(x => x.element, x => x.keyFrame.value) select new KeyDataUnit { Time = time_group.Key, Value = elements.ContainsKey('w') ? new Vector4(elements['x'], elements['y'], elements['z'], elements['w']) : new Vector4(elements['x'], elements['y'], elements['z'], 0.0f) }; }
private void RemoveFromCandidates(PropertyModification[] modifications) { if (!(this.m_CandidateClip == null)) { EditorCurveBinding[] array = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, this.state.activeRootGameObject, this.m_CandidateClip); if (array.Length != 0) { Undo.RegisterCompleteObjectUndo(this.m_CandidateClip, "Edit Candidate Curve"); for (int i = 0; i < array.Length; i++) { EditorCurveBinding binding = array[i]; if (binding.isPPtrCurve) { AnimationUtility.SetObjectReferenceCurve(this.m_CandidateClip, binding, null); } else { AnimationUtility.SetEditorCurve(this.m_CandidateClip, binding, null); } } if (AnimationUtility.GetCurveBindings(this.m_CandidateClip).Length == 0 && AnimationUtility.GetObjectReferenceCurveBindings(this.m_CandidateClip).Length == 0) { this.ClearCandidates(); } } } }
private static System.Type GetEditorCurveValueType(EditorCurveBinding curveBinding) { CurveBindingUtility.PrepareHierarchy(curveBinding); return AnimationUtility.GetEditorCurveValueType(CurveBindingUtility.s_Root, curveBinding); }
public static System.Type GetEditorCurveValueType(GameObject rootGameObject, EditorCurveBinding curveBinding) { if ((UnityEngine.Object) rootGameObject != (UnityEngine.Object) null) return AnimationUtility.GetEditorCurveValueType(rootGameObject, curveBinding); return CurveBindingUtility.GetEditorCurveValueType(curveBinding); }
public void ExportAnimation(AnimationClip clipAnimation, PrefabContext prefabContext) { if (!_engine.Options.ExportAnimations) { return; } var name = GetSafeFileName(_engine.DecorateName(clipAnimation.name)); //_assetCollection.AddAnimationPath(clipAnimation, fileName); var aniFilePath = EvaluateAnimationName(clipAnimation, prefabContext); using (var file = _engine.TryCreate(clipAnimation.GetKey(), aniFilePath, ExportUtils.GetLastWriteTimeUtc(clipAnimation))) { if (file == null) { return; } using (var writer = new BinaryWriter(file)) { writer.Write(new byte[] { 0x55, 0x41, 0x4e, 0x49 }); WriteStringSZ(writer, _engine.DecorateName(clipAnimation.name)); writer.Write(clipAnimation.length); if (clipAnimation.legacy) { WriteTracksAsIs(clipAnimation, writer); } else { var allBindings = AnimationUtility.GetCurveBindings(clipAnimation); var rootBones = new HashSet <string>(allBindings.Select(_ => GetRootBoneName(_)).Where(_ => _ != null)); if (rootBones.Count != 1) { Debug.LogWarning(aniFilePath + ": Multiple root bones found (" + string.Join(", ", rootBones.ToArray()) + "), falling back to curve export"); WriteTracksAsIs(clipAnimation, writer); } else { var rootBoneName = rootBones.First(); var rootGOs = _skeletons .Select(_ => _.name == rootBoneName ? _.transform : _.transform.Find(rootBoneName)) .Where(_ => _ != null).ToList(); if (rootGOs.Count == 1) { WriteSkelAnimation(clipAnimation, rootGOs.First().gameObject, writer); } else { Debug.LogWarning(aniFilePath + ": Multiple game objects found that match root bone name, falling back to curve export"); WriteTracksAsIs(clipAnimation, writer); } } } } } }
private void MakeAnimationCurves(GameObject root, AnimationClip animClip, Animation animation) { acb = new AnimationCurveBuilder(); //Get a list of all sprites on this GO var allSprites = root.GetComponentsInChildren <Transform>(true).Select(sr => AnimationUtility.CalculateTransformPath(sr.transform, root.transform)); //Add a key for all objects on the first frame SetGameObjectForKey(root, animClip, animation.MainlineKeys.First(), 0); foreach (var mainlineKey in animation.MainlineKeys) { var visibleSprites = SetGameObjectForKey(root, animClip, mainlineKey); var hiddenSprites = allSprites.Except(visibleSprites); HideSprites(root, hiddenSprites, mainlineKey.Time); } switch (animation.LoopType) { case LoopType.True: //Cycle back to first frame SetGameObjectForKey(root, animClip, animation.MainlineKeys.First(), animation.Length); break; case LoopType.False: //Duplicate the last key at the end time of the animation SetGameObjectForKey(root, animClip, animation.MainlineKeys.Last(), animation.Length); break; default: Debug.LogWarning("Unsupported loop type: " + animation.LoopType.ToString()); break; } //Add the curves to our animation clip //NOTE: This MUST be done before modifying the settings, thus the double switch statement acb.AddCurves(animClip); foreach (var sprite in spriteChangeKeys) { if (sprite.Value.Count > 0) { BuildSpriteChangeCurve(ref animClip, sprite); } } //Set the loop/wrap settings for the animation clip var animSettings = AnimationUtility.GetAnimationClipSettings(animClip); switch (animation.LoopType) { case LoopType.True: animClip.wrapMode = WrapMode.Loop; animSettings.loopTime = true; break; case LoopType.False: animClip.wrapMode = WrapMode.ClampForever; break; case LoopType.PingPong: animClip.wrapMode = WrapMode.PingPong; animSettings.loopTime = true; break; default: Debug.LogWarning("Unsupported loop type: " + animation.LoopType.ToString()); break; } animClip.SetAnimationSettings(animSettings); //Debug.Log(string.Format("Setting animation {0} to {1} loop mode (WrapMode:{2} LoopTime:{3}) ", animClip.name, animation.LoopType, animClip.wrapMode, animSettings.loopTime)); }
//Defines Gui Features void OnGUI() { if (selectedObject != null) { EditorGUILayout.LabelField("Animations for " + selectedObject.name); EditorGUILayout.Separator(); controllerName = EditorGUILayout.TextField("Controller Name", controllerName); numAnimations = EditorGUILayout.IntField("How many animations", numAnimations); for (int i = 0; i < numAnimations; i++) { //Allows the user to name the animation animationNames[i] = EditorGUILayout.TextField("Animation Name", animationNames[i]); //Animation length modifiers for GUI EditorGUILayout.BeginHorizontal(); startFrames[i] = EditorGUILayout.IntField("Start Frame", startFrames[i]); endFrames[i] = EditorGUILayout.IntField("End Frame", endFrames[i]); EditorGUILayout.EndHorizontal(); //Frame Rate modifiers for GUI EditorGUILayout.BeginHorizontal(); clipFrameRate[i] = EditorGUILayout.FloatField("Frame Rate", clipFrameRate[i]); clipTimeBetween[i] = EditorGUILayout.FloatField("Frame Spacing", clipTimeBetween[i]); EditorGUILayout.EndHorizontal(); //Animation behaviour modifiers for GUI EditorGUILayout.BeginHorizontal(); loop[i] = EditorGUILayout.Toggle("Loop", loop[i]); pingPong[i] = EditorGUILayout.Toggle("Ping Pong", pingPong[i]); EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); } //if the user presses the create button if (GUILayout.Button("Create")) { UnityEditor.Animations.AnimatorController controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath( ("Assets/" + controllerName + ".controller")); for (int i = 0; i < numAnimations; i++) { //apply changes to the Animation AnimationClip tempClip = CreateClip(selectedObject, animationNames[i], startFrames[i], endFrames[i], clipFrameRate[i], clipTimeBetween[i], pingPong[i]); //Sets up loop behaviour if (loop[i]) { AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(tempClip); settings.loopTime = true; settings.loopBlend = true; AnimationUtility.SetAnimationClipSettings(tempClip, settings); } controller.AddMotion(tempClip); } //Creates a prefab of the given Ojbect PrefabUtility.InstantiatePrefab(selectedObject); Instantiate(selectedObject); //Refreshs the AssetDatabase AssetDatabase.Refresh(); } } }
/// <summary> /// 创建动画文件 /// </summary> /// <param name="type">动画的类型,用于标记是Sprite或Image</param> /// <param name="sprites">Sprite帧列表</param> /// <param name="textureAssetNamePath">如:Assets/Textures/idle</param> private static void CreateAnimationFile(AnimationType type, Sprite[] sprites, string textureAssetNamePath) { int len = sprites.Length; AnimationClip animationClip = new AnimationClip(); //帧频 animationClip.frameRate = FrameRate; //设置循环 SerializedObject serializedClip = new SerializedObject(animationClip); SerializedProperty clipSettings = serializedClip.FindProperty("m_AnimationClipSettings"); SerializedProperty loopTimeSet = clipSettings.FindPropertyRelative("m_LoopTime"); loopTimeSet.boolValue = true; serializedClip.ApplyModifiedProperties(); //动画曲线 EditorCurveBinding curveBinding = new EditorCurveBinding(); if (type == AnimationType.Sprite) { curveBinding.type = typeof(SpriteRenderer); } else { curveBinding.type = typeof(Image); } curveBinding.path = ""; curveBinding.propertyName = "m_Sprite"; //添加帧 ObjectReferenceKeyframe[] keyframes = new ObjectReferenceKeyframe[len]; const float frameTime = 1f / FrameRate; for (int i = 0; i < len; i++) { Sprite sprite = sprites[i]; ObjectReferenceKeyframe keyframe = new ObjectReferenceKeyframe(); keyframe.time = frameTime * i; keyframe.value = sprite; keyframes[i] = keyframe; } AnimationUtility.SetObjectReferenceCurve(animationClip, curveBinding, keyframes); //创建.anim文件 string animFilePath; if (type == AnimationType.Sprite) { animFilePath = textureAssetNamePath + "_sprite.anim"; } else { animFilePath = textureAssetNamePath + "_image.anim"; } AssetDatabase.CreateAsset(animationClip, animFilePath); //创建.controller文件 if (s_isCreateAnimatorController) { string controllerFilePath; if (type == AnimationType.Sprite) { controllerFilePath = textureAssetNamePath + "_sprite.controller"; } else { controllerFilePath = textureAssetNamePath + "_image.controller"; } AnimatorController animatorController = AnimatorController.CreateAnimatorControllerAtPath(controllerFilePath); AnimatorControllerLayer layer = animatorController.layers[0]; AnimatorStateMachine stateMachine = layer.stateMachine; AnimatorState state = stateMachine.AddState(animationClip.name); state.motion = animationClip; stateMachine.AddEntryTransition(state); } //AssetDatabase.SaveAssets(); }
static void ImportBundle() { string path = EditorUtility.OpenFilePanel("Bit exported bundle", "", "zip"); if (path == "") { return; } try { string tempDirectory = Application.dataPath + "/Resources/Bit/Import"; FileUtil.DeleteFileOrDirectory(tempDirectory); ZipFile.ExtractToDirectory(path, tempDirectory); BitProject currentProject = JsonUtility.FromJson <BitProject>(System.IO.File.ReadAllText(tempDirectory + "/bit.json")); FileUtil.DeleteFileOrDirectory(Application.dataPath + "/Resources/Bit/" + currentProject.id); string projectDirectory = "Assets/Resources/Bit/" + currentProject.id; AssetDatabase.CreateFolder("Assets/Resources/Bit", currentProject.id); AssetDatabase.CreateFolder("Assets/Resources/Bit/" + currentProject.id, "assets"); AssetDatabase.CreateFolder("Assets/Resources/Bit/" + currentProject.id, "prefabs"); FileUtil.ReplaceDirectory(tempDirectory, Application.dataPath + "/Resources/Bit/" + currentProject.id + "/assets"); FileUtil.DeleteFileOrDirectory(tempDirectory); AssetDatabase.Refresh(); Material defaultMaterial = new Material(Shader.Find("Sprites/Diffuse")); AssetDatabase.CreateAsset(defaultMaterial, "Assets/Resources/Bit/" + currentProject.id + "/sprite.mat"); foreach (BitAssetData asset in currentProject.assets) { string filePath = "Bit/" + currentProject.id + "/assets/" + asset.sprite.Replace(".png", ""); Texture2D texture = Resources.Load <Texture2D> (filePath); string texturePath = AssetDatabase.GetAssetPath(texture); TextureImporter ti = AssetImporter.GetAtPath(texturePath) as TextureImporter; ti.isReadable = true; ti.filterMode = FilterMode.Point; ti.spriteImportMode = SpriteImportMode.Multiple; ti.compressionQuality = 100; ti.textureCompression = TextureImporterCompression.Uncompressed; List <SpriteMetaData> newData = new List <SpriteMetaData>(); int SliceWidth = (int)asset.tileSize.x; int SliceHeight = (int)asset.tileSize.y; for (int i = 0; i < texture.width; i += SliceWidth) { for (int j = texture.height; j > 0; j -= SliceHeight) { SpriteMetaData smd = new SpriteMetaData(); smd.pivot = new Vector2(0.5f, 0.5f); smd.alignment = 9; smd.name = (texture.height - j) / SliceHeight + ", " + i / SliceWidth; smd.rect = new Rect(i, j - SliceHeight, SliceWidth, SliceHeight); newData.Add(smd); } } ti.spritesheet = newData.ToArray(); AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate); AssetDatabase.Refresh(); List <AnimationClip> animationClips = new List <AnimationClip>(); Sprite[] sprites = Resources.LoadAll <Sprite>(filePath); AnimationClip idleClip = new AnimationClip(); idleClip.frameRate = 60; idleClip.name = "idle"; idleClip.wrapMode = WrapMode.Loop; AnimationClipSettings idleSettings = AnimationUtility.GetAnimationClipSettings(idleClip); idleSettings.loopTime = true; AnimationUtility.SetAnimationClipSettings(idleClip, idleSettings); EditorCurveBinding idleSpriteBinding = new EditorCurveBinding(); idleSpriteBinding.type = typeof(SpriteRenderer); idleSpriteBinding.path = ""; idleSpriteBinding.propertyName = "m_Sprite"; ObjectReferenceKeyframe[] idleSpriteFrames = new ObjectReferenceKeyframe[1]; idleSpriteFrames[0] = new ObjectReferenceKeyframe(); idleSpriteFrames[0].time = 1; idleSpriteFrames[0].value = sprites[asset.defaultTile]; AnimationUtility.SetObjectReferenceCurve(idleClip, idleSpriteBinding, idleSpriteFrames); animationClips.Add(idleClip); foreach (BitAssetAnimation anim in asset.animations) { AnimationClip clip = new AnimationClip(); clip.frameRate = 60; clip.name = anim.name; clip.wrapMode = WrapMode.Loop; AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip); settings.loopTime = true; AnimationUtility.SetAnimationClipSettings(clip, settings); EditorCurveBinding spriteBinding = new EditorCurveBinding(); spriteBinding.type = typeof(SpriteRenderer); spriteBinding.path = ""; spriteBinding.propertyName = "m_Sprite"; ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[anim.tiles.Count]; for (int i = 0; i < (anim.tiles.Count); i++) { spriteKeyFrames[i] = new ObjectReferenceKeyframe(); spriteKeyFrames[i].time = ((float)(i * (anim.frameskip)) / 60f); spriteKeyFrames[i].value = sprites[anim.tiles[i]]; } AnimationUtility.SetObjectReferenceCurve(clip, spriteBinding, spriteKeyFrames); animationClips.Add(clip); } var animatorController = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath( "Assets/Resources/Bit/" + currentProject.id + "/assets/" + asset.id + "_animationController.controller" ); string controllerPath = AssetDatabase.GetAssetPath(animatorController); foreach (AnimationClip a in animationClips) { AssetDatabase.AddObjectToAsset(a, animatorController); AnimatorState state = animatorController.AddMotion(a, 0); state.name = a.name; } AssetDatabase.ImportAsset(controllerPath); GameObject assetGameObject = new GameObject(asset.id); SpriteRenderer assetRenderer = assetGameObject.AddComponent <SpriteRenderer>(); BitAsset assetScript = assetGameObject.AddComponent <BitAsset>(); assetRenderer.material = defaultMaterial; assetRenderer.sprite = sprites[0]; assetRenderer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask; Animator animator = assetGameObject.AddComponent <Animator>(); animator.runtimeAnimatorController = animatorController; assetScript.animator = animator; assetScript.assetRenderer = assetRenderer; PrefabUtility.SaveAsPrefabAssetAndConnect( assetGameObject, "Assets/Resources/Bit/" + currentProject.id + "/prefabs/" + asset.id + ".prefab", InteractionMode.AutomatedAction ); DestroyImmediate(assetGameObject); } GameObject rootGameObject = new GameObject(currentProject.name); GameObject canvasGameObject = new GameObject("canvas"); canvasGameObject.transform.parent = rootGameObject.transform; SpriteMask spriteMask = canvasGameObject.AddComponent <SpriteMask>(); SpriteRenderer canvasRenderer = canvasGameObject.AddComponent <SpriteRenderer>(); Sprite backgroundSprite = (Sprite)AssetDatabase.LoadAssetAtPath("Assets/Resources/Bit/" + currentProject.id + "/assets/background.png", typeof(Sprite));; spriteMask.sprite = backgroundSprite; canvasRenderer.sprite = backgroundSprite; canvasRenderer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask; canvasRenderer.material = defaultMaterial; Vector3 projectScaleVector = new Vector3(currentProject.scale, currentProject.scale, currentProject.scale); for (int x = currentProject.scene.Count - 1; x >= 0; x--) { List <GameObject> children = new List <GameObject>(); BitEntityData entity = currentProject.scene[x]; BitAssetData assetData = currentProject.getAssetById(entity.assetId); GameObject entityGameObject = new GameObject(currentProject.scene.Count - x + "." + entity.name); entityGameObject.transform.parent = canvasGameObject.transform; BitEntity entityScript = entityGameObject.AddComponent <BitEntity>(); entityScript.animationName = assetData.getAnimationName(entity.data.animationIndex); entity.data.assetId = entity.assetId; entity.data.id = entity.id; entity.data.name = entity.name; entityScript.data = entity.data; entityScript.assetData = assetData; entityScript.assets = new List <BitAsset>(); entityScript.baseScale = currentProject.scale; Vector3 scaleVector = new Vector3( currentProject.scale + (entity.data.scale - 1), currentProject.scale + (entity.data.scale - 1), currentProject.scale + (entity.data.scale - 1) ); UnityEngine.Object assetPrefab = (UnityEngine.Object)AssetDatabase.LoadAssetAtPath("Assets/Resources/Bit/" + currentProject.id + "/prefabs/" + entity.assetId + ".prefab", typeof(UnityEngine.Object)); GameObject currentAsset = PrefabUtility.InstantiatePrefab(assetPrefab) as GameObject; SpriteRenderer assetRenderer = currentAsset.GetComponent <SpriteRenderer>(); string filePath = "Bit/" + currentProject.id + "/assets/" + assetData.sprite.Replace(".png", ""); Sprite[] sprites = Resources.LoadAll <Sprite>(filePath); assetRenderer.sprite = sprites[Mathf.Max(entity.data.defaultTile, 0)]; Color tintColor = new Color( entity.data.tint[0], entity.data.tint[1], entity.data.tint[2] ); tintColor.a = (float)entity.data.alpha / 255f; if ( entity.data.tint[0] == 0 && entity.data.tint[1] == 0 && entity.data.tint[2] == 0 && entity.data.alpha == 0 ) { tintColor.r = 255; tintColor.g = 255; tintColor.b = 255; tintColor.a = 1f; } assetRenderer.flipX = entity.data.flipX; assetRenderer.flipY = entity.data.flipY; assetRenderer.color = tintColor; currentAsset.transform.parent = entityGameObject.transform; currentAsset.transform.eulerAngles = new Vector3(0, 0, -entity.data.rotation); currentAsset.transform.localScale = scaleVector; if (entity.data.mirrorX && entity.data.mirrorY) { float xPos = (entity.data.mirror.x / 2) * renderScaleMultiplier; float yPos = (entity.data.mirror.y / 2) * renderScaleMultiplier; Vector2 pos1 = new Vector2(-xPos, yPos); // <-- top left corner Vector2 pos2 = new Vector2(xPos, yPos); // <-- top right corner Vector2 pos3 = new Vector2(-xPos, -yPos); // <-- bottom left corner Vector2 pos4 = new Vector2(xPos, -yPos); // <-- bottom right corner currentAsset.transform.localPosition = pos1; List <GameObject> p1Container = new List <GameObject>(); List <GameObject> p2Container = new List <GameObject>(); List <GameObject> p3Container = new List <GameObject>(); List <GameObject> p4Container = new List <GameObject>(); p1Container.Add(currentAsset); GameObject x1 = CloneInstansiatedPrefab( assetPrefab, currentAsset, pos2, Quaternion.Euler(0, 0, entity.data.rotation), entityGameObject.transform ); x1.transform.localScale = scaleVector; SpriteRenderer x1R = x1.GetComponent <SpriteRenderer>(); x1R.flipX = !entity.data.flipX; p2Container.Add(x1); x1.GetComponent <BitAsset>().isMirroredX = true; GameObject y1 = CloneInstansiatedPrefab( assetPrefab, currentAsset, pos3, Quaternion.Euler(0, 0, entity.data.rotation), entityGameObject.transform ); y1.transform.localScale = scaleVector; SpriteRenderer x2R = y1.GetComponent <SpriteRenderer>(); x2R.flipY = !entity.data.flipY; p3Container.Add(y1); y1.GetComponent <BitAsset>().isMirroredX = true; GameObject xy1 = CloneInstansiatedPrefab( assetPrefab, currentAsset, pos4, Quaternion.Euler(0, 0, -entity.data.rotation), entityGameObject.transform ); xy1.transform.localScale = scaleVector; SpriteRenderer x3R = xy1.GetComponent <SpriteRenderer>(); x3R.flipY = !entity.data.flipY; x3R.flipX = !entity.data.flipX; p4Container.Add(xy1); for (int r = 0; r < entity.data.rotateRepeat; r++) { GameObject repeated1 = CloneInstansiatedPrefab( assetPrefab, currentAsset, pos1, Quaternion.Euler(0, 0, -(entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated1.transform.localScale = scaleVector; p1Container.Add(repeated1); GameObject repeated2 = CloneInstansiatedPrefab( assetPrefab, x1, pos2, Quaternion.Euler(0, 0, (entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated2.transform.localScale = scaleVector; p2Container.Add(repeated2); GameObject repeated3 = CloneInstansiatedPrefab( assetPrefab, y1, pos3, Quaternion.Euler(0, 0, (entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated3.transform.localScale = scaleVector; p3Container.Add(repeated3); GameObject repeated4 = CloneInstansiatedPrefab( assetPrefab, xy1, pos4, Quaternion.Euler(0, 0, -(entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated4.transform.localScale = scaleVector; p4Container.Add(repeated4); } GameObject p1G = new GameObject("mirrorXTop"); p1G.transform.parent = entityGameObject.transform; foreach (GameObject child in p1Container) { child.transform.parent = p1G.transform; } children.Add(p1G); GameObject p2G = new GameObject("mirrorYTop"); p2G.transform.parent = entityGameObject.transform; foreach (GameObject child in p2Container) { child.transform.parent = p2G.transform; } children.Add(p2G); GameObject p3G = new GameObject("mirrorXBottom"); p3G.transform.parent = entityGameObject.transform; foreach (GameObject child in p3Container) { child.transform.parent = p3G.transform; } children.Add(p3G); GameObject p4G = new GameObject("mirrorYBottom"); p4G.transform.parent = entityGameObject.transform; foreach (GameObject child in p4Container) { child.transform.parent = p4G.transform; } children.Add(p4G); } else if (entity.data.mirrorX) { float xPos = (entity.data.mirror.x / 2) * renderScaleMultiplier; Vector2 pos1 = new Vector2(-xPos, 0); // <-- left side Vector2 pos2 = new Vector2(xPos, 0); // <-- right side currentAsset.transform.localPosition = pos1; List <GameObject> p1Container = new List <GameObject>(); List <GameObject> p2Container = new List <GameObject>(); p1Container.Add(currentAsset); GameObject x1 = CloneInstansiatedPrefab( assetPrefab, currentAsset, pos2, Quaternion.Euler(0, 0, entity.data.rotation), entityGameObject.transform ); x1.transform.localScale = scaleVector; x1.GetComponent <SpriteRenderer>().flipX = !entity.data.flipX; p2Container.Add(x1); x1.GetComponent <BitAsset>().isMirroredX = true; for (int r = 0; r < entity.data.rotateRepeat; r++) { GameObject repeated1 = CloneInstansiatedPrefab( assetPrefab, currentAsset, pos1, Quaternion.Euler(0, 0, -(entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated1.transform.localScale = scaleVector; p1Container.Add(repeated1); GameObject repeated2 = CloneInstansiatedPrefab( assetPrefab, x1, pos2, Quaternion.Euler(0, 0, (entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated2.transform.localScale = scaleVector; p2Container.Add(repeated2); } GameObject p1G = new GameObject("mirrorXLeft"); p1G.transform.parent = entityGameObject.transform; foreach (GameObject child in p1Container) { child.transform.parent = p1G.transform; } children.Add(p1G); GameObject p2G = new GameObject("mirrorXRight"); p2G.transform.parent = entityGameObject.transform; foreach (GameObject child in p2Container) { child.transform.parent = p2G.transform; } children.Add(p2G); } else if (entity.data.mirrorY) { float yPos = (entity.data.mirror.y / 2) * renderScaleMultiplier; Vector2 pos1 = new Vector2(0, yPos); // <-- top side Vector2 pos2 = new Vector2(0, -yPos); // <-- bottom side currentAsset.transform.localPosition = pos1; List <GameObject> p1Container = new List <GameObject>(); List <GameObject> p2Container = new List <GameObject>(); p1Container.Add(currentAsset); GameObject y1 = CloneInstansiatedPrefab( assetPrefab, currentAsset, pos2, Quaternion.Euler(0, 0, entity.data.rotation), entityGameObject.transform ); y1.transform.localScale = scaleVector; y1.GetComponent <SpriteRenderer>().flipY = !entity.data.flipY; p2Container.Add(y1); for (int r = 0; r < entity.data.rotateRepeat; r++) { GameObject repeated1 = CloneInstansiatedPrefab( assetPrefab, currentAsset, pos1, Quaternion.Euler(0, 0, -(entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated1.transform.localScale = scaleVector; p1Container.Add(repeated1); GameObject repeated2 = CloneInstansiatedPrefab( assetPrefab, y1, pos2, Quaternion.Euler(0, 0, (entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated2.transform.localScale = scaleVector; p2Container.Add(repeated2); } GameObject p1G = new GameObject("mirrorYTop"); p1G.transform.parent = entityGameObject.transform; foreach (GameObject child in p1Container) { child.transform.parent = p1G.transform; } children.Add(p1G); GameObject p2G = new GameObject("mirrorYBottom"); p2G.transform.parent = entityGameObject.transform; foreach (GameObject child in p2Container) { child.transform.parent = p2G.transform; } children.Add(p2G); } else { children.Add(currentAsset); for (int r = 0; r < entity.data.rotateRepeat; r++) { GameObject repeated = CloneInstansiatedPrefab( assetPrefab, currentAsset, currentAsset.transform.position, Quaternion.Euler(0, 0, -(entity.data.rotation + ((r + 1) * entity.data.rotateRepeatSpace))), entityGameObject.transform ); repeated.transform.localScale = scaleVector; children.Add(repeated); } } GameObject entityContainer = new GameObject("container"); entityContainer.transform.parent = entityGameObject.transform; foreach (GameObject child in children) { child.transform.parent = entityContainer.transform; } int countXLeft = 0; int countXRight = 0; for (int xc = entity.data.repeatXCount; xc > 0; --xc) { float xp = 0; if (xc % 2 == 0) { countXLeft++; xp = -(countXLeft * entity.data.repeatXOffset) * renderScaleMultiplier; } else { countXRight++; xp = (countXRight * entity.data.repeatXOffset) * renderScaleMultiplier; } GameObject containerX = Instantiate(entityContainer); containerX.transform.localPosition = new Vector2(xp, 0); containerX.transform.parent = entityGameObject.transform; int countYLeftX = 0; int countYRightX = 0; for (int yc = entity.data.repeatYCount; yc > 0; --yc) { float yp = 0; if (yc % 2 == 0) { countYLeftX++; yp = (countYLeftX * entity.data.repeatYOffset) * renderScaleMultiplier; } else { countYRightX++; yp = -(countYRightX * entity.data.repeatYOffset) * renderScaleMultiplier; } GameObject container1 = Instantiate(entityContainer); container1.transform.localPosition = new Vector2(xp, yp); container1.transform.parent = entityGameObject.transform; } } int countYLeft = 0; int countYRight = 0; for (int yc = entity.data.repeatYCount; yc > 0; --yc) { float yp = 0; if (yc % 2 == 0) { countYLeft++; yp = (countYLeft * entity.data.repeatYOffset) * renderScaleMultiplier; } else { countYRight++; yp = -(countYRight * entity.data.repeatYOffset) * renderScaleMultiplier; } GameObject container1 = Instantiate(entityContainer); container1.transform.localPosition = new Vector2(0, yp); container1.transform.parent = entityGameObject.transform; } entityGameObject.transform.localPosition = new Vector2( entity.data.position.x * renderScaleMultiplier, -entity.data.position.y * renderScaleMultiplier ); } SpriteRenderer[] renderers = rootGameObject.GetComponentsInChildren <SpriteRenderer>(); for (int i = 0; i < renderers.Length; i++) { renderers[i].sortingOrder = 20 + (renderers.Length - i); } canvasRenderer.sortingOrder = 20; BitEntity[] entities = rootGameObject.GetComponentsInChildren <BitEntity>(); for (int i = 0; i < entities.Length; i++) { BitAsset[] assets = entities[i].gameObject.GetComponentsInChildren <BitAsset>(); entities[i].assets = new List <BitAsset>(assets); } PrefabUtility.SaveAsPrefabAssetAndConnect( rootGameObject, "Assets/Resources/Bit/" + currentProject.id + "/" + currentProject.name + ".prefab", InteractionMode.AutomatedAction ); AssetDatabase.SaveAssets(); } finally { AssetDatabase.Refresh(); } }
public static void Import(PictureFileImporterParam param) { if (param.DoNotCopy) { param.strDstFolder = param.strSrcFolder.Replace("\\", "/"); } else { string dstFolder = param.strDstFolder.Replace("\\", "/"); if (param.mode == PictureFileImporterParam.Mode.StreamingAssets) { if (dstFolder.StartsWith(Application.dataPath) && !dstFolder.StartsWith(Path.Combine(Application.dataPath, "StreamingAssets").Replace("\\", "/"))) { Debug.LogError("Files must be located under StreamingAssets folder."); return; } } else { if (dstFolder.StartsWith(Application.dataPath) && dstFolder.StartsWith(Path.Combine(Application.dataPath, "StreamingAssets").Replace("\\", "/"))) { Debug.LogError("Files must not be located under StreamingAssets folder."); return; } } foreach (string relPath in param.RelativeFilePaths) { string strAbsFilePathDst = Path.Combine(param.strDstFolder, relPath).Replace("\\", "/"); if (File.Exists(strAbsFilePathDst)) { File.Delete(strAbsFilePathDst); } string strAbsFilePathSrc = Path.Combine(param.strSrcFolder, relPath).Replace("\\", "/"); Directory.CreateDirectory(Path.GetDirectoryName(strAbsFilePathDst));//make sure dir exists FileUtil.CopyFileOrDirectory(strAbsFilePathSrc, strAbsFilePathDst); } } // create assets StreamingImageSequencePlayableAssetParam trackMovieContainer = new StreamingImageSequencePlayableAssetParam(); trackMovieContainer.Pictures = new string[param.RelativeFilePaths.Count]; for (int ii = 0; ii < param.RelativeFilePaths.Count; ii++) { trackMovieContainer.Pictures[ii] = param.RelativeFilePaths[ii]; } /// if possible, convert folder names to relative path. string strUnityProjectFolder = null; Regex regAssetFolder = new Regex("/Assets$"); strUnityProjectFolder = Application.dataPath; strUnityProjectFolder = regAssetFolder.Replace(strUnityProjectFolder, ""); if (param.strDstFolder.StartsWith(strUnityProjectFolder)) { int start = strUnityProjectFolder.Length + 1; int end = param.strDstFolder.Length - start; param.strDstFolder = param.strDstFolder.Substring(start, end); } trackMovieContainer.Folder = param.strDstFolder; if (param.mode == PictureFileImporterParam.Mode.SpriteAnimation) { Sprite[] sprites = new Sprite[param.RelativeFilePaths.Count]; for (int ii = 0; ii < param.RelativeFilePaths.Count; ii++) { string strAssetPath = Path.Combine(param.strDstFolder, param.RelativeFilePaths[ii]).Replace("\\", "/"); AssetDatabase.ImportAsset(strAssetPath); TextureImporter importer = AssetImporter.GetAtPath(strAssetPath) as TextureImporter; importer.textureType = TextureImporterType.Sprite; AssetDatabase.WriteImportSettingsIfDirty(strAssetPath); Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath(strAssetPath, typeof(Texture2D)); sprites[ii] = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), new Vector2(0.5f, 0.5f)); } AnimationClip newClip = new AnimationClip(); newClip.wrapMode = WrapMode.Once; SerializedObject serializedClip = new SerializedObject(newClip); SerializedProperty settings = serializedClip.FindProperty("m_AnimationClipSettings"); while (settings.Next(true)) { if (settings.name == "m_LoopTime") { break; } } settings.boolValue = true; serializedClip.ApplyModifiedProperties(); ObjectReferenceKeyframe[] Keyframes = new ObjectReferenceKeyframe[param.RelativeFilePaths.Count]; EditorCurveBinding curveBinding = new EditorCurveBinding(); for (int ii = 0; ii < param.RelativeFilePaths.Count; ii++) { Keyframes[ii] = new ObjectReferenceKeyframe(); Keyframes[ii].time = 0.25F * ii; Keyframes[ii].value = sprites[ii]; } #if false curveBinding.type = typeof(SpriteRenderer); curveBinding.path = string.Empty; curveBinding.propertyName = "m_Sprite"; #else curveBinding.type = typeof(Image); curveBinding.path = string.Empty; curveBinding.propertyName = "m_Sprite"; #endif AnimationUtility.SetObjectReferenceCurve(newClip, curveBinding, Keyframes); AssetDatabase.CreateAsset(newClip, Path.Combine(param.strDstFolder, "Animation.anim").Replace("\\", "/")); // var proxyAsset = ScriptableObject.CreateInstance<StreamingImageSequencePlayableAsset>(); //new StreamingImageSequencePlayableAsset(trackMovieContainer); // proxyAsset.SetParam(trackMovieContainer); // var strProxyPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine("Assets", param.strAssetName + "_MovieProxy.playable").Replace("\\", "/"));*/ AssetDatabase.Refresh(); } else { //StreamingAsset StreamingImageSequencePlayableAsset proxyAsset = param.TargetAsset; if (null == proxyAsset) { proxyAsset = ScriptableObject.CreateInstance <StreamingImageSequencePlayableAsset>(); var strProxyPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine("Assets", param.strAssetName + "_MovieProxy.playable").Replace("\\", "/")); AssetDatabase.CreateAsset(proxyAsset, strProxyPath); } proxyAsset.SetParam(trackMovieContainer); if (!param.DoNotCopy) { AssetDatabase.Refresh(); } } }
static void OnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType deleted) { AnimationUtility.onCurveWasModified -= OnCurveWasModified; bool flag = Event.current == null || (Event.current != null && Event.current.type != EventType.ExecuteCommand); if (flag && deleted == AnimationUtility.CurveModifiedType.CurveModified && binding.type == typeof(Transform) && binding.propertyName.Contains("localEulerAnglesRaw")) { Transform transform = AnimationWindowExtra.rootGameObject.transform.Find(binding.path); Vector3 eulerAngles = BoneUtils.GetLocalEulerAngles(transform); int frame = AnimationWindowExtra.frame; AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding); for (int i = 0; i < curve.length; i++) { Keyframe keyframe = curve[i]; int keyframeFrame = (int)AnimationWindowExtra.TimeToFrame(keyframe.time); if (frame == keyframeFrame) { if (binding.propertyName.Contains(".x")) { if (keyframe.value != eulerAngles.x) { //Debug.Log(binding.propertyName + " " + keyframe.value + " -> " + eulerAngles.x.ToString()); keyframe.value = eulerAngles.x; } } else if (binding.propertyName.Contains(".y")) { if (keyframe.value != eulerAngles.y) { //Debug.Log(binding.propertyName + " " + keyframe.value + " -> " + eulerAngles.y.ToString()); keyframe.value = eulerAngles.y; } } else if (binding.propertyName.Contains(".z")) { if (keyframe.value != eulerAngles.z) { //Debug.Log(binding.propertyName + " " + keyframe.value + " -> " + eulerAngles.z.ToString()); keyframe.value = eulerAngles.z; } } curve.MoveKey(i, keyframe); CurveUtility.UpdateTangentsFromModeSurrounding(curve, i); break; } } AnimationUtility.SetEditorCurve(clip, binding, curve); } AnimationUtility.onCurveWasModified += OnCurveWasModified; }
public GameObject GenerateUnityObject(AudioData playable, Context ctx) { AudioClip clip = null; var dir = Application.dataPath + Path.GetDirectoryName(ctx.ctx.assetPath).Substring(6); var clipPath = dir + "/" + Path.GetFileNameWithoutExtension(ctx.ctx.assetPath) + "_audio/" + playable.displayName + "_audio.wav"; if (savedClips.ContainsKey(playable.audioDataKey)) { clip = savedClips[playable.audioDataKey]; } else { var assetPath = clipPath.Replace(Application.dataPath, "Assets"); if (!File.Exists(clipPath)) { clip = stage.AudioDataPool.RetrieveClipFromPool(playable.audioDataKey); if (clip) { clip.name = playable.displayName + "_audio"; SavWav.Save(clipPath, clip); AssetDatabase.ImportAsset(assetPath); if (Settings.AudioImport != AudioImportSetting.ClipsAndTracks) { needsAudioReimport = true; } } } clip = AssetDatabase.LoadAssetAtPath <AudioClip>(assetPath); savedClips[playable.audioDataKey] = clip; } if (Settings.AudioImport != AudioImportSetting.ClipsAndTracks) { return(null); } float start = playable.AbsoluteTimeOffset / stage.fps - playable.TrimIn; float duration = clip ? clip.length : 1 + playable.TrimIn + playable.TrimOut; var playableObj = MakePlayableBaseObject(playable, ref ctx, start, duration); var audioSource = playableObj.AddComponent <AudioSource>(); audioSource.spatialBlend = playable.Spatialize ? 1 : 0; audioSource.spatialize = playable.Spatialize; audioSource.spatializePostEffects = playable.Spatialize; var pathForName = AnimationUtility.CalculateTransformPath(playableObj.transform, ctx.rootTransform); var groupTrack = ctx.parentTimeline.CreateTrack <GroupTrack>(null, playable.displayName); ctx.ctx.AddObjectToAsset(pathForName + "_GroupTrack", groupTrack); var track = ctx.parentTimeline.CreateTrack <AudioTrack>(groupTrack, playable.displayName); ctx.ctx.AddObjectToAsset(pathForName + "_audioTrack", track); bool loop = playable.LoopType == AnimVR.LoopType.Loop; audioSource.loop = loop; var audioTrackClip = track.CreateDefaultClip(); audioTrackClip.displayName = playable.displayName; (audioTrackClip.asset as AudioPlayableAsset).clip = clip; typeof(AudioPlayableAsset).GetField("m_Loop", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance). SetValue(audioTrackClip.asset, loop); if (loop) { audioTrackClip.start = 0; audioTrackClip.duration = ctx.parentTimeline.fixedDuration; audioTrackClip.clipIn = duration - start % duration; } else { audioTrackClip.start = playable.TrimIn / ctx.fps; audioTrackClip.duration = duration; } ctx.ctx.AddObjectToAsset(pathForName + "_asset", audioTrackClip.asset); ctx.director.SetGenericBinding(track, audioSource); return(playableObj); }
protected void finishRecording(ProgressBar progress) { string targetFolderPath = targetFolder.Path; if (targetFolderPath == null) { if (gameObject.scene.IsValid() && !string.IsNullOrEmpty(gameObject.scene.path)) { string sceneFolder = Path.GetDirectoryName(gameObject.scene.path); targetFolderPath = Path.Combine(sceneFolder, "Recordings"); } else { targetFolderPath = Path.Combine("Assets", "Recordings"); } } int folderSuffix = 1; string finalSubFolder; do { finalSubFolder = Path.Combine(targetFolderPath, recordingName + " " + folderSuffix.ToString().PadLeft(2, '0')); folderSuffix++; } while (Directory.Exists(finalSubFolder)); string dataDirectory = Path.Combine(finalSubFolder, "_Data"); Directory.CreateDirectory(dataDirectory); Directory.CreateDirectory(finalSubFolder); AssetDatabase.Refresh(); progress.Begin(6, "Saving Recording", "", () => { if (!_isRecording) { return; } _isRecording = false; //Turn on auto-pushing for all auto-proxy components foreach (var autoProxy in GetComponentsInChildren <AutoValueProxy>()) { autoProxy.autoPushingEnabled = true; } progress.Begin(3, "", "Reverting Scene State", () => { //For all of our transform data, revert to the first piece recorded progress.Begin(_transformData.Count, "", "", () => { foreach (var pair in _transformData) { progress.Step(); var transform = pair.Key; var data = pair.Value; if (transform == null || data.Count == 0) { continue; } data[0].ApplyTo(transform); } }); //For all recorded curves, revert to start of curve progress.Begin(_curves.Count, "", "", () => { AnimationClip tempClip = new AnimationClip(); foreach (var data in _curves) { progress.Step(); AnimationUtility.SetEditorCurve(tempClip, data.binding, data.curve); } tempClip.SampleAnimation(gameObject, 0); }); //For all non-transform components, revert to original serialized values progress.Begin(_initialComponentData.Count, "", "", () => { foreach (var pair in _initialComponentData) { progress.Step(); var component = pair.Key; var sobj = pair.Value; if (component == null || component is Transform) { continue; } //We don't want to revert method recordings! if (component is MethodRecording || component is RecordedAudio) { continue; } var flags = sobj.FindProperty("m_ObjectHideFlags"); if (flags == null) { Debug.LogError("Could not find hide flags for " + component); continue; } //We have to dirty the serialized object somehow //apparently there is no api to do this //all objects have hide flags so we just touch them and revert them int originalFlags = flags.intValue; flags.intValue = ~originalFlags; flags.intValue = originalFlags; try { //Applies previous state of entire component sobj.ApplyModifiedProperties(); } catch (Exception e) { Debug.LogError("Exception when trying to apply properties to " + component); Debug.LogException(e); } } }); }); progress.Begin(1, "", "Patching Materials: ", () => { GetComponentsInChildren(true, _recorders); foreach (var recorder in _recorders) { DestroyImmediate(recorder); } //Patch up renderer references to materials var allMaterials = Resources.FindObjectsOfTypeAll <Material>(). Query(). Where(AssetDatabase.IsMainAsset). ToList(); var renderers = GetComponentsInChildren <Renderer>(includeInactive: true); progress.Begin(renderers.Length, "", "", () => { foreach (var renderer in renderers) { progress.Step(renderer.name); var materials = renderer.sharedMaterials; for (int i = 0; i < materials.Length; i++) { var material = materials[i]; if (material == null) { continue; } if (!AssetDatabase.IsMainAsset(material)) { var matchingMaterial = allMaterials.Query().FirstOrDefault(m => material.name.Contains(m.name) && material.shader == m.shader); if (matchingMaterial != null) { materials[i] = matchingMaterial; } } } renderer.sharedMaterials = materials; } }); }); progress.Begin(_behaviourActivity.Count, "", "Converting Activity Data: ", () => { foreach (var pair in _behaviourActivity) { var targetBehaviour = pair.Key; var activityData = pair.Value; if (targetBehaviour == null) { continue; } progress.Step(targetBehaviour.name); string path = AnimationUtility.CalculateTransformPath(targetBehaviour.transform, transform); Type type = targetBehaviour.GetType(); string propertyName = "m_Enabled"; AnimationCurve curve = new AnimationCurve(); foreach (var dataPoint in activityData) { int index = curve.AddKey(dataPoint.time, dataPoint.enabled ? 1 : 0); AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant); } if (curve.IsConstant()) { continue; } var binding = EditorCurveBinding.FloatCurve(path, type, propertyName); if (_curves.Query().Any(c => c.binding == binding)) { Debug.LogError("Binding already existed?"); Debug.LogError(binding.path + " : " + binding.propertyName); continue; } _curves.Add(new CurveData() { binding = binding, curve = curve }); } }); progress.Begin(_transformData.Count, "", "Converting Transform Data: ", () => { foreach (var pair in _transformData) { var targetTransform = pair.Key; var targetData = pair.Value; progress.Step(targetTransform.name); string path = AnimationUtility.CalculateTransformPath(targetTransform, transform); bool isActivityConstant = true; bool isPositionConstant = true; bool isRotationConstant = true; bool isScaleConstant = true; { bool startEnabled = targetData[0].enabled; Vector3 startPosition = targetData[0].localPosition; Quaternion startRotation = targetData[0].localRotation; Vector3 startScale = targetData[0].localScale; for (int i = 1; i < targetData.Count; i++) { isActivityConstant &= targetData[i].enabled == startEnabled; isPositionConstant &= targetData[i].localPosition == startPosition; isRotationConstant &= targetData[i].localRotation == startRotation; isScaleConstant &= targetData[i].localScale == startScale; } } for (int i = 0; i < TransformData.CURVE_COUNT; i++) { string propertyName = TransformData.GetName(i); Type type = typeof(Transform); AnimationCurve curve = new AnimationCurve(); var dataType = TransformData.GetDataType(i); switch (dataType) { case TransformDataType.Position: if (isPositionConstant) { continue; } break; case TransformDataType.Rotation: if (isRotationConstant) { continue; } break; case TransformDataType.Scale: if (isScaleConstant) { continue; } break; case TransformDataType.Activity: if (isActivityConstant) { continue; } type = typeof(GameObject); break; } for (int j = 0; j < targetData.Count; j++) { int index = curve.AddKey(targetData[j].time, targetData[j].GetFloat(i)); if (dataType == TransformDataType.Activity) { AnimationUtility.SetKeyLeftTangentMode(curve, index, AnimationUtility.TangentMode.Constant); AnimationUtility.SetKeyRightTangentMode(curve, index, AnimationUtility.TangentMode.Constant); } } var binding = EditorCurveBinding.FloatCurve(path, type, propertyName); if (_curves.Query().Any(c => c.binding == binding)) { Debug.LogError("Duplicate object was created??"); Debug.LogError("Named " + targetTransform.name + " : " + binding.path + " : " + binding.propertyName); } else { _curves.Add(new CurveData() { binding = binding, curve = curve }); } } } }); progress.Begin(_curves.Count, "", "Compressing Data: ", () => { _curves.Sort((a, b) => a.binding.propertyName.CompareTo(b.binding.propertyName)); foreach (var data in _curves) { using (new ProfilerSample("A")) { EditorCurveBinding binding = data.binding; AnimationCurve curve = data.curve; progress.Step(binding.propertyName); GameObject animationGameObject; { var animatedObj = AnimationUtility.GetAnimatedObject(gameObject, binding); if (animatedObj is GameObject) { animationGameObject = animatedObj as GameObject; } else { animationGameObject = (animatedObj as Component).gameObject; } } bool isMatBinding = binding.propertyName.StartsWith("material.") && binding.type.IsSubclassOf(typeof(Renderer)); //But if the curve is constant, just get rid of it! //Except for material curves, which we always need to keep if (curve.IsConstant() && !isMatBinding) { //Check to make sure there are no other matching curves that are //non constant. If X and Y are constant but Z is not, we need to //keep them all :( if (_curves.Query().Where(p => p.binding.path == binding.path && p.binding.type == binding.type && p.binding.propertyName.TrimEnd(2) == binding.propertyName.TrimEnd(2)). All(k => k.curve.IsConstant())) { continue; } } //First do a lossless compression using (new ProfilerSample("B")) { curve = AnimationCurveUtil.Compress(curve, Mathf.Epsilon, checkSteps: 3); } Transform targetTransform = null; var targetObj = AnimationUtility.GetAnimatedObject(gameObject, binding); if (targetObj is GameObject) { targetTransform = (targetObj as GameObject).transform; } else if (targetObj is Component) { targetTransform = (targetObj as Component).transform; } else { Debug.LogError("Target obj was of type " + targetObj.GetType().Name); } } } }); }); progress.Begin(4, "Finalizing Assets", "", () => { var postProcessComponent = gameObject.AddComponent <HierarchyPostProcess>(); GameObject myGameObject = gameObject; DestroyImmediate(this); //Create all the files for the method recording progress.Step("Creating Method Recording Files..."); var methodRecordings = myGameObject.GetComponentsInChildren <MethodRecording>(); for (int i = 0; i < methodRecordings.Length; i++) { var methodRecording = methodRecordings[i]; string fullPath = Path.Combine(finalSubFolder, "MethodRecording_" + i + ".asset"); methodRecording.ExitRecordingMode(fullPath); } postProcessComponent.dataFolder = new AssetFolder(dataDirectory); //Create the asset that holds all of the curve data progress.Begin(_curves.Count, "", "", () => { string curveFile = Path.Combine(dataDirectory, "Curves.data"); using (var writer = File.CreateText(curveFile)) { foreach (var data in _curves) { progress.Step(data.binding.propertyName); var bindingData = new EditorCurveBindingData() { path = data.binding.path, propertyName = data.binding.propertyName, typeName = data.binding.type.Name, curve = data.curve }; writer.WriteLine(JsonUtility.ToJson(bindingData)); } } }); //Create the asset that holds all of the leap data if (_leapData.Count > 0) { progress.Begin(_leapData.Count, "", "", () => { string leapFile = Path.Combine(dataDirectory, "Frames.data"); using (var writer = File.CreateText(leapFile)) { for (int i = 0; i < _leapData.Count; i++) { progress.Step("Frame " + i); writer.WriteLine(JsonUtility.ToJson(_leapData[i])); } } }); } progress.Step("Creating Final Prefab..."); //Init the post process component postProcessComponent.recordingName = recordingName; postProcessComponent.assetFolder = new AssetFolder(finalSubFolder); string prefabPath = Path.Combine(finalSubFolder, recordingName + " Raw.prefab"); #if UNITY_2018_3_OR_NEWER var path = prefabPath.Replace('\\', '/'); PrefabUtility.SaveAsPrefabAsset(myGameObject, path, out bool didSucceed); if (!didSucceed) { Debug.LogError($"Error saving prefab asset to {path}"); } #else PrefabUtility.CreatePrefab(prefabPath.Replace('\\', '/'), myGameObject); #endif AssetDatabase.Refresh(); EditorApplication.isPlaying = false; }); }
public GameObject GenerateUnityObject(FrameData frame, Context ctx, int index) { var playableObj = new GameObject(index.ToString()); playableObj.transform.parent = ctx.parentTransform; playableObj.transform.localPosition = frame.transform.pos.V3; playableObj.transform.localRotation = frame.transform.rot.Q; playableObj.transform.localScale = frame.transform.scl.V3; var pathForName = AnimationUtility.CalculateTransformPath(playableObj.transform, ctx.rootTransform); List <List <CombineInstance> > instances = new List <List <CombineInstance> >(); List <CombineInstance> currentList = new List <CombineInstance>(); instances.Add(currentList); int vCount = 0; foreach (var line in frame.RuntimeLines) { try { List <Vector3> verts = new List <Vector3>(); List <int> indices = new List <int>(); List <Vector4> colors = new List <Vector4>(); List <Vector2> uvs = new List <Vector2>(); List <Vector3> normals = new List <Vector3>(); MeshUtils.GeneratePositionData(line, verts, indices, colors, uvs, normals); CombineInstance instance = new CombineInstance(); if (verts.Count == 0) { continue; } Mesh mesh = new Mesh(); mesh.SetVertices(verts); mesh.SetTriangles(indices, 0); mesh.SetColors(colors.Select(c => new Color(c.x, c.y, c.z, c.w)).ToList()); mesh.SetUVs(0, uvs); mesh.SetNormals(normals); instance.mesh = mesh; vCount += verts.Count; if (vCount > 60000) { currentList = new List <CombineInstance>(); instances.Add(currentList); vCount -= 60000; } currentList.Add(instance); totalLines++; } catch (Exception e) { Debug.LogWarning(e.Message); } } totalVertices += vCount; int meshId = 0; foreach (var mesh in instances) { var subObj = new GameObject("Submesh" + meshId); subObj.transform.SetParent(playableObj.transform, false); var mf = subObj.AddComponent <MeshFilter>(); var mr = subObj.AddComponent <MeshRenderer>(); Mesh combinedMesh = new Mesh(); combinedMesh.CombineMeshes(mesh.ToArray(), true, false, false); combinedMesh.name = pathForName + meshId; mf.sharedMesh = combinedMesh; mr.sharedMaterial = baseMaterial; ctx.ctx.AddObjectToAsset(pathForName + "_mesh" + meshId, mf.sharedMesh); meshId++; } return(playableObj); }
public static List <AnimationEvent> GetEvents(this AnimationClip clip) { return(new List <AnimationEvent>(AnimationUtility.GetAnimationEvents(clip))); }
void ReplaceRoot(string oldRoot, string newRoot) { float fProgress = 0.0f; sReplacementOldRoot = oldRoot; sReplacementNewRoot = newRoot; AssetDatabase.StartAssetEditing(); for (int iCurrentClip = 0; iCurrentClip < animationClips.Count; iCurrentClip++) { AnimationClip animationClip = animationClips[iCurrentClip]; Undo.RecordObject(animationClip, "Animation Hierarchy Root Change"); for (int iCurrentPath = 0; iCurrentPath < pathsKeys.Count; iCurrentPath++) { string path = pathsKeys[iCurrentPath] as string; ArrayList curves = (ArrayList)paths[path]; for (int i = 0; i < curves.Count; i++) { EditorCurveBinding binding = (EditorCurveBinding)curves[i]; if (path.Contains(sReplacementOldRoot)) { if (!path.Contains(sReplacementNewRoot)) { string sNewPath = Regex.Replace(path, "^" + sReplacementOldRoot, sReplacementNewRoot); AnimationCurve curve = AnimationUtility.GetEditorCurve(animationClip, binding); if (curve != null) { AnimationUtility.SetEditorCurve(animationClip, binding, null); binding.path = sNewPath; AnimationUtility.SetEditorCurve(animationClip, binding, curve); } else { ObjectReferenceKeyframe[] objectReferenceCurve = AnimationUtility.GetObjectReferenceCurve(animationClip, binding); AnimationUtility.SetObjectReferenceCurve(animationClip, binding, null); binding.path = sNewPath; AnimationUtility.SetObjectReferenceCurve(animationClip, binding, objectReferenceCurve); } } } } // Update the progress meter float fChunk = 1f / animationClips.Count; fProgress = (iCurrentClip * fChunk) + fChunk * ((float)iCurrentPath / (float)pathsKeys.Count); EditorUtility.DisplayProgressBar( "Animation Hierarchy Progress", "How far along the animation editing has progressed.", fProgress); } } AssetDatabase.StopAssetEditing(); EditorUtility.ClearProgressBar(); FillModel(); this.Repaint(); }
public static void SetEvents(this AnimationClip clip, AnimationEvent[] events) { EditorHelper.Dirty(clip, () => { AnimationUtility.SetAnimationEvents(clip, events); }); }
void CheckResources() { ActiveTextures.Clear(); ActiveMaterials.Clear(); ActiveMeshDetails.Clear(); MissingObjects.Clear(); thingsMissing = false; Renderer[] renderers = FindObjects <Renderer>(); MaterialDetails skyMat = new MaterialDetails(); skyMat.material = RenderSettings.skybox; skyMat.isSky = true; ActiveMaterials.Add(skyMat); //Debug.Log("Total renderers "+renderers.Length); foreach (Renderer renderer in renderers) { //Debug.Log("Renderer is "+renderer.name); foreach (Material material in renderer.sharedMaterials) { MaterialDetails tMaterialDetails = FindMaterialDetails(material); if (tMaterialDetails == null) { tMaterialDetails = new MaterialDetails(); tMaterialDetails.material = material; ActiveMaterials.Add(tMaterialDetails); } tMaterialDetails.FoundInRenderers.Add(renderer); } if (renderer is SpriteRenderer) { SpriteRenderer tSpriteRenderer = (SpriteRenderer)renderer; if (tSpriteRenderer.sprite != null) { var tSpriteTextureDetail = GetTextureDetail(tSpriteRenderer.sprite.texture, renderer); if (!ActiveTextures.Contains(tSpriteTextureDetail)) { ActiveTextures.Add(tSpriteTextureDetail); } } else if (tSpriteRenderer.sprite == null) { MissingGraphic tMissing = new MissingGraphic(); tMissing.Object = tSpriteRenderer.transform; tMissing.type = "sprite"; tMissing.name = tSpriteRenderer.transform.name; MissingObjects.Add(tMissing); thingsMissing = true; } } } if (IncludeLightmapTextures) { LightmapData[] lightmapTextures = LightmapSettings.lightmaps; // Unity lightmaps foreach (LightmapData lightmapData in lightmapTextures) { if (lightmapData.lightmapColor != null) { var textureDetail = GetTextureDetail(lightmapData.lightmapColor); if (!ActiveTextures.Contains(textureDetail)) { ActiveTextures.Add(textureDetail); } } if (lightmapData.lightmapDir != null) { var textureDetail = GetTextureDetail(lightmapData.lightmapColor); if (!ActiveTextures.Contains(textureDetail)) { ActiveTextures.Add(textureDetail); } } if (lightmapData.shadowMask != null) { var textureDetail = GetTextureDetail(lightmapData.shadowMask); if (!ActiveTextures.Contains(textureDetail)) { ActiveTextures.Add(textureDetail); } } } } if (IncludeGuiElements) { Graphic[] graphics = FindObjects <Graphic>(); foreach (Graphic graphic in graphics) { if (graphic.mainTexture) { var tSpriteTextureDetail = GetTextureDetail(graphic.mainTexture, graphic); if (!ActiveTextures.Contains(tSpriteTextureDetail)) { ActiveTextures.Add(tSpriteTextureDetail); } } if (graphic.materialForRendering) { MaterialDetails tMaterialDetails = FindMaterialDetails(graphic.materialForRendering); if (tMaterialDetails == null) { tMaterialDetails = new MaterialDetails(); tMaterialDetails.material = graphic.materialForRendering; tMaterialDetails.isgui = true; ActiveMaterials.Add(tMaterialDetails); } tMaterialDetails.FoundInGraphics.Add(graphic); } } Button[] buttons = FindObjects <Button>(); foreach (Button button in buttons) { CheckButtonSpriteState(button, button.spriteState.disabledSprite); CheckButtonSpriteState(button, button.spriteState.highlightedSprite); CheckButtonSpriteState(button, button.spriteState.pressedSprite); } } foreach (MaterialDetails tMaterialDetails in ActiveMaterials) { Material tMaterial = tMaterialDetails.material; if (tMaterial != null) { var dependencies = EditorUtility.CollectDependencies(new UnityEngine.Object[] { tMaterial }); foreach (Object obj in dependencies) { if (obj is Texture) { Texture tTexture = obj as Texture; var tTextureDetail = GetTextureDetail(tTexture, tMaterial, tMaterialDetails); tTextureDetail.isSky = tMaterialDetails.isSky; tTextureDetail.instance = tMaterialDetails.instance; tTextureDetail.isgui = tMaterialDetails.isgui; ActiveTextures.Add(tTextureDetail); } } //if the texture was downloaded, it won't be included in the editor dependencies if (tMaterial.HasProperty("_MainTex")) { if (tMaterial.mainTexture != null && !dependencies.Contains(tMaterial.mainTexture)) { var tTextureDetail = GetTextureDetail(tMaterial.mainTexture, tMaterial, tMaterialDetails); ActiveTextures.Add(tTextureDetail); } } } } MeshFilter[] meshFilters = FindObjects <MeshFilter>(); foreach (MeshFilter tMeshFilter in meshFilters) { Mesh tMesh = tMeshFilter.sharedMesh; if (tMesh != null) { MeshDetails tMeshDetails = FindMeshDetails(tMesh); if (tMeshDetails == null) { tMeshDetails = new MeshDetails(); tMeshDetails.mesh = tMesh; ActiveMeshDetails.Add(tMeshDetails); } tMeshDetails.FoundInMeshFilters.Add(tMeshFilter); if (GameObjectUtility.AreStaticEditorFlagsSet(tMeshFilter.gameObject, StaticEditorFlags.BatchingStatic)) { tMeshDetails.StaticBatchingEnabled.Add(tMeshFilter.gameObject); } } else if (tMesh == null && tMeshFilter.transform.GetComponent("TextContainer") == null) { MissingGraphic tMissing = new MissingGraphic(); tMissing.Object = tMeshFilter.transform; tMissing.type = "mesh"; tMissing.name = tMeshFilter.transform.name; MissingObjects.Add(tMissing); thingsMissing = true; } var meshRenderrer = tMeshFilter.transform.GetComponent <MeshRenderer>(); if (meshRenderrer == null || meshRenderrer.sharedMaterial == null) { MissingGraphic tMissing = new MissingGraphic(); tMissing.Object = tMeshFilter.transform; tMissing.type = "material"; tMissing.name = tMeshFilter.transform.name; MissingObjects.Add(tMissing); thingsMissing = true; } } SkinnedMeshRenderer[] skinnedMeshRenderers = FindObjects <SkinnedMeshRenderer>(); foreach (SkinnedMeshRenderer tSkinnedMeshRenderer in skinnedMeshRenderers) { Mesh tMesh = tSkinnedMeshRenderer.sharedMesh; if (tMesh != null) { MeshDetails tMeshDetails = FindMeshDetails(tMesh); if (tMeshDetails == null) { tMeshDetails = new MeshDetails(); tMeshDetails.mesh = tMesh; ActiveMeshDetails.Add(tMeshDetails); } tMeshDetails.FoundInSkinnedMeshRenderer.Add(tSkinnedMeshRenderer); } else if (tMesh == null) { MissingGraphic tMissing = new MissingGraphic(); tMissing.Object = tSkinnedMeshRenderer.transform; tMissing.type = "mesh"; tMissing.name = tSkinnedMeshRenderer.transform.name; MissingObjects.Add(tMissing); thingsMissing = true; } if (tSkinnedMeshRenderer.sharedMaterial == null) { MissingGraphic tMissing = new MissingGraphic(); tMissing.Object = tSkinnedMeshRenderer.transform; tMissing.type = "material"; tMissing.name = tSkinnedMeshRenderer.transform.name; MissingObjects.Add(tMissing); thingsMissing = true; } } if (IncludeSpriteAnimations) { Animator[] animators = FindObjects <Animator>(); foreach (Animator anim in animators) { #if UNITY_4_6 || UNITY_4_5 || UNITY_4_4 || UNITY_4_3 UnityEditorInternal.AnimatorController ac = anim.runtimeAnimatorController as UnityEditorInternal.AnimatorController; #elif UNITY_5 || UNITY_5_3_OR_NEWER UnityEditor.Animations.AnimatorController ac = anim.runtimeAnimatorController as UnityEditor.Animations.AnimatorController; #endif //Skip animators without layers, this can happen if they don't have an animator controller. if (!ac || ac.layers == null || ac.layers.Length == 0) { continue; } for (int x = 0; x < anim.layerCount; x++) { UnityEditor.Animations.AnimatorStateMachine sm = ac.layers[x].stateMachine; int cnt = sm.states.Length; for (int i = 0; i < cnt; i++) { UnityEditor.Animations.AnimatorState state = sm.states[i].state; Motion m = state.motion; if (m != null) { AnimationClip clip = m as AnimationClip; if (clip != null) { EditorCurveBinding[] ecbs = AnimationUtility.GetObjectReferenceCurveBindings(clip); foreach (EditorCurveBinding ecb in ecbs) { if (ecb.propertyName == "m_Sprite") { foreach (ObjectReferenceKeyframe keyframe in AnimationUtility.GetObjectReferenceCurve(clip, ecb)) { Sprite tSprite = keyframe.value as Sprite; if (tSprite != null) { var tTextureDetail = GetTextureDetail(tSprite.texture, anim); if (!ActiveTextures.Contains(tTextureDetail)) { ActiveTextures.Add(tTextureDetail); } } } } } } } } } } } if (IncludeScriptReferences) { MonoBehaviour[] scripts = FindObjects <MonoBehaviour>(); foreach (MonoBehaviour script in scripts) { BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; // only public non-static fields are bound to by Unity. FieldInfo[] fields = script.GetType().GetFields(flags); foreach (FieldInfo field in fields) { System.Type fieldType = field.FieldType; if (fieldType == typeof(Sprite)) { Sprite tSprite = field.GetValue(script) as Sprite; if (tSprite != null) { var tSpriteTextureDetail = GetTextureDetail(tSprite.texture, script); if (!ActiveTextures.Contains(tSpriteTextureDetail)) { ActiveTextures.Add(tSpriteTextureDetail); } } } if (fieldType == typeof(Mesh)) { Mesh tMesh = field.GetValue(script) as Mesh; if (tMesh != null) { MeshDetails tMeshDetails = FindMeshDetails(tMesh); if (tMeshDetails == null) { tMeshDetails = new MeshDetails(); tMeshDetails.mesh = tMesh; tMeshDetails.instance = true; ActiveMeshDetails.Add(tMeshDetails); } } } if (fieldType == typeof(Material)) { Material tMaterial = field.GetValue(script) as Material; if (tMaterial != null) { MaterialDetails tMatDetails = FindMaterialDetails(tMaterial); if (tMatDetails == null) { tMatDetails = new MaterialDetails(); tMatDetails.instance = true; tMatDetails.material = tMaterial; if (!ActiveMaterials.Contains(tMatDetails)) { ActiveMaterials.Add(tMatDetails); } } if (tMaterial.mainTexture) { var tSpriteTextureDetail = GetTextureDetail(tMaterial.mainTexture); if (!ActiveTextures.Contains(tSpriteTextureDetail)) { ActiveTextures.Add(tSpriteTextureDetail); } } var dependencies = EditorUtility.CollectDependencies(new UnityEngine.Object[] { tMaterial }); foreach (Object obj in dependencies) { if (obj is Texture) { Texture tTexture = obj as Texture; var tTextureDetail = GetTextureDetail(tTexture, tMaterial, tMatDetails); if (!ActiveTextures.Contains(tTextureDetail)) { ActiveTextures.Add(tTextureDetail); } } } } } } } } TotalTextureMemory = 0; foreach (TextureDetails tTextureDetails in ActiveTextures) { TotalTextureMemory += tTextureDetails.memSizeKB; } TotalMeshVertices = 0; foreach (MeshDetails tMeshDetails in ActiveMeshDetails) { TotalMeshVertices += tMeshDetails.mesh.vertexCount; } // Sort by size, descending ActiveTextures.Sort(delegate(TextureDetails details1, TextureDetails details2) { return(details2.memSizeKB - details1.memSizeKB); }); ActiveTextures = ActiveTextures.Distinct().ToList(); ActiveMeshDetails.Sort(delegate(MeshDetails details1, MeshDetails details2) { return(details2.mesh.vertexCount - details1.mesh.vertexCount); }); collectedInPlayingMode = Application.isPlaying; // Sort by render queue ActiveMaterials.Sort(MaterialSorter); }
public void CreateAnimation(ImportedAnimation anim, string basePath, string masterName, AnimationTargetObjectType targetType) { AnimationClip clip; string fileName = basePath + "/" + masterName + "_" + anim.name + ".anim"; bool isLooping = anim.isLooping; // check if animation file already exists clip = AssetDatabase.LoadAssetAtPath <AnimationClip>(fileName); if (clip != null) { // get previous animation settings targetType = PreviousImportSettings.GetAnimationTargetFromExistingClip(clip); } else { clip = new AnimationClip(); AssetDatabase.CreateAsset(clip, fileName); } // change loop settings if (isLooping) { clip.wrapMode = WrapMode.Loop; clip.SetLoop(true); } else { clip.wrapMode = WrapMode.Clamp; clip.SetLoop(false); } // convert keyframes ImportedAnimationFrame[] srcKeyframes = anim.ListFramesAccountingForPlaybackDirection().ToArray(); ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[srcKeyframes.Length + 1]; float timeOffset = 0f; for (int i = 0; i < srcKeyframes.Length; i++) { // first sprite will be set at the beginning (t=0) of the animation keyFrames[i] = new ObjectReferenceKeyframe { time = timeOffset, value = srcKeyframes[i].sprite }; // add duration of frame in seconds timeOffset += srcKeyframes[i].duration / 1000f; } // repeating the last frame at a point "just before the end" so the animation gets its correct length keyFrames[srcKeyframes.Length] = new ObjectReferenceKeyframe { time = timeOffset - (1f / clip.frameRate), // substract the duration of one frame value = srcKeyframes.Last().sprite }; // save curve into clip, either for SpriteRenderer, Image, or both if (targetType == AnimationTargetObjectType.SpriteRenderer) { AnimationUtility.SetObjectReferenceCurve(clip, AnimationClipUtility.spriteRendererCurveBinding, keyFrames); AnimationUtility.SetObjectReferenceCurve(clip, AnimationClipUtility.imageCurveBinding, null); } else if (targetType == AnimationTargetObjectType.Image) { AnimationUtility.SetObjectReferenceCurve(clip, AnimationClipUtility.spriteRendererCurveBinding, null); AnimationUtility.SetObjectReferenceCurve(clip, AnimationClipUtility.imageCurveBinding, keyFrames); } else if (targetType == AnimationTargetObjectType.SpriteRendererAndImage) { AnimationUtility.SetObjectReferenceCurve(clip, AnimationClipUtility.spriteRendererCurveBinding, keyFrames); AnimationUtility.SetObjectReferenceCurve(clip, AnimationClipUtility.imageCurveBinding, keyFrames); } EditorUtility.SetDirty(clip); anim.animationClip = clip; }
private static void ExportTransformAnimationClipData(GameObject source, Transform transform, BabylonIAnimatable animatable, UnityEditor.AnimationState animationState, ref List <AnimationClip> states, ref UnityMetaData metaData, Animator animator) { ExporterWindow.ReportProgress(1, "Exporting transform clips: " + transform.gameObject.name); int frameRate = 0; int firstClipEnd = 0; int totalFrameCount = 0; List <string> stateNameCache = new List <string>(); List <BabylonAnimation> animations = new List <BabylonAnimation>(); var positionX = new List <BabylonAnimationKey>(); var positionY = new List <BabylonAnimationKey>(); var positionZ = new List <BabylonAnimationKey>(); var rotationX = new List <BabylonAnimationKey>(); var rotationY = new List <BabylonAnimationKey>(); var rotationZ = new List <BabylonAnimationKey>(); var rotationW = new List <BabylonAnimationKey>(); var scaleX = new List <BabylonAnimationKey>(); var scaleY = new List <BabylonAnimationKey>(); var scaleZ = new List <BabylonAnimationKey>(); int frameOffest = 0; float playbackSpeed = (animationState != null) ? animationState.playbackSpeed : 1.0f; foreach (var state in states) { if (state == null) { continue; } AnimationClip clip = state as AnimationClip; if (frameRate <= 0) { frameRate = (int)clip.frameRate; } //var frameTime = 1.0f / frameRate; int clipFrameCount = (int)(clip.length * frameRate); if (firstClipEnd <= 0) { firstClipEnd = (clipFrameCount - 1); } var settings = AnimationUtility.GetAnimationClipSettings(clip); BabylonLoopBehavior behavior = (settings.loopTime) ? BabylonLoopBehavior.Cycle : BabylonLoopBehavior.Constant; if (settings.loopTime && settings.loopBlend) { behavior = BabylonLoopBehavior.Relative; } ExporterWindow.ReportProgress(1, "Transforming: " + transform.gameObject.name + " - " + clip.name); // Set Animation State Meta Data if (!stateNameCache.Contains(clip.name)) { stateNameCache.Add(clip.name); // Animation Clip Information Dictionary <string, object> animStateInfo = new Dictionary <string, object>(); animStateInfo.Add("type", "transform"); animStateInfo.Add("name", clip.name); animStateInfo.Add("start", frameOffest); animStateInfo.Add("stop", (frameOffest + clipFrameCount - 1)); animStateInfo.Add("rate", frameRate); animStateInfo.Add("behavior", (int)behavior); animStateInfo.Add("playback", playbackSpeed); metaData.animationClips.Add(animStateInfo); } // Animation Curve Bindings var curveBindings = AnimationUtility.GetCurveBindings(clip); foreach (var binding in curveBindings) { var curve = AnimationUtility.GetEditorCurve(clip, binding); switch (binding.propertyName) { //Position case "m_LocalPosition.x": IEnumerable <BabylonAnimationKey> px_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value } }); positionX.AddRange(px_keys); break; case "m_LocalPosition.y": IEnumerable <BabylonAnimationKey> py_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value } }); positionY.AddRange(py_keys); break; case "m_LocalPosition.z": IEnumerable <BabylonAnimationKey> pz_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value } }); positionZ.AddRange(pz_keys); break; // Rotation case "localEulerAnglesRaw.x": IEnumerable <BabylonAnimationKey> rx_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value *(float)Math.PI / 180 } }); rotationX.AddRange(rx_keys); break; case "localEulerAnglesRaw.y": IEnumerable <BabylonAnimationKey> ry_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value *(float)Math.PI / 180 } }); rotationY.AddRange(ry_keys); break; case "localEulerAnglesRaw.z": IEnumerable <BabylonAnimationKey> rz_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value *(float)Math.PI / 180 } }); rotationZ.AddRange(rz_keys); break; case "localEulerAnglesRaw.w": IEnumerable <BabylonAnimationKey> rw_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value *(float)Math.PI / 180 } }); rotationW.AddRange(rw_keys); break; // Scaling case "m_LocalScale.x": IEnumerable <BabylonAnimationKey> sx_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value } }); scaleX.AddRange(sx_keys); break; case "m_LocalScale.y": IEnumerable <BabylonAnimationKey> sy_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value } }); scaleY.AddRange(sy_keys); break; case "m_LocalScale.z": IEnumerable <BabylonAnimationKey> sz_keys = curve.keys.Select(keyFrame => new BabylonAnimationKey { frame = (int)((keyFrame.time * frameRate) + frameOffest), values = new[] { keyFrame.value } }); scaleZ.AddRange(sz_keys); break; default: continue; } } frameOffest += clipFrameCount; totalFrameCount += clipFrameCount; } // Position properties string property = "none"; if (positionX.Count > 0) { property = "position.x"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = positionX.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } property = "none"; if (positionY.Count > 0) { property = "position.y"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = positionY.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } property = "none"; if (positionZ.Count > 0) { property = "position.z"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = positionZ.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } // Rotation properties property = "none"; if (rotationX.Count > 0) { property = "rotation.x"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = rotationX.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } property = "none"; if (rotationY.Count > 0) { property = "rotation.y"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = rotationY.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } property = "none"; if (rotationZ.Count > 0) { property = "rotation.z"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = rotationZ.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } property = "none"; if (rotationW.Count > 0) { property = "rotation.w"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = rotationW.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } // Scale properties property = "none"; if (scaleX.Count > 0) { property = "scaling.x"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = scaleX.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } property = "none"; if (scaleY.Count > 0) { property = "scaling.y"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = scaleY.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } property = "none"; if (scaleZ.Count > 0) { property = "scaling.z"; animations.Add(new BabylonAnimation { dataType = (int)BabylonAnimation.DataType.Float, name = property + " animation", keys = scaleZ.ToArray(), framePerSecond = frameRate, enableBlending = false, blendingSpeed = 0.0f, loopBehavior = (int)BabylonAnimation.LoopBehavior.Relative, property = property }); } if (animations.Count > 0) { animatable.animations = animations.ToArray(); } }
// Use this for initialization public void Run() { RecursivelyFindFolderPath("Assets"); Debug.Log("Baking the following animations...."); List <AnimationClip> animClips = GetAnimationLengths(); bones = GetListBones(); for (int j = 0; j < animClips.Count; j++) { newClip = new AnimationClip(); //AnimatorStateInfo state = transform.GetComponent<Animator> ().GetCurrentAnimatorStateInfo(0); //float leng = state.length; clip = animClips[j]; float leng = clip.length; //Debug.Log(leng); curvePosX.Clear(); curvePosY.Clear(); curvePosZ.Clear(); curveRotX.Clear(); curveRotY.Clear(); curveRotZ.Clear(); curveRotW.Clear(); curveScaleX.Clear(); curveScaleY.Clear(); curveScaleZ.Clear(); for (int i = 0; i < bones.Count; i++) { curvePosX.Add(new AnimationCurve()); curvePosY.Add(new AnimationCurve()); curvePosZ.Add(new AnimationCurve()); curveRotX.Add(new AnimationCurve()); curveRotY.Add(new AnimationCurve()); curveRotZ.Add(new AnimationCurve()); curveRotW.Add(new AnimationCurve()); curveScaleX.Add(new AnimationCurve()); curveScaleY.Add(new AnimationCurve()); curveScaleZ.Add(new AnimationCurve()); } //Time.timeScale = 0.0f; //float _lastRealTime = 0.0f; frameTime = 1f / clip.frameRate; float numFramesInAnim = (leng * clip.frameRate); for (int i = 0; i < numFramesInAnim + 1; i++) { AnimationMode.StartAnimationMode(); AnimationMode.BeginSampling(); AnimationMode.SampleAnimationClip(transform.gameObject, clip, i * frameTime); transform.GetComponent <Puppet2D_GlobalControl>().Run(); foreach (Transform bone in bones) { bakeAnimation(bone, i * frameTime); } } AnimationMode.EndSampling(); AnimationMode.StopAnimationMode(); newClip.name = clip.name + "_Baked"; newClip.wrapMode = clip.wrapMode; AnimationClipSettings animClipSettings = new AnimationClipSettings(); animClipSettings.stopTime = clip.length; #if UNITY_5_1 newClip.legacy = false; #else AnimationUtility.SetAnimationType(newClip, ModelImporterAnimationType.Generic); #endif SaveAnimationClip(newClip); AnimationEvent[] events = new AnimationEvent[1]; events[0] = new AnimationEvent(); events[0].time = clip.length; AnimationUtility.SetAnimationEvents(newClip, events); AnimationEvent[] events2 = new AnimationEvent[0]; AnimationUtility.SetAnimationEvents(newClip, events2); /*AnimationClipCurveData[] curveDatas = AnimationUtility.GetAllCurves(newClip, true); * for (int i=0; i<curveDatas.Length; i++) * { * AnimationUtility.SetEditorCurve( * newClip, * curveDatas[i].path, * curveDatas[i].type, * curveDatas[i].propertyName, * curveDatas[i].curve * ); * }*/ AssetDatabase.SaveAssets(); UnityEngine.Object[] newSelection = new UnityEngine.Object[Selection.objects.Length + 1]; for (int i = 0; i < Selection.objects.Length; i++) { newSelection [i] = Selection.objects [i]; } newSelection [newSelection.Length - 1] = newClip; Selection.objects = newSelection; /* * transform.GetComponent<Animator> ().StartRecording (0); * * * Invoke ("stopRecording", leng); */ } Debug.Log("Finished Baking."); }