/*
* Copyright (c) 2006-2007 Hypertriton, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Simple arc specified by a radius and two angles.
*/
#include
#include
#include "sk.h"
#include "sk_gui.h"
SK_Arc *
SK_ArcNew(void *pnode)
{
SK_Arc *arc;
arc = Malloc(sizeof(SK_Arc));
SK_ArcInit(arc, SK_GenNodeName(SKNODE(pnode)->sk, "Arc"));
SK_NodeAttach(pnode, arc);
return (arc);
}
void
SK_ArcInit(void *p, Uint name)
{
SK_Arc *arc = p;
SK_NodeInit(arc, &skArcOps, name, 0);
arc->color = M_ColorRGB(0.0, 1.0, 0.0);
arc->r = 0.0f;
arc->p = NULL;
arc->e1 = NULL;
arc->e2 = NULL;
}
int
SK_ArcLoad(SK *sk, void *p, AG_DataSource *buf)
{
SK_Arc *arc = p;
arc->color = M_ReadColor(buf);
arc->r = M_ReadReal(buf);
arc->p = SK_ReadRef(buf, sk, "Point");
arc->e1 = SK_ReadRef(buf, sk, "Point");
arc->e2 = SK_ReadRef(buf, sk, "Point");
if (arc->p == NULL) {
AG_SetError("Missing center point (%s)", AG_GetError());
return (-1);
}
if (arc->e1 == NULL || arc->e2 == NULL) {
AG_SetError("Missing endpoints (%s)", AG_GetError());
return (-1);
}
SK_NodeAddReference(arc, arc->p);
SK_NodeAddReference(arc, arc->e1);
SK_NodeAddReference(arc, arc->e2);
return (0);
}
int
SK_ArcSave(SK *sk, void *p, AG_DataSource *buf)
{
SK_Arc *arc = p;
M_WriteColor(buf, &arc->color);
M_WriteReal(buf, arc->r);
SK_WriteRef(buf, arc->p);
SK_WriteRef(buf, arc->e1);
SK_WriteRef(buf, arc->e2);
return (0);
}
void
SK_ArcDraw(void *p, SK_View *skv)
{
SK_Arc *arc = p;
M_Vector3 v = SK_Pos(arc->p);
M_Real i, incr;
if (arc->r < skv->wPixel) {
return;
}
incr = (2*M_PI)/10.0;
GL_Translatev(&v);
GL_Begin(GL_LINE_LOOP);
GL_Color3v(&arc->color);
for (i = 0.0; i < M_PI*2; i+=incr) {
GL_Vertex2(Cos(i)*arc->r,
Sin(i)*arc->r);
}
GL_End();
GL_Translate(M_VecFlip3(v));
}
M_Real
SK_ArcProximity(void *p, const M_Vector3 *v, M_Vector3 *vC)
{
/* TODO */
return (M_INFINITY);
}
void
SK_ArcColor(SK_Arc *arc, M_Color c)
{
arc->color = c;
}
SK_NodeOps skArcOps = {
"Arc",
sizeof(SK_Arc),
0,
SK_ArcInit,
NULL, /* destroy */
SK_ArcLoad,
SK_ArcSave,
SK_ArcDraw,
NULL, /* redraw */
NULL, /* edit */
SK_ArcProximity,
NULL, /* delete */
NULL, /* move */
NULL, /* constrained */
};
#ifdef EDITION
struct sk_arc_tool {
SK_Tool tool;
SK_Arc *cur_arc;
SK_Point *cur_e1;
};
static void
ToolInit(void *_Nonnull p)
{
struct sk_arc_tool *t = p;
t->cur_arc = NULL;
t->cur_e1 = NULL;
}
static int
ToolMouseMotion(void *_Nonnull p, M_Vector3 pos, M_Vector3 vel, int btn)
{
struct sk_arc_tool *t = p;
M_Vector3 vCenter;
if (t->cur_arc != NULL) {
vCenter = SK_Pos(t->cur_arc->p);
t->cur_arc->r = M_VecDistance3(vCenter, pos);
}
return (0);
}
static int
ToolMouseButtonDown(void *_Nonnull p, M_Vector3 pos, int btn)
{
struct sk_arc_tool *t = p;
SK *sk = SKTOOL(t)->skv->sk;
SK_Arc *arc;
if (btn != AG_MOUSE_LEFT)
return (0);
if (t->cur_arc == NULL) {
arc = SK_ArcNew(sk->root);
arc->p = SK_PointNew(sk->root);
SK_NodeAddReference(arc, arc->p);
SK_Translatev(arc->p, &pos);
t->cur_arc = arc;
} else {
arc = t->cur_arc;
if (t->cur_e1 == NULL) {
arc->e1 = SK_PointNew(sk->root);
SK_NodeAddReference(arc, arc->e1);
t->cur_e1 = arc->e1;
} else {
arc->e2 = SK_PointNew(sk->root);
SK_NodeAddReference(arc, arc->e2);
t->cur_e1 = NULL;
t->cur_arc = NULL;
}
}
SK_Update(sk);
return (1);
}
SK_ToolOps skArcToolOps = {
N_("Arc"),
N_("Insert an arc into the sketch"),
NULL,
sizeof(struct sk_arc_tool),
0,
ToolInit,
NULL, /* destroy */
NULL, /* edit */
ToolMouseMotion,
ToolMouseButtonDown,
NULL, /* buttonup */
NULL, /* keydown */
NULL /* keyup */
};
#endif /* EDITION */