private void OnEnable () {
			source = Selection.activeObject as Texture2D;
			rgbFillMode = (RGBFillMode)EditorPrefs.GetInt(rgbModeKey);
			insideDistance = EditorPrefs.GetFloat(insideDistanceKey, 3f);
			outsideDistance = EditorPrefs.GetFloat(outsideDistanceKey, 3f);
			postProcessDistance = EditorPrefs.GetFloat(postProcessDistanceKey);
		}
 void OnEnable()
 {
     source              = Selection.activeObject as Texture2D;
     rgbFillMode         = (RGBFillMode)EditorPrefs.GetInt(rgbModeKey);
     insideDistance      = EditorPrefs.GetFloat(insideDistanceKey, 3f);
     outsideDistance     = EditorPrefs.GetFloat(outsideDistanceKey, 3f);
     postProcessDistance = EditorPrefs.GetFloat(postProcessDistanceKey);
 }
Exemple #3
0
        /// <summary>
        /// Fill a texture with a signed distance field generated from the alpha channel of a source texture.
        /// </summary>
        /// <param name="source">
        /// Source texture. Alpha values of 1 are considered inside, values of 0 are considered outside, and any other values are considered
        /// to be on the edge. Must be readable.
        /// </param>
        /// <param name="destination">
        /// Destination texture. Must be the same size as the source texture. Must be readable.
        /// The texture change does not get applied automatically, you need to do that yourself.
        /// </param>
        /// <param name="maxInside">
        /// Maximum pixel distance measured inside the edge, resulting in an alpha value of 1.
        /// If set to or below 0, everything inside will have an alpha value of 1.
        /// </param>
        /// <param name="maxOutside">
        /// Maximum pixel distance measured outside the edge, resulting in an alpha value of 0.
        /// If set to or below 0, everything outside will have an alpha value of 0.
        /// </param>
        /// <param name="postProcessDistance">
        /// Pixel distance from the edge within which pixels will be post-processed using the edge gradient.
        /// </param>
        /// <param name="rgbMode">
        /// How to fill the destination texture's RGB channels.
        /// </param>
        public static void Generate(
            Texture2D source,
            Texture2D destination,
            float maxInside,
            float maxOutside,
            float postProcessDistance,
            RGBFillMode rgbMode)
        {
            if (source.height != destination.height || source.width != destination.width)
            {
                Debug.LogError("Source and destination textures must be the same size.");
                return;
            }

            width  = source.width;
            height = source.height;
            pixels = new Pixel[width, height];
            int   x, y;
            float scale;
            Color c = rgbMode == RGBFillMode.White ? Color.white : Color.black;

            for (y = 0; y < height; y++)
            {
                for (x = 0; x < width; x++)
                {
                    pixels[x, y] = new Pixel();
                }
            }
            if (maxInside > 0f)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        pixels[x, y].alpha = 1f - source.GetPixel(x, y).a;
                    }
                }
                ComputeEdgeGradients();
                GenerateDistanceTransform();
                if (postProcessDistance > 0f)
                {
                    PostProcess(postProcessDistance);
                }
                scale = 1f / maxInside;
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c.a = Mathf.Clamp01(pixels[x, y].distance * scale);
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            if (maxOutside > 0f)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        pixels[x, y].alpha = source.GetPixel(x, y).a;
                    }
                }
                ComputeEdgeGradients();
                GenerateDistanceTransform();
                if (postProcessDistance > 0f)
                {
                    PostProcess(postProcessDistance);
                }
                scale = 1f / maxOutside;
                if (maxInside > 0f)
                {
                    for (y = 0; y < height; y++)
                    {
                        for (x = 0; x < width; x++)
                        {
                            c.a = 0.5f + (destination.GetPixel(x, y).a -
                                          Mathf.Clamp01(pixels[x, y].distance * scale)) * 0.5f;
                            destination.SetPixel(x, y, c);
                        }
                    }
                }
                else
                {
                    for (y = 0; y < height; y++)
                    {
                        for (x = 0; x < width; x++)
                        {
                            c.a = Mathf.Clamp01(1f - pixels[x, y].distance * scale);
                            destination.SetPixel(x, y, c);
                        }
                    }
                }
            }

            if (rgbMode == RGBFillMode.Distance)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c   = destination.GetPixel(x, y);
                        c.r = c.a;
                        c.g = c.a;
                        c.b = c.a;
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            else if (rgbMode == RGBFillMode.Source)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c   = source.GetPixel(x, y);
                        c.a = destination.GetPixel(x, y).a;
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            pixels = null;
        }
