Beispiel #1
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var path           = ctx.assetPath;
            var data           = VoxFileImport.Load(path);
            var palleteTexture =
                VoxFileImport.CreateTextureFromColor16x16(VoxFileImport.CreateColor32FromPelatte(data.palette.values));

            var boundsCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            var bounds     = data.chunkChild
                             .Select(chunk => new Vector3(chunk.size.x, chunk.size.z, chunk.size.y)).Aggregate(
                Vector3.zero,
                (result, chunk) => new Vector3(
                    Mathf.Max(result.x, chunk.x),
                    Mathf.Max(result.z, chunk.z),
                    Mathf.Max(result.y, chunk.y)
                    ));

            boundsCube.transform.localScale = bounds;


            for (var chunkIndex = 0; chunkIndex < data.chunkChild.Length; chunkIndex++)
            {
                var chunk         = data.chunkChild[chunkIndex];
                var volumeTexture = new Texture3D(chunk.size.x, chunk.size.z, chunk.size.y, TextureFormat.RGBA32, false);
                var volumePixels  = new Color32[chunk.size.x * chunk.size.z * chunk.size.y];

                for (int z = 0; z < chunk.size.y; z++)
                {
                    var zSliceTexture = new Texture2D(chunk.size.x, chunk.size.z, TextureFormat.RGBA32, false);
                    var pixels        = new Color32[chunk.size.x * chunk.size.z];

                    for (int x = 0; x < chunk.size.x; x++)
                    {
                        for (int y = 0; y < chunk.size.z; y++)
                        {
                            var voxel = chunk.xyzi.voxels.voxels[x, y, z];
                            volumePixels[z * chunk.size.x * chunk.size.z + y * chunk.size.x + x] =
                                pixels[y * chunk.size.x + x] =
                                    voxel == Int32.MaxValue ? new Color32(0, 0, 0, 0) : new Color32(255, 255, 255, 255);
                        }
                    }

                    zSliceTexture.SetPixels32(pixels);
                    zSliceTexture.Apply();
                    zSliceTexture.name = $"slice-{chunkIndex}-{z}";
                    ctx.AddObjectToAsset(zSliceTexture.name, zSliceTexture);
                }

                volumeTexture.SetPixels32(volumePixels);
                volumeTexture.Apply();
                volumeTexture.name = $"volume-{chunkIndex}";
                ctx.AddObjectToAsset(volumeTexture.name, volumeTexture);
                if (chunkIndex == 0)
                {
                    ctx.SetMainObject(volumeTexture);
                }
            }

            boundsCube.name = "bounds";
            ctx.AddObjectToAsset(boundsCube.name, boundsCube);
            palleteTexture.name = "pallete";
            ctx.AddObjectToAsset(palleteTexture.name, palleteTexture);

//	        for (int z = 0; z < data.; z++)
//	        {
//
//	        }

//            var content = File.ReadAllBytes(path);
//
//            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
//            ctx.AddObjectToAsset("cube", cube);
//            ctx.SetMainObject(cube);
//
//            var material = new Material(Shader.Find("Standard"));
//            material.color = Color.red;
//
//            // Assets must be assigned a unique identifier string consistent across imports
//            ctx.AddObjectToAsset("my Material", material);
        }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var oldShader = AssetDatabase.LoadAssetAtPath <Shader>(ctx.assetPath);

            if (oldShader != null)
            {
                ShaderUtil.ClearShaderMessages(oldShader);
            }

            List <PropertyCollector.TextureInfo> configuredTextures;
            string path = ctx.assetPath;

            AssetCollection assetCollection = new AssetCollection();

            MinimalGraphData.GatherMinimalDependenciesFromFile(assetPath, assetCollection);

            var textGraph = File.ReadAllText(path, Encoding.UTF8);
            var graph     = new GraphData
            {
                messageManager = new MessageManager(), assetGuid = AssetDatabase.AssetPathToGUID(path)
            };

            MultiJson.Deserialize(graph, textGraph);
            graph.OnEnable();
            graph.ValidateGraph();

            Shader shader = null;

#if VFX_GRAPH_10_0_0_OR_NEWER
            if (!graph.isOnlyVFXTarget)
#endif
            {
                // build the shader text
                // this will also add Target dependencies into the asset collection
                var text = GetShaderText(path, out configuredTextures, assetCollection, graph);

#if UNITY_2021_1_OR_NEWER
                // 2021.1 or later is guaranteed to have the new version of this function
                shader = ShaderUtil.CreateShaderAsset(ctx, text, false);
#else
                // earlier builds of Unity may or may not have it
                // here we try to invoke the new version via reflection
                var createShaderAssetMethod = typeof(ShaderUtil).GetMethod(
                    "CreateShaderAsset",
                    System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.ExactBinding,
                    null,
                    new Type[] { typeof(AssetImportContext), typeof(string), typeof(bool) },
                    null);

                if (createShaderAssetMethod != null)
                {
                    shader = createShaderAssetMethod.Invoke(null, new Object[] { ctx, text, false }) as Shader;
                }
                else
                {
                    // method doesn't exist in this version of Unity, call old version
                    // this doesn't create dependencies properly, but is the best that we can do
                    shader = ShaderUtil.CreateShaderAsset(text, false);
                }
#endif

                if (graph.messageManager.nodeMessagesChanged)
                {
                    foreach (var pair in graph.messageManager.GetNodeMessages())
                    {
                        var node = graph.GetNodeFromId(pair.Key);
                        MessageManager.Log(node, path, pair.Value.First(), shader);
                    }
                }

                EditorMaterialUtility.SetShaderDefaults(
                    shader,
                    configuredTextures.Where(x => x.modifiable).Select(x => x.name).ToArray(),
                    configuredTextures.Where(x => x.modifiable).Select(x => EditorUtility.InstanceIDToObject(x.textureId) as Texture).ToArray());
                EditorMaterialUtility.SetShaderNonModifiableDefaults(
                    shader,
                    configuredTextures.Where(x => !x.modifiable).Select(x => x.name).ToArray(),
                    configuredTextures.Where(x => !x.modifiable).Select(x => EditorUtility.InstanceIDToObject(x.textureId) as Texture).ToArray());
            }

            UnityEngine.Object mainObject = shader;
#if VFX_GRAPH_10_0_0_OR_NEWER
            ShaderGraphVfxAsset vfxAsset = null;
            if (graph.hasVFXTarget)
            {
                vfxAsset = GenerateVfxShaderGraphAsset(graph);
                if (mainObject == null)
                {
                    mainObject = vfxAsset;
                }
                else
                {
                    //Correct main object if we have a shader and ShaderGraphVfxAsset : save as sub asset
                    vfxAsset.name = Path.GetFileNameWithoutExtension(path);
                    ctx.AddObjectToAsset("VFXShaderGraph", vfxAsset);
                }
            }
#endif

            Texture2D texture = Resources.Load <Texture2D>("Icons/sg_graph_icon@64");
            ctx.AddObjectToAsset("MainAsset", mainObject, texture);
            ctx.SetMainObject(mainObject);

            foreach (var target in graph.activeTargets)
            {
                if (target is IHasMetadata iHasMetadata)
                {
                    var metadata = iHasMetadata.GetMetadataObject();
                    if (metadata == null)
                    {
                        continue;
                    }

                    metadata.hideFlags = HideFlags.HideInHierarchy;
                    ctx.AddObjectToAsset($"{iHasMetadata.identifier}:Metadata", metadata);
                }
            }

            var sgMetadata = ScriptableObject.CreateInstance <ShaderGraphMetadata>();
            sgMetadata.hideFlags         = HideFlags.HideInHierarchy;
            sgMetadata.assetDependencies = new List <UnityEngine.Object>();

            foreach (var asset in assetCollection.assets)
            {
                if (asset.Value.HasFlag(AssetCollection.Flags.IncludeInExportPackage))
                {
                    // this sucks that we have to fully load these assets just to set the reference,
                    // which then gets serialized as the GUID that we already have here.  :P

                    var dependencyPath = AssetDatabase.GUIDToAssetPath(asset.Key);
                    if (!string.IsNullOrEmpty(dependencyPath))
                    {
                        sgMetadata.assetDependencies.Add(
                            AssetDatabase.LoadAssetAtPath(dependencyPath, typeof(UnityEngine.Object)));
                    }
                }
            }
            ctx.AddObjectToAsset("SGInternal:Metadata", sgMetadata);

            // declare dependencies
            foreach (var asset in assetCollection.assets)
            {
                if (asset.Value.HasFlag(AssetCollection.Flags.SourceDependency))
                {
                    ctx.DependsOnSourceAsset(asset.Key);

                    // I'm not sure if this warning below is actually used or not, keeping it to be safe
                    var assetPath = AssetDatabase.GUIDToAssetPath(asset.Key);

                    // Ensure that dependency path is relative to project
                    if (!string.IsNullOrEmpty(assetPath) && !assetPath.StartsWith("Packages/") && !assetPath.StartsWith("Assets/"))
                    {
                        Debug.LogWarning($"Invalid dependency path: {assetPath}", mainObject);
                    }
                }

                // NOTE: dependencies declared by GatherDependenciesFromSourceFile are automatically registered as artifact dependencies
                // HOWEVER: that path ONLY grabs dependencies via MinimalGraphData, and will fail to register dependencies
                // on GUIDs that don't exist in the project.  For both of those reasons, we re-declare the dependencies here.
                if (asset.Value.HasFlag(AssetCollection.Flags.ArtifactDependency))
                {
                    ctx.DependsOnArtifact(asset.Key);
                }
            }
        }
Beispiel #3
0
        GameObject GenerateModel(VoxModel model, AssetImportContext ctx)
        {
            var parser = new MagicaVoxelParser();

            parser.LoadModel(ctx.assetPath, model,
                             s => EditorUtility.DisplayProgressBar("vox", s, 0));

            var subAssets = new List <Object>();

            ctx.GetObjects(subAssets);
            var assetMeshes = subAssets
                              .Select(s => s as Mesh)
                              .Where(s => s != null)
                              .ToArray();
            var updateOpaque      = false;
            var updateTransparent = false;

            var uv3 = new List <Vector4>();

            var assetIndex = 0;

            for (int i = 0; i < model.meshes.Count; i++)
            {
                for (int l = 0; l < model.meshes[i].LODs.Count; l++)
                {
                    MeshSet m;
                    //get mesh
                    m.opaque      = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null;
                    m.transparent = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null;
                    updateOpaque  = m.opaque == null;
                    if (updateOpaque)
                    {
                        m.opaque = new Mesh();
                    }
                    updateTransparent = m.transparent == null;
                    if (updateTransparent)
                    {
                        m.transparent = new Mesh();
                    }

                    //turn temp meshes into assets

                    EditorUtility.DisplayProgressBar("vox",
                                                     $"asset: frame={i}/{model.meshes.Count}, lod={l}/{model.meshes[i].LODs.Count}",
                                                     .5f + (.5f * i) / model.voxelFrames.Count);
                    var frame = model.meshes[i].LODs[l];
                    BuildMesh(m.opaque, frame.opaque,
                              $"{name}.{i}.{l}.opaque", uv3, model.Settings.OmitsUVUnwrapping);
                    BuildMesh(m.transparent, frame.transparent,
                              $"{name}.{i}.{l}.transparent", uv3, model.Settings.OmitsUVUnwrapping);
                    //new mesh
                    if (updateOpaque)
                    {
                        ctx.AddObjectToAsset(m.opaque.name, m.opaque);
                    }
                    if (updateTransparent)
                    {
                        ctx.AddObjectToAsset(m.transparent.name, m.transparent);
                    }
                    model.meshes[i].LODs[l] = m;
                }
            }

            var baseGO = ctx.mainObject as GameObject;

            if (baseGO == null)
            {
                baseGO = new GameObject();
                ctx.AddObjectToAsset("main", baseGO);
                ctx.SetMainObject(baseGO);
            }
            var gos = Enumerable.Range(0, baseGO.transform.childCount)
                      .Select(i => baseGO.transform.GetChild(i))
                      .Select(t => t.gameObject)
                      .ToList();
            var gosCount = gos.Count;

            for (int i = gosCount; i < model.meshes.Count; i++)
            {
                var target = new GameObject();
                target.transform.SetParent(baseGO.transform);
                gos.Add(target.gameObject);
            }
            BuildLODGroups(model, gos);
            if (model.Settings.asSceneGraph)
            {
                var root = BuildSceneGraph(model, gos);
                DestroyImmediate(baseGO);
                baseGO = root;
                ctx.AddObjectToAsset("main", root);
                ctx.SetMainObject(root);
            }
            //destroy unneeded meshes
            var meshSetContained = model.meshes.SelectMany(x => x.LODs).ToArray();

            foreach (var go in subAssets
                     .Where(s => (s as Mesh) != null)
                     .Where(s => !meshSetContained.Any(x => x.Contains(s as Mesh))))
            {
                DestroyImmediate(go, true);
            }

            //DestroyImmediate(baseGO);
            return(baseGO);
        }
