C++RAW #include "UnityPrefix.h" #include "Configuration/UnityConfigure.h" #include "Runtime/Mono/MonoExportUtility.h" #include "Runtime/Scripting/ScriptingExportUtility.h" #include "Runtime/Scripting/ScriptingManager.h" #include "Runtime/Scripting/Backend/ScriptingTypeRegistry.h" #include "Runtime/Scripting/Scripting.h" #include "Runtime/Scripting/ScriptingObjectWithIntPtrField.h" #include "Runtime/Misc/GraphicsScriptingUtility.h" #include "Runtime/GfxDevice/GfxDevice.h" #include "Runtime/Graphics/Texture2D.h" #include "Runtime/Graphics/CubemapTexture.h" #include "Runtime/Graphics/Texture3D.h" #include "Runtime/Graphics/RenderTexture.h" #include "Runtime/Graphics/RenderBufferManager.h" #include "Runtime/Graphics/ImageConversion.h" #include "Runtime/Geometry/TextureAtlas.h" #include "Runtime/Math/Color.h" #include "Runtime/Math/Rect.h" #include "Runtime/Misc/BuildSettings.h" CSRAW using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Collections; namespace UnityEngine { NONSEALED_CLASS Texture : Object CUSTOM_PROP static int masterTextureLimit { return Texture::GetMasterTextureLimit (); } { Texture::SetMasterTextureLimit (value); } CUSTOM_PROP static AnisotropicFiltering anisotropicFiltering { return Texture::GetAnisoLimit (); } { Texture::SetAnisoLimit (value); } CUSTOM static void SetGlobalAnisotropicFilteringLimits( int forcedMin, int globalMax ) { Texture::SetGlobalAnisoLimits(forcedMin, globalMax); } CUSTOM private static int Internal_GetWidth (Texture mono) { return mono->GetDataWidth(); } CUSTOM private static int Internal_GetHeight (Texture mono) { return mono->GetDataHeight(); } CSRAW virtual public int width { get { return Internal_GetWidth(this); } set { throw new Exception("not implemented"); } } CSRAW virtual public int height { get { return Internal_GetHeight(this); } set { throw new Exception("not implemented"); } } AUTO_PROP FilterMode filterMode GetFilterMode SetFilterMode AUTO_PROP int anisoLevel GetAnisoLevel SetAnisoLevel AUTO_PROP TextureWrapMode wrapMode GetWrapMode SetWrapMode AUTO_PROP float mipMapBias GetMipMapBias SetMipMapBias // Workaround for gcc/msvc where passing small mono structures by value does not work CUSTOM private static void Internal_GetTexelSize (Texture tex, out Vector2 output) { Texture& texture = *tex; output->x = texture.GetTexelSizeX(); output->y = texture.GetTexelSizeY(); } CSRAW public Vector2 texelSize { get { Vector2 r; Internal_GetTexelSize(this, out r); return r; } } CUSTOM IntPtr GetNativeTexturePtr () { return self->GetNativeTexturePtr(); } CUSTOM int GetNativeTextureID () { return self->GetNativeTextureID(); } END CLASS Texture2D : Texture C++RAW #define CHECK_READABLE { if (!self->GetIsReadable()) Scripting::RaiseMonoException("Texture '%s' is not readable, the texture memory can not be accessed from scripts. You can make the texture readable in the Texture Import Settings.", self->GetName()); } // Check if reading of texture is allowed by crossdomain security and throw if not C++RAW static void CheckReadAllowedAndThrow(Texture2D *tex) { #if ENABLE_MONO && ENABLE_SECURITY if ( !tex->GetReadAllowed() ) Scripting::RaiseSecurityException("No read access to the texture data: %s", tex->GetName()); #endif } C++RAW static void CheckScreenReadAllowedAndThrow() { if ( !Texture2D::GetScreenReadAllowed() ) Scripting::RaiseSecurityException("Reading from the screen is not allowed when you have used a downloaded texture without proper crossdomain.xml authorization"); } AUTO_PROP int mipmapCount CountDataMipmaps CSRAW public Texture2D (int width, int height) { Internal_Create(this, width, height, TextureFormat.ARGB32, true, false, IntPtr.Zero); } CSRAW public Texture2D (int width, int height, TextureFormat format, bool mipmap) { Internal_Create(this, width, height, format, mipmap, false, IntPtr.Zero); } CSRAW public Texture2D (int width, int height, TextureFormat format, bool mipmap, bool linear) { Internal_Create(this, width, height, format, mipmap, linear, IntPtr.Zero); } CUSTOM private static void Internal_Create ([Writable]Texture2D mono, int width, int height, TextureFormat format, bool mipmap, bool linear, IntPtr nativeTex) { if(!GetBuildSettings().hasAdvancedVersion && nativeTex != 0) { Scripting::RaiseMonoException("Creating texture from native texture is PRO only."); return; } Texture2D* texture = NEW_OBJECT_MAIN_THREAD (Texture2D); texture->Reset(); if (texture->InitTexture(width, height, format, mipmap ? Texture2D::kMipmapMask : Texture2D::kNoMipmap, 1, (intptr_t)nativeTex)) { texture->SetStoredColorSpace (linear ? kTexColorSpaceLinear : kTexColorSpaceSRGB); Scripting::ConnectScriptingWrapperToObject (mono.GetScriptingObject(), texture); texture->AwakeFromLoad(kInstantiateOrCreateFromCodeAwakeFromLoad); } else { DestroySingleObject (texture); Scripting::RaiseMonoException("Failed to create texture because of invalid parameters."); } } CONDITIONAL ENABLE_TEXTUREID_MAP CSRAW internal Texture2D (int width, int height, TextureFormat format, bool mipmap, bool linear, IntPtr nativeTex) { Internal_Create(this, width, height, format, mipmap, linear, nativeTex); } CONDITIONAL ENABLE_TEXTUREID_MAP CSRAW static public Texture2D CreateExternalTexture(int width, int height, TextureFormat format, bool mipmap, bool linear, IntPtr nativeTex) { return new Texture2D(width, height, format, mipmap, linear, nativeTex); } CONDITIONAL ENABLE_TEXTUREID_MAP CUSTOM public void UpdateExternalTexture(IntPtr nativeTex) { if(!GetBuildSettings().hasAdvancedVersion) { Scripting::RaiseMonoException("Updating native texture is PRO only."); return; } GetGfxDevice().UpdateExternalTextureFromNative(self->GetTextureID(), (intptr_t)nativeTex); } AUTO_PROP TextureFormat format GetTextureFormat CUSTOM void SetPixel (int x, int y, Color color) { CHECK_READABLE self->SetPixel (0, x, y, color); } CUSTOM Color GetPixel (int x, int y) { CHECK_READABLE CheckReadAllowedAndThrow(self); return self->GetPixel (0, x, y); } CUSTOM Color GetPixelBilinear (float u, float v) { CHECK_READABLE CheckReadAllowedAndThrow(self); return self->GetPixelBilinear (0, u, v); } CSRAW public void SetPixels(Color[] colors, int miplevel = 0) { int w = width >> miplevel; if( w < 1 ) w = 1; int h = height >> miplevel; if( h < 1 ) h = 1; SetPixels( 0, 0, w, h, colors, miplevel ); } CUSTOM void SetPixels(int x, int y, int blockWidth, int blockHeight, Color[] colors, int miplevel = 0) { CHECK_READABLE self->SetPixels( x, y, blockWidth, blockHeight, GetScriptingArraySize(colors), Scripting::GetScriptingArrayStart(colors), miplevel ); } CUSTOM void SetPixels32(Color32[] colors, int miplevel = 0) { CHECK_READABLE self->SetPixels32( miplevel, Scripting::GetScriptingArrayStart(colors), GetScriptingArraySize(colors) ); } CUSTOM bool LoadImage (byte[] data) { return LoadMemoryBufferIntoTexture(*self, Scripting::GetScriptingArrayStart(data), GetScriptingArraySize(data), IsCompressedDXTTextureFormat(self->GetTextureFormat())?kLoadImageDXTCompressDithered:kLoadImageUncompressed); } CUSTOM void LoadRawTextureData(byte[] data) { CHECK_READABLE if(GetScriptingArraySize(data) < self->GetRawImageDataSize()) { Scripting::RaiseMonoException("LoadRawTextureData: not enough data provided (will result in overread)."); return; } ::memcpy(self->GetRawImageData(), Scripting::GetScriptingArrayStart(data), self->GetRawImageDataSize()); } CSRAW public Color[] GetPixels(int miplevel = 0) { int w = width >> miplevel; if( w < 1 ) w = 1; int h = height >> miplevel; if( h < 1 ) h = 1; return GetPixels( 0, 0, w, h, miplevel ); } CUSTOM Color[] GetPixels(int x, int y, int blockWidth, int blockHeight, int miplevel = 0) { CHECK_READABLE CheckReadAllowedAndThrow(self); int res = blockWidth * blockHeight; if (blockWidth != 0 && blockHeight != res / blockWidth) { return SCRIPTING_NULL; } ScriptingArrayPtr colors = CreateScriptingArray(GetScriptingManager().GetCommonClasses().color, blockWidth * blockHeight); ColorRGBAf* firstElement = Scripting::GetScriptingArrayStart(colors); self->GetPixels( x, y, blockWidth, blockHeight, miplevel, firstElement); return colors; } CUSTOM public Color32[] GetPixels32(int miplevel = 0) { CHECK_READABLE CheckReadAllowedAndThrow(self); int w = self->GetDataWidth() >> miplevel; if( w < 1 ) w = 1; int h = self->GetDataHeight() >> miplevel; if( h < 1 ) h = 1; ScriptingArrayPtr colors = CreateScriptingArray(GetScriptingManager().GetCommonClasses().color32, w * h); ColorRGBA32* firstElement = Scripting::GetScriptingArrayStart(colors); self->GetPixels32( miplevel, firstElement); return colors; } CUSTOM void Apply (bool updateMipmaps=true, bool makeNoLongerReadable=false) { CHECK_READABLE self->Apply(updateMipmaps, makeNoLongerReadable); } CUSTOM public bool Resize (int width, int height, TextureFormat format, bool hasMipMap) { return self->ResizeWithFormat (width, height, format, hasMipMap ? Texture2D::kMipmapMask : Texture2D::kNoMipmap); } CSRAW public bool Resize (int width, int height) { return Internal_ResizeWH(width, height); } CUSTOM private bool Internal_ResizeWH (int width, int height) { CHECK_READABLE return self->Resize(width, height); } AUTO void Compress (bool highQuality); CUSTOM Rect[] PackTextures( Texture2D[] textures, int padding, int maximumAtlasSize = 2048, bool makeNoLongerReadable = false ) { int textureCount = GetScriptingArraySize(textures); Texture2D** texturePtrs = new Texture2D*[textureCount]; for( int i = 0; i < textureCount; ++i ) { Texture2D* tex = ScriptingObjectToObject(Scripting::GetScriptingArrayElementNoRef(textures,i)); if (tex && !tex->GetIsReadable()) { ErrorString("Texture atlas needs textures to have Readable flag set!"); tex = NULL; } texturePtrs[i] = tex; } ScriptingArrayPtr rects = CreateScriptingArray(GetScriptingManager().GetCommonClasses().rect, textureCount); Rectf* firstElement = Scripting::GetScriptingArrayStart(rects); if( !PackTextureAtlasSimple( &*self, maximumAtlasSize, textureCount, texturePtrs, firstElement, padding, true, makeNoLongerReadable ) ) { delete[] texturePtrs; // TODO: error return SCRIPTING_NULL; } delete[] texturePtrs; return rects; } CUSTOM void ReadPixels (Rect source, int destX, int destY, bool recalculateMipMaps = true) { #if !UNITY_FLASH CHECK_READABLE CheckScreenReadAllowedAndThrow(); bool flipVertical = GetGfxDevice().GetInvertProjectionMatrix(); self->ReadPixels (0, (int)source.x, (int)source.y, (int)source.Width(), (int)source.Height(), destX, destY, flipVertical, recalculateMipMaps); #elif UNITY_FLASH printf_console("ReadPixels is unsupported on Flash"); #endif } CUSTOM byte[] EncodeToPNG () { #if ENABLE_PNG_JPG CHECK_READABLE CheckReadAllowedAndThrow(self); Texture2D* tex = self; if( !tex ) { ErrorString( "EncodeToPNG failed: texture is null" ); return SCRIPTING_NULL; } dynamic_array buffer; if( !tex->EncodeToPNG( buffer ) ) { return SCRIPTING_NULL; } return CreateScriptingArray( &buffer[0], buffer.size(), GetScriptingManager().GetCommonClasses().byte ); #else return SCRIPTING_NULL; #endif } CONDITIONAL UNITY_EDITOR AUTO_PROP bool alphaIsTransparency GetAlphaIsTransparency SetAlphaIsTransparency END CLASS Cubemap : Texture CUSTOM void SetPixel (CubemapFace face, int x, int y, Color color) { CHECK_READABLE self->SetPixel (face, x, y, color); } CUSTOM Color GetPixel (CubemapFace face, int x, int y) { CHECK_READABLE return self->GetPixel (face, x, y); } CUSTOM Color[] GetPixels(CubemapFace face, int miplevel = 0) { CHECK_READABLE int size = std::max(self->GetDataWidth() >> miplevel, 1); ScriptingArrayPtr colors = CreateScriptingArray(GetScriptingManager().GetCommonClasses().color, size*size); ColorRGBAf* firstElement = Scripting::GetScriptingArrayStart(colors); self->GetPixels( 0, 0, size, size, miplevel, firstElement, (int)face ); return colors; } CUSTOM void SetPixels(Color[] colors, CubemapFace face, int miplevel = 0) { CHECK_READABLE int size = std::max(self->GetDataWidth() >> miplevel, 1); self->SetPixels( 0, 0, size, size, GetScriptingArraySize(colors), Scripting::GetScriptingArrayStart(colors), miplevel, (int)face ); } CUSTOM void Apply (bool updateMipmaps = true, bool makeNoLongerReadable=false) { #if !UNITY_EDITOR CHECK_READABLE #endif if(makeNoLongerReadable) { self->SetIsReadable(false); self->SetIsUnreloadable(true); } if (updateMipmaps) self->UpdateImageData(); else self->UpdateImageDataDontTouchMipmap(); } AUTO_PROP TextureFormat format GetTextureFormat CSRAW public Cubemap (int size, TextureFormat format, bool mipmap) { Internal_Create(this, size, format, mipmap); } CUSTOM private static void Internal_Create ([Writable]Cubemap mono, int size, TextureFormat format, bool mipmap) { Cubemap* texture = NEW_OBJECT_MAIN_THREAD (Cubemap); texture->Reset(); if (texture->InitTexture(size, size, format, mipmap ? Texture2D::kMipmapMask : Texture2D::kNoMipmap, 6)) { Scripting::ConnectScriptingWrapperToObject (mono.GetScriptingObject(), texture); texture->AwakeFromLoad(kInstantiateOrCreateFromCodeAwakeFromLoad); } else { Scripting::RaiseMonoException("Failed to create texture because of invalid parameters."); } } CUSTOM void SmoothEdges (int smoothRegionWidthInPixels = 1) { self->FixupEdges (smoothRegionWidthInPixels); } END CLASS Texture3D : Texture AUTO_PROP int depth GetDepth CUSTOM Color[] GetPixels(int miplevel = 0) { int w = std::max(self->GetDataWidth() >> miplevel, 1); int h = std::max(self->GetDataHeight() >> miplevel, 1); int d = std::max(self->GetDepth() >> miplevel, 1); ScriptingArrayPtr colors = CreateScriptingArray(GetScriptingManager().GetCommonClasses().color, w*h*d); ColorRGBAf* firstElement = Scripting::GetScriptingArrayStart(colors); self->GetPixels (firstElement, miplevel); return colors; } CUSTOM void SetPixels(Color[] colors, int miplevel = 0) { int arrSize = GetScriptingArraySize(colors); const ColorRGBAf* ptr = Scripting::GetScriptingArrayStart(colors); self->SetPixels (arrSize, ptr, miplevel); } CUSTOM void Apply (bool updateMipmaps = true) { self->UpdateImageData (updateMipmaps); } AUTO_PROP TextureFormat format GetTextureFormat CSRAW public Texture3D (int width, int height, int depth, TextureFormat format, bool mipmap) { Internal_Create(this, width, height, depth, format, mipmap); } CUSTOM private static void Internal_Create ([Writable]Texture3D mono, int width, int height, int depth, TextureFormat format, bool mipmap) { Texture3D* texture = NEW_OBJECT_MAIN_THREAD (Texture3D); texture->Reset(); if (texture->InitTexture(width, height, depth, format, mipmap)) { Scripting::ConnectScriptingWrapperToObject (mono.GetScriptingObject(), texture); texture->AwakeFromLoad(kInstantiateOrCreateFromCodeAwakeFromLoad); } else { Scripting::RaiseMonoException("Failed to create texture because of invalid parameters."); } } END CLASS RenderTexture : Texture CUSTOM private static void Internal_CreateRenderTexture ([Writable]RenderTexture rt) { RenderTexture* texture = NEW_OBJECT_MAIN_THREAD (RenderTexture); texture->SetCreatedFromScript(true); texture->Reset(); Scripting::ConnectScriptingWrapperToObject (rt.GetScriptingObject(), texture); texture->AwakeFromLoad(kInstantiateOrCreateFromCodeAwakeFromLoad); } CSRAW public RenderTexture (int width, int height, int depth, RenderTextureFormat format, RenderTextureReadWrite readWrite) { Internal_CreateRenderTexture (this); this.width = width; this.height = height; this.depth = depth; this.format = format; bool sRGB = readWrite == RenderTextureReadWrite.sRGB; if (readWrite == RenderTextureReadWrite.Default) { sRGB = QualitySettings.activeColorSpace == ColorSpace.Linear; } Internal_SetSRGBReadWrite (this, sRGB); this.isPowerOfTwo = Mathf.IsPowerOfTwo(width) && Mathf.IsPowerOfTwo(height); } CSRAW public RenderTexture (int width, int height, int depth, RenderTextureFormat format) { Internal_CreateRenderTexture (this); this.width = width; this.height = height; this.depth = depth; this.format = format; Internal_SetSRGBReadWrite (this, QualitySettings.activeColorSpace == ColorSpace.Linear); this.isPowerOfTwo = Mathf.IsPowerOfTwo(width) && Mathf.IsPowerOfTwo(height); } CSRAW public RenderTexture (int width, int height, int depth) { Internal_CreateRenderTexture (this); this.width = width; this.height = height; this.depth = depth; this.format = RenderTextureFormat.Default; Internal_SetSRGBReadWrite (this, QualitySettings.activeColorSpace == ColorSpace.Linear); this.isPowerOfTwo = Mathf.IsPowerOfTwo(width) && Mathf.IsPowerOfTwo(height); } CUSTOM static RenderTexture GetTemporary (int width, int height, int depthBuffer = 0, RenderTextureFormat format = RenderTextureFormat.Default, RenderTextureReadWrite readWrite = RenderTextureReadWrite.Default, int antiAliasing = 1) { DepthBufferFormat depthFormat = DepthBufferFormatFromBits(depthBuffer); UInt32 flags = RenderBufferManager::kRBCreatedFromScript; return Scripting::ScriptingWrapperFor (GetRenderBufferManager().GetTempBuffer (width, height, depthFormat, static_cast(format), flags, readWrite, antiAliasing)); } CUSTOM static void ReleaseTemporary (RenderTexture temp) { GetRenderBufferManager().ReleaseTempBuffer (temp); } CUSTOM private static int Internal_GetWidth (RenderTexture mono) { return mono->GetWidth(); } CUSTOM private static void Internal_SetWidth (RenderTexture mono, int width) { mono->SetWidth(width); } CUSTOM private static int Internal_GetHeight (RenderTexture mono) { return mono->GetHeight(); } CUSTOM private static void Internal_SetHeight (RenderTexture mono, int width) { mono->SetHeight(width); } CUSTOM private static void Internal_SetSRGBReadWrite (RenderTexture mono, bool sRGB) { mono->SetSRGBReadWrite(sRGB); } CSRAW override public int width { get { return Internal_GetWidth(this); } set { Internal_SetWidth(this,value); } } CSRAW override public int height { get { return Internal_GetHeight(this); } set { Internal_SetHeight(this,value); } } CUSTOM_PROP int depth { DepthBufferFormat depthFormat = self->GetDepthFormat(); static int kDepthFormatBits[kDepthFormatCount] = { 0, 16, 24 }; return kDepthFormatBits[depthFormat]; } { DepthBufferFormat depthFormat = DepthBufferFormatFromBits(value); self->SetDepthFormat( depthFormat ); } CUSTOM_PROP bool isPowerOfTwo { return self->GetIsPowerOfTwo(); } { } CUSTOM_PROP bool sRGB { return self->GetSRGBReadWrite(); } CUSTOM_PROP RenderTextureFormat format { return self->GetColorFormat(); } { self->SetColorFormat( static_cast(value) ); } AUTO_PROP bool useMipMap GetMipMap SetMipMap AUTO_PROP bool generateMips GetGenerateMips SetGenerateMips CUSTOM_PROP bool isCubemap { return self->GetDimension()==kTexDimCUBE; } { self->SetDimension (value ? kTexDimCUBE : kTexDim2D); } CUSTOM_PROP bool isVolume { return self->GetDimension()==kTexDim3D; } { self->SetDimension (value ? kTexDim3D : kTexDim2D); } CUSTOM_PROP int volumeDepth { return self->GetVolumeDepth(); } { self->SetVolumeDepth(value); } AUTO_PROP int antiAliasing GetAntiAliasing SetAntiAliasing AUTO_PROP bool enableRandomWrite GetEnableRandomWrite SetEnableRandomWrite AUTO bool Create (); AUTO void Release (); AUTO bool IsCreated (); AUTO void DiscardContents(); CUSTOM void DiscardContents(bool discardColor, bool discardDepth) { self->DiscardContents(discardColor, discardDepth); } AUTO void MarkRestoreExpected(); CSRAW public RenderBuffer colorBuffer { get { RenderBuffer res; GetColorBuffer (out res); return res; } } CSRAW public RenderBuffer depthBuffer { get { RenderBuffer res; GetDepthBuffer (out res); return res; } } CUSTOM private void GetColorBuffer (out RenderBuffer res) { RenderTexture* rt = self; if (rt) { res->m_RenderTextureInstanceID = rt->GetInstanceID(); if (!rt->IsCreated()) rt->Create(); res->m_BufferPtr = rt->GetColorSurfaceHandle().object; } else { res->m_RenderTextureInstanceID = 0; res->m_BufferPtr = NULL; } } CUSTOM private void GetDepthBuffer (out RenderBuffer res) { RenderTexture* rt = self; if (rt) { res->m_RenderTextureInstanceID = rt->GetInstanceID(); if (!rt->IsCreated()) rt->Create(); res->m_BufferPtr = rt->GetDepthSurfaceHandle().object; } else { res->m_RenderTextureInstanceID = 0; res->m_BufferPtr = NULL; } } CUSTOM void SetGlobalShaderProperty (string propertyName) { self->SetGlobalProperty (ScriptingStringToProperty (propertyName)); } CUSTOM_PROP static RenderTexture active { return Scripting::ScriptingWrapperFor (RenderTexture::GetActive ()); } { RenderTexture::SetActive (value); RenderTexture::FindAndSetSRGBWrite (value); } OBSOLETE warning Use SystemInfo.supportsRenderTextures instead. CUSTOM_PROP static bool enabled { return RenderTexture::IsEnabled (); } { RenderTexture::SetEnabled (value); } CUSTOM private static void Internal_GetTexelOffset (RenderTexture tex, out Vector2 output) { if( GetGfxDevice().UsesHalfTexelOffset() ) { RenderTexture& renderTex = *tex; output->x = renderTex.GetTexelSizeX() * 0.5f; output->y = renderTex.GetTexelSizeY() * 0.5f; } else { output->x = 0.0f; output->y = 0.0f; } } CSRAW public Vector2 GetTexelOffset () { Vector2 r; Internal_GetTexelOffset(this, out r); return r; } CUSTOM public static bool SupportsStencil(RenderTexture rt) { return RenderTextureSupportsStencil(rt); } OBSOLETE error RenderTexture.SetBorderColor was removed CSRAW public void SetBorderColor (Color color) { } END CSRAW }