You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
8.6 KiB
C#
281 lines
8.6 KiB
C#
/******************************************************************************/
|
|
/*
|
|
Project - MudBun
|
|
Publisher - Long Bunny Labs
|
|
http://LongBunnyLabs.com
|
|
Author - Ming-Lun "Allen" Chou
|
|
http://AllenChou.net
|
|
*/
|
|
/******************************************************************************/
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace MudBun
|
|
{
|
|
[ExecuteInEditMode]
|
|
[RequireComponent(typeof(MudMaterial))]
|
|
public class MudSolid : MudBrush
|
|
{
|
|
public enum SymmetryMode
|
|
{
|
|
None,
|
|
FlipX,
|
|
MirrorX,
|
|
FlipMirrorX,
|
|
}
|
|
|
|
public static Aabb SymmetryBounds(SymmetryMode mode, Aabb bounds)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case SymmetryMode.FlipX:
|
|
{
|
|
Vector3 center = bounds.Center;
|
|
Vector3 extent = bounds.Extent;
|
|
center.x = -center.x;
|
|
bounds = new Aabb(center - extent, center + extent);
|
|
break;
|
|
}
|
|
|
|
case SymmetryMode.MirrorX:
|
|
{
|
|
Vector3 newMin = bounds.Min;
|
|
newMin.x = -Mathf.Max(0.0f, bounds.Max.x);
|
|
bounds = new Aabb(newMin, bounds.Max);
|
|
break;
|
|
}
|
|
|
|
case SymmetryMode.FlipMirrorX:
|
|
{
|
|
Vector3 center = bounds.Center;
|
|
Vector3 extent = bounds.Extent;
|
|
center.x = -center.x;
|
|
bounds = new Aabb(center - extent, center + extent);
|
|
Vector3 newMin = bounds.Min;
|
|
newMin.x = -Mathf.Max(0.0f, bounds.Max.x);
|
|
bounds = new Aabb(newMin, bounds.Max);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bounds.IsEmpty)
|
|
return Aabb.Empty;
|
|
|
|
return bounds;
|
|
}
|
|
|
|
public override Aabb BoundsRs => SymmetryBounds(m_symmetry, base.BoundsRs);
|
|
|
|
[SerializeField] private SdfBrush.OperatorEnum m_operator = SdfBrush.OperatorEnum.Union;
|
|
public SdfBrush.OperatorEnum Operator { get => m_operator; set { m_operator = value; MarkDirty(); } }
|
|
|
|
[SerializeField] [ConditionalField("m_operator", SdfBrush.OperatorEnum.Union, SdfBrush.OperatorEnum.Subtract, SdfBrush.OperatorEnum.Intersect, Label = " Type")]
|
|
private SdfBrush.BooleanOperatorTypeEnum m_booleanOperatorType = SdfBrush.BooleanOperatorTypeEnum.Cubic;
|
|
public SdfBrush.BooleanOperatorTypeEnum BooleanOperatorType { get => m_booleanOperatorType; set { m_booleanOperatorType = value; MarkDirty(); } }
|
|
|
|
[SerializeField] [ConditionalField("m_operator", SdfBrush.OperatorEnum.Dye, Label = " Blend Mode")]
|
|
private SdfBrush.DyeBlendModeEnum m_dyeBlendMode = SdfBrush.DyeBlendModeEnum.Overwrite;
|
|
public SdfBrush.DyeBlendModeEnum DyeBlendMode { get => m_dyeBlendMode; set { m_dyeBlendMode = value; MarkDirty(); } }
|
|
|
|
[SerializeField] private float m_blend;
|
|
public float Blend { get => m_blend; set { m_blend = value; MarkDirty(); } }
|
|
|
|
// TODO: not ready for auto-rigging yet
|
|
[SerializeField] private SymmetryMode m_symmetry = SymmetryMode.None;
|
|
public SymmetryMode Symmetry { get => m_symmetry; set { m_symmetry = value; MarkDirty(); } }
|
|
|
|
[Tooltip("If checked, this brush will be counted as bone during auto rigging.")]
|
|
[SerializeField] [ConditionalField("m_canCountAsBone", true)] public bool m_countAsBone = true;
|
|
[SerializeField] [HideInInspector] protected bool m_canCountAsBone = true;
|
|
public override bool CountAsBone => m_countAsBone || (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal); // Metal is weird
|
|
//[ConditionalField("m_mirrorX", true, Label = " Create Mirrored Bone")] public bool CreateMirroredBone = true;
|
|
|
|
public override float BoundsRsPadding => m_blend;
|
|
public override bool ShouldUseAccumulatedBounds
|
|
{
|
|
get
|
|
{
|
|
switch (m_operator)
|
|
{
|
|
case SdfBrush.OperatorEnum.Intersect:
|
|
case SdfBrush.OperatorEnum.Pipe:
|
|
case SdfBrush.OperatorEnum.CullOutside:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal override bool UsesMaterial => true;
|
|
internal override int MaterialHash => GetComponent<MudMaterial>().MaterialHash;
|
|
|
|
internal MudMaterial m_material;
|
|
|
|
public override void SanitizeParameters()
|
|
{
|
|
base.SanitizeParameters();
|
|
|
|
Validate.NonNegative(ref m_blend);
|
|
}
|
|
|
|
public override void FillBrushData(ref SdfBrush brush, int iBrush)
|
|
{
|
|
base.FillBrushData(ref brush, iBrush);
|
|
|
|
brush.Operator = SdfBrush.GetShaderOperatorIntValue(m_operator, m_booleanOperatorType, m_dyeBlendMode);
|
|
brush.Blend = Blend;
|
|
|
|
if (!m_material)
|
|
m_material = GetComponent<MudMaterial>();
|
|
#if MUDBUN_DEV
|
|
Assert.True(m_material != null, "Mussing brush material. A solid brush must have a MudMaterial component.");
|
|
#endif
|
|
|
|
brush.Flags.AssignBit((int) SdfBrush.FlagBit.ContributeMaterial, m_material.ContributeMaterial);
|
|
|
|
switch (m_symmetry)
|
|
{
|
|
case SymmetryMode.FlipX:
|
|
brush.Flags.SetBit((int) SdfBrush.FlagBit.FlipX);
|
|
break;
|
|
|
|
case SymmetryMode.MirrorX:
|
|
brush.Flags.SetBit((int) SdfBrush.FlagBit.MirrorX);
|
|
break;
|
|
|
|
case SymmetryMode.FlipMirrorX:
|
|
brush.Flags.SetBit((int) SdfBrush.FlagBit.FlipX);
|
|
brush.Flags.SetBit((int) SdfBrush.FlagBit.MirrorX);
|
|
break;
|
|
}
|
|
|
|
brush.Flags.AssignBit((int) SdfBrush.FlagBit.CountAsBone, CountAsBone);
|
|
//brush.Flags.AssignBit((int) SdfBrush.FlagBit.CreateMirroredBone, CreateMirroredBone);
|
|
}
|
|
|
|
public override void FillBrushMaterialData(ref SdfBrushMaterial mat)
|
|
{
|
|
base.FillBrushMaterialData(ref mat);
|
|
|
|
if (!m_material)
|
|
m_material = GetComponent<MudMaterial>();
|
|
#if MUDBUN_DEV
|
|
Assert.True(m_material != null, "Missing brush material. A solid brush must have a MudMaterial component.");
|
|
#endif
|
|
|
|
mat.Color = m_material.Color;
|
|
mat.EmissionHash = m_material.Emission;
|
|
mat.MetallicSmoothnessSizeTightness.Set(m_material.Metallic, m_material.Smoothness, m_material.SplatSize, m_material.BlendTightness);
|
|
mat.TextureWeight.Set
|
|
(
|
|
(m_material.TextureIndex == 0 ? 1.0f : 0.0f),
|
|
(m_material.TextureIndex == 1 ? 1.0f : 0.0f),
|
|
(m_material.TextureIndex == 2 ? 1.0f : 0.0f),
|
|
(m_material.TextureIndex == 3 ? 1.0f : 0.0f)
|
|
);
|
|
}
|
|
|
|
public override void ValidateMaterial()
|
|
{
|
|
var material = GetComponent<MudMaterial>();
|
|
if (material != null)
|
|
return;
|
|
|
|
material = gameObject.AddComponent<MudMaterial>();
|
|
}
|
|
|
|
private bool OperatorShouldDrawOutline(SdfBrush.OperatorEnum op)
|
|
{
|
|
if (Renderer != null
|
|
&& Renderer.ClickSelection != MudRendererBase.ClickSelectionEnum.Gizmos)
|
|
return false;
|
|
|
|
switch (op)
|
|
{
|
|
case SdfBrush.OperatorEnum.Union:
|
|
{
|
|
if (Renderer == null)
|
|
break;
|
|
|
|
if (Renderer.RenderModeCategory != MudRendererBase.RenderModeCategoryEnum.Splats)
|
|
break;
|
|
|
|
var material = GetComponent<MudMaterial>();
|
|
if (material == null)
|
|
break;
|
|
|
|
return
|
|
Renderer.SplatSize * material.SplatSize < 0.1f
|
|
|| material.Color.a < 0.25f;
|
|
}
|
|
|
|
case SdfBrush.OperatorEnum.Subtract:
|
|
case SdfBrush.OperatorEnum.Intersect:
|
|
case SdfBrush.OperatorEnum.Pipe:
|
|
case SdfBrush.OperatorEnum.Engrave:
|
|
case SdfBrush.OperatorEnum.CullInside:
|
|
case SdfBrush.OperatorEnum.CullOutside:
|
|
case SdfBrush.OperatorEnum.NoOp:
|
|
return true;
|
|
|
|
default:
|
|
if (SdfBrush.IsDyeOperator(op))
|
|
return true;
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override void DrawGizmosRs()
|
|
{
|
|
base.DrawGizmosRs();
|
|
|
|
bool selected = IsSelected();
|
|
|
|
bool shouldDrawOutlines =
|
|
selected
|
|
|| (Renderer != null
|
|
&& (Renderer.Enable2dMode
|
|
|| Renderer.AlwaysDrawGizmos));
|
|
|
|
if (!shouldDrawOutlines)
|
|
{
|
|
shouldDrawOutlines = OperatorShouldDrawOutline(m_operator);
|
|
}
|
|
|
|
if (!shouldDrawOutlines)
|
|
{
|
|
var parent = transform.parent;
|
|
while (parent != null)
|
|
{
|
|
var groupComp = parent.GetComponent<MudBrushGroup>();
|
|
if (groupComp != null)
|
|
{
|
|
shouldDrawOutlines = OperatorShouldDrawOutline(groupComp.Operator);
|
|
break;
|
|
}
|
|
|
|
if (parent == m_renderer)
|
|
break;
|
|
|
|
parent = parent.parent;
|
|
}
|
|
}
|
|
|
|
if (shouldDrawOutlines)
|
|
{
|
|
Color prevColor = Gizmos.color;
|
|
if (selected)
|
|
Gizmos.color = GizmosUtil.OutlineSelected;
|
|
|
|
DrawOutlineGizmosRs();
|
|
|
|
Gizmos.color = prevColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|