Class TX3DNode

Unit

Declaration

type TX3DNode = class(TX3DFileItem)

Description

X3D node. Every X3D node class descends from this.

Hierarchy

Overview

Fields

Protected VRML1ChildrenAllowed: boolean;
Protected VRML1ChildrenParsingAllowed: boolean;

Methods

Protected function DeepCopyCore(CopyState: TX3DNodeDeepCopyState): TX3DNode; virtual;
Protected function DeepCopyCreate(CopyState: TX3DNodeDeepCopyState): TX3DNode; virtual;
Protected procedure AddFunctionality(const F: TNodeFunctionality);
Protected class function VRML1ChildrenSaveToStream: boolean; virtual;
Protected function DirectEnumerateActive( Func: TEnumerateChildrenFunction): Pointer; virtual;
Protected function DirectEnumerateActiveForTraverse( Func: TEnumerateChildrenFunction; StateStack: TX3DGraphTraverseStateStack): Pointer; virtual;
Protected function DirectEnumerateAll( Func: TEnumerateChildrenFunction): Pointer;
Protected function DirectEnumerate( Func: TEnumerateChildrenFunction; OnlyActive: boolean): Pointer;
Protected procedure BeforeTraverse(StateStack: TX3DGraphTraverseStateStack); virtual;
Protected procedure MiddleTraverse(StateStack: TX3DGraphTraverseStateStack); virtual;
Protected procedure AfterTraverse(StateStack: TX3DGraphTraverseStateStack); virtual;
Protected function ParseNodeBodyElement(Lexer: TX3DLexer; Reader: TX3DReaderNames; const APositionInParent: Integer): boolean; virtual;
Protected procedure ParseAfter(Reader: TX3DReaderNames); virtual;
Protected procedure CreateNode; virtual;
Protected procedure GroupBeforeTraverse(const State: TX3DGraphTraverseState; var WasPointingDeviceSensor: Boolean); virtual;
Public function FieldsCount: Integer;
Public procedure AddField(const Value: TX3DField);
Public function IndexOfField(const AName: string): Integer;
Public function EventsCount: Integer;
Public procedure AddEvent(const Value: TX3DEvent);
Public function IndexOfEvent(const AName: string): Integer;
Public function Field(const AName: string; const RaiseOnError: Boolean = false): TX3DField;
Public function FieldOrEvent(const AName: string; const RaiseOnError: Boolean = false): TX3DFieldOrEvent;
Public function AnyEvent(const AName: string; const RaiseOnError: Boolean = false): TX3DEvent;
Public function VRML1ChildrenCount: integer;
Public procedure VRML1ChildAdd(const Index: Integer; const Child: TX3DNode); overload;
Public procedure VRML1ChildAdd(const Child: TX3DNode); overload;
Public procedure VRML1ChildRemove(const I: Integer);
Public procedure VRML1ChildrenClear;
Public function VRML1ChildExtract(const I: Integer): TX3DNode;
Public function VRML1ParentsCount: integer;
Public function ParentFieldsCount: Integer;
Public procedure FreeRemovingFromAllParents;
Public procedure FreeIfUnused;
Public procedure KeepExistingBegin;
Public procedure KeepExistingEnd;
Public function PathFromBaseUrl(const RelativePath: string): string;
Public procedure Parse(Lexer: TX3DLexer; Reader: TX3DReaderNames); virtual;
Public procedure ParseXML(Element: TDOMElement; Reader: TX3DReaderNames);
Public constructor Create(const AX3DName: string = ''; const ABaseUrl: string = ''); virtual;
Public destructor Destroy; override;
Public function X3DType: string; virtual;
Public function NodeTypeName: string; deprecated 'use X3DType';
Public class function ClassX3DType: string; virtual;
Public function Traverse( NodeClass: TX3DNodeClass; TraversingFunc: TTraversingFunc): Pointer;
Public function TraverseInternal(StateStack: TX3DGraphTraverseStateStack; NodeClass: TX3DNodeClass; TraversingFunc: TTraversingFunc; ParentInfo: PTraversingInfo): Pointer;
Public function TraverseIntoChildren(StateStack: TX3DGraphTraverseStateStack; NodeClass: TX3DNodeClass; TraversingFunc: TTraversingFunc; ParentInfo: PTraversingInfo): Pointer;
Public procedure EnumerateNodes( proc: TX3DNodeProc; OnlyActive: boolean); overload;
Public procedure EnumerateNodes(nodeClass: TX3DNodeClass; proc: TX3DNodeProc; OnlyActive: boolean); overload;
Public procedure EnumerateNodes(nodeClass: TX3DNodeClass; const SeekNodeName: string; proc: TX3DNodeProc; OnlyActive: boolean); overload;
Public function SearchNodes(const Proc: TX3DNodeSearchProc; const OnlyActive: boolean): Pointer;
Public function TryFindNodeByName(FindClass: TX3DNodeClass; const FindName: string; OnlyActive: boolean): TX3DNode; deprecated 'use FindNode';
Public function FindNodeByName(FindClass: TX3DNodeClass; const FindName: string; OnlyActive: boolean): TX3DNode; deprecated 'use FindNode';
Public function TryFindNode(FindClass: TX3DNodeClass; OnlyActive: boolean): TX3DNode; deprecated 'use FindNode';
Public function FindNode(FindClass: TX3DNodeClass; OnlyActive: boolean): TX3DNode; overload; deprecated 'use FindNode';
Public function FindNode(const NodeClass: TX3DNodeClass; const FindName: string; const Options: TFindNodeOptions = []): TX3DNode; overload;
Public function FindNode(const FindName: string): TX3DNode; overload; deprecated 'use FindNode(NodeClass, FindName)';
Public function TryFindNodeState( NodeClass: TX3DNodeClass; out Node: TX3DNode; out State: TX3DGraphTraverseState): boolean; deprecated 'use FindNode to look for nodes easier; or iterate over TCastleScene.Shapes.TraverseList if you really need to know nodes with their TX3DGraphTraverseState';
Public function TryFindNodeTransform( NodeClass: TX3DNodeClass; out Node: TX3DNode; out Transform: TMatrix4; out TransformScale: Single): boolean; deprecated 'use FindNode to look for nodes easier; or iterate over TCastleScene.Shapes.TraverseList if you really need to know nodes with their transformations';
Public function TryFindParentByName(const FindName: string): TX3DNode;
Public function FindParentByName(const FindName: string): TX3DNode;
Public function HasParentNode(Node: TX3DNode): boolean;
Public function TryFindDirectParentByName(const FindName: string): TX3DNode;
Public function IsNodePresent(Node: TX3DNode; OnlyActive: boolean): boolean;
Public function NodesCount(NodeClass: TX3DNodeClass; CountOnlyActiveNodes: boolean): integer;
Public procedure SaveToStream(Writer: TX3DWriter); override;
Public class function VRML1StateNode(out StateNode: TVRML1StateNode): boolean;
Public class function ForVRMLVersion(const Version: TX3DVersion): boolean; virtual;
Public function EnumerateReplaceChildren( Func: TEnumerateReplaceNodesFunction): Cardinal;
Public function RemoveChildrenWithMatchingName( const Wildcard: string; IgnoreCase: Boolean): Cardinal;
Public function PrototypesCount: Integer;
Public procedure AddPrototype(const Value: TX3DPrototypeBase);
Public function RoutesCount: Integer;
Public procedure AddRoute(const Value: TX3DRoute); overload;
Public procedure AddRoute(const Source, Destination: TX3DFieldOrEvent); overload;
Public function ImportsCount: Integer;
Public procedure AddImport(const Value: TX3DImport);
Public function ExportsCount: Integer;
Public procedure AddExport(const Value: TX3DExport);
Public function DeepCopy: TX3DNode;
Public procedure AddDestructionNotification(const Event: TNodeDestructionNotification);
Public procedure RemoveDestructionNotification(const Event: TNodeDestructionNotification);
Public procedure PostAddInterfaceDeclaration(IDecl: TX3DInterfaceDeclaration); virtual;
Public procedure AddCustomField(AField: TX3DField);
Public procedure AddCustomFieldOrEvent(AFieldOrEvent: TX3DFieldOrEvent);
Public function NiceName: string;
Public procedure UnregisterScene;
Public function FieldSetByEvent(const Event: TX3DEvent): TX3DField; virtual;
Public function FieldSendingEvent(const Event: TX3DEvent): TX3DField; virtual;
Public function Functionality( const FunctionalityClass: TNodeFunctionalityClass): TNodeFunctionality;