Beispiel #4
0
        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);
            }
        }
        /// <inheritdoc />
        public override void OnImportAsset(AssetImportContext ctx)
        {
            if (ctx == null)
            {
                return;
            }

            var outputFilePath = Path.Combine(Path.GetDirectoryName(ctx.assetPath), Path.GetFileNameWithoutExtension(ctx.assetPath) + ".cs");
            var src            = File.ReadAllText(ctx.assetPath);

            TemplateGenerator generator;

            switch (importerVersion)
            {
            case ImporterVersion.Stable:
                generator = new TemplateGenerator();
                break;

            case ImporterVersion.Beta:
            {
                generator = UnityDataHost <Object> .CreateInstance(embeddedData, additionalTypes);

                break;
            }

            default:
                throw new InvalidOperationException();
            }

            if (generator.ProcessTemplate(ctx.assetPath, src, ref outputFilePath, out string dst))
            {
                if (!removeIfEmptyGeneration || dst.Length > 0)
                {
                    File.WriteAllText(outputFilePath, dst);
                }

                EditorUtils.Once(() =>
                {
                    // TODO(bengreenier): is there a less expensive way to force it to reload scripts/appdomain?
                    AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
                });
            }
            else
            {
                for (var i = 0; i < generator.Errors.Count; i++)
                {
                    var err = generator.Errors[i];

                    Debug.LogError(err.ToString());
                }
            }

            // core asset import
            var asset = new TextAsset(src);

            ctx.AddObjectToAsset("text", asset);
            ctx.SetMainObject(asset);

            // setup data dependency
            if (embeddedData != null && importerVersion == ImporterVersion.Beta)
            {
                var dataPath = AssetDatabase.GetAssetPath(embeddedData);
                var dataGuid = AssetDatabase.GUIDFromAssetPath(dataPath);

                ctx.DependsOnArtifact(dataGuid);

                // needed to enforce the dependency
                AssetDatabase.LoadAssetAtPath <Object>(dataPath);
            }
        }
    public override void OnImportAsset(AssetImportContext ctx)
    {
        // We're using a hardcoded window size of 100x100. This way, using a pixels per point value of 100
        // results in a sprite of size 1 when the SVG file has a viewbox specified.
        SVGParser.SceneInfo sceneInfo;
        using (StreamReader stream = new StreamReader(ctx.assetPath))
        {
            sceneInfo = SVGParser.ImportSVG(stream, 0, 1, 100, 100, PreserveViewport);
        }

        if (sceneInfo.Scene == null || sceneInfo.Scene.Root == null)
        {
            throw new Exception("Wowzers!");
        }

        float stepDist         = StepDistance;
        float samplingStepDist = SamplingStepDistance;
        float maxCord          = MaxCordDeviationEnabled ? MaxCordDeviation : float.MaxValue;
        float maxTangent       = MaxTangentAngleEnabled ? MaxTangentAngle : Mathf.PI * 0.5f;

        if (!AdvancedMode)
        {
            // Automatically compute sensible tessellation options from the
            // vector scene's bouding box and target resolution
            ComputeTessellationOptions(sceneInfo, TargetResolution, ResolutionMultiplier, out stepDist, out maxCord, out maxTangent);
        }

        var tessOptions = new ShapeUtils.TessellationOptions();

        tessOptions.MaxCordDeviation     = maxCord;
        tessOptions.MaxTanAngleDeviation = maxTangent;
        tessOptions.SamplingStepSize     = 1.0f / (float)samplingStepDist;
        tessOptions.StepDistance         = stepDist;

        var rect = Rect.zero;

        if (PreserveViewport)
        {
            rect = sceneInfo.SceneViewport;
        }

        var geometry = ShapeUtils.TessellateScene(sceneInfo.Scene, tessOptions, sceneInfo.NodeOpacity);

        string name = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath);

        var gameObject = new GameObject("Shape" + name, typeof(MeshFilter), typeof(MeshRenderer));

        var mesh = new Mesh();

        mesh.name = "Mesh" + name;
        CalculateSideExtrusion(mesh, geometry);

        mesh.RecalculateBounds();
        mesh.RecalculateNormals();

        var mat = new Material(Shader.Find("Standard"));

        mat.name = "Material" + name;

        gameObject.GetComponent <MeshFilter>().mesh       = mesh;
        gameObject.GetComponent <MeshRenderer>().material = mat;

        ctx.AddObjectToAsset("shape", gameObject);
        ctx.AddObjectToAsset("mesh", mesh);
        ctx.AddObjectToAsset("material", mat);
        ctx.SetMainObject(gameObject);
    }
