Пример #1
0
    public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        BakedPointCloud data = ImportAsBakedPointCloud(ctx.assetPath);

        if (data != null)
        {
            ctx.AddObjectToAsset("container", data);
            ctx.AddObjectToAsset("position", data.PositionMap);
            ctx.AddObjectToAsset("color", data.ColorMap);
            ctx.SetMainObject(data);
        }
    }
Пример #2
0
    public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        var prefax = Path.GetExtension(ctx.assetPath).Substring(1);
        var text   = File.ReadAllText(ctx.assetPath);
        var asset  = new TextAsset(text);

        ctx.AddObjectToAsset("main obj", asset, LoadIconTexture(prefax));
        ctx.SetMainObject(asset);
    }
Пример #3
0
        public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
        {
            var str = File.ReadAllText(ctx.assetPath);

            var textAsset = new TextAsset(str);

            ctx.AddObjectToAsset("text", textAsset);
            ctx.SetMainObject(textAsset);
        }
        // Allow overriding this in tests
        public virtual UnityEngine.Object DeclareDependencyAndLoad(string path, string subAssetPath)
        {
            if (path.StartsWith(kThemePrefix))
            {
                var themeName = path.Substring(kThemePrefix.Length);


                if (!ThemeRegistry.themes.TryGetValue(themeName, out var themePath))
                {
                    return(null);
                }

                var themeAssetToCopy = EditorGUIUtility.Load(themePath);
                Debug.Assert(themeAssetToCopy != null, $"Theme not found searching for '{themeName}' at <{themePath}>.");

                if (themeAssetToCopy != null)
                {
                    var clonedAssets = DeepCopyAsset(themeAssetToCopy);

                    if (clonedAssets.Count > 0)
                    {
                        clonedAssets[0].name = themeName;
                        int assetIndex = 0;
                        foreach (var clonedAsset in clonedAssets)
                        {
                            m_Context.AddObjectToAsset($"asset {assetIndex++}: clonedAsset.name", clonedAsset);
                        }

                        return(clonedAssets[0]);
                    }
                }
                return(null);
            }

            m_Context?.DependsOnSourceAsset(path);

            if (string.IsNullOrEmpty(subAssetPath))
            {
                return(AssetDatabase.LoadMainAssetAtPath(path));
            }

            var mainAsset = AssetDatabase.LoadMainAssetAtPath(path);

            foreach (var o in AssetDatabase.LoadAllAssetsAtPath(path))
            {
                if (o == mainAsset)
                {
                    continue; // We're looking for a sub-asset here
                }
                if (o.name == subAssetPath)
                {
                    return(o);
                }
            }
            return(null);
        }
Пример #5
0
    public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        string[] lines = File.ReadAllLines(ctx.assetPath);

        if (lines.Length > 0 && lines[0] == "WIREMESH")
        {
            Mesh m = new Mesh();

            if (lines.Length > 1)
            {
                List <Vector3> vertices = new List <Vector3>();
                int[]          indices  = new int[(lines.Length - 1) * 2];


                for (int i = 1; i < lines.Length; i++)
                {
                    string[] values = lines[i].Split(separators);

                    if (values.Length != 6)
                    {
                        throw new System.IO.InvalidDataException("Invalid wire data length");
                    }

                    float[] linedata = new float[6];
                    for (int j = 0; j < 6; j++)
                    {
                        linedata[j] = float.Parse(values[j], System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture);
                    }

                    vertices.Add(new Vector3(linedata[0], linedata[1], linedata[2]));
                    vertices.Add(new Vector3(linedata[3], linedata[4], linedata[5]));

                    indices[(i - 1) * 2]     = (i - 1) * 2;
                    indices[(i - 1) * 2 + 1] = (i - 1) * 2 + 1;
                }

                m.SetVertices(vertices);
                m.SetIndices(indices, MeshTopology.Lines, 0, true);
            }
            else
            {
                Debug.LogWarning("Empty Mesh");
            }

            m.name = Path.GetFileNameWithoutExtension(ctx.assetPath);
            ctx.AddObjectToAsset("Mesh", m);
            ctx.SetMainObject(m);
        }
        else
        {
            throw new System.IO.InvalidDataException("Invalid File!");
        }
    }
