Example #1
0
        private static Bitmap DownscaleTexture(Bitmap texture, string path, CookingRules rules)
        {
            int MaxSize        = GetMaxAtlasSize().Width;
            int scaleThreshold = Platform == TargetPlatform.Android ? 32 : 256;
            var ratio          = rules.TextureScaleFactor;

            if (texture.Width > MaxSize || texture.Height > MaxSize)
            {
                var max = (float)Math.Max(texture.Width, texture.Height);
                ratio *= MaxSize / max;
            }
            int newWidth  = texture.Width;
            int newHeight = texture.Height;

            if (texture.Width > scaleThreshold)
            {
                newWidth = Math.Min((texture.Width * ratio).Round(), MaxSize);
            }
            if (texture.Height > scaleThreshold)
            {
                newHeight = Math.Min((texture.Height * ratio).Round(), MaxSize);
            }
            Console.WriteLine("{0} downscaled to {1}x{2}", path, newWidth, newHeight);
            return(texture.Rescale(newWidth, newHeight));
        }
Example #2
0
 public static void AfterAssetUpdated(Lime.AssetBundle bundle, CookingRules cookingRules, string path)
 {
     foreach (var i in CurrentPlugin.AfterAssetUpdated)
     {
         i(bundle, cookingRules, path);
     }
 }
Example #3
0
 private static bool ShouldDownscale(Bitmap texture, CookingRules rules)
 {
     if (rules.TextureScaleFactor != 1.0f)
     {
         int scaleThreshold = Platform == TargetPlatform.Android ? 32 : 256;
         if (texture.Width > scaleThreshold || texture.Height > scaleThreshold)
         {
             return(true);
         }
     }
     return(false);
 }
Example #4
0
 public void SyncUpdated(string fileExtension, string bundleAssetExtension, Converter converter, Func <string, string, bool> extraOutOfDateChecker = null)
 {
     foreach (var fileInfo in InputBundle.EnumerateFileInfos(null, fileExtension))
     {
         UserInterface.Instance.IncreaseProgressBar();
         var srcPath    = fileInfo.Path;
         var dstPath    = Path.ChangeExtension(srcPath, bundleAssetExtension);
         var bundled    = OutputBundle.FileExists(dstPath);
         var srcRules   = CookingRulesMap[srcPath];
         var needUpdate = !bundled || fileInfo.LastWriteTime != OutputBundle.GetFileLastWriteTime(dstPath);
         needUpdate = needUpdate || !srcRules.SHA1.SequenceEqual(OutputBundle.GetCookingRulesSHA1(dstPath));
         needUpdate = needUpdate || (extraOutOfDateChecker?.Invoke(srcPath, dstPath) ?? false);
         if (needUpdate)
         {
             if (converter != null)
             {
                 try {
                     if (converter(srcPath, dstPath))
                     {
                         Console.WriteLine((bundled ? "* " : "+ ") + dstPath);
                         CookingRules rules = null;
                         if (!string.IsNullOrEmpty(dstPath))
                         {
                             CookingRulesMap.TryGetValue(dstPath, out rules);
                         }
                         PluginLoader.AfterAssetUpdated(OutputBundle, rules, dstPath);
                     }
                 } catch (System.Exception e) {
                     Console.WriteLine(
                         "An exception was caught while processing '{0}': {1}\n", srcPath, e.Message);
                     throw;
                 }
             }
             else
             {
                 Console.WriteLine((bundled ? "* " : "+ ") + dstPath);
                 using (var stream = InputBundle.OpenFile(srcPath)) {
                     OutputBundle.ImportFile(dstPath, stream, 0, fileExtension,
                                             InputBundle.GetFileLastWriteTime(srcPath), AssetAttributes.None,
                                             CookingRulesMap[srcPath].SHA1);
                 }
             }
         }
     }
 }
Example #5
0
        public CookingRules InheritClone()
        {
            var r = new CookingRules(false);

            r.Parent = this;
            foreach (var kv in TargetRules)
            {
                r.TargetRules.Add(kv.Key, kv.Value.InheritClone());
            }
            if (EffectiveRules != null)
            {
                r.CommonRules    = EffectiveRules.InheritClone();
                r.EffectiveRules = EffectiveRules.InheritClone();
            }
            else
            {
                r.CommonRules = CommonRules.InheritClone();
            }
            return(r);
        }
