Sfoglia il codice sorgente

Updated scroll area so that scroll bars may have their own style and you can disable or force specific scroll bars

Marko Pintera 12 anni fa
parent
commit
cfc0c9a228

+ 24 - 3
BansheeEngine/Include/BsGUIScrollArea.h

@@ -5,13 +5,29 @@
 
 namespace BansheeEngine
 {
+	enum class ScrollBarType
+	{
+		ShowIfDoesntFit,
+		AlwaysShow,
+		NeverShow
+	};
+
 	class BS_EXPORT GUIScrollArea : public GUIElement
 	{
 	public:
 		static const CM::String& getGUITypeName();
 
-		static GUIScrollArea* create(GUIWidget& parent, const GUIElementStyle* style = nullptr);
-		static GUIScrollArea* create(GUIWidget& parent, const GUIOptions& layoutOptions, const GUIElementStyle* style = nullptr);
+		static GUIScrollArea* create(GUIWidget& parent, ScrollBarType vertBarType, ScrollBarType horzBarType, 
+			const GUIElementStyle* scrollBarStyle = nullptr, const GUIElementStyle* scrollAreaStyle = nullptr);
+
+		static GUIScrollArea* create(GUIWidget& parent, ScrollBarType vertBarType, ScrollBarType horzBarType, 
+			const GUIOptions& layoutOptions, const GUIElementStyle* scrollBarStyle = nullptr, 
+			const GUIElementStyle* scrollAreaStyle = nullptr);
+
+		static GUIScrollArea* create(GUIWidget& parent, const GUIElementStyle* scrollBarStyle = nullptr, const GUIElementStyle* scrollAreaStyle = nullptr);
+
+		static GUIScrollArea* create(GUIWidget& parent, const GUIOptions& layoutOptions, const GUIElementStyle* scrollBarStyle = nullptr, 
+			const GUIElementStyle* scrollAreaStyle = nullptr);
 
 		GUILayout& getLayout() const { return *mContentLayout; }
 
@@ -51,7 +67,12 @@ namespace BansheeEngine
 
 		virtual CM::Vector2I _getOptimalSize() const;
 	private:
-		GUIScrollArea(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions);
+		GUIScrollArea(GUIWidget& parent, ScrollBarType vertBarType, ScrollBarType horzBarType, 
+			const GUIElementStyle* scrollBarStyle, const GUIElementStyle* scrollAreaStyle, const GUILayoutOptions& layoutOptions);
+
+		ScrollBarType mVertBarType;
+		ScrollBarType mHorzBarType;
+		const GUIElementStyle* mScrollBarStyle;
 
 		GUILayout* mContentLayout;
 		GUIScrollBarVert* mVertScroll;

+ 108 - 39
BansheeEngine/Source/BsGUIScrollArea.cpp

@@ -18,9 +18,11 @@ namespace BansheeEngine
 	const UINT32 GUIScrollArea::MinHandleSize = 4;
 	const UINT32 GUIScrollArea::WheelScrollAmount = 50;
 
-	GUIScrollArea::GUIScrollArea(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
-		:GUIElement(parent, style, layoutOptions, false), mVertScroll(nullptr), mHorzScroll(nullptr), mVertOffset(0), mHorzOffset(0),
-		mContentWidth(0), mContentHeight(0), mClippedContentWidth(0), mClippedContentHeight(0)
+	GUIScrollArea::GUIScrollArea(GUIWidget& parent, ScrollBarType vertBarType, ScrollBarType horzBarType, 
+		const GUIElementStyle* scrollBarStyle, const GUIElementStyle* scrollAreaStyle, const GUILayoutOptions& layoutOptions)
+		:GUIElement(parent, scrollAreaStyle, layoutOptions, false), mVertScroll(nullptr), mHorzScroll(nullptr), mVertOffset(0), mHorzOffset(0),
+		mContentWidth(0), mContentHeight(0), mClippedContentWidth(0), mClippedContentHeight(0), mVertBarType(vertBarType), mHorzBarType(horzBarType),
+		mScrollBarStyle(scrollBarStyle)
 	{
 		mContentLayout = &addLayoutYInternal(this);
 	}
@@ -75,9 +77,12 @@ namespace BansheeEngine
 		mClippedContentHeight = height;
 
 		RectI layoutClipRect = clipRect;
+		bool addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentWidth > mWidth) || 
+			mHorzBarType == ScrollBarType::AlwaysShow && mHorzBarType != ScrollBarType::NeverShow;
 
 		bool hasHorzScrollbar = false;
-		if(contentWidth > mWidth)
+		bool hasVertScrollbar = false;
+		if(addHorzScrollbar)
 		{ 
 			// Make room for scrollbar
 			mClippedContentHeight = (UINT32)std::max(0, (INT32)height - (INT32)ScrollBarWidth);
@@ -91,11 +96,15 @@ namespace BansheeEngine
 			contentHeight = mContentLayout->_getActualHeight();
 		}
 
-		if(contentHeight > mClippedContentHeight)
+		bool addVertScrollbar = (mVertBarType == ScrollBarType::ShowIfDoesntFit && contentHeight > mClippedContentHeight) || 
+			mVertBarType == ScrollBarType::AlwaysShow && mVertBarType != ScrollBarType::NeverShow;
+
+		if(addVertScrollbar)
 		{
 			// Make room for scrollbar
 			mClippedContentWidth = (UINT32)std::max(0, (INT32)width - (INT32)ScrollBarWidth);
 			layoutClipRect.width = mClippedContentWidth;
+			hasVertScrollbar = true;
 
 			if(hasHorzScrollbar)
 			{
@@ -113,32 +122,47 @@ namespace BansheeEngine
 			contentWidth = mContentLayout->_getActualWidth();
 			contentHeight = mContentLayout->_getActualHeight();
 
-			if(!hasHorzScrollbar && contentWidth > mClippedContentWidth) // Since width has been reduced, we need to check if we require the horizontal scrollbar
+			if(!hasHorzScrollbar) // Since width has been reduced, we need to check if we require the horizontal scrollbar
 			{
-				// Make room for scrollbar
-				mClippedContentHeight = (UINT32)std::max(0, (INT32)height - (INT32)ScrollBarWidth);
-				layoutClipRect.height = mClippedContentHeight;
-
-				mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y - Math::floorToInt(mVertOffset), 
-					mClippedContentWidth + Math::floorToInt(mHorzOffset), mClippedContentHeight + Math::floorToInt(mVertOffset), 
-					layoutClipRect, widgetDepth, areaDepth);
+				addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentWidth > mClippedContentWidth) && mHorzBarType != ScrollBarType::NeverShow;
+
+				if(addHorzScrollbar)
+				{
+					// Make room for scrollbar
+					mClippedContentHeight = (UINT32)std::max(0, (INT32)height - (INT32)ScrollBarWidth);
+					layoutClipRect.height = mClippedContentHeight;
+
+					mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y - Math::floorToInt(mVertOffset), 
+						mClippedContentWidth + Math::floorToInt(mHorzOffset), mClippedContentHeight + Math::floorToInt(mVertOffset), 
+						layoutClipRect, widgetDepth, areaDepth);
+				}
 			}
 		}
 
 		// Add/remove/update vertical scrollbar as needed
