diff --git a/.gitignore b/.gitignore index a09bc06..103a37b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,10 @@ +# Unity generated directories +/Library/ +/Temp/ + +# Visual Studio cache directory +/.vs/ + +# Autogenerated VS/MD/Consulo solution and project files +*.csproj *.sln -*.userprefs -Temp -Library diff --git a/Assets/Spriter2UnityDX/Editor/AnimationBuilder.cs b/Assets/Spriter2UnityDX/Editor/AnimationBuilder.cs index 1222318..cb421c1 100644 --- a/Assets/Spriter2UnityDX/Editor/AnimationBuilder.cs +++ b/Assets/Spriter2UnityDX/Editor/AnimationBuilder.cs @@ -24,19 +24,24 @@ public class AnimationBuilder : UnityEngine.Object { private string PrefabPath; private string AnimationsPath; private Transform Root; - private IDictionary OriginalClips = new Dictionary (); + private IDictionary OriginalClips = new Dictionary (); private IDictionary DefaultBones; private IDictionary DefaultSprites; private AnimatorController Controller; private bool ModdedController = false; public AnimationBuilder (ScmlProcessingInfo info, IDictionary> folders, - IDictionary transforms, IDictionary defaultBones, - IDictionary defaultSprites, - string prefabPath, AnimatorController controller) { - ProcessingInfo = info; Folders = folders; Transforms = transforms; PrefabPath = prefabPath; - DefaultBones = defaultBones; DefaultSprites = defaultSprites; - Root = Transforms ["rootTransform"]; Controller = controller; + IDictionary transforms, IDictionary defaultBones, + IDictionary defaultSprites, + string prefabPath, AnimatorController controller) { + ProcessingInfo = info; + Folders = folders; + Transforms = transforms; + PrefabPath = prefabPath; + DefaultBones = defaultBones; + DefaultSprites = defaultSprites; + Root = Transforms ["rootTransform"]; + Controller = controller; AnimationsPath = PrefabPath.Substring (0, PrefabPath.LastIndexOf ('.')) + "_Anims"; foreach (var item in GetOrigClips ()) { @@ -58,8 +63,10 @@ public Object[] GetOrigClips () { public void Build (Animation animation, IDictionary timeLines) { var clip = new AnimationClip (); clip.name = animation.name; - var pendingTransforms = new Dictionary (Transforms); //This Dictionary will shrink in size for every transform - foreach (var key in animation.mainlineKeys) { //that is considered "used" + //This Dictionary will shrink in size for every transform + //that is considered "used" + var pendingTransforms = new Dictionary (Transforms); + foreach (var key in animation.mainlineKeys) { var parentTimelines = new Dictionary> (); var brefs = new Queue (key.boneRefs ?? new Ref [0]); while (brefs.Count > 0) { @@ -68,7 +75,8 @@ public void Build (Animation animation, IDictionary timeLines) { var timeLine = timeLines [bref.timeline]; parentTimelines [bref.id] = new List (timeLine.keys); Transform bone; - if (pendingTransforms.TryGetValue (timeLine.name, out bone)) { //Skip it if it's already "used" + //Skip it if it's already "used" + if (pendingTransforms.TryGetValue (timeLine.name, out bone)) { List parentTimeline; parentTimelines.TryGetValue (bref.parent, out parentTimeline); SetCurves (bone, DefaultBones [timeLine.name], parentTimeline, timeLine, clip, animation); @@ -89,7 +97,8 @@ public void Build (Animation animation, IDictionary timeLines) { pendingTransforms.Remove (timeLine.name); } } - foreach (var kvPair in pendingTransforms) { //Disable the remaining tansforms if they are sprites and not already disabled + //Disable the remaining tansforms if they are sprites and not already disabled + foreach (var kvPair in pendingTransforms) { if (DefaultSprites.ContainsKey (kvPair.Key) && kvPair.Value.gameObject.activeSelf) { var curve = new AnimationCurve (new Keyframe (0f, 0f, inf, inf)); clip.SetCurve (GetPathToChild (kvPair.Value), typeof(GameObject), "m_IsActive", curve); @@ -97,14 +106,17 @@ public void Build (Animation animation, IDictionary timeLines) { } } var settings = AnimationUtility.GetAnimationClipSettings (clip); - settings.stopTime = animation.length; //Set the animation's length and other settings + //Set the animation's length and other settings + settings.stopTime = animation.length; if (animation.looping) { clip.wrapMode = WrapMode.Loop; settings.loopTime = true; } else clip.wrapMode = WrapMode.ClampForever; AnimationUtility.SetAnimationClipSettings (clip, settings); - if (OriginalClips.ContainsKey (animation.name)) { //If the clip already exists, copy this clip into the old one + //If the clip already exists, copy this clip into the old one + //Otherwise create a new one + if (OriginalClips.ContainsKey (animation.name)) { var oldClip = OriginalClips [animation.name]; var cachedEvents = oldClip.events; EditorUtility.CopySerialized (clip, oldClip); @@ -113,8 +125,8 @@ public void Build (Animation animation, IDictionary timeLines) { ProcessingInfo.ModifiedAnims.Add (clip); } else { switch (S2USettings.ImportStyle) { - case AnimationImportOption.NestedInPrefab : - AssetDatabase.AddObjectToAsset (clip, PrefabPath); //Otherwise create a new one + case AnimationImportOption.NestedInPrefab : + AssetDatabase.AddObjectToAsset (clip, PrefabPath); break; case AnimationImportOption.SeparateFolder : if (!AssetDatabase.IsValidFolder (AnimationsPath)) { @@ -128,10 +140,14 @@ public void Build (Animation animation, IDictionary timeLines) { } ProcessingInfo.NewAnims.Add (clip); } - if (!ArrayUtility.Contains (Controller.animationClips, clip)) { //Don't add the clip if it's already there - var state = GetStateFromController (clip.name); //Find a state of the same name - if (state != null) state.motion = clip; //If it exists, replace it - else Controller.AddMotion (clip); //Otherwise add it as a new state + //Don't add the clip if it's already there + if (!ArrayUtility.Contains (Controller.animationClips, clip)) { + //Find a state of the same name + var state = GetStateFromController (clip.name); + //If it exists, replace it + //Otherwise add it as a new state + if (state != null) state.motion = clip; + else Controller.AddMotion (clip); if (!ModdedController) { if (!ProcessingInfo.NewControllers.Contains (Controller) && !ProcessingInfo.ModifiedControllers.Contains (Controller)) ProcessingInfo.ModifiedControllers.Add (Controller); @@ -147,8 +163,10 @@ private void SetCurves (Transform child, SpatialInfo defaultInfo, List parentTimeline, TimeLine timeLine, AnimationClip clip, Animation animation, ref float defaultZ) { var childPath = GetPathToChild (child); - foreach (var kvPair in GetCurves (timeLine, defaultInfo, parentTimeline)) { //Makes sure that curves are only added for properties - switch (kvPair.Key) { //that actually mutate in the animation + //Makes sure that curves are only added for properties + //that actually mutate in the animation + foreach (var kvPair in GetCurves (timeLine, defaultInfo, parentTimeline)) { + switch (kvPair.Key) { case ChangedValues.PositionX : SetKeys (kvPair.Value, timeLine, x => x.x, animation); clip.SetCurve (childPath, typeof(Transform), "localPosition.x", kvPair.Value); @@ -160,7 +178,8 @@ private void SetCurves (Transform child, SpatialInfo defaultInfo, List x.rotation.z, animation); @@ -187,21 +206,20 @@ private void SetCurves (Transform child, SpatialInfo defaultInfo, List(); - if (swapper == null) - { //Add a Texture Controller if one doesn't already exist - swapper = child.gameObject.AddComponent(); - var info = (SpriteInfo)defaultInfo; - swapper.Sprites = new[] { Folders[info.folder][info.file] }; - } - SetKeys(kvPair.Value, timeLine, ref swapper.Sprites, animation); - clip.SetCurve(childPath, typeof(TextureController), "DisplayedSprite", kvPair.Value); - } + if (ScmlImportOptions.options != null && ScmlImportOptions.options.useUnitySpriteSwapping) { + SetSpriteSwapKeys (child, timeLine, clip, animation); + } + else { + var swapper = child.GetComponent (); + if (swapper == null) { + //Add a Texture Controller if one doesn't already exist + swapper = child.gameObject.AddComponent (); + var info = (SpriteInfo)defaultInfo; + swapper.Sprites = new[] { Folders [info.folder] [info.file] }; + } + SetKeys (kvPair.Value, timeLine, ref swapper.Sprites, animation); + clip.SetCurve (childPath, typeof(TextureController), "DisplayedSprite", kvPair.Value); + } break; } } @@ -213,10 +231,13 @@ private void SetAdditionalCurves (Transform child, MainLineKey[] keys, TimeLine var positionChanged = false; var kfsZ = new List (); var changedZ = false; - var active = child.gameObject.activeSelf; //If the sprite or bone isn't present in the mainline, - var kfsActive = new List (); //Disable the GameObject if it isn't already disabled + //If the sprite or bone isn't present in the mainline, + //Disable the GameObject if it isn't already disabled + //If it is present, enable the GameObject if it isn't already enabled + var active = child.gameObject.activeSelf; + var kfsActive = new List (); var childPath = GetPathToChild (child); - foreach (var key in keys) { //If it is present, enable the GameObject if it isn't already enabled + foreach (var key in keys) { var mref = ArrayUtility.Find (key.objectRefs, x => x.timeline == timeLine.id); if (mref != null) { if (defaultZ == inf) { @@ -227,7 +248,7 @@ private void SetAdditionalCurves (Transform child, MainLineKey[] keys, TimeLine changedZ = true; if (key.time > 0) kfsZ.Add (new Keyframe (0f, defaultZ, inf, inf)); } - if (changedZ) + if (changedZ) kfsZ.Add (new Keyframe (key.time, mref.z_index, inf, inf)); if (!active) { if (kfsActive.Count <= 0 && key.time > 0) kfsActive.Add (new Keyframe (0f, 0f, inf, inf)); @@ -240,11 +261,13 @@ private void SetAdditionalCurves (Transform child, MainLineKey[] keys, TimeLine kfsActive.Add (new Keyframe (key.time, 0f, inf, inf)); active = false; } - } //Only add these curves if there is actually a mutation + } + //Only add these curves if there is actually a mutation if (kfsZ.Count > 0) { clip.SetCurve (childPath, typeof(Transform), "localPosition.z", new AnimationCurve (kfsZ.ToArray ())); + //If these curves don't actually exist, add some empty ones if (!positionChanged) { - var info = timeLine.keys [0].info; //If these curves don't actually exist, add some empty ones + var info = timeLine.keys [0].info; clip.SetCurve (childPath, typeof(Transform), "localPosition.x", new AnimationCurve (new Keyframe (0f, info.x))); clip.SetCurve (childPath, typeof(Transform), "localPosition.y", new AnimationCurve (new Keyframe (0f, info.y))); } @@ -253,42 +276,58 @@ private void SetAdditionalCurves (Transform child, MainLineKey[] keys, TimeLine } private void SetKeys (AnimationCurve curve, TimeLine timeLine, Func infoValue, Animation animation) { - foreach (var key in timeLine.keys) { //Create a keyframe for every key on its personal TimeLine + //Create a keyframe for every key on its personal TimeLine + foreach (var key in timeLine.keys) { curve.AddKey (key.time, infoValue (key.info)); } - var lastIndex = (animation.looping) ? 0 : timeLine.keys.Length - 1; //Depending on the loop type, duplicate the first or last frame - curve.AddKey (animation.length, infoValue (timeLine.keys [lastIndex].info)); //At the end of the curve + //Depending on the loop type, duplicate the first or last frame + //At the end of the curve + var lastIndex = (animation.looping) ? 0 : timeLine.keys.Length - 1; + curve.AddKey (animation.length, infoValue (timeLine.keys [lastIndex].info)); } private void SetKeys (AnimationCurve curve, TimeLine timeLine, ref Sprite[] sprites, Animation animation) { - foreach (var key in timeLine.keys) { //Create a key for every key on its personal TimeLine + //Create a key for every key on its personal TimeLine + foreach (var key in timeLine.keys) { var info = (SpriteInfo)key.info; curve.AddKey (new Keyframe (key.time, GetIndexOrAdd (ref sprites, Folders [info.folder] [info.file]), inf, inf)); - } //InTangent and OutTangent are set to Infinity to make transitions instant instead of gradual + } + //InTangent and OutTangent are set to Infinity to make transitions instant instead of gradual var lastIndex = (animation.looping) ? 0 : timeLine.keys.Length - 1; var lastInfo = (SpriteInfo)timeLine.keys [lastIndex].info; curve.AddKey (new Keyframe (animation.length, GetIndexOrAdd (ref sprites, Folders [lastInfo.folder] [lastInfo.file]), inf, inf)); } - void SetSpriteSwapKeys(Transform child, TimeLine timeLine, AnimationClip clip, Animation animation) - { - // Create ObjectReferenceCurve for swapping sprites. This curve will save data in object form instead of floats like regular AnimationCurve. - var keyframes = new List(); - foreach (var key in timeLine.keys) - { - var info = (SpriteInfo)key.info; - var sprite = Folders[info.folder][info.file]; - keyframes.Add(new ObjectReferenceKeyframe { time = key.time, value = sprite }); - } - var lastIndex = (animation.looping) ? 0 : timeLine.keys.Length - 1; - var lastInfo = (SpriteInfo)timeLine.keys[lastIndex].info; - keyframes.Add(new ObjectReferenceKeyframe { time = animation.length, value = Folders[lastInfo.folder][lastInfo.file] }); - AnimationUtility.SetObjectReferenceCurve(clip, new EditorCurveBinding { path = GetPathToChild(child), propertyName = "m_Sprite", type = typeof(SpriteRenderer) }, keyframes.ToArray()); - } + void SetSpriteSwapKeys(Transform child, TimeLine timeLine, AnimationClip clip, Animation animation) { + // Create ObjectReferenceCurve for swapping sprites. This curve will save data in object form instead of floats like regular AnimationCurve. + var keyframes = new List(); + foreach (var key in timeLine.keys) + { + var info = (SpriteInfo)key.info; + var sprite = Folders [info.folder] [info.file]; + keyframes.Add (new ObjectReferenceKeyframe { + time = key.time, + value = sprite + }); + } + var lastIndex = (animation.looping) ? 0 : timeLine.keys.Length - 1; + var lastInfo = (SpriteInfo)timeLine.keys [lastIndex].info; + keyframes.Add (new ObjectReferenceKeyframe { + time = animation.length, + value = Folders [lastInfo.folder] [lastInfo.file] + }); + AnimationUtility.SetObjectReferenceCurve(clip, new EditorCurveBinding { + path = GetPathToChild(child), + propertyName = "m_Sprite", + type = typeof(SpriteRenderer) + }, keyframes.ToArray()); + } private int GetIndexOrAdd (ref Sprite[] sprites, Sprite sprite) { - var index = ArrayUtility.IndexOf (sprites, sprite); //If the array already contains the sprite, return index - if (index < 0) { //Otherwise, add sprite to array, then return index + //If the array already contains the sprite, return index + //Otherwise, add sprite to array, then return index + var index = ArrayUtility.IndexOf (sprites, sprite); + if (index < 0) { ArrayUtility.Add (ref sprites, sprite); index = ArrayUtility.IndexOf (sprites, sprite); } @@ -313,18 +352,33 @@ private AnimatorState GetStateFromMachine (AnimatorStateMachine machine, string } return null; } - + private IDictionary ChildPaths = new Dictionary (); - private string GetPathToChild (Transform child) { //Caches the relative paths to children so they only have to be calculated once + //Caches the relative paths to children so they only have to be calculated once + private string GetPathToChild (Transform child) { string path; - if (ChildPaths.TryGetValue (child, out path)) return path; + if (ChildPaths.TryGetValue (child, out path)) return path; else return ChildPaths [child] = AnimationUtility.CalculateTransformPath (child, Root); } - private enum ChangedValues { None, Sprite, PositionX, PositionY, PositionZ, RotationZ, RotationW, ScaleX, ScaleY, ScaleZ, Alpha } + private enum ChangedValues { + None, + Sprite, + PositionX, + PositionY, + PositionZ, + RotationZ, + RotationW, + ScaleX, + ScaleY, + ScaleZ, + Alpha, + } + //This method checks every animatable property for changes + //And creates a curve for that property if changes are detected private IDictionary GetCurves (TimeLine timeLine, SpatialInfo defaultInfo, List parentTimeline) { - var rv = new Dictionary (); //This method checks every animatable property for changes - foreach (var key in timeLine.keys) { //And creates a curve for that property if changes are detected + var rv = new Dictionary (); + foreach (var key in timeLine.keys) { var info = key.info; if (!info.processed) { SpatialInfo parentInfo = null; @@ -344,13 +398,16 @@ private IDictionary GetCurves (TimeLine timeLine, } info.Process (parentInfo); } + //There will be irregular behaviour if curves aren't added for all members + //in a group, so when one is set, the others have to be set as well if (!rv.ContainsKey (ChangedValues.PositionX) && (defaultInfo.x != info.x || defaultInfo.y != info.y)) { - rv [ChangedValues.PositionX] = new AnimationCurve (); //There will be irregular behaviour if curves aren't added for all members - rv [ChangedValues.PositionY] = new AnimationCurve (); //in a group, so when one is set, the others have to be set as well + rv [ChangedValues.PositionX] = new AnimationCurve (); + rv [ChangedValues.PositionY] = new AnimationCurve (); rv [ChangedValues.PositionZ] = new AnimationCurve (); } if (!rv.ContainsKey (ChangedValues.RotationZ) && (defaultInfo.rotation.z != info.rotation.z || defaultInfo.rotation.w != info.rotation.w)) { - rv [ChangedValues.RotationZ] = new AnimationCurve ();//x and y not necessary since the default of 0 is fine + //x and y not necessary since the default of 0 is fine + rv [ChangedValues.RotationZ] = new AnimationCurve (); rv [ChangedValues.RotationW] = new AnimationCurve (); } if (!rv.ContainsKey (ChangedValues.ScaleX) && (defaultInfo.scale_x != info.scale_x || defaultInfo.scale_y != info.scale_y)) { diff --git a/Assets/Spriter2UnityDX/Editor/CustomEditors.cs b/Assets/Spriter2UnityDX/Editor/CustomEditors.cs index ad8b84e..f2f930f 100644 --- a/Assets/Spriter2UnityDX/Editor/CustomEditors.cs +++ b/Assets/Spriter2UnityDX/Editor/CustomEditors.cs @@ -16,24 +16,38 @@ private void OnEnable () { } // Get the sorting layer names - private string[] GetSortingLayerNames() { - var sortingLayers = typeof(InternalEditorUtility).GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic); - return (string[])sortingLayers.GetValue(null, new object[0]); + private string[] GetSortingLayerNames () { + var sortingLayers = typeof(InternalEditorUtility).GetProperty ("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic); + return (string[])sortingLayers.GetValue (null, new object[0]); } - public override void OnInspectorGUI () - { + public override void OnInspectorGUI () { var changed = false; var color = EditorGUILayout.ColorField ("Color", renderer.Color); - if (color != renderer.Color) {renderer.Color = color; changed = true;} + if (color != renderer.Color) { + renderer.Color = color; + changed = true; + } var material = (Material)EditorGUILayout.ObjectField ("Material", renderer.Material, typeof(Material), false); - if (material != renderer.Material) {renderer.Material = material; changed = true;} + if (material != renderer.Material) { + renderer.Material = material; + changed = true; + } var sortIndex = EditorGUILayout.Popup ("Sorting Layer", GetIndex (renderer.SortingLayerName), layerNames, GUILayout.ExpandWidth (true)); - if (layerNames [sortIndex] != renderer.SortingLayerName) {renderer.SortingLayerName = layerNames[sortIndex]; changed = true;} + if (layerNames [sortIndex] != renderer.SortingLayerName) { + renderer.SortingLayerName = layerNames[sortIndex]; + changed = true; + } var sortingOrder = EditorGUILayout.IntField ("Order In Layer", renderer.SortingOrder); - if (sortingOrder != renderer.SortingOrder) {renderer.SortingOrder = sortingOrder; changed = true;} + if (sortingOrder != renderer.SortingOrder) { + renderer.SortingOrder = sortingOrder; + changed = true; + } var applyZ = EditorGUILayout.Toggle ("Apply Spriter Z Order", renderer.ApplySpriterZOrder); - if (applyZ != renderer.ApplySpriterZOrder) {renderer.ApplySpriterZOrder = applyZ; changed = true;} + if (applyZ != renderer.ApplySpriterZOrder) { + renderer.ApplySpriterZOrder = applyZ; + changed = true; + } if (changed) EditorUtility.SetDirty(renderer); } diff --git a/Assets/Spriter2UnityDX/Editor/PrefabBuilder.cs b/Assets/Spriter2UnityDX/Editor/PrefabBuilder.cs index 5d15d9d..4e95f96 100644 --- a/Assets/Spriter2UnityDX/Editor/PrefabBuilder.cs +++ b/Assets/Spriter2UnityDX/Editor/PrefabBuilder.cs @@ -24,26 +24,34 @@ public bool Build (ScmlObject obj, string scmlPath) { //The process begins by loading up all the textures var success = true; var directory = Path.GetDirectoryName (scmlPath); - var folders = new Dictionary> (); //I find these slightly more useful than Lists because - foreach (var folder in obj.folders ) { //you can be 100% sure that the ids match - var files = folders [folder.id] = new Dictionary (); //And items can be added in any order + //I find these slightly more useful than Lists because + //you can be 100% sure that the ids match + //And items can be added in any order + var folders = new Dictionary> (); + foreach (var folder in obj.folders ) { + var files = folders [folder.id] = new Dictionary (); foreach (var file in folder.files) { var path = string.Format ("{0}/{1}", directory, file.name); files [file.id] = GetSpriteAtPath (path, file, ref success); } - } //The process ends here if any of the textures need to have their settings altered - if (!success) return false; //The process will be reattempted after the next import cycle - foreach (var entity in obj.entities) { //Now begins the real prefab build process + } + //The process ends here if any of the textures need to have their settings altered + //The process will be reattempted after the next import cycle + if (!success) return false; + //Now begins the real prefab build process + foreach (var entity in obj.entities) { var prefabPath = string.Format ("{0}/{1}.prefab", directory, entity.name); var prefab = (GameObject)AssetDatabase.LoadAssetAtPath (prefabPath, typeof(GameObject)); GameObject instance; - if (prefab == null) { //Creates an empty prefab if one doesn't already exists + //Creates an empty prefab if one doesn't already exists + //instantiates the prefab if it does exist + if (prefab == null) { instance = new GameObject (entity.name); prefab = PrefabUtility.CreatePrefab (prefabPath, instance, ReplacePrefabOptions.ConnectToPrefab); ProcessingInfo.NewPrefabs.Add (prefab); } else { - instance = (GameObject)PrefabUtility.InstantiatePrefab (prefab); //instantiates the prefab if it does exist + instance = (GameObject)PrefabUtility.InstantiatePrefab (prefab); ProcessingInfo.ModifiedPrefabs.Add (prefab); } try { @@ -51,7 +59,7 @@ public bool Build (ScmlObject obj, string scmlPath) { } catch (Exception e) { DestroyImmediate (instance); - Debug.LogErrorFormat("Unable to build a prefab for '{0}'. Reason: {1}", entity.name, e); + Debug.LogErrorFormat ("Unable to build a prefab for '{0}'. Reason: {1}", entity.name, e); } } return success; @@ -59,45 +67,63 @@ public bool Build (ScmlObject obj, string scmlPath) { private void TryBuild (Entity entity, GameObject prefab, GameObject instance, string directory, string prefabPath, IDictionary> folders) { var controllerPath = string.Format ("{0}/{1}.controller", directory, entity.name); - var animator = instance.GetComponent (); //Fetches the prefab's Animator - if (animator == null) animator = instance.AddComponent (); //Or creates one if it doesn't exist + //Fetches the prefab's Animator + //Or creates one if it doesn't exist + var animator = instance.GetComponent (); + if (animator == null) animator = instance.AddComponent (); AnimatorController controller = null; - if (animator.runtimeAnimatorController != null) { //The controller we use is hopefully the controller attached to the animator - controller = animator.runtimeAnimatorController as AnimatorController ?? //Or the one that's referenced by an OverrideController + //The controller we use is hopefully the controller attached to the animator + //Or the one that's referenced by an OverrideController + if (animator.runtimeAnimatorController != null) { + controller = animator.runtimeAnimatorController as AnimatorController ?? (AnimatorController)((AnimatorOverrideController)animator.runtimeAnimatorController).runtimeAnimatorController; } - if (controller == null) { //Otherwise we have to check the AssetDatabase for our controller + //Otherwise we have to check the AssetDatabase for our controller + if (controller == null) { controller = (AnimatorController)AssetDatabase.LoadAssetAtPath (controllerPath, typeof(AnimatorController)); + //Or create a new one if it doesn't exist. if (controller == null) { - controller = AnimatorController.CreateAnimatorControllerAtPath (controllerPath); //Or create a new one if it doesn't exist. + controller = AnimatorController.CreateAnimatorControllerAtPath (controllerPath); ProcessingInfo.NewControllers.Add (controller); } animator.runtimeAnimatorController = controller; } - var transforms = new Dictionary (); //All of the bones and sprites, identified by TimeLine.name, because those are truly unique - transforms ["rootTransform"] = instance.transform; //The root GameObject needs to be part of this hierarchy as well - var defaultBones = new Dictionary (); //These are basically the object states on the first frame of the first animation - var defaultSprites = new Dictionary (); //They are used as control values in determining whether something has changed + //All of the bones and sprites, identified by TimeLine.name, because those are truly unique + //The root GameObject needs to be part of this hierarchy as well + //These are basically the object states on the first frame of the first animation + //They are used as control values in determining whether something has changed + var transforms = new Dictionary (); + transforms ["rootTransform"] = instance.transform; + var defaultBones = new Dictionary (); + var defaultSprites = new Dictionary (); var animBuilder = new AnimationBuilder (ProcessingInfo, folders, transforms, defaultBones, defaultSprites, prefabPath, controller); - var firstAnim = true; //The prefab's graphic will be determined by the first frame of the first animation + //The prefab's graphic will be determined by the first frame of the first animation + var firstAnim = true; foreach (var animation in entity.animations) { var timeLines = new Dictionary (); - foreach (var timeLine in animation.timelines) //TimeLines hold all the critical data such as positioning and graphics used + //TimeLines hold all the critical data such as positioning and graphics used + foreach (var timeLine in animation.timelines) timeLines [timeLine.id] = timeLine; foreach (var key in animation.mainlineKeys) { - var parents = new Dictionary (); //Parents are referenced by different IDs V_V - parents [-1] = "rootTransform"; //This is where "-1 == no parent" comes in handy + //Parents are referenced by different IDs V_V + //This is where "-1 == no parent" comes in handy + var parents = new Dictionary (); + parents [-1] = "rootTransform"; var boneRefs = new Queue (key.boneRefs ?? new Ref[0]); while (boneRefs.Count > 0) { var bone = boneRefs.Dequeue (); var timeLine = timeLines [bone.timeline]; parents [bone.id] = timeLine.name; - if (!transforms.ContainsKey (timeLine.name)) { //We only need to go through this once, so ignore it if it's already in the dict - if (parents.ContainsKey (bone.parent)) { //If the parent cannot be found, it will probably be found later, so save it + //We only need to go through this once, so ignore it if it's already in the dict + if (!transforms.ContainsKey (timeLine.name)) { + //If the parent cannot be found, it will probably be found later, so save it + if (parents.ContainsKey (bone.parent)) { var parentID = parents [bone.parent]; var parent = transforms [parentID]; - var child = parent.Find (timeLine.name); //Try to find the child transform if it exists - if (child == null) { //Or create a new one + //Try to find the child transform if it exists + var child = parent.Find (timeLine.name); + //Or create a new one + if (child == null) { child = new GameObject (timeLine.name).transform; child.SetParent (parent); } @@ -117,7 +143,8 @@ private void TryBuild (Entity entity, GameObject prefab, GameObject instance, st } foreach (var oref in key.objectRefs) { var timeLine = timeLines [oref.timeline]; - if (!transforms.ContainsKey (timeLine.name)) { //Same as above + //Same as above + if (!transforms.ContainsKey (timeLine.name)) { var parentID = parents [oref.parent]; var parent = transforms [parentID]; var child = parent.Find (timeLine.name); @@ -126,9 +153,11 @@ private void TryBuild (Entity entity, GameObject prefab, GameObject instance, st child.SetParent (parent); } transforms [timeLine.name] = child; - var swapper = child.GetComponent (); //Destroy the Sprite Swapper, we'll make a new one later + //Destroy the Sprite Swapper, we'll make a new one later + var swapper = child.GetComponent (); if (swapper != null) DestroyImmediate (swapper); - var renderer = child.GetComponent (); //Get or create a Sprite Renderer + //Get or create a Sprite Renderer + var renderer = child.GetComponent (); if (renderer == null) renderer = child.gameObject.AddComponent (); var spriteInfo = defaultSprites [timeLine.name] = (SpriteInfo)ArrayUtility.Find (timeLine.keys, x => x.id == 0).info; renderer.sprite = folders [spriteInfo.folder] [spriteInfo.file]; @@ -137,45 +166,58 @@ private void TryBuild (Entity entity, GameObject prefab, GameObject instance, st defaultBones.TryGetValue (parentID, out parentInfo); spriteInfo.Process (parentInfo); } - child.localPosition = new Vector3 (spriteInfo.x, spriteInfo.y, oref.z_index); //Z-index helps determine draw order - child.localEulerAngles = new Vector3 (0f, 0f, spriteInfo.angle); //The reason I don't use layers or layer orders is because - child.localScale = new Vector3 (spriteInfo.scale_x, spriteInfo.scale_y, 1f); //There tend to be a LOT of body parts, it's better to treat - var color = renderer.color; //The entity as a single sprite for layer sorting purposes. + //Z-index helps determine draw + //The reason I don't use layers or layer orders is because + //There tend to be a LOT of body parts, it's better to treat + //The entity as a single sprite for layer sorting purposes. + child.localPosition = new Vector3 (spriteInfo.x, spriteInfo.y, oref.z_index); + child.localEulerAngles = new Vector3 (0f, 0f, spriteInfo.angle); + child.localScale = new Vector3 (spriteInfo.scale_x, spriteInfo.scale_y, 1f); + var color = renderer.color; color.a = spriteInfo.a; renderer.color = color; - if (!firstAnim) child.gameObject.SetActive (false); //Disable the GameObject if this isn't the first frame of the first animation + //Disable the GameObject if this isn't the first frame of the first animation + if (!firstAnim) child.gameObject.SetActive (false); } } if (firstAnim) firstAnim = false; } try { - animBuilder.Build (animation, timeLines); //Builds the currently processed AnimationClip, see AnimationBuilder for more info + //Builds the currently processed AnimationClip, see AnimationBuilder for more info + animBuilder.Build (animation, timeLines); } catch (Exception e) { Debug.LogErrorFormat ("Unable to build animation '{0}' for '{1}', reason: {2}", animation.name, entity.name, e); } } - if (instance.GetComponent () == null) instance.AddComponent (); //Adds an EntityRenderer if one is not already present + //Adds an EntityRenderer if one is not already present + if (instance.GetComponent () == null) instance.AddComponent (); PrefabUtility.ReplacePrefab (instance, prefab, ReplacePrefabOptions.ConnectToPrefab); - DestroyImmediate (instance); //Apply the instance's changes to the prefab, then destroy the instance. + //Apply the instance's changes to the prefab, then destroy the instance. + DestroyImmediate (instance); } - private IList InvalidImporters = new List (); //Importers in this list have already been processed and don't need to be processed again + //Importers in this list have already been processed and don't need to be processed again + private IList InvalidImporters = new List (); private Sprite GetSpriteAtPath (string path, File file, ref bool success) { var importer = TextureImporter.GetAtPath (path) as TextureImporter; - if (importer != null) { //If no TextureImporter exists, there's no texture to be found - if ((importer.textureType != TextureImporterType.Sprite || importer.spritePivot.x != file.pivot_x - || importer.spritePivot.y != file.pivot_y || (ScmlImportOptions.options != null && importer.spritePixelsPerUnit != ScmlImportOptions.options.pixelsPerUnit)) && !InvalidImporters.Contains (importer)) { - if (success) success = false; //If the texture type isn't Sprite, or the pivot isn't set properly, - var settings = new TextureImporterSettings (); //set the texture type and pivot - importer.ReadTextureSettings (settings); //and make success false so the process can abort - settings.ApplyTextureType (TextureImporterType.Sprite, true); //after all the textures have been processed + //If no TextureImporter exists, there's no texture to be found + if (importer != null) { + //If the texture type isn't Sprite, or the pivot isn't set properly, + //set the texture type and pivot + //and make success false so the process can abort + //after all the textures have been processed + if ((importer.textureType != TextureImporterType.Sprite || importer.spritePivot.x != file.pivot_x + || importer.spritePivot.y != file.pivot_y || (ScmlImportOptions.options != null && importer.spritePixelsPerUnit != ScmlImportOptions.options.pixelsPerUnit)) && !InvalidImporters.Contains (importer)) { + if (success) success = false; + var settings = new TextureImporterSettings (); + importer.ReadTextureSettings (settings); + settings.ApplyTextureType (TextureImporterType.Sprite, true); settings.spriteAlignment = (int)SpriteAlignment.Custom; settings.spritePivot = new Vector2 (file.pivot_x, file.pivot_y); - if(ScmlImportOptions.options != null) - { - settings.spritePixelsPerUnit = ScmlImportOptions.options.pixelsPerUnit; - } + if (ScmlImportOptions.options != null) { + settings.spritePixelsPerUnit = ScmlImportOptions.options.pixelsPerUnit; + } importer.SetTextureSettings (settings); importer.SaveAndReimport (); InvalidImporters.Add (importer); diff --git a/Assets/Spriter2UnityDX/Editor/S2USettings.cs b/Assets/Spriter2UnityDX/Editor/S2USettings.cs index cd433b2..be00575 100644 --- a/Assets/Spriter2UnityDX/Editor/S2USettings.cs +++ b/Assets/Spriter2UnityDX/Editor/S2USettings.cs @@ -19,9 +19,13 @@ public static void Select () { } } - public enum AnimationImportOption : byte { NestedInPrefab, SeparateFolder } + public enum AnimationImportOption : byte { + NestedInPrefab, + SeparateFolder, + } - [CustomEditor (typeof(S2USettings))] public class SettingsEditor: Editor { + [CustomEditor (typeof(S2USettings))] + public class SettingsEditor: Editor { private AnimationImportOption importStyle; private void OnEnable () { @@ -34,7 +38,7 @@ private void OnDisable () { public override void OnInspectorGUI () { EditorGUI.BeginChangeCheck (); - var label = new GUIContent ("Animation Import Style", + var label = new GUIContent ("Animation Import Style", "By default, animations are nested into the generated prefab. Change this option to instead place animations into a separate folder."); importStyle = (AnimationImportOption)EditorGUILayout.EnumPopup (label, importStyle); if (EditorGUI.EndChangeCheck ()) S2USettings.ImportStyle = importStyle; diff --git a/Assets/Spriter2UnityDX/Editor/ScmlImportOptions.cs b/Assets/Spriter2UnityDX/Editor/ScmlImportOptions.cs index 0692e7b..a9871c5 100644 --- a/Assets/Spriter2UnityDX/Editor/ScmlImportOptions.cs +++ b/Assets/Spriter2UnityDX/Editor/ScmlImportOptions.cs @@ -2,39 +2,30 @@ using UnityEngine; using System.Collections; -namespace Spriter2UnityDX.Importing -{ - public class ScmlImportOptionsWindow : EditorWindow - { - public System.Action OnClose; - - void OnEnable() - { - titleContent = new GUIContent("Import Options"); - } +namespace Spriter2UnityDX.Importing { + public class ScmlImportOptionsWindow : EditorWindow { + public System.Action OnClose; - void OnGUI() - { - ScmlImportOptions.options.pixelsPerUnit = EditorGUILayout.FloatField("Pixels per unit", ScmlImportOptions.options.pixelsPerUnit); - ScmlImportOptions.options.useUnitySpriteSwapping = EditorGUILayout.Toggle("Unity's native sprite swapping", ScmlImportOptions.options.useUnitySpriteSwapping); - if(GUILayout.Button("Done")) - { - Close(); - } - } + private void OnEnable() { + titleContent = new GUIContent ("Import Options"); + } - void OnDestroy() - { - OnClose(); - } - } + private void OnGUI() { + ScmlImportOptions.options.pixelsPerUnit = EditorGUILayout.FloatField ("Pixels per unit", ScmlImportOptions.options.pixelsPerUnit); + ScmlImportOptions.options.useUnitySpriteSwapping = EditorGUILayout.Toggle ("Unity's native sprite swapping", ScmlImportOptions.options.useUnitySpriteSwapping); + if (GUILayout.Button ("Done")) { + Close (); + } + } - public class ScmlImportOptions - { - public static ScmlImportOptions options = null; + private void OnDestroy() { + OnClose (); + } + } - public float pixelsPerUnit = 100f; - - public bool useUnitySpriteSwapping; - } -} \ No newline at end of file + public class ScmlImportOptions { + public static ScmlImportOptions options = null; + public float pixelsPerUnit = 100f; + public bool useUnitySpriteSwapping; + } +} diff --git a/Assets/Spriter2UnityDX/Editor/ScmlImportOptions.cs.meta b/Assets/Spriter2UnityDX/Editor/ScmlImportOptions.cs.meta new file mode 100644 index 0000000..182da0d --- /dev/null +++ b/Assets/Spriter2UnityDX/Editor/ScmlImportOptions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 620d2ac71a2a5b54b996076fd0da92f5 +timeCreated: 1522924039 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spriter2UnityDX/Editor/ScmlPostProcessor.cs b/Assets/Spriter2UnityDX/Editor/ScmlPostProcessor.cs index de2baec..8b288e7 100644 --- a/Assets/Spriter2UnityDX/Editor/ScmlPostProcessor.cs +++ b/Assets/Spriter2UnityDX/Editor/ScmlPostProcessor.cs @@ -20,45 +20,41 @@ public class ScmlPostProcessor : AssetPostprocessor { //Called after an import, detects if imported files end in .scml private static void OnPostprocessAllAssets (string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { var filesToProcess = new List (); - bool optionsNeedUpdated = false; - foreach (var path in importedAssets) - { - if (path.EndsWith(".scml") && !path.Contains("autosave")) - { - filesToProcess.Add(path); - if(!cachedPaths.Contains(path)) - { - optionsNeedUpdated = true; - } - } - } - foreach (var path in cachedPaths) { //Are there any incomplete processes from the last import cycle? + bool optionsNeedUpdated = false; + foreach (var path in importedAssets) { + if (path.EndsWith (".scml") && !path.Contains ("autosave")) { + filesToProcess.Add (path); + if (!cachedPaths.Contains (path)) { + optionsNeedUpdated = true; + } + } + } + //Are there any incomplete processes from the last import cycle? + foreach (var path in cachedPaths) { if (!filesToProcess.Contains (path)) filesToProcess.Add (path); } cachedPaths.Clear (); - if (filesToProcess.Count > 0) - { - if(optionsNeedUpdated || ScmlImportOptions.options == null) - { - ScmlImportOptionsWindow optionsWindow = EditorWindow.GetWindow(); - ScmlImportOptions.options = new ScmlImportOptions(); - optionsWindow.OnClose += () => ProcessFiles(filesToProcess); - } - else - { - ProcessFiles(filesToProcess); - } - } - + if (filesToProcess.Count > 0) { + if (optionsNeedUpdated || ScmlImportOptions.options == null) { + ScmlImportOptionsWindow optionsWindow = EditorWindow.GetWindow (); + ScmlImportOptions.options = new ScmlImportOptions (); + optionsWindow.OnClose += () => ProcessFiles (filesToProcess); + } + else { + ProcessFiles (filesToProcess); + } + } } private static void ProcessFiles (IList paths) { var info = new ScmlProcessingInfo (); var builder = new PrefabBuilder (info); - foreach (var path in paths) - if (!builder.Build (Deserialize (path), path)) //Process will fail if texture import settings need to be updated - cachedPaths.Add (path); //Failed processes will be saved and re-attempted during the next import cycle + foreach (var path in paths) + //Process will fail if texture import settings need to be updated + //Failed processes will be saved and re-attempted during the next import cycle + if (!builder.Build (Deserialize (path), path)) + cachedPaths.Add (path); AssetDatabase.Refresh (); AssetDatabase.SaveAssets (); PostProcess (info); @@ -86,9 +82,12 @@ public class ScmlProcessingInfo { public List NewControllers { get; set; } public List ModifiedControllers { get; set; } public ScmlProcessingInfo () { - NewPrefabs = new List (); ModifiedPrefabs = new List (); - NewAnims = new List (); ModifiedAnims = new List (); - NewControllers = new List (); ModifiedControllers = new List (); + NewPrefabs = new List (); + ModifiedPrefabs = new List (); + NewAnims = new List (); + ModifiedAnims = new List (); + NewControllers = new List (); + ModifiedControllers = new List (); } } } diff --git a/Assets/Spriter2UnityDX/Editor/ScmlSupport.cs b/Assets/Spriter2UnityDX/Editor/ScmlSupport.cs index bf1ddf6..b2a87ab 100644 --- a/Assets/Spriter2UnityDX/Editor/ScmlSupport.cs +++ b/Assets/Spriter2UnityDX/Editor/ScmlSupport.cs @@ -12,19 +12,26 @@ //It is directly deserialized into these classes, although some individual values are //modified into a format that can be used by Unity namespace Spriter2UnityDX.Importing { + //Master class that holds all the other data [XmlRoot ("spriter_data")] - public class ScmlObject { //Master class that holds all the other data - [XmlElement ("folder")] public Folder[] folders { get; set; } // tags - [XmlElement ("entity")] public Entity[] entities { get; set; } // tags + public class ScmlObject { + // tags + [XmlElement ("folder")] public Folder[] folders { get; set; } + // tags + [XmlElement ("entity")] public Entity[] entities { get; set; } } - + public class Folder : ScmlElement { [XmlAttribute] public string name { get; set; } - [XmlElement ("file")] public File[] files { get; set; } // tags + // tags + [XmlElement ("file")] public File[] files { get; set; } } public class File : ScmlElement { - public File () {pivot_x=0f; pivot_y=1f;} + public File () { + pivot_x = 0f; + pivot_y = 1f; + } [XmlAttribute] public string name { get; set; } [XmlAttribute] public float pivot_x { get; set; } [XmlAttribute] public float pivot_y { get; set; } @@ -33,145 +40,203 @@ public class File : ScmlElement { //Dengar.NOTE: the above comments are an artifact from the pseudocode that these classes are based on //I don't use the 'fileReference' variable because I access everything a bit differently } - + public class Entity : ScmlElement { [XmlAttribute] public string name { get; set; } - [XmlElement ("character_map")] public CharacterMap[] characterMaps { get; set; } // tags - [XmlElement ("animation")] public Animation[] animations { get; set; } // tags + // tags + [XmlElement ("character_map")] public CharacterMap[] characterMaps { get; set; } + // tags + [XmlElement ("animation")] public Animation[] animations { get; set; } } - + public class CharacterMap : ScmlElement { [XmlAttribute] public string name { get; set; } - [XmlElement ("map")] public MapInstruction[] maps { get; set; } // tags + // tags + [XmlElement ("map")] public MapInstruction[] maps { get; set; } } public class MapInstruction { - public MapInstruction () {target_folder=-1; target_file=-1;} + public MapInstruction () { + target_folder = -1; + target_file = -1; + } [XmlAttribute] public int folder { get; set; } [XmlAttribute] public int file { get; set; } [XmlAttribute] public int target_folder { get; set; } [XmlAttribute] public int target_file { get; set; } } - + public class Animation : ScmlElement { - public Animation () {looping=true;} + public Animation () { + looping = true; + } [XmlAttribute] public string name { get; set; } private float _length; - [XmlAttribute] public float length { + [XmlAttribute] public float length { get { return _length; } set { _length = value * 0.001f; } } - [XmlAttribute] public bool looping { get; set; } // enum : NO_LOOPING,LOOPING //Dengar.NOTE: the actual values are true and false, so it's a bool + // enum : NO_LOOPING,LOOPING + //Dengar.NOTE: the actual values are true and false, so it's a bool + [XmlAttribute] public bool looping { get; set; } + // tags within a single tag [XmlArray ("mainline"), XmlArrayItem ("key")] - public MainLineKey[] mainlineKeys { get; set; } // tags within a single tag - [XmlElement ("timeline")] public TimeLine[] timelines { get; set; } // tags + public MainLineKey[] mainlineKeys { get; set; } + // tags + [XmlElement ("timeline")] public TimeLine[] timelines { get; set; } } public class MainLineKey : ScmlElement { - public MainLineKey () {time=0;} + public MainLineKey () { + time = 0; + } private float _time; - [XmlAttribute] public float time { //Dengar.NOTE: In Spriter, Time is measured in milliseconds + [XmlAttribute] public float time { + //Dengar.NOTE: In Spriter, Time is measured in milliseconds get { return _time; } - set { _time = value * 0.001f; } //Dengar.NOTE: In Unity, it is measured in seconds instead, so we need to translate that - } - [XmlElement ("bone_ref")] public Ref[] boneRefs { get; set; } // tags - [XmlElement ("object_ref")] public Ref[] objectRefs { get; set; } // tags + //Dengar.NOTE: In Unity, it is measured in seconds instead, so we need to translate that + set { _time = value * 0.001f; } + } + // tags + [XmlElement ("bone_ref")] public Ref[] boneRefs { get; set; } + // tags + [XmlElement ("object_ref")] public Ref[] objectRefs { get; set; } } public class Ref : ScmlElement { - public Ref () {parent=-1;} - [XmlAttribute] public int parent { get; set; } // -1==no parent - uses ScmlObject spatialInfo as parentInfo - [XmlAttribute] public int timeline { get; set; } //Dengar.NOTE: Again, the above comment is an artifact from the pseudocode - [XmlAttribute] public int key { get; set; } //However, the fact that -1 equals "no parent" does come in useful later + public Ref () { + parent = -1; + } + // -1==no parent - uses ScmlObject spatialInfo as parentInfo + //Dengar.NOTE: Again, the above comment is an artifact from the pseudocode + //However, the fact that -1 equals "no parent" does come in useful later + [XmlAttribute] public int parent { get; set; } + [XmlAttribute] public int timeline { get; set; } + [XmlAttribute] public int key { get; set; } private float z; - [XmlAttribute] public float z_index { //Translate Sprite's Z-index in something we can use in Unity - get { return z; } //I choose to use position_z instead of order in layer because there are just potentially way too many - set { z = value * -0.001f; } //body parts to work with. This way the order in layer is reserved for entire Spriter entities + //Translate Sprite's Z-index in something we can use in Unity + //I choose to use position_z instead of order in layer because there are just potentially way too many + //body parts to work with. This way the order in layer is reserved for entire Spriter entities + [XmlAttribute] public float z_index { + get { return z; } + set { z = value * -0.001f; } } } - - public enum ObjectType {sprite, bone, box, point, sound, entity, variable} + + public enum ObjectType { + sprite, + bone, + box, + point, + sound, + entity, + variable, + } public class TimeLine : ScmlElement { [XmlAttribute] public string name { get; set; } - [XmlAttribute] public ObjectType objectType { get; set; } // enum : SPRITE,BONE,BOX,POINT,SOUND,ENTITY,VARIABLE //Dengar.NOTE (except not in all caps) - [XmlElement ("key")] public TimeLineKey[] keys { get; set; } // tags within tags + // enum : SPRITE,BONE,BOX,POINT,SOUND,ENTITY,VARIABLE + //Dengar.NOTE (except not in all caps) + [XmlAttribute] public ObjectType objectType { get; set; } + // tags within tags + [XmlElement ("key")] public TimeLineKey[] keys { get; set; } } - public enum CurveType {instant, linear, quadratic, cubic} + public enum CurveType { + instant, + linear, + quadratic, + cubic, + } public class TimeLineKey : ScmlElement { - public TimeLineKey () {time=0; spin=1;} + public TimeLineKey () { + time = 0; + spin = 1; + } private float _time; - [XmlAttribute] public float time { + [XmlAttribute] public float time { get { return _time; } - set { _time = value * 0.001f; } //See MainLineKey + //See MainLineKey + set { _time = value * 0.001f; } } - [XmlAttribute] public CurveType curve_type { get; set; } // enum : INSTANT,LINEAR,QUADRATIC,CUBIC //Dengar.NOTE (again, no caps) - [XmlAttribute] public float c1 { get; set; } - [XmlAttribute] public float c2 { get; set; } //I think these should be implemented some time in the future + // enum : INSTANT,LINEAR,QUADRATIC,CUBIC + //Dengar.NOTE (again, no caps) + [XmlAttribute] public CurveType curve_type { get; set; } + [XmlAttribute] public float c1 { get; set; } + //I think these should be implemented some time in the future + [XmlAttribute] public float c2 { get; set; } [XmlAttribute] public int spin { get; set; } [XmlElement ("bone", typeof(SpatialInfo)), XmlElement ("object", typeof(SpriteInfo))] public SpatialInfo info { get; set; } } - + public class SpatialInfo { - public SpatialInfo () {x=0; y=0; angle=0; scale_x=1; scale_y=1; trueScaleX=float.NaN; trueScaleY=float.NaN; a=1;} + public SpatialInfo () { + x = 0; + y = 0; + angle = 0; + scale_x = 1; + scale_y = 1; + trueScaleX = float.NaN; + trueScaleY = float.NaN; + a = 1; + } private float _x; - [XmlAttribute] public float x { + [XmlAttribute] public float x { get { return _x; } - set - { - if (ScmlImportOptions.options != null) - { - _x = value * (1f / ScmlImportOptions.options.pixelsPerUnit); // Convert Spriter space into Unity space using pixelsPerUnit - } - else - { - _x = value * 0.01f; - } - } - } + set { + if (ScmlImportOptions.options != null) { + // Convert Spriter space into Unity space using pixelsPerUnit + _x = value * (1f / ScmlImportOptions.options.pixelsPerUnit); + } + else { + _x = value * 0.01f; + } + } + } private float _y; - [XmlAttribute] public float y { + [XmlAttribute] public float y { get { return _y; } - set - { - if (ScmlImportOptions.options != null) - { - _y = value * (1f / ScmlImportOptions.options.pixelsPerUnit); // Convert Spriter space into Unity space using pixelsPerUnit - } - else - { - _y = value * 0.01f; - } - } - } - public Quaternion rotation { get; set; } //"angle" refers to a euler angle's Z value - [XmlAttribute] public float angle { //Unity doesn't actually use euler angles below the hood though - get { return rotation.eulerAngles.z; } //So we're translating the angle to a quaternion + set { + if (ScmlImportOptions.options != null) { + // Convert Spriter space into Unity space using pixelsPerUnit + _y = value * (1f / ScmlImportOptions.options.pixelsPerUnit); + } + else { + _y = value * 0.01f; + } + } + } + //"angle" refers to a euler angle's Z value + public Quaternion rotation { get; set; } + //Unity doesn't actually use euler angles below the hood though + //So we're translating the angle to a quaternion + [XmlAttribute] public float angle { + get { return rotation.eulerAngles.z; } set { rotation = Quaternion.Euler (0, 0, value); } } private float sx; - [XmlAttribute] public float scale_x { + [XmlAttribute] public float scale_x { get { return sx; } set { sx = value; - if (float.IsNaN(trueScaleX)) trueScaleX = value; + if (float.IsNaN (trueScaleX)) trueScaleX = value; } - } + } private float trueScaleX; private float sy; - [XmlAttribute] public float scale_y { + [XmlAttribute] public float scale_y { get { return sy; } set { sy = value; - if (float.IsNaN(trueScaleY)) trueScaleY = value; + if (float.IsNaN (trueScaleY)) trueScaleY = value; } - } + } private float trueScaleY; - [XmlAttribute] public float a { get; set; } //Alpha + //Alpha + [XmlAttribute] public float a { get; set; } public bool processed = false; //Some very funky maths to make sure all the scale values are off the bones and on the sprite instead - public bool Process (SpatialInfo parent) { + public bool Process (SpatialInfo parent) { if (GetType () == typeof(SpatialInfo)) { scale_x = (scale_x > 0) ? 1 : -1; scale_y = (scale_y > 0) ? 1 : -1; @@ -202,9 +267,12 @@ public bool Process (SpatialInfo parent) { return processed = true; } } - + public class SpriteInfo : SpatialInfo { - public SpriteInfo () : base () {pivot_x=0; pivot_y=1;} + public SpriteInfo () : base () { + pivot_x = 0; + pivot_y = 1; + } [XmlAttribute] public int folder { get; set; } [XmlAttribute] public int file { get; set; } [XmlAttribute] public float pivot_x { get; set; } diff --git a/Assets/Spriter2UnityDX/Runtime/EntityRenderer.cs b/Assets/Spriter2UnityDX/Runtime/EntityRenderer.cs index af183c5..0617724 100644 --- a/Assets/Spriter2UnityDX/Runtime/EntityRenderer.cs +++ b/Assets/Spriter2UnityDX/Runtime/EntityRenderer.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; namespace Spriter2UnityDX { - [DisallowMultipleComponent, ExecuteInEditMode, AddComponentMenu("")] + [DisallowMultipleComponent] + [ExecuteInEditMode] + [AddComponentMenu("")] public class EntityRenderer : MonoBehaviour { private SpriteRenderer[] renderers = new SpriteRenderer [0]; private SortingOrderUpdater[] updaters = new SortingOrderUpdater [0]; @@ -38,11 +40,11 @@ public string SortingLayerName { [SerializeField, HideInInspector] private int sortingOrder = 0; public int SortingOrder { get { return sortingOrder; } - set { + set { sortingOrder = value; if (applySpriterZOrder) - for (var i = 0; i < updaters.Length; i++) - updaters [i].SortingOrder = value; + foreach (var updater in updaters) + updater.SortingOrder = value; else DoForAll (x => x.sortingOrder = value); } } @@ -50,7 +52,7 @@ public int SortingOrder { [SerializeField, HideInInspector] private bool applySpriterZOrder = false; public bool ApplySpriterZOrder { get { return applySpriterZOrder; } - set { + set { applySpriterZOrder = value; if (applySpriterZOrder) { var list = new List (); @@ -65,9 +67,9 @@ public bool ApplySpriterZOrder { updaters = list.ToArray (); } else { - for (var i = 0; i < updaters.Length; i++) { - if (Application.isPlaying) Destroy (updaters [i]); - else DestroyImmediate (updaters [i]); + foreach (var updater in updaters) { + if (Application.isPlaying) Destroy (updater); + else DestroyImmediate (updater); } updaters = new SortingOrderUpdater [0]; DoForAll (x => x.sortingOrder = sortingOrder); @@ -86,7 +88,7 @@ private void OnEnable () { private void OnDisable () { DoForAll (x => x.enabled = false); } - + private void DoForAll (Action action) { for (var i = 0; i < renderers.Length; i++) action (renderers [i]); } @@ -95,7 +97,7 @@ public void RefreshRenders () { renderers = GetComponentsInChildren (true); updaters = GetComponentsInChildren (true); var length = updaters.Length; - for (var i = 0; i < length; i++) updaters [i].SpriteCount = length; + foreach (var updater in updaters) updater.SpriteCount = length; _first = null; } } diff --git a/Assets/Spriter2UnityDX/Runtime/SortingOrderUpdater.cs b/Assets/Spriter2UnityDX/Runtime/SortingOrderUpdater.cs index 5501d1a..2529666 100644 --- a/Assets/Spriter2UnityDX/Runtime/SortingOrderUpdater.cs +++ b/Assets/Spriter2UnityDX/Runtime/SortingOrderUpdater.cs @@ -3,7 +3,10 @@ using System.Collections; namespace Spriter2UnityDX { - [RequireComponent (typeof(SpriteRenderer)), ExecuteInEditMode, DisallowMultipleComponent, AddComponentMenu("")] + [RequireComponent (typeof(SpriteRenderer))] + [ExecuteInEditMode] + [DisallowMultipleComponent] + [AddComponentMenu("")] public class SortingOrderUpdater : MonoBehaviour { private Transform trans; private SpriteRenderer srenderer; @@ -12,7 +15,7 @@ public class SortingOrderUpdater : MonoBehaviour { private int sor; public int SortingOrder { get { return sor; } - set { + set { sor = value; UpdateSortingOrder (); } diff --git a/Assets/Spriter2UnityDX/Runtime/TextureController.cs b/Assets/Spriter2UnityDX/Runtime/TextureController.cs index 40ff2c0..dde621b 100644 --- a/Assets/Spriter2UnityDX/Runtime/TextureController.cs +++ b/Assets/Spriter2UnityDX/Runtime/TextureController.cs @@ -12,15 +12,20 @@ namespace Spriter2UnityDX { //textures, such as facial expressions. This component will override any changes //you make to the SpriteRenderer's textures, so if you want to change textures //at runtime, please make these changes to this component, rather than SpriteRenderer - [RequireComponent (typeof(SpriteRenderer)), DisallowMultipleComponent, ExecuteInEditMode, AddComponentMenu("")] + [RequireComponent (typeof(SpriteRenderer))] + [DisallowMultipleComponent] + [ExecuteInEditMode] + [AddComponentMenu("")] public class TextureController : MonoBehaviour { - public float DisplayedSprite = 0f; //Input from the AnimationClip - public Sprite[] Sprites; //If you want to swap textures at runtime, change the sprites in this array + //Input from the AnimationClip + public float DisplayedSprite = 0f; + //If you want to swap textures at runtime, change the sprites in this array + public Sprite[] Sprites; private SpriteRenderer srenderer; private Animator animator; private int lastDisplayed; - + private void Awake () { srenderer = GetComponent (); lastDisplayed = (int)DisplayedSprite; @@ -34,7 +39,7 @@ private void Start () { private void Update () { //Only change the sprite when the DisplayedSprite property has actually been changed //It will ignore changes that happen during transitions because it might get messy otherwise - if ((int)DisplayedSprite != lastDisplayed && !IsTransitioning () ) { + if ((int)DisplayedSprite != lastDisplayed && !IsTransitioning ()) { lastDisplayed = (int)DisplayedSprite; srenderer.sprite = Sprites [lastDisplayed]; } @@ -42,7 +47,7 @@ private void Update () { private bool IsTransitioning () { for (var i = 0; i < animator.layerCount; i++) - if (animator.IsInTransition(i)) return true; + if (animator.IsInTransition (i)) return true; return false; } }