Example #6
0
 static void SyncUpdated(string fileExtension, string bundleAssetExtension, AssetBundle bundle, Converter converter)
 {
     foreach (var srcFileInfo in The.Workspace.AssetFiles.Enumerate(fileExtension))
     {
         var srcPath    = srcFileInfo.Path;
         var dstPath    = Path.ChangeExtension(srcPath, bundleAssetExtension);
         var bundled    = bundle.FileExists(dstPath);
         var srcRules   = cookingRulesMap[srcPath];
         var needUpdate = !bundled || srcFileInfo.LastWriteTime > bundle.GetFileLastWriteTime(dstPath);
         needUpdate = needUpdate || !srcRules.SHA1.SequenceEqual(bundle.GetCookingRulesSHA1(dstPath));
         if (needUpdate)
         {
             if (converter != null)
             {
                 try {
                     if (converter(srcPath, dstPath))
                     {
                         Console.WriteLine((bundled ? "* " : "+ ") + dstPath);
                         CookingRules rules = null;
                         if (!string.IsNullOrEmpty(dstPath))
                         {
                             cookingRulesMap.TryGetValue(dstPath, out rules);
                         }
                         PluginLoader.AfterAssetUpdated(bundle, rules, dstPath);
                     }
                 } catch (System.Exception e) {
                     Console.WriteLine(
                         "An exception was caught while processing '{0}': {1}\n", srcPath, e.Message);
                     throw;
                 }
             }
             else
             {
                 Console.WriteLine((bundled ? "* " : "+ ") + dstPath);
                 using (Stream stream = new FileStream(srcPath, FileMode.Open, FileAccess.Read)) {
                     bundle.ImportFile(dstPath, stream, 0, fileExtension, AssetAttributes.None, cookingRulesMap[srcPath].SHA1);
                 }
             }
         }
     }
 }
Example #7
0
        private static CookingRules ParseCookingRules(CookingRules basicRules, string path, Target target)
        {
            var rules        = basicRules.InheritClone();
            var currentRules = rules.CommonRules;

            try {
                rules.CommonRules.LastChangeTime = File.GetLastWriteTime(path);
                using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    TextReader r = new StreamReader(s);
                    string     line;
                    while ((line = r.ReadLine()) != null)
                    {
                        line = line.Trim();
                        if (line == "")
                        {
                            continue;
                        }
                        var words = line.Split(' ');
                        if (words.Length < 2)
                        {
                            throw new Lime.Exception("Invalid rule format");
                        }
                        // target-specific cooking rules
                        if (words[0].EndsWith(")"))
                        {
                            int cut = words[0].IndexOf('(');
                            if (cut >= 0)
                            {
                                string targetName = words[0].Substring(cut + 1, words[0].Length - cut - 2);
                                words[0]     = words[0].Substring(0, cut);
                                currentRules = null;
                                Target currentTarget = null;
                                foreach (var t in The.Workspace.Targets)
                                {
                                    if (targetName == t.Name)
                                    {
                                        currentTarget = t;
                                    }
                                }
                                if (currentTarget == null)
                                {
                                    throw new Lime.Exception($"Invalid target: {targetName}");
                                }
                                currentRules = rules.TargetRules[currentTarget];
                                {
                                    var targetPlatformAttribute = (TargetPlatformsAttribute)typeof(ICookingRules)
                                                                  .GetProperty(words[0]).GetCustomAttribute(typeof(TargetPlatformsAttribute));
                                    if (targetPlatformAttribute != null && !targetPlatformAttribute.TargetPlatforms.Contains(currentTarget.Platform))
                                    {
                                        throw new Lime.Exception($"Invalid platform {currentTarget.Platform} for cooking rule {words[0]}");
                                    }
                                }
                            }
                        }
                        else
                        {
                            currentRules = rules.CommonRules;
                        }
                        ParseRule(currentRules, words, path);
                    }
                }
            } catch (Lime.Exception e) {
                if (!Path.IsPathRooted(path))
                {
                    path = Path.Combine(Directory.GetCurrentDirectory(), path);
                }
                throw new Lime.Exception("Syntax error in {0}: {1}", path, e.Message);
            }
            rules.DeduceEffectiveRules(target);
            return(rules);
        }
