/* interfaceDeclaration.C */ #include "vrml.H" #include "error.H" /* ********************* field/event redirections ********************** */ // This struct stores what interface field/exposedField/eventIn/eventOut of what // node a PROTO scenegraph node interface field/exposedField/.... is a synonym for // as specified with IS statement in VRML input file. class redirection { SFNode *node; interfaceDeclaration *decl; // member of the interface of the node above public: inline redirection(SFNode *n, interfaceDeclaration *d) { node=n; decl=d; } inline operator interfaceDeclaration*() { return decl; } // resolves a redirection void set_node(SFNode *n) { int idx = decl - node->interface; node = n; decl = &(node->interface[idx]); } friend ostream& operator<<(ostream& s, redirection& v) { return s << " -> " << v.node->name() << " " << v.decl->Id; } }; char* interfaceKindName(const interfaceKind& kind) { return (kind == kdummy ? "dummy" : (kind == keventIn ? "eventIn" : (kind == kexposedField ? "exposedField" : (kind == kfield? "field" : (kind == keventOut ? "eventOut" : "invalid"))))); } void interfaceDeclaration::construct(interfaceKind k, fieldType t, char *id, fieldValue val, class redirection *r) { kind = k; type = t; Id = id; value = val; if (type != fieldType(value)) Fatal(-1, "interfaceDeclaration::construct", "value type '%s' doesn't match %s type '%s'", fieldTypeName(fieldType(value)), interfaceKindName(kind), fieldTypeName(type)); checkval = 0; clock = -1; ref = r ? new redirection(*r) : 0; nodeClassId = 0; nodeClass = 0; } void interfaceDeclaration::destruct(void) { if (ref) delete ref; } // value will be new fieldValue object of given type interfaceDeclaration::interfaceDeclaration(interfaceKind k, fieldType t, char* id) { construct(k, t, id, fieldValue(t), 0); } interfaceDeclaration::interfaceDeclaration(interfaceKind k, fieldType t, char* id, fieldValue val) { construct(k, t, id, val, 0); } interfaceDeclaration::interfaceDeclaration(const interfaceDeclaration& src) { construct(src.kind, src.type, src.Id, src.value, src.ref); checkval = src.checkval; nodeClassId = src.nodeClassId; nodeClass = src.nodeClass; } interfaceDeclaration& interfaceDeclaration::operator=(const interfaceDeclaration& src) { if (this != &src) { destruct(); construct(src.kind, src.type, src.Id, src.value, src.ref); checkval = src.checkval; nodeClassId = src.nodeClassId; nodeClass = src.nodeClass; } return *this; } interfaceDeclaration::~interfaceDeclaration(void) { destruct(); } ostream& operator<<(ostream& s, interfaceDeclaration& v) { s << v.kind << '\t' << v.type << '\t' << v.Id << '\t'; if (v.kind==kfield || v.kind==kexposedField) s << v.value; if (v.ref) { s << *v.ref << " clock=" << v.clock << ", ref clock=" << ((interfaceDeclaration *)*v.ref)->clock; if (v.clock != ((interfaceDeclaration *)*v.ref)->clock) s << " (to be updated)"; } return s << '\n'; } void interfaceDeclaration::redirect(SFNode *node, interfaceDeclaration *decl) { if (ref) ref->set_node(node); else ref = new redirection(node, decl); decl = (interfaceDeclaration *)(*ref); value.assign_or_duplicate_if_nil(decl->value); clock = decl->clock; } void interfaceDeclaration::initialize(fieldValue& val) { value.assign_or_duplicate_if_nil(val); clock = 0; if (checkval && !checkval(value)) return; // value rejected } void interfaceDeclaration::instantiate(Proto *master) { switch (kind) { case kfield: case kexposedField: if (ref) redirect(master); else if ((void*)value!=0) // will be nil for unresolved EXTERNPROTO's value.instantiate(master); break; default: break; } } void interfaceDeclaration::assign(fieldValue& val) { value.assign(val); clock++; if (checkval && !checkval(value)) return; // value rejected if (ref) ((interfaceDeclaration *)ref)->assign(val); } void interfaceDeclaration::do_synchronize(void) { interfaceDeclaration *refdecl = (interfaceDeclaration *)*ref; if (refdecl->clock != clock) { value.assign(refdecl->value); clock = refdecl->clock; } }