Skip to content

Commit

Permalink
Add rounding to offset and scale of the snarl view to combat rounding…
Browse files Browse the repository at this point in the history
… errors
  • Loading branch information
zakarumych committed Jan 27, 2025
1 parent ba6a91c commit a42ca64
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 24 deletions.
13 changes: 7 additions & 6 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,11 +713,12 @@ impl<T> Snarl<T> {
if viewport.contains(hover_pos) && ui.rect_contains_pointer(viewport) =>
{
if input.zoom_delta != 1.0 {
let new_scale = (snarl_state.scale()
* input.zoom_delta.powf(style.get_scale_velocity()))
.clamp(style.get_min_scale(), style.get_max_scale());

snarl_state.set_scale(new_scale);
snarl_state.zoom_delta(
input.zoom_delta,
style.get_scale_velocity(),
style.get_min_scale(),
style.get_max_scale(),
);
}
}
_ => {}
Expand Down Expand Up @@ -1472,7 +1473,7 @@ impl<T> Snarl<T> {
.map(|idx| OutPin::new(self, OutPinId { node, output: idx }))
.collect::<Vec<_>>();

let node_pos = snarl_state.graph_pos_to_screen(pos, viewport);
let node_pos = snarl_state.graph_pos_to_screen(pos, viewport).round();

// Generate persistent id for the node.
let node_id = snarl_id.with(("snarl-node", node));
Expand Down
50 changes: 32 additions & 18 deletions src/ui/state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::hash::Hash;

use egui::{ahash::HashSet, style::Spacing, Context, Id, Pos2, Rect, Ui, Vec2};
use egui::{ahash::HashSet, style::Spacing, vec2, Context, Id, Pos2, Rect, Ui, Vec2};

use crate::{InPinId, NodeId, OutPinId, Snarl};

Expand Down Expand Up @@ -66,7 +66,8 @@ impl NodeState {
egui::vec2(
self.size.x,
f32::max(self.header_height, self.size.y * openness),
),
)
.round(),
)
}

Expand Down Expand Up @@ -338,36 +339,48 @@ impl SnarlState {
}
}

pub fn set_offset(&mut self, offset: Vec2) {
if self.offset != offset {
self.offset = offset;
self.dirty = true;
}
}

#[inline(always)]
pub fn pan(&mut self, delta: Vec2) {
self.offset += delta;
self.dirty = true;
if delta != Vec2::ZERO {
self.offset += delta;
self.dirty = true;
}
}

#[inline(always)]
pub const fn scale(&self) -> f32 {
self.scale
pub fn scale(&self) -> f32 {
rounding(self.scale)
}

#[inline(always)]
pub const fn offset(&self) -> Vec2 {
self.offset
pub fn offset(&self) -> Vec2 {
self.offset.round()
}

#[inline(always)]
pub fn set_scale(&mut self, scale: f32) {
self.target_scale = scale;
pub fn zoom_delta(&mut self, zoom_delta: f32, velocity: f32, min: f32, max: f32) {
if zoom_delta == 1.0 {
return;
}
self.target_scale = (self.target_scale * zoom_delta.powf(velocity)).clamp(min, max);
self.dirty = true;
}

#[inline(always)]
pub fn screen_pos_to_graph(&self, pos: Pos2, viewport: Rect) -> Pos2 {
(pos + self.offset - viewport.center().to_vec2()) / self.scale
(pos + self.offset() - viewport.center().to_vec2()) / self.scale()
}

#[inline(always)]
pub fn graph_pos_to_screen(&self, pos: Pos2, viewport: Rect) -> Pos2 {
pos * self.scale - self.offset + viewport.center().to_vec2()
pos * self.scale() - self.offset() + viewport.center().to_vec2()
}

#[inline(always)]
Expand All @@ -393,7 +406,7 @@ impl SnarlState {

#[inline(always)]
pub fn screen_vec_to_graph(&self, size: Vec2) -> Vec2 {
size / self.scale
size / self.scale()
}

// #[inline(always)]
Expand Down Expand Up @@ -524,11 +537,6 @@ impl SnarlState {
self.dirty = true;
}

pub fn set_offset(&mut self, offset: Vec2) {
self.offset = offset;
self.dirty = true;
}

pub fn selected_nodes(&self) -> &[NodeId] {
&self.selected_nodes
}
Expand Down Expand Up @@ -634,3 +642,9 @@ impl<T> Snarl<T> {
})
}
}

fn rounding(scale: f32) -> f32 {
// Assuming IEEE 754 binary32 format.

f32::from_bits(scale.to_bits() & 0xFFFFF000)
}

0 comments on commit a42ca64

Please sign in to comment.