Properties

Protected property CDataField: TMFString read FCDataField write FCDataField;
Public property Fields [constIndex:Integer]: TX3DField read GetFields;
Public property Events [constIndex:Integer]: TX3DEvent read GetEvents;
Public property VRML1Children [constI:Integer]: TX3DNode read GetVRML1Child write SetVRML1Child;
Public property VRML1Parents [constI:Integer]: TX3DNode read GetVRML1Parent;
Public property ParentFields[Index:Integer]: TX3DField read GetParentFieldsItem;
Public property ParentFieldsNode[Index:Integer]: TX3DNode read GetParentFieldsNodeItem;
Public property KeepExisting: Cardinal read FKeepExisting write FKeepExisting;
Public property X3DName: string read FX3DName write FX3DName;
Public property NodeName: string read FX3DName write FX3DName; deprecated 'use X3DName';
Public property BaseUrl: string read FBaseUrl write FBaseUrl;
Public property WWWBasePath: string read FBaseUrl write FBaseUrl; deprecated;
Public property Prototypes [constIndex:Integer]: TX3DPrototypeBase read GetPrototypes;
Public property Routes [constIndex:Integer]: TX3DRoute read GetRoutes;
Public property ImportsList [constIndex:Integer]: TX3DImport read GetImports;
Public property ExportsList [constIndex:Integer]: TX3DExport read GetExports;
Public property PrototypeInstance: boolean read FPrototypeInstance;
Public property PrototypeInstanceSourceNode: TX3DPrototypeNode read FPrototypeInstanceSourceNode;
Public property PrototypeInstanceHelpers: TX3DNode read FPrototypeInstanceHelpers;
Public property DefaultContainerField: string read FDefaultContainerField write FDefaultContainerField;
Public property HasInterfaceDeclarations: TX3DAccessTypes read FHasInterfaceDeclarations write SetHasInterfaceDeclarations default [];
Public property InterfaceDeclarations: TX3DInterfaceDeclarationList read FInterfaceDeclarations;
Public property Scene: TX3DEventsEngine read FScene write FScene;
Public property TransformFunctionality: TTransformFunctionality read FTransformFunctionality;
Public property TimeFunctionality: TTimeDependentFunctionality read FTimeFunctionality;
Public property GenTexFunctionality: TGeneratedTextureFunctionality read FGenTexFunctionality;

Description

Fields

Protected VRML1ChildrenAllowed: boolean;

Are VRML 1.0 children allowed. This condition is checked in VRML1ChildAdd, so it's strictly impossible to add a node that is not allowed.

Note that in some special cases VRML1ChildrenAllowed and VRML1ChildrenParsingAllowed values may be changed during object lifetime. Currently, this may concern TX3DUnknownNode.

Default False.

Protected VRML1ChildrenParsingAllowed: boolean;

VRML 1.0 children allowed to be added during parsing. This is used only by *Inline nodes for now, that do not allow reading children during parsing but may get new children in memory. So their VRML1ChildrenParsingAllowed must be empty, but VRML1ChildrenAllowed must allow all.

When VRML1ChildrenAllowed is False then VRML1ChildrenParsingAllowed should also be False.

Default False.

Methods

Protected function DeepCopyCore(CopyState: TX3DNodeDeepCopyState): TX3DNode; virtual;

Does actual DeepCopy work. You can override this to copy some more properties for descendants.

Protected function DeepCopyCreate(CopyState: TX3DNodeDeepCopyState): TX3DNode; virtual;

This should be a mere call to constructor of your own class.

In TX3DNode, this simply calls default virtual constructor, which is Ok for all normal nodes. But we have some special nodes, like TX3DPrototypeNode or TX3DUnknownNode, that simply cannot be created by default constructor. They need to override this.

