/* * Copyright (c) 2007-2023 Julien Nadeau Carriere * * 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. */ /* * Generic selection tool for sketch editor. */ #include #include "sk.h" #include "sk_gui.h" typedef struct sk_select_tool { SK_Tool tool; Uint flags; #define SELECT_POINTS 0x01 #define SELECT_LINES 0x02 #define SELECT_ARCS 0x04 int moving; } SK_SelectTool; static void ToolInit(void *_Nonnull p) { SK_SelectTool *t = p; t->flags = SELECT_POINTS|SELECT_LINES|SELECT_ARCS; t->moving = 0; } static int ToolMouseMotion(void *_Nonnull p, M_Vector3 pos, M_Vector3 vel) { SK_SelectTool *t = p; SK_View *skv = SKTOOL(t)->skv; SK *sk = skv->sk; M_Vector3 vC; SK_Node *node, *oNode; const int btnState = WIDGET(skv)->drv->mouse->btnState; int update = 0; Uint i; if (!t->moving) return (0); TAILQ_FOREACH(node, &sk->nodes, nodes) { if (node->flags & SK_NODE_MOUSEOVER) { node->flags &= ~(SK_NODE_MOUSEOVER); SK_NodeRedraw(node, skv); } node->flags &= ~(SK_NODE_MOVED); } if ((node = SK_ProximitySearch(sk, "Point", &pos, &vC, NULL)) != NULL && M_VecDistance3p(&pos, &vC) < skv->rSnap) { node->flags |= SK_NODE_MOUSEOVER; SK_NodeRedraw(node, skv); } else { if ((node = SK_ProximitySearch(sk, NULL, &pos, &vC, NULL)) != NULL) { node->flags |= SK_NODE_MOUSEOVER; SK_NodeRedraw(node, skv); } } /* Move selected elements. */ if (btnState & AG_MOUSE_LEFT) { TAILQ_FOREACH(node, &sk->nodes, nodes) { if (node->flags & (SK_NODE_MOVED|SK_NODE_FIXED| SK_NODE_KNOWN)) { continue; } if (node->flags & SK_NODE_SELECTED && node->ops->move != NULL) { if (node->ops->move(node, &pos, &vel) == 1) { update = 1; } node->flags |= SK_NODE_MOVED; TAILQ_FOREACH(oNode, &sk->nodes, nodes) { for (i = 0; i < oNode->nRefNodes; i++) { if (oNode->refNodes[i] != node) continue; oNode->flags |= SK_NODE_MOVED; } } } } } if (update) { SK_Update(sk); } return (0); } static int ToolMouseButtonDown(void *_Nonnull pTool, M_Vector3 pos, int btn) { SK_SelectTool *t = pTool; SK_View *skv = SKTOOL(t)->skv; SK *sk = skv->sk; SK_Node *node; M_Vector3 vC; int ctrlMode; if (btn != AG_MOUSE_LEFT) { return (0); } t->moving = 1; if (!(ctrlMode = (AG_GetModState(skv) & AG_KEYMOD_CTRL))) { TAILQ_FOREACH(node, &sk->nodes, nodes) { node->flags &= ~(SK_NODE_SELECTED); SK_NodeRedraw(node, skv); } } /* Give point proximity more weight than other entities. */ if ((node = SK_ProximitySearch(sk, "Point", &pos, &vC, NULL)) == NULL || M_VecDistance3p(&pos, &vC) >= skv->rSnap) { if ((node = SK_ProximitySearch(sk, NULL, &pos, &vC, NULL)) == NULL) return (0); } if (ctrlMode && node->flags & SK_NODE_SELECTED) { node->flags &= ~SK_NODE_SELECTED; } else { node->flags |= SK_NODE_SELECTED; } SK_NodeRedraw(node, skv); return (1); } static int ToolMouseButtonUp(void *_Nonnull pTool, M_Vector3 pos, int btn) { SK_SelectTool *t = pTool; if (btn == AG_MOUSE_LEFT) { t->moving = 0; } return (0); } static void ToolEdit(void *_Nonnull p, void *_Nonnull box) { SK_SelectTool *t = p; static const AG_FlagDescr flagDescr[] = { { SELECT_POINTS, N_("Select Points"), 1 }, { SELECT_LINES, N_("Select Lines"), 1 }, { SELECT_ARCS, N_("Select Arcs"), 1 }, { 0, NULL, 0 } }; AG_CheckboxSetFromFlags(box, 0, &t->flags, flagDescr); } SK_ToolOps skSelectToolOps = { N_("Select"), N_("Select and move sketch items"), NULL, sizeof(SK_SelectTool), 0, ToolInit, NULL, /* destroy */ ToolEdit, ToolMouseMotion, ToolMouseButtonDown, ToolMouseButtonUp, NULL, /* keydown */ NULL /* keyup */ };