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-2021 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 class SoFieldSensor; 00076 00077 #ifndef HIDDEN_FROM_DOC 00078 // If the field is connected or there are any FieldSensors attached to 00079 // this field, flags.hasAuditors will be TRUE, and this structure is 00080 // used to contain the extra information needed. Done this way to 00081 // save space in the common case. 00085 struct SoFieldAuditorInfo { 00086 SoFieldAuditorInfo() 00087 : container(NULL) 00088 { connection.field=NULL; } 00089 00090 SoFieldContainer *container; 00091 00092 // List of auditors: objects to pass notification to. 00093 SoAuditorList auditors; 00094 // The "connection" field points to either an engine output, 00095 // a VRMLInterpolator output, or 00096 // another field: 00097 union { 00098 SoEngineOutput *engineOutput; 00099 SoField *field; 00100 SoVRMLInterpOutput *interpOutput; 00101 } connection; 00102 }; 00103 00104 // If the field has a connections from other fields, there is a 00105 // SoFieldConnectionInfo structure for each connection and the index 00106 // of the last connection that touched this field is in the variable 00107 // lastTouched. The variable numConnected containes the number of connections 00108 // to this field. If multiple connections are allowed, this is also the 00109 // next connection index. 00113 struct SoFieldConnectionInfo { 00114 // The "connection" field points to either an engine output, 00115 // a VRMLInterpolator output, or 00116 // another field: 00117 void* indexToField; 00118 union { 00119 SoEngineOutput *engineOutput; 00120 SoField *field; 00121 SoVRMLInterpOutput *interpOutput; 00122 } connection; 00123 struct { 00124 unsigned int converted : 1; // Connection required converter 00125 unsigned int fromEngine : 1; // Connection is from engine 00126 unsigned int fromVRMLInterp : 1; // Connection is from 00127 // VRMLInterpolator 00128 } flags; 00129 }; 00130 #endif // HIDDEN_FROM_DOC 00131 00133 // 00134 // Class: SoField 00135 // 00136 // Base class for all kinds of fields. SoField maintains the state 00137 // (ignored, modified, default, ...) of the field. 00138 // 00140 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 00495 virtual size_t getValueSize() const { return 0; } 00496 00504 virtual void touch(); 00505 00510 int operator ==(const SoField &f) const 00511 { return isSame(f); } 00516 int operator !=(const SoField &f) const 00517 { return ! isSame(f); } 00518 00519 SoEXTENDER private: 00520 // Constuctor: 00521 SoField(); 00522 00523 private: 00524 static void initClass(); 00525 static void exitClass(); 00526 00527 SB_THREAD_TLS_HEADER(); 00528 00529 // Initialize ALL Inventor node classes 00530 static void initClasses(); 00531 static void exitClasses(); 00532 00533 // Sets value of field from the Inventor data file format 00534 // information in the value string. Returns TRUE if successful, 00535 // FALSE otherwise. This is used in SoVRMLPROTOInstance to set the 00536 // fields value that is an SFNode. It is necessary for the SoInput created to 00537 // know that this is a VRML2 file so it will know a PROTO if it it is the 00538 // default field 00539 SbBool setVRML(const char *valueString); 00540 00541 00542 // Sets default flag 00543 void setDefault(SbBool def) { flags.hasDefault = def; } 00544 00545 // Initiates or propagates notification through container 00546 virtual void startNotify(); 00547 virtual void notify(SoNotList *list); 00548 00549 // Sets the containing node. This also calls enableNotify(TRUE) 00550 // and setDefault(TRUE). 00551 void setContainer(SoFieldContainer *cont); 00552 00553 // Returns TRUE if the field really needs to be written out. 00554 // Fields with default values that aren't ignored and 00555 // aren't connected to anything will return FALSE. 00556 SbBool shouldWrite() const; 00557 00558 // Adds/removes an auditor to/from list 00559 void addAuditor(void *auditor, SoNotRec::Type type); 00560 void removeAuditor(void *auditor, SoNotRec::Type type); 00561 00562 // Indicates whether notification will propagate as the result of 00563 // setting the field value. Engines turn this off when writing 00564 // results into fields, since notification has already propagated. 00565 SbBool enableNotify(SbBool flag); 00566 SbBool isNotifyEnabled() const 00567 { return flags.notifyEnabled; } 00568 00569 // Indicates to a field that a change has been made involving a 00570 // connection from it (as source) to another field. Passed the 00571 // number of things being connected to the field; the number will 00572 // be negative when things are disconnected. 00573 // The default method does nothing. 00574 virtual void connectionStatusChanged(int numConnections); 00575 00576 // If this returns TRUE, it means we're in the middle of doing a 00577 // setValue()+valueChanged() and values from an upstream 00578 // connection shouldn't write into this field. 00579 SbBool isReadOnly() const { return flags.readOnly; } 00580 00581 // Returns TRUE if the given field is of the same type and has the 00582 // same value(s) as this. Subclasses must define this as well as 00583 // an == operator. 00584 virtual SbBool isSame(const SoField &f) const = 0; 00585 00586 // Copies the value from one field to another, assuming same subclass 00587 virtual void copyFrom(const SoField &f) = 0; 00588 00589 // After a field value has been copied using copyFrom(), 00590 // this is called to allow fields to update the copy. This is used 00591 // by node, engine, and path fields to make sure instances are 00592 // handled properly. The default implementation does nothing. 00593 virtual void fixCopy(SbBool copyConnections); 00594 00595 // This returns TRUE if this field contains a reference to a node 00596 // or engine that is copied during a copy operation (i.e., it is 00597 // "inside"). The default method just checks if the field is 00598 // connected to such a node or engine. Subclasses may contain 00599 // other tests, such as those that contain pointers to nodes or 00600 // engines. 00601 virtual SbBool referencesCopy() const; 00602 00603 // Copies connection from one field to another. Assumes fields are 00604 // the same subclass and that this field is connected. 00605 void copyConnection(const SoField *fromField); 00606 00607 // Reads value of field (with given name) from file as defined by 00608 // SoInput. This does the work common to all fields, then calls 00609 // other read methods to do the rest. 00610 virtual SbBool read(SoInput *in, const SbName &name); 00611 00612 // Writes field (with given name) to file as defined by SoOutput 00613 virtual void write(SoOutput *out, const SbName &name) const; 00614 00615 // Counts write-references on field to prepare for writing 00616 virtual void countWriteRefs(SoOutput *out) const; 00617 00618 // Evaluates the field from whatever it's connected to. If 00619 // there's no connection or we don't need to evaluate, this does 00620 // nothing. This has to be const because it's used by getValue 00621 // methods. 00622 void evaluate() const 00623 { if (flags.dirty) evaluateConnection(); } 00624 00625 // This is used to set the fieldType member of the flags structure 00626 void setFieldType( int flagValue) 00627 { flags.fieldType = flagValue; }; 00628 00629 // This is used to get the fieldType member of the flags structure 00630 int getFieldType() const 00631 { return flags.fieldType; }; 00632 00633 // Get the dirty flag so that the actions know to evaluate the events 00634 SbBool getDirty() const 00635 { return flags.dirty; }; 00636 00637 void setDirty(SbBool value) 00638 { flags.dirty = value; }; 00639 00640 // Get the userDataIsUsed flag 00641 SbBool getUserDataIsUsed() const 00642 { return flags.userDataIsUsed; }; 00643 00644 void setUserDataIsUsed(SbBool value) 00645 { flags.userDataIsUsed = value; }; 00646 00647 // Get the sameValueNotificationEnabled flag 00648 SbBool getSameValueNotificationEnabled() const 00649 { return flags.sameValueNotificationEnabled; }; 00650 00651 // Connects the field to the given output of an engine or to 00652 // another field. Returns FALSE if the connection could not be made. 00653 SbBool connectFrom(SoEngineOutput *engineOutput, SbBool notDefault); 00654 00655 SbBool connectFrom(SoField *field, SbBool notDefault); 00656 00657 // Connects the field to the given output of an VRMLInterpolator. 00658 // Returns FALSE if the connection could not be ade. 00659 SbBool connectFrom(SoVRMLInterpOutput *interpOutput, SbBool notDefault); 00660 00661 // Connects the field to the given output of an engine or to 00662 // another field. Returns FALSE if the connection could not be made. 00663 SbBool connectFrom(SoEngineOutput *engineOutput, 00664 SbBool notDefault, SbBool append); 00665 00666 SbBool connectFrom(SoField *field, SbBool notDefault, SbBool append); 00667 00668 // Connects the field to the given output of an VRMLInterpolator. 00669 // Returns FALSE if the connection could not be made. 00670 SbBool connectFrom(SoVRMLInterpOutput *interpOutput, 00671 SbBool notDefault, SbBool append); 00672 00673 // Changed to support FanIn for VRML2 but used by Inventor also. 00674 00675 // Appends the field to the given output of an engine or to 00676 // another field. Returns FALSE if the connection could not be made. 00677 // An overloaded function to allow the appendConnection to not do 00678 // the notify if setting up a ROUTE-TO connection. 00679 SbBool appendConnection(SoEngineOutput *engineOutput, 00680 SbBool notDefault); 00681 00682 SbBool appendConnection(SoField *field, SbBool notDefault); 00683 00684 // Connects the field to the given output of an VRMLInterpolator. 00685 // Returns FALSE if the connection could not be made. 00686 // An overloaded function to allow the appendConnection to not do 00687 // the notify if setting up a ROUTE-TO connection. 00688 SbBool appendConnection(SoVRMLInterpOutput *interpOutput, 00689 SbBool notDefault); 00690 00691 // Set callback function or lambda called on the field value change 00692 void setOnValueChangedCallback( const std::function<void( SoField* current )>& value ); 00693 00694 virtual bool isEnabledMemObj() { return false; } 00695 virtual SoMemoryObject* getMemObj() { return NULL; } 00696 virtual void setMemObj( SoMemoryObject* ) { } 00697 00698 00699 enum FieldType 00700 { 00701 HIDDEN_FIELD = 0, 00702 EVENTIN_FIELD = 1, 00703 EVENTOUT_FIELD = 2, 00704 FIELD_EVENTIN_FIELD = 3, 00705 INTERNAL_FIELD = 4, 00706 EXPOSED_FIELD = 5, 00707 PRIVATE_FIELD = 6, 00708 UNSUPPORTED_FIELD = 7 00709 }; 00710 00711 private: 00712 // Called by an instance to indicate that a value has changed. If 00713 // resetDefault is TRUE, this turns off default flag. Initiates 00714 // notification, if necessary. 00715 void valueChangedBasic(SbBool resetDefault = TRUE); 00716 00717 // Evaluates the field or engine the field is connected to, 00718 // storing the result in the field. This is const because it is 00719 // called by evaluate(). 00720 virtual void evaluateConnection() const; 00721 00722 // Reads value(s) of field 00723 virtual SbBool readValue(SoInput *in) = 0; 00724 00725 // Reads connection. 00726 virtual SbBool readConnection(SoInput *in); 00727 00728 // Writes value(s) of field 00729 virtual void writeValue(SoOutput *out) const = 0; 00730 00731 // Writes field connection 00732 virtual void writeConnection(SoOutput *out) const; 00733 00734 // These are used by SoField::get()/SoMField::get1() 00735 // to hold the returned field string 00736 static SbThreadMutex s_classMutex; 00737 struct MTstruct 00738 { 00739 char *fieldBuf; 00740 size_t fieldBufSize; 00741 }; 00742 // This is used to reallocate the string buffer used by SoField::get() 00743 static void *reallocFieldBuf(void *ptr, size_t newSize); 00744 00745 // Number of values (0 by default for SoSField) 00746 // only used by SoMField but here for memory padding reasons. 00747 int num; 00748 00749 private: 00750 static SoType classTypeId; 00751 // set if by default notification is triggered when doing SoSFField::setValue() with same value than previous. 00752 // this is controlled with OIV_ENABLE_SAMEVALUE_NOTIFICATION envvar. Default is TRUE. 00753 static bool s_defaultSameValueNotificationEnabled; 00754 00755 00756 // The "flags" field contains several bit flags: 00757 struct Flags { 00758 unsigned int hasDefault : 1; // Field is set to default value 00759 unsigned int ignored : 1; // Field value is to be ignored 00760 unsigned int connected : 1; // Field connected from something 00761 unsigned int converted : 1; // Connection required converter 00762 unsigned int fromEngine : 1; // Connection is from engine 00763 unsigned int connectionEnabled : 1; // Connection is enabled 00764 unsigned int notifyEnabled : 1; // Notification is enabled 00765 unsigned int hasAuditors : 1; // Connected, or FieldSensor 00766 unsigned int isEngineModifying : 1; // Engine evaluating 00767 unsigned int readOnly : 1; // Must not write into this field 00768 unsigned int dirty : 1; // Field was notified and needs evaluation 00769 unsigned int fromVRMLInterp : 1; // Connection is from VRMLInterpolator 00770 unsigned int fieldType : 3; // Specifies field type for VRML2 nodes. 00771 unsigned int userDataIsUsed : 1; // 1 if user data array is used and if enableDeleteValues has never been called (only used by SoMField). 00772 unsigned int sameValueNotificationEnabled : 1; // 1 if doing a setValue() with same value than previous generate a notification (only used by SoSField) 00773 // 0 = hidden field 0 0 0 00774 // 1 = eventIn 0 0 1 00775 // 2 = eventOut 0 1 0 00776 // 3 = field and eventIn 0 1 1 00777 // 4 = internal field 0 0 1 00778 // 5 = exposedField 1 0 1 00779 // 6 = private field 1 1 0 // Useful for IvTune, fields which are not displayed 00780 }; 00781 Flags flags; 00782 00783 // If no other auditors, the container for this field is stored 00784 // directly here. If the field has other auditors (flags.hasAuditors) 00785 // then the connection information and the container are 00786 // stored in an opaque SoFieldAuditorInfo structure. This is 00787 // done to save space in the common case. 00788 union { 00789 00790 SoFieldContainer *container; 00791 00792 SoFieldAuditorInfo *auditorInfo; 00793 }; 00794 00795 SbPList *indexToConnectInfo; 00796 00797 // Creates auditorInfo structure, if necessary: 00798 void createAuditorInfo(); 00799 00800 // Creates connectionInfo strucuture, if necessary: 00801 SoFieldConnectionInfo* createConnectionInfo(void* fromWhere); 00802 00803 // return index of the connection info that have the indexToField member equal to fromWhere 00804 // -1 if not found 00805 int findConnectionInfo(void* fromWhere) const ; 00806 00807 // Creates a converter engine to convert from the given field 00808 // type to the type of this field. Returns NULL on error. 00809 SoFieldConverter *createConverter(const SoType &fromFieldType) const; 00810 00811 // Really disconnects field from whatever it's connected to 00812 void reallyDisconnect(); 00813 00814 // Returns pointer to field converter, if fields was connected 00815 // through one 00816 SoFieldConverter *getConverter() const; 00817 00818 // Looks up what field connection is from (container and field/output name) 00819 void getConnectionInfo(SoFieldContainer *&, SbName &) const; 00820 00821 // Callback for field sync 00822 std::function<void( SoField* current )> m_onValueChanged; 00823 SoFieldSensor * m_onValueChangedFieldSensor; 00824 00825 friend class SoEngineOutput; 00826 friend class SoVRMLInterpOutput; 00827 }; 00828 00829 // for compatibility we include also this 2 headers 00830 // that were previously implemented here 00831 #include <Inventor/fields/SoSField.h> 00832 #include <Inventor/fields/SoMField.h> 00833 00834 #endif /* _SO_FIELD_ */ 00835 00836 00837