00001 /*======================================================================= 00002 * Copyright 1991-1996, Silicon Graphics, Inc. 00003 * ALL RIGHTS RESERVED 00004 * 00005 * UNPUBLISHED -- Rights reserved under the copyright laws of the United 00006 * States. Use of a copyright notice is precautionary only and does not 00007 * imply publication or disclosure. 00008 * 00009 * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: 00010 * Use, duplication or disclosure by the Government is subject to restrictions 00011 * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights 00012 * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or 00013 * in similar or successor clauses in the FAR, or the DOD or NASA FAR 00014 * Supplement. Contractor/manufacturer is Silicon Graphics, Inc., 00015 * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. 00016 * 00017 * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY 00018 * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION, 00019 * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY 00020 * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON 00021 * GRAPHICS, INC. 00022 **=======================================================================*/ 00023 /*======================================================================= 00024 ** Author : Paul S. Strauss (MMM yyyy) 00025 ** Modified by : Nick Thompson (MMM yyyy) 00026 ** Modified by : Gavin Bell (MMM yyyy) 00027 **=======================================================================*/ 00028 /*======================================================================= 00029 *** THE CONTENT OF THIS WORK IS PROPRIETARY TO FEI S.A.S, (FEI S.A.S.), *** 00030 *** AND IS DISTRIBUTED UNDER A LICENSE AGREEMENT. *** 00031 *** *** 00032 *** REPRODUCTION, DISCLOSURE, OR USE, IN WHOLE OR IN PART, OTHER THAN AS *** 00033 *** SPECIFIED IN THE LICENSE ARE NOT TO BE UNDERTAKEN EXCEPT WITH PRIOR *** 00034 *** WRITTEN AUTHORIZATION OF FEI S.A.S. *** 00035 *** *** 00036 *** RESTRICTED RIGHTS LEGEND *** 00037 *** USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT OF THE CONTENT OF THIS *** 00038 *** WORK OR RELATED DOCUMENTATION IS SUBJECT TO RESTRICTIONS AS SET FORTH IN *** 00039 *** SUBPARAGRAPH (C)(1) OF THE COMMERCIAL COMPUTER SOFTWARE RESTRICTED RIGHT *** 00040 *** CLAUSE AT FAR 52.227-19 OR SUBPARAGRAPH (C)(1)(II) OF THE RIGHTS IN *** 00041 *** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 52.227-7013. *** 00042 *** *** 00043 *** COPYRIGHT (C) 1996-2017 BY FEI S.A.S, *** 00044 *** MERIGNAC, FRANCE *** 00045 *** ALL RIGHTS RESERVED *** 00046 **=======================================================================*/ 00047 /*======================================================================= 00048 ** Modified by : VSG (MMM YYYY) 00049 **=======================================================================*/ 00050 00051 00052 #ifndef _SO_FIELD_ 00053 #define _SO_FIELD_ 00054 00055 #include <Inventor/SbString.h> 00056 #include <Inventor/SoTypedObject.h> 00057 #include <Inventor/misc/SoNotification.h> 00058 #include <Inventor/misc/SoAuditorList.h> 00059 #include <Inventor/threads/SbThreadMutex.h> 00060 #include <Inventor/threads/SbThreadLocalStorage.h> 00061 #include <Inventor/sensors/SoDataSensor.h> 00062 #include <Inventor/misc/SoMemoryObject.h> 00063 00064 class SoEngineOutput; 00065 class SoVRMLInterpOutput; 00066 struct SoFieldConnectionInfo; 00067 class SoFieldContainer; 00068 struct SoFieldAuditorInfo; 00069 class SoFieldConverter; 00070 class SoFieldList; 00071 class SoInput; 00072 class SoMemoryObject; 00073 class SoNotList; 00074 class SoOutput; 00075 00076 #ifndef HIDDEN_FROM_DOC 00077 // If the field is connected or there are any FieldSensors attached to 00078 // this field, flags.hasAuditors will be TRUE, and this structure is 00079 // used to contain the extra information needed. Done this way to 00080 // save space in the common case. 00084 struct SoFieldAuditorInfo { 00085 SoFieldAuditorInfo() 00086 : container(NULL) 00087 { connection.field=NULL; } 00088 00089 SoFieldContainer *container; 00090 00091 // List of auditors: objects to pass notification to. 00092 SoAuditorList auditors; 00093 // The "connection" field points to either an engine output, 00094 // a VRMLInterpolator output, or 00095 // another field: 00096 union { 00097 SoEngineOutput *engineOutput; 00098 SoField *field; 00099 SoVRMLInterpOutput *interpOutput; 00100 } connection; 00101 }; 00102 00103 // If the field has a connections from other fields, there is a 00104 // SoFieldConnectionInfo structure for each connection and the index 00105 // of the last connection that touched this field is in the variable 00106 // lastTouched. The variable numConnected containes the number of connections 00107 // to this field. If multiple connections are allowed, this is also the 00108 // next connection index. 00112 struct SoFieldConnectionInfo { 00113 // The "connection" field points to either an engine output, 00114 // a VRMLInterpolator output, or 00115 // another field: 00116 void* indexToField; 00117 union { 00118 SoEngineOutput *engineOutput; 00119 SoField *field; 00120 SoVRMLInterpOutput *interpOutput; 00121 } connection; 00122 struct { 00123 unsigned int converted : 1; // Connection required converter 00124 unsigned int fromEngine : 1; // Connection is from engine 00125 unsigned int fromVRMLInterp : 1; // Connection is from 00126 // VRMLInterpolator 00127 } flags; 00128 }; 00129 #endif // HIDDEN_FROM_DOC 00130 00132 // 00133 // Class: SoField 00134 // 00135 // Base class for all kinds of fields. SoField maintains the state 00136 // (ignored, modified, default, ...) of the field. 00137 // 00139 00233 class SoField: public SoTypedObject { 00234 00235 public: 00236 00237 // Destructor 00238 #ifndef HIDDEN_FROM_DOC 00239 virtual ~SoField(); 00240 #endif // HIDDEN_FROM_DOC 00241 00257 void setIgnored(SbBool ig); 00261 SbBool isIgnored() const { return flags.ignored; } 00262 00270 SbBool isDefault() const { return flags.hasDefault; } 00271 00275 static SoType getClassTypeId(); 00276 00291 void enableConnection(SbBool flag); 00292 00297 SbBool isConnectionEnabled() const 00298 { return flags.connectionEnabled; } 00299 00307 SbBool connectFrom(SoEngineOutput *engineOutput); 00308 00316 SbBool connectFrom(SoField *field); 00317 00325 SbBool connectFrom(SoVRMLInterpOutput *interpOutput); 00326 00333 SbBool appendConnection(SoEngineOutput *engineOutput); 00334 00341 SbBool appendConnection(SoField *field); 00342 00349 SbBool appendConnection(SoVRMLInterpOutput *interpOutput); 00350 00355 void disconnect(SoEngineOutput *engineOutput); 00356 00361 void disconnect(SoField *field); 00362 00367 void disconnect(SoVRMLInterpOutput *interpOutput); 00368 00372 int getNumConnections() const 00373 { 00374 if (indexToConnectInfo) 00375 return indexToConnectInfo->getLength(); 00376 return 0; 00377 } 00378 00382 int getConnections(SoFieldList &list) ; 00383 00388 void disconnect(); 00389 00393 SbBool isConnected() const { return flags.connected; } 00394 00398 SbBool isConnectedFromVRMLInterp() const; 00399 00403 SbBool isConnectedFromEngine() const; 00404 00408 SbBool isConnectedFromField() const; 00409 00410 // Returns the engine or field the output field is connected to. 00411 // Returns FALSE if there is no connection of the appropriate type. 00412 00418 SbBool getConnectedEngine(SoEngineOutput *&engineOutput) const; 00419 00425 SbBool getConnectedField(SoField *&writingField) const; 00426 00431 SbBool getConnectedVRMLInterp(SoVRMLInterpOutput *&interpOutput) const; 00432 00438 int getForwardConnections(SoFieldList &list) const; 00439 00460 SoFieldContainer *getContainer() const; 00461 00472 SoNONUNICODE SbBool set(const char *valueString); 00473 00482 SbBool set( const SbString& valueString ); 00483 00484 00489 void get(SbString &valueString); 00490 00494 virtual size_t getValueSize() const { return 0; } 00495 00503 virtual void touch(); 00504 00509 int operator ==(const SoField &f) const 00510 { return isSame(f); } 00515 int operator !=(const SoField &f) const 00516 { return ! isSame(f); } 00517 00518 SoEXTENDER private: 00519 // Constuctor: 00520 SoField(); 00521 00522 private: 00523 static void initClass(); 00524 static void exitClass(); 00525 00526 SB_THREAD_TLS_HEADER(); 00527 00528 // Initialize ALL Inventor node classes 00529 static void initClasses(); 00530 static void exitClasses(); 00531 00532 // Sets value of field from the Inventor data file format 00533 // information in the value string. Returns TRUE if successful, 00534 // FALSE otherwise. This is used in SoVRMLPROTOInstance to set the 00535 // fields value that is an SFNode. It is necessary for the SoInput created to 00536 // know that this is a VRML2 file so it will know a PROTO if it it is the 00537 // default field 00538 SbBool setVRML(const char *valueString); 00539 00540 00541 // Sets default flag 00542 void setDefault(SbBool def) { flags.hasDefault = def; } 00543 00544 // Initiates or propagates notification through container 00545 virtual void startNotify(); 00546 virtual void notify(SoNotList *list); 00547 00548 // Sets the containing node. This also calls enableNotify(TRUE) 00549 // and setDefault(TRUE). 00550 void setContainer(SoFieldContainer *cont); 00551 00552 // Returns TRUE if the field really needs to be written out. 00553 // Fields with default values that aren't ignored and 00554 // aren't connected to anything will return FALSE. 00555 SbBool shouldWrite() const; 00556 00557 // Adds/removes an auditor to/from list 00558 void addAuditor(void *auditor, SoNotRec::Type type); 00559 void removeAuditor(void *auditor, SoNotRec::Type type); 00560 00561 // Indicates whether notification will propagate as the result of 00562 // setting the field value. Engines turn this off when writing 00563 // results into fields, since notification has already propagated. 00564 SbBool enableNotify(SbBool flag); 00565 SbBool isNotifyEnabled() const 00566 { return flags.notifyEnabled; } 00567 00568 // Indicates to a field that a change has been made involving a 00569 // connection from it (as source) to another field. Passed the 00570 // number of things being connected to the field; the number will 00571 // be negative when things are disconnected. 00572 // The default method does nothing. 00573 virtual void connectionStatusChanged(int numConnections); 00574 00575 // If this returns TRUE, it means we're in the middle of doing a 00576 // setValue()+valueChanged() and values from an upstream 00577 // connection shouldn't write into this field. 00578 SbBool isReadOnly() const { return flags.readOnly; } 00579 00580 // Returns TRUE if the given field is of the same type and has the 00581 // same value(s) as this. Subclasses must define this as well as 00582 // an == operator. 00583 virtual SbBool isSame(const SoField &f) const = 0; 00584 00585 // Copies the value from one field to another, assuming same subclass 00586 virtual void copyFrom(const SoField &f) = 0; 00587 00588 // After a field value has been copied using copyFrom(), 00589 // this is called to allow fields to update the copy. This is used 00590 // by node, engine, and path fields to make sure instances are 00591 // handled properly. The default implementation does nothing. 00592 virtual void fixCopy(SbBool copyConnections); 00593 00594 // This returns TRUE if this field contains a reference to a node 00595 // or engine that is copied during a copy operation (i.e., it is 00596 // "inside"). The default method just checks if the field is 00597 // connected to such a node or engine. Subclasses may contain 00598 // other tests, such as those that contain pointers to nodes or 00599 // engines. 00600 virtual SbBool referencesCopy() const; 00601 00602 // Copies connection from one field to another. Assumes fields are 00603 // the same subclass and that this field is connected. 00604 void copyConnection(const SoField *fromField); 00605 00606 // Reads value of field (with given name) from file as defined by 00607 // SoInput. This does the work common to all fields, then calls 00608 // other read methods to do the rest. 00609 virtual SbBool read(SoInput *in, const SbName &name); 00610 00611 // Writes field (with given name) to file as defined by SoOutput 00612 virtual void write(SoOutput *out, const SbName &name) const; 00613 00614 // Counts write-references on field to prepare for writing 00615 virtual void countWriteRefs(SoOutput *out) const; 00616 00617 // Evaluates the field from whatever it's connected to. If 00618 // there's no connection or we don't need to evaluate, this does 00619 // nothing. This has to be const because it's used by getValue 00620 // methods. 00621 void evaluate() const 00622 { if (flags.dirty) evaluateConnection(); } 00623 00624 // This is used to set the fieldType member of the flags structure 00625 void setFieldType( int flagValue) 00626 { flags.fieldType = flagValue; }; 00627 00628 // This is used to get the fieldType member of the flags structure 00629 int getFieldType() const 00630 { return flags.fieldType; }; 00631 00632 // Get the dirty flag so that the actions know to evaluate the events 00633 SbBool getDirty() const 00634 { return flags.dirty; }; 00635 00636 void setDirty(SbBool value) 00637 { flags.dirty = value; }; 00638 00639 // Get the userDataIsUsed flag 00640 SbBool getUserDataIsUsed() const 00641 { return flags.userDataIsUsed; }; 00642 00643 void setUserDataIsUsed(SbBool value) 00644 { flags.userDataIsUsed = value; }; 00645 00646 // Get the sameValueNotificationEnabled flag 00647 SbBool getSameValueNotificationEnabled() const 00648 { return flags.sameValueNotificationEnabled; }; 00649 00650 // Connects the field to the given output of an engine or to 00651 // another field. Returns FALSE if the connection could not be made. 00652 SbBool connectFrom(SoEngineOutput *engineOutput, SbBool notDefault); 00653 00654 SbBool connectFrom(SoField *field, SbBool notDefault); 00655 00656 // Connects the field to the given output of an VRMLInterpolator. 00657 // Returns FALSE if the connection could not be ade. 00658 SbBool connectFrom(SoVRMLInterpOutput *interpOutput, SbBool notDefault); 00659 00660 // Connects the field to the given output of an engine or to 00661 // another field. Returns FALSE if the connection could not be made. 00662 SbBool connectFrom(SoEngineOutput *engineOutput, 00663 SbBool notDefault, SbBool append); 00664 00665 SbBool connectFrom(SoField *field, SbBool notDefault, SbBool append); 00666 00667 // Connects the field to the given output of an VRMLInterpolator. 00668 // Returns FALSE if the connection could not be made. 00669 SbBool connectFrom(SoVRMLInterpOutput *interpOutput, 00670 SbBool notDefault, SbBool append); 00671 00672 // Changed to support FanIn for VRML2 but used by Inventor also. 00673 00674 // Appends the field to the given output of an engine or to 00675 // another field. Returns FALSE if the connection could not be made. 00676 // An overloaded function to allow the appendConnection to not do 00677 // the notify if setting up a ROUTE-TO connection. 00678 SbBool appendConnection(SoEngineOutput *engineOutput, 00679 SbBool notDefault); 00680 00681 SbBool appendConnection(SoField *field, SbBool notDefault); 00682 00683 // Connects the field to the given output of an VRMLInterpolator. 00684 // Returns FALSE if the connection could not be made. 00685 // An overloaded function to allow the appendConnection to not do 00686 // the notify if setting up a ROUTE-TO connection. 00687 SbBool appendConnection(SoVRMLInterpOutput *interpOutput, 00688 SbBool notDefault); 00689 00690 virtual bool isEnabledMemObj() { return false; } 00691 virtual SoMemoryObject* getMemObj() { return NULL; } 00692 virtual void setMemObj( SoMemoryObject* ) { } 00693 00694 00695 enum FieldType 00696 { 00697 HIDDEN_FIELD = 0, 00698 EVENTIN_FIELD = 1, 00699 EVENTOUT_FIELD = 2, 00700 FIELD_EVENTIN_FIELD = 3, 00701 INTERNAL_FIELD = 4, 00702 EXPOSED_FIELD = 5, 00703 PRIVATE_FIELD = 6, 00704 UNSUPPORTED_FIELD = 7 00705 }; 00706 00707 private: 00708 // Called by an instance to indicate that a value has changed. If 00709 // resetDefault is TRUE, this turns off default flag. Initiates 00710 // notification, if necessary. 00711 void valueChangedBasic(SbBool resetDefault = TRUE); 00712 00713 // Evaluates the field or engine the field is connected to, 00714 // storing the result in the field. This is const because it is 00715 // called by evaluate(). 00716 virtual void evaluateConnection() const; 00717 00718 // Reads value(s) of field 00719 virtual SbBool readValue(SoInput *in) = 0; 00720 00721 // Reads connection. 00722 virtual SbBool readConnection(SoInput *in); 00723 00724 // Writes value(s) of field 00725 virtual void writeValue(SoOutput *out) const = 0; 00726 00727 // Writes field connection 00728 virtual void writeConnection(SoOutput *out) const; 00729 00730 // These are used by SoField::get()/SoMField::get1() 00731 // to hold the returned field string 00732 static SbThreadMutex s_classMutex; 00733 struct MTstruct 00734 { 00735 char *fieldBuf; 00736 size_t fieldBufSize; 00737 }; 00738 // This is used to reallocate the string buffer used by SoField::get() 00739 static void *reallocFieldBuf(void *ptr, size_t newSize); 00740 00741 // Number of values (0 by default for SoSField) 00742 // only used by SoMField but here for memory padding reasons. 00743 int num; 00744 00745 private: 00746 static SoType classTypeId; 00747 // set if by default notification is triggered when doing SoSFField::setValue() with same value than previous. 00748 // this is controlled with OIV_ENABLE_SAMEVALUE_NOTIFICATION envvar. Default is TRUE. 00749 static bool s_defaultSameValueNotificationEnabled; 00750 00751 00752 // The "flags" field contains several bit flags: 00753 struct Flags { 00754 unsigned int hasDefault : 1; // Field is set to default value 00755 unsigned int ignored : 1; // Field value is to be ignored 00756 unsigned int connected : 1; // Field connected from something 00757 unsigned int converted : 1; // Connection required converter 00758 unsigned int fromEngine : 1; // Connection is from engine 00759 unsigned int connectionEnabled : 1; // Connection is enabled 00760 unsigned int notifyEnabled : 1; // Notification is enabled 00761 unsigned int hasAuditors : 1; // Connected, or FieldSensor 00762 unsigned int isEngineModifying : 1; // Engine evaluating 00763 unsigned int readOnly : 1; // Must not write into this field 00764 unsigned int dirty : 1; // Field was notified and needs evaluation 00765 unsigned int fromVRMLInterp : 1; // Connection is from VRMLInterpolator 00766 unsigned int fieldType : 3; // Specifies field type for VRML2 nodes. 00767 unsigned int userDataIsUsed : 1; // 1 if user data array is used and if enableDeleteValues has never been called (only used by SoMField). 00768 unsigned int sameValueNotificationEnabled : 1; // 1 if doing a setValue() with same value than previous generate a notification (only used by SoSField) 00769 // 0 = hidden field 0 0 0 00770 // 1 = eventIn 0 0 1 00771 // 2 = eventOut 0 1 0 00772 // 3 = field and eventIn 0 1 1 00773 // 4 = internal field 0 0 1 00774 // 5 = exposedField 1 0 1 00775 // 6 = private field 1 1 0 // Useful for IvTune, fields which are not displayed 00776 }; 00777 Flags flags; 00778 00779 // If no other auditors, the container for this field is stored 00780 // directly here. If the field has other auditors (flags.hasAuditors) 00781 // then the connection information and the container are 00782 // stored in an opaque SoFieldAuditorInfo structure. This is 00783 // done to save space in the common case. 00784 union { 00785 00786 SoFieldContainer *container; 00787 00788 SoFieldAuditorInfo *auditorInfo; 00789 }; 00790 00791 SbPList *indexToConnectInfo; 00792 00793 // Creates auditorInfo structure, if necessary: 00794 void createAuditorInfo(); 00795 00796 // Creates connectionInfo strucuture, if necessary: 00797 SoFieldConnectionInfo* createConnectionInfo(void* fromWhere); 00798 00799 // return index of the connection info that have the indexToField member equal to fromWhere 00800 // -1 if not found 00801 int findConnectionInfo(void* fromWhere) const ; 00802 00803 // Creates a converter engine to convert from the given field 00804 // type to the type of this field. Returns NULL on error. 00805 SoFieldConverter *createConverter(const SoType &fromFieldType) const; 00806 00807 // Really disconnects field from whatever it's connected to 00808 void reallyDisconnect(); 00809 00810 // Returns pointer to field converter, if fields was connected 00811 // through one 00812 SoFieldConverter *getConverter() const; 00813 00814 // Looks up what field connection is from (container and field/output name) 00815 void getConnectionInfo(SoFieldContainer *&, SbName &) const; 00816 00817 friend class SoEngineOutput; 00818 friend class SoVRMLInterpOutput; 00819 }; 00820 00821 // for compatibility we include also this 2 headers 00822 // that were previously implemented here 00823 #include <Inventor/fields/SoSField.h> 00824 #include <Inventor/fields/SoMField.h> 00825 00826 #endif /* _SO_FIELD_ */ 00827 00828 00829