public VPaintVertexData GetOrCreate(VPaintObject vc) { if (vc == null) { return(null); } var data = Get(vc); if (data != null) { return(data); } data = new VPaintVertexData(); data.vpaintObject = vc; var cols = vc.GetDefaultColors(); data.colors = new Color[cols.Length]; data.transparency = new float[cols.Length]; paintData.Add(data); return(data); }
public void Remove(IVPaintIdentifier vc) { for (int i = 0; i < paintData.Count; i++) { VPaintVertexData data = paintData[i]; if (data.identifier.IsEqualTo(vc)) { paintData.RemoveAt(i); i--; } } }
public VPaintVertexData Clone() { VPaintVertexData data = new VPaintVertexData(); data.colorer = colorer; data.colors = new Color[colors.Length]; data.transparency = new float[colors.Length]; for (int i = 0; i < colors.Length; i++) { data.colors[i] = colors[i]; data.transparency[i] = transparency[i]; } return(data); }
public VPaintVertexData Get(IVPaintIdentifier vc) { if (vc == null) { return(null); } for (int i = 0; i < paintData.Count; i++) { VPaintVertexData data = paintData[i]; if (vc.IsEqualTo(data.identifier)) { return(data); } } return(null); }
public void Merge(VPaintLayer layer, Color baseColor = new Color()) { foreach (VPaintVertexData data in layer.paintData) { var rootData = Get(data.identifier); Color[] cols = null; float[] trans = null; if (rootData != null) { cols = rootData.colors; trans = rootData.transparency; } else { cols = new Color[data.colors.Length]; for (int i = 0; i < cols.Length; i++) { cols[i] = baseColor; } trans = new float[data.transparency.Length]; rootData = new VPaintVertexData(); rootData.colors = cols; rootData.transparency = trans; rootData.colorer = data.colorer; paintData.Add(rootData); } VPaintUtility.MergeColors( cols, trans, data.colors, data.transparency, layer.blendMode, layer.opacity, layer.maskR, layer.maskG, layer.maskB, layer.maskA ); } }
/// <summary> /// Blends colors between objects using the radial method. /// </summary> /// <param name='layers'> /// The layers to affect. If acting on a VPaintLayerStack, use VPaintLayerStack.layers.ToArray() /// </param> /// <param name='blendObjects'> /// The objects to blend /// </param> /// <param name='blendTargets'> /// The objects to blend towards /// </param> /// <param name='direction'> /// The direction to apply the sample /// </param> /// <param name='distance'> /// The distance of the sample /// </param> /// <param name='intensity'> /// (Optional) The intensity of the blend operation /// </param> /// <param name='falloff'> /// (Optional) The falloff of the blend opreation /// </param> /// <param name='offset'> /// (Optional) the offset of the blend sample. Use this to avoid blend samples "missing" when the object intersects the target. /// </param> /// <param name='bounds'> /// (Optional) the bounds to constrain this blend operation to /// </param> public static IEnumerator <VPaintProgress> BlendDirectionalAsync( VPaintLayer[] layers, VPaintObject[] blendObjects, VPaintObject[] blendTargets, Vector3 direction, float distance, float intensity = 1, float falloff = 1, Vector3?offset = null, Bounds?bounds = null ) { if (!offset.HasValue) { offset = Vector3.zero; } var validTargets = new List <VPaintObject>(); foreach (var vc in blendTargets) { if (Application.isPlaying && !vc.isDynamic) { throw new VPaintObjectNotDynamicException(); } if (bounds.HasValue) { if (!bounds.Value.Intersects(vc.editorCollider.bounds)) { continue; } } validTargets.Add(vc); } for (int l = 0; l < layers.Length; l++) { var layer = layers[l]; for (int i = 0; i < blendObjects.Length; i++) { var vc = blendObjects[i]; string message = "Blending " + vc.name + " on layer " + layer.name; float progressBase = (float)i / blendObjects.Length; float progressRange = ((float)(i + 1) / blendObjects.Length - progressBase) / 1; Mesh m = vc.GetMeshInstance(); Vector3[] vertices = m.vertices; var paintData = layer.GetOrCreate(vc); Color[] colors = paintData.colors; float[] trans = paintData.transparency; Transform t = vc.transform; float offsetMagnitude = offset.Value.magnitude; for (int v = 0; v < vertices.Length; v++) { yield return(new VPaintProgress() { message = message, progress = progressBase + (progressRange * (float)v / vertices.Length) }); var vert = t.TransformPoint(vertices[v]); if (bounds.HasValue) { if (!bounds.Value.Contains(vert)) { continue; } } Vector4 avgCol = Vector4.zero; float avgTran = 0; float fac = 0; float count = 0; foreach (var target in validTargets) { var mc = target.editorCollider; Ray r = new Ray(vert + offset.Value, direction); RaycastHit hit; if (mc.Raycast(r, out hit, distance)) { if (bounds.HasValue) { if (!bounds.Value.Contains(hit.point)) { continue; } } Mesh mi = target.GetMeshInstance(); if (!mi) { continue; } int[] triangles = mi.triangles; VPaintVertexData pd = layer.GetOrCreate(target); int t1 = triangles[(hit.triangleIndex * 3) + 0]; int t2 = triangles[(hit.triangleIndex * 3) + 1]; int t3 = triangles[(hit.triangleIndex * 3) + 2]; //Colors Color c1 = pd.colors[t1]; Color c2 = pd.colors[t2]; Color c3 = pd.colors[t3]; float tr1 = pd.transparency[t1]; float tr2 = pd.transparency[t2]; float tr3 = pd.transparency[t3]; Vector3 bc = hit.barycentricCoordinate; Color sampleColor = c1 * bc.x + c2 * bc.y + c3 * bc.z; float sampleTran = tr1 * bc.x + tr2 * bc.y + tr3 * bc.z; float factor = Mathf.Pow(1 - (hit.distance - offsetMagnitude) / distance, falloff); fac += factor; avgTran += sampleTran * factor; avgCol += (Vector4)sampleColor * factor; count++; } } Color col = (Color)(avgCol / fac); float tran = avgTran / fac; if (fac != 0) { float lerp = intensity * (fac / count); colors[v] = Color.Lerp(colors[v], col, lerp); trans[v] = Mathf.Lerp(trans[v], tran, lerp); } } } } }