Exemple #4
0
        /// <summary>
        /// Fill a texture with a signed distance field generated from the alpha channel of a source texture.
        /// </summary>
        /// <param name="source">
        /// Source texture. Alpha values of 1 are considered inside, values of 0 are considered outside, and any other values are considered
        /// to be on the edge. Must be readable.
        /// </param>
        /// <param name="destination">
        /// Destination texture. Must be the same size as the source texture. Must be readable.
        /// The texture change does not get applied automatically, you need to do that yourself.
        /// </param>
        /// <param name="maxInside">
        /// Maximum pixel distance measured inside the edge, resulting in an alpha value of 1.
        /// If set to or below 0, everything inside will have an alpha value of 1.
        /// </param>
        /// <param name="maxOutside">
        /// Maximum pixel distance measured outside the edge, resulting in an alpha value of 0.
        /// If set to or below 0, everything outside will have an alpha value of 0.
        /// </param>
        /// <param name="postProcessDistance">
        /// Pixel distance from the edge within which pixels will be post-processed using the edge gradient.
        /// </param>
        /// <param name="rgbMode">
        /// How to fill the destination texture's RGB channels.
        /// </param>
        public static void Generate(
            Image <Rgba32> source,
            Image <Rgba32> destination,
            float maxInside,
            float maxOutside,
            float postProcessDistance,
            RGBFillMode rgbMode)
        {
            if (source.Height != destination.Height || source.Width != destination.Width)
            {
                Console.Out.WriteLine("Source and destination textures must be the same size.");
                return;
            }

            width  = source.Width;
            height = source.Height;
            pixels = new Pixel[width, height];
            int    x, y;
            float  scale;
            Rgba32 c = rgbMode == RGBFillMode.White ? Color.White : Color.Black;

            for (y = 0; y < height; y++)
            {
                for (x = 0; x < width; x++)
                {
                    pixels[x, y] = new Pixel();
                }
            }
            if (maxInside > 0f)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        pixels[x, y].alpha = source.GetPixel(x, y).R / 255f;
                    }
                }
                ComputeEdgeGradients();
                GenerateDistanceTransform();
                if (postProcessDistance > 0f)
                {
                    PostProcess(postProcessDistance);
                }
                scale = 1f / maxInside;
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c.A = (byte)(255f * Math.Clamp(pixels[x, y].distance * scale, 0, 1));
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            if (maxOutside > 0f)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        pixels[x, y].alpha = 1f - source.GetPixel(x, y).R / 255f;
                    }
                }
                ComputeEdgeGradients();
                GenerateDistanceTransform();
                if (postProcessDistance > 0f)
                {
                    PostProcess(postProcessDistance);
                }
                scale = 1f / maxOutside;
                if (maxInside > 0f)
                {
                    for (y = 0; y < height; y++)
                    {
                        for (x = 0; x < width; x++)
                        {
                            c.A = (byte)(255f * (0.5f + (destination.GetPixel(x, y).A / 255f -
                                                         Math.Clamp(pixels[x, y].distance * scale, 0, 1)) * 0.5f));
                            destination.SetPixel(x, y, c);
                        }
                    }
                }
                else
                {
                    for (y = 0; y < height; y++)
                    {
                        for (x = 0; x < width; x++)
                        {
                            c.A = (byte)(255f * Math.Clamp(1f - pixels[x, y].distance * scale, 0, 1));
                            destination.SetPixel(x, y, c);
                        }
                    }
                }
            }

            if (rgbMode == RGBFillMode.Distance)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c   = destination.GetPixel(x, y);
                        c.R = c.A;
                        c.G = c.A;
                        c.B = c.A;
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            else if (rgbMode == RGBFillMode.Source)
            {
                for (y = 0; y < height; y++)
                {
                    for (x = 0; x < width; x++)
                    {
                        c   = source.GetPixel(x, y);
                        c.A = destination.GetPixel(x, y).A;
                        destination.SetPixel(x, y, c);
                    }
                }
            }
            pixels = null;
        }
        void OnGUI()
        {
            GUILayout.BeginArea(new Rect(2f, 2f, 220f, position.height - 4f));

            EditorGUI.BeginChangeCheck();
            source = (Texture2D)EditorGUILayout.ObjectField(sourceTextureContent, source, typeof(Texture2D), false);
            if (EditorGUI.EndChangeCheck())
            {
                DestroyImmediate(destination);
                allowSave = false;
            }

            EditorGUI.BeginChangeCheck();
            rgbFillMode = (RGBFillMode)EditorGUILayout.EnumPopup(rgbFillModeContent, rgbFillMode);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetInt(rgbModeKey, (int)rgbFillMode);
                allowSave = false;
            }

            EditorGUI.BeginChangeCheck();
            insideDistance = EditorGUILayout.FloatField(insideContent, insideDistance);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetFloat(insideDistanceKey, insideDistance);
                allowSave = false;
            }

            EditorGUI.BeginChangeCheck();
            outsideDistance = EditorGUILayout.FloatField(outsideContent, outsideDistance);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetFloat(outsideDistanceKey, outsideDistance);
                allowSave = false;
            }

            EditorGUI.BeginChangeCheck();
            postProcessDistance = EditorGUILayout.FloatField(postprocessContent, postProcessDistance);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetFloat(postProcessDistanceKey, postProcessDistance);
                allowSave = false;
            }

            if (source != null && GUILayout.Button("Generate"))
            {
                Generate();
            }

            if (allowSave && GUILayout.Button("Save PNG file"))
            {
                SaveTexture();
            }

            GUILayout.EndArea();

            if (destination != null)
            {
                scrollPosition = GUI.BeginScrollView(
                    new Rect(224f, 2f, position.width - 226f, position.height - 4f),
                    scrollPosition,
                    new Rect(0f, 0f, destination.width, destination.height));
                EditorGUI.DrawTextureAlpha(new Rect(0f, 0f, destination.width, destination.height), destination);
                GUI.EndScrollView();
            }
        }
		private void OnGUI () {
			GUILayout.BeginArea(new Rect(2f, 2f, 220f, position.height - 4f));

			EditorGUI.BeginChangeCheck();
			source = (Texture2D)EditorGUILayout.ObjectField(sourceTextureContent, source, typeof(Texture2D), false);
			if (EditorGUI.EndChangeCheck()) {
				DestroyImmediate(destination);
				allowSave = false;
			}

			EditorGUI.BeginChangeCheck();
			rgbFillMode = (RGBFillMode)EditorGUILayout.EnumPopup(rgbFillModeContent, rgbFillMode);
			if (EditorGUI.EndChangeCheck()) {
				EditorPrefs.SetInt(rgbModeKey, (int)rgbFillMode);
				allowSave = false;
			}
			
			EditorGUI.BeginChangeCheck();
			insideDistance = EditorGUILayout.FloatField(insideContent, insideDistance);
			if (EditorGUI.EndChangeCheck()) {
				EditorPrefs.SetFloat(insideDistanceKey, insideDistance);
				allowSave = false;
			}

			EditorGUI.BeginChangeCheck();
			outsideDistance = EditorGUILayout.FloatField(outsideContent, outsideDistance);
			if (EditorGUI.EndChangeCheck()) {
				EditorPrefs.SetFloat(outsideDistanceKey, outsideDistance);
				allowSave = false;
			}

			EditorGUI.BeginChangeCheck();
			postProcessDistance = EditorGUILayout.FloatField(postprocessContent, postProcessDistance);
			if (EditorGUI.EndChangeCheck()) {
				EditorPrefs.SetFloat(postProcessDistanceKey, postProcessDistance);
				allowSave = false;
			}
			
			if (source != null && GUILayout.Button("Generate")) {
				Generate();
			}
			
			if (allowSave && GUILayout.Button("Save PNG file")) {
				string filePath = EditorUtility.SaveFilePanel(
					"Save Signed Distance Field",
					new FileInfo(AssetDatabase.GetAssetPath(source)).DirectoryName,
					source.name + " SDF",
					"png");
				if (filePath.Length > 0) {
					File.WriteAllBytes(filePath, destination.EncodeToPNG());
					AssetDatabase.Refresh();
				}
			}
			
			GUILayout.EndArea();

			if (destination != null) {
				scrollPosition = GUI.BeginScrollView(
				new Rect(224f, 2f, position.width - 226f, position.height - 4f),
				scrollPosition,
				new Rect(0f, 0f, destination.width, destination.height));
				EditorGUI.DrawTextureAlpha(new Rect(0f, 0f, destination.width, destination.height), destination);
				GUI.EndScrollView();
			}
		}
        private void OnGUI()
        {
            GUILayout.BeginArea(new Rect(2f, 2f, 220f, position.height - 4f));

            EditorGUI.BeginChangeCheck();
            source = (Texture2D)EditorGUILayout.ObjectField(sourceTextureContent, source, typeof(Texture2D), false);
            if (EditorGUI.EndChangeCheck())
            {
                DestroyImmediate(destination);
                allowSave = false;
            }

            EditorGUI.BeginChangeCheck();
            rgbFillMode = (RGBFillMode)EditorGUILayout.EnumPopup(rgbFillModeContent, rgbFillMode);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetInt(rgbModeKey, (int)rgbFillMode);
                allowSave = false;
            }

            EditorGUI.BeginChangeCheck();
            insideDistance = EditorGUILayout.FloatField(insideContent, insideDistance);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetFloat(insideDistanceKey, insideDistance);
                allowSave = false;
            }

            EditorGUI.BeginChangeCheck();
            outsideDistance = EditorGUILayout.FloatField(outsideContent, outsideDistance);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetFloat(outsideDistanceKey, outsideDistance);
                allowSave = false;
            }

            EditorGUI.BeginChangeCheck();
            postProcessDistance = EditorGUILayout.FloatField(postprocessContent, postProcessDistance);
            if (EditorGUI.EndChangeCheck())
            {
                EditorPrefs.SetFloat(postProcessDistanceKey, postProcessDistance);
                allowSave = false;
            }

            if (source != null && GUILayout.Button("Generate"))
            {
                Generate();
            }

            if (allowSave && GUILayout.Button("Save PNG file"))
            {
                string filePath = EditorUtility.SaveFilePanel(
                    "Save Signed Distance Field",
                    new FileInfo(AssetDatabase.GetAssetPath(source)).DirectoryName,
                    source.name + " SDF",
                    "png");
                if (filePath.Length > 0)
                {
                    File.WriteAllBytes(filePath, destination.EncodeToPNG());
                    AssetDatabase.Refresh();
                }
            }

            GUILayout.EndArea();

            if (destination != null)
            {
                scrollPosition = GUI.BeginScrollView(
                    new Rect(224f, 2f, position.width - 226f, position.height - 4f),
                    scrollPosition,
                    new Rect(0f, 0f, destination.width, destination.height));
                EditorGUI.DrawTextureAlpha(new Rect(0f, 0f, destination.width, destination.height), destination);
                GUI.EndScrollView();
            }
        }