-		if(contentHeight > mClippedContentHeight)
+		if((mVertBarType == ScrollBarType::ShowIfDoesntFit && contentHeight > mClippedContentHeight) || mVertBarType == ScrollBarType::AlwaysShow &&
+			mVertBarType != ScrollBarType::NeverShow)
 		{
 			if(mVertScroll == nullptr)
 			{
-				mVertScroll = GUIScrollBarVert::create(_getParentWidget());
+				if(mScrollBarStyle != nullptr)
+					mVertScroll = GUIScrollBarVert::create(_getParentWidget(), mScrollBarStyle);
+				else
+					mVertScroll = GUIScrollBarVert::create(_getParentWidget());
+
 				mVertScroll->onScrollPositionChanged.connect(boost::bind(&GUIScrollArea::vertScrollUpdate, this, _1));
 				mVertScroll->_setAcceptsKeyboardFocus(false);
 			}
 
-			Vector2I offset(x + mClippedContentWidth, y);
+			INT32 scrollBarOffset = (UINT32)std::max(0, (INT32)width - (INT32)ScrollBarWidth);
+			UINT32 scrollBarHeight = height;
+			if(hasHorzScrollbar)
+				scrollBarHeight = (UINT32)std::max(0, (INT32)scrollBarHeight - (INT32)ScrollBarWidth);
+
+			Vector2I offset(x + scrollBarOffset, y);
 			mVertScroll->_setOffset(offset);
 			mVertScroll->_setWidth(ScrollBarWidth);
-			mVertScroll->_setHeight(mClippedContentHeight);
+			mVertScroll->_setHeight(scrollBarHeight);
 			mVertScroll->_setAreaDepth(areaDepth);
 			mVertScroll->_setWidgetDepth(widgetDepth);
 
@@ -147,15 +171,18 @@ namespace BansheeEngine
 			mVertScroll->_setClipRect(elemClipRect);
 
 			// This element is not a child of any layout so we treat it as a root element
-			RectI scrollBarLayoutClipRect(clipRect.x + mClippedContentWidth, clipRect.y, clippedScrollbarWidth, clipRect.height);
-			mVertScroll->_updateLayout(offset.x, offset.y, ScrollBarWidth, mClippedContentHeight, scrollBarLayoutClipRect, widgetDepth, areaDepth);
+			RectI scrollBarLayoutClipRect(clipRect.x + scrollBarOffset, clipRect.y, clippedScrollbarWidth, clipRect.height);
+			mVertScroll->_updateLayout(offset.x, offset.y, ScrollBarWidth, scrollBarHeight, scrollBarLayoutClipRect, widgetDepth, areaDepth);
 
 			// Set new handle size and update position to match the new size
-			UINT32 newHandleSize = (UINT32)Math::floorToInt(mVertScroll->getMaxHandleSize() * (mClippedContentHeight / (float)contentHeight));
+			UINT32 newHandleSize = (UINT32)Math::floorToInt(mVertScroll->getMaxHandleSize() * (scrollBarHeight / (float)contentHeight));
 			newHandleSize = std::max(newHandleSize, MinHandleSize);
 
-			UINT32 scrollableHeight = (UINT32)std::max(0, INT32(contentHeight) - INT32(mClippedContentHeight));
-			float newScrollPct = mVertOffset / scrollableHeight;
+			UINT32 scrollableHeight = (UINT32)std::max(0, INT32(contentHeight) - INT32(scrollBarHeight));
+			float newScrollPct = 0.0f;
+
+			if(scrollableHeight > 0)
+				newScrollPct = mVertOffset / scrollableHeight;
 
 			mVertScroll->setHandleSize(newHandleSize);
 			mVertScroll->setScrollPos(newScrollPct);
@@ -172,18 +199,28 @@ namespace BansheeEngine
 		}
 
 		// Add/remove/update horizontal scrollbar as needed
