1.0.0-preview.3
# [1.0.0-preview.3](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v1.0.0-preview.2...v1.0.0-preview.3) (2020-06-04) ### Bug Fixes * outside interaction doesn't work when the RaycastFilter option is off ([pull/122/head1935650
](19356500c5
)) ### Features * Add ignore self graphic option. ([91c0099
](91c00993b9
)) * TextMeshPro support ([5b0906b
](5b0906b608
)) ### BREAKING CHANGES * TextMeshPro support is now an option. If a shader or material has errors after a version upgrade, you will need to import the asset. Please see the README for more information.
parent
7ebbdeb251
commit
9ad7d46a10
20
CHANGELOG.md
20
CHANGELOG.md
|
@ -1,3 +1,23 @@
|
|||
# [1.0.0-preview.3](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v1.0.0-preview.2...v1.0.0-preview.3) (2020-06-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* outside interaction doesn't work when the RaycastFilter option is off ([1935650](https://github.com/mob-sakai/SoftMaskForUGUI/commit/19356500c5b777aa5857fa5176fc09f0fd7951cb))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add ignore self graphic option. ([91c0099](https://github.com/mob-sakai/SoftMaskForUGUI/commit/91c00993b9afbdda0386b8e426e181f8f31618b9))
|
||||
* TextMeshPro support ([5b0906b](https://github.com/mob-sakai/SoftMaskForUGUI/commit/5b0906b6086193bc8f62fa174955c9df901ef3f0))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* TextMeshPro support is now an option.
|
||||
If a shader or material has errors after a version upgrade, you will need to import the asset.
|
||||
Please see the README for more information.
|
||||
|
||||
# [1.0.0-preview.2](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v1.0.0-preview.1...v1.0.0-preview.2) (2020-05-13)
|
||||
|
||||
|
||||
|
|
36
README.md
36
README.md
|
@ -66,6 +66,7 @@ By using SoftMask instead of the default Mask component, you can beautifully rep
|
|||
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Demo
|
||||
|
||||
|
@ -73,6 +74,7 @@ By using SoftMask instead of the default Mask component, you can beautifully rep
|
|||
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Installation
|
||||
|
||||
|
@ -117,23 +119,19 @@ Or, use [UpmGitExtension](https://github.com/mob-sakai/UpmGitExtension) to insta
|
|||
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## How to play demo
|
||||
|
||||
#### For Unity 2019.1 or later
|
||||
- For Unity 2019.1 or later
|
||||
- Open `Package Manager` window and select `UI Soft Mask` package in package list and click `Demo > Import in project` button
|
||||
- For Unity 2018.4 or earlier
|
||||
- Click `Assets/Samples/UISoftMask/Import Demo` from menu
|
||||
|
||||
1. Open `Package Manager` window and select `UI Soft Mask` package in package list
|
||||
2. Click `Import in project` button
|
||||

|
||||
3. The demo will be imported into `Assets/Samples/UI Soft Mask/{version}/Demo`。
|
||||
Open `UISoftMask_Demo` scene and play it
|
||||
The assets will be imported into `Assets/Samples/UI Soft Mask/{version}/Demo`.
|
||||
Open `UISoftMask_Demo` scene and play it.
|
||||
|
||||
#### For Unity 2018.4 or earlier
|
||||
|
||||
1. Select `Assets/Samples/UI Soft Mask Demo` from menu
|
||||

|
||||
2. The demo will be imported into `Assets/Samples/UI Soft Mask/{version}/Demo`.
|
||||
Open `UISoftMask_Demo` scene and play it
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
|
@ -152,6 +150,20 @@ Or, add a SoftMaskable components from the inspector of the SoftMask component.
|
|||
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Support TextMeshPro
|
||||
|
||||
To use SoftMask with TextMeshPro, import a sample asset.
|
||||
|
||||
- For Unity 2019.1 or later
|
||||
- Open `Package Manager` window and select `UI Soft Mask` package in package list and click `TextMeshPro Support > Import in project` button
|
||||
- For Unity 2018.4 or earlier
|
||||
- Click `Assets/Samples/UISoftMask/Import TextMeshPro Support` from menu
|
||||
|
||||
The assets will be imported into `Assets/Samples/UI Soft Mask/{version}/TextMeshPro Support`.
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Support soft masks with your custom shaders
|
||||
|
||||
|
@ -183,7 +195,7 @@ This operation determines the final alpha according to the soft mask buffer.
|
|||
color.a *= SoftMask(IN.vertex, IN.worldPosition);
|
||||
```
|
||||
|
||||
As an example of implementation, please see [UI-Default-SoftMask.shader](https://raw.githubusercontent.com/mob-sakai/SoftMaskForUGUI/upm/Shaders/Resources/UI-Default-SoftMask.shader).
|
||||
As an example of implementation, please see [UI-Default-SoftMask.shader](https://github.com/mob-sakai/SoftMaskForUGUI/blob/upm/Shaders/Resources/UI-Default-SoftMaskable.shader).
|
||||
|
||||
|
||||
|
||||
|
|
2
Shaders/TextMeshProSupport/TMP_SDF (SoftMaskable).shader.meta → Samples~/TextMeshPro Support/TMP_SDF (SoftMaskable).shader.meta
Executable file → Normal file
2
Shaders/TextMeshProSupport/TMP_SDF (SoftMaskable).shader.meta → Samples~/TextMeshPro Support/TMP_SDF (SoftMaskable).shader.meta
Executable file → Normal file
|
@ -1,7 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 935b7be1c88464d2eb87204fdfab5a38
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,7 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e65241fa80a374114b3f55ed746c04d9
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,9 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 94593ebff37d04a64936ebe46ce7e769
|
||||
timeCreated: 1450517184
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -5,7 +5,6 @@ using UnityEditor;
|
|||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Coffee.UISoftMask
|
||||
{
|
||||
internal static class EditorUtils
|
||||
|
@ -36,7 +35,7 @@ namespace Coffee.UISoftMask
|
|||
var so = new SerializedObject(target);
|
||||
so.Update();
|
||||
|
||||
bool oldEnable = target.enabled;
|
||||
var oldEnable = target.enabled;
|
||||
target.enabled = false;
|
||||
|
||||
// Find MonoScript of the specified component.
|
||||
|
|
|
@ -8,13 +8,18 @@ namespace Coffee.UISoftMask
|
|||
{
|
||||
public static class ImportSampleMenu
|
||||
{
|
||||
[MenuItem("Assets/Samples/Import UISoftMask Sample")]
|
||||
private static void ImportSample()
|
||||
{
|
||||
const string jsonGuid = "c43fd233e88b347cdabc530c23ffe30a";
|
||||
const string dirName = "Demo";
|
||||
private const string jsonGuid = "c43fd233e88b347cdabc530c23ffe30a";
|
||||
|
||||
ImportSample(jsonGuid, dirName);
|
||||
[MenuItem("Assets/Samples/UISoftMask/Import Demo")]
|
||||
private static void ImportDemo()
|
||||
{
|
||||
ImportSample(jsonGuid, "Demo");
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Samples/UISoftMask/Import TextMeshPro Support")]
|
||||
private static void ImportTextMeshProSupport()
|
||||
{
|
||||
ImportSample(jsonGuid, "TextMeshProSupport");
|
||||
}
|
||||
|
||||
private static void ImportSample(string jsonGuid, string sampleName)
|
||||
|
|
|
@ -14,9 +14,9 @@ namespace Coffee.UISoftMask
|
|||
[CanEditMultipleObjects]
|
||||
public class SoftMaskEditor : Editor
|
||||
{
|
||||
const string k_PrefsPreview = "SoftMaskEditor_Preview";
|
||||
static readonly List<Graphic> s_Graphics = new List<Graphic>();
|
||||
static bool s_Preview;
|
||||
private const string k_PrefsPreview = "SoftMaskEditor_Preview";
|
||||
private static readonly List<Graphic> s_Graphics = new List<Graphic>();
|
||||
private static bool s_Preview;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
|
@ -35,9 +35,7 @@ namespace Coffee.UISoftMask
|
|||
if (0 < fixTargets.Count)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.HelpBox(
|
||||
"There are child Graphics that does not have a SoftMaskable component.\nAdd SoftMaskable component to them.",
|
||||
MessageType.Warning);
|
||||
EditorGUILayout.HelpBox("There are child Graphics that does not have a SoftMaskable component.\nAdd SoftMaskable component to them.", MessageType.Warning);
|
||||
GUILayout.BeginVertical();
|
||||
if (GUILayout.Button("Fix"))
|
||||
{
|
||||
|
@ -59,9 +57,8 @@ namespace Coffee.UISoftMask
|
|||
}
|
||||
|
||||
// Preview buffer.
|
||||
GUILayout.BeginHorizontal(EditorStyles.helpBox);
|
||||
if (s_Preview != (s_Preview = EditorGUILayout.ToggleLeft("Preview Buffer", s_Preview,
|
||||
GUILayout.MaxWidth(EditorGUIUtility.labelWidth))))
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
if (s_Preview != (s_Preview = EditorGUILayout.ToggleLeft("Preview Buffer", s_Preview)))
|
||||
{
|
||||
EditorPrefs.SetBool(k_PrefsPreview, s_Preview);
|
||||
}
|
||||
|
@ -69,37 +66,35 @@ namespace Coffee.UISoftMask
|
|||
if (s_Preview)
|
||||
{
|
||||
var tex = current.softMaskBuffer;
|
||||
var width = tex.width * 64 / tex.height;
|
||||
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(width, 64), tex, null, ScaleMode.ScaleToFit);
|
||||
var width = tex.width * 128 / tex.height;
|
||||
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(width, 128), tex, null, ScaleMode.ScaleToFit);
|
||||
Repaint();
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
GUILayout.EndHorizontal();
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
|
||||
//%%%% Context menu for editor %%%%
|
||||
[MenuItem("CONTEXT/Mask/Convert To SoftMask", true)]
|
||||
static bool _ConvertToSoftMask(MenuCommand command)
|
||||
private static bool _ConvertToSoftMask(MenuCommand command)
|
||||
{
|
||||
return EditorUtils.CanConvertTo<SoftMask>(command.context);
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/Mask/Convert To SoftMask", false)]
|
||||
static void ConvertToSoftMask(MenuCommand command)
|
||||
private static void ConvertToSoftMask(MenuCommand command)
|
||||
{
|
||||
EditorUtils.ConvertTo<SoftMask>(command.context);
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/Mask/Convert To Mask", true)]
|
||||
static bool _ConvertToMask(MenuCommand command)
|
||||
private static bool _ConvertToMask(MenuCommand command)
|
||||
{
|
||||
return EditorUtils.CanConvertTo<Mask>(command.context);
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/Mask/Convert To Mask", false)]
|
||||
static void ConvertToMask(MenuCommand command)
|
||||
private static void ConvertToMask(MenuCommand command)
|
||||
{
|
||||
EditorUtils.ConvertTo<Mask>(command.context);
|
||||
}
|
||||
|
|
|
@ -2,15 +2,17 @@ using System.Collections.Generic;
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Object = UnityEngine.Object;
|
||||
using MaskIntr = UnityEngine.SpriteMaskInteraction;
|
||||
using System.IO;
|
||||
|
||||
namespace Coffee.UISoftMask
|
||||
{
|
||||
internal enum MaskInteraction : int
|
||||
{
|
||||
VisibleInsideMask = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6),
|
||||
VisibleOutsideMask = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6),
|
||||
Custom = -1,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SoftMaskable editor.
|
||||
/// </summary>
|
||||
|
@ -18,18 +20,16 @@ namespace Coffee.UISoftMask
|
|||
[CanEditMultipleObjects]
|
||||
public class SoftMaskableEditor : Editor
|
||||
{
|
||||
public enum MaskInteraction : int
|
||||
{
|
||||
VisibleInsideMask = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6),
|
||||
VisibleOutsideMask = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6),
|
||||
Custom = -1,
|
||||
}
|
||||
private static readonly List<Mask> s_TmpMasks = new List<Mask>();
|
||||
private static GUIContent s_MaskWarning;
|
||||
private SerializedProperty _spMaskInteraction;
|
||||
private bool _custom;
|
||||
|
||||
MaskInteraction maskInteraction
|
||||
private MaskInteraction maskInteraction
|
||||
{
|
||||
get
|
||||
{
|
||||
int value = _spMaskInteraction.intValue;
|
||||
var value = _spMaskInteraction.intValue;
|
||||
return _custom
|
||||
? MaskInteraction.Custom
|
||||
: System.Enum.IsDefined(typeof(MaskInteraction), value)
|
||||
|
@ -46,31 +46,26 @@ namespace Coffee.UISoftMask
|
|||
}
|
||||
}
|
||||
|
||||
bool _custom = false;
|
||||
|
||||
static readonly List<Graphic> s_Graphics = new List<Graphic>();
|
||||
SerializedProperty _spMaskInteraction;
|
||||
List<Mask> tmpMasks = new List<Mask>();
|
||||
static GUIContent s_MaskWarning;
|
||||
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_spMaskInteraction = serializedObject.FindProperty("m_MaskInteraction");
|
||||
_custom = (maskInteraction == MaskInteraction.Custom);
|
||||
s_MaskWarning = new GUIContent(EditorGUIUtility.FindTexture("console.warnicon.sml"),
|
||||
"This is not a SoftMask component.");
|
||||
}
|
||||
|
||||
if (s_MaskWarning == null)
|
||||
{
|
||||
s_MaskWarning = new GUIContent(EditorGUIUtility.FindTexture("console.warnicon.sml"), "This is not a SoftMask component.");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMaskInteractions()
|
||||
{
|
||||
var softMaskable = target as SoftMaskable;
|
||||
if (softMaskable == null) return;
|
||||
|
||||
softMaskable.GetComponentsInParent<Mask>(true, tmpMasks);
|
||||
tmpMasks.RemoveAll(x => !x.enabled);
|
||||
tmpMasks.Reverse();
|
||||
softMaskable.GetComponentsInParent<Mask>(true, s_TmpMasks);
|
||||
s_TmpMasks.RemoveAll(x => !x.enabled);
|
||||
s_TmpMasks.Reverse();
|
||||
|
||||
maskInteraction = (MaskInteraction) EditorGUILayout.EnumPopup("Mask Interaction", maskInteraction);
|
||||
if (!_custom) return;
|
||||
|
@ -80,10 +75,10 @@ namespace Coffee.UISoftMask
|
|||
|
||||
using (var ccs = new EditorGUI.ChangeCheckScope())
|
||||
{
|
||||
int intr0 = DrawMaskInteraction(0);
|
||||
int intr1 = DrawMaskInteraction(1);
|
||||
int intr2 = DrawMaskInteraction(2);
|
||||
int intr3 = DrawMaskInteraction(3);
|
||||
var intr0 = DrawMaskInteraction(0);
|
||||
var intr1 = DrawMaskInteraction(1);
|
||||
var intr2 = DrawMaskInteraction(2);
|
||||
var intr3 = DrawMaskInteraction(3);
|
||||
|
||||
if (ccs.changed)
|
||||
{
|
||||
|
@ -94,24 +89,24 @@ namespace Coffee.UISoftMask
|
|||
EditorGUIUtility.labelWidth = l;
|
||||
}
|
||||
|
||||
|
||||
private int DrawMaskInteraction(int layer)
|
||||
{
|
||||
Mask mask = layer < tmpMasks.Count ? tmpMasks[layer] : null;
|
||||
MaskIntr intr = (MaskIntr) ((_spMaskInteraction.intValue >> layer * 2) & 0x3);
|
||||
var mask = layer < s_TmpMasks.Count ? s_TmpMasks[layer] : null;
|
||||
var intr = (MaskIntr) ((_spMaskInteraction.intValue >> layer * 2) & 0x3);
|
||||
if (!mask)
|
||||
{
|
||||
return (int) intr;
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.LabelField(mask is SoftMask ? GUIContent.none : s_MaskWarning, GUILayout.Width(16));
|
||||
GUILayout.Space(-5);
|
||||
EditorGUILayout.ObjectField("Mask " + layer, mask, typeof(Mask), false);
|
||||
GUILayout.Space(-15);
|
||||
return (int) (MaskIntr) EditorGUILayout.EnumPopup(intr);
|
||||
}
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(mask is SoftMask ? GUIContent.none : s_MaskWarning, GUILayout.Width(16));
|
||||
GUILayout.Space(-5);
|
||||
EditorGUILayout.ObjectField("Mask " + layer, mask, typeof(Mask), false);
|
||||
GUILayout.Space(-15);
|
||||
intr = (MaskIntr) EditorGUILayout.EnumPopup(intr);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
return (int) intr;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
|
@ -124,61 +119,20 @@ namespace Coffee.UISoftMask
|
|||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
var current = target as SoftMaskable;
|
||||
if (current == null) return;
|
||||
|
||||
current.GetComponentsInChildren<Graphic>(true, s_Graphics);
|
||||
var fixTargets = s_Graphics.Where(x =>
|
||||
x.gameObject != current.gameObject && !x.GetComponent<SoftMaskable>() &&
|
||||
(!x.GetComponent<Mask>() || x.GetComponent<Mask>().showMaskGraphic)).ToList();
|
||||
if (0 < fixTargets.Count)
|
||||
var mask = current.softMask;
|
||||
if (mask) return;
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.HelpBox("This is unnecessary SoftMaskable.\nCan't find any SoftMask components above.", MessageType.Warning);
|
||||
if (GUILayout.Button("Remove", GUILayout.Height(40)))
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.HelpBox(
|
||||
"There are child Graphics that does not have a SoftMaskable component.\nAdd SoftMaskable component to them.",
|
||||
MessageType.Warning);
|
||||
GUILayout.BeginVertical();
|
||||
if (GUILayout.Button("Fix"))
|
||||
{
|
||||
foreach (var p in fixTargets)
|
||||
{
|
||||
p.gameObject.AddComponent<SoftMaskable>();
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Ping"))
|
||||
{
|
||||
EditorGUIUtility.PingObject(fixTargets[0]);
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
GUILayout.EndHorizontal();
|
||||
DestroyImmediate(current);
|
||||
EditorUtils.MarkPrefabDirty();
|
||||
}
|
||||
|
||||
if (!DetectMask(current.transform.parent))
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.HelpBox("This is unnecessary SoftMaskable.\nCan't find any SoftMask components above.",
|
||||
MessageType.Warning);
|
||||
if (GUILayout.Button("Remove", GUILayout.Height(40)))
|
||||
{
|
||||
DestroyImmediate(current);
|
||||
|
||||
EditorUtils.MarkPrefabDirty();
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
static bool DetectMask(Transform transform)
|
||||
{
|
||||
while (transform)
|
||||
{
|
||||
if (transform.GetComponent<SoftMask>()) return true;
|
||||
|
||||
transform = transform.parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,20 @@ namespace Coffee.UISoftMask
|
|||
GraphicConnector.FindConnector(graphic).SetMaterialDirty(graphic);
|
||||
}
|
||||
|
||||
public static Shader FindEffectShader(this Graphic graphic)
|
||||
public static T GetComponentInParentEx<T>(this Component component, bool includeInactive = false) where T : MonoBehaviour
|
||||
{
|
||||
return GraphicConnector.FindConnector(graphic).FindEffectShader(graphic);
|
||||
if (!component) return null;
|
||||
var trans = component.transform;
|
||||
|
||||
while (trans)
|
||||
{
|
||||
var c = trans.GetComponent<T>();
|
||||
if (c && (includeInactive || c.isActiveAndEnabled)) return c;
|
||||
|
||||
trans = trans.parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,10 +38,7 @@ namespace Coffee.UISoftMask
|
|||
public class GraphicConnector
|
||||
{
|
||||
private static readonly List<GraphicConnector> s_Connectors = new List<GraphicConnector>();
|
||||
|
||||
private static readonly Dictionary<Type, GraphicConnector> s_ConnectorMap =
|
||||
new Dictionary<Type, GraphicConnector>();
|
||||
|
||||
private static readonly Dictionary<Type, GraphicConnector> s_ConnectorMap = new Dictionary<Type, GraphicConnector>();
|
||||
private static readonly GraphicConnector s_EmptyConnector = new GraphicConnector();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
@ -75,15 +83,6 @@ namespace Coffee.UISoftMask
|
|||
get { return -1; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Find effect shader.
|
||||
/// </summary>
|
||||
public virtual Shader FindEffectShader(Graphic graphic)
|
||||
{
|
||||
return Shader.Find("Hidden/UI/SoftMaskable");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The connector is valid for the component.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,42 +1,44 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.UISoftMask
|
||||
{
|
||||
internal class MaterialCache
|
||||
internal class MaterialEntry
|
||||
{
|
||||
public delegate void ModifyAction(Material material, Graphic graphic);
|
||||
public Material material;
|
||||
public int referenceCount;
|
||||
|
||||
static Dictionary<Hash128, MaterialEntry> materialMap = new Dictionary<Hash128, MaterialEntry>();
|
||||
|
||||
private class MaterialEntry
|
||||
public void Release()
|
||||
{
|
||||
public Material material;
|
||||
public int referenceCount;
|
||||
|
||||
public void Release()
|
||||
if (material)
|
||||
{
|
||||
if (material)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
UnityEngine.Object.DestroyImmediate(material, false);
|
||||
}
|
||||
|
||||
material = null;
|
||||
else
|
||||
#endif
|
||||
UnityEngine.Object.Destroy(material);
|
||||
}
|
||||
|
||||
material = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class MaterialCache
|
||||
{
|
||||
static readonly Dictionary<Hash128, MaterialEntry> s_MaterialMap = new Dictionary<Hash128, MaterialEntry>();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.InitializeOnLoadMethod]
|
||||
private static void ClearCache()
|
||||
{
|
||||
foreach (var entry in materialMap.Values)
|
||||
foreach (var entry in s_MaterialMap.Values)
|
||||
{
|
||||
entry.Release();
|
||||
}
|
||||
|
||||
materialMap.Clear();
|
||||
s_MaterialMap.Clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -45,7 +47,7 @@ namespace Coffee.UISoftMask
|
|||
if (!hash.isValid) return null;
|
||||
|
||||
MaterialEntry entry;
|
||||
if (!materialMap.TryGetValue(hash, out entry))
|
||||
if (!s_MaterialMap.TryGetValue(hash, out entry))
|
||||
{
|
||||
entry = new MaterialEntry()
|
||||
{
|
||||
|
@ -56,7 +58,7 @@ namespace Coffee.UISoftMask
|
|||
};
|
||||
|
||||
onModify(entry.material);
|
||||
materialMap.Add(hash, entry);
|
||||
s_MaterialMap.Add(hash, entry);
|
||||
}
|
||||
|
||||
entry.referenceCount++;
|
||||
|
@ -67,13 +69,13 @@ namespace Coffee.UISoftMask
|
|||
public static void Unregister(Hash128 hash)
|
||||
{
|
||||
MaterialEntry entry;
|
||||
if (!hash.isValid || !materialMap.TryGetValue(hash, out entry)) return;
|
||||
if (!hash.isValid || !s_MaterialMap.TryGetValue(hash, out entry)) return;
|
||||
//Debug.LogFormat("Unregister: {0}, {1}", hash, entry.referenceCount -1);
|
||||
|
||||
if (--entry.referenceCount > 0) return;
|
||||
|
||||
entry.Release();
|
||||
materialMap.Remove(hash);
|
||||
s_MaterialMap.Remove(hash);
|
||||
//Debug.LogFormat("Unregister: Release Emtry: {0}, {1} (Total: {2})", hash, entry.referenceCount, materialMap.Count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UI;
|
||||
|
@ -25,7 +24,7 @@ namespace Coffee.UISoftMask
|
|||
x8 = 8,
|
||||
}
|
||||
|
||||
static readonly List<SoftMask>[] s_TmpSoftMasks = new List<SoftMask>[]
|
||||
private static readonly List<SoftMask>[] s_TmpSoftMasks = new List<SoftMask>[]
|
||||
{
|
||||
new List<SoftMask>(),
|
||||
new List<SoftMask>(),
|
||||
|
@ -33,7 +32,7 @@ namespace Coffee.UISoftMask
|
|||
new List<SoftMask>(),
|
||||
};
|
||||
|
||||
static readonly Color[] s_ClearColors = new Color[]
|
||||
private static readonly Color[] s_ClearColors = new Color[]
|
||||
{
|
||||
new Color(0, 0, 0, 0),
|
||||
new Color(1, 0, 0, 0),
|
||||
|
@ -41,50 +40,49 @@ namespace Coffee.UISoftMask
|
|||
new Color(1, 1, 1, 0),
|
||||
};
|
||||
|
||||
static bool s_UVStartsAtTop;
|
||||
|
||||
static Shader s_SoftMaskShader;
|
||||
static Texture2D s_ReadTexture;
|
||||
static readonly List<SoftMask> s_ActiveSoftMasks = new List<SoftMask>();
|
||||
static readonly List<SoftMask> s_TempRelatables = new List<SoftMask>();
|
||||
static readonly Dictionary<int, Matrix4x4> s_previousViewProjectionMatrices = new Dictionary<int, Matrix4x4>();
|
||||
static readonly Dictionary<int, Matrix4x4> s_nowViewProjectionMatrices = new Dictionary<int, Matrix4x4>();
|
||||
static int s_StencilCompId;
|
||||
static int s_ColorMaskId;
|
||||
static int s_MainTexId;
|
||||
static int s_SoftnessId;
|
||||
static int s_GameVPId;
|
||||
static int s_GameTVPId;
|
||||
static int s_Alpha;
|
||||
MaterialPropertyBlock _mpb;
|
||||
CommandBuffer _cb;
|
||||
Material _material;
|
||||
RenderTexture _softMaskBuffer;
|
||||
int _stencilDepth;
|
||||
Mesh _mesh;
|
||||
SoftMask _parent;
|
||||
readonly List<SoftMask> _children = new List<SoftMask>();
|
||||
bool _hasChanged = false;
|
||||
bool _hasStencilStateChanged = false;
|
||||
private static bool s_UVStartsAtTop;
|
||||
private static Shader s_SoftMaskShader;
|
||||
private static Texture2D s_ReadTexture;
|
||||
private static readonly List<SoftMask> s_ActiveSoftMasks = new List<SoftMask>();
|
||||
private static readonly List<SoftMask> s_TempRelatables = new List<SoftMask>();
|
||||
private static readonly Dictionary<int, Matrix4x4> s_PreviousViewProjectionMatrices = new Dictionary<int, Matrix4x4>();
|
||||
private static readonly Dictionary<int, Matrix4x4> s_NowViewProjectionMatrices = new Dictionary<int, Matrix4x4>();
|
||||
private static int s_StencilCompId;
|
||||
private static int s_ColorMaskId;
|
||||
private static int s_MainTexId;
|
||||
private static int s_SoftnessId;
|
||||
private static int s_GameVPId;
|
||||
private static int s_GameTVPId;
|
||||
private static int s_Alpha;
|
||||
private MaterialPropertyBlock _mpb;
|
||||
private CommandBuffer _cb;
|
||||
private Material _material;
|
||||
private RenderTexture _softMaskBuffer;
|
||||
private int _stencilDepth;
|
||||
private Mesh _mesh;
|
||||
private SoftMask _parent;
|
||||
internal readonly List<SoftMask> _children = new List<SoftMask>();
|
||||
private bool _hasChanged = false;
|
||||
private bool _hasStencilStateChanged = false;
|
||||
|
||||
|
||||
[Tooltip("The desampling rate for soft mask buffer.")] [SerializeField]
|
||||
DesamplingRate m_DesamplingRate = DesamplingRate.None;
|
||||
[SerializeField, Tooltip("The desampling rate for soft mask buffer.")]
|
||||
private DesamplingRate m_DesamplingRate = DesamplingRate.None;
|
||||
|
||||
[Tooltip(
|
||||
"The value used by the soft mask to select the area of influence defined over the soft mask's graphic.")]
|
||||
[SerializeField]
|
||||
[Range(0.01f, 1)]
|
||||
float m_Softness = 1;
|
||||
[SerializeField, Range(0.01f, 1), Tooltip("The value used by the soft mask to select the area of influence defined over the soft mask's graphic.")]
|
||||
private float m_Softness = 1;
|
||||
|
||||
[Tooltip("The transparency of the whole masked graphic.")] [SerializeField] [Range(0f, 1f)]
|
||||
float m_Alpha = 1;
|
||||
[SerializeField, Range(0f, 1f), Tooltip("The transparency of the whole masked graphic.")]
|
||||
private float m_Alpha = 1;
|
||||
|
||||
[Tooltip("Should the soft mask ignore parent soft masks?")] [SerializeField]
|
||||
bool m_IgnoreParent = false;
|
||||
[SerializeField, Tooltip("Should the soft mask ignore parent soft masks?")]
|
||||
private bool m_IgnoreParent = false;
|
||||
|
||||
[Tooltip("Is the soft mask a part of parent soft mask?")] [SerializeField]
|
||||
bool m_PartOfParent = false;
|
||||
[SerializeField, Tooltip("Is the soft mask a part of parent soft mask?")]
|
||||
private bool m_PartOfParent = false;
|
||||
|
||||
[SerializeField, Tooltip("Self Graphic will not be drawn to soft mask buffer.")]
|
||||
private bool m_IgnoreSelfGraphic;
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
@ -214,6 +212,19 @@ namespace Coffee.UISoftMask
|
|||
get { return _parent; }
|
||||
}
|
||||
|
||||
public bool ignoreSelfGraphic
|
||||
{
|
||||
get { return m_IgnoreSelfGraphic; }
|
||||
set
|
||||
{
|
||||
if (m_IgnoreSelfGraphic == value) return;
|
||||
m_IgnoreSelfGraphic = value;
|
||||
hasChanged = true;
|
||||
graphic.SetVerticesDirtyEx();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Material material
|
||||
{
|
||||
get
|
||||
|
@ -267,7 +278,15 @@ namespace Coffee.UISoftMask
|
|||
void IMeshModifier.ModifyMesh(VertexHelper verts)
|
||||
{
|
||||
if (isActiveAndEnabled)
|
||||
{
|
||||
if (ignoreSelfGraphic)
|
||||
{
|
||||
verts.Clear();
|
||||
}
|
||||
|
||||
verts.FillMesh(mesh);
|
||||
}
|
||||
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
|
@ -336,7 +355,7 @@ namespace Coffee.UISoftMask
|
|||
_mpb = new MaterialPropertyBlock();
|
||||
_cb = new CommandBuffer();
|
||||
|
||||
graphic.SetVerticesDirty();
|
||||
graphic.SetVerticesDirtyEx();
|
||||
|
||||
base.OnEnable();
|
||||
_hasStencilStateChanged = false;
|
||||
|
@ -411,7 +430,8 @@ namespace Coffee.UISoftMask
|
|||
/// </summary>
|
||||
protected override void OnValidate()
|
||||
{
|
||||
graphic.SetMaterialDirty();
|
||||
graphic.SetVerticesDirtyEx();
|
||||
graphic.SetMaterialDirtyEx();
|
||||
OnTransformParentChanged();
|
||||
base.OnValidate();
|
||||
_hasStencilStateChanged = false;
|
||||
|
@ -441,8 +461,8 @@ namespace Coffee.UISoftMask
|
|||
var nowVP = cam.projectionMatrix * cam.worldToCameraMatrix;
|
||||
var previousVP = default(Matrix4x4);
|
||||
var id = cam.GetInstanceID();
|
||||
s_previousViewProjectionMatrices.TryGetValue(id, out previousVP);
|
||||
s_nowViewProjectionMatrices[id] = nowVP;
|
||||
s_PreviousViewProjectionMatrices.TryGetValue(id, out previousVP);
|
||||
s_NowViewProjectionMatrices[id] = nowVP;
|
||||
|
||||
if (previousVP != nowVP)
|
||||
{
|
||||
|
@ -478,13 +498,13 @@ namespace Coffee.UISoftMask
|
|||
MaskUtilities.NotifyStencilStateChanged(sm);
|
||||
}
|
||||
|
||||
s_previousViewProjectionMatrices.Clear();
|
||||
foreach (var id in s_nowViewProjectionMatrices.Keys)
|
||||
s_PreviousViewProjectionMatrices.Clear();
|
||||
foreach (var id in s_NowViewProjectionMatrices.Keys)
|
||||
{
|
||||
s_previousViewProjectionMatrices[id] = s_nowViewProjectionMatrices[id];
|
||||
s_PreviousViewProjectionMatrices[id] = s_NowViewProjectionMatrices[id];
|
||||
}
|
||||
|
||||
s_nowViewProjectionMatrices.Clear();
|
||||
s_NowViewProjectionMatrices.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -15,40 +15,37 @@ namespace Coffee.UISoftMask
|
|||
#else
|
||||
[ExecuteInEditMode]
|
||||
# endif
|
||||
[RequireComponent(typeof(Graphic))]
|
||||
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter
|
||||
#if UNITY_EDITOR
|
||||
, ISerializationCallbackReceiver
|
||||
# endif
|
||||
{
|
||||
const int kVisibleInside = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6);
|
||||
const int kVisibleOutside = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||
static readonly Hash128 k_InvalidHash = new Hash128();
|
||||
private const int kVisibleInside = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6);
|
||||
private const int kVisibleOutside = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||
private static readonly Hash128 k_InvalidHash = new Hash128();
|
||||
|
||||
static int s_SoftMaskTexId;
|
||||
static int s_StencilCompId;
|
||||
static int s_MaskInteractionId;
|
||||
static List<SoftMaskable> s_ActiveSoftMaskables;
|
||||
static int[] s_Interactions = new int[4];
|
||||
private static int s_SoftMaskTexId;
|
||||
private static int s_StencilCompId;
|
||||
private static int s_MaskInteractionId;
|
||||
private static List<SoftMaskable> s_ActiveSoftMaskables;
|
||||
private static int[] s_Interactions = new int[4];
|
||||
|
||||
[Tooltip("The graphic will be visible only in areas where no mask is present.")]
|
||||
[System.Obsolete]
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
bool m_Inverse = false;
|
||||
[SerializeField, HideInInspector, System.Obsolete]
|
||||
private bool m_Inverse;
|
||||
|
||||
[Tooltip("The interaction for each masks.")] [HideInInspector] [SerializeField]
|
||||
int m_MaskInteraction = kVisibleInside;
|
||||
[SerializeField, Tooltip("The interaction for each masks."), HideInInspector]
|
||||
private int m_MaskInteraction = kVisibleInside;
|
||||
|
||||
[Tooltip("Use stencil to mask.")] [SerializeField]
|
||||
bool m_UseStencil = false;
|
||||
[SerializeField, Tooltip("Use stencil to mask.")]
|
||||
private bool m_UseStencil;
|
||||
|
||||
[Tooltip("Use soft-masked raycast target.\n\nNote: This option is expensive.")] [SerializeField]
|
||||
bool m_RaycastFilter = false;
|
||||
[SerializeField, Tooltip("Use soft-masked raycast target.\n\nNote: This option is expensive.")]
|
||||
private bool m_RaycastFilter;
|
||||
|
||||
Graphic _graphic = null;
|
||||
SoftMask _softMask = null;
|
||||
Material _maskMaterial = null;
|
||||
Hash128 _effectMaterialHash;
|
||||
private Graphic _graphic;
|
||||
private SoftMask _softMask;
|
||||
private Hash128 _effectMaterialHash;
|
||||
|
||||
/// <summary>
|
||||
/// The graphic will be visible only in areas where no mask is present.
|
||||
|
@ -82,6 +79,11 @@ namespace Coffee.UISoftMask
|
|||
get { return _graphic ? _graphic : _graphic = GetComponent<Graphic>(); }
|
||||
}
|
||||
|
||||
public SoftMask softMask
|
||||
{
|
||||
get { return _softMask ? _softMask : _softMask = this.GetComponentInParentEx<SoftMask>(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform material modification in this function.
|
||||
/// </summary>
|
||||
|
@ -98,27 +100,13 @@ namespace Coffee.UISoftMask
|
|||
// If this component is disabled, the material is returned as is.
|
||||
if (!isActiveAndEnabled) return baseMaterial;
|
||||
|
||||
// Find the nearest parent softmask.
|
||||
var parentTransform = transform.parent;
|
||||
while (parentTransform)
|
||||
{
|
||||
var sm = parentTransform.GetComponent<SoftMask>();
|
||||
if (sm && sm.enabled)
|
||||
{
|
||||
_softMask = sm;
|
||||
break;
|
||||
}
|
||||
|
||||
parentTransform = parentTransform.parent;
|
||||
}
|
||||
|
||||
// If the parents do not have a soft mask component, the material is returned as is.
|
||||
if (!_softMask) return baseMaterial;
|
||||
if (!softMask) return baseMaterial;
|
||||
|
||||
// Generate soft maskable material.
|
||||
_effectMaterialHash = new Hash128(
|
||||
(uint) baseMaterial.GetInstanceID(),
|
||||
(uint) _softMask.GetInstanceID(),
|
||||
(uint) softMask.GetInstanceID(),
|
||||
(uint) m_MaskInteraction,
|
||||
(uint) (m_UseStencil ? 1 : 0)
|
||||
);
|
||||
|
@ -130,7 +118,7 @@ namespace Coffee.UISoftMask
|
|||
#if UNITY_EDITOR
|
||||
mat.EnableKeyword("SOFTMASK_EDITOR");
|
||||
#endif
|
||||
mat.SetTexture(s_SoftMaskTexId, _softMask.softMaskBuffer);
|
||||
mat.SetTexture(s_SoftMaskTexId, softMask.softMaskBuffer);
|
||||
mat.SetInt(s_StencilCompId,
|
||||
m_UseStencil ? (int) CompareFunction.Equal : (int) CompareFunction.Always);
|
||||
mat.SetVector(s_MaskInteractionId, new Vector4(
|
||||
|
@ -140,7 +128,6 @@ namespace Coffee.UISoftMask
|
|||
((m_MaskInteraction >> 6) & 0x3)
|
||||
));
|
||||
});
|
||||
_maskMaterial = modifiedMaterial;
|
||||
|
||||
return modifiedMaterial;
|
||||
}
|
||||
|
@ -153,21 +140,45 @@ namespace Coffee.UISoftMask
|
|||
/// <param name="eventCamera">Raycast camera.</param>
|
||||
bool ICanvasRaycastFilter.IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
|
||||
{
|
||||
if (!isActiveAndEnabled || !_softMask)
|
||||
if (!isActiveAndEnabled || !softMask)
|
||||
return true;
|
||||
if (!RectTransformUtility.RectangleContainsScreenPoint(transform as RectTransform, sp, eventCamera))
|
||||
return false;
|
||||
if (!m_RaycastFilter)
|
||||
return true;
|
||||
|
||||
var sm = _softMask;
|
||||
for (var i = 0; i < 4; i++)
|
||||
if (m_RaycastFilter)
|
||||
{
|
||||
s_Interactions[i] = sm ? ((m_MaskInteraction >> i * 2) & 0x3) : 0;
|
||||
sm = sm ? sm.parent : null;
|
||||
}
|
||||
var sm = _softMask;
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
s_Interactions[i] = sm ? ((m_MaskInteraction >> i * 2) & 0x3) : 0;
|
||||
sm = sm ? sm.parent : null;
|
||||
}
|
||||
|
||||
return _softMask.IsRaycastLocationValid(sp, eventCamera, graphic, s_Interactions);
|
||||
return _softMask.IsRaycastLocationValid(sp, eventCamera, graphic, s_Interactions);
|
||||
}
|
||||
else
|
||||
{
|
||||
var sm = _softMask;
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
if (!sm) break;
|
||||
s_Interactions[i] = sm ? ((m_MaskInteraction >> i * 2) & 0x3) : 0;
|
||||
var interaction = s_Interactions[i] == 1;
|
||||
var inRect = RectTransformUtility.RectangleContainsScreenPoint(sm.transform as RectTransform, sp, eventCamera);
|
||||
if (!sm.ignoreSelfGraphic && interaction != inRect) return false;
|
||||
|
||||
foreach (var child in sm._children)
|
||||
{
|
||||
if (!child) break;
|
||||
var inRectChild = RectTransformUtility.RectangleContainsScreenPoint(child.transform as RectTransform, sp, eventCamera);
|
||||
if (!child.ignoreSelfGraphic && interaction != inRectChild) return false;
|
||||
}
|
||||
|
||||
sm = sm ? sm.parent : null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -243,7 +254,7 @@ namespace Coffee.UISoftMask
|
|||
if (m_Inverse)
|
||||
{
|
||||
m_Inverse = false;
|
||||
m_MaskInteraction = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||
m_MaskInteraction = kVisibleOutside;
|
||||
}
|
||||
#pragma warning restore 0612
|
||||
|
||||
|
|
59
package.json
59
package.json
|
@ -1,29 +1,34 @@
|
|||
{
|
||||
"name": "com.coffee.softmask-for-ugui",
|
||||
"displayName": "UI Soft Mask",
|
||||
"description": "UI Soft Mask is a smooth masking component for Unity UI (uGUI) elements.\nBy using SoftMask instead of the default Mask component, you can beautifully represent the rounded edges of UI elements.",
|
||||
"version": "1.0.0-preview.2",
|
||||
"unity": "2017.1",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mob-sakai/SoftMaskForUGUI.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "mob-sakai",
|
||||
"email": "sakai861104@gmail.com",
|
||||
"url": "https://github.com/mob-sakai"
|
||||
},
|
||||
"dependencies": {},
|
||||
"keywords": [
|
||||
"ui",
|
||||
"softmask"
|
||||
],
|
||||
"samples": [
|
||||
{
|
||||
"displayName": "Demo",
|
||||
"description": "UI Soft Mask Demo",
|
||||
"path": "Samples~/Demo"
|
||||
}
|
||||
]
|
||||
"name": "com.coffee.softmask-for-ugui",
|
||||
"displayName": "UI Soft Mask",
|
||||
"description": "UI Soft Mask is a smooth masking component for Unity UI (uGUI) elements.\nBy using SoftMask instead of the default Mask component, you can beautifully represent the rounded edges of UI elements.",
|
||||
"version": "1.0.0-preview.3",
|
||||
"unity": "2017.1",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mob-sakai/SoftMaskForUGUI.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "mob-sakai",
|
||||
"email": "sakai861104@gmail.com",
|
||||
"url": "https://github.com/mob-sakai"
|
||||
},
|
||||
"dependencies": {},
|
||||
"keywords": [
|
||||
"ui",
|
||||
"softmask"
|
||||
],
|
||||
"samples": [
|
||||
{
|
||||
"displayName": "Demo",
|
||||
"description": "UI Soft Mask Demo",
|
||||
"path": "Samples~/Demo"
|
||||
},
|
||||
{
|
||||
"displayName": "TextMeshPro Support",
|
||||
"description": "TextMeshPro Support",
|
||||
"path": "Samples~/TextMeshPro Support"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue