817 lines
26 KiB
C#
817 lines
26 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Es.InkPainter.Effective;
|
|
using UnityEngine;
|
|
|
|
namespace Es.InkPainter
|
|
{
|
|
[RequireComponent(typeof(Renderer))]
|
|
[DisallowMultipleComponent]
|
|
public class InkCanvas : MonoBehaviour
|
|
{
|
|
[Serializable]
|
|
public class PaintSet
|
|
{
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public Material material;
|
|
|
|
[SerializeField]
|
|
[Tooltip("The property name of the main texture.")]
|
|
public string mainTextureName = "_MainTex";
|
|
|
|
[SerializeField]
|
|
[Tooltip("Normal map texture property name.")]
|
|
public string normalTextureName = "_BumpMap";
|
|
|
|
[SerializeField]
|
|
[Tooltip("The property name of the heightmap texture.")]
|
|
public string heightTextureName = "_ParallaxMap";
|
|
|
|
[SerializeField]
|
|
[Tooltip("Whether or not use main texture paint.")]
|
|
public bool useMainPaint = true;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Whether or not use normal map paint (you need material on normal maps).")]
|
|
public bool useNormalPaint;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Whether or not use heightmap painting (you need material on the heightmap).")]
|
|
public bool useHeightPaint;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public Texture mainTexture;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public RenderTexture paintMainTexture;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public Texture normalTexture;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public RenderTexture paintNormalTexture;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public Texture heightTexture;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public RenderTexture paintHeightTexture;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public int mainTexturePropertyID;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public int normalTexturePropertyID;
|
|
|
|
[NonSerialized]
|
|
[HideInInspector]
|
|
public int heightTexturePropertyID;
|
|
|
|
public PaintSet()
|
|
{
|
|
}
|
|
|
|
public PaintSet(string mainTextureName, string normalTextureName, string heightTextureName, bool useMainPaint, bool useNormalPaint, bool useHeightPaint)
|
|
{
|
|
this.mainTextureName = mainTextureName;
|
|
this.normalTextureName = normalTextureName;
|
|
this.heightTextureName = heightTextureName;
|
|
this.useMainPaint = useMainPaint;
|
|
this.useNormalPaint = useNormalPaint;
|
|
this.useHeightPaint = useHeightPaint;
|
|
}
|
|
|
|
public PaintSet(string mainTextureName, string normalTextureName, string heightTextureName, bool useMainPaint, bool useNormalPaint, bool useHeightPaint, Material material)
|
|
: this(mainTextureName, normalTextureName, heightTextureName, useMainPaint, useNormalPaint, useHeightPaint)
|
|
{
|
|
this.material = material;
|
|
}
|
|
}
|
|
|
|
private static Material paintMainMaterial;
|
|
|
|
private static Material paintNormalMaterial;
|
|
|
|
private static Material paintHeightMaterial;
|
|
|
|
private bool eraseFlag;
|
|
|
|
private RenderTexture debugEraserMainView;
|
|
|
|
private RenderTexture debugEraserNormalView;
|
|
|
|
private RenderTexture debugEraserHeightView;
|
|
|
|
private bool eraserDebug;
|
|
|
|
[SerializeField]
|
|
private List<PaintSet> paintSet;
|
|
|
|
private int paintUVPropertyID;
|
|
|
|
private int brushTexturePropertyID;
|
|
|
|
private int brushScalePropertyID;
|
|
|
|
private int brushRotatePropertyID;
|
|
|
|
private int brushColorPropertyID;
|
|
|
|
private int brushNormalTexturePropertyID;
|
|
|
|
private int brushNormalBlendPropertyID;
|
|
|
|
private int brushHeightTexturePropertyID;
|
|
|
|
private int brushHeightBlendPropertyID;
|
|
|
|
private int brushHeightColorPropertyID;
|
|
|
|
private const string COLOR_BLEND_USE_CONTROL = "INK_PAINTER_COLOR_BLEND_USE_CONTROL";
|
|
|
|
private const string COLOR_BLEND_USE_BRUSH = "INK_PAINTER_COLOR_BLEND_USE_BRUSH";
|
|
|
|
private const string COLOR_BLEND_NEUTRAL = "INK_PAINTER_COLOR_BLEND_NEUTRAL";
|
|
|
|
private const string COLOR_BLEND_ALPHA_ONLY = "INK_PAINTER_COLOR_BLEND_ALPHA_ONLY";
|
|
|
|
private const string NORMAL_BLEND_USE_BRUSH = "INK_PAINTER_NORMAL_BLEND_USE_BRUSH";
|
|
|
|
private const string NORMAL_BLEND_ADD = "INK_PAINTER_NORMAL_BLEND_ADD";
|
|
|
|
private const string NORMAL_BLEND_SUB = "INK_PAINTER_NORMAL_BLEND_SUB";
|
|
|
|
private const string NORMAL_BLEND_MIN = "INK_PAINTER_NORMAL_BLEND_MIN";
|
|
|
|
private const string NORMAL_BLEND_MAX = "INK_PAINTER_NORMAL_BLEND_MAX";
|
|
|
|
private const string DXT5NM_COMPRESS_USE = "DXT5NM_COMPRESS_USE";
|
|
|
|
private const string DXT5NM_COMPRESS_UNUSE = "DXT5NM_COMPRESS_UNUSE";
|
|
|
|
private const string HEIGHT_BLEND_USE_BRUSH = "INK_PAINTER_HEIGHT_BLEND_USE_BRUSH";
|
|
|
|
private const string HEIGHT_BLEND_ADD = "INK_PAINTER_HEIGHT_BLEND_ADD";
|
|
|
|
private const string HEIGHT_BLEND_SUB = "INK_PAINTER_HEIGHT_BLEND_SUB";
|
|
|
|
private const string HEIGHT_BLEND_MIN = "INK_PAINTER_HEIGHT_BLEND_MIN";
|
|
|
|
private const string HEIGHT_BLEND_MAX = "INK_PAINTER_HEIGHT_BLEND_MAX";
|
|
|
|
private const string HEIGHT_BLEND_COLOR_RGB_HEIGHT_A = "INK_PAINTER_HEIGHT_BLEND_COLOR_RGB_HEIGHT_A";
|
|
|
|
private MeshOperator meshOperator;
|
|
|
|
public List<PaintSet> PaintDatas
|
|
{
|
|
get
|
|
{
|
|
return paintSet;
|
|
}
|
|
set
|
|
{
|
|
paintSet = value;
|
|
}
|
|
}
|
|
|
|
public MeshOperator MeshOperator
|
|
{
|
|
get
|
|
{
|
|
if (meshOperator == null)
|
|
{
|
|
Debug.LogError("To take advantage of the features must Mesh filter or Skinned mesh renderer component associated Mesh.");
|
|
}
|
|
return meshOperator;
|
|
}
|
|
}
|
|
|
|
public event Action<InkCanvas> OnCanvasAttached;
|
|
|
|
public event Action<InkCanvas> OnInitializedStart;
|
|
|
|
public event Action<InkCanvas> OnInitializedAfter;
|
|
|
|
public event Action<InkCanvas, Brush> OnPaintStart;
|
|
|
|
public event Action<InkCanvas> OnPaintEnd;
|
|
|
|
private void Awake()
|
|
{
|
|
if (this.OnCanvasAttached != null)
|
|
{
|
|
this.OnCanvasAttached(this);
|
|
}
|
|
InitPropertyID();
|
|
SetMaterial();
|
|
SetTexture();
|
|
MeshDataCache();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (this.OnInitializedStart != null)
|
|
{
|
|
this.OnInitializedStart(this);
|
|
}
|
|
SetRenderTexture();
|
|
if (this.OnInitializedAfter != null)
|
|
{
|
|
this.OnInitializedAfter(this);
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
Debug.Log("InkCanvas has been destroyed.");
|
|
ReleaseRenderTexture();
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
if (eraserDebug)
|
|
{
|
|
if (debugEraserMainView != null)
|
|
{
|
|
GUI.DrawTexture(new Rect(0f, 0f, 100f, 100f), debugEraserMainView);
|
|
}
|
|
if (debugEraserNormalView != null)
|
|
{
|
|
GUI.DrawTexture(new Rect(0f, 100f, 100f, 100f), debugEraserNormalView);
|
|
}
|
|
if (debugEraserHeightView != null)
|
|
{
|
|
GUI.DrawTexture(new Rect(0f, 200f, 100f, 100f), debugEraserHeightView);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void MeshDataCache()
|
|
{
|
|
MeshFilter component = GetComponent<MeshFilter>();
|
|
SkinnedMeshRenderer component2 = GetComponent<SkinnedMeshRenderer>();
|
|
if (component != null)
|
|
{
|
|
meshOperator = new MeshOperator(component.sharedMesh);
|
|
}
|
|
else if (component2 != null)
|
|
{
|
|
meshOperator = new MeshOperator(component2.sharedMesh);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("Sometimes if the MeshFilter or SkinnedMeshRenderer does not exist in the component part does not work correctly.");
|
|
}
|
|
}
|
|
|
|
private void InitPropertyID()
|
|
{
|
|
foreach (PaintSet item in paintSet)
|
|
{
|
|
item.mainTexturePropertyID = Shader.PropertyToID(item.mainTextureName);
|
|
item.normalTexturePropertyID = Shader.PropertyToID(item.normalTextureName);
|
|
item.heightTexturePropertyID = Shader.PropertyToID(item.heightTextureName);
|
|
}
|
|
paintUVPropertyID = Shader.PropertyToID("_PaintUV");
|
|
brushTexturePropertyID = Shader.PropertyToID("_Brush");
|
|
brushScalePropertyID = Shader.PropertyToID("_BrushScale");
|
|
brushRotatePropertyID = Shader.PropertyToID("_BrushRotate");
|
|
brushColorPropertyID = Shader.PropertyToID("_ControlColor");
|
|
brushNormalTexturePropertyID = Shader.PropertyToID("_BrushNormal");
|
|
brushNormalBlendPropertyID = Shader.PropertyToID("_NormalBlend");
|
|
brushHeightTexturePropertyID = Shader.PropertyToID("_BrushHeight");
|
|
brushHeightBlendPropertyID = Shader.PropertyToID("_HeightBlend");
|
|
brushHeightColorPropertyID = Shader.PropertyToID("_Color");
|
|
}
|
|
|
|
private void SetMaterial()
|
|
{
|
|
if (paintMainMaterial == null)
|
|
{
|
|
paintMainMaterial = new Material(Resources.Load<Material>("Es.InkPainter.PaintMain"));
|
|
}
|
|
if (paintNormalMaterial == null)
|
|
{
|
|
paintNormalMaterial = new Material(Resources.Load<Material>("Es.InkPainter.PaintNormal"));
|
|
}
|
|
if (paintHeightMaterial == null)
|
|
{
|
|
paintHeightMaterial = new Material(Resources.Load<Material>("Es.InkPainter.PaintHeight"));
|
|
}
|
|
Material[] materials = GetComponent<Renderer>().materials;
|
|
for (int i = 0; i < materials.Length; i++)
|
|
{
|
|
if (paintSet[i].material == null)
|
|
{
|
|
paintSet[i].material = materials[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetTexture()
|
|
{
|
|
foreach (PaintSet item in paintSet)
|
|
{
|
|
if (item.material.HasProperty(item.mainTexturePropertyID))
|
|
{
|
|
item.mainTexture = item.material.GetTexture(item.mainTexturePropertyID);
|
|
}
|
|
if (item.material.HasProperty(item.normalTexturePropertyID))
|
|
{
|
|
item.normalTexture = item.material.GetTexture(item.normalTexturePropertyID);
|
|
}
|
|
if (item.material.HasProperty(item.heightTexturePropertyID))
|
|
{
|
|
item.heightTexture = item.material.GetTexture(item.heightTexturePropertyID);
|
|
}
|
|
}
|
|
}
|
|
|
|
private RenderTexture SetupRenderTexture(Texture baseTex, int propertyID, Material material)
|
|
{
|
|
RenderTexture renderTexture = new RenderTexture(baseTex.width, baseTex.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
|
renderTexture.filterMode = baseTex.filterMode;
|
|
Graphics.Blit(baseTex, renderTexture);
|
|
material.SetTexture(propertyID, renderTexture);
|
|
return renderTexture;
|
|
}
|
|
|
|
private void SetRenderTexture()
|
|
{
|
|
foreach (PaintSet item in paintSet)
|
|
{
|
|
if (item.useMainPaint)
|
|
{
|
|
if (item.mainTexture != null)
|
|
{
|
|
item.paintMainTexture = SetupRenderTexture(item.mainTexture, item.mainTexturePropertyID, item.material);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("To take advantage of the main texture paint must set main texture to materials.");
|
|
}
|
|
}
|
|
if (item.useNormalPaint)
|
|
{
|
|
if (item.normalTexture != null)
|
|
{
|
|
item.paintNormalTexture = SetupRenderTexture(item.normalTexture, item.normalTexturePropertyID, item.material);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("To take advantage of the normal map paint must set normal map to materials.");
|
|
}
|
|
}
|
|
if (item.useHeightPaint)
|
|
{
|
|
if (item.heightTexture != null)
|
|
{
|
|
item.paintHeightTexture = SetupRenderTexture(item.heightTexture, item.heightTexturePropertyID, item.material);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("To take advantage of the height map paint must set height map to materials.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ReleaseRenderTexture()
|
|
{
|
|
foreach (PaintSet item in paintSet)
|
|
{
|
|
if (RenderTexture.active != item.paintMainTexture && item.paintMainTexture != null && item.paintMainTexture.IsCreated())
|
|
{
|
|
item.paintMainTexture.Release();
|
|
}
|
|
if (RenderTexture.active != item.paintNormalTexture && item.paintNormalTexture != null && item.paintNormalTexture.IsCreated())
|
|
{
|
|
item.paintNormalTexture.Release();
|
|
}
|
|
if (RenderTexture.active != item.paintHeightTexture && item.paintHeightTexture != null && item.paintHeightTexture.IsCreated())
|
|
{
|
|
item.paintHeightTexture.Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetPaintMainData(Brush brush, Vector2 uv)
|
|
{
|
|
paintMainMaterial.SetVector(paintUVPropertyID, uv);
|
|
paintMainMaterial.SetTexture(brushTexturePropertyID, brush.BrushTexture);
|
|
paintMainMaterial.SetFloat(brushScalePropertyID, brush.Scale);
|
|
paintMainMaterial.SetFloat(brushRotatePropertyID, brush.RotateAngle);
|
|
paintMainMaterial.SetVector(brushColorPropertyID, brush.Color);
|
|
string[] shaderKeywords = paintMainMaterial.shaderKeywords;
|
|
foreach (string keyword in shaderKeywords)
|
|
{
|
|
paintMainMaterial.DisableKeyword(keyword);
|
|
}
|
|
switch (brush.ColorBlending)
|
|
{
|
|
case Brush.ColorBlendType.UseColor:
|
|
paintMainMaterial.EnableKeyword("INK_PAINTER_COLOR_BLEND_USE_CONTROL");
|
|
break;
|
|
case Brush.ColorBlendType.UseBrush:
|
|
paintMainMaterial.EnableKeyword("INK_PAINTER_COLOR_BLEND_USE_BRUSH");
|
|
break;
|
|
case Brush.ColorBlendType.Neutral:
|
|
paintMainMaterial.EnableKeyword("INK_PAINTER_COLOR_BLEND_NEUTRAL");
|
|
break;
|
|
case Brush.ColorBlendType.AlphaOnly:
|
|
paintMainMaterial.EnableKeyword("INK_PAINTER_COLOR_BLEND_ALPHA_ONLY");
|
|
break;
|
|
default:
|
|
paintMainMaterial.EnableKeyword("INK_PAINTER_COLOR_BLEND_USE_CONTROL");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void SetPaintNormalData(Brush brush, Vector2 uv, bool erase)
|
|
{
|
|
paintNormalMaterial.SetVector(paintUVPropertyID, uv);
|
|
paintNormalMaterial.SetTexture(brushTexturePropertyID, brush.BrushTexture);
|
|
paintNormalMaterial.SetTexture(brushNormalTexturePropertyID, brush.BrushNormalTexture);
|
|
paintNormalMaterial.SetFloat(brushScalePropertyID, brush.Scale);
|
|
paintNormalMaterial.SetFloat(brushRotatePropertyID, brush.RotateAngle);
|
|
paintNormalMaterial.SetFloat(brushNormalBlendPropertyID, brush.NormalBlend);
|
|
string[] shaderKeywords = paintNormalMaterial.shaderKeywords;
|
|
foreach (string keyword in shaderKeywords)
|
|
{
|
|
paintNormalMaterial.DisableKeyword(keyword);
|
|
}
|
|
switch (brush.NormalBlending)
|
|
{
|
|
case Brush.NormalBlendType.UseBrush:
|
|
paintNormalMaterial.EnableKeyword("INK_PAINTER_NORMAL_BLEND_USE_BRUSH");
|
|
break;
|
|
case Brush.NormalBlendType.Add:
|
|
paintNormalMaterial.EnableKeyword("INK_PAINTER_NORMAL_BLEND_ADD");
|
|
break;
|
|
case Brush.NormalBlendType.Sub:
|
|
paintNormalMaterial.EnableKeyword("INK_PAINTER_NORMAL_BLEND_SUB");
|
|
break;
|
|
case Brush.NormalBlendType.Min:
|
|
paintNormalMaterial.EnableKeyword("INK_PAINTER_NORMAL_BLEND_MIN");
|
|
break;
|
|
case Brush.NormalBlendType.Max:
|
|
paintNormalMaterial.EnableKeyword("INK_PAINTER_NORMAL_BLEND_MAX");
|
|
break;
|
|
default:
|
|
paintNormalMaterial.EnableKeyword("INK_PAINTER_NORMAL_BLEND_USE_BRUSH");
|
|
break;
|
|
}
|
|
if (erase)
|
|
{
|
|
paintNormalMaterial.EnableKeyword("DXT5NM_COMPRESS_UNUSE");
|
|
}
|
|
else
|
|
{
|
|
paintNormalMaterial.EnableKeyword("DXT5NM_COMPRESS_USE");
|
|
}
|
|
}
|
|
|
|
private void SetPaintHeightData(Brush brush, Vector2 uv)
|
|
{
|
|
paintHeightMaterial.SetVector(paintUVPropertyID, uv);
|
|
paintHeightMaterial.SetTexture(brushTexturePropertyID, brush.BrushTexture);
|
|
paintHeightMaterial.SetTexture(brushHeightTexturePropertyID, brush.BrushHeightTexture);
|
|
paintHeightMaterial.SetFloat(brushScalePropertyID, brush.Scale);
|
|
paintHeightMaterial.SetFloat(brushRotatePropertyID, brush.RotateAngle);
|
|
paintHeightMaterial.SetFloat(brushHeightBlendPropertyID, brush.HeightBlend);
|
|
paintHeightMaterial.SetVector(brushHeightColorPropertyID, brush.Color);
|
|
string[] shaderKeywords = paintHeightMaterial.shaderKeywords;
|
|
foreach (string keyword in shaderKeywords)
|
|
{
|
|
paintHeightMaterial.DisableKeyword(keyword);
|
|
}
|
|
switch (brush.HeightBlending)
|
|
{
|
|
case Brush.HeightBlendType.UseBrush:
|
|
paintHeightMaterial.EnableKeyword("INK_PAINTER_HEIGHT_BLEND_USE_BRUSH");
|
|
break;
|
|
case Brush.HeightBlendType.Add:
|
|
paintHeightMaterial.EnableKeyword("INK_PAINTER_HEIGHT_BLEND_ADD");
|
|
break;
|
|
case Brush.HeightBlendType.Sub:
|
|
paintHeightMaterial.EnableKeyword("INK_PAINTER_HEIGHT_BLEND_SUB");
|
|
break;
|
|
case Brush.HeightBlendType.Min:
|
|
paintHeightMaterial.EnableKeyword("INK_PAINTER_HEIGHT_BLEND_MIN");
|
|
break;
|
|
case Brush.HeightBlendType.Max:
|
|
paintHeightMaterial.EnableKeyword("INK_PAINTER_HEIGHT_BLEND_MAX");
|
|
break;
|
|
case Brush.HeightBlendType.ColorRGB_HeightA:
|
|
paintHeightMaterial.EnableKeyword("INK_PAINTER_HEIGHT_BLEND_COLOR_RGB_HEIGHT_A");
|
|
break;
|
|
default:
|
|
paintHeightMaterial.EnableKeyword("INK_PAINTER_HEIGHT_BLEND_ADD");
|
|
break;
|
|
}
|
|
}
|
|
|
|
private Brush GetEraser(Brush brush, PaintSet paintSet, Vector2 uv, bool useMainPaint, bool useNormalPaint, bool useHeightpaint)
|
|
{
|
|
Brush brush2 = brush.Clone() as Brush;
|
|
brush2.Color = Color.white;
|
|
brush2.ColorBlending = Brush.ColorBlendType.UseBrush;
|
|
brush2.NormalBlending = Brush.NormalBlendType.UseBrush;
|
|
brush2.HeightBlending = Brush.HeightBlendType.UseBrush;
|
|
brush2.NormalBlend = 1f;
|
|
brush2.HeightBlend = 1f;
|
|
if (useMainPaint)
|
|
{
|
|
RenderTexture temporary = RenderTexture.GetTemporary(brush.BrushTexture.width, brush.BrushTexture.height);
|
|
GrabArea.Clip(brush.BrushTexture, brush.Scale, paintSet.mainTexture, uv, brush.RotateAngle, GrabArea.GrabTextureWrapMode.Clamp, temporary);
|
|
brush2.BrushTexture = temporary;
|
|
}
|
|
if (useNormalPaint)
|
|
{
|
|
RenderTexture temporary2 = RenderTexture.GetTemporary(brush.BrushNormalTexture.width, brush.BrushNormalTexture.height);
|
|
GrabArea.Clip(brush.BrushNormalTexture, brush.Scale, paintSet.normalTexture, uv, brush.RotateAngle, GrabArea.GrabTextureWrapMode.Clamp, temporary2, replaceAlpha: false);
|
|
brush2.BrushNormalTexture = temporary2;
|
|
}
|
|
if (useHeightpaint)
|
|
{
|
|
RenderTexture temporary3 = RenderTexture.GetTemporary(brush.BrushHeightTexture.width, brush.BrushHeightTexture.height);
|
|
GrabArea.Clip(brush.BrushHeightTexture, brush.Scale, paintSet.heightTexture, uv, brush.RotateAngle, GrabArea.GrabTextureWrapMode.Clamp, temporary3, replaceAlpha: false);
|
|
brush2.BrushHeightTexture = temporary3;
|
|
}
|
|
if (eraserDebug)
|
|
{
|
|
if (debugEraserMainView == null && useMainPaint)
|
|
{
|
|
debugEraserMainView = new RenderTexture(brush2.BrushTexture.width, brush2.BrushTexture.height, 0);
|
|
}
|
|
if (debugEraserNormalView == null && useNormalPaint)
|
|
{
|
|
debugEraserNormalView = new RenderTexture(brush2.BrushNormalTexture.width, brush2.BrushNormalTexture.height, 0);
|
|
}
|
|
if (debugEraserHeightView == null && useHeightpaint)
|
|
{
|
|
debugEraserHeightView = new RenderTexture(brush2.BrushHeightTexture.width, brush2.BrushHeightTexture.height, 0);
|
|
}
|
|
if (useMainPaint)
|
|
{
|
|
Graphics.Blit(brush2.BrushTexture, debugEraserMainView);
|
|
}
|
|
if (useNormalPaint)
|
|
{
|
|
Graphics.Blit(brush2.BrushNormalTexture, debugEraserNormalView);
|
|
}
|
|
if (useHeightpaint)
|
|
{
|
|
Graphics.Blit(brush2.BrushHeightTexture, debugEraserHeightView);
|
|
}
|
|
}
|
|
return brush2;
|
|
}
|
|
|
|
private void ReleaseEraser(Brush brush, bool useMainPaint, bool useNormalPaint, bool useHeightpaint)
|
|
{
|
|
if (useMainPaint && brush.BrushTexture is RenderTexture)
|
|
{
|
|
RenderTexture.ReleaseTemporary(brush.BrushTexture as RenderTexture);
|
|
}
|
|
if (useNormalPaint && brush.BrushNormalTexture is RenderTexture)
|
|
{
|
|
RenderTexture.ReleaseTemporary(brush.BrushNormalTexture as RenderTexture);
|
|
}
|
|
if (useHeightpaint && brush.BrushHeightTexture is RenderTexture)
|
|
{
|
|
RenderTexture.ReleaseTemporary(brush.BrushHeightTexture as RenderTexture);
|
|
}
|
|
}
|
|
|
|
public bool PaintUVDirect(Brush brush, Vector2 uv, Func<PaintSet, bool> materialSelector = null)
|
|
{
|
|
if (brush == null)
|
|
{
|
|
Debug.LogError("Do not set the brush.");
|
|
eraseFlag = false;
|
|
return false;
|
|
}
|
|
if (this.OnPaintStart != null)
|
|
{
|
|
brush = brush.Clone() as Brush;
|
|
this.OnPaintStart(this, brush);
|
|
}
|
|
IEnumerable<PaintSet> enumerable;
|
|
if (materialSelector != null)
|
|
{
|
|
enumerable = paintSet.Where(materialSelector);
|
|
}
|
|
else
|
|
{
|
|
IEnumerable<PaintSet> enumerable2 = paintSet;
|
|
enumerable = enumerable2;
|
|
}
|
|
foreach (PaintSet item in enumerable)
|
|
{
|
|
bool flag = item.useMainPaint && brush.BrushTexture != null && item.paintMainTexture != null && item.paintMainTexture.IsCreated();
|
|
bool flag2 = item.useNormalPaint && brush.BrushNormalTexture != null && item.paintNormalTexture != null && item.paintNormalTexture.IsCreated();
|
|
bool flag3 = item.useHeightPaint && brush.BrushHeightTexture != null && item.paintHeightTexture != null && item.paintHeightTexture.IsCreated();
|
|
if (eraseFlag)
|
|
{
|
|
brush = GetEraser(brush, item, uv, flag, flag2, flag3);
|
|
}
|
|
if (flag)
|
|
{
|
|
RenderTexture temporary = RenderTexture.GetTemporary(item.paintMainTexture.width, item.paintMainTexture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
|
SetPaintMainData(brush, uv);
|
|
Graphics.Blit(item.paintMainTexture, temporary, paintMainMaterial);
|
|
Graphics.Blit(temporary, item.paintMainTexture);
|
|
RenderTexture.ReleaseTemporary(temporary);
|
|
}
|
|
if (flag2)
|
|
{
|
|
RenderTexture temporary2 = RenderTexture.GetTemporary(item.paintNormalTexture.width, item.paintNormalTexture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
|
SetPaintNormalData(brush, uv, eraseFlag);
|
|
Graphics.Blit(item.paintNormalTexture, temporary2, paintNormalMaterial);
|
|
Graphics.Blit(temporary2, item.paintNormalTexture);
|
|
RenderTexture.ReleaseTemporary(temporary2);
|
|
}
|
|
if (flag3)
|
|
{
|
|
RenderTexture temporary3 = RenderTexture.GetTemporary(item.paintHeightTexture.width, item.paintHeightTexture.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
|
|
SetPaintHeightData(brush, uv);
|
|
Graphics.Blit(item.paintHeightTexture, temporary3, paintHeightMaterial);
|
|
Graphics.Blit(temporary3, item.paintHeightTexture);
|
|
RenderTexture.ReleaseTemporary(temporary3);
|
|
}
|
|
if (eraseFlag)
|
|
{
|
|
ReleaseEraser(brush, flag, flag2, flag3);
|
|
}
|
|
}
|
|
if (this.OnPaintEnd != null)
|
|
{
|
|
this.OnPaintEnd(this);
|
|
}
|
|
eraseFlag = false;
|
|
return true;
|
|
}
|
|
|
|
public bool PaintNearestTriangleSurface(Brush brush, Vector3 worldPos, Func<PaintSet, bool> materialSelector = null, Camera renderCamera = null)
|
|
{
|
|
Vector3 localPoint = base.transform.worldToLocalMatrix.MultiplyPoint(worldPos);
|
|
Vector3 point = MeshOperator.NearestLocalSurfacePoint(localPoint);
|
|
return Paint(brush, base.transform.localToWorldMatrix.MultiplyPoint(point), materialSelector, renderCamera);
|
|
}
|
|
|
|
public bool Paint(Brush brush, Vector3 worldPos, Func<PaintSet, bool> materialSelector = null, Camera renderCamera = null)
|
|
{
|
|
if (renderCamera == null)
|
|
{
|
|
renderCamera = Camera.main;
|
|
}
|
|
Vector3 localPoint = base.transform.InverseTransformPoint(worldPos);
|
|
Matrix4x4 matrixMVP = renderCamera.projectionMatrix * renderCamera.worldToCameraMatrix * base.transform.localToWorldMatrix;
|
|
if (MeshOperator.LocalPointToUV(localPoint, matrixMVP, out var uv))
|
|
{
|
|
return PaintUVDirect(brush, uv, materialSelector);
|
|
}
|
|
Debug.LogWarning("Could not get the point on the surface.");
|
|
return PaintNearestTriangleSurface(brush, worldPos, materialSelector, renderCamera);
|
|
}
|
|
|
|
public bool Paint(Brush brush, RaycastHit hitInfo, Func<PaintSet, bool> materialSelector = null)
|
|
{
|
|
if (hitInfo.collider != null)
|
|
{
|
|
if (hitInfo.collider is MeshCollider)
|
|
{
|
|
return PaintUVDirect(brush, hitInfo.textureCoord, materialSelector);
|
|
}
|
|
Debug.LogWarning("If you want to paint using a RaycastHit, need set MeshCollider for object.");
|
|
return PaintNearestTriangleSurface(brush, hitInfo.point, materialSelector);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool EraseUVDirect(Brush brush, Vector2 uv, Func<PaintSet, bool> materialSelector = null)
|
|
{
|
|
eraseFlag = true;
|
|
return PaintUVDirect(brush, uv, materialSelector);
|
|
}
|
|
|
|
public bool EraseNearestTriangleSurface(Brush brush, Vector3 worldPos, Func<PaintSet, bool> materialSelector = null, Camera renderCamera = null)
|
|
{
|
|
eraseFlag = true;
|
|
return PaintNearestTriangleSurface(brush, worldPos, materialSelector, renderCamera);
|
|
}
|
|
|
|
public bool Erase(Brush brush, Vector3 worldPos, Func<PaintSet, bool> materialSelector = null, Camera renderCamera = null)
|
|
{
|
|
eraseFlag = true;
|
|
return Paint(brush, worldPos, materialSelector, renderCamera);
|
|
}
|
|
|
|
public bool Erase(Brush brush, RaycastHit hitInfo, Func<PaintSet, bool> materialSelector = null)
|
|
{
|
|
eraseFlag = true;
|
|
return Paint(brush, hitInfo, materialSelector);
|
|
}
|
|
|
|
public void ResetPaint()
|
|
{
|
|
ReleaseRenderTexture();
|
|
SetRenderTexture();
|
|
if (this.OnInitializedAfter != null)
|
|
{
|
|
this.OnInitializedAfter(this);
|
|
}
|
|
}
|
|
|
|
public Texture GetMainTexture(string materialName)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
return paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName)?.mainTexture;
|
|
}
|
|
|
|
public RenderTexture GetPaintMainTexture(string materialName)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
return paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName)?.paintMainTexture;
|
|
}
|
|
|
|
public void SetPaintMainTexture(string materialName, RenderTexture newTexture)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
PaintSet paintSet = this.paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName);
|
|
if (paintSet == null)
|
|
{
|
|
Debug.LogError("Failed to set texture.");
|
|
return;
|
|
}
|
|
paintSet.paintMainTexture = newTexture;
|
|
paintSet.material.SetTexture(paintSet.mainTextureName, paintSet.paintMainTexture);
|
|
paintSet.useMainPaint = true;
|
|
}
|
|
|
|
public Texture GetNormalTexture(string materialName)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
return paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName)?.normalTexture;
|
|
}
|
|
|
|
public RenderTexture GetPaintNormalTexture(string materialName)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
return paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName)?.paintNormalTexture;
|
|
}
|
|
|
|
public void SetPaintNormalTexture(string materialName, RenderTexture newTexture)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
PaintSet paintSet = this.paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName);
|
|
if (paintSet == null)
|
|
{
|
|
Debug.LogError("Failed to set texture.");
|
|
return;
|
|
}
|
|
paintSet.paintNormalTexture = newTexture;
|
|
paintSet.material.SetTexture(paintSet.normalTextureName, paintSet.paintNormalTexture);
|
|
paintSet.useNormalPaint = true;
|
|
}
|
|
|
|
public Texture GetHeightTexture(string materialName)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
return paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName)?.heightTexture;
|
|
}
|
|
|
|
public RenderTexture GetPaintHeightTexture(string materialName)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
return paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName)?.paintHeightTexture;
|
|
}
|
|
|
|
public void SetPaintHeightTexture(string materialName, RenderTexture newTexture)
|
|
{
|
|
materialName = materialName.Replace(" (Instance)", "");
|
|
PaintSet paintSet = this.paintSet.FirstOrDefault((PaintSet p) => p.material.name.Replace(" (Instance)", "") == materialName);
|
|
if (paintSet == null)
|
|
{
|
|
Debug.LogError("Failed to set texture.");
|
|
return;
|
|
}
|
|
paintSet.paintHeightTexture = newTexture;
|
|
paintSet.material.SetTexture(paintSet.heightTextureName, paintSet.paintHeightTexture);
|
|
paintSet.useHeightPaint = true;
|
|
}
|
|
}
|
|
}
|