-		if(contentWidth > mClippedContentWidth)
+		if((mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentWidth > mClippedContentWidth) || mHorzBarType == ScrollBarType::AlwaysShow &&
+			mHorzBarType != ScrollBarType::NeverShow)
 		{ 
 			if(mHorzScroll == nullptr)
 			{
-				mHorzScroll = GUIScrollBarHorz::create(_getParentWidget());
+				if(mScrollBarStyle != nullptr)
+					mHorzScroll = GUIScrollBarHorz::create(_getParentWidget(), mScrollBarStyle);
+				else
+					mHorzScroll = GUIScrollBarHorz::create(_getParentWidget());
+
 				mHorzScroll->onScrollPositionChanged.connect(boost::bind(&GUIScrollArea::horzScrollUpdate, this, _1));
 				mHorzScroll->_setAcceptsKeyboardFocus(false);
 			}
 
-			Vector2I offset(x, y + mClippedContentHeight);
+			INT32 scrollBarOffset = (UINT32)std::max(0, (INT32)height - (INT32)ScrollBarWidth);
+			UINT32 scrollBarWidth = width;
+			if(hasVertScrollbar)
+				scrollBarWidth = (UINT32)std::max(0, (INT32)scrollBarWidth - (INT32)ScrollBarWidth);
+
+			Vector2I offset(x, y + scrollBarOffset);
 			mHorzScroll->_setOffset(offset);
-			mHorzScroll->_setWidth(mClippedContentWidth);
+			mHorzScroll->_setWidth(scrollBarWidth);
 			mHorzScroll->_setHeight(ScrollBarWidth);
 			mHorzScroll->_setAreaDepth(areaDepth);
 			mHorzScroll->_setWidgetDepth(widgetDepth);
@@ -193,15 +230,18 @@ namespace BansheeEngine
 			mHorzScroll->_setClipRect(elemClipRect);
 
 			// This element is not a child of any layout so we treat it as a root element
-			RectI scrollBarLayoutClipRect(clipRect.x, clipRect.y + mClippedContentHeight, clipRect.width, clippedScrollbarHeight);
-			mHorzScroll->_updateLayout(offset.x, offset.y, mClippedContentWidth, ScrollBarWidth, scrollBarLayoutClipRect, widgetDepth, areaDepth);
+			RectI scrollBarLayoutClipRect(clipRect.x, clipRect.y + scrollBarOffset, clipRect.width, clippedScrollbarHeight);
+			mHorzScroll->_updateLayout(offset.x, offset.y, scrollBarWidth, ScrollBarWidth, scrollBarLayoutClipRect, widgetDepth, areaDepth);
 
 			// Set new handle size and update position to match the new size
-			UINT32 newHandleSize = (UINT32)Math::floorToInt(mHorzScroll->getMaxHandleSize() * (mClippedContentWidth / (float)contentWidth));
+			UINT32 newHandleSize = (UINT32)Math::floorToInt(mHorzScroll->getMaxHandleSize() * (scrollBarWidth / (float)contentWidth));
 			newHandleSize = std::max(newHandleSize, MinHandleSize);
 
-			UINT32 scrollableWidth = (UINT32)std::max(0, INT32(contentWidth) - INT32(mClippedContentWidth));
-			float newScrollPct = mHorzOffset / scrollableWidth;
+			UINT32 scrollableWidth = (UINT32)std::max(0, INT32(contentWidth) - INT32(scrollBarWidth));
+			float newScrollPct = 0.0f;
+			
+			if(scrollableWidth > 0)
+				newScrollPct = mHorzOffset / scrollableWidth;
 
 			mHorzScroll->setHandleSize(newHandleSize);
 			mHorzScroll->setScrollPos(newScrollPct);
@@ -268,26 +308,55 @@ namespace BansheeEngine
 			mHorzScroll->_changeParentWidget(widget);
 	}
 
