diff --git a/swCommonLib/Common/Buffers/BufferRaw.h b/swCommonLib/Common/Buffers/BufferRaw.h index 5bdb8063..d65ee0e1 100644 --- a/swCommonLib/Common/Buffers/BufferRaw.h +++ b/swCommonLib/Common/Buffers/BufferRaw.h @@ -93,6 +93,8 @@ inline BufferRaw& BufferRaw::operator= ( BufferRaw&& bufferRaw ) bufferRaw.m_data = nullptr; bufferRaw.m_size = 0; + + return *this; } // ================================ // diff --git a/swGUI/.gitignore b/swGUI/.gitignore index c36039fa..a22d7c6e 100644 --- a/swGUI/.gitignore +++ b/swGUI/.gitignore @@ -58,6 +58,7 @@ Documentation/ *.log *.scc *.html +*.orig # Visual C++ cache files ipch/ diff --git a/swGUI/Core/Controls/Shapes/Ellipse.cpp b/swGUI/Core/Controls/Shapes/Ellipse.cpp new file mode 100644 index 00000000..5a5c6ebb --- /dev/null +++ b/swGUI/Core/Controls/Shapes/Ellipse.cpp @@ -0,0 +1,68 @@ +/** +@file Ellipse.cpp +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ +#include "swGUI/Core/stdafx.h" + +#include "Ellipse.h" +#include "swGUI/Core/Media/Geometry/EllipseGeometry.h" + + +namespace sw { +namespace gui +{ + + +// ================================ // +// +Ellipse::Ellipse() + : m_strokeThickness( 1 ) +{ + Shape::SetWidth( 100 ); + Shape::SetHeight( 100 ); + + auto rectGeom = std::make_shared< EllipseGeometry >(); + rectGeom->SetWidth( GetSize().x ); + rectGeom->SetHeight( GetSize().y ); + rectGeom->SetThickness( m_strokeThickness ); + + SetGeometry( rectGeom ); +} + +// ================================ // +// +void Ellipse::SetWidth ( float width ) +{ + Shape::SetWidth( width ); + + auto geom = std::static_pointer_cast< EllipseGeometry >( GetGeometry() ); + geom->SetWidth( GetSize().x ); +} + +// ================================ // +// +void Ellipse::SetHeight ( float height ) +{ + Shape::SetHeight( height ); + + auto geom = std::static_pointer_cast< EllipseGeometry >( GetGeometry() ); + geom->SetHeight( GetSize().y ); +} + +// ================================ // +// +void Ellipse::SetThickness ( float thickness ) +{ + m_strokeThickness = thickness; + + auto geom = std::static_pointer_cast< EllipseGeometry >( GetGeometry() ); + geom->SetThickness( m_strokeThickness ); +} + + + +} // gui +} // sw + + diff --git a/swGUI/Core/Controls/Shapes/Ellipse.h b/swGUI/Core/Controls/Shapes/Ellipse.h new file mode 100644 index 00000000..04c6ddda --- /dev/null +++ b/swGUI/Core/Controls/Shapes/Ellipse.h @@ -0,0 +1,47 @@ +#pragma once +/** +@file Ellipse.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + +#include "Shape.h" + + + + +namespace sw { +namespace gui +{ + +/**@brief Draws ellipse shape. +@ingroup Shapes +@ingroup Controls*/ +class Ellipse : public Shape +{ + RTTR_ENABLE( Shape ); + RTTR_REGISTRATION_FRIEND; +private: + + float m_strokeThickness; + +protected: +public: + + explicit Ellipse (); + virtual ~Ellipse () = default; + + + virtual void SetWidth ( float width ) override; + virtual void SetHeight ( float height ) override; + void SetThickness ( float thickness ); + +}; + +DEFINE_OPTR_TYPE( Ellipse ); + + +} // gui +} // sw + + diff --git a/swGUI/Core/Controls/Shapes/Rectangle.cpp b/swGUI/Core/Controls/Shapes/Rectangle.cpp index e788f142..384f4a7d 100644 --- a/swGUI/Core/Controls/Shapes/Rectangle.cpp +++ b/swGUI/Core/Controls/Shapes/Rectangle.cpp @@ -17,13 +17,14 @@ namespace gui // ================================ // // Rectangle::Rectangle() - : m_width( 100 ) - , m_height( 100 ) - , m_strokeThickness( 1 ) + : m_strokeThickness( 1 ) { + Shape::SetWidth( 100 ); + Shape::SetHeight( 100 ); + auto rectGeom = std::make_shared< RectangleGeometry >(); - rectGeom->SetWidth( m_width ); - rectGeom->SetHeight( m_height ); + rectGeom->SetWidth( GetSize().x ); + rectGeom->SetHeight( GetSize().y ); rectGeom->SetThickness( m_strokeThickness ); SetGeometry( rectGeom ); @@ -33,20 +34,22 @@ Rectangle::Rectangle() // void Rectangle::SetWidth ( float width ) { - m_width = width; + Shape::SetWidth( width ); auto geom = std::static_pointer_cast< RectangleGeometry >( GetGeometry() ); - geom->SetWidth( m_width ); + geom->SetWidth( GetSize().x ); + + } // ================================ // // void Rectangle::SetHeight ( float height ) { - m_height = height; + Shape::SetHeight( height ); auto geom = std::static_pointer_cast< RectangleGeometry >( GetGeometry() ); - geom->SetHeight( m_height ); + geom->SetHeight( GetSize().y ); } // ================================ // diff --git a/swGUI/Core/Controls/Shapes/Rectangle.h b/swGUI/Core/Controls/Shapes/Rectangle.h index 12e378f7..ddf17c1f 100644 --- a/swGUI/Core/Controls/Shapes/Rectangle.h +++ b/swGUI/Core/Controls/Shapes/Rectangle.h @@ -23,8 +23,6 @@ class Rectangle : public Shape RTTR_REGISTRATION_FRIEND; private: - float m_width; ///< Remove in future. This should be implemented in ArrangeCore. - float m_height; ///< Remove in future. This should be implemented in ArrangeCore. float m_strokeThickness; protected: @@ -34,9 +32,9 @@ class Rectangle : public Shape virtual ~Rectangle () = default; - void SetWidth ( float width ); - void SetHeight ( float height ); - void SetThickness ( float thickness ); + virtual void SetWidth ( float width ) override; + virtual void SetHeight ( float height ) override; + void SetThickness ( float thickness ); }; diff --git a/swGUI/Core/Controls/Visual.cpp b/swGUI/Core/Controls/Visual.cpp index 48ab6f04..774c192d 100644 --- a/swGUI/Core/Controls/Visual.cpp +++ b/swGUI/Core/Controls/Visual.cpp @@ -17,6 +17,20 @@ Visual::Visual() : m_offset( Position( 0.0f, 0.0f ) ) {} +// ================================ // +// +void Visual::SetWidth ( float width ) +{ + m_size.x = width; +} + +// ================================ // +// +void Visual::SetHeight ( float height ) +{ + m_size.y = height; +} + } // gui } // sw diff --git a/swGUI/Core/Controls/Visual.h b/swGUI/Core/Controls/Visual.h index 88418100..19870d0a 100644 --- a/swGUI/Core/Controls/Visual.h +++ b/swGUI/Core/Controls/Visual.h @@ -34,6 +34,7 @@ class Visual : public DependencyObject private: Position m_offset; ///< Control position relative to parent. + Size2D m_size; ///< Size of control (bounding box). protected: @@ -61,10 +62,13 @@ class Visual : public DependencyObject Position GetVisualOffset () const { return m_offset; } + Size2D GetSize () const { return m_size; } public: // Temporary void SetOffset ( Position pos ) { m_offset = pos; } + virtual void SetWidth ( float width ); + virtual void SetHeight ( float height ); }; diff --git a/swGUI/Core/Media/Brushes/AngleGradientBrush.cpp b/swGUI/Core/Media/Brushes/AngleGradientBrush.cpp new file mode 100644 index 00000000..efd6f5fa --- /dev/null +++ b/swGUI/Core/Media/Brushes/AngleGradientBrush.cpp @@ -0,0 +1,58 @@ +/** +@file AngleGradientBrush.cpp +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + + +#include "swGUI/Core/stdafx.h" +#include "AngleGradientBrush.h" + + + +namespace sw { +namespace gui +{ + +// ================================ // +// +AngleGradientBrush::AngleGradientBrush() + : GradientBrush( AngleGradientBrush::ConstantsSize() ) +{ + m_constants.GradientCenter = Position( 0.5f, 0.5f ); +} + + +// ================================ // +// +BufferRange AngleGradientBrush::BufferData () +{ + return PrepareBuffer( m_constants.GetView() ); +} + +// ================================ // +// +filesystem::Path AngleGradientBrush::ShaderFunctionFile () +{ + return "$(CoreGUI-Shader-Dir)/Brush/AngleGradientBrush.psh"; +} + +// ================================ // +// +void AngleGradientBrush::SetGradientCenter ( Point center ) +{ + m_constants.GradientCenter = center; + + InvalidateConstants(); +} + +// ================================ // +// +Size AngleGradientBrush::ConstantsSize () const +{ + return sizeof( m_constants ); +} + + +} // gui +} // sw \ No newline at end of file diff --git a/swGUI/Core/Media/Brushes/AngleGradientBrush.h b/swGUI/Core/Media/Brushes/AngleGradientBrush.h new file mode 100644 index 00000000..705116b5 --- /dev/null +++ b/swGUI/Core/Media/Brushes/AngleGradientBrush.h @@ -0,0 +1,61 @@ +#pragma once +/** +@file AngleGradientBrush.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + + + +#include "GradientBrush.h" + +#include "swCommonLib/Common/Buffers/StackBuffer.h" +#include "swCommonLib/System/Path.h" +#include "swGUI/Core/System/CommonTypes/CommonTypes.h" + + + +namespace sw { +namespace gui +{ + + +/**@brief Draws angle gradient on @ref Geometry. +@ingroup Brushes*/ +class AngleGradientBrush : public GradientBrush +{ + RTTR_ENABLE( GradientBrush ); + RTTR_REGISTRATION_FRIEND; +public: + + struct Constants + { + Point GradientCenter; + }; + +private: +protected: + + StackBuffer< Constants > m_constants; + +public: + explicit AngleGradientBrush (); + virtual ~AngleGradientBrush () = default; + + + virtual BufferRange BufferData () override; + virtual filesystem::Path ShaderFunctionFile () override; + + void SetGradientCenter ( Point center ); + +protected: + + virtual Size ConstantsSize () const override; +}; + +DEFINE_PTR_TYPE( AngleGradientBrush ); + + +} // gui +} // sw + diff --git a/swGUI/Core/Media/Brushes/Brush.cpp b/swGUI/Core/Media/Brushes/Brush.cpp index 9cf40887..1f27b67d 100644 --- a/swGUI/Core/Media/Brushes/Brush.cpp +++ b/swGUI/Core/Media/Brushes/Brush.cpp @@ -21,6 +21,7 @@ Brush::Brush ( ConstantBufferMode enableCB ) : m_useConstantBuffer( enableCB == ConstantBufferMode::Enable ) , m_invalidateConstants( false ) , m_invalidateTexture( false ) + , m_changeCBuffer( false ) { InvalidateShader(); } @@ -47,6 +48,13 @@ void Brush::InvalidateTexture () m_invalidateTexture = true; } +// ================================ // +// +void Brush::InvalidateConstsBuffer () +{ + m_changeCBuffer = true; +} + // ================================ // // void Brush::ShaderUpdated () @@ -68,5 +76,12 @@ void Brush::ConstantsUpdated () m_invalidateConstants = false; } +// ================================ // +// +void Brush::BufferChanged () +{ + m_changeCBuffer = false; +} + } // gui } // sw \ No newline at end of file diff --git a/swGUI/Core/Media/Brushes/Brush.h b/swGUI/Core/Media/Brushes/Brush.h index 933fc9ad..788e4574 100644 --- a/swGUI/Core/Media/Brushes/Brush.h +++ b/swGUI/Core/Media/Brushes/Brush.h @@ -45,6 +45,7 @@ class Brush : public EngineObject bool m_useConstantBuffer : 1; bool m_invalidateConstants : 1; + bool m_changeCBuffer : 1; bool m_invalidateShader : 1; bool m_invalidateTexture : 1; @@ -56,6 +57,7 @@ class Brush : public EngineObject void InvalidateConstants (); void InvalidateShader (); void InvalidateTexture (); + void InvalidateConstsBuffer (); ///@} @@ -88,12 +90,14 @@ class Brush : public EngineObject void ShaderUpdated (); void TextureUpdated (); void ConstantsUpdated (); + void BufferChanged (); protected: bool NeedsShaderUpdate () const { return m_invalidateShader; } bool NeedsTextureUpdate () const { return m_invalidateTexture; } bool NeedsConstantsUpdate () const { return m_invalidateConstants; } + bool NeedsBufferChange () const { return m_changeCBuffer; } bool UsesConstantBuffer () const { return m_useConstantBuffer; } diff --git a/swGUI/Core/Media/Brushes/GradientBrush.cpp b/swGUI/Core/Media/Brushes/GradientBrush.cpp new file mode 100644 index 00000000..65f31715 --- /dev/null +++ b/swGUI/Core/Media/Brushes/GradientBrush.cpp @@ -0,0 +1,184 @@ +/** +@file GradientBrush.cpp +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ +#include "swGUI/Core/stdafx.h" + +#include "GradientBrush.h" + +#include "swCommonLib/Common/Buffers/BufferTyped.h" +#include "swCommonLib/Common/fmt.h" + + +#include + + +namespace sw { +namespace gui +{ + + +// ================================ // +// +Size Padding16 ( Size size ) +{ + return ( 16 - size % 16 ) % 16; +} + +// ================================ // +// +Size Align16 ( Size size ) +{ + return size + Padding16( size ); +} + + + +// ================================ // +// +GradientBrush::GradientBrush( Size constantsSize ) + : Brush( ConstantBufferMode::Enable ) + , m_buffer( BufferTyped< uint8 >( ExpectedBufferSize( constantsSize ) ).MoveToRawBuffer() ) +{} + + +// ================================ // +// +void GradientBrush::AddGradientStop ( GradientStop stop ) +{ + m_gradientStops.push_back( stop ); + std::sort( m_gradientStops.begin(), m_gradientStops.end(), []( const GradientStop& left, const GradientStop& right ) + { + if( left.Offset < right.Offset ) + return true; + return false; + } ); + + if( m_buffer.GetSize() != ExpectedBufferSize() ) + InvalidateConstants(); +} + +// ================================ // +// +void GradientBrush::RemoveGradientStop ( Size idx ) +{ + m_gradientStops.erase( m_gradientStops.begin() + idx ); + + if( m_buffer.GetSize() != ExpectedBufferSize() ) + InvalidateConstants(); +} + +// ================================ // +// +AssetPath GradientBrush::ConstantsName () +{ + auto expSize = ExpectedBufferSize(); + return fmt::format( "::sw::gui::GradientBrush::CB[Size={}]", expSize ); +} + +// ================================ // +// +AssetPath GradientBrush::TextureSource () +{ + // No texture by default. + return AssetPath(); +} + + +// ================================ // +// +BufferRange GradientBrush::PrepareBuffer ( BufferRange constants ) +{ + auto expectedSize = ExpectedBufferSize(); + if( m_buffer.GetSize() != expectedSize ) + ReallocateBuffer( expectedSize ); + + FillBufferContent( constants ); + + return BufferRange( m_buffer.GetData(), m_buffer.GetSize() ); +} + +// ================================ // +// +Size GradientBrush::ExpectedBufferSize () const +{ + return ExpectedBufferSize( ConstantsSize() ); +} + +// ================================ // +// +Size GradientBrush::ExpectedBufferSize ( Size constantsSize ) const +{ + auto neededSize = GradientStopsSize( constantsSize ) + constantsSize; + neededSize = Align16( neededSize ); + + return neededSize; +} + +// ================================ // +// +Size GradientBrush::GradientStopsSize ( Size constsSize ) const +{ + auto gradientStopsAlign = Padding16( sizeof( GradientStop ) ); + + // Size of GradientStops array + size of number of array elements on the begining. + auto gradientStopsSize = ( sizeof( GradientStop ) + gradientStopsAlign ) * m_gradientStops.size(); + return gradientStopsSize + NumStopsSize( constsSize ); +} + +// ================================ // +// +Size GradientBrush::NumStopsSize ( Size constsSize ) const +{ + Size restFromConsts = Padding16( constsSize ); + if( restFromConsts == 0) + { + // uint32 size + alignement. + return Align16( sizeof( uint32 ) ); + } + else + { + // uint32 will be in the same register as last variables from constants. + return restFromConsts; + } +} + +// ================================ // +// +void GradientBrush::ReallocateBuffer ( Size newSize ) +{ + BufferTyped< uint8 > bufferTyped( newSize ); + m_buffer = bufferTyped.MoveToRawBuffer(); +} + +// ================================ // +// +void GradientBrush::FillBufferContent ( BufferRange constants ) +{ + // Copy buffer from derived class. + auto dataPtr = m_buffer.GetData(); + memcpy( dataPtr, constants.DataPtr, constants.DataSize ); + + // Copy GradientStops. + dataPtr += constants.DataSize; + + uint32 numGradientStops = (uint32)m_gradientStops.size(); + memcpy( dataPtr, &numGradientStops, sizeof( uint32 ) ); + + dataPtr += NumStopsSize( constants.DataSize ); + + for( Size i = 0; i < m_gradientStops.size(); i++ ) + { + auto gradientStopsAlign = Padding16( sizeof( GradientStop ) ); + + memcpy( dataPtr, &m_gradientStops[ i ], sizeof( GradientStop ) ); + dataPtr += ( sizeof( GradientStop ) + gradientStopsAlign ); + } +} + + + + +} // gui +} // sw diff --git a/swGUI/Core/Media/Brushes/GradientBrush.h b/swGUI/Core/Media/Brushes/GradientBrush.h index bd5511ac..6b0b51c5 100644 --- a/swGUI/Core/Media/Brushes/GradientBrush.h +++ b/swGUI/Core/Media/Brushes/GradientBrush.h @@ -1,24 +1,84 @@ #pragma once +/** +@file GradientBrush.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ #include "Brush.h" +#include "swCommonLib/Common/Buffers/BufferRaw.h" + +#include "swGraphicAPI/ResourceManager/PathTranslators/AssetPath.h" + +#include + namespace sw { namespace gui { -/**@brief +/**@brief Gradient point. +@ingroup Brushes*/ +struct GradientStop +{ + uint32 Color; + float Offset; + +// ================================ // +// + GradientStop() {} + + GradientStop( uint32 color, float offset ) + : Color( color ) + , Offset( offset ) + {} +}; + + + +/**@brief Base class for gradients. @ingroup Brushes*/ class GradientBrush : public Brush { private: protected: + + std::vector< GradientStop > m_gradientStops; + BufferRaw m_buffer; + public: - explicit GradientBrush () = default; - ~GradientBrush () = default; + explicit GradientBrush ( Size constantsSize ); + virtual ~GradientBrush () = default; + + + virtual AssetPath ConstantsName (); + virtual AssetPath TextureSource () override; + +public: + + void AddGradientStop ( GradientStop stop ); + void RemoveGradientStop ( Size idx ); + + const std::vector< GradientStop >& GetGradintStops () const { return m_gradientStops; } + +protected: + + BufferRange PrepareBuffer ( BufferRange constants ); + + virtual Size ConstantsSize () const = 0; + +private: + + Size ExpectedBufferSize () const; + Size ExpectedBufferSize ( Size constantsSize ) const; + Size GradientStopsSize ( Size constsSize ) const; + Size NumStopsSize ( Size constsSize ) const; + void ReallocateBuffer ( Size newSize ); + void FillBufferContent ( BufferRange constants ); }; diff --git a/swGUI/Core/Media/Brushes/ImageBrush.cpp b/swGUI/Core/Media/Brushes/ImageBrush.cpp new file mode 100644 index 00000000..ef89a2ba --- /dev/null +++ b/swGUI/Core/Media/Brushes/ImageBrush.cpp @@ -0,0 +1,77 @@ +/** +@file ImageBrush.cpp +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + + +#include "swGUI/Core/stdafx.h" +#include "ImageBrush.h" + + + +namespace sw { +namespace gui +{ + +// ================================ // +// +ImageBrush::ImageBrush() + : ImageBrush( AssetPath() ) +{} + +// ================================ // +// +ImageBrush::ImageBrush( AssetPath tex ) + : Brush( ConstantBufferMode::Enable ) + , m_textureSource( std::move( tex ) ) +{ + Rect region; + region.Left = 0.0f; + region.Top = 1.0f; + region.Right = 1.0f; + region.Bottom = 0.0f; + + m_constants.TextureRegion = region; + m_constants.Stretch = Stretch::Fill; +} + +// ================================ // +// +void ImageBrush::SetTexture ( AssetPath tex ) +{ + m_textureSource = std::move( tex ); + InvalidateTexture(); +} + +// ================================ // +// +BufferRange ImageBrush::BufferData () +{ + return m_constants.GetView(); +} + +// ================================ // +// +filesystem::Path ImageBrush::ShaderFunctionFile () +{ + return "$(CoreGUI-Shader-Dir)/Brush/ImageBrush.psh"; +} + +// ================================ // +// +AssetPath ImageBrush::TextureSource () +{ + // Brush doesn't use textures. + return m_textureSource; +} + +// ================================ // +// +AssetPath ImageBrush::ConstantsName () +{ + return "::sw::gui::ImageBrush::CB"; +} + +} // gui +} // sw \ No newline at end of file diff --git a/swGUI/Core/Media/Brushes/ImageBrush.h b/swGUI/Core/Media/Brushes/ImageBrush.h index a339e3b8..4107fac1 100644 --- a/swGUI/Core/Media/Brushes/ImageBrush.h +++ b/swGUI/Core/Media/Brushes/ImageBrush.h @@ -1,4 +1,10 @@ #pragma once +/** +@file ImageBrush.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + #include "Brush.h" @@ -15,13 +21,51 @@ class ImageBrush : public Brush RTTR_ENABLE( Brush ); RTTR_REGISTRATION_FRIEND private: +public: + + enum Stretch + { + None = 0, + Fill = 1, + Uniform = 2, + UniformToFill = 3 + }; + protected: + + struct Constants + { + Rect TextureRegion; + Stretch Stretch; + }; + +protected: + + StackBufferA< Constants > m_constants; + AssetPath m_textureSource; + +public: + explicit ImageBrush (); + explicit ImageBrush ( AssetPath tex ); + virtual ~ImageBrush () = default; + +public: + + void SetTexture ( AssetPath tex ); + const AssetPath& GetTexture () const { return m_textureSource; } + + void SetTextureRegion ( Rect region ) { m_constants.TextureRegion = region; } + Rect GetTextureRegion () const { return m_constants.TextureRegion; } + public: - explicit ImageBrush () = default; - ~ImageBrush () = default; + virtual BufferRange BufferData () override; + virtual filesystem::Path ShaderFunctionFile () override; + virtual AssetPath TextureSource () override; + virtual AssetPath ConstantsName () override; }; +DEFINE_PTR_TYPE( ImageBrush ); } // gui } // sw diff --git a/swGUI/Core/Media/Brushes/LinearGradient.h b/swGUI/Core/Media/Brushes/LinearGradient.h deleted file mode 100644 index a3d8899c..00000000 --- a/swGUI/Core/Media/Brushes/LinearGradient.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "GradientBrush.h" - - - -namespace sw { -namespace gui -{ - -/**@brief -@ingroup Brushes*/ -class LinearGradient : public GradientBrush -{ - RTTR_ENABLE( GradientBrush ); -private: -protected: -public: - explicit LinearGradient () = default; - ~LinearGradient () = default; - -}; - - -} // gui -} // sw - diff --git a/swGUI/Core/Media/Brushes/LinearGradientBrush.cpp b/swGUI/Core/Media/Brushes/LinearGradientBrush.cpp new file mode 100644 index 00000000..99608ef7 --- /dev/null +++ b/swGUI/Core/Media/Brushes/LinearGradientBrush.cpp @@ -0,0 +1,60 @@ +/** +@file LinearGradientBrush.cpp +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + + +#include "swGUI/Core/stdafx.h" +#include "LinearGradientBrush.h" + + + +namespace sw { +namespace gui +{ + +// ================================ // +// +LinearGradientBrush::LinearGradientBrush() + : GradientBrush( LinearGradientBrush::ConstantsSize() ) +{ + m_constants.GradientStart = Position( 0.5f, 0.0f ); + m_constants.GradientEnd = Position( 0.5f, 1.0f ); +} + + +// ================================ // +// +BufferRange LinearGradientBrush::BufferData () +{ + return PrepareBuffer( m_constants.GetView() ); +} + +// ================================ // +// +filesystem::Path LinearGradientBrush::ShaderFunctionFile () +{ + return "$(CoreGUI-Shader-Dir)/Brush/LinearGradientBrush.psh"; +} + +// ================================ // +// +void LinearGradientBrush::SetGradientAxis ( Point start, Point end ) +{ + m_constants.GradientStart = start; + m_constants.GradientEnd = end; + + InvalidateConstants(); +} + +// ================================ // +// +Size LinearGradientBrush::ConstantsSize () const +{ + return sizeof( m_constants ); +} + + +} // gui +} // sw \ No newline at end of file diff --git a/swGUI/Core/Media/Brushes/LinearGradientBrush.h b/swGUI/Core/Media/Brushes/LinearGradientBrush.h new file mode 100644 index 00000000..2729037e --- /dev/null +++ b/swGUI/Core/Media/Brushes/LinearGradientBrush.h @@ -0,0 +1,62 @@ +#pragma once +/** +@file LinearGradientBrush.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + + + +#include "GradientBrush.h" + +#include "swCommonLib/Common/Buffers/StackBuffer.h" +#include "swCommonLib/System/Path.h" +#include "swGUI/Core/System/CommonTypes/CommonTypes.h" + + + +namespace sw { +namespace gui +{ + + +/**@brief Draws linear gradient on @ref Geometry. +@ingroup Brushes*/ +class LinearGradientBrush : public GradientBrush +{ + RTTR_ENABLE( GradientBrush ); + RTTR_REGISTRATION_FRIEND; +public: + + struct Constants + { + Point GradientStart; + Point GradientEnd; + }; + +private: +protected: + + StackBuffer< Constants > m_constants; + +public: + explicit LinearGradientBrush (); + virtual ~LinearGradientBrush () = default; + + + virtual BufferRange BufferData () override; + virtual filesystem::Path ShaderFunctionFile () override; + + void SetGradientAxis ( Point start, Point end ); + +protected: + + virtual Size ConstantsSize () const override; +}; + +DEFINE_PTR_TYPE( LinearGradientBrush ); + + +} // gui +} // sw + diff --git a/swGUI/Core/Media/Brushes/RadialGradient.h b/swGUI/Core/Media/Brushes/RadialGradientBrush.h similarity index 100% rename from swGUI/Core/Media/Brushes/RadialGradient.h rename to swGUI/Core/Media/Brushes/RadialGradientBrush.h diff --git a/swGUI/Core/Media/Geometry/EllipseGeometry.cpp b/swGUI/Core/Media/Geometry/EllipseGeometry.cpp new file mode 100644 index 00000000..9df20e52 --- /dev/null +++ b/swGUI/Core/Media/Geometry/EllipseGeometry.cpp @@ -0,0 +1,133 @@ +/** +@file EllipseGeometry.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ +#include "swGUI/Core/stdafx.h" + +#include "EllipseGeometry.h" + +#include "swGeometrics/BasicShapes/Shapes2D/EllipseWithBorder.h" +#include "swGeometrics/BasicShapes/CoordsUV/PlanarUV.h" +#include "swGeometrics/GeometricsCore/Generators/Generator.h" +#include "swGeometrics/GeometricsCore/Processors/Transform/Translate2D.h" + +#include "swGUI/Core/Media/Geometry/Layouts/VertexShape2D.h" +#include "swCommonLib/Common/Buffers/IndexedGeometryBuffer.h" + +#include "swCommonLib/Common/fmt.h" + + + +namespace sw { +namespace gui +{ + +// ================================ // +// +EllipseGeometry::EllipseGeometry() + : Geometry( Geometry::ConstantBufferMode::Disable ) +{} + +// ================================ // +// +void EllipseGeometry::SetWidth ( float width ) +{ + m_width = width; + InvalidateGeometry(); +} + +// ================================ // +// +void EllipseGeometry::SetHeight ( float height ) +{ + m_height = height; + InvalidateGeometry(); +} + +// ================================ // +// +void EllipseGeometry::SetThickness ( float thickness ) +{ + m_strokeThickness = thickness; + InvalidateGeometry(); +} + +// ================================ // +// +bool EllipseGeometry::HitTest ( const Point& point ) +{ + if( pow( point.x / ( m_width / 2.0f ), 2 ) + pow( point.y / ( m_height / 2.0f ), 2 ) < 1.0f ) + return true; + + return false; +} + +// ================================ // +// +bool EllipseGeometry::HitTest ( const Rect& rectangle ) +{ + assert( !"Implement me" ); + return false; +} + +// ================================ // +// +GeometryData EllipseGeometry::Generate () +{ + geom::EllipseWithBorder< VertexShape2D, Index16 > ellipse; + ellipse.Width = m_width; + ellipse.Height = m_height; + ellipse.StrokeThickness = m_strokeThickness; + ellipse.Tesselation = uint32( m_width + m_height ) / 4; // Estimate tesselation based on ellipse size. + + geom::PlanarUV< VertexShape2D > planarUV; + planarUV.MinX = 0.0f; + planarUV.MinY = -m_height; + planarUV.MaxX = m_width; + planarUV.MaxY = 0.0f; + + auto geometry = geom::Generate< geom::IndexedGeometryBuffer< VertexShape2D, Index16 > >( ellipse, geom::Translate2D< VertexShape2D >( m_width / 2, -m_height / 2 ), planarUV ); + /// @todo Error handling or logging. + + GeometryData geomData( geometry.Get().Verticies.MoveToRawBuffer(), geometry.Get().Indicies.MoveToRawBuffer() ); + geomData.FillIdxEnd = (uint32)ellipse.GetNumberFillIndicies(); + geomData.BorderIdxEnd = (uint32)ellipse.GetNumberFillIndicies() + (uint32)ellipse.GetNumberBorderIndicies(); + geomData.ExtendedIB = false; + geomData.Topology = PrimitiveTopology::Triangles; + + return std::move( geomData ); +} + +// ================================ // +// +BufferRange EllipseGeometry::BufferData () +{ + // Rectangle doesn't use contants buffer. + return BufferRange(); +} + +// ================================ // +// +filesystem::Path EllipseGeometry::ShaderFunctionFile () +{ + return "$(CoreGUI-Shader-Dir)/Geometry/ForwardAttributes.vsh"; +} + +// ================================ // +// +std::string EllipseGeometry::GeometryName () +{ + return fmt::format( "EllipseGeometry-[Width={}][Height={}][StrokeThickness={}]", m_width, m_height, m_strokeThickness ); +} + +// ================================ // +// +AssetPath EllipseGeometry::ConstantsName () +{ + // Rectangle doesn't use contants buffer. + return AssetPath(); +} + +} // gui +} // sw diff --git a/swGUI/Core/Media/Geometry/EllipseGeometry.h b/swGUI/Core/Media/Geometry/EllipseGeometry.h new file mode 100644 index 00000000..0386c1ef --- /dev/null +++ b/swGUI/Core/Media/Geometry/EllipseGeometry.h @@ -0,0 +1,56 @@ +#pragma once +/** +@file EllipseGeometry.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + +#include "swGUI/Core/Media/Geometry/Geometry.h" + + +namespace sw { +namespace gui +{ + + +/**@brief Generates Ellipse. +@ingroup Geometries*/ +class EllipseGeometry : public Geometry +{ +private: +protected: + + float m_width; + float m_height; + float m_strokeThickness; + +public: + + explicit EllipseGeometry (); + virtual ~EllipseGeometry () = default; + + void SetWidth ( float width ); + void SetHeight ( float height ); + void SetThickness ( float thickness ); + +public: + + // Inherited via Geometry + virtual bool HitTest ( const Point& point ) override; + virtual bool HitTest ( const Rect& rectangle ) override; + + virtual GeometryData Generate () override; + virtual BufferRange BufferData () override; + + virtual filesystem::Path ShaderFunctionFile () override; + virtual std::string GeometryName () override; + virtual AssetPath ConstantsName () override; + +}; + + + +} // gui +} // sw + + diff --git a/swGUI/Core/Media/Media.h b/swGUI/Core/Media/Media.h index 7fcd836b..d25c8112 100644 --- a/swGUI/Core/Media/Media.h +++ b/swGUI/Core/Media/Media.h @@ -16,8 +16,8 @@ // Brushes #include "Brushes/SolidColorBrush.h" -#include "Brushes/LinearGradient.h" -#include "Brushes/RadialGradient.h" +#include "Brushes/LinearGradientBrush.h" +#include "Brushes/RadialGradientBrush.h" #include "Brushes/ImageBrush.h" // Geometry diff --git a/swGUI/Core/Shaders/hlsl/Brush/AngleGradientBrush.psh b/swGUI/Core/Shaders/hlsl/Brush/AngleGradientBrush.psh new file mode 100644 index 00000000..c7ffeefe --- /dev/null +++ b/swGUI/Core/Shaders/hlsl/Brush/AngleGradientBrush.psh @@ -0,0 +1,96 @@ +#define MAX_GRADIENTS_STOPS 127 + + +// ================================ // +// +struct GradientStop +{ + uint Color; + float Offset; +}; + +// ================================ // +// +cbuffer AngleGradientBrushConsts : register( b2 ) +{ + float2 Center; + uint NumStops; + GradientStop GradientStops[ MAX_GRADIENTS_STOPS ]; +} + +// ================================ // +// +float4 LoadIntColor ( uint color ) +{ + // Color format 0xAARRGGBB + + float4 result; + result.w = ( color & 0xFF000000 ) >> 24; + result.x = ( color & 0x00FF0000 ) >> 16; + result.y = ( color & 0x0000FF00 ) >> 8; + result.z = color & 0x000000FF; + + return result / 255.0; +} + +// ================================ // +// +float4 ComputeColor ( float factor, GradientStop first, GradientStop second ) +{ + float firstOffset = first.Offset; + float secondOffset = second.Offset; + + factor = ( factor - firstOffset ) / ( secondOffset - firstOffset ); + + float4 firstColor = LoadIntColor( first.Color ); + float4 secondColor = LoadIntColor( second.Color ); + + return lerp( firstColor, secondColor, factor ); +} + +// ================================ // +// +float4 ComputeGradient ( float factor ) +{ + // Handle situation, when we are before first GradientStop. + if( factor < GradientStops[ 0 ].Offset ) + return LoadIntColor( GradientStops[ 0 ].Color ); + + // Find pair of GradientStops. Our pixel should be between them. + uint i = 1; + for( ; i < NumStops; ++i ) + { + if( factor < GradientStops[ i ].Offset ) + { + return ComputeColor( factor, GradientStops[ i - 1 ], GradientStops[ i ] ); + } + } + + // Handle situation, when we are after last GradientStop. + return LoadIntColor( GradientStops[ NumStops - 1 ].Color ); +} + +// ================================ // +// +float4 BrushFunction ( float4 pos, float2 tex ) +{ + float2 referenceVec = float2( 0.0, 1.0 ); + float2 pixelVec = normalize( tex - Center ); + + float cosAngle = dot( referenceVec, pixelVec ); + float direction = cross( float3( referenceVec, 0.0 ), float3( pixelVec, 0.0 ) ).z; + + // We don't know yet, on which side of reference vector we are. + float factorPreproduct = degrees( acos( cosAngle ) ); + + // Sinus tells us on which side of reference vector we are. + float factor = 0; + if( direction <= 0 ) + factor = factorPreproduct / 360; + else + factor = ( 360 - factorPreproduct ) / 360; + + return ComputeGradient( factor ); +} + + diff --git a/swGUI/Core/Shaders/hlsl/Brush/ImageBrush.psh b/swGUI/Core/Shaders/hlsl/Brush/ImageBrush.psh new file mode 100644 index 00000000..c4ab70c8 --- /dev/null +++ b/swGUI/Core/Shaders/hlsl/Brush/ImageBrush.psh @@ -0,0 +1,48 @@ + + +// Stretch values. Check in ImageBrush.h +#define None 0 +#define Fill 1 +#define Uniform 2 +#define UniformToFill 3 + +// ================================ // +// +cbuffer ImageBrushConsts : register( b2 ) +{ + float4 TextureRange; ///< [minX, maxX, maxY, minY] + uint Stretch; +} + +Texture2D image; + +// ================================ // +// +SamplerState TextureSampler +{ + Filter = LINEAR; + AddressU = Wrap; + AddressV = Wrap; +}; + +// ================================ // +// +float2 TransformToRange ( float4 range, float2 uv ) +{ + float xRange = range.y - range.x; + float yRange = range.z - range.w; + + float2 transformed = float2( range.x, range.w ); + transformed = transformed.x + uv.x / xRange; + transformed.x = transformed.y + uv.y / yRange; + + return transformed; +} + + +// ================================ // +// +float4 BrushFunction ( float4 pos, float2 tex ) +{ + return image.Sample( TextureSampler, TransformToRange( TextureRange, tex ) ); +} diff --git a/swGUI/Core/Shaders/hlsl/Brush/LinearGradientBrush.psh b/swGUI/Core/Shaders/hlsl/Brush/LinearGradientBrush.psh new file mode 100644 index 00000000..d2dffe1e --- /dev/null +++ b/swGUI/Core/Shaders/hlsl/Brush/LinearGradientBrush.psh @@ -0,0 +1,104 @@ + +#define MAX_GRADIENTS_STOPS 127 + + +// ================================ // +// +struct GradientStop +{ + uint Color; + float Offset; +}; + +// ================================ // +// +cbuffer LinearGradientBrushConsts : register( b2 ) +{ + float2 StartPoint; + float2 StopPoint; + uint NumStops; + GradientStop GradientStops[ MAX_GRADIENTS_STOPS ]; +} + + +// ================================ // +// +float4 LoadIntColor ( uint color ) +{ + // Color format 0xAARRGGBB + + float4 result; + result.w = ( color & 0xFF000000 ) >> 24; + result.x = ( color & 0x00FF0000 ) >> 16; + result.y = ( color & 0x0000FF00 ) >> 8; + result.z = color & 0x000000FF; + + return result / 255.0; +} + +// ================================ // +// +float4 ComputeColor ( float factor, GradientStop first, GradientStop second ) +{ + float firstOffset = first.Offset; + float secondOffset = second.Offset; + + factor = ( factor - firstOffset ) / ( secondOffset - firstOffset ); + + float4 firstColor = LoadIntColor( first.Color ); + float4 secondColor = LoadIntColor( second.Color ); + + return lerp( firstColor, secondColor, factor ); +} + +// ================================ // +// +float4 ComputeGradient ( float factor ) +{ + // Handle situation, when we are before first GradientStop. + if( factor < GradientStops[ 0 ].Offset ) + return LoadIntColor( GradientStops[ 0 ].Color ); + + // Find pair of GradientStops. Our pixel should be between them. + uint i = 1; + for( ; i < NumStops; ++i ) + { + if( factor < GradientStops[ i ].Offset ) + { + return ComputeColor( factor, GradientStops[ i - 1 ], GradientStops[ i ] ); + } + } + + // Handle situation, when we are after last GradientStop. + return LoadIntColor( GradientStops[ NumStops - 1 ].Color ); +} + + +// ================================ // +// +float4 BrushFunction ( float4 pos, float2 tex ) +{ + float2 gradientVec = StopPoint - StartPoint; + float2 pixelVec = tex - StartPoint; + + // UV coordinates are in range [0,1] in both dimensions, what causes, that gradient + // looks like it was scaled square. We must transform coordinates using + // knowledge of Visual bounding box. + float aspect = _swVisualSize.y / _swVisualSize.x; + gradientVec.y = gradientVec.y * aspect; + pixelVec.y = pixelVec.y * aspect; + + // Dot product of equal vectors gives us square of length of vector. + float gradientVecLen = sqrt( dot( gradientVec, gradientVec ) ); + float2 gradientVecNorm = gradientVec / gradientVecLen; + + // Dot product is length of projection pixelVec on gradientVecNorm. + float factor = dot( pixelVec, gradientVecNorm ) / gradientVecLen; + + // Handle situation, when we are before first GradientStop. + if( factor < GradientStops[ 0 ].Offset ) + return LoadIntColor( GradientStops[ 0 ].Color ); + + return ComputeGradient( factor ); +} + diff --git a/swGUI/Core/Shaders/hlsl/Brush/SolidColorBrush.psh b/swGUI/Core/Shaders/hlsl/Brush/SolidColorBrush.psh index c8616f56..edd474cb 100644 --- a/swGUI/Core/Shaders/hlsl/Brush/SolidColorBrush.psh +++ b/swGUI/Core/Shaders/hlsl/Brush/SolidColorBrush.psh @@ -2,7 +2,7 @@ // ================================ // // -cbuffer SolidColorBrushConsts : register( b0 ) +cbuffer SolidColorBrushConsts : register( b2 ) { float4 Color; } diff --git a/swGUI/Core/Shaders/hlsl/Templates/Basic.psh b/swGUI/Core/Shaders/hlsl/Templates/Basic.psh index 3c22e5ea..f7f079e2 100644 --- a/swGUI/Core/Shaders/hlsl/Templates/Basic.psh +++ b/swGUI/Core/Shaders/hlsl/Templates/Basic.psh @@ -8,12 +8,36 @@ struct OutputVS noperspective float2 Tex : TEXCOORD; }; +// ================================ // +// +cbuffer RenderingSystemConsts : register( b0 ) +{ + float2 _swViewportSize; +} // ================================ // // -float4 main ( OutputVS input ) : SV_Target +cbuffer VisualConsts : register( b1 ) { - float4 color = BrushFunction( input.Pos, input.Tex ); + float2 _swVisualOffset; + float2 _swVisualSize; +} - return color; +// ================================ // +// +float2 swTransformToDirectX ( float2 tex ) +{ + float2 directxTex = tex; + directxTex.y = 1.0 - directxTex.y; + + return directxTex; +} + +#UserCode + +// ================================ // +// +float4 main ( OutputVS input ) : SV_Target +{ + return BrushFunction( input.Pos, input.Tex ); } diff --git a/swGUI/Core/Shaders/hlsl/Templates/Basic.vsh b/swGUI/Core/Shaders/hlsl/Templates/Basic.vsh index 846bc6e9..677b4304 100644 --- a/swGUI/Core/Shaders/hlsl/Templates/Basic.vsh +++ b/swGUI/Core/Shaders/hlsl/Templates/Basic.vsh @@ -20,29 +20,32 @@ struct OutputVS // cbuffer RenderingSystemConsts : register( b0 ) { - float2 _RenderingSystemConsts_ViewportSize; + float2 _swViewportSize; } // ================================ // // cbuffer VisualConsts : register( b1 ) { - float2 _VisualConstants_Offset; + float2 _swVisualOffset; + float2 _swVisualSize; } +#UserCode + // ================================ // // -float4 TransformVertex ( float2 pos ) +float4 swTransformVertex ( float2 pos ) { // GUI uses coordinates system with y-axis directed to bottom. // We have to inverse offset for directX. - float2 offset = _VisualConstants_Offset; + float2 offset = _swVisualOffset; offset.y = -offset.y; float2 offsetedPos = pos + offset; // Rescale object from screen size to [-1.0, 1.0] range. - float2 halfViewportSize = _RenderingSystemConsts_ViewportSize / 2.0f; + float2 halfViewportSize = _swViewportSize / 2.0f; float4 vertex = { 0.0, 0.0, 0.5, 1.0 }; vertex.xy = offsetedPos / halfViewportSize; @@ -65,7 +68,7 @@ OutputVS main ( InputVS input ) output.Pos = GeometryFunctionPos( input.Pos, input.Tex ); output.Tex = GeometryFunctionTex( input.Pos, input.Tex ); - output.Pos = TransformVertex( output.Pos.xy ); + output.Pos = swTransformVertex( output.Pos.xy ); return output; } diff --git a/swGUI/Core/System/CommonTypes/CommonTypes.h b/swGUI/Core/System/CommonTypes/CommonTypes.h index 0fad3623..4303f7c7 100644 --- a/swGUI/Core/System/CommonTypes/CommonTypes.h +++ b/swGUI/Core/System/CommonTypes/CommonTypes.h @@ -38,6 +38,8 @@ struct Rect float Top; float Bottom; + // ================================ // + // float GetWidth () { return Right - Left; } float GetHeight () { return Top - Bottom; } diff --git a/swGUI/Core/System/GUISystem.cpp b/swGUI/Core/System/GUISystem.cpp index cb38dc99..ec959696 100644 --- a/swGUI/Core/System/GUISystem.cpp +++ b/swGUI/Core/System/GUISystem.cpp @@ -66,6 +66,8 @@ GUISystem::~GUISystem() for( auto window : m_windows ) delete window; + m_renderingSystem.release(); + m_graphicApi->ReleaseAPI(); delete m_resourceManager; delete m_graphicApi; diff --git a/swGUI/Core/System/Rendering/Drawings/Drawing.cpp b/swGUI/Core/System/Rendering/Drawings/Drawing.cpp index 13965c9d..968d3c96 100644 --- a/swGUI/Core/System/Rendering/Drawings/Drawing.cpp +++ b/swGUI/Core/System/Rendering/Drawings/Drawing.cpp @@ -73,7 +73,8 @@ bool Drawing::UpdateBrushTexture ( ResourceManagerAPI rm, Brush* brush ) // bool Drawing::UpdateBrushConstants ( ResourceManagerAPI rm, Brush* brush ) { - if( !m_brushData.BrushConstants && brush->UsesConstantBuffer() ) + if( ( !m_brushData.BrushConstants && brush->UsesConstantBuffer() ) + || brush->NeedsBufferChange() ) { AssetPath name = brush->ConstantsName(); @@ -84,6 +85,9 @@ bool Drawing::UpdateBrushConstants ( ResourceManagerAPI rm, Brush* brush ) constantsBuffer = rm.CreateConstantsBuffer( name, bufferRange ).Get(); /// @todo What in case of error? } + if( brush->NeedsBufferChange() ) + brush->BufferChanged(); + m_brushData.BrushConstants = constantsBuffer; return true; } @@ -109,7 +113,8 @@ bool Drawing::UpdatePenTexture ( ResourceManagerAPI rm, Brush* pen ) // bool Drawing::UpdatePenConstants ( ResourceManagerAPI rm, Brush* pen ) { - if( !m_penData.BrushConstants && pen->UsesConstantBuffer() ) + if( ( !m_penData.BrushConstants && pen->UsesConstantBuffer() ) + || pen->NeedsBufferChange() ) { AssetPath name = pen->ConstantsName(); @@ -120,6 +125,9 @@ bool Drawing::UpdatePenConstants ( ResourceManagerAPI rm, Brush* pen ) constantsBuffer = rm.CreateConstantsBuffer( name, bufferRange ).Get(); /// @todo What in case of error? } + if( pen->NeedsBufferChange() ) + pen->BufferChanged(); + m_penData.BrushConstants = constantsBuffer; return true; } @@ -369,7 +377,7 @@ void Drawing::RenderImpl ( IRenderer* renderer, impl::GeometryRenderingDat helper.SetTexture( setShaderCmd, brush.Texture.Ptr(), 0, (uint8)ShaderType::PixelShader ); renderer->SetShaderState( setShaderCmd ); - helper.BindBuffer( brush.BrushConstants.Ptr(), 0, (uint8)ShaderType::PixelShader ); + helper.BindBuffer( brush.BrushConstants.Ptr(), 2, (uint8)ShaderType::PixelShader ); helper.BindBuffer( geom.GeometryConstants.Ptr(), 2, (uint8)ShaderType::VertexShader ); DrawCommand drawCmd; diff --git a/swGUI/Core/System/Rendering/RenderingParams.h b/swGUI/Core/System/Rendering/RenderingParams.h index 29d2f8de..0b36d286 100644 --- a/swGUI/Core/System/Rendering/RenderingParams.h +++ b/swGUI/Core/System/Rendering/RenderingParams.h @@ -18,7 +18,7 @@ namespace gui struct RenderingParams { Position ParentOffset; ///< Control offset relative to parent. - + Size2D VisualSize; ///< Size of control (bounding box). }; // ================================ // diff --git a/swGUI/Core/System/Rendering/RenderingSystem.cpp b/swGUI/Core/System/Rendering/RenderingSystem.cpp index 1ed8599c..b5b070b4 100644 --- a/swGUI/Core/System/Rendering/RenderingSystem.cpp +++ b/swGUI/Core/System/Rendering/RenderingSystem.cpp @@ -99,6 +99,7 @@ void RenderingSystem::SetRenderTarget ( IRenderer* renderer, HostWindow* ho helper.UpdateBuffer( m_renderingSystemBuffer.Ptr(), paramsBuffer ); helper.BindBuffer( m_renderingSystemBuffer.Ptr(), 0, (uint8)ShaderType::VertexShader ); + helper.BindBuffer( m_renderingSystemBuffer.Ptr(), 0, (uint8)ShaderType::PixelShader ); helper.ClearRenderTargetAndDepth( host->GetRenderTarget().Ptr(), DirectX::XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f ), 1.0f ); helper.SetRenderTarget( host->GetRenderTarget().Ptr(), m_rasterizerState.Ptr(), m_transparentBlendState.Ptr(), m_depthState.Ptr() ); @@ -111,10 +112,11 @@ void RenderingSystem::SetSystemConstants ( IRenderer* renderer, const Rende RenderingHelper helper( renderer ); StackBufferA< RenderingParams > paramsBuffer; - paramsBuffer.ParentOffset = params.ParentOffset; + static_cast< RenderingParams& >( paramsBuffer ) = params; helper.UpdateBuffer( m_visualBuffer.Ptr(), paramsBuffer ); helper.BindBuffer( m_visualBuffer.Ptr(), 1, (uint8)ShaderType::VertexShader ); + helper.BindBuffer( m_visualBuffer.Ptr(), 1, (uint8)ShaderType::PixelShader ); } // ================================ // @@ -140,6 +142,7 @@ void RenderingSystem::RenderTree ( IRenderer* renderer, Visual* visual, c RenderingParams params; params.ParentOffset.x = parentParams.ParentOffset.x + visual->GetVisualOffset().x; params.ParentOffset.y = parentParams.ParentOffset.y + visual->GetVisualOffset().y; + params.VisualSize = visual->GetSize(); DrawVisual( renderer, visual, params ); diff --git a/swGUI/Core/System/Rendering/Shading/ShaderBuilder.cpp b/swGUI/Core/System/Rendering/Shading/ShaderBuilder.cpp index e74677eb..09250849 100644 --- a/swGUI/Core/System/Rendering/Shading/ShaderBuilder.cpp +++ b/swGUI/Core/System/Rendering/Shading/ShaderBuilder.cpp @@ -5,10 +5,11 @@ */ #include "swGUI/Core/stdafx.h" - #include "ShaderBuilder.h" +#include + namespace sw { @@ -19,8 +20,8 @@ namespace gui // std::string ShaderBuilder::BuildShader ( const std::string& shaderTemplate, const std::string& shaderFunction ) const { - // This version simply adds function at the beginning without checking content. - return shaderFunction + shaderTemplate; + // Template should contain #UserCode marker. Simply replace with user provided code. + return std::regex_replace( shaderTemplate, std::regex( "#UserCode" ), shaderFunction ); } diff --git a/swGUI/ProjectDir/Output/Application-Dir/pool-water-texture.jpg b/swGUI/ProjectDir/Output/Application-Dir/pool-water-texture.jpg new file mode 100644 index 00000000..278ed34b Binary files /dev/null and b/swGUI/ProjectDir/Output/Application-Dir/pool-water-texture.jpg differ diff --git a/swGUI/ProjectDir/Visual2015/CoreGUI/CoreGUI.vcxproj b/swGUI/ProjectDir/Visual2015/CoreGUI/CoreGUI.vcxproj index 5e2270d5..6aa75549 100644 --- a/swGUI/ProjectDir/Visual2015/CoreGUI/CoreGUI.vcxproj +++ b/swGUI/ProjectDir/Visual2015/CoreGUI/CoreGUI.vcxproj @@ -134,17 +134,20 @@ + + - - + + + @@ -205,12 +208,18 @@ + + + + + + @@ -265,6 +274,28 @@ + + true + true + true + true + + + Pixel + Pixel + Pixel + Pixel + true + true + true + true + + + true + true + true + true + true true diff --git a/swGUI/ProjectDir/Visual2015/CoreGUI/CoreGUI.vcxproj.filters b/swGUI/ProjectDir/Visual2015/CoreGUI/CoreGUI.vcxproj.filters index 6e4e2d73..db2e0b94 100644 --- a/swGUI/ProjectDir/Visual2015/CoreGUI/CoreGUI.vcxproj.filters +++ b/swGUI/ProjectDir/Visual2015/CoreGUI/CoreGUI.vcxproj.filters @@ -198,12 +198,6 @@ Core\Media\Brushes - - Core\Media\Brushes - - - Core\Media\Brushes - Core\System\Events @@ -318,6 +312,21 @@ Core\Media\Geometry + + Core\Media\Geometry + + + Core\Controls\Shapes + + + Core\Media\Brushes + + + Core\Media\Brushes + + + Core\Media\Brushes + @@ -452,6 +461,24 @@ Core\Controls\Shapes + + Core\Media\Geometry + + + Core\Controls\Shapes + + + Core\Media\Brushes + + + Core\Media\Brushes + + + Core\Media\Brushes + + + Core\Media\Brushes + @@ -477,5 +504,14 @@ Core\Shaders\hlsl\Geometry + + Core\Shaders\hlsl\Brush + + + Core\Shaders\hlsl\Brush + + + Core\Shaders\hlsl\Brush + \ No newline at end of file diff --git a/swGUI/ProjectDir/Visual2015/Tests/TestRenderingSystem/TestRenderingSystem.vcxproj b/swGUI/ProjectDir/Visual2015/Tests/TestRenderingSystem/TestRenderingSystem.vcxproj index 8be891d7..4e88bd3b 100644 --- a/swGUI/ProjectDir/Visual2015/Tests/TestRenderingSystem/TestRenderingSystem.vcxproj +++ b/swGUI/ProjectDir/Visual2015/Tests/TestRenderingSystem/TestRenderingSystem.vcxproj @@ -41,6 +41,7 @@ + diff --git a/swGUI/ProjectDir/Visual2015/Tests/TestRenderingSystem/TestRenderingSystem.vcxproj.filters b/swGUI/ProjectDir/Visual2015/Tests/TestRenderingSystem/TestRenderingSystem.vcxproj.filters index 3b59a5c1..a8b7e532 100644 --- a/swGUI/ProjectDir/Visual2015/Tests/TestRenderingSystem/TestRenderingSystem.vcxproj.filters +++ b/swGUI/ProjectDir/Visual2015/Tests/TestRenderingSystem/TestRenderingSystem.vcxproj.filters @@ -22,5 +22,8 @@ TestRenderingSystem + + TestRenderingSystem + \ No newline at end of file diff --git a/swGUI/Prototypes/PrototyperGUI/Application.cpp b/swGUI/Prototypes/PrototyperGUI/Application.cpp index b710ea34..80cbe567 100644 --- a/swGUI/Prototypes/PrototyperGUI/Application.cpp +++ b/swGUI/Prototypes/PrototyperGUI/Application.cpp @@ -1,7 +1,12 @@ #include "Application.h" #include "swGUI/Core/Controls/Shapes/Rectangle.h" +#include "swGUI/Core/Controls/Shapes/Ellipse.h" + #include "swGUI/Core/Media/Brushes/SolidColorBrush.h" +#include "swGUI/Core/Media/Brushes/LinearGradientBrush.h" +#include "swGUI/Core/Media/Brushes/AngleGradientBrush.h" +#include "swGUI/Core/Media/Brushes/ImageBrush.h" #include "PrototyperUtils.h" @@ -40,13 +45,29 @@ void AddRectangle ( HostWindow* host, BrushPtr brush, BrushPtr stroke, floa host->AddChild( std::move( rectangleControl ) ); } +// ================================ // +// +void AddEllipse ( HostWindow* host, BrushPtr brush, BrushPtr stroke, float width, float height, float broderThickness, Position pos ) +{ + EllipseOPtr ellipseControl = EllipseOPtr( new Ellipse() ); + + ellipseControl->SetFill( brush ); + ellipseControl->SetStroke( stroke ); + + ellipseControl->SetHeight( height ); + ellipseControl->SetWidth( width ); + ellipseControl->SetThickness( broderThickness ); + + ellipseControl->SetOffset( pos ); + + host->AddChild( std::move( ellipseControl ) ); +} + // ================================ // // -void AddRectangle ( HostWindow* host ) +void AddControls ( HostWindow* host ) { - RectangleOPtr rectangleControl = RectangleOPtr( new Rectangle() ); - auto brush = std::make_shared< SolidColorBrush >( Color( 1.0, 0.0, 0.0, 1.0 ) ); auto stroke = std::make_shared< SolidColorBrush >( Color( 0.0, 1.0, 0.0, 1.0 ) ); @@ -61,9 +82,76 @@ void AddRectangle ( HostWindow* host ) stroke = std::make_shared< SolidColorBrush >( Color( 0.0, 1.0, 0.0, 1.0 ) ); AddRectangle( host, stroke, brush, 100, 768, 2, Position( 400, 0 ) ); + + brush = std::make_shared< SolidColorBrush >( Color( 0.0, 0.0, 1.0, 1.0 ) ); + stroke = std::make_shared< SolidColorBrush >( Color( 0.0, 0.0, 0.0, 1.0 ) ); + + AddEllipse( host, stroke, brush, 100, 200, 8, Position( 200, 300 ) ); + + auto gradientBrush = std::make_shared< LinearGradientBrush >(); + gradientBrush->AddGradientStop( GradientStop( 0xFFFF0000, 0.0f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFF0000FF, 1.0f ) ); + stroke = std::make_shared< SolidColorBrush >( Color( 0.0, 0.0, 0.0, 1.0 ) ); + + AddRectangle( host, gradientBrush, stroke, 40, 768, 2, Position( 600, 0 ) ); + + gradientBrush = std::make_shared< LinearGradientBrush >(); + gradientBrush->AddGradientStop( GradientStop( 0xFFFF0000, 0.3f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFF0000FF, 0.7f ) ); + stroke = std::make_shared< SolidColorBrush >( Color( 0.0, 0.0, 0.0, 1.0 ) ); + + AddRectangle( host, gradientBrush, stroke, 40, 768, 2, Position( 650, 0 ) ); + + gradientBrush = std::make_shared< LinearGradientBrush >(); + gradientBrush->AddGradientStop( GradientStop( 0xFFFF0000, 0.0f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFF00FF00, 0.4f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFF0000FF, 0.7f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFFFFFF00, 1.0f ) ); + stroke = std::make_shared< SolidColorBrush >( Color( 0.0, 0.0, 0.0, 1.0 ) ); + + AddRectangle( host, gradientBrush, stroke, 40, 768, 2, Position( 700, 0 ) ); + + gradientBrush = std::make_shared< LinearGradientBrush >(); + gradientBrush->SetGradientAxis( Point( 0.0f, 0.0f ), Point( 1.0f, 1.0f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFFFF0000, 0.0f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFF00FF00, 0.4f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFF0000FF, 0.7f ) ); + gradientBrush->AddGradientStop( GradientStop( 0xFFFFFF00, 1.0f ) ); + stroke = std::make_shared< SolidColorBrush >( Color( 0.0, 0.0, 0.0, 1.0 ) ); + + AddRectangle( host, gradientBrush, stroke, 120, 768, 2, Position( 750, 0 ) ); } +// ================================ // +// +void AddControls2 ( HostWindow* host ) +{ + auto angleBrush = std::make_shared< AngleGradientBrush >(); + angleBrush->SetGradientCenter( Point( 0.5f, 0.5f ) ); + angleBrush->AddGradientStop( GradientStop( 0xFFFF0000, 0.0f ) ); + angleBrush->AddGradientStop( GradientStop( 0xFFFFFF00, 1.0f ) ); + auto stroke = std::make_shared< SolidColorBrush >( Color( 0.0, 0.0, 0.0, 1.0 ) ); + + AddRectangle( host, angleBrush, stroke, 200, 200, 2, Position( 30, 30 ) ); + + auto fill = std::make_shared< SolidColorBrush >( Color( 0.0, 0.0, 0.0, 0.0 ) ); + angleBrush = std::make_shared< AngleGradientBrush >(); + angleBrush->SetGradientCenter( Point( 0.5f, 0.5f ) ); + angleBrush->AddGradientStop( GradientStop( 0xFFFF0000, 0.0f ) ); + angleBrush->AddGradientStop( GradientStop( 0xFFFFFF00, 0.3f ) ); + angleBrush->AddGradientStop( GradientStop( 0xFF00FFFF, 0.7f ) ); + angleBrush->AddGradientStop( GradientStop( 0xFF0000FF, 1.0f ) ); + + AddEllipse( host, fill, angleBrush, 150, 150, 15, Position( 220, 300 ) ); + + auto imageBrush = std::make_shared< ImageBrush >(); + imageBrush->SetTexture( "$(Application-Dir)/pool-water-texture.jpg" ); + stroke = std::make_shared< SolidColorBrush >( Color( 1.0, 0.0, 0.0, 1.0 ) ); + + AddRectangle( host, imageBrush, stroke, 200, 200, 2, Position( 250, 30 ) ); +} + // ================================ // @@ -79,8 +167,10 @@ If you need specific gui initialization in your application override this functi You can set different GraphicApi or input api.*/ sw::ReturnResult Application::Initialize() { + m_guiConfig.DebugGraphics = true; + sw::ReturnResult result = sw::Result::Success; - + result = result && DefaultInit( 1024, 768, "Window Tittle" ); result = result && OverridePaths(); @@ -93,6 +183,7 @@ sw::ReturnResult Application::OverridePaths () { auto coreGUISourcePath = FindCoreGUISourcePath( m_nativeGUI->GetOS()->GetApplicationDir() ); + m_pathsManager->RegisterAlias( "$(Application-Dir)", coreGUISourcePath / "ProjectDir/Output/Application-Dir/" ); return m_pathsManager->OverrideAlias( "$(CoreGUI-Shader-Dir)", coreGUISourcePath / "Core/Shaders/hlsl" ); } @@ -111,8 +202,8 @@ sw::ReturnResult Application::OnInitialized() window.Get()->PreviewMouseMove() += MouseMoveEventHandler( &MouseMoveEventReceived ); m_windows[ 0 ]->PreviewMouseMove() += MouseMoveEventHandler( &MouseMoveEventReceived ); - //AddRectangle( window ); - AddRectangle( m_windows[ 0 ] ); + AddControls( m_windows[ 0 ] ); + AddControls2( m_windows[ 1 ] ); return sw::Result::Success; } diff --git a/swGUI/Prototypes/PrototyperGUI/Sizeofs/Sizeofs.cpp b/swGUI/Prototypes/PrototyperGUI/Sizeofs/Sizeofs.cpp index 98d67e40..519a80a5 100644 --- a/swGUI/Prototypes/PrototyperGUI/Sizeofs/Sizeofs.cpp +++ b/swGUI/Prototypes/PrototyperGUI/Sizeofs/Sizeofs.cpp @@ -15,6 +15,7 @@ #include "swGUI/Core/Controls/Visual.h" #include "swGUI/Core/Controls/Shapes/Rectangle.h" +#include "swGUI/Core/Controls/Shapes/Ellipse.h" #include "swGUI/Core/System/DataBinding/BindingInfo.h" @@ -70,7 +71,8 @@ void PrintControlsSizeofs () PrintSizeofType< sw::gui::Shape >( std::cout ); PrintSizeofType< sw::gui::Rectangle >( std::cout ); - + PrintSizeofType< sw::gui::Ellipse >( std::cout ); + std::cout << std::endl; } diff --git a/swGUI/TestFramework/Utils/Mocks/Media/FakeBrush.cpp b/swGUI/TestFramework/Utils/Mocks/Media/FakeBrush.cpp index 69123b8a..9cf061aa 100644 --- a/swGUI/TestFramework/Utils/Mocks/Media/FakeBrush.cpp +++ b/swGUI/TestFramework/Utils/Mocks/Media/FakeBrush.cpp @@ -18,6 +18,7 @@ namespace gui FakeBrush::FakeBrush() : Brush( Brush::ConstantBufferMode::Enable ) , m_shaderFun( "$(CoreGUI-Shader-Dir)/FakeBrush.ps" ) + , m_cBuffer( "::FakeBrush-Constants" ) {} // ================================ // @@ -45,7 +46,7 @@ AssetPath FakeBrush::TextureSource () // AssetPath FakeBrush::ConstantsName () { - return "::FakeBrush-Constants"; + return AssetPath( "", m_cBuffer ); } // ================================ // @@ -64,6 +65,17 @@ void FakeBrush::SetTextureFile ( const std::string& tex ) InvalidateTexture(); } +// ================================ // +// +void FakeBrush::ChangeConstsBuffer ( const std::string& newBuffer ) +{ + if( m_cBuffer != newBuffer ) + { + m_cBuffer = newBuffer; + InvalidateConstsBuffer(); + } +} + } // gui } // sw \ No newline at end of file diff --git a/swGUI/TestFramework/Utils/Mocks/Media/FakeBrush.h b/swGUI/TestFramework/Utils/Mocks/Media/FakeBrush.h index 87daee89..d96351fc 100644 --- a/swGUI/TestFramework/Utils/Mocks/Media/FakeBrush.h +++ b/swGUI/TestFramework/Utils/Mocks/Media/FakeBrush.h @@ -29,7 +29,7 @@ class FakeBrush : public Brush std::string m_shaderFun; std::string m_textureFile; - + std::string m_cBuffer; StackBufferA< Params > m_constants; public: @@ -50,11 +50,13 @@ class FakeBrush : public Brush using Brush::NeedsShaderUpdate; using Brush::NeedsTextureUpdate; using Brush::NeedsConstantsUpdate; + using Brush::NeedsBufferChange; public: void SetShaderFunction ( const std::string& shaderFun ); void SetTextureFile ( const std::string& tex ); + void ChangeConstsBuffer ( const std::string& newBuffer ); }; DEFINE_PTR_TYPE( FakeBrush ) diff --git a/swGUI/Tests/TestRenderingSystem.DX11/TestBrushShaderCompilation.cpp b/swGUI/Tests/TestRenderingSystem.DX11/TestBrushShaderCompilation.cpp index cee592a9..0c33a351 100644 --- a/swGUI/Tests/TestRenderingSystem.DX11/TestBrushShaderCompilation.cpp +++ b/swGUI/Tests/TestRenderingSystem.DX11/TestBrushShaderCompilation.cpp @@ -8,6 +8,9 @@ // Include Brushes #include "swGUI/Core/Media/Brushes/SolidColorBrush.h" +#include "swGUI/Core/Media/Brushes/LinearGradientBrush.h" +#include "swGUI/Core/Media/Brushes/AngleGradientBrush.h" +#include "swGUI/Core/Media/Brushes/ImageBrush.h" @@ -34,3 +37,54 @@ TEST_CASE( "GUI.Rendering.DX11.Brush.ShaderCompilation.SolidColorBrush", "[GUISy CHECK( renderingData.PixelShader != nullptr ); } +// ================================ // +// +TEST_CASE( "GUI.Rendering.DX11.Brush.ShaderCompilation.LinearGradientBrush", "[GUISystem][RenderingSystem][Drawing]" ) +{ + TestFramework* framework = GetGlobalTestFramework(); + + FakeDrawingPtr drawing = std::make_shared< FakeDrawing >(); + LinearGradientBrushPtr brush = std::make_shared< LinearGradientBrush >(); + + drawing->UpdateBrushShader( framework->GetRenderingSystem()->GetShaderProvider(), brush.get() ); + + auto& renderingData = CLASS_TESTER( Drawing )::GetBrushRenderingData( drawing.get() ); + + INFO( "[LinearGradientBrush] Brush Shader compilation failed." ); + CHECK( renderingData.PixelShader != nullptr ); +} + +// ================================ // +// +TEST_CASE( "GUI.Rendering.DX11.Brush.ShaderCompilation.AngleGradientBrush", "[GUISystem][RenderingSystem][Drawing]" ) +{ + TestFramework* framework = GetGlobalTestFramework(); + + FakeDrawingPtr drawing = std::make_shared< FakeDrawing >(); + AngleGradientBrushPtr brush = std::make_shared< AngleGradientBrush >(); + + drawing->UpdateBrushShader( framework->GetRenderingSystem()->GetShaderProvider(), brush.get() ); + + auto& renderingData = CLASS_TESTER( Drawing )::GetBrushRenderingData( drawing.get() ); + + INFO( "[AngleGradientBrush] Brush Shader compilation failed." ); + CHECK( renderingData.PixelShader != nullptr ); +} + +// ================================ // +// +TEST_CASE( "GUI.Rendering.DX11.Brush.ShaderCompilation.ImageBrush", "[GUISystem][RenderingSystem][Drawing]" ) +{ + TestFramework* framework = GetGlobalTestFramework(); + + FakeDrawingPtr drawing = std::make_shared< FakeDrawing >(); + ImageBrushPtr brush = std::make_shared< ImageBrush >(); + + drawing->UpdateBrushShader( framework->GetRenderingSystem()->GetShaderProvider(), brush.get() ); + + auto& renderingData = CLASS_TESTER( Drawing )::GetBrushRenderingData( drawing.get() ); + + INFO( "[ImageBrush] Brush Shader compilation failed." ); + CHECK( renderingData.PixelShader != nullptr ); +} + diff --git a/swGUI/Tests/TestRenderingSystem.DX11/TestPenShaderCompilation.cpp b/swGUI/Tests/TestRenderingSystem.DX11/TestPenShaderCompilation.cpp index 11d7e7dd..5b657519 100644 --- a/swGUI/Tests/TestRenderingSystem.DX11/TestPenShaderCompilation.cpp +++ b/swGUI/Tests/TestRenderingSystem.DX11/TestPenShaderCompilation.cpp @@ -8,6 +8,9 @@ // Include Brushes #include "swGUI/Core/Media/Brushes/SolidColorBrush.h" +#include "swGUI/Core/Media/Brushes/LinearGradientBrush.h" +#include "swGUI/Core/Media/Brushes/AngleGradientBrush.h" +#include "swGUI/Core/Media/Brushes/ImageBrush.h" @@ -41,3 +44,53 @@ TEST_CASE( "GUI.Rendering.DX11.Pen.ShaderCompilation.SolidColorBrush", "[GUISyst CHECK( renderingData.PixelShader != nullptr ); } +// ================================ // +// +TEST_CASE( "GUI.Rendering.DX11.Pen.ShaderCompilation.LinearGradientBrush", "[GUISystem][RenderingSystem][Drawing]" ) +{ + TestFramework* framework = GetGlobalTestFramework(); + + FakeDrawingPtr drawing = std::make_shared< FakeDrawing >(); + LinearGradientBrushPtr brush = std::make_shared< LinearGradientBrush >(); + + drawing->UpdatePenShader( framework->GetRenderingSystem()->GetShaderProvider(), brush.get() ); + + auto& renderingData = CLASS_TESTER( Drawing )::GetPenRenderingData( drawing.get() ); + + INFO( "[LinearGradientBrush] Pen Shader compilation failed." ); + CHECK( renderingData.PixelShader != nullptr ); +} + +// ================================ // +// +TEST_CASE( "GUI.Rendering.DX11.Pen.ShaderCompilation.AngleGradientBrush", "[GUISystem][RenderingSystem][Drawing]" ) +{ + TestFramework* framework = GetGlobalTestFramework(); + + FakeDrawingPtr drawing = std::make_shared< FakeDrawing >(); + AngleGradientBrushPtr brush = std::make_shared< AngleGradientBrush >(); + + drawing->UpdatePenShader( framework->GetRenderingSystem()->GetShaderProvider(), brush.get() ); + + auto& renderingData = CLASS_TESTER( Drawing )::GetPenRenderingData( drawing.get() ); + + INFO( "[AngleGradientBrush] Pen Shader compilation failed." ); + CHECK( renderingData.PixelShader != nullptr ); +} + +// ================================ // +// +TEST_CASE( "GUI.Rendering.DX11.Pen.ShaderCompilation.ImageBrush", "[GUISystem][RenderingSystem][Drawing]" ) +{ + TestFramework* framework = GetGlobalTestFramework(); + + FakeDrawingPtr drawing = std::make_shared< FakeDrawing >(); + ImageBrushPtr brush = std::make_shared< ImageBrush >(); + + drawing->UpdatePenShader( framework->GetRenderingSystem()->GetShaderProvider(), brush.get() ); + + auto& renderingData = CLASS_TESTER( Drawing )::GetPenRenderingData( drawing.get() ); + + INFO( "[ImageBrush] Pen Shader compilation failed." ); + CHECK( renderingData.PixelShader != nullptr ); +} diff --git a/swGUI/Tests/TestRenderingSystem.DX11/TestWindowRendering.cpp b/swGUI/Tests/TestRenderingSystem.DX11/TestWindowRendering.cpp index d297a91c..84e163db 100644 --- a/swGUI/Tests/TestRenderingSystem.DX11/TestWindowRendering.cpp +++ b/swGUI/Tests/TestRenderingSystem.DX11/TestWindowRendering.cpp @@ -11,7 +11,9 @@ #include "swGUI/Native/MockNativeGUI/MockGUI.h" #include "swGUI/Core/Controls/Shapes/Rectangle.h" +#include "swGUI/Core/Controls/Shapes/Ellipse.h" #include "swGUI/Core/Media/Brushes/SolidColorBrush.h" +#include "swGUI/Core/Media/Brushes/LinearGradientBrush.h" using namespace sw; diff --git a/swGUI/Tests/TestRenderingSystem/TestDrawing.cpp b/swGUI/Tests/TestRenderingSystem/TestDrawing.cpp index 7592a8c1..0cd30cac 100644 --- a/swGUI/Tests/TestRenderingSystem/TestDrawing.cpp +++ b/swGUI/Tests/TestRenderingSystem/TestDrawing.cpp @@ -220,6 +220,59 @@ TEST_CASE( "GUI.Rendering.Drawing.Geometry.UpdateConstants", "[GUISystem][Render CHECK( renderingData.GeometryConstants != nullptr ); } +// ================================ // +// +TEST_CASE( "GUI.Rendering.Drawing.Brush.ChangeConstantsBuffer", "[GUISystem][RenderingSystem][Drawing]" ) +{ + TestFramework framework( 0, nullptr ); framework.Init(); + + FakeDrawingPtr drawing = std::make_shared< FakeDrawing >(); + FakeBrushPtr brush = std::make_shared< FakeBrush >(); + + auto& renderingData = CLASS_TESTER( Drawing )::GetBrushRenderingData( drawing.get() ); + REQUIRE( renderingData.BrushConstants == nullptr ); + + drawing->UpdateBrushConstants( framework.GetResourceManagerAPI(), brush.get() ); + + auto prevBuff = renderingData.BrushConstants; + CHECK( prevBuff != nullptr ); + + brush->ChangeConstsBuffer( "NewBuffer" ); + CHECK( brush->NeedsBufferChange() == true ); + + drawing->UpdateBrushConstants( framework.GetResourceManagerAPI(), brush.get() ); + + CHECK( prevBuff != renderingData.BrushConstants ); + CHECK( brush->NeedsBufferChange() == false ); +} + +// ================================ // +// +TEST_CASE( "GUI.Rendering.Drawing.Pen.ChangeConstantsBuffer", "[GUISystem][RenderingSystem][Drawing]" ) +{ + TestFramework framework( 0, nullptr ); framework.Init(); + + FakeDrawingPtr drawing = std::make_shared< FakeDrawing >(); + FakeBrushPtr pen = std::make_shared< FakeBrush >(); + + auto& renderingData = CLASS_TESTER( Drawing )::GetPenRenderingData( drawing.get() ); + REQUIRE( renderingData.BrushConstants == nullptr ); + + drawing->UpdatePenConstants( framework.GetResourceManagerAPI(), pen.get() ); + + auto prevBuff = renderingData.BrushConstants; + CHECK( prevBuff != nullptr ); + + pen->ChangeConstsBuffer( "NewBuffer" ); + CHECK( pen->NeedsBufferChange() == true ); + + drawing->UpdatePenConstants( framework.GetResourceManagerAPI(), pen.get() ); + + CHECK( prevBuff != renderingData.BrushConstants ); + CHECK( pen->NeedsBufferChange() == false ); +} + + //====================================================================================// // Geometry update //====================================================================================// diff --git a/swGUI/Tests/TestRenderingSystem/TestGradientBrush.cpp b/swGUI/Tests/TestRenderingSystem/TestGradientBrush.cpp new file mode 100644 index 00000000..8155c255 --- /dev/null +++ b/swGUI/Tests/TestRenderingSystem/TestGradientBrush.cpp @@ -0,0 +1,148 @@ +#include "swCommonLib/External/Catch/catch.hpp" + +#include "swGUI/TestFramework/TestFramework.h" + +#include "swGUI/Core/System/Rendering/Drawings/Drawing.h" +#include "swGUI/Core/Media/Brushes/LinearGradientBrush.h" +#include "swGUI/Core/Media/Brushes/AngleGradientBrush.h" + +#include "swGUI/TestFramework/Testers/Rendering/DrawingTester.h" + + +using namespace sw; +using namespace sw::gui; + + +// ================================ // +// Adding GradientStops should cause change of buffer. +TEST_CASE( "GUI.Rendering.Brush.GradientBrush.AddingGradientStops", "[GUISystem][RenderingSystem][Brush]" ) +{ + TestFramework framework( 0, nullptr ); framework.Init(); + LinearGradientBrushPtr brush = std::make_shared< LinearGradientBrush >(); + + auto constsName = brush->ConstantsName(); + + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + + CHECK( constsName != brush->ConstantsName() ); +} + + +// ================================ // +// Adding GradientStops should cause change of buffer. +TEST_CASE( "GUI.Rendering.Brush.GradientBrush.RemovingGradientStops", "[GUISystem][RenderingSystem][Brush]" ) +{ + TestFramework framework( 0, nullptr ); framework.Init(); + LinearGradientBrushPtr brush = std::make_shared< LinearGradientBrush >(); + + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + + auto constsName = brush->ConstantsName(); + + brush->RemoveGradientStop( 0 ); + brush->RemoveGradientStop( 0 ); + brush->RemoveGradientStop( 0 ); + + CHECK( constsName != brush->ConstantsName() ); +} + +// ================================ // +// Tests if GradientBrush produces buffer with layout expected by GPU. +TEST_CASE( "GUI.Rendering.Brush.GradientBrush.BufferGeneration.LinearGradientBrush", "[GUISystem][RenderingSystem][Brush]" ) +{ + TestFramework framework( 0, nullptr ); framework.Init(); + LinearGradientBrushPtr brush = std::make_shared< LinearGradientBrush >(); + + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + brush->AddGradientStop( GradientStop( 0xFFFF0000, 0.4f ) ); + brush->AddGradientStop( GradientStop( 0xFFFFFF00, 0.6f ) ); + brush->AddGradientStop( GradientStop( 0xFF0000FF, 1.0f ) ); + + + struct TestBufferLayout + { + Point GradientStart; + Point GradientEnd; + uint32 NumStops; + uint32 Padding[ 3 ]; + + // Note: Shader will place each Gradient stop in separate register. + // We must add 8 bytes to achive the same in this structure. + std::pair< GradientStop, double > Stops[ 4 ]; + }; + + auto buffer = brush->BufferData(); + auto bufferTyped = reinterpret_cast( buffer.DataPtr ); + + CHECK( buffer.DataSize == sizeof( TestBufferLayout ) ); + CHECK( buffer.DataSize % 16 == 0 ); + + CHECK( bufferTyped->NumStops == 4 ); + CHECK( bufferTyped->Stops[ 0 ].first.Color == 0xFFFF00FF ); + CHECK( bufferTyped->Stops[ 0 ].first.Offset == 0.0f ); + CHECK( bufferTyped->Stops[ 1 ].first.Color == 0xFFFF0000 ); + CHECK( bufferTyped->Stops[ 1 ].first.Offset == 0.4f ); + CHECK( bufferTyped->Stops[ 2 ].first.Color == 0xFFFFFF00 ); + CHECK( bufferTyped->Stops[ 2 ].first.Offset == 0.6f ); + CHECK( bufferTyped->Stops[ 3 ].first.Color == 0xFF0000FF ); + CHECK( bufferTyped->Stops[ 3 ].first.Offset == 1.0f ); + + // Manually check buffer offsets. If something fails here you should check + // Brush structure, because they might change size. + CHECK( offsetof( TestBufferLayout, NumStops ) == 16 ); + CHECK( offsetof( TestBufferLayout, Stops ) == 32 ); + CHECK( offsetof( TestBufferLayout, Stops[ 1 ] ) == 48 ); +} + +// ================================ // +// Tests if GradientBrush produces buffer with layout expected by GPU. +TEST_CASE( "GUI.Rendering.Brush.GradientBrush.BufferGeneration.AngleGradientBrush", "[GUISystem][RenderingSystem][Brush]" ) +{ + TestFramework framework( 0, nullptr ); framework.Init(); + AngleGradientBrushPtr brush = std::make_shared< AngleGradientBrush >(); + + brush->AddGradientStop( GradientStop( 0xFFFF00FF, 0.0f ) ); + brush->AddGradientStop( GradientStop( 0xFFFF0000, 0.4f ) ); + brush->AddGradientStop( GradientStop( 0xFFFFFF00, 0.6f ) ); + brush->AddGradientStop( GradientStop( 0xFF0000FF, 1.0f ) ); + + + struct TestBufferLayout + { + Point Center; + uint32 NumStops; + uint32 Padding[ 1 ]; + + // Note: Shader will place each Gradient stop in separate register. + // We must add 8 bytes to achive the same in this structure. + std::pair< GradientStop, double > Stops[ 4 ]; + }; + + auto buffer = brush->BufferData(); + auto bufferTyped = reinterpret_cast< TestBufferLayout* >( buffer.DataPtr ); + + CHECK( buffer.DataSize == sizeof( TestBufferLayout ) ); + CHECK( buffer.DataSize % 16 == 0 ); + + CHECK( bufferTyped->NumStops == 4 ); + CHECK( bufferTyped->Stops[ 0 ].first.Color == 0xFFFF00FF ); + CHECK( bufferTyped->Stops[ 0 ].first.Offset == 0.0f ); + CHECK( bufferTyped->Stops[ 1 ].first.Color == 0xFFFF0000 ); + CHECK( bufferTyped->Stops[ 1 ].first.Offset == 0.4f ); + CHECK( bufferTyped->Stops[ 2 ].first.Color == 0xFFFFFF00 ); + CHECK( bufferTyped->Stops[ 2 ].first.Offset == 0.6f ); + CHECK( bufferTyped->Stops[ 3 ].first.Color == 0xFF0000FF ); + CHECK( bufferTyped->Stops[ 3 ].first.Offset == 1.0f ); + + // Manually check buffer offsets. If something fails here you should check + // Brush structure, because they might change size. + CHECK( offsetof( TestBufferLayout, NumStops ) == 8 ); + CHECK( offsetof( TestBufferLayout, Stops ) == 16 ); + CHECK( offsetof( TestBufferLayout, Stops[ 1 ] ) == 32 ); +} diff --git a/swGeometrics/BasicShapes/Shapes2D/Ellipse.h b/swGeometrics/BasicShapes/Shapes2D/Ellipse.h new file mode 100644 index 00000000..d4bfdbc1 --- /dev/null +++ b/swGeometrics/BasicShapes/Shapes2D/Ellipse.h @@ -0,0 +1,60 @@ +#pragma once +/** +@file Ellipse.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + + + +#include "swCommonLib/Common/TypesDefinitions.h" +#include "swGeometrics/GeometricsCore/Types/Accessors/DefaultAccessors.h" +#include "swGeometrics/GeometricsCore/Types/Traits/GeneratorTraits.h" + + + + +namespace sw { +namespace geom +{ + + + +/**@brief Ellipse generator. +@ingroup Shapes2D*/ +template< typename VertexType, typename IndexType, typename PositionAcc = DefaultPositionAcc< VertexType > > +class Ellipse : public GeneratorTraits< VertexType, IndexType > +{ +private: +public: + + float Width; + float Height; + uint32 Tesselation; + +public: + + inline explicit Ellipse (); + + + inline void GenerateVertex ( VertexType& vertex, Size vertexIdx ); + + template< class IndexBuffer > + inline void GenerateIndexBuffer ( IndexBuffer& idxBuffer, Size startIdx ); + + inline Size GetNumberVerticies () const; + inline Size GetNumberIndicies () const; + + inline ReturnResult ValidateParams () const; + +protected: + + inline void GenerateVertex ( VertexType& vertex, Size vertexIdx, float width, float height ); +}; + + + +} // geom +} // sw + +#include "Ellipse.inl" diff --git a/swGeometrics/BasicShapes/Shapes2D/Ellipse.inl b/swGeometrics/BasicShapes/Shapes2D/Ellipse.inl new file mode 100644 index 00000000..1edb91f9 --- /dev/null +++ b/swGeometrics/BasicShapes/Shapes2D/Ellipse.inl @@ -0,0 +1,123 @@ +#pragma once +/** +@file Ellipse.inl +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + +#include "Ellipse.h" + +#include "swCommonLib/Common/Converters.h" +#include "swCommonLib/Common/Exceptions/ErrorsCollector.h" + +#define _USE_MATH_DEFINES +#include + + + +namespace sw { +namespace geom +{ + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline Ellipse< VertexType, IndexType, PositionAcc >::Ellipse () + : Tesselation( 10 ) + , Width( 1.0f ) + , Height( 1.0f ) +{} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline void Ellipse< VertexType, IndexType, PositionAcc >::GenerateVertex ( VertexType& vertex, Size vertexIdx ) +{ + GenerateVertex( vertex, vertexIdx, Width, Height ); +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline void Ellipse< VertexType, IndexType, PositionAcc >::GenerateVertex ( VertexType& vertex, Size vertexIdx, float width, float height ) +{ + float angleDelta = float( 2 * M_PI / Tesselation ); + float angle = angleDelta * vertexIdx; + + auto& pos = PositionAcc::Get( vertex ); + pos.x = width * sinf( angle ) / 2.0f; + pos.y = height * cosf( angle ) / 2.0f; +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +template< class IndexBuffer > +inline void Ellipse< VertexType, IndexType, PositionAcc >::GenerateIndexBuffer ( IndexBuffer& idxBuffer, Size startIdx ) +{ + IndexType numVerts = (IndexType)GetNumberVerticies(); + IndexType rightIdx = 1; + IndexType leftIdx = numVerts - 1; // Last vertex. + + // Add top triangle without pair. + AddTriangleCW( idxBuffer, startIdx, 0, rightIdx, leftIdx ); + + // Add pairs of triangles from left to right side of circle. + while( leftIdx - rightIdx > 3 ) + { + AddTriangleCW( idxBuffer, startIdx, leftIdx, rightIdx, leftIdx - 1 ); + AddTriangleCW( idxBuffer, startIdx, leftIdx - 1, rightIdx, rightIdx + 1 ); + + rightIdx++; + leftIdx--; + } + + // If there's one vertex left, we need to add one triangle else. Note that if + // we have even number of verticies, two last verticies were already used to create two traingles + // in previous while loop. + if( leftIdx - rightIdx == 2 ) + AddTriangleCW( idxBuffer, startIdx, leftIdx, rightIdx, leftIdx - 1 ); +} + + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline Size Ellipse< VertexType, IndexType, PositionAcc >::GetNumberVerticies () const +{ + return Tesselation; +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline Size Ellipse< VertexType, IndexType, PositionAcc >::GetNumberIndicies () const +{ + return 3 * ( Tesselation - 2 ); +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline ReturnResult Ellipse< VertexType, IndexType, PositionAcc >::ValidateParams () const +{ + ErrorsCollector collector; + + if( Tesselation <= 2 ) + collector.Add( "[Circle] Invalid parameter [Tesselation=" + Convert::ToString( Tesselation ) + "] should be greater then 2." ); + + if( Width <= 0.0f ) + collector.Add( "[Circle] Invalid parameter [Width=" + Convert::ToString( Width ) + "] should be greater then 0." ); + + if( Height <= 0.0f ) + collector.Add( "[Circle] Invalid parameter [Width=" + Convert::ToString( Height ) + "] should be greater then 0." ); + + return collector; +} + + + +} // geom +} // sw + + diff --git a/swGeometrics/BasicShapes/Shapes2D/EllipseWithBorder.h b/swGeometrics/BasicShapes/Shapes2D/EllipseWithBorder.h new file mode 100644 index 00000000..3a027130 --- /dev/null +++ b/swGeometrics/BasicShapes/Shapes2D/EllipseWithBorder.h @@ -0,0 +1,55 @@ +#pragma once +/** +@file EllipseWithBorder.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + +#include "Ellipse.h" + + +namespace sw { +namespace geom +{ + + + + +/**@brief Ellipse with border generator for GUI. +@ingroup Shapes2D*/ +template< typename VertexType, typename IndexType, typename PositionAcc = DefaultPositionAcc< VertexType > > +class EllipseWithBorder : public Ellipse< VertexType, IndexType, PositionAcc > +{ +private: + + typedef Ellipse< VertexType, IndexType, PositionAcc > Parent; + +public: + + float StrokeThickness; + +public: + + inline explicit EllipseWithBorder (); + + + inline void GenerateVertex ( VertexType& vertex, Size vertexIdx ); + + template< class IndexBuffer > + inline void GenerateIndexBuffer ( IndexBuffer& idxBuffer, Size startIdx ); + + inline Size GetNumberVerticies () const; + inline Size GetNumberIndicies () const; + + inline Size GetNumberFillIndicies () const; + inline Size GetNumberBorderIndicies () const; + + inline ReturnResult ValidateParams () const; + +}; + + +} // geom +} // sw + +#include "EllipseWithBorder.inl" diff --git a/swGeometrics/BasicShapes/Shapes2D/EllipseWithBorder.inl b/swGeometrics/BasicShapes/Shapes2D/EllipseWithBorder.inl new file mode 100644 index 00000000..f619386f --- /dev/null +++ b/swGeometrics/BasicShapes/Shapes2D/EllipseWithBorder.inl @@ -0,0 +1,111 @@ +#pragma once +/** +@file EllipseWithBorder.inl +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + +#include "EllipseWithBorder.h" + + + + +namespace sw { +namespace geom +{ + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline EllipseWithBorder< VertexType, IndexType, PositionAcc >::EllipseWithBorder () + : StrokeThickness( 0 ) +{} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline void EllipseWithBorder< VertexType, IndexType, PositionAcc >::GenerateVertex ( VertexType& vertex, Size vertexIdx ) +{ + if( vertexIdx < Parent::GetNumberVerticies() ) + Parent::GenerateVertex( vertex, vertexIdx, Width, Height ); + else + Parent::GenerateVertex( vertex, vertexIdx, Width - 2 * StrokeThickness, Height - 2 * StrokeThickness ); +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +template< class IndexBuffer > +inline void EllipseWithBorder< VertexType, IndexType, PositionAcc >::GenerateIndexBuffer ( IndexBuffer& idxBuffer, Size startIdx ) +{ + Parent::GenerateIndexBuffer( idxBuffer, startIdx ); + + startIdx += Parent::GetNumberIndicies(); + IndexType borderOffset = (IndexType)Parent::GetNumberVerticies(); + + IndexType idx = 0; + for( ; idx < Parent::GetNumberVerticies() - 1; ++idx ) + { + AddTriangleCW( idxBuffer, startIdx, idx + borderOffset, idx, idx + borderOffset + 1 ); + AddTriangleCW( idxBuffer, startIdx, idx + borderOffset + 1, idx, idx + 1 ); + } + + // Last triangles reference last and first vertex. + AddTriangleCW( idxBuffer, startIdx, idx + borderOffset, idx, borderOffset ); + AddTriangleCW( idxBuffer, startIdx, borderOffset, idx, 0 ); +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline Size EllipseWithBorder< VertexType, IndexType, PositionAcc >::GetNumberVerticies () const +{ + return 2 * Parent::GetNumberVerticies(); +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline Size EllipseWithBorder< VertexType, IndexType, PositionAcc >::GetNumberIndicies () const +{ + return Parent::GetNumberIndicies() + GetNumberBorderIndicies(); +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline Size EllipseWithBorder< VertexType, IndexType, PositionAcc >::GetNumberFillIndicies () const +{ + return Parent::GetNumberIndicies(); +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline Size EllipseWithBorder< VertexType, IndexType, PositionAcc >::GetNumberBorderIndicies () const +{ + return 6 * Parent::GetNumberVerticies(); +} + +// ================================ // +// +template< typename VertexType, typename IndexType, typename PositionAcc > +inline ReturnResult EllipseWithBorder< VertexType, IndexType, PositionAcc >::ValidateParams () const +{ + ErrorsCollector collector; + collector.Add( Parent::ValidateParams() ); + + if( Width <= 2 * StrokeThickness ) + collector.Add( "[EllipseWithBorder] Invalid parameter [StrokeThickness=" + Convert::ToString( StrokeThickness ) + "]. Width <= 2 * StrokeThickness" ); + + if( Height <= 2 * StrokeThickness ) + collector.Add( "[EllipseWithBorder] Invalid parameter [StrokeThickness=" + Convert::ToString( StrokeThickness ) + "]. Height <= 2 * StrokeThickness" ); + + return collector; +} + + +} // geom +} // sw + + diff --git a/swGeometrics/GeometricsCore/Processors/Transform/Translate2D.h b/swGeometrics/GeometricsCore/Processors/Transform/Translate2D.h new file mode 100644 index 00000000..a81e8a55 --- /dev/null +++ b/swGeometrics/GeometricsCore/Processors/Transform/Translate2D.h @@ -0,0 +1,96 @@ +#pragma once +/** +@file Translate2D.h +@author nieznanysprawiciel +@copyright File is part of Sleeping Wombat Libraries. +*/ + +#include "swCommonLib/Common/TypesDefinitions.h" +#include "swCommonLib/Common/Converters.h" +#include "swCommonLib/Common/Exceptions/ErrorsCollector.h" + +#include "swGeometrics/GeometricsCore/Types/Traits/ProcessorTraits.h" +#include "swGeometrics/GeometricsCore/Types/Accessors/DefaultAccessors.h" + + +namespace sw { +namespace geom +{ + + +/**@brief Generated planar UV mapping. +@ingroup Coordinates*/ +template< typename VertexType, typename PositionAcc = DefaultPositionAcc< VertexType > > +class Translate2D : public ProcessorTraits< VertexType > +{ +private: +public: + + float TranslateX; + float TranslateY; + +public: + + inline explicit Translate2D (); + inline explicit Translate2D ( float x, float y ); + + inline void GenerateVertex ( VertexType& vertex, Size vertexIdx ); + + + ReturnResult ValidateParams () const; +}; + +//====================================================================================// +// Implementation +//====================================================================================// + + +// ================================ // +// +template< typename VertexType, typename PositionAcc > +inline Translate2D< VertexType, PositionAcc >::Translate2D () + : TranslateX( 0.0f ) + , TranslateY( 0.0f ) +{} + +// ================================ // +// +template< typename VertexType, typename PositionAcc > +inline Translate2D< VertexType, PositionAcc >::Translate2D ( float x, float y ) + : TranslateX( x ) + , TranslateY( y ) +{} + +// ================================ // +// +template< typename VertexType, typename PositionAcc > +inline void Translate2D< VertexType, PositionAcc >::GenerateVertex ( VertexType& vertex, Size ) +{ + auto& vertexPos = PositionAcc::Get( vertex ); + + vertexPos.x += TranslateX; + vertexPos.y += TranslateY; +} + +// ================================ // +// +template< typename VertexType, typename PositionAcc > +inline ReturnResult Translate2D< VertexType, PositionAcc >::ValidateParams () const +{ + ErrorsCollector collector; + + if( !isfinite( TranslateX ) ) + collector.Add( "[Translate2D] Invalid parameter [TranslateX=" + Convert::ToString( TranslateX ) + "]."); + + if( !isfinite( TranslateY ) ) + collector.Add( "[Translate2D] Invalid parameter [TranslateY=" + Convert::ToString( TranslateY ) + "]."); + + return collector; +} + + + + +} // geom +} // sw + diff --git a/swGeometrics/ProjectDir/Visual2015/BasicShapes/BasicShapes.vcxproj b/swGeometrics/ProjectDir/Visual2015/BasicShapes/BasicShapes.vcxproj index 8f066fd4..3bca0eed 100644 --- a/swGeometrics/ProjectDir/Visual2015/BasicShapes/BasicShapes.vcxproj +++ b/swGeometrics/ProjectDir/Visual2015/BasicShapes/BasicShapes.vcxproj @@ -29,6 +29,8 @@ + + @@ -43,6 +45,8 @@ + + diff --git a/swGeometrics/ProjectDir/Visual2015/BasicShapes/BasicShapes.vcxproj.filters b/swGeometrics/ProjectDir/Visual2015/BasicShapes/BasicShapes.vcxproj.filters index 9b8a0c43..ddfeb4fb 100644 --- a/swGeometrics/ProjectDir/Visual2015/BasicShapes/BasicShapes.vcxproj.filters +++ b/swGeometrics/ProjectDir/Visual2015/BasicShapes/BasicShapes.vcxproj.filters @@ -32,6 +32,12 @@ Shapes2D + + Shapes2D + + + Shapes2D + @@ -43,5 +49,11 @@ Shapes2D + + Shapes2D + + + Shapes2D + \ No newline at end of file diff --git a/swGeometrics/ProjectDir/Visual2015/GeometricsCore/GeometricsCore.vcxproj b/swGeometrics/ProjectDir/Visual2015/GeometricsCore/GeometricsCore.vcxproj index 5211493b..097091ba 100644 --- a/swGeometrics/ProjectDir/Visual2015/GeometricsCore/GeometricsCore.vcxproj +++ b/swGeometrics/ProjectDir/Visual2015/GeometricsCore/GeometricsCore.vcxproj @@ -30,6 +30,7 @@ Create Create + diff --git a/swGeometrics/ProjectDir/Visual2015/GeometricsCore/GeometricsCore.vcxproj.filters b/swGeometrics/ProjectDir/Visual2015/GeometricsCore/GeometricsCore.vcxproj.filters index a0ebc8e4..71c45741 100644 --- a/swGeometrics/ProjectDir/Visual2015/GeometricsCore/GeometricsCore.vcxproj.filters +++ b/swGeometrics/ProjectDir/Visual2015/GeometricsCore/GeometricsCore.vcxproj.filters @@ -25,6 +25,9 @@ {fb9386c8-df63-4a64-bce5-fb04924b00a2} + + {e0aa2870-9ed2-4cf6-bcc6-899b942a78d6} + @@ -68,5 +71,8 @@ Geometric\Types\Traits + + Geometric\Processors\Transform + \ No newline at end of file diff --git a/swGeometrics/ProjectDir/Visual2015/Tests/TestBasicShapes/TestBasicShapes.vcxproj b/swGeometrics/ProjectDir/Visual2015/Tests/TestBasicShapes/TestBasicShapes.vcxproj index 59bd1723..5e11ceec 100644 --- a/swGeometrics/ProjectDir/Visual2015/Tests/TestBasicShapes/TestBasicShapes.vcxproj +++ b/swGeometrics/ProjectDir/Visual2015/Tests/TestBasicShapes/TestBasicShapes.vcxproj @@ -28,6 +28,7 @@ + diff --git a/swGeometrics/ProjectDir/Visual2015/Tests/TestGenerationFramework/TestGenerationFramework.vcxproj b/swGeometrics/ProjectDir/Visual2015/Tests/TestGenerationFramework/TestGenerationFramework.vcxproj index 2617e377..4f215d4e 100644 --- a/swGeometrics/ProjectDir/Visual2015/Tests/TestGenerationFramework/TestGenerationFramework.vcxproj +++ b/swGeometrics/ProjectDir/Visual2015/Tests/TestGenerationFramework/TestGenerationFramework.vcxproj @@ -24,6 +24,7 @@ + diff --git a/swGeometrics/Tests/TestBasicShapes/TestEllipse.cpp b/swGeometrics/Tests/TestBasicShapes/TestEllipse.cpp new file mode 100644 index 00000000..37917a8b --- /dev/null +++ b/swGeometrics/Tests/TestBasicShapes/TestEllipse.cpp @@ -0,0 +1,104 @@ +#include "swCommonLib/External/Catch/catch.hpp" + + +#include "swGeometrics/GeometricsCore/Generators/Generator.h" +#include "swGeometrics/GeometricsCore/Types/VertexLayouts/VertexShape2D.h" +#include "swGeometrics/GeometricsCore/Types/IndexTypes.h" + +#include "swGeometrics/BasicShapes/Shapes2D/Ellipse.h" + + +using namespace sw; +using namespace sw::geom; + + +//====================================================================================// +// Helper functions +//====================================================================================// + +// ================================ // +// Defined in TestCircle.cpp +bool IsOnCircle ( const DirectX::XMFLOAT2& vertex, float radius ); + +// ================================ // +// +bool IsEllipse ( const std::vector< VertexShape2D >& verticies, float width, float height ) +{ + bool isCircle = true; + for( auto& vertex : verticies ) + { + auto scaleToCircle = DirectX::XMFLOAT2( 2.0f * vertex.Position.x / width, 2.0f * vertex.Position.y / height ); + if( !IsOnCircle( scaleToCircle, 1.0f ) ) + return false; + } + + return true; +} + + +// ================================ // +// +TEST_CASE( "Geometrics.BasicShapes.Ellipse.EvenTesselation", "[Geometrics][BasicShapes]" ) +{ + Ellipse< VertexShape2D, Index16 > ellipse; + ellipse.Width = 2.5f; + ellipse.Height = 0.5f; + ellipse.Tesselation = 30; + + auto geometry = Generate< IndexedGeometry< VertexShape2D, Index16 > >( ellipse ).Get(); + + CHECK( geometry.Verticies.size() == 30 ); + CHECK( geometry.Indicies.size() == 84 ); + + bool isCircle = IsEllipse( geometry.Verticies, 2.5f, 0.5f ); + CHECK( isCircle == true ); +} + +// ================================ // +// +TEST_CASE( "Geometrics.BasicShapes.Ellipse.OddTesselation", "[Geometrics][BasicShapes]" ) +{ + Ellipse< VertexShape2D, Index16 > ellipse; + ellipse.Width = 1.0f; + ellipse.Height = 4.0f; + ellipse.Tesselation = 31; + + auto geometry = Generate< IndexedGeometry< VertexShape2D, Index16 > >( ellipse ).Get(); + + CHECK( geometry.Verticies.size() == 31 ); + CHECK( geometry.Indicies.size() == 87 ); + + bool isCircle = IsEllipse( geometry.Verticies, 1.0f, 4.0f ); + CHECK( isCircle == true ); +} + +// ================================ // +// Circle should have Tesselation parameter set at least to 3. +TEST_CASE( "Geometrics.BasicShapes.Ellipse.ToLowTesselation", "[Geometrics][BasicShapes]" ) +{ + Ellipse< VertexShape2D, Index16 > ellipse; + ellipse.Width = 2.5f; + ellipse.Height = 0.5f; + ellipse.Tesselation = 0; + + CHECK( Generate< IndexedGeometry< VertexShape2D, Index16 > >( ellipse ).IsValid() == false ); + + ellipse.Tesselation = 1; + CHECK( Generate< IndexedGeometry< VertexShape2D, Index16 > >( ellipse ).IsValid() == false ); + + ellipse.Tesselation = 2; + CHECK( Generate< IndexedGeometry< VertexShape2D, Index16 > >( ellipse ).IsValid() == false ); +} + + +// ================================ // +// Radius should be greater then 0. +TEST_CASE( "Geometrics.BasicShapes.Ellipse.NegativeRadius", "[Geometrics][BasicShapes]" ) +{ + Ellipse< VertexShape2D, Index16 > ellipse; + ellipse.Width = -2.5f; + ellipse.Height = -0.5f; + ellipse.Tesselation = 10; + + CHECK( Generate< IndexedGeometry< VertexShape2D, Index16 > >( ellipse ).IsValid() == false ); +} diff --git a/swGeometrics/Tests/TestGenerationFramework/TestTransforms.cpp b/swGeometrics/Tests/TestGenerationFramework/TestTransforms.cpp new file mode 100644 index 00000000..b83ee0e8 --- /dev/null +++ b/swGeometrics/Tests/TestGenerationFramework/TestTransforms.cpp @@ -0,0 +1,103 @@ +#include "swCommonLib/External/Catch/catch.hpp" + + +#include "swGeometrics/GeometricsCore/Generators/Generator.h" +#include "swGeometrics/GeometricsCore/Types/VertexLayouts/VertexShape2D.h" +#include "swGeometrics/GeometricsCore/Types/IndexTypes.h" + +#include "swGeometrics/GeometricsCore/Processors/Transform/Translate2D.h" + +#include "swGeometrics/BasicShapes/Shapes2D/Rectangle.h" + + +#include + + +using namespace sw; +using namespace sw::geom; + + + +// ================================ // +// +TEST_CASE( "Geometrics.Transforms.Translate2D.TranslateRect", "[Geometrics][Transform]" ) +{ + Rectangle< VertexShape2D, Index16 > rect; + rect.TopLeftX = 30; + rect.TopLeftY = 30; + rect.Height = 20; + rect.Width = 20; + + auto geometry = Generate< IndexedGeometry< VertexShape2D, Index16 > >( rect, Translate2D< VertexShape2D >( 3.5f, 5.3f ) ).Get(); + + // Check vertex buffer. + CHECK( geometry.Verticies.size() == 4 ); + + CHECK( geometry.Verticies[ 0 ].Position.x == 33.5f ); + CHECK( geometry.Verticies[ 0 ].Position.y == 35.3f ); + + CHECK( geometry.Verticies[ 1 ].Position.x == 53.5f ); + CHECK( geometry.Verticies[ 1 ].Position.y == 35.3f ); + + CHECK( geometry.Verticies[ 2 ].Position.x == 53.5f ); + CHECK( geometry.Verticies[ 2 ].Position.y == 15.3f ); + + CHECK( geometry.Verticies[ 3 ].Position.x == 33.5f ); + CHECK( geometry.Verticies[ 3 ].Position.y == 15.3f ); +} + +// ================================ // +// +TEST_CASE( "Geometrics.Transforms.Translate2D.XisInfinity", "[Geometrics][Transform]" ) +{ + Rectangle< VertexShape2D, Index16 > rect; + rect.TopLeftX = 30; + rect.TopLeftY = 30; + rect.Height = 20; + rect.Width = 20; + + auto geometry = Generate< IndexedGeometry< VertexShape2D, Index16 > >( rect, Translate2D< VertexShape2D >( std::numeric_limits< float >::infinity(), 5.3f ) ); + CHECK( geometry.IsValid() == false ); +} + +// ================================ // +// +TEST_CASE( "Geometrics.Transforms.Translate2D.YisInfinity", "[Geometrics][Transform]" ) +{ + Rectangle< VertexShape2D, Index16 > rect; + rect.TopLeftX = 30; + rect.TopLeftY = 30; + rect.Height = 20; + rect.Width = 20; + + auto geometry = Generate< IndexedGeometry< VertexShape2D, Index16 > >( rect, Translate2D< VertexShape2D >( 5.3f, std::numeric_limits< float >::infinity() ) ); + CHECK( geometry.IsValid() == false ); +} + +// ================================ // +// +TEST_CASE( "Geometrics.Transforms.Translate2D.XisNaN", "[Geometrics][Transform]" ) +{ + Rectangle< VertexShape2D, Index16 > rect; + rect.TopLeftX = 30; + rect.TopLeftY = 30; + rect.Height = 20; + rect.Width = 20; + + auto geometry = Generate< IndexedGeometry< VertexShape2D, Index16 > >( rect, Translate2D< VertexShape2D >( std::numeric_limits< float >::quiet_NaN(), 5.3f ) ); + CHECK( geometry.IsValid() == false ); +} + +// ================================ // +// +TEST_CASE( "Geometrics.Transforms.Translate2D.YisNaN", "[Geometrics][Transform]" ) +{ + Rectangle< VertexShape2D, Index16 > rect; + rect.TopLeftX = 30; + rect.TopLeftY = 30; + rect.Height = 20; + rect.Width = 20; + + auto geometry = Generate< IndexedGeometry< VertexShape2D, Index16 > >( rect, Translate2D< VertexShape2D >( 5.3f, std::numeric_limits< float >::quiet_NaN() ) ); + CHECK( geometry.IsValid() == false ); +} \ No newline at end of file diff --git a/swGraphicAPI/DX11API/DX11Resources/DX11Compiler.cpp b/swGraphicAPI/DX11API/DX11Resources/DX11Compiler.cpp index f09359b4..894f0558 100644 --- a/swGraphicAPI/DX11API/DX11Resources/DX11Compiler.cpp +++ b/swGraphicAPI/DX11API/DX11Resources/DX11Compiler.cpp @@ -114,8 +114,10 @@ Nullable< ComPtr< ID3D10Blob > > DX11Compiler::CompileShader ( const std::st ComPtr< ID3D10Blob > errorBlob = nullptr; UINT flags = D3DCOMPILE_ENABLE_STRICTNESS; - if( config.Debug ) - flags |= D3DCOMPILE_DEBUG; + if( config.Debug ) + { + flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; + } std::string shaderModel = config.ShaderModel.ToString(); diff --git a/swGraphicAPI/ResourceManager/AssetCreators/Buffers/BufferCreator.cpp b/swGraphicAPI/ResourceManager/AssetCreators/Buffers/BufferCreator.cpp index feaba9a5..36121549 100644 --- a/swGraphicAPI/ResourceManager/AssetCreators/Buffers/BufferCreator.cpp +++ b/swGraphicAPI/ResourceManager/AssetCreators/Buffers/BufferCreator.cpp @@ -8,8 +8,10 @@ #include "BufferCreator.h" #include "swGraphicAPI/Resources/MeshResources.h" + #include "swCommonLib/Common/Converters.h" #include "swCommonLib/Common/Buffers/BufferTyped.h" +#include "swCommonLib/Common/fmt.h" @@ -136,7 +138,7 @@ Nullable< Buffer* > BufferCreator::CreateConstantsBuffer ( const AssetPath& na Nullable< Buffer* > BufferCreator::CreateConstantsBuffer ( const AssetPath& name, const ConstantBufferInitData& data ) { if( data.ElementSize % 16 != 0 ) - return "[BufferCreator] Invalid Buffer size. Should be multiply of 16."; + return fmt::format( "[BufferCreator] Invalid Buffer size={}. Should be multiply of 16.", data.ElementSize ); return ResourcesFactory::CreateBufferFromMemory( name, data.Data, data.CreateBufferInfo() ); } diff --git a/swLibraries-Versions.xml b/swLibraries-Versions.xml index 10983242..20c228fd 100644 --- a/swLibraries-Versions.xml +++ b/swLibraries-Versions.xml @@ -1,4 +1,39 @@ + + + + Fix BufferRaw - return *this from operator=. + + + + + DX11Compiler doesn't optimize code if debug layer is enabled (easier shaders debugging). + DX11Renderer throw exception on invalid pipeline even in release mode. + Fix SoilTextureLoader compilation in release. Precompiled header problem. + + + + + + Added EllipseGeometry. + New Brushes: AngleGradientBrush, LinearGradientBrush, ImageBrush. + Shader templetes use #UserCode marker to paste Brush or Geometry code written by developer. + Fix RenderingSystem deinitialization order in GUISystem. + RenderingSystem constants and Visual constants are bound to both shaders. + Shader constants availble for developer: _swViewportSize, _swVisualOffset, _swVisualSize. + Shader function swTransformToDirectX avaible for developer. + Width, height and size are properties of Visual. + Fix: initialize Geometry invalidation variables in constructor, what caused non-deterministic problems in release builds. + + + + + Ellipse and EllipseWithBorder generation. + Translate2D operation added. + Compilation fix: Add Reflection dependency to GeometricsCore. + + +