release v0.5.0
commit
7536f0ed30
|
@ -1,8 +1,22 @@
|
|||
# Changelog
|
||||
|
||||
## [0.4.0](https://github.com/mob-sakai/SoftMaskForUGUI/tree/0.4.0) (2019-01-13)
|
||||
## [v0.5.0](https://github.com/mob-sakai/SoftMaskForUGUI/tree/v0.5.0) (2019-02-01)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v0.3.0...0.4.0)
|
||||
[Full Changelog](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v0.4.0...v0.5.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Mask interaction for each layer [\#31](https://github.com/mob-sakai/SoftMaskForUGUI/issues/31)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- SoftMask is not clipped by RectMask2D [\#30](https://github.com/mob-sakai/SoftMaskForUGUI/issues/30)
|
||||
- Does not work with flipped/rotated images [\#27](https://github.com/mob-sakai/SoftMaskForUGUI/issues/27)
|
||||
- SceneView does not display SoftMask properly [\#16](https://github.com/mob-sakai/SoftMaskForUGUI/issues/16)
|
||||
|
||||
## [v0.4.0](https://github.com/mob-sakai/SoftMaskForUGUI/tree/v0.4.0) (2019-01-13)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v0.3.0...v0.4.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
|
@ -60,4 +74,4 @@
|
|||
|
||||
|
||||
|
||||
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
||||
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
||||
|
|
|
@ -8,7 +8,7 @@ Soft masking for uGUI elements in Unity.
|
|||
[](https://github.com/mob-sakai/SoftMaskForUGUI/releases)
|
||||
[](https://github.com/mob-sakai/SoftMaskForUGUI/releases)
|
||||

|
||||
[](https://github.com/mob-sakai/SoftMaskForUGUI/blob/master/LICENSE.txt)
|
||||
[](https://github.com/mob-sakai/SoftMaskForUGUI/blob/upm/LICENSE.txt)
|
||||
[](http://makeapullrequest.com)
|
||||
[](https://twitter.com/intent/follow?screen_name=mob_sakai)
|
||||
|
||||
|
@ -58,9 +58,6 @@ By using SoftMask instead of default Mask, rounded edges of UI elements can be e
|
|||
* Support TextMeshPro.
|
||||

|
||||
|
||||
#### Known issues
|
||||
|
||||
* SceneView does not display SoftMask properly. It is displayed like Mask. ([By design](#why-is-not-it-displayed-properly-in-sceneview))
|
||||
|
||||
#### Components
|
||||
|
||||
|
@ -87,7 +84,7 @@ Find the manifest.json file in the Packages folder of your project and edit it t
|
|||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"com.coffee.softmask-for-ugui": "https://github.com/mob-sakai/SoftMaskForUGUI.git#0.4.0",
|
||||
"com.coffee.softmask-for-ugui": "https://github.com/mob-sakai/SoftMaskForUGUI.git#0.5.0",
|
||||
...
|
||||
},
|
||||
}
|
||||
|
@ -151,20 +148,7 @@ You can support soft masks in your custom shaders, by adding just 3 lines!
|
|||
color.a *= SoftMask(IN.vertex);
|
||||
```
|
||||
|
||||
As an example of implementation, please see [UI-Default-SoftMask.shader](https://raw.githubusercontent.com/mob-sakai/SoftMaskForUGUI/master/Assets/Coffee/UIExtensions/SoftMaskForUGUI/Resources/UI-Default-SoftMask.shader).
|
||||
|
||||
|
||||
<br><br>
|
||||
#### Why is not it displayed properly in SceneView?
|
||||
|
||||
SoftMask calculates the final alpha value based on the value of each channel of the soft mask buffer.
|
||||
The soft mask buffer is a buffer generated based on GameView's screen space.
|
||||
|
||||
Since SceneView has a view matrix and a projection matrix independent of GameView, the SceneView's camera can not refer to the soft mask buffer properly.
|
||||
|
||||
Therefore, in GameView, it is displayed properly. but in ScreenView, it is displayed like default Mask.
|
||||
|
||||

|
||||
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).
|
||||
|
||||
|
||||
<br><br>
|
||||
|
@ -247,7 +231,7 @@ static void ConvertToMask(MenuCommand command)
|
|||
}
|
||||
```
|
||||
|
||||
For details, please see [SoftMaskEditor.cs](https://raw.githubusercontent.com/mob-sakai/SoftMaskForUGUI/master/Assets/Coffee/UIExtensions/SoftMaskForUGUI/Scripts/Editor/SoftMaskEditor.cs).
|
||||
For details, please see [SoftMaskEditor.cs](https://raw.githubusercontent.com/mob-sakai/SoftMaskForUGUI/upm/Scripts/Editor/SoftMaskEditor.cs).
|
||||
|
||||
|
||||
<br><br>
|
||||
|
@ -333,4 +317,4 @@ UnityEditor.EditorApplication.update += ()
|
|||
* Releases : https://github.com/mob-sakai/SoftMaskForUGUI/releases
|
||||
* Issue tracker : https://github.com/mob-sakai/SoftMaskForUGUI/issues
|
||||
* Current project : https://github.com/mob-sakai/SoftMaskForUGUI/projects/1
|
||||
* Change log : https://github.com/mob-sakai/SoftMaskForUGUI/blob/master/CHANGELOG.md
|
||||
* Change log : https://github.com/mob-sakai/SoftMaskForUGUI/blob/upm/CHANGELOG.md
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using Object = UnityEngine.Object;
|
||||
using MaskIntr = UnityEngine.SpriteMaskInteraction;
|
||||
using System.IO;
|
||||
|
||||
namespace Coffee.UIExtensions.Editors
|
||||
|
@ -17,6 +18,38 @@ namespace Coffee.UIExtensions.Editors
|
|||
[CanEditMultipleObjects]
|
||||
public class SoftMaskableEditor : Editor
|
||||
{
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
//################################
|
||||
public enum MaskInteraction : int
|
||||
{
|
||||
VisibleInsideMask = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6),
|
||||
VisibleOutsideMask = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6),
|
||||
Custom = -1,
|
||||
}
|
||||
|
||||
MaskInteraction maskInteraction
|
||||
{
|
||||
get
|
||||
{
|
||||
int value = _spMaskInteraction.intValue;
|
||||
return _custom
|
||||
? MaskInteraction.Custom
|
||||
: System.Enum.IsDefined(typeof(MaskInteraction), value)
|
||||
? (MaskInteraction)value
|
||||
: MaskInteraction.Custom;
|
||||
}
|
||||
set
|
||||
{
|
||||
_custom = (value == MaskInteraction.Custom);
|
||||
if (!_custom)
|
||||
{
|
||||
_spMaskInteraction.intValue = (int)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool _custom = false;
|
||||
|
||||
static readonly Type s_TypeTMPro = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (x => x.GetTypes ()).FirstOrDefault (x => x.Name == "TMP_Text");
|
||||
static readonly Type s_TypeTMP_SpriteAsset = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (x => x.GetTypes ()).FirstOrDefault (x => x.Name == "TMP_SpriteAsset");
|
||||
static readonly Type s_TypeTMProSettings = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (x => x.GetTypes ()).FirstOrDefault (x => x.Name == "TMP_Settings");
|
||||
|
@ -36,9 +69,13 @@ namespace Coffee.UIExtensions.Editors
|
|||
Shader _mobileShader;
|
||||
Shader _spriteShader;
|
||||
List<MaterialEditor> _materialEditors = new List<MaterialEditor> ();
|
||||
SerializedProperty _spMaskInteraction;
|
||||
|
||||
private void OnEnable ()
|
||||
{
|
||||
_spMaskInteraction = serializedObject.FindProperty("m_MaskInteraction");
|
||||
_custom = (maskInteraction == MaskInteraction.Custom);
|
||||
|
||||
ClearMaterialEditors ();
|
||||
|
||||
_shader = Shader.Find ("TextMeshPro/Distance Field (SoftMaskable)");
|
||||
|
@ -58,6 +95,8 @@ namespace Coffee.UIExtensions.Editors
|
|||
s_PiDefaultFontAssetPath = s_TypeTMProSettings.GetProperty ("defaultFontAssetPath", BindingFlags.Static | BindingFlags.Public);
|
||||
s_PiDefaultSpriteAssetPath = s_TypeTMProSettings.GetProperty ("defaultSpriteAssetPath", BindingFlags.Static | BindingFlags.Public);
|
||||
}
|
||||
|
||||
s_MaskWarning = new GUIContent(EditorGUIUtility.FindTexture("console.warnicon.sml"), "This component is not SoftMask. Use SoftMask instead of Mask.");
|
||||
}
|
||||
|
||||
private void OnDisable ()
|
||||
|
@ -65,10 +104,105 @@ namespace Coffee.UIExtensions.Editors
|
|||
ClearMaterialEditors ();
|
||||
}
|
||||
|
||||
List<Mask> tmpMasks = new List<Mask>();
|
||||
|
||||
void DrawMaskInteractions()
|
||||
{
|
||||
(target as SoftMaskable).GetComponentsInParent<Mask>(true, tmpMasks);
|
||||
tmpMasks.RemoveAll(x => !x.enabled);
|
||||
tmpMasks.Reverse();
|
||||
|
||||
maskInteraction = (MaskInteraction)EditorGUILayout.EnumPopup("Mask Interaction", maskInteraction);
|
||||
if (_custom)
|
||||
{
|
||||
var l = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 45;
|
||||
|
||||
using (var ccs = new EditorGUI.ChangeCheckScope())
|
||||
{
|
||||
int intr0 = DrawMaskInteraction(0);
|
||||
int intr1 = DrawMaskInteraction(1);
|
||||
int intr2 = DrawMaskInteraction(2);
|
||||
int intr3 = DrawMaskInteraction(3);
|
||||
|
||||
if (ccs.changed) {
|
||||
_spMaskInteraction.intValue = (intr0 << 0) + (intr1 << 2) + (intr2 << 4) + (intr3 << 6);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = l;
|
||||
}
|
||||
}
|
||||
|
||||
static GUIContent s_MaskWarning = new GUIContent();
|
||||
|
||||
int DrawMaskInteraction(int layer)
|
||||
{
|
||||
Mask mask = layer < tmpMasks.Count ? tmpMasks[layer] : null;
|
||||
MaskIntr 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);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI ()
|
||||
{
|
||||
base.OnInspectorGUI ();
|
||||
|
||||
serializedObject.Update();
|
||||
DrawMaskInteractions();
|
||||
|
||||
// maskInteraction = (MaskInteraction)EditorGUILayout.EnumPopup("Mask Interaction", maskInteraction);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
/*
|
||||
EditorGUI.indentLevel++;
|
||||
var l = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 60;
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.ObjectField("Mask 0", null, typeof(Mask), false);
|
||||
EditorGUILayout.EnumPopup (MaskIntr.None);
|
||||
}
|
||||
EditorGUIUtility.labelWidth = l;
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
var spMaskInteraction = serializedObject.FindProperty ("m_MaskInteraction");
|
||||
MaskIntr intr0 = (MaskIntr)((spMaskInteraction.intValue >> 0) & 0x3);
|
||||
MaskIntr intr1 = (MaskIntr)((spMaskInteraction.intValue >> 2) & 0x3);
|
||||
MaskIntr intr2 = (MaskIntr)((spMaskInteraction.intValue >> 4) & 0x3);
|
||||
MaskIntr intr3 = (MaskIntr)((spMaskInteraction.intValue >> 6) & 0x3);
|
||||
|
||||
using (var ccs = new EditorGUI.ChangeCheckScope ()) {
|
||||
|
||||
intr0 = (MaskIntr)EditorGUILayout.EnumPopup ("Layer 0", intr0);
|
||||
intr1 = (MaskIntr)EditorGUILayout.EnumPopup ("Layer 1", intr1);
|
||||
intr2 = (MaskIntr)EditorGUILayout.EnumPopup ("Layer 2", intr2);
|
||||
intr3 = (MaskIntr)EditorGUILayout.EnumPopup ("Layer 3", intr3);
|
||||
|
||||
if (ccs.changed) {
|
||||
current.SetMaskInteractions (intr0,intr1,intr2,intr3);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// spMaskInteraction.intValue = (intr0 << 0) | (intr1 << 2) | (intr2 << 4) | (intr3 << 6);
|
||||
//
|
||||
// serializedObject.ApplyModifiedProperties ();
|
||||
|
||||
|
||||
|
||||
|
||||
// var current = target as SoftMaskable;
|
||||
var current = target as SoftMaskable;
|
||||
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 ();
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Coffee.UIExtensions
|
|||
/// Soft mask.
|
||||
/// Use instead of Mask for smooth masking.
|
||||
/// </summary>
|
||||
public class SoftMask : Mask, IMeshModifier, ICanvasRaycastFilter
|
||||
public class SoftMask : Mask, IMeshModifier
|
||||
{
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
|
@ -106,7 +106,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
m_IgnoreParent = value;
|
||||
hasChanged = true;
|
||||
OnTransformParentChanged ();
|
||||
OnTransformParentChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,9 +132,9 @@ namespace Coffee.UIExtensions
|
|||
ReleaseRT(ref _softMaskBuffer);
|
||||
}
|
||||
|
||||
if(!_softMaskBuffer)
|
||||
if (!_softMaskBuffer)
|
||||
{
|
||||
_softMaskBuffer = RenderTexture.GetTemporary (w, h, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
|
||||
_softMaskBuffer = RenderTexture.GetTemporary(w, h, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default);
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
private set
|
||||
{
|
||||
if(_parent)
|
||||
if (_parent)
|
||||
{
|
||||
_parent.hasChanged = value;
|
||||
}
|
||||
|
@ -158,6 +158,15 @@ namespace Coffee.UIExtensions
|
|||
}
|
||||
}
|
||||
|
||||
public SoftMask parent
|
||||
{
|
||||
get
|
||||
{
|
||||
return _parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Perform material modification in this function.
|
||||
/// </summary>
|
||||
|
@ -203,34 +212,23 @@ namespace Coffee.UIExtensions
|
|||
/// <param name="sp">Screen position.</param>
|
||||
/// <param name="eventCamera">Raycast camera.</param>
|
||||
/// <param name="g">Target graphic.</param>
|
||||
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera, Graphic g)
|
||||
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera, Graphic g, int[] interactions)
|
||||
{
|
||||
if (!isActiveAndEnabled || (g == graphic && !g.raycastTarget))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = (int)(softMaskBuffer.width * sp.x / Screen.width);
|
||||
int y = (int)(softMaskBuffer.height * sp.y / Screen.height);
|
||||
return 0.5f < GetPixelValue(x, y);
|
||||
return 0.5f < GetPixelValue(x, y, interactions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a point and a camera is the raycast valid.
|
||||
/// </summary>
|
||||
/// <returns>Valid.</returns>
|
||||
/// <param name="sp">Screen position.</param>
|
||||
/// <param name="eventCamera">Raycast camera.</param>
|
||||
public override bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
|
||||
{
|
||||
return IsRaycastLocationValid(sp, eventCamera, graphic);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Protected Members.
|
||||
//################################
|
||||
|
@ -329,12 +327,12 @@ namespace Coffee.UIExtensions
|
|||
hasChanged = true;
|
||||
}
|
||||
|
||||
protected override void OnRectTransformDimensionsChange ()
|
||||
protected override void OnRectTransformDimensionsChange()
|
||||
{
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
|
||||
/// </summary>
|
||||
|
@ -382,13 +380,13 @@ namespace Coffee.UIExtensions
|
|||
continue;
|
||||
|
||||
var rt = sm.rectTransform;
|
||||
if(rt.hasChanged)
|
||||
if (rt.hasChanged)
|
||||
{
|
||||
rt.hasChanged = false;
|
||||
sm.hasChanged = true;
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
if(!Application.isPlaying)
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
sm.hasChanged = true;
|
||||
}
|
||||
|
@ -403,7 +401,7 @@ namespace Coffee.UIExtensions
|
|||
sm._hasChanged = false;
|
||||
if (!sm._parent)
|
||||
{
|
||||
sm.UpdateMaskTexture ();
|
||||
sm.UpdateMaskTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -413,13 +411,12 @@ namespace Coffee.UIExtensions
|
|||
/// </summary>
|
||||
void UpdateMaskTexture()
|
||||
{
|
||||
if(!graphic || !graphic.canvas)
|
||||
if (!graphic || !graphic.canvas)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Transform stopAfter = MaskUtilities.FindRootSortOverrideCanvas(transform);
|
||||
_stencilDepth = MaskUtilities.GetStencilDepth(transform, stopAfter);
|
||||
_stencilDepth = MaskUtilities.GetStencilDepth(transform, MaskUtilities.FindRootSortOverrideCanvas(transform));
|
||||
|
||||
// Collect children soft masks.
|
||||
int depth = 0;
|
||||
|
@ -448,9 +445,9 @@ namespace Coffee.UIExtensions
|
|||
else
|
||||
{
|
||||
var pos = c.transform.localPosition;
|
||||
var vm = Matrix4x4.TRS (-pos, Quaternion.identity, new Vector3 (1, 1, -1f));
|
||||
var pm = Matrix4x4.TRS (new Vector3 (0, 0, -1), Quaternion.identity, new Vector3 (1 / pos.x, 1 / pos.y, -2 / 1000f));
|
||||
_cb.SetViewProjectionMatrices (vm, pm);
|
||||
var vm = Matrix4x4.TRS(new Vector3(-pos.x, -pos.y, -1000), Quaternion.identity, new Vector3(1, 1, -1f));
|
||||
var pm = Matrix4x4.TRS(new Vector3(0, 0, -1), Quaternion.identity, new Vector3(1 / pos.x, 1 / pos.y, -2 / 10000f));
|
||||
_cb.SetViewProjectionMatrices(vm, pm);
|
||||
}
|
||||
|
||||
// Draw soft masks.
|
||||
|
@ -461,6 +458,11 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
var sm = s_TmpSoftMasks[i][j];
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
sm._stencilDepth = MaskUtilities.GetStencilDepth(sm.transform, MaskUtilities.FindRootSortOverrideCanvas(sm.transform));
|
||||
}
|
||||
|
||||
// Set material property.
|
||||
sm.material.SetInt(s_ColorMaskId, (int)1 << (3 - _stencilDepth - i));
|
||||
sm._mpb.SetTexture(s_MainTexId, sm.graphic.mainTexture);
|
||||
|
@ -562,7 +564,7 @@ namespace Coffee.UIExtensions
|
|||
/// <summary>
|
||||
/// Gets the pixel value.
|
||||
/// </summary>
|
||||
float GetPixelValue(int x, int y)
|
||||
float GetPixelValue(int x, int y, int[] interactions)
|
||||
{
|
||||
if (!s_ReadTexture)
|
||||
{
|
||||
|
@ -576,18 +578,23 @@ namespace Coffee.UIExtensions
|
|||
RenderTexture.active = currentRT;
|
||||
|
||||
var colors = s_ReadTexture.GetRawTextureData();
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
switch (interactions[(i + 3)%4])
|
||||
{
|
||||
case 0: colors[i] = 255; break;
|
||||
case 2: colors[i] = (byte)(255 - colors[i]); break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (_stencilDepth)
|
||||
{
|
||||
case 0:
|
||||
return (colors[1] / 255f);
|
||||
case 1:
|
||||
return (colors[1] / 255f) * (colors[2] / 255f);
|
||||
case 2:
|
||||
return (colors[1] / 255f) * (colors[2] / 255f) * (colors[3] / 255f);
|
||||
case 3:
|
||||
return (colors[1] / 255f) * (colors[2] / 255f) * (colors[3] / 255f) * (colors[0] / 255f);
|
||||
default:
|
||||
return 0;
|
||||
case 0: return (colors[1] / 255f);
|
||||
case 1: return (colors[1] / 255f) * (colors[2] / 255f);
|
||||
case 2: return (colors[1] / 255f) * (colors[2] / 255f) * (colors[3] / 255f);
|
||||
case 3: return (colors[1] / 255f) * (colors[2] / 255f) * (colors[3] / 255f) * (colors[0] / 255f);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
|||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.UI;
|
||||
using MaskIntr = UnityEngine.SpriteMaskInteraction;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
|
@ -11,20 +13,27 @@ namespace Coffee.UIExtensions
|
|||
/// Add this component to Graphic under SoftMask for smooth masking.
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter
|
||||
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter, ISerializationCallbackReceiver
|
||||
{
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
//################################
|
||||
static List<SoftMaskable> s_ActiveSoftMaskables;
|
||||
static Material defaultMaterial = null;
|
||||
const int kVisibleInside = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6);
|
||||
const int kVisibleOutside = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||
|
||||
|
||||
//################################
|
||||
// Serialize Members.
|
||||
//################################
|
||||
[Tooltip("The graphic will be visible only in areas where no mask is present.")]
|
||||
[System.Obsolete]
|
||||
[HideInInspector]
|
||||
[SerializeField] bool m_Inverse = false;
|
||||
[Tooltip("The interaction for each masks.")]
|
||||
[HideInInspector]
|
||||
[SerializeField] int m_MaskInteraction = kVisibleInside;
|
||||
[Tooltip("Use stencil for masking.")]
|
||||
[SerializeField] bool m_UseStencil = false;
|
||||
|
||||
|
||||
//################################
|
||||
|
@ -62,17 +71,13 @@ namespace Coffee.UIExtensions
|
|||
result = new Material(baseMaterial);
|
||||
result.hideFlags = HideFlags.HideAndDontSave;
|
||||
result.SetTexture(s_SoftMaskTexId, _softMask.softMaskBuffer);
|
||||
|
||||
if (m_Inverse)
|
||||
{
|
||||
result.SetFloat(s_SoftMaskInverseId, 1);
|
||||
result.SetInt(s_StencilCompId, (int)CompareFunction.Always);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.SetFloat(s_SoftMaskInverseId, 0);
|
||||
result.SetInt(s_StencilCompId, (int)CompareFunction.Equal);
|
||||
}
|
||||
result.SetInt(s_StencilCompId, m_UseStencil ? (int)CompareFunction.Equal : (int)CompareFunction.Always);
|
||||
result.SetVector(s_MaskInteractionId, new Vector4(
|
||||
(m_MaskInteraction & 0x3),
|
||||
((m_MaskInteraction >> 2) & 0x3),
|
||||
((m_MaskInteraction >> 4) & 0x3),
|
||||
((m_MaskInteraction >> 6) & 0x3)
|
||||
));
|
||||
|
||||
StencilMaterial.Remove(baseMaterial);
|
||||
ReleaseMaterial(ref _maskMaterial);
|
||||
|
@ -103,22 +108,34 @@ namespace Coffee.UIExtensions
|
|||
return true;
|
||||
|
||||
if (!RectTransformUtility.RectangleContainsScreenPoint(transform as RectTransform, sp, eventCamera))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _softMask.IsRaycastLocationValid(sp, eventCamera, graphic) != m_Inverse;
|
||||
var sm = _softMask;
|
||||
for (int 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);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The graphic will be visible only in areas where no mask is present.
|
||||
/// </summary>
|
||||
[System.Obsolete("Use SetMaskInteractions method instead.")]
|
||||
public bool inverse
|
||||
{
|
||||
get { return m_Inverse; }
|
||||
get { return m_MaskInteraction == kVisibleOutside; }
|
||||
set
|
||||
{
|
||||
if (m_Inverse != value)
|
||||
int intValue = value ? kVisibleOutside : kVisibleInside;
|
||||
if (m_MaskInteraction != intValue)
|
||||
{
|
||||
m_Inverse = value;
|
||||
m_MaskInteraction = intValue;
|
||||
graphic.SetMaterialDirty();
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +146,25 @@ namespace Coffee.UIExtensions
|
|||
/// </summary>
|
||||
public Graphic graphic{ get { return _graphic ? _graphic : _graphic = GetComponent<Graphic>(); } }
|
||||
|
||||
/// <summary>
|
||||
/// Set the interaction for each mask.
|
||||
/// </summary>
|
||||
public void SetMaskInteraction(SpriteMaskInteraction intr)
|
||||
{
|
||||
SetMaskInteraction(intr, intr, intr, intr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the interaction for each mask.
|
||||
/// </summary>
|
||||
public void SetMaskInteraction(SpriteMaskInteraction layer0, SpriteMaskInteraction layer1, SpriteMaskInteraction layer2, SpriteMaskInteraction layer3)
|
||||
{
|
||||
m_MaskInteraction = (int)layer0 + ((int)layer1 << 2) + ((int)layer2 << 4) + ((int)layer3 << 6);
|
||||
if (graphic)
|
||||
{
|
||||
graphic.SetMaterialDirty();
|
||||
}
|
||||
}
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
|
@ -138,7 +174,13 @@ namespace Coffee.UIExtensions
|
|||
Material _maskMaterial = null;
|
||||
static int s_SoftMaskTexId;
|
||||
static int s_StencilCompId;
|
||||
static int s_SoftMaskInverseId;
|
||||
static int s_MaskInteractionId;
|
||||
static int s_SceneVId;
|
||||
static int s_ScenePId;
|
||||
static int s_GameVPId;
|
||||
static List<SoftMaskable> s_ActiveSoftMaskables;
|
||||
static int[] s_Interactions = new int[4];
|
||||
static Material s_DefaultMaterial;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
|
@ -156,16 +198,30 @@ namespace Coffee.UIExtensions
|
|||
Matrix4x4 w2c = cam.worldToCameraMatrix;
|
||||
Matrix4x4 prj = cam.projectionMatrix;
|
||||
|
||||
s_ActiveSoftMaskables.RemoveAll(x=>!x);
|
||||
foreach (var sm in s_ActiveSoftMaskables)
|
||||
{
|
||||
if(sm)
|
||||
if (!sm || !sm._maskMaterial || !sm.graphic || !sm.graphic.canvas)
|
||||
{
|
||||
Material mat = sm._maskMaterial;
|
||||
if (mat)
|
||||
{
|
||||
mat.SetMatrix ("_SceneView", w2c);
|
||||
mat.SetMatrix ("_SceneProj", prj);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Material mat = sm._maskMaterial;
|
||||
mat.SetMatrix(s_SceneVId, w2c);
|
||||
mat.SetMatrix(s_ScenePId, prj);
|
||||
|
||||
var c = sm.graphic.canvas.rootCanvas;
|
||||
if (c.renderMode != RenderMode.ScreenSpaceOverlay && c.worldCamera)
|
||||
{
|
||||
var wcam = c.worldCamera;
|
||||
var pv = wcam.projectionMatrix * wcam.worldToCameraMatrix;
|
||||
mat.SetMatrix(s_GameVPId, pv);
|
||||
}
|
||||
else
|
||||
{
|
||||
var pos = c.transform.localPosition;
|
||||
var pv = Matrix4x4.TRS(new Vector3(0, 0, 0), Quaternion.identity, new Vector3(1 / pos.x, 1 / pos.y, -2 / 1000f)) * Matrix4x4.Translate(-pos);
|
||||
mat.SetMatrix(s_GameVPId, pv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -194,11 +250,14 @@ namespace Coffee.UIExtensions
|
|||
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.update += UpdateSceneViewMatrixForShader;
|
||||
s_SceneVId = Shader.PropertyToID("_SceneV");
|
||||
s_ScenePId = Shader.PropertyToID("_SceneP");
|
||||
s_GameVPId = Shader.PropertyToID("_GameVP");
|
||||
#endif
|
||||
|
||||
s_SoftMaskTexId = Shader.PropertyToID("_SoftMaskTex");
|
||||
s_StencilCompId = Shader.PropertyToID("_StencilComp");
|
||||
s_SoftMaskInverseId = Shader.PropertyToID("_SoftMaskInverse");
|
||||
s_MaskInteractionId = Shader.PropertyToID("_MaskInteraction");
|
||||
}
|
||||
s_ActiveSoftMaskables.Add(this);
|
||||
|
||||
|
@ -208,7 +267,7 @@ namespace Coffee.UIExtensions
|
|||
{
|
||||
if (!g.material || g.material == Graphic.defaultGraphicMaterial)
|
||||
{
|
||||
g.material = defaultMaterial ?? (defaultMaterial = new Material (Resources.Load<Shader> ("UI-Default-SoftMask")) { hideFlags = HideFlags.HideAndDontSave, });
|
||||
g.material = s_DefaultMaterial ?? (s_DefaultMaterial = new Material(Resources.Load<Shader>("UI-Default-SoftMask")) { hideFlags = HideFlags.HideAndDontSave, });
|
||||
}
|
||||
g.SetMaterialDirty();
|
||||
}
|
||||
|
@ -225,7 +284,7 @@ namespace Coffee.UIExtensions
|
|||
var g = graphic;
|
||||
if (g)
|
||||
{
|
||||
if (g.material == defaultMaterial)
|
||||
if (g.material == s_DefaultMaterial)
|
||||
{
|
||||
g.material = null;
|
||||
}
|
||||
|
@ -258,5 +317,21 @@ namespace Coffee.UIExtensions
|
|||
mat = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
#pragma warning disable 0612
|
||||
if (m_Inverse)
|
||||
{
|
||||
m_Inverse = false;
|
||||
m_MaskInteraction = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||
}
|
||||
#pragma warning restore 0612
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ SubShader {
|
|||
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
|
||||
LOD 100
|
||||
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
ColorMask [_ColorMask]
|
||||
|
|
|
@ -102,15 +102,13 @@ Shader "UI/Default-SoftMask"
|
|||
{
|
||||
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
|
||||
|
||||
#ifdef UNITY_UI_CLIP_RECT
|
||||
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_UI_ALPHACLIP
|
||||
clip (color.a - 0.001);
|
||||
#endif
|
||||
|
||||
color.a *= SoftMask(IN.vertex); // Add for soft mask
|
||||
color.a *= SoftMask(IN.vertex, IN.worldPosition); // Add for soft mask
|
||||
|
||||
return color;
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
#define UI_SOFTMASK_INCLUDED
|
||||
|
||||
sampler2D _SoftMaskTex;
|
||||
fixed _SoftMaskInverse;
|
||||
float _Stencil;
|
||||
float4x4 _SceneView;
|
||||
float4x4 _SceneProj;
|
||||
|
||||
float4x4 _SceneV;
|
||||
float4x4 _SceneP;
|
||||
float4x4 _GameVP;
|
||||
half4 _MaskInteraction;
|
||||
|
||||
fixed Approximately(float4x4 a, float4x4 b)
|
||||
{
|
||||
|
@ -16,31 +16,36 @@ fixed Approximately(float4x4 a, float4x4 b)
|
|||
max(d._m10,max(d._m11,max(d._m12,max(d._m13,
|
||||
max(d._m20,max(d._m21,max(d._m22,max(d._m23,
|
||||
max(d._m30,max(d._m31,max(d._m32,d._m33))))))))))))))),
|
||||
0.01);
|
||||
1);
|
||||
}
|
||||
|
||||
half SoftMask(float4 clipPos)
|
||||
fixed GetMaskAlpha(fixed alpha, fixed stencilId, fixed interaction)
|
||||
{
|
||||
fixed onStencil = step(stencilId, _Stencil);
|
||||
alpha = lerp(1, alpha, onStencil * step(1, interaction));
|
||||
return lerp(alpha, 1 - alpha, onStencil * step(2, interaction));
|
||||
}
|
||||
|
||||
half SoftMask(float4 clipPos, float4 wpos)
|
||||
{
|
||||
half2 view = clipPos.xy/_ScreenParams.xy;
|
||||
#if SOFTMASK_EDITOR
|
||||
fixed isSceneView = max(Approximately(UNITY_MATRIX_V, _SceneV), Approximately(UNITY_MATRIX_P, _SceneP));
|
||||
float4 cpos = mul(_GameVP, mul(UNITY_MATRIX_M, wpos));
|
||||
view = lerp(view, cpos.xy / cpos.w * 0.5 + 0.5, isSceneView);
|
||||
#endif
|
||||
|
||||
#if UNITY_UV_STARTS_AT_TOP
|
||||
view.y = 1.0 - view.y;
|
||||
#endif
|
||||
|
||||
half alpha =
|
||||
lerp(1, tex2D(_SoftMaskTex, view).a, step(15, _Stencil))
|
||||
* lerp(1, tex2D(_SoftMaskTex, view).b, step(7, _Stencil))
|
||||
* lerp(1, tex2D(_SoftMaskTex, view).g, step(3, _Stencil))
|
||||
* lerp(1, tex2D(_SoftMaskTex, view).r, step(1, _Stencil));
|
||||
|
||||
alpha = lerp(alpha, 1 - alpha, _SoftMaskInverse);
|
||||
|
||||
#if SOFTMASK_EDITOR
|
||||
fixed isSceneView = max(Approximately(UNITY_MATRIX_V, _SceneView), Approximately(UNITY_MATRIX_P, _SceneProj));
|
||||
alpha = lerp(alpha, 1, isSceneView);
|
||||
#endif
|
||||
fixed4 mask = tex2D(_SoftMaskTex, view);
|
||||
half alpha = GetMaskAlpha(mask.x, 1, _MaskInteraction.x)
|
||||
* GetMaskAlpha(mask.y, 3, _MaskInteraction.y)
|
||||
* GetMaskAlpha(mask.z, 7, _MaskInteraction.z)
|
||||
* GetMaskAlpha(mask.w, 15, _MaskInteraction.w);
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
|
||||
#endif // UI_SOFTMASK_INCLUDED
|
||||
#endif // UI_SOFTMASK_INCLUDED
|
|
@ -2,7 +2,7 @@
|
|||
"name": "com.coffee.softmask-for-ugui",
|
||||
"displayName": "Soft Mask For uGUI",
|
||||
"description": "SoftMask is a smooth masking component for uGUI elements in Unity.\nBy using SoftMask instead of default Mask, rounded edges of UI elements can be expressed beautifully.",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"unity": "2017.1",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
@ -11,6 +11,8 @@
|
|||
},
|
||||
"src": "Assets/Coffee/UIExtensions/SoftMaskForUGUI",
|
||||
"author": "mob-sakai <sakai861104@gmail.com> (https://github.com/mob-sakai)",
|
||||
"editorOnly": false,
|
||||
"upmSupport": true,
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 7.1 KiB |
|
@ -2064,7 +2064,7 @@ MonoBehaviour:
|
|||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: Mask vs SoftMask
|
||||
m_Text: TextMeshPro
|
||||
--- !u!222 &234968673
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -4065,7 +4065,7 @@ RectTransform:
|
|||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1454678126}
|
||||
m_RootOrder: 2
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
|
@ -4540,7 +4540,7 @@ RectTransform:
|
|||
- {fileID: 1231113645}
|
||||
- {fileID: 633508442}
|
||||
m_Father: {fileID: 1454678126}
|
||||
m_RootOrder: 4
|
||||
m_RootOrder: 3
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
|
@ -7547,12 +7547,12 @@ RectTransform:
|
|||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 1864891675}
|
||||
m_Father: {fileID: 1454678126}
|
||||
m_Father: {fileID: 1079849196}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 3.5183, y: -3.5}
|
||||
m_AnchoredPosition: {x: 3.5183, y: 3.4999847}
|
||||
m_SizeDelta: {x: 197.94, y: 197.9}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &717488798
|
||||
|
@ -8615,7 +8615,7 @@ RectTransform:
|
|||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 840664485}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalRotation: {x: 0, y: 1, z: 0, w: 0}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
|
@ -8623,7 +8623,7 @@ RectTransform:
|
|||
- {fileID: 1797995909}
|
||||
m_Father: {fileID: 1983144426}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
|
@ -10479,6 +10479,7 @@ GameObject:
|
|||
- component: {fileID: 1079849199}
|
||||
- component: {fileID: 1079849198}
|
||||
- component: {fileID: 1079849197}
|
||||
- component: {fileID: 1079849200}
|
||||
m_Layer: 5
|
||||
m_Name: Background Button
|
||||
m_TagString: Untagged
|
||||
|
@ -10497,6 +10498,7 @@ RectTransform:
|
|||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 70046605}
|
||||
- {fileID: 714905548}
|
||||
m_Father: {fileID: 1454678126}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
@ -10579,6 +10581,17 @@ CanvasRenderer:
|
|||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1079849195}
|
||||
--- !u!114 &1079849200
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 1079849195}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: -146154839, guid: f70555f144d8491a825f0804e09c671c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &1084240451
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -11567,7 +11580,7 @@ RectTransform:
|
|||
m_LocalScale: {x: 0.9999819, y: 0.9999819, z: 0.9999819}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1454678126}
|
||||
m_RootOrder: 3
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0}
|
||||
m_AnchorMax: {x: 0.5, y: 0}
|
||||
|
@ -14568,7 +14581,6 @@ RectTransform:
|
|||
m_LocalScale: {x: 1.0000144, y: 1.0000144, z: 1.0000144}
|
||||
m_Children:
|
||||
- {fileID: 1079849196}
|
||||
- {fileID: 714905548}
|
||||
- {fileID: 416831082}
|
||||
- {fileID: 1170415755}
|
||||
- {fileID: 469601973}
|
||||
|
@ -15905,10 +15917,9 @@ MonoBehaviour:
|
|||
m_GameObject: {fileID: 1582707149}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 97bc2ebab6563400c95b036136d26ea6, type: 3}
|
||||
m_Script: {fileID: -146154839, guid: f70555f144d8491a825f0804e09c671c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Inverse: 0
|
||||
--- !u!1 &1590748265
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -16007,7 +16018,7 @@ MonoBehaviour:
|
|||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: '>> SoftMask v0.4.0 <<'
|
||||
m_Text: '>> SoftMask v0.5.0 <<'
|
||||
--- !u!222 &1590748270
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -16563,7 +16574,7 @@ RectTransform:
|
|||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 1}
|
||||
m_AnchorMax: {x: 0.5, y: 1}
|
||||
m_AnchoredPosition: {x: -115, y: 44.000008}
|
||||
m_AnchoredPosition: {x: -115, y: 44.000015}
|
||||
m_SizeDelta: {x: 230, y: 44}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!114 &1658073997
|
||||
|
@ -17947,7 +17958,7 @@ RectTransform:
|
|||
- {fileID: 90419014}
|
||||
- {fileID: 1154869346}
|
||||
m_Father: {fileID: 1454678126}
|
||||
m_RootOrder: 5
|
||||
m_RootOrder: 4
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Assets/Coffee/UIExtensions/SoftMaskForUGUI/CHANGELOG.md
|
|
@ -0,0 +1,77 @@
|
|||
# Changelog
|
||||
|
||||
## [v0.5.0](https://github.com/mob-sakai/SoftMaskForUGUI/tree/v0.5.0) (2019-02-01)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v0.4.0...v0.5.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Mask interaction for each layer [\#31](https://github.com/mob-sakai/SoftMaskForUGUI/issues/31)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- SoftMask is not clipped by RectMask2D [\#30](https://github.com/mob-sakai/SoftMaskForUGUI/issues/30)
|
||||
- Does not work with flipped/rotated images [\#27](https://github.com/mob-sakai/SoftMaskForUGUI/issues/27)
|
||||
- SceneView does not display SoftMask properly [\#16](https://github.com/mob-sakai/SoftMaskForUGUI/issues/16)
|
||||
|
||||
## [v0.4.0](https://github.com/mob-sakai/SoftMaskForUGUI/tree/v0.4.0) (2019-01-13)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v0.3.0...v0.4.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Integrate with UnityPackageManager [\#22](https://github.com/mob-sakai/SoftMaskForUGUI/issues/22)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Flipped soft mask texture [\#25](https://github.com/mob-sakai/SoftMaskForUGUI/issues/25)
|
||||
|
||||
## [v0.3.0](https://github.com/mob-sakai/SoftMaskForUGUI/tree/v0.3.0) (2019-01-07)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v0.2.0...v0.3.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Remove TMPro resources in repo [\#21](https://github.com/mob-sakai/SoftMaskForUGUI/issues/21)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- An error occur when SoftMask is destroyed on editor [\#23](https://github.com/mob-sakai/SoftMaskForUGUI/issues/23)
|
||||
|
||||
## [v0.2.0](https://github.com/mob-sakai/SoftMaskForUGUI/tree/v0.2.0) (2018-12-21)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/SoftMaskForUGUI/compare/v0.1.0...v0.2.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Set default material on disable [\#17](https://github.com/mob-sakai/SoftMaskForUGUI/issues/17)
|
||||
- Component icon [\#15](https://github.com/mob-sakai/SoftMaskForUGUI/issues/15)
|
||||
- Support TextMeshPro [\#14](https://github.com/mob-sakai/SoftMaskForUGUI/issues/14)
|
||||
- Preview soft mask buffer in inspector [\#13](https://github.com/mob-sakai/SoftMaskForUGUI/issues/13)
|
||||
- Add a SoftMaskable component to the child UI elements of SoftMask From the inspector [\#12](https://github.com/mob-sakai/SoftMaskForUGUI/issues/12)
|
||||
- Render the soft mask buffer only when needed to improve performance [\#11](https://github.com/mob-sakai/SoftMaskForUGUI/issues/11)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Doesn't work with overlay canvas on 2018.3 [\#20](https://github.com/mob-sakai/SoftMaskForUGUI/issues/20)
|
||||
|
||||
## [v0.1.0](https://github.com/mob-sakai/SoftMaskForUGUI/tree/v0.1.0) (2018-11-20)
|
||||
|
||||
[Full Changelog](https://github.com/mob-sakai/SoftMaskForUGUI/compare/0d87935fa566cd1cb5e54a6f8826bb72fffb29b8...v0.1.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Convert existing Mask to SoftMask from context menu [\#10](https://github.com/mob-sakai/SoftMaskForUGUI/issues/10)
|
||||
- Desample soft mask buffer to improve performance [\#9](https://github.com/mob-sakai/SoftMaskForUGUI/issues/9)
|
||||
- Custom shaders supporting [\#8](https://github.com/mob-sakai/SoftMaskForUGUI/issues/8)
|
||||
- Filter raycast only for the visible part [\#7](https://github.com/mob-sakai/SoftMaskForUGUI/issues/7)
|
||||
- Inverse soft mask [\#6](https://github.com/mob-sakai/SoftMaskForUGUI/issues/6)
|
||||
- Nested soft masks [\#5](https://github.com/mob-sakai/SoftMaskForUGUI/issues/5)
|
||||
- Support multiple-sprites and SpriteAtlas [\#4](https://github.com/mob-sakai/SoftMaskForUGUI/issues/4)
|
||||
- Adjust the visible part [\#3](https://github.com/mob-sakai/SoftMaskForUGUI/issues/3)
|
||||
- Compatible with Mask [\#2](https://github.com/mob-sakai/SoftMaskForUGUI/issues/2)
|
||||
- Screen space soft masking [\#1](https://github.com/mob-sakai/SoftMaskForUGUI/issues/1)
|
||||
|
||||
|
||||
|
||||
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
|
@ -1 +0,0 @@
|
|||
Assets/Coffee/UIExtensions/SoftMaskForUGUI/LICENSE.md
|
|
@ -0,0 +1,7 @@
|
|||
Copyright 2018 mob-sakai
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,320 @@
|
|||
SoftMaskForUGUI
|
||||
===
|
||||
|
||||
Soft masking for uGUI elements in Unity.
|
||||
|
||||

|
||||
|
||||
[](https://github.com/mob-sakai/SoftMaskForUGUI/releases)
|
||||
[](https://github.com/mob-sakai/SoftMaskForUGUI/releases)
|
||||

|
||||
[](https://github.com/mob-sakai/SoftMaskForUGUI/blob/upm/LICENSE.txt)
|
||||
[](http://makeapullrequest.com)
|
||||
[](https://twitter.com/intent/follow?screen_name=mob_sakai)
|
||||
|
||||
<< [Description](#Description) | [WebGL Demo](#demo) | [Download](https://github.com/mob-sakai/SoftMaskForUGUI/releases) | [Usage](#usage) | [Development Note](#development-note) >>
|
||||
|
||||
### What's new? [See changelog ](https://github.com/mob-sakai/SoftMaskForUGUI/blob/develop/CHANGELOG.md)
|
||||
### Do you want to receive notifications for new releases? [Watch this repo ](https://github.com/mob-sakai/SoftMaskForUGUI/subscription)
|
||||
### Support me on Patreon! [](https://www.patreon.com/join/2343451?)
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Description
|
||||
|
||||
SoftMask is a smooth masking component for uGUI elements in Unity.
|
||||
By using SoftMask instead of default Mask, rounded edges of UI elements can be expressed beautifully.
|
||||
|
||||

|
||||
|
||||
#### Features
|
||||
|
||||
* SoftMask is compatible with Mask.
|
||||
* You can adjust the visible part.
|
||||

|
||||
* Text, Image, RawImage can be used as a masking.
|
||||
* Support multiple-sprites and SpriteAtlas.
|
||||
* Support up to 4 nested soft masks.
|
||||

|
||||
* Support scroll view.
|
||||

|
||||
* Support inversed soft mask.
|
||||

|
||||
* Support overlay, camera space and world space.
|
||||

|
||||
* Raycast is filtered only for the visible part.
|
||||

|
||||
* Contain soft maskable UI shader.
|
||||
* Support soft masks in your custom shaders by adding just 3 lines. For details, please see [Development Note](#support-soft-masks-in-your-custom-shaders).
|
||||
* Adjust soft mask buffer size to improve performance.
|
||||
* Convert existing Mask to SoftMask from context menu.
|
||||

|
||||
* Render the soft mask buffer only when needed to improve performance.
|
||||
* Add a SoftMaskable component to the child UI elements of SoftMask from the inspector.
|
||||

|
||||
* Preview soft mask buffer in inspector.
|
||||

|
||||
* Support TextMeshPro.
|
||||

|
||||
|
||||
|
||||
#### Components
|
||||
|
||||
|Component|Description|Screenshot|
|
||||
|-|-|-|
|
||||
|SoftMask|Use instead of Mask for smooth masking.<br><br>**Show Mask Graphic:** Show the graphic that is associated with the Mask render area.<br>**Desampling Rate:** The desampling rate for soft mask buffer. The larger the value, the better the performance but the lower the quality.<br>**Softness:** The value used by the soft mask to select the area of influence defined over the soft mask's graphic.<br>**Ignore Parent:** Should the soft mask ignore parent soft masks?|<img src="https://user-images.githubusercontent.com/12690315/50319746-377a0200-050c-11e9-96ae-a3a0ec81765f.png" width="600px">|
|
||||
|SoftMaskable|Add this component to Graphic under SoftMask for smooth masking.<br><br>**Inverse:** The graphic will be visible only in areas where no mask is present.|<img src="https://user-images.githubusercontent.com/12690315/50319747-39dc5c00-050c-11e9-85fa-dd6ea9065daf.png" width="600px">|
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Demo
|
||||
|
||||
[WebGL Demo](http://mob-sakai.github.io/SoftMaskForUGUI)
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Install
|
||||
|
||||
#### Using UnityPackageManager (for Unity 2018.3+)
|
||||
|
||||
Find the manifest.json file in the Packages folder of your project and edit it to look like this:
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"com.coffee.softmask-for-ugui": "https://github.com/mob-sakai/SoftMaskForUGUI.git#0.5.0",
|
||||
...
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### Using .unitypackage file (for Unity 2017.1+)
|
||||
|
||||
Download `*.unitypackage` from [Releases](https://github.com/mob-sakai/SoftMaskForUGUI/releases) and import the package into your Unity project.
|
||||
Select `Assets > Import Package > Custom Package` from the menu.
|
||||

|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## How to play demo
|
||||
|
||||
* Import `SoftMask_Demo.unitypackage` into your project.
|
||||
* The unitypackage exists in `Assets/Assets/Coffee/UIExtensions/SoftMaskForUGUI` or `Packages/Soft Mask For uGUI`.
|
||||

|
||||
* Open SoftMask_Demo scene and play it.
|
||||
* The demo requires `TextMeshPro` and `TextMeshPro Essential Resources`. Import it before playing.
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Usage
|
||||
|
||||
1. Add SoftMask component instead of Mask component.
|
||||
Or, convert existing Mask component to SoftMask component from the context menu.
|
||||

|
||||
2. Add SoftMaskable components to the child UI elements of SoftMask component.
|
||||

|
||||
Or, add SoftMaskable components from the inspector of SoftMask component.
|
||||

|
||||
3. Adjust softness of SoftMask.
|
||||

|
||||
4. Enjoy!
|
||||
|
||||
|
||||
##### Requirement
|
||||
|
||||
* Unity 2017+ *(including Unity 2018.x)*
|
||||
* No other SDK are required
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## Development Note
|
||||
|
||||
#### Support soft masks in your custom shaders
|
||||
|
||||
You can support soft masks in your custom shaders, by adding just 3 lines!
|
||||
|
||||
1. Add `#pragma` and `#include`. `SOFTMASK_EDITOR` is a keyword for editor, not included in the build.
|
||||
```
|
||||
#include "Assets/Coffee/UIExtensions/SoftMaskForUGUI/SoftMask.cginc"
|
||||
#pragma shader_feature __ SOFTMASK_EDITOR
|
||||
```
|
||||
2. Apply a soft mask in the fragment shader. `IN.vertex` is clip position.
|
||||
```
|
||||
color.a *= SoftMask(IN.vertex);
|
||||
```
|
||||
|
||||
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).
|
||||
|
||||
|
||||
<br><br>
|
||||
#### Tips: Convert component from context menu
|
||||
|
||||
Converting components from the context menu is very convenient.
|
||||
You can convert multiple components at the same time, without having to remove the source components.
|
||||
|
||||

|
||||
|
||||
If the destination component has the same properties as the source component, the value is set automatically.
|
||||
|
||||
In addition, if the destination component is compatible with the source component, it will not lose its reference.
|
||||
For example, if `public Mask mask;` refers to a Mask, converting it to SoftMask in this way does not lose references.
|
||||
|
||||
This way consists of two generic methods.
|
||||
|
||||
```cs
|
||||
/// <summary>
|
||||
/// Verify whether it can be converted to the specified component.
|
||||
/// </summary>
|
||||
protected static bool CanConvertTo<T>(Object context)
|
||||
where T : MonoBehaviour
|
||||
{
|
||||
return context && context.GetType() != typeof(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert to the specified component.
|
||||
/// </summary>
|
||||
protected static void ConvertTo<T>(Object context) where T : MonoBehaviour
|
||||
{
|
||||
var target = context as MonoBehaviour;
|
||||
var so = new SerializedObject(target);
|
||||
so.Update();
|
||||
|
||||
bool oldEnable = target.enabled;
|
||||
target.enabled = false;
|
||||
|
||||
// Find MonoScript of the specified component.
|
||||
foreach (var script in Resources.FindObjectsOfTypeAll<MonoScript>())
|
||||
{
|
||||
if (script.GetClass() != typeof(T))
|
||||
continue;
|
||||
|
||||
// Set 'm_Script' to convert.
|
||||
so.FindProperty("m_Script").objectReferenceValue = script;
|
||||
so.ApplyModifiedProperties();
|
||||
break;
|
||||
}
|
||||
|
||||
(so.targetObject as MonoBehaviour).enabled = oldEnable;
|
||||
}
|
||||
```
|
||||
|
||||
In SoftMask, they are implemented as follows.
|
||||
* Mask and SoftMask can be converted to each other.
|
||||
* If conversion is not possible, gray out the context menu.
|
||||
|
||||
```cs
|
||||
[MenuItem("CONTEXT/Mask/Convert To SoftMask", true)]
|
||||
static bool _ConvertToSoftMask(MenuCommand command)
|
||||
{
|
||||
return CanConvertTo<SoftMask>(command.context);
|
||||
}
|
||||
[MenuItem("CONTEXT/Mask/Convert To SoftMask", false)]
|
||||
static void ConvertToSoftMask(MenuCommand command)
|
||||
{
|
||||
ConvertTo<SoftMask>(command.context);
|
||||
}
|
||||
[MenuItem("CONTEXT/Mask/Convert To Mask", true)]
|
||||
static bool _ConvertToMask(MenuCommand command)
|
||||
{
|
||||
return CanConvertTo<Mask>(command.context);
|
||||
}
|
||||
[MenuItem("CONTEXT/Mask/Convert To Mask", false)]
|
||||
static void ConvertToMask(MenuCommand command)
|
||||
{
|
||||
ConvertTo<Mask>(command.context);
|
||||
}
|
||||
```
|
||||
|
||||
For details, please see [SoftMaskEditor.cs](https://raw.githubusercontent.com/mob-sakai/SoftMaskForUGUI/upm/Scripts/Editor/SoftMaskEditor.cs).
|
||||
|
||||
|
||||
<br><br>
|
||||
#### Tips: Shader code for editor only
|
||||
|
||||
Do you know how to implement shader code "for editor only"?
|
||||
SoftMask uses `SOFTMASK_EDITOR` keyword in shader code to determine whether it is running in the editor.
|
||||
|
||||
`#pragma shader_feature __ SOFTMASK_EDITOR`
|
||||
|
||||
`SOFTMASK_EDITOR` keyword is set from the editor script, but it is not set after it is built. Also, this shader variant will be excluded from build.
|
||||
|
||||
```cs
|
||||
#if UNITY_EDITOR
|
||||
material = new Material(shader);
|
||||
material.hideFlags = HideFlags.HideAndDontSave;
|
||||
material.EnableKeyword("SOFTMASK_EDITOR");
|
||||
#endif
|
||||
```
|
||||
|
||||
|
||||
<br><br>
|
||||
#### Tips: Shader code for SceneView only
|
||||
|
||||
Do you know how to implement shader code "for SceneView only"?
|
||||
SoftMask understands that the current rendering is for SceneView, when SceneView's view projection matrix and UNITY_MATRIX_VP match.
|
||||
|
||||
`fixed isSceneView = 1 - any(UNITY_MATRIX_VP - _SceneViewVP);`
|
||||
|
||||
Actually, because of the movement operation in SceneView, use "approximate" instead of "match".
|
||||
|
||||
```cs
|
||||
float4x4 _SceneViewVP;
|
||||
|
||||
fixed Approximate(float4x4 a, float4x4 b)
|
||||
{
|
||||
float4x4 d = abs(a - b);
|
||||
return step(
|
||||
max(d._m00,max(d._m01,max(d._m02,max(d._m03,
|
||||
max(d._m10,max(d._m11,max(d._m12,max(d._m13,
|
||||
max(d._m20,max(d._m21,max(d._m22,max(d._m23,
|
||||
max(d._m30,max(d._m31,max(d._m32,d._m33))))))))))))))),
|
||||
0.01);
|
||||
}
|
||||
|
||||
fixed isSceneView = Approximate(UNITY_MATRIX_VP, _SceneViewVP);
|
||||
```
|
||||
|
||||
`_SceneViewVP` is set every frame from the editor script.
|
||||
|
||||
```cs
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.update += ()
|
||||
{
|
||||
Camera cam = UnityEditor.SceneView.lastActiveSceneView.camera;
|
||||
Matrix4x4 vp = cam.projectionMatrix * cam.worldToCameraMatrix;
|
||||
material.SetMatrix("_SceneViewVP", vp);
|
||||
};
|
||||
#endif
|
||||
```
|
||||
|
||||
|
||||
|
||||
<br><br><br><br>
|
||||
## License
|
||||
|
||||
* MIT
|
||||
* © UTJ/UCL
|
||||
|
||||
|
||||
|
||||
## Author
|
||||
|
||||
[mob-sakai](https://github.com/mob-sakai)
|
||||
[](https://twitter.com/intent/follow?screen_name=mob_sakai)
|
||||
[](https://www.patreon.com/join/2343451?)
|
||||
|
||||
|
||||
|
||||
## See Also
|
||||
|
||||
* GitHub page : https://github.com/mob-sakai/SoftMaskForUGUI
|
||||
* Releases : https://github.com/mob-sakai/SoftMaskForUGUI/releases
|
||||
* Issue tracker : https://github.com/mob-sakai/SoftMaskForUGUI/issues
|
||||
* Current project : https://github.com/mob-sakai/SoftMaskForUGUI/projects/1
|
||||
* Change log : https://github.com/mob-sakai/SoftMaskForUGUI/blob/upm/CHANGELOG.md
|
|
@ -1 +0,0 @@
|
|||
Assets/Coffee/UIExtensions/SoftMaskForUGUI/package.json
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "com.coffee.softmask-for-ugui",
|
||||
"displayName": "Soft Mask For uGUI",
|
||||
"description": "SoftMask is a smooth masking component for uGUI elements in Unity.\nBy using SoftMask instead of default Mask, rounded edges of UI elements can be expressed beautifully.",
|
||||
"version": "0.5.0",
|
||||
"unity": "2017.1",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mob-sakai/SoftMaskForUGUI.git"
|
||||
},
|
||||
"src": "Assets/Coffee/UIExtensions/SoftMaskForUGUI",
|
||||
"author": "mob-sakai <sakai861104@gmail.com> (https://github.com/mob-sakai)",
|
||||
"editorOnly": false,
|
||||
"upmSupport": true,
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# NOTE: Run the following command at the prompt
|
||||
# bash <(curl -sL 'https://gist.github.com/mob-sakai/a883999a32dd8b1927639e46b3cd6801/raw/unity_release.sh')
|
||||
# bash <(curl -sL 'https://gist.github.com/mob-sakai/e281baa04e1a47148b62387f9c7967df/raw/unity_release.sh')
|
||||
# NOTE: Set an environment variable `CHANGELOG_GITHUB_TOKEN` by running the following command at the prompt, or by adding it to your shell profile (e.g., ~/.bash_profile or ~/.zshrc):
|
||||
# export CHANGELOG_GITHUB_TOKEN="«your-40-digit-github-token»"
|
||||
|
||||
|
@ -12,6 +12,8 @@ echo -e ">> Start Github Release:"
|
|||
PACKAGE_NAME=`node -pe 'require("./package.json").name'`
|
||||
echo -e ">> Package name: ${PACKAGE_NAME}"
|
||||
CURRENT_VERSION=`grep -o -e "\"version\".*$" package.json | sed -e "s/\"version\": \"\(.*\)\".*$/\1/"`
|
||||
EDITOR_ONLY=`grep -o -e "\"editorOnly\".*$" package.json | sed -e "s/\"editorOnly\": \(.*\),$/\1/"`
|
||||
UNITY_PACKAGE_MANAGER=`grep -o -e "\"upmSupport\".*$" package.json | sed -e "s/\"upmSupport\": \(.*\),$/\1/"`
|
||||
|
||||
read -p "[? (1/8) Input release version (for current: ${CURRENT_VERSION}): " RELEASE_VERSION
|
||||
[ -z "${RELEASE_VERSION}" ] && exit
|
||||
|
@ -19,11 +21,13 @@ read -p "[? (1/8) Input release version (for current: ${CURRENT_VERSION}): " REL
|
|||
read -p "[? Are the issues on this release closed all? (y/N):" yn
|
||||
case "$yn" in [yY]*) ;; *) exit ;; esac
|
||||
|
||||
read -p "[? Is package editor only? (y/N):" yn
|
||||
case "$yn" in [yY]*) EDITOR_ONLY=true;; *) ;; esac
|
||||
[ -z $EDITOR_ONLY ] && read -p "[? Is package editor only? (y/N):" ynEditorOnly
|
||||
case "$ynEditorOnly" in [yY]*) EDITOR_ONLY=true;; *) ;; esac
|
||||
|
||||
read -p "[? Is package for UnityPackageManager? (y/N):" yn
|
||||
case "$yn" in [yY]*) UNITY_PACKAGE_MANAGER=true;; *) ;; esac
|
||||
[ -z $UNITY_PACKAGE_MANAGER ] && read -p "[? Is package for UnityPackageManager? (y/N):" ynUPM
|
||||
case "$ynUPM" in [yY]*) UNITY_PACKAGE_MANAGER=true;; *) ;; esac
|
||||
|
||||
[ "$UNITY_PACKAGE_MANAGER" == "true" ] && RELEASE_VERSION_TAG="${RELEASE_VERSION}" || RELEASE_VERSION_TAG="v${RELEASE_VERSION}"
|
||||
|
||||
echo -e ">> OK"
|
||||
|
||||
|
@ -31,10 +35,8 @@ echo -e ">> OK"
|
|||
|
||||
# 2. << Update version in package.json >>
|
||||
echo -e "\n>> (2/8) Update version... package.json"
|
||||
[ -L package.json ] && PKG_JSON_PATH=`readlink package.json` || PKG_JSON_PATH=package.json
|
||||
git checkout -B release develop
|
||||
sed -i -e "s/\"version\": \(.*\)/\"version\": \"${RELEASE_VERSION}\",/g" "${PKG_JSON_PATH}"
|
||||
rm "${PKG_JSON_PATH}-e"
|
||||
sed -i '' -e "s/\"version\": \(.*\)/\"version\": \"${RELEASE_VERSION}\",/g" package.json
|
||||
echo -e ">> OK"
|
||||
|
||||
|
||||
|
@ -45,7 +47,7 @@ UNITY_EDITOR="/Applications/Unity/Hub/Editor/${UNITY_VER}/Unity.app/Contents/Mac
|
|||
UNITY_LOG="unity.log"
|
||||
UNITY_ARGS="-quit -batchmode -projectPath `pwd` -logFile $UNITY_LOG"
|
||||
UNITY_PACKAGE_SRC=`node -pe 'require("./package.json").src'`
|
||||
UNITY_PACKAGE_NAME="${PACKAGE_NAME}_${RELEASE_VERSION}.unitypackage"
|
||||
UNITY_PACKAGE_NAME="${PACKAGE_NAME}_v${RELEASE_VERSION_TAG}.unitypackage"
|
||||
echo -e "\n>> (3/8) Check exporting package is available..."
|
||||
echo -e "Version: $UNITY_VER ($UNITY_EDITOR)"
|
||||
echo -e "Package Source: $UNITY_PACKAGE_SRC"
|
||||
|
@ -73,11 +75,11 @@ set -e
|
|||
|
||||
# 4. << Generate change log >>
|
||||
CHANGELOG_GENERATOR_ARG=`grep -o -e ".*git\"$" package.json | sed -e "s/^.*\/\([^\/]*\)\/\([^\/]*\).git.*$/--user \1 --project \2/"`
|
||||
CHANGELOG_GENERATOR_ARG="--future-release ${RELEASE_VERSION} ${CHANGELOG_GENERATOR_ARG}"
|
||||
CHANGELOG_GENERATOR_ARG="--future-release v${RELEASE_VERSION_TAG} ${CHANGELOG_GENERATOR_ARG}"
|
||||
echo -e "\n>> (4/8) Generate change log... ${CHANGELOG_GENERATOR_ARG}"
|
||||
github_changelog_generator ${CHANGELOG_GENERATOR_ARG}
|
||||
|
||||
[ -L CHANGELOG.md ] && git diff -- `readlink CHANGELOG.md` || git diff -- CHANGELOG.md
|
||||
git diff -- CHANGELOG.md
|
||||
read -p "[? Is the change log correct? (y/N):" yn
|
||||
case "$yn" in [yY]*) ;; *) exit ;; esac
|
||||
echo -e ">> OK"
|
||||
|
@ -87,6 +89,7 @@ echo -e ">> OK"
|
|||
# 5. << Export unitypackage >>
|
||||
echo -e "\n>> (5/8) Export unitypackage..."
|
||||
set +e
|
||||
cp -f package.json CHANGELOG.md README.md $UNITY_PACKAGE_SRC
|
||||
"$UNITY_EDITOR" $UNITY_ARGS -exportpackage $UNITY_PACKAGE_SRC $UNITY_PACKAGE_NAME
|
||||
[ $? != 0 ] && echo -e "\n>> Error : \n`cat $UNITY_LOG | grep -E ': error CS|Fatal Error'`" && exit
|
||||
set -e
|
||||
|
@ -96,26 +99,17 @@ echo -e ">> OK"
|
|||
|
||||
# 6. << Commit release files >>
|
||||
echo -e "\n>> (6/8) Commit release files..."
|
||||
[ -L CHANGELOG.md ] && git add -- "`readlink CHANGELOG.md`" || git add -- CHANGELOG.md
|
||||
[ -L package.json ] && git add -- "`readlink package.json`" || git add -- package.json
|
||||
git commit -m "update change log"
|
||||
git add -u
|
||||
git commit -m "update documents for v$RELEASE_VERSION_TAG"
|
||||
echo -e ">> OK"
|
||||
|
||||
|
||||
|
||||
# 7. << Split for upm >>
|
||||
if [ "$UNITY_PACKAGE_MANAGER" == "true" ]; then
|
||||
echo -e "\n>> Split for upm..."
|
||||
git subtree split --prefix="$UNITY_PACKAGE_SRC" --branch upm
|
||||
git push origin upm
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# 7. << Merge and push master and develop branch >>
|
||||
echo -e "\n>> (7/8) Merge and push..."
|
||||
git checkout master
|
||||
git merge --no-ff release -m "release $RELEASE_VERSION"
|
||||
git merge --no-ff release -m "release v$RELEASE_VERSION_TAG"
|
||||
git branch -D release
|
||||
git push origin master
|
||||
git checkout develop
|
||||
|
@ -127,11 +121,18 @@ echo -e ">> OK"
|
|||
|
||||
# 8. << Upload unitypackage and release on Github >>
|
||||
echo -e "\n>> (8/8) Releasing..."
|
||||
[ "$UNITY_PACKAGE_MANAGER" == "true" ] && git checkout upm -f
|
||||
gh-release --assets $UNITY_PACKAGE_NAME --name $RELEASE_VERSION --tag_name $RELEASE_VERSION
|
||||
gh-release --assets $UNITY_PACKAGE_NAME
|
||||
echo -e ">> OK"
|
||||
|
||||
|
||||
|
||||
# 9. << Split for upm >>
|
||||
if [ "$UNITY_PACKAGE_MANAGER" == "true" ]; then
|
||||
echo -e "\n>> Split for upm..."
|
||||
git subtree split --prefix="$UNITY_PACKAGE_SRC" --branch upm
|
||||
git push origin upm
|
||||
fi
|
||||
|
||||
echo -e "\n\n>> $PACKAGE_NAME $RELEASE_VERSION has been successfully released!\n"
|
||||
|
||||
|
||||
echo -e "\n\n>> $PACKAGE_NAME v$RELEASE_VERSION_TAG has been successfully released!\n"
|
Loading…
Reference in New Issue