From 30baf7a73449a5a0b5c6ea7f3952d4d614ec741f Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Mon, 30 Mar 2015 12:48:56 +0200 Subject: [PATCH] - svg image support - bug fixes --- GOLib.csproj | 21 +- Images/Icons/question_mark.svg | 105 ++++ Tests/GOLIBTest_1.cs | 55 ++ Tests/GOLIBTest_3.cs | 51 ++ Tests/Interfaces/test1.xml | 9 + Tests/Interfaces/test3.xml | 9 + Tests/Tests.csproj | 12 + Tests/image/Mana.svg | 725 +++++++++++++++++++++++ Tests/image/u.svg | 249 ++++++++ src/Colors.cs | 9 + src/CompilerServices/CompilerServices.cs | 8 +- src/GraphicObjects/Button.cs | 4 +- src/GraphicObjects/Container.cs | 13 + src/GraphicObjects/GraphicObject.cs | 26 +- src/GraphicObjects/Group.cs | 20 +- src/GraphicObjects/ILayoutable.cs | 3 + src/GraphicObjects/Image.cs | 46 +- src/GraphicObjects/Label.cs | 2 +- src/GraphicObjects/ProgressBar.cs | 1 + src/GraphicObjects/Window.cs | 12 + src/OpenTKGameWindow.cs | 52 +- 21 files changed, 1392 insertions(+), 40 deletions(-) create mode 100644 Images/Icons/question_mark.svg create mode 100644 Tests/GOLIBTest_1.cs create mode 100755 Tests/GOLIBTest_3.cs create mode 100755 Tests/Interfaces/test1.xml create mode 100755 Tests/Interfaces/test3.xml create mode 100755 Tests/image/Mana.svg create mode 100644 Tests/image/u.svg create mode 100644 src/GraphicObjects/Window.cs diff --git a/GOLib.csproj b/GOLib.csproj index 1d36e410..98f87430 100644 --- a/GOLib.csproj +++ b/GOLib.csproj @@ -21,6 +21,7 @@ OnBuildSuccess 8.0.30703 2.0 + v4.5 true @@ -44,6 +45,10 @@ _WIN32 + + __linux__;DEBUG;TRACE + anycpu + @@ -85,6 +90,7 @@ + @@ -99,6 +105,12 @@ dependencies\OpenTK.dll + + rsvg2-sharp-2.0 + + + glib-sharp-3.0 + @@ -120,8 +132,11 @@ - - PreserveNewest - + + + + + go.image.icons.question_mark + diff --git a/Images/Icons/question_mark.svg b/Images/Icons/question_mark.svg new file mode 100644 index 00000000..9272381f --- /dev/null +++ b/Images/Icons/question_mark.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + ? + + diff --git a/Tests/GOLIBTest_1.cs b/Tests/GOLIBTest_1.cs new file mode 100644 index 00000000..91692b66 --- /dev/null +++ b/Tests/GOLIBTest_1.cs @@ -0,0 +1,55 @@ +#define MONO_CAIRO_DEBUG_DISPOSE + + +using System; +using System.Runtime.InteropServices; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using OpenTK.Input; + +using System.Diagnostics; + +//using GGL; +using go; +using System.Threading; + + +namespace test +{ + class GOLIBTest_1 : OpenTKGameWindow + { + public GOLIBTest_1 () + : base(1024, 600,"test") + {} + + Container g; + + protected override void OnLoad (EventArgs e) + { + base.OnLoad (e); + LoadInterface("Interfaces/test1.xml", out g); + + } + protected override void OnRenderFrame (FrameEventArgs e) + { + GL.Clear (ClearBufferMask.ColorBufferBit); + base.OnRenderFrame (e); + SwapBuffers (); + } + + protected override void OnUpdateFrame (FrameEventArgs e) + { + base.OnUpdateFrame (e); + } + + [STAThread] + static void Main () + { + Console.WriteLine ("starting example"); + + using (GOLIBTest_1 win = new GOLIBTest_1( )) { + win.Run (30.0); + } + } + } +} \ No newline at end of file diff --git a/Tests/GOLIBTest_3.cs b/Tests/GOLIBTest_3.cs new file mode 100755 index 00000000..f0dc3de8 --- /dev/null +++ b/Tests/GOLIBTest_3.cs @@ -0,0 +1,51 @@ +#define MONO_CAIRO_DEBUG_DISPOSE + + +using System; +using System.Runtime.InteropServices; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using OpenTK.Input; + +using System.Diagnostics; + +//using GGL; +using go; +using System.Threading; + + +namespace test +{ + class GOLIBTest_3 : OpenTKGameWindow + { + public GOLIBTest_3 () + : base(1024, 600,"test") + {} + + GraphicObject g; + + protected override void OnLoad (EventArgs e) + { + base.OnLoad (e); + g = LoadInterface("Interfaces/test3.xml"); + + } + protected override void OnRenderFrame (FrameEventArgs e) + { + GL.Clear (ClearBufferMask.ColorBufferBit); + base.OnRenderFrame (e); + SwapBuffers (); + } + + + [STAThread] + static void Main () + { + Console.WriteLine ("starting example"); + + using (GOLIBTest_3 win = new GOLIBTest_3( )) { + win.Run (30.0); + } + } + } +} \ No newline at end of file diff --git a/Tests/Interfaces/test1.xml b/Tests/Interfaces/test1.xml new file mode 100755 index 00000000..43524e85 --- /dev/null +++ b/Tests/Interfaces/test1.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/Tests/Interfaces/test3.xml b/Tests/Interfaces/test3.xml new file mode 100755 index 00000000..f6aa393b --- /dev/null +++ b/Tests/Interfaces/test3.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 2d3abacb..c02c0094 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -56,6 +56,8 @@ + + @@ -67,9 +69,19 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + diff --git a/Tests/image/Mana.svg b/Tests/image/Mana.svg new file mode 100755 index 00000000..ef455e09 --- /dev/null +++ b/Tests/image/Mana.svg @@ -0,0 +1,725 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/Tests/image/u.svg b/Tests/image/u.svg new file mode 100644 index 00000000..5dfe5d89 --- /dev/null +++ b/Tests/image/u.svg @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/src/Colors.cs b/src/Colors.cs index 7d739815..2d428bae 100755 --- a/src/Colors.cs +++ b/src/Colors.cs @@ -71,6 +71,15 @@ namespace go double.Parse(c[3])); } + public static implicit operator OpenTK.Vector4(Color c) + { + return new OpenTK.Vector4 ((float)c.R, (float)c.G, (float)c.B, (float)c.A); + } + public static implicit operator Color(OpenTK.Vector4 v) + { + return new Color (v.X, v.Y, v.Z, v.W); + } + public static implicit operator System.Drawing.Color(Color c) { return System.Drawing.Color.FromArgb((int)(c.A * 255), (int)(c.R * 255), (int)(c.G * 255), (int)(c.B * 255)); diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index 54f43486..034180d1 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -140,13 +140,7 @@ namespace go //emit left operand assignment il.Emit(lopSetOC, lopSetMbi); } - - - - - - - + il.Emit(OpCodes.Ret); #endregion diff --git a/src/GraphicObjects/Button.cs b/src/GraphicObjects/Button.cs index 837b7012..c0c12565 100755 --- a/src/GraphicObjects/Button.cs +++ b/src/GraphicObjects/Button.cs @@ -13,7 +13,7 @@ using System.ComponentModel; namespace go { - public class Button : Container, IXmlSerializable + public class Button : Container { #region CTOR public Button() : base() @@ -37,7 +37,7 @@ namespace go set { base.Height = value; } } [XmlAttributeAttribute()][DefaultValue("Gray")] - public virtual Color Background { + public override Color Background { get { return base.Background; } set { base.Background = value; } } diff --git a/src/GraphicObjects/Container.cs b/src/GraphicObjects/Container.cs index 67d9e6ff..c1134ec5 100644 --- a/src/GraphicObjects/Container.cs +++ b/src/GraphicObjects/Container.cs @@ -2,6 +2,7 @@ using System; using System.Xml.Serialization; using System.Reflection; using OpenTK.Input; +using System.ComponentModel; namespace go { @@ -35,6 +36,13 @@ namespace go } #region GraphicObject Overrides + //check if not causing problems + [XmlAttributeAttribute()][DefaultValue(true)] + public override bool Focusable + { + get { return base.Focusable; } + set { base.Focusable = value; } + } [XmlIgnore]public override bool LayoutIsValid { get @@ -56,6 +64,11 @@ namespace go return child == null ? null : child.FindByName (nameToFind); } + public override bool Contains (GraphicObject goToFind) + { + return child == goToFind ? true : + child == null ? false : child.Contains(goToFind); + } public override void InvalidateLayout() { base.InvalidateLayout(); diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index ec3b7fef..935729f2 100755 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -114,7 +114,9 @@ namespace go return cb; } } - + [XmlIgnore]public virtual OpenTKGameWindow TopContainer { + get { return Parent.TopContainer; } + } public virtual void InvalidateLayout () { bmp = null; @@ -134,6 +136,10 @@ namespace go { return Slot; } + public virtual Rectangle getBounds() + { + return Bounds; + } #endregion #region EVENT HANDLERS @@ -279,8 +285,15 @@ namespace go return; _isVisible = value; - if (Parent != null) - Parent.InvalidateLayout (); + + //add slot to clipping to redraw + OpenTKGameWindow.gobjsToRedraw.Add (this); + + //ensure main win doesn't keep hidden childrens ref + if (this.Contains (OpenTKGameWindow.currentWindow.hoverWidget)) + OpenTKGameWindow.currentWindow.hoverWidget = null; +// if (Parent != null) +// Parent.InvalidateLayout (); //else // registerForRedraw(); } @@ -347,6 +360,9 @@ namespace go public virtual GraphicObject FindByName(string nameToFind){ return nameToFind == _name ? this : null; } + public virtual bool Contains(GraphicObject goToFind){ + return false; + } /// @@ -429,7 +445,7 @@ namespace go Slot.X = Parent.ClientRectangle.Width / 2 - Slot.Width / 2; break; } - } else + } else// if (Parent.getBounds().Width>=0) xIsValid = false; } @@ -451,7 +467,7 @@ namespace go Slot.Y = Parent.ClientRectangle.Height / 2 - Slot.Height / 2; break; } - } else + } else// if (Parent.getBounds().Height>=0) yIsValid = false; } } diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index ef101ed1..4e8e5492 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -114,6 +114,16 @@ namespace go } return null; } + public override bool Contains (GraphicObject goToFind) + { + foreach (GraphicObject w in Children) { + if (w == goToFind) + return true; + if (w.Contains (goToFind)) + return true; + } + return false; + } public override void InvalidateLayout() { base.InvalidateLayout(); @@ -162,10 +172,16 @@ namespace go if (c.LayoutIsValid) continue; - if (Width < 0 && c.Width != 0) + if (Width < 0 && c.Width != 0) { + if (!atLeastOneChildHasWNotDependingOnParent && !(this is GenericStack)) + c.XIsValid = true; atLeastOneChildHasWNotDependingOnParent = true; - if (Height < 0 && c.Height != 0) + } + if (Height < 0 && c.Height != 0) { + if (!atLeastOneChildHasHNotDependingOnParent && !(this is GenericStack)) + c.YIsValid = true; atLeastOneChildHasHNotDependingOnParent = true; + } c.UpdateLayout (); } diff --git a/src/GraphicObjects/ILayoutable.cs b/src/GraphicObjects/ILayoutable.cs index 6560eb6c..579fe2b0 100644 --- a/src/GraphicObjects/ILayoutable.cs +++ b/src/GraphicObjects/ILayoutable.cs @@ -16,6 +16,9 @@ namespace go Rectangle ClientRectangle { get; } Rectangle getSlot(); + Rectangle getBounds(); + + OpenTKGameWindow TopContainer { get; } void InvalidateLayout (); diff --git a/src/GraphicObjects/Image.cs b/src/GraphicObjects/Image.cs index a71205b6..aa3ea56d 100755 --- a/src/GraphicObjects/Image.cs +++ b/src/GraphicObjects/Image.cs @@ -2,10 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; - -//using OpenTK.Graphics.OpenGL; using Cairo; using System.IO; +using System.Runtime.InteropServices; namespace go { @@ -13,6 +12,7 @@ namespace go { byte[] image; + Rsvg.Handle hSVG; Size imgSize; string _imgPath; @@ -58,19 +58,33 @@ namespace go protected override Size measureRawSize () { - if (image == null) - loadImage (@"Images/Icons/icon_alert.gif"); + if (image == null && hSVG == null) + loadRessourceSvg ("go.image.icons.question_mark"); return imgSize + Margin*2; } - + void loadRessourceSvg(string resId) + { + Stream s = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resId); + using (MemoryStream ms = new MemoryStream ()) { + s.CopyTo (ms); + hSVG = new Rsvg.Handle (ms.ToArray ()); + imgSize = new Size (hSVG.Dimensions.Width, hSVG.Dimensions.Height); + _imgPath = resId; + //loadImage (@"Images/Icons/question_mark.svg"); + } + } //load image via System.Drawing.Bitmap, cairo load png only public void loadImage (string path) { if (!File.Exists(path)) return; - loadImage (new System.Drawing.Bitmap (path)); + if (path.EndsWith (".svg", true,System.Globalization.CultureInfo.InvariantCulture)) { + hSVG = new Rsvg.Handle (path); + imgSize = new Size (hSVG.Dimensions.Width, hSVG.Dimensions.Height); + }else + loadImage (new System.Drawing.Bitmap (path)); _imgPath = path; } @@ -97,19 +111,25 @@ namespace go protected override void onDraw (Context gr) { base.onDraw (gr); - float ratio = 1f; + float widthRatio = (float)ClientRectangle.Width / imgSize.Width; float heightRatio = (float)ClientRectangle.Height / imgSize.Height; + float ratio = Math.Min (widthRatio, heightRatio); - ratio = Math.Min (widthRatio, heightRatio); Rectangle rImg = ClientRectangle; - + gr.Save (); gr.Scale (widthRatio, heightRatio); - using (ImageSurface imgSurf = new ImageSurface(image, Format.Argb32, - imgSize.Width, imgSize.Height, 4 * imgSize.Width)) { - gr.SetSourceSurface (imgSurf, (int)(rImg.X / widthRatio), (int)(rImg.Y / heightRatio)); - gr.Paint (); + if (hSVG == null) { + using (ImageSurface imgSurf = new ImageSurface (image, Format.Argb32, + imgSize.Width, imgSize.Height, 4 * imgSize.Width)) { + gr.SetSourceSurface (imgSurf, (int)(rImg.X / widthRatio), (int)(rImg.Y / heightRatio)); + gr.Paint (); + } + } else { + gr.Translate (rImg.X/widthRatio, rImg.Y/heightRatio); + hSVG.RenderCairo (gr); } + gr.Restore (); } } } diff --git a/src/GraphicObjects/Label.cs b/src/GraphicObjects/Label.cs index 91f53291..37e2b8c7 100755 --- a/src/GraphicObjects/Label.cs +++ b/src/GraphicObjects/Label.cs @@ -115,7 +115,7 @@ namespace go string[] lines = getLines; - using (ImageSurface img = new ImageSurface (Format.Argb32, 1, 1)) { + using (ImageSurface img = new ImageSurface (Format.Argb32, 10, 10)) { using (Context gr = new Context (img)) { //Cairo.FontFace cf = gr.GetContextFontFace (); diff --git a/src/GraphicObjects/ProgressBar.cs b/src/GraphicObjects/ProgressBar.cs index ad43fc23..ed3c09df 100644 --- a/src/GraphicObjects/ProgressBar.cs +++ b/src/GraphicObjects/ProgressBar.cs @@ -91,6 +91,7 @@ namespace go if (BorderWidth > 0) rBack.Inflate(-BorderWidth, -BorderWidth); + rBack.Width = (int)((double)rBack.Width / Maximum * Value); gr.Color = Foreground; diff --git a/src/GraphicObjects/Window.cs b/src/GraphicObjects/Window.cs new file mode 100644 index 00000000..750478da --- /dev/null +++ b/src/GraphicObjects/Window.cs @@ -0,0 +1,12 @@ +using System; + +namespace go +{ + public class Window : Container + { + public Window () + { + } + } +} + diff --git a/src/OpenTKGameWindow.cs b/src/OpenTKGameWindow.cs index df9cc903..1e937545 100755 --- a/src/OpenTKGameWindow.cs +++ b/src/OpenTKGameWindow.cs @@ -31,7 +31,7 @@ namespace go // DisplayDevice.Default, // 3,0,OpenTK.Graphics.GraphicsContextFlags.Default) public OpenTKGameWindow(int _width, int _height, string _title="golib") - : base(_width, _height, new OpenTK.Graphics.GraphicsMode(32, 24, 0, 0), + : base(_width, _height, new OpenTK.Graphics.GraphicsMode(32, 24, 0, 8), _title,GameWindowFlags.Default,DisplayDevice.Default, 3,2,OpenTK.Graphics.GraphicsContextFlags.Debug|OpenTK.Graphics.GraphicsContextFlags.ForwardCompatible) // public OpenTKGameWindow(int _width, int _height, string _title="golib") @@ -54,6 +54,15 @@ namespace go public static List gobjsToRedraw = new List(); internal static OpenTKGameWindow currentWindow; + #region Events + //those events are raised only if mouse isn't in a graphic object + public event EventHandler MouseWheelChanged = delegate { }; + public event EventHandler MouseButtonUp = delegate { }; + public event EventHandler MouseButtonDown = delegate { }; + public event EventHandler MouseClick = delegate { }; + public event EventHandler MouseMove = delegate { }; + #endregion + #region focus GraphicObject _activeWidget; //button is pressed on widget @@ -197,10 +206,13 @@ namespace go //Debug.WriteLine ("otd:" + gobjsToRedraw.Count.ToString () + "-"); //redraw clip should be added when layout is complete among parents, //that's why it take place in a second pass - foreach (GraphicObject p in gobjsToRedraw) { + GraphicObject[] gotr = new GraphicObject[gobjsToRedraw.Count]; + gobjsToRedraw.CopyTo (gotr); + gobjsToRedraw.Clear (); + foreach (GraphicObject p in gotr) { p.registerClipRect (); } - gobjsToRedraw.Clear (); + lock (redrawClip) { if (redrawClip.count > 0) { @@ -260,11 +272,23 @@ namespace go g.Parent = this; GraphicObjects.Add (g); } + public void DeleteWidget(GraphicObject g) + { + g.Visible = false;//ensure clip is added to refresh zone + GraphicObjects.Remove (g); + } public void LoadInterface(string path, out T result) { GraphicObject.Load (path, out result, this); AddWidget (result as GraphicObject); } + public T LoadInterface (string Path) + { + T result; + GraphicObject.Load (Path, out result, this); + AddWidget (result as GraphicObject); + return result; + } #region Game win overrides protected override void OnUpdateFrame(FrameEventArgs e) @@ -362,6 +386,7 @@ namespace go } } _hoverWidget = null; + MouseMove (this, e); } void Mouse_ButtonUp(object sender, MouseButtonEventArgs e) { @@ -370,17 +395,21 @@ namespace go _activeWidget.onMouseButtonUp (this, e); _activeWidget = null; + MouseButtonUp (this, e); } void Mouse_ButtonDown(object sender, MouseButtonEventArgs e) { - if (_hoverWidget == null) + if (_hoverWidget == null) { + MouseButtonDown (this, e); return; + } GraphicObject g = _hoverWidget; while (!g.Focusable) { g = g.Parent as GraphicObject; - if (g == null) + if (g == null) { return; + } } _activeWidget = g; @@ -388,8 +417,10 @@ namespace go } void Mouse_WheelChanged(object sender, MouseWheelEventArgs e) { - if (_hoverWidget == null) + if (_hoverWidget == null) { + MouseWheelChanged (this, e); return; + } _hoverWidget.onMouseWheel (this, e); } #endregion @@ -452,11 +483,18 @@ namespace go get { return new Size(this.ClientRectangle.Size.Width,this.ClientRectangle.Size.Height); } } + public OpenTKGameWindow TopContainer { + get { return this; } + } + public Rectangle getSlot () { return ClientRectangle; } - + public Rectangle getBounds ()//redundant but fill ILayoutable implementation + { + return ClientRectangle; + } public bool WIsValid { get { return true; -- 2.47.3