diff --git a/Source/abci/Importer/AlembicImporter.cpp b/Source/abci/Importer/AlembicImporter.cpp index 2f5eb2693..463af7d2c 100644 --- a/Source/abci/Importer/AlembicImporter.cpp +++ b/Source/abci/Importer/AlembicImporter.cpp @@ -254,6 +254,13 @@ abciAPI void aiPolyMeshFillVertexBuffer(aiPolyMeshSample* sample, aiPolyMeshData sample->fillVertexBuffer(vbs, ibs); } +abciAPI char* aiPolyMeshReadPropertyName(aiPolyMeshSample* sample, int idx) +{ + if (sample) + return sample->readPropertyName(idx); + return "\0"; +} + abciAPI void aiSubDGetSummary(aiSubD* schema, aiMeshSummary* dst) { if (schema) diff --git a/Source/abci/Importer/AlembicImporter.h b/Source/abci/Importer/AlembicImporter.h index 2bfa5e673..e1fbb919d 100644 --- a/Source/abci/Importer/AlembicImporter.h +++ b/Source/abci/Importer/AlembicImporter.h @@ -16,6 +16,7 @@ class aiPolyMeshSample; // : aiSample class aiSubDSample; // : aiSample class aiPointsSample; // : aiSample class aiCurves; +struct FixedString128; #else // force make castable using aiSchema = void; @@ -148,6 +149,7 @@ struct aiMeshSummary bool constant_uv1 = false; bool constant_rgba = false; bool constant_rgb = false; + int numV2FVertexProperties = 0; }; struct aiMeshSampleSummary @@ -189,6 +191,8 @@ struct aiPolyMeshData abcV2 *uv1 = nullptr; abcV4 *rgba = nullptr; abcV4 *rgb = nullptr; + abcV2 **v2fParams = nullptr; + // FixedString128* v2fParamNames = nullptr; int *indices = nullptr; int vertex_count = 0; @@ -196,6 +200,8 @@ struct aiPolyMeshData abcV3 center = { 0.0f, 0.0f, 0.0f }; abcV3 extents = { 0.0f, 0.0f, 0.0f }; + + // need the data for c# }; struct aiSubmeshData @@ -322,6 +328,7 @@ abciAPI void aiPolyMeshGetSampleSummary(aiPolyMeshSample* sample, aiM abciAPI void aiPolyMeshGetSplitSummaries(aiPolyMeshSample* sample, aiMeshSplitSummary *dst); abciAPI void aiPolyMeshGetSubmeshSummaries(aiPolyMeshSample* sample, aiSubmeshSummary* dst); abciAPI void aiPolyMeshFillVertexBuffer(aiPolyMeshSample* sample, aiPolyMeshData* vbs, aiSubmeshData* ibs); +abciAPI char* aiPolyMeshReadPropertyName(aiPolyMeshSample* sample, int idx); abciAPI void aiSubDGetSummary(aiSubD* schema, aiMeshSummary* dst); abciAPI void aiSubDGetSampleSummary(aiSubDSample* sample, aiMeshSampleSummary* dst); diff --git a/Source/abci/Importer/aiMeshSchema.cpp b/Source/abci/Importer/aiMeshSchema.cpp index d0d386490..a5d874bd8 100644 --- a/Source/abci/Importer/aiMeshSchema.cpp +++ b/Source/abci/Importer/aiMeshSchema.cpp @@ -7,6 +7,8 @@ #include "aiMeshSchema.h" #include "aiSubD.h" +constexpr size_t FixedString128::MaxLength; + aiMeshTopology::aiMeshTopology() { } diff --git a/Source/abci/Importer/aiMeshSchema.h b/Source/abci/Importer/aiMeshSchema.h index 5fa830d25..3e71f81fa 100644 --- a/Source/abci/Importer/aiMeshSchema.h +++ b/Source/abci/Importer/aiMeshSchema.h @@ -1,4 +1,5 @@ #pragma once +#include #include "aiMeshOps.h" namespace @@ -13,6 +14,15 @@ namespace } } } + +struct FixedString128 +{ + static constexpr size_t MaxLength = 126; + unsigned short Length; + char String[MaxLength]; +}; + + using abcFaceSetSchemas = std::vector; using abcFaceSetSamples = std::vector; @@ -64,6 +74,8 @@ class aiMeshTopology RawVector m_remap_rgba; RawVector m_remap_rgb; + std::vector > m_remap_m_IV2fGeomParam; + int m_vertex_count = 0; int m_index_count = 0; // triangulated }; @@ -84,6 +96,7 @@ class aiMeshSample : public aiSample void fillSplitVertices(int split_index, aiPolyMeshData &data) const; void fillSubmeshIndices(int submesh_index, aiSubmeshData &data) const; void fillVertexBuffer(aiPolyMeshData* vbs, aiSubmeshData* ibs); + char* readPropertyName(int index); public: Abc::P3fArraySamplePtr m_points_sp, m_points_sp2; @@ -95,6 +108,10 @@ class aiMeshSample : public aiSample AbcGeom::IC3fGeomParam::Sample m_rgb_sp, m_rgb_sp2; Abc::Box3d m_bounds; + std::vector m_IV2fGeomParam_sp; + std::vector m_IV2fGeomParamName; + std::vector > m_IV2fGeomParam; + IArray m_points_ref; IArray m_velocities_ref; IArray m_uv0_ref, m_uv1_ref; @@ -112,6 +129,8 @@ class aiMeshSample : public aiSample RawVector m_rgba, m_rgba2, m_rgba_int; RawVector m_rgb, m_rgb2, m_rgb_int; + //// props + TopologyPtr m_topology; bool m_topology_changed = false; @@ -147,13 +166,15 @@ class aiMeshSchema : public aiTSchema protected: virtual AbcGeom::IN3fGeomParam readNormalsParam(); aiMeshSummaryInternal m_summary; - AbcGeom::IV2fGeomParam m_uv1_param; + AbcGeom::IV2fGeomParam m_uv1_param; // obsolete AbcGeom::IC4fGeomParam m_rgba_param; AbcGeom::IC3fGeomParam m_rgb_param; TopologyPtr m_shared_topology; abcFaceSetSchemas m_facesets; bool m_varying_topology = false; + + std::vector m_IV2fGeomParam; }; template @@ -190,7 +211,12 @@ inline aiMeshSchema::aiMeshSchema(aiObject * parent, const abcObject & abc // uv if (AbcGeom::IV2fGeomParam::matches(header)) { - m_uv1_param = AbcGeom::IV2fGeomParam(geom_params, header.getName()); + m_uv1_param = AbcGeom::IV2fGeomParam(geom_params, header.getName()); // obsolete + } + + if (AbcGeom::IV2fGeomParam::matches(header)) + { + m_IV2fGeomParam.push_back(AbcGeom::IV2fGeomParam(geom_params, header.getName())); // obsolete } } } @@ -224,6 +250,18 @@ static inline void copy_or_clear(T* dst, const IArray& src, const MeshRefiner } } +template +static inline void copy_or_clear(T* dst, const RawVector& src, const MeshRefiner::Split& split) +{ + if (dst) + { + if (!src.empty()) + memcpy(dst, src.data() + split.vertex_offset, sizeof(T) * split.vertex_count); + else + memset(dst, 0, split.vertex_count * sizeof(T)); + } +} + template static inline void copy_or_clear_3_to_4(T1* dst, const IArray& src, const MeshRefiner::Split& split) { @@ -422,6 +460,8 @@ void aiMeshSchema::updateSummary() if (summary.has_rgb_prop && !summary.constant_rgb) summary.interpolate_rgb = true; } + + summary.numV2FVertexProperties = m_IV2fGeomParam.size(); } template @@ -539,6 +579,25 @@ void aiMeshSchema::readSampleBody(U& sample, uint64_t idx) } } + if (sample.m_IV2fGeomParam_sp.size() != m_IV2fGeomParam.size()) + { + sample.m_IV2fGeomParam_sp = std::vector(m_IV2fGeomParam.size()); + } + + if (sample.m_IV2fGeomParamName.size() != m_IV2fGeomParam.size()) + { + sample.m_IV2fGeomParamName = std::vector(m_IV2fGeomParam.size()); + } + + for (int i = 0; i < m_IV2fGeomParam.size(); ++i) + { + auto param = m_IV2fGeomParam[i]; + // sample.m_IV2fGeomParamName[i]. = param.getName(); + strncpy(sample.m_IV2fGeomParamName[i].String, param.getName().c_str(), std::min(FixedString128::MaxLength, param.getName().size())); + param.getIndexed(sample.m_IV2fGeomParam_sp[i], ss); + /// deal with interpolation + } + auto bounds_param = this->m_schema.getSelfBoundsProperty(); if (bounds_param && bounds_param.getNumSamples() > 0) bounds_param.get(sample.m_bounds, ss); @@ -562,7 +621,7 @@ void aiMeshSchema::cookSampleBody(U& sample) { onTopologyChange(sample); } - else if (this->m_sample_index_changed) + else if (this->m_sample_index_changed) // Not happening in solutions { onTopologyDetermined(); @@ -966,6 +1025,42 @@ void aiMeshSchema::onTopologyChange(U& sample) } + /// Arbitrary V2f attributes + if (sample.m_IV2fGeomParam.size() != sample.m_IV2fGeomParam_sp.size()) + { + sample.m_IV2fGeomParam = std::vector >(sample.m_IV2fGeomParam_sp.size()); + } + + if (topology.m_remap_m_IV2fGeomParam.size() != sample.m_IV2fGeomParam_sp.size()) + { + topology.m_remap_m_IV2fGeomParam = std::vector >(sample.m_IV2fGeomParam_sp.size()); + } + + for (int i = 0; i < sample.m_IV2fGeomParam_sp.size(); ++i) + { + auto sp = sample.m_IV2fGeomParam_sp[i]; + if (sp.valid()) + { + IArray src{sp.getVals()->get(), sp.getVals()->size()}; + auto &dst = sample.m_IV2fGeomParam[i]; + + if (sp.isIndexed() && sp.getIndices()->size() == refiner.indices.size()) + { + IArray indices{(int *)sp.getIndices()->get(), sp.getIndices()->size()}; + refiner.template addIndexedAttribute(src, indices, dst, topology.m_remap_m_IV2fGeomParam[i]); + } + else if (src.size() == refiner.indices.size()) + { + refiner.template addExpandedAttribute(src, dst, topology.m_remap_m_IV2fGeomParam[i]); + } + else if (src.size() == refiner.points.size()) + { + refiner.template addIndexedAttribute(src, refiner.indices, dst, topology.m_remap_m_IV2fGeomParam[i]); + } + } + } + /// + refiner.refine(); refiner.retopology(config.swap_face_winding); @@ -1180,6 +1275,18 @@ void aiMeshSample::fillSplitVertices(int split_index, aiPolyMeshData &data) c copy_or_clear(data.uv1, m_uv1_ref, split); copy_or_clear((abcC4*)data.rgba, m_rgba_ref, split); copy_or_clear_3_to_4((abcC4*)data.rgb, m_rgb_ref, split); + + if (data.v2fParams != nullptr) + { + for (int i = 0; i < m_IV2fGeomParam.size(); ++i) + { + abcV2 *dst = data.v2fParams[i]; + copy_or_clear(dst, m_IV2fGeomParam[i], split); + + // data.v2fParamNames[i] = m_IV2fGeomParamName[i]; + // strncpy(data.v2fParamNames[i].String, m_IV2fGeomParamName[i].String, FixedString128::MaxLength); + } + } } template @@ -1203,3 +1310,9 @@ void aiMeshSample::fillVertexBuffer(aiPolyMeshData * vbs, aiSubmeshData * ibs for (int smi = 0; smi < (int)refiner.submeshes.size(); ++smi) fillSubmeshIndices(smi, ibs[smi]); } + +template +char* aiMeshSample::readPropertyName(int idx) +{ + return &(m_IV2fGeomParamName[idx].String[0]); +} diff --git a/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs b/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs new file mode 100644 index 000000000..d9351190a --- /dev/null +++ b/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs @@ -0,0 +1,56 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Formats.Alembic.Importer; + +[ExecuteInEditMode] +public class AlembicMeshCustomDataMapper : MonoBehaviour +{ + AlembicCustomData customData; + + Mesh mesh; + // Start is called before the first frame update + + // Update is called once per frame + void LateUpdate() + { + customData = GetComponent(); + var mf = GetComponent(); + if (mf != null) + { + mesh = mf.sharedMesh; + } + + if (customData == null || mesh == null) + { + return; + } + + // Make sure the Alembic is up to date; + var asp = GetComponentInParent(); + asp.UpdateImmediately(asp.CurrentTime); + + foreach (var attribute in customData.VertexAttributes) + { + + if (attribute.Name == "furUVs") + { + mesh.SetUVs(1, attribute.Data); + } + else if (attribute.Name == "rigUVs") + { + mesh.SetUVs(3, attribute.Data); + } + else if (attribute.Name == "transferUVs") + { + mesh.SetUVs(2, attribute.Data); + } + else + { + Debug.LogWarning($"Unhandled Attribute: {attribute.Name.Value}"); + } + + + } + } +} diff --git a/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs.meta b/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs.meta new file mode 100644 index 000000000..b5e2071fd --- /dev/null +++ b/TestProjects/AlembicImporter/Assets/AlembicMeshCustomDataMapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e71c42918b3e4a5c88636e40b1f4c56 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.formats.alembic/CHANGELOG.md b/com.unity.formats.alembic/CHANGELOG.md index d83cc9f76..8bf80e89d 100644 --- a/com.unity.formats.alembic/CHANGELOG.md +++ b/com.unity.formats.alembic/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.4.0-pre.1] - 2022-12-05 +### Added +- Added support for custom Vector2 Mesh vertex attributes. +### Changed +### Fixed + ## [2.3.1] - 2022-12-06 ### Added ### Changed diff --git a/com.unity.formats.alembic/Editor/Importer/AlembicCustomDataEditor.cs b/com.unity.formats.alembic/Editor/Importer/AlembicCustomDataEditor.cs index 96c1aef28..c23721fcd 100644 --- a/com.unity.formats.alembic/Editor/Importer/AlembicCustomDataEditor.cs +++ b/com.unity.formats.alembic/Editor/Importer/AlembicCustomDataEditor.cs @@ -1,3 +1,4 @@ +using Unity.Collections; using UnityEngine.Formats.Alembic.Importer; namespace UnityEditor.Formats.Alembic.Importer @@ -5,11 +6,24 @@ namespace UnityEditor.Formats.Alembic.Importer [CustomEditor(typeof(AlembicCustomData))] class AlembicCustomDataEditor : Editor { + bool v2fParams; public override void OnInspectorGUI() { using (new EditorGUI.DisabledScope(true)) { base.OnInspectorGUI(); + v2fParams = EditorGUILayout.Foldout(v2fParams, "VertexParams"); + if (v2fParams) + { + using (new EditorGUI.IndentLevelScope()) + { + var customData = target as AlembicCustomData; + foreach (var v2f in customData.VertexAttributes) + { + EditorGUILayout.LabelField(v2f.Name.Value); + } + } + } } } } diff --git a/com.unity.formats.alembic/Editor/Unity.Formats.Alembic.Editor.asmdef b/com.unity.formats.alembic/Editor/Unity.Formats.Alembic.Editor.asmdef index e1448a58d..2bd769578 100644 --- a/com.unity.formats.alembic/Editor/Unity.Formats.Alembic.Editor.asmdef +++ b/com.unity.formats.alembic/Editor/Unity.Formats.Alembic.Editor.asmdef @@ -5,7 +5,8 @@ "Unity.Formats.Alembic.Runtime", "Unity.Timeline", "Unity.Recorder.Editor", - "Unity.Timeline.Editor" + "Unity.Timeline.Editor", + "Unity.Collections" ], "includePlatforms": [ "Editor" @@ -29,4 +30,4 @@ } ], "noEngineReferences": false -} +} \ No newline at end of file diff --git a/com.unity.formats.alembic/Runtime/Scripts/Exporter/AbcAPI.cs b/com.unity.formats.alembic/Runtime/Scripts/Exporter/AbcAPI.cs index b56b1006d..d387508aa 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Exporter/AbcAPI.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Exporter/AbcAPI.cs @@ -411,6 +411,8 @@ static class NativeMethods [DllImport(Abci.Lib)] public static extern void aiPolyMeshGetSubmeshSummaries(IntPtr sample, IntPtr dst); [DllImport(Abci.Lib)] public static extern void aiPolyMeshFillVertexBuffer(IntPtr sample, IntPtr vbs, IntPtr ibs); + [DllImport(Abci.Lib)] public static extern unsafe char* aiPolyMeshReadPropertyName(IntPtr sample, int idx); + [DllImport(Abci.Lib)] public static extern void aiPointsGetSampleSummary(IntPtr sample, ref aiPointsSampleSummary dst); [DllImport(Abci.Lib)] public static extern void aiPointsFillData(IntPtr sample, IntPtr dst); diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs index f98350f04..99d7a802a 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/AbcAPI.cs @@ -158,6 +158,7 @@ struct aiMeshSummary public Bool constantUV1 { get; set; } public Bool constantRgba { get; set; } public Bool constantRgb { get; set; } + public int numV2FVertexProperties { get; set; } } [StructLayout(LayoutKind.Sequential)] @@ -202,6 +203,8 @@ unsafe struct aiPolyMeshData public void* uv1; public void* rgba; public void* rgb; + public void* v2fProps; + // public void* v2fPropsNames; public IntPtr indices; @@ -551,6 +554,15 @@ internal void FillVertexBuffer(NativeArray vbs, NativeArray uv1; public NativeArray rgba; public NativeArray rgb; + public UnsafeList> v2fParams; public Mesh mesh; public GameObject host; @@ -61,6 +62,18 @@ public void Dispose() uv1.DisposeIfPossible(); rgba.DisposeIfPossible(); rgb.DisposeIfPossible(); + + if (v2fParams.IsCreated) + { + foreach (var t in v2fParams) + { + var v2FParam = t; + v2FParam.DisposeIfPossible(); + } + + v2fParams.Dispose(); + } + if (mesh != null && (mesh.hideFlags & HideFlags.DontSave) != 0) { DestroyUnityObject(mesh); @@ -255,6 +268,39 @@ public override unsafe void AbcSyncDataBegin() } vertexData.rgb = split.rgb.GetPointer(); + if (m_summary.numV2FVertexProperties > 0 && topologyChanged) + { + if (!split.v2fParams.IsCreated) + { + split.v2fParams = + new UnsafeList>(m_summary.numV2FVertexProperties, + Allocator.Persistent); + } + + var prevSize = split.v2fParams.Length; + split.v2fParams.Resize(m_summary.numV2FVertexProperties); + for (var i = prevSize; i < split.v2fParams.Length; ++i) + { + split.v2fParams[i] = new NativeArray(0, Allocator.Persistent); + } + + + using (var v2fs = new NativeArray(m_summary.numV2FVertexProperties, Allocator.Temp)) + { + for (var i = 0; i < m_summary.numV2FVertexProperties; ++i) + { + var arr = split.v2fParams[i]; + arr.ResizeIfNeeded(vertexCount); + var nativeArray = v2fs; + nativeArray[i] = new IntPtr(arr.GetPointer()); + split.v2fParams[i] = arr; + } + + vertexData.v2fProps = v2fs.GetUnsafePtr(); + } + // vertexData.v2fPropsNames = split.v2fParamsNames.GetUnsafePtr(); + } + m_splitData[spi] = vertexData; } @@ -409,8 +455,8 @@ public override void AbcSyncDataEnd() split.mesh.SetTangents(split.tangents); if (split.uv0.Length > 0) split.mesh.SetUVs(0, split.uv0); - if (split.uv1.Length > 0) - split.mesh.SetUVs(1, split.uv1); + /* if (split.uv1.Length > 0) + split.mesh.SetUVs(1, split.uv1);*/ if (split.velocities.Length > 0) { m_PostProcessJobs[s].Complete(); @@ -423,6 +469,19 @@ public override void AbcSyncDataEnd() else if (split.rgb.Length > 0) split.mesh.SetColors(split.rgb); + if (split.v2fParams.Length > 0) + { + var customData = split.host.GetOrAddComponent(); + customData.ClearCustomAttributes(); + for (var i = 0; i < split.v2fParams.Length; ++i) + { + var name = m_abcSchema.sample.PolyMeshReadPropertyName(i); + var d = split.v2fParams[i]; + customData.VertexAttributes.Add( + new AlembicCustomData.V2FAttribute(name, d)); + } + } + // update the bounds var data = m_splitData[s]; split.mesh.bounds = new Bounds(data.center, data.extents); diff --git a/com.unity.formats.alembic/Runtime/Scripts/Importer/Behaviours/AlembicCustomData.cs b/com.unity.formats.alembic/Runtime/Scripts/Importer/Behaviours/AlembicCustomData.cs index 0f1a1d619..2b5477c44 100644 --- a/com.unity.formats.alembic/Runtime/Scripts/Importer/Behaviours/AlembicCustomData.cs +++ b/com.unity.formats.alembic/Runtime/Scripts/Importer/Behaviours/AlembicCustomData.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using Unity.Collections; namespace UnityEngine.Formats.Alembic.Importer { @@ -15,6 +17,37 @@ public class AlembicCustomData : MonoBehaviour /// public List FaceSetNames => faceSetNames; + public struct V2FAttribute + { + public FixedString128Bytes Name; + public NativeArray Data; + + public V2FAttribute(FixedString128Bytes name, NativeArray data) + { + Name = name; + Data = new NativeArray(data.Length, Allocator.Persistent); + Data.CopyFrom(data); + } + } + + public List VertexAttributes = new(); + + void OnDisable() + { + ClearCustomAttributes(); + } + + internal void ClearCustomAttributes() + { + foreach (var attribute in VertexAttributes) + { + var v2FAttribute = attribute; + v2FAttribute.Data.DisposeIfPossible(); + } + + VertexAttributes.Clear(); + } + internal void SetFacesetNames(List names) { faceSetNames = names; diff --git a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api index b03eda716..2268f5925 100644 --- a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api +++ b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.api @@ -37,8 +37,15 @@ namespace UnityEngine.Formats.Alembic.Importer public class AlembicCustomData : UnityEngine.MonoBehaviour { + public System.Collections.Generic.List VertexAttributes; public System.Collections.Generic.List FaceSetNames { get; } public AlembicCustomData() {} + public struct V2FAttribute + { + public Unity.Collections.NativeArray Data; + public Unity.Collections.FixedString128Bytes Name; + public V2FAttribute(Unity.Collections.FixedString128Bytes name, Unity.Collections.NativeArray data) {} + } } [UnityEngine.ExecuteInEditMode] public class AlembicPointsCloud : UnityEngine.MonoBehaviour diff --git a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.asmdef b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.asmdef index fa057d1d6..8dde43781 100644 --- a/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.asmdef +++ b/com.unity.formats.alembic/Runtime/Unity.Formats.Alembic.Runtime.asmdef @@ -3,7 +3,8 @@ "rootNamespace": "", "references": [ "Unity.Timeline", - "Unity.Burst" + "Unity.Burst", + "Unity.Collections" ], "includePlatforms": [ "Editor", diff --git a/com.unity.formats.alembic/package.json b/com.unity.formats.alembic/package.json index 0c39f6fdf..213c2d419 100644 --- a/com.unity.formats.alembic/package.json +++ b/com.unity.formats.alembic/package.json @@ -2,7 +2,8 @@ "dependencies": { "com.unity.timeline": "1.0.0", "com.unity.modules.unityanalytics": "1.0.0", - "com.unity.modules.cloth": "1.0.0" + "com.unity.modules.cloth": "1.0.0", + "com.unity.collections" : "1.0.0" }, "description": "Import and export Alembic files (.abc), record and stream animations in the Alembic format directly in Unity.\nNOTE: Supported build platforms: only Windows 64, MacOS X, Linux 64, and Stadia.\n\nThe Alembic format is commonly used in animation to transfer facial, cloth, and other simulation between applications in the form of baked data.", "displayName": "Alembic", @@ -15,6 +16,6 @@ "simulation" ], "name": "com.unity.formats.alembic", - "unity": "2019.4", - "version": "2.3.1" + "unity": "2023.1", + "version": "2.4.0-pre.1" }