Beispiel #7
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var currentTime = DateTime.Now.Ticks;

            if (ctx.assetPath != path)
            {
                ctx.LogImportError("The sgpostsubgraph extension may only be used internally by Shader Graph.");
                return;
            }

            if (SubGraphDatabase.instance == null)
            {
                SubGraphDatabase.instance = ScriptableObject.CreateInstance <SubGraphDatabase>();
            }
            var database = SubGraphDatabase.instance;

            var allSubGraphGuids = AssetDatabase.FindAssets($"t:{nameof(SubGraphAsset)}").ToList();

            allSubGraphGuids.Sort();
            var subGraphMap  = new Dictionary <string, SubGraphData>();
            var graphDataMap = new Dictionary <string, GraphData>();

            foreach (var subGraphData in database.subGraphs)
            {
                if (allSubGraphGuids.BinarySearch(subGraphData.assetGuid) >= 0)
                {
                    subGraphMap.Add(subGraphData.assetGuid, subGraphData);
                }
            }

            var dirtySubGraphGuids = new List <string>();

            foreach (var subGraphGuid in allSubGraphGuids)
            {
                var subGraphAsset = AssetDatabase.LoadAssetAtPath <SubGraphAsset>(AssetDatabase.GUIDToAssetPath(subGraphGuid));
                if (!subGraphMap.TryGetValue(subGraphGuid, out var subGraphData))
                {
                    subGraphData = new SubGraphData();
                }

                if (subGraphAsset.importedAt > subGraphData.processedAt)
                {
                    dirtySubGraphGuids.Add(subGraphGuid);
                    subGraphData.Reset();
                    subGraphData.processedAt = currentTime;
                    var subGraphPath = AssetDatabase.GUIDToAssetPath(subGraphGuid);
                    var textGraph    = File.ReadAllText(subGraphPath, Encoding.UTF8);
                    var graphData    = new GraphData {
                        isSubGraph = true, assetGuid = subGraphGuid
                    };
                    JsonUtility.FromJsonOverwrite(textGraph, graphData);
                    subGraphData.children.AddRange(graphData.GetNodes <SubGraphNode>().Select(x => x.subGraphGuid).Distinct());
                    subGraphData.assetGuid     = subGraphGuid;
                    subGraphMap[subGraphGuid]  = subGraphData;
                    graphDataMap[subGraphGuid] = graphData;
                }
                else
                {
                    subGraphData.ancestors.Clear();
                    subGraphData.descendents.Clear();
                    subGraphData.isRecursive = false;
                }
            }

            database.subGraphs.Clear();
            database.subGraphs.AddRange(subGraphMap.Values);
            database.subGraphs.Sort((s1, s2) => s1.assetGuid.CompareTo(s2.assetGuid));
            database.subGraphGuids.Clear();
            database.subGraphGuids.AddRange(database.subGraphs.Select(x => x.assetGuid));

            var permanentMarks = new HashSet <string>();
            var stack          = new Stack <string>(allSubGraphGuids.Count);

            // Detect recursion, and populate `ancestors` and `descendents` per sub graph.
            foreach (var rootSubGraphData in database.subGraphs)
            {
                var rootSubGraphGuid = rootSubGraphData.assetGuid;
                stack.Push(rootSubGraphGuid);
                while (stack.Count > 0)
                {
                    var subGraphGuid = stack.Pop();
                    if (!permanentMarks.Add(subGraphGuid))
                    {
                        continue;
                    }

                    var subGraphData = subGraphMap[subGraphGuid];
                    if (subGraphData != rootSubGraphData)
                    {
                        subGraphData.ancestors.Add(rootSubGraphGuid);
                        rootSubGraphData.descendents.Add(subGraphGuid);
                    }
                    foreach (var childSubGraphGuid in subGraphData.children)
                    {
                        if (childSubGraphGuid == rootSubGraphGuid)
                        {
                            rootSubGraphData.isRecursive = true;
                        }
                        else if (subGraphMap.ContainsKey(childSubGraphGuid))
                        {
                            stack.Push(childSubGraphGuid);
                        }
                    }
                }
                permanentMarks.Clear();
            }

            // Next up we build a list of sub graphs to be processed, which will later be sorted topologically.
            var sortedSubGraphs = new List <SubGraphData>();

            foreach (var subGraphGuid in dirtySubGraphGuids)
            {
                var subGraphData = subGraphMap[subGraphGuid];
                if (permanentMarks.Add(subGraphGuid))
                {
                    sortedSubGraphs.Add(subGraphData);
                }

                // Note that we're traversing up the graph via ancestors rather than descendents, because all Sub Graphs using the current sub graph needs to be re-processed.
                foreach (var ancestorGuid in subGraphData.ancestors)
                {
                    if (permanentMarks.Add(ancestorGuid))
                    {
                        var ancestorSubGraphData = subGraphMap[ancestorGuid];
                        sortedSubGraphs.Add(ancestorSubGraphData);
                    }
                }
            }
            permanentMarks.Clear();

            // Sort topologically. At this stage we can assume there are no loops because all recursive sub graphs have been filtered out.
            sortedSubGraphs.Sort((s1, s2) => s1.descendents.Contains(s2.assetGuid) ? 1 : s2.descendents.Contains(s1.assetGuid) ? -1 : 0);

            // Finally process the topologically sorted sub graphs without recursion.
            var registry       = new FunctionRegistry(new ShaderStringBuilder(), true);
            var messageManager = new MessageManager();

            foreach (var subGraphData in sortedSubGraphs)
            {
                try
                {
                    var subGraphPath = AssetDatabase.GUIDToAssetPath(subGraphData.assetGuid);
                    if (!graphDataMap.TryGetValue(subGraphData.assetGuid, out var graphData))
                    {
                        var textGraph = File.ReadAllText(subGraphPath, Encoding.UTF8);
                        graphData = new GraphData {
                            isSubGraph = true, assetGuid = subGraphData.assetGuid
                        };
                        JsonUtility.FromJsonOverwrite(textGraph, graphData);
                    }

                    graphData.messageManager = messageManager;
                    ProcessSubGraph(subGraphMap, registry, subGraphData, graphData);
                    if (messageManager.nodeMessagesChanged)
                    {
                        var subGraphAsset = AssetDatabase.LoadAssetAtPath <SubGraphAsset>(AssetDatabase.GUIDToAssetPath(subGraphData.assetGuid));
                        foreach (var pair in messageManager.GetNodeMessages())
                        {
                            var node = graphData.GetNodeFromTempId(pair.Key);
                            foreach (var message in pair.Value)
                            {
                                MessageManager.Log(node, subGraphPath, message, subGraphAsset);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    subGraphData.isValid = false;
                    var subGraphAsset = AssetDatabase.LoadAssetAtPath <SubGraphAsset>(AssetDatabase.GUIDToAssetPath(subGraphData.assetGuid));
                    Debug.LogException(e, subGraphAsset);
                }
                finally
                {
                    subGraphData.processedAt = currentTime;
                    messageManager.ClearAll();
                }
            }

            // Carry over functions used by sub-graphs that were not re-processed in this import.
            foreach (var subGraphData in database.subGraphs)
            {
                foreach (var functionName in subGraphData.functionNames)
                {
                    if (!registry.sources.ContainsKey(functionName))
                    {
                        registry.sources.Add(functionName, database.functionSources[database.functionNames.BinarySearch(functionName)]);
                    }
                }
            }

            var functions = registry.sources.ToList();

            functions.Sort((p1, p2) => p1.Key.CompareTo(p2.Key));
            database.functionNames.Clear();
            database.functionSources.Clear();
            foreach (var pair in functions)
            {
                database.functionNames.Add(pair.Key);
                database.functionSources.Add(pair.Value);
            }

            ctx.AddObjectToAsset("MainAsset", database);
            ctx.SetMainObject(database);

            SubGraphDatabase.instance = null;
        }
        public static async void OnImportGltfAsset(AssetImportContext context)
        {
            var importedObject = await GltfUtility.ImportGltfObjectFromPathAsync(context.assetPath);

            if (importedObject == null ||
                importedObject.GameObjectReference == null)
            {
                Debug.LogError("Failed to import glTF object");
                return;
            }

            var gltfAsset = (GltfAsset)ScriptableObject.CreateInstance(typeof(GltfAsset));

            gltfAsset.GltfObject = importedObject;
            gltfAsset.name       = $"{gltfAsset.GltfObject.Name}{Path.GetExtension(context.assetPath)}";
            gltfAsset.Model      = importedObject.GameObjectReference;
            context.AddObjectToAsset("main", gltfAsset.Model);
            context.SetMainObject(importedObject.GameObjectReference);
            context.AddObjectToAsset("glTF data", gltfAsset);

            bool reImport = false;

            for (var i = 0; i < gltfAsset.GltfObject.textures?.Length; i++)
            {
                GltfTexture gltfTexture = gltfAsset.GltfObject.textures[i];

                if (gltfTexture == null)
                {
                    continue;
                }

                var path = AssetDatabase.GetAssetPath(gltfTexture.Texture);

                if (string.IsNullOrWhiteSpace(path))
                {
                    var textureName = gltfTexture.name;

                    if (string.IsNullOrWhiteSpace(textureName))
                    {
                        textureName = $"Texture_{i}";
                        gltfTexture.Texture.name = textureName;
                    }

                    context.AddObjectToAsset(textureName, gltfTexture.Texture);
                }
                else
                {
                    if (!gltfTexture.Texture.isReadable)
                    {
                        var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
                        if (textureImporter != null)
                        {
                            textureImporter.isReadable = true;
                            textureImporter.SetPlatformTextureSettings(new TextureImporterPlatformSettings {
                                format = TextureImporterFormat.RGBA32
                            });
                            textureImporter.SaveAndReimport();
                            reImport = true;
                        }
                    }
                }
            }

            if (reImport)
            {
                var importer = AssetImporter.GetAtPath(context.assetPath);
                importer.SaveAndReimport();
                return;
            }

            for (var i = 0; i < gltfAsset.GltfObject.meshes?.Length; i++)
            {
                GltfMesh gltfMesh = gltfAsset.GltfObject.meshes[i];

                string meshName = string.IsNullOrWhiteSpace(gltfMesh.name) ? $"Mesh_{i}" : gltfMesh.name;

                gltfMesh.Mesh.name = meshName;
                context.AddObjectToAsset($"{meshName}", gltfMesh.Mesh);
            }

            if (gltfAsset.GltfObject.materials != null)
            {
                foreach (GltfMaterial gltfMaterial in gltfAsset.GltfObject.materials)
                {
                    if (context.assetPath.EndsWith(".glb"))
                    {
                        context.AddObjectToAsset(gltfMaterial.name, gltfMaterial.Material);
                    }
                    else
                    {
                        var relativePath = Path.GetFullPath(Path.GetDirectoryName(context.assetPath)).Replace(Path.GetFullPath(Application.dataPath), "Assets");
                        relativePath = Path.Combine(relativePath, $"{gltfMaterial.name}.mat");
                        AssetDatabase.CreateAsset(gltfMaterial.Material, relativePath);
                        gltfMaterial.Material = AssetDatabase.LoadAssetAtPath <Material>(relativePath);
                    }
                }
            }
        }
    public override void OnImportAsset(AssetImportContext ctx)
    {
        var mesh = new Mesh();

        ctx.AddObjectToAsset("mesh0", mesh);
        ctx.SetMainObject(mesh);

        using (BinaryReader reader = new BinaryReader(File.Open(ctx.assetPath, FileMode.Open))) {
            byte[] searchBuf = new byte[32];
            var    markerStr = "DatasmithMeshSourceModel";

            byte[] marker       = System.Text.Encoding.ASCII.GetBytes(markerStr);
            uint   markerLength = (uint)markerStr.Length;

            bool didFindMarker = false;
            while (reader.BaseStream.Position < (reader.BaseStream.Length - markerLength))
            {
                reader.BaseStream.Read(searchBuf, 0, (int)markerLength);
                if (0 == memcmp(searchBuf, marker, markerLength))
                {
                    reader.BaseStream.Position += 2; // Skip 2 extra null bytes after the marker
                    didFindMarker = true;
                    break;
                }

                // rewind to 1 byte after the previous read position
                reader.BaseStream.Position -= (markerLength - 1);
            }

            if (!didFindMarker)
            {
                throw new Exception("Couldn't find marker " + markerStr + " in file " + ctx.assetPath);
            }

            for (uint i = 0; i < 6; ++i)
            {
                if (reader.ReadUInt32() != 0)
                {
                    Console.Out.WriteLine("Warning: expected all zeros between marker and start of material index array");
                }
            }

            reader.ReadUInt32(); // length1
            reader.ReadUInt32(); // length2
            reader.ReadUInt32(); // unknown 9c 00 00 00
            reader.ReadUInt32(); // unknown 00 00 00 00
            reader.ReadUInt32(); // unknown 01 00 00 00
            reader.ReadUInt32(); // unknown 00 00 00 00


            uint   materialIndexCount = reader.ReadUInt32();
            uint[] materialIndices    = new uint[materialIndexCount];
            for (uint i = 0; i < materialIndexCount; ++i)
            {
                materialIndices[i] = reader.ReadUInt32();
            }

            uint   unknownCount = reader.ReadUInt32();
            uint[] unknownData  = new uint[unknownCount];
            for (uint i = 0; i < unknownCount; ++i)
            {
                unknownData[i] = reader.ReadUInt32();
            }

            List <Vector3> vertices = new List <Vector3>();

            Dictionary <int, int> indexRemap = new Dictionary <int, int>();
            {
                // Collapse vertices and generate an index remapping table
                Dictionary <Vector3, int> uniqueVertices = new Dictionary <Vector3, int>();


                int fileVertexCount = (int)reader.ReadUInt32();
                int vertexLimit     = 524288;

                if (fileVertexCount > vertexLimit)
                {
                    ctx.LogImportError(String.Format("UdsMeshImporter: Sanity check failed: File {0} has too many vertices ({1}, limit is {2}) -- returning empty mesh.", ctx.assetPath, fileVertexCount, vertexLimit));
                    return;
                }

                for (int i = 0; i < fileVertexCount; ++i)
                {
                    Vector3 v = new Vector3();
                    // Adjust scale from cm -> meters
                    v.x = reader.ReadSingle() * 0.01f;
                    v.y = reader.ReadSingle() * 0.01f;
                    v.z = reader.ReadSingle() * 0.01f;

                    if (!uniqueVertices.ContainsKey(v))
                    {
                        vertices.Add(v);
                        uniqueVertices.Add(v, vertices.Count - 1);
                    }

                    indexRemap.Add(i, uniqueVertices[v]);
                }

                /*
                 * if (vertices.Count < fileVertexCount) {
                 * Debug.Log(String.Format("Vertex position remapping removed {0} nonunique positions", fileVertexCount - vertices.Count));
                 * }
                 */
            }


            uint  indexCount      = reader.ReadUInt32();
            int[] triangleIndices = new int[indexCount];
            for (uint triIdx = 0; triIdx < (indexCount / 3); ++triIdx)
            {
                triangleIndices[(triIdx * 3) + 0] = indexRemap[(int)reader.ReadUInt32()];
                triangleIndices[(triIdx * 3) + 1] = indexRemap[(int)reader.ReadUInt32()];
                triangleIndices[(triIdx * 3) + 2] = indexRemap[(int)reader.ReadUInt32()];
            }

            reader.ReadUInt32(); // unknown-zero, maybe a count of an unused field
            reader.ReadUInt32(); // unknown-zero, maybe a count of an unused field
            uint      normalCount = reader.ReadUInt32();
            Vector3[] normals     = new Vector3[normalCount];
            for (uint i = 0; i < normalCount; ++i)
            {
                normals[i].x = reader.ReadSingle();
                normals[i].y = reader.ReadSingle();
                normals[i].z = reader.ReadSingle();
            }


            uint      uvCount = reader.ReadUInt32();
            Vector2[] uvs     = new Vector2[uvCount];
            for (uint i = 0; i < uvCount; ++i)
            {
                uvs[i].x = reader.ReadSingle();
                uvs[i].y = reader.ReadSingle();
            }

            // Datasmith hands us per-face-vertex normals and UVs, which Unity can't handle.
            // Use the Datasmith-supplied index array to write new per-submesh (material group) position/normal/UV buffers.

            {
                var  materialToSubmesh = new SortedDictionary <uint, uint>();
                uint submeshCount      = 0;
                for (uint triIdx = 0; triIdx < materialIndexCount; ++triIdx)
                {
                    uint midx = materialIndices[triIdx];
                    if (!materialToSubmesh.ContainsKey(midx))
                    {
                        materialToSubmesh[midx] = submeshCount;
                        submeshCount           += 1;
                    }
                }


                List <Vector3>     cookedPositions      = new List <Vector3>();
                List <Vector2>     cookedUVs            = new List <Vector2>();
                List <Vector3>     cookedNormals        = new List <Vector3>();
                List <List <int> > cookedSubmeshIndices = new List <List <int> >();

                List <Dictionary <Hash128, int> > vertexCollapseData = new List <Dictionary <Hash128, int> >(vertices.Count);
                // Prepopulate the vertex-collapse list with empty dicts
                for (int vIdx = 0; vIdx < vertices.Count; ++vIdx)
                {
                    vertexCollapseData.Add(new Dictionary <Hash128, int>());
                }


                for (uint submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
                {
                    List <int> thisSubmeshIndices = new List <int>();

                    for (uint triIdx = 0; triIdx < materialIndexCount; ++triIdx)
                    {
                        if (materialToSubmesh[materialIndices[triIdx]] != submeshIndex)
                        {
                            continue; // this triangle is not relevant in this submesh.
                        }
                        for (uint triVIdx = 0; triVIdx < 3; ++triVIdx)
                        {
                            uint triVIdx_adj = 2 - triVIdx; // Adjusted to swap winding order

                            int     positionIndex = triangleIndices[(triIdx * 3) + triVIdx_adj];
                            Vector3 fvP           = vertices[positionIndex];
                            Vector2 fvUV          = uvs[(triIdx * 3) + triVIdx_adj];
                            Vector3 fvN           = normals[(triIdx * 3) + triVIdx_adj];

                            // Try and find an existing vertex/normal/UV set to reuse
                            // We already collapsed coincident positions while reading the vertex and index buffers, so we can partition our search by position index.
                            Dictionary <Hash128, int> collapseData = vertexCollapseData[positionIndex];
                            Hash128 targetHash = NUVHash(fvN, fvUV);
                            int     targetVIdx;

                            if (collapseData.ContainsKey(targetHash))
                            {
                                // Match found, reuse the previous vertex
                                targetVIdx = collapseData[targetHash];
                            }
                            else
                            {
                                // No match found, so we add it
                                cookedPositions.Add(fvP);
                                cookedUVs.Add(fvUV);
                                cookedNormals.Add(fvN);

                                targetVIdx = cookedPositions.Count - 1;
                                collapseData.Add(targetHash, targetVIdx);
                            }


                            thisSubmeshIndices.Add(targetVIdx);
                        }
                    }
                    cookedSubmeshIndices.Add(thisSubmeshIndices);
                }

                mesh.Clear();
                if (cookedPositions.Count > 65535)
                {
                    ctx.LogImportWarning(String.Format("Mesh \"{0}\" has more than 65535 vertices ({1}) and requires a 32-bit index buffer. This mesh may not render correctly on all platforms.", ctx.assetPath, cookedPositions.Count));
                    mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
                }

                mesh.SetVertices(cookedPositions);
                mesh.SetUVs(0, cookedUVs);
                mesh.SetNormals(cookedNormals);
                mesh.subMeshCount = (int)submeshCount;
                for (uint submeshIndex = 0; submeshIndex < submeshCount; ++submeshIndex)
                {
                    mesh.SetIndices(cookedSubmeshIndices[(int)submeshIndex].ToArray(), MeshTopology.Triangles, (int)submeshIndex);
                }

                // Generate lightmap UVs
                if (materialIndexCount > 50000 /*triangles*/)
                {
                    if (m_ForceLightmapUVGeneration)
                    {
                        UnityEditor.Unwrapping.GenerateSecondaryUVSet(mesh);
                    }
                    else
                    {
                        ctx.LogImportWarning(String.Format("Mesh \"{0}\": lightmap UVs won't automatically be generated due to complexity limits. Turn on \"Force Lightmap UV generation\" to override.", ctx.assetPath));
                    }
                }

                mesh.RecalculateBounds();
                mesh.RecalculateTangents();
            }
        }
    }
Beispiel #10
0
 public void Add(string identifier, Object asset)
 {
     m_ctx.AddObjectToAsset(identifier, asset);
 }
        // [SerializeField] private bool _useJpgTextures = false;

        public override void OnImportAsset(AssetImportContext ctx)
        {
            string     sceneName = null;
            GameObject gltfScene = null;

            UnityEngine.Mesh[] meshes = null;
            try
            {
                sceneName = Path.GetFileNameWithoutExtension(ctx.assetPath);
                gltfScene = CreateGLTFScene(ctx.assetPath);

                // Remove empty roots
                if (_removeEmptyRootObjects)
                {
                    var t = gltfScene.transform;
                    while (
                        gltfScene.transform.childCount == 1 &&
                        gltfScene.GetComponents <Component>().Length == 1)
                    {
                        var parent = gltfScene;
                        gltfScene = gltfScene.transform.GetChild(0).gameObject;
                        t         = gltfScene.transform;
                        t.parent  = null;                // To keep transform information in the new parent
                        Object.DestroyImmediate(parent); // Get rid of the parent
                    }
                }

                // Ensure there are no hide flags present (will cause problems when saving)
                gltfScene.hideFlags &= ~(HideFlags.HideAndDontSave);
                foreach (Transform child in gltfScene.transform)
                {
                    child.gameObject.hideFlags &= ~(HideFlags.HideAndDontSave);
                }

                // Zero position
                gltfScene.transform.position = Vector3.zero;

                // Get meshes
                var meshNames   = new List <string>();
                var meshHash    = new HashSet <UnityEngine.Mesh>();
                var meshFilters = gltfScene.GetComponentsInChildren <MeshFilter>().Select(x => (x.gameObject, x.sharedMesh)).ToList();
                meshFilters.AddRange(gltfScene.GetComponentsInChildren <SkinnedMeshRenderer>().Select(x => (x.gameObject, x.sharedMesh)));
                var vertexBuffer = new List <Vector3>();
                meshes = meshFilters.Select(mf =>
                {
                    var mesh = mf.sharedMesh;
                    vertexBuffer.Clear();
                    mesh.GetVertices(vertexBuffer);
                    for (var i = 0; i < vertexBuffer.Count; ++i)
                    {
                        vertexBuffer[i] *= _scaleFactor;
                    }
                    mesh.SetVertices(vertexBuffer);
                    if (_swapUvs)
                    {
                        var uv   = mesh.uv;
                        var uv2  = mesh.uv2;
                        mesh.uv  = uv2;
                        mesh.uv2 = uv2;
                    }
                    if (_importNormals == GLTFImporterNormals.None)
                    {
                        mesh.normals = new Vector3[0];
                    }
                    if (_importNormals == GLTFImporterNormals.Calculate && mesh.GetTopology(0) == MeshTopology.Triangles)
                    {
                        mesh.RecalculateNormals();
                    }
                    mesh.UploadMeshData(!_readWriteEnabled);

                    if (_generateColliders)
                    {
                        var collider        = mf.gameObject.AddComponent <MeshCollider>();
                        collider.sharedMesh = mesh;
                    }

                    if (meshHash.Add(mesh))
                    {
                        var meshName = string.IsNullOrEmpty(mesh.name) ? mf.gameObject.name : mesh.name;
                        mesh.name    = ObjectNames.GetUniqueName(meshNames.ToArray(), meshName);
                        meshNames.Add(mesh.name);
                    }

                    return(mesh);
                }).ToArray();

                var animations = gltfScene.GetComponentsInChildren <Animation>();
                var clips      = animations.SelectMany(x => AnimationUtility.GetAnimationClips(x.gameObject));
                foreach (var clip in clips)
                {
                    ctx.AddObjectToAsset(clip.name, clip);
                }

                var renderers = gltfScene.GetComponentsInChildren <Renderer>();

                if (_importMaterials)
                {
                    // Get materials
                    var materialNames = new List <string>();
                    var materialHash  = new HashSet <UnityEngine.Material>();
                    var materials     = renderers.SelectMany(r =>
                    {
                        return(r.sharedMaterials.Select(mat =>
                        {
                            if (materialHash.Add(mat))
                            {
                                var matName = string.IsNullOrEmpty(mat.name) ? mat.shader.name : mat.name;
                                if (matName == mat.shader.name)
                                {
                                    matName = matName.Substring(Mathf.Min(matName.LastIndexOf("/") + 1, matName.Length - 1));
                                }

                                // Ensure name is unique
                                matName = ObjectNames.NicifyVariableName(matName);
                                matName = ObjectNames.GetUniqueName(materialNames.ToArray(), matName);

                                mat.name = matName;
                                materialNames.Add(matName);
                            }

                            return mat;
                        }));
                    }).Distinct().ToArray();

                    // Get textures
                    var textureNames   = new List <string>();
                    var textureHash    = new HashSet <Texture2D>();
                    var texMaterialMap = new Dictionary <Texture2D, List <TexMaterialMap> >();
                    var textures       = materials.SelectMany(mat =>
                    {
                        var shader = mat.shader;
                        if (!shader)
                        {
                            return(Enumerable.Empty <Texture2D>());
                        }

                        var matTextures = new List <Texture2D>();
                        for (var i = 0; i < ShaderUtil.GetPropertyCount(shader); ++i)
                        {
                            if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv)
                            {
                                var propertyName = ShaderUtil.GetPropertyName(shader, i);
                                var tex          = mat.GetTexture(propertyName) as Texture2D;
                                if (tex)
                                {
                                    if (textureHash.Add(tex))
                                    {
                                        var texName = tex.name;
                                        if (string.IsNullOrEmpty(texName))
                                        {
                                            if (propertyName.StartsWith("_"))
                                            {
                                                texName = propertyName.Substring(Mathf.Min(1, propertyName.Length - 1));
                                            }
                                        }

                                        // Ensure name is unique
                                        texName = string.Format("{0} {1}", sceneName, ObjectNames.NicifyVariableName(texName));
                                        texName = ObjectNames.GetUniqueName(textureNames.ToArray(), texName);

                                        tex.name = texName;
                                        textureNames.Add(texName);
                                        matTextures.Add(tex);
                                    }

                                    List <TexMaterialMap> materialMaps;
                                    if (!texMaterialMap.TryGetValue(tex, out materialMaps))
                                    {
                                        materialMaps = new List <TexMaterialMap>();
                                        texMaterialMap.Add(tex, materialMaps);
                                    }

                                    materialMaps.Add(new TexMaterialMap(mat, propertyName, propertyName == "_BumpMap"));
                                }
                            }
                        }
                        return(matTextures);
                    }).Distinct().ToArray();

                    // var folderName = Path.GetDirectoryName(ctx.assetPath);

                    // Save textures as separate assets and rewrite refs
                    // TODO: Support for other texture types
                    if (textures.Length > 0)
                    {
                        // var texturesRoot = string.Concat(folderName, "/", "Textures/");
                        // Directory.CreateDirectory(texturesRoot);

                        foreach (var tex in textures)
                        {
                            // var ext = _useJpgTextures ? ".jpg" : ".png";
                            // var texPath = string.Concat(texturesRoot, tex.name, ext);
                            // File.WriteAllBytes(texPath, _useJpgTextures ? tex.EncodeToJPG() : tex.EncodeToPNG());
                            //
                            // AssetDatabase.ImportAsset(texPath);
                            ctx.AddObjectToAsset(tex.name, tex);
                        }
                    }

                    AssetDatabase.Refresh();

                    // Save materials as separate assets and rewrite refs
                    if (materials.Length > 0)
                    {
                        // var materialRoot = string.Concat(folderName, "/", "Materials/");
                        // Directory.CreateDirectory(materialRoot);

                        foreach (var mat in materials)
                        {
                            // var materialPath = string.Concat(materialRoot, mat.name, ".mat");
                            // var newMat = mat;
                            // CopyOrNew(mat, materialPath, m =>
                            // {
                            //     // Fix references
                            //     newMat = m;
                            //     foreach (var r in renderers)
                            //     {
                            //         var sharedMaterials = r.sharedMaterials;
                            //         for (var i = 0; i < sharedMaterials.Length; ++i)
                            //         {
                            //             var sharedMaterial = sharedMaterials[i];
                            //             if (sharedMaterial.name == mat.name) sharedMaterials[i] = m;
                            //         }
                            //         sharedMaterials = sharedMaterials.Where(sm => sm).ToArray();
                            //         r.sharedMaterials = sharedMaterials;
                            //     }
                            // });
                            ctx.AddObjectToAsset(mat.name, mat);

                            // Fix textures
                            // HACK: This needs to be a delayed call.
                            // Unity needs a frame to kick off the texture import so we can rewrite the ref
                            // if (textures.Length > 0)
                            // {
                            //     EditorApplication.delayCall += () =>
                            //     {
                            //         for (var i = 0; i < textures.Length; ++i)
                            //         {
                            //             var tex = textures[i];
                            //             var texturesRoot = string.Concat(folderName, "/", "Textures/");
                            //             var ext = _useJpgTextures ? ".jpg" : ".png";
                            //             var texPath = string.Concat(texturesRoot, tex.name, ext);
                            //
                            //             // Grab new imported texture
                            //             var materialMaps = texMaterialMap[tex];
                            //             var importer = (TextureImporter)TextureImporter.GetAtPath(texPath);
                            //             var importedTex = AssetDatabase.LoadAssetAtPath<Texture2D>(texPath);
                            //             if (importer != null)
                            //             {
                            //                 var isNormalMap = false;
                            //                 foreach (var materialMap in materialMaps)
                            //                 {
                            //                     if (materialMap.Material == mat)
                            //                     {
                            //                         isNormalMap |= materialMap.IsNormalMap;
                            //                         newMat.SetTexture(materialMap.Property, importedTex);
                            //                     }
                            //                 };
                            //
                            //                 if (isNormalMap)
                            //                 {
                            //                     // Try to auto-detect normal maps
                            //                     importer.textureType = TextureImporterType.NormalMap;
                            //                 }
                            //                 else if (importer.textureType == TextureImporterType.Sprite)
                            //                 {
                            //                     // Force disable sprite mode, even for 2D projects
                            //                     importer.textureType = TextureImporterType.Default;
                            //                 }
                            //             }
                            //             else
                            //             {
                            //                 Debug.LogWarning("GLTFImporter: Unable to import texture from path reference");
                            //             }
                            //         }
                            //     };
                            // }
                        }
                    }

                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                }
                else
                {
                    var temp = GameObject.CreatePrimitive(PrimitiveType.Plane);
                    temp.SetActive(false);
                    var defaultMat = new[] { temp.GetComponent <Renderer>().sharedMaterial };
                    DestroyImmediate(temp);

                    foreach (var rend in renderers)
                    {
                        rend.sharedMaterials = defaultMat;
                    }
                }
            }
            catch
            {
                if (gltfScene)
                {
                    DestroyImmediate(gltfScene);
                }
                throw;
            }



#if UNITY_2017_3_OR_NEWER
            // Set main asset
            ctx.AddObjectToAsset("main asset", gltfScene);

            // Add meshes
            foreach (var mesh in meshes)
            {
                try {
                    ctx.AddObjectToAsset("mesh " + mesh.name, mesh);
                } catch (System.InvalidOperationException e) {
                    Debug.LogWarning(e.ToString(), mesh);
                }
            }

            ctx.SetMainObject(gltfScene);
#else
            // Set main asset
            ctx.SetMainAsset("main asset", gltfScene);

            // Add meshes
            foreach (var mesh in meshes)
            {
                try {
                    ctx.AddSubAsset("mesh " + mesh.name, mesh);
                } catch (System.InvalidOperationException e) {
                    Debug.LogWarning(e.ToString(), mesh);
                }
            }
#endif
        }
Beispiel #12
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            if (ctx == null)
            {
                return;
            }

            var path = ctx.assetPath;

            AlembicStream.DisconnectStreamsWithPath(path);

            var fileName       = Path.GetFileNameWithoutExtension(path);
            var previousGoName = fileName;

            if (!string.IsNullOrEmpty(rootGameObjectName))
            {
                previousGoName = rootGameObjectName;
            }
            var go = new GameObject(previousGoName);

            var streamDescriptor = ScriptableObject.CreateInstance <AlembicStreamDescriptor>();

            streamDescriptor.name      = go.name + "_ABCDesc";
            streamDescriptor.PathToAbc = path;
            streamDescriptor.Settings  = StreamSettings;

            using (new RuntimeUtils.DisableUndoGuard(true))
            {
                using (var abcStream = new AlembicStream(go, streamDescriptor))
                {
                    abcStream.AbcLoad(true, true);
                    abcStream.GetTimeRange(out abcStartTime, out abcEndTime);
                    if (firstImport)
                    {
                        startTime = abcStartTime;
                        endTime   = abcEndTime;
                    }

                    streamDescriptor.MediaStartTime = (float)abcStartTime;
                    streamDescriptor.MediaEndTime   = (float)abcEndTime;

                    var streamPlayer = go.AddComponent <AlembicStreamPlayer>();
                    streamPlayer.StreamSource     = AlembicStreamPlayer.AlembicStreamSource.Internal;
                    streamPlayer.StreamDescriptor = streamDescriptor;
                    streamPlayer.StartTime        = (float)StartTime;
                    streamPlayer.EndTime          = (float)EndTime;

                    var subassets = new Subassets(ctx);
                    subassets.Add(streamDescriptor.name, streamDescriptor);
                    GenerateSubAssets(subassets, abcStream.abcTreeRoot, streamDescriptor);

                    AlembicStream.ReconnectStreamsWithPath(path);

                    var prevIdName = fileName;
                    if (!string.IsNullOrEmpty(rootGameObjectId))
                    {
                        prevIdName = rootGameObjectId;
                    }

                    ctx.AddObjectToAsset(prevIdName, go);
                    ctx.SetMainObject(go);

                    isHDF5 = abcStream.IsHDF5();
                    if (IsHDF5)
                    {
                        Debug.LogError(path + ": Unsupported HDF5 file format detected. Please convert to Ogawa.");
                    }
                }
            }

            firstImport = false;
        }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var width         = 64;
            var height        = 64;
            var mipmapEnabled = true;
            var textureFormat = TextureFormat.ARGB32;
            var srgbTexture   = true;

            // Check if the input textures are valid to be used to build the texture array.
            var isValid = Verify(ctx, false);

            if (isValid)
            {
                // Use the texture assigned to the first slice as "master".
                // This means all other textures have to use same settings as the master texture.
                var sourceTexture = m_Textures[0];
                width         = sourceTexture.width;
                height        = sourceTexture.height;
                textureFormat = sourceTexture.format;

                var sourceTexturePath = AssetDatabase.GetAssetPath(sourceTexture);
                var textureImporter   = (TextureImporter)AssetImporter.GetAtPath(sourceTexturePath);
                mipmapEnabled = textureImporter.mipmapEnabled;
                srgbTexture   = textureImporter.sRGBTexture;
            }

            // Create the texture array.
            // When the texture array asset is being created, there are no input textures added yet,
            // thus we do Max(1, Count) to make sure to add at least 1 slice.
            var texture2DArray = new Texture2DArray(width, height, Mathf.Max(1, m_Textures.Count), textureFormat, mipmapEnabled, !srgbTexture);

            texture2DArray.wrapMode   = m_WrapMode;
            texture2DArray.filterMode = m_FilterMode;
            texture2DArray.anisoLevel = m_AnisoLevel;

            if (isValid)
            {
                // If everything is valid, copy source textures over to the texture array.
                for (var n = 0; n < m_Textures.Count; ++n)
                {
                    var source = m_Textures[n];
                    Graphics.CopyTexture(source, 0, texture2DArray, n);
                }
            }
            else
            {
                // If there is any error, copy a magenta colored texture into every slice.
                // I was thinking to only make the invalid slice magenta, but then it's way less obvious that
                // something isn't right with the texture array. Thus I mark the entire texture array as broken.
                var errorTexture = new Texture2D(width, height, textureFormat, mipmapEnabled);
                try
                {
                    var errorPixels = errorTexture.GetPixels32();
                    for (var n = 0; n < errorPixels.Length; ++n)
                    {
                        errorPixels[n] = Color.magenta;
                    }
                    errorTexture.SetPixels32(errorPixels);
                    errorTexture.Apply();

                    for (var n = 0; n < texture2DArray.depth; ++n)
                    {
                        Graphics.CopyTexture(errorTexture, 0, texture2DArray, n);
                    }
                }
                finally
                {
                    DestroyImmediate(errorTexture);
                }
            }

            // Mark all input textures as dependency to the texture array.
            // This causes the texture array to get re-generated when any input texture changes or when the build target changed.
            for (var n = 0; n < m_Textures.Count; ++n)
            {
                var source = m_Textures[n];
                if (source != null)
                {
                    var path = AssetDatabase.GetAssetPath(source);
                    ctx.DependsOnSourceAsset(path);
                }
            }

            ctx.AddObjectToAsset("Texture2DArray", texture2DArray);
            ctx.SetMainObject(texture2DArray);

            if (!isValid)
            {
                // Run the verify step again, but this time we have the main object asset.
                // Console logs should ping the asset, but they don't in 2019.3 beta, bug?
                Verify(ctx, true);
            }
        }
