private void DrawLayerAdvanced(ImportLayerData layer, Rect rPiv, Rect rScale, Rect rReset) { using (var check = new EditorGUI.ChangeCheckScope()) { layer.Alignment = (SpriteAlignment)EditorGUI.EnumPopup(rPiv, GUIContent.none, layer.Alignment); layer.ScaleFactor = (ScaleFactor)EditorGUI.EnumPopup(rScale, GUIContent.none, layer.ScaleFactor); if (check.changed) { layer.useDefaults = false; settingsChanged = true; } } using (new EditorGUI.DisabledGroupScope(layer.useDefaults)) { if (GUI.Button(rReset, "R", EditorStyles.miniButton)) { settingsChanged = true; layer.useDefaults = true; layer.Pivot = importSettings.DefaultPivot; layer.Alignment = importSettings.DefaultAlignment; layer.ScaleFactor = importSettings.ScaleFactor; } } }
public static void Reconstruct(Object psdFile, ImportUserData importSettings, ImportLayerData reconstructRoot, Vector2 documentPivot, IReconstructor reconstructor) { string psdPath = GetPsdFilepath(psdFile); if (string.IsNullOrEmpty(psdPath)) { return; } using (var psdDoc = PsdDocument.Create(psdPath)) { ReconstructData data = GetReconstructData(psdDoc, psdPath, documentPivot, importSettings, reconstructRoot); var GO = reconstructor.Reconstruct(reconstructRoot, data, Selection.activeGameObject); if (GO != null) { EditorGUIUtility.PingObject(GO); Selection.activeGameObject = GO; } } }
public static Texture2D GetLayerTexture(Object psdFile, int[] layerIdx) { ImportLayerData setting = new ImportLayerData() { Alignment = SpriteAlignment.Center, Pivot = new Vector2(0.5f, 0.5f), ScaleFactor = ScaleFactor.Full, Childs = new List <ImportLayerData>(), import = true, indexId = layerIdx }; return(GetLayerTexture(psdFile, setting)); }
private bool ParentWillImport(int[] layerIdx) { bool willImport = true; ImportLayerData currentLayer = importSettings.DocRoot; for (int i = 0; i < layerIdx.Length - 1; i++) { int idx = layerIdx[i]; currentLayer = currentLayer.Childs[idx]; willImport &= currentLayer.import; if (willImport == false) { break; } } return(willImport); }
public static Texture2D GetLayerTexture(Object psdFile, ImportLayerData setting) { string filepath = GetPsdFilepath(psdFile); if (string.IsNullOrEmpty(filepath)) { return(null); } Texture2D texture = null; using (PsdDocument psd = PsdDocument.Create(filepath)) { var layer = GetPsdLayerByIndex(psd, setting.indexId); texture = GetLayerTexture(psd, layer, setting); } return(texture); }
private void RecursiveQuickSelect(ImportLayerData layer, bool inSelection) { SetQuickSelect(layer.indexId, inSelection); layer.Iterate( childLayer => { if (layer.Childs == null) { return; } if (childLayer.import) { SetQuickSelect(childLayer.indexId, inSelection); } } ); GetSelectCount(); }
/// <summary> /// Resolve setting differences from stored data and built data /// </summary> /// <param name="storedData"></param> /// <param name="builtData"></param> /// <returns></returns> private ImportLayerData ResolveData(ImportLayerData storedData, ImportLayerData builtData) { // Nothing was stored, used built data if (storedData == null) { return(builtData); } // Flatten out stored to a dictionary, using the path as keys Dictionary <string, ImportLayerData> storedIndex = new Dictionary <string, ImportLayerData>(); storedData.Iterate( layerCallback: layer => { if (storedIndex.ContainsKey(layer.path) == false) { storedIndex.Add(layer.path, layer); } else { storedIndex[layer.path] = layer; } } ); // Iterate through the built data now, checking for settings from storedIndex builtData.Iterate( layerCallback: layer => { ImportLayerData existingSettings; if (storedIndex.TryGetValue(layer.path, out existingSettings)) { layer.useDefaults = existingSettings.useDefaults; layer.Alignment = existingSettings.Alignment; layer.Pivot = existingSettings.Pivot; layer.ScaleFactor = existingSettings.ScaleFactor; layer.import = existingSettings.import; } } ); return(builtData); }
public ImportLayerData GetLayerData(int[] layerIdx) { if (DocRoot == null) { return(null); } ImportLayerData currentLayer = DocRoot; foreach (int idx in layerIdx) { if (idx < 0 || idx >= currentLayer.Childs.Count) { return(null); } currentLayer = currentLayer.Childs[idx]; } return(currentLayer); }
private static ReconstructData GetReconstructData(PsdDocument psdDoc, string psdPath, Vector2 documentPivot, ImportUserData importSettings, ImportLayerData reconstructRoot) { // Get the texture import setting of the PSD TextureImporter psdUnitySettings = (TextureImporter)AssetImporter.GetAtPath(psdPath); TextureImporterSettings psdUnityImport = new TextureImporterSettings(); psdUnitySettings.ReadTextureSettings(psdUnityImport); Vector2 docSize = new Vector2(psdDoc.Width, psdDoc.Height); ReconstructData data = new ReconstructData(docSize, documentPivot, psdUnitySettings.spritePixelsPerUnit); reconstructRoot.Iterate( layerCallback: layer => { if (layer.import == false) { return; } var psdLayer = GetPsdLayerByIndex(psdDoc, layer.indexId); Rect layerBounds = new Rect() { xMin = psdLayer.Left, xMax = psdLayer.Right, yMin = psdDoc.Height - psdLayer.Bottom, yMax = psdDoc.Height - psdLayer.Top }; data.layerBoundsIndex.Add(layer.indexId, layerBounds); string layerDir; string layerPath = GetFilePath(psdLayer, importSettings, "png", out layerDir); string layerMeshDir; string layerMeshPath = GetFilePath(psdLayer, importSettings, "asset", out layerMeshDir); Sprite layerSprite = AssetDatabase.LoadAssetAtPath <Sprite>(layerPath); SpriteMesh layerSpriteMesh = AssetDatabase.LoadAssetAtPath <SpriteMesh>(layerMeshPath); if (layerSprite == null) { layerSprite = ImportLayer(psdDoc, importSettings, layer, psdUnityImport); } if (layerSpriteMesh == null && importSettings.GenerateSpriteMesh) { layerSpriteMesh = GenerateSpriteMesh(layerSprite); } Vector2 spriteAnchor = Vector2.zero; if (layerSprite != null) { TextureImporter layerImporter = (TextureImporter)AssetImporter.GetAtPath(layerPath); TextureImporterSettings layerSettings = new TextureImporterSettings(); layerImporter.ReadTextureSettings(layerSettings); if (layerSettings.spriteAlignment == (int)SpriteAlignment.Custom) { spriteAnchor = layerSettings.spritePivot; } else { spriteAnchor = AlignmentToPivot((SpriteAlignment)layerSettings.spriteAlignment); } } data.AddSprite(layer.indexId, layerSprite, spriteAnchor); if (importSettings.GenerateSpriteMesh) { data.AddSpriteMesh(layer.indexId, layerSpriteMesh); } }, canEnterGroup: checkGroup => checkGroup.import ); return(data); }
private static IEnumerator ImportCoroutine(Object psdFile, string targetDirectory, ImportUserData importSettings, List <int[]> layerIndices, Action <int, ImportLayerData> layerCallback = null, Action <List <Sprite> > completeCallback = null) { string filepath = GetPsdFilepath(psdFile); if (string.IsNullOrEmpty(filepath)) { completeCallback?.Invoke(null); yield break; } if (string.IsNullOrEmpty(targetDirectory)) { targetDirectory = filepath.Substring(0, filepath.LastIndexOf("/")); } // Get the texture importer for the PSD TextureImporter psdUnitySettings = (TextureImporter)AssetImporter.GetAtPath(filepath); TextureImporterSettings psdUnityImport = new TextureImporterSettings(); psdUnitySettings.ReadTextureSettings(psdUnityImport); int importCurrent = 0; var sprites = new List <Sprite>(); using (PsdDocument psd = PsdDocument.Create(filepath)) { var layersSettings = new List <ImportLayerData>(); foreach (int[] layerIdx in layerIndices) { ImportLayerData layerSettings = importSettings.GetLayerData(layerIdx); if (layerSettings == null) { continue; } layerCallback?.Invoke(importCurrent, layerSettings); layersSettings.Add(layerSettings); } const float totalSteps = 4.0f; float currentStep = 0.0f; EditorCoroutineRunner.UpdateUI($"Getting psd layers", ++currentStep / totalSteps); yield return(null); var psdLayers = GetPsdLayers(layersSettings, psd); EditorCoroutineRunner.UpdateUI($"CreateTextures2D", ++currentStep / totalSteps); yield return(null); var textures = CreateTextures2D(psdLayers, psd, importSettings, psdUnityImport); EditorCoroutineRunner.UpdateUI($"GetTextureWithPathData", ++currentStep / totalSteps); yield return(null); var texturesData = GetTextureWithPathData(textures, psdLayers.Select(x => x.psdLayer).ToArray(), importSettings.fileNaming, importSettings.groupMode, targetDirectory); EditorCoroutineRunner.UpdateUI($"CreateSpriteAssets", ++currentStep / totalSteps); yield return(null); sprites.AddRange(CreateSpriteAssets(texturesData, layersSettings, psdUnityImport, importSettings.PackingTag)); } completeCallback?.Invoke(sprites); }
private static Sprite ImportLayer(PsdDocument psdDoc, ImportUserData importSettings, ImportLayerData layerSettings, TextureImporterSettings psdUnityImport) { if (layerSettings == null) { return(null); } PsdLayer psdLayer = GetPsdLayerByIndex(psdDoc, layerSettings.indexId); if (psdLayer.IsGroup) { return(null); } // Generate the texture Texture2D layerTexture = GetLayerTexture(psdDoc, psdLayer, layerSettings); if (layerTexture == null) { return(null); } // Save the texture as an asset Sprite layerSprite = SaveAsset(psdLayer, psdUnityImport, layerTexture, importSettings, layerSettings); return(layerSprite); }
private static Sprite SaveAsset(PsdLayer psdLayer, TextureImporterSettings psdUnityImport, Texture2D texture, ImportUserData importSettings, ImportLayerData layerSettings) { // Generate the file path for this layer string fileDir; string filepath = GetFilePath(psdLayer, importSettings, "png", out fileDir); // Create the folder if non existent if (AssetDatabase.IsValidFolder(fileDir) == false) { var subPaths = fileDir.Split('/'); string parentFolder = subPaths[0]; foreach (string folder in subPaths.Skip(1)) { string targetFolder = string.Format("{0}/{1}", parentFolder, folder); if (AssetDatabase.IsValidFolder(targetFolder) == false) { AssetDatabase.CreateFolder(parentFolder, folder); } parentFolder = targetFolder; } } // Write out the texture contents into the file AssetDatabase.CreateAsset(texture, filepath); byte[] buf = texture.EncodeToPNG(); File.WriteAllBytes(filepath, buf); AssetDatabase.ImportAsset(filepath, ImportAssetOptions.ForceUpdate); Texture2D textureObj = AssetDatabase.LoadAssetAtPath <Texture2D>(filepath); // Get the texture importer for the asset TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(filepath); // Read out the texture import settings so settings can be changed TextureImporterSettings texSetting = new TextureImporterSettings(); textureImporter.ReadTextureSettings(texSetting); float finalPPU = psdUnityImport.spritePixelsPerUnit; switch (layerSettings.ScaleFactor) { case ScaleFactor.Half: finalPPU /= 2; break; case ScaleFactor.Quarter: finalPPU /= 4; break; } // Change settings texSetting.spriteAlignment = (int)layerSettings.Alignment; texSetting.spritePivot = layerSettings.Pivot; texSetting.spritePixelsPerUnit = finalPPU; texSetting.filterMode = psdUnityImport.filterMode; texSetting.wrapMode = psdUnityImport.wrapMode; texSetting.textureType = TextureImporterType.Sprite; texSetting.spriteMode = (int)SpriteImportMode.Single; texSetting.mipmapEnabled = false; texSetting.alphaIsTransparency = true; texSetting.npotScale = TextureImporterNPOTScale.None; // Set the rest of the texture settings textureImporter.spritePackingTag = importSettings.PackingTag; // Write in the texture import settings textureImporter.SetTextureSettings(texSetting); EditorUtility.SetDirty(textureObj); AssetDatabase.WriteImportSettingsIfDirty(filepath); AssetDatabase.ImportAsset(filepath, ImportAssetOptions.ForceUpdate); return((Sprite)AssetDatabase.LoadAssetAtPath(filepath, typeof(Sprite))); }
private static Texture2D GetLayerTexture(PsdDocument psdDoc, PsdLayer psdLayer, ImportLayerData setting) { if (psdLayer == null || psdLayer.IsGroup) { return(null); } Texture2D layerTexture = GetTexture(psdLayer); if (setting.ScaleFactor != ScaleFactor.Full) { int mipMapLevel = setting.ScaleFactor == ScaleFactor.Half ? 1 : 2; layerTexture = ScaleTextureByMipmap(layerTexture, mipMapLevel); } return(layerTexture); }
private static IEnumerator ImportCoroutine(Object psdFile, ImportUserData importSettings, List <int[]> layerIndices, bool doYield = false, Action <int, ImportLayerData> layerCallback = null, Action <List <Sprite> > completeCallback = null) { string filepath = GetPsdFilepath(psdFile); if (string.IsNullOrEmpty(filepath)) { if (completeCallback != null) { completeCallback(null); } yield break; } // No target directory set, use PSD file directory if (string.IsNullOrEmpty(importSettings.TargetDirectory)) { importSettings.TargetDirectory = filepath.Substring(0, filepath.LastIndexOf("/")); } // Get the texture importer for the PSD TextureImporter psdUnitySettings = (TextureImporter)AssetImporter.GetAtPath(filepath); TextureImporterSettings psdUnityImport = new TextureImporterSettings(); psdUnitySettings.ReadTextureSettings(psdUnityImport); int importCurrent = 0; List <Sprite> sprites = new List <Sprite>(); using (PsdDocument psd = PsdDocument.Create(filepath)) { foreach (int[] layerIdx in layerIndices) { ImportLayerData layerSettings = importSettings.GetLayerData(layerIdx); if (layerSettings == null) { continue; } if (layerCallback != null) { layerCallback(importCurrent, layerSettings); } var sprite = ImportLayer(psd, importSettings, layerSettings, psdUnityImport); if (importSettings.GenerateSpriteMesh) { GenerateSpriteMesh(sprite); } sprites.Add(sprite); importCurrent++; if (doYield) { yield return(null); } } } if (completeCallback != null) { completeCallback(sprites); } }
private void DrawIterateLayers(ImportLayerData layerData) { layerRectLookup.Clear(); layerEntryYMax = 0; layerData.Iterate( layerCallback: layer => { var display = GetDisplayData(layer.indexId); if (display == null) { return; } if (string.IsNullOrEmpty(searchFilter) == false) { if (layer.name.ToLower().Contains(searchFilter.ToLower()) == false) { return; } } DrawLayerEntry(layer, display); }, canEnterGroup: layer => { var display = GetDisplayData(layer.indexId); if (display == null) { return(true); } if (string.IsNullOrEmpty(searchFilter) == false) { return(true); } return(display.isOpen); }, enterGroupCallback: data => indentLevel++, exitGroupCallback: data => indentLevel-- ); // Process mouse events var evt = Event.current; bool willChangeSelection = false; int[] targetLayer = null; foreach (var kvp in layerRectLookup) { if (kvp.Value.Contains(evt.mousePosition)) { var checkLayer = GetLayerData(kvp.Key); if (checkLayer == null || checkLayer.Childs == null) { continue; } bool layerIsGroup = checkLayer.Childs.Count > 0; if (evt.type == EventType.MouseDown) { willChangeSelection = layerIsGroup == false; bool willAddSelect = quickSelect.Contains(kvp.Key) == false; if (willAddSelect) { lastSelectedLayer = kvp.Key; } if (willChangeSelection) { isChangingSelection = true; targetLayer = kvp.Key; selectionChangeState = willAddSelect; } else { RecursiveQuickSelect(checkLayer, willAddSelect); if (willAddSelect == false) { lastSelectedLayer = null; } Repaint(); } evt.Use(); } if (evt.type == EventType.MouseUp) { isChangingSelection = false; } if (isChangingSelection && evt.type == EventType.MouseDrag && layerIsGroup == false) { willChangeSelection = true; targetLayer = kvp.Key; } break; } } if (willChangeSelection && targetLayer != null) { SetQuickSelect(targetLayer, selectionChangeState); GetSelectCount(); Repaint(); } }
private void DrawLayerEntry(ImportLayerData layer, DisplayLayerData display) { bool isGroup = display.isGroup; bool isSelected = quickSelect.Contains(layer.indexId); GUIStyle entryStyle = isSelected ? styleLayerSelected : styleLayerEntry; using (new GUILayout.HorizontalScope(entryStyle, layerHeight)) { Rect rEntry = GUILayoutUtility.GetRect(rTableSize.x, rTableSize.x, rTableSize.y, rTableSize.y); Rect rToggle = new Rect(rImportToggle); Rect rVis = new Rect(rVisible); Rect rLayer = new Rect(rLayerDisplay); Rect rPiv = new Rect(rPivot); Rect rScale = new Rect(rScaling); Rect rReset = new Rect(rMakeDefault); rToggle.y += rEntry.y; rVis.y += rEntry.y; rLayer.y += rEntry.y; rPiv.y += rEntry.y; rScale.y += rEntry.y; rReset.y += rEntry.y; bool parentWillImport = ParentWillImport(layer.indexId); using (new EditorGUI.DisabledScope(parentWillImport == false)) { var displayImport = layer.import && parentWillImport; EditorGUI.BeginChangeCheck(); displayImport = GUI.Toggle(rToggle, displayImport, GUIContent.none); if (EditorGUI.EndChangeCheck() && parentWillImport) { layer.import = displayImport; CollateImportList(); quickSelect.Clear(); selectionCount = 0; lastSelectedLayer = null; } } using (new EditorGUI.DisabledScope(true)) { var visStyle = display.isVisible ? styleVisOn : styleVisOff; GUI.Label(rVis, GUIContent.none, visStyle); } rLayer.xMin += indentLevel * indentWidth; GUIContent layerContent = new GUIContent() { image = isGroup ? icnFolder : icnTexture, text = layer.name }; if (isGroup) { float min, max; EditorStyles.popup.CalcMinMaxWidth(layerContent, out min, out max); rLayer.width = min; display.isOpen = EditorGUI.Foldout(rLayer, display.isOpen, layerContent); } else { EditorGUI.LabelField(rLayer, layerContent); if (isAdvancedMode) { DrawLayerAdvanced(layer, rPiv, rScale, rReset); } } } Rect layerRect = GUILayoutUtility.GetLastRect(); layerRect.xMin += 40; layerRectLookup.Add(layer.indexId, layerRect); layerEntryYMax = Mathf.Max(layerEntryYMax, layerRect.yMax); }
public static void BuildImportLayerData(Object file, ImportUserData importSettings, Action <ImportLayerData, DisplayLayerData> callback) { string filepath = GetPsdFilepath(file); if (string.IsNullOrEmpty(filepath)) { if (callback != null) { callback(null, null); } return; } using (PsdDocument psd = PsdDocument.Create(filepath)) { ImportLayerData docImportData = new ImportLayerData() { name = DOC_ROOT, indexId = new int[] { -1 }, Childs = new List <ImportLayerData>() }; DisplayLayerData docDisplayData = new DisplayLayerData() { indexId = new int[] { -1 }, Childs = new List <DisplayLayerData>() }; EditorCoroutineRunner.StartCoroutine( ParseLayers(psd.Childs, false, onLayer: (layer, indexId) => { // Walk down the index id to get the parent layers // and build the full path string fullPath = ""; ImportLayerData parentLayer = docImportData; DisplayLayerData parentDisplay = docDisplayData; if (indexId.Length > 1) { for (int idIdx = 0; idIdx < indexId.Length - 1; idIdx++) { int idx = indexId[idIdx]; parentLayer = parentLayer.Childs[idx]; parentDisplay = parentDisplay.Childs[idx]; if (string.IsNullOrEmpty(fullPath) == false) { fullPath += "/"; } fullPath += parentLayer.name; } } if (string.IsNullOrEmpty(fullPath) == false) { fullPath += "/"; } fullPath += layer.Name; ImportLayerData layerImportData = new ImportLayerData() { name = layer.Name, path = fullPath, indexId = indexId, import = layer.IsVisible, useDefaults = true, Alignment = importSettings.DefaultAlignment, Pivot = importSettings.DefaultPivot, ScaleFactor = importSettings.ScaleFactor, Childs = new List <ImportLayerData>() }; DisplayLayerData layerDisplayData = new DisplayLayerData() { indexId = indexId, isVisible = layer.IsVisible, isGroup = layer.Childs.Length > 0, isOpen = layer.IsFolderOpen }; int layerIdx = indexId[indexId.Length - 1]; int maxLayers = layerIdx + 1; while (parentLayer.Childs.Count < maxLayers) { parentLayer.Childs.Add(null); } parentLayer.Childs[layerIdx] = layerImportData; while (parentDisplay.Childs.Count < maxLayers) { parentDisplay.Childs.Add(null); } parentDisplay.Childs[layerIdx] = layerDisplayData; }, onComplete: () => { if (callback != null) { callback(docImportData, docDisplayData); } }) ); } }
private static Sprite CreateSpriteAsset(PsdDocument psdDoc, ImportUserData importSettings, ImportLayerData layerSettings, TextureImporterSettings psdUnityImport) { if (layerSettings == null) { return(null); } PsdLayer psdLayer = GetPsdLayerByIndex(psdDoc, layerSettings.indexId); if (psdLayer.IsGroup) { return(null); } // Generate the texture Texture2D layerTexture = GetLayerTexture(psdDoc, psdLayer, layerSettings.ScaleFactor); if (layerTexture == null) { return(null); } var layerPath = PathUtils.GetLayerPath(psdLayer, importSettings.fileNaming, importSettings.groupMode); // Save the texture as an asset return(SaveAsset(layerPath, psdUnityImport, layerTexture, importSettings.TargetDirectory, importSettings.PackingTag, layerSettings)); }
private void DrawReconstructor() { if (importSettings == null) { return; } EditorGUILayout.LabelField(labelUseConstructor, EditorStyles.boldLabel); ImportLayerData reconstructLayer = null; if (lastSelectedLayer != null) { reconstructLayer = GetLayerData(lastSelectedLayer); if (reconstructLayer != null && reconstructLayer.Childs.Count == 0) { reconstructLayer = null; } } selectedReconstructor = EditorGUILayout.Popup(labelSelConstructor, selectedReconstructor, dropdownReconstruct); SpriteAlignUI.DrawGUILayout(labelDocAlign, importSettings.DocAlignment, alignment => { importSettings.DocAlignment = alignment; if (alignment != SpriteAlignment.Custom) { importSettings.DocPivot = PsdImporter.AlignmentToPivot(alignment); } Repaint(); }); if (importSettings.DocAlignment == SpriteAlignment.Custom) { EditorGUI.indentLevel++; importSettings.DocPivot = EditorGUILayout.Vector2Field(labelDocPivot, importSettings.DocPivot); EditorGUI.indentLevel--; } bool canReconstruct = reconstructLayer != null; IReconstructor reconstructorInstance = null; if (canReconstruct) { if (selectedReconstructor > -1 && selectedReconstructor < reconstructors.Length) { reconstructorInstance = reconstructors[selectedReconstructor]; canReconstruct = reconstructorInstance.CanReconstruct(Selection.activeGameObject); } else { canReconstruct = false; } } if (canReconstruct) { string strButton = string.Format("Build {0} as {1}", reconstructLayer.name, reconstructorInstance.DisplayName); if (GUILayout.Button(strButton, bigButton)) { GetLayerData(lastSelectedLayer); PsdImporter.Reconstruct(importFile, importSettings, reconstructLayer, importSettings.DocPivot, reconstructorInstance); } } else { string helpMessage = "Select a layer group"; if (reconstructLayer != null && reconstructorInstance != null) { helpMessage = reconstructorInstance.HelpMessage; } EditorGUILayout.HelpBox(helpMessage, MessageType.Info); } }