Пример #6
0
    public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        List <Object> objectList = new List <Object>();

        Debug.Log("MAIN OBJECT  " + ctx.mainObject);
        ctx.GetObjects(objectList);
        Debug.Log(" OBJECTS  " + objectList.Count);


        var textGraph = File.ReadAllText(ctx.assetPath, Encoding.UTF8);
        LogicGraphObject loadedGraphObject = AssetDatabase.LoadAssetAtPath <LogicGraphObject>(ctx.assetPath);

        if (loadedGraphObject == null)
        {
            Debug.Log("Generating new");
            var graph = JsonUtility.FromJson <LogicGraphData>(textGraph);
            LogicGraphObject logicGraphObject = ScriptableObject.CreateInstance <LogicGraphObject>();
            logicGraphObject.Initialize(graph);
            ctx.AddObjectToAsset("MainAsset", logicGraphObject);
            ctx.SetMainObject(logicGraphObject);
        }
        else
        {
            Debug.Log("Updating Old");
            JsonUtility.FromJsonOverwrite(textGraph, loadedGraphObject.GraphData);
            ctx.AddObjectToAsset("MainAsset", loadedGraphObject);
            ctx.SetMainObject(loadedGraphObject);
        }

        Debug.Log(loadedGraphObject);

//        AssetDatabase.SaveAssets();
//        EditorSceneManager.SaveOpenScenes();



        Debug.Log("Set Asset");

//        AssetDatabase.Refresh();
    }
Пример #7
0
    private void ImportCompiledYarn(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        var bytes = File.ReadAllBytes(ctx.assetPath);

        try {
            // Validate that this can be parsed as a Program protobuf
            var _ = Program.Parser.ParseFrom(bytes);
        } catch (Google.Protobuf.InvalidProtocolBufferException) {
            ctx.LogImportError("Invalid compiled yarn file. Please re-compile the source code.");
            return;
        }

        isSuccesfullyCompiled = true;

        // Create a container for storing the bytes
        var programContainer = ScriptableObject.CreateInstance <YarnProgram>();

        programContainer.compiledProgram = bytes;

        // Add this container to the imported asset; it will be
        // what the user interacts with in Unity
        ctx.AddObjectToAsset("Program", programContainer);
        ctx.SetMainObject(programContainer);
    }