Beispiel #14
0
        /// <summary>
        /// Common method performing the import of the asset
        /// </summary>
        /// <param name="ctx">Asset importer context.</param>
        public override void OnImportAsset(AssetImportContext ctx)
        {
            engine.TextureGenerationType = TextureImporterType.Default;

            Texture cookieTextureCube = null;
            Texture cookieTexture2D   = null;

            string iesFilePath  = Path.Combine(Path.GetDirectoryName(Application.dataPath), ctx.assetPath);
            string errorMessage = engine.ReadFile(iesFilePath);

            if (string.IsNullOrEmpty(errorMessage))
            {
                iesMetaData.FileFormatVersion      = engine.FileFormatVersion;
                iesMetaData.IESPhotometricType     = engine.GetPhotometricType();
                iesMetaData.Manufacturer           = engine.GetKeywordValue("MANUFAC");
                iesMetaData.LuminaireCatalogNumber = engine.GetKeywordValue("LUMCAT");
                iesMetaData.LuminaireDescription   = engine.GetKeywordValue("LUMINAIRE");
                iesMetaData.LampCatalogNumber      = engine.GetKeywordValue("LAMPCAT");
                iesMetaData.LampDescription        = engine.GetKeywordValue("LAMP");

                (iesMetaData.IESMaximumIntensity, iesMetaData.IESMaximumIntensityUnit) = engine.GetMaximumIntensity();

                string warningMessage;

                (warningMessage, cookieTextureCube) = engine.GenerateCubeCookie(iesMetaData.CookieCompression, (int)iesMetaData.iesSize);
                if (!string.IsNullOrEmpty(warningMessage))
                {
                    ctx.LogImportWarning($"Cannot properly generate IES Cube texture: {warningMessage}");
                }
                cookieTextureCube.IncrementUpdateCount();

                (warningMessage, cookieTexture2D) = engine.Generate2DCookie(iesMetaData.CookieCompression, iesMetaData.SpotAngle, (int)iesMetaData.iesSize, iesMetaData.ApplyLightAttenuation);
                if (!string.IsNullOrEmpty(warningMessage))
                {
                    ctx.LogImportWarning($"Cannot properly generate IES 2D texture: {warningMessage}");
                }
                cookieTexture2D.IncrementUpdateCount();
            }
            else
            {
                ctx.LogImportError($"Cannot read IES file '{iesFilePath}': {errorMessage}");
            }

            string iesFileName = Path.GetFileNameWithoutExtension(ctx.assetPath);

            var iesObject = ScriptableObject.CreateInstance <IESObject>();

            iesObject.iesMetaData = iesMetaData;
            GameObject lightObject = new GameObject(iesFileName);

            lightObject.transform.localEulerAngles = new Vector3(90f, 0f, iesMetaData.LightAimAxisRotation);

            Light light = lightObject.AddComponent <Light>();

            light.type      = (iesMetaData.PrefabLightType == IESLightType.Point) ? LightType.Point : LightType.Spot;
            light.intensity = 1f;  // would need a better intensity value formula
            light.range     = 10f; // would need a better range value formula
            light.spotAngle = iesMetaData.SpotAngle;

            ctx.AddObjectToAsset("IES", iesObject);
            ctx.SetMainObject(iesObject);

            IESImporter.createRenderPipelinePrefabLight?.Invoke(ctx, iesFileName, iesMetaData.UseIESMaximumIntensity, iesMetaData.IESMaximumIntensityUnit, iesMetaData.IESMaximumIntensity, light, (iesMetaData.PrefabLightType == IESLightType.Point) ? cookieTextureCube : cookieTexture2D);

            if (cookieTextureCube != null)
            {
                cookieTextureCube.name = iesFileName + "-Cube-IES";
                ctx.AddObjectToAsset(cookieTextureCube.name, cookieTextureCube);
            }
            if (cookieTexture2D != null)
            {
                cookieTexture2D.name = iesFileName + "-2D-IES";
                ctx.AddObjectToAsset(cookieTexture2D.name, cookieTexture2D);
            }
        }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            ////REVIEW: need to check with version control here?
            // Read file.
            string text;
            try
            {
                text = File.ReadAllText(ctx.assetPath);
            }
            catch (Exception exception)
            {
                ctx.LogImportError(string.Format("Could read file '{0}' ({1})",
                    ctx.assetPath, exception));
                return;
            }

            // Create asset.
            var asset = ScriptableObject.CreateInstance<InputActionAsset>();

            // Parse JSON.
            try
            {
                ////TODO: make sure action names are unique
                asset.LoadFromJson(text);
            }
            catch (Exception exception)
            {
                ctx.LogImportError(string.Format("Could not parse input actions in JSON format from '{0}' ({1})",
                    ctx.assetPath, exception));
                DestroyImmediate(asset);
                return;
            }

            ctx.AddObjectToAsset("<root>", asset);
            ctx.SetMainObject(asset);

            // Make sure every map and every action has a stable ID assigned to it.
            var maps = asset.actionMaps;
            foreach (var map in maps)
            {
                if (map.idDontGenerate == Guid.Empty)
                {
                    // Generate and remember GUID.
                    var id = map.id;
                    ArrayHelpers.Append(ref m_ActionMapGuids, new RememberedGuid
                    {
                        guid = id.ToString(),
                        name = map.name,
                    });
                }
                else
                {
                    // Retrieve remembered GUIDs.
                    if (m_ActionMapGuids != null)
                    {
                        for (var i = 0; i < m_ActionMapGuids.Length; ++i)
                        {
                            if (string.Compare(m_ActionMapGuids[i].name, map.name,
                                StringComparison.InvariantCultureIgnoreCase) == 0)
                            {
                                map.m_Guid = Guid.Empty;
                                map.m_Id = m_ActionMapGuids[i].guid;
                                break;
                            }
                        }
                    }
                }

                foreach (var action in map.actions)
                {
                    var actionName = string.Format("{0}/{1}", map.name, action.name);
                    if (action.idDontGenerate == Guid.Empty)
                    {
                        // Generate and remember GUID.
                        var id = action.id;
                        ArrayHelpers.Append(ref m_ActionGuids, new RememberedGuid
                        {
                            guid = id.ToString(),
                            name = actionName,
                        });
                    }
                    else
                    {
                        // Retrieve remembered GUIDs.
                        if (m_ActionGuids != null)
                        {
                            for (var i = 0; i < m_ActionGuids.Length; ++i)
                            {
                                if (string.Compare(m_ActionGuids[i].name, actionName,
                                    StringComparison.InvariantCultureIgnoreCase) == 0)
                                {
                                    action.m_Guid = Guid.Empty;
                                    action.m_Id = m_ActionGuids[i].guid;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            // Create subasset for each action.
            foreach (var map in maps)
            {
                var haveSetName = !string.IsNullOrEmpty(map.name);

                foreach (var action in map.actions)
                {
                    var actionReference = ScriptableObject.CreateInstance<InputActionReference>();
                    actionReference.Set(action);

                    var objectName = action.name;
                    if (haveSetName)
                        objectName = string.Format("{0}/{1}", map.name, action.name);

                    actionReference.name = objectName;
                    ctx.AddObjectToAsset(objectName, actionReference);
                }
            }

            // Generate wrapper code, if enabled.
            if (m_GenerateWrapperCode)
            {
                var wrapperFilePath = m_WrapperCodePath;
                if (string.IsNullOrEmpty(wrapperFilePath))
                {
                    var assetPath = ctx.assetPath;
                    var directory = Path.GetDirectoryName(assetPath);
                    var fileName = Path.GetFileNameWithoutExtension(assetPath);
                    wrapperFilePath = Path.Combine(directory, fileName) + ".cs";
                }

                var options = new InputActionCodeGenerator.Options
                {
                    sourceAssetPath = ctx.assetPath,
                    namespaceName = m_WrapperCodeNamespace,
                    className = m_WrapperClassName,
                    generateEvents = m_GenerateActionEvents,
                    generateInterfaces = m_GenerateInterfaces,
                };

                if (InputActionCodeGenerator.GenerateWrapperCode(wrapperFilePath, maps, asset.controlSchemes, options))
                {
                    // Inform database that we modified a source asset *during* import.
                    AssetDatabase.ImportAsset(wrapperFilePath);
                }
            }

            // Refresh editors.
            AssetInspectorWindow.RefreshAllOnAssetReimport();
        }
        /// <summary>
        /// Import a .htre file.
        /// </summary>
        /// <param name="ctx"></param>
        public override void OnImportAsset(AssetImportContext ctx)
        {
            // Get the corresponding TerrainAsset.
            var baseName      = Path.GetFileNameWithoutExtension(ctx.assetPath).Substring(0, 4);
            var terrainAssets = (from tile in UnityFileUtils.GetAllAssetsOfType <TerrainAsset>()
                                 where tile.name.StartsWith(baseName)
                                 select tile).ToArray();

            if (terrainAssets.Length == 0)
            {
                ctx.LogImportError("Corresponding TerrainAsset could not be found for " + ctx.assetPath + ". Did you forget to import its .tre2 file?");
                return;
            }

            var terrainAsset = terrainAssets[0];

            var heightTiles            = new List <float[, ]>(4);
            var materialWeightMapTiles = new List <Color[, ]>(4);
            var materialIdMapTiles     = new List <Color[, ]>(4);
            var materialSelectMapTiles = new List <Color[, ]>(4);

            const int HalfWidth = HEIGHTMAP_WIDTH / 2;

            var asset = ScriptableObject.CreateInstance <TerrainTileAsset>();

            asset.name = Path.GetFileNameWithoutExtension(ctx.assetPath);

            ctx.AddObjectToAsset("Main", asset);
            ctx.SetMainObject(asset);

            using (var reader = new BinaryReader(new FileStream(ctx.assetPath, FileMode.Open)))
            {
                var version = reader.ReadUInt32();

                if (version == 3)
                {
                    reader.BaseStream.Seek(HEIGHTMAP_OFFSET_VERSION3, SeekOrigin.Begin);
                }
                else if (version == 4)
                {
                    reader.BaseStream.Seek(HEIGHTMAP_OFFSET_VERSION4, SeekOrigin.Begin);
                }
                else
                {
                    Debug.LogError("Unrecognized htre version number: " + version);
                }

                // Read heightmap
                for (var tile = 0; tile < 4; tile++)
                {
                    var heightValues = new float[HEIGHTMAP_WIDTH / 2, HEIGHTMAP_HEIGHT / 2];
                    heightTiles.Add(heightValues);

                    for (var i = 0; i < HalfWidth; i++)
                    {
                        for (var j = 0; j < HalfWidth; j++)
                        {
                            var height = reader.ReadSingle();
                            heightValues[j, i] = (height - terrainAsset.HeightRangeMin) / (terrainAsset.HeightRangeMax - terrainAsset.HeightRangeMin);
                        }
                    }
                }

                // Read material weight map
                for (var tile = 0; tile < 4; tile++)
                {
                    var materialWeightValues = new Color[HEIGHTMAP_WIDTH / 2, HEIGHTMAP_HEIGHT / 2];
                    materialWeightMapTiles.Add(materialWeightValues);

                    for (var i = 0; i < HalfWidth; i++)
                    {
                        for (var j = 0; j < HalfWidth; j++)
                        {
                            var r = reader.ReadByte();
                            var g = reader.ReadByte();
                            var b = reader.ReadByte();
                            var a = reader.ReadByte();
                            materialWeightValues[j, i] = new Color(r, g, b, a);
                        }
                    }
                }

                // Skip unknown section
                reader.BaseStream.Position += 64L;

                // Read material ID map
                // This can't be only 2x2, can it?
                for (var tile = 0; tile < 4; tile++)
                {
                    var materialIdValues = new Color[2, 2];
                    materialIdMapTiles.Add(materialIdValues);

                    for (var i = 0; i < 1; i++)
                    {
                        for (var j = 0; j < 1; j++)
                        {
                            var r = reader.ReadByte();
                            var g = reader.ReadByte();
                            var b = reader.ReadByte();
                            var a = reader.ReadByte();
                            materialIdValues[j, i] = new Color(r, g, b, a);
                        }
                    }
                }

                // Skip unknown (heightmap LOD?) section
                reader.BaseStream.Position += 32L;

                // Read material select map
                // This can't be only 2x2, can it?
                for (var tile = 0; tile < 4; tile++)
                {
                    var materialSelectValues = new Color[2, 2];
                    materialSelectMapTiles.Add(materialSelectValues);

                    for (var i = 0; i < 1; i++)
                    {
                        for (var j = 0; j < 1; j++)
                        {
                            var r = reader.ReadByte();
                            var g = reader.ReadByte();
                            var b = reader.ReadByte();
                            var a = reader.ReadByte();
                            materialSelectValues[j, i] = new Color(r, g, b, a);
                        }
                    }
                }
            }

            var name = Path.GetFileNameWithoutExtension(ctx.assetPath);

            // Create material weight map.
            var materialWeightMap =
                new Texture2D(64, 64, TextureFormat.ARGB32, true)
            {
                name = name + "_MaterialWeightMap"
            };

            materialWeightMap.wrapMode = TextureWrapMode.Clamp;

            materialWeightMap.SetPixels(0, 0, HalfWidth, HalfWidth, materialWeightMapTiles[0].Cast <Color>().ToArray());
            materialWeightMap.SetPixels(HalfWidth, 0, HalfWidth, HalfWidth, materialWeightMapTiles[2].Cast <Color>().ToArray());

            materialWeightMap.SetPixels(0, HalfWidth, HalfWidth, HalfWidth, materialWeightMapTiles[1].Cast <Color>().ToArray());
            materialWeightMap.SetPixels(HalfWidth, HalfWidth, HalfWidth, HalfWidth, materialWeightMapTiles[3].Cast <Color>().ToArray());

            ctx.AddObjectToAsset(name + "MaterialWeightMap", materialWeightMap);

            // Create material ID map.
            var materialIndicesMap =
                new Texture2D(2, 2, TextureFormat.ARGB32, true)
            {
                name = name + "_MaterialIndicesMap"
            };

            materialIndicesMap.wrapMode = TextureWrapMode.Clamp;

            materialIndicesMap.SetPixels(0, 0, 1, 1, materialIdMapTiles[0].Cast <Color>().ToArray());
            materialIndicesMap.SetPixels(1, 0, 1, 1, materialIdMapTiles[2].Cast <Color>().ToArray());

            materialIndicesMap.SetPixels(0, 1, 1, 1, materialIdMapTiles[1].Cast <Color>().ToArray());
            materialIndicesMap.SetPixels(1, 1, 1, 1, materialIdMapTiles[3].Cast <Color>().ToArray());

            ctx.AddObjectToAsset(name + "MaterialIndicesMap", materialIndicesMap);

            // Create material select map.
            var materialSelectMap =
                new Texture2D(2, 2, TextureFormat.ARGB32, true)
            {
                name = name + "_MaterialSelectMap"
            };

            materialSelectMap.wrapMode = TextureWrapMode.Clamp;

            materialSelectMap.SetPixels(0, 0, 1, 1, materialSelectMapTiles[0].Cast <Color>().ToArray());
            materialSelectMap.SetPixels(1, 0, 1, 1, materialSelectMapTiles[2].Cast <Color>().ToArray());

            materialSelectMap.SetPixels(0, 1, 1, 1, materialSelectMapTiles[1].Cast <Color>().ToArray());
            materialSelectMap.SetPixels(1, 1, 1, 1, materialSelectMapTiles[3].Cast <Color>().ToArray());

            ctx.AddObjectToAsset(name + "MaterialSelectMap", materialSelectMap);

            // Create heightmap.
            var heightMap = new Texture2D(HEIGHTMAP_WIDTH, HEIGHTMAP_HEIGHT, TextureFormat.RGBAFloat, true, true);

            heightMap.name       = name + "_Heightmap";
            heightMap.wrapMode   = TextureWrapMode.Clamp;
            heightMap.filterMode = FilterMode.Bilinear;

            var colors = from height in heightTiles[0].Cast <float>()
                         select new Color(height, height, height);

            heightMap.SetPixels(0, 0, HalfWidth, HalfWidth, colors.ToArray());

            colors = from height in heightTiles[2].Cast <float>()
                     select new Color(height, height, height);
            heightMap.SetPixels(HalfWidth, 0, HalfWidth, HalfWidth, colors.ToArray());

            colors = from height in heightTiles[1].Cast <float>()
                     select new Color(height, height, height);
            heightMap.SetPixels(0, HalfWidth, HalfWidth, HalfWidth, colors.ToArray());

            colors = from height in heightTiles[3].Cast <float>()
                     select new Color(height, height, height);
            heightMap.SetPixels(HalfWidth, HalfWidth, HalfWidth, HalfWidth, colors.ToArray());

            ctx.AddObjectToAsset(name + "HeightMap", heightMap);

            asset.Heightmap          = heightMap;
            asset.MaterialSelectMap  = materialSelectMap;
            asset.MaterialIndicesMap = materialIndicesMap;
            asset.MaterialWeightMap  = materialWeightMap;
        }
Beispiel #17
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var width         = 8;
            var height        = 8;
            var mipmapEnabled = true;
            var textureFormat = TextureFormat.ARGB32;
            //var srgbTexture = true;

            // Check if the input textures are valid to be used to build the texture array.
            var isValid = Verify(ctx, false);

            if (isValid)
            {
                // Use the texture assigned to the first slice as "master".
                // This means all other textures have to use same settings as the master texture.
                var sourceTexture = m_Textures[0];
                width         = sourceTexture.width;
                height        = sourceTexture.height;
                textureFormat = sourceTexture.format;

                var sourceTexturePath = AssetDatabase.GetAssetPath(sourceTexture);
                var textureImporter   = (TextureImporter)AssetImporter.GetAtPath(sourceTexturePath);
                mipmapEnabled = textureImporter.mipmapEnabled;
                //srgbTexture = textureImporter.sRGBTexture;
            }

            // Create the texture array.
            // When the texture array asset is being created, there are no input textures added yet,
            // thus we do Max(1, Count) to make sure to add at least 1 slice.
            var texture3D = new Texture3D(width, height, Mathf.Max(1, m_Textures.Count), textureFormat, mipmapEnabled);//, !srgbTexture);

            texture3D.wrapMode   = m_WrapMode;
            texture3D.filterMode = m_FilterMode;
            texture3D.anisoLevel = m_AnisoLevel;

            if (isValid)
            {
                // If everything is valid, copy source textures over to the texture array.
                for (var n = 0; n < m_Textures.Count; ++n)
                {
                    var source = m_Textures[n];
                    Graphics.CopyTexture(source, 0, texture3D, n);
                }
            }
            else
            {
                // If there is any error, copy a magenta colored texture into every slice.
                // I was thinking to only make the invalid slice magenta, but then it's way less obvious that
                // something isn't right with the texture array. Thus I mark the entire texture array as broken.

                var errorPixels = new Color32[width * height];
                for (var n = 0; n < errorPixels.Length; ++n)
                {
                    errorPixels[n] = Color.magenta;
                }

                var texture3DPixels = new Color32[width * height * texture3D.depth];

                for (var n = 0; n < texture3D.depth; ++n)
                {
                    System.Array.Copy(errorPixels, 0, texture3DPixels, width * height * n, errorPixels.Length);
                }

                texture3D.SetPixels32(texture3DPixels);
                texture3D.Apply();
            }

            // Mark all input textures as dependency to the texture array.
            // This causes the texture array to get re-generated when any input texture changes or when the build target changed.
            for (var n = 0; n < m_Textures.Count; ++n)
            {
                var source = m_Textures[n];
                if (source != null)
                {
                    var path = AssetDatabase.GetAssetPath(source);
#if UNITY_2020_1_OR_NEWER
                    ctx.DependsOnArtifact(path);
#else
                    ctx.DependsOnSourceAsset(path);
#endif
                }
            }

#if !UNITY_2020_1_OR_NEWER
            // This value is not really used in this importer,
            // but getting the build target here will add a dependency to the current active buildtarget.
            // Because DependsOnArtifact does not exist in 2019.4, adding this dependency on top of the DependsOnSourceAsset
            // will force a re-import when the target platform changes in case it would have impacted any texture this importer depends on.
            var buildTarget = ctx.selectedBuildTarget;
#endif

            // this should have been named "MainAsset" to be conform with Unity, but changing it now
            // would break all existing Texture3DAtlas assets, so we don't touch it.
            ctx.AddObjectToAsset("Texture3D", texture3D);
            ctx.SetMainObject(texture3D);

            if (!isValid)
            {
                // Run the verify step again, but this time we have the main object asset.
                // Console logs should ping the asset, but they don't in 2019.3 beta, bug?
                Verify(ctx, true);
            }
        }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var graphAsset   = ScriptableObject.CreateInstance <SubGraphAsset>();
            var subGraphPath = ctx.assetPath;
            var subGraphGuid = AssetDatabase.AssetPathToGUID(subGraphPath);

            graphAsset.assetGuid = subGraphGuid;
            var textGraph      = File.ReadAllText(subGraphPath, Encoding.UTF8);
            var messageManager = new MessageManager();
            var graphData      = new GraphData
            {
                isSubGraph = true, assetGuid = subGraphGuid, messageManager = messageManager
            };

            MultiJson.Deserialize(graphData, textGraph);

            try
            {
                ProcessSubGraph(graphAsset, graphData);
            }
            catch (Exception e)
            {
                graphAsset.isValid = false;
                Debug.LogException(e, graphAsset);
            }
            finally
            {
                if (messageManager.AnyError())
                {
                    graphAsset.isValid = false;
                    foreach (var pair in messageManager.GetNodeMessages())
                    {
                        var node = graphData.GetNodeFromId(pair.Key);
                        foreach (var message in pair.Value)
                        {
                            MessageManager.Log(node, subGraphPath, message, graphAsset);
                        }
                    }
                }
                messageManager.ClearAll();
            }

            Texture2D texture = Resources.Load <Texture2D>("Icons/sg_subgraph_icon");

            ctx.AddObjectToAsset("MainAsset", graphAsset, texture);
            ctx.SetMainObject(graphAsset);

            var metadata = ScriptableObject.CreateInstance <ShaderSubGraphMetadata>();

            metadata.hideFlags         = HideFlags.HideInHierarchy;
            metadata.assetDependencies = new List <UnityEngine.Object>();

            AssetCollection assetCollection = new AssetCollection();

            MinimalGraphData.GatherMinimalDependenciesFromFile(assetPath, assetCollection);

            foreach (var asset in assetCollection.assets)
            {
                if (asset.Value.HasFlag(AssetCollection.Flags.IncludeInExportPackage))
                {
                    // this sucks that we have to fully load these assets just to set the reference,
                    // which then gets serialized as the GUID that we already have here.  :P

                    var dependencyPath = AssetDatabase.GUIDToAssetPath(asset.Key);
                    if (!string.IsNullOrEmpty(dependencyPath))
                    {
                        metadata.assetDependencies.Add(
                            AssetDatabase.LoadAssetAtPath(dependencyPath, typeof(UnityEngine.Object)));
                    }
                }
            }
            ctx.AddObjectToAsset("Metadata", metadata);

            // declare dependencies
            foreach (var asset in assetCollection.assets)
            {
                if (asset.Value.HasFlag(AssetCollection.Flags.SourceDependency))
                {
                    ctx.DependsOnSourceAsset(asset.Key);

                    // I'm not sure if this warning below is actually used or not, keeping it to be safe
                    var assetPath = AssetDatabase.GUIDToAssetPath(asset.Key);

                    // Ensure that dependency path is relative to project
                    if (!string.IsNullOrEmpty(assetPath) && !assetPath.StartsWith("Packages/") && !assetPath.StartsWith("Assets/"))
                    {
                        Debug.LogWarning($"Invalid dependency path: {assetPath}", graphAsset);
                    }
                }

                // NOTE: dependencies declared by GatherDependenciesFromSourceFile are automatically registered as artifact dependencies
                // HOWEVER: that path ONLY grabs dependencies via MinimalGraphData, and will fail to register dependencies
                // on GUIDs that don't exist in the project.  For both of those reasons, we re-declare the dependencies here.
                if (asset.Value.HasFlag(AssetCollection.Flags.ArtifactDependency))
                {
                    ctx.DependsOnArtifact(asset.Key);
                }
            }
        }
        public override void OnImportAsset(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);
            }
        }
        /// <summary>
        /// Import a .lpsh file.
        /// </summary>
        /// <param name="ctx"></param>
        public override void OnImportAsset(AssetImportContext ctx)
        {
            // Note: Doesn't seem to always load coefficients? Look at avr_stage.lpsh.
            var asset = ScriptableObject.CreateInstance <LightProbeSHCoefficientsAsset>();

            asset.name = Path.GetFileNameWithoutExtension(ctx.assetPath);

            using (var reader = new BinaryReader(new FileStream(ctx.assetPath, FileMode.Open), Encoding.ASCII))
            {
                var version = reader.ReadUInt32();
                Assert.IsTrue(version == 4, "Unsupported lpsh file format.");

                var unknown1 = reader.ReadUInt32();
                var fileSize = reader.ReadUInt32();

                reader.BaseStream.Seek(124L, SeekOrigin.Begin);

                var numLightProbes = reader.ReadUInt32();

                reader.BaseStream.Seek(140L, SeekOrigin.Begin);

                var numDivs = reader.ReadUInt32();

                reader.BaseStream.Seek(208L, SeekOrigin.Begin);
                for (var i = 0; i < numDivs; i++)
                {
                    asset.TimeValues.Add(reader.ReadUInt32());
                }

                AlignRead(reader.BaseStream, 16);

                var lpMetadata = new List <LightProbeMetadata>();
                for (var i = 0; i < numLightProbes; i++)
                {
                    lpMetadata.Add(new LightProbeMetadata(reader.ReadUInt32(), reader.ReadUInt32(), reader.ReadUInt32()));
                }

                var shSets = new List <LightProbeSHCoefficientsAsset.LightProbe.ShCoefficientsSet>();
                for (var i = 0; i < lpMetadata.Count; i++)
                {
                    var metadata = lpMetadata[i];
                    reader.BaseStream.Seek(metadata.NameAddress, SeekOrigin.Begin);

                    var nameBuilder = new StringBuilder();
                    var nextChar    = reader.ReadChar();
                    while (nextChar != '\0')
                    {
                        nameBuilder.Append(nextChar);
                        nextChar = reader.ReadChar();
                    }

                    var lightProbe = new LightProbeSHCoefficientsAsset.LightProbe
                    {
                        Name = nameBuilder.ToString()
                    };

                    var shSet = new LightProbeSHCoefficientsAsset.LightProbe.ShCoefficientsSet();
                    lightProbe.CoefficientsSets.Add(shSet);

                    asset.LightProbes.Add(lightProbe);
                    shSets.Add(shSet);
                }

                for (var i = 0; i < shSets.Count; i++)
                {
                    var metadata = lpMetadata[i];
                    reader.BaseStream.Seek(metadata.ShDataAddress, SeekOrigin.Begin);

                    var shSet = shSets[i];

                    var isLastProbe = i == shSets.Count - 1;
                    while (isLastProbe || reader.BaseStream.Position < lpMetadata[i + 1].ShDataAddress)
                    {
                        for (var coefficientIndex = 0; coefficientIndex < 9; coefficientIndex++)
                        {
                            Func <float> readHalf     = () => Half.ToHalf(reader.ReadUInt16());
                            var          r            = readHalf();
                            var          g            = readHalf();
                            var          b            = readHalf();
                            var          skyOcclusion = readHalf();

                            SetMatrixValue(ref shSet.TermR, 15 - coefficientIndex, r);
                            SetMatrixValue(ref shSet.TermG, 15 - coefficientIndex, g);
                            SetMatrixValue(ref shSet.TermB, 15 - coefficientIndex, b);
                            SetMatrixValue(ref shSet.SkyOcclusion, 15 - coefficientIndex, skyOcclusion);
                        }

                        if (reader.BaseStream.Position + 32L > fileSize)
                        {
                            break;
                        }
                    }
                }
            }

            ctx.AddObjectToAsset(asset.name, asset);
            ctx.SetMainObject(asset);
        }
    public override void OnImportAsset(AssetImportContext ctx)
    {
        var texture = Resources.Load <Texture2D>("zepeto-studio-icon");

        ctx.AddObjectToAsset("Texture", texture, texture);
    }
Beispiel #22
0
    public override void OnImportAsset(AssetImportContext ctx)
    {
        IndexedTextureData texture = ParseLBM.ImportFile(ctx.assetPath);
        {
            texture.pixelsPerUnit     = pixelsPerUnit;
            texture.indexedImage.name = "Indexed image";
            ctx.AddObjectToAsset("Indexed image", texture.indexedImage);
            texture.pallete.name = "Pallete";
            ctx.AddObjectToAsset("Palette", texture.pallete);

            if (ignoreFirstAnimation)
            {
                texture.animations.RemoveAt(0);
            }

            texture.name = "texture data";
            ctx.AddObjectToAsset("texture data", texture);
            texture.image.name = "Color image";
            ctx.AddObjectToAsset("image", texture.image);
        }


        Sprite sprite = Sprite.Create(texture.image, new Rect(0, 0, texture.width, texture.height), new Vector2(1f / 2, 1f / 2), pixelsPerUnit);

        {
            sprite.name = "Sprite";
            ctx.AddObjectToAsset("Sprite", sprite);
        }

        // Atlas - image for segmentation
        if (generatePNG)
        {
            // adds a secondary image for segmentation
            string filename  = Path.GetFileNameWithoutExtension(ctx.assetPath);
            string imagepath = Path.GetDirectoryName(ctx.assetPath) + "\\" + filename + "-atlas.png";

            File.WriteAllBytes(imagepath, texture.image.EncodeToPNG());

            // Create image metadata
            // TODO FIX: this is not called the first time, as the image might still be under creation
            TextureImporter ti = (TextureImporter)TextureImporter.GetAtPath(imagepath);
            if (ti)
            {
                ti.textureType         = TextureImporterType.Sprite;
                ti.spritePixelsPerUnit = pixelsPerUnit;
                ti.spriteImportMode    = SpriteImportMode.Multiple;
                ti.filterMode          = FilterMode.Point;
                var spriteData = new SpriteMetaData[1];
                spriteData[0]       = new SpriteMetaData();
                spriteData[0].pivot = new Vector2(1f / 2, 1f / 2);
                spriteData[0].rect  = new Rect(0, 0, texture.width, texture.height);
                spriteData[0].name  = "sprite";
                ti.spritesheet      = spriteData;

                AssetDatabase.ImportAsset(imagepath, ImportAssetOptions.ForceUpdate);
            }
        }

        var prefab = new GameObject();
        {
            var material = new Material(Shader.Find("Sprites/IndexedPallete"));
            {
                material.name = "Material";
                material.SetTexture("_Indexed", texture.indexedImage);
                material.SetTexture("_Pallete", texture.pallete);

                ctx.AddObjectToAsset("material", material);
            }
            SpriteRenderer renderer = prefab.AddComponent <SpriteRenderer>();
            {
                renderer.sprite   = sprite;
                renderer.material = material;
            }
            IndexedTextureAnimator itr = prefab.AddComponent <IndexedTextureAnimator>();
            {
                itr.texture = texture;
            }
            ctx.AddObjectToAsset("prefab", prefab, texture.image);
            ctx.SetMainObject(prefab);
        }

        // Assets that are not passed into the context as import outputs must be destroyed
        //DestroyImmediate(<unused>);
    }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var oldShader = AssetDatabase.LoadAssetAtPath <Shader>(ctx.assetPath);

            if (oldShader != null)
            {
                ShaderUtil.ClearShaderMessages(oldShader);
            }

            List <PropertyCollector.TextureInfo> configuredTextures;
            string path = ctx.assetPath;
            var    sourceAssetDependencyPaths = new List <string>();

            UnityEngine.Object mainObject;

            var textGraph = File.ReadAllText(path, Encoding.UTF8);
            var graph     = new GraphData
            {
                messageManager = new MessageManager(), assetGuid = AssetDatabase.AssetPathToGUID(path)
            };

            MultiJson.Deserialize(graph, textGraph);
            graph.OnEnable();
            graph.ValidateGraph();

            // TODO: How to handle this?
            if (graph.isVFXTarget)
            {
                var vfxAsset = GenerateVfxShaderGraphAsset(graph);
                mainObject = vfxAsset;
            }
            else
            {
                var text   = GetShaderText(path, out configuredTextures, sourceAssetDependencyPaths, graph);
                var shader = ShaderUtil.CreateShaderAsset(text, false);


                if (graph != null && graph.messageManager.nodeMessagesChanged)
                {
                    foreach (var pair in graph.messageManager.GetNodeMessages())
                    {
                        var node = graph.GetNodeFromId(pair.Key);
                        MessageManager.Log(node, path, pair.Value.First(), shader);
                    }
                }

                EditorMaterialUtility.SetShaderDefaults(
                    shader,
                    configuredTextures.Where(x => x.modifiable).Select(x => x.name).ToArray(),
                    configuredTextures.Where(x => x.modifiable).Select(x => EditorUtility.InstanceIDToObject(x.textureId) as Texture).ToArray());
                EditorMaterialUtility.SetShaderNonModifiableDefaults(
                    shader,
                    configuredTextures.Where(x => !x.modifiable).Select(x => x.name).ToArray(),
                    configuredTextures.Where(x => !x.modifiable).Select(x => EditorUtility.InstanceIDToObject(x.textureId) as Texture).ToArray());

                mainObject = shader;
            }
            Texture2D texture = Resources.Load <Texture2D>("Icons/sg_graph_icon@64");

            ctx.AddObjectToAsset("MainAsset", mainObject, texture);
            ctx.SetMainObject(mainObject);

            if (graph != null)
            {
                foreach (var target in graph.activeTargets)
                {
                    if (target is IHasMetadata iHasMetadata)
                    {
                        var metadata = iHasMetadata.GetMetadataObject();
                        if (metadata == null)
                        {
                            continue;
                        }

                        metadata.hideFlags = HideFlags.HideInHierarchy;
                        ctx.AddObjectToAsset($"{iHasMetadata.identifier}:Metadata", metadata);
                    }
                }
            }

            var sgMetadata = ScriptableObject.CreateInstance <ShaderGraphMetadata>();

            sgMetadata.hideFlags         = HideFlags.HideInHierarchy;
            sgMetadata.assetDependencies = new List <UnityEngine.Object>();
            var deps = GatherDependenciesFromSourceFile(ctx.assetPath);

            foreach (string dependency in deps)
            {
                sgMetadata.assetDependencies.Add(AssetDatabase.LoadAssetAtPath(dependency, typeof(UnityEngine.Object)));
            }
            ctx.AddObjectToAsset("SGInternal:Metadata", sgMetadata);


            foreach (var sourceAssetDependencyPath in sourceAssetDependencyPaths.Distinct())
            {
                // Ensure that dependency path is relative to project
                if (!sourceAssetDependencyPath.StartsWith("Packages/") && !sourceAssetDependencyPath.StartsWith("Assets/"))
                {
                    Debug.LogWarning($"Invalid dependency path: {sourceAssetDependencyPath}", mainObject);
                    continue;
                }

                ctx.DependsOnSourceAsset(sourceAssetDependencyPath);
            }
        }
