From 758572934f6a08d3064adb7580d18a141272db4f Mon Sep 17 00:00:00 2001 From: Ronen Date: Wed, 28 Dec 2016 00:37:42 +0200 Subject: [PATCH] made all entities support OutlineColor by default --- .../GeonBit.UI/Entities/ColoredRectangle.cs | 10 -- GeonBit.UI/GeonBit.UI/Entities/Dropdown.cs | 39 +++-- GeonBit.UI/GeonBit.UI/Entities/Entity.cs | 163 +++++++++++++----- GeonBit.UI/GeonBit.UI/Entities/Paragraph.cs | 13 +- GeonBit.UI/GeonBit.UI/Entities/RootPanel.cs | 34 ++++ GeonBit.UI/GeonBitUI_Examples.cs | 8 +- 6 files changed, 197 insertions(+), 70 deletions(-) diff --git a/GeonBit.UI/GeonBit.UI/Entities/ColoredRectangle.cs b/GeonBit.UI/GeonBit.UI/Entities/ColoredRectangle.cs index d03d81d..085728f 100644 --- a/GeonBit.UI/GeonBit.UI/Entities/ColoredRectangle.cs +++ b/GeonBit.UI/GeonBit.UI/Entities/ColoredRectangle.cs @@ -96,13 +96,9 @@ override protected void DrawEntity(SpriteBatch spriteBatch) // get outline width int outlineWidth = OutlineWidth; - // mark if we rendered outline or not - bool renderedOutline = false; - // draw outline if (outlineWidth > 0) { - renderedOutline = true; Rectangle outlineDest = _destRect; outlineDest.X -= outlineWidth; outlineDest.Y -= outlineWidth; @@ -114,12 +110,6 @@ override protected void DrawEntity(SpriteBatch spriteBatch) // get fill color Color fill = FillColor; - // sanity check - can't have transperancy with border - if (fill.A < 255 && renderedOutline) - { - throw new System.Exception("Can't draw colored rectangle with transperancy and borders!"); - } - // draw the rectangle spriteBatch.Draw(Resources.WhiteTexture, _destRect, fill); diff --git a/GeonBit.UI/GeonBit.UI/Entities/Dropdown.cs b/GeonBit.UI/GeonBit.UI/Entities/Dropdown.cs index 9a0be4e..c1c6d3f 100644 --- a/GeonBit.UI/GeonBit.UI/Entities/Dropdown.cs +++ b/GeonBit.UI/GeonBit.UI/Entities/Dropdown.cs @@ -34,14 +34,17 @@ public class DropDown : SelectList /// Default styling for the dropdown currently-selected label. Note: loaded from UI theme xml file. public static StyleSheet DefaultSelectedParagraphStyle = new StyleSheet(); - // internal panel and paragraph to show selected value + // internal panel and paragraph to show selected value. Panel _selectedTextPanel; Paragraph _selectedTextParagraph; - // the height, in pixels, of the panel to show currently selected value + // the height, in pixels, of the panel to show currently selected value. static int SelectedPanelHeight = 67; - // is the list part currently visible? + // set temporarily to true while we render dropdown outlines. + private bool _isOutlinePass = false; + + // is the list part currently visible or not. bool _isListVisible = false; /// @@ -143,6 +146,17 @@ protected override void OnResize(bool recalcDestRect = true) } } + /// + /// Draw entity outline. Override in dropdown to indicate when we are in outline rendering pass. + /// + /// Sprite batch to draw on. + override protected void DrawEntityOutline(SpriteBatch spriteBatch) + { + _isOutlinePass = true; + base.DrawEntityOutline(spriteBatch); + _isOutlinePass = false; + } + /// /// Draw the entity. /// @@ -152,14 +166,17 @@ override protected void DrawEntity(SpriteBatch spriteBatch) // draw the list only when visible if (_isListVisible) { - // first move the dest rect down below the selected item text - int extraY = (int)(_selectedTextPanel.Size.Y * UserInterface.SCALE); - _destRect.Y += extraY; - _destRectInternal.Y += extraY; - - // also remove the selected part height from the total height, so the element size.y will be absolute - _destRect.Height -= extraY; - _destRectInternal.Height -= extraY; + if (!_isOutlinePass) + { + // first move the dest rect down below the selected item text + int extraY = (int)(_selectedTextPanel.Size.Y * UserInterface.SCALE); + _destRect.Y += extraY; + _destRectInternal.Y += extraY; + + // also remove the selected part height from the total height, so the element size.y will be absolute + _destRect.Height -= extraY; + _destRectInternal.Height -= extraY; + } // now draw the list part base.DrawEntity(spriteBatch); diff --git a/GeonBit.UI/GeonBit.UI/Entities/Entity.cs b/GeonBit.UI/GeonBit.UI/Entities/Entity.cs index 15334a9..97f2d9a 100644 --- a/GeonBit.UI/GeonBit.UI/Entities/Entity.cs +++ b/GeonBit.UI/GeonBit.UI/Entities/Entity.cs @@ -218,6 +218,9 @@ public class Entity /// If true, this entity and its children will not respond to events (but will be drawn normally, unlike when disabled). public bool Locked = false; + /// Is this entity currently disabled? + private bool _isCurrentlyDisabled = false; + /// Current entity state. protected EntityState _entityState = EntityState.Default; @@ -675,7 +678,7 @@ protected List GetSortedChildren() /// Draw this entity and its children. /// /// SpriteBatch to use for drawing. - public void Draw(SpriteBatch spriteBatch) + virtual public void Draw(SpriteBatch spriteBatch) { // if not visible skip if (!Visible) @@ -683,6 +686,9 @@ public void Draw(SpriteBatch spriteBatch) return; } + // update if disabled + _isCurrentlyDisabled = IsDisabled(); + // draw background if (Background != null) { @@ -699,50 +705,14 @@ public void Draw(SpriteBatch spriteBatch) _destRect = CalcDestRect(); _destRectInternal = CalcInternalRect(); - // if there's a shadow - if (ShadowColor.A > 0 && ShadowScale > 0f) - { - // update position to draw shadow - _destRect.X += (int)ShadowOffset.X; - _destRect.Y += (int)ShadowOffset.Y; - - // store previous state and colors - Color oldFill = FillColor; - Color oldOutline = OutlineColor; - float oldScale = Scale; - int oldOutlineWidth = OutlineWidth; - EntityState oldState = _entityState; - - // set default colors and state for shadow pass - FillColor = ShadowColor; - OutlineColor = Color.Transparent; - OutlineWidth = 0; - Scale = ShadowScale; - _entityState = EntityState.Default; - - // if disabled, turn color into greyscale - if (IsDisabled()) - { - FillColor = new Color(Color.White * (((FillColor.R + FillColor.G + FillColor.B) / 3f) / 255f), FillColor.A); - } + // draw shadow + DrawEntityShadow(spriteBatch); - // draw with shadow effect - DrawUtils.StartDrawSilhouette(spriteBatch); - DrawEntity(spriteBatch); - DrawUtils.EndDraw(spriteBatch); - - // return position and colors back to what they were - _destRect.X -= (int)ShadowOffset.X; - _destRect.Y -= (int)ShadowOffset.Y; - FillColor = oldFill; - Scale = oldScale; - OutlineColor = oldOutline; - OutlineWidth = oldOutlineWidth; - _entityState = oldState; - } + // draw entity outline + DrawEntityOutline(spriteBatch); // draw the entity itself - DrawUtils.StartDraw(spriteBatch, IsDisabled()); + DrawUtils.StartDraw(spriteBatch, _isCurrentlyDisabled); DrawEntity(spriteBatch); DrawUtils.EndDraw(spriteBatch); @@ -759,6 +729,109 @@ public void Draw(SpriteBatch spriteBatch) OnAfterDraw(spriteBatch); } + /// + /// Draw entity shadow (if defined shadow). + /// + /// Sprite batch to draw on. + virtual protected void DrawEntityShadow(SpriteBatch spriteBatch) + { + // get current shadow color and if transparent skip + Color shadowColor = ShadowColor; + if (shadowColor.A == 0) { return; } + + // get shadow scale + float shadowScale = ShadowScale; + + // update position to draw shadow + _destRect.X += (int)ShadowOffset.X; + _destRect.Y += (int)ShadowOffset.Y; + + // store previous state and colors + Color oldFill = FillColor; + Color oldOutline = OutlineColor; + float oldScale = Scale; + int oldOutlineWidth = OutlineWidth; + EntityState oldState = _entityState; + + // set default colors and state for shadow pass + FillColor = shadowColor; + OutlineColor = Color.Transparent; + OutlineWidth = 0; + Scale = shadowScale; + _entityState = EntityState.Default; + + // if disabled, turn color into greyscale + if (_isCurrentlyDisabled) + { + FillColor = new Color(Color.White * (((shadowColor.R + shadowColor.G + shadowColor.B) / 3f) / 255f), shadowColor.A); + } + + // draw with shadow effect + DrawUtils.StartDrawSilhouette(spriteBatch); + DrawEntity(spriteBatch); + DrawUtils.EndDraw(spriteBatch); + + // return position and colors back to what they were + _destRect.X -= (int)ShadowOffset.X; + _destRect.Y -= (int)ShadowOffset.Y; + FillColor = oldFill; + Scale = oldScale; + OutlineColor = oldOutline; + OutlineWidth = oldOutlineWidth; + _entityState = oldState; + } + + /// + /// Draw entity outline. + /// + /// Sprite batch to draw on. + virtual protected void DrawEntityOutline(SpriteBatch spriteBatch) + { + // get outline width and if 0 return + int outlineWidth = OutlineWidth; + if (OutlineWidth == 0) { return; } + + // get outline color + Color outlineColor = OutlineColor; + + // if disabled, turn outline to grey + if (_isCurrentlyDisabled) + { + outlineColor = new Color(Color.White * (((outlineColor.R + outlineColor.G + outlineColor.B) / 3f) / 255f), outlineColor.A); + } + + // store previous fill color + Color oldFill = FillColor; + + // store original destination rect + Rectangle originalDest = _destRect; + Rectangle originalIntDest = _destRectInternal; + + // store entity previous state + EntityState oldState = _entityState; + + // set fill color + SetStyleProperty("FillColor", new StyleProperty(outlineColor), oldState); + + // draw the entity outline + DrawUtils.StartDrawSilhouette(spriteBatch); + _destRect.Location = originalDest.Location + new Point(-outlineWidth, 0); + DrawEntity(spriteBatch); + _destRect.Location = originalDest.Location + new Point(0, -outlineWidth); + DrawEntity(spriteBatch); + _destRect.Location = originalDest.Location + new Point(outlineWidth, 0); + DrawEntity(spriteBatch); + _destRect.Location = originalDest.Location + new Point(0, outlineWidth); + DrawEntity(spriteBatch); + DrawUtils.EndDraw(spriteBatch); + + // turn back to previous fill color + SetStyleProperty("FillColor", new StyleProperty(oldFill), oldState); + + // return to the original destination rect + _destRect = originalDest; + _destRectInternal = originalIntDest; + } /// /// The internal function to draw the entity itself. @@ -1282,11 +1355,15 @@ virtual public void Update(InputHelper input, ref Entity targetEntity, ref Entit _entityState = _parent._entityState; _isMouseOver = _parent._isMouseOver; IsFocused = _parent.IsFocused; + _isCurrentlyDisabled = _parent._isCurrentlyDisabled; return; } + // get if disabled + _isCurrentlyDisabled = IsDisabled(); + // if disabled , invisible, or locked - skip - if (IsDisabled() || IsLocked() || !IsVisible()) + if (_isCurrentlyDisabled || IsLocked() || !IsVisible()) { // if this very entity is locked (eg not locked due to parent being locked), // iterate children and invoke those with DoEventsIfDirectParentIsLocked setting diff --git a/GeonBit.UI/GeonBit.UI/Entities/Paragraph.cs b/GeonBit.UI/GeonBit.UI/Entities/Paragraph.cs index 77fac8e..115e9f8 100644 --- a/GeonBit.UI/GeonBit.UI/Entities/Paragraph.cs +++ b/GeonBit.UI/GeonBit.UI/Entities/Paragraph.cs @@ -352,6 +352,14 @@ public void PrepareForDraw() } + /// + /// Draw entity outline. Note: in paragraph its a special case and we implement it inside the DrawEntity function. + /// + /// Sprite batch to draw on. + override protected void DrawEntityOutline(SpriteBatch spriteBatch) + { + } + /// /// Draw the entity. /// @@ -361,12 +369,13 @@ override protected void DrawEntity(SpriteBatch spriteBatch) // calculate internal stuff PrepareForDraw(); - // get some properties + // get outline width int outlineWidth = OutlineWidth; - // if got outline, draw it first + // if we got outline draw it if (outlineWidth > 0) { + // get outline color Color outlineColor = OutlineColor; // for not-too-thick outline we render just two corners diff --git a/GeonBit.UI/GeonBit.UI/Entities/RootPanel.cs b/GeonBit.UI/GeonBit.UI/Entities/RootPanel.cs index 49170a6..3a9fb34 100644 --- a/GeonBit.UI/GeonBit.UI/Entities/RootPanel.cs +++ b/GeonBit.UI/GeonBit.UI/Entities/RootPanel.cs @@ -11,6 +11,7 @@ #endregion using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using System.Collections.Generic; namespace GeonBit.UI.Entities { @@ -28,6 +29,7 @@ public RootPanel() : { Padding = Vector2.Zero; ShadowColor = Color.Transparent; + OutlineWidth = 0; } /// @@ -40,5 +42,37 @@ override public Rectangle CalcDestRect() int height = UserInterface.ScreenHeight; return new Rectangle(0, 0, width, height); } + + /// + /// Draw this entity and its children. + /// + /// SpriteBatch to use for drawing. + override public void Draw(SpriteBatch spriteBatch) + { + // if not visible skip + if (!Visible) + { + return; + } + + // do before draw event + OnBeforeDraw(spriteBatch); + + // calc desination rect + _destRect = CalcDestRect(); + _destRectInternal = CalcInternalRect(); + + // get sorted children list + List childrenSorted = GetSortedChildren(); + + // draw all children + foreach (Entity child in childrenSorted) + { + child.Draw(spriteBatch); + } + + // do after draw event + OnAfterDraw(spriteBatch); + } } } diff --git a/GeonBit.UI/GeonBitUI_Examples.cs b/GeonBit.UI/GeonBitUI_Examples.cs index 12748bb..5a09470 100644 --- a/GeonBit.UI/GeonBitUI_Examples.cs +++ b/GeonBit.UI/GeonBitUI_Examples.cs @@ -637,7 +637,7 @@ This UI is part of the GeonBit project. // create panel tabs PanelTabs tabs = new PanelTabs(); panel.AddChild(tabs); - + // add first panel { PanelTabs.TabData tab = tabs.AddTab("Tab 1"); @@ -909,9 +909,9 @@ This UI is part of the GeonBit project. // add character name, last name, and age // first add the labels - entitiesGroup.AddChild(new Label(@"First Name: ", Anchor.AutoInline, size: new Vector2(250, -1))); - entitiesGroup.AddChild(new Label(@"Last Name: ", Anchor.AutoInline, size: new Vector2(250, -1))); - entitiesGroup.AddChild(new Label(@"Age: ", Anchor.AutoInline, size: new Vector2(100, -1))); + entitiesGroup.AddChild(new Label(@"First Name: ", Anchor.AutoInline, size: new Vector2(0.4f, -1))); + entitiesGroup.AddChild(new Label(@"Last Name: ", Anchor.AutoInline, size: new Vector2(0.4f, -1))); + entitiesGroup.AddChild(new Label(@"Age: ", Anchor.AutoInline, size: new Vector2(0.2f, -1))); // now add the text inputs