added controllers and avalonia integration. Already can render elements
This commit is contained in:
Родитель
db3418d09b
Коммит
624c857c60
|
@ -1,7 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<attachedFolders>
|
||||
<Path>../SomeCharts_</Path>
|
||||
</attachedFolders>
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Folder Include="src\data" />
|
||||
<Folder Include="src\elements\charts" />
|
||||
<Folder Include="src\elements\ui" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -10,13 +10,8 @@ namespace SomeChartsUi.backends;
|
|||
/// all positions and scales are in screen-space transform
|
||||
/// </summary>
|
||||
public abstract class ChartsBackendBase {
|
||||
public ChartsCanvas owner;
|
||||
public ChartCanvasRenderer renderer;
|
||||
|
||||
protected ChartsBackendBase(ChartsCanvas owner, ChartCanvasRenderer renderer) {
|
||||
this.owner = owner;
|
||||
this.renderer = renderer;
|
||||
}
|
||||
public ChartsCanvas owner = null!;
|
||||
public ChartCanvasRenderer renderer = null!;
|
||||
|
||||
public abstract unsafe void DrawMesh(float2* points, float2* uvs, color* colors, ushort* indexes, int vertexCount, int indexCount);
|
||||
public abstract void DrawMesh(float2[] points, float2[]? uvs, color[]? colors, ushort[] indexes);
|
||||
|
@ -24,4 +19,6 @@ public abstract class ChartsBackendBase {
|
|||
public abstract void DrawText(string text, float2 pos, color col, FontData font, float scale = 12);
|
||||
|
||||
public abstract void DrawRect(rect rectangle, color color);
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using SomeChartsUi.themes.colors;
|
||||
using SomeChartsUi.ui.elements;
|
||||
using SomeChartsUi.utils.rects;
|
||||
using SomeChartsUi.utils.vectors;
|
||||
|
||||
namespace SomeChartsUi.elements.other;
|
||||
|
||||
public class TestRenderable : RenderableBase {
|
||||
protected override void Render() {
|
||||
rect r = new(-100, -100, 200, 200);
|
||||
float2[] points = {r.leftBottom, r.leftTop, r.rightTop, r.rightBottom};
|
||||
color[] colors = {color.red, color.softRed, color.blue, color.softBlue};
|
||||
ushort[] indexes = {0, 1, 2, 0, 2, 3};
|
||||
DrawVertices(points, null, colors, indexes);
|
||||
//Console.WriteLine("render");
|
||||
}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
using SomeChartsUi.backends;
|
||||
using SomeChartsUi.ui.layers;
|
||||
|
||||
namespace SomeChartsUi.ui.canvas;
|
||||
|
||||
public class ChartCanvasRenderer {
|
||||
public ChartsCanvas owner;
|
||||
public ChartsBackendBase backend;
|
||||
|
||||
public readonly ChartsBackendBase backend;
|
||||
|
||||
public readonly List<CanvasLayer> layers = new();
|
||||
public readonly Dictionary<string, int> layerNames = new();
|
||||
|
||||
public ChartCanvasRenderer(ChartsCanvas owner, ChartsBackendBase backend) {
|
||||
this.owner = owner;
|
||||
|
|
|
@ -5,8 +5,8 @@ using SomeChartsUi.utils.vectors;
|
|||
namespace SomeChartsUi.ui.canvas;
|
||||
|
||||
public class ChartCanvasTransform {
|
||||
public CanvasAnimVariable<float2> position = new(float2.zero);
|
||||
public CanvasAnimVariable<float2> zoom = new(float2.one);
|
||||
public CanvasAnimVariable<float2> position = new(float2.zero, animationSpeed: .05f);
|
||||
public CanvasAnimVariable<float2> zoom = new(float2.one, animationSpeed: .05f);
|
||||
public CanvasAnimVariable<float> rotation = new(0);
|
||||
|
||||
public rect screenBounds;
|
||||
|
@ -25,4 +25,10 @@ public class ChartCanvasTransform {
|
|||
|
||||
worldBounds = screenBounds.ToWorld(position, zoom);
|
||||
}
|
||||
|
||||
public void SetAnimToCurrent() {
|
||||
position.OnUpdate(10000);
|
||||
zoom.OnUpdate(10000);
|
||||
rotation.OnUpdate(10000);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
using SomeChartsUi.backends;
|
||||
using SomeChartsUi.ui.canvas.controls;
|
||||
using SomeChartsUi.ui.layers;
|
||||
|
||||
namespace SomeChartsUi.ui.canvas;
|
||||
|
||||
|
@ -6,8 +8,30 @@ public class ChartsCanvas {
|
|||
public ChartCanvasTransform transform;
|
||||
public ChartCanvasRenderer renderer;
|
||||
|
||||
public ChartCanvasControllerBase? controller;
|
||||
private List<CanvasLayer> layers => renderer.layers;
|
||||
private Dictionary<string, int> layerNames => renderer.layerNames;
|
||||
|
||||
public ChartsCanvas(ChartsBackendBase backend) {
|
||||
transform = new();
|
||||
renderer = new(this, backend);
|
||||
backend.owner = this;
|
||||
backend.renderer = renderer;
|
||||
}
|
||||
|
||||
public CanvasLayer AddLayer(string name) {
|
||||
CanvasLayer l = new(this, name);
|
||||
renderer.layerNames.Add(name, layers.Count);
|
||||
layers.Add(l);
|
||||
return l;
|
||||
}
|
||||
|
||||
public void RemoveLayer(string name) {
|
||||
if (!layerNames.ContainsKey(name)) return;
|
||||
layers.RemoveAt(layerNames[name]);
|
||||
layerNames.Remove(name);
|
||||
}
|
||||
|
||||
public CanvasLayer? GetLayer(string name) => layerNames.TryGetValue(name, out int i) ? layers[i] : null;
|
||||
public CanvasLayer GetLayer(int i) => layers[i];
|
||||
}
|
|
@ -4,8 +4,25 @@ namespace SomeChartsUi.ui.canvas;
|
|||
|
||||
//TODO: method arguments is a subject of change
|
||||
public interface ICanvasControls {
|
||||
public void OnMouseMove(float2 pointerPos) {}
|
||||
public void OnMouseDown(PointerButtons buttons, keymods mods) {}
|
||||
public void OnMouseUp(PointerButtons buttons, keymods mods) {}
|
||||
public void OnMouseMove(MouseState state) {}
|
||||
public void OnMouseDown(MouseState state) {}
|
||||
public void OnMouseUp(MouseState state) {}
|
||||
public void OnMouseScroll(MouseState state) {}
|
||||
public void OnKey(keycode key, keymods mods) {}
|
||||
}
|
||||
|
||||
public class MouseState {
|
||||
public float2 pos;
|
||||
public float2 wheel;
|
||||
public PointerButtons buttons;
|
||||
public keymods modifiers;
|
||||
public object? capture;
|
||||
|
||||
public MouseState(float2 pos, float2 wheel, PointerButtons buttons, keymods modifiers, object? capture) {
|
||||
this.pos = pos;
|
||||
this.wheel = wheel;
|
||||
this.buttons = buttons;
|
||||
this.modifiers = modifiers;
|
||||
this.capture = capture;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
namespace SomeChartsUi.ui.canvas.controls;
|
||||
|
||||
public class CanvasCompositeController : ChartCanvasControllerBase {
|
||||
public List<CanvasCompositeController> controllers = new();
|
||||
|
||||
public CanvasCompositeController(ChartsCanvas owner) : base(owner) { }
|
||||
|
||||
public override void OnUpdate(float deltatime) {
|
||||
foreach (CanvasCompositeController ctrl in controllers)
|
||||
ctrl.OnUpdate(deltatime);
|
||||
}
|
||||
|
||||
public override void OnMouseMove(MouseState state) {
|
||||
foreach (CanvasCompositeController ctrl in controllers)
|
||||
ctrl.OnMouseMove(state);
|
||||
}
|
||||
public override void OnMouseDown(MouseState state) {
|
||||
foreach (CanvasCompositeController ctrl in controllers)
|
||||
ctrl.OnMouseDown(state);
|
||||
}
|
||||
public override void OnMouseUp(MouseState state) {
|
||||
foreach (CanvasCompositeController ctrl in controllers)
|
||||
ctrl.OnMouseUp(state);
|
||||
}
|
||||
public override void OnMouseScroll(MouseState state) {
|
||||
foreach (CanvasCompositeController ctrl in controllers)
|
||||
ctrl.OnMouseScroll(state);
|
||||
}
|
||||
public override void OnKey(keycode key, keymods mods) {
|
||||
foreach (CanvasCompositeController ctrl in controllers)
|
||||
ctrl.OnKey(key, mods);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
using SomeChartsUi.utils.vectors;
|
||||
|
||||
namespace SomeChartsUi.ui.canvas.controls;
|
||||
|
||||
public class CanvasUiController : ChartCanvasControllerBase {
|
||||
private float2 _start;
|
||||
private float2 _origin;
|
||||
|
||||
public float zoomSpeed = .2f;
|
||||
|
||||
public CanvasUiController(ChartsCanvas owner) : base(owner) { }
|
||||
|
||||
public override void OnMouseMove(MouseState state) {
|
||||
float2 pointerPos = state.pos;
|
||||
pointerPos.FlipY();
|
||||
if (state.capture == null) return;
|
||||
|
||||
float speed = 1;
|
||||
if ((state.modifiers & keymods.alt) != 0) speed = 4;
|
||||
|
||||
float2 mov = (pointerPos - _start) / owner.transform.zoom.currentValue * speed + _origin;
|
||||
|
||||
SetPosition(mov);
|
||||
|
||||
//_start = e.GetPosition(this);
|
||||
//_start.FlipY();
|
||||
_start = pointerPos;
|
||||
_origin = mov;
|
||||
}
|
||||
public override void OnMouseDown(MouseState state) {
|
||||
float2 pointerPos = state.pos;
|
||||
pointerPos.FlipY();
|
||||
state.capture = this;
|
||||
|
||||
_start = pointerPos;
|
||||
|
||||
_origin = owner.transform.position.currentValue;
|
||||
//Cursor = Cursor.Parse("Hand");
|
||||
}
|
||||
public override void OnMouseUp(MouseState state) {
|
||||
state.capture = null;
|
||||
//Cursor = Cursor.Default;
|
||||
}
|
||||
|
||||
public override void OnMouseScroll(MouseState state) {
|
||||
float2 pointerPos = state.pos;
|
||||
pointerPos.FlipY();
|
||||
bool disableAnim = false;
|
||||
|
||||
float2 zoomAdd = zoomSpeed * state.wheel.yy;
|
||||
|
||||
if ((state.modifiers & keymods.shift) != 0) zoomAdd.x = 0;
|
||||
if ((state.modifiers & keymods.ctrl) != 0) zoomAdd.y = 0;
|
||||
if ((state.modifiers & keymods.alt) != 0) {
|
||||
zoomAdd.x *= 2;
|
||||
zoomAdd.y *= 2;
|
||||
disableAnim = true;
|
||||
}
|
||||
|
||||
float2 oldScale = owner.transform.zoom.currentValue;
|
||||
float2 newScale = float2.Clamp(oldScale * (1 + zoomAdd), .001f, 1.5f);
|
||||
// float2 newScale = new(Math.Clamp(oldScale.x * (1 + zoomAdd.x), .001f, 1.5f), Math.Clamp(oldScale.y * (1 + zoomAdd.y), .001f, 1.5f));
|
||||
zoomAdd = 1 - newScale / oldScale;
|
||||
|
||||
SetZoom(newScale);
|
||||
float2 posOffset = new(pointerPos.x * zoomAdd.x / newScale.x,
|
||||
(owner.transform.screenBounds.height + pointerPos.y) * zoomAdd.y / newScale.y);
|
||||
|
||||
Move(posOffset);
|
||||
|
||||
if (disableAnim) owner.transform.SetAnimToCurrent();
|
||||
}
|
||||
|
||||
public override void OnUpdate(float deltatime) { }
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@ using SomeChartsUi.utils.vectors;
|
|||
|
||||
namespace SomeChartsUi.ui.canvas.controls;
|
||||
|
||||
public abstract class ChartCanvasControllerBase : ICanvasUpdate {
|
||||
public abstract class ChartCanvasControllerBase : ICanvasUpdate, ICanvasControls {
|
||||
protected ChartsCanvas owner;
|
||||
|
||||
protected ChartCanvasControllerBase(ChartsCanvas owner) => this.owner = owner;
|
||||
|
@ -30,4 +30,16 @@ public abstract class ChartCanvasControllerBase : ICanvasUpdate {
|
|||
owner.transform.position.OnUpdate(1000);
|
||||
owner.transform.zoom.OnUpdate(1000);
|
||||
}
|
||||
|
||||
public virtual void OnMouseMove(MouseState state) {
|
||||
|
||||
}
|
||||
public virtual void OnMouseDown(MouseState state) {
|
||||
}
|
||||
public virtual void OnMouseUp(MouseState state) {
|
||||
}
|
||||
public virtual void OnMouseScroll(MouseState state) {
|
||||
}
|
||||
public virtual void OnKey(keycode key, keymods mods) {
|
||||
}
|
||||
}
|
|
@ -5,16 +5,23 @@ using SomeChartsUi.ui.elements;
|
|||
namespace SomeChartsUi.ui.layers;
|
||||
|
||||
public class CanvasLayer {
|
||||
public ChartsCanvas owner;
|
||||
public readonly string name;
|
||||
public readonly ChartsCanvas owner;
|
||||
public color? background;
|
||||
public List<RenderableBase> elements = new();
|
||||
public readonly List<RenderableBase> elements = new();
|
||||
|
||||
public CanvasLayer(ChartsCanvas owner) => this.owner = owner;
|
||||
public CanvasLayer(ChartsCanvas owner, string name) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void AddElement(RenderableBase r) => elements.Add(r);
|
||||
public void RemoveElement(RenderableBase r) => elements.Remove(r);
|
||||
|
||||
public void Render() {
|
||||
|
||||
if (background != null) owner.renderer.backend.DrawRect(owner.transform.screenBounds, background.Value);
|
||||
foreach (RenderableBase element in elements) {
|
||||
element.Render(owner);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,11 @@ public struct rect {
|
|||
public float right => left + width;
|
||||
public float top => bottom + height;
|
||||
|
||||
public float2 leftBottom => new(left, bottom);
|
||||
public float2 leftTop => new(left, top);
|
||||
public float2 rightTop => new(right, top);
|
||||
public float2 rightBottom => new(right, bottom);
|
||||
|
||||
public float midX => left + width * .5f;
|
||||
public float midY => bottom + height * .5f;
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ public struct float2 {
|
|||
public void FlipY() => y = -y;
|
||||
public void FlipX() => x = -x;
|
||||
public void Flip() => (x, y) = (-x, -y);
|
||||
|
||||
|
||||
|
||||
public static implicit operator float2(float v) => new(v);
|
||||
public static implicit operator float2(int v) => new(v);
|
||||
|
@ -62,8 +64,14 @@ public struct float2 {
|
|||
|
||||
public static float2 SinCos(float rad) => new(MathF.Sin(rad), MathF.Cos(rad));
|
||||
public static float2 SinCos(float rad, float len) => new(MathF.Sin(rad) * len, MathF.Cos(rad) * len);
|
||||
|
||||
public static float2 Min(float2 a, float2 b) => new(math.min(a.x, b.x), math.min(a.y, b.y));
|
||||
public static float2 Max(float2 a, float2 b) => new(math.max(a.x, b.x), math.max(a.y, b.y));
|
||||
public static float2 Clamp(float2 v, float2 min, float2 max) => Max(Min(v, max), min);
|
||||
|
||||
public bool Equals(float2 other) => x == other.x && y == other.y;
|
||||
public override bool Equals(object? obj) => obj is float2 other && Equals(other);
|
||||
public override int GetHashCode() => HashCode.Combine(x, y);
|
||||
|
||||
public override string ToString() => $"({x},{y})";
|
||||
}
|
|
@ -2,8 +2,10 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:SomeChartsUiAvalonia.controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SomeChartsUiAvalonia.MainWindow"
|
||||
Title="SomeChartsUiAvalonia">
|
||||
Welcome to Avalonia!
|
||||
|
||||
<controls:AvaloniaChartsCanvas/>
|
||||
</Window>
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.88.0-preview.187" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="src\controls" />
|
||||
<Folder Include="src\ui" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -48,16 +48,21 @@ public class SkiaChartsBackend : ChartsBackendBase, IDisposable {
|
|||
// skia using flipped y axis, so flip back it
|
||||
canvas.Scale(1,-1);
|
||||
canvas.Translate(0, -owner.transform.screenBounds.height);
|
||||
|
||||
canvas.Scale((owner.transform.zoom.animatedValue).sk());
|
||||
canvas.Translate(owner.transform.position.animatedValue.sk());
|
||||
|
||||
_canvas?.Dispose();
|
||||
_canvas = canvas;
|
||||
_paint ??= new();
|
||||
|
||||
_paint.SubpixelText = true;
|
||||
_paint.Color = SKColors.White;
|
||||
_paint.StrokeWidth = 2;
|
||||
//_paint.Typeface = owner.theme.uiFontName;
|
||||
_paint.IsAntialias = true;
|
||||
}
|
||||
|
||||
public SkiaChartsBackend(ChartsCanvas owner, ChartCanvasRenderer renderer) : base(owner, renderer) { }
|
||||
|
||||
public void Dispose() {
|
||||
_canvas?.Dispose();
|
||||
_paint?.Dispose();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.SceneGraph;
|
||||
using Avalonia.Skia;
|
||||
using SkiaSharp;
|
||||
using SomeChartsUi.elements.other;
|
||||
using SomeChartsUi.themes.colors;
|
||||
using SomeChartsUi.ui;
|
||||
using SomeChartsUi.ui.canvas;
|
||||
using SomeChartsUi.ui.canvas.controls;
|
||||
using SomeChartsUi.ui.elements;
|
||||
using SomeChartsUi.ui.layers;
|
||||
using SomeChartsUi.utils.vectors;
|
||||
using SomeChartsUiAvalonia.backends;
|
||||
using SomeChartsUiAvalonia.utils;
|
||||
|
||||
namespace SomeChartsUiAvalonia.controls;
|
||||
|
||||
public class AvaloniaChartsCanvas : Panel {
|
||||
public ChartsCanvas canvas = CreateCanvas();
|
||||
|
||||
public TimeSpan zoomUpdateTime;
|
||||
public TimeSpan panUpdateTime;
|
||||
public int updateInterval_hover = 16;
|
||||
public int updateInterval = 200;
|
||||
public string chartName = "???";
|
||||
public bool stopRender;
|
||||
private Timer? _updateTimer;
|
||||
private TimeSpan _prevUpdTime;
|
||||
|
||||
private static ChartsCanvas CreateCanvas() {
|
||||
ChartsCanvas canvas = new(new SkiaChartsBackend());
|
||||
canvas.AddLayer("bg");
|
||||
canvas.AddLayer("normal");
|
||||
canvas.AddLayer("top");
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
public AvaloniaChartsCanvas() {
|
||||
_updateTimer = new(_ => Update(), null, 0, 10);
|
||||
canvas.controller = new CanvasUiController(canvas);
|
||||
canvas.GetLayer("bg")!.background = color.purple;
|
||||
AddElement(new TestRenderable());
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e) {
|
||||
PointerPoint currentPoint = e.GetCurrentPoint(this);
|
||||
|
||||
PointerButtons buttons = default;
|
||||
if (currentPoint.Properties.IsLeftButtonPressed) buttons |= PointerButtons.left;
|
||||
if (currentPoint.Properties.IsRightButtonPressed) buttons |= PointerButtons.right;
|
||||
if (currentPoint.Properties.IsMiddleButtonPressed) buttons |= PointerButtons.middle;
|
||||
if (currentPoint.Properties.IsXButton1Pressed) buttons |= PointerButtons.forward;
|
||||
if (currentPoint.Properties.IsXButton2Pressed) buttons |= PointerButtons.backward;
|
||||
|
||||
keymods mods = default;
|
||||
if ((e.KeyModifiers & KeyModifiers.Shift) != 0) mods |= keymods.shift;
|
||||
if ((e.KeyModifiers & KeyModifiers.Control) != 0) mods |= keymods.ctrl;
|
||||
if ((e.KeyModifiers & KeyModifiers.Alt) != 0) mods |= keymods.alt;
|
||||
if ((e.KeyModifiers & KeyModifiers.Meta) != 0) mods |= keymods.super;
|
||||
|
||||
MouseState s = new(currentPoint.Position.ch(), float2.zero, buttons, mods, currentPoint.Pointer.Captured);
|
||||
|
||||
canvas.controller?.OnMouseDown(s);
|
||||
}
|
||||
protected override void OnPointerMoved(PointerEventArgs e) {
|
||||
PointerPoint currentPoint = e.GetCurrentPoint(this);
|
||||
|
||||
PointerButtons buttons = default;
|
||||
if (currentPoint.Properties.IsLeftButtonPressed) buttons |= PointerButtons.left;
|
||||
if (currentPoint.Properties.IsRightButtonPressed) buttons |= PointerButtons.right;
|
||||
if (currentPoint.Properties.IsMiddleButtonPressed) buttons |= PointerButtons.middle;
|
||||
if (currentPoint.Properties.IsXButton1Pressed) buttons |= PointerButtons.forward;
|
||||
if (currentPoint.Properties.IsXButton2Pressed) buttons |= PointerButtons.backward;
|
||||
|
||||
keymods mods = default;
|
||||
if ((e.KeyModifiers & KeyModifiers.Shift) != 0) mods |= keymods.shift;
|
||||
if ((e.KeyModifiers & KeyModifiers.Control) != 0) mods |= keymods.ctrl;
|
||||
if ((e.KeyModifiers & KeyModifiers.Alt) != 0) mods |= keymods.alt;
|
||||
if ((e.KeyModifiers & KeyModifiers.Meta) != 0) mods |= keymods.super;
|
||||
|
||||
MouseState s = new(currentPoint.Position.ch(), float2.zero, buttons, mods, currentPoint.Pointer.Captured);
|
||||
|
||||
canvas.controller?.OnMouseMove(s);
|
||||
}
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e) {
|
||||
PointerPoint currentPoint = e.GetCurrentPoint(this);
|
||||
|
||||
PointerButtons buttons = default;
|
||||
if (currentPoint.Properties.IsLeftButtonPressed) buttons |= PointerButtons.left;
|
||||
if (currentPoint.Properties.IsRightButtonPressed) buttons |= PointerButtons.right;
|
||||
if (currentPoint.Properties.IsMiddleButtonPressed) buttons |= PointerButtons.middle;
|
||||
if (currentPoint.Properties.IsXButton1Pressed) buttons |= PointerButtons.forward;
|
||||
if (currentPoint.Properties.IsXButton2Pressed) buttons |= PointerButtons.backward;
|
||||
|
||||
keymods mods = default;
|
||||
if ((e.KeyModifiers & KeyModifiers.Shift) != 0) mods |= keymods.shift;
|
||||
if ((e.KeyModifiers & KeyModifiers.Control) != 0) mods |= keymods.ctrl;
|
||||
if ((e.KeyModifiers & KeyModifiers.Alt) != 0) mods |= keymods.alt;
|
||||
if ((e.KeyModifiers & KeyModifiers.Meta) != 0) mods |= keymods.super;
|
||||
|
||||
MouseState s = new(currentPoint.Position.ch(), float2.zero, buttons, mods, currentPoint.Pointer.Captured);
|
||||
|
||||
canvas.controller?.OnMouseUp(s);
|
||||
}
|
||||
protected override void OnPointerWheelChanged(PointerWheelEventArgs e) {
|
||||
PointerPoint currentPoint = e.GetCurrentPoint(this);
|
||||
|
||||
PointerButtons buttons = default;
|
||||
if (currentPoint.Properties.IsLeftButtonPressed) buttons |= PointerButtons.left;
|
||||
if (currentPoint.Properties.IsRightButtonPressed) buttons |= PointerButtons.right;
|
||||
if (currentPoint.Properties.IsMiddleButtonPressed) buttons |= PointerButtons.middle;
|
||||
if (currentPoint.Properties.IsXButton1Pressed) buttons |= PointerButtons.forward;
|
||||
if (currentPoint.Properties.IsXButton2Pressed) buttons |= PointerButtons.backward;
|
||||
|
||||
keymods mods = default;
|
||||
if ((e.KeyModifiers & KeyModifiers.Shift) != 0) mods |= keymods.shift;
|
||||
if ((e.KeyModifiers & KeyModifiers.Control) != 0) mods |= keymods.ctrl;
|
||||
if ((e.KeyModifiers & KeyModifiers.Alt) != 0) mods |= keymods.alt;
|
||||
if ((e.KeyModifiers & KeyModifiers.Meta) != 0) mods |= keymods.super;
|
||||
|
||||
MouseState s = new(currentPoint.Position.ch(), e.Delta.ch(), buttons, mods, currentPoint.Pointer.Captured);
|
||||
|
||||
canvas.controller?.OnMouseScroll(s);
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyEventArgs e) {
|
||||
// if (e.Key == Key.R) {
|
||||
// if ((e.KeyModifiers & KeyModifiers.Shift) != 0) ResetTransform();
|
||||
// else ResetXYZoom();
|
||||
// }
|
||||
//
|
||||
// if (e.Key == Key.T) ToggleTheme();
|
||||
//
|
||||
// if (e.Key == Key.P) {
|
||||
// UpdateTransformAnimation();
|
||||
// using var img = RenderImage();
|
||||
// using var data = img.Encode(SKEncodedImageFormat.Png, 100);
|
||||
//
|
||||
// using FileStream fs = new(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + $"/SomeChartsSnapshot_{new Random().Next(100_000, 999_999):X}.png", FileMode.Create);
|
||||
// data.SaveTo(fs);
|
||||
// Console.WriteLine("aaaa");
|
||||
// }
|
||||
//
|
||||
// if (e.Key == Key.W) positionWithoutAnim.Y -= 100 / scale.Y;
|
||||
// if (e.Key == Key.S) positionWithoutAnim.Y += 100 / scale.Y;
|
||||
// if (e.Key == Key.A) positionWithoutAnim.X += 100 / scale.X;
|
||||
// if (e.Key == Key.D) positionWithoutAnim.X -= 100 / scale.X;
|
||||
}
|
||||
|
||||
public void Rebuild() {
|
||||
canvas.transform.screenBounds = Bounds.ch();
|
||||
canvas.transform.Update();
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
private void Update() {
|
||||
try {
|
||||
if (stopRender || !CheckUpdateDelay()) return;
|
||||
//UpdateAnim();
|
||||
Rebuild();
|
||||
_prevUpdTime = DateTime.Now.TimeOfDay;
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckUpdateDelay() {
|
||||
if (Environment.HasShutdownStarted) {
|
||||
_updateTimer = null;
|
||||
stopRender = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
var now = DateTime.Now.TimeOfDay;
|
||||
var maxDiff = TimeSpan.FromMilliseconds(IsPointerOver ? updateInterval_hover : updateInterval);
|
||||
return now - _prevUpdTime >= maxDiff;
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context) {
|
||||
canvas.transform.screenBounds = Bounds.ch();
|
||||
//renderer!.bounds = Bounds;
|
||||
//renderer.position = position;
|
||||
//renderer.scale = scale;
|
||||
//renderer.theme = theme;
|
||||
context.Custom(new CustomRender(canvas, Bounds));
|
||||
}
|
||||
|
||||
public SKImage RenderImage() => throw new NotImplementedException();
|
||||
// SKImageInfo info = new((int)Bounds.Width, (int)Bounds.Height);
|
||||
//
|
||||
// using var surf = SKSurface.Create(info);
|
||||
//
|
||||
// var canvas = surf.Canvas;
|
||||
// canvas.Scale(1, -1);
|
||||
// canvas.Translate(0, (float)-Bounds.Height);
|
||||
// renderer!.Render();
|
||||
// canvas.DrawBitmap(renderer.snapshot, renderer.bounds);
|
||||
// return surf.Snapshot();
|
||||
public void AddElement(RenderableBase el, string layer = "normal") {
|
||||
(canvas.GetLayer(layer) ?? canvas.GetLayer(1)).AddElement(el);
|
||||
}
|
||||
|
||||
public void RemoveElement(RenderableBase el, string layer = "normal") {
|
||||
(canvas.GetLayer(layer) ?? canvas.GetLayer(1)).RemoveElement(el);
|
||||
}
|
||||
|
||||
private class CustomRender : ICustomDrawOperation {
|
||||
private readonly ChartsCanvas _owner;
|
||||
public CustomRender(ChartsCanvas owner, Rect bounds) {
|
||||
_owner = owner;
|
||||
Bounds = bounds;
|
||||
}
|
||||
public Rect Bounds { get; }
|
||||
public void Dispose() { }
|
||||
public bool HitTest(Point p) => Bounds.Contains(p);
|
||||
public bool Equals(ICustomDrawOperation? other) => false;
|
||||
|
||||
public void Render(IDrawingContextImpl context) {
|
||||
((SkiaChartsBackend)_owner.renderer.backend).SetRenderingVariables(context);
|
||||
//((ISkiaDrawingContextImpl) context).SkCanvas.Clear();
|
||||
foreach (CanvasLayer layer in _owner.renderer!.layers)
|
||||
layer.Render();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using Avalonia;
|
||||
using SkiaSharp;
|
||||
using SomeChartsUi.themes.colors;
|
||||
using SomeChartsUi.utils.rects;
|
||||
|
@ -6,12 +7,15 @@ using SomeChartsUi.utils.vectors;
|
|||
namespace SomeChartsUiAvalonia.utils;
|
||||
|
||||
public static class SkiaChartsUtils {
|
||||
public static SKRect sk(this rect v) => new(v.left, v.bottom, v.right, v.top); // skia using inverted y axis, so swap bottom and top
|
||||
public static rect ch(this SKRect v) => new(v.Left, v.Bottom, v.Right, v.Top); // skia using inverted y axis, so swap bottom and top
|
||||
public static SKRect sk(this rect v) => new(v.left, v.bottom, v.right, v.top); // skia using inverted y axis, so swap bottom and top
|
||||
public static rect ch(this SKRect v) => new(v.Left, v.Bottom, v.Right, v.Top); // skia using inverted y axis, so swap bottom and top
|
||||
public static rect ch(this Rect v) => new((float)v.Left, (float) v.Bottom, (float)v.Right, (float)v.Top);// skia using inverted y axis, so swap bottom and top
|
||||
|
||||
public static SKColor sk(this color v) => new(v.raw);
|
||||
public static color ch(this SKColor v) => new(v.Red, v.Green, v.Blue, v.Alpha);
|
||||
|
||||
public static SKPoint sk(this float2 v) => new(v.x, v.y);
|
||||
public static float2 ch(this SKPoint v) => new(v.X, v.Y);
|
||||
public static float2 ch(this Point v) => new((float)v.X, (float)v.Y);
|
||||
public static float2 ch(this Vector v) => new((float)v.X, (float)v.Y);
|
||||
}
|
Загрузка…
Ссылка в новой задаче