123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- /* the way boxas align punchies
- */
- #include "common/sketchbook.hpp"
- constexpr float circle_radius = .12;
- constexpr float corner_radius = 14.f;
- constexpr float precision_mode_motion_scale = .01f;
- constexpr float2 half = float2::one(.5f);
- struct line
- {
- float2 start;
- float2 direction;
- };
- struct circle
- {
- float2 center;
- float radius;
- float magnitude() const;
- explicit operator range2f() const;
- bool contains(float2 point) const;
- };
- line l;
- circle c;
- bool precision_mode = false;
- float2* dragged_point = nullptr;
- float* dragged_radius = nullptr;
- circle* dragged_circle = nullptr;
- bool is_near(float2 corner, float2 position);
- sketch arrow(sketch s, float2 start, float2 end);
- void start(Program& program)
- {
- program.key_down = [](scancode code, keycode)
- {
- switch(code)
- {
- case scancode::lshift:
- case scancode::rshift:
- precision_mode = true;
- break;
- default: break;
- }
- };
- program.key_up = [&program](scancode code, keycode)
- {
- switch(code)
- {
- case scancode::leftbracket:
- case scancode::c:
- if(pressed(scancode::rctrl) || pressed(scancode::lctrl))
- case scancode::escape:
- program.end();
- break;
- case scancode::lshift:
- case scancode::rshift:
- precision_mode = false;
- break;
- default: break;
- }
- };
- program.mouse_down = [](float2 position, auto)
- {
- if(is_near(l.start + l.direction, position))
- dragged_point = &l.direction;
- else if(is_near(l.start, position))
- dragged_point = &l.start;
- else if(c.contains(position))
- dragged_circle = &c;
- };
- program.mouse_up = [](auto, auto)
- {
- dragged_point = nullptr;
- dragged_circle = nullptr;
- dragged_radius = nullptr;
- };
- program.mouse_move = [](auto, float2 motion)
- {
- if(precision_mode)
- motion *= precision_mode_motion_scale;
- if(dragged_circle)
- dragged_circle->center += motion;
- if(dragged_point)
- (*dragged_point) += motion;
- if(dragged_radius)
- (*dragged_radius) += motion.x();
- };
- program.draw_once = [](auto frame)
- {
- const float2 center = frame.size / 2;
- c.center = center;
- c.radius = frame.size.x() * circle_radius;
- l.start = center - 2 * c.radius;
- l.direction = float2::one(4 * c.radius);
- };
- program.draw_loop = [](auto frame, auto)
- {
- const float2 center_direction = c.center - l.start;
- bool itchin = center_direction(l.direction) < l.direction.quadrance();
- frame.begin_sketch()
- .rectangle(rect{ frame.size })
- .fill(0xffffff_rgb)
- ;
- geom::loop(frame.size/3, [&](auto i) {
- const float2 center_direction = c.center - i*3;
- const auto quadrance = l.direction.quadrance();
- auto normal = common::normalize(common::rotate(l.direction, common::protractor<>::tau(1/4.f)));
- bool itchin = center_direction(l.direction) < quadrance
- && center_direction(normal) < c.radius
- && center_direction(-normal) < c.radius
- ;
- frame.begin_sketch().ellipse(rect{float2::one(3), i*3}).fill(itchin ? 0xaa0000_rgb : 0xffffff_rgb);
- });
- frame.begin_sketch()
- .ellipse(range2f(c))
- .fill(itchin ? 0x00aa00_rgb : 0xaaaaaa_rgb)
- ;
- arrow(frame.begin_sketch(), l.start, l.start + l.direction)
- .line_width(1).outline(0x770077_rgb)
- ;
- frame.begin_sketch()
- .ellipse(rect{float2::one(corner_radius), l.start, half})
- .line_width(1).outline(0x555555_rgb)
- ;
- const float2 line_point = l.start + l.direction;
- frame.begin_sketch()
- .ellipse(rect{float2::one(corner_radius), line_point, half})
- .line_width(1).outline(0x555555_rgb)
- ;
- };
- }
- float circle::magnitude() const
- {
- return radius * radius;
- }
- circle::operator range2f() const
- {
- return {center - radius, center + radius};
- }
- bool circle::contains(float2 point) const
- {
- return (center - point).magnitude() < magnitude();
- }
- bool is_near(float2 corner, float2 position)
- {
- return circle{corner, corner_radius}.contains(position);
- }
- sketch arrow(sketch s, float2 start, float2 end)
- {
- float2 direction = end - start;
- float2 perpendicular = direction.mix<1,0>() * float2(-1.f,1.f);
- float2 shaft = start + direction * .8f;
- s.line(start, end);
- s.line(end, shaft + perpendicular * .1f);
- s.line(end, shaft - perpendicular * .1f);
- return s;
- }
|