Пример #8
0
    public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        //Load file contents
        M2 file = new M2();

        file.LoadFile(ctx.assetPath);
        //Prepare blank asset
        GameObject model = new GameObject();

        model.AddComponent <Animator>();
        model.AddComponent <SkinnedMeshRenderer>();
        SkinnedMeshRenderer renderer = model.GetComponent <SkinnedMeshRenderer>();
        Mesh mesh = new Mesh();

        mesh.name = file.Name + "_mesh";
        //Fill vertex data
        Vector3[]    vertices = new Vector3[file.Vertices.Length];
        Vector3[]    normals  = new Vector3[file.Vertices.Length];
        BoneWeight[] weights  = new BoneWeight[file.Vertices.Length];
        Vector2[]    uv       = new Vector2[file.Vertices.Length];
        Vector2[]    uv2      = new Vector2[file.Vertices.Length];
        for (int i = 0; i < file.Vertices.Length; i++)
        {
            vertices[i] = new Vector3(-file.Vertices[i].Position.X / 2, file.Vertices[i].Position.Z / 2, -file.Vertices[i].Position.Y / 2);
            normals[i]  = new Vector3(-file.Vertices[i].Normal.X, file.Vertices[i].Normal.Z, -file.Vertices[i].Normal.Y);
            BoneWeight weight = new BoneWeight
            {
                boneIndex0 = file.Vertices[i].Bones[0],
                boneIndex1 = file.Vertices[i].Bones[1],
                boneIndex2 = file.Vertices[i].Bones[2],
                boneIndex3 = file.Vertices[i].Bones[3],
                weight0    = file.Vertices[i].Weights[0] / 255f,
                weight1    = file.Vertices[i].Weights[1] / 255f,
                weight2    = file.Vertices[i].Weights[2] / 255f,
                weight3    = file.Vertices[i].Weights[3] / 255f
            };
            weights[i] = weight;
            uv[i]      = new Vector2(file.Vertices[i].UV[0].X, 1 - file.Vertices[i].UV[0].Y);
            uv2[i]     = new Vector2(file.Vertices[i].UV[1].X, 1 - file.Vertices[i].UV[1].Y);
        }
        mesh.vertices    = vertices;
        mesh.normals     = normals;
        mesh.boneWeights = weights;
        mesh.uv          = uv;
        mesh.uv2         = uv2;
        //Fill Submesh data
        mesh.subMeshCount = file.Skin.Submeshes.Length;
        for (int i = 0; i < mesh.subMeshCount; i++)
        {
            int[] triangles = new int[file.Skin.Submeshes[i].Count];
            for (int j = 0; j < triangles.Length; j++)
            {
                triangles[j] = file.Skin.Indices[file.Skin.Submeshes[i].Start + j];
            }
            mesh.SetTriangles(triangles, i);
        }
        //Generate bones
        Transform[] bones = new Transform[file.Skeleton.Bones.Length];
        for (int i = 0; i < bones.Length; i++)
        {
            bones[i]          = new GameObject("Bone" + i).transform;
            bones[i].position = new Vector3(-file.Skeleton.Bones[i].Pivot.X / 2, file.Skeleton.Bones[i].Pivot.Z / 2, -file.Skeleton.Bones[i].Pivot.Y / 2);
        }
        GameObject skeleton = new GameObject("Skeleton");

        for (int i = 0; i < bones.Length; i++)
        {
            if (file.Skeleton.Bones[i].Parent == -1)
            {
                bones[i].parent = skeleton.transform;
            }
            else
            {
                bones[i].parent = bones[file.Skeleton.Bones[i].Parent];
            }
        }
        Matrix4x4[] bind = new Matrix4x4[bones.Length];
        for (int i = 0; i < bones.Length; i++)
        {
            bind[i] = bones[i].worldToLocalMatrix * model.transform.localToWorldMatrix;
        }
        skeleton.transform.parent = model.transform;
        renderer.materials        = new Material[mesh.subMeshCount];
        renderer.sharedMesh       = mesh;
        renderer.bones            = bones;
        renderer.rootBone         = bones[0];
        mesh.bindposes            = bind;
        //Seralize data in json so they can be accessible at runtime
        TextAsset json = new TextAsset(JsonConvert.SerializeObject(file));

        json.name = file.Name + "_data";
        model.AddComponent <M2Model>();
        model.GetComponent <M2Model>().json = json;
        //Fill particle effect data
        if (file.Particles.Length > 0)
        {
            GameObject[] particles = new GameObject[file.Particles.Length];
            for (int i = 0; i < particles.Length; i++)
            {
                particles[i] = ParticleEffect(file.Particles[i]);
                particles[i].transform.parent        = bones[file.Particles[i].Bone];
                particles[i].transform.localPosition = Vector3.zero;
                particles[i].name = "Particle" + i;
                ctx.AddObjectToAsset(particles[i].name, particles[i]);
            }
        }
        //Populate the asset
        ctx.AddObjectToAsset(file.Name, model);
        ctx.AddObjectToAsset(mesh.name, mesh);
        ctx.AddObjectToAsset(skeleton.name, skeleton);
        ctx.AddObjectToAsset(json.name, json);
    }
