diff --git a/MonoGame.Framework.Content.Pipeline/Graphics/MeshHelper.cs b/MonoGame.Framework.Content.Pipeline/Graphics/MeshHelper.cs
index a653be6a1d6..78b252ef9d8 100644
--- a/MonoGame.Framework.Content.Pipeline/Graphics/MeshHelper.cs
+++ b/MonoGame.Framework.Content.Pipeline/Graphics/MeshHelper.cs
@@ -1,6 +1,11 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using Microsoft.Xna.Framework.Content.Pipeline.Processors;
+using Microsoft.Xna.Framework.Graphics;
namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics
{
@@ -361,10 +366,64 @@ public static BoneContent FindSkeleton(NodeContent node)
return root;
}
- // We didn't find any bones!
+ // We didn't find any bones!
return null;
}
+ ///
+ /// Builds a set of BoneContent nodes and injects them into a Model which
+ /// contains Mesh based Animations but has Zero BoneContent nodes.
+ ///
+ /// The base note on which to build the new BoneContent
+ /// The root Skeleton Node.
+ internal static BoneContent BuildSkeleton (NodeContent node)
+ {
+ var nodes = node.AsEnumerable().SelectDeep(n => n.Children).ToList ();
+ var meshes = nodes.FindAll(n => n is MeshContent).Cast().ToList();
+ BoneContent root = null;
+ foreach (var mesh in meshes) {
+ var parent = mesh.Parent;
+ parent.Children.Remove (mesh);
+ var bone = new BoneContent () {
+ Name = "bone_" + mesh.Name,
+ Transform = mesh.Transform,
+ };
+ if (root == null)
+ root = bone;
+ bone.Parent = null;
+ mesh.Parent = null;
+ mesh.Transform = Matrix.Identity;
+ parent.Children.Add (bone);
+ bone.Children.Add (mesh);
+ // foreach (var animation in mesh.Animations) {
+ // if (!node.Animations.TryGetValue (animation.Key, out AnimationContent ac)) {
+ // ac = new AnimationContent ();
+ // node.Animations.Add (animation.Key, ac);
+ // ac.Duration = animation.Value.Duration;
+ // ac.Identity = animation.Value.Identity;
+ // }
+
+ // // foreach (var c in animation.Value.Channels) {
+ // // var key = "bone_" + c.Key;
+ // // if (!ac.Channels.TryGetValue (key, out AnimationChannel chan)) {
+ // // ac.Channels.Add(key, c.Value);
+ // // }
+ // // chan.Add (c.Value.)
+ // // }
+ // }
+ foreach (var geometry in mesh.Geometry) {
+ var weightsName = VertexChannelNames.Weights ();
+ var xnaWeights = new List();
+ var weights = new BoneWeightCollection();
+ weights.Add(new BoneWeight("bone_" + mesh.Name, 1.0f));
+ for (int i=0; i <= geometry.Vertices.VertexCount-1; i++)
+ xnaWeights.Add (weights);
+ geometry.Vertices.Channels.Add (weightsName, xnaWeights );
+ }
+ }
+ return root;
+ }
+
///
/// Traverses a skeleton depth-first and builds a list of its bones.
///
diff --git a/MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj b/MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj
index 05ae4a62d78..c87ebb4e388 100644
--- a/MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj
+++ b/MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj
@@ -82,7 +82,7 @@
-
+
@@ -170,6 +170,11 @@
runtimes\osx\native\libfreetype6.dylib
PreserveNewest
+
+ libassimp.dylib
+ runtimes\osx\native\libassimp.dylib
+ PreserveNewest
+
runtimes\osx\native
PreserveNewest
diff --git a/MonoGame.Framework.Content.Pipeline/Processors/ModelProcessor.cs b/MonoGame.Framework.Content.Pipeline/Processors/ModelProcessor.cs
index e5ea9b33f3a..c00e81e8eba 100644
--- a/MonoGame.Framework.Content.Pipeline/Processors/ModelProcessor.cs
+++ b/MonoGame.Framework.Content.Pipeline/Processors/ModelProcessor.cs
@@ -105,7 +105,6 @@ public override ModelContent Process(NodeContent input, ContentProcessorContext
var scale = Matrix.CreateScale(Scale);
MeshHelper.TransformScene(input, rotZ * rotX * rotY * scale);
}
-
// Gather all the nodes in tree traversal order.
var nodes = input.AsEnumerable().SelectDeep(n => n.Children).ToList();
@@ -113,6 +112,12 @@ public override ModelContent Process(NodeContent input, ContentProcessorContext
var geometries = meshes.SelectMany(m => m.Geometry).ToList();
var distinctMaterials = geometries.Select(g => g.Material).Distinct().ToList();
+ // var hasBones = MeshHelper.FindSkeleton (input) != null;
+ // var hasRootAnimations = input.Animations.Any ();
+ // var hasMeshAnimations = meshes.Any (x => x.Animations.Count > 0);
+ // if (!hasBones && (hasRootAnimations || hasMeshAnimations))
+ // MeshHelper.BuildSkeleton (input);
+
// Loop through all distinct materials, passing them through the conversion method
// only once, and then processing all geometries using that material.
foreach (var inputMaterial in distinctMaterials)
@@ -238,6 +243,7 @@ protected virtual void ProcessGeometryUsingMaterial(MaterialContent material,
else if (material is SkinnedMaterialContent)
{
textureChannels = 1;
+ // if we don't have bones but have animations we need to add "fake" weights.
vertexWeights = true;
}
else if (material is EnvironmentMapMaterialContent)
diff --git a/MonoGame.Framework.Content.Pipeline/Serialization/Compiler/ModelWriter.cs b/MonoGame.Framework.Content.Pipeline/Serialization/Compiler/ModelWriter.cs
index 02d4addf800..be0b2c16040 100644
--- a/MonoGame.Framework.Content.Pipeline/Serialization/Compiler/ModelWriter.cs
+++ b/MonoGame.Framework.Content.Pipeline/Serialization/Compiler/ModelWriter.cs
@@ -38,6 +38,7 @@ protected internal override void Write(ContentWriter output, ModelContent value)
WriteBoneReference(output, value.Root, value.Bones);
output.WriteObject(value.Tag);
+ // Add serialization of Animation data here.
}
private void WriteBones(ContentWriter output, ModelBoneContentCollection bones)
diff --git a/MonoGame.Framework.DesktopGL.sln b/MonoGame.Framework.DesktopGL.sln
index d5661193e55..c7d884e2d1a 100644
--- a/MonoGame.Framework.DesktopGL.sln
+++ b/MonoGame.Framework.DesktopGL.sln
@@ -7,6 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Framework.DesktopG
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Tests.DesktopGL", "Tests\MonoGame.Tests.DesktopGL.csproj", "{3EA1BB98-6F7F-4CEC-9804-8553A599AA3B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Framework.Content.Pipeline", "MonoGame.Framework.Content.Pipeline\MonoGame.Framework.Content.Pipeline.csproj", "{50610F72-EE08-475E-84E4-88B86E05ED77}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{8792B021-CB1C-420C-8A1E-AB9CB3B7751F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Tools.Tests", "Tools\MonoGame.Tools.Tests\MonoGame.Tools.Tests.csproj", "{44A60138-0D95-4673-A597-36E528571D53}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -41,6 +47,30 @@ Global
{3EA1BB98-6F7F-4CEC-9804-8553A599AA3B}.Release|x64.Build.0 = Release|Any CPU
{3EA1BB98-6F7F-4CEC-9804-8553A599AA3B}.Release|x86.ActiveCfg = Release|Any CPU
{3EA1BB98-6F7F-4CEC-9804-8553A599AA3B}.Release|x86.Build.0 = Release|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|x64.Build.0 = Debug|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Debug|x86.Build.0 = Debug|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Release|Any CPU.Build.0 = Release|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Release|x64.ActiveCfg = Release|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Release|x64.Build.0 = Release|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Release|x86.ActiveCfg = Release|Any CPU
+ {50610F72-EE08-475E-84E4-88B86E05ED77}.Release|x86.Build.0 = Release|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Debug|x64.Build.0 = Debug|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Debug|x86.Build.0 = Debug|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Release|Any CPU.Build.0 = Release|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Release|x64.ActiveCfg = Release|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Release|x64.Build.0 = Release|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Release|x86.ActiveCfg = Release|Any CPU
+ {44A60138-0D95-4673-A597-36E528571D53}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -48,4 +78,7 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {847BFB97-3FE9-4E70-B4D0-0B0C8F6921A8}
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {44A60138-0D95-4673-A597-36E528571D53} = {8792B021-CB1C-420C-8A1E-AB9CB3B7751F}
+ EndGlobalSection
EndGlobal
diff --git a/MonoGame.Framework/Content/ContentExtensions.cs b/MonoGame.Framework/Content/ContentExtensions.cs
index 1b6dac6e37f..f5aa61a6cb7 100644
--- a/MonoGame.Framework/Content/ContentExtensions.cs
+++ b/MonoGame.Framework/Content/ContentExtensions.cs
@@ -1,12 +1,17 @@
using System;
using System.Reflection;
using System.Linq;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.Xna.Framework.Content
{
internal static class ContentExtensions
{
- public static ConstructorInfo GetDefaultConstructor(this Type type)
+ public static ConstructorInfo GetDefaultConstructor(
+#if NET5_0_OR_GREATER
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
+#endif
+ this Type type)
{
#if NET45
var typeInfo = type.GetTypeInfo();
@@ -18,7 +23,11 @@ public static ConstructorInfo GetDefaultConstructor(this Type type)
#endif
}
- public static PropertyInfo[] GetAllProperties(this Type type)
+ public static PropertyInfo[] GetAllProperties(
+#if NET5_0_OR_GREATER
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
+#endif
+ this Type type)
{
// Sometimes, overridden properties of abstract classes can show up even with
diff --git a/MonoGame.Framework/Content/ContentManager.cs b/MonoGame.Framework/Content/ContentManager.cs
index 27bd2c5a410..205cfa21b9b 100644
--- a/MonoGame.Framework/Content/ContentManager.cs
+++ b/MonoGame.Framework/Content/ContentManager.cs
@@ -112,6 +112,7 @@ private static void RemoveContentManager(ContentManager contentManager)
}
}
+#if __ANDROID__
internal static void ReloadGraphicsContent()
{
lock (ContentManagerLock)
@@ -134,6 +135,7 @@ internal static void ReloadGraphicsContent()
}
}
}
+#endif
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
@@ -406,6 +408,7 @@ protected virtual Dictionary LoadedAssets
get { return loadedAssets; }
}
+#if __ANDROID__
protected virtual void ReloadGraphicsAssets()
{
foreach (var asset in LoadedAssets)
@@ -420,6 +423,7 @@ protected virtual void ReloadGraphicsAssets()
genericMethod.Invoke(this, new object[] { asset.Key, Convert.ChangeType(asset.Value, asset.Value.GetType()) });
}
}
+#endif
protected virtual void ReloadAsset(string originalAssetName, T currentAsset)
{
diff --git a/MonoGame.Framework/Content/ContentReaders/ModelReader.cs b/MonoGame.Framework/Content/ContentReaders/ModelReader.cs
index 537c2855f11..a547bc2a31f 100644
--- a/MonoGame.Framework/Content/ContentReaders/ModelReader.cs
+++ b/MonoGame.Framework/Content/ContentReaders/ModelReader.cs
@@ -128,9 +128,11 @@ protected internal override Model Read(ContentReader reader, Model existingInsta
if (existingInstance != null)
part = existingInstance.Meshes[i].MeshParts[(int)j];
else
+#pragma warning disable CS0618 // Type or member is obsolete
part = new ModelMeshPart();
+#pragma warning restore CS0618 // Type or member is obsolete
- part.VertexOffset = reader.ReadInt32();
+ part.VertexOffset = reader.ReadInt32();
part.NumVertices = reader.ReadInt32();
part.StartIndex = reader.ReadInt32();
part.PrimitiveCount = reader.ReadInt32();
@@ -191,6 +193,11 @@ protected internal override Model Read(ContentReader reader, Model existingInsta
// Tag?
model.Tag = reader.ReadObject