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-2020 BY FEI S.A.S, *** 00044 *** BORDEAUX, 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 00234 class SoField: public SoTypedObject { 00235 00236 public: 00237 00238 // Destructor 00239 #ifndef HIDDEN_FROM_DOC 00240 virtual ~SoField(); 00241 #endif // HIDDEN_FROM_DOC 00242 00258 void setIgnored(SbBool ig); 00262 SbBool isIgnored() const { return flags.ignored; } 00263 00271 SbBool isDefault() const { return flags.hasDefault; } 00272 00276 static SoType getClassTypeId(); 00277 00292 void enableConnection(SbBool flag); 00293 00298 SbBool isConnectionEnabled() const 00299 { return flags.connectionEnabled; } 00300 00308 SbBool connectFrom(SoEngineOutput *engineOutput); 00309 00317 SbBool connectFrom(SoField *field); 00318 00326 SbBool connectFrom(SoVRMLInterpOutput *interpOutput); 00327 00334 SbBool appendConnection(SoEngineOutput *engineOutput); 00335 00342 SbBool appendConnection(SoField *field); 00343 00350 SbBool appendConnection(SoVRMLInterpOutput *interpOutput); 00351 00356 void disconnect(SoEngineOutput *engineOutput); 00357 00362 void disconnect(SoField *field); 00363 00368 void disconnect(SoVRMLInterpOutput *interpOutput); 00369 00373 int getNumConnections() const 00374 { 00375 if (indexToConnectInfo) 00376 return indexToConnectInfo->getLength(); 00377 return 0; 00378 } 00379 00383 int getConnections(SoFieldList &list) ; 00384 00389 void disconnect(); 00390 00394 SbBool isConnected() const { return flags.connected; } 00395 00399 SbBool isConnectedFromVRMLInterp() const; 00400 00404 SbBool isConnectedFromEngine() const; 00405 00409 SbBool isConnectedFromField() const; 00410 00411 // Returns the engine or field the output field is connected to. 00412 // Returns FALSE if there is no connection of the appropriate type. 00413 00419 SbBool getConnectedEngine(SoEngineOutput *&engineOutput) const; 00420 00426 SbBool getConnectedField(SoField *&writingField) const; 00427 00432 SbBool getConnectedVRMLInterp(SoVRMLInterpOutput *&interpOutput) const; 00433 00439 int getForwardConnections(SoFieldList &list) const; 00440 00461 SoFieldContainer *getContainer() const; 00462 00473 SoNONUNICODE SbBool set(const char *valueString); 00474 00483 SbBool set( const SbString& valueString ); 00484 00485 00490 void get(SbString &valueString); 00491 00499 virtual void touch(); 00500 00505 int operator ==(const SoField &f) const 00506 { return isSame(f); } 00511 int operator !=(const SoField &f) const 00512 { return ! isSame(f); } 00513 00514 SoEXTENDER private: 00515 // Constuctor: 00516 SoField(); 00517 00518 private: 00519 static void initClass(); 00520 static void exitClass(); 00521 00522 SB_THREAD_TLS_HEADER(); 00523 00524 // Initialize ALL Inventor node classes 00525 static void initClasses(); 00526 static void exitClasses(); 00527 00528 // Sets value of field from the Inventor data file format 00529 // information in the value string. Returns TRUE if successful, 00530 // FALSE otherwise. This is used in SoVRMLPROTOInstance to set the 00531 // fields value that is an SFNode. It is necessary for the SoInput created to 00532 // know that this is a VRML2 file so it will know a PROTO if it it is the 00533 // default field 00534 SbBool setVRML(const char *valueString); 00535 00536 00537 // Sets default flag 00538 void setDefault(SbBool def) { flags.hasDefault = def; } 00539 00540 // Initiates or propagates notification through container 00541 virtual void startNotify(); 00542 virtual void notify(SoNotList *list); 00543 00544 // Sets the containing node. This also calls enableNotify(TRUE) 00545 // and setDefault(TRUE). 00546 void setContainer(SoFieldContainer *cont); 00547 00548 // Returns TRUE if the field really needs to be written out. 00549 // Fields with default values that aren't ignored and 00550 // aren't connected to anything will return FALSE. 00551 SbBool shouldWrite() const; 00552 00553 // Adds/removes an auditor to/from list 00554 void addAuditor(void *auditor, SoNotRec::Type type); 00555 void removeAuditor(void *auditor, SoNotRec::Type type); 00556 00557 // Indicates whether notification will propagate as the result of 00558 // setting the field value. Engines turn this off when writing 00559 // results into fields, since notification has already propagated. 00560 SbBool enableNotify(SbBool flag); 00561 SbBool isNotifyEnabled() const 00562 { return flags.notifyEnabled; } 00563 00564 // Indicates to a field that a change has been made involving a 00565 // connection from it (as source) to another field. Passed the 00566 // number of things being connected to the field; the number will 00567 // be negative when things are disconnected. 00568 // The default method does nothing. 00569 virtual void connectionStatusChanged(int numConnections); 00570 00571 // If this returns TRUE, it means we're in the middle of doing a 00572 // setValue()+valueChanged() and values from an upstream 00573 // connection shouldn't write into this field. 00574 SbBool isReadOnly() const { return flags.readOnly; } 00575 00576 // Returns TRUE if the given field is of the same type and has the 00577 // same value(s) as this. Subclasses must define this as well as 00578 // an == operator. 00579 virtual SbBool isSame(const SoField &f) const = 0; 00580 00581 // Copies the value from one field to another, assuming same subclass 00582 virtual void copyFrom(const SoField &f) = 0; 00583 00584 // After a field value has been copied using copyFrom(), 00585 // this is called to allow fields to update the copy. This is used 00586 // by node, engine, and path fields to make sure instances are 00587 // handled properly. The default implementation does nothing. 00588 virtual void fixCopy(SbBool copyConnections); 00589 00590 // This returns TRUE if this field contains a reference to a node 00591 // or engine that is copied during a copy operation (i.e., it is 00592 // "inside"). The default method just checks if the field is 00593 // connected to such a node or engine. Subclasses may contain 00594 // other tests, such as those that contain pointers to nodes or 00595 // engines. 00596 virtual SbBool referencesCopy() const; 00597 00598 // Copies connection from one field to another. Assumes fields are 00599 // the same subclass and that this field is connected. 00600 void copyConnection(const SoField *fromField); 00601 00602 // Reads value of field (with given name) from file as defined by 00603 // SoInput. This does the work common to all fields, then calls 00604 // other read methods to do the rest. 00605 virtual SbBool read(SoInput *in, const SbName &name); 00606 00607 // Writes field (with given name) to file as defined by SoOutput 00608 virtual void write(SoOutput *out, const SbName &name) const; 00609 00610 // Counts write-references on field to prepare for writing 00611 virtual void countWriteRefs(SoOutput *out) const; 00612 00613 // Evaluates the field from whatever it's connected to. If 00614 // there's no connection or we don't need to evaluate, this does 00615 // nothing. This has to be const because it's used by getValue 00616 // methods. 00617 void evaluate() const 00618 { if (flags.dirty) evaluateConnection(); } 00619 00620 // This is used to set the fieldType member of the flags structure 00621 void setFieldType( int flagValue) 00622 { flags.fieldType = flagValue; }; 00623 00624 // This is used to get the fieldType member of the flags structure 00625 int getFieldType() const 00626 { return flags.fieldType; }; 00627 00628 // Get the dirty flag so that the actions know to evaluate the events 00629 SbBool getDirty() const 00630 { return flags.dirty; }; 00631 00632 void setDirty(SbBool value) 00633 { flags.dirty = value; }; 00634 00635 // Get the userDataIsUsed flag 00636 SbBool getUserDataIsUsed() const 00637 { return flags.userDataIsUsed; }; 00638 00639 void setUserDataIsUsed(SbBool value) 00640 { flags.userDataIsUsed = value; }; 00641 00642 // Get the sameValueNotificationEnabled flag 00643 SbBool getSameValueNotificationEnabled() const 00644 { return flags.sameValueNotificationEnabled; }; 00645 00646 virtual void setSameValueNotificationEnabled(SbBool value) 00647 { flags.sameValueNotificationEnabled = value; }; 00648 00649 // Connects the field to the given output of an engine or to 00650 // another field. Returns FALSE if the connection could not be made. 00651 SbBool connectFrom(SoEngineOutput *engineOutput, SbBool notDefault); 00652 00653 SbBool connectFrom(SoField *field, SbBool notDefault); 00654 00655 // Connects the field to the given output of an VRMLInterpolator. 00656 // Returns FALSE if the connection could not be ade. 00657 SbBool connectFrom(SoVRMLInterpOutput *interpOutput, SbBool notDefault); 00658 00659 // Connects the field to the given output of an engine or to 00660 // another field. Returns FALSE if the connection could not be made. 00661 SbBool connectFrom(SoEngineOutput *engineOutput, 00662 SbBool notDefault, SbBool append); 00663 00664 SbBool connectFrom(SoField *field, SbBool notDefault, SbBool append); 00665 00666 // Connects the field to the given output of an VRMLInterpolator. 00667 // Returns FALSE if the connection could not be made. 00668 SbBool connectFrom(SoVRMLInterpOutput *interpOutput, 00669 SbBool notDefault, SbBool append); 00670 00671 // Changed to support FanIn for VRML2 but used by Inventor also. 00672 00673 // Appends the field to the given output of an engine or to 00674 // another field. Returns FALSE if the connection could not be made. 00675 // An overloaded function to allow the appendConnection to not do 00676 // the notify if setting up a ROUTE-TO connection. 00677 SbBool appendConnection(SoEngineOutput *engineOutput, 00678 SbBool notDefault); 00679 00680 SbBool appendConnection(SoField *field, SbBool notDefault); 00681 00682 // Connects the field to the given output of an VRMLInterpolator. 00683 // Returns FALSE if the connection could not be made. 00684 // An overloaded function to allow the appendConnection to not do 00685 // the notify if setting up a ROUTE-TO connection. 00686 SbBool appendConnection(SoVRMLInterpOutput *interpOutput, 00687 SbBool notDefault); 00688 00689 virtual bool isEnabledMemObj() { return false; } 00690 virtual SoMemoryObject* getMemObj() { return NULL; } 00691 virtual void setMemObj( SoMemoryObject* ) { } 00692 virtual size_t getValueSize() const { return 0; } 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 }; 00705 00706 private: 00707 // Called by an instance to indicate that a value has changed. If 00708 // resetDefault is TRUE, this turns off default flag. Initiates 00709 // notification, if necessary. 00710 void valueChangedBasic(SbBool resetDefault = TRUE); 00711 00712 // Evaluates the field or engine the field is connected to, 00713 // storing the result in the field. This is const because it is 00714 // called by evaluate(). 00715 virtual void evaluateConnection() const; 00716 00717 // Reads value(s) of field 00718 virtual SbBool readValue(SoInput *in) = 0; 00719 00720 // Reads connection. 00721 virtual SbBool readConnection(SoInput *in); 00722 00723 // Writes value(s) of field 00724 virtual void writeValue(SoOutput *out) const = 0; 00725 00726 // Writes field connection 00727 virtual void writeConnection(SoOutput *out) const; 00728 00729 // These are used by SoField::get()/SoMField::get1() 00730 // to hold the returned field string 00731 static SbThreadMutex s_classMutex; 00732 struct MTstruct 00733 { 00734 char *fieldBuf; 00735 size_t fieldBufSize; 00736 }; 00737 // This is used to reallocate the string buffer used by SoField::get() 00738 static void *reallocFieldBuf(void *ptr, size_t newSize); 00739 00740 // Number of values (0 by default for SoSField) 00741 // only used by SoMField but here for memory padding reasons. 00742 int num; 00743 00744 private: 00745 static SoType classTypeId; 00746 // set if by default notification is triggered when doing SoSFField::setValue() with same value than previous. 00747 // this is controlled with OIV_ENABLE_SAMEVALUE_NOTIFICATION envvar. Default is TRUE. 00748 static bool s_defaultSameValueNotificationEnabled; 00749 00750 00751 // The "flags" field contains several bit flags: 00752 struct Flags { 00753 unsigned int hasDefault : 1; // Field is set to default value 00754 unsigned int ignored : 1; // Field value is to be ignored 00755 unsigned int connected : 1; // Field connected from something 00756 unsigned int converted : 1; // Connection required converter 00757 unsigned int fromEngine : 1; // Connection is from engine 00758 unsigned int connectionEnabled : 1; // Connection is enabled 00759 unsigned int notifyEnabled : 1; // Notification is enabled 00760 unsigned int hasAuditors : 1; // Connected, or FieldSensor 00761 unsigned int isEngineModifying : 1; // Engine evaluating 00762 unsigned int readOnly : 1; // Must not write into this field 00763 unsigned int dirty : 1; // Field was notified and needs evaluation 00764 unsigned int fromVRMLInterp : 1; // Connection is from VRMLInterpolator 00765 unsigned int fieldType : 3; // Specifies field type for VRML2 nodes. 00766 unsigned int userDataIsUsed : 1; // 1 if user data array is used and if enableDeleteValues has never been called (only used by SoMField). 00767 unsigned int sameValueNotificationEnabled : 1; // 1 if doing a setValue() with same value than previous generate a notification (only used by SoSField) 00768 // 0 = hidden field 0 0 0 00769 // 1 = eventIn 0 0 1 00770 // 2 = eventOut 0 1 0 00771 // 3 = field and eventIn 0 1 1 00772 // 4 = internal field 0 0 1 00773 // 5 = exposedField 1 0 1 00774 // 6 = private field 1 1 0 // Useful for IvTune, fields which are not displayed 00775 }; 00776 Flags flags; 00777 00778 // If no other auditors, the container for this field is stored 00779 // directly here. If the field has other auditors (flags.hasAuditors) 00780 // then the connection information and the container are 00781 // stored in an opaque SoFieldAuditorInfo structure. This is 00782 // done to save space in the common case. 00783 union { 00784 00785 SoFieldContainer *container; 00786 00787 SoFieldAuditorInfo *auditorInfo; 00788 }; 00789 00790 SbPList *indexToConnectInfo; 00791 00792 // Creates auditorInfo structure, if necessary: 00793 void createAuditorInfo(); 00794 00795 // Creates connectionInfo strucuture, if necessary: 00796 SoFieldConnectionInfo* createConnectionInfo(void* fromWhere); 00797 00798 // return index of the connection info that have the indexToField member equal to fromWhere 00799 // -1 if not found 00800 int findConnectionInfo(void* fromWhere) const ; 00801 00802 // Creates a converter engine to convert from the given field 00803 // type to the type of this field. Returns NULL on error. 00804 SoFieldConverter *createConverter(const SoType &fromFieldType) const; 00805 00806 // Really disconnects field from whatever it's connected to 00807 void reallyDisconnect(); 00808 00809 // Returns pointer to field converter, if fields was connected 00810 // through one 00811 SoFieldConverter *getConverter() const; 00812 00813 // Looks up what field connection is from (container and field/output name) 00814 void getConnectionInfo(SoFieldContainer *&, SbName &) const; 00815 00816 friend class SoEngineOutput; 00817 friend class SoVRMLInterpOutput; 00818 }; 00819 00820 // for compatibility we include also this 2 headers 00821 // that were previously implemented here 00822 #include <Inventor/fields/SoSField.h> 00823 #include <Inventor/fields/SoMField.h> 00824 00825 #endif /* _SO_FIELD_ */ 00826 00827 00828