diff --git a/Src/Noesis/Core/Src/Core/Extend.cs b/Src/Noesis/Core/Src/Core/Extend.cs index d8f0962..a439995 100644 --- a/Src/Noesis/Core/Src/Core/Extend.cs +++ b/Src/Noesis/Core/Src/Core/Extend.cs @@ -1289,6 +1289,13 @@ public static IntPtr RegisterNativeType(Type type, bool registerDP) PropertyInfo indexerInfo = null; IndexerAccessor indexer = null; + #if UNITY_5_3_OR_NEWER + if (typeof(UnityEngine.Texture).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) + { + nativeType = Noesis.TextureSource.Extend(TypeFullName(type)); + } + else + #endif if (typeof(Noesis.IScrollInfo).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()) && typeof(Noesis.VirtualizingPanel).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) { @@ -1470,7 +1477,12 @@ private static ExtendTypeData CreateNativeTypeData(System.Type type, IntPtr nati { ExtendTypeData typeData = new ExtendTypeData(); typeData.type = nativeType.ToInt64(); - typeData.baseType = EnsureNativeType(type.GetTypeInfo().BaseType).ToInt64(); + typeData.baseType = + #if UNITY_5_3_OR_NEWER + typeof(UnityEngine.Texture).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()) ? + TryGetNativeType(typeof(Noesis.TextureSource)).ToInt64() : + #endif + EnsureNativeType(type.GetTypeInfo().BaseType).ToInt64(); var typeConverter = type.GetTypeInfo().GetCustomAttribute(); if (typeConverter != null) @@ -4612,7 +4624,7 @@ public static IntPtr GetCPtr(BaseComponent instance, Type extendType) } //////////////////////////////////////////////////////////////////////////////////////////////// - public static IntPtr NewCPtr(System.Type type, object instance) + public static IntPtr NewCPtr(System.Type type) { // Ensure native type is registered IntPtr nativeType = EnsureNativeType(type); @@ -4687,10 +4699,7 @@ private static void DeleteInstance(IntPtr cPtr) { try { - if (Initialized) - { - RemoveExtendInfo(cPtr); - } + RemoveExtendInfo(cPtr); } catch (Exception e) { @@ -5015,9 +5024,17 @@ public static HandleRef GetInstanceHandle(object instance) cPtr = FindInstancePtr(instance); if (cPtr == IntPtr.Zero && Initialized) { - cPtr = NewCPtr(instance.GetType(), instance); + cPtr = NewCPtr(instance.GetType()); AddExtendInfo(cPtr, instance); RegisterInterfaces(instance); + + #if UNITY_5_3_OR_NEWER + // Automatic conversion from Unity's Texture to a TextureSource proxy + if (instance is UnityEngine.Texture) + { + Noesis.TextureSource.SetTexture(cPtr, (UnityEngine.Texture)instance); + } + #endif } } @@ -5068,7 +5085,15 @@ private static IntPtr FindWeakInstancePtr(object instance) WeakInfo info = extends[i]; if (info.weak.Target == instance) { - cPtr = new IntPtr(info.ptr); + if (!Initialized && !_extends.ContainsKey(info.ptr)) + { + // Extend already destroyed + cPtr = IntPtr.Zero; + } + else + { + cPtr = new IntPtr(info.ptr); + } break; } } diff --git a/Src/Noesis/Core/Src/Proxies/BaseComponentExtend.cs b/Src/Noesis/Core/Src/Proxies/BaseComponentExtend.cs index 287f1ec..f1a2e12 100644 --- a/Src/Noesis/Core/Src/Proxies/BaseComponentExtend.cs +++ b/Src/Noesis/Core/Src/Proxies/BaseComponentExtend.cs @@ -82,7 +82,7 @@ protected virtual IntPtr CreateCPtr(Type type, out bool registerExtend) protected IntPtr CreateExtendCPtr(Type type, out bool registerExtend) { registerExtend = true; - return Noesis.Extend.NewCPtr(type, this); + return Noesis.Extend.NewCPtr(type); } public static IntPtr GetPtr(object instance) diff --git a/Src/Noesis/Core/Src/Proxies/ManipulationDelta.cs b/Src/Noesis/Core/Src/Proxies/ManipulationDelta.cs index 0608c98..0149991 100644 --- a/Src/Noesis/Core/Src/Proxies/ManipulationDelta.cs +++ b/Src/Noesis/Core/Src/Proxies/ManipulationDelta.cs @@ -45,58 +45,57 @@ public virtual void Dispose() { } } - public Point Expansion { - set { - NoesisGUI_PINVOKE.ManipulationDelta_Expansion_set(swigCPtr, ref value); + public Vector Scale { + get { + float scale = GetScaleHelper(); + return new Vector(scale, scale); } + } + public Vector Translation { get { - IntPtr ret = NoesisGUI_PINVOKE.ManipulationDelta_Expansion_get(swigCPtr); - if (ret != IntPtr.Zero) { - return Marshal.PtrToStructure(ret); - } - else { - return new Point(); - } + Point trans = GetTranslationHelper(); + return new Vector(trans.X, trans.Y); } + } + public Vector Expansion { + get { + Point exp = GetExpansionHelper(); + return new Vector(exp.X, exp.Y); + } } public float Rotation { - set { - NoesisGUI_PINVOKE.ManipulationDelta_Rotation_set(swigCPtr, value); - } get { float ret = NoesisGUI_PINVOKE.ManipulationDelta_Rotation_get(swigCPtr); return ret; } } - public float Scale { - set { - NoesisGUI_PINVOKE.ManipulationDelta_Scale_set(swigCPtr, value); - } - get { - float ret = NoesisGUI_PINVOKE.ManipulationDelta_Scale_get(swigCPtr); - return ret; - } + private float GetScaleHelper() { + float ret = NoesisGUI_PINVOKE.ManipulationDelta_GetScaleHelper(swigCPtr); + return ret; } - public Point Translation { - set { - NoesisGUI_PINVOKE.ManipulationDelta_Translation_set(swigCPtr, ref value); + private Point GetTranslationHelper() { + IntPtr ret = NoesisGUI_PINVOKE.ManipulationDelta_GetTranslationHelper(swigCPtr); + if (ret != IntPtr.Zero) { + return Marshal.PtrToStructure(ret); } - - get { - IntPtr ret = NoesisGUI_PINVOKE.ManipulationDelta_Translation_get(swigCPtr); - if (ret != IntPtr.Zero) { - return Marshal.PtrToStructure(ret); - } - else { - return new Point(); - } + else { + return new Point(); } + } + private Point GetExpansionHelper() { + IntPtr ret = NoesisGUI_PINVOKE.ManipulationDelta_GetExpansionHelper(swigCPtr); + if (ret != IntPtr.Zero) { + return Marshal.PtrToStructure(ret); + } + else { + return new Point(); + } } public ManipulationDelta() : this(NoesisGUI_PINVOKE.new_ManipulationDelta(), true) { diff --git a/Src/Noesis/Core/Src/Proxies/ManipulationDeltaEventArgs.cs b/Src/Noesis/Core/Src/Proxies/ManipulationDeltaEventArgs.cs index 6840531..0746918 100644 --- a/Src/Noesis/Core/Src/Proxies/ManipulationDeltaEventArgs.cs +++ b/Src/Noesis/Core/Src/Proxies/ManipulationDeltaEventArgs.cs @@ -70,17 +70,17 @@ public Point ManipulationOrigin { } - public ManipulationDelta CumulativeManipulation { + public ManipulationDelta DeltaManipulation { get { - IntPtr cPtr = NoesisGUI_PINVOKE.ManipulationDeltaEventArgs_CumulativeManipulation_get(swigCPtr); + IntPtr cPtr = NoesisGUI_PINVOKE.ManipulationDeltaEventArgs_DeltaManipulation_get(swigCPtr); ManipulationDelta ret = (cPtr == IntPtr.Zero) ? null : new ManipulationDelta(cPtr, false); return ret; } } - public ManipulationDelta DeltaManipulation { + public ManipulationDelta CumulativeManipulation { get { - IntPtr cPtr = NoesisGUI_PINVOKE.ManipulationDeltaEventArgs_DeltaManipulation_get(swigCPtr); + IntPtr cPtr = NoesisGUI_PINVOKE.ManipulationDeltaEventArgs_CumulativeManipulation_get(swigCPtr); ManipulationDelta ret = (cPtr == IntPtr.Zero) ? null : new ManipulationDelta(cPtr, false); return ret; } diff --git a/Src/Noesis/Core/Src/Proxies/Matrix4.cs b/Src/Noesis/Core/Src/Proxies/Matrix4.cs index 4e542d6..2a09c86 100644 --- a/Src/Noesis/Core/Src/Proxies/Matrix4.cs +++ b/Src/Noesis/Core/Src/Proxies/Matrix4.cs @@ -331,6 +331,11 @@ public static Matrix4 Inverse(Matrix4 m, float determinant) { d30, d31, d32, d33); } + public Rect TransformBounds(Rect bounds) { + bounds.Transform(this); + return bounds; + } + } } diff --git a/Src/Noesis/Core/Src/Proxies/NoesisGUI_PINVOKE.cs b/Src/Noesis/Core/Src/Proxies/NoesisGUI_PINVOKE.cs index 1d88420..884f681 100644 --- a/Src/Noesis/Core/Src/Proxies/NoesisGUI_PINVOKE.cs +++ b/Src/Noesis/Core/Src/Proxies/NoesisGUI_PINVOKE.cs @@ -3391,29 +3391,17 @@ internal class NoesisGUI_PINVOKE { [DllImport(Library.Name)] public static extern void delete_ManipulationStartedEventArgs(HandleRef jarg1); - [DllImport(Library.Name)] - public static extern void ManipulationDelta_Expansion_set(HandleRef jarg1, ref Point jarg2); - - [DllImport(Library.Name)] - public static extern IntPtr ManipulationDelta_Expansion_get(HandleRef jarg1); - - [DllImport(Library.Name)] - public static extern void ManipulationDelta_Rotation_set(HandleRef jarg1, float jarg2); - [DllImport(Library.Name)] public static extern float ManipulationDelta_Rotation_get(HandleRef jarg1); [DllImport(Library.Name)] - public static extern void ManipulationDelta_Scale_set(HandleRef jarg1, float jarg2); + public static extern float ManipulationDelta_GetScaleHelper(HandleRef jarg1); [DllImport(Library.Name)] - public static extern float ManipulationDelta_Scale_get(HandleRef jarg1); + public static extern IntPtr ManipulationDelta_GetTranslationHelper(HandleRef jarg1); [DllImport(Library.Name)] - public static extern void ManipulationDelta_Translation_set(HandleRef jarg1, ref Point jarg2); - - [DllImport(Library.Name)] - public static extern IntPtr ManipulationDelta_Translation_get(HandleRef jarg1); + public static extern IntPtr ManipulationDelta_GetExpansionHelper(HandleRef jarg1); [DllImport(Library.Name)] public static extern IntPtr new_ManipulationDelta(); @@ -3449,10 +3437,10 @@ internal class NoesisGUI_PINVOKE { public static extern IntPtr ManipulationDeltaEventArgs_ManipulationOrigin_get(HandleRef jarg1); [DllImport(Library.Name)] - public static extern IntPtr ManipulationDeltaEventArgs_CumulativeManipulation_get(HandleRef jarg1); + public static extern IntPtr ManipulationDeltaEventArgs_DeltaManipulation_get(HandleRef jarg1); [DllImport(Library.Name)] - public static extern IntPtr ManipulationDeltaEventArgs_DeltaManipulation_get(HandleRef jarg1); + public static extern IntPtr ManipulationDeltaEventArgs_CumulativeManipulation_get(HandleRef jarg1); [DllImport(Library.Name)] public static extern IntPtr ManipulationDeltaEventArgs_Velocities_get(HandleRef jarg1); diff --git a/Src/NoesisApp/Core/Src/Interactivity/TranslateZoomRotateBehavior.cs b/Src/NoesisApp/Core/Src/Interactivity/TranslateZoomRotateBehavior.cs index 1d2aa99..70cfef2 100644 --- a/Src/NoesisApp/Core/Src/Interactivity/TranslateZoomRotateBehavior.cs +++ b/Src/NoesisApp/Core/Src/Interactivity/TranslateZoomRotateBehavior.cs @@ -172,10 +172,10 @@ private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) ManipulationDelta delta = e.DeltaManipulation; // Update Scale transform - float scale = delta.Scale * _scale.ScaleX; - scale = Math.Max(Math.Max(0.00001f, MinimumScale), Math.Min(scale, MaximumScale)); - _scale.ScaleX = scale; - _scale.ScaleY = scale; + float scaleX = delta.Scale.X * _scale.ScaleX; + _scale.ScaleX = Math.Max(Math.Max(0.00001f, MinimumScale), Math.Min(scaleX, MaximumScale)); + float scaleY = delta.Scale.Y * _scale.ScaleY; + _scale.ScaleY = Math.Max(Math.Max(0.00001f, MinimumScale), Math.Min(scaleY, MaximumScale)); // Update Rotate transform _rotate.Angle += delta.Rotation; diff --git a/Src/NoesisApp/RenderContexts/EGL/Src/RenderContextEGL.cs b/Src/NoesisApp/RenderContexts/EGL/Src/RenderContextEGL.cs index b7c6e0a..a4582a4 100644 --- a/Src/NoesisApp/RenderContexts/EGL/Src/RenderContextEGL.cs +++ b/Src/NoesisApp/RenderContexts/EGL/Src/RenderContextEGL.cs @@ -126,7 +126,40 @@ public override void SetDefaultRenderTarget(int width, int height, bool doClearC public override ImageCapture CaptureRenderTarget(RenderTarget surface) { - throw new NotImplementedException(); + int[] viewport = new int[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + int x = viewport[0]; + int y = viewport[1]; + int width = viewport[2]; + int height = viewport[3]; + + byte[] src = new byte[width * height * 4]; + int srcStride = width * 4; + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, src); + + ImageCapture img = new ImageCapture((uint)width, (uint)height); + + byte[] dst = img.Pixels; + + for (int i = 0; i < height; ++i) + { + int dstRow = i * (int)img.Stride; + int srcRow = i * srcStride; + + for (int j = 0; j < width; ++j) + { + // RGBA -> BGRA + dst[dstRow + 4 * j + 2] = src[srcRow + 4 * j + 0]; + dst[dstRow + 4 * j + 1] = src[srcRow + 4 * j + 1]; + dst[dstRow + 4 * j + 0] = src[srcRow + 4 * j + 2]; + dst[dstRow + 4 * j + 3] = src[srcRow + 4 * j + 3]; + } + } + + return img; } public override void Swap() @@ -205,6 +238,10 @@ public override void Resize() { } private const uint GL_FRAMEBUFFER = 0x8D40; private const uint GL_STENCIL_BUFFER_BIT = 0x00000400; private const uint GL_COLOR_BUFFER_BIT = 0x00004000; + private const uint GL_VIEWPORT = 0x00000BA2; + private const uint GL_PACK_ALIGNMENT = 0x00000D05; + private const uint GL_UNSIGNED_BYTE = 0x00001401; + private const uint GL_RGBA = 0x00001908; [DllImport("GLESv2")] static extern void glBindFramebuffer(uint target, uint framebuffer); @@ -223,5 +260,15 @@ public override void Resize() { } [DllImport("GLESv2")] static extern void glClearColor(float r, float g, float b, float a); + + [DllImport("GLESv2")] + public static extern void glGetIntegerv(uint pname, int[] param); + + [DllImport("GLESv2")] + public static extern void glPixelStorei(uint pname, int param); + + [DllImport("GLESv2")] + public static extern void glReadPixels(int x, int y, int width, int height, + uint format, uint type, byte[] pixels); } } diff --git a/Src/NoesisApp/RenderContexts/GLX/Src/RenderContextGLX.cs b/Src/NoesisApp/RenderContexts/GLX/Src/RenderContextGLX.cs index 25ba5d9..b6298ed 100644 --- a/Src/NoesisApp/RenderContexts/GLX/Src/RenderContextGLX.cs +++ b/Src/NoesisApp/RenderContexts/GLX/Src/RenderContextGLX.cs @@ -186,7 +186,40 @@ public override void SetDefaultRenderTarget(int width, int height, bool doClearC public override ImageCapture CaptureRenderTarget(RenderTarget surface) { - throw new NotImplementedException(); + int[] viewport = new int[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + int x = viewport[0]; + int y = viewport[1]; + int width = viewport[2]; + int height = viewport[3]; + + byte[] src = new byte[width * height * 4]; + int srcStride = width * 4; + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, src); + + ImageCapture img = new ImageCapture((uint)width, (uint)height); + + byte[] dst = img.Pixels; + + for (int i = 0; i < height; ++i) + { + int dstRow = i * (int)img.Stride; + int srcRow = i * srcStride; + + for (int j = 0; j < width; ++j) + { + // RGBA -> BGRA + dst[dstRow + 4 * j + 2] = src[srcRow + 4 * j + 0]; + dst[dstRow + 4 * j + 1] = src[srcRow + 4 * j + 1]; + dst[dstRow + 4 * j + 0] = src[srcRow + 4 * j + 2]; + dst[dstRow + 4 * j + 3] = src[srcRow + 4 * j + 3]; + } + } + + return img; } public override void Swap() @@ -278,6 +311,10 @@ public static TDelegate GetProcAddress(string name) where TDelegate : private const uint GL_FRAMEBUFFER = 0x8D40; private const uint GL_STENCIL_BUFFER_BIT = 0x00000400; private const uint GL_COLOR_BUFFER_BIT = 0x00004000; + private const uint GL_VIEWPORT = 0x00000BA2; + private const uint GL_PACK_ALIGNMENT = 0x00000D05; + private const uint GL_UNSIGNED_BYTE = 0x00001401; + private const uint GL_RGBA = 0x00001908; private const string OpenGLLibraryName = "GL"; @@ -298,5 +335,15 @@ public static TDelegate GetProcAddress(string name) where TDelegate : [DllImport(OpenGLLibraryName)] static extern void glClearColor(float r, float g, float b, float a); + + [DllImport(OpenGLLibraryName)] + public static extern void glGetIntegerv(uint pname, int[] param); + + [DllImport(OpenGLLibraryName)] + public static extern void glPixelStorei(uint pname, int param); + + [DllImport(OpenGLLibraryName)] + public static extern void glReadPixels(int x, int y, int width, int height, + uint format, uint type, byte[] pixels); } } diff --git a/Src/NoesisApp/RenderContexts/NSGL/Src/RenderContextNSGL.cs b/Src/NoesisApp/RenderContexts/NSGL/Src/RenderContextNSGL.cs index ad0612b..80d71af 100644 --- a/Src/NoesisApp/RenderContexts/NSGL/Src/RenderContextNSGL.cs +++ b/Src/NoesisApp/RenderContexts/NSGL/Src/RenderContextNSGL.cs @@ -97,7 +97,40 @@ public override void SetDefaultRenderTarget(int width, int height, bool doClearC public override ImageCapture CaptureRenderTarget(RenderTarget surface) { - throw new NotImplementedException(); + int[] viewport = new int[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + int x = viewport[0]; + int y = viewport[1]; + int width = viewport[2]; + int height = viewport[3]; + + byte[] src = new byte[width * height * 4]; + int srcStride = width * 4; + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, src); + + ImageCapture img = new ImageCapture((uint)width, (uint)height); + + byte[] dst = img.Pixels; + + for (int i = 0; i < height; ++i) + { + int dstRow = i * (int)img.Stride; + int srcRow = i * srcStride; + + for (int j = 0; j < width; ++j) + { + // RGBA -> BGRA + dst[dstRow + 4 * j + 2] = src[srcRow + 4 * j + 0]; + dst[dstRow + 4 * j + 1] = src[srcRow + 4 * j + 1]; + dst[dstRow + 4 * j + 0] = src[srcRow + 4 * j + 2]; + dst[dstRow + 4 * j + 3] = src[srcRow + 4 * j + 3]; + } + } + + return img; } public override void Swap() @@ -110,9 +143,13 @@ public override void Resize() _context.Update(); } - private const uint GL_FRAMEBUFFER = 0x8D40; - private const uint GL_STENCIL_BUFFER_BIT = 0x00000400; - private const uint GL_COLOR_BUFFER_BIT = 0x00004000; + private const uint GL_FRAMEBUFFER = 0x8D40; + private const uint GL_STENCIL_BUFFER_BIT = 0x00000400; + private const uint GL_COLOR_BUFFER_BIT = 0x00004000; + private const uint GL_VIEWPORT = 0x00000BA2; + private const uint GL_PACK_ALIGNMENT = 0x00000D05; + private const uint GL_UNSIGNED_BYTE = 0x00001401; + private const uint GL_RGBA = 0x00001908; private const string LibraryName = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; @@ -133,5 +170,15 @@ public override void Resize() [DllImport(LibraryName)] static extern void glClearColor(float r, float g, float b, float a); + + [DllImport(LibraryName)] + public static extern void glGetIntegerv(uint pname, int[] param); + + [DllImport(LibraryName)] + public static extern void glPixelStorei(uint pname, int param); + + [DllImport(LibraryName)] + public static extern void glReadPixels(int x, int y, int width, int height, + uint format, uint type, byte[] pixels); } }