| Description | Hierarchy | Fields | Methods | Properties |
type TVRMLNode = class(TVRMLFileItem, IVRMLNode)
VRML node.
Descendant implementors note: Each descendant should override constructor to create and add his fields and events. Like Fields.Add(TSFFloat.Create('width', 2, true)). Also, you should define FdXxx properties that allow fast, comfortable and type-secure way to retrieve and set these fields.
![]() |
fAllowedChildren: boolean; |
![]() |
fParsingAllowedChildren: boolean; |
![]() |
function DeepCopyCore(CopyState: TVRMLNodeDeepCopyState): TVRMLNode; virtual; |
![]() |
function DeepCopyCreate(CopyState: TVRMLNodeDeepCopyState): TVRMLNode; virtual; |
![]() |
procedure DirectEnumerateActive( Func: TEnumerateChildrenFunction); virtual; |
![]() |
procedure DirectEnumerateAll( Func: TEnumerateChildrenFunction); |
![]() |
procedure DirectEnumerate( Func: TEnumerateChildrenFunction; OnlyActive: boolean); |
![]() |
procedure BeforeTraverse(var State: TVRMLGraphTraverseState); virtual; |
![]() |
procedure MiddleTraverse(State: TVRMLGraphTraverseState); virtual; |
![]() |
procedure AfterTraverse(var State: TVRMLGraphTraverseState); virtual; |
![]() |
function ParseNodeBodyElement(Lexer: TVRMLLexer; const APositionInParent: Integer): boolean; virtual; |
![]() |
procedure SaveContentsToStream(SaveProperties: TVRMLSaveToStreamProperties); virtual; |
![]() |
function FieldOrEvent(const Name: string): TVRMLFieldOrEvent; |
![]() |
function AnyEvent(const Name: string): TVRMLEvent; |
![]() |
function ChildrenCount: integer; |
![]() |
procedure AddChild(Index: Integer; child: TVRMLNode); overload; |
![]() |
procedure AddChild(child: TVRMLNode); overload; |
![]() |
procedure RemoveChild(i: integer); |
![]() |
procedure RemoveAllChildren; |
![]() |
function ExtractChild(I: Integer): TVRMLNode; |
![]() |
function ParentNodesCount: integer; |
![]() |
function ParentFieldsCount: Integer; |
![]() |
procedure FreeRemovingFromAllParents; |
![]() |
procedure FreeIfUnused; |
![]() |
function PathFromWWWBasePath(const RelativePath: string): string; |
![]() |
procedure Parse(Lexer: TVRMLLexer); virtual; |
![]() |
constructor Create(const ANodeName: string; const AWWWBasePath: string); virtual; |
![]() |
constructor CreateParse(const ANodeName: string; Lexer: TVRMLLexer); |
![]() |
destructor Destroy; override; |
![]() |
function NodeTypeName: string; virtual; |
![]() |
class function ClassNodeTypeName: string; virtual; |
![]() |
procedure Traverse( NodeClass: TVRMLNodeClass; TraversingFunc: TTraversingFunc; TraversingFuncAfter: TTraversingFunc = nil); |
![]() |
procedure EnumerateNodes( proc: TVRMLNodeProc; OnlyActive: boolean); overload; |
![]() |
procedure EnumerateNodes(nodeClass: TVRMLNodeClass; proc: TVRMLNodeProc; OnlyActive: boolean); overload; |
![]() |
procedure EnumerateNodes(nodeClass: TVRMLNodeClass; const SeekNodeName: string; proc: TVRMLNodeProc; OnlyActive: boolean); overload; |
![]() |
function TryFindNodeByName(FindClass: TVRMLNodeClass; const FindName: string; OnlyActive: boolean): TVRMLNode; |
![]() |
function FindNodeByName(FindClass: TVRMLNodeClass; const FindName: string; OnlyActive: boolean): TVRMLNode; |
![]() |
function TryFindNode(FindClass: TVRMLNodeClass; OnlyActive: boolean): TVRMLNode; |
![]() |
function FindNode(FindClass: TVRMLNodeClass; OnlyActive: boolean): TVRMLNode; |
![]() |
function TryFindNodeState( NodeClass: TVRMLNodeClass; out Node: TVRMLNode; out State: TVRMLGraphTraverseState): boolean; |
![]() |
function TryFindNodeTransform( NodeClass: TVRMLNodeClass; out Node: TVRMLNode; out Transform: TMatrix4Single; out AverageScaleTransform: Single): boolean; |
![]() |
function TryFindParentByName(const FindName: string): TVRMLNode; |
![]() |
function FindParentByName(const FindName: string): TVRMLNode; |
![]() |
function HasParent(Node: TVRMLNode): boolean; |
![]() |
function TryFindDirectParentByName(const FindName: string): TVRMLNode; |
![]() |
function IsNodePresent(Node: TVRMLNode; OnlyActive: boolean): boolean; |
![]() |
function NodesCount(NodeClass: TVRMLNodeClass; CountOnlyActiveNodes: boolean): integer; |
![]() |
procedure SaveToStream(SaveProperties: TVRMLSaveToStreamProperties); override; |
![]() |
class function TraverseStateLastNodesIndex: Integer; |
![]() |
class function ForVRMLVersion(const VerMajor, VerMinor: Integer): boolean; virtual; |
![]() |
function ChildrenField: TMFNode; virtual; |
![]() |
procedure SmartAddChild(Node: TVRMLNode); |
![]() |
function SmartChildrenCount: integer; |
![]() |
function SmartExtractChild(Index: Integer): TVRMLNode; |
![]() |
function SuggestedVRMLVersion( out VerMajor, VerMinor, SuggestionPriority: Integer): boolean; virtual; |
![]() |
class function ChildrenSaveToStream: boolean; virtual; |
![]() |
function EnumerateReplaceChildren( Func: TEnumerateReplaceNodesFunction): Cardinal; |
![]() |
function RemoveChildrenWithMatchingName( const Wildcard: string; IgnoreCase: Boolean): Cardinal; |
![]() |
function DeepCopy: TVRMLNode; |
![]() |
procedure Bind(NodeNameBinding: TStringList); |
![]() |
class function URNMatching(const URN: string): boolean; virtual; |
![]() |
procedure TraverseBlenderObjects( TraversingFunc: TBlenderTraversingFunc); overload; |
![]() |
property Fields: TVRMLFieldsList read FFields; |
![]() |
property Events: TVRMLEventsList read FEvents; |
![]() |
property Children[i: integer]: TVRMLNode
read GetChildrenItem write SetChildrenItem; |
![]() |
property ParentNodes[i: integer]: TVRMLNode read GetParentNodesItem; |
![]() |
property ParentFields[Index: Integer]: TVRMLField read GetParentFieldsItem; |
![]() |
property ParentFieldsNode[Index: Integer]: TVRMLNode
read GetParentFieldsNodeItem; |
![]() |
property AllowedChildren: boolean read fAllowedChildren default false; |
![]() |
property ParsingAllowedChildren: boolean
read fParsingAllowedChildren default false; |
![]() |
property NodeName: string read fNodeName write FNodeName; |
![]() |
property WWWBasePath: string read FWWWBasePath write FWWWBasePath; |
![]() |
property SmartChildren[Index: Integer]: TVRMLNode read GetSmartChildren; |
![]() |
property Prototypes: TVRMLPrototypeBasesList read FPrototypes; |
![]() |
property Routes: TVRMLRoutesList read FRoutes; |
![]() |
property PrototypeInstance: boolean read FPrototypeInstance; |
![]() |
property PrototypeInstanceSourceNode: TVRMLPrototypeNode
read FPrototypeInstanceSourceNode; |
![]() |
property PrototypeInstanceHelpers: TVRMLNode read FPrototypeInstanceHelpers; |
![]() |
property DefaultContainerField: string
read FDefaultContainerField write FDefaultContainerField; |
![]() |
property ExplicitContainerField: string
read FExplicitContainerField write FExplicitContainerField; |
![]() |
property HasInterfaceDeclarations: TVRMLAccessTypes
read FHasInterfaceDeclarations
write SetHasInterfaceDeclarations default []; |
![]() |
property InterfaceDeclarations: TVRMLInterfaceDeclarationsList
read FInterfaceDeclarations; |
![]() |
property CDataAllowed: boolean read FCDataAllowed write FCDataAllowed; |
![]() |
property CDataExists: boolean read FCDataExists write FCDataExists; |
![]() |
property CData: string read FCData write FCData; |
![]() |
property DestructionNotifications: TDynNodeDestructionNotificationArray
read FDestructionNotifications; |
![]() |
property ParentEventsProcessor: TObject
read FParentEventsProcessor write FParentEventsProcessor; |
![]() |
fAllowedChildren: boolean; |
![]() |
fParsingAllowedChildren: boolean; |
![]() |
function DeepCopyCore(CopyState: TVRMLNodeDeepCopyState): TVRMLNode; virtual; |
|
Does actual DeepCopy work. You can override this to copy some more properties for descendants. | |
![]() |
function DeepCopyCreate(CopyState: TVRMLNodeDeepCopyState): TVRMLNode; virtual; |
|
This should be a mere call to constructor of your own class. In TVRMLNode, this simply calls default virtual constructor, which is Ok for all normal nodes. But we have some special nodes, like TVRMLPrototypeNode or TVRMLUnknownNode, that simply cannot be created by default constructor. They need to override this. | |
![]() |
procedure DirectEnumerateActive( Func: TEnumerateChildrenFunction); virtual; |
|
This enumerates all active child nodes of given node. "Active nodes" are the ones affecting current VRML graph 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 Children nodes in VRML 1.0 style and nodes within TSFNode and TMFNode fields. Default implementation in this class returns 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're not required to call inherited when overriding this. | |
![]() |
procedure DirectEnumerateAll( Func: TEnumerateChildrenFunction); |
|
This simply enumerates all direct descendant nodes of this node. I.e. 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. | |
![]() |
procedure DirectEnumerate( Func: TEnumerateChildrenFunction; OnlyActive: boolean); |
|
This enumerates direct descendant nodes of this node. This is equivalent to DirectEnumerateActive or DirectEnumerateAll, depending on value of OnlyActive param. | |
![]() |
procedure BeforeTraverse(var State: TVRMLGraphTraverseState); virtual; |
|
You can override these methods to determine what happens when given node is traversed during Traverse call. The main use of this is to modify TVRMLGraphTraverseState. Remember to always call inherited when overriding. In Besides changing State fields, you can even replace the curent State instance in | |
![]() |
procedure MiddleTraverse(State: TVRMLGraphTraverseState); virtual; |
![]() |
procedure AfterTraverse(var State: TVRMLGraphTraverseState); virtual; |
![]() |
function ParseNodeBodyElement(Lexer: TVRMLLexer; 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:
When overriding, always check inherited result first, and exit if inherited handled successfully. Otherwise either read your stuff and return | |
![]() |
procedure SaveContentsToStream(SaveProperties: TVRMLSaveToStreamProperties); virtual; |
|
This will be called by SaveToStream within { }. Usually you want to save here what you read in your overridden ParseNodeBodyElement. | |
![]() |
function FieldOrEvent(const Name: string): TVRMLFieldOrEvent; |
|
Search by name for given field or event (exposed by some field or not).
| |
![]() |
function AnyEvent(const Name: string): TVRMLEvent; |
|
Search by name for given event (exposed by some field or not).
| |
![]() |
function ChildrenCount: integer; |
![]() |
procedure AddChild(Index: Integer; child: TVRMLNode); overload; |
|
AddChild z Index (musi byc w zakresie 0..ChildrenCount) przesuwa elementy o numerach Index i wiekszych w prawo i wstawia child na wskazane Index. | |
![]() |
procedure AddChild(child: TVRMLNode); overload; |
|
| |
![]() |
procedure RemoveChild(i: integer); |
![]() |
procedure RemoveAllChildren; |
![]() |
function ExtractChild(I: Integer): TVRMLNode; |
|
Remove and return children indexed I, and never free it. Compare this with RemoveChild, that removes children I and frees it if it's reference count gets 0.
| |
![]() |
function ParentNodesCount: integer; |
![]() |
function ParentFieldsCount: Integer; |
![]() |
function PathFromWWWBasePath(const RelativePath: string): string; |
|
This returns absolute path, assuming that RelativePath is relative path from WWWBasePath or that RelativePath is already absolute. | |
![]() |
procedure Parse(Lexer: TVRMLLexer); virtual; |
|
Parse node. This should set values of your fields, VRML 1.0 Children list, WWWBasePath. In special cases like TVRMLUnknownNode this may actually initialize whole Fields list (by VRML 1.0 "fields" extensibility feature). | |
![]() |
constructor Create(const ANodeName: string; const AWWWBasePath: string); virtual; |
|
Konstruktor. Inicjuje wszystko (jak to konstruktor), w szczegolnosci :
| |
![]() |
constructor CreateParse(const ANodeName: string; Lexer: TVRMLLexer); |
|
| |
![]() |
destructor Destroy; override; |
![]() |
function NodeTypeName: string; virtual; |
|
Nie zmienia sie przez caly czas zycia obiektu, tzn. raz zainicjowana w konstruktorze juz taka pozostaje. Even for special nodes, like TVRMLUnknownNode and TVRMLPrototypeNode (where this is determined at runtime, since these special nodes are used to instantiate special nodes that are not built-in) — but still even for these special nodes, W tej klasie | |
![]() |
class function ClassNodeTypeName: string; virtual; |
|
Jezeli masz do dyspozycji instancje obiektu to nie powinienes uzywac tej funkcji. Jedyna jej zaleta ponad NodeTypeName jest ze jest funkcja klasy. Jezeli masz do dyspozycji tylko klase obiektu to uzywajac tej funkcji musisz sie zdecydowac co zrobic jesli dostaniesz w odpowiedzi '' (albo jakos sie zabezpieczyc zeby nigdy w danym kontekscie takich klas nie miec...) Uwagi do implementacji podklas TVRMLNode: W tej klasie | |
![]() |
procedure Traverse( NodeClass: TVRMLNodeClass; TraversingFunc: TTraversingFunc; TraversingFuncAfter: TTraversingFunc = nil); |
|
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.
Also, TraversingInfo is passed to each TraversingFunc call. This allows you to investigate, during TraversingFunc call, the parents hierarchy (you can't use ParentNodes / ParentFields of the current node, since a node may have many parents). The scheme of how
BeforeTraverse;
if Self is NodeClass then TraversingFunc (Self, State)
MiddleTraverse
for all children returned by DirectEnumerateActive
call their Traverse(State)
AfterTraverse,
if Self is NodeClass then TraversingFuncAfter (Self, State)
dodaj Self do stanu State do LastNode (o ile Self wsrod
TraverseStateLastNodesClasses)
Note: I didn't decide yet whether TraversingFuncAfter should be before or after AfterTraverse call. Report if you have any good reason for any setting. Jezeli zostalo wykonane BeforeTraverse, na pewno zostanie wykonane tez AfterTraverse (wywolanie AfterTraverse jest w finally..end). Kolejnosc w jakiej przechodzi graf jest naturalnie istotna. W czasie wykonywania | |
![]() |
procedure EnumerateNodes( proc: TVRMLNodeProc; OnlyActive: boolean); overload; |
|
Enumerate all our children of some class. Recursively. Zwroci do proc() takze sam obiekt na ktorym EnumerateNodes zostalo wywolane, jezeli tylko ten obiekt jest klasy nodeClass. This enumerates both VRML 1.0 Children as well as 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. Wersja z argumentem SeekNodeName wymaga ponadto aby node mial NodeName= SeekNodeName (gdy SeekNodeName = '' to znajduje nienazwane node'y, wiec wartosc '' nie jest tu traktowana specjalnie). Zaczyna przegladac dzieci dopiero jak przegladnie Self. Jezeli np. w proc. zmodyfikowales (np. dodales) wlasne Children to EnumerateNodes will enumerate these new children. To ma znaczenie np. w TVRMLScene.LoadAllInlined gdzie w proc robimy LoadInlined. Poniewaz EnumerateNodes przeglada dzieci po wywolaniu proc., wiadomo ze przegladnie tez nowo zaladowane dziecko. BTW modyfikowanie dzieci node'a ktory wlasnie dostales do proc() to jedyna dozwolona modyfikacja na hierarchii VRMLa ktora mozesz wykonywac w czasie EnumerateNodes. | |
![]() |
procedure EnumerateNodes(nodeClass: TVRMLNodeClass; proc: TVRMLNodeProc; OnlyActive: boolean); overload; |
![]() |
procedure EnumerateNodes(nodeClass: TVRMLNodeClass; const SeekNodeName: string; proc: TVRMLNodeProc; OnlyActive: boolean); overload; |
![]() |
function TryFindNodeByName(FindClass: TVRMLNodeClass; const FindName: string; OnlyActive: boolean): TVRMLNode; |
|
These functions are quite like EnumerateNodes, except they stop at the first occurence and return it.
| |
![]() |
function FindNodeByName(FindClass: TVRMLNodeClass; const FindName: string; OnlyActive: boolean): TVRMLNode; |
![]() |
function TryFindNode(FindClass: TVRMLNodeClass; OnlyActive: boolean): TVRMLNode; |
![]() |
function FindNode(FindClass: TVRMLNodeClass; OnlyActive: boolean): TVRMLNode; |
![]() |
function TryFindNodeState( NodeClass: TVRMLNodeClass; out Node: TVRMLNode; out State: TVRMLGraphTraverseState): boolean; |
|
Znajdz pierwszy Node (zadanej klasy NodeClass) razem ze State (lub tylko z Transform). Dziala jak TraverseFromDefaultState ktore zatrzymuje sie po pierwszej udanej probie. W przypadku TryFindNodeTransform nie musisz o tym pamietac, no i TryFindNodeTransform dziala nieco szybciej. Zwraca false and sets Node, State and Transform to undefined (because they are "out" params) if not found. | |
![]() |
function TryFindNodeTransform( NodeClass: TVRMLNodeClass; out Node: TVRMLNode; out Transform: TMatrix4Single; out AverageScaleTransform: Single): boolean; |
![]() |
function TryFindParentByName(const FindName: string): TVRMLNode; |
|
This seeks Self and parent nodes (from ParentNodes 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. | |
![]() |
function FindParentByName(const FindName: string): TVRMLNode; |
![]() |
function HasParent(Node: TVRMLNode): boolean; |
|
Przeszukuje podobnie jak powyzsze FindParentByName. Zwraca true jesli znalazl tam gdzies node Node. | |
![]() |
function TryFindDirectParentByName(const FindName: string): TVRMLNode; |
|
Searches immediate parents of this node for a node with given FindName. Returns | |
![]() |
function IsNodePresent(Node: TVRMLNode; OnlyActive: boolean): boolean; |
|
sprawdza czy istnieje w grafie VRML'a zaczepionym w danym punkcie node Node. If OnlyActive, then only active parts are searched ("active" as defined by Traverse). | |
![]() |
function NodesCount(NodeClass: TVRMLNodeClass; CountOnlyActiveNodes: boolean): integer; |
|
policz ile jest node'ow danej klasy. Uzywajac np. TVRMLLightNode mozesz sprawdzic czy na scenie zostalo zdefiniowane jakiekolwiek swiato. 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. | |
![]() |
procedure SaveToStream(SaveProperties: TVRMLSaveToStreamProperties); override; |
|
Save node to stream. This saves everything, including node name, node type, then node contents within { }. We use SaveProperties.NodeNameBinding, pretty much like when parsing. If a node name is already bound with this node, then we know we have to write only USE ... statement. Otherwise we write full node contents, with eventual DEF ... statement. Note that if ChildrenSaveToStream returns | |
![]() |
class function TraverseStateLastNodesIndex: Integer; |
|
szuka tej klasy node'a (rzeczywistej koncowej klasy, z ClassType) w TraverseStateLastNodesClasses. Zwraca indeks lub -1 jesli nie znalazl. | |
![]() |
class function ForVRMLVersion(const VerMajor, VerMinor: Integer): boolean; virtual; |
|
Some of the nodes are meant to be handled only for specific VRML versions. This functions says whether this node is supposed to be present in given VRML version. VerMajor and VerMinor arguments are expected in the same form as TVRMLLexer.VRMLVerMajor, TVRMLLexer.VRMLVerMinor. 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 TNodeCone_1 works with VRML < 2.0, TNodeCone_2 works with VRML >= 2.0. NodesManager will use this. Default implementation of this function returns always In practice I only use this function when both VRML 1.0 and 2.0 specify the same node name but
| |
![]() |
function ChildrenField: TMFNode; virtual; |
|
MFNode field of this node that should be treated as general "children" field of this node. This is used in some places, like SmartAddChild. Should return nil if this node doesn't have such field (that's the default implementation in this class). This should always return the same value for given class instance (in other words, don't implement this to sometimes return one field, sometimes the other, sometimes nil, etc.). | |
![]() |
procedure SmartAddChild(Node: TVRMLNode); |
|
These operate on children nodes, in either VRML 2.0 style (if ChildrenField is non-nil, then these get/set ChildrenField.Items) or in VRML 1.0 style (if ChildrenField is nil, then these get/set our Children). This is useful to operate on grouping nodes both in VRML 1.0 and VRML 2.0 style using the same code. | |
![]() |
function SmartChildrenCount: integer; |
![]() |
function SmartExtractChild(Index: Integer): TVRMLNode; |
![]() |
function SuggestedVRMLVersion( out VerMajor, VerMinor, SuggestionPriority: Integer): boolean; virtual; |
|
SuggestionPriority should be used to indicate the "strongness" of this suggestion. The idea is that if there are two nodes that have different VRML version suggestions, then the one with greater SuggestionPriority "wins". Currently used priorities:
Default implementation in this class enumerates all SFNode and MFNoden fields and Children nodes and determines their suggested VRML version. | |
![]() |
class function ChildrenSaveToStream: boolean; virtual; |
|
Returns should SaveToStream save our Children. In this class default implementation returns | |
![]() |
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 RemoveChild 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 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. ReturnsThe number of removed nodes. | |
![]() |
function DeepCopy: TVRMLNode; |
|
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, ParentEventsProcessor, ParentNodes, ParentFields. ParentNodes 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. | |
![]() |
procedure Bind(NodeNameBinding: TStringList); |
|
Add Self (NodeName must be initialized) to nodes namespace. Doesn't do anything if NodeName = ''. | |
![]() |
class function URNMatching(const URN: string): boolean; virtual; |
|
Should we use this node when URN is required by EXTERNPROTO ? Implementors note: in this class, this returns | |
![]() |
procedure TraverseBlenderObjects( TraversingFunc: TBlenderTraversingFunc); overload; |
|
Traverses all Blender objects/meshes instances in this model, assuming that this VRML node was created by Blender VRML 1.0 or 2.0 exporter. For each Blender object (which means, for each Blender mesh instantiation), this calls TraversingFunc. Since each Blender object is unique in file, you can be sure that each BlenderObjectNode will be enumerated only once by TraversingFunc, as long as this file was really made by Blender exporter. As for BlenderObjectName, Blender VRML 1.0 exporter doesn't write object names (only meshes), so it's always '' for VRML 1.0. Mesh may occur many times in the file, and both Blender exporters correctly use VRML DEF/USE mechanism, so the same BlenderMeshNode and BlenderMeshName may be enumerated many times by TraversingFunc. Implementation of this follows the logic of Blender VRML 1.0 and 2.0 standard exporters, there's no other way to implement this. If you wrote in Python your own Blender exporter for VRML, this method may obviously not work. But it's guaranteed that this method will not crash or anything on any VRML model. The worst thing that can happen on all VRML models is simply that TraversingFunc will enumerate something that doesn't correspond to any Blender object... | |
![]() |
property Fields: TVRMLFieldsList read FFields; |
|
Node fields. For normal nodes, all Fields are created and added to Fields list in constructor. Fields default values are set, and of course 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. TVRMLPrototypeNode has their fields set according to it's VRML 2.0 prototype. TVRMLUnknownNode 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 object. | |
![]() |
property Events: TVRMLEventsList read FEvents; |
|
Explicit | |
![]() |
property Children[i: integer]: TVRMLNode
read GetChildrenItem write SetChildrenItem; |
|
Children property lists children VRML nodes, in the sense of VRML 1.0. In VRML 2.0, nodes never have any Children nodes expressed on this list (however, their children nodes may be expressed as items of TMFNode / TSFNode fields). Kazdy VRML nodes moze miec dowolnie wiele Children. Kiedy jakis node jest na liscie Children jednego node'a to ma swojego rodzica na swojej liscie ParentNodes. Wiec w ten sposob mozemy podrozowac po grafie w obie strony. (pamietaj ze graf VRML'a nie ma cykli gdy na niego patrzec jak na graf skierowany (a takim wlasnie jest) ale kazdy node moze miec wiele rodzicow wiec jezeli potraktujemy go jako graf nieskierowany to mozemy otrzymac cykle; wszystko przez to ze node moze miec wiele ParentNodes bo moze uzywac mechanizmu USE). Kiedy jakis node jest na liscie Children innego node'a to gdy ten inny node bedzie go kasowal ze swojej listy Children (a w destruktorze kazdy node kasuje wszystkich ze swojej listy Children) to wywola jego destruktora. Innymi slowy, gdy jakis node jest czyims dzieckiem to jest reference-counted i automatycznie zwalniany. Actually, nodes can be children of both nodes (VRML 1.0 style, then Children and ParentNodes 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. Wazna konwencja : jak widac, rodzic automatycznie martwi sie o swoje dzieci. Natomiast dziecko w swoim Free nie martwi sie o uaktualnienie swoich rodzicow. Zwracam tez uwage ze RemoveChild wymaga indeksu. Okreslanie dziecka jako children: TVRMLNode jest nie-1-znaczne bo przeciez jeden node moze miec kilka razy to samo dziecko (i w rezultacie, nawiasem mowiac, kazde dziecko moze miec wiele razy tego samego Parenta). A nie chcemy przeciez pomieszac sobie kolejnosci w Children (ona determinuje przeciez kolejnosc przegladania grafu, a wiec Renderowania itp.) (Natomiast mozemy sobie pozwolic i nieraz pozwalamy na ew. pomieszanie kolejnosci w ParentNodes; inaczej musielibysmy z kazdym ParentNodes pamietac swoj index na jego liscie). Tak wiec na listach Children i ParentNodes moga byc duplikaty i zdecydowanie nie powinnismy nigdzie niefrasobliwie "czyscic" tych list przez DeleteDuplicates; You can also replace one children with another by writing to this property, like | |
![]() |
property ParentNodes[i: integer]: TVRMLNode read GetParentNodesItem; |
|
All nodes where this node is referenced as a child. This counts "parents" in the VRML 1.0 / Inventor sense. | |
![]() |
property ParentFields[Index: Integer]: TVRMLField read GetParentFieldsItem; |
|
This lists all SFNode and MFNode fields where this node is referenced. This is somewhat analogous for ParentNodes, but for VRML 2.0. ParentFieldsNode is just for your comfort, it returns always appropriate field's ParentNode property value (i.e. | |
![]() |
property ParentFieldsNode[Index: Integer]: TVRMLNode
read GetParentFieldsNodeItem; |
![]() |
property AllowedChildren: boolean read fAllowedChildren default false; |
|
ParsingAllowedChildren okresla jakie dzieci moga byc odczytane ze strumienia jako dzieci tego node'a. Chwilowo ma to zastosowanie tylko dla wezlow *Inline ktore w strumieniu nie moze miec zapisanych zadnych dzieci ale laduja swoje inline jako swoje Child. Wiec musza miec ParsingAllowedChildren=[] i TODO: jak bedzie mi to potrzebne to zaimplementuje te pola jako tablice TDynVRMLNodeClassArray z dodatkowym polem Any. Taka tablica bedzie pasowala do wszystkiego gdy Any = true, wpp. tylko do wymienionych na niej elementow. Wartosc * Naturalnie ParsingAllowedChildren musi sie zawierac w Note that in some special cases | |
![]() |
property ParsingAllowedChildren: boolean
read fParsingAllowedChildren default false; |
![]() |
property NodeName: string read fNodeName write FNodeName; |
|
Name of this node, as defined by VRML "DEF" construct.
It's named Note that this is writeable property, so you can change | |
![]() |
property WWWBasePath: string read FWWWBasePath write FWWWBasePath; |
|
This way URL's in node's fields may contain relative names. If TODO: chwilowo, poniewaz tylko odwolania do lokalnych plikow sa zaimplementowane, cale to bajanie o URL'ach to tylko mowa "jak kiedys bedzie". Chwilowo
| |
![]() |
property SmartChildren[Index: Integer]: TVRMLNode read GetSmartChildren; |
![]() |
property Prototypes: TVRMLPrototypeBasesList read FPrototypes; |
![]() |
property Routes: TVRMLRoutesList read FRoutes; |
![]() |
property PrototypeInstance: boolean read FPrototypeInstance; |
|
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 (TVRMLPrototypeNode.Instantiate) and when linking ROUTE (TVRMLRoute.SetSource, TVRMLRoute.SetDestination). PrototypeInstanceHelpers may be
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.
TODO: memory leaks are known to be possible in some difficult cases with PrototypeInstanceHelpers. See e.g. ../../../kambi_vrml_test_suite/vrml_2/warnings/errors/proto_leak.wrl and ../../../kambi_vrml_test_suite/vrml_2/warnings/errors/proto_leak_2.wrl for simple testcases. Reason: PrototypeInstanceHelpers may contain, by DEF statements, links to Self. This causes circular dependency (Self is child of some node on PrototypeInstanceHelpers, but PrototypeInstanceHelpers will be freed only if Self is freed) causing some memory to be left always allocated. Note that for TVRMLPrototypeNode (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 TVRMLPrototypeNode.Instantiate implementation comments for gory details about this.) | |
![]() |
property PrototypeInstanceSourceNode: TVRMLPrototypeNode
read FPrototypeInstanceSourceNode; |
![]() |
property PrototypeInstanceHelpers: TVRMLNode read FPrototypeInstanceHelpers; |
![]() |
property DefaultContainerField: string
read FDefaultContainerField write FDefaultContainerField; |
|
Default value of "containerField" attribute for this node in X3D XML encoding. | |
![]() |
property HasInterfaceDeclarations: TVRMLAccessTypes
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 | |
![]() |
property InterfaceDeclarations: TVRMLInterfaceDeclarationsList
read FInterfaceDeclarations; |
![]() |
property CDataAllowed: boolean read FCDataAllowed write FCDataAllowed; |
|
Does this node allow CDATA section when encoded in XML. See X3D XML encoding specification about "Encapsulating Script node code", instantreality also uses CDATA to encode shader source code within XML file and this seems sensible (following the intention of the spec?). This is only used to produce eventual warnings when CDATA is encountered. Whether or not This should be set in descendants constructor. | |
![]() |
property CData: string read FCData write FCData; |
![]() |
property DestructionNotifications: TDynNodeDestructionNotificationArray
read FDestructionNotifications; |
|
Functions registered here will be called when this TVRMLNode descendant will be destroyed. | |
![]() |
property ParentEventsProcessor: TObject
read FParentEventsProcessor write FParentEventsProcessor; |
|
Events processing object for this node, or Currently this must always be an instance of TVRMLScene class (although it cannot be declared as such, since TVRMLScene is not known in this unit). It must have ProcessEvents = Note: While it is possble and perfectly fine to have the same VRML node included in more than one TVRMLScene instance, only one of such scenes may have ProcessEvents = | |