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