-
Notifications
You must be signed in to change notification settings - Fork 263
Model Viewer Programming Discussion
Games contain graphic models of game objects, such as characters and vehicles. The ATF Model Viewer Sample renders 3D models of objects in ATGI and Collada format files, with .atgi
and .dae
extensions. The model can be rendered in variety of ways, as a wireframe, for instance.
Besides rendering model data, this sample illustrates handling documents, commands, and controls in ATF. Although this application does not have its own data model or edit data, it still makes use of the ATF DOM by treating the model data as a tree of DOM nodes.
This topic only briefly touches on ATGI and Collada. While largely routine, the MEF initialization for ModelViewer uses the Component Model API to get an exported component.
Although ModelViewer does not edit data, it makes use of the ATGI and Collada data models expressed in their XML Schema. It uses the AtgiResolver
and ColladaResolver
components, which implement IResourceResolver
to both load the schema files and to load model files, creating DomNode
trees from their data.
ModelViewer treats the loaded data as a document. Its ModelDocument
implements IDocument
and its document client class ModelViewer
implements IDocumentClient
.
RenderView
registers a DesignControl
to display a 3D scene from the active document. The RenderCommands
component works with RenderView
to change the rendering mode. RenderView
builds a scene graph from the model's DomNode
tree. A DesignControl
traverses the scene graph to render the model: each IRenderObject
object in the scene graph is traversed to create a TraverseNode
instance and add it to the traverse list. This results in the Traverse()
method in the DOM adapters RenderTransform
and RenderPrimitive
being called for each IRenderObject
. RenderTransform
transforms model objects properly, and RenderPrimitives
does the lowest level rendering using OpenGL®. OpenGL® is not discussed here, because it is distinct from ATF and well-documented elsewhere.
ATGI and Collada offer formats for exchanging digital assets among graphics software applications. ATGI is a Sony intermediate file format for game art data. COLLADA (from collaborative design activity) defines an open standard format.
Both provide XML schema defining the formats' types. Collada model files have the extension .dae
(digital asset exchange). ATGI model files have the .atgi
extension.
For details on Collada, see http://collada.org.
ModelViewer creates a MEF TypeCatalog
as many samples do and uses many of the common components, such as ControlHostService
and StandardFileCommands
. It uses several standard components to open model files:
-
AtgiResolver
: resource resolver for ATGI files. -
ColladaResolver
: resolves COLLADA resource files.
-
ModelViewer
: document client for 3D model files, opening model files. -
RenderView
: registers aDesignControl
to display a 3D scene from a model document. -
RenderCommands
: provides user commands related to change the view of the model.
CompositionContainer
, CompositionBatch
, and MainForm
creation and handling, the sample application determines which menu items appear under the File menu, just Open in this case. This must be set before component initialization, which immediately follows:
StandardFileCommands stdfile = container.GetExportedValue<StandardFileCommands>();
stdfile.RegisterCommands = StandardFileCommands.CommandRegister.FileOpen;
// Initialize components
foreach (IInitializable initializable in container.GetExportedValues<IInitializable>())
initializable.Initialize();
The ExportProvider.GetExportedValue<T>()
method gets the exported value for the StandardFileCommands
component and sets its RegisterCommands
property, which contains a mask for the File menu items that are used. This property must be set before StandardFileCommands
is initialized.
After this, the sample directly initializes the components by calling Initialize()
for every component in the CompositionContainer
object, but it could just as well have used the IInitializable.InitializeAll()
extension method like this, which is what most samples do:
container.InitializeAll();
The advantage of this latter method is that it first instantiates the components, because components are loaded in a lazy fashion otherwise, only created when required to satisfy another component's import.
ModelViewer can view two different kinds of model data: from ATGI and from Collada. Although these two data models are different, they can both be specified in the XML Schema Definition Language (XSD), also known as XML Schemas. The data model defines a set of data types that describe the data in a model file. ATF includes two type definition files in this format, "atgi.xsd" and "collada.xsd".
The ATF DOM can use XML Schemas for its data models, and many of the ATF DOM's facilities are used in the ModelViewer sample. For details, see the ATF Programmer's Guide: Document Object Model (DOM), downloadable at ATF Documentation.
How does the ModelViewer use the XML Schema for ATGI and Collada? It imports the available IResourceResolver
objects, the AtgiResolver
and ColladaResolver
components. These resolvers do two things:
- Load the schema file for model data.
- Provide a
Resolve()
method to load a model file from a given URI.
The Initialize()
method for each resolver component loads the model schema. Here is Initialize()
for AtgiResolver
:
public void Initialize()
{
if (m_initialized)
return;
m_initialized = true;
Assembly assembly = Assembly.GetExecutingAssembly();
m_loader.SchemaResolver = new ResourceStreamResolver(assembly, assembly.GetName().Name + "/schemas");
m_loader.Load("atgi.xsd");
}
The m_loader
field is initialized this way:
private AtgiSchemaTypeLoader m_loader = new AtgiSchemaTypeLoader();
AtgiSchemaTypeLoader
derives from XmlSchemaTypeLoader
, which can load schema files with its Load()
method. AtgiSchemaTypeLoader
uses this load method to load the ATGI schema file "atgi.xsd" after resolving its URI.
ColladaResolver
uses the ColladaSchemaTypeLoader
, also derived from XmlSchemaTypeLoader
, to load the Collada schema.
Both ATGI and Collada schema files are loaded when the AtgiSchemaTypeLoader
and ColladaResolver
components are initialized while the application starts up. These schema definitions provide the information needed to parse and view model files governed by the data models defined in the schemas.
Once the schema describing model files has been loaded into the application, ModelViewer can load model files.
The IResourceResolver.Resolve()
method loads a file from a given URI and produces an object implementing IResource
, a resource with a type and unique URI.
The DomNode
class represents an object of one of the types described in the data model for ATGI or Collada. The Resolve()
method creates a tree of DomNode
objects representing all the data in the model file. Resolve()
returns a DomNode
that is the root of the DomNode
tree.
The returned DomNode
is adapted to IResource
, as this code for ColladaResolver.Resolve()
demonstrates:
public IResource Resolve(Uri uri)
{
string fileName = PathUtil.GetCanonicalPath(uri);
if (!fileName.EndsWith(".dae"))
return null;
DomNode domNode = null;
try
{
using (Stream stream = File.OpenRead(fileName))
{
var persister = new ColladaXmlPersister(m_loader);
domNode = persister.Read(stream, uri);
}
}
catch (IOException e)
{
Outputs.WriteLine(OutputMessageType.Warning, "Could not load resource: " + e.Message);
}
IResource resource = Adapters.As<IResource>(domNode);
if (resource != null)
resource.Uri = uri;
return resource;
}
Resolve()
does the following:
- Checks that the file extension is "dae".
- Creates a
DomNode
. - Reads file data with a
Stream
. - Creates a
ColladaXmlPersister
, which derives fromDomXmlReader
, using theColladaSchemaTypeLoader
object. This loader has the information from the Collada schema. - Call
ColladaXmlPersister.Read()
to convert the stream data into a tree ofDomNode
objects, with aDomNode
at the root. TheColladaXmlPersister
has the information to do this from theColladaSchemaTypeLoader
that loaded the Collada schema. - Adapts the root
DomNode
to anIResource
and returns it.
AtgiResolver.Resolve()
method performs similarly.
Loading the model file's data creates a tree of DomNode
objects that the application can work with to render the model file's data.
In addition to the type definition files, each model provides a Schema
class, generated by the ATF DomGen utility from the XML schema definitions for the ATGI and Collada data models. DomGen creates a metadata class, such as DomNodeType
, for every type in the schema definition file and provides a convenient way to reference the types in the two different data models. In particular, each DomNode
has a DomNodeType
metadata object associated with it, describing the node's type.
These metadata classes in the Schema
classes are used when the application starts up by the document client component, ModelViewer
, as part of its initialization. For details, see ModelViewer Class.
ModelViewer implements IDocument
and IDocumentClient
to handle documents in a class and a component. For general information about documents, see Documents in ATF.
In ModelViewer, the ModelDocument
class implements IDocument
and holds the model data in a file. ModelDocument
's constructor takes parameters for a DomNode
and a URI:
public ModelDocument(DomNode node, Uri ur);
The DomNode
here is the root of a tree of DomNode
objects, because model data in the document is treated as a tree of DOM nodes, just as in the ATF DOM. This is discussed in Model Data Handling.
The ModelDocument
constructor sets the RootNode
property to this root DomNode
, and this property is referenced wherever the model data is needed.
ModelViewer only reads documents and does not edit them, so these properties are set accordingly:
public bool IsReadOnly
{
get { return true; }
}
...
public bool Dirty
{
get { return false; }
set { throw new InvalidOperationException(); }
}
IDocument
derives from IResource
, so it also defines the Type
property to indicate the document type:
public string Type
{
get { return "3D Model"; }
}
The ModelViewer
component is a document client, implementing IDocumentClient
. Its constructor creates a DocumentClientInfo
, obtained from the IDocumentClient.Info
property. This determines the document type and extensions the application handles:
public ModelViewer()
{
string[] exts = { ".atgi", ".dae" };
m_info = new DocumentClientInfo("3D Model", exts, null, null, false);
}
...
DocumentClientInfo IDocumentClient.Info
{
get { return m_info; }
}
The ModelViewer
component's initialization defines DOM extensions used for various DomNode
types:
void IInitializable.Initialize()
{
// Register ATGI and Collada nodes
Register<RenderTransform>(Sce.Atf.Atgi.Schema.nodeType.Type);
Register<RenderPrimitives>(Sce.Atf.Atgi.Schema.vertexArray_primitives.Type);
Register<RenderTransform>(Sce.Atf.Collada.Schema.node.Type);
Register<RenderPrimitives>(Sce.Atf.Collada.Schema.polylist.Type);
Register<RenderPrimitives>(Sce.Atf.Collada.Schema.triangles.Type);
Register<RenderPrimitives>(Sce.Atf.Collada.Schema.trifans.Type);
Register<RenderPrimitives>(Sce.Atf.Collada.Schema.tristrips.Type);
if (m_scriptingService != null)
m_scriptingService.SetVariable("viewer", this);
}
...
private static void Register<T>(DomNodeType nodeType) where T : new()
{
nodeType.Define(new ExtensionInfo<T>());
}
Defining a DOM extension on a type allows DomNode
objects of this type to be adapted to other objects, whose API is more suitable to the task at hand. The classes here, RenderTransform
and RenderPrimitives
, are known as DOM adapters, and are discussed in Rendering DOM Adapters.
In most of the samples, DOM extensions are defined in the application's Schema loader. However, ModelViewer has no Schema loader, since it doesn't define its own data model. Instead, it uses the schemas defined for ATGI and Collada data. In particular, it uses metadata classes like Sce.Atf.Atgi.Schema.nodeType.Type
, as shown in the IInitializable.Initialize()
above. These metadata classes are in the Schema
classes generated by DomGen, as discussed in ATGI and Collada Schema Classes.
ModelViewer only views model data; it doesn't change it, so the document client doesn't need to save data to a file or even close the file. Only open functions are needed; all the other methods in IDocumentClient
do nothing.
CanOpen()
simply checks that the file extension is appropriate:
bool IDocumentClient.CanOpen(Uri uri)
{
return m_info.IsCompatibleUri(uri);
}
The Open()
method creates a ModelDocument
:
IDocument IDocumentClient.Open(Uri uri)
{
foreach (IResourceResolver resolver in m_resolvers)
{
DomResource res = resolver.Resolve(uri) as DomResource;
if (res != null)
{
return new ModelDocument(res.DomNode, uri);
}
}
return null;
}
This Open()
method, though also brief, requires some explanation.
First, the IResourceResolver
objects are iterated from the field m_resolvers
, which is imported from all components exporting IResourceResolver
:
[ImportMany]
private IEnumerable<IResourceResolver> m_resolvers;
ModelViewer has two such IResourceResolver
exporters: AtgiResolver
and ColladaResolver
, discussed in the Resource Resolvers section.
The loop attempts to resolve the URI using all the IResourceResolver
objects it has. It calls Resolve()
for each resolver and sees if it gets a non-null
result, indicating resolution succeeded. Resolve()
creates a tree of DomNode
objects from the data in the model file. This tree is used to render the model into a 3D drawing.
Open()
constructs a new ModelDocument
using the URI and the DomNode
tree's root, and then returns the ModelDocument
.
The resource resolver components AtgiResolver
and ColladaResolver
load a model file and create a tree of DomNode
objects. Each DomNode
represents an object that can be rendered. During the rendering process, these DomNode
objects are adapted to various interfaces, such as IRenderObject
, through which rendering ultimately occurs.
Two ModelViewer components facilitate model rendering.
RenderView
registers a DesignControl
that is used to display a 3D scene from the active document.
Several classes are used to render objects. SceneNode
objects hold all the render objects and constraints that are associated with an object being rendered. SceneNode
objects are arranged in a graph that determines which objects to render, and in what order nodes are traversed during rendering. Scene
derives from SceneNode
and holds the root SceneNode
of the scene graph.
SceneGraphBuilder
builds a scene graph from a root source object, typically a DomNode
. In the ModelViewer application, the scene graph is built from the DomNode
tree. A SceneNode
object holds a reference to its underlying source object, the DomNode
.
The RenderView
constructor creates two objects:
public RenderView()
{
m_scene = new Scene();
m_designControl = new DesignControl(m_scene);
}
DesignControl
extends CanvasControl3D
to provide scene graph rendering and picking, using the scene graph provided in its constructor's Scene
parameter. DesignControl
is the canvas on which model objects are drawn.
The IInitializable.Initialize()
method for the RenderView
component registers the DesignControl
and subscribes to the active document changed event:
void IInitializable.Initialize()
{
ControlInfo cinfo = new ControlInfo("3D View", "3d viewer", StandardControlGroup.CenterPermanent);
m_controlHostService.RegisterControl(m_designControl, cinfo, null);
m_documentRegistry.ActiveDocumentChanged += (sender, e) =>
{
ClearRenderGraph(m_context);
m_context = null;
ModelDocument doc = m_documentRegistry.GetActiveDocument<ModelDocument>();
if (doc != null)
{
m_context = doc.RootNode;
SceneGraphBuilder builder = new SceneGraphBuilder(typeof(IRenderThumbnail));
builder.Build(doc.RootNode, m_scene);
Fit();
}
};
}
A lambda expression is used for the event handler. In this expression, ClearRenderGraph()
clears the DesignControl
canvas, because a model is going to be rendered for the new active document. The handler creates a ModelDocument
for the active document.
If the new document is valid, the lambda expression constructs a SceneGraphBuilder
that builds a scene graph from the specified type of IRenderObject
objects. In this case, objects to render must implement IRenderThumbnail
, which is an interface for objects that can generate thumbnails. The IRenderThumbnail
interface is empty, so this is not much of a restriction.
IRenderObject
is an interface for renderable objects. IRenderObject
extends IBuildSceneNode
, which enables scene graph building for a DOM object. The nodes in the model's DomNode
tree are adapted to IRenderObject
in the process of rendering.
The SceneGraphBuilder.Build()
method creates a scene graph from the DomNode
tree. This scene graph is used for rendering a document's model in the DesignControl
as long as that document is active.
The Fit()
method fits the rendered object in the DesignControl
window. It changes the settings of DesignControl
's Camera
to fit the object.
The RenderCommands
component provides user commands related to the RenderView
component to change rendering mode.
Its IInitializable.Initialize()
method registers commands with the CommandService
component, which it imported into the m_commandService
field:
public virtual void Initialize()
{
m_commandService.RegisterCommand(
Command.Fit,
StandardMenu.View,
CommandGroup,
"Fit",
"Fit All",
Keys.F,
null,
CommandVisibility.Menu,
this);
m_commandService.RegisterCommand(
Command.RenderSmooth,
StandardMenu.View,
CommandGroup,
"Smooth",
"Smooth shading",
Keys.None,
Resources.SmoothImage,
CommandVisibility.All,
this);
...
m_commandService.RegisterCommand(
Command.RenderCycle,
StandardMenu.View,
CommandGroup,
"CycleRenderModes",
"Cycle render modes",
Keys.Space,
null,
CommandVisibility.Menu,
this);
Commands are triggered by a menu item and/or a tool button, depending on the setting of the CommandVisibility
parameter. Icons for menu items and tool buttons are specified in the icon parameter, which references items like Resources.SmoothImage
. All these image resources are in the Resources
class, which provides several sizes of each image so the right size can be used for a menu item or tool button.
RenderCommands
implements ICommandClient
, whose methods determine whether commands can be performed and performs them. CanDoCommand()
returns true when the DesignControl
exists.
The DoCommand()
method performs all the registered commands:
public void DoCommand(object commandTag)
{
if (commandTag is Command)
{
DesignControl control = m_renderView.ViewControl;
switch ((Command)commandTag)
{
case Command.Fit:
m_renderView.Fit();
break;
case Command.RenderSmooth:
control.RenderState.RenderMode &= ~RenderMode.Wireframe;
control.RenderState.RenderMode |= (RenderMode.Smooth | RenderMode.SolidColor |
RenderMode.Lit | RenderMode.CullBackFace | RenderMode.Textured);
control.Invalidate();
break;
In the Command.Fit
case, the Fit()
method fits the rendered object in the canvas.
Most of the other commands, such as Command.RenderSmooth
, change how the model is rendered. RenderState
is a platform-independent representation of a GPU render state. It uses the RenderMode
enum, which corresponds to various rendering modes, such as wireframe. The commands here set a new RenderState
for the control and then call Invalidate()
to trigger repainting the model object in the DesignControl
, which is discussed in DesignControl Operation.
Finally, the UpdateCommand()
method updates the UI appearance based on the current rendering state. This results in the appropriate menu item being checked and tool button highlighted.
After the scene graph is built, it is traversed by DesignControl
to render the model. The actual rendering is done by methods called in the DOM adapters, RenderTransform
and RenderPrimitives
, discussed in Rendering DOM Adapters.
DesignControl
's constructor sets up several objects to assist in the rendering process:
public DesignControl(Scene scene)
{
m_scene = scene;
m_renderAction = new RenderAction(RenderStateGuardian);
m_pickAction = new PickAction(RenderStateGuardian);
// default render states. These correspond to the state of the toggles on the toolbar,
// like wireframe on/off, lighting on/off, backface culling on/off, and textures on/off.
m_renderState.RenderMode = RenderMode.Smooth | RenderMode.CullBackFace | RenderMode.Textured | RenderMode.Lit | RenderMode.Alpha;
m_renderState.WireframeColor = new Vec4F(0, 0.015f, 0.376f, 1.0f);
m_renderState.SolidColor = new Vec4F(1,1,1, 1.0f);
}
A RenderAction
is created and default values for a RenderState
object m_renderState
are set. RenderAction
implements IRenderAction
, which features methods to build a traverse list from the scene graph and dispatch the list for rendering.
When a Paint
event occurs for the DesignControl
, such as when the view is invalidated, it calls its Render()
method:
protected override void OnPaint(PaintEventArgs e)
{
Render(m_renderAction, false, false);
m_invalidated = false;
}
Render()
calls RenderAction.Dispatch()
, which calls BuildTraverseList()
to build a traverse list of TraverseNode
objects. TraverseNode
is a class for encapsulating the rendering state for each IRenderObject
object. BuildTraverseList()
calls the IRenderObject.Traverse()
method for each IRenderObject
object in the scene graph to create a TraverseNode
instance and add it to the traverse list, if the object is to be rendered. This results in the Traverse()
method in RenderTransform
and RenderPrimitive
being called for each IRenderObject
, as seen in Rendering DOM Adapters.
After creating the traverse list, RenderAction.Dispatch()
calls RenderPass()
to render the traverse list. This results in the Render()
method in RenderPrimitive
being called for each IRenderObject
, so each node is rendered, which is commented on in RenderPrimitives DOM Adapter.
DesignControl
uses a Camera
object with default settings to display rendered objects.
Recall that the ModelViewer
component's initialization defines DOM extensions for some DomNode
types, as shown in ModelViewer Initialization. DOM extensions for ATGI types are seen here:
void IInitializable.Initialize()
{
// Register ATGI and Collada nodes
Register<RenderTransform>(Sce.Atf.Atgi.Schema.nodeType.Type);
Register<RenderPrimitives>(Sce.Atf.Atgi.Schema.vertexArray_primitives.Type);
...
The result of these definitions is to allow DomNode
objects to be adapted to another class. From the second definition above, for instance, a DomNode
of type Sce.Atf.Atgi.Schema.vertexArray_primitives.Type
is adapted to RenderPrimitives
, a DOM adapter class. This means that all the methods and properties of RenderPrimitives
can be used on this type's DomNode
.
The ModelViewer application defines two DOM adapters, RenderTransform
and RenderPrimitives
. Note that:
- Both these DOM adapters derive from
RenderObject
and thus implementIRenderObject
. Thus, aDomNode
object of any type for which these DOM extensions are defined implementsIRenderObject
. This is a prerequisite for being rendered, as mentioned in Rendering Components. - Both implement
IRenderThumbnail
, soSceneGraphBuilder
can build a scene graph using anyDomNode
of types for which DOM extensions are defined. For details onSceneGraphBuilder
andIRenderThumbnail
, see RenderView Component.
This DOM adapter is used for "node" types in both ATGI and Collada that contain other nodes.
RenderTransform
implements ISetsLocalTransform
:
public class RenderTransform : RenderObject, IRenderThumbnail, ISetsLocalTransform
ISetsLocalTransform
is an interface for IRenderObject
objects that sets the local transform matrix (the transform from the parent to this render object) by calling IRenderAction.PushMatrix()
in the Traverse()
method.
The Traverse()
method has this call:
action.PushMatrix(m_node.Transform, true);
The m_node
field is set from the original DomNode
, adapted to ITransformable
, an interface for objects that maintain 3D transformation information:
m_node = this.Cast<ITransformable>();
m_node
is a node with transformation information obtained from its Transform
property, which contains a local transformation matrix. This transformation information comes from the original DomNode
.
This node basically specifies that any of its child node renderable objects should be transformed using the given matrix.
To demonstrate what this means, this figure shows a model drawn using the transformations performed by this DOM adapter:
Now, suppose that this line is removed from the ModelViewer
component defining the DOM extensions, so the transform doesn't occur:
Register<RenderTransform>(Sce.Atf.Collada.Schema.node.Type);
Here is the resulting model:
The propellor is now in the cockpit, which is very bad news for the pilot! This group of renderable objects was not transformed properly.
This change to the transformation matrix is undone in PostTraverse()
, which is called after post visiting the SceneNode
specified by the graph path, so the original transformation matrix state is restored:
action.PopMatrix();
This adapter actually does the work of rendering the model, using OpenGL®. This class also derives from RenderObject
and implements IRenderThumbnail
, but not ISetsLocalTransform
because it does not change the transformation matrix:
public class RenderPrimitives : RenderObject, IRenderPick, IRenderThumbnail
The RenderPrimitives.Traverse()
method is simpler than the version for RenderTransform
. It mainly calls the base Traverse()
method that creates a TraverseNode
instance and adds it to the traverse list.
The Init()
method initializes the render object, which happens once, when SceneGraphBuilder
builds a scene graph in its Build()
method, as described in RenderView Component.
The RenderPrimitives.Render()
method is called to render the object.
Both Init()
and RenderPrimitives.Render()
actually use OpenGL® to perform the rendering. OpenGL®'s operation is beyond the scope of this discussion.
- Circuit Editor Programming Discussion: Learn how ATF handles graphs, and provides editors for kinds of graphs, such as circuits.
- Code Editor Programming Discussion: Shows how to interface third party software to an ATF application: the ActiproSoftware SyntaxEditor.
- Diagram Editor Programming Discussion: Very simply combines components from the CircuitEditor, FsmEditor, and StateChartEditor samples into one application, with the abilities of all three, showing the power of components.
-
DOM Property Editor Programming Discussion: Shows how to use the ATF DOM with an XML Schema to define application data with a large variety of attribute types, whose values can be viewed and edited using the ATF
PropertyEditor
component, using various value editors to view and edit attributes. - DOM Tree Editor Programming Discussion: Shows how to edit DOM data using a tree control and display properties in a variety of value editors.
- File Explorer Programming Discussion: Discusses the ATF File Explorer Sample using list and tree controls with adapters.
- FSM Editor Programming Discussion: Tells you about how the ATF FSM Editor Sample edits simple graphs for state machines, using DOM adapters for contexts and validation.
-
Model Viewer Programming Discussion: Shows how the ATF Model Viewer Sample is written, discussing how ATGI and Collada model data is handled, using rendering components, and using a
DesignControl
as a canvas for rendering. -
Simple DOM Editor Programming Discussion: Programming the ATF Simple DOM Editor Sample, creating a palette, using DOM adapters and contexts, editing application data, and searching
DomNode
s. - Simple DOM Editor WPF Programming Discussion: Programming the ATF Simple DOM Editor WPF Sample, which is similar to ATF Simple DOM Editor Sample, but implemented using ATF's WPF framework.
- Simple DOM No XML Editor Programming Discussion: Programming the ATF Simple DOM No XML Editor Sample, which is very similar to ATF Simple DOM Editor Sample, except that it doesn't use XML for either its data model or persisting application data.
- State Chart Editor Programming Discussion: Shows using ATF graph and other classes to create a statechart editor, using DOM adapters, documents, contexts, and validators.
- Target Manager Programming Discussion: Description of how a target manager is implemented using ATF components to manage target devices, such as PlayStation®Vita or PS3™ consoles. A target manager is used in other tools, such as the StateMachine tool.
- Timeline Editor Programming Discussion: Discusses how to create a fairly full-featured timeline editor using the ATF timeline facilities, such as the timeline renderer and the timeline control and its manipulators.
-
Tree List Control Programming Discussion: Demonstrates using the
TreeListControl
andTreeListItemRenderer
classes to display and edit hierarchical data in a tree view with details in columns. -
Tree List Editor Programming Discussion: Demonstrates how to use the ATF tree controls
TreeListView
and its enhancement,TreeListViewEditor
.TreeListView
usesTreeListViewAdapter
, which adaptsTreeListView
to display data in a tree. - Using Dom Programming Discussion: Shows how to use the various parts of the ATF DOM: an XML Schema, a schema metadata class file generated by DomGen, DOM adapters for the data types, a schema loader, and saving application data to an XML file.
- Home
- Getting Started
- Features & Benefits
- Requirements & Dependencies
- Gallery
- Technology & Samples
- Adoption
- News
- Release Notes
- ATF Community
- Searching Documentation
- Using Documentation
- Videos
- Tutorials
- How To
- Programmer's Guide
- Reference
- Code Samples
- Documentation Files
© 2014-2015, Sony Computer Entertainment America LLC