public static void BuildSprites(GameObject root, PSDLayerGroupInfo group, PsdExportSettings settings, PsdFileInfo fileInfo, SpriteAlignment createAlign) { BuildPsd(root, group, settings, fileInfo, createAlign, new SpriteConstructor()); }
public static void Export(PsdExportSettings settings, PsdFileInfo fileInfo, bool exportExisting = true) { List<int> layerIndices = GetExportLayers(settings, fileInfo); // If not going to export existing, filter out layers with existing files if (exportExisting == false) { layerIndices = layerIndices.Where(delegate(int layerIndex) { string filePath = GetLayerFilename(settings, layerIndex); // If file exists, don't export return !File.Exists(filePath); }).ToList(); } int exportCount = 0; foreach (int layerIndex in layerIndices) { string infoString = string.Format("Importing {0} / {1} Layers", exportCount, layerIndices.Count); string fileString = string.Format("Importing PSD Layers: {0}", settings.Filename); float progress = exportCount/(float) layerIndices.Count; EditorUtility.DisplayProgressBar(fileString, infoString, progress); CreateSprite(settings, layerIndex); exportCount++; } EditorUtility.ClearProgressBar(); settings.SaveMetaData(); settings.SaveLayerMetaData(); }
public static void Export(PsdExportSettings settings, PsdFileInfo fileInfo, bool exportExisting = true) { List <int> layerIndices = GetExportLayers(settings, fileInfo); // If not going to export existing, filter out layers with existing files if (exportExisting == false) { layerIndices = layerIndices.Where(delegate(int layerIndex) { string filePath = GetLayerFilename(settings, layerIndex); // If file exists, don't export return(!File.Exists(filePath)); }).ToList(); } int exportCount = 0; foreach (int layerIndex in layerIndices) { string infoString = string.Format("Importing {0} / {1} Layers", exportCount, layerIndices.Count); string fileString = string.Format("Importing PSD Layers: {0}", settings.Filename); float progress = exportCount / (float)layerIndices.Count; EditorUtility.DisplayProgressBar(fileString, infoString, progress); CreateSprite(settings, layerIndex); exportCount++; } EditorUtility.ClearProgressBar(); settings.SaveMetaData(); settings.SaveLayerMetaData(); }
public static Sprite CreateSprite(PsdExportSettings settings, int layerIndex) { var layer = settings.Psd.Layers[layerIndex]; Texture2D tex = CreateTexture(layer); if (tex == null) return null; Sprite sprite = SaveAsset(settings, tex, layerIndex); Object.DestroyImmediate(tex); return sprite; }
public static GameObject BuildPsdRoot(GameObject root, PsdExportSettings settings, PsdFileInfo fileInfo, SpriteAlignment align, IPsdConstructor constructor) { GameObject spriteObject = constructor.CreateGameObject(settings.Filename, root); PSDLayerGroupInfo rootGroup = new PSDLayerGroupInfo(settings.Filename, settings.Psd.Layers.Count - 1, true, true); rootGroup.start = 0; BuildPsd(spriteObject, rootGroup, settings, fileInfo, align, constructor); return(spriteObject); }
public static string GetLayerFilename(PsdExportSettings settings, int layerIndex) { // Strip out invalid characters from the file name string layerName = settings.Psd.Layers[layerIndex].Name; // foreach (char invalidChar in Path.GetInvalidFileNameChars()) // { // layerName = layerName.Replace(invalidChar, '-'); // } layerName = settings.GetLayerPath(layerName); return(layerName); }
public static Sprite CreateSprite(PsdExportSettings settings, int layerIndex) { var layer = settings.Psd.Layers[layerIndex]; Texture2D tex = CreateTexture(layer); if (tex == null) { return(null); } Sprite sprite = SaveAsset(settings, tex, layerIndex); Object.DestroyImmediate(tex); return(sprite); }
private bool LoadImage() { settings = new PsdExportSettings(image); showImportSettings = !settings.HasMetaData; bool valid = (settings.Psd != null); if (valid) { // Parse the layer info fileInfo = new PsdFileInfo(settings.Psd); settings.LoadLayers(fileInfo); } return(valid); }
private static void ExecuteAutoImport() { // This function only fires once, unhook from update function immediately EditorApplication.update -= ExecuteAutoImport; for (int i = 0; i < reimports.Count; i++) { var target = reimports[i]; var exportSettings = new PsdExportSettings(target); if (exportSettings.AutoReImport) { PsdFileInfo psdInfo = new PsdFileInfo(exportSettings.Psd); exportSettings.LoadLayers(psdInfo); PSDExporter.Export(exportSettings, psdInfo); } } reimports.Clear(); }
public static List<int> GetExportLayers(PsdExportSettings settings, PsdFileInfo fileInfo) { List<int> exportLayers = new List<int>(); foreach (var keypair in settings.layerSettings) { PsdExportSettings.LayerSetting layerSetting = keypair.Value; // Don't export if not set to export if (!layerSetting.doExport) continue; // Don't export if group is off var groupInfo = fileInfo.GetGroupByLayerIndex(layerSetting.layerIndex); if (groupInfo != null && !groupInfo.visible) continue; exportLayers.Add(layerSetting.layerIndex); } return exportLayers; }
private static List <PanelNode> GetLayer(Texture2D psdFile, string filter = "") { List <PanelNode> PanelNodeList = new List <PanelNode> (); PsdExportSettings settings = new PsdExportSettings(psdFile); PsdFileInfo fileInfo = new PsdFileInfo(settings.Psd); bool valid = (settings.Psd != null); if (valid) { settings.LoadLayers(fileInfo); PsdFile psd = settings.Psd; int layerIndexMin = 0; int layerIndexMax = 0; for (int i = 0; i < psd.Layers.Count; i++) { PSDLayerGroupInfo groupInfo = fileInfo.GetGroupByLayerIndex(i); //Debug.Log (groupInfo.start + "-" + groupInfo.end + ":" + groupInfo.name); if (groupInfo != null && !PanelNodeList.Exists(a => a.Name.Equals(groupInfo.name))) { PanelNode panelNode = new PanelNode(groupInfo.name); panelNode.visible = groupInfo.visible; panelNode.idxStart = groupInfo.start; panelNode.idxEnd = groupInfo.end; panelNode.isGroup = true; PanelNodeList.Add(panelNode); } } for (int i = 0; i < fileInfo.LayerIndices.Length; i++) { int layerIndex = fileInfo.LayerIndices [i]; Layer layer = psd.Layers [layerIndex]; PanelNode panelNode = new PanelNode(layer.Name); panelNode.visible = layer.Visible; panelNode.Index = layerIndex; panelNode.isGroup = false; panelNode.layer = layer; PanelNodeList.Add(panelNode); } ArrangementNode(PanelNodeList); } return(PanelNodeList); }
public static List <int> GetExportLayers(PsdExportSettings settings, PsdFileInfo fileInfo) { List <int> exportLayers = new List <int>(); foreach (var keypair in settings.layerSettings) { PsdExportSettings.LayerSetting layerSetting = keypair.Value; // Don't export if not set to export if (!layerSetting.doExport) { continue; } // Don't export if group is off var groupInfo = fileInfo.GetGroupByLayerIndex(layerSetting.layerIndex); if (groupInfo != null && !groupInfo.visible) { continue; } exportLayers.Add(layerSetting.layerIndex); } return(exportLayers); }
public static void BuildPsd(GameObject root, PSDLayerGroupInfo group, PsdExportSettings settings, PsdFileInfo fileInfo, SpriteAlignment align, IPsdConstructor constructor) { // Run the export on non exported layers PSDExporter.Export(settings, fileInfo, false); // Find all the layers being exported var exportLayers = PSDExporter.GetExportLayers(settings, fileInfo); // Stores the root object for each encountered group Dictionary <PSDLayerGroupInfo, GameObject> groupHeaders = new Dictionary <PSDLayerGroupInfo, GameObject>(); // Store the last parent, for traversal GameObject lastParent = root; GameObject rootBase = null; int groupVisibleMask = 1; int groupDepth = 0; // Loop through all the layers of the PSD file // backwards so they appear in the expected order // Going through all the layers, and not just the exported layers // so that the groups can be setup for (int i = group.end; i >= group.start; i--) { // Skip if layer is hidden if (fileInfo.LayerVisibility[i] == false) { continue; } var groupInfo = fileInfo.GetGroupByLayerIndex(i); bool inGroup = groupInfo != null; // Skip if layer belongs to a hidden group if (inGroup && groupInfo.visible == false) { continue; } // When inside a group... if (inGroup) { // Inverted because starting backwards bool startGroup = groupInfo.end == i; bool closeGroup = groupInfo.start == i; // Go up or down group depths if (startGroup) { groupDepth++; groupVisibleMask |= ((groupInfo.visible ? 1 : 0) << groupDepth); } if (closeGroup) { // Reset group visible flag when closing group groupVisibleMask &= ~(1 << groupDepth); groupDepth--; } // First, check if parents of this group is visible in the first place bool parentVisible = true; for (int parentMask = groupDepth - 1; parentMask > 0; parentMask--) { bool isVisible = (groupVisibleMask & (1 << parentMask)) > 0; parentVisible &= isVisible; } // Parents not visible, continue to next layer if (!parentVisible) { continue; } // Finally, check if layer being processed is start/end of group if (startGroup || closeGroup) { // If start or end of the group, call HandleGroupObject // which creates the group layer object and assignment of lastParent HandleGroupObject(groupInfo, groupHeaders, startGroup, constructor, ref lastParent); // A bunch of book keeping needs to be done at the start of a group if (startGroup) { // If this is the start of the group being constructed // store as the rootBase if (i == group.end) { rootBase = lastParent; } } // Start or end group doesn't have visible sprite object, skip to next layer continue; } } // End processing of group start/end // If got to here, processing a visual layer // Skip if the export layers list doesn't contain this index if (exportLayers.Contains(i) == false) { continue; } // If got here and root base hasn't been set, that's a problem if (rootBase == null) { throw new Exception("Trying to create image layer before root base has been set"); } // Get layer info Layer layer = settings.Psd.Layers[i]; // Create the game object for the sprite string layerName = Utility.PinYinHelper.Convert(layer.Name); GameObject spriteObject = constructor.CreateGameObject(layerName, lastParent); // Reparent created object to last parent if (lastParent != null) { spriteObject.transform.SetParent(lastParent.transform, false); } Vector2 spritePivot = GetPivot(SpriteAlignment.Center); if (layer.IsText) { var layerText = layer.LayerText; Text text = spriteObject.AddComponent <Text>(); text.horizontalOverflow = HorizontalWrapMode.Overflow; text.verticalOverflow = VerticalWrapMode.Overflow; text.fontSize = (int)layerText.FontSize; text.rectTransform.SetAsFirstSibling(); text.rectTransform.sizeDelta = new Vector2(layer.Rect.width, layer.Rect.height); text.text = layerText.Text.Replace("\r\n", "\n").Replace("\r", "\n"); FontStyle fontStyle = FontStyle.Normal; if (layerText.FauxBold) { fontStyle |= FontStyle.Bold; } if (layerText.FauxItalic) { fontStyle |= FontStyle.Italic; } float a = ((layerText.FillColor | 0xFF000000U) >> 24) / 255f; float r = ((layerText.FillColor | 0xFF0000U) >> 16) / 255f; float g = ((layerText.FillColor | 0xFF00U) >> 8) / 255f; float b = (layerText.FillColor | 0xFFU) / 255f; text.color = new Color(r, g, b, a); } else { // Retrieve sprite from asset database string sprPath = PSDExporter.GetLayerFilename(settings, i); Sprite sprite = AssetDatabase.LoadAssetAtPath <Sprite>(sprPath); // Get the pivot settings for the sprite TextureImporter sprImporter = (TextureImporter)AssetImporter.GetAtPath(sprPath); TextureImporterSettings sprSettings = new TextureImporterSettings(); sprImporter.ReadTextureSettings(sprSettings); sprImporter = null; // Add components to the sprite object for the visuals constructor.AddComponents(i, spriteObject, sprite, sprSettings); // Reposition the sprite object according to PSD position spritePivot = GetPivot(sprSettings); } Vector3 layerPos = constructor.GetLayerPosition(layer.Rect, spritePivot, settings.PixelsToUnitSize); // reverse y axis layerPos.y = fileInfo.height - layerPos.y; // Scaling factor, if sprites were scaled down float posScale = 1f; switch (settings.ScaleBy) { case 1: posScale = 0.5f; break; case 2: posScale = 0.25f; break; } layerPos *= posScale; // Sprite position is based on root object position initially Transform spriteT = spriteObject.transform; spriteT.position = layerPos; } // End layer loop } // End BuildPsd()
public static string GetLayerFilename(PsdExportSettings settings, int layerIndex) { // Strip out invalid characters from the file name string layerName = settings.Psd.Layers[layerIndex].Name; foreach (char invalidChar in Path.GetInvalidFileNameChars()) { layerName = layerName.Replace(invalidChar, '-'); } layerName = settings.GetLayerPath(layerName); return layerName; }
public static int GetExportCount(PsdExportSettings settings, PsdFileInfo fileInfo) { var exportLayers = GetExportLayers(settings, fileInfo); return(exportLayers.Count); }
private static Sprite SaveAsset(PsdExportSettings settings, Texture2D tex, int layer) { string assetPath = GetLayerFilename(settings, layer); // Setup scaling variables float pixelsToUnits = settings.PixelsToUnitSize; // Apply global scaling, if any if (settings.ScaleBy > 0) { tex = ScaleTextureByMipmap(tex, settings.ScaleBy); } PsdExportSettings.LayerSetting layerSetting = settings.layerSettings[layer]; // Then scale by layer scale if (layerSetting.scaleBy != ScaleDown.Default) { // By default, scale by half int scaleLevel = 1; pixelsToUnits = Mathf.RoundToInt(settings.PixelsToUnitSize / 2f); // Setting is actually scale by quarter if (layerSetting.scaleBy == ScaleDown.Quarter) { scaleLevel = 2; pixelsToUnits = Mathf.RoundToInt(settings.PixelsToUnitSize / 4f); } // Apply scaling tex = ScaleTextureByMipmap(tex, scaleLevel); } byte[] buf = tex.EncodeToPNG(); File.WriteAllBytes(assetPath, buf); AssetDatabase.Refresh(); // Load the texture so we can change the type var textureObj = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Texture2D)); // Get the texture importer for the asset TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(assetPath); // Read out the texture import settings so import pivot point can be changed TextureImporterSettings importSetting = new TextureImporterSettings(); textureImporter.ReadTextureSettings(importSetting); // Set the pivot import setting importSetting.spriteAlignment = (int)settings.Pivot; // But if layer setting has a different pivot, set as new pivot if (settings.Pivot != layerSetting.pivot) { importSetting.spriteAlignment = (int)layerSetting.pivot; } // Pivot settings are the same but custom, set the vector //else if (settings.Pivot == SpriteAlignment.Custom) // importSetting.spritePivot = settings.PivotVector; importSetting.mipmapEnabled = false; importSetting.spritePixelsPerUnit = pixelsToUnits; // Set the rest of the texture settings textureImporter.textureType = TextureImporterType.Sprite; textureImporter.spriteImportMode = SpriteImportMode.Single; textureImporter.spritePackingTag = settings.PackingTag; // Write in the texture import settings textureImporter.SetTextureSettings(importSetting); EditorUtility.SetDirty(textureObj); AssetDatabase.WriteImportSettingsIfDirty(assetPath); AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); return((Sprite)AssetDatabase.LoadAssetAtPath(assetPath, typeof(Sprite))); }
private static Sprite SaveAsset(PsdExportSettings settings, Texture2D tex, int layer) { string assetPath = GetLayerFilename(settings, layer); // Setup scaling variables float pixelsToUnits = settings.PixelsToUnitSize; // Apply global scaling, if any if (settings.ScaleBy > 0) { tex = ScaleTextureByMipmap(tex, settings.ScaleBy); } PsdExportSettings.LayerSetting layerSetting = settings.layerSettings[layer]; // Then scale by layer scale if (layerSetting.scaleBy != ScaleDown.Default) { // By default, scale by half int scaleLevel = 1; pixelsToUnits = Mathf.RoundToInt(settings.PixelsToUnitSize/2f); // Setting is actually scale by quarter if (layerSetting.scaleBy == ScaleDown.Quarter) { scaleLevel = 2; pixelsToUnits = Mathf.RoundToInt(settings.PixelsToUnitSize/4f); } // Apply scaling tex = ScaleTextureByMipmap(tex, scaleLevel); } byte[] buf = tex.EncodeToPNG(); File.WriteAllBytes(assetPath, buf); AssetDatabase.Refresh(); // Load the texture so we can change the type var textureObj = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Texture2D)); // Get the texture importer for the asset TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(assetPath); // Read out the texture import settings so import pivot point can be changed TextureImporterSettings importSetting = new TextureImporterSettings(); textureImporter.ReadTextureSettings(importSetting); // Set the pivot import setting importSetting.spriteAlignment = (int) settings.Pivot; // But if layer setting has a different pivot, set as new pivot if (settings.Pivot != layerSetting.pivot) importSetting.spriteAlignment = (int)layerSetting.pivot; // Pivot settings are the same but custom, set the vector //else if (settings.Pivot == SpriteAlignment.Custom) // importSetting.spritePivot = settings.PivotVector; importSetting.spritePixelsPerUnit = pixelsToUnits; // Set the rest of the texture settings textureImporter.textureType = TextureImporterType.Sprite; textureImporter.spriteImportMode = SpriteImportMode.Single; textureImporter.spritePackingTag = settings.PackingTag; // Write in the texture import settings textureImporter.SetTextureSettings(importSetting); EditorUtility.SetDirty(textureObj); AssetDatabase.WriteImportSettingsIfDirty(assetPath); AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); return (Sprite)AssetDatabase.LoadAssetAtPath(assetPath, typeof(Sprite)); }
public static void BuildPsd(GameObject root, PSDLayerGroupInfo group, PsdExportSettings settings, PsdFileInfo fileInfo, SpriteAlignment align, IPsdConstructor constructor) { // Run the export on non exported layers PSDExporter.Export(settings, fileInfo, false); // Find all the layers being exported var exportLayers = PSDExporter.GetExportLayers(settings, fileInfo); // Stores the root object for each encountered group Dictionary <PSDLayerGroupInfo, GameObject> groupHeaders = new Dictionary <PSDLayerGroupInfo, GameObject>(); // Store the last parent, for traversal GameObject lastParent = root; GameObject rootBase = null; Transform rootBaseT = null; int groupVisibleMask = 1; int groupDepth = 0; // Loop through all the layers of the PSD file // backwards so they appear in the expected order // Going through all the layers, and not just the exported layers // so that the groups can be setup for (int i = group.end; i >= group.start; i--) { // Skip if layer is hidden if (fileInfo.LayerVisibility[i] == false) { continue; } var groupInfo = fileInfo.GetGroupByLayerIndex(i); bool inGroup = groupInfo != null; // Skip if layer belongs to a hidden group if (inGroup && groupInfo.visible == false) { continue; } // When inside a group... if (inGroup) { // Inverted because starting backwards bool startGroup = groupInfo.end == i; bool closeGroup = groupInfo.start == i; // Go up or down group depths if (startGroup) { groupDepth++; groupVisibleMask |= ((groupInfo.visible ? 1 : 0) << groupDepth); } if (closeGroup) { // Reset group visible flag when closing group groupVisibleMask &= ~(1 << groupDepth); groupDepth--; } // First, check if parents of this group is visible in the first place bool parentVisible = true; for (int parentMask = groupDepth - 1; parentMask > 0; parentMask--) { bool isVisible = (groupVisibleMask & (1 << parentMask)) > 0; parentVisible &= isVisible; } // Parents not visible, continue to next layer if (!parentVisible) { continue; } // Finally, check if layer being processed is start/end of group if (startGroup || closeGroup) { // If start or end of the group, call HandleGroupObject // which creates the group layer object and assignment of lastParent HandleGroupObject(groupInfo, groupHeaders, startGroup, constructor, ref lastParent); // A bunch of book keeping needs to be done at the start of a group if (startGroup) { // If this is the start of the group being constructed // store as the rootBase if (i == group.end) { rootBase = lastParent; rootBaseT = rootBase.transform; } } // Start or end group doesn't have visible sprite object, skip to next layer continue; } } // End processing of group start/end // If got to here, processing a visual layer // Skip if the export layers list doesn't contain this index if (exportLayers.Contains(i) == false) { continue; } // If got here and root base hasn't been set, that's a problem if (rootBase == null) { throw new Exception("Trying to create image layer before root base has been set"); } // Get layer info Layer layer = settings.Psd.Layers[i]; // Create the game object for the sprite GameObject spriteObject = constructor.CreateGameObject(layer.Name, lastParent); // Reparent created object to last parent if (lastParent != null) { spriteObject.transform.SetParent(lastParent.transform, false); } // Retrieve sprite from asset database string sprPath = PSDExporter.GetLayerFilename(settings, i); Sprite sprite = AssetDatabase.LoadAssetAtPath <Sprite>(sprPath); // Get the pivot settings for the sprite TextureImporter sprImporter = (TextureImporter)AssetImporter.GetAtPath(sprPath); TextureImporterSettings sprSettings = new TextureImporterSettings(); sprImporter.ReadTextureSettings(sprSettings); sprImporter = null; // Add components to the sprite object for the visuals constructor.AddComponents(i, spriteObject, sprite, sprSettings); Transform spriteT = spriteObject.transform; // Reposition the sprite object according to PSD position Vector2 spritePivot = GetPivot(sprSettings); Vector3 layerPos = constructor.GetLayerPosition(layer.Rect, spritePivot, settings.PixelsToUnitSize); // Scaling factor, if sprites were scaled down float posScale = 1f; switch (settings.ScaleBy) { case 1: posScale = 0.5f; break; case 2: posScale = 0.25f; break; } layerPos *= posScale; // Sprite position is based on root object position initially spriteT.position = (rootBaseT.position + layerPos); } // End layer loop // Loop through the groups and reposition according to alignment var groups = groupHeaders.Values.ToArray(); for (int grpIndex = 0; grpIndex < groups.Length; grpIndex++) { var groupObject = groups[grpIndex]; if (groupObject == null) { continue; } Transform groupT = groupObject.transform; // Store the sibling index, order important for UI // reconstruction that was established earlier int siblingIndex = groupT.GetSiblingIndex(); // Get the position from the root pos function Vector3 groupPos = constructor.GetGroupPosition(groupObject, align); // Create a new object GameObject newRoot = constructor.CreateGameObject(groupObject.name, groupObject); // Reparent new object to same parent as old group object Transform newRootT = newRoot.transform; newRootT.SetParent(groupT.parent); // Take over the sibling index of the old group object newRootT.SetSiblingIndex(siblingIndex); // Reposition the new object newRootT.position = groupPos; // Reparent the children from the old root object to new root while (groupT.childCount > 0) { groupT.GetChild(0).SetParent(newRootT, true); } // If the group we're handling is rootBaseT, position the // replacement group header over old root if (groupT == rootBaseT) { newRootT.position = rootBaseT.position; } // Destroy the old root Object.DestroyImmediate(groups[grpIndex]); } // End reposition loop } // End BuildPsd()
public static int GetExportCount(PsdExportSettings settings, PsdFileInfo fileInfo) { var exportLayers = GetExportLayers(settings, fileInfo); return exportLayers.Count; }
public static void BuildPsd(GameObject root, PSDLayerGroupInfo group, PsdExportSettings settings, PsdFileInfo fileInfo, SpriteAlignment align, IPsdConstructor constructor) { // Run the export on non exported layers PSDExporter.Export(settings, fileInfo, false); // Find all the layers being exported var exportLayers = PSDExporter.GetExportLayers(settings, fileInfo); // Stores the root object for each encountered group Dictionary<PSDLayerGroupInfo, GameObject> groupHeaders = new Dictionary<PSDLayerGroupInfo, GameObject>(); // Store the last parent, for traversal GameObject lastParent = root; GameObject rootBase = null; Transform rootBaseT = null; int groupVisibleMask = 1; int groupDepth = 0; // Loop through all the layers of the PSD file // backwards so they appear in the expected order // Going through all the layers, and not just the exported layers // so that the groups can be setup for (int i = group.end; i >= group.start; i--) { // Skip if layer is hidden if (fileInfo.LayerVisibility[i] == false) continue; var groupInfo = fileInfo.GetGroupByLayerIndex(i); bool inGroup = groupInfo != null; // Skip if layer belongs to a hidden group if (inGroup && groupInfo.visible == false) continue; // When inside a group... if (inGroup) { // Inverted because starting backwards bool startGroup = groupInfo.end == i; bool closeGroup = groupInfo.start == i; // Go up or down group depths if (startGroup) { groupDepth++; groupVisibleMask |= ((groupInfo.visible ? 1 : 0) << groupDepth); } if (closeGroup) { // Reset group visible flag when closing group groupVisibleMask &= ~(1 << groupDepth); groupDepth--; } // First, check if parents of this group is visible in the first place bool parentVisible = true; for (int parentMask = groupDepth - 1; parentMask > 0; parentMask--) { bool isVisible = (groupVisibleMask & (1 << parentMask)) > 0; parentVisible &= isVisible; } // Parents not visible, continue to next layer if (!parentVisible) continue; // Finally, check if layer being processed is start/end of group if (startGroup || closeGroup) { // If start or end of the group, call HandleGroupObject // which creates the group layer object and assignment of lastParent HandleGroupObject(groupInfo, groupHeaders, startGroup, constructor, ref lastParent); // A bunch of book keeping needs to be done at the start of a group if (startGroup) { // If this is the start of the group being constructed // store as the rootBase if (i == group.end) { rootBase = lastParent; rootBaseT = rootBase.transform; } } // Start or end group doesn't have visible sprite object, skip to next layer continue; } } // End processing of group start/end // If got to here, processing a visual layer // Skip if the export layers list doesn't contain this index if (exportLayers.Contains(i) == false) continue; // If got here and root base hasn't been set, that's a problem if (rootBase == null) { throw new Exception("Trying to create image layer before root base has been set"); } // Get layer info Layer layer = settings.Psd.Layers[i]; // Create the game object for the sprite GameObject spriteObject = constructor.CreateGameObject(layer.Name, lastParent); // Reparent created object to last parent if (lastParent != null) spriteObject.transform.SetParent(lastParent.transform, false); // Retrieve sprite from asset database string sprPath = PSDExporter.GetLayerFilename(settings, i); Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(sprPath); // Get the pivot settings for the sprite TextureImporter sprImporter = (TextureImporter)AssetImporter.GetAtPath(sprPath); TextureImporterSettings sprSettings = new TextureImporterSettings(); sprImporter.ReadTextureSettings(sprSettings); sprImporter = null; // Add components to the sprite object for the visuals constructor.AddComponents(i, spriteObject, sprite, sprSettings); Transform spriteT = spriteObject.transform; // Reposition the sprite object according to PSD position Vector2 spritePivot = GetPivot(sprSettings); Vector3 layerPos = constructor.GetLayerPosition(layer.Rect, spritePivot, settings.PixelsToUnitSize); // Scaling factor, if sprites were scaled down float posScale = 1f; switch (settings.ScaleBy) { case 1: posScale = 0.5f; break; case 2: posScale = 0.25f; break; } layerPos *= posScale; // Sprite position is based on root object position initially spriteT.position = (rootBaseT.position + layerPos); } // End layer loop // Loop through the groups and reposition according to alignment var groups = groupHeaders.Values.ToArray(); for (int grpIndex = 0; grpIndex < groups.Length; grpIndex++) { var groupObject = groups[grpIndex]; if (groupObject == null) continue; Transform groupT = groupObject.transform; // Store the sibling index, order important for UI // reconstruction that was established earlier int siblingIndex = groupT.GetSiblingIndex(); // Get the position from the root pos function Vector3 groupPos = constructor.GetGroupPosition(groupObject, align); // Create a new object GameObject newRoot = constructor.CreateGameObject(groupObject.name, groupObject); // Reparent new object to same parent as old group object Transform newRootT = newRoot.transform; newRootT.SetParent(groupT.parent); // Take over the sibling index of the old group object newRootT.SetSiblingIndex(siblingIndex); // Reposition the new object newRootT.position = groupPos; // Reparent the children from the old root object to new root while (groupT.childCount > 0) { groupT.GetChild(0).SetParent(newRootT, true); } // If the group we're handling is rootBaseT, position the // replacement group header over old root if (groupT == rootBaseT) { newRootT.position = rootBaseT.position; } // Destroy the old root Object.DestroyImmediate(groups[grpIndex]); } // End reposition loop } // End BuildPsd()