Beispiel #24
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var assetName = Path.GetFileNameWithoutExtension(ctx.assetPath);

            var mainAsset = new GameObject();

            ctx.AddObjectToAsset("main obj", mainAsset);
            ctx.SetMainObject(mainAsset);
            var matProps = mainAsset.AddComponent <MaterialProperties>();

            // Parse object
            var v  = new List <float[]>();
            var vn = new List <float[]>();
            var f  = new List <int[]>();
            var e  = new List <int[]>();

            using (StreamReader sr = File.OpenText(ctx.assetPath)) {
                string s;
                while ((s = sr.ReadLine()) != null)
                {
                    var line = s.Trim().Split(' ');
                    if (line[0].Equals("o"))
                    {
                        assetName = s.Remove(0, 2);
                    }
                    else if (line[0].Equals("prop"))
                    {
                        if (line[1].Equals("color"))
                        {
                            var values = Array.ConvertAll(line.Skip(3).ToArray(), float.Parse);
                            if (line[2].Equals("diffuse"))
                            {
                                matProps.SolidColor = new Color(values[0], values[1], values[2]);
                            }
                        }
                        else if (line[1].Equals("opacity"))
                        {
                            matProps.Opacity = float.Parse(line[2]);
                        }
                    }
                    else if (line[0].Equals("v"))
                    {
                        v.Add(Array.ConvertAll(s.Split(' ').Skip(1).ToArray(), float.Parse));
                    }
                    else if (line[0].Equals("vn"))
                    {
                        vn.Add(Array.ConvertAll(s.Split(' ').Skip(1).ToArray(), float.Parse));
                    }
                    else if (line[0].Equals("f"))
                    {
                        line = s.Split(' ');
                        if (line.Length > 4)
                        {
                            Debug.LogError("Your model must be exported with triangulated faces.");
                            continue;
                        }
                        f.Add(Array.ConvertAll(s.Split(' ').Skip(1).ToArray(), int.Parse));
                    }
                    else if (line[0].Equals("l"))
                    {
                        // Convert 1-based obj indices to 0-based
                        // TODO: switch to 0-based? Would break general obj. compatibility
                        e.Add(Array.ConvertAll(line.Skip(1).ToArray(), int.Parse).Select(i => i - 1).ToArray());
                    }
                }
            }

            // Construct mesh
            Mesh mesh;
            var  triangleSubmeshExists = false;

            if (f.Count > 0 && e.Count > 0)
            {
                mesh = new Mesh {
                    subMeshCount = 2
                };
                triangleSubmeshExists = true;
            }
            else if (f.Count > 0)
            {
                mesh = new Mesh {
                    subMeshCount = 1
                };
                triangleSubmeshExists = true;
            }
            else if (e.Count > 0)
            {
                mesh = new Mesh {
                    subMeshCount = 1
                };
            }
            else
            {
                return;
            }

            var vertices = new Vector3[v.Count];

            for (var i = 0; i < v.Count; i++)
            {
                vertices[i] = new Vector3(v[i][0], v[i][1], v[i][2]);
            }
            mesh.vertices = vertices;

            // TODO: subMesh 0 is like a regular mesh which uses MeshTopology.Triangles
            //if (f.Count > 0) {
            //    int[] triangleIndices = new int[f.Count * 3];
            //    for (int i = 0; i < f.Count; i++) {
            //        string[] raw = f[i];
            //        string s1 = raw[0];
            //        string s2 = raw[1];
            //        string s3 = raw[2];
            //        if (s1.Contains("//")) {
            //            s1 = s1.Remove(s1.IndexOf("//"));
            //        }
            //        if (s2.Contains("//")) {
            //            s2 = s2.Remove(s2.IndexOf("//"));
            //        }
            //        if (s3.Contains("//")) {
            //            s3 = s3.Remove(s3.IndexOf("//"));
            //        }
            //        int v1 = int.Parse(s1) - 1;
            //        int v2 = int.Parse(s2) - 1;
            //        int v3 = int.Parse(s3) - 1;
            //        triangleIndices[i * 3] = v1;
            //        triangleIndices[i * 3 + 1] = v2;
            //        triangleIndices[i * 3 + 2] = v3;
            //    }
            //    mesh.SetIndices(triangleIndices, MeshTopology.Triangles, 0, false);
            //    mesh.RecalculateNormals();
            //}


            // subMesh 1 is the line mesh which uses MeshTopology.Lines
            if (e.Count > 0)
            {
                var indicesList = new List <int>();
                foreach (var indices in e)
                {
                    for (var i = 0; i < indices.Length - 1; i++)
                    {
                        indicesList.Add(indices[i]);
                        indicesList.Add(indices[i + 1]);
                    }
                }

                mesh.SetIndices(indicesList.ToArray(), MeshTopology.Lines, triangleSubmeshExists ? 1 : 0, false);
            }

            mesh.RecalculateBounds();
            mesh.name = assetName;
            var meshFilter = mainAsset.AddComponent <MeshFilter>();

            meshFilter.sharedMesh = mesh;
            ctx.AddObjectToAsset("Mesh", mesh);

            mainAsset.AddComponent <MeshRenderer>();
            matProps.ColorBy  = MaterialProperties.ColorMode.SolidColor;
            matProps.Lighting = MaterialProperties.LightingMode.Unlit;
        }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var oldShader = AssetDatabase.LoadAssetAtPath <Shader>(ctx.assetPath);

            if (oldShader != null)
            {
                ShaderUtil.ClearShaderMessages(oldShader);
            }

            List <PropertyCollector.TextureInfo> configuredTextures;
            string path = ctx.assetPath;
            var    sourceAssetDependencyPaths = new List <string>();

            UnityEngine.Object mainObject;

            var       textGraph = File.ReadAllText(path, Encoding.UTF8);
            GraphData graph     = JsonUtility.FromJson <GraphData>(textGraph);

            graph.messageManager = new MessageManager();
            graph.assetGuid      = AssetDatabase.AssetPathToGUID(path);
            graph.OnEnable();
            graph.ValidateGraph();

            if (graph.outputNode is VfxMasterNode vfxMasterNode)
            {
                var vfxAsset = GenerateVfxShaderGraphAsset(vfxMasterNode);

                mainObject = vfxAsset;
            }
            else
            {
                var text   = GetShaderText(path, out configuredTextures, sourceAssetDependencyPaths, graph);
                var shader = ShaderUtil.CreateShaderAsset(text, false);

                if (graph != null && graph.messageManager.nodeMessagesChanged)
                {
                    foreach (var pair in graph.messageManager.GetNodeMessages())
                    {
                        var node = graph.GetNodeFromTempId(pair.Key);
                        MessageManager.Log(node, path, pair.Value.First(), shader);
                    }
                }

                EditorMaterialUtility.SetShaderDefaults(
                    shader,
                    configuredTextures.Where(x => x.modifiable).Select(x => x.name).ToArray(),
                    configuredTextures.Where(x => x.modifiable).Select(x => EditorUtility.InstanceIDToObject(x.textureId) as Texture).ToArray());
                EditorMaterialUtility.SetShaderNonModifiableDefaults(
                    shader,
                    configuredTextures.Where(x => !x.modifiable).Select(x => x.name).ToArray(),
                    configuredTextures.Where(x => !x.modifiable).Select(x => EditorUtility.InstanceIDToObject(x.textureId) as Texture).ToArray());

                mainObject = shader;
            }
            Texture2D texture = Resources.Load <Texture2D>("Icons/sg_graph_icon@64");

            ctx.AddObjectToAsset("MainAsset", mainObject, texture);
            ctx.SetMainObject(mainObject);

            var metadata = ScriptableObject.CreateInstance <ShaderGraphMetadata>();

            metadata.hideFlags = HideFlags.HideInHierarchy;
            if (graph != null)
            {
                metadata.outputNodeTypeName = graph.outputNode.GetType().FullName;
            }
            ctx.AddObjectToAsset("Metadata", metadata);

            foreach (var sourceAssetDependencyPath in sourceAssetDependencyPaths.Distinct())
            {
                // Ensure that dependency path is relative to project
                if (!sourceAssetDependencyPath.StartsWith("Packages/") && !sourceAssetDependencyPath.StartsWith("Assets/"))
                {
                    Debug.LogWarning($"Invalid dependency path: {sourceAssetDependencyPath}", mainObject);
                    continue;
                }

                ctx.DependsOnSourceAsset(sourceAssetDependencyPath);
            }
        }
 public void AddObjectToAsset(string identifier, UnityEngine.Object obj)
 {
     m_Context.AddObjectToAsset(identifier, obj);
 }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var shortAssetPath = ctx.assetPath.Replace("Assets", "");

            AlembicStream.DisconnectStreamsWithPath(shortAssetPath);
            var sourcePath    = Application.dataPath + shortAssetPath;
            var destPath      = Application.streamingAssetsPath + shortAssetPath;
            var directoryPath = Path.GetDirectoryName(destPath);

            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
            if (File.Exists(destPath))
            {
                File.SetAttributes(destPath, FileAttributes.Normal);
            }
            File.Copy(sourcePath, destPath, true);

            var fileName = Path.GetFileNameWithoutExtension(destPath);
            var go       = new GameObject(fileName);

            go.transform.localScale *= scaleFactor;

            AlembicStreamDescriptor streamDescriptor = ScriptableObject.CreateInstance <AlembicStreamDescriptor>();

            streamDescriptor.name      = go.name + "_ABCDesc";
            streamDescriptor.pathToAbc = destPath;
            streamDescriptor.settings  = streamSettings;

            using (var abcStream = new AlembicStream(go, streamDescriptor))
            {
                abcStream.AbcLoad();
                AbcStartTime  = abcStream.AbcStartTime;
                AbcEndTime    = abcStream.AbcEndTime;
                AbcFrameCount = abcStream.AbcFrameCount;

                startFrame = startFrame < 0 ? 0 : startFrame;
                endFrame   = endFrame > AbcFrameCount - 1 ? AbcFrameCount - 1 : endFrame;

                streamDescriptor.minFrame      = startFrame;
                streamDescriptor.maxFrame      = endFrame;
                streamDescriptor.abcFrameCount = AbcFrameCount;
                streamDescriptor.abcDuration   = AbcEndTime - AbcStartTime;
                streamDescriptor.abcStartTime  = AbcStartTime;

                var streamPlayer = go.AddComponent <AlembicStreamPlayer>();
                streamPlayer.streamDescriptor = streamDescriptor;
                streamPlayer.startFrame       = startFrame;
                streamPlayer.endFrame         = endFrame;

                AddObjectToAsset(ctx, streamDescriptor.name, streamDescriptor);
                GenerateSubAssets(ctx, abcStream.alembicTreeRoot, streamDescriptor);

                AlembicStream.ReconnectStreamsWithPath(shortAssetPath);

#if UNITY_2017_3_OR_NEWER
                ctx.AddObjectToAsset(go.name, go);
                ctx.SetMainObject(go);
#else
                ctx.SetMainAsset(go.name, go);
#endif
            }
        }
