Example #1
0
        public override IEnumerable <AssetItem> Import(UFile rawAssetPath, AssetImporterParameters importParameters)
        {
            var outputAssets = new List <AssetItem>();

            if (!SpriteStudioXmlImport.SanityCheck(rawAssetPath))
            {
                importParameters.Logger.Error("Invalid xml file or some required files are missing.");
                return(null);
            }

            //pre-process models
            var    nodes = new List <SpriteStudioNode>();
            string modelName;

            if (!SpriteStudioXmlImport.ParseModel(rawAssetPath, nodes, out modelName))
            {
                importParameters.Logger.Error("Failed to parse SpriteStudio model.");
                return(null);
            }

            if (importParameters.IsTypeSelectedForOutput <SpriteStudioModelAsset>())
            {
                var model = new SpriteStudioModelAsset {
                    Source = rawAssetPath
                };
                foreach (var node in nodes)
                {
                    model.NodeNames.Add(node.Name);
                }
                outputAssets.Add(new AssetItem(modelName, model));
            }

            if (importParameters.IsTypeSelectedForOutput <SpriteStudioAnimationAsset>())
            {
                //pre-process anims
                var anims = new List <SpriteStudioAnim>();
                if (!SpriteStudioXmlImport.ParseAnimations(rawAssetPath, anims))
                {
                    importParameters.Logger.Error("Failed to parse SpriteStudio animations.");
                    return(null);
                }

                foreach (var studioAnim in anims)
                {
                    var anim = new SpriteStudioAnimationAsset {
                        Source = rawAssetPath, AnimationName = studioAnim.Name
                    };
                    outputAssets.Add(new AssetItem(modelName + "_" + studioAnim.Name, anim));
                }
            }

            return(outputAssets);
        }
Example #2
0
        protected override void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
        {
            var asset             = (SpriteStudioModelAsset)assetItem.Asset;
            var gameSettingsAsset = context.GetGameSettingsAsset();
            var renderingSettings = gameSettingsAsset.GetOrCreate <RenderingSettings>(context.Platform);
            var colorSpace        = renderingSettings.ColorSpace;

            var cells  = new List <SpriteStudioCell>();
            var images = new List <UFile>();

            if (!SpriteStudioXmlImport.ParseCellMaps(asset.Source, images, cells))
            {
                throw new Exception("Failed to parse SpriteStudio cell textures.");
            }

            var texIndex = 0;

            asset.BuildTextures.Clear();
            foreach (var texture in images)
            {
                var textureAsset = new TextureAsset
                {
                    Id              = AssetId.Empty, // CAUTION: It is important to use an empty GUID here, as we don't want the command to be rebuilt (by default, a new asset is creating a new guid)
                    IsStreamable    = false,
                    IsCompressed    = false,
                    GenerateMipmaps = true,
                    Type            = new ColorTextureType
                    {
                        Alpha            = AlphaFormat.Auto,
                        PremultiplyAlpha = true,
                        UseSRgbSampling  = true,
                    }
                };

                var textureConvertParameters = new TextureConvertParameters(texture, textureAsset, context.Platform, context.GetGraphicsPlatform(assetItem.Package), renderingSettings.DefaultGraphicsProfile, gameSettingsAsset.GetOrCreate <TextureSettings>().TextureQuality, colorSpace);
                var textureConvertCommand    = new TextureAssetCompiler.TextureConvertCommand(targetUrlInStorage + texIndex, textureConvertParameters, assetItem.Package);
                result.BuildSteps.Add(textureConvertCommand);

                asset.BuildTextures.Add(targetUrlInStorage + texIndex);

                texIndex++;
            }

            var step = new AssetBuildStep(assetItem);

            step.Add(new SpriteStudioModelAssetCommand(targetUrlInStorage, asset, colorSpace, assetItem.Package));
            result.BuildSteps.Add(step);
        }