Пример #9
0
    public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        // NOTE: repere bas gauche, Y up.

        int ret = OIIOAPI.oiio_open_image(assetPath);

        if (ret == 0)
        {
            Debug.Log("could not open " + assetPath);
            return;
        }

        int width     = -1;
        int height    = -1;
        int nchannels = -1;

        OIIOAPI.BASETYPE format = OIIOAPI.BASETYPE.NONE;
        ret = OIIOAPI.oiio_get_image_info(ref width, ref height, ref nchannels, ref format);
        if (ret == 0)
        {
            Debug.Log("Could not get width/height of " + assetPath);
            return;
        }

        imageDimensions.Set(width, height);
        TextureFormat textureFormat = Format2Format(format, nchannels);
        var           image         = new Texture2D(width, height, textureFormat, false, true); // with mips, linear

        int do_rgb_to_rgba = 0;

        if ((format == OIIOAPI.BASETYPE.FLOAT && nchannels == 3) ||
            (format == OIIOAPI.BASETYPE.HALF && nchannels == 3))
        {
            do_rgb_to_rgba = 1;
        }
        //Color[] pixels = image.GetPixels();
        var      pixels = image.GetRawTextureData();
        GCHandle handle = GCHandle.Alloc(pixels, GCHandleType.Pinned);

        ret = OIIOAPI.oiio_fill_image_data(handle.AddrOfPinnedObject(), do_rgb_to_rgba);
        if (ret == 1)
        {
            image.LoadRawTextureData(pixels);
            //image.SetPixels(pixels);
            image.Apply();
        }
        else
        {
            Debug.Log("Could not fill texture data of " + assetPath);
            return;
        }



#if UNITY_2017_3_OR_NEWER
        var filename = Path.GetFileNameWithoutExtension(assetPath);
        ctx.AddObjectToAsset(filename, image);
        ctx.SetMainObject(image);
#else
        ctx.SetMainObject(image);
#endif
    }
Пример #10
0
    private void ImportYarn(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        var    sourceText = File.ReadAllText(ctx.assetPath);
        string fileName   = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath);

        try
        {
            // Compile the source code into a compiled Yarn program (or
            // generate a parse error)
            compilationStatus = Compiler.CompileString(sourceText, fileName, out var compiledProgram, out var stringTable);

            // Create a container for storing the bytes
            var programContainer = ScriptableObject.CreateInstance <YarnProgram>();

            using (var memoryStream = new MemoryStream())
                using (var outputStream = new Google.Protobuf.CodedOutputStream(memoryStream))
                {
                    // Serialize the compiled program to memory
                    compiledProgram.WriteTo(outputStream);
                    outputStream.Flush();

                    byte[] compiledBytes = memoryStream.ToArray();

                    programContainer.compiledProgram = compiledBytes;

                    // Add this container to the imported asset; it will be
                    // what the user interacts with in Unity
                    ctx.AddObjectToAsset("Program", programContainer, YarnEditorUtility.GetYarnDocumentIconTexture());
                    ctx.SetMainObject(programContainer);

                    isSuccesfullyCompiled = true;

                    // var outPath = Path.ChangeExtension(ctx.assetPath, ".yarnc");
                    // File.WriteAllBytes(outPath, compiledBytes);
                }

            if (stringTable.Count > 0)
            {
                using (var memoryStream = new MemoryStream())
                    using (var textWriter = new StreamWriter(memoryStream)) {
                        // Generate the localised .csv file

                        // Use the invariant culture when writing the CSV
                        var configuration = new CsvHelper.Configuration.Configuration(
                            System.Globalization.CultureInfo.InvariantCulture
                            );

                        var csv = new CsvHelper.CsvWriter(
                            textWriter,   // write into this stream
                            configuration // use this configuration
                            );

                        var lines = stringTable.Select(x => new {
                            id         = x.Key,
                            text       = x.Value.text,
                            file       = x.Value.fileName,
                            node       = x.Value.nodeName,
                            lineNumber = x.Value.lineNumber
                        });

                        csv.WriteRecords(lines);

                        textWriter.Flush();

                        memoryStream.Position = 0;

                        using (var reader = new StreamReader(memoryStream)) {
                            var textAsset = new TextAsset(reader.ReadToEnd());
                            textAsset.name = $"{fileName} ({baseLanguageID})";

                            ctx.AddObjectToAsset("Strings", textAsset);

                            programContainer.baseLocalisationStringTable = textAsset;
                            baseLanguage = textAsset;
                            programContainer.localizations = localizations;
                        }

                        stringIDs = lines.Select(l => l.id).ToArray();
                    }
            }
        }
        catch (Yarn.Compiler.ParseException e)
        {
            isSuccesfullyCompiled   = false;
            compilationErrorMessage = e.Message;
            ctx.LogImportError(e.Message);
            return;
        }
    }