-	GUIScrollArea* GUIScrollArea::create(GUIWidget& parent, const GUIElementStyle* style)
+	GUIScrollArea* GUIScrollArea::create(GUIWidget& parent, ScrollBarType vertBarType, ScrollBarType horzBarType, 
+		const GUIElementStyle* scrollBarStyle, const GUIElementStyle* scrollAreaStyle)
+	{
+		if(scrollAreaStyle == nullptr)
+		{
+			const GUISkin& skin = parent.getSkin();
+			scrollAreaStyle = skin.getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIScrollArea, PoolAlloc>()) GUIScrollArea(parent, vertBarType, horzBarType, scrollBarStyle, 
+			scrollAreaStyle, GUILayoutOptions::create(scrollAreaStyle));
+	}
+
+	GUIScrollArea* GUIScrollArea::create(GUIWidget& parent, const GUIOptions& layoutOptions, const GUIElementStyle* scrollBarStyle, 
+		const GUIElementStyle* scrollAreaStyle)
+	{
+		if(scrollAreaStyle == nullptr)
+		{
+			const GUISkin& skin = parent.getSkin();
+			scrollAreaStyle = skin.getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIScrollArea, PoolAlloc>()) GUIScrollArea(parent, ScrollBarType::ShowIfDoesntFit, 
+			ScrollBarType::ShowIfDoesntFit, scrollBarStyle, scrollAreaStyle, GUILayoutOptions::create(layoutOptions, scrollAreaStyle));
+	}
+
+	GUIScrollArea* GUIScrollArea::create(GUIWidget& parent, const GUIElementStyle* scrollBarStyle, const GUIElementStyle* scrollAreaStyle)
 	{
-		if(style == nullptr)
+		if(scrollAreaStyle == nullptr)
 		{
 			const GUISkin& skin = parent.getSkin();
-			style = skin.getStyle(getGUITypeName());
+			scrollAreaStyle = skin.getStyle(getGUITypeName());
 		}
 
-		return new (cm_alloc<GUIScrollArea, PoolAlloc>()) GUIScrollArea(parent, style, GUILayoutOptions::create(style));
+		return new (cm_alloc<GUIScrollArea, PoolAlloc>()) GUIScrollArea(parent, ScrollBarType::ShowIfDoesntFit, ScrollBarType::ShowIfDoesntFit, scrollBarStyle, 
+			scrollAreaStyle, GUILayoutOptions::create(scrollAreaStyle));
 	}
 
