1=pod
2
3=head1 NAME
4
5examples/spline.pl - A spline demo
6
7=head1 FEATURES
8
9Demonstrates parabolic splines as graphic primitives.
10The points arount the filled shapes are spline vertexes,
11which are dragable by the mouse.
12
13Using L<Prima::Drawable::CurvedText>.
14
15=cut
16
17use strict;
18use warnings;
19use Prima qw(Application Drawable::CurvedText);
20
21my @bounds;
22my @points = (
23	10, 10,
24	130, 30,
25	20, 20,
26	20, 300,
27	50, 300,
28);
29my @vectors = (
30	2, 2,
31	2, 1,
32	-1, -1,
33	-1, 3,
34	-2, 2,
35);
36my @rgb = (
37	0,
38	0,
39	0,
40);
41my @rgb_vectors = (
42	-1.04,
43	1.79,
44	1.38,
45);
46my $capture;
47my $aperture = 6 * $::application-> uiScaling;
48
49my $w = Prima::MainWindow-> create(
50	text => 'Spline demo',
51	antialias => (( $ARGV[0] // '' ) eq 'aa'),
52	backColor => cl::Black,
53	buffered => 1,
54	onPaint => sub {
55		my ( $self, $canvas) = @_;
56		$canvas-> clear;
57
58		my $spline = $canvas-> render_spline( [ @points, @points[0,1]]);
59		$canvas-> fillpoly( $spline);
60		if ( defined $capture) {
61			$canvas-> fill_ellipse(
62				$points[$capture], $points[$capture+1],
63				$aperture, $aperture
64			);
65		}
66
67		$canvas-> rop( rop::XorPut);
68		$canvas-> curved_text_out("Hello, world!", $spline);
69
70		my $i;
71		for ( $i = 0; $i < @points; $i+=2) {
72			$canvas-> ellipse(
73				$points[$i], $points[$i+1],
74				$aperture, $aperture
75			);
76		}
77	},
78	onSize => sub {
79		my ( $self, $ox, $oy, $x, $y) = @_;
80		@bounds = ( $x, $y);
81	},
82	onMouseDown => sub {
83		my ( $self, $btn, $mod, $x, $y) = @_;
84		my $i;
85		$capture = undef;
86		for ( $i = 0; $i < @points; $i+=2) {
87			if ( $points[$i] > $x - $aperture && $points[$i] < $x + $aperture &&
88				$points[$i+1] > $y - $aperture && $points[$i+1] < $y + $aperture) {
89				$capture = $i;
90				last;
91			}
92		}
93	},
94	onMouseUp => sub {
95		undef $capture;
96	},
97	onMouseMove => sub {
98		my ( $self, $btn, $x, $y) = @_;
99		return unless defined $capture;
100		$points[$capture] = $x if $x >= 0 && $x < $bounds[0];
101		$points[$capture+1] = $y if $y >= 0 && $y < $bounds[1];
102	},
103);
104
105$w-> insert( Timer =>
106	timeout => 50,
107	onTick => sub {
108		my $i;
109		my $idx = 0;
110		for ( $i = 0; $i < @points; $i++) {
111			next if defined $capture && ( $capture == $i || $capture == $i - 1);
112			$points[$i] += $vectors[$i];
113			if ( $points[$i] < 0) {
114				$points[$i] *= -1;
115				$vectors[$i] *= -1;
116			} elsif ( $points[$i] >= $bounds[$idx]) {
117				$points[$i] = $bounds[$idx] * 2 - $points[$i];
118				$vectors[$i] *= -1;
119			}
120			$idx = ($idx ? 0 : 1);
121		}
122
123		for ( $i = 0; $i < 3; $i++) {
124			$rgb[$i] += $rgb_vectors[$i];
125			if ( $rgb[$i] < 0) {
126				$rgb_vectors[$i] *= -1;
127				$rgb[$i] *= -1;
128			} elsif ( $rgb[$i] > 255) {
129				$rgb[$i] = 511 - $rgb[$i];
130				$rgb_vectors[$i] *= -1;
131			}
132		}
133		$w-> color( int($rgb[2]) + int($rgb[1]) * 256 + int($rgb[0]) * 65536);
134	},
135)-> start;
136
137run Prima;
138