Пример #11
0
        public override void OnImportAsset(UnityEditor.AssetImporters.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 "byte":
                        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 byte/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 "byte":
                            val = Mathf.Clamp01(((int)pcache.buckets[idx][i]) / 256.0f);
                            break;

                        case "float":
                            val = ((float)pcache.buckets[idx][i]);
                            break;

                        default: throw new NotImplementedException("Types other than byte/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();
                    kvp.Value.hideFlags = HideFlags.HideInHierarchy;
                    ctx.AddObjectToAsset(kvp.Key.Name, kvp.Value);
                    cache.surfaces[k] = kvp.Value;
                    k++;
                }
            }
            catch (System.Exception e)
            {
                Debug.LogException(e);
            }
        }
    public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
    {
        //Load file contents
        BoneLib.Bone file = new BoneLib.Bone();
        file.LoadFile(ctx.assetPath);
        //Load skel file for reference
        Skel skeleton = new Skel();

        skeleton.LoadFile(ctx.assetPath.Substring(0, ctx.assetPath.Length - 8) + ".skel");
        //Create empty animation clip
        AnimationClip  clip = new AnimationClip();
        AnimationCurve curve;
        Matrix4x4      matrix;

        Vector4[] columns = new Vector4[4];
        float     value;

        //Generate temporary bones
        Transform[] bones = new Transform[skeleton.Bones.Length];
        for (int i = 0; i < bones.Length; i++)
        {
            bones[i]          = new GameObject("Bone" + i).transform;
            bones[i].position = new Vector3(-skeleton.Bones[i].Pivot.X / 2, skeleton.Bones[i].Pivot.Z / 2, -skeleton.Bones[i].Pivot.Y / 2);
        }
        GameObject rig = new GameObject("Skeleton");

        for (int i = 0; i < bones.Length; i++)
        {
            if (skeleton.Bones[i].Parent == -1)
            {
                bones[i].parent = rig.transform;
            }
            else
            {
                bones[i].parent = bones[skeleton.Bones[i].Parent];
            }
        }
        //Fill animation data for each bone
        for (int i = 0; i < file.Bones.Length; i++)
        {
            string path = GetBonePath(skeleton.Bones[file.Bones[i]].Parent, skeleton.Bones) + "Bone" + file.Bones[i];
            for (int j = 0; j < 4; j++)
            {
                columns[j] = new Vector4(file.Transformations[i][j][0], file.Transformations[i][j][1], file.Transformations[i][j][2], file.Transformations[i][j][3]);
            }
            matrix = new Matrix4x4(columns[0], columns[1], columns[2], columns[3]);
            value  = -matrix.m03 / 2 + bones[file.Bones[i]].localPosition.x;
            curve  = AnimationCurve.Linear(0f, value, 0.1f, value);;
            clip.SetCurve(path, typeof(Transform), "localPosition.x", curve);
            value = matrix.m23 / 2 + bones[file.Bones[i]].localPosition.y;
            curve = AnimationCurve.Linear(0f, value, 0.1f, value);
            clip.SetCurve(path, typeof(Transform), "localPosition.y", curve);
            value = -matrix.m13 / 2 + bones[file.Bones[i]].localPosition.z;
            curve = AnimationCurve.Linear(0f, value, 0.1f, value);
            clip.SetCurve(path, typeof(Transform), "localPosition.z", curve);
            UnityEngine.Quaternion rotation = matrix.rotation;
            curve = AnimationCurve.Linear(0f, -rotation.x, 1f, rotation.x);
            clip.SetCurve(path, typeof(Transform), "localRotation.x", curve);
            curve = AnimationCurve.Linear(0f, -rotation.z, 0.1f, rotation.z);
            clip.SetCurve(path, typeof(Transform), "localRotation.y", curve);
            curve = AnimationCurve.Linear(0f, rotation.y, 0.1f, rotation.y);
            clip.SetCurve(path, typeof(Transform), "localRotation.z", curve);
            curve = AnimationCurve.Linear(0f, rotation.w, 0.1f, rotation.w);
            clip.SetCurve(path, typeof(Transform), "localRotation.w", curve);
            Vector3 scale = matrix.lossyScale;
            curve = AnimationCurve.Linear(0f, scale.x, 0.1f, scale.x);
            clip.SetCurve(path, typeof(Transform), "localScale.x", curve);
            curve = AnimationCurve.Linear(0f, scale.z, 0.1f, scale.z);
            clip.SetCurve(path, typeof(Transform), "localScale.y", curve);
            curve = AnimationCurve.Linear(0f, scale.y, 0.1f, scale.y);
            clip.SetCurve(path, typeof(Transform), "localScale.z", curve);
        }
        //Clear temporary bones and add animation clip to the asset
        DestroyImmediate(rig);
        ctx.AddObjectToAsset(Path.GetFileNameWithoutExtension(ctx.assetPath.Replace("/", "\\")), clip);
    }