-	GUIScrollArea* GUIScrollArea::create(GUIWidget& parent, const GUIOptions& layoutOptions, const GUIElementStyle* style)
+	GUIScrollArea* GUIScrollArea::create(GUIWidget& parent, ScrollBarType vertBarType, 
+		ScrollBarType horzBarType, const GUIOptions& layoutOptions, const GUIElementStyle* scrollBarStyle, 
+		const GUIElementStyle* scrollAreaStyle)
 	{
-		if(style == nullptr)
+		if(scrollAreaStyle == nullptr)
 		{
 			const GUISkin& skin = parent.getSkin();
-			style = skin.getStyle(getGUITypeName());
+			scrollAreaStyle = skin.getStyle(getGUITypeName());
 		}
 
-		return new (cm_alloc<GUIScrollArea, PoolAlloc>()) GUIScrollArea(parent, style, GUILayoutOptions::create(layoutOptions, style));
+		return new (cm_alloc<GUIScrollArea, PoolAlloc>()) GUIScrollArea(parent, vertBarType, horzBarType, scrollBarStyle, scrollAreaStyle, GUILayoutOptions::create(layoutOptions, scrollAreaStyle));
 	}
 
 	const String& GUIScrollArea::getGUITypeName()

+ 16 - 72
CSharpWrap.txt

@@ -10,10 +10,6 @@ Resources:
   - DepthStencil/Blend/Rasterizer/Sampler state
 
 Core objects:
- - RenderTarget
-  - RenderWindow
-  - RenderTexture
-  - MultiRenderTexture
  - SceneObject
  - Component
   - plus specific components Camera, Renderable, maybe others
@@ -37,73 +33,25 @@ Systems:
 
  -----------------
 
-For EditorWindow, add a new class in BansheeEditor, which pretty much does the job of  EditorWidget::open
- - Except it creates an empty widget. (It will also create a window, but in C++ code)
- - All the window docking/undocking moving/resizing is done in C++
- - EditorWindow only has a reference to EditorWidget
-
- -----------------
-
  Implementation steps:
- - Get EditorApplication finished and make the main window open from C#
- - Add support for Resources
-   - Importer - Likely invisible for outside world
-   - Resources.Save/Load - Will likely need some kind of an AssetManager for all imported assets
-   - Texture, Mesh, Font, Shader, Material
-     - Before this I will also probably require all the basic classes like Vector3, etc.
- - Emulate current CamelotClient tests in C#
-
- -----------------
-
- But which ones will I need initially?
-  - [EditorApplication] - Entry point. Creates a MainEditorWindow
-  - [EditorWindow] (Scene, Project, Hierarchy, etc.)
-   - show()/hide()
-  - [MainEditorWindow]
-   - Slight variation of EditorWindow as there can be only one of them
-   - Contains [TitleBar], [DockManager]
-  - When adding GUI elements I need to make it easy to add game GUI elements,
-    but also make a distinction and make it possible to add editor GUI elements.
-	- Each EditorWindow contains a [GUIWidget] (created by default)
-	  - This GUIWIdget is created specially with EditorWindow as its target
-	- GUIWidget is also a Component which can be used for rendering to Game view
-	  - All game GUIWidgets are created with Game render target as their target
-  - [GameObject], [Component]
-    - Need something to add GUIWidget to
-  - I need to have [Application] running within EditorApplication
-    - So when I remove EditorApplication everything runs as normal
-	- How to make the distinction?
-	  - Application needs to render to RenderTarget when in editor, and have its own window when standalone
-	   - When in Editor, EditorApplication will call application and tell it to create a render target
-	   - When published I will have a Game class, which will also call Application and run it in a window
-	  - Certain components should only exists in editor (Like Scene camera, gizmos and etc.)
-	   - Add a flag to GameObjects like in Unity, that can hide the object in Hierarchy, or make it not save
-	   - Editor objects would be hidden and would not save with the level, which would make publishing work
-  - GUIWidget
-    - [GUILayoutX], [GUILayoutY], [GUIArea], [GUISpace], [GUIFlexibleSpace]
-	- [GUIElement]
-	  - [GUILabel], [GUIButton], etc.
-	- TODO: GUISkin? - Will I need to create interface for textures and resource loading/importing as well? Probably
-  
-  ----------------
-
-Eventually make all math classes templates that work on both doubles and floats. (Very low priority)
+  - Finish up minor scroll area issues
+  - Implement flexible TreeView GUI component
+  - Finish up Window Docking
+  - EditorApplication
+   - a way to return currently open project
+  - Rethink how Resource .metas are handled
+  - Implement Resource window
+    - C# Importer (Internal class)
+     - Imports resources and stores it within Library of the current Project folder
+    - C# Resources, Save, Create
+    - (Drag and drop import)
+    - (File edit tracking)
 
 ----------------------------
 
-Implement:
-ScrollArea will likely need:
- C++/C#: always/never show horz/vert scroll bar
- C++/C#: optional styles for scroll bars
- C++/C#: scrollTo(pct)
-
- Are GUI element instances kept anywhere? After GUI.Add* is called I think they're lost and destructed?
- I should create a handle in C++ code and only release it once Destroy is called?
-   - Creating a child hierarchy of GUIElements (where each GUIElement holds references to all its children) can work
-    - Destroy() is then called recursively from parent element
-    - Each element will then also have "GetNumChildren", and "GetChild" methods
-    - Also consider adding GUIElement.Move(GUILayout), GUIElement.Move(GUILayout, int position),
-      GUIElement.Move(int offset)
+ScrollBar update:
+  Ensure that scroll bar type is actually used somewhere in GUIScrollBar.cpp
+  Test it properly
 
  - GUISkin
    - List of properties with all common styles, like .button, .label
@@ -120,11 +68,7 @@ When loading resources I need to be able to load both project resources and engi
 
  BsApplication::getPrimaryViewport is not implemented
 
-----------------------------
-
-  I want my .exe to be native. Internally it will call MBansheeEngine and MBansheeEditor.
-
-This will allow me to debug and start C++ as usual.
+ Ensure I can easily ensure that engine and run separate from editor for when game publishing will be implemented.
 
  -----------------
 

+ 13 - 0
MBansheeEngine/GUIElement.cs

@@ -17,6 +17,19 @@ namespace BansheeEngine
                 parent.children.Add(this);
         }
 
+        public int GetNumChildren()
+        {
+            return children.Count;
+        }
+
+        public GUIElement GetChild(int index)
+        {
+            if (index < 0 || index >= children.Count)
+                return null;
+
+            return children[index];
+        }
+
         public void Destroy()
         {
             for (int i = 0; i < children.Count; i++)

+ 22 - 2
MBansheeEngine/GUILayout.cs

@@ -104,14 +104,34 @@ namespace BansheeEngine
             return new GUITextBox(this, false, null, options);
         }
 
