/* * Copyright (c) 2005-2010 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. */ /* * Generic node class. */ #include #include #include "sg.h" #include "sg_gui.h" #include static void Attached(AG_Event *event) { void *parent = AG_SENDER(); SG_Node *node = AG_SELF(); SG *sg = NULL; if (AG_OfClass(parent, "SG:*")) { sg = (SG *)parent; } else if (AG_OfClass(parent, "SG_Node:*")) { sg = SGNODE(parent)->sg; } else { AG_FatalError("Invalid SG_Node parent"); } AG_ObjectLock(sg); TAILQ_INSERT_TAIL(&sg->nodes, node, nodes); node->sg = sg; AG_ObjectUnlock(sg); } static void Detached(AG_Event *event) { void *parent = AG_SENDER(); SG_Node *node = AG_SELF(); SG *sg = NULL; if (AG_OfClass(parent, "SG:*")) { sg = (SG *)parent; } else if (AG_OfClass(parent, "SG_Node:*")) { sg = SGNODE(parent)->sg; } else { AG_FatalError("Invalid SG_Node parent"); } AG_ObjectLock(sg); TAILQ_REMOVE(&sg->nodes, node, nodes); node->sg = NULL; AG_ObjectUnlock(sg); } static void Init(void *obj) { SG_Node *node = obj; node->flags = 0; M_MatIdentity44v(&node->T); AG_SetEvent(node, "attached", Attached, NULL); AG_SetEvent(node, "detached", Detached, NULL); } static int Load(void *obj, AG_DataSource *buf, const AG_Version *ver) { SG_Node *node = obj; node->flags = (Uint)AG_ReadUint32(buf); M_ReadMatrix44v(buf, &node->T); return (0); } static int Save(void *obj, AG_DataSource *buf) { SG_Node *node = obj; AG_WriteUint32(buf, (Uint32)node->flags); M_WriteMatrix44(buf, &node->T); return (0); } static void * Edit(void *obj, SG_View *sgv) { SG_Node *node = obj; AG_Box *box; box = AG_BoxNewVert(NULL, AG_BOX_HFILL); AG_LabelNew(box, 0, _("Node Name: %s"), AGOBJECT(node)->name); return (box); } /* Generic edit() operation for node objects. */ void * SG_NodeEdit(void *obj) { SG_Node *node = obj; AG_Window *win; void *wEdit; AG_ObjectClass **hier; int i, nHier; win = AG_WindowNew(0); AG_WindowSetCaptionS(win, OBJECT(node)->name); if (AG_ObjectGetInheritHier(node, &hier, &nHier) != 0) { AG_FatalError(NULL); } for (i = 0; i < nHier; i++) { SG_NodeClass *nc = (SG_NodeClass *)hier[i]; if (!AG_ClassIsNamed(hier[i], "SG_Node:*") || nc->edit == NULL) continue; wEdit = nc->edit(node, NULL); if (wEdit != NULL && AG_OfClass(wEdit, "AG_Widget:*")) AG_ObjectAttach(win, wEdit); } Free(hier); return (win); } SG_NodeClass sgNodeClass = { { "SG_Node", sizeof(SG_Node), { 0,0 }, Init, NULL, /* free */ NULL, /* destroy */ Load, Save, SG_NodeEdit }, NULL, /* menuInstance */ NULL, /* menuClass */ NULL, /* draw */ NULL, /* intersect */ Edit };