Protected procedure AddFunctionality(const F: TNodeFunctionality);

Register new TNodeFunctionality instance to be returned by Functionality, and automatically freed when this node is freed.

Protected class function VRML1ChildrenSaveToStream: boolean; virtual;

Should SaveToStream save our VRML1Children. In this class default implementation returns True, this is what you will want in 99% of cases. It's useful to set this to false if you use VRML1Children internally, e.g. *Inline nodes.

Protected function DirectEnumerateActive( Func: TEnumerateChildrenFunction): Pointer; virtual;

Enumerate all active child nodes of given node.

"Active nodes" are the ones affecting current look or collisions, e.g. from Switch node only one child will be enumerated. See Traverse for more precise definition.

"Direct" means that this enumerates only direct descendants, i.e. this is not recursive. See methods like Traverse or EnumerateNodes if you want recursive behavior.

This can enumerate both VRML1Children nodes and nodes within TSFNode and TMFNode fields.

Default implementation in this class enumerates all Children nodes of VRML 1.0. If you need to remove some children for VRML 1.0 (e.g. for Switch or LOD nodes) or add some children for VRML 2.0 you have to override this. You do not need to call inherited when overriding this — in fact, you should not, if you want to omit some nodes.

Stops and returns immediately if Func returns non-nil for some child.

Protected function DirectEnumerateActiveForTraverse( Func: TEnumerateChildrenFunction; StateStack: TX3DGraphTraverseStateStack): Pointer; virtual;

Enumerate all active child nodes of given node, and may additionally modify StateStack. It's used by Traverse.

Default implementation in this class simply calls DirectEnumerateActive, ignoring StateStack, and this is suitable for 99% of nodes. However, for some special nodes (only Collision node for now), they have to modify state during traversing into various children, and then they can override this.

Stops and returns immediately in Func returns non-nil for some child.

Protected function DirectEnumerateAll( Func: TEnumerateChildrenFunction): Pointer;

Simply enumerate all direct descendant nodes. That is, all children in VRML 1.0 style and all nodes in SFNode and MFNode fields. This includes prototype stuff, if this node is expanded from prototype: PrototypeInstanceSourceNode and PrototypeInstanceHelpers.

Protected function DirectEnumerate( Func: TEnumerateChildrenFunction; OnlyActive: boolean): Pointer;

This enumerates direct descendant nodes of this node. This is equivalent to DirectEnumerateActive or DirectEnumerateAll, depending on value of OnlyActive param.

Protected procedure BeforeTraverse(StateStack: TX3DGraphTraverseStateStack); virtual;

Override these methods to determine what happens when given node is traversed during Traverse call. The main use of this is to operate on TX3DGraphTraverseStateStack.

Remember to always call inherited when overriding. In BeforeTraverse and MiddleTraverse you should call inherited at the beginning, in AfterTraverse inherited should be called at the end.

Besides changing StateStack.Top fields, you can do push/pop on the stack. Remember that if you do StateStack.Push in BeforeTraverse, and then you must call StateStack.Pop in AfterTraverse.

Protected procedure MiddleTraverse(StateStack: TX3DGraphTraverseStateStack); virtual;
 
Protected procedure AfterTraverse(StateStack: TX3DGraphTraverseStateStack); virtual;
 
Protected function ParseNodeBodyElement(Lexer: TX3DLexer; Reader: TX3DReaderNames; const APositionInParent: Integer): boolean; virtual;

Parse VRML node body element. Usually, this is a field. May also be VRML 1.0 style child node. May also be VRML 2.0 Script node interface declaration, etc. — see VRML 2.0 grammar spec.

This should be overriden to parse special features within particular nodes. While generally VRML is very clean and there's no need to override this, there's one use for this currently:

  1. Since we handle a couple of VRML flavors (at least Inventor, VRML 1.0 and VRML 97), sometimes the same node has different fields to express the same things in various VRML flavors. So it may be useful to parse a field and copy it's value into other fields.

    Example: TShapeHintsNode_1 in Inventor parses "hints" field, and copies it's value to other fields as appropriate. "hints" field is not exposed in TShapeHintsNode_1 interface, so everything is clean in the interface, and under the hood TShapeHintsNode_1 can "magically" handle "hints" field for Inventor.

When overriding, always check inherited result first, and exit if inherited handled successfully. Otherwise either read your stuff and return True (Lexer should advance to the position of next "nodeBodyElement"). Or return False without changing Lexer position.

Protected procedure ParseAfter(Reader: TX3DReaderNames); virtual;

Called at the end of parsing this node (including children) in any encoding.

Protected procedure CreateNode; virtual;
 
Protected procedure GroupBeforeTraverse(const State: TX3DGraphTraverseState; var WasPointingDeviceSensor: Boolean); virtual;

React when this node is processed as an immediate child of a grouping node, within grouping node's BeforeTraverse.

Public function FieldsCount: Integer;
 
Public procedure AddField(const Value: TX3DField);
 
Public function IndexOfField(const AName: string): Integer;
 
Public function EventsCount: Integer;
 
Public procedure AddEvent(const Value: TX3DEvent);
 
Public function IndexOfEvent(const AName: string): Integer;
 
Public function Field(const AName: string; const RaiseOnError: Boolean = false): TX3DField;

Search by name for given field. When RaiseOnError=false (default) returns Nil when not found. When RaiseOnError=true raises EX3DNotFound when not found.

Exceptions raised
EX3DNotFound
Public function FieldOrEvent(const AName: string; const RaiseOnError: Boolean = false): TX3DFieldOrEvent;

Search by name for given field or event (exposed by some field or not). When RaiseOnError=false (default) returns Nil when not found. When RaiseOnError=true raises EX3DNotFound when not found.

Exceptions raised
EX3DNotFound
Public function AnyEvent(const AName: string; const RaiseOnError: Boolean = false): TX3DEvent;

Search by name for given event (exposed by some field or not). When RaiseOnError=false (default) returns Nil when not found. When RaiseOnError=true raises EX3DNotFound when not found.