+        public GUIScrollArea AddScrollArea(ScrollBarType vertBarType, ScrollBarType horzBarType, GUIElementStyle style, params GUIOption[] options)
+        {
+            return new GUIScrollArea(this, vertBarType, horzBarType, null, style, options);
+        }
+
+        public GUIScrollArea AddScrollArea(ScrollBarType vertBarType, ScrollBarType horzBarType, params GUIOption[] options)
+        {
+            return new GUIScrollArea(this, vertBarType, horzBarType, null, null, options);
+        }
+
         public GUIScrollArea AddScrollArea(GUIElementStyle style, params GUIOption[] options)
         {
-            return new GUIScrollArea(this, style, options);
+            return new GUIScrollArea(this, ScrollBarType.ShowIfDoesntFit, ScrollBarType.ShowIfDoesntFit, null, style, options);
         }
 
         public GUIScrollArea AddScrollArea(params GUIOption[] options)
         {
-            return new GUIScrollArea(this, null, options);
+            return new GUIScrollArea(this, ScrollBarType.ShowIfDoesntFit, ScrollBarType.ShowIfDoesntFit, null, null, options);
+        }
+
+        public GUIScrollArea AddScrollArea(ScrollBarType vertBarType, ScrollBarType horzBarType, GUIElementStyle scrollBarStyle, GUIElementStyle scrollAreaStyle, params GUIOption[] options)
+        {
+            return new GUIScrollArea(this, vertBarType, horzBarType, scrollBarStyle, scrollAreaStyle, options);
+        }
+
+        public GUIScrollArea AddScrollArea(GUIElementStyle scrollBarStyle, GUIElementStyle scrollAreaStyle, params GUIOption[] options)
+        {
+            return new GUIScrollArea(this, ScrollBarType.ShowIfDoesntFit, ScrollBarType.ShowIfDoesntFit, scrollBarStyle, scrollAreaStyle, options);
         }
 
         public GUIListBox AddListBox(LocString[] elements, GUIElementStyle style, params GUIOption[] options)

+ 12 - 3
MBansheeEngine/GUIScrollArea.cs

@@ -2,6 +2,13 @@
 
 namespace BansheeEngine
 {
+    public enum ScrollBarType
+	{
+		ShowIfDoesntFit,
+		AlwaysShow,
+		NeverShow
+	};
+
     public sealed class GUIScrollArea : GUIElement
     {
         private GUILayout _mainLayout;
@@ -11,14 +18,16 @@ namespace BansheeEngine
             get { return _mainLayout; }
         }
 
-        internal GUIScrollArea(GUILayout parentLayout, GUIElementStyle style, params GUIOption[] options)
+        internal GUIScrollArea(GUILayout parentLayout, ScrollBarType vertBarType, ScrollBarType horzBarType, 
+            GUIElementStyle scrollBarStyle, GUIElementStyle scrollAreaStyle, params GUIOption[] options)
             :base(parentLayout)
         {
-            Internal_CreateInstance(this, parentLayout, style, options);
+            Internal_CreateInstance(this, parentLayout, vertBarType, horzBarType, scrollBarStyle, scrollAreaStyle, options);
             _mainLayout = new GUILayoutY(this);
         }
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(GUIScrollArea instance, GUILayout parentLayout, GUIElementStyle style, params GUIOption[] options);
+        private static extern void Internal_CreateInstance(GUIScrollArea instance, GUILayout parentLayout, ScrollBarType vertBarType, ScrollBarType horzBarType,
+            GUIElementStyle scrollBarStyle, GUIElementStyle scrollAreaStyle, params GUIOption[] options);
     }
 }

+ 4 - 2
SBansheeEngine/Include/BsScriptGUIScrollArea.h

@@ -2,6 +2,7 @@
 
 #include "BsScriptEnginePrerequisites.h"
 #include "BsScriptObject.h"
