diff options
Diffstat (limited to 'Runtime/Camera/RenderLayers')
-rw-r--r-- | Runtime/Camera/RenderLayers/GUIElement.cpp | 31 | ||||
-rw-r--r-- | Runtime/Camera/RenderLayers/GUIElement.h | 30 | ||||
-rw-r--r-- | Runtime/Camera/RenderLayers/GUILayer.cpp | 104 | ||||
-rw-r--r-- | Runtime/Camera/RenderLayers/GUILayer.h | 33 | ||||
-rw-r--r-- | Runtime/Camera/RenderLayers/GUIText.cpp | 303 | ||||
-rw-r--r-- | Runtime/Camera/RenderLayers/GUIText.h | 93 | ||||
-rw-r--r-- | Runtime/Camera/RenderLayers/GUITexture.cpp | 524 | ||||
-rw-r--r-- | Runtime/Camera/RenderLayers/GUITexture.h | 73 |
8 files changed, 1191 insertions, 0 deletions
diff --git a/Runtime/Camera/RenderLayers/GUIElement.cpp b/Runtime/Camera/RenderLayers/GUIElement.cpp new file mode 100644 index 0000000..73ff0e0 --- /dev/null +++ b/Runtime/Camera/RenderLayers/GUIElement.cpp @@ -0,0 +1,31 @@ +#include "UnityPrefix.h" +#include "GUIElement.h" +#include "GUILayer.h" +#include "Runtime/Math/Vector2.h" + +GUIElement::GUIElement (MemLabelId label, ObjectCreationMode mode) +: Super(label, mode) +{ +} + +GUIElement::~GUIElement () +{ +} + +void GUIElement::AddToManager () +{ + GUILayer::ms_GUIElements->add_delayed (this); +} + +void GUIElement::RemoveFromManager () +{ + GUILayer::ms_GUIElements->remove_delayed (this); +} + +bool GUIElement::HitTest (const Vector2f& screenSpacePosition, const Rectf& cameraRect) +{ + Rectf rect = GetScreenRect (cameraRect); + return rect.Contains (screenSpacePosition.x, screenSpacePosition.y); +} + +IMPLEMENT_CLASS (GUIElement) diff --git a/Runtime/Camera/RenderLayers/GUIElement.h b/Runtime/Camera/RenderLayers/GUIElement.h new file mode 100644 index 0000000..0092da9 --- /dev/null +++ b/Runtime/Camera/RenderLayers/GUIElement.h @@ -0,0 +1,30 @@ +#ifndef GUIELEMENT_H +#define GUIELEMENT_H + +#include "Runtime/GameCode/Behaviour.h" +#include "Runtime/Math/Rect.h" +class Vector2f; + + +// Base class for all GUI elements. +// Registers itself with the GUILayer when enabled. +class GUIElement : public Behaviour +{ +public: + + REGISTER_DERIVED_ABSTRACT_CLASS (GUIElement, Behaviour) + + GUIElement (MemLabelId label, ObjectCreationMode mode); + + virtual void RenderGUIElement (const Rectf& cameraRect) = 0; + virtual Rectf GetScreenRect (const Rectf& cameraRect) = 0; + + bool HitTest (const Vector2f& screenSpaceCoordinates, const Rectf& cameraRect); + +private: + + virtual void AddToManager (); + virtual void RemoveFromManager (); +}; + +#endif diff --git a/Runtime/Camera/RenderLayers/GUILayer.cpp b/Runtime/Camera/RenderLayers/GUILayer.cpp new file mode 100644 index 0000000..69deeb8 --- /dev/null +++ b/Runtime/Camera/RenderLayers/GUILayer.cpp @@ -0,0 +1,104 @@ +#include "UnityPrefix.h" +#include "GUILayer.h" +#include "Runtime/Camera/Camera.h" +#include "Runtime/Graphics/Transform.h" +#include "Runtime/Camera/RenderManager.h" +#include "Runtime/Math/Vector2.h" +#include "Runtime/BaseClasses/Tags.h" +#include "Runtime/Allocator/MemoryMacros.h" +#include "Runtime/Profiler/ExternalGraphicsProfiler.h" + +PROFILER_INFORMATION(gGUILayerProfile, "Camera.GUILayer", kProfilerRender); + +GUILayer::GUIElements* GUILayer::ms_GUIElements = NULL; + +GUILayer::GUILayer(MemLabelId label, ObjectCreationMode mode) +: Super(label, mode) +{ +} + +GUILayer::~GUILayer () +{ +} + +inline bool SortGUIByDepth (GUIElement* lhs, GUIElement* rhs) +{ + return lhs->GetComponent (Transform).GetLocalPosition ().z < rhs->GetComponent (Transform).GetLocalPosition ().z; +} + +void GUILayer::InitializeClass () +{ + ms_GUIElements = new GUIElements; +} + +void GUILayer::CleanupClass() +{ + delete ms_GUIElements; +} + + +void GUILayer::RenderGUILayer () +{ + PROFILER_AUTO_GFX(gGUILayerProfile, this); + + ms_GUIElements->apply_delayed (); + if (ms_GUIElements->empty()) + return; + + typedef UNITY_TEMP_VECTOR(GUIElement*) TempElements; + TempElements elements (ms_GUIElements->begin (), ms_GUIElements->end ()); + + std::sort (elements.begin (), elements.end (), SortGUIByDepth); + + Camera& camera = GetComponent(Camera); + UInt32 cullingMask = camera.GetCullingMask (); + Rectf cameraRect = camera.GetScreenViewportRect(); + + for (TempElements::iterator it=elements.begin(), itEnd = elements.end(); it != itEnd; ++it) + { + GUIElement& element = **it; + if (element.GetGameObject ().GetLayerMask () & cullingMask) + element.RenderGUIElement (cameraRect); + } +} + +GUIElement* GUILayer::HitTest (const Vector2f& screenPosition) +{ + Camera& camera = GetComponent (Camera); + Vector3f viewportPos3D = camera.ScreenToViewportPoint (Vector3f (screenPosition.x, screenPosition.y, camera.GetNear())); + Vector2f viewportPos (viewportPos3D.x, viewportPos3D.y); + Rectf normalized (0.0F,0.0F,1.0F,1.0F); + + if (!normalized.Contains (viewportPos.x, viewportPos.y)) + return NULL; + + Rectf cameraRect = camera.GetScreenViewportRect(); + + Rectf windowRect = GetRenderManager ().GetWindowRect (); + viewportPos.x *= windowRect.Width (); + viewportPos.y *= windowRect.Height (); + + GUIElement* topmost = NULL; + float topmostZ = -std::numeric_limits<float>::infinity (); + + // GUI hit testing always ignores IgnoreRaycast layer + UInt32 cullingMask = camera.GetCullingMask() & ~(kIgnoreRaycastMask); + + for (GUIElements::iterator it=ms_GUIElements->begin (), itEnd = ms_GUIElements->end (); it != itEnd; ++it) + { + GUIElement* element = *it; + if (element && (element->GetGameObject ().GetLayerMask () & cullingMask) && element->HitTest (viewportPos, cameraRect)) + { + float z = element->GetComponent (Transform).GetLocalPosition ().z; + if (z > topmostZ) + { + topmost = element; + topmostZ = z; + } + } + } + + return topmost; +} + +IMPLEMENT_CLASS_HAS_INIT(GUILayer) diff --git a/Runtime/Camera/RenderLayers/GUILayer.h b/Runtime/Camera/RenderLayers/GUILayer.h new file mode 100644 index 0000000..925b070 --- /dev/null +++ b/Runtime/Camera/RenderLayers/GUILayer.h @@ -0,0 +1,33 @@ +#ifndef GUILAYER_H +#define GUILAYER_H + +#include "GUIElement.h" +#include "Runtime/GameCode/Behaviour.h" +#include "Runtime/Utilities/delayed_set.h" + +/// A GUI Layer is attached to the camera. +/// It tracks all enabled GUIElements (eg. Text, GUITexture) and renders them +class GUILayer : public Behaviour +{ +public: + REGISTER_DERIVED_CLASS (GUILayer, Behaviour) + + GUILayer (MemLabelId label, ObjectCreationMode mode); + + void RenderGUILayer(); + GUIElement* HitTest (const Vector2f& screenPosition); + + static void InitializeClass (); + static void CleanupClass (); + + // Behaviour + virtual void AddToManager() { }; + virtual void RemoveFromManager() { }; + +private: + typedef delayed_set <PPtr<GUIElement> > GUIElements; + static GUIElements* ms_GUIElements; + friend class GUIElement; +}; + +#endif diff --git a/Runtime/Camera/RenderLayers/GUIText.cpp b/Runtime/Camera/RenderLayers/GUIText.cpp new file mode 100644 index 0000000..9602bdd --- /dev/null +++ b/Runtime/Camera/RenderLayers/GUIText.cpp @@ -0,0 +1,303 @@ +#include "UnityPrefix.h" +#include "GUIText.h" +#include "Runtime/Filters/Misc/Font.h" +#include "Runtime/Misc/ResourceManager.h" +#include "Runtime/Graphics/Transform.h" +#include "Runtime/IMGUI/TextMeshGenerator2.h" +#include "Runtime/Shaders/Material.h" +#include "Runtime/Filters/Mesh/Mesh.h" +#include "Runtime/Camera/RenderManager.h" +#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h" +#include "Runtime/Shaders/Shader.h" +#include "Runtime/GfxDevice/GfxDevice.h" +#include "Runtime/Shaders/VBO.h" +#include "Runtime/Camera/CameraUtil.h" +#include "External/shaderlab/Library/intshader.h" +#include "Runtime/Profiler/Profiler.h" + +static Font* gDefaultFont = NULL; + +GUIText::GUIText (MemLabelId label, ObjectCreationMode mode) +: Super(label, mode) +{ + m_FontSize = 0; + m_FontStyle = 0; + m_RichText = true; + m_Color = 0xffffffff; +} + +GUIText::~GUIText () +{ +} + +Font * GUIText::GetFont () const { + Font *f = m_Font; + if (!f) { + if (!gDefaultFont) + gDefaultFont = GetBuiltinResource<Font> (kDefaultFontName); + return gDefaultFont; + } + else { + return f; + } + +} + +PROFILER_INFORMATION(gRenderGUIText, "GUIText.Render", kProfilerGUI) +PROFILER_INFORMATION(gSubmitVBOProfileGUIText, "Mesh.SubmitVBO", kProfilerRender) + +void GUIText::RenderGUIElement (const Rectf& cameraRect) +{ + if (m_Text.empty ()) + return; + + PROFILER_AUTO(gRenderGUIText, this) + + pair<Font*, Material*> temp = GetFontAndMaterial (); + Font* font = temp.first; + Material* material = temp.second; + if (font == NULL || material == NULL) + return; + + TextMeshGenerator2 &tmgen = TextMeshGenerator2::Get (UTF16String(m_Text.c_str()), font, (TextAnchor)m_Anchor, (TextAlignment)m_Alignment, 0, m_TabSize, m_LineSpacing, m_RichText, m_PixelCorrect, m_Color, m_FontSize, m_FontStyle); + + GfxDevice& device = GetGfxDevice(); + DeviceMVPMatricesState preserveMVP; // save MVP matrices, restore when returning from this function! + + Vector2f size = tmgen.GetSize (); + Vector2f offset = tmgen.GetTextOffset (Rectf (0, 0, -size.x, size.y * 2)); + switch (m_Alignment) + { + case kRight: offset.x += size.x; break; + case kCenter: + if (m_PixelCorrect) + offset.x += Roundf(size.x * 0.5f); + else + offset.x += size.x * 0.5f; + break; + } + Matrix4x4f textMatrix; + if (!m_PixelCorrect) + { + Matrix4x4f ortho; + ortho.SetOrtho( 0, 1, 0, 1, -1, 100 ); + device.SetProjectionMatrix (ortho); + + Transform& transform = GetComponent (Transform); + Vector3f position = transform.GetPosition (); + position.z = 0.0F; + Vector3f scale = transform.GetWorldScaleLossy (); + scale.x *= 0.05F * font->GetDeprecatedPixelScale (); + scale.y *= -0.05F * font->GetDeprecatedPixelScale (); + scale.z = 1.0F; + + position.x += offset.x * scale.x; + position.y -= offset.y * scale.y; + + textMatrix.SetTranslate( position ); + textMatrix.Scale( scale ); + } + else { + // Find out how large a rect the font should be rendered into, so that it is pixel correct. call the generator with this size. + Rectf rectNoOffset = cameraRect; + rectNoOffset.Move( -rectNoOffset.x, -rectNoOffset.y ); + LoadPixelMatrix( rectNoOffset, device, true, false ); + + Transform& transform = GetComponent (Transform); + Vector3f position = transform.GetPosition (); + position.z = 0.0F; + + textMatrix.SetTranslate( Vector3f( Roundf (position.x * cameraRect.Width() + m_PixelOffset.x), Roundf(position.y * cameraRect.Height() + m_PixelOffset.y), 0.0f ) ); + textMatrix.Scale( Vector3f( 1.0F, -1.0F, 1.0f ) ); + + textMatrix.Translate( Vector3f( offset.x, -offset.y, 0.0f ) ); + } + device.SetViewMatrix( textMatrix.GetPtr() ); + + int passCount = material->GetPassCount (); + for (int i=0;i < passCount ;i++) + { + const ChannelAssigns* channels = material->SetPass (i); + tmgen.RenderRaw (*channels); + } +} + + +void DrawGUIText (const std::string& text, Font* font, Material* material) +{ + if (text.empty()) + return; + if (font == NULL || material == NULL) + return; + + PROFILER_AUTO(gRenderGUIText, NULL) + + TextMeshGenerator2 &tmgen = TextMeshGenerator2::Get (UTF16String(text.c_str()), font, kUpperLeft, kAuto, 0, 0, 1.0f, false, true, 0xffffffff, 0, 0); + + static SHADERPROP (MainTex); + Texture* fontTexture = font->GetTexture(); + // In the case when font is a custum font, GetTexture() will return NULL, so in this case take the main texture from font's material + if (fontTexture == NULL && font->GetMaterial()) + { + fontTexture = font->GetMaterial()->GetTexture(kSLPropMainTex); + } + material->SetTexture(kSLPropMainTex, fontTexture); + + int passCount = material->GetPassCount (); + for (int i=0;i < passCount ;i++) + { + const ChannelAssigns* channels = material->SetPass (i); + tmgen.RenderRaw (*channels); + } +} + +Rectf GUIText::GetScreenRect (const Rectf& cameraRect) +{ + if (m_Text.empty ()) + return Rectf(); + + Font* font = GetFontAndMaterial ().first; + if (font == NULL) + return Rectf(); + + TextMeshGenerator2 &tmgen = TextMeshGenerator2::Get (UTF16String(m_Text.c_str()), font, (TextAnchor)m_Anchor, (TextAlignment)m_Alignment, 0, m_TabSize, m_LineSpacing, m_RichText, m_PixelCorrect, m_Color, m_FontSize, m_FontStyle); + Vector2f size = tmgen.GetSize (); + Vector2f offset = tmgen.GetTextOffset (Rectf (0, 0, -size.x, size.y * 2)); + Rectf rect (offset.x, -offset.y, size.x, size.y); + + Transform& transform = GetComponent (Transform); + if (!m_PixelCorrect) + { + Vector3f position = transform.GetPosition (); + position.z = 0.0F; + Vector3f scale = transform.GetWorldScaleLossy (); + scale.x *= 0.05F * font->GetDeprecatedPixelScale (); + scale.y *= -0.05F * font->GetDeprecatedPixelScale (); + scale.z = 1.0F; + + rect.Scale (scale.x, scale.y); + rect.Move (position.x, position.y); + Rectf windowRect = GetRenderManager ().GetWindowRect (); + rect.Scale (windowRect.Width (), windowRect.Height ()); + } + else + { + Rectf windowRect = GetRenderManager ().GetWindowRect (); + + Vector3f position = transform.GetPosition (); + position.x = Roundf (position.x * windowRect.Width() + m_PixelOffset.x); + position.y = Roundf (position.y * windowRect.Height() + m_PixelOffset.y); + + Vector3f scale = Vector3f (1.0F ,-1.0F,1); + + rect.Scale (scale.x, scale.y); + rect.Move (position.x, position.y); + } + if (rect.height < 0) + { + rect.height = -rect.height; + rect.y -= rect.height; + } + return rect; +} + +pair<Font*, Material*> GUIText::GetFontAndMaterial () +{ + Font* font = m_Font; + Material* material = m_Material; + if (font != NULL && material == NULL) + material = font->GetMaterial (); + + // Use default resource instead! + if (font == NULL || material == NULL) + { + if (gDefaultFont == NULL) + { + gDefaultFont = GetBuiltinResource<Font> (kDefaultFontName); + if (!gDefaultFont) + { + LogString ("Couldn't load default font!"); + return std::make_pair<Font*, Material*> (NULL, NULL); + } + if (!gDefaultFont->GetMaterial()) + { + LogString ("Couldn't load default font material!"); + return std::make_pair<Font*, Material*> (NULL, NULL); + } + } + + if (font == NULL) + font = gDefaultFont; + if (material == NULL) + material = gDefaultFont->GetMaterial(); + } + + return std::make_pair (font, material); +} + +void GUIText::Reset () +{ + Super::Reset (); + m_PixelCorrect = true; + m_Anchor = kUpperLeft; + m_Alignment = kLeft; + m_LineSpacing = 1.0F; + m_TabSize = 4.0F; + m_PixelOffset = Vector2f(0,0); +} + +Material* GUIText::GetMaterial () +{ + return GetFontAndMaterial ().second; +} + +void GUIText::SetMaterial (Material* material) +{ + m_Material = material; + SetDirty (); +} + +void GUIText::SetFont (PPtr<Font> font) +{ + m_Font = font; + SetDirty(); +} + + +template<class TransferFunction> inline +void GUIText::Transfer (TransferFunction& transfer) +{ + Super::Transfer (transfer); + transfer.SetVersion (3); + TRANSFER_SIMPLE(m_Text); + TRANSFER_SIMPLE(m_Anchor); + TRANSFER_SIMPLE(m_Alignment); + TRANSFER(m_PixelOffset); + TRANSFER(m_LineSpacing); + TRANSFER(m_TabSize); + TRANSFER(m_Font); + TRANSFER(m_Material); + TRANSFER(m_FontSize); + TRANSFER(m_FontStyle); + TRANSFER(m_Color); + + TRANSFER(m_PixelCorrect); + TRANSFER(m_RichText); + + #if UNITY_EDITOR + // Explanation: in verson 1.2.2 we added pixel correct drawing. By default it is on. + // for backwards compatbility we disable it + if(transfer.IsOldVersion(1)) + m_PixelCorrect = false; + + // In version 1.5.0 line spacing is multiplicative instead of additive + if(transfer.IsOldVersion(1) || transfer.IsOldVersion(2)) + { + Font* font = GetFont(); + m_LineSpacing = (font->GetLineSpacing() + m_LineSpacing) / font->GetLineSpacing(); + } + #endif +} + +IMPLEMENT_CLASS (GUIText) +IMPLEMENT_OBJECT_SERIALIZE (GUIText) diff --git a/Runtime/Camera/RenderLayers/GUIText.h b/Runtime/Camera/RenderLayers/GUIText.h new file mode 100644 index 0000000..fdfeeb9 --- /dev/null +++ b/Runtime/Camera/RenderLayers/GUIText.h @@ -0,0 +1,93 @@ +#ifndef GUITEXT_H +#define GUITEXT_H + +#include <string> +#include "GUIElement.h" +#include "Runtime/Math/Color.h" +#include "Runtime/Math/Vector2.h" + +class Font; +namespace Unity { class Material; } + +/// Can be Attached to any game object in the scene. +/// Registers with GUILayer, GUILayer renders it. +/// Position comes from transform.position.x,y +/// size comes from transform.scale.x,y +class GUIText : public GUIElement +{ + public: + + REGISTER_DERIVED_CLASS (GUIText, GUIElement) + DECLARE_OBJECT_SERIALIZE (GUIText) + + GUIText (MemLabelId label, ObjectCreationMode mode); + virtual void Reset (); + + const UnityStr& GetText () const { return m_Text; } + void SetText (const std::string& text) { m_Text = text; } + + // GUIElement + virtual void RenderGUIElement (const Rectf& cameraRect); + virtual Rectf GetScreenRect (const Rectf& cameraRect); + + void SetFont (PPtr<Font> font); + Font * GetFont () const; + + Material* GetMaterial (); + void SetMaterial (Material* material); + + void SetPixelOffset (const Vector2f& offset) { m_PixelOffset = offset; SetDirty(); } + Vector2f GetPixelOffset () { return m_PixelOffset; } + + void SetLineSpacing (float space) { m_LineSpacing = space; SetDirty(); } + float GetLineSpacing() const { return m_LineSpacing; } + + void SetTabSize (float size) { m_TabSize = size; SetDirty(); } + float GetTabSize() const { return m_TabSize; } + + void SetAlignment (int align) { m_Alignment = align; SetDirty(); } + int GetAlignment() const { return m_Alignment; } + + void SetAnchor (int size) { m_Anchor = size; SetDirty(); } + int GetAnchor() const { return m_Anchor; } + + void SetFontSize (int size) { m_FontSize = size; SetDirty(); } + int GetFontSize() const { return m_FontSize; } + + void SetFontStyle (int style) { m_FontStyle = style; SetDirty(); } + int GetFontStyle() const { return m_FontStyle; } + + void SetRichText (bool richText) { m_RichText = richText; SetDirty(); } + bool GetRichText() const { return m_RichText; } + + void SetColor (ColorRGBA32 color) { m_Color = color; SetDirty(); } + ColorRGBA32 GetColor() const { return m_Color; } + + private: + + std::pair<Font*, Material*> GetFontAndMaterial (); + + UnityStr m_Text; + + short m_Alignment; ///< enum { left, center, right } + short m_Anchor; ///< Where the text-mesh is anchored related to local origo. enum { upper left, upper center, upper right, middle left, middle center, middle right, lower left, lower center, lower right } + + float m_LineSpacing; ///< Spacing between lines as multiplum of height of a character. + float m_TabSize; ///< Length of one tab + bool m_PixelCorrect; ///< Place & scale the text to a pixel-correct position. + bool m_RichText;///< Enable HTML-style tags for text formatting. + Vector2f m_PixelOffset; + + int m_FontSize; ///<The font size to use. Set to 0 to use default font size. Only applicable for dynamic fonts. + int m_FontStyle; ///<The font style to use. Only applicable for dynamic fonts. enum { Normal, Bold, Italic, Bold and Italic } + + ColorRGBA32 m_Color; + + PPtr<Font> m_Font; + PPtr<Material> m_Material; +}; + + +void DrawGUIText (const std::string& text, Font* font, Material* material); + +#endif diff --git a/Runtime/Camera/RenderLayers/GUITexture.cpp b/Runtime/Camera/RenderLayers/GUITexture.cpp new file mode 100644 index 0000000..b30d7e4 --- /dev/null +++ b/Runtime/Camera/RenderLayers/GUITexture.cpp @@ -0,0 +1,524 @@ +#include "UnityPrefix.h" +#include "GUITexture.h" +#include "External/shaderlab/Library/texenv.h" +#include "Runtime/Graphics/Transform.h" +#include "Runtime/Shaders/Shader.h" +#include "Runtime/Shaders/Material.h" +#include "External/shaderlab/Library/properties.h" +#include "Runtime/Utilities/BitUtility.h" +#include "Runtime/GfxDevice/GfxDevice.h" +#include "Runtime/Shaders/VBO.h" +#include "Runtime/Camera/CameraUtil.h" +#include "Runtime/Shaders/GraphicsCaps.h" +#include "External/shaderlab/Library/intshader.h" +#include "Runtime/Profiler/Profiler.h" +#include "Runtime/Misc/ResourceManager.h" + +extern bool IsNPOTTextureAllowed(bool hasMipMap); + +static SHADERPROP (MainTex); +static Shader* gGUI2DShader = NULL; +static Material* gGUI2DMaterial = NULL; + + +// can't do in InitializeClass because graphics might not be created yet +static void InitializeGUIShaders() +{ + if( !gGUI2DMaterial ) + { + Shader* shader = GetBuiltinResource<Shader> ("Internal-GUITexture.shader"); + gGUI2DMaterial = Material::CreateMaterial (*shader, Object::kHideAndDontSave); + gGUI2DShader = gGUI2DMaterial->GetShader (); + } +} + +void GUITexture::InitializeClass () +{ +} + +void GUITexture::CleanupClass () +{ + gGUI2DShader = NULL; + gGUI2DMaterial = NULL; +} + +GUITexture::GUITexture (MemLabelId label, ObjectCreationMode mode) +: Super(label, mode) +{ + m_Sheet = NULL; + m_PrevTextureWidth = 0; + m_PrevTextureHeight = 0; + m_PrevTextureBaseLevel = Texture::GetMasterTextureLimit(); +} + +GUITexture::~GUITexture () +{ + SAFE_RELEASE_LABEL(m_Sheet, kMemShader); +} + +void GUITexture::BuildSheet() +{ + InitializeGUIShaders(); + + Texture* texture = m_Texture; + if( !texture ) + return; + + SAFE_RELEASE_LABEL(m_Sheet, kMemShader); + bool is2D = (texture->GetDimension () == kTexDim2D); + m_Sheet = gGUI2DShader->MakeProperties(); + m_Sheet->SetTexture (kSLPropMainTex, texture); + + ShaderLab::PropertySheet::TextureProperty* prop = m_Sheet->GetTextureProperty (kSLPropMainTex); + if (prop && prop->scaleOffsetValue) + { + // for NPOT textures (in case it is not supported) override the GL texture name and texture scale + // so that we use unscaled texture and ignore the padded dummy portion + bool isNPOT = !IsPowerOfTwo(m_PrevTextureWidth) || !IsPowerOfTwo(m_PrevTextureHeight); + if( is2D && isNPOT && !IsNPOTTextureAllowed(texture->HasMipMap()) ) + { + // Need to take master texture limit into account because that + // changes scaling... + int baseMipLevel = Texture::GetMasterTextureLimit(); + if( !texture->HasMipMap() ) + baseMipLevel = 0; + int texWidth = texture->GetDataWidth() >> baseMipLevel; + int texHeight = texture->GetDataHeight() >> baseMipLevel; + int actualWidth = texture->GetGLWidth() >> baseMipLevel; + int actualHeight = texture->GetGLHeight() >> baseMipLevel; + // ...and shifting above might produce zeros + float scaleX = (actualWidth > 0) ? float(texWidth) / float(actualWidth) : 1.0f; + float scaleY = (actualHeight > 0) ? float(texHeight) / float(actualHeight) : 1.0f; + scaleX *= texture->GetUVScaleX(); + scaleY *= texture->GetUVScaleY(); + prop->texEnv->OverrideTextureInfo( texture->GetUnscaledTextureID(), scaleX, scaleY ); + prop->scaleOffsetValue->Set (scaleX, scaleY, 0,0); + } + else + { + prop->scaleOffsetValue->Set (1,1,0,0); + } + } +} + +void GUITexture::AwakeFromLoad (AwakeFromLoadMode awakeMode) { + Super::AwakeFromLoad (awakeMode); + BuildSheet (); +} + +void GUITexture::SetTexture (Texture* tex) +{ + m_Texture = tex; + if( tex ) + { + m_PrevTextureWidth = tex->GetDataWidth(); + m_PrevTextureHeight = tex->GetDataHeight(); + } + m_PrevTextureBaseLevel = Texture::GetMasterTextureLimit(); + if( tex && !tex->HasMipMap() ) + m_PrevTextureBaseLevel = 0; + BuildSheet (); +} + +Texture* GUITexture::GetTexture () +{ + return m_Texture; +} + +void GUITexture::Reset () +{ + Super::Reset (); + m_Color = ColorRGBAf (.5, .5, .5, .5); + m_LeftBorder = m_RightBorder = m_TopBorder = m_BottomBorder = 0; + m_PixelInset = Rectf (0,0,0,0); +} + +void GUITexture::SetColor (const ColorRGBAf& color) { + m_Color = color; + BuildSheet (); + SetDirty (); +} + +struct GUITextureVertex { + Vector3f vert; + ColorRGBA32 color; + Vector2f uv; +}; + +static bool FillGUITextureVBOChunk( const Rectf &screenRect, Texture* tex, const Rectf &sourceRect, int leftBorder, int rightBorder, int topBorder, int bottomBorder, ColorRGBA32 color ) +{ + DebugAssertIf( !tex ); + Vector2f texScale (1.0f / (float)tex->GetDataWidth(), 1.0f / (float)tex->GetDataHeight()); + + float x0 = RoundfToInt(screenRect.x); + float x3 = RoundfToInt(screenRect.GetRight()); + + int y0 = RoundfToInt(screenRect.y); + int y3 = RoundfToInt(screenRect.GetBottom()); + + float x1 = x0 + (float)leftBorder; + float x2 = x3 - (float)rightBorder; + int y1 = int(y0 + (float)bottomBorder); + int y2 = int(y3 - (float)topBorder); + + float tx0 = sourceRect.x; + float tx1 = tx0 + texScale.x * (float)leftBorder; + float tx3 = sourceRect.GetRight(); + float tx2 = tx3 - texScale.x * (float)rightBorder; + + float ty0 = sourceRect.y; + float ty1 = ty0 + texScale.y * (float)bottomBorder; + float ty3 = sourceRect.GetBottom(); + float ty2 = ty3 - texScale.y * (float)topBorder; + + GUITextureVertex* vbPtr; + unsigned short* ibPtr; + DynamicVBO& vbo = GetGfxDevice().GetDynamicVBO(); + if( !vbo.GetChunk( + (1<<kShaderChannelVertex) | (1<<kShaderChannelColor) | (1<<kShaderChannelTexCoord0), + 16, // 16 vertices + 9*6, // 9 quads + DynamicVBO::kDrawIndexedTriangles, + (void**)&vbPtr, (void**)&ibPtr ) ) + { + return false; + } + + vbPtr[ 0].vert.Set( x0, y0, 0.0f ); vbPtr[ 0].color = color; vbPtr[ 0].uv.Set( tx0, ty0 ); + vbPtr[ 1].vert.Set( x1, y0, 0.0f ); vbPtr[ 1].color = color; vbPtr[ 1].uv.Set( tx1, ty0 ); + vbPtr[ 2].vert.Set( x2, y0, 0.0f ); vbPtr[ 2].color = color; vbPtr[ 2].uv.Set( tx2, ty0 ); + vbPtr[ 3].vert.Set( x3, y0, 0.0f ); vbPtr[ 3].color = color; vbPtr[ 3].uv.Set( tx3, ty0 ); + vbPtr[ 4].vert.Set( x0, y1, 0.0f ); vbPtr[ 4].color = color; vbPtr[ 4].uv.Set( tx0, ty1 ); + vbPtr[ 5].vert.Set( x1, y1, 0.0f ); vbPtr[ 5].color = color; vbPtr[ 5].uv.Set( tx1, ty1 ); + vbPtr[ 6].vert.Set( x2, y1, 0.0f ); vbPtr[ 6].color = color; vbPtr[ 6].uv.Set( tx2, ty1 ); + vbPtr[ 7].vert.Set( x3, y1, 0.0f ); vbPtr[ 7].color = color; vbPtr[ 7].uv.Set( tx3, ty1 ); + vbPtr[ 8].vert.Set( x0, y2, 0.0f ); vbPtr[ 8].color = color; vbPtr[ 8].uv.Set( tx0, ty2 ); + vbPtr[ 9].vert.Set( x1, y2, 0.0f ); vbPtr[ 9].color = color; vbPtr[ 9].uv.Set( tx1, ty2 ); + vbPtr[10].vert.Set( x2, y2, 0.0f ); vbPtr[10].color = color; vbPtr[10].uv.Set( tx2, ty2 ); + vbPtr[11].vert.Set( x3, y2, 0.0f ); vbPtr[11].color = color; vbPtr[11].uv.Set( tx3, ty2 ); + vbPtr[12].vert.Set( x0, y3, 0.0f ); vbPtr[12].color = color; vbPtr[12].uv.Set( tx0, ty3 ); + vbPtr[13].vert.Set( x1, y3, 0.0f ); vbPtr[13].color = color; vbPtr[13].uv.Set( tx1, ty3 ); + vbPtr[14].vert.Set( x2, y3, 0.0f ); vbPtr[14].color = color; vbPtr[14].uv.Set( tx2, ty3 ); + vbPtr[15].vert.Set( x3, y3, 0.0f ); vbPtr[15].color = color; vbPtr[15].uv.Set( tx3, ty3 ); + + static UInt16 ib[9*6] = { + 0, 4, 1, 1, 4, 5, + 1, 5, 2, 2, 5, 6, + 2, 6, 3, 3, 6, 7, + 4, 8, 5, 5, 8, 9, + 5, 9, 6, 6, 9, 10, + 6, 10, 7, 7, 10, 11, + 8, 12, 9, 9, 12, 13, + 9, 13, 10, 10, 13, 14, + 10, 14, 11, 11, 14, 15, + }; + memcpy( ibPtr, ib, sizeof(ib) ); + vbo.ReleaseChunk( 16, 9*6 ); + + return true; +} + +PROFILER_INFORMATION(gRenderGUITexture, "GUITexture.Render", kProfilerGUI) +PROFILER_INFORMATION(gSubmitVBOProfileGUITexture, "Mesh.SubmitVBO", kProfilerRender) + +void GUITexture::DrawGUITexture (const Rectf &bounds) +{ + PROFILER_AUTO(gRenderGUITexture, NULL) + + InitializeGUIShaders(); + + Shader* shader = gGUI2DShader; + + GfxDevice& device = GetGfxDevice(); + DynamicVBO& vbo = device.GetDynamicVBO(); + + ColorRGBA32 color = m_Color; + color = device.ConvertToDeviceVertexColor(color); + + if( !FillGUITextureVBOChunk( bounds, m_Texture, Rectf(0,0,1,1), m_LeftBorder, m_RightBorder, m_TopBorder, m_BottomBorder, color ) ) + return; + const ShaderLab::SubShader& ss = shader->GetShaderLabShader()->GetActiveSubShader(); + const int passCount = ss.GetValidPassCount(); + for( int i = 0; i != passCount; ++i ) + { + const ChannelAssigns* channels = shader->SetPass (0, i, 0, m_Sheet); + + PROFILER_BEGIN(gSubmitVBOProfileGUITexture, this) + vbo.DrawChunk (*channels); + GPU_TIMESTAMP(); + PROFILER_END + } +} + +void GUITexture::RenderGUIElement (const Rectf& cameraRect) +{ + Texture* tex = m_Texture; + if( !tex ) + return; + + // Before rendering check whether something serious has changed: + // * texture could have changed from POT to NPOT, or the size may have changed (at least in the editor) + // * global texture limit might have changed + int texWidth = tex->GetDataWidth(); + int texHeight = tex->GetDataHeight(); + int masterTexLimit = Texture::GetMasterTextureLimit(); + if( !tex->HasMipMap() ) + masterTexLimit = 0; + if( texWidth != m_PrevTextureWidth || texHeight != m_PrevTextureHeight || m_PrevTextureBaseLevel != masterTexLimit ) + { + m_PrevTextureWidth = texWidth; + m_PrevTextureHeight = texHeight; + m_PrevTextureBaseLevel = masterTexLimit; + BuildSheet(); + } + + GfxDevice& device = GetGfxDevice(); + DeviceMVPMatricesState preserveMVP; + + Rectf rectNoOffset = cameraRect; + rectNoOffset.Move( -rectNoOffset.x, -rectNoOffset.y ); + LoadPixelMatrix( rectNoOffset, device, true, false ); + + Rectf drawBox = CalculateDrawBox (cameraRect); + DrawGUITexture (drawBox); +} + +Rectf GUITexture::CalculateDrawBox (const Rectf& screenViewportRect) +{ + Transform& transform = GetComponent (Transform); + Rectf drawBox; + + Vector3f position = transform.GetPosition (); + Vector3f scale = transform.GetWorldScaleLossy (); + + float xmin = position.x - scale.x * 0.5F; + float xmax = position.x + scale.x * 0.5F; + + float ymin = position.y - scale.y * 0.5F; + float ymax = position.y + scale.y * 0.5F; + + drawBox.x = screenViewportRect.Width() * xmin + m_PixelInset.x; + drawBox.SetRight( screenViewportRect.Width() * xmax + m_PixelInset.GetRight() ); + drawBox.y = screenViewportRect.Height() * ymin + m_PixelInset.y; + drawBox.SetBottom( screenViewportRect.Height() * ymax + m_PixelInset.GetBottom() ); + + return drawBox; +} + +Rectf GUITexture::GetScreenRect (const Rectf& cameraRect) +{ + return CalculateDrawBox (cameraRect); +} + +template<class TransferFunction> +void GUITexture::Transfer (TransferFunction& transfer) +{ + Super::Transfer (transfer); + TRANSFER_SIMPLE (m_Texture); + TRANSFER_SIMPLE (m_Color); + + TRANSFER (m_PixelInset); + + TRANSFER (m_LeftBorder); + TRANSFER (m_RightBorder); + TRANSFER (m_TopBorder); + TRANSFER (m_BottomBorder); +} + +IMPLEMENT_CLASS_HAS_INIT (GUITexture) +IMPLEMENT_OBJECT_SERIALIZE (GUITexture) + +void DrawGUITexture (const Rectf &screenRect, Texture* texture, ColorRGBA32 color, Material* material) { + DrawGUITexture (screenRect, texture, 0,0,0,0, color, material); +} +void DrawGUITexture (const Rectf &screenRect, Texture* texture, int leftBorder, int rightBorder, int topBorder, int bottomBorder, ColorRGBA32 color, Material* material) { + DrawGUITexture (screenRect, texture, Rectf (0,0,1,1), leftBorder, rightBorder, topBorder, bottomBorder, color, material); +} + +void HandleGUITextureProps( ShaderLab::PropertySheet *sheet, Texture *texture ) +{ + sheet->SetTexture (kSLPropMainTex, texture); + + int texWidth = texture->GetDataWidth(); + int texHeight = texture->GetDataHeight(); + + ShaderLab::PropertySheet::TextureProperty* prop = sheet->GetTextureProperty (kSLPropMainTex); + if (prop && prop->scaleOffsetValue) + { + float uvScaleX = texture->GetUVScaleX(); + float uvScaleY = texture->GetUVScaleY(); + + // for NPOT textures (in case it is not supported) override the GL texture name and texture scale + // so that we use unscaled texture and ignore the padded dummy portion + bool isNPOT = !IsPowerOfTwo(texWidth) || !IsPowerOfTwo(texHeight); + if( texture->GetDimension() == kTexDim2D && isNPOT && !IsNPOTTextureAllowed(texture->HasMipMap()) ) + { + // Need to take master texture limit into account because that + // changes scaling... + int baseMipLevel = Texture::GetMasterTextureLimit(); + if (!texture->HasMipMap()) + baseMipLevel = 0; + texWidth = texWidth >> baseMipLevel; + texHeight = texHeight >> baseMipLevel; + int actualWidth = texture->GetGLWidth() >> baseMipLevel; + int actualHeight = texture->GetGLHeight() >> baseMipLevel; + // ...and shifting above might produce zeros + float scaleX = (actualWidth > 0) ? float(texWidth) / float(actualWidth) : 1.0f; + float scaleY = (actualHeight > 0) ? float(texHeight) / float(actualHeight) : 1.0f; + scaleX *= uvScaleX; + scaleY *= uvScaleY; + prop->texEnv->OverrideTextureInfo( texture->GetUnscaledTextureID(), scaleX, scaleY ); + prop->scaleOffsetValue->Set (scaleX, scaleY, 0, 0); + } + else + { + prop->scaleOffsetValue->Set (uvScaleX,uvScaleY,0,0); + } + } +} + +// Fills out the VBO with the new inverted-coordinate GUI rectangle + +static bool FillGUITextureVBOChunkInverted( const Rectf &screenRect, Texture* tex, const Rectf &sourceRect, int leftBorder, int rightBorder, int topBorder, int bottomBorder, ColorRGBA32 color, UInt32* outTriangles ) +{ + DebugAssertIf( !tex ); + Vector2f texScale (1.0f / (float)tex->GetDataWidth(), 1.0f / (float)tex->GetDataHeight()); + + float x0 = RoundfToInt(screenRect.x); + float x3 = RoundfToInt(screenRect.GetRight()); + float y0 = RoundfToInt(screenRect.GetBottom()); + float y3 = RoundfToInt(screenRect.y); + + float tx0 = sourceRect.x; + float tx3 = sourceRect.GetRight(); + float ty0 = sourceRect.y; + float ty3 = sourceRect.GetBottom(); + + GUITextureVertex* vbPtr; + unsigned short* ibPtr; + DynamicVBO& vbo = GetGfxDevice().GetDynamicVBO(); + + if ((leftBorder|rightBorder|topBorder|bottomBorder) == 0) + { + // no borders, texture is just a quad + if( !vbo.GetChunk( + (1<<kShaderChannelVertex) | (1<<kShaderChannelColor) | (1<<kShaderChannelTexCoord0), + 4, // 4 vertices + 6, // 1 quad + DynamicVBO::kDrawIndexedTriangles, + (void**)&vbPtr, (void**)&ibPtr ) ) + { + return false; + } + + vbPtr[ 0].vert.Set( x0, y0, 0.0f ); vbPtr[ 0].color = color; vbPtr[ 0].uv.Set( tx0, ty0 ); + vbPtr[ 1].vert.Set( x3, y0, 0.0f ); vbPtr[ 1].color = color; vbPtr[ 1].uv.Set( tx3, ty0 ); + vbPtr[ 2].vert.Set( x0, y3, 0.0f ); vbPtr[ 2].color = color; vbPtr[ 2].uv.Set( tx0, ty3 ); + vbPtr[ 3].vert.Set( x3, y3, 0.0f ); vbPtr[ 3].color = color; vbPtr[ 3].uv.Set( tx3, ty3 ); + static UInt16 ib[1*6] = { + 0, 2, 1, 1, 2, 3, + }; + memcpy( ibPtr, ib, sizeof(ib) ); + vbo.ReleaseChunk( 4, 6 ); + *outTriangles = 2; + } + else + { + // with borders, texture is a 3x3 quad grid + float x1 = x0 + (float)leftBorder; + float x2 = x3 - (float)rightBorder; + float y1 = y0 - (float)topBorder; + float y2 = y3 + (float)bottomBorder; + + float tx1 = tx0 + texScale.x * (float)leftBorder; + float tx2 = tx3 - texScale.x * (float)rightBorder; + float ty1 = ty0 + texScale.y * (float)topBorder; + float ty2 = ty3 - texScale.y * (float)bottomBorder; + + if( !vbo.GetChunk( + (1<<kShaderChannelVertex) | (1<<kShaderChannelColor) | (1<<kShaderChannelTexCoord0), + 16, // 16 vertices + 9*6, // 9 quads + DynamicVBO::kDrawIndexedTriangles, + (void**)&vbPtr, (void**)&ibPtr ) ) + { + return false; + } + + vbPtr[ 0].vert.Set( x0, y0, 0.0f ); vbPtr[ 0].color = color; vbPtr[ 0].uv.Set( tx0, ty0 ); + vbPtr[ 1].vert.Set( x1, y0, 0.0f ); vbPtr[ 1].color = color; vbPtr[ 1].uv.Set( tx1, ty0 ); + vbPtr[ 2].vert.Set( x2, y0, 0.0f ); vbPtr[ 2].color = color; vbPtr[ 2].uv.Set( tx2, ty0 ); + vbPtr[ 3].vert.Set( x3, y0, 0.0f ); vbPtr[ 3].color = color; vbPtr[ 3].uv.Set( tx3, ty0 ); + vbPtr[ 4].vert.Set( x0, y1, 0.0f ); vbPtr[ 4].color = color; vbPtr[ 4].uv.Set( tx0, ty1 ); + vbPtr[ 5].vert.Set( x1, y1, 0.0f ); vbPtr[ 5].color = color; vbPtr[ 5].uv.Set( tx1, ty1 ); + vbPtr[ 6].vert.Set( x2, y1, 0.0f ); vbPtr[ 6].color = color; vbPtr[ 6].uv.Set( tx2, ty1 ); + vbPtr[ 7].vert.Set( x3, y1, 0.0f ); vbPtr[ 7].color = color; vbPtr[ 7].uv.Set( tx3, ty1 ); + vbPtr[ 8].vert.Set( x0, y2, 0.0f ); vbPtr[ 8].color = color; vbPtr[ 8].uv.Set( tx0, ty2 ); + vbPtr[ 9].vert.Set( x1, y2, 0.0f ); vbPtr[ 9].color = color; vbPtr[ 9].uv.Set( tx1, ty2 ); + vbPtr[10].vert.Set( x2, y2, 0.0f ); vbPtr[10].color = color; vbPtr[10].uv.Set( tx2, ty2 ); + vbPtr[11].vert.Set( x3, y2, 0.0f ); vbPtr[11].color = color; vbPtr[11].uv.Set( tx3, ty2 ); + vbPtr[12].vert.Set( x0, y3, 0.0f ); vbPtr[12].color = color; vbPtr[12].uv.Set( tx0, ty3 ); + vbPtr[13].vert.Set( x1, y3, 0.0f ); vbPtr[13].color = color; vbPtr[13].uv.Set( tx1, ty3 ); + vbPtr[14].vert.Set( x2, y3, 0.0f ); vbPtr[14].color = color; vbPtr[14].uv.Set( tx2, ty3 ); + vbPtr[15].vert.Set( x3, y3, 0.0f ); vbPtr[15].color = color; vbPtr[15].uv.Set( tx3, ty3 ); + static UInt16 ib[9*6] = { + 0, 4, 1, 1, 4, 5, // Top-left + 1, 5, 2, 2, 5, 6, // Top-mid + 2, 6, 3, 3, 6, 7, // Top-right + 4, 8, 5, 5, 8, 9, // mid-left + 5, 9, 6, 6, 9, 10, // mid-center + 6, 10, 7, 7, 10, 11, // mid-right + 8, 12, 9, 9, 12, 13, // bottom-left + 9, 13, 10, 10, 13, 14, // bottom-mid + 10, 14, 11, 11, 14, 15, // bottom-right + }; + memcpy( ibPtr, ib, sizeof(ib) ); + vbo.ReleaseChunk( 16, 9*6 ); + *outTriangles = 9 * 2; + } + + return true; +} + +void DrawGUITexture (const Rectf &screenRect, Texture* tex, const Rectf &sourceRect, int leftBorder, int rightBorder, int topBorder, int bottomBorder, ColorRGBA32 color, Material* material) +{ + InitializeGUIShaders(); + + if( !tex ) + { + ErrorString ("DrawGUITexture: texture is null"); + return; + } + + GfxDevice& device = GetGfxDevice(); + color = device.ConvertToDeviceVertexColor( color ); + UInt32 triCount; + + // temp workaround to flip Y-axis. should probably be done in FillGUITextureVBOChunk - but for now we do it here + if( !FillGUITextureVBOChunkInverted( screenRect, tex, sourceRect, leftBorder, rightBorder, bottomBorder, topBorder, color, &triCount ) ) + return; + + if (material) + { + HandleGUITextureProps( &material->GetWritableProperties(), tex ); + } + else + { + HandleGUITextureProps( &gGUI2DMaterial->GetWritableProperties(), tex ); + material = gGUI2DMaterial; + } + + int passCount = material->GetPassCount(); + + DynamicVBO& vbo = device.GetDynamicVBO(); + + for( int i = 0; i < passCount; ++i) + { + const ChannelAssigns* channels = material->SetPass (i, 0, false); + + PROFILER_BEGIN(gSubmitVBOProfileGUITexture, NULL); + vbo.DrawChunk (*channels); + GPU_TIMESTAMP(); + PROFILER_END + } +} diff --git a/Runtime/Camera/RenderLayers/GUITexture.h b/Runtime/Camera/RenderLayers/GUITexture.h new file mode 100644 index 0000000..55988ae --- /dev/null +++ b/Runtime/Camera/RenderLayers/GUITexture.h @@ -0,0 +1,73 @@ +#ifndef GUITEXTURE_H +#define GUITEXTURE_H + +#include "GUIElement.h" +#include "Runtime/Graphics/Texture.h" +#include "Runtime/Math/Color.h" +#include "Runtime/Math/Rect.h" + + +namespace Unity { class Material; } +namespace ShaderLab { class PropertySheet; } + +// Attached to any game object in the scene. +// Registers with GUILayer, GUILayer renders it. +// Position comes from transform.position.x,y +// size comes from transform.scale.x,y +class GUITexture : public GUIElement +{ +public: + + REGISTER_DERIVED_CLASS (GUITexture, GUIElement) + DECLARE_OBJECT_SERIALIZE (GUITexture) + + GUITexture (MemLabelId label, ObjectCreationMode mode); + + virtual void Reset (); + + // GUIElement + virtual void RenderGUIElement (const Rectf& cameraRect); + virtual Rectf GetScreenRect (const Rectf& cameraRect); + + virtual void AwakeFromLoad(AwakeFromLoadMode mode); + + void SetColor (const ColorRGBAf& color); + inline ColorRGBAf GetColor () { return m_Color; } + + void SetTexture (Texture* tex); + Texture* GetTexture (); + + int m_LeftBorder; ///< The border pixels - this part of texture is never scaled. + int m_RightBorder; ///< The border pixels - this part of texture is never scaled. + int m_TopBorder; ///< The border pixels - this part of texture is never scaled. + int m_BottomBorder; ///< The border pixels - this part of texture is never scaled. + + PPtr<Texture> m_Texture; ///< The texture to use. + ColorRGBAf m_Color; ///< Tint color. + + static void InitializeClass(); + static void CleanupClass(); + + const Rectf &GetPixelInset() const { return m_PixelInset; } + void SetPixelInset(const Rectf &r) { m_PixelInset = r; SetDirty(); } + +private: + void DrawGUITexture (const Rectf& bounds); + void BuildSheet (); + Rectf CalculateDrawBox (const Rectf& screenViewportRect); + + Rectf m_PixelInset; + + ShaderLab::PropertySheet *m_Sheet; + int m_PrevTextureWidth; + int m_PrevTextureHeight; + int m_PrevTextureBaseLevel; +}; + +// Immediate mode DrawGUITexture API +void DrawGUITexture (const Rectf &screenRect, Texture* texture, const Rectf &sourceRect, int leftBorder, int rightBorder, int topBorder, int bottomBorder, ColorRGBA32 color, Material* material = NULL); +void DrawGUITexture (const Rectf &screenRect, Texture* texture, int leftBorder, int rightBorder, int topBorder, int bottomBorder, ColorRGBA32 color, Material* material = NULL); +void DrawGUITexture (const Rectf &screenRect, Texture* texture, ColorRGBA32 color, Material* material = NULL); +void HandleGUITextureProps (ShaderLab::PropertySheet *sheet, Texture *texture); + +#endif |