private void OnTemplatesAdd(ReorderableList _list) { if (templates.Count > 0) { SpriteTemplate _lastTemplate = templates[templates.Count - 1]; SpriteTemplate _template = new SpriteTemplate() { DoBakeLights = _lastTemplate.DoBakeLights, DoUsePowerOfTwoTexture = _lastTemplate.DoUsePowerOfTwoTexture, Layer = _lastTemplate.Layer, OrderInLayer = _lastTemplate.OrderInLayer, Material = _lastTemplate.Material, }; templates.Add(_template); } else { templates.Add(new SpriteTemplate()); } }
// ---------------- public void DrawSpriteScraper() { // GUIStyles initialization. if (!areGUIStylesInitialized) { areGUIStylesInitialized = true; headerInfoStyle = new GUIStyle(EditorStyles.label); headerInfoStyle.alignment = TextAnchor.MiddleCenter; } // Sprite Scraper mode GUILayout.Space(5); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); scraperMode = GUILayout.Toolbar(scraperMode, scraperModes, GUI.skin.button, GUI.ToolbarButtonSize.FitToContents, GUILayout.Height(25)); EditorGUILayout.EndHorizontal(); // Settings areSettingsUnfolded = EditorGUILayout.Foldout(areSettingsUnfolded, settingsGUI, true); if (areSettingsUnfolded) { EditorGUI.indentLevel++; // Save texture folder. EditorGUILayout.BeginHorizontal(); EditorGUILayout.TextField(saveTextureFolderGUI, saveTextureFolder); Rect _rect = EditorGUILayout.GetControlRect(false, 16, GUILayout.Width(16)); _rect.Set ( _rect.x - 2, _rect.y - 1, _rect.width + 2, _rect.height + 1 ); if (GUI.Button(_rect, GUIContent.none)) { string _folder = EditorUtility.OpenFolderPanel(textureFolderPanel, string.Empty, string.Empty); if (_folder.Contains(Application.dataPath)) { doDisplayInvalidFolderMessage = false; saveTextureFolder = _folder.Remove(0, Application.dataPath.Length - 6) + Path.AltDirectorySeparatorChar; } else { doDisplayInvalidFolderMessage = true; } } _rect.width = 30; _rect.x -= (_rect.width / 2) - 2; _rect.y += 1; EditorGUI.LabelField(_rect, EditorGUIUtility.IconContent(browseIconName)); EditorGUILayout.EndHorizontal(); if (doDisplayInvalidFolderMessage) { EditorGUILayout.HelpBox(invalidFolderMessage, MessageType.Error); } // Unlit material. unlitMaterial = (Material)EditorGUILayout.ObjectField(unlitMaterialGUI, unlitMaterial, typeof(Material), false); EditorGUI.indentLevel--; } if (!unlitMaterial) { EditorGUILayout.HelpBox(noUnlitMessage, MessageType.Warning); } GUILayout.Space(5); EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, 1), Color.grey); GUILayout.Space(5); templatesList.DoLayoutList(); // List cleaner buttons GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button(cleanButton) && EditorUtility.DisplayDialog(confirmDialogTitle, cleanMessage, confirmDialogOK, confirmDialogCancel)) { templates.Clear(); } if (GUILayout.Button(removeUnusedButton) && EditorUtility.DisplayDialog(confirmDialogTitle, removeUnusedMessage, confirmDialogOK, confirmDialogCancel)) { for (int _i = 0; _i < templates.Count; _i++) { if (!templates[_i].IsSelected) { templates.RemoveAt(_i); _i--; } } } GUILayout.EndHorizontal(); // Merge scraps into beautiful artworks. if (GUILayout.Button(mergeScrapsGUI, GUILayout.MaxWidth(100), GUILayout.Height(25))) { #region Scraper if (templates.Count > 0) { doDisplayNoTemplateMessage = false; // Create and configure camera used to capture templates. Camera _renderCamera = new GameObject().AddComponent <Camera>(); Rect _viewport = new Rect(0, 0, 1, 1); _renderCamera.orthographic = true; _renderCamera.clearFlags = CameraClearFlags.SolidColor; _renderCamera.backgroundColor = Color.clear; _renderCamera.cullingMask = ~2; _renderCamera.allowDynamicResolution = true; Renderer[] _allRenderers = FindObjectsOfType <Renderer>(); GameObject[] _artworks = new GameObject[templates.Count]; int[] _artworksLayer = new int[templates.Count]; for (int _n = 0; _n < templates.Count; _n++) { if (!templates[_n].IsSelected || !templates[_n].Root) { continue; } SpriteTemplate _template = templates[_n]; SpriteRenderer[] _sprites = _template.Root.GetComponentsInChildren <SpriteRenderer>(); SpriteMask[] _masks = _template.Root.GetComponentsInChildren <SpriteMask>(); // Set template bounds volume entirely in camera view. Bounds _bounds = new Bounds(_sprites[0].bounds.center, _sprites[0].bounds.size); for (int _i = 1; _i < _sprites.Length; _i++) { _bounds.Encapsulate(_sprites[_i].bounds); } _renderCamera.orthographicSize = 5; _renderCamera.transform.position = new Vector3(_bounds.center.x, _bounds.center.y, _bounds.center.z - 10); while (!(_viewport.Contains(_renderCamera.WorldToViewportPoint(_bounds.min)) && _viewport.Contains(_renderCamera.WorldToViewportPoint(_bounds.max)))) { _renderCamera.orthographicSize++; } // Set all visible renderers on a different layer (not visible anymore). Plane[] _frustrumPlanes = GeometryUtility.CalculateFrustumPlanes(_renderCamera); Dictionary <GameObject, int> _renderers = new Dictionary <GameObject, int>(); for (int _i = 0; _i < _allRenderers.Length; _i++) { if (GeometryUtility.TestPlanesAABB(_frustrumPlanes, _allRenderers[_i].bounds) && !_sprites.Contains(_allRenderers[_i]) && !_masks.Contains(_allRenderers[_i]) && !_renderers.ContainsKey(_allRenderers[_i].gameObject)) { _renderers.Add(_allRenderers[_i].gameObject, _allRenderers[_i].gameObject.layer); _allRenderers[_i].gameObject.layer = 1; } } // Get artwork texture information and capture template. Vector2 _offset = _renderCamera.WorldToScreenPoint(_bounds.min); Vector2 _boundsSize = (Vector2)_renderCamera.WorldToScreenPoint(_bounds.max) - _offset; Vector2Int _size; if (_template.DoUsePowerOfTwoTexture) { _size = new Vector2Int(Mathf.NextPowerOfTwo((int)_boundsSize.x), Mathf.NextPowerOfTwo((int)_boundsSize.y)); } else { _size = new Vector2Int((int)_boundsSize.x, (int)_boundsSize.y); } RenderTexture _renderTexture = new RenderTexture(_renderCamera.pixelWidth, _renderCamera.pixelHeight, 32); RenderTexture.active = _renderTexture; _renderCamera.targetTexture = _renderTexture; // Set template sprites material to unlit if not baking light. Material[] _spritesMaterial = null; bool _doNotBakeLight = !_template.DoBakeLights && unlitMaterial; if (_doNotBakeLight) { _spritesMaterial = new Material[_sprites.Length]; for (int _i = 0; _i < _sprites.Length; _i++) { _spritesMaterial[_i] = _sprites[_i].sharedMaterial; _sprites[_i].material = unlitMaterial; } } _renderCamera.Render(); // Restore template sprites material. if (_doNotBakeLight) { for (int _i = 0; _i < _sprites.Length; _i++) { _sprites[_i].material = _spritesMaterial[_i]; } } // Reset renderers layer. foreach (KeyValuePair <GameObject, int> _renderer in _renderers) { _renderer.Key.layer = _renderer.Value; } // Create full transparent texture, then paint capture on it. var _capture = new Texture2D(_size.x, _size.y, TextureFormat.RGBA32, false); Color[] _colors = _capture.GetPixels(); for (int _i = 0; _i < _colors.Length; _i++) { _colors[_i] = Color.clear; } _capture.SetPixels(_colors); // Reversed Y starting position _capture.ReadPixels(new Rect(_offset.x, _renderCamera.pixelHeight - _offset.y - _boundsSize.y, _boundsSize.x, _boundsSize.y), 0, 0); _capture.Apply(); // Create artwork based on template. SpriteRenderer _artwork = new GameObject(_template.Root.name).AddComponent <SpriteRenderer>(); Vector2 _pivot = new Vector2((_boundsSize.x * .5f) / _size.x, 0); float _pixelPerUnit = _renderCamera.pixelHeight / (_renderCamera.orthographicSize * 2f); _artwork.gameObject.layer = 1; _artwork.sortingOrder = _template.OrderInLayer; _artwork.transform.position = new Vector3(_bounds.min.x + _bounds.extents.x, _bounds.min.y, _bounds.center.z); if (_template.Material) { _artwork.material = _template.Material; } _artworks[_n] = _artwork.gameObject; _artworksLayer[_n] = _template.Layer; // Save texture according to selected mode. if (scraperMode < 2) { string _path = Application.dataPath + saveTextureFolder.Remove(0, 6); if (!Directory.Exists(_path)) { Directory.CreateDirectory(_path); } // Get unique file path. _path += _artwork.name + textureExtension; if (File.Exists(_path)) { string _originalPath = _path.Insert(_path.Length - 4, "_"); int _number = 0; do { _path = _originalPath.Insert(_originalPath.Length - 4, _number.ToString()); _number++; } while (File.Exists(_path)); } // Save texture as PNG. File.WriteAllBytes(_path, _capture.EncodeToPNG()); _path = _path.Remove(0, Application.dataPath.Length - 6); AssetDatabase.ImportAsset(_path, ImportAssetOptions.ForceUpdate); TextureImporter _importer = (TextureImporter)AssetImporter.GetAtPath(_path); TextureImporterSettings _settings = new TextureImporterSettings(); _importer.textureType = TextureImporterType.Sprite; _importer.spritePixelsPerUnit = _pixelPerUnit; _importer.ReadTextureSettings(_settings); _settings.spriteAlignment = (int)SpriteAlignment.Custom; _importer.SetTextureSettings(_settings); _importer.spritePivot = _pivot; _importer.SaveAndReimport(); _artwork.sprite = AssetDatabase.LoadAssetAtPath <Sprite>(_path); } else { _artwork.sprite = Sprite.Create(_capture, new Rect(0, 0, _size.x, _size.y), _pivot, _pixelPerUnit); } } // Replace templates by artworks on new scene mode. if (scraperMode == 0) { for (int _i = 0; _i < _artworks.Length; _i++) { if (_artworks[_i] && templates[_i].Root) { _artworks[_i].transform.SetParent(templates[_i].Root.parent); try { DestroyImmediate(templates[_i].Root.gameObject); } catch (InvalidOperationException) { GameObject _prefabRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(templates[_i].Root.gameObject); PrefabUtility.UnpackPrefabInstance(_prefabRoot, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); DestroyImmediate(templates[_i].Root.gameObject); } } } // Save scene as new one. templates.Clear(); EditorApplication.ExecuteMenuItem(saveAsMenuPath); } // Set artowrks layer. for (int _i = 0; _i < _artworks.Length; _i++) { if (_artworks[_i]) { _artworks[_i].layer = _artworksLayer[_i]; } } // Clean capture tools. DestroyImmediate(_renderCamera.gameObject); RenderTexture.active = null; } else { doDisplayNoTemplateMessage = true; } #endregion } if (doDisplayNoTemplateMessage) { EditorGUILayout.HelpBox(noTemplateMessage, MessageType.Error); } }