|
To automate VrmlPad tasks using Automation, you must understand the VrmlPad object model. This model consists of VrmlPad objects and their associated properties and methods. Objects are the fundamental building block of VrmlPad; nearly everything you do in VrmlPad involves modifying objects. Every element of VrmlPad - document, window, text selection and so on - can be represented by an object.
The VrmlPad Automation provides two levels of objects:

The first level knows nothing about VRML and lets you manipulate with the application window and perform simple text operations in a text editor window, such as moving the caret, controlling which text is selected, and modifing the contents of the selection.
The second level interprets a document as the hierarchical VRML scene tree. An object represents an element of VRML, such as a VRML node, a PROTO, a field, or a route. A collection is an object that contains several other objects, usually of the same type; for example, all the named (using DEF) node objects in a document are contained in a single collection object. Using properties and methods, you can modify a single object or an entire collection of objects. The following figure shows these objects and their relationships.
Using the Document Object
The Document object is at the top, and the other objects are subordinate to it. The Document object includes properties and methods that return top-level objects. For example, the RootNodes property returns a Nodes collection of top-level VRML nodes.
In a VBScript or JavaScript macro, you can control the existing open document by manipulating its corresponding Document object. Because the Document object is the topmost object, its name is implied when you access its properties and methods. Accordingly, you only need to specify its property or method names. For example, instead of writing Document.Selection = "Text", you can write Selection = "Text".
To use Automation to control VrmlPad from another application, use the CreateObject or GetObject function to return a new VrmlPad Document object. The following Visual Basic example starts VrmlPad and opens an existing document.
Set doc = New VrmlPad.Document
doc.OpenFile "C:\My Scenes\Home.wrl"
doc.Window.Visible = True
|
In VBScript and JavaScript macros, you access Document members by automatically using late binding. In add-ins however, you can also access Document members by using early binding. Early binding offers better performance than late binding by making calls into the interface faster at run time.
Opening a document
To open an VRML file, use the OpenFile method with the Document object. The FileName argument must include complete path of the VRML file. Because an instance of VrmlPad can have only one document, the active document will be closed during this operation. The following instruction opens a document named "Home.wrl" located in the folder named "MyFolder", without saving changes in the existing document.
OpenFile "C:\MyFolder\Home.wrl", vpDoNotSaveChanges
|
To close the active document and creating a new one, use NewFile method with the Document object.
Saving a document
To save a new document or an existing document, use the Save method with the Document object. The following instruction saves the active document as "Temp.wrl" in the current folder.
Using the Range Object
A common task when using Automation is to specify an area in a document and then do something with it, such as insert or delete text. For example, you may want to write a macro that locates a word or phrase within a portion of a document. The portion of the document can be represented by a Range object. After the Range object is identified, methods and properties of the Range object can be applied in order to modify the contents of the range.
A Range object refers to a contiguous area in a document. Each Range object is defined by a starting and ending character position. Similar to the way bookmarks are used in a document, Range objects are used in Automation to identify specific portions of a document. A Range object can be as small as the insertion point or as large as the entire document.
The FromLine, FromRow, ToLine and ToRow properties return or set the starting and ending character positions of the Range object and uniquely identify a Range object. You can define the beginning and end points of a range using the line and row numbers, or using the MoveTo method. The following example creates a Range object beginning at the start of the first root node and ending after the third root node.
Set Range1 = RootNodes(1).Range
Set Range2 = RootNodes(3).Range
Range1.MoveTo Range2.ToLine, Range2.ToRow, True
|
Range objects are independent of the selection. That is, you can define and modify a range without changing the current selection. You can also define multiple ranges in a document, while there is only one selection per document. When you need to refer to a Range object multiple times, you can use the Set statement in VBScript or Visual Basic to set a variable equal to the Range object. However, if you only need to perform a single action on a Range object, there's no need to store the object in a variable. The same results can be achieved using just one instruction that identifies the range and selects it.
RootNodes(1).Range.Select
|
Using the Range property
The Range property appears on multiple objects, such as Document, Node, Proto, Route, and Field, and is used to return a Range object. The following example returns a Range object that refers to the first PROTO declaration in the document.
Set MyRange = Protos(1).Range
|
After you have a Range object, you can use any of its properties or methods to modify the Range object. If you need to apply numerous properties or methods to the same Range object, you can use the With...End With structure. The following example moves the insertion point to the beginning of the first PROTO declaration in the document.
Set MyRange = Protos(1).Range
With MyRange
.MoveTo .FromLine, .FromRow
.Select
End With
|
Using the VRML objects
The VRML object model includes the following types of object:
- Collections
- Entity objects (within collections)
- Field value objects
Using collections
A collection object is an ordered set of items that can be referred to as a unit. A collection object provides a convenient way to refer to a related group of items as a single object. The interface of collections is regulated, therefore, it is easy to work with them.
Collections have the Count and the Item properties and the Add method. It is also possible to iterate through the elements of the collection using the For Each...Next statement in Visual Basic and VBScript or For...in statement in JavaScript. The following example in Visual Basic prints all node names in the document to the Immediate pane.
Dim node As Node
For Each node In Document.Nodes
Debug.Print node.Name
Next node
|
The Item property returns a single object from a collection. The following example sets the FirstProto variable to a Proto object that represents the first PROTO declaration in the Protos collection.
Set FirstProto = Protos.Item(1)
|
Many VrmlPad objects have a default property or method. Visual Basic and VBScript applies the default property or method to a given object to resolve an expression that wouldn't otherwise be valid. You can write statements that use default properties or methods more concisely by omitting the default keywords. The Item property is the default property for collections, so you don't have to reference Item explicitly.
Set FirstProto = Protos(1)
|
Although you can usually specify an one-based integer value with the Item property, it may be more convenient to return an object by name. The following example counts all IndexedFaceSet nodes in the document.
MsgBox StdProtos("IndexedFaceSet").Instances.Count
|
When you reference a collection, the reference always reflects the current contents of the collection. For example, suppose you have two procedures (A and B). In procedure A, you set a global variable to the collection, and in procedure B you use the variable. When you use it, the variable will reflect the current contents of the collection — not the contents present when you set the variable. So if you specify numbers for the Item property, do not store these for later use because the indices might change as objects are added or removed.
The VRML object model includes four different collections types: Nodes, Fields, Protos and Routes. Collections are a default property for most objects, that would reduce code in Visual Basic and VBScript macros. The following example sets the value to the geometry field of the SomeShape node.
Document.Nodes("SomeShape").Fields("geometry").Value = "Box"
'Reduced code:
Document("SomeShape")("geometry") = "Box"
'More reduced code (only in Visual Basic):
Document!SomeShape!geometry = "Box"
|
Using entity objects
The VRML object model includes four objects - Node, Field, Proto and Route - that have the common set of properties and methods and may be assigned to a variable of Entity type. And vice versa, some VrmlPad objects include properties and methods returning an Entity object, that is actually Node, Field, Proto or Route object, depending on value of the EntityType property.
| EntityType | VRML object | Actual Type |
 |
