You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
7.4 KiB
213 lines
7.4 KiB
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Globalization;
|
|
using UnityEngine;
|
|
#if UNITY_2020_2_OR_NEWER
|
|
using UnityEditor.AssetImporters;
|
|
#else
|
|
using UnityEditor.Experimental.AssetImporters;
|
|
#endif
|
|
|
|
|
|
namespace UnityEditor.Experimental.VFX.Utility
|
|
{
|
|
[ScriptedImporter(1, "pcache")]
|
|
class PointCacheImporter : ScriptedImporter
|
|
{
|
|
public static T[] SubArray<T>(T[] data, int index, int length)
|
|
{
|
|
T[] result = new T[length];
|
|
Array.Copy(data, index, result, 0, length);
|
|
return result;
|
|
}
|
|
|
|
class InProperty
|
|
{
|
|
public string PropertyType;
|
|
public string Name;
|
|
public int Index;
|
|
public OutProperty OutProperty;
|
|
|
|
public InProperty(string propertyType, string name, int index, OutProperty outProperty)
|
|
{
|
|
PropertyType = propertyType;
|
|
Name = name;
|
|
Index = index;
|
|
OutProperty = outProperty;
|
|
}
|
|
}
|
|
|
|
class OutProperty
|
|
{
|
|
public string PropertyType;
|
|
public string Name;
|
|
public int Size;
|
|
public OutProperty(string propertyType, string name, int size)
|
|
{
|
|
PropertyType = propertyType;
|
|
Name = name;
|
|
Size = size;
|
|
}
|
|
}
|
|
|
|
public static void GetHeader(Stream s, out long byteLength, out List<string> lines)
|
|
{
|
|
byteLength = 0;
|
|
bool found_end_header = false;
|
|
lines = new List<string>();
|
|
|
|
s.Seek(0, SeekOrigin.Begin);
|
|
BinaryReader sr = new BinaryReader(s);
|
|
|
|
do
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
bool newline = false;
|
|
do
|
|
{
|
|
char c = sr.ReadChar();
|
|
byteLength++;
|
|
if ((c == '\n' || c == '\r') && sb.Length > 0) newline = true;
|
|
else sb.Append(c);
|
|
}
|
|
while (!newline);
|
|
|
|
string line = sb.ToString();
|
|
lines.Add(line);
|
|
if (line == "end_header") found_end_header = true;
|
|
}
|
|
while (!found_end_header);
|
|
}
|
|
|
|
public override void OnImportAsset(AssetImportContext ctx)
|
|
{
|
|
try
|
|
{
|
|
PCache pcache = PCache.FromFile(ctx.assetPath);
|
|
|
|
PointCacheAsset cache = ScriptableObject.CreateInstance<PointCacheAsset>();
|
|
cache.name = "PointCache";
|
|
ctx.AddObjectToAsset("PointCache", cache);
|
|
ctx.SetMainObject(cache);
|
|
|
|
List<InProperty> inProperties = new List<InProperty>();
|
|
Dictionary<string, OutProperty> outProperties = new Dictionary<string, OutProperty>();
|
|
Dictionary<OutProperty, Texture2D> surfaces = new Dictionary<OutProperty, Texture2D>();
|
|
|
|
foreach (var prop in pcache.properties)
|
|
{
|
|
OutProperty p_out;
|
|
if (outProperties.ContainsKey(prop.ComponentName))
|
|
{
|
|
p_out = outProperties[prop.ComponentName];
|
|
p_out.Size = Math.Max(p_out.Size, prop.ComponentIndex + 1);
|
|
}
|
|
else
|
|
{
|
|
p_out = new OutProperty(prop.Type, prop.ComponentName, prop.ComponentIndex + 1);
|
|
outProperties.Add(prop.ComponentName, p_out);
|
|
}
|
|
|
|
inProperties.Add(new InProperty(prop.Type, prop.Name, prop.ComponentIndex, p_out));
|
|
}
|
|
|
|
|
|
int width, height;
|
|
FindBestSize(pcache.elementCount, out width, out height);
|
|
|
|
// Output Surface Creation
|
|
foreach (var kvp in outProperties)
|
|
{
|
|
TextureFormat surfaceFormat = TextureFormat.Alpha8;
|
|
switch (kvp.Value.PropertyType)
|
|
{
|
|
case "uchar":
|
|
if (kvp.Value.Size == 1) surfaceFormat = TextureFormat.Alpha8;
|
|
else surfaceFormat = TextureFormat.RGBA32;
|
|
break;
|
|
case "float":
|
|
if (kvp.Value.Size == 1) surfaceFormat = TextureFormat.RHalf;
|
|
else surfaceFormat = TextureFormat.RGBAHalf;
|
|
break;
|
|
default: throw new NotImplementedException("Types other than uchar/float are not supported yet");
|
|
}
|
|
|
|
Texture2D surface = new Texture2D(width, height, surfaceFormat, false);
|
|
surface.name = kvp.Key;
|
|
surfaces.Add(kvp.Value, surface);
|
|
}
|
|
|
|
cache.PointCount = pcache.elementCount;
|
|
cache.surfaces = new Texture2D[surfaces.Count];
|
|
|
|
Dictionary<OutProperty, Color> outValues = new Dictionary<OutProperty, Color>();
|
|
foreach (var kvp in outProperties)
|
|
outValues.Add(kvp.Value, new Color());
|
|
|
|
for (int i = 0; i < pcache.elementCount; i++)
|
|
{
|
|
int idx = 0;
|
|
foreach (var prop in inProperties)
|
|
{
|
|
float val = 0.0f;
|
|
switch (prop.PropertyType)
|
|
{
|
|
case "uchar":
|
|
val = Mathf.Clamp01(((byte)pcache.buckets[idx][i]) / 255.0f);
|
|
break;
|
|
case "float":
|
|
val = ((float)pcache.buckets[idx][i]);
|
|
break;
|
|
default: throw new NotImplementedException("Types other than uchar/float are not supported yet");
|
|
}
|
|
|
|
SetPropValue(prop.Index, outValues, prop.OutProperty, val);
|
|
idx++;
|
|
}
|
|
foreach (var kvp in outProperties)
|
|
{
|
|
surfaces[kvp.Value].SetPixel(i % width, i / width, outValues[kvp.Value]);
|
|
}
|
|
}
|
|
|
|
int k = 0;
|
|
|
|
foreach (var kvp in surfaces)
|
|
{
|
|
kvp.Value.Apply();
|
|
ctx.AddObjectToAsset(kvp.Key.Name, kvp.Value);
|
|
cache.surfaces[k] = kvp.Value;
|
|
k++;
|
|
}
|
|
}
|
|
catch (System.Exception e)
|
|
{
|
|
Debug.LogException(e);
|
|
}
|
|
}
|
|
|
|
private void SetPropValue(int index, Dictionary<OutProperty, Color> data, OutProperty prop, float val)
|
|
{
|
|
Color c = data[prop];
|
|
|
|
switch (index)
|
|
{
|
|
case 0: if (prop.Size == 1 && prop.PropertyType == "int") c.a = val; else c.r = val; break;
|
|
case 1: c.g = val; break;
|
|
case 2: c.b = val; break;
|
|
case 3: c.a = val; break;
|
|
}
|
|
data[prop] = c;
|
|
}
|
|
|
|
private void FindBestSize(int count, out int width, out int height)
|
|
{
|
|
float r = Mathf.Sqrt(count);
|
|
width = (int)Mathf.Ceil(r);
|
|
height = width;
|
|
}
|
|
}
|
|
}
|