lib/glimmer/libui/perfect_shaped.rb
require 'forwardable'
module Glimmer
module LibUI
# GUI View objects that can be represented by PerfectShape objects
module PerfectShaped
extend Forwardable
def_delegators :perfect_shape,
:min_x, :min_y, :max_x, :max_y, :center_point, :center_x, :center_y
# Returns if shape contains point on the inside when outline is false (default)
# or if point is on the outline when outline is true
# distance_tolerance is used when outline is true to enable a fuzz factor in
# determining if a point lies on the outline (e.g. makes it easier to select
# a shape by mouse)
def contain?(*point, outline: false, distance_tolerance: 0)
# TODO inverse transform point with `uiDrawMatrixTransformPoint` before checking containment
perfect_shape&.contain?(*point, outline: outline, distance_tolerance: distance_tolerance)
end
# Returns if shape includes point on the inside when filled
# or if shape includes point on the outline when stroked
def include?(*point)
if respond_to?(:fill) && fill.empty?
# TODO check if distance_tolerance should be half the thickness in case it is checked against both sides of out and in
contain?(*point, outline: true, distance_tolerance: ((stroke[:thickness] || 1) - 1))
else
contain?(*point)
end
end
# Returns bounding box Array consisting of
# [minx, miny, width, height]
def bounding_box
perfect_shape_bounding_box = perfect_shape&.bounding_box
return if perfect_shape_bounding_box.nil?
[
perfect_shape_bounding_box.x,
perfect_shape_bounding_box.y,
perfect_shape_bounding_box.width,
perfect_shape_bounding_box.height,
]
end
# moves by x delta and y delta. Classes must implement
def move_by(x_delta, y_delta)
# No Op
end
alias translate move_by
def move(x, y)
x_delta = x - perfect_shape.min_x
y_delta = y - perfect_shape.min_y
move_by(x_delta, y_delta)
end
# Returns PerfectShape object matching this shape to enable
# executing computational geometry algorithms
#
# Including classes must implement
def perfect_shape
# No Op
end
# Returns PerfectShape object dependencies to determine if the PerfectShape
# object changed or not for caching purposes.
# Every shape/path implements this uniquely for its own PerfectShape attribute dependencies
def perfect_shape_dependencies
# No Op
end
end
end
end