Exceptions raised
EX3DNotFound
Public function VRML1ChildrenCount: integer;
 
Public procedure VRML1ChildAdd(const Index: Integer; const Child: TX3DNode); overload;

Add a VRML 1.0 child node at given position. Index (position) must be in [0..VRML1ChildrenCount]. Items at and above Index position are moved to the right, to insert new child at Index position.

Public procedure VRML1ChildAdd(const Child: TX3DNode); overload;

Add a VRML 1.0 child node at the end of VRML1Children list.

Public procedure VRML1ChildRemove(const I: Integer);
 
Public procedure VRML1ChildrenClear;
 
Public function VRML1ChildExtract(const I: Integer): TX3DNode;

Remove a VRML 1.0 children at index I and return it (do not free it). Compare this with VRML1Remove, that removes children I and frees it if it's no longer used by anything.

This removes children I, appropriately adjusting all parent / children links, but even if a node is unused after removing, it is not freed. It's always returned.

Public function VRML1ParentsCount: integer;
 
Public function ParentFieldsCount: Integer;
 
Public procedure FreeRemovingFromAllParents;

Free this object (if it's not Nil) also removing it from all parent nodes and fields.

By design, normal destructor (Destroy called by Free) doesn't care about removing references to this object from it's parents. That's because it's the parents that usually initialize freeing of their children, and they free child when it's reference count is 0. So this freeing method is special in this regard.

Use this if you really want to remove all node occurrences from the middle of VRML hierarchy.

Public procedure FreeIfUnused;

Free this node if it is not referenced by any parent fields or nodes. Takes into account that node may have VRML 1.0 parent nodes and VRML 2.0 / X3D parent fields (SFNode or MFNode). This is a safe way of removing a node that may, but doesn't have to, be part of some VRML/X3D graph. The idea is that if a node is a part of some graph, we don't need to do anything (since you should have a reference to the entine graph somewhere anyway), otherwise node is considered unused and freed.

Analogous to standard TObject.Free, this also works when called on a Nil value (does nothing in this case).

For safety, it's advised to set reference to Nil after calling FreeIfUnused. You can use FreeIfUnusedAndNil utility for this (that employs a trick to Nil the visible reference even before freeing, which is even safer). This is analogous to standard FreeAndNil.

Public procedure KeepExistingBegin;
 
Public procedure KeepExistingEnd;
 
Public function PathFromBaseUrl(const RelativePath: string): string;

Returns an absolute path, assuming that RelativePath is relative path from BaseUrl or that RelativePath is already absolute.

Public procedure Parse(Lexer: TX3DLexer; Reader: TX3DReaderNames); virtual;

Parse node. This should set values of your fields, VRML 1.0 Children list, BaseUrl.

In special cases like TX3DUnknownNode this may actually initialize whole Fields list (by VRML 1.0 "fields" extensibility feature).

Public procedure ParseXML(Element: TDOMElement; Reader: TX3DReaderNames);

Parse node body, i.e. mainly node's fields.

Public constructor Create(const AX3DName: string = ''; const ABaseUrl: string = ''); virtual;

Constructor. Initializes various properties:

  • Name, BaseUrl are initialized from given parameters.

  • The Fields, Events lists are filled in every descendant, to have all the fields/events defined by the specification.

  • DefaultContainerField, and other node-specific stuff, is filled in descendants. This is actually implemented in CreateNode, that is called at the end of this constructor.

Public destructor Destroy; override;
 
Public function X3DType: string; virtual;

Type of the node in X3D, like 'Group' or 'Shape'. Never empty. Constant for the class lifetime (even for special TX3DUnknownNode and TX3DPrototypeNode, where this is calculated at runtime).

Note that VRML/X3D is generally case-sensitive, so this property is too.

In TX3DNode, this returns ClassX3DType, which is suitable for most nodes. See ClassX3DType.

Public function NodeTypeName: string; deprecated 'use X3DType';

Warning: this symbol is deprecated: use X3DType

 
Public class function ClassX3DType: string; virtual;

Node type name in VRML/X3D, for this class. Normal VRML/X3D node classes should override this to return something non-empty, and then X3DType automatically will return the same value.

Empty for classes that don't have a hardcoded VRML/X3D node name, like a special TX3DUnknownNode. Such special classes should override then X3DType to return actual non-empty name there.

You usually should call X3DType. The only use of this method is that it works on classes (it's "class function"), without needing at actual instance.

Public function Traverse( NodeClass: TX3DNodeClass; TraversingFunc: TTraversingFunc): Pointer;

Traverse all the nodes of VRML graph that are active.

An "active" part of the VRML graph are the nodes that actually change what the VRML file represents, in terms of geometry, collision detection etc. For example, the Switch node has only one child usually active. Nodes that merely influence the active graph by some events and routes do not have to be active (these nodes may change what the VRML file actually represents, but only by changing other nodes).

For all nodes of NodeClass TraversingFunc will be called. If if returns non-nil for some node, the processing of following nodes (children and siblings) will be aborted and result will be returned.

Traverse not only enumerates these nodes, it also collects all state (transformation, etc — see TX3DGraphTraverseState) that affects how given node should be presented.

Also, TraversingInfo is passed to each TraversingFunc call. This allows you to investigate, during TraversingFunc call, the parents hierarchy (you can't use VRML1Parents / ParentFields of the current node, since a node may have many parents). Traverse calls are naturally recursive, and so the stack of TraversingInfo structures is naturally build and destroyed by recursive calls. For the root node (the one where you called Traverse without specifying initial TraversingInfo), ParentInfo is simply Nil.

The scheme of how Traverse works:

BeforeTraverse;

TraverseIntoChildren := true;
if Self is NodeClass then TraversingFunc (Self, State, TraverseIntoChildren);

MiddleTraverse;

if TraverseIntoChildren is still true then
  for all children returned by DirectEnumerateActive
    call their Traverse(State);

AfterTraverse;

Add Self to State.VRML1State (for VRML 1.0 state nodes);

Note: setting TraverseIntoChildren to false means that some part of the tree is explicitly omitted from traversing. Use this only if you know what you're doing, as for some nodes they actually affect their parents too (for example, chilren within VRML 1.0 Group affect other nodes too; global lights within VRML >= 2.0 affect all nodes; and so on...). Usually, you will use this only for separator-like nodes (for VRML >= 2.0, all Group, Transform, Switch etc. act like separators), and only when you will somehow traverse into these nodes anyway.

We guarantee that AfterTraverse will be called if BeforeTraverse was called and finished (that is, AfterTraverse is called in the finally..end).

During traversing, you can only modify the children (direct or not) nodes of the current node.

Public function TraverseInternal(StateStack: TX3DGraphTraverseStateStack; NodeClass: TX3DNodeClass; TraversingFunc: TTraversingFunc; ParentInfo: PTraversingInfo): Pointer;

Like Traverse, but it takes explicit starting state stack and starting ParentInfo. Not generally useful, use only for special purposes.

Public function TraverseIntoChildren(StateStack: TX3DGraphTraverseStateStack; NodeClass: TX3DNodeClass; TraversingFunc: TTraversingFunc; ParentInfo: PTraversingInfo): Pointer;

Like Traverse, but only enters children. This does the job of Traverse normally omitted if your Traverse callback returns TraverseIntoChildren = False. Using this method, you can traverse into children explicitly from your callback.

Public procedure EnumerateNodes( proc: TX3DNodeProc; OnlyActive: boolean); overload;

Enumerate all our children of some class. Recursively. Enumerates also this instance (Self), if it satisfies the NodeClass and SeekNodeName conditions.

This enumerates both VRML 1.0 children (VRML1Children) as well as VRML >= 2.0 (including X3D) children (nodes in TSFNode and TMFNode fields).

If OnlyActive then it will enumerate only active parts of the graph ("active" as defined by Traverse), so it will work as a simpler version of Traverse (simpler, because it doesn't track any state).

If not OnlyActive then it will simply enumerate all nodes. This will include then also prototype helpers, if this node was expanded from prototype: see PrototypeInstanceSourceNode and PrototypeInstanceHelpers.

If you give SeekNodeName parameter, we'll only look for nodes with X3DName = SeekNodeName. When SeekNodeName = '' it, consistently, looks for unnamed nodes (where X3DName = '').

Enumerates children only after enumerating Self. So you can modify children before enumerating them in the Proc callback. You can only modify your children in the Proc callback.

Public procedure EnumerateNodes(nodeClass: TX3DNodeClass; proc: TX3DNodeProc; OnlyActive: boolean); overload;
 
Public procedure EnumerateNodes(nodeClass: TX3DNodeClass; const SeekNodeName: string; proc: TX3DNodeProc; OnlyActive: boolean); overload;
 
Public function SearchNodes(const Proc: TX3DNodeSearchProc; const OnlyActive: boolean): Pointer;

Search nodes, like enumerating nodes but allows early exit during the enumeration. We search for a node for which Proc(Node) returns something non-nil.

For every node, the given Proc callback is run. If the Proc callback returns something non-nil, the enumeration of the following nodes stops, and we return the callback result.

Public function TryFindNodeByName(FindClass: TX3DNodeClass; const FindName: string; OnlyActive: boolean): TX3DNode; deprecated 'use FindNode';

Warning: this symbol is deprecated: use FindNode

TryFindNodeByName and TryFindNode seek for a node with given class (and node name, in case of TryFindNodeByName). If OnlyActive then they seek among only active nodes ("active" as defined by Traverse), otherwise all nodes.

These functions are quite like EnumerateNodes, except they stop at the first occurrence and return it.

TryFindNodeByName and TryFindNode return Nil if such node is not found. FindNodeByName and FindNode raise exception EX3DNotFound in this case.

Exceptions raised
EX3DNotFound
FindNodeByName and FindNode raise this exception when node is not found.
Public function FindNodeByName(FindClass: TX3DNodeClass; const FindName: string; OnlyActive: boolean): TX3DNode; deprecated 'use FindNode';

Warning: this symbol is deprecated: use FindNode

 
Public function TryFindNode(FindClass: TX3DNodeClass; OnlyActive: boolean): TX3DNode; deprecated 'use FindNode';

Warning: this symbol is deprecated: use FindNode

 
Public function FindNode(FindClass: TX3DNodeClass; OnlyActive: boolean): TX3DNode; overload; deprecated 'use FindNode';

Warning: this symbol is deprecated: use FindNode

 
Public function FindNode(const NodeClass: TX3DNodeClass; const FindName: string; const Options: TFindNodeOptions = []): TX3DNode; overload;

Find a node by name and class, in this node and children (recursively).

By default it searches both active and inactive graph parts. Add fnOnlyActive to search only in active parts.

Exceptions raised
EX3DNotFound
When node is not found. Unless fnNilOnMissing in Options, then it returns Nil on missing node, and EX3DNotFound is never raised.
Public function FindNode(const FindName: string): TX3DNode; overload; deprecated 'use FindNode(NodeClass, FindName)';

Warning: this symbol is deprecated: use FindNode(NodeClass, FindName)

 
Public function TryFindNodeState( NodeClass: TX3DNodeClass; out Node: TX3DNode; out State: TX3DGraphTraverseState): boolean; deprecated 'use FindNode to look for nodes easier; or iterate over TCastleScene.Shapes.TraverseList if you really need to know nodes with their TX3DGraphTraverseState';

Warning: this symbol is deprecated: use FindNode to look for nodes easier; or iterate over TCastleScene.Shapes.TraverseList if you really need to know nodes with their TX3DGraphTraverseState

Find the first node with given class (NodeClass), return it's state or just transformation. Similar to Traverse, but stops as soon as the given node is found.

Returns False when not found ("out" parametrs Node, State and Transform are undefined then).

Public function TryFindNodeTransform( NodeClass: TX3DNodeClass; out Node: TX3DNode; out Transform: TMatrix4; out TransformScale: Single): boolean; deprecated 'use FindNode to look for nodes easier; or iterate over TCastleScene.Shapes.TraverseList if you really need to know nodes with their transformations';

Warning: this symbol is deprecated: use FindNode to look for nodes easier; or iterate over TCastleScene.Shapes.TraverseList if you really need to know nodes with their transformations

 
Public function TryFindParentByName(const FindName: string): TX3DNode;

Seeks Self and parent nodes (from VRML1Parents and ParentFields, recursively) for given node name.

In other words, this is similar to TryNodeByName or NodeByName, but it goes "upward" in graph hierarchy. Note that this never restricts itself only to "active" graph part ("active" as defined by Traverse) because you really can't detect what is the "active" part of the graph when going upward.

Exceptions raised
EX3DNotFound
FindParentByName raises this exception when node is not found.
Public function FindParentByName(const FindName: string): TX3DNode;
 
Public function HasParentNode(Node: TX3DNode): boolean;

Looks for a given Node in parents (and self), recursively. Similar to TryFindParentByName. Returns True only if found.

Public function TryFindDirectParentByName(const FindName: string): TX3DNode;

Search immediate parents of this node for a node with given FindName. Returns Nil if not found.

Public function IsNodePresent(Node: TX3DNode; OnlyActive: boolean): boolean;

Looks for a given node in our children (direct and not, including self). If OnlyActive, then only active parts are searched ("active" as defined by Traverse).

Public function NodesCount(NodeClass: TX3DNodeClass; CountOnlyActiveNodes: boolean): integer;

Count the occurrences of given node class in our children. For example, you can pass NodeClass = TAbstractLightNode to count the light sources in the scene.

If CountOnlyActiveNodes, then only active parts are searched ("active" as defined by Traverse).

This traverses both VRML 1.0 children nodes and VRML 2.0 nodes inside SFNode and MFNode fields.

Public procedure SaveToStream(Writer: TX3DWriter); override;

Save node to a stream. Saves everything, including node name, node type, and node contents.

Public class function VRML1StateNode(out StateNode: TVRML1StateNode): boolean;

Do the nodes of (exactly) this class should be included in VRML 1.0 state (see TX3DGraphTraverseState.VRML1State).

Public class function ForVRMLVersion(const Version: TX3DVersion): boolean; virtual;

Some nodes are present only in specific VRML/X3D version. This functions decides it.

For example some nodes can only work in VRML < 2.0, some others only in VRML >= 2.0. There are even some pairs of nodes: for example TConeNode_1 works with VRML < 2.0, TConeNode works with VRML >= 2.0.

NodesManager will use this.

Default implementation of this function returns always True. Generally, I don't try to set this too aggresively — in other words, for all cases when it's sensible, I allow nodes to be used in every VRML/X3D version, even when official specification doesn't. This means that when reading VRML 1.0 files actually a large part of VRML 2.0 is allowed too, and also while reading VRML 2.0 many constructs from VRML 1.0 (officially no longer present in VRML 2.0) are allowed too. I'm trying to support what I call a "sum of VRML 1.0 and 2.0".

In practice I only use this function when various VRML/X3D versions specify the same node name but

  • With different fields.

    For example Cone and Cylinder have slightly different fields, due to the fact that VRML 2.0 resigned from using TSFBitMask fields.

  • With different behavior.

    For example definitions of Sphere for VRML 1.0 and 2.0 are practically equal. However, the behavior from where to take texture and material info is different — in VRML 1.0 we take last Texture2, Material etc. nodes, while in VRML 2.0 we look in parent Shape's "appearance" field. So once again two different Sphere classes are needed.

Public function EnumerateReplaceChildren( Func: TEnumerateReplaceNodesFunction): Cardinal;

Enumerates all children nodes (recursively), allowing you to decide for each node to replace or remove it.

So this is something like EnumerateNodes, except that it allows you to remove the nodes. It always enumerates all nodes, not only active (e.g. it enumerates all Switch node children, not only the chosen one).

Note that (unlike regular EnumerateNodes) this doesn't report Self to Func !. Which is natural, since this may remove nodes by normal VRML1ChildRemove calls, so it needs to know ParentNode of the removed node.

For each node Func will be called, with ParentNode and Node set. If you change the Node to something else, then the old node will be removed and new Node inserted in the same place. If new Node is Nil, then only the old node will be removed.

Nodes are traversed in depth-first search. Node is first reported to Func, and then (if it's not replaced) we descend into this Node.

Returns

The number of removed (and possibly replaced) nodes.

Public function RemoveChildrenWithMatchingName( const Wildcard: string; IgnoreCase: Boolean): Cardinal;

Removes all children (and their children, recursively) with node names matchig Wildcard. You can use * and ? special chars in the Wildcard.

Returns

The number of removed nodes.

Public function PrototypesCount: Integer;
 
Public procedure AddPrototype(const Value: TX3DPrototypeBase);
 
Public function RoutesCount: Integer;
 
Public procedure AddRoute(const Value: TX3DRoute); overload;
 
Public procedure AddRoute(const Source, Destination: TX3DFieldOrEvent); overload;
 
Public function ImportsCount: Integer;
 
Public procedure AddImport(const Value: TX3DImport);
 
Public function ExportsCount: Integer;
 
Public procedure AddExport(const Value: TX3DExport);
 
Public function DeepCopy: TX3DNode;

Create a deep copy of this node and all it's children.

New copy is completely independent from original, having all children nodes (in both VRML 1.0 sense (Children) and VRML >= 2.0 (inside SFNode and MFNode fields)) also duplicated. New copy has protypes, routes, interface declarations and generally everything established like in the original, using copied nodes.

Doesn't copy things which are dependent on container hierarchy. (So copying them would be more dangerous than useful.) This means: DestructionNotifications, Scene, VRML1Parents, ParentFields. VRML1Parents and ParentFields will be set for children anyway (to appropriate copies).

Caller owns this newly created copy — as returned by this method, it's not linked anywhere.

Public procedure AddDestructionNotification(const Event: TNodeDestructionNotification);

Callbacks registered here will be called when this node is destroyed.

Public procedure RemoveDestructionNotification(const Event: TNodeDestructionNotification);
 
Public procedure PostAddInterfaceDeclaration(IDecl: TX3DInterfaceDeclaration); virtual;

This will be always called by VRML parsers after adding new item to our InterfaceDeclarations.

In this class, this simply adds IDecl.FieldOrEvent to our normal fields/events by IDecl.AddFieldOrEvent. You may override this in subclasses to react in some special way to new fields/events, for example Script node may register here to receive notification when input event is received.

Public procedure AddCustomField(AField: TX3DField);

Add to node InterfaceDeclarations given field. This should only be used with nodes having HasInterfaceDeclarations = True, like Script or ComposedShader.

Public procedure AddCustomFieldOrEvent(AFieldOrEvent: TX3DFieldOrEvent);

Add to node InterfaceDeclarations given field or event. This should only be used with nodes having HasInterfaceDeclarations = True, like Script or ComposedShader.

Public function NiceName: string;

Nice and concise node description for user. Shows node type and name.

Public procedure UnregisterScene;

Detach this node from parent scene, recursively. Useful if you take a node and want to put it in another TCastleSceneCore.

You almost never need to call this method from your application. This is done automatically for you when TCastleSceneCore is destroyed. And a node can only be part of one TCastleSceneCore instance at one time.

Notable exceptions when you need to call this:

  1. If you process RootNode graph and extract some node from it (that is, delete node from one RootNode graph, but instead of freeing it you insert it into some other VRML/X3D graph) you must call it to manually detach this node (and all it's children) from a previous TCastleSceneCore instance.

  2. Right now the TCastleSceneCore doesn't call RootNode.UnregisterScene when TCastleSceneCore.OwnsRootNode. This is done for speed, because it's not needed in 99% cases.

    However, if your scene contains some node that isn't freed because of KeepExistingBegin, then such node will remain attached to non-existing scene. You should call UnregisterScene on such node manually, for now.

Public function FieldSetByEvent(const Event: TX3DEvent): TX3DField; virtual;

Find field set by given event of this node. Nil if not found (including when this Event doesn't actually belong to this node).

Public function FieldSendingEvent(const Event: TX3DEvent): TX3DField; virtual;

Find field that sends given event of this node. Nil if not found (including when this Event doesn't actually belong to this node).

Public function Functionality( const FunctionalityClass: TNodeFunctionalityClass): TNodeFunctionality;

Return an instance performing given functionality of this class (like a fog, transformation, material...), or Nil if none. This implements a simple component system inside TX3DNode, allowing some functionality to have common interface and implementation across a few nodes that are not otherwise related in the ancestor hierarchy.

Descendants should register TNodeFunctionality classes using AddFunctionality.

Properties

Protected property CDataField: TMFString read FCDataField write FCDataField;

The field where CDATA section from XML is added. Used when loading X3D in XML encoding: XML elements may contain CDATA sections, that are added to "url" field. See X3D XML encoding specification about "Encapsulating Script node code" [http://www.web3d.org/x3d/specifications/ISO-IEC-19776-1.2-X3DEncodings-XML/Part01/concepts.html#EncapsulatingScriptNodeCode]. We also allow this for shader nodes (sensible (follows the intention of the spec) and compatible with InstantReality).

When not assigned, then CDATA section for this node is not allowed.

This should be set in descendants constructor.

Public property Fields [constIndex:Integer]: TX3DField read GetFields;

Node fields.

For normal nodes, all fields are created and added using AddField from the constructor. Fields default values are set, and current field values are set to these defaults. Later, we only modify these fields current values (e.g. when parsing).

However, there are special node classes that set their fields differently. TX3DPrototypeNode has their fields set according to it's VRML 2.0 prototype. TX3DUnknownNode may have it's fields set by VRML 1.0 "fields" feature (so it's Fields are initialized by parsing it).

Nodes with HasInterfaceDeclarations have some Fields and Events added when reading node.

All fields on this list are owned by this instance.

Public property Events [constIndex:Integer]: TX3DEvent read GetEvents;

Explicit events (that is, not exposed by some field) of this node. For exposed events, see each field's property ExposedEvents.

Public property VRML1Children [constI:Integer]: TX3DNode read GetVRML1Child write SetVRML1Child;

VRML 1.0 children nodes. These are nodes directly specified inside a VRML 1.0 node, they don't belong to any node field. (In VRML 1.0, there was no SFNode / MFNode fields.)

In VRML 2.0, this is always empty.

VRML 1.0 nodes may have any number of children. The children nodes refer back to it's parent nodes in VRML1Parents list. When travelling over VRML/X3D graph, remember that cycles are possible, because of DEF/USE. Obviously, they possible when travelling along the VRML1Parents list. We currently assume that there are no cycles when we treat the graph as directed, but it may change one day (some VRML/X3D models create real cycles).

Adding/removing stuff from the VRML1Children list keeps track of how many times a node is used. If the child node has no parents, it will be freed. Actually, nodes can be children of both nodes (VRML 1.0 style, then VRML1Children and VRML1Parents is used) or fields (TMFNode or TSFNode, in VRML 2.0 style; then ParentFields is used). So the node is freed only when it's not referenced by any node and not referenced by any field. Generally, it's the parent that takes care of reference-counting and freeing the children, not the other way around.

Note that given node instance may be a children of a single node multiple times, through DEF/USE mechanism. The order of children is important and preserved. (On the other hand, the order of VRML1Parents is not important, as that list is mostly for reference-counting.)

You can replace one children with another like VRML1Children[I] := NewChildren;. This works like a shortcut for VRML1ChildRemove(I); VRML1ChildAdd(I, NewChildren);. But 1. it's more efficient; 2. it's safer — if Children[I] is already equal to NewChildren, it does nothing.

Public property VRML1Parents [constI:Integer]: TX3DNode read GetVRML1Parent;

All VRML 1.0 parent nodes. VRML1Parents is a reverse of VRML1Children — it lists all the nodes where we are on VRML1Children list.

Public property ParentFields[Index:Integer]: TX3DField read GetParentFieldsItem;

All SFNode and MFNode fields where this node is referenced. This is somewhat analogous for VRML1Parents, but for VRML 2.0.

ParentFieldsNode is just for your comfort, it returns always appropriate field's ParentNode property value (i.e. (ParentField[Index] as TSFNode).ParentNode or (ParentField[Index] as TMFNode).ParentNode).

Public property ParentFieldsNode[Index:Integer]: TX3DNode read GetParentFieldsNodeItem;
 
Public property KeepExisting: Cardinal read FKeepExisting write FKeepExisting;

Increase KeepExisting property value to disable automatic freeing of the node when unused. This may be useful in cases when you remove the node from VRML graph hierarchy, but you want to keep a valid reference to it anyway (for example, maybe you'll free it later by hand or add it somewhere else).

Simple methods KeepExistingBegin and KeepExistingEnd simply increase / decrease KeepExisting value by 1. This is the most usual usage.

Public property X3DName: string read FX3DName write FX3DName;

Name of this node. When saving/loading, this comes from VRML/X3D "DEF" construct. Empty value means that the name is not defined. Do not change this during loading / saving of the X3D graph, or searching for nodes e.g. by EnumerateNodes.

Note that this property is deliberately not called Name. In the future, this class may descend from the standard TComponent class, that defines a Name field with a special restrictions (it must be a valid Pascal identifier), which cannot apply to X3D node names (that can have quite free names, see http://www.web3d.org/documents/specifications/19776-2/V3.3/Part02/grammar.html ). We don't want to confuse these two properties.

Public property NodeName: string read FX3DName write FX3DName; deprecated 'use X3DName';

Warning: this symbol is deprecated: use X3DName

 
Public property BaseUrl: string read FBaseUrl write FBaseUrl;

Base URL for all URLs inside our fields. Used everywhere as a base for relative URLs, to handle fields that refer to external files like textures, other 3D models (ImageTexture, Inline nodes, many others).

It must be an absolute URL. Currently, it doesn't have to contain a protocol, and is then interpreted as a path on local filesystem (just like it had file:// prefix). Still, it must be an absolute path.

This is set in constructor, and eventually adjusted by various parsing routines. This way we could, if only we would like to, resolve nodes like Inline or ImageTexture immediately after parsing them.

Public property WWWBasePath: string read FBaseUrl write FBaseUrl; deprecated;

Warning: this symbol is deprecated.

Old deprecated name for BaseUrl.

Public property Prototypes [constIndex:Integer]: TX3DPrototypeBase read GetPrototypes;
 
Public property Routes [constIndex:Integer]: TX3DRoute read GetRoutes;
 
Public property ImportsList [constIndex:Integer]: TX3DImport read GetImports;
 
Public property ExportsList [constIndex:Integer]: TX3DExport read GetExports;
 
Public property PrototypeInstance: boolean read FPrototypeInstance;

PrototypeInstance = True indicates that this node was created from a non-external prototype instantiation.

Then PrototypeInstanceSourceNode is non-nil and indicates parsed prototype node (and PrototypeInstanceSourceNode.Prototype gives you even a link to the actual prototype specification).

PrototypeInstanceSourceNode is used for events: any ROUTEs specified outside of prototype and leading to/from instantiated prototype should actually lead to PrototypeInstanceSourceNode events (not to events of Self). Reason: prototype events may be different than actual expanded node events, and ROUTEs want to lead to prototype events. This is implemented when expanding prototype (TX3DPrototypeNode.Instantiate) and when linking ROUTE (TX3DRoute.SetSource, TX3DRoute.SetDestination).

PrototypeInstanceHelpers may be Nil if empty, or may contain a list of other nodes duplicated along with the main prototype node. From VRML spec:

Any other nodes and accompanying scene graphs are not part of the transformation hierarchy, but may be referenced by ROUTE statements or Script nodes in the prototype definition.

Note that for TX3DPrototypeNode (within PrototypeInstanceSourceNode) these have a little different meaning: they describe the nested prototype, if any, that was used to create this node. This may happen if the node was expanded from one prototype within another. (Usually, you shouldn't be concerned about this; see TX3DPrototypeNode.Instantiate implementation comments for gory details about this.)

Public property PrototypeInstanceSourceNode: TX3DPrototypeNode read FPrototypeInstanceSourceNode;
 
Public property PrototypeInstanceHelpers: TX3DNode read FPrototypeInstanceHelpers;
 
Public property DefaultContainerField: string read FDefaultContainerField write FDefaultContainerField;

Default value of "containerField" attribute for this node in X3D XML encoding.

Public property HasInterfaceDeclarations: TX3DAccessTypes read FHasInterfaceDeclarations write SetHasInterfaceDeclarations default [];

For some special VRML / X3D nodes (like Script, ComposedShader) that allow the definition of additional fields/events within.

In X3D specification this is marked like

# And any number of:
fieldType [in]     fieldName
fieldType [in,out] fieldName    initialValue
fieldType [out]    fieldName
fieldType []       fieldName    initialValue

If HasInterfaceDeclarations is not [], then InterfaceDeclarations will be non-nil and parser (classic VRML parser in this unit, X3D XML reader too) will read this from VRML files. Moreover, for each interface declaration, also appropriate field/event will be added to the list of Fields or Events, so fields/events created by interface declarations will function just like other standard fields everywhere.

Public property InterfaceDeclarations: TX3DInterfaceDeclarationList read FInterfaceDeclarations;
 
Public property Scene: TX3DEventsEngine read FScene write FScene;

Scene that will be notified about changes to this node. This is necessary to allow the scene to properly process VRML/X3D events, and also to react properly to any other changes to the nodes (like when you change some field directly by ObjectPascal code, e.g. by TX3DField.Send).

May be Nil if none.

A given TX3DNode may be renderable only by a single renderer. This means it can be placed only within one TCastleScene.

Public property TransformFunctionality: TTransformFunctionality read FTransformFunctionality;

Fast shortcut to Functionality(TTransformFunctionality).

Public property TimeFunctionality: TTimeDependentFunctionality read FTimeFunctionality;

Fast shortcut to Functionality(TTimeDependentFunctionality).

Public property GenTexFunctionality: TGeneratedTextureFunctionality read FGenTexFunctionality;

Fast shortcut to Functionality(TGeneratedTextureFunctionality).


Generated by PasDoc 0.16.0.