mod carry;
mod resolve;
#[cfg(test)]
mod tests;
use super::*;
use crate::compositor::overlap::read::OverlapReadContext;
use crate::frame_loop::anim_style_for;
pub(crate) use crate::compositor::overlap::read::CollisionExtents;
pub(crate) use carry::carry_surface_non_overlap;
pub(crate) use resolve::{request_toplevel_resize, resolve_surface_overlap};
fn overlap_read_context(st: &Halley) -> OverlapReadContext<'_> {
OverlapReadContext {
field: &st.model.field,
monitor_state: &st.model.monitor_state,
interaction_state: &st.input.interaction_state,
spawn_state: &st.model.spawn_state,
render_state: &st.ui.render_state,
workspace_state: &st.model.workspace_state,
tuning: &st.runtime.tuning,
viewport: st.model.viewport,
camera_render_scale: st.camera_render_scale(),
}
}
#[inline]
fn clamp_speed(v: Vec2, max_speed: f32) -> Vec2 {
OverlapReadContext::clamp_speed(v, max_speed)
}
#[inline]
fn physics_damping_per_sec(st: &Halley) -> f32 {
overlap_read_context(st).physics_damping_per_sec()
}
#[inline]
fn physics_inv_mass(st: &Halley, id: NodeId, pinned: bool) -> f32 {
overlap_read_context(st).physics_inv_mass(id, pinned)
}
#[inline]
fn node_participates_in_overlap(st: &Halley, id: NodeId) -> bool {
overlap_read_context(st).node_participates_in_overlap(id)
}
pub(crate) fn non_overlap_gap_world(st: &Halley) -> f32 {
overlap_read_context(st).non_overlap_gap_world()
}
#[inline]
pub(crate) fn required_sep_x(
st: &Halley,
a_pos_x: f32,
a_ext: CollisionExtents,
b_pos_x: f32,
b_ext: CollisionExtents,
gap: f32,
) -> f32 {
overlap_read_context(st).required_sep_x(a_pos_x, a_ext, b_pos_x, b_ext, gap)
}
#[inline]
fn nodes_share_overlap_group(st: &Halley, a: NodeId, b: NodeId) -> bool {
overlap_read_context(st).nodes_share_overlap_group(a, b)
}
#[inline]
pub(crate) fn required_sep_y(
st: &Halley,
a_pos_y: f32,
a_ext: CollisionExtents,
b_pos_y: f32,
b_ext: CollisionExtents,
gap: f32,
) -> f32 {
overlap_read_context(st).required_sep_y(a_pos_y, a_ext, b_pos_y, b_ext, gap)
}
pub(super) fn carry_overlap_node_direct(st: &mut Halley, id: NodeId, to: Vec2) -> bool {
if st
.model
.field
.node(id)
.is_some_and(|node| node.kind == halley_core::field::NodeKind::Core)
{
st.model.field.carry_cluster_by_core(id, to)
} else {
st.model.field.carry(id, to)
}
}
pub(crate) fn surface_window_collision_extents(
st: &Halley,
n: &halley_core::field::Node,
) -> CollisionExtents {
overlap_read_context(st).surface_window_collision_extents(n)
}
pub(crate) fn spawn_obstacle_extents_for_node(
st: &Halley,
n: &halley_core::field::Node,
) -> CollisionExtents {
if n.kind == halley_core::field::NodeKind::Surface {
overlap_read_context(st).spawn_obstacle_extents_for_node(n)
} else {
collision_extents_for_node(st, n)
}
}
pub(crate) fn collision_extents_for_node(
st: &Halley,
n: &halley_core::field::Node,
) -> CollisionExtents {
let anim = anim_style_for(st, n.id, n.state.clone(), Instant::now());
match n.state {
halley_core::field::NodeState::Active => {
let basis = st
.model
.workspace_state
.last_active_size
.get(&n.id)
.copied()
.unwrap_or(n.intrinsic_size);
let s = OverlapReadContext::active_collision_scale(anim.scale, basis.x, basis.y);
let ext = overlap_read_context(st).surface_window_collision_extents(n);
CollisionExtents {
left: ext.left * s,
right: ext.right * s,
top: ext.top * s,
bottom: ext.bottom * s,
}
}
halley_core::field::NodeState::Node => {
overlap_read_context(st).node_collision_extents(n.intrinsic_size, &n.label, anim.scale)
}
halley_core::field::NodeState::Core => {
overlap_read_context(st).core_node_collision_extents()
}
halley_core::field::NodeState::Drifting => CollisionExtents::symmetric(n.footprint),
}
}
pub(crate) fn collision_size_for_node(st: &Halley, n: &halley_core::field::Node) -> Vec2 {
collision_extents_for_node(st, n).size()
}
pub(super) fn layout_collision_extents_for_node(
st: &Halley,
n: &halley_core::field::Node,
) -> CollisionExtents {
match n.state {
halley_core::field::NodeState::Node | halley_core::field::NodeState::Core => {
collision_extents_for_node(st, n)
}
_ => collision_extents_for_node(st, n),
}
}