From 9850f0cfe33f1f133bde4807a6707f0e31389ae2 Mon Sep 17 00:00:00 2001 From: Yan Maniez Date: Sat, 27 Jul 2019 12:14:56 +0200 Subject: [PATCH] Charts urho --- AideDeJeu/AideDeJeu/Views/DicesPage.xaml.cs | 7 +- AideDeJeu/AideDeJeu/Views/UrhoTest.cs | 229 ++++++++++++++++++++ 2 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 AideDeJeu/AideDeJeu/Views/UrhoTest.cs diff --git a/AideDeJeu/AideDeJeu/Views/DicesPage.xaml.cs b/AideDeJeu/AideDeJeu/Views/DicesPage.xaml.cs index 1a29a8c3..10e9a6ff 100644 --- a/AideDeJeu/AideDeJeu/Views/DicesPage.xaml.cs +++ b/AideDeJeu/AideDeJeu/Views/DicesPage.xaml.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; - +using Urho; using Xamarin.Forms; using Xamarin.Forms.Xaml; @@ -85,7 +85,8 @@ namespace AideDeJeu.Views private async void ContentPage_Appearing(object sender, EventArgs e) { - await HelloWorldUrhoSurface.Show(new Urho.ApplicationOptions(assetsFolder: null)); + //await HelloWorldUrhoSurface.Show(new Urho.ApplicationOptions(assetsFolder: null)); + await HelloWorldUrhoSurface.Show(new Urho.ApplicationOptions(assetsFolder: null)); } } public class HelloWorld : Urho.Application @@ -116,4 +117,6 @@ namespace AideDeJeu.Views UI.Root.AddChild(text); } } + + } \ No newline at end of file diff --git a/AideDeJeu/AideDeJeu/Views/UrhoTest.cs b/AideDeJeu/AideDeJeu/Views/UrhoTest.cs new file mode 100644 index 00000000..2b62c59a --- /dev/null +++ b/AideDeJeu/AideDeJeu/Views/UrhoTest.cs @@ -0,0 +1,229 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using Urho; +using Urho.Actions; +using Urho.Gui; +using Urho.Shapes; + +namespace AideDeJeu.Views +{ + public class Charts : Application + { + bool movementsEnabled; + Scene scene; + Node plotNode; + Camera camera; + Octree octree; + List bars; + + public Bar SelectedBar { get; private set; } + + public IEnumerable Bars => bars; + + [Preserve] + public Charts(ApplicationOptions options = null) : base(options) { } + + static Charts() + { + UnhandledException += (s, e) => + { + if (Debugger.IsAttached) + Debugger.Break(); + e.Handled = true; + }; + } + + protected override void Start() + { + base.Start(); + CreateScene(); + SetupViewport(); + } + + async void CreateScene() + { + Input.SubscribeToTouchEnd(OnTouched); + + scene = new Scene(); + octree = scene.CreateComponent(); + + plotNode = scene.CreateChild(); + var baseNode = plotNode.CreateChild().CreateChild(); + var plane = baseNode.CreateComponent(); + plane.Model = CoreAssets.Models.Plane; + + var cameraNode = scene.CreateChild(); + camera = cameraNode.CreateComponent(); + cameraNode.Position = new Vector3(10, 15, 10) / 1.75f; + cameraNode.Rotation = new Quaternion(-0.121f, 0.878f, -0.305f, -0.35f); + + Node lightNode = cameraNode.CreateChild(); + var light = lightNode.CreateComponent(); + light.LightType = LightType.Point; + light.Range = 100; + light.Brightness = 1.3f; + + int size = 3; + baseNode.Scale = new Vector3(size * 1.5f, 1, size * 1.5f); + bars = new List(size * size); + for (var i = 0f; i < size * 1.5f; i += 1.5f) + { + for (var j = 0f; j < size * 1.5f; j += 1.5f) + { + var boxNode = plotNode.CreateChild(); + boxNode.Position = new Vector3(size / 2f - i, 0, size / 2f - j); + var box = new Bar(new Color(RandomHelper.NextRandom(), RandomHelper.NextRandom(), RandomHelper.NextRandom(), 0.9f)); + boxNode.AddComponent(box); + box.SetValueWithAnimation((Math.Abs(i) + Math.Abs(j) + 1) / 2f); + bars.Add(box); + } + } + + SelectedBar = bars.First(); + SelectedBar.Select(); + + + + try + { + await plotNode.RunActionsAsync(new EaseBackOut(new RotateBy(2f, 0, 360, 0))); + } + catch (OperationCanceledException) { } + movementsEnabled = true; + } + + void OnTouched(TouchEndEventArgs e) + { + Ray cameraRay = camera.GetScreenRay((float)e.X / Graphics.Width, (float)e.Y / Graphics.Height); + var results = octree.RaycastSingle(cameraRay, RayQueryLevel.Triangle, 100, DrawableFlags.Geometry); + if (results != null) + { + var bar = results.Value.Node?.Parent?.GetComponent(); + if (SelectedBar != bar) + { + SelectedBar?.Deselect(); + SelectedBar = bar; + SelectedBar?.Select(); + } + } + } + + protected override void OnUpdate(float timeStep) + { + if (Input.NumTouches >= 1 && movementsEnabled) + { + var touch = Input.GetTouch(0); + plotNode.Rotate(new Quaternion(0, -touch.Delta.X, 0), TransformSpace.Local); + } + base.OnUpdate(timeStep); + } + + public void Rotate(float toValue) + { + plotNode.Rotate(new Quaternion(0, toValue, 0), TransformSpace.Local); + } + + void SetupViewport() + { + var renderer = Renderer; + var vp = new Viewport(Context, scene, camera, null); + renderer.SetViewport(0, vp); + } + } + + public class Bar : Component + { + Node barNode; + Node textNode; + Text3D text3D; + Color color; + float lastUpdateValue; + + public float Value + { + get { return barNode.Scale.Y; } + set { barNode.Scale = new Vector3(1, value < 0.3f ? 0.3f : value, 1); } + } + + public void SetValueWithAnimation(float value) => barNode.RunActionsAsync(new EaseBackOut(new ScaleTo(3f, 1, value, 1))); + + public Bar(Color color) + { + this.color = color; + ReceiveSceneUpdates = true; + } + + public override void OnAttachedToNode(Node node) + { + barNode = node.CreateChild(); + barNode.Scale = new Vector3(1, 0, 1); //means zero height + var box = barNode.CreateComponent(); + box.Color = color; + + textNode = node.CreateChild(); + textNode.Rotate(new Quaternion(0, 180, 0), TransformSpace.World); + textNode.Position = new Vector3(0, 10, 0); + text3D = textNode.CreateComponent(); + text3D.SetFont(CoreAssets.Fonts.AnonymousPro, 60); + text3D.TextEffect = TextEffect.Stroke; + + base.OnAttachedToNode(node); + } + + protected override void OnUpdate(float timeStep) + { + var pos = barNode.Position; + var scale = barNode.Scale; + barNode.Position = new Vector3(pos.X, scale.Y / 2f, pos.Z); + textNode.Position = new Vector3(0.5f, scale.Y + 0.2f, 0); + var newValue = (float)Math.Round(scale.Y, 1); + if (lastUpdateValue != newValue) + text3D.Text = newValue.ToString("F01", CultureInfo.InvariantCulture); + lastUpdateValue = newValue; + } + + public void Deselect() + { + barNode.RemoveAllActions();//TODO: remove only "selection" action + barNode.RunActions(new EaseBackOut(new TintTo(1f, color.R, color.G, color.B))); + } + + public void Select() + { + Selected?.Invoke(this); + // "blinking" animation + barNode.RunActions(new RepeatForever(new TintTo(0.3f, 1f, 1f, 1f), new TintTo(0.3f, color.R, color.G, color.B))); + } + + public event Action Selected; + } + + public static class RandomHelper + { + static readonly Random random = new Random(); + + /// + /// Return a random float between 0.0 (inclusive) and 1.0 (exclusive.) + /// + public static float NextRandom() { return (float)random.NextDouble(); } + + /// + /// Return a random float between 0.0 and range, inclusive from both ends. + /// + public static float NextRandom(float range) { return (float)random.NextDouble() * range; } + + /// + /// Return a random float between min and max, inclusive from both ends. + /// + public static float NextRandom(float min, float max) { return (float)((random.NextDouble() * (max - min)) + min); } + + /// + /// Return a random integer between min and max - 1. + /// + public static int NextRandom(int min, int max) { return random.Next(min, max); } + } +}