Example #8
0
        // pass target as null to build cooking rules disregarding targets
        public static Dictionary <string, CookingRules> Build(IFileEnumerator fileEnumerator, Target target)
        {
            var shouldRescanEnumerator = false;
            var pathStack  = new Stack <string>();
            var rulesStack = new Stack <CookingRules>();
            var map        = new Dictionary <string, CookingRules>();

            pathStack.Push("");
            var rootRules = new CookingRules();

            rootRules.DeduceEffectiveRules(target);
            rulesStack.Push(rootRules);
            using (new DirectoryChanger(fileEnumerator.Directory)) {
                foreach (var fileInfo in fileEnumerator.Enumerate())
                {
                    var path = fileInfo.Path;
                    while (!path.StartsWith(pathStack.Peek()))
                    {
                        rulesStack.Pop();
                        pathStack.Pop();
                    }
                    if (Path.GetFileName(path) == CookingRulesFilename)
                    {
                        var dirName = Lime.AssetPath.GetDirectoryName(path);
                        pathStack.Push(dirName == string.Empty ? "" : dirName + "/");
                        var rules = ParseCookingRules(rulesStack.Peek(), path, target);
                        rules.SourceFilename = AssetPath.Combine(fileEnumerator.Directory, path);
                        rulesStack.Push(rules);
                        // Add 'ignore' cooking rules for this #CookingRules.txt itself
                        var ignoreRules = rules.InheritClone();
                        ignoreRules.Ignore = true;
                        map[path]          = ignoreRules;
                        var directoryName = pathStack.Peek();
                        if (!string.IsNullOrEmpty(directoryName))
                        {
                            directoryName = directoryName.Remove(directoryName.Length - 1);
                            // it is possible for map to not contain this directoryName since not every IFileEnumerator enumerates directories
                            if (map.ContainsKey(directoryName))
                            {
                                map[directoryName] = rules;
                            }
                        }
                    }
                    else
                    {
                        if (Path.GetExtension(path) == ".txt")
                        {
                            var filename = path.Remove(path.Length - 4);
                            if (File.Exists(filename) || Directory.Exists(filename))
                            {
                                continue;
                            }
                        }
                        var rulesFile = path + ".txt";
                        var rules     = rulesStack.Peek();
                        if (File.Exists(rulesFile))
                        {
                            rules = ParseCookingRules(rulesStack.Peek(), rulesFile, target);
                            rules.SourceFilename = AssetPath.Combine(fileEnumerator.Directory, rulesFile);
                            // Add 'ignore' cooking rules for this cooking rules text file
                            var ignoreRules = rules.InheritClone();
                            ignoreRules.Ignore = true;
                            map[rulesFile]     = ignoreRules;
                        }
                        if (rules.CommonRules.LastChangeTime > fileInfo.LastWriteTime)
                        {
                            try {
                                File.SetLastWriteTime(path, rules.CommonRules.LastChangeTime);
                            } catch (UnauthorizedAccessException) {
                                // In case this is a folder
                            }
                            shouldRescanEnumerator = true;
                        }
                        map[path] = rules;
                    }
                }
            }
            if (shouldRescanEnumerator)
            {
                fileEnumerator.Rescan();
            }
            return(map);
        }
Example #9
0
        public static void DownscaleTextureInfo(TargetPlatform platform, BitmapInfo textureInfo, string path, CookingRules rules)
        {
            int newHeight;
            int newWidth;

            DownscaleTextureHelper(platform, textureInfo.Width, textureInfo.Height, path, rules, out newWidth, out newHeight);
            textureInfo.Height = newHeight;
            textureInfo.Width  = newWidth;
        }
Example #10
0
 public static bool ShouldDownscale(TargetPlatform platform, BitmapInfo textureInfo, CookingRules rules)
 {
     return(ShouldDownscaleHelper(platform, textureInfo.Width, textureInfo.Height, rules));
 }
Example #11
0
 private static bool ShouldDownscaleHelper(TargetPlatform platform, int width, int height, CookingRules rules)
 {
     if (rules.TextureScaleFactor != 1.0f)
     {
         int scaleThreshold = platform == TargetPlatform.Android ? 32 : 256;
         if (width > scaleThreshold || height > scaleThreshold)
         {
             return(true);
         }
     }
     return(false);
 }
Example #12
0
        private static void DownscaleTextureHelper(TargetPlatform platform, int width, int height, string path, CookingRules rules, out int newWidth, out int newHeight)
        {
            int MaxSize        = GetMaxAtlasSize().Width;
            int scaleThreshold = platform == TargetPlatform.Android ? 32 : 256;
            var ratio          = rules.TextureScaleFactor;

            if (width > MaxSize || height > MaxSize)
            {
                var max = (float)Math.Max(width, height);
                ratio *= MaxSize / max;
            }
            newWidth  = width;
            newHeight = height;
            if (width > scaleThreshold)
            {
                newWidth = Math.Min((width * ratio).Round(), MaxSize);
            }
            if (height > scaleThreshold)
            {
                newHeight = Math.Min((height * ratio).Round(), MaxSize);
            }
            Console.WriteLine("{0} downscaled to {1}x{2}", path, newWidth, newHeight);
        }
Example #13
0
        public static Bitmap DownscaleTexture(TargetPlatform platform, Bitmap texture, string path, CookingRules rules)
        {
            int newHeight;
            int newWidth;

            DownscaleTextureHelper(platform, texture.Width, texture.Height, path, rules, out newWidth, out newHeight);
            return(texture.Rescale(newWidth, newHeight));
        }