| vpNode | Node definition | The Node object |
 |
| vpNodeRef | Node reference (USE) | The Node object |
 |
| vpProto | PROTO declaration | The Proto object |
 |
| vpExternProto | EXTERNPROTO declaration | The Proto object |
 |
| vpField | Node's field definition | The Field object |
 |
| vpFieldDecl | Script's or PROTO's field declaration | The Field object |
 |
| vpProtoURL | URL of EXTERNPROTO's declaration | The Field object |
 |
| vpRoute | ROUTE definition | The Route object |
 |
| vpExpired | Corresponding VRML object has been removed | |
When you need to cast an Entity object to a particular object type, you can use the Set statement in Visual Basic to set a variable of required type equal to the Entity object. In C++, you can use QueryInterface to get required interface. VBScript and JavaScript is typeless languages, so you don't have to do such conversion.
The following VBScript macro prompts about entity type at the caret position in Editor window or the current selection in Scene Tree pane.
Set e = CurrentEntity
If e Is Nothing Then
MsgBox "Nothing"
Else
Select Case e.EntityType
Case vpNode, vpNodeRef
MsgBox "Node " & e.TypeName
Case vpField, vpFieldDecl, vpProtoURL
MsgBox "Field " & e.Name
Case vpProto, vpExternProto
MsgBox "Proto " & e.Name
Case vpRoute
MsgBox "Route from " & e.FromField.Name
End Select
End If
|
You can use the EntityType property to determine the exact type of the corresponding VRML object. The following example determines is the Node object refers to a node reference or to a node definition.
Function IsReference (n As Node) As Boolean
Select Case n.EntityType
Case vpNode
IsReference = False
Case vpNodeRef
IsReference = True
Case Else
MsgBox "The node object is not valid"
End Select
End Function
|
Using field value objects
The Value property of the Field objects returns Variant result, that can be Integer for the SFInt32 field type, Float for the SFFloat and SFTime field types, String for the SFString field type and the Node object for the SFNode field type. For the SFVec2f, SFVec3f, SFRotation, SFColor and all multiple field types the Value property returns an object of the appropriate type (SFVec2f, SFVec3f, SFRotation, SFColor or MFValue). The Value property is the default property for the Field objects, so you don't have to reference it explicitly.
The MFValue object is a collection object that contains all subvalues of the multiple field object. To find a particular value, iterate through the collection by using the Value property of the Field object. For the MFVec2f, MFVec3f, MFRotation and MFColor field types the Item property returns an object of the type SFVec2f, SFVec3f, SFRotation or SFColor respectively. The following example replaces X and Y coordinates in a field of the MFVec2f type.
Dim v As SFVec2f
For Each v In Nodes("TexCoords")("point").Value
v.Set v.y, v.x
Next
|
The MFValue object has the Array property that returns two-dimensional array of Variants for the MFVec2f, MFVec3f, MFRotation and MFColor field types and one-dimensional array for the other types. So the previous example may be rewritten using arrays to increase performance.
Dim f As Field
Dim arr
Dim tmp As Single
Set f = Nodes("TexCoords")("point")
arr = f.Array
For i = 0 To UBound(arr, 1)
tmp = arr(i, 0)
arr(i, 0) = arr(i, 1)
arr(i, 1) = tmp
Next
f = arr
|
Use the Add method of the MFValue object to add new subvalues to multiple field value. Omitting the first argument, a default value will be inserted. The following example adds subvalue (0, 0) to a field value and inserts (0.9, -0.1) before the first subvalue.
Dim f As Field
Set f = Nodes("TexCoords")("point")
f.Add
f.Add Array(0.9, -0.1), 1
|
The next example adds a Shape node to the children field and then adds reference to this node.
Dim f As Field
Set f = Document.RootNodes(1)("children")
f.Add "Shape"
f.Add f(1)
|
|