diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index e967995..0000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-patreon: zigurous
-custom: zigurous.com
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
deleted file mode 100644
index 856609e..0000000
--- a/.github/workflows/docs.yml
+++ /dev/null
@@ -1,61 +0,0 @@
-name: Docs
-
-on:
- push:
- branches:
- - main
-
-jobs:
- docs:
- name: Docs
- runs-on: windows-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v2
- with:
- submodules: true
- token: ${{ secrets.DOCS_TOKEN }}
-
- - name: Setup dotnet
- uses: actions/setup-dotnet@v1
- with:
- dotnet-version: 3.1.x
-
- - name: Setup docfx
- uses: crazy-max/ghaction-chocolatey@v1
- with:
- args: install docfx
-
- - name: Setup node
- uses: actions/setup-node@v2
- with:
- node-version: '14'
-
- - name: Install dependencies
- working-directory: docs~
- run: npm install
- env:
- NPM_TOKEN: ${{ secrets.DOCS_TOKEN }}
-
- - name: Generate metadata
- working-directory: docs~
- run: npm run-script docfx
- env:
- NPM_TOKEN: ${{ secrets.DOCS_TOKEN }}
-
- - name: Build docs
- working-directory: docs~
- continue-on-error: false
- run: npm run-script build
- env:
- NPM_TOKEN: ${{ secrets.DOCS_TOKEN }}
-
- - name: Publish
- if: github.event_name == 'push'
- uses: peaceiris/actions-gh-pages@v3
- with:
- personal_token: ${{ secrets.DOCS_TOKEN }}
- external_repository: zigurous/docs
- destination_dir: com.zigurous.graphics
- publish_dir: docs~/public
- publish_branch: main
diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml
new file mode 100644
index 0000000..983e0ab
--- /dev/null
+++ b/.github/workflows/generate-docs.yml
@@ -0,0 +1,23 @@
+name: Generate Docs
+
+on:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ generate:
+ name: Docs
+ uses: zigurous/docs/.github/workflows/unity-package.yml@main
+ with:
+ package_title: "Graphics Utils"
+ package_base_path: com.zigurous.graphics
+ package_workflow: generate-docs.yml
+ package_artifact: docs
+ secrets:
+ token: ${{ secrets.DOCS_TOKEN }}
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 76f97e0..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,4 +0,0 @@
-[submodule "docs~"]
- path = docs~
- url = https://github.com/zigurous/docjs
- branch = com.zigurous.graphics
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72bb985..1070fdd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.4.0] - 2023/06/19
+
+### Added
+
+- New `MeshGenerator` static class to generate procedural meshes
+- New `Triangulator` static class to split polygons into triangles
+- New `HiddenMaterialPropertyDrawer` attribute to hide material properties
+- New `Mesh.RecalculateUV` extension method
+- New texture extension methods
+ - `GetPixelCoordinates`
+ - `GetUVCoordinates`
+ - `Sample(u, v)`
+ - `Sample(rect, point)`
+ - `Sample(bounds, position)`
+ - `SetColor`
+- Context menu added to `SaveMesh` to save directly from the editor
+- Help URLs added to all behaviors
+
+### Changed
+
+- Refactored `TextureDrawer` as a ScriptableObject and a separate `TextureDrawerRenderer` behavior
+- Improved `CombineChildrenMeshes` with better transform matrix, option to set mesh name, and toggle to destroy or disable child game objects
+- Renamed `AutoTile.Submesh` to `AutoTile.SubmeshTiling`
+- Formatting changes
+
+### Removed
+
+- `ShaderProperty` and `AnimatedShaderProperty` (moved to AnimationLibrary package)
+
## [0.3.0] - 2021/11/14
### Added
diff --git a/Documentation~/articles/custom-meshes.md b/Documentation~/articles/custom-meshes.md
new file mode 100644
index 0000000..adf438f
--- /dev/null
+++ b/Documentation~/articles/custom-meshes.md
@@ -0,0 +1,61 @@
+---
+slug: "/manual/custom-meshes"
+---
+
+# Custom Meshes
+
+The **Graphics Utils** package includes a few custom cube meshes.
+
+- `Cube-3.mesh`: cube mesh with 3 submeshes (one for each axis)
+- `Cube-6.mesh`: cube mesh with 6 submeshes (one for each face)
+- `Cube-Inverted.mesh`: cube mesh with inverted normals and triangles (inside-out)
+- `Cube-Tiling.mesh` cube mesh designed specifically for [Material Tiling](/manual/material-tiling)
+
+There are also 3 different scripts to generate these cube meshes at runtime:
+
+- [CubeMesh](/api/Zigurous.Graphics/CubeMesh)
+- [CubeMesh3](/api/Zigurous.Graphics/CubeMesh3)
+- [CubeMesh6](/api/Zigurous.Graphics/CubeMesh6)
+
+
+
+## ⭕ Inverting Meshes
+
+Sometimes it is useful to invert a mesh so it renders inside out. This is especially useful for cubes. Inverting a mesh flips the triangles and the normals. The **Graphics Utils** package comes with an [InvertMesh](/api/Zigurous.Graphics/InvertMesh) script that handles this automatically.
+
+You can also manually invert the normals and triangles of a mesh using extension methods:
+
+```csharp
+mesh.InvertNormals();
+mesh.InvertTriangles();
+
+// Returns the inverted values without changing the actual mesh
+Vector3[] normals = mesh.InvertedNormals();
+int[] triangles = mesh.InvertedTriangles();
+```
+
+
+
+## 🔰 Combining Meshes
+
+The **Graphics Utils** package includes a script to combine multiple meshes into a single mesh. This can be used to improve rendering performance, or as a way to create custom meshes and turn them into assets. Add the [CombineChildrenMeshes](/api/Zigurous.Graphics/CombineChildrenMeshes) script to the parent game object of children meshes. The combined mesh will be assigned to the mesh filter of the parent object, and the child game objects will either be destroyed or disabled.
+
+You can also manually combine meshes through an extension method:
+
+```csharp
+MeshFilter[] filters = GetComponentsInChildren();
+Mesh combinedMesh = filters.CombineMesh();
+```
+
+
+
+## 💾 Saving Meshes
+
+Often when generating meshes at runtime, you may want to save that mesh as an asset for future use so you don't need to regenerate them again. The **Graphics Utils** package comes with a [SaveMesh](/api/Zigurous.Graphics/SaveMesh) script that will save a mesh as an asset at runtime.
+
+You can also manually save a mesh through extension methods:
+
+```csharp
+mesh.Save("Custom");
+meshFilter.SaveMesh("Custom");
+```
diff --git a/Documentation~/articles/extension-methods.md b/Documentation~/articles/extension-methods.md
new file mode 100644
index 0000000..2ebbc17
--- /dev/null
+++ b/Documentation~/articles/extension-methods.md
@@ -0,0 +1,15 @@
+---
+slug: "/manual/extension-methods"
+---
+
+# Extension Methods
+
+The **Graphics Utils** package contains dozens of extension methods to provide enhanced support for common Unity classes. See each Scripting API for more information:
+
+#### [Material](/api/Zigurous.Architecture/MaterialExtensions)
+
+#### [Mesh](/api/Zigurous.Architecture/MeshExtensions)
+
+#### [MeshFilter](/api/Zigurous.Architecture/MeshFilterExtensions)
+
+#### [Texture](/api/Zigurous.Architecture/TextureExtensions)
diff --git a/Documentation~/articles/index.md b/Documentation~/articles/index.md
new file mode 100644
index 0000000..4264f24
--- /dev/null
+++ b/Documentation~/articles/index.md
@@ -0,0 +1,33 @@
+---
+slug: "/manual"
+---
+
+# Graphics Utils
+
+The **Graphics Utils** package provides scripts and utilities for graphics and rendering purposes in Unity projects. The package is still early in development, and more functionality will be added over time. Let us know what other features you would like to see.
+
+
+
+## Overview
+
+#### ⚙️ [Installation](/installation)
+
+#### 🧰 [Scripting API](/api/Zigurous.Graphics)
+
+#### 📋 [Changelog](/changelog)
+
+#### ⚖️ [License](/license)
+
+
+
+## Reference
+
+#### 🔰 [Custom Meshes](/manual/custom-meshes)
+
+#### ⛰️ [Procedural Generation](/manual/procedural-generation)
+
+#### 🛤️ [Material Tiling](/manual/material-tiling)
+
+#### 🖼️ [Texture Drawers](/manual/texture-drawers)
+
+#### 🔌 [Extension Methods](/manual/extension-methods)
diff --git a/Documentation~/articles/installation.md b/Documentation~/articles/installation.md
new file mode 100644
index 0000000..f4a7db6
--- /dev/null
+++ b/Documentation~/articles/installation.md
@@ -0,0 +1,34 @@
+---
+slug: "/installation"
+---
+
+# Installation
+
+Use the Unity [Package Manager](https://docs.unity3d.com/Manual/upm-ui.html) to install the **Graphics Utils** package.
+
+1. Open the Package Manager in `Window > Package Manager`
+2. Click the add (`+`) button in the status bar
+3. Select `Add package from git URL` from the add menu
+4. Enter the following Git URL in the text box and click Add:
+
+```http
+https://github.com/zigurous/unity-graphics-utils.git
+```
+
+
+
+## 🏷️ Namespace
+
+Import the package namespace in each script or file you want to use it. You may need to regenerate project files/assemblies first.
+
+```csharp
+using Zigurous.Graphics;
+```
+
+
+
+## 💻 Source Code
+
+The source code for the **Graphics Utils** package is in the following repository:
+
+- https://github.com/zigurous/unity-graphics-utils
diff --git a/Documentation~/articles/material-tiling.md b/Documentation~/articles/material-tiling.md
new file mode 100644
index 0000000..5a8325c
--- /dev/null
+++ b/Documentation~/articles/material-tiling.md
@@ -0,0 +1,17 @@
+---
+slug: "/manual/material-tiling"
+---
+
+# Material Tiling
+
+One of the most powerful features included in the **Graphics Utils** package is the ability to auto tile materials based on the object's scale. In doing so, new materials are created that are unique to the object. This makes the workflow of creating materials for tiled objects effortless. Without this feature, you often end up creating dozens of variants of a material just to change the tiling values for different objects.
+
+Add the [AutoTile](/api/Zigurous.Graphics/AutoTile) script to the object you want to tile. The main property that is usually edited is `submeshes`. Each element in the array indicates how a submesh of the mesh is tiled, such as which axis the object is tiled on, the unit scale of the object, the texture offset, etc. For example, a plane is usually tiled around the Y+ axis, has a unit scale of 10, and only 1 submesh.
+
+
+
+## 🕋 Cube Tiling
+
+When tiling cubes, the [AutoTile](/api/Zigurous.Graphics/AutoTile) script gives the best results when used with the `Cube-Tiling.mesh` asset instead of Unity's default cube mesh. This mesh asset is split into 3 separate submeshes so you can tile each axis independently from the others. The mesh also has custom UV coordinates so the materials are tiled from the center of each axis. Using the custom tiling mesh, the script should be set up with 3 submeshes tiled around the X+, Y+, and Z+ axis, respectively, and the unit scale set to 1.
+
+
diff --git a/Documentation~/articles/procedural-generation.md b/Documentation~/articles/procedural-generation.md
new file mode 100644
index 0000000..c4a173f
--- /dev/null
+++ b/Documentation~/articles/procedural-generation.md
@@ -0,0 +1,38 @@
+---
+slug: "/manual/procedural-generation"
+---
+
+# Procedural Generation
+
+The **Graphics Utils** package provides a utility class to generate procedural meshes at runtime. For example, use the [MeshGenerator](/api/Zigurous.Graphics/MeshGenerator) class to create a new procedural mesh that forms a grid of points.
+
+```csharp
+Mesh mesh = MeshGenerator.Create(64, 64);
+```
+
+This is a useful starting point to create more complex meshes, such as procedural terrain. The [MeshGenerator](/api/Zigurous.Graphics/MeshGenerator) class allows you to provide your own custom vertex generation function to create these more complex meshes.
+
+```csharp
+void GenerateTerrain()
+{
+ Mesh terrain = MeshGenerator.Create(64, 64, VertexGenerator);
+}
+
+void VertexGenerator(int x, int y, float u, float v)
+{
+ // sample terrain height using a noise function
+ float height = Mathf.PerlinNoise(x, y);
+ return new Vector3(x, height, y);
+}
+```
+
+
+
+## 💎 Triangulation
+
+Sometimes it is useful to split a polygon into triangles in order to generate a custom mesh for the polygon. The [Triangulator](/api/Zigurous.Graphics/Triangulator) class provides this utility. Pass in the points that form the polygon, and the indices of the triangles will be returned.
+
+```csharp
+Vector2[] polygon; // array of points that form a polygon
+int[] triangles = Triangulator.Triangulate(polygon);
+```
diff --git a/Documentation~/articles/texture-drawers.md b/Documentation~/articles/texture-drawers.md
new file mode 100644
index 0000000..40c62d7
--- /dev/null
+++ b/Documentation~/articles/texture-drawers.md
@@ -0,0 +1,38 @@
+---
+slug: "/manual/texture-drawers"
+---
+
+# Texture Drawers
+
+The **Graphics Utils** package includes a base class for drawing textures at runtime. It provides the boilerplate code for creating and drawing new textures programmatically.
+
+Create a new class that inherits from [TextureDrawer](/api/Zigurous.Graphics/TextureDrawer) and override the function `SetPixels(Texture2D)` to complete the implementation.
+
+Since [TextureDrawer](/api/Zigurous.Graphics/TextureDrawer) is a ScriptableObject, you'll want to add the `[CreateAssetMenu]` attribute to your class so you can save an instance of the class as an asset in your project using Unity's asset menu.
+
+```csharp
+[CreateAssetMenu]
+public class CustomTextureDrawer : TextureDrawer
+{
+ public override void SetPixels(Texture2D texture)
+ {
+ // Handle setting the pixel colors here...
+ }
+}
+```
+
+
+
+## 🖼️ Rendering
+
+The **Graphics Utils** package comes with a script to quickly render the result of a [TextureDrawer](/api/Zigurous.Graphics/TextureDrawer). This is an optional, but useful script to preview the texture without having to write any other code to manually assign the texture to a material.
+
+Add the [TextureDrawerRenderer](/api/Zigurous.Graphics/TextureDrawerRenderer) script to any game object that contains any type of Renderer component. Assign the texture drawer you want to use and customize any other options you'd like. You can even render the texture in the editor without having to run the game.
+
+
+
+## 🏁 Checkerboard
+
+The **Graphics Utils** package includes a script [CheckerboardTextureDrawer](/api/Zigurous.Graphics/CheckerboardTextureDrawer) as a sample implementation. It is, of course, a fully functional script that draws a checkerboard pattern. This can be used however you desire, and there are even a number of customization options available.
+
+To create a new checkerboard pattern texture, use the asset menu `Create > Zigurous > Graphics > Checkerboard Texture Drawer`.
diff --git a/Documentation~/data/header.json b/Documentation~/data/header.json
new file mode 100644
index 0000000..a2cc351
--- /dev/null
+++ b/Documentation~/data/header.json
@@ -0,0 +1,18 @@
+[
+ {
+ "name": "Manual",
+ "path": "/manual"
+ },
+ {
+ "name": "Scripting API",
+ "path": "/api"
+ },
+ {
+ "name": "Changelog",
+ "path": "/changelog"
+ },
+ {
+ "name": "License",
+ "path": "/license"
+ }
+]
diff --git a/Documentation~/data/sidenav.json b/Documentation~/data/sidenav.json
new file mode 100644
index 0000000..a7cfdd1
--- /dev/null
+++ b/Documentation~/data/sidenav.json
@@ -0,0 +1,88 @@
+[
+ {
+ "title": "📌 Overview",
+ "items": [
+ {
+ "name": "Getting Started",
+ "path": "/manual"
+ },
+ {
+ "name": "Installation",
+ "path": "/installation"
+ },
+ {
+ "name": "Changelog",
+ "path": "/changelog"
+ },
+ {
+ "name": "License",
+ "path": "/license"
+ }
+ ]
+ },
+ {
+ "title": "📖 Reference",
+ "items": [
+ {
+ "name": "Custom Meshes",
+ "path": "/manual/custom-meshes"
+ },
+ {
+ "name": "Procedural Generation",
+ "path": "/manual/procedural-generation"
+ },
+ {
+ "name": "Material Tiling",
+ "path": "/manual/material-tiling"
+ },
+ {
+ "name": "Texture Drawers",
+ "path": "/manual/texture-drawers"
+ },
+ {
+ "name": "Extension Methods",
+ "path": "/manual/extension-methods"
+ }
+ ]
+ },
+ {
+ "title": "💬 Contact",
+ "items": [
+ {
+ "name": "Discord",
+ "href": "https://discord.gg/DdYyWVb",
+ "icon": "launch"
+ },
+ {
+ "name": "Twitter",
+ "href": "https://twitter.com/zigurous",
+ "icon": "launch"
+ }
+ ]
+ },
+ {
+ "title": "🔗 Other Links",
+ "items": [
+ {
+ "name": "GitHub",
+ "href": "https://github.com/zigurous/unity-graphics-utils",
+ "icon": "launch"
+ },
+ {
+ "name": "Asset Store",
+ "href": "https://assetstore.unity.com/publishers/51884",
+ "icon": "launch"
+ },
+ {
+ "name": "YouTube",
+ "href": "https://youtube.com/c/zigurous?sub_confirmation=1",
+ "icon": "launch"
+ },
+ {
+ "name": "Patreon",
+ "href": "https://patreon.com/zigurous",
+ "icon": "launch"
+ }
+ ]
+ }
+]
diff --git a/Documentation~/images/tiling.jpg b/Documentation~/images/tiling.jpg
new file mode 100644
index 0000000..f7f58c4
Binary files /dev/null and b/Documentation~/images/tiling.jpg differ
diff --git a/Editor/HiddenMaterialPropertyDrawer.cs b/Editor/HiddenMaterialPropertyDrawer.cs
new file mode 100644
index 0000000..f6bb9c6
--- /dev/null
+++ b/Editor/HiddenMaterialPropertyDrawer.cs
@@ -0,0 +1,17 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace Zigurous.Graphics.Editor
+{
+ public sealed class HiddenMaterialPropertyDrawer : MaterialPropertyDrawer
+ {
+ public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) {}
+
+ public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor)
+ {
+ return -EditorGUIUtility.standardVerticalSpacing;
+ }
+
+ }
+
+}
diff --git a/Editor/ShaderPropertyPropertyDrawer.cs.meta b/Editor/HiddenMaterialPropertyDrawer.cs.meta
similarity index 83%
rename from Editor/ShaderPropertyPropertyDrawer.cs.meta
rename to Editor/HiddenMaterialPropertyDrawer.cs.meta
index 59ec774..83582e5 100644
--- a/Editor/ShaderPropertyPropertyDrawer.cs.meta
+++ b/Editor/HiddenMaterialPropertyDrawer.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: cb6df95fcbc802f408a71ed0688373cc
+guid: 7487b70c78507b64fa1642a570f69200
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Editor/ShaderPropertyPropertyDrawer.cs b/Editor/ShaderPropertyPropertyDrawer.cs
deleted file mode 100644
index f74e01b..0000000
--- a/Editor/ShaderPropertyPropertyDrawer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using UnityEditor;
-using UnityEngine;
-
-namespace Zigurous.Graphics.Editor
-{
- [CustomPropertyDrawer(typeof(ShaderProperty))]
- public sealed class ShaderPropertyPropertyDrawer : PropertyDrawer
- {
- public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
- {
- SerializedProperty id = property.FindPropertyRelative("m_Id");
- SerializedProperty name = property.FindPropertyRelative("m_Name");
-
- EditorGUI.BeginProperty(position, label, property);
- position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
-
- string value = EditorGUI.TextField(position, name.stringValue);
-
- if (value != name.stringValue)
- {
- name.stringValue = value;
- id.intValue = Shader.PropertyToID(value);
- }
-
- EditorGUI.EndProperty();
- }
-
- }
-
-}
diff --git a/README.md b/README.md
index 58191e9..527b510 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,11 @@ The **Graphics Utils** package provides scripts and utilities for graphics and r
## Reference
-- [Auto Tiling](https://docs.zigurous.com/com.zigurous.graphics/manual/material-tiling)
- [Custom Meshes](https://docs.zigurous.com/com.zigurous.graphics/manual/custom-meshes)
-- [Shader Properties](https://docs.zigurous.com/com.zigurous.graphics/manual/shader-properties)
+- [Procedural Generation](https://docs.zigurous.com/com.zigurous.graphics/manual/procedural-generation)
+- [Material Tiling](https://docs.zigurous.com/com.zigurous.graphics/manual/material-tiling)
- [Texture Drawers](https://docs.zigurous.com/com.zigurous.graphics/manual/texture-drawers)
+- [Extension Methods](https://docs.zigurous.com/com.zigurous.graphics/manual/extension-methods)
## Installation
@@ -20,7 +21,7 @@ Use the Unity [Package Manager](https://docs.unity3d.com/Manual/upm-ui.html) to
3. Select `Add package from git URL` from the add menu
4. Enter the following Git URL in the text box and click Add:
-```http
+```
https://github.com/zigurous/unity-graphics-utils.git
```
diff --git a/Runtime/AnimatedShaderProperty.cs b/Runtime/AnimatedShaderProperty.cs
deleted file mode 100644
index b5197ec..0000000
--- a/Runtime/AnimatedShaderProperty.cs
+++ /dev/null
@@ -1,158 +0,0 @@
-using System.Collections.Generic;
-using UnityEngine;
-
-namespace Zigurous.Graphics
-{
- ///
- /// A shader property that can be animated.
- ///
- [System.Serializable]
- public abstract class AnimatedShaderProperty
- {
- ///
- /// The shader property to animate.
- ///
- [Tooltip("The shader property to animate.")]
- public ShaderProperty property;
-
- ///
- /// Creates a new animated shader property.
- ///
- /// The shader property to animate.
- public AnimatedShaderProperty(string property)
- {
- this.property = property;
- }
-
- ///
- /// Animates the shader property.
- ///
- /// The material to animate.
- /// The time of the animation to evaluate.
- public abstract void Animate(Material material, float time);
-
- }
-
- ///
- /// A shader float property that can be animated.
- ///
- [System.Serializable]
- public class AnimatedShaderFloatProperty : AnimatedShaderProperty
- {
- ///
- /// The value over time of the shader property.
- ///
- [Tooltip("The value over time of the shader property.")]
- public AnimationCurve valueOverTime;
-
- ///
- /// Creates a new animated shader float property.
- ///
- /// The value over time of the shader property.
- /// The shader property to animate.
- public AnimatedShaderFloatProperty(AnimationCurve valueOverTime, string property) : base(property)
- {
- this.valueOverTime = valueOverTime;
- }
-
- ///
- public override void Animate(Material material, float time)
- {
- material.SetFloat(property.id, valueOverTime.Evaluate(time));
- }
-
- }
-
- ///
- /// A shader int property that can be animated.
- ///
- [System.Serializable]
- public class AnimatedShaderIntProperty : AnimatedShaderProperty
- {
- ///
- /// The value over time of the shader property.
- ///
- [Tooltip("The value over time of the shader property.")]
- public AnimationCurve valueOverTime;
-
- ///
- /// Creates a new animated shader int property.
- ///
- /// The value over time of the shader property.
- /// The shader property to animate.
- public AnimatedShaderIntProperty(AnimationCurve valueOverTime, string property) : base(property)
- {
- this.valueOverTime = valueOverTime;
- }
-
- ///
- public override void Animate(Material material, float time)
- {
- material.SetInt(property.id, (int)valueOverTime.Evaluate(time));
- }
-
- }
-
- ///
- /// A shader color property that can be animated.
- ///
- [System.Serializable]
- public class AnimatedShaderColorProperty : AnimatedShaderProperty
- {
- ///
- /// The color over time of the shader property.
- ///
- public Gradient colorOverTime;
-
- ///
- /// Creates a new animated shader color property.
- ///
- /// The color over time of the shader property.
- /// The shader property to animate.
- public AnimatedShaderColorProperty(Gradient colorOverTime, string property) : base(property)
- {
- this.colorOverTime = colorOverTime;
- }
-
- ///
- public override void Animate(Material material, float time)
- {
- material.SetColor(property.id, colorOverTime.Evaluate(time));
- }
-
- }
-
- ///
- /// Extension methods for .
- ///
- public static class AnimatedShaderPropertyExtensions
- {
- ///
- /// Animates an array of shader properties.
- ///
- /// The shader properties to animate.
- /// The material to animate.
- /// The time of the animation to evaluate.
- public static void Animate(this AnimatedShaderProperty[] properties, Material material, float time)
- {
- for (int i = 0; i < properties.Length; i++) {
- properties[i].Animate(material, time);
- }
- }
-
- ///
- /// Animates an array of shader properties.
- ///
- /// The shader properties to animate.
- /// The material to animate.
- /// The time of the animation to evaluate.
- public static void Animate(this List properties, Material material, float time)
- {
- foreach (AnimatedShaderProperty property in properties) {
- property.Animate(material, time);
- }
- }
-
- }
-
-}
diff --git a/Runtime/AutoTile.cs b/Runtime/AutoTile.cs
index 7a1eb0a..3a0f922 100644
--- a/Runtime/AutoTile.cs
+++ b/Runtime/AutoTile.cs
@@ -1,17 +1,22 @@
#if UNITY_EDITOR
using UnityEditor;
+#if UNITY_2021_2_OR_NEWER
+using UnityEditor.SceneManagement;
+#else
using UnityEditor.Experimental.SceneManagement;
#endif
+#endif
using UnityEngine;
namespace Zigurous.Graphics
{
///
- /// Automatically tiles the material textures based on the object's scale.
+ /// Automatically tiles the material's textures based on the object's scale.
///
[ExecuteAlways]
- [RequireComponent(typeof(Renderer))]
[AddComponentMenu("Zigurous/Graphics/Auto Tile")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/AutoTile")]
+ [RequireComponent(typeof(Renderer))]
public sealed class AutoTile : MonoBehaviour
{
///
@@ -54,7 +59,7 @@ public enum Axis
/// A representation of a submesh that can be individually tiled.
///
[System.Serializable]
- public sealed class Submesh
+ public sealed class SubmeshTiling
{
#if UNITY_EDITOR
///
@@ -98,7 +103,7 @@ public sealed class Submesh
/// The submeshes that are tiled on the renderer.
///
[Tooltip("The submeshes that are tiled on the renderer.")]
- public Submesh[] submeshes = new Submesh[1] { new Submesh() };
+ public SubmeshTiling[] submeshes = new SubmeshTiling[1] { new SubmeshTiling() };
///
/// The names of the textures that are tiled on the material.
@@ -131,11 +136,11 @@ private void Reset()
if (mesh != null)
{
- submeshes = new Submesh[mesh.subMeshCount];
+ submeshes = new SubmeshTiling[mesh.subMeshCount];
for (int i = 0; i < submeshes.Length; i++)
{
- Submesh submesh = new Submesh();
+ SubmeshTiling submesh = new SubmeshTiling();
submesh.submeshIndex = i;
submeshes[i] = submesh;
}
@@ -199,7 +204,7 @@ private void UpdateMaterials(Material[] materials)
{
for (int i = 0; i < submeshes.Length; i++)
{
- Submesh submesh = submeshes[i];
+ SubmeshTiling submesh = submeshes[i];
if (submesh.submeshIndex >= 0 && submesh.submeshIndex < materials.Length) {
UpdateMaterial(materials[submesh.submeshIndex], submesh);
@@ -212,7 +217,7 @@ private void UpdateMaterialsInEditor(Material[] materials)
{
for (int i = 0; i < submeshes.Length; i++)
{
- Submesh submesh = submeshes[i];
+ SubmeshTiling submesh = submeshes[i];
if (submesh.submeshIndex >= 0 && submesh.submeshIndex < materials.Length)
{
@@ -236,7 +241,7 @@ private void UpdateMaterialsInEditor(Material[] materials)
}
#endif
- private void UpdateMaterial(Material material, Submesh submesh)
+ private void UpdateMaterial(Material material, SubmeshTiling submesh)
{
if (material == null || textureNames == null) {
return;
diff --git a/Runtime/CheckerboardTextureDrawer.cs b/Runtime/CheckerboardTextureDrawer.cs
index 5ab26b3..13dd385 100644
--- a/Runtime/CheckerboardTextureDrawer.cs
+++ b/Runtime/CheckerboardTextureDrawer.cs
@@ -3,75 +3,48 @@
namespace Zigurous.Graphics
{
///
- /// Draws a texture of a checkerboard pattern.
+ /// Draws a checkerboard pattern texture.
///
- [AddComponentMenu("Zigurous/Graphics/Checkerboard Texture Drawer")]
+ [CreateAssetMenu(menuName = "Zigurous/Graphics/Checkerboard Texture Drawer")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/CheckerboardTextureDrawer")]
public sealed class CheckerboardTextureDrawer : TextureDrawer
{
///
- /// The checkerboard settings of a .
+ /// The number of rows in the checkerboard.
///
- [System.Serializable]
- public struct CheckerboardSettings
- {
- ///
- /// The number of rows in the checkerboard.
- ///
- [Tooltip("The number of rows in the checkerboard.")]
- public int rows;
-
- ///
- /// The number of columns in the checkerboard.
- ///
- [Tooltip("The number of columns in the checkerboard.")]
- public int columns;
-
- ///
- /// The first color of the checkerboard.
- ///
- [Tooltip("The first color of the checkerboard.")]
- public Color colorA;
+ [Header("Checkerboard Settings")]
+ [Tooltip("The number of rows in the checkerboard.")]
+ public int rows = 4;
- ///
- /// The second color of the checkerboard.
- ///
- [Tooltip("The second color of the checkerboard.")]
- public Color colorB;
-
- ///
- /// Creates new checkerboard settings with the specified values.
- ///
- /// The number of rows in the checkerboard.
- /// The number of columns in the checkerboard.
- /// The first color of the checkerboard.
- /// The second color of the checkerboard.
- public CheckerboardSettings(int rows, int columns, Color colorA, Color colorB)
- {
- this.rows = rows;
- this.columns = columns;
- this.colorA = colorA;
- this.colorB = colorB;
- }
+ ///
+ /// The number of columns in the checkerboard.
+ ///
+ [Tooltip("The number of columns in the checkerboard.")]
+ public int columns = 4;
- }
+ ///
+ /// The first color of the checkerboard.
+ ///
+ [Tooltip("The first color of the checkerboard.")]
+ public Color colorA = Color.white;
///
- /// The checkerboard settings.
+ /// The second color of the checkerboard.
///
- [Tooltip("The checkerboard settings.")]
- public CheckerboardSettings checkerboard = new CheckerboardSettings(4, 4, Color.white, Color.black);
+ [Tooltip("The second color of the checkerboard.")]
+ public Color colorB = Color.black;
///
- protected override void SetPixels(Texture2D texture)
+ public override void SetPixels(Texture2D texture)
{
- int rectWidth = texture.width / checkerboard.columns;
- int rectHeight = texture.height / checkerboard.rows;
+ int rectWidth = texture.width / columns;
+ int rectHeight = texture.height / rows;
- for (int row = 0; row < checkerboard.rows; row++)
+ for (int row = 0; row < rows; row++)
{
- for (int col = 0; col < checkerboard.columns; col++)
+ for (int col = 0; col < columns; col++)
{
- Color color = (row + col) % 2 == 0 ? checkerboard.colorA : checkerboard.colorB;
+ Color color = (row + col) % 2 == 0 ? colorA : colorB;
int positionX = col * rectWidth;
int positionY = row * rectHeight;
@@ -87,19 +60,6 @@ protected override void SetPixels(Texture2D texture)
}
}
- protected override void OnValidate()
- {
- base.OnValidate();
-
- if (checkerboard.rows < 2) {
- checkerboard.rows = 2;
- }
-
- if (checkerboard.columns < 2) {
- checkerboard.columns = 2;
- }
- }
-
}
}
diff --git a/Runtime/CombineChildrenMeshes.cs b/Runtime/CombineChildrenMeshes.cs
index 33d72c1..5cb5fc7 100644
--- a/Runtime/CombineChildrenMeshes.cs
+++ b/Runtime/CombineChildrenMeshes.cs
@@ -3,13 +3,19 @@
namespace Zigurous.Graphics
{
///
- /// Combines the meshes of the children of the game object into one mesh.
+ /// Combines children meshes into one mesh.
///
- [RequireComponent(typeof(MeshFilter))]
- [RequireComponent(typeof(MeshRenderer))]
[AddComponentMenu("Zigurous/Graphics/Combine Children Meshes")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/CombineChildrenMeshes")]
+ [RequireComponent(typeof(MeshFilter))]
public sealed class CombineChildrenMeshes : MonoBehaviour
{
+ ///
+ /// The name of the combined mesh.
+ ///
+ [Tooltip("The name of the combined mesh.")]
+ public string combinedMeshName = "Combined Mesh";
+
///
/// Combines the mesh on start, otherwise it needs to be called manually.
///
@@ -17,10 +23,10 @@ public sealed class CombineChildrenMeshes : MonoBehaviour
public bool combineOnStart = true;
///
- /// Removes the child meshes from the game object after combining.
+ /// Destroys the child game objects after combining.
///
- [Tooltip("Removes the child meshes from the game object after combining.")]
- public bool removeChildMeshes = true;
+ [Tooltip("Destroys the child game objects after combining.")]
+ public bool deleteChildren = true;
///
/// Combines all of the meshes into a single submesh.
@@ -40,6 +46,11 @@ public sealed class CombineChildrenMeshes : MonoBehaviour
[Tooltip("Recalculates the bounding volume of the combined mesh.")]
public bool recalculateBounds = true;
+ private void Reset()
+ {
+ enabled = false;
+ }
+
private void Start()
{
MeshFilter parent = GetComponent();
@@ -56,7 +67,7 @@ private void Start()
public Mesh Combine()
{
MeshFilter[] children = GetComponentsInChildren();
- CombineInstance[] combine = new CombineInstance[children.Length - 1];
+ CombineInstance[] combine = new CombineInstance[children.Length];
int submesh = 0;
@@ -64,28 +75,27 @@ public Mesh Combine()
{
MeshFilter child = children[i];
- // Ignore the parent mesh
- if (child.transform == transform) {
+ if (child.mesh == null) {
continue;
}
- // Create a mesh combine instance
CombineInstance instance = new CombineInstance();
instance.mesh = child.mesh;
- instance.transform = Matrix4x4.TRS(child.transform.localPosition, child.transform.localRotation, child.transform.localScale);
+ instance.transform = child.transform.localToWorldMatrix;
combine[submesh++] = instance;
- // Destroy the child mesh
- if (removeChildMeshes)
+ if (child.transform != this.transform)
{
- Destroy(child.GetComponent());
- Destroy(child);
+ if (deleteChildren) {
+ Destroy(child.gameObject);
+ } else {
+ child.gameObject.SetActive(false);
+ }
}
}
- // Create a new mesh from all of the combined children
Mesh combinedMesh = new Mesh();
- combinedMesh.name = "Combined Mesh";
+ combinedMesh.name = combinedMeshName;
combinedMesh.CombineMeshes(combine, mergeSubmeshes);
if (optimizeMesh) {
diff --git a/Runtime/CubeMesh.cs b/Runtime/CubeMesh.cs
index 8f97076..fb958f8 100644
--- a/Runtime/CubeMesh.cs
+++ b/Runtime/CubeMesh.cs
@@ -6,8 +6,9 @@ namespace Zigurous.Graphics
/// Generates a new cube mesh and applies it to the mesh filter.
///
[ExecuteAlways]
- [RequireComponent(typeof(MeshFilter))]
[AddComponentMenu("Zigurous/Graphics/Cube Mesh")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/CubeMesh")]
+ [RequireComponent(typeof(MeshFilter))]
public sealed class CubeMesh : MonoBehaviour
{
private static Mesh m_SharedMesh;
diff --git a/Runtime/CubeMesh3.cs b/Runtime/CubeMesh3.cs
index 7b533cb..8c02acc 100644
--- a/Runtime/CubeMesh3.cs
+++ b/Runtime/CubeMesh3.cs
@@ -7,8 +7,9 @@ namespace Zigurous.Graphics
/// applies it to the mesh filter.
///
[ExecuteAlways]
- [RequireComponent(typeof(MeshFilter))]
[AddComponentMenu("Zigurous/Graphics/Cube Mesh 3")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/CubeMesh3")]
+ [RequireComponent(typeof(MeshFilter))]
public sealed class CubeMesh3 : MonoBehaviour
{
///
diff --git a/Runtime/CubeMesh6.cs b/Runtime/CubeMesh6.cs
index 96286c0..3625ca4 100644
--- a/Runtime/CubeMesh6.cs
+++ b/Runtime/CubeMesh6.cs
@@ -7,8 +7,9 @@ namespace Zigurous.Graphics
/// applies it to the mesh filter.
///
[ExecuteAlways]
- [RequireComponent(typeof(MeshFilter))]
[AddComponentMenu("Zigurous/Graphics/Cube Mesh 6")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/CubeMesh6")]
+ [RequireComponent(typeof(MeshFilter))]
public sealed class CubeMesh6 : MonoBehaviour
{
///
diff --git a/Runtime/Extensions/MaterialExtensions.cs b/Runtime/Extensions/MaterialExtensions.cs
index e9b74db..032faf9 100644
--- a/Runtime/Extensions/MaterialExtensions.cs
+++ b/Runtime/Extensions/MaterialExtensions.cs
@@ -19,14 +19,10 @@ public static RenderingMode GetRenderingMode(this Material material)
switch (mode)
{
- case 1:
- return RenderingMode.Cutout;
- case 2:
- return RenderingMode.Fade;
- case 3:
- return RenderingMode.Transparent;
- default:
- return RenderingMode.Opaque;
+ case 1: return RenderingMode.Cutout;
+ case 2: return RenderingMode.Fade;
+ case 3: return RenderingMode.Transparent;
+ default: return RenderingMode.Opaque;
}
}
diff --git a/Runtime/Extensions/MeshExtensions.cs b/Runtime/Extensions/MeshExtensions.cs
index 0b72acb..7456141 100644
--- a/Runtime/Extensions/MeshExtensions.cs
+++ b/Runtime/Extensions/MeshExtensions.cs
@@ -10,7 +10,6 @@ namespace Zigurous.Graphics
///
public static class MeshExtensions
{
- #if UNITY_EDITOR
///
/// Saves the mesh as a project asset (Editor only).
///
@@ -18,11 +17,12 @@ public static class MeshExtensions
/// The name to save the asset as.
public static void Save(this Mesh mesh, string assetName)
{
+ #if UNITY_EDITOR
if (mesh != null) {
- AssetDatabase.CreateAsset(mesh, "Assets/" + assetName + ".mesh");
+ AssetDatabase.CreateAsset(mesh, $"Assets/{assetName}.mesh");
}
+ #endif
}
- #endif
///
/// Returns a new copy of the mesh.
@@ -135,6 +135,24 @@ public static int[] InvertedTriangles(this Mesh mesh, int submesh)
return triangles;
}
+ ///
+ /// Calculates and assigns the UV coordinates of the mesh using its verticies.
+ ///
+ /// The mesh to calculate and assign the UV coordinates to.
+ public static void RecalculateUV(this Mesh mesh)
+ {
+ Bounds bounds = mesh.bounds;
+
+ Vector3[] verticies = mesh.vertices;
+ Vector2[] uvs = new Vector2[verticies.Length];
+
+ for (int i = 0; i < verticies.Length; i++) {
+ uvs[i] = new Vector2(verticies[i].x / bounds.size.x, verticies[i].y / bounds.size.y);
+ }
+
+ mesh.uv = uvs;
+ }
+
}
}
diff --git a/Runtime/Extensions/MeshFilterExtensions.cs b/Runtime/Extensions/MeshFilterExtensions.cs
index 6d518d7..93c89fc 100644
--- a/Runtime/Extensions/MeshFilterExtensions.cs
+++ b/Runtime/Extensions/MeshFilterExtensions.cs
@@ -5,22 +5,29 @@
namespace Zigurous.Graphics
{
+ ///
+ /// Extension methods for mesh filters.
+ ///
public static class MeshFilterExtensions
{
- #if UNITY_EDITOR
///
/// Saves the mesh of the filter as a project asset (Editor only).
///
/// The mesh filter to save the mesh of.
public static void SaveMesh(this MeshFilter filter)
{
- if (filter != null && filter.mesh != null) {
- AssetDatabase.CreateAsset(filter.mesh, "Assets/" + filter.mesh.name + ".mesh");
+ #if UNITY_EDITOR
+ if (filter != null)
+ {
+ if (Application.isPlaying) {
+ AssetDatabase.CreateAsset(filter.mesh, $"Assets/{filter.mesh.name}.mesh");
+ } else {
+ AssetDatabase.CreateAsset(filter.sharedMesh, $"Assets/{filter.mesh.name}.mesh");
+ }
}
+ #endif
}
- #endif
- #if UNITY_EDITOR
///
/// Saves the mesh of the filter as a project asset (Editor only).
///
@@ -28,34 +35,48 @@ public static void SaveMesh(this MeshFilter filter)
/// The name to save the asset as.
public static void SaveMesh(this MeshFilter filter, string assetName)
{
- if (filter != null && filter.mesh != null) {
- AssetDatabase.CreateAsset(filter.mesh, "Assets/" + assetName + ".mesh");
+ #if UNITY_EDITOR
+ if (filter != null)
+ {
+ if (Application.isPlaying) {
+ AssetDatabase.CreateAsset(filter.mesh, $"Assets/{assetName}.mesh");
+ } else {
+ AssetDatabase.CreateAsset(filter.sharedMesh, $"Assets/{assetName}.mesh");
+ }
}
+ #endif
}
- #endif
///
/// Combines the meshes of the mesh filters into one mesh.
///
/// The mesh filters to combine.
+ /// The name of the new combined mesh.
/// Optimizes the combined mesh data to improve rendering performance.
/// Recalculates the bounding volume of the combined mesh.
/// The combined mesh.
- public static Mesh CombineMeshes(this MeshFilter[] filters, bool optimizeMesh = true, bool recalculateBounds = true)
+ public static Mesh CombineMeshes(this MeshFilter[] filters, string combinedMeshName = "Combined Mesh", bool optimizeMesh = true, bool recalculateBounds = true)
{
CombineInstance[] combine = new CombineInstance[filters.Length];
+ int submesh = 0;
+
for (int i = 0; i < filters.Length; i++)
{
- MeshFilter child = filters[i];
+ MeshFilter filter = filters[i];
+
+ if (filter.mesh == null) {
+ continue;
+ }
+
CombineInstance instance = new CombineInstance();
- instance.mesh = child.mesh;
- instance.transform = Matrix4x4.TRS(child.transform.localPosition, child.transform.localRotation, child.transform.localScale);
- combine[i] = instance;
+ instance.mesh = filter.mesh;
+ instance.transform = filter.transform.localToWorldMatrix;
+ combine[submesh++] = instance;
}
Mesh combinedMesh = new Mesh();
- combinedMesh.name = "Combined Mesh";
+ combinedMesh.name = combinedMeshName;
combinedMesh.CombineMeshes(combine);
if (optimizeMesh) {
diff --git a/Runtime/Extensions/TextureExtensions.cs b/Runtime/Extensions/TextureExtensions.cs
new file mode 100644
index 0000000..fbc0bdf
--- /dev/null
+++ b/Runtime/Extensions/TextureExtensions.cs
@@ -0,0 +1,116 @@
+using UnityEngine;
+
+namespace Zigurous.Graphics
+{
+ ///
+ /// Extension methods for textures.
+ ///
+ public static class TextureExtensions
+ {
+ ///
+ /// Maps the UV coordinates in the range [0..1] to pixel coordinates
+ /// in the range [0..width-1] and [0..height-1].
+ ///
+ /// The texture to get the pixel coordinates from.
+ /// The UV coordinate in the x-axis.
+ /// The UV coordinate in the y-axis.
+ /// The output pixel coordinate in the x-axis.
+ /// The output pixel coordinate in the y-axis.
+ public static void GetPixelCoordinates(this Texture2D texture, float u, float v, out int px, out int py)
+ {
+ px = (int)Mathf.Lerp(0, texture.width - 1, u);
+ py = (int)Mathf.Lerp(0, texture.height - 1, v);
+ }
+
+ ///
+ /// Maps the pixel coordinates in the range [0..width-1] and
+ /// [0..height-1] to UV coordinates in the range [0..1].
+ ///
+ /// The texture to get the UV coordinates from.
+ /// The pixel coordinate in the x-axis.
+ /// The pixel coordinate in the y-axis.
+ /// The output UV coordinate in the x-axis.
+ /// The output UV coordinate in the y-axis.
+ public static void GetUVCoordinates(this Texture2D texture, int px, int py, out float u, out float v)
+ {
+ u = Mathf.InverseLerp(0, texture.width - 1, px);
+ v = Mathf.InverseLerp(0, texture.height - 1, py);
+ }
+
+ ///
+ /// Gets the pixel color at the specified UV coordinates.
+ ///
+ /// The texture to sample from.
+ /// The UV coordinate in the x-axis.
+ /// The UV coordinate in the y-axis.
+ /// The pixel color.
+ public static Color Sample(this Texture2D texture, float u, float v)
+ {
+ if (texture == null || texture.width == 0 || texture.height == 0) {
+ return Color.clear;
+ }
+
+ texture.GetPixelCoordinates(u, v, out int px, out int py);
+ return texture.GetPixel(px, py);
+ }
+
+ ///
+ /// Gets the pixel color at the UV coordinates calculated from a point
+ /// inside a rectangle.
+ ///
+ /// The texture to sample from.
+ /// The rectangle to sample from.
+ /// The point inside the rectangle.
+ /// The pixel color.
+ public static Color Sample(this Texture2D texture, Rect rect, Vector2 point)
+ {
+ if (texture == null || texture.width == 0 || texture.height == 0) {
+ return Color.clear;
+ }
+
+ float u = Mathf.InverseLerp(rect.min.x, rect.max.x, point.x);
+ float v = Mathf.InverseLerp(rect.min.y, rect.max.y, point.y);
+
+ return Sample(texture, u, v);
+ }
+
+ ///
+ /// Gets the pixel color at the UV coordinates calculated from a
+ /// position inside a bounds. The position uses the x and z axis.
+ ///
+ /// The texture to sample from.
+ /// The bounds to sample from.
+ /// The position inside the bounds.
+ /// The pixel color.
+ public static Color Sample(this Texture2D texture, Bounds bounds, Vector3 position)
+ {
+ if (texture == null || texture.width == 0 || texture.height == 0) {
+ return Color.clear;
+ }
+
+ float u = Mathf.InverseLerp(bounds.min.x, bounds.max.x, position.x);
+ float v = Mathf.InverseLerp(bounds.min.z, bounds.max.z, position.z);
+
+ return Sample(texture, u, v);
+ }
+
+ ///
+ /// Sets every pixel in the texture to the specified color.
+ ///
+ /// The texture to set the color of.
+ /// The color to set the texture to.
+ public static void SetColor(this Texture2D texture, Color32 color)
+ {
+ var colors = texture.GetRawTextureData();
+ int length = colors.Length;
+
+ for (int i = 0; i < length; i++) {
+ colors[i] = color;
+ }
+
+ texture.Apply();
+ }
+
+ }
+
+}
diff --git a/Runtime/AnimatedShaderProperty.cs.meta b/Runtime/Extensions/TextureExtensions.cs.meta
similarity index 83%
rename from Runtime/AnimatedShaderProperty.cs.meta
rename to Runtime/Extensions/TextureExtensions.cs.meta
index 9672563..d978d12 100644
--- a/Runtime/AnimatedShaderProperty.cs.meta
+++ b/Runtime/Extensions/TextureExtensions.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: a53bfe0a27b00db4f905734ac4f77ad0
+guid: 3ab0b023fcc831b429ae0f7b8cbd088c
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Runtime/InvertMesh.cs b/Runtime/InvertMesh.cs
index 9644fc3..122e192 100644
--- a/Runtime/InvertMesh.cs
+++ b/Runtime/InvertMesh.cs
@@ -5,8 +5,9 @@ namespace Zigurous.Graphics
///
/// Inverts the normals and triangles of the mesh so it renders inside-out.
///
- [RequireComponent(typeof(MeshFilter))]
[AddComponentMenu("Zigurous/Graphics/Invert Mesh")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/InvertMesh")]
+ [RequireComponent(typeof(MeshFilter))]
public sealed class InvertMesh : MonoBehaviour
{
///
diff --git a/Runtime/MeshGenerator.cs b/Runtime/MeshGenerator.cs
new file mode 100644
index 0000000..7ee91d0
--- /dev/null
+++ b/Runtime/MeshGenerator.cs
@@ -0,0 +1,137 @@
+using UnityEngine;
+using UnityEngine.Rendering;
+
+namespace Zigurous.Graphics
+{
+ ///
+ /// Utility class to generate procedural meshes at runtime.
+ ///
+ public static class MeshGenerator
+ {
+ public delegate Vector3 VertexGenerator(int x, int y, float u, float v);
+
+ ///
+ /// Creates a new procedural mesh of a grid of points.
+ ///
+ /// The width of the grid of points.
+ /// The height of the grid of points.
+ public static Mesh Create(int width, int height)
+ {
+ Mesh mesh = new Mesh();
+
+ if (width * height > 65535) {
+ mesh.indexFormat = IndexFormat.UInt32;
+ }
+
+ mesh.vertices = CreateVertices(width, height, DefaultVertexGenerator);
+ mesh.triangles = CreateTriangles(width, height);
+ mesh.uv = CreateUVs(width, height);
+ mesh.RecalculateNormals();
+
+ return mesh;
+ }
+
+ ///
+ /// Creates a new procedural mesh using a custom vertex function.
+ ///
+ /// The width of the grid of points.
+ /// The height of the grid of points.
+ /// A custom function to calculate the vertex for a given point.
+ public static Mesh Create(int width, int height, VertexGenerator vertexGenerator)
+ {
+ if (vertexGenerator == null) {
+ vertexGenerator = DefaultVertexGenerator;
+ }
+
+ Mesh mesh = new Mesh();
+
+ if (width * height > 65535) {
+ mesh.indexFormat = IndexFormat.UInt32;
+ }
+
+ mesh.vertices = CreateVertices(width, height, vertexGenerator);
+ mesh.triangles = CreateTriangles(width, height);
+ mesh.uv = CreateUVs(width, height);
+ mesh.RecalculateNormals();
+
+ return mesh;
+ }
+
+ private static Vector3[] CreateVertices(int width, int height, VertexGenerator vertexGenerator)
+ {
+ Vector3[] verticies = new Vector3[(width + 1) * (height + 1)];
+
+ int index = 0;
+
+ for (int y = 0; y <= height; y++)
+ {
+ for (int x = 0; x <= width; x++)
+ {
+ float u = x / (float)width;
+ float v = y / (float)height;
+
+ verticies[index] = vertexGenerator(x, y, u, v);
+ index++;
+ }
+ }
+
+ return verticies;
+ }
+
+ private static int[] CreateTriangles(int width, int height)
+ {
+ int[] triangles = new int[width * height * 6];
+
+ int vert = 0;
+ int tris = 0;
+
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ triangles[tris + 0] = vert + 0;
+ triangles[tris + 1] = vert + width + 1;
+ triangles[tris + 2] = vert + 1;
+ triangles[tris + 3] = vert + 1;
+ triangles[tris + 4] = vert + width + 1;
+ triangles[tris + 5] = vert + width + 2;
+
+ vert++;
+ tris += 6;
+ }
+
+ vert++;
+ }
+
+ return triangles;
+ }
+
+ private static Vector2[] CreateUVs(int width, int height)
+ {
+ Vector2[] uvs = new Vector2[(width + 1) * (height + 1)];
+
+ int index = 0;
+
+ for (int y = 0; y <= height; y++)
+ {
+ for (int x = 0; x <= width; x++)
+ {
+ float u = x / (float)width;
+ float v = y / (float)height;
+
+ uvs[index] = new Vector2(u, v);
+ index++;
+ }
+ }
+
+ return uvs;
+ }
+
+ private static Vector3 DefaultVertexGenerator(int x, int y, float u, float v)
+ {
+ return new Vector3(x, 0f, y);
+ }
+
+ }
+
+}
diff --git a/Runtime/ShaderProperty.cs.meta b/Runtime/MeshGenerator.cs.meta
similarity index 83%
rename from Runtime/ShaderProperty.cs.meta
rename to Runtime/MeshGenerator.cs.meta
index ad4dd92..3664a7e 100644
--- a/Runtime/ShaderProperty.cs.meta
+++ b/Runtime/MeshGenerator.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: db26498e97261284aa5e11a8e8a022e9
+guid: aaeb0dc493c4e8d498132268be89d3a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Runtime/SaveMesh.cs b/Runtime/SaveMesh.cs
index 44dd6ad..58823e6 100644
--- a/Runtime/SaveMesh.cs
+++ b/Runtime/SaveMesh.cs
@@ -1,19 +1,23 @@
-using UnityEngine;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+using UnityEngine;
namespace Zigurous.Graphics
{
///
- /// Saves the mesh of a mesh filter into a project asset.
+ /// Saves the mesh of a mesh filter as a project asset.
///
- [RequireComponent(typeof(MeshFilter))]
[AddComponentMenu("Zigurous/Graphics/Save Mesh")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/SaveMesh")]
+ [RequireComponent(typeof(MeshFilter))]
public sealed class SaveMesh : MonoBehaviour
{
///
/// The name of the saved asset. The mesh name will be used if not set.
///
[Tooltip("The name of the saved asset. The mesh name will be used if not set.")]
- public string assetName;
+ public string assetName = "New Mesh";
///
/// Saves the mesh on start, otherwise it needs to be called manually.
@@ -37,18 +41,17 @@ private void Reset()
assetName = filter.sharedMesh.name;
}
}
+
+ enabled = false;
}
private void Start()
{
- #if UNITY_EDITOR
if (saveOnStart) {
Save();
}
- #endif
}
- #if UNITY_EDITOR
///
/// Saves the mesh as a project asset.
///
@@ -56,10 +59,24 @@ public void Save()
{
MeshFilter filter = GetComponent();
- if (assetName.Length > 0) {
- filter.SaveMesh(assetName);
- } else {
+ if (string.IsNullOrEmpty(assetName)) {
filter.SaveMesh();
+ } else {
+ filter.SaveMesh(assetName);
+ }
+ }
+
+ #if UNITY_EDITOR
+ [MenuItem("CONTEXT/SaveMesh/Save Mesh")]
+ private static void ContextMenu_Save()
+ {
+ if (Selection.activeGameObject != null)
+ {
+ SaveMesh mesh = Selection.activeGameObject.GetComponent();
+
+ if (mesh != null) {
+ mesh.Save();
+ }
}
}
#endif
diff --git a/Runtime/ShaderProperty.cs b/Runtime/ShaderProperty.cs
deleted file mode 100644
index 8ca0613..0000000
--- a/Runtime/ShaderProperty.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using UnityEngine;
-
-namespace Zigurous.Graphics
-{
- ///
- /// A shader property that can be set on a material. An id is automatically
- /// created for the property for optimal code.
- ///
- [System.Serializable]
- public struct ShaderProperty
- {
- [SerializeField]
- [HideInInspector]
- private int m_Id;
-
- ///
- /// The id of the shader property (Read only).
- ///
- public int id
- {
- get
- {
- if (m_Id == 0) {
- m_Id = Shader.PropertyToID(m_Name);
- }
- return m_Id;
- }
- }
-
- [SerializeField]
- [Tooltip("The name of the shader property.")]
- private string m_Name;
-
- ///
- /// The name of the shader property.
- ///
- public string name
- {
- get => m_Name;
- set
- {
- m_Name = value;
- m_Id = Shader.PropertyToID(value);
- }
- }
-
- ///
- /// Creates a new shader property with the given name.
- ///
- /// The name of the shader property.
- public ShaderProperty(string name)
- {
- m_Name = name;
- m_Id = Shader.PropertyToID(name);
- }
-
- ///
- /// Implicitly converts a name to a shader property.
- ///
- /// The name of the shader property.
- /// A shader property with the given name.
- public static implicit operator ShaderProperty(string name) => new ShaderProperty(name);
-
- ///
- /// Implicitly converts a shader property to an id.
- ///
- /// The shader property to convert to an id.
- /// The id of the shader property.
- public static implicit operator int(ShaderProperty property) => property.id;
-
- }
-
-}
diff --git a/Runtime/TextureDrawer.cs b/Runtime/TextureDrawer.cs
index cdaae78..89f2af1 100644
--- a/Runtime/TextureDrawer.cs
+++ b/Runtime/TextureDrawer.cs
@@ -3,171 +3,34 @@
namespace Zigurous.Graphics
{
///
- /// Draws a custom texture at runtime.
+ /// The base class to draw a custom texture at runtime.
///
- [ExecuteAlways]
- public abstract class TextureDrawer : MonoBehaviour
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/TextureDrawer")]
+ public abstract class TextureDrawer : ScriptableObject
{
- ///
- /// The texture settings of a .
- ///
- [System.Serializable]
- public struct TextureSettings
- {
- ///
- /// The width and height of the texture.
- ///
- [Tooltip("The width and height of the texture.")]
- public Vector2Int size;
-
- ///
- /// The filter mode of the texture.
- ///
- [Tooltip("The filter mode of the texture.")]
- public FilterMode filterMode;
-
- ///
- /// The wrap mode of the texture.
- ///
- [Tooltip("The wrap mode of the texture.")]
- public TextureWrapMode wrapMode;
-
- ///
- /// Creates new texture settings with specified values.
- ///
- /// The size of the texture.
- /// The filter mode of the texture.
- /// The wrap mode of the texture.
- public TextureSettings(Vector2Int size, FilterMode filterMode, TextureWrapMode wrapMode)
- {
- this.size = size;
- this.filterMode = filterMode;
- this.wrapMode = wrapMode;
- }
-
- }
-
- ///
- /// The render settings of a .
- ///
- [System.Serializable]
- public struct RenderSettings
- {
- ///
- /// The shader property that holds the texture.
- ///
- [Tooltip("The shader property that holds the texture.")]
- public ShaderProperty shaderTextureName;
-
- ///
- /// The amount of scaling to apply to the transform (as a multiplier).
- ///
- [Tooltip("The amount of scaling to apply to the transform (as a multiplier).")]
- public float scaleFactor;
-
- ///
- /// Scales the transform of the object to match the texture size.
- ///
- [Tooltip("Scales the transform of the object to match the texture size.")]
- public bool scaleTransform;
-
- #if UNITY_EDITOR
- ///
- /// Updates the texture while in the editor.
- ///
- [Tooltip("Updates the texture while in the editor.")]
- public bool updateInEditor;
- #endif
-
- ///
- /// Creates new render settings with the specified values.
- ///
- /// The shader property that holds the texture.
- /// The amount of scaling to apply to the transform (as a multiplier).
- /// Scales the transform of the object to match the texture size.
- public RenderSettings(ShaderProperty shaderTextureName, float scaleFactor = 1f, bool scaleTransform = false)
- {
- this.shaderTextureName = shaderTextureName;
- this.scaleFactor = scaleFactor;
- this.scaleTransform = scaleTransform;
-
- #if UNITY_EDITOR
- this.updateInEditor = false;
- #endif
- }
-
- }
-
///
/// The drawn texture (Read only).
///
public Texture2D texture { get; private set; }
///
- /// The texture settings.
- ///
- [Tooltip("The texture settings.")]
- public TextureSettings textureSettings = new TextureSettings(new Vector2Int(1024, 1024), FilterMode.Bilinear, TextureWrapMode.Clamp);
-
- ///
- /// The renderer component that holds the material the texture is added
- /// to (Read only).
+ /// The width and height of the texture.
///
- public new Renderer renderer { get; private set; }
+ [Header("Texture Settings")]
+ [Tooltip("The width and height of the texture.")]
+ public Vector2Int size = new Vector2Int(1024, 1024);
///
- /// The render settings.
+ /// The filter mode of the texture.
///
- [Tooltip("The render settings.")]
- public RenderSettings renderSettings = new RenderSettings("_MainTex", 1f, false);
+ [Tooltip("The filter mode of the texture.")]
+ public FilterMode filterMode = FilterMode.Bilinear;
///
- /// Whether the settings have changed since the texture was last drawn
- /// (Read only).
+ /// The wrap mode of the texture.
///
- public bool invalidated { get; internal set; }
-
- protected virtual void Awake()
- {
- renderer = GetComponent();
- }
-
- protected virtual void OnValidate()
- {
- invalidated = true;
-
- if (textureSettings.size.x < 1) {
- textureSettings.size.x = 1;
- }
-
- if (textureSettings.size.y < 1) {
- textureSettings.size.y = 1;
- }
-
- if (renderer == null) {
- renderer = GetComponent();
- }
- }
-
- protected virtual void OnEnable()
- {
- if (Application.isPlaying) {
- Draw();
- }
- }
-
- private void Update()
- {
- #if UNITY_EDITOR
- if (!(Application.isPlaying || renderSettings.updateInEditor)) {
- return;
- }
- #endif
-
- if (invalidated) {
- Draw();
- }
- }
+ [Tooltip("The wrap mode of the texture.")]
+ public TextureWrapMode wrapMode = TextureWrapMode.Clamp;
///
/// Draws the texture.
@@ -175,64 +38,24 @@ private void Update()
/// The drawn texture.
public Texture2D Draw()
{
- if (texture == null || texture.width != textureSettings.size.x || texture.height != textureSettings.size.y) {
- texture = new Texture2D(textureSettings.size.x, textureSettings.size.y);
+ if (texture == null || texture.width != size.x || texture.height != size.y) {
+ texture = new Texture2D(size.x, size.y);
}
- texture.filterMode = textureSettings.filterMode;
- texture.wrapMode = textureSettings.wrapMode;
- invalidated = false;
+ texture.filterMode = filterMode;
+ texture.wrapMode = wrapMode;
SetPixels(texture);
-
texture.Apply();
- ApplyTexture();
- SetTransformScale();
-
return texture;
}
- ///
- /// Applies the texture to the renderer material.
- ///
- private void ApplyTexture()
- {
- if (renderer == null) {
- return;
- }
-
- if (Application.isPlaying) {
- renderer.material.SetTexture(renderSettings.shaderTextureName.id, texture);
- } else {
- renderer.sharedMaterial = new Material(renderer.sharedMaterial);
- renderer.sharedMaterial.SetTexture(renderSettings.shaderTextureName.id, texture);
- }
- }
-
- ///
- /// Sets the scale of the transform based on the texture size.
- ///
- private void SetTransformScale()
- {
- if (texture == null || !renderSettings.scaleTransform) {
- return;
- }
-
- Vector3 scale = new Vector2(texture.width, texture.height);
- scale *= renderSettings.scaleFactor;
- scale.z = 1f;
-
- if (scale.x != Mathf.Infinity && scale.y != Mathf.Infinity) {
- transform.localScale = scale;
- }
- }
-
///
/// Sets the pixels of the texture.
///
/// The texture to set the pixels on.
- protected abstract void SetPixels(Texture2D texture);
+ public abstract void SetPixels(Texture2D texture);
}
diff --git a/Runtime/TextureDrawerRenderer.cs b/Runtime/TextureDrawerRenderer.cs
new file mode 100644
index 0000000..18fdbb5
--- /dev/null
+++ b/Runtime/TextureDrawerRenderer.cs
@@ -0,0 +1,167 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace Zigurous.Graphics
+{
+ ///
+ /// Renders the result of a .
+ ///
+ [ExecuteAlways]
+ [AddComponentMenu("Zigurous/Graphics/Texture Drawer Renderer")]
+ [HelpURL("https://docs.zigurous.com/com.zigurous.graphics/api/Zigurous.Graphics/TextureDrawerRenderer")]
+ [RequireComponent(typeof(Renderer))]
+ public sealed class TextureDrawerRenderer : MonoBehaviour
+ {
+ private Renderer m_Renderer;
+
+ [Tooltip("The drawer that creates the texture.")]
+ [SerializeField] private TextureDrawer m_Drawer;
+
+ [Tooltip("The shader property that holds the texture.")]
+ [SerializeField] private string m_ShaderTextureName = "_MainTex";
+
+ [Tooltip("The amount of scaling to apply to the transform (as a multiplier).")]
+ [SerializeField] private float m_ScaleFactor = 1f;
+
+ [Tooltip("Scales the transform of the object to match the texture size.")]
+ [SerializeField] private bool m_ScaleTransform = false;
+
+ ///
+ /// The drawer that creates the texture.
+ ///
+ public TextureDrawer drawer
+ {
+ get => m_Drawer;
+ set
+ {
+ m_Drawer = value;
+ Render();
+ }
+ }
+
+ ///
+ /// The shader property that holds the texture.
+ ///
+ public string shaderTextureName
+ {
+ get => m_ShaderTextureName;
+ set
+ {
+ m_ShaderTextureName = value;
+ Render();
+ }
+ }
+
+ ///
+ /// The amount of scaling to apply to the transform (as a multiplier).
+ ///
+ public float scaleFactor
+ {
+ get => m_ScaleFactor;
+ set
+ {
+ m_ScaleFactor = value;
+ Render();
+ }
+ }
+
+ ///
+ /// Scales the transform of the object to match the texture size.
+ ///
+ public bool scaleTransform
+ {
+ get => m_ScaleTransform;
+ set
+ {
+ m_ScaleTransform = value;
+ Render();
+ }
+ }
+
+ #if UNITY_EDITOR
+ [SerializeField]
+ private bool m_UpdateInEditor;
+ private bool m_Invalidated;
+
+ private void OnValidate()
+ {
+ if (m_UpdateInEditor) {
+ m_Invalidated = true;
+ }
+ }
+
+ private void Update()
+ {
+ if (m_Invalidated)
+ {
+ ForceRender();
+ m_Invalidated = false;
+ }
+ }
+ #endif
+
+ private void OnEnable()
+ {
+ Render();
+ }
+
+ private void Render()
+ {
+ if (enabled && Application.isPlaying) {
+ ForceRender();
+ }
+ }
+
+ private void ForceRender()
+ {
+ if (drawer == null) {
+ return;
+ }
+
+ if (m_Renderer == null) {
+ m_Renderer = GetComponent();
+ }
+
+ Texture2D texture = drawer.Draw();
+
+ if (Application.isPlaying) {
+ m_Renderer.material.SetTexture(shaderTextureName, texture);
+ } else {
+ m_Renderer.sharedMaterial = new Material(m_Renderer.sharedMaterial);
+ m_Renderer.sharedMaterial.SetTexture(shaderTextureName, texture);
+ }
+
+ if (scaleTransform)
+ {
+ Vector3 scale = new Vector2(texture.width, texture.height) * scaleFactor;
+ scale.z = 1f;
+
+ if (scale.x != Mathf.Infinity && scale.y != Mathf.Infinity) {
+ transform.localScale = scale;
+ }
+ }
+ }
+
+ #if UNITY_EDITOR
+ [MenuItem("CONTEXT/TextureDrawerRenderer/Force Update")]
+ private static void ForceUpdate()
+ {
+ if (Selection.activeGameObject != null)
+ {
+ TextureDrawerRenderer renderer = Selection.activeGameObject.GetComponent();
+
+ if (renderer != null)
+ {
+ if (renderer.m_UpdateInEditor) {
+ renderer.m_Invalidated = true;
+ } else if (Application.isPlaying) {
+ renderer.ForceRender();
+ }
+ }
+ }
+ }
+ #endif
+
+ }
+
+}
diff --git a/Runtime/TextureDrawerRenderer.cs.meta b/Runtime/TextureDrawerRenderer.cs.meta
new file mode 100644
index 0000000..e265448
--- /dev/null
+++ b/Runtime/TextureDrawerRenderer.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0794de26c7ce8c94ebe99c53ff5ba1ed
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Triangle.cs b/Runtime/Triangle.cs
index d404734..fd5d0ac 100644
--- a/Runtime/Triangle.cs
+++ b/Runtime/Triangle.cs
@@ -102,9 +102,9 @@ public override int GetHashCode()
unchecked // Overflow is fine, just wrap
{
int hash = 17;
- hash = hash * 23 + v1.GetHashCode();
- hash = hash * 23 + v2.GetHashCode();
- hash = hash * 23 + v3.GetHashCode();
+ hash = hash * 31 + v1.GetHashCode();
+ hash = hash * 31 + v2.GetHashCode();
+ hash = hash * 31 + v3.GetHashCode();
return hash;
}
}
diff --git a/Runtime/Triangulator.cs b/Runtime/Triangulator.cs
new file mode 100644
index 0000000..08b98d3
--- /dev/null
+++ b/Runtime/Triangulator.cs
@@ -0,0 +1,158 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Zigurous.Graphics
+{
+ ///
+ /// Splits a polygon into triangles.
+ ///
+ public static class Triangulator
+ {
+ ///
+ /// Splits a polygon into triangles. Supports concave polygons but not
+ /// polygons with holes.
+ ///
+ /// The points that form a polygon.
+ /// The indices of the triangles.
+ public static int[] Triangulate(Vector2[] points)
+ {
+ int n = points.Length;
+
+ if (n < 3) {
+ return new int[0];
+ }
+
+ int[] V = new int[n];
+
+ if (Area(points) > 0f)
+ {
+ for (int v = 0; v < n; v++) {
+ V[v] = v;
+ }
+ }
+ else
+ {
+ for (int v = 0; v < n; v++) {
+ V[v] = (n - 1) - v;
+ }
+ }
+
+ List indices = new List();
+
+ int nv = n;
+ int count = 2 * nv;
+
+ for (int m = 0, v = nv - 1; nv > 2;)
+ {
+ if ((count--) <= 0) {
+ return indices.ToArray();
+ }
+
+ int u = v;
+
+ if (nv <= u) {
+ u = 0;
+ }
+
+ v = u + 1;
+
+ if (nv <= v) {
+ v = 0;
+ }
+
+ int w = v + 1;
+
+ if (nv <= w) {
+ w = 0;
+ }
+
+ if (Snip(points, u, v, w, nv, V))
+ {
+ int a, b, c, s, t;
+
+ a = V[u];
+ b = V[v];
+ c = V[w];
+
+ indices.Add(a);
+ indices.Add(b);
+ indices.Add(c);
+
+ m++;
+
+ for (s = v, t = v + 1; t < nv; s++, t++) {
+ V[s] = V[t];
+ }
+
+ nv--;
+ count = 2 * nv;
+ }
+ }
+
+ indices.Reverse();
+ return indices.ToArray();
+ }
+
+ private static float Area(Vector2[] points)
+ {
+ int n = points.Length;
+ float A = 0f;
+
+ for (int p = n - 1, q = 0; q < n; p = q++)
+ {
+ Vector2 pval = points[p];
+ Vector2 qval = points[q];
+ A += pval.x * qval.y - qval.x * pval.y;
+ }
+
+ return (A * 0.5f);
+ }
+
+ private static bool Snip(Vector2[] points, int u, int v, int w, int n, int[] V)
+ {
+ Vector2 A = points[V[u]];
+ Vector2 B = points[V[v]];
+ Vector2 C = points[V[w]];
+
+ if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x)))) {
+ return false;
+ }
+
+ for (int p = 0; p < n; p++)
+ {
+ if ((p == u) || (p == v) || (p == w)) {
+ continue;
+ }
+
+ Vector2 P = points[V[p]];
+
+ if (InsideTriangle(A, B, C, P)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool InsideTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P)
+ {
+ float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
+ float cCROSSap, bCROSScp, aCROSSbp;
+
+ ax = C.x - B.x; ay = C.y - B.y;
+ bx = A.x - C.x; by = A.y - C.y;
+ cx = B.x - A.x; cy = B.y - A.y;
+ apx = P.x - A.x; apy = P.y - A.y;
+ bpx = P.x - B.x; bpy = P.y - B.y;
+ cpx = P.x - C.x; cpy = P.y - C.y;
+
+ aCROSSbp = ax * bpy - ay * bpx;
+ cCROSSap = cx * apy - cy * apx;
+ bCROSScp = bx * cpy - by * cpx;
+
+ return ((aCROSSbp >= 0f) && (bCROSScp >= 0f) && (cCROSSap >= 0f));
+ }
+
+ }
+
+}
diff --git a/Runtime/Triangulator.cs.meta b/Runtime/Triangulator.cs.meta
new file mode 100644
index 0000000..33afc25
--- /dev/null
+++ b/Runtime/Triangulator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 61cdf4181a75e484797fd76671c72f13
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/docs~ b/docs~
deleted file mode 160000
index 4d87b26..0000000
--- a/docs~
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 4d87b267f5c990de54b03c55fbb259f9a7d4004e
diff --git a/package.json b/package.json
index 2ad8bfb..61c6b9c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "com.zigurous.graphics",
- "version": "0.3.0",
+ "version": "0.4.0",
"displayName": "Graphics Utils",
"description": "The Graphics Utils package provides scripts and utilities for graphics and rendering purposes in Unity projects.",
"unity": "2019.4",