Example #3
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var    nodes = new List <SpriteStudioNode>();
                string modelName;

                if (!SpriteStudioXmlImport.ParseModel(Parameters.Source, nodes, out modelName))
                {
                    return(null);
                }

                var cells    = new List <SpriteStudioCell>();
                var textures = new List <UFile>();

                if (!SpriteStudioXmlImport.ParseCellMaps(Parameters.Source, textures, cells))
                {
                    return(null);
                }

                var anims = new List <SpriteStudioAnim>();

                if (!SpriteStudioXmlImport.ParseAnimations(Parameters.Source, anims))
                {
                    return(null);
                }

                var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);

                var sheet = new SpriteSheet();

                foreach (var cell in cells)
                {
                    var sprite = new Sprite(cell.Name, AttachedReferenceManager.CreateProxyObject <Texture>(AssetId.Empty, Parameters.BuildTextures[cell.TextureIndex]))
                    {
                        Region        = cell.Rectangle,
                        Center        = cell.Pivot,
                        IsTransparent = true
                    };
                    sheet.Sprites.Add(sprite);
                }

                var nodeMapping = nodes.Select((x, i) => new { Name = x.Name, Index = i }).ToDictionary(x => x.Name, x => x.Index);

                //fill up some basic data for our model using the first animation in the array
                var anim = anims[0];

                foreach (var data in anim.NodesData)
                {
                    int nodeIndex;
                    if (!nodeMapping.TryGetValue(data.Key, out nodeIndex))
                    {
                        continue;
                    }

                    var node = nodes[nodeIndex];

                    foreach (var pair in data.Value.Data)
                    {
                        var tag = pair.Key;
                        if (pair.Value.All(x => x["time"] != "0"))
                        {
                            continue;
                        }
                        var value = pair.Value.First()["value"]; //do we always have a frame 0? should be the case actually
                        switch (tag)
                        {
                        case "POSX":
                            node.BaseState.Position.X = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "POSY":
                            node.BaseState.Position.Y = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "ROTZ":
                            node.BaseState.RotationZ = MathUtil.DegreesToRadians(float.Parse(value, CultureInfo.InvariantCulture));
                            break;

                        case "PRIO":
                            node.BaseState.Priority = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "SCLX":
                            node.BaseState.Scale.X = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "SCLY":
                            node.BaseState.Scale.Y = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "ALPH":
                            node.BaseState.Transparency = float.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "HIDE":
                            node.BaseState.Hide = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "FLPH":
                            node.BaseState.HFlipped = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "FLPV":
                            node.BaseState.VFlipped = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "CELL":
                            node.BaseState.SpriteId = int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "COLV":
                            var color = new Color4(Color.FromBgra(int.Parse(value, CultureInfo.InvariantCulture)));
                            node.BaseState.BlendColor = colorSpace == ColorSpace.Linear ? color.ToLinear() : color;
                            break;

                        case "COLB":
                            node.BaseState.BlendType = (SpriteStudioBlending)int.Parse(value, CultureInfo.InvariantCulture);
                            break;

                        case "COLF":
                            node.BaseState.BlendFactor = float.Parse(value, CultureInfo.InvariantCulture);
                            break;
                        }
                    }
                }

                var spriteStudioSheet = new SpriteStudioSheet
                {
                    NodesInfo   = nodes,
                    SpriteSheet = sheet
                };

                assetManager.Save(Url, spriteStudioSheet);

                return(Task.FromResult(ResultStatus.Successful));
            }
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var    nodes = new List <SpriteStudioNode>();
                string modelName;

                if (!SpriteStudioXmlImport.ParseModel(Parameters.Source, nodes, out modelName))
                {
                    return(null);
                }

                var anims = new List <SpriteStudioAnim>();

                if (!SpriteStudioXmlImport.ParseAnimations(Parameters.Source, anims))
                {
                    return(null);
                }

                var assetManager = new ContentManager(MicrothreadLocalDatabases.ProviderService);

                var anim = anims.First(x => x.Name == Parameters.AnimationName);

                //Compile the animations
                var animation = new AnimationClip
                {
                    Duration   = TimeSpan.FromSeconds((1.0 / anim.Fps) * anim.FrameCount),
                    RepeatMode = Parameters.RepeatMode
                };

                var nodeMapping = nodes.Select((x, i) => new { Name = x.Name, Index = i }).ToDictionary(x => x.Name, x => x.Index);

                foreach (var pair in anim.NodesData)
                {
                    int nodeIndex;
                    if (!nodeMapping.TryGetValue(pair.Key, out nodeIndex))
                    {
                        continue;
                    }

                    var data = pair.Value;
                    if (data.Data.Count == 0)
                    {
                        continue;
                    }

                    var keyPrefix = $"[SpriteStudioComponent.Key].Nodes[{nodeIndex}]";

                    if (data.Data.ContainsKey("POSX"))
                    {
                        var posxCurve = new AnimationCurve <float>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.Position)}.{nameof(Vector2.X)}", posxCurve);
                        posxCurve.InterpolationType = data.Data["POSX"].Any(x => x["curve"] != "linear") ? AnimationCurveInterpolationType.Cubic : AnimationCurveInterpolationType.Linear;

                        foreach (var nodeData in data.Data["POSX"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = float.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            posxCurve.KeyFrames.Add(new KeyFrameData <float>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("POSY"))
                    {
                        var posyCurve = new AnimationCurve <float>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.Position)}.{nameof(Vector2.Y)}", posyCurve);
                        posyCurve.InterpolationType = data.Data["POSY"].Any(x => x["curve"] != "linear") ? AnimationCurveInterpolationType.Cubic : AnimationCurveInterpolationType.Linear;

                        foreach (var nodeData in data.Data["POSY"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = float.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            posyCurve.KeyFrames.Add(new KeyFrameData <float>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("ROTZ"))
                    {
                        var anglCurve = new AnimationCurve <float>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.RotationZ)}", anglCurve);
                        anglCurve.InterpolationType = data.Data["ROTZ"].Any(x => x["curve"] != "linear") ? AnimationCurveInterpolationType.Cubic : AnimationCurveInterpolationType.Linear;

                        foreach (var nodeData in data.Data["ROTZ"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = MathUtil.DegreesToRadians(float.Parse(nodeData["value"], CultureInfo.InvariantCulture));
                            anglCurve.KeyFrames.Add(new KeyFrameData <float>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("PRIO"))
                    {
                        var prioCurve = new AnimationCurve <int>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.Priority)}", prioCurve);
                        prioCurve.InterpolationType = AnimationCurveInterpolationType.Constant;

                        foreach (var nodeData in data.Data["PRIO"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = int.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            prioCurve.KeyFrames.Add(new KeyFrameData <int>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("SCLX"))
                    {
                        var scaxCurve = new AnimationCurve <float>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.Scale)}.{nameof(Vector2.X)}", scaxCurve);
                        scaxCurve.InterpolationType = data.Data["SCLX"].Any(x => x["curve"] != "linear") ? AnimationCurveInterpolationType.Cubic : AnimationCurveInterpolationType.Linear;

                        foreach (var nodeData in data.Data["SCLX"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = float.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            scaxCurve.KeyFrames.Add(new KeyFrameData <float>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("SCLY"))
                    {
                        var scayCurve = new AnimationCurve <float>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.Scale)}.{nameof(Vector2.Y)}", scayCurve);
                        scayCurve.InterpolationType = data.Data["SCLY"].Any(x => x["curve"] != "linear") ? AnimationCurveInterpolationType.Cubic : AnimationCurveInterpolationType.Linear;

                        foreach (var nodeData in data.Data["SCLY"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = float.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            scayCurve.KeyFrames.Add(new KeyFrameData <float>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("ALPH"))
                    {
                        var tranCurve = new AnimationCurve <float>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.Transparency)}", tranCurve);
                        tranCurve.InterpolationType = data.Data["ALPH"].Any(x => x["curve"] != "linear") ? AnimationCurveInterpolationType.Cubic : AnimationCurveInterpolationType.Linear;

                        foreach (var nodeData in data.Data["ALPH"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = float.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            tranCurve.KeyFrames.Add(new KeyFrameData <float>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("HIDE"))
                    {
                        var hideCurve = new AnimationCurve <int>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.Hide)}", hideCurve);
                        hideCurve.InterpolationType = AnimationCurveInterpolationType.Constant;

                        foreach (var nodeData in data.Data["HIDE"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = int.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            hideCurve.KeyFrames.Add(new KeyFrameData <int>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("FLPH"))
                    {
                        var flphCurve = new AnimationCurve <int>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.HFlipped)}", flphCurve);
                        flphCurve.InterpolationType = AnimationCurveInterpolationType.Constant;

                        foreach (var nodeData in data.Data["FLPH"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = int.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            flphCurve.KeyFrames.Add(new KeyFrameData <int>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("FLPV"))
                    {
                        var flpvCurve = new AnimationCurve <int>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.VFlipped)}", flpvCurve);
                        flpvCurve.InterpolationType = AnimationCurveInterpolationType.Constant;

                        foreach (var nodeData in data.Data["FLPV"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = int.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            flpvCurve.KeyFrames.Add(new KeyFrameData <int>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("CELL"))
                    {
                        var cellCurve = new AnimationCurve <int>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.SpriteId)}", cellCurve);
                        cellCurve.InterpolationType = AnimationCurveInterpolationType.Constant;

                        foreach (var nodeData in data.Data["CELL"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = int.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            cellCurve.KeyFrames.Add(new KeyFrameData <int>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("COLV"))
                    {
                        var colvCurve = new AnimationCurve <Vector4>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.BlendColor)}", colvCurve);
                        colvCurve.InterpolationType = AnimationCurveInterpolationType.Linear;

                        foreach (var nodeData in data.Data["COLV"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var color = new Color4(Color.FromBgra(int.Parse(nodeData["value"], CultureInfo.InvariantCulture)));
                            color = colorSpace == ColorSpace.Linear ? color.ToLinear() : color;
                            colvCurve.KeyFrames.Add(new KeyFrameData <Vector4>(time, color.ToVector4()));
                        }
                    }

                    if (data.Data.ContainsKey("COLB"))
                    {
                        var colbCurve = new AnimationCurve <int>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.BlendType)}", colbCurve);
                        colbCurve.InterpolationType = AnimationCurveInterpolationType.Constant;

                        foreach (var nodeData in data.Data["COLB"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = int.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            colbCurve.KeyFrames.Add(new KeyFrameData <int>(time, value));
                        }
                    }

                    if (data.Data.ContainsKey("COLF"))
                    {
                        var colfCurve = new AnimationCurve <float>();
                        animation.AddCurve($"{keyPrefix}.{nameof(SpriteStudioNodeState.BlendFactor)}", colfCurve);
                        colfCurve.InterpolationType = data.Data["COLF"].Any(x => x["curve"] != "linear") ? AnimationCurveInterpolationType.Cubic : AnimationCurveInterpolationType.Linear;

                        foreach (var nodeData in data.Data["COLF"])
                        {
                            var time  = CompressedTimeSpan.FromSeconds((1.0 / anim.Fps) * int.Parse(nodeData["time"], CultureInfo.InvariantCulture));
                            var value = float.Parse(nodeData["value"], CultureInfo.InvariantCulture);
                            colfCurve.KeyFrames.Add(new KeyFrameData <float>(time, value));
                        }
                    }
                }

                animation.Optimize();

                assetManager.Save(Url, animation);

                return(Task.FromResult(ResultStatus.Successful));
            }