Files
2026-03-04 10:03:45 +08:00

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;
}
}
}