diff --git a/runtime/bindings-generator.cs b/runtime/bindings-generator.cs index 8e46f9955588..05549d4b1dc8 100644 --- a/runtime/bindings-generator.cs +++ b/runtime/bindings-generator.cs @@ -1444,6 +1444,26 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // Quaternion func ()", + Prefix = "simd__", + Variants = Variants.All, + ReturnType = Types.QuatF, + } + ); + + data.Add ( + new FunctionData { + Comment = " // void func (Quaternion)", + Prefix = "simd__", + Variants = Variants.NonStret, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.QuatF }, + }, + } + ); + // Required for ModelIO data.Add ( new FunctionData { @@ -1994,6 +2014,12 @@ static void MarshalToManaged (StringWriter writer, TypeData type, string nativeV writer.WriteLine ("\t\t{0}.points [i].c = {1}.points [i] [2];", managedVariable, nativeVariable); writer.WriteLine ("\t}"); break; + case "Quaternion": + writer.WriteLine ("\t{0}.vector.a = {1}.vector [0];", managedVariable, nativeVariable); + writer.WriteLine ("\t{0}.vector.b = {1}.vector [1];", managedVariable, nativeVariable); + writer.WriteLine ("\t{0}.vector.c = {1}.vector [2];", managedVariable, nativeVariable); + writer.WriteLine ("\t{0}.vector.d = {1}.vector [3];", managedVariable, nativeVariable); + break; default: throw new NotImplementedException (string.Format ("MarshalToManaged for: NativeType: {0} ManagedType: {1}", type.NativeType, type.ManagedType)); } @@ -2081,6 +2107,12 @@ static void MarshalToNative (StringWriter writer, TypeData type, string nativeVa writer.WriteLine ("\t\t{0}.points [i][2] = {1}.points [i].c;", nativeVariable, managedVariable); writer.WriteLine ("\t}"); break; + case "Quaternion": + writer.WriteLine ("\t{0}.vector [0] = {1}.vector.a;", nativeVariable, managedVariable); + writer.WriteLine ("\t{0}.vector [1] = {1}.vector.b;", nativeVariable, managedVariable); + writer.WriteLine ("\t{0}.vector [2] = {1}.vector.c;", nativeVariable, managedVariable); + writer.WriteLine ("\t{0}.vector [3] = {1}.vector.d;", nativeVariable, managedVariable); + break; default: throw new NotImplementedException (string.Format ("MarshalToNative for: NativeType: {0} ManagedType: {1}", type.NativeType, type.ManagedType)); } @@ -2658,6 +2690,13 @@ public static class Types { NativeWrapperType = "CGSize", RequireMarshal = false, }; + + public static TypeData QuatF = new TypeData { + ManagedType = "Quaternion", + NativeType = "simd_quatf", + NativeWrapperType = "struct QuatF", + RequireMarshal = true, + }; } } diff --git a/runtime/bindings.h b/runtime/bindings.h index fd91e261a072..d8e07b3fb5d1 100644 --- a/runtime/bindings.h +++ b/runtime/bindings.h @@ -83,6 +83,8 @@ typedef struct { vector_float2 columns[2]; } matrix_float2x2; typedef struct { vector_float3 columns[3]; } matrix_float3x3; typedef struct { vector_float4 columns[4]; } matrix_float4x4; +typedef struct { vector_float4 vector; } simd_quatf; + typedef struct { vector_float3 maxBounds; vector_float3 minBounds; @@ -149,6 +151,10 @@ struct Matrix4f { Vector4f columns [4]; }; +struct QuatF { + Vector4f vector; +}; + struct MDLAxisAlignedBoundingBoxWrapper { Vector3f maxBounds; Vector3f minBounds; diff --git a/src/SpriteKit/Enums.cs b/src/SpriteKit/Enums.cs index 3ca62af8ec74..4bdef22eba97 100644 --- a/src/SpriteKit/Enums.cs +++ b/src/SpriteKit/Enums.cs @@ -183,4 +183,14 @@ public enum SKTileAdjacencyMask : nuint LowerLeftCorner = Up | Right | LowerRight | Down | LowerLeft | Left | UpperLeft, UpperLeftCorner = Up | UpperRight | Right | Down | LowerLeft | Left | UpperLeft, } + + [NoWatch] + [NoMac] + [TV (11,0), iOS (11,0)] + [Native] + public enum SKNodeFocusBehavior : nint { + None = 0, + Occluding, + Focusable, + } } diff --git a/src/spritekit.cs b/src/spritekit.cs index b91288a64d06..1cce92bb055d 100644 --- a/src/spritekit.cs +++ b/src/spritekit.cs @@ -21,6 +21,9 @@ using XamCore.CoreGraphics; using XamCore.CoreVideo; using XamCore.SceneKit; +#if !WATCH +using XamCore.Metal; +#endif using Vector2 = global::OpenTK.Vector2; using Vector3 = global::OpenTK.Vector3; @@ -28,6 +31,7 @@ using Matrix3 = global::OpenTK.Matrix3; using Matrix4 = global::OpenTK.Matrix4; using Vector4 = global::OpenTK.Vector4; +using Quaternion = global::OpenTK.Quaternion; #if MONOMAC using XamCore.AppKit; @@ -37,6 +41,7 @@ using pfloat = System.nfloat; #else using XamCore.UIKit; +using NSLineBreakMode = global::XamCore.UIKit.UILineBreakMode; using pfloat = System.Single; #if !WATCH using UIView = global::XamCore.UIKit.UIView; @@ -51,6 +56,11 @@ interface AVPlayer {} interface CIFilter {} interface GKPolygonObstacle {} interface UIView {} + interface IMTLCommandBuffer {} + interface IMTLCommandQueue {} + interface IMTLDevice {} + interface IMTLRenderCommandEncoder {} + interface MTLRenderPassDescriptor {} #endif delegate void SKNodeChildEnumeratorHandler (SKNode node, out bool stop); @@ -166,6 +176,12 @@ partial interface SKNode : NSCoding, NSCopying { [Export ("userInteractionEnabled")] bool UserInteractionEnabled { [Bind ("isUserInteractionEnabled")] get; set; } + [NoWatch] + [NoMac] + [TV (11,0), iOS (11,0)] + [Export ("focusBehavior", ArgumentSemantic.Assign)] + SKNodeFocusBehavior FocusBehavior { get; set; } + [Export ("parent")] SKNode Parent { get; } @@ -1182,12 +1198,29 @@ partial interface SKLabelNode { [Static, Export ("labelNodeWithText:")] SKLabelNode FromText ([NullAllowed] string text); + [TV (11,0), Watch (4,0), Mac (13,0), iOS (11,0)] + [Static] + [Export ("labelNodeWithAttributedText:")] + SKLabelNode FromText ([NullAllowed] NSAttributedString attributedText); + [Export ("verticalAlignmentMode")] SKLabelVerticalAlignmentMode VerticalAlignmentMode { get; set; } [Export ("horizontalAlignmentMode")] SKLabelHorizontalAlignmentMode HorizontalAlignmentMode { get; set; } + [TV (11,0), Watch (4,0), Mac (13,0), iOS (11,0)] + [Export ("numberOfLines")] + nint NumberOfLines { get; set; } + + [TV (11,0), Watch (4,0), Mac (13,0), iOS (11,0)] + [Export ("lineBreakMode", ArgumentSemantic.Assign)] + NSLineBreakMode LineBreakMode { get; set; } + + [TV (11,0), Watch (4,0), Mac (13,0), iOS (11,0)] + [Export ("preferredMaxLayoutWidth")] + nfloat PreferredMaxLayoutWidth { get; set; } + [Export ("fontName", ArgumentSemantic.Copy)] string FontName { get; set; } @@ -1195,6 +1228,10 @@ partial interface SKLabelNode { [NullAllowed] // nullable in Xcode7 headers and caught by introspection tests string Text { get; set; } + [TV (11,0), Watch (4,0), Mac (13,0), iOS (11,0)] + [NullAllowed, Export ("attributedText", ArgumentSemantic.Copy)] + NSAttributedString AttributedText { get; set; } + [Export ("fontSize")] nfloat FontSize { get; set; } @@ -3223,5 +3260,78 @@ interface SKWarpGeometryGrid : NSCoding [Export ("gridByReplacingDestPositions:")] SKWarpGeometryGrid _GridByReplacingDestPositions (IntPtr destPositions); } + + // SKRenderer is not available for WatchKit apps and the iOS simulator + [NoWatch] + [TV (11,0), Mac (10,13), iOS (11,0)] + [BaseType (typeof(NSObject))] + [DisableDefaultCtor] + interface SKRenderer { + [Static] + [Export ("rendererWithDevice:")] + [return: NullAllowed] + SKRenderer FromDevice ([NullAllowed] IMTLDevice device); + + [Export ("renderWithViewport:commandBuffer:renderPassDescriptor:")] + void Render (CGRect viewport, IMTLCommandBuffer commandBuffer, MTLRenderPassDescriptor renderPassDescriptor); + + [Export ("renderWithViewport:renderCommandEncoder:renderPassDescriptor:commandQueue:")] + void Render (CGRect viewport, IMTLRenderCommandEncoder renderCommandEncoder, MTLRenderPassDescriptor renderPassDescriptor, IMTLCommandQueue commandQueue); + + [Export ("updateAtTime:")] + void Update (double currentTime); + + [NullAllowed, Export ("scene", ArgumentSemantic.Assign)] + SKScene Scene { get; set; } + + [Export ("ignoresSiblingOrder")] + bool IgnoresSiblingOrder { get; set; } + + [Export ("shouldCullNonVisibleNodes")] + bool ShouldCullNonVisibleNodes { get; set; } + + [Export ("showsDrawCount")] + bool ShowsDrawCount { get; set; } + + [Export ("showsNodeCount")] + bool ShowsNodeCount { get; set; } + + [Export ("showsQuadCount")] + bool ShowsQuadCount { get; set; } + + [Export ("showsPhysics")] + bool ShowsPhysics { get; set; } + + [Export ("showsFields")] + bool ShowsFields { get; set; } + } + + [TV (11,0), Watch (4,0), Mac (13,0), iOS (11,0)] + [BaseType (typeof(SKNode))] + interface SKTransformNode { + [Export ("xRotation")] + nfloat XRotation { get; set; } + + [Export ("yRotation")] + nfloat YRotation { get; set; } + + [Export ("eulerAngles")] + Vector3 EulerAngles { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; + } + + [Export ("rotationMatrix")] + Matrix3 RotationMatrix { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; + } + + [Export ("quaternion")] + Quaternion Quaternion { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; + } + } } #endif diff --git a/tests/introspection/iOS/iOSApiSelectorTest.cs b/tests/introspection/iOS/iOSApiSelectorTest.cs index ba705baac34a..69b393522929 100644 --- a/tests/introspection/iOS/iOSApiSelectorTest.cs +++ b/tests/introspection/iOS/iOSApiSelectorTest.cs @@ -92,8 +92,9 @@ protected override bool Skip (Type type) case "UILocalNotification": return true; - // Metal is not available on the (iOS8) simulator + // Metal is not available on the simulator case "CAMetalLayer": + case "SKRenderer": return (Runtime.Arch == Arch.SIMULATOR); // iOS 10 - this type can only be instantiated on devices, but the selectors are forwarded diff --git a/tests/monotouch-test/Asserts.cs b/tests/monotouch-test/Asserts.cs index 8d468eb504c5..fe3d7c325158 100644 --- a/tests/monotouch-test/Asserts.cs +++ b/tests/monotouch-test/Asserts.cs @@ -83,6 +83,14 @@ public static void AreEqual (MDLAxisAlignedBoundingBox expected, MDLAxisAlignedB AreEqual (expected.MaxBounds, actual.MaxBounds, message + " (MaxBounds)"); AreEqual (expected.MinBounds, actual.MinBounds, message + " (MinBounds)"); } + + public static void AreEqual (Quaternion expected, Quaternion actual, string message) + { + Assert.AreEqual (expected.X, actual.X, message + " (X)"); + Assert.AreEqual (expected.Y, actual.Y, message + " (Y)"); + Assert.AreEqual (expected.Z, actual.Z, message + " (Z)"); + Assert.AreEqual (expected.W, actual.W, message + " (W)"); + } #endif // !__WATCHOS__ } diff --git a/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs b/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs new file mode 100644 index 000000000000..2f2fcfa13574 --- /dev/null +++ b/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs @@ -0,0 +1,72 @@ +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +#if !MONOMAC +using UIKit; +#endif +using SpriteKit; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.SpriteKit; +using MonoTouch.UIKit; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using NUnit.Framework; + +namespace MonoTouchFixtures.SpriteKit { + + [TestFixture] + [Preserve (AllMembers = true)] + public class SKTransformNodeTest { + [SetUp] + public void VersionCheck () + { + TestRuntime.AssertXcodeVersion (9, 0); + } + + [Test] + public void EulerAngles () + { + Vector3 V3; + + using (var obj = new SKTransformNode ()) { + Asserts.AreEqual (Vector3.Zero, obj.EulerAngles, "1 EulerAngles"); + V3 = new Vector3 (1, 2, 3); + obj.EulerAngles = V3; + // The values bellow match what the same code in Swift returns. + Assert.AreEqual (-2.14159298f, obj.EulerAngles.X, "#x1"); + Assert.AreEqual (1.14159274f, obj.EulerAngles.Y, "#y1"); + Assert.AreEqual (-0.141592711f, obj.EulerAngles.Z, "#z1"); + } + } + + [Test] + public void RotationMatrix () + { + using (var obj = new SKTransformNode ()) { + obj.RotationMatrix = Matrix3.Zero; + // In Swift, a rotated zero matrice also becomes the identity matrice. + Asserts.AreEqual (Matrix3.Identity, obj.RotationMatrix, "RotationMatrix"); + } + } + + [Test] + public void QuaternionTest () + { + Quaternion Q; + + using (var obj = new SKTransformNode ()) { + Asserts.AreEqual (Quaternion.Identity, obj.Quaternion, "1 Quaternion"); + Q = new Quaternion (new Vector3 (1, 2, 3), 4); + obj.Quaternion = Q; + Asserts.AreEqual (Q, obj.Quaternion, "2 Quaternion"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/monotouch-test.csproj b/tests/monotouch-test/monotouch-test.csproj index 53c53030c816..6bb0e3e9b6f9 100644 --- a/tests/monotouch-test/monotouch-test.csproj +++ b/tests/monotouch-test/monotouch-test.csproj @@ -657,6 +657,7 @@ +