public override void OnImportAsset(AssetImportContext ctx) { byte[] bytes = File.ReadAllBytes(ctx.assetPath); Texture2D sourceTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false); sourceTexture.LoadImage(bytes); originalWidth = sourceTexture.width; originalHeight = sourceTexture.height; cols = sourceTexture.width / pageSize; if (cols == 0) { cols = 1; } rows = sourceTexture.height / pageSize; if (rows == 0) { rows = 1; } bool changedPageSize = false; while (cols * rows > 2048) { pageSize *= 2; cols /= 2; rows /= 2; changedPageSize = true; } if (changedPageSize) { ctx.LogImportWarning("Texture Width * Texture Height * Page Size must be less or equal to 2048, so the Page Size is increased to " + pageSize); } int resizeX = sourceTexture.width; int resizeY = sourceTexture.height; if (sourceTexture.width % pageSize != 0) { resizeX = cols * pageSize; } if (sourceTexture.height % pageSize != 0) { resizeY = rows * pageSize; } if (resizeX != sourceTexture.width || resizeY != sourceTexture.height) { TextureScaler.Scale(sourceTexture, resizeX, resizeY); ctx.LogImportWarning("The width and height of the texture must be equal to Page Size * N, so the texture size is changed to " + resizeX + "x" + resizeY); } Texture2DArray array = InitTexture2DArray(sourceTexture, ctx); ctx.AddObjectToAsset("_MainTex", array); ctx.SetMainObject(array); DestroyImmediate(sourceTexture); }
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>(); 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.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 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 = string.Format("{0} {1}", sceneName, ObjectNames.NicifyVariableName(matName)); matName = ObjectNames.GetUniqueName(materialNames.ToArray(), matName); mat.name = matName; materialNames.Add(matName); } return mat; })); }).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); }).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); } } // 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; } }); // 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; } importer.SaveAndReimport(); } else { Debug.LogWarning(string.Format("GLTFImporter: Unable to import texture at path: {0}", texPath)); } } }; } } } } 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) { ctx.AddObjectToAsset("mesh " + mesh.name, mesh); } ctx.SetMainObject(gltfScene); #else // Set main asset ctx.SetMainAsset("main asset", gltfScene); // Add meshes foreach (var mesh in meshes) { ctx.AddSubAsset("mesh " + mesh.name, mesh); } #endif }
public override void OnImportAsset(AssetImportContext ctx) { { var ext = Path.GetExtension(ctx.assetPath).ToLower(); if (ext == ".vox") { fileType = VoxelBase.FileType.vox; } else if (ext == ".qb") { fileType = VoxelBase.FileType.qb; } else { return; } } var gameObject = new GameObject(Path.GetFileNameWithoutExtension(ctx.assetPath)); var voxelObject = gameObject.AddComponent <VoxelObject>(); { voxelObject.legacyVoxImport = legacyVoxImport; voxelObject.importMode = importMode; voxelObject.importScale = importScale; voxelObject.importOffset = importOffset; voxelObject.combineFaces = combineFaces; voxelObject.ignoreCavity = ignoreCavity; voxelObject.voxelStructure = outputStructure ? ScriptableObject.CreateInstance <VoxelStructure>() : null; voxelObject.generateLightmapUVs = generateLightmapUVs; voxelObject.meshFaceVertexOffset = meshFaceVertexOffset; voxelObject.loadFromVoxelFile = loadFromVoxelFile; voxelObject.generateMipMaps = generateMipMaps; } var objectCore = new VoxelObjectCore(voxelObject); try { if (!objectCore.Create(ctx.assetPath, null)) { Debug.LogErrorFormat("<color=green>[Voxel Importer]</color> ScriptedImporter error. file:{0}", ctx.assetPath); DestroyImmediate(gameObject); return; } } catch { Debug.LogErrorFormat("<color=green>[Voxel Importer]</color> ScriptedImporter error. file:{0}", ctx.assetPath); DestroyImmediate(gameObject); return; } #region Material if (retainExisting) { bool changed = false; var assets = AssetDatabase.LoadAllAssetsAtPath(ctx.assetPath); for (int i = 0; i < voxelObject.materials.Count; i++) { var material = assets.FirstOrDefault(c => c.name == string.Format("mat{0}", i)) as Material; if (material != null) { material.mainTexture = voxelObject.atlasTexture; voxelObject.materials[i] = material; changed = true; } } if (changed) { var renderer = gameObject.GetComponent <MeshRenderer>(); renderer.sharedMaterials = voxelObject.materials.ToArray(); } } #endregion #region Collider switch (colliderType) { case ColliderType.Box: gameObject.AddComponent <BoxCollider>(); break; case ColliderType.Sphere: gameObject.AddComponent <SphereCollider>(); break; case ColliderType.Capsule: gameObject.AddComponent <CapsuleCollider>(); break; case ColliderType.Mesh: gameObject.AddComponent <MeshCollider>(); break; } #endregion #if UNITY_2017_3_OR_NEWER ctx.AddObjectToAsset(gameObject.name, gameObject); ctx.AddObjectToAsset(voxelObject.mesh.name = "mesh", voxelObject.mesh); for (int i = 0; i < voxelObject.materials.Count; i++) { ctx.AddObjectToAsset(voxelObject.materials[i].name = string.Format("mat{0}", i), voxelObject.materials[i]); } ctx.AddObjectToAsset(voxelObject.atlasTexture.name = "tex", voxelObject.atlasTexture); if (voxelObject.voxelStructure != null) { ctx.AddObjectToAsset(voxelObject.voxelStructure.name = "structure", voxelObject.voxelStructure); } VoxelObject.DestroyImmediate(voxelObject); ctx.SetMainObject(gameObject); #else ctx.SetMainAsset(gameObject.name, gameObject); ctx.AddSubAsset(voxelObject.mesh.name = "mesh", voxelObject.mesh); for (int i = 0; i < voxelObject.materials.Count; i++) { ctx.AddSubAsset(voxelObject.materials[i].name = string.Format("mat{0}", i), voxelObject.materials[i]); } ctx.AddSubAsset(voxelObject.atlasTexture.name = "tex", voxelObject.atlasTexture); if (voxelObject.voxelStructure != null) { ctx.AddSubAsset(voxelObject.voxelStructure.name = "structure", voxelObject.voxelStructure); } VoxelObject.DestroyImmediate(voxelObject); #endif }
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"); 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); } } }
private void ImportYarn(AssetImportContext ctx) { var sourceText = File.ReadAllText(ctx.assetPath); string fileName = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath); Yarn.Program compiledProgram = null; IDictionary <string, Yarn.Compiler.StringInfo> stringTable = null; compilationErrorMessage = null; try { // Compile the source code into a compiled Yarn program (or // generate a parse error) compilationStatus = Yarn.Compiler.Compiler.CompileString(sourceText, fileName, out compiledProgram, out stringTable); isSuccesfullyCompiled = true; compilationErrorMessage = string.Empty; } catch (Yarn.Compiler.ParseException e) { isSuccesfullyCompiled = false; compilationErrorMessage = e.Message; ctx.LogImportError(e.Message); } // Create a container for storing the bytes if (programContainer == null) { programContainer = ScriptableObject.CreateInstance <YarnProgram>(); } byte[] compiledBytes = null; if (compiledProgram != null) { using (var memoryStream = new MemoryStream()) using (var outputStream = new Google.Protobuf.CodedOutputStream(memoryStream)) { // Serialize the compiled program to memory compiledProgram.WriteTo(outputStream); outputStream.Flush(); compiledBytes = memoryStream.ToArray(); } } programContainer.compiledProgram = compiledBytes; // Add this container to the imported asset; it will be // what the user interacts with in Unity ctx.AddObjectToAsset("Program", programContainer, YarnEditorUtility.GetYarnDocumentIconTexture()); ctx.SetMainObject(programContainer); if (stringTable?.Count > 0) { var lines = stringTable.Select(x => new StringTableEntry { ID = x.Key, Language = baseLanguageID, Text = x.Value.text, File = x.Value.fileName, Node = x.Value.nodeName, LineNumber = x.Value.lineNumber.ToString(), Lock = GetHashString(x.Value.text, 8), }).OrderBy(entry => int.Parse(entry.LineNumber)); var stringTableCSV = StringTableEntry.CreateCSV(lines); var textAsset = new TextAsset(stringTableCSV); textAsset.name = $"{fileName} ({baseLanguageID})"; ctx.AddObjectToAsset("Strings", textAsset); programContainer.baseLocalizationId = baseLanguageID; baseLanguage = textAsset; programContainer.localizations = localizations.Append(new YarnProgram.YarnTranslation(baseLanguageID, textAsset)).ToArray(); programContainer.baseLocalizationId = baseLanguageID; stringIDs = lines.Select(l => l.ID).ToArray(); } }
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(); 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.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); var metadata = ScriptableObject.CreateInstance <ShaderGraphMetadata>(); metadata.hideFlags = HideFlags.HideInHierarchy; if (graph != null) { metadata.outputNodeTypeName = graph.outputNode.GetType().FullName; } metadata.assetDependencies = new List <UnityEngine.Object>(); var deps = GatherDependenciesFromSourceFile(ctx.assetPath); foreach (string dependency in deps) { metadata.assetDependencies.Add(AssetDatabase.LoadAssetAtPath(dependency, typeof(UnityEngine.Object))); } 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 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 not 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; } // Load icons. ////REVIEW: the icons won't change if the user changes skin; not sure it makes sense to differentiate here var isDarkSkin = EditorGUIUtility.isProSkin; var assetIcon = (Texture2D)EditorGUIUtility.Load(isDarkSkin ? kAssetIconDark : kAssetIcon); var actionIcon = (Texture2D)EditorGUIUtility.Load(isDarkSkin ? kActionIconDark : kActionIcon); // Add asset. ctx.AddObjectToAsset("<root>", asset, assetIcon); 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, actionIcon); } } // 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(); }
// static string[] GatherDependenciesFromSourceFile(string path) { // // Called before actual import for each changed asset that is imported by this importer type // // Extract the dependencies for the asset specified in path. // // For asset dependencies that are discovered, return them in the string array, where the string is the path to asset // // // TODO: Texture files with relative URIs should be included here // return null; // } public override void OnImportAsset(AssetImportContext ctx) { reportItems = null; var downloadProvider = new EditorDownloadProvider(); var logger = new CollectingLogger(); m_Gltf = new GltfImport( downloadProvider, new UninterruptedDeferAgent(), null, logger ); if (importSettings == null) { // Design-time import specific settings importSettings = new ImportSettings { // Avoid naming conflicts by default nodeNameMethod = ImportSettings.NameImportMethod.OriginalUnique }; } var success = AsyncHelpers.RunSync <bool>(() => m_Gltf.Load(ctx.assetPath, importSettings)); GameObjectInstantiator instantiator = null; CollectingLogger instantiationLogger = null; if (success) { m_ImportedNames = new HashSet <string>(); m_ImportedObjects = new HashSet <Object>(); var go = new GameObject("root"); instantiationLogger = new CollectingLogger(); instantiator = new GameObjectInstantiator(m_Gltf, go.transform, instantiationLogger); for (var sceneIndex = 0; sceneIndex < m_Gltf.sceneCount; sceneIndex++) { success = m_Gltf.InstantiateScene(instantiator, sceneIndex); if (!success) { break; } var sceneTransform = go.transform.GetChild(sceneIndex); var sceneGo = sceneTransform.gameObject; AddObjectToAsset(ctx, $"scenes/{sceneGo.name}", sceneGo); if (sceneIndex == m_Gltf.defaultSceneIndex) { ctx.SetMainObject(sceneGo); } } for (var i = 0; i < m_Gltf.textureCount; i++) { var texture = m_Gltf.GetTexture(i); if (texture != null) { AddObjectToAsset(ctx, $"textures/{texture.name}", texture); } } for (var i = 0; i < m_Gltf.materialCount; i++) { var mat = m_Gltf.GetMaterial(i); AddObjectToAsset(ctx, $"materials/{mat.name}", mat); } if (m_Gltf.defaultMaterial != null) { // If a default/fallback material was created, import it as well' // to avoid (pink) objects without materials var mat = m_Gltf.defaultMaterial; AddObjectToAsset(ctx, $"materials/{mat.name}", mat); } var meshes = m_Gltf.GetMeshes(); if (meshes != null) { foreach (var mesh in meshes) { AddObjectToAsset(ctx, $"meshes/{mesh.name}", mesh); } } var clips = m_Gltf.GetAnimationClips(); if (clips != null) { foreach (var animationClip in clips) { AddObjectToAsset(ctx, $"animations/{animationClip.name}", animationClip); } } m_ImportedNames = null; m_ImportedObjects = null; } var deps = new List <GltfAssetDependency>(); for (var index = 0; index < downloadProvider.assetDependencies.Count; index++) { var dependency = downloadProvider.assetDependencies[index]; if (ctx.assetPath == dependency.originalUri) { // Skip original gltf/glb file continue; } var guid = AssetDatabase.AssetPathToGUID(dependency.originalUri); if (!string.IsNullOrEmpty(guid)) { dependency.assetPath = dependency.originalUri; ctx.DependsOnSourceAsset(dependency.assetPath); } deps.Add(dependency); } assetDependencies = deps.ToArray(); var reportItemList = new List <LogItem>(); reportItemList.AddRange(logger.items); if (instantiationLogger?.items != null) { reportItemList.AddRange(instantiationLogger.items); } reportItems = reportItemList.ToArray(); }
public override void OnImportAsset(AssetImportContext ctx) { GameObject temp = new GameObject(); GameObject gameObject; GameObject mesh; GameObject brick = temp; List <GameObject> meshes = new List <GameObject>(); List <GameObject> parts = new List <GameObject>(); List <Mesh> bricks = new List <Mesh>(); List <string> names = new List <string>(); List <Material> materials = new List <Material>(); List <short> files = new List <short>(); List <short> parents = new List <short>(); string name; short material; Vector3[] vertices; Vector3[] normals; int[] indices; Vector2[] uv; Matrix4x4 matrix; using (BinaryReader reader = new BinaryReader(File.Open(ctx.assetPath, FileMode.Open))) { name = reader.ReadString(); gameObject = new GameObject(name.Replace(".obl", "")); while (reader.BaseStream.Position < reader.BaseStream.Length) { name = reader.ReadString(); mesh = new GameObject(name + "_" + reader.ReadInt16()); if (name.EndsWith("x0")) { parents.Add(reader.ReadInt16()); parts.Add(mesh); mesh.transform.parent = gameObject.transform; matrix = new Matrix4x4(new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()), new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()), new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()), new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle())); mesh.transform.position = matrix.GetColumn(3); mesh.transform.rotation = matrix.rotation; brick = mesh; } else { mesh.transform.parent = brick.transform; mesh.transform.position = brick.transform.position; mesh.transform.rotation = brick.transform.rotation; } material = reader.ReadInt16(); if (!files.Contains(material)) { Material mat = Resources.Load <Material>("Materials/" + material); materials.Add(mat); files.Add(material); } vertices = new Vector3[reader.ReadInt32()]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } normals = new Vector3[reader.ReadInt32()]; for (int i = 0; i < normals.Length; i++) { normals[i] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } indices = new int[reader.ReadInt32()]; for (int i = 0; i < indices.Length; i++) { indices[i] = reader.ReadInt16(); } uv = new Vector2[vertices.Length]; for (int i = 0; i < uv.Length; i++) { Vector3 v = vertices[i]; uv[i] = new Vector2((v.x + v.y) / 2, (v.y + v.z) / 2); } if (!names.Contains(name)) { Mesh m = new Mesh { vertices = vertices, normals = normals, triangles = indices, uv = uv }; bricks.Add(m); names.Add(name); } mesh.AddComponent <MeshFilter>(); mesh.GetComponent <MeshFilter>().mesh = bricks[names.IndexOf(name)]; mesh.AddComponent <MeshRenderer>(); mesh.GetComponent <MeshRenderer>().materials = new Material[] { materials[files.IndexOf(material)] }; meshes.Add(mesh); } } for (int i = 0; i < parts.Count; i++) { int index = parts.FindIndex(x => x.name.EndsWith(parents[i].ToString())); if (parents[i] != -1) { parts[i].transform.parent = parts[index].transform; } } gameObject.transform.localScale = new Vector3(0.5f, 0.5f, -0.5f); ctx.AddObjectToAsset(gameObject.name, gameObject); ctx.SetMainObject(gameObject); for (int i = 0; i < bricks.Count; i++) { ctx.AddObjectToAsset(names[i], bricks[i]); } for (int i = 0; i < materials.Count; i++) { ctx.AddObjectToAsset(files[i].ToString(), materials[i]); } DestroyImmediate(temp); }
public override void OnImportAsset(AssetImportContext ase) { switch (Pivot) { case PivotPositionEnum.TopLeft: PivotPosition = new Vector2(0, 1); break; case PivotPositionEnum.TopCenter: PivotPosition = new Vector2(.5f, 1); break; case PivotPositionEnum.TopRight: PivotPosition = new Vector2(1, 1); break; case PivotPositionEnum.MidleLeft: PivotPosition = new Vector2(0, .5f); break; case PivotPositionEnum.MiddleCenter: PivotPosition = new Vector2(.5f, .5f); break; case PivotPositionEnum.MiddleRight: PivotPosition = new Vector2(1, .5f); break; case PivotPositionEnum.BottomLeft: PivotPosition = new Vector2(0, 0); break; case PivotPositionEnum.BottomCenter: PivotPosition = new Vector2(.5f, 0); break; case PivotPositionEnum.BottomRight: PivotPosition = new Vector2(1, 0); break; } Aseprite = new Aseprite(File.ReadAllBytes(ase.assetPath), MergedLayersImportOption, SeparateLayersImportOption, PivotPosition, Path.GetFileNameWithoutExtension(ase.assetPath)); if ((int)SeparateLayersImportOption > 0) { for (var l = 0; l < Aseprite.Layers.Length; l++) { ase.AddObjectToAsset(Aseprite.Layers[l].Texture.name, Aseprite.Layers[l].Texture); if ((int)SeparateLayersImportOption > 1) { foreach (var sprite in Aseprite.Layers[l].Sprites) { ase.AddObjectToAsset(sprite.name, sprite); } if ((int)SeparateLayersImportOption > 2) { AddAnimation($"Layer_{l}_", Aseprite.Layers[l].Sprites, ase); } } } } if (Aseprite.ColorPalette != null) { ase.AddObjectToAsset("Palette", Aseprite.ColorPalette); } if ((int)MergedLayersImportOption > 0) { ase.AddObjectToAsset(Aseprite.MergedLayer.Texture.name, Aseprite.MergedLayer.Texture); ase.SetMainObject(Aseprite.MergedLayer.Texture); if ((int)MergedLayersImportOption > 1) { foreach (var sprite in Aseprite.MergedLayer.Sprites) { ase.AddObjectToAsset(sprite.name, sprite); } if ((int)MergedLayersImportOption > 2) { AddAnimation("", Aseprite.MergedLayer.Sprites, ase); } } } else { if (Aseprite.ColorPalette != null) { ase.SetMainObject(Aseprite.ColorPalette); } } }
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 ReportErrors(graph, shader, path); 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"); 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))); } } } List <GraphInputData> inputInspectorDataList = new List <GraphInputData>(); foreach (AbstractShaderProperty property in graph.properties) { // Don't write out data for non-exposed blackboard items if (!property.isExposed) { continue; } // VTs are treated differently if (property is VirtualTextureShaderProperty virtualTextureShaderProperty) { inputInspectorDataList.Add(MinimalCategoryData.ProcessVirtualTextureProperty(virtualTextureShaderProperty)); } else { inputInspectorDataList.Add(new GraphInputData() { referenceName = property.referenceName, propertyType = property.propertyType, isKeyword = false }); } } foreach (ShaderKeyword keyword in graph.keywords) { // Don't write out data for non-exposed blackboard items if (!keyword.isExposed) { continue; } var sanitizedReferenceName = keyword.referenceName; if (keyword.keywordType == KeywordType.Boolean && keyword.referenceName.Contains("_ON")) { sanitizedReferenceName = sanitizedReferenceName.Replace("_ON", String.Empty); } inputInspectorDataList.Add(new GraphInputData() { referenceName = sanitizedReferenceName, keywordType = keyword.keywordType, isKeyword = true }); } sgMetadata.categoryDatas = new List <MinimalCategoryData>(); foreach (CategoryData categoryData in graph.categories) { // Don't write out empty categories if (categoryData.childCount == 0) { continue; } MinimalCategoryData mcd = new MinimalCategoryData() { categoryName = categoryData.name, propertyDatas = new List <GraphInputData>() }; foreach (var input in categoryData.Children) { GraphInputData propData; // Only write out data for exposed blackboard items if (input.isExposed == false) { continue; } // VTs are treated differently if (input is VirtualTextureShaderProperty virtualTextureShaderProperty) { propData = MinimalCategoryData.ProcessVirtualTextureProperty(virtualTextureShaderProperty); inputInspectorDataList.RemoveAll(inputData => inputData.referenceName == propData.referenceName); mcd.propertyDatas.Add(propData); continue; } else if (input is ShaderKeyword keyword) { var sanitizedReferenceName = keyword.referenceName; if (keyword.keywordType == KeywordType.Boolean && keyword.referenceName.Contains("_ON")) { sanitizedReferenceName = sanitizedReferenceName.Replace("_ON", String.Empty); } propData = new GraphInputData() { referenceName = sanitizedReferenceName, keywordType = keyword.keywordType, isKeyword = true }; } else { var prop = input as AbstractShaderProperty; propData = new GraphInputData() { referenceName = input.referenceName, propertyType = prop.propertyType, isKeyword = false }; } mcd.propertyDatas.Add(propData); inputInspectorDataList.Remove(propData); } sgMetadata.categoryDatas.Add(mcd); } // Any uncategorized elements get tossed into an un-named category at the top as a fallback if (inputInspectorDataList.Count > 0) { sgMetadata.categoryDatas.Insert(0, new MinimalCategoryData() { categoryName = "", propertyDatas = inputInspectorDataList }); } 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); } } }
public override void OnImportAsset(AssetImportContext ctx) { name = Path.GetFileNameWithoutExtension(ctx.assetPath); //name = GetFileName(ctx.assetPath); AseFile aseFile = ReadAseFile(ctx.assetPath); if (LayersToTextures) { GenerateSeparateTexturesFromLayers(ctx, aseFile); return; } SpriteAtlasBuilder atlasBuilder = new SpriteAtlasBuilder(textureSettings, aseFile.Header.Width, aseFile.Header.Height); Texture2D[] frames = null; if (importType != AseFileImportType.LayerToSprite) { frames = aseFile.GetFrames(); } else { frames = aseFile.GetLayersAsFrames(); } SpriteImportData[] spriteImportData = new SpriteImportData[0]; //if (textureSettings.transparentMask) //{ // atlas = atlasBuilder.GenerateAtlas(frames, out spriteImportData, textureSettings.transparentColor, false); //} //else //{ // atlas = atlasBuilder.GenerateAtlas(frames, out spriteImportData, false); //} Texture2D atlas = atlasBuilder.GenerateAtlas(frames, out spriteImportData, textureSettings.transparentMask, false); atlas.filterMode = textureSettings.filterMode; atlas.alphaIsTransparency = false; atlas.wrapMode = TextureWrapMode.Clamp; atlas.name = "Texture"; ctx.AddObjectToAsset("Texture", atlas); ctx.SetMainObject(atlas); switch (importType) { case AseFileImportType.LayerToSprite: case AseFileImportType.Sprite: ImportSprites(ctx, aseFile, spriteImportData, atlas); break; case AseFileImportType.Tileset: ImportTileset(ctx, atlas); break; } ctx.SetMainObject(atlas); }
// Called by Unity to perform an import public override void OnImportAsset(AssetImportContext ctx) { // "ctx" contains information about the import that Unity wants us // to do; it contains the path to the file, and we'll put the Unity // objects into it when we're done // "cube" files will contain JSON that describes the color and size // of the cube. // Create a variable to load the cube description into CubeDescription cubeDescription; // Attempt to load the JSON. try { var text = System.IO.File.ReadAllText(ctx.assetPath); cubeDescription = JsonUtility.FromJson <CubeDescription>(text); } catch (System.ArgumentException e) { // We failed to load the JSON. Maybe it's not valid. Report the // error. Debug.LogErrorFormat( "{0} is not a valid cube: {1}", ctx.assetPath, e.Message); return; } catch (System.Exception e) { // We caught some other kind of exception, and can't continue. // Re-throw the error. throw e; } // Create a generic cube object, which we'll make changes to and // save as a new asset. var cubeObject = GameObject.CreatePrimitive(PrimitiveType.Cube); // Get the last part of the file path, and use it as the cube's // name string name = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath); // Next, we'll create a cube that's the right size. The default // cube mesh is 1x1x1; we'll scale it based on the size that was // passed in. // Copy the default cube mesh. var cubeMesh = Instantiate(cubeObject.GetComponent <MeshFilter>().sharedMesh); // Create a matrix that scales vertices by the given X, Y and Z // amounts. var scaleMatrix = Matrix4x4.Scale(cubeDescription.size); // Get a copy of the vertices in the mesh. var vertices = cubeMesh.vertices; // For each of these vertices, apply the scale by multiplying the // matrix against the vertex. for (int v = 0; v < vertices.Length; v++) { vertices[v] = scaleMatrix.MultiplyPoint(vertices[v]); } // Store these scaled vertices in the mesh. cubeMesh.vertices = vertices; // Tell the cube's MeshFilter to use this new mesh. cubeObject.GetComponent <MeshFilter>().sharedMesh = cubeMesh; // Give the mesh a name. cubeMesh.name = name + " Mesh"; // Create a new material, using the Standard shader (which is the // default) var cubeMaterial = new Material(Shader.Find("Standard")); // Apply the color that we loaded. cubeMaterial.color = cubeDescription.color; // Give it a name, too. cubeMaterial.name = name + " Material"; // Tell the cube's MeshRenderer to use this material. cubeObject.GetComponent <MeshRenderer>().material = cubeMaterial; // Now we store the objects we just created as assets. // First, store the GameObject (the collection of components that // uses and renders the mesh and material), and mark it as the // "main" object. ctx.AddObjectToAsset(name, cubeObject); ctx.SetMainObject(cubeObject); // We also need to store the mesh and material as well. ctx.AddObjectToAsset(cubeMaterial.name, cubeMaterial); ctx.AddObjectToAsset(cubeMesh.name, cubeMesh); }
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 { 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 void SetMainObject(UnityEngine.Object obj) { m_Context.SetMainObject(obj); }
public override void OnImportAsset(AssetImportContext ctx) { { var ext = Path.GetExtension(ctx.assetPath).ToLower(); if (ext == ".vox") { fileType = VoxelBase.FileType.vox; } else if (ext == ".qb") { fileType = VoxelBase.FileType.qb; } else { return; } } #region DefaultScale if (dataVersion == 0 && importScale == Vector3.one && AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(ctx.assetPath) == null) { var x = EditorPrefs.GetFloat("VoxelImporter_DefaultScaleX", 1f); var y = EditorPrefs.GetFloat("VoxelImporter_DefaultScaleY", 1f); var z = EditorPrefs.GetFloat("VoxelImporter_DefaultScaleZ", 1f); importScale = new Vector3(x, y, z); } #endregion Action <string> LogImportError = (log) => { #if UNITY_2018_1_OR_NEWER ctx.LogImportError(log); #else Debug.LogError(log); #endif }; var gameObject = new GameObject(Path.GetFileNameWithoutExtension(ctx.assetPath)); var voxelObject = gameObject.AddComponent <VoxelObject>(); { voxelObject.legacyVoxImport = legacyVoxImport; voxelObject.importMode = importMode; voxelObject.importScale = importScale; voxelObject.importOffset = importOffset; voxelObject.combineFaces = combineFaces; voxelObject.ignoreCavity = ignoreCavity; voxelObject.shareSameFace = shareSameFace; voxelObject.voxelStructure = outputStructure ? ScriptableObject.CreateInstance <VoxelStructure>() : null; voxelObject.generateLightmapUVs = generateLightmapUVs; voxelObject.generateLightmapUVsAngleError = generateLightmapUVsAngleError; voxelObject.generateLightmapUVsAreaError = generateLightmapUVsAreaError; voxelObject.generateLightmapUVsHardAngle = generateLightmapUVsHardAngle; voxelObject.generateLightmapUVsPackMargin = generateLightmapUVsPackMargin; voxelObject.generateTangents = generateTangents; voxelObject.meshFaceVertexOffset = meshFaceVertexOffset; voxelObject.loadFromVoxelFile = loadFromVoxelFile; voxelObject.generateMipMaps = generateMipMaps; } var objectCore = new VoxelObjectCore(voxelObject); try { if (!objectCore.Create(ctx.assetPath, null)) { LogImportError(string.Format("<color=green>[Voxel Importer]</color> ScriptedImporter error. file:{0}", ctx.assetPath)); DestroyImmediate(gameObject); return; } } catch { LogImportError(string.Format("<color=green>[Voxel Importer]</color> ScriptedImporter error. file:{0}", ctx.assetPath)); DestroyImmediate(gameObject); return; } #region Correspondence in Issue ID 947055 Correction in case before correction is applied for (int i = 0; i < voxelObject.materials.Count; i++) { if (voxelObject.materials[i] != null) { voxelObject.materials[i].hideFlags |= HideFlags.NotEditable; } } if (voxelObject.atlasTexture != null) { voxelObject.atlasTexture.hideFlags |= HideFlags.NotEditable; } if (voxelObject.mesh != null) { voxelObject.mesh.hideFlags |= HideFlags.NotEditable; } #endregion #region Material { materials = new Material[voxelObject.materialIndexes.Count]; materialNames = new string[voxelObject.materialIndexes.Count]; for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var index = voxelObject.materialIndexes[i]; var material = voxelObject.materials[index]; material.name = string.Format("mat{0}", index); materials[i] = material; materialNames[i] = material.name; } if (remappedMaterials != null) { remappedMaterials = remappedMaterials.Where(item => item.material != null).ToArray(); } } #endregion #region Collider switch (colliderType) { case ColliderType.Box: gameObject.AddComponent <BoxCollider>(); break; case ColliderType.Sphere: gameObject.AddComponent <SphereCollider>(); break; case ColliderType.Capsule: gameObject.AddComponent <CapsuleCollider>(); break; case ColliderType.Mesh: gameObject.AddComponent <MeshCollider>(); break; } #endregion #if UNITY_2017_3_OR_NEWER ctx.AddObjectToAsset(gameObject.name, gameObject); ctx.AddObjectToAsset(voxelObject.mesh.name = "mesh", voxelObject.mesh); { var materials = new List <Material>(); for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var material = voxelObject.materials[voxelObject.materialIndexes[i]]; materials.Add(material); if (remappedMaterials != null) { var index = ArrayUtility.FindIndex(remappedMaterials, (t) => { return(t.name == material.name); }); if (index >= 0) { materials[i] = remappedMaterials[index].material; continue; } } ctx.AddObjectToAsset(material.name, material); } gameObject.GetComponent <MeshRenderer>().sharedMaterials = materials.ToArray(); } ctx.AddObjectToAsset(voxelObject.atlasTexture.name = "tex", voxelObject.atlasTexture); if (voxelObject.voxelStructure != null) { ctx.AddObjectToAsset(voxelObject.voxelStructure.name = "structure", voxelObject.voxelStructure); } VoxelObject.DestroyImmediate(voxelObject); ctx.SetMainObject(gameObject); #else ctx.SetMainAsset(gameObject.name, gameObject); ctx.AddSubAsset(voxelObject.mesh.name = "mesh", voxelObject.mesh); for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var material = voxelObject.materials[voxelObject.materialIndexes[i]]; ctx.AddSubAsset(material.name, material); } ctx.AddSubAsset(voxelObject.atlasTexture.name = "tex", voxelObject.atlasTexture); if (voxelObject.voxelStructure != null) { ctx.AddSubAsset(voxelObject.voxelStructure.name = "structure", voxelObject.voxelStructure); } VoxelObject.DestroyImmediate(voxelObject); #endif dataVersion = EditorDataVersion; }
public override void OnImportAsset(AssetImportContext ctx) { #if YARNSPINNER_DEBUG UnityEngine.Profiling.Profiler.enabled = true; #endif var project = ScriptableObject.CreateInstance <YarnProject>(); project.name = Path.GetFileNameWithoutExtension(ctx.assetPath); // Start by creating the asset - no matter what, we need to // produce an asset, even if it doesn't contain valid Yarn // bytecode, so that other assets don't lose their references. ctx.AddObjectToAsset("Project", project); ctx.SetMainObject(project); foreach (var script in sourceScripts) { string path = AssetDatabase.GetAssetPath(script); if (string.IsNullOrEmpty(path)) { // This is, for some reason, not a valid script we can // use. Don't add a dependency on it. continue; } ctx.DependsOnSourceAsset(path); } // Parse declarations var localDeclarationsCompileJob = CompilationJob.CreateFromFiles(ctx.assetPath); localDeclarationsCompileJob.CompilationType = CompilationJob.Type.DeclarationsOnly; IEnumerable <Declaration> localDeclarations; compileError = null; try { var result = Compiler.Compiler.Compile(localDeclarationsCompileJob); localDeclarations = result.Declarations; } catch (ParseException e) { ctx.LogImportError($"Error in Yarn Project: {e.Message}"); compileError = $"Error in Yarn Project {ctx.assetPath}: {e.Message}"; return; } // Store these so that we can continue displaying them after // this import step, in case there are compile errors later. // We'll replace this with a more complete list later if // compilation succeeds. serializedDeclarations = localDeclarations .Where(decl => decl.DeclarationType == Declaration.Type.Variable) .Select(decl => new SerializedDeclaration(decl)).ToList(); // We're done processing this file - we've parsed it, and // pulled any information out of it that we need to. Now to // compile the scripts associated with this project. var scriptImporters = sourceScripts.Where(s => s != null).Select(s => AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(s)) as YarnImporter); // First step: check to see if there's any parse errors in the // files. var scriptsWithParseErrors = scriptImporters.Where(script => script.isSuccessfullyParsed == false); if (scriptsWithParseErrors.Count() != 0) { // Parse errors! We can't continue. string failingScriptNameList = string.Join("\n", scriptsWithParseErrors.Select(script => script.assetPath)); compileError = $"Parse errors exist in the following files:\n{failingScriptNameList}"; return; } // Get paths to the scripts we're importing, and also map them // to their corresponding importer var pathsToImporters = scriptImporters.ToDictionary(script => script.assetPath, script => script); if (pathsToImporters.Count == 0) { return; // nothing further to do here } // We now now compile! var job = CompilationJob.CreateFromFiles(pathsToImporters.Keys); job.VariableDeclarations = localDeclarations; CompilationResult compilationResult; try { compilationResult = Compiler.Compiler.Compile(job); } catch (TypeException e) { ctx.LogImportError($"Error compiling: {e.Message}"); compileError = e.Message; var importer = pathsToImporters[e.FileName]; importer.parseErrorMessage = e.Message; EditorUtility.SetDirty(importer); return; } catch (ParseException e) { ctx.LogImportError(e.Message); compileError = e.Message; var importer = pathsToImporters[e.FileName]; importer.parseErrorMessage = e.Message; EditorUtility.SetDirty(importer); return; } if (compilationResult.Program == null) { ctx.LogImportError("Internal error: Failed to compile: resulting program was null, but compiler did not throw a parse exception."); return; } // Store _all_ declarations - both the ones in this // .yarnproject file, and the ones inside the .yarn files serializedDeclarations = localDeclarations .Concat(compilationResult.Declarations) .Where(decl => decl.DeclarationType == Declaration.Type.Variable) .Select(decl => new SerializedDeclaration(decl)).ToList(); // Clear error messages from all scripts - they've all passed // compilation foreach (var importer in pathsToImporters.Values) { importer.parseErrorMessage = null; } // Will we need to create a default localization? This variable // will be set to false if any of the languages we've // configured in languagesToSourceAssets is the default // language. var shouldAddDefaultLocalization = true; foreach (var pair in languagesToSourceAssets) { // Don't create a localization if the language ID was not // provided if (string.IsNullOrEmpty(pair.languageID)) { Debug.LogWarning($"Not creating a localization for {project.name} because the language ID wasn't provided. Add the language ID to the localization in the Yarn Project's inspector."); continue; } IEnumerable <StringTableEntry> stringTable; // Where do we get our strings from? If it's the default // language, we'll pull it from the scripts. If it's from // any other source, we'll pull it from the CSVs. if (pair.languageID == defaultLanguage) { // We'll use the program-supplied string table. stringTable = GenerateStringsTable(); // We don't need to add a default localization. shouldAddDefaultLocalization = false; } else { try { if (pair.stringsFile == null) { // We can't create this localization because we // don't have any data for it. Debug.LogWarning($"Not creating a localization for {pair.languageID} in the Yarn Project {project.name} because a text asset containing the strings wasn't found. Add a .csv file containing the translated lines to the Yarn Project's inspector."); continue; } stringTable = StringTableEntry.ParseFromCSV(pair.stringsFile.text); } catch (System.ArgumentException e) { Debug.LogWarning($"Not creating a localization for {pair.languageID} in the Yarn Project {project.name} because an error was encountered during text parsing: {e}"); continue; } } var newLocalization = ScriptableObject.CreateInstance <Localization>(); newLocalization.LocaleCode = pair.languageID; newLocalization.AddLocalizedStrings(stringTable); project.localizations.Add(newLocalization); newLocalization.name = pair.languageID; if (pair.assetsFolder != null) { var assetsFolderPath = AssetDatabase.GetAssetPath(pair.assetsFolder); if (assetsFolderPath == null) { // This was somehow not a valid reference? Debug.LogWarning($"Can't find assets for localization {pair.languageID} in {project.name} because a path for the provided assets folder couldn't be found."); } else { var stringIDsToAssets = FindAssetsForLineIDs(stringTable.Select(s => s.ID), assetsFolderPath); #if YARNSPINNER_DEBUG var stopwatch = System.Diagnostics.Stopwatch.StartNew(); #endif newLocalization.AddLocalizedObjects(stringIDsToAssets.AsEnumerable()); #if YARNSPINNER_DEBUG stopwatch.Stop(); Debug.Log($"Imported {stringIDsToAssets.Count()} assets for {project.name} \"{pair.languageID}\" in {stopwatch.ElapsedMilliseconds}ms"); #endif } } ctx.AddObjectToAsset("localization-" + pair.languageID, newLocalization); if (pair.languageID == defaultLanguage) { // If this is our default language, set it as such project.baseLocalization = newLocalization; } else { // This localization depends upon a source asset. Make // this asset get re-imported if this source asset was // modified ctx.DependsOnSourceAsset(AssetDatabase.GetAssetPath(pair.stringsFile)); } } if (shouldAddDefaultLocalization) { // We didn't add a localization for the default language. // Create one for it now. var developmentLocalization = ScriptableObject.CreateInstance <Localization>(); developmentLocalization.LocaleCode = defaultLanguage; var stringTableEntries = compilationResult.StringTable.Select(x => new StringTableEntry { ID = x.Key, Language = defaultLanguage, Text = x.Value.text, File = x.Value.fileName, Node = x.Value.nodeName, LineNumber = x.Value.lineNumber.ToString(), Lock = YarnImporter.GetHashString(x.Value.text, 8), }); developmentLocalization.AddLocalizedStrings(stringTableEntries); project.baseLocalization = developmentLocalization; project.localizations.Add(project.baseLocalization); developmentLocalization.name = $"Default ({defaultLanguage})"; ctx.AddObjectToAsset("default-language", developmentLocalization); } // Store the compiled program byte[] compiledBytes = null; using (var memoryStream = new MemoryStream()) using (var outputStream = new Google.Protobuf.CodedOutputStream(memoryStream)) { // Serialize the compiled program to memory compilationResult.Program.WriteTo(outputStream); outputStream.Flush(); compiledBytes = memoryStream.ToArray(); } project.compiledYarnProgram = compiledBytes; #if YARNSPINNER_DEBUG UnityEngine.Profiling.Profiler.enabled = false; #endif }
public override void OnImportAsset(AssetImportContext ctx) { Debug.Log("OnImportAsset to " + ctx.assetPath); try { // Parse var parser = new GltfParser(); parser.ParsePath(ctx.assetPath); // Build Unity Model var externalObjectMap = GetExternalObjectMap() .Select(kv => (kv.Key.name, kv.Value)) ; var context = new ImporterContext(parser, null, externalObjectMap); context.InvertAxis = m_reverseAxis; context.Load(); context.ShowMeshes(); // Texture foreach (var info in context.TextureFactory.Textures) { if (!info.IsUsed) { continue; } if (!info.IsExternal) { var texture = info.Texture; ctx.AddObjectToAsset(texture.name, texture); } } // Material foreach (var info in context.MaterialFactory.Materials) { if (!info.UseExternal) { var material = info.Asset; ctx.AddObjectToAsset(material.name, material); } } // Mesh foreach (var mesh in context.Meshes.Select(x => x.Mesh)) { ctx.AddObjectToAsset(mesh.name, mesh); } // Animation foreach (var clip in context.AnimationClips) { ctx.AddObjectToAsset(clip.name, clip); } // Root ctx.AddObjectToAsset(context.Root.name, context.Root); ctx.SetMainObject(context.Root); } catch (System.Exception ex) { Debug.LogError(ex); } }
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. // Graphics.CopyTexture does not work with Texture3D, I submitted bug-report: // (Case 1208825) 2019.3: Graphics.CopyTexture does not work with Texture3D // When Unity Technologies fixed this bug, I can use this code to copy data instead: //for (var n = 0; n < m_Textures.Count; ++n) //{ // var source = m_Textures[n]; // Graphics.CopyTexture(source, 0, texture3D, n); //} var colorData = new Color32[width * height * texture3D.depth]; for (var n = 0; n < m_Textures.Count; ++n) { var source = m_Textures[n]; var sourcePixels = source.GetPixels32(); System.Array.Copy(sourcePixels, 0, colorData, width * height * n, sourcePixels.Length); } texture3D.SetPixels32(colorData); texture3D.Apply(); } 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); ctx.DependsOnSourceAsset(path); } } 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) { // Parse JSON. var text = File.ReadAllText(ctx.assetPath); var sets = InputActionSet.FromJson(text); ////TODO: catch errors ////TODO: make sure action names are unique // Create asset. var asset = ScriptableObject.CreateInstance <InputActionAsset>(); asset.m_ActionSets = sets; ctx.AddObjectToAsset("<root>", asset); ctx.SetMainObject(asset); // Create subasset for each action. for (var i = 0; i < sets.Length; ++i) { var set = sets[i]; var haveSetName = !string.IsNullOrEmpty(set.name); foreach (var action in set.actions) { var actionObject = ScriptableObject.CreateInstance <InputActionReference>(); actionObject.m_Asset = asset; actionObject.m_SetName = set.name; actionObject.m_ActionName = action.name; var objectName = action.name; if (haveSetName) { objectName = string.Format("{0}/{1}", set.name, action.name); } actionObject.name = objectName; ctx.AddObjectToAsset(objectName, actionObject); } } // 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 = Path.GetFileNameWithoutExtension(ctx.assetPath) }; if (InputActionCodeGenerator.GenerateWrapperCode(wrapperFilePath, sets, options)) { // Inform database that we modified a source asset *during* import. AssetDatabase.ImportAsset(wrapperFilePath); } } }
/// <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 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) { 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 (var abcStream = new AlembicStream(go, streamDescriptor)) { abcStream.AbcLoad(true, true); abcStream.GetTimeRange(ref abcStartTime, ref abcEndTime); if (firstImport) { startTime = abcStartTime; endTime = abcEndTime; } streamDescriptor.abcStartTime = abcStartTime; streamDescriptor.abcEndTime = abcEndTime; var streamPlayer = go.AddComponent <AlembicStreamPlayer>(); streamPlayer.StreamDescriptor = streamDescriptor; streamPlayer.StartTime = StartTime; streamPlayer.EndTime = 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); } firstImport = false; }
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) { var item = LoadItemFromFile(ctx.assetPath); var root = new GameObject(Path.GetFileNameWithoutExtension(ctx.assetPath)); ctx.AddObjectToAsset("root", root); ctx.SetMainObject(root); for (int a = 0; a < item.Arrangements.Count; a++) { var arrangement = item.Arrangements[a]; var diffuseTexture = LoadTexture( string.Format("{0}_Diffuse", arrangement.Id), arrangement.DiffuseTexture); var normalTexture = LoadTexture( string.Format("{0}_Normal", arrangement.Id), arrangement.NormalTexture); var gearstackTexture = LoadTexture( string.Format("{0}_Gearstack", arrangement.Id), arrangement.GearstackTexture); ctx.AddObjectToAsset(diffuseTexture.name, diffuseTexture); ctx.AddObjectToAsset(normalTexture.name, normalTexture); ctx.AddObjectToAsset(gearstackTexture.name, gearstackTexture); var material = new Material(Shader.Find("Standard 2-Sided")); material.name = string.Format("{0}_Material", arrangement.Id); material.SetTexture("_MainTex", diffuseTexture); material.SetTexture("_BumpMap", normalTexture); ctx.AddObjectToAsset(material.name, material); for (int b = 0; b < arrangement.Bobs.Count; b++) { var bob = arrangement.Bobs[b]; for (int p = 0; p < bob.Bits.Count; p++) { var bit = bob.Bits[p]; string name = string.Format("{0}_{1}", arrangement.Id, p); var indices = bob.Indices.Skip(bit.StartIndex) .Take(bit.EndIndex - bit.StartIndex).ToArray(); if (!bob.IsTriangleList) { indices = ConvertTriangleStripToTriangleList(indices); } // remove loose vertices int minIndex = indices.Min(); int maxIndex = indices.Max(); var vertices = bob.Vertices.Skip(minIndex) .Take(maxIndex - minIndex + 1).ToArray(); indices = indices.Select(i => i - minIndex).ToArray(); var obj = CreateMesh(name, vertices, indices); obj.transform.SetParent(root.transform); var mesh = obj.GetComponent <MeshFilter>().sharedMesh; ctx.AddObjectToAsset(mesh.name, mesh); obj.GetComponent <MeshRenderer>().sharedMaterial = material; } } } }
/// <summary> /// Import a .ftex file. /// </summary> /// <param name="ctx"></param> public override void OnImportAsset(AssetImportContext ctx) { #region Readers var filepathSansExtension = Path.GetDirectoryName(assetPath) + "\\" + Path.GetFileNameWithoutExtension(assetPath); List <BinaryReader> binaryReaders = new List <BinaryReader>(); binaryReaders.Add(new BinaryReader(new FileStream(assetPath, FileMode.Open))); for (int i = 1; i < 7; i++) { var file = filepathSansExtension + "." + i + ".ftexs"; if (!File.Exists(file)) { break; } var fileStream = new FileStream(file, FileMode.Open); binaryReaders.Add(new BinaryReader(fileStream)); } #endregion try { var readFunctions = (from reader in binaryReaders select new FoxLib.GrTexture.ReadFunctions(reader.ReadUInt16, reader.ReadUInt32, reader.ReadUInt64, reader.ReadByte, reader.ReadBytes, (numberOfBytes => SkipBytes(reader, numberOfBytes)), (bytePos => MoveStream(reader, bytePos)))).ToArray(); FoxLib.GrTexture.GrTexture grTexture = FoxLib.GrTexture.Read(readFunctions); var textureFormat = GrTextureUtils.GetTextureFormat(grTexture.PixelFormat, grTexture.Depth); var isLinear = GrTextureUtils.GetLinear(grTexture.TextureType); if (grTexture.TextureType == FoxLib.GrTexture.TextureType.Cube) { #region Cube var texture = new Cubemap(grTexture.Width, UnityEngine.Experimental.Rendering.GraphicsFormat.R8G8B8A8_SRGB, UnityEngine.Experimental.Rendering.TextureCreationFlags.MipChain); var textureData = DirectXTexHelper.Decompress(grTexture.Width, grTexture.Height, GrTextureUtils.GetDXGIFormat(grTexture.PixelFormat), grTexture.MipMapCount, grTexture.DDSData); for (int i = 0; i < textureData.Length; i++) { var faceData = textureData[i]; { var colours = new Color[faceData.Length / 4]; for (int j = 0; j < faceData.Length / 4; j++) { var data = faceData.Skip(j * 4).Take(4).ToArray(); float R = data[0]; float G = data[1]; float B = data[2]; float A = data[3]; float nrmR = R / 255.0f; float nrmG = G / 255.0f; float nrmB = B / 255.0f; float nrmA = A / 255.0f; colours[j] = new Color(nrmR, nrmG, nrmB, nrmA); } texture.SetPixels(colours, (CubemapFace)i); } } texture.Apply(true); ctx.AddObjectToAsset("ftex", texture); ctx.SetMainObject(texture); #endregion } else { if (grTexture.Depth == 1) { #region 2D var hasMipmaps = grTexture.MipMapCount > 1; var texture = new Texture2D(grTexture.Width, grTexture.Height, textureFormat, hasMipmaps, isLinear); if (hasMipmaps) { if (texture.mipmapCount > grTexture.MipMapCount) { var length = grTexture.DDSData.Length; IntPtr pixelBuffer = DirectXTexHelper.GenerateNecessaryMipMapsAndFlipImage(grTexture.Width, grTexture.Height, GrTextureUtils.GetDXGIFormat(grTexture.PixelFormat), grTexture.MipMapCount, grTexture.DDSData, ref length); texture.LoadRawTextureData(pixelBuffer, length); } else { texture.LoadRawTextureData(grTexture.DDSData); } } else { byte[] newPixelData = DirectXTexHelper.Flip2DImage(grTexture.Width, grTexture.Height, GrTextureUtils.GetDXGIFormat(grTexture.PixelFormat), grTexture.MipMapCount, grTexture.DDSData); texture.LoadRawTextureData(newPixelData); texture.Apply(); } ctx.AddObjectToAsset("ftex", texture, texture); ctx.SetMainObject(texture); #endregion } else { #region 3D var texture = GrTextureUtils.CreateTexture3D(grTexture.Width, grTexture.Height, grTexture.Depth, GrTextureUtils.GetTextureFormat(grTexture.PixelFormat, grTexture.Depth), grTexture.DDSData); ctx.AddObjectToAsset("ftex", texture); ctx.SetMainObject(texture); #endregion } } this.userData = "NrtFlag: " + grTexture.NrtFlag + ", TextureType: " + grTexture.TextureType + ", UnknownFlags: " + grTexture.UnknownFlags; } finally { foreach (var reader in binaryReaders) { reader.Close(); } } }
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(); kvp.Value.hideFlags = HideFlags.HideInHierarchy; ctx.AddObjectToAsset(kvp.Key.Name, kvp.Value); cache.surfaces[k] = kvp.Value; k++; } } catch (System.Exception e) { Debug.LogException(e); } }
public override void OnImportAsset(AssetImportContext ctx) { { var ext = Path.GetExtension(ctx.assetPath).ToLower(); if (ext == ".vox") { fileType = VoxelBase.FileType.vox; } else if (ext == ".qb") { fileType = VoxelBase.FileType.qb; } else { return; } } #region DefaultScale if (dataVersion == 0 && importScale == Vector3.one && AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(ctx.assetPath) == null) { var x = EditorPrefs.GetFloat("VoxelImporter_DefaultScaleX", 1f); var y = EditorPrefs.GetFloat("VoxelImporter_DefaultScaleY", 1f); var z = EditorPrefs.GetFloat("VoxelImporter_DefaultScaleZ", 1f); importScale = new Vector3(x, y, z); } #endregion Action <string> LogImportError = (log) => { #if UNITY_2018_1_OR_NEWER ctx.LogImportError(log); #else Debug.LogError(log); #endif }; Action <VoxelBase> SetBasicOptions = (voxelObject) => { voxelObject.legacyVoxImport = legacyVoxImport; voxelObject.importMode = importMode; voxelObject.importScale = importScale; voxelObject.importOffset = importOffset; voxelObject.combineFaces = combineFaces; voxelObject.ignoreCavity = ignoreCavity; voxelObject.shareSameFace = shareSameFace; voxelObject.removeUnusedPalettes = removeUnusedPalettes; voxelObject.voxelStructure = outputStructure ? ScriptableObject.CreateInstance <VoxelStructure>() : null; voxelObject.generateLightmapUVs = generateLightmapUVs; voxelObject.generateLightmapUVsAngleError = generateLightmapUVsAngleError; voxelObject.generateLightmapUVsAreaError = generateLightmapUVsAreaError; voxelObject.generateLightmapUVsHardAngle = generateLightmapUVsHardAngle; voxelObject.generateLightmapUVsPackMargin = generateLightmapUVsPackMargin; voxelObject.generateTangents = generateTangents; voxelObject.meshFaceVertexOffset = meshFaceVertexOffset; voxelObject.loadFromVoxelFile = loadFromVoxelFile; voxelObject.generateMipMaps = generateMipMaps; }; Action <VoxelBaseCore> Export = (core) => { if (export) { var fullPath = Application.dataPath + ctx.assetPath.Remove(0, "Assets".Length); fullPath = fullPath.Remove(fullPath.LastIndexOf('.')) + ".dae"; core.ExportDaeFile(fullPath, false); } }; var gameObject = new GameObject(Path.GetFileNameWithoutExtension(ctx.assetPath)); if (string.IsNullOrEmpty(gameObjectName)) { gameObjectName = gameObject.name; } if (meshMode == MeshMode.Combine) { #region Combine var voxelObject = gameObject.AddComponent <VoxelObject>(); SetBasicOptions(voxelObject); var objectCore = new VoxelObjectCore(voxelObject); try { if (!objectCore.Create(ctx.assetPath, null)) { LogImportError(string.Format("<color=green>[Voxel Importer]</color> ScriptedImporter error. file:{0}", ctx.assetPath)); DestroyImmediate(gameObject); return; } } catch { LogImportError(string.Format("<color=green>[Voxel Importer]</color> ScriptedImporter error. file:{0}", ctx.assetPath)); DestroyImmediate(gameObject); return; } #region Correspondence in Issue ID 947055 Correction in case before correction is applied foreach (var material in voxelObject.materials) { if (material != null) { material.hideFlags |= HideFlags.NotEditable; } } if (voxelObject.atlasTexture != null) { voxelObject.atlasTexture.hideFlags |= HideFlags.NotEditable; } if (voxelObject.mesh != null) { voxelObject.mesh.hideFlags |= HideFlags.NotEditable; } #endregion #region Material { materials = new Material[voxelObject.materialIndexes.Count]; materialNames = new string[voxelObject.materialIndexes.Count]; for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var index = voxelObject.materialIndexes[i]; var material = voxelObject.materials[index]; material.name = string.Format("mat{0}", index); materials[i] = material; materialNames[i] = material.name; } if (remappedMaterials != null) { remappedMaterials = remappedMaterials.Where(item => item.material != null && materialNames.Contains(item.name)).ToArray(); } } #endregion #region Collider switch (colliderType) { case ColliderType.Box: gameObject.AddComponent <BoxCollider>(); break; case ColliderType.Sphere: gameObject.AddComponent <SphereCollider>(); break; case ColliderType.Capsule: gameObject.AddComponent <CapsuleCollider>(); break; case ColliderType.Mesh: gameObject.AddComponent <MeshCollider>(); break; } #endregion Export(objectCore); #if UNITY_2017_3_OR_NEWER ctx.AddObjectToAsset(gameObjectName, gameObject); ctx.AddObjectToAsset(voxelObject.mesh.name = "mesh", voxelObject.mesh); { var list = new List <Material>(); for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var material = voxelObject.materials[voxelObject.materialIndexes[i]]; list.Add(material); if (remappedMaterials != null) { var index = ArrayUtility.FindIndex(remappedMaterials, (t) => { return(t.name == material.name); }); if (index >= 0) { list[i] = remappedMaterials[index].material; continue; } } ctx.AddObjectToAsset(material.name, material); } gameObject.GetComponent <MeshRenderer>().sharedMaterials = list.ToArray(); } ctx.AddObjectToAsset(voxelObject.atlasTexture.name = "tex", voxelObject.atlasTexture); if (voxelObject.voxelStructure != null) { ctx.AddObjectToAsset(voxelObject.voxelStructure.name = "structure", voxelObject.voxelStructure); } VoxelObject.DestroyImmediate(voxelObject); ctx.SetMainObject(gameObject); #else ctx.SetMainAsset(gameObjectName, gameObject); ctx.AddSubAsset(voxelObject.mesh.name = "mesh", voxelObject.mesh); for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var material = voxelObject.materials[voxelObject.materialIndexes[i]]; ctx.AddSubAsset(material.name, material); } ctx.AddSubAsset(voxelObject.atlasTexture.name = "tex", voxelObject.atlasTexture); if (voxelObject.voxelStructure != null) { ctx.AddSubAsset(voxelObject.voxelStructure.name = "structure", voxelObject.voxelStructure); } VoxelObject.DestroyImmediate(voxelObject); #endif #endregion } else if (meshMode == MeshMode.Individual) { #region Individual var voxelObject = gameObject.AddComponent <VoxelChunksObject>(); SetBasicOptions(voxelObject); { voxelObject.createContactChunkFaces = createContactChunkFaces; voxelObject.materialMode = materialMode; } var objectCore = new VoxelChunksObjectCore(voxelObject); { objectCore.chunkNameFormat = "{0}"; } try { if (!objectCore.Create(ctx.assetPath, null)) { LogImportError(string.Format("<color=green>[Voxel Importer]</color> ScriptedImporter error. file:{0}", ctx.assetPath)); DestroyImmediate(gameObject); return; } } catch { LogImportError(string.Format("<color=green>[Voxel Importer]</color> ScriptedImporter error. file:{0}", ctx.assetPath)); DestroyImmediate(gameObject); return; } #region Correspondence in Issue ID 947055 Correction in case before correction is applied if (voxelObject.materials != null) { foreach (var material in voxelObject.materials) { if (material != null) { material.hideFlags |= HideFlags.NotEditable; } } } if (voxelObject.atlasTexture != null) { voxelObject.atlasTexture.hideFlags |= HideFlags.NotEditable; } foreach (var chunk in voxelObject.chunks) { if (chunk.materials != null) { foreach (var material in chunk.materials) { if (material != null) { material.hideFlags |= HideFlags.NotEditable; } } } if (chunk.atlasTexture != null) { chunk.atlasTexture.hideFlags |= HideFlags.NotEditable; } if (chunk.mesh != null) { chunk.mesh.hideFlags |= HideFlags.NotEditable; } } #endregion #region Material { if (materialMode == VoxelChunksObject.MaterialMode.Combine) { materials = new Material[voxelObject.materialIndexes.Count]; materialNames = new string[voxelObject.materialIndexes.Count]; for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var index = voxelObject.materialIndexes[i]; var material = voxelObject.materials[index]; material.name = string.Format("mat{0}", index); materials[i] = material; materialNames[i] = material.name; } } else if (materialMode == VoxelChunksObject.MaterialMode.Individual) { List <Material> list = new List <Material>(); foreach (var chunk in voxelObject.chunks) { for (int i = 0; i < chunk.materialIndexes.Count; i++) { var index = chunk.materialIndexes[i]; var material = chunk.materials[index]; material.name = chunk.gameObject.name + string.Format("_mat{0}", index); if (!list.Contains(material)) { list.Add(material); } } } materials = list.ToArray(); materialNames = new string[list.Count]; for (int i = 0; i < list.Count; i++) { materialNames[i] = list[i].name; } } if (remappedMaterials != null) { remappedMaterials = remappedMaterials.Where(item => item.material != null && materialNames.Contains(item.name)).ToArray(); } } #endregion #region Collider foreach (var chunk in voxelObject.chunks) { switch (colliderType) { case ColliderType.Box: chunk.gameObject.AddComponent <BoxCollider>(); break; case ColliderType.Sphere: chunk.gameObject.AddComponent <SphereCollider>(); break; case ColliderType.Capsule: chunk.gameObject.AddComponent <CapsuleCollider>(); break; case ColliderType.Mesh: chunk.gameObject.AddComponent <MeshCollider>(); break; } } #endregion Export(objectCore); #if UNITY_2017_3_OR_NEWER ctx.AddObjectToAsset(gameObjectName, gameObject); foreach (var chunk in voxelObject.chunks) { ctx.AddObjectToAsset(chunk.mesh.name = chunk.gameObject.name + "_mesh", chunk.mesh); } { if (materialMode == VoxelChunksObject.MaterialMode.Combine) { var materials = new List <Material>(); for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var material = voxelObject.materials[voxelObject.materialIndexes[i]]; materials.Add(material); if (remappedMaterials != null) { var index = ArrayUtility.FindIndex(remappedMaterials, (t) => { return(t.name == material.name); }); if (index >= 0) { materials[i] = remappedMaterials[index].material; continue; } } ctx.AddObjectToAsset(material.name, material); } foreach (var chunk in voxelObject.chunks) { chunk.gameObject.GetComponent <MeshRenderer>().sharedMaterials = materials.ToArray(); } ctx.AddObjectToAsset(voxelObject.atlasTexture.name = "tex", voxelObject.atlasTexture); } else if (materialMode == VoxelChunksObject.MaterialMode.Individual) { foreach (var chunk in voxelObject.chunks) { var materials = new List <Material>(); for (int i = 0; i < chunk.materialIndexes.Count; i++) { var material = chunk.materials[chunk.materialIndexes[i]]; materials.Add(material); if (remappedMaterials != null) { var index = ArrayUtility.FindIndex(remappedMaterials, (t) => { return(t.name == material.name); }); if (index >= 0) { materials[i] = remappedMaterials[index].material; continue; } } ctx.AddObjectToAsset(material.name, material); } chunk.gameObject.GetComponent <MeshRenderer>().sharedMaterials = materials.ToArray(); ctx.AddObjectToAsset(chunk.atlasTexture.name = chunk.gameObject.name + "_tex", chunk.atlasTexture); } } } if (voxelObject.voxelStructure != null) { ctx.AddObjectToAsset(voxelObject.voxelStructure.name = "structure", voxelObject.voxelStructure); } foreach (var chunk in voxelObject.chunks) { VoxelChunksObjectChunk.DestroyImmediate(chunk.GetComponent <VoxelChunksObjectChunk>()); } VoxelObject.DestroyImmediate(voxelObject); ctx.SetMainObject(gameObject); #else ctx.SetMainAsset(gameObjectName, gameObject); foreach (var chunk in voxelObject.chunks) { ctx.AddSubAsset(chunk.mesh.name = chunk.gameObject.name + "_mesh", chunk.mesh); } { if (materialMode == VoxelChunksObject.MaterialMode.Combine) { var materials = new List <Material>(); for (int i = 0; i < voxelObject.materialIndexes.Count; i++) { var material = voxelObject.materials[voxelObject.materialIndexes[i]]; materials.Add(material); if (remappedMaterials != null) { var index = ArrayUtility.FindIndex(remappedMaterials, (t) => { return(t.name == material.name); }); if (index >= 0) { materials[i] = remappedMaterials[index].material; continue; } } ctx.AddSubAsset(material.name, material); } foreach (var chunk in voxelObject.chunks) { chunk.gameObject.GetComponent <MeshRenderer>().sharedMaterials = materials.ToArray(); } ctx.AddSubAsset(voxelObject.atlasTexture.name = "tex", voxelObject.atlasTexture); } else if (materialMode == VoxelChunksObject.MaterialMode.Individual) { foreach (var chunk in voxelObject.chunks) { var materials = new List <Material>(); for (int i = 0; i < chunk.materialIndexes.Count; i++) { var material = chunk.materials[chunk.materialIndexes[i]]; materials.Add(material); if (remappedMaterials != null) { var index = ArrayUtility.FindIndex(remappedMaterials, (t) => { return(t.name == material.name); }); if (index >= 0) { materials[i] = remappedMaterials[index].material; continue; } } ctx.AddSubAsset(material.name, material); } chunk.gameObject.GetComponent <MeshRenderer>().sharedMaterials = materials.ToArray(); ctx.AddSubAsset(chunk.atlasTexture.name = chunk.gameObject.name + "_tex", chunk.atlasTexture); } } } if (voxelObject.voxelStructure != null) { ctx.AddSubAsset(voxelObject.voxelStructure.name = "structure", voxelObject.voxelStructure); } foreach (var chunk in voxelObject.chunks) { VoxelChunksObjectChunk.DestroyImmediate(chunk.GetComponent <VoxelChunksObjectChunk>()); } VoxelObject.DestroyImmediate(voxelObject); #endif #endregion } dataVersion = EditorDataVersion; }
public override void OnImportAsset(AssetImportContext ctx) { Debug.Log("OnImportAsset to " + ctx.assetPath); try { // Create model VrmLib.Model model = CreateGlbModel(ctx.assetPath); Debug.Log($"ModelLoader.Load: {model}"); // Build Unity Model var builder = new UniVRM10.EditorUnityBuilder(); var assets = builder.ToUnityAsset(model, assetPath, this); // Texture var externalTextures = this.GetExternalUnityObjects <UnityEngine.Texture2D>(); foreach (var texture in assets.Textures) { if (texture == null) { continue; } if (externalTextures.ContainsValue(texture)) { } else { ctx.AddObjectToAsset(texture.name, texture); } } // Material var externalMaterials = this.GetExternalUnityObjects <UnityEngine.Material>(); foreach (var material in assets.Materials) { if (material == null) { continue; } if (externalMaterials.ContainsValue(material)) { } else { ctx.AddObjectToAsset(material.name, material); } } // Mesh foreach (var mesh in assets.Meshes) { ctx.AddObjectToAsset(mesh.name, mesh); } // Root ctx.AddObjectToAsset(assets.Root.name, assets.Root); ctx.SetMainObject(assets.Root); } catch (System.Exception ex) { Debug.LogError(ex); } }
public override void OnImportAsset(AssetImportContext ctx) { var path = ctx.assetPath; var name = Path.GetFileNameWithoutExtension(path); var text = File.ReadAllText(path); var lines = text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var definitionFile = ScriptableObject.CreateInstance <OdinAttributeDefinitionFile>(); definitionFile.name = name; ctx.AddObjectToAsset(name, definitionFile); ctx.SetMainObject(definitionFile); string globalCondition = string.Empty; Type currentType = null; OdinAttributeDefinition currentDefinition = null; for (int lineIndex = 0; lineIndex < lines.Length; ++lineIndex) { // Strip leading spaces string line = lines[lineIndex].Trim(); if (line[0] == '?') // If the first character is a ? then this is a condition { var substring = line.Substring(1); if (currentDefinition == null) { if (string.IsNullOrEmpty(globalCondition)) { globalCondition = substring; } else { Debug.LogError($"Only a single global condition per OAD. '{substring}' ignored."); } } else { if (string.IsNullOrEmpty(globalCondition) && string.IsNullOrEmpty(currentDefinition.requiredCondition)) { currentDefinition.requiredCondition = substring; } else { if (!string.IsNullOrEmpty(globalCondition)) { Debug.LogError($"Global condition is already set. Local '{substring}' ignored."); } if (!string.IsNullOrEmpty(currentDefinition.requiredCondition)) { Debug.LogError($"Local condition is already set. '{substring}' ignored."); } } } } else if (line[0] == '%') // If the first character is a % sign then it's a type { var substring = line.Substring(1); var type = OdinAttributeDefinition.GetTypeFromString(substring); if (type == null) { Debug.LogError($"{substring} could not be converted to a type."); break; } currentType = type; currentDefinition = ScriptableObject.CreateInstance <OdinAttributeDefinition>(); currentDefinition.name = $"{type.FullName}_OAD"; currentDefinition.type = type; ctx.AddObjectToAsset(currentDefinition.name, currentDefinition); definitionFile.definitions.Add(currentDefinition); } else if (line[0] == '+') { var substring = line.Substring(1); if (currentDefinition == null) { Debug.LogError($"{substring}: no active type."); break; } currentDefinition.addedSelfAttributeStrings.Add(substring); } else if (line[0] == '-') { var substring = line.Substring(1); if (currentDefinition == null) { Debug.LogError($"{substring}: no active type."); break; } if (line.Length >= 2 && line[1] == '-') // -- Means remove all attributes from this type { currentDefinition.removeAllSelfAttributes = true; if (line.Length >= 3 && line[2] == '-') // --- Means remove all attributes from this type and all it's members { currentDefinition.removeAllMemberAttributes = true; } } else { currentDefinition.removedSelfAttributeStrings.Add(substring); } } // TODO: Add '-' to allow removing attributes else if (line[0] == '*') // *memberName+new LabelWidthAttribute { var substring = line.Substring(1); if (currentDefinition == null) { Debug.LogError($"{substring}: no active type."); break; } int plusIndex = substring.IndexOf('+'); int minusIndex = substring.IndexOf('-'); // Definitely not valid if (plusIndex == -1 && minusIndex == -1) { Debug.LogError($"{substring}: No member action found (+,-)."); break; } if (plusIndex >= 0) { string memberSubstring = substring.Substring(0, plusIndex); if (plusIndex + 1 >= substring.Length) { Debug.LogError($"{substring}: No attribute found"); break; } string attributeSubstring = substring.Substring(plusIndex + 1); List <string> attributes = null; if (!currentDefinition.addedMemberAttributeStrings.TryGetValue(memberSubstring, out attributes)) { currentDefinition.addedMemberAttributeStrings[memberSubstring] = attributes = new List <string>(); } attributes.Add(attributeSubstring); } else { string memberSubstring = substring.Substring(0, minusIndex); if (minusIndex + 1 >= substring.Length) { Debug.LogError($"{substring}: No attribute found"); break; } string attributeSubstring = substring.Substring(minusIndex + 1); if (attributeSubstring.Trim() == "-") // Found '--', remove all attributes from member name { currentDefinition.removeMemberAttributesAll.Add(memberSubstring); } else { List <string> attributes = null; if (!currentDefinition.removedMemberAttributeStrings.TryGetValue(memberSubstring, out attributes)) { currentDefinition.removedMemberAttributeStrings[memberSubstring] = attributes = new List <string>(); } attributes.Add(attributeSubstring); } } } else if (line[0] == ';') { continue; } } foreach (var definition in definitionFile.definitions) { if (string.IsNullOrEmpty(definition.requiredCondition)) { definition.requiredCondition = globalCondition; } } }