1 /*
2 * Copyright (c) 2004-2008 Hypertriton, Inc. <http://hypertriton.com/>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23 * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 /*
27 * Circular arc element.
28 */
29
30 #include <agar/core/core.h>
31 #include <agar/gui/widget.h>
32 #include <agar/gui/primitive.h>
33 #include <agar/gui/numerical.h>
34 #include <agar/gui/iconmgr.h>
35 #include <agar/vg/vg.h>
36 #include <agar/vg/vg_view.h>
37 #include <agar/vg/icons.h>
38
39 static void
Init(void * p)40 Init(void *p)
41 {
42 VG_Arc *va = p;
43
44 va->p = NULL;
45 va->r = 0.5f;
46 va->a1 = 0.0f;
47 va->a2 = 360.0f;
48 }
49
50 static int
Load(void * p,AG_DataSource * ds,const AG_Version * ver)51 Load(void *p, AG_DataSource *ds, const AG_Version *ver)
52 {
53 VG_Arc *va = p;
54
55 if ((va->p = VG_ReadRef(ds, va, "Point")) == NULL) {
56 return (-1);
57 }
58 va->r = AG_ReadFloat(ds);
59 va->a1 = AG_ReadFloat(ds);
60 va->a2 = AG_ReadFloat(ds);
61 return (0);
62 }
63
64 static void
Save(void * p,AG_DataSource * ds)65 Save(void *p, AG_DataSource *ds)
66 {
67 VG_Arc *va = p;
68
69 VG_WriteRef(ds, va->p);
70 AG_WriteFloat(ds, va->r);
71 AG_WriteFloat(ds, va->a1);
72 AG_WriteFloat(ds, va->a2);
73 }
74
75 static void
Draw(void * p,VG_View * vv)76 Draw(void *p, VG_View *vv)
77 {
78 VG_Arc *va = p;
79 int a1 = (int)va->a1;
80 int a2 = (int)va->a2;
81 long r = (long)va->r;
82 int x, y, xPos, yPos;
83 int xPrev = 0, yPrev = 0;
84 VG_Vector vCenter = VG_Pos(va->p);
85 AG_Color c = VG_MapColorRGB(VGNODE(va)->color);
86 int a;
87
88 VG_GetViewCoords(vv, vCenter, &xPos, &yPos);
89
90 while (a2 < a1) {
91 a2 += 360;
92 }
93 for (a = a1; a <= a2; a++) {
94 x = ((long)vg_cos_tbl[a % 360]*(long)r/1024) + xPos;
95 y = ((long)vg_sin_tbl[a % 360]*(long)r/1024) + yPos;
96 if (a != a1) {
97 AG_DrawLine(vv, xPrev, yPrev, x, y, c);
98 }
99 xPrev = x;
100 yPrev = y;
101 }
102 }
103
104 static void
Extent(void * p,VG_View * vv,VG_Vector * a,VG_Vector * b)105 Extent(void *p, VG_View *vv, VG_Vector *a, VG_Vector *b)
106 {
107 VG_Arc *va = p;
108 VG_Vector vCenter = VG_Pos(va->p);
109
110 a->x = vCenter.x - va->r;
111 a->y = vCenter.y - va->r;
112 b->x = vCenter.x + va->r;
113 b->y = vCenter.y + va->r;
114 }
115
116 static float
PointProximity(void * p,VG_View * vv,VG_Vector * vPt)117 PointProximity(void *p, VG_View *vv, VG_Vector *vPt)
118 {
119 VG_Arc *va = p;
120 VG_Vector vCenter = VG_Pos(va->p);
121 float a1 = VG_Radians(va->a1);
122 float a2 = VG_Radians(va->a2);
123 float d, theta;
124
125 theta = Atan2(vPt->y - vCenter.y,
126 vPt->x - vCenter.x);
127 if (theta < a1) {
128 theta = a1;
129 } else if (theta > a2) {
130 theta = a2;
131 }
132 d = VG_Distance(vCenter, *vPt) - va->r;
133 vPt->x = vCenter.x + va->r*Cos(theta);
134 vPt->y = vCenter.y + va->r*Sin(theta);
135 return (d);
136 }
137
138 static void
Delete(void * p)139 Delete(void *p)
140 {
141 VG_Arc *va = p;
142
143 if (VG_DelRef(va, va->p) == 0)
144 VG_Delete(va->p);
145 }
146
147 static void
Move(void * p,VG_Vector vCurs,VG_Vector vRel)148 Move(void *p, VG_Vector vCurs, VG_Vector vRel)
149 {
150 VG_Arc *va = p;
151
152 va->r = VG_Distance(VG_Pos(va->p), vCurs);
153 }
154
155 static void *
Edit(void * p,VG_View * vv)156 Edit(void *p, VG_View *vv)
157 {
158 VG_Arc *va = p;
159 AG_Box *box = AG_BoxNewVert(NULL, AG_BOX_EXPAND);
160
161 AG_NumericalNewFlt(box, 0, NULL, _("Radius: "), &va->r);
162 AG_NumericalNewFlt(box, 0, NULL, _("Start angle: "), &va->a1);
163 AG_NumericalNewFlt(box, 0, NULL, _("End angle: "), &va->a2);
164
165 return (box);
166 }
167
168 VG_NodeOps vgArcOps = {
169 N_("Arc"),
170 &vgIconBezier,
171 sizeof(VG_Arc),
172 Init,
173 NULL, /* destroy */
174 Load,
175 Save,
176 Draw,
177 Extent,
178 PointProximity,
179 NULL, /* lineProximity */
180 Delete,
181 Move,
182 Edit
183 };
184