Beispiel #28
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            string[] text = ReadFile(ctx.assetPath);

            this.Populate(text);

            var root = new GameObject();

            root.name = Path.GetFileNameWithoutExtension(ctx.assetPath);
            GameObject[] nodes = this.GenerateNodes();
            this.GenerateMarkers(nodes);

            nodes[0].transform.parent = root.transform;

            Material[] materials = this.materials.Select(
                m => {
                var material  = new Material(Shader.Find("Diffuse"));
                material.name = m.name;
                return(material);
            }
                ).ToArray();

            Mesh[] meshes = this.GenerateMeshesh();

            GameObject[] models = meshes.Select(
                mesh => {
                var model = new GameObject(mesh.name);

                MeshFilter meshFilter = model.AddComponent <MeshFilter>();
                SkinnedMeshRenderer skinnedMeshRenderer = model.AddComponent <SkinnedMeshRenderer>();

                meshFilter.sharedMesh          = mesh;
                skinnedMeshRenderer.sharedMesh = mesh;

                skinnedMeshRenderer.quality = SkinQuality.Bone2;

                mesh.bindposes = nodes.Select(
                    node => node.transform.worldToLocalMatrix * model.transform.localToWorldMatrix
                    ).ToArray();

                skinnedMeshRenderer.bones    = nodes.Select(e => e.transform).ToArray();
                skinnedMeshRenderer.rootBone = nodes[0].transform;

                skinnedMeshRenderer.sharedMaterials = materials;

                model.transform.parent = root.transform;

                return(model);
            }
                ).ToArray();

            foreach (Material mat in materials)
            {
                ctx.AddObjectToAsset(mat.name, mat);
            }

            foreach (Mesh mesh in meshes)
            {
                ctx.AddObjectToAsset(mesh.name, mesh);
            }


            // avatar
            Avatar avatar = AvatarBuilder.BuildGenericAvatar(root, nodes[0].transform.name);

            avatar.name = root.name + "Avatar";

            avatar.hideFlags = HideFlags.None;

            Animator animator = root.AddComponent <Animator>();

            animator.avatar = avatar;

            AvatarMask mask = new AvatarMask();

            mask.name = root.name + "AvatarMask";
            foreach (var node in nodes)
            {
                mask.AddTransformPath(node.transform);
            }

            ctx.AddObjectToAsset(avatar.name, avatar);
            ctx.AddObjectToAsset(mask.name, mask);
            ctx.AddObjectToAsset("root", root);

            ctx.SetMainObject(root);
        }