+#include "BsGUIScrollArea.h"
 
 namespace BansheeEngine
 {
@@ -15,7 +16,8 @@ namespace BansheeEngine
 
 		GUIWidget& getParentWidget() const;
 	private:
-		static void internal_createInstance(MonoObject* instance, MonoObject* parentLayout, MonoObject* style, MonoArray* guiOptions);
+		static void internal_createInstance(MonoObject* instance, MonoObject* parentLayout, ScrollBarType vertBarType, ScrollBarType horzBarType, 
+			MonoObject* scrollBarStyle, MonoObject* scrollAreaStyle, MonoArray* guiOptions);
 		static void internal_destroyInstance(ScriptGUIScrollArea* nativeInstance);
 
 		static void internal_destroy(ScriptGUIScrollArea* nativeInstance);
@@ -24,7 +26,7 @@ namespace BansheeEngine
 
 		static void initRuntimeData();
 
-		ScriptGUIScrollArea(GUIScrollArea* button, GUIWidget& parentWidget);
+		ScriptGUIScrollArea(GUIScrollArea* scrollArea, GUIWidget& parentWidget);
 
 		GUIScrollArea* mScrollArea;
 		GUIWidget& mParentWidget;

+ 11 - 5
SBansheeEngine/Source/BsScriptGUIScrollArea.cpp

@@ -47,7 +47,8 @@ namespace BansheeEngine
 		return mParentWidget;
 	}
 
-	void ScriptGUIScrollArea::internal_createInstance(MonoObject* instance, MonoObject* parentLayout, MonoObject* style, MonoArray* guiOptions)
+	void ScriptGUIScrollArea::internal_createInstance(MonoObject* instance, MonoObject* parentLayout, ScrollBarType vertBarType, ScrollBarType horzBarType, 
+		MonoObject* scrollBarStyle, MonoObject* scrollAreaStyle, MonoArray* guiOptions)
 	{
 		ScriptGUILayout* scriptLayout = ScriptGUILayout::toNative(parentLayout);
 		GUIOptions options;
@@ -56,12 +57,17 @@ namespace BansheeEngine
 		for(UINT32 i = 0; i < arrayLen; i++)
 			options.addOption(mono_array_get(guiOptions, GUIOption, i));
 
-		GUIElementStyle* elemStyle = nullptr;
+		GUIElementStyle* scrollAreaNativeStyle = nullptr;
 
-		if(style != nullptr)
-			elemStyle = ScriptGUIElementStyle::toNative(style)->getInternalValue();
+		if(scrollAreaStyle != nullptr)
+			scrollAreaNativeStyle = ScriptGUIElementStyle::toNative(scrollAreaStyle)->getInternalValue();
 
-		GUIScrollArea* guiScrollArea = GUIScrollArea::create(scriptLayout->getParentWidget(), options, elemStyle);
+		GUIElementStyle* scrollBarNativeStyle = nullptr;
+
+		if(scrollBarNativeStyle != nullptr)
+			scrollBarNativeStyle = ScriptGUIElementStyle::toNative(scrollBarStyle)->getInternalValue();
+
+		GUIScrollArea* guiScrollArea = GUIScrollArea::create(scriptLayout->getParentWidget(), vertBarType, horzBarType, options, scrollBarNativeStyle, scrollAreaNativeStyle);
 		GUILayout* nativeLayout = scriptLayout->getInternalValue();
 		nativeLayout->addElement(guiScrollArea);
 

+ 2 - 1
TODO.txt

@@ -143,4 +143,5 @@ Optional:
  - Vertex buffer start offset is not supported when calling Draw methods
  - When rendering Scale9Grid GUI elements the stretched center will cause linear interpolation to kick in and blend the edges with the border parts of the texture.
   - I should use point filtering for scale9grid, but that doesn't work in general case for stretched textures as they would look bad
- - Win32DropTarget: I need to be able to set drop DROPEFFECT when various IDropTarget methods are called. Otherwise the drag cursor always remains the same, whether the drag will be accepted or not. 
+ - Win32DropTarget: I need to be able to set drop DROPEFFECT when various IDropTarget methods are called. Otherwise the drag cursor always remains the same, whether the drag will be accepted or not. 
+ - Eventually make all math classes templates that work on both doubles and floats. (Very low priority)