Пример #13
0
        public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
        {
            byte[] bytes = File.ReadAllBytes(ctx.assetPath);
            int    width = 1, height = 1, depth = 1;

            try
            {
                int    channels = 0;
                string fourcc   = Encoding.UTF8.GetString(SubArray <byte>(bytes, 0, 4));

                if (fourcc != "VF_F" && fourcc != "VF_V")
                {
                    throw new Exception("Invalid VF File Header. Need VF_F or VF_V, found :" + fourcc);
                }
                else
                {
                    if (fourcc == "VF_F")
                    {
                        channels = 1;
                    }
                    if (fourcc == "VF_V")
                    {
                        channels = 3;
                    }
                }

                TextureFormat outFormat = TextureFormat.Alpha8;
                switch (m_OutputFormat)
                {
                case VectorFieldOutputFormat.Byte: outFormat = channels == 3 ? TextureFormat.RGBA32 : TextureFormat.Alpha8; break;

                case VectorFieldOutputFormat.Half: outFormat = channels == 3 ? TextureFormat.RGBAHalf : TextureFormat.RHalf; break;

                case VectorFieldOutputFormat.Float: outFormat = channels == 3 ? TextureFormat.RGBAFloat : TextureFormat.RFloat; break;
                }

                if (bytes.Length < 10)
                {
                    throw new Exception("Malformed VF File, invalid header (less than 10 bytes)");
                }

                width  = BitConverter.ToUInt16(bytes, 4);
                height = BitConverter.ToUInt16(bytes, 6);
                depth  = BitConverter.ToUInt16(bytes, 8);

                int requiredLength = 10 + (4 * channels * (width * height * depth));

                if (bytes.Length != requiredLength)
                {
                    throw new Exception("Malformed VF File, invalid length (expected :" + requiredLength + ", found :" + bytes.Length + ")");
                }

                Texture3D texture = new Texture3D(width, height, depth, outFormat, m_GenerateMipMaps);
                texture.wrapMode   = m_WrapMode;
                texture.filterMode = m_FilterMode;
                texture.anisoLevel = m_AnisoLevel;

                int count = width * height * depth;

                Color[] colors = new Color[count];

                for (int i = 0; i < count; i++)
                {
                    Color c;
                    if (channels == 1)
                    {
                        float x = BitConverter.ToSingle(bytes, 10 + (i * 4 * channels));
                        c = new Color(x, 0, 0);
                    }
                    else
                    {
                        float x = BitConverter.ToSingle(bytes, 10 + (i * 4 * channels));
                        float y = BitConverter.ToSingle(bytes, 14 + (i * 4 * channels));
                        float z = BitConverter.ToSingle(bytes, 18 + (i * 4 * channels));
                        c = new Color(x, y, z);
                    }
                    colors[i] = c;
                }

                texture.SetPixels(colors);
                texture.Apply(true, true);
                ctx.AddObjectToAsset("VectorField", texture);
                ctx.SetMainObject(texture);
            }
            catch (System.Exception e)
            {
                Debug.LogException(e);
            }
        }