Beispiel #29
0
        private void GenerateAnimations(AssetImportContext ctx, AseFile aseFile, Sprite[] sprites)
        {
            if (animationSettings == null)
            {
                animationSettings = new AseFileAnimationSettings[0];
            }

            var animSettings = new List <AseFileAnimationSettings>(animationSettings);
            var animations   = aseFile.GetAnimations();

            if (animations.Length <= 0)
            {
                return;
            }

            if (animationSettings != null)
            {
                RemoveUnusedAnimationSettings(animSettings, animations);
            }

            int index = 0;

            foreach (var animation in animations)
            {
                AnimationClip animationClip = new AnimationClip();
                animationClip.name      = animation.TagName;
                animationClip.frameRate = 25;

                AseFileAnimationSettings importSettings = GetAnimationSettingFor(animSettings, animation);
                importSettings.about = GetAnimationAbout(animation);


                EditorCurveBinding spriteBinding = new EditorCurveBinding();
                spriteBinding.type         = typeof(SpriteRenderer);
                spriteBinding.path         = "";
                spriteBinding.propertyName = "m_Sprite";


                int length = animation.FrameTo - animation.FrameFrom + 1;
                ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[length];

                float time = 0;

                int from = (animation.Animation != LoopAnimation.Reverse) ? animation.FrameFrom : animation.FrameTo;
                int step = (animation.Animation != LoopAnimation.Reverse) ? 1 : -1;

                int keyIndex = from;

                for (int i = 0; i < length; i++)
                {
                    if (i >= length)
                    {
                        keyIndex = from;
                    }


                    ObjectReferenceKeyframe frame = new ObjectReferenceKeyframe();
                    frame.time  = time;
                    frame.value = sprites[keyIndex];

                    time += aseFile.Frames[keyIndex].FrameDuration / 1000f;

                    keyIndex          += step;
                    spriteKeyFrames[i] = frame;
                }

                AnimationUtility.SetObjectReferenceCurve(animationClip, spriteBinding, spriteKeyFrames);
                AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(animationClip);

                switch (animation.Animation)
                {
                case LoopAnimation.Forward:
                    animationClip.wrapMode = WrapMode.Loop;
                    settings.loopTime      = true;
                    break;

                case LoopAnimation.Reverse:
                    animationClip.wrapMode = WrapMode.Loop;
                    settings.loopTime      = true;
                    break;

                case LoopAnimation.PingPong:
                    animationClip.wrapMode = WrapMode.PingPong;
                    settings.loopTime      = true;
                    break;
                }

                if (!importSettings.loopTime)
                {
                    animationClip.wrapMode = WrapMode.Once;
                    settings.loopTime      = false;
                }

                AnimationUtility.SetAnimationClipSettings(animationClip, settings);
                ctx.AddObjectToAsset(animation.TagName, animationClip);

                index++;
            }

            animationSettings = animSettings.ToArray();
        }
Beispiel #30
0
        Shader BuildAllShaders(
            AssetImportContext importContext,
            AssetImportErrorLog importErrorLog,
            AssetCollection allImportAssetDependencies,
            GraphData graph)
        {
            Shader primaryShader = null;

            string path = importContext.assetPath;
            var    primaryShaderName = Path.GetFileNameWithoutExtension(path);

            try
            {
                // this will also add Target dependencies into the asset collection
                Generator generator;
                generator = new Generator(graph, graph.outputNode, GenerationMode.ForReals, primaryShaderName, assetCollection: allImportAssetDependencies);

                bool first = true;
                foreach (var generatedShader in generator.allGeneratedShaders)
                {
                    var shaderString = generatedShader.codeString;

                    // we only care if an error was reported for a node that we actually used
                    if (graph.messageManager.AnyError((nodeId) => NodeWasUsedByGraph(nodeId, graph)) ||
                        shaderString == null)
                    {
                        shaderString = k_ErrorShader.Replace("Hidden/GraphErrorShader2", generatedShader.shaderName);
                    }

                    var shader = ShaderUtil.CreateShaderAsset(importContext, shaderString, false);

                    ReportErrors(graph, shader, path, importErrorLog);

                    EditorMaterialUtility.SetShaderDefaults(
                        shader,
                        generatedShader.assignedTextures.Where(x => x.modifiable).Select(x => x.name).ToArray(),
                        generatedShader.assignedTextures.Where(x => x.modifiable).Select(x => EditorUtility.InstanceIDToObject(x.textureId) as Texture).ToArray());

                    EditorMaterialUtility.SetShaderNonModifiableDefaults(
                        shader,
                        generatedShader.assignedTextures.Where(x => !x.modifiable).Select(x => x.name).ToArray(),
                        generatedShader.assignedTextures.Where(x => !x.modifiable).Select(x => EditorUtility.InstanceIDToObject(x.textureId) as Texture).ToArray());

                    if (first)
                    {
                        // first shader is always the primary shader
                        // we return the primary shader so it can be attached to the import context at the outer level
                        // allowing it to bind a custom icon as well
                        primaryShader = shader;

                        // only the main shader gets a material created
                        Material material = new Material(shader)
                        {
                            name = primaryShaderName + " Material"
                        };
                        importContext.AddObjectToAsset("Material", material);

                        first = false;
                    }
                    else
                    {
                        importContext.AddObjectToAsset($"Shader-{generatedShader.shaderName}", shader);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
                // ignored
            }

            return(primaryShader);
        }