1/*!
2
3\page Usd_Page_GeneratingSchemas Creating New Schema Classes with usdGenSchema
4
5USD provides a code generator script 'usdGenSchema' for creating new schema
6classes. The script is driven by a USD layer (typically named schema.usda) and
7generates the necessary C++ classes and supporting Python code for all the
8schema classes defined in it.
9
10This USD layer must meet the following prerequisites in order for generated code
11to compile and work with USD Core successfully.
12
13  - Must specify the libraryName as layer metadata.
14  - Schema typenames must be unique across all libraries.
15  - Attribute names and tokens must be camelCased valid C/python identifiers,
16    with the allowance that ':' signifies property namespacing.  See
17    \ref Usd_OM_UsdProperty and \ref Usd_NameSpacedPropertiesInCodeGen
18    for more information.
19  - usd/schema.usda must exist in the LayerStack, not necessarily as a direct
20    subLayer.
21
22See pxr/usd/lib/usdGeom/schema.usda for an example.
23
24\section Usd_IsAVsAPISchemas IsA Vs. API Schemas
25
26Schema classes can be classified into the following two types:
27
28 - <b>API schema</b> - An API schema provides an interface to a
29   prim's qualities, but does not specify a typeName for the underlying prim.
30   The prim's qualities include its inheritance structure, attributes,
31   relationships etc. Since it cannot provide a typeName, an API schema is
32   considered to be non-concrete. As a convention, the C++/python class name for
33   an API schema must end with "API".  In core USD, UsdModelAPI is an example of
34   an API schema; UsdRiMaterialAPI is an example from our RenderMan schema
35   module, which adds/extracts RenderMan-specific shading information from a
36   generic UsdShadeMaterial-typed prim.  Also by convention (with which
37   usdGenSchema can help), the properties that "belong" to an API schema are
38   typically namespaced with the base-name of the schema, camelCased. For
39   example, UsdRiMaterialAPI::CreateSurfaceAttr() will create an attribute named
40   outputs:ri:surface.
41   API schemas are classified into the following two sub-types:
42        - <b>Non-applied API schemas</b> - If an API schema only provides an
43        interface to certain core bits of metadata (like UsdModelAPI, which sets
44        model kind and UsdClipsAPI, which sets value-clips related metadata) or
45        if there is no use of recording the application of the API schema on a
46        prim (for the purpose of interchange), we make it a non-applied API
47        schema. Examples of non-applied API schemas include UsdModelAPI,
48        UsdClipsAPI, UsdShadeConnectableAPI and UsdGeomPrimvarsAPI. Typically,
49        non-applied API schemas can apply to any prim-type (eg, UsdClipsAPI) or
50        to a known fixed set of prim types, like in the case of
51        UsdShadeConnectableAPI which is only applicable to types that implement
52        connectability behaviors such as shaders and lights.
53        - <b>Applied API Schemas</b> - If there is a need to record and discover
54        whether an API schema has been applied to a prim, we make it an applied
55        API schema. An applied schema will impart its properties as additional
56        built-in properties on the prim. A public Apply() method is
57        auto-generated for applied API schemas. Once an API schema has been
58        applied to a prim, prim.HasAPI<APISchemaType>() will return
59        true. An applied API schema must be applied to a prim via a call to the
60        Apply() method, for the schema object to evaluate to true when
61        converted to a bool using the explicit bool conversion operator.
62        Examples of applied API schemas include UsdCollectionAPI,
63        UsdGeomModelAPI and UsdGeomMotionAPI. All API schemas must inherit from
64        UsdAPISchemaBase directly and cannot inherit from other schemas. Applied
65        API schemas are further classified into the following two categories:
66            - <b>Single-Apply API Schemas</b> - Applied API schemas that can
67            only be applied as a single instance to a prim.  Even though API
68            schemas cannot inherit from other API schemas, single-apply API
69            schemas can include other API schemas as
70            \ref Usd_BuiltinAPISchemas "built-ins".
71            Examples of single-apply API schemas include UsdGeomModelAPI and
72            UsdGeomMotionAPI.
73            - <b>Multiple-Apply API Schemas</b> - Applied API schemas that can
74            be applied multiple times on the same prim with different instance
75            names. For example, UsdCollectionAPI, which must be applied once
76            per collection owned by a prim. Properties instantiated by this
77            API schema are prefixed with the namespace prefix of the schema
78            followed by the instance name. There is specific metadata one
79            authors in schema.usda to identify the prefix for multi-apply
80            schemas, and the properties for a multi-apply schema should
81            be listed without any prefix.
82
83 - <b>IsA schema</b> - An IsA schema can impart a typeName to a prim in
84    addition to providing an interface to a prim's qualities. Every IsA
85    schema must derive from the core class UsdTyped, which is the base class
86    for all typed schemas. Furthermore, an IsA schema can be concrete or
87    non-concrete. An IsA schema will be concrete (or instantiable) if its
88    schema declaration provides both a name for the schema (in quotes) and a
89    typeName in the schema.usda file in which it is defined. A non-concrete
90    (abstract) IsA schema provides only a name for the schema, and hence
91    cannot be instantiated; non-concrete schemas exist to serve as
92    super-classes for related sets of concrete IsA schemas. UsdGeomImageable
93    is an example of a non-concrete IsA schema. UsdGeomScope is an example of
94    a concrete, typed IsA schema.
95
96\note "Instantiable," in this context, means instantiable as a typed prim in
97scene description.  The generated classes for all schemas, be they API,
98concrete-typed or non-concrete-typed are always instantiable in C++ or python
99as interface objects through which one can interact with UsdPrim objects.
100
101The definitions of both IsA schemas and applied API schemas are published, at
102runtime, into an introspectable
103\ref Usd_OM_SchemaDefinitionRegistry "schema definition registry", which
104produces the \ref UsdPrimDefinition "prim definitions" consulted by
105core USD when performing property value resolution (i.e. retrieving a property's
106value at a given UsdTimeCode). This allows IsA and applied API schemas to
107provide \em fallback \em values for their properties, that is, a value
108that the property will possess, even when none has been authored. Because a
109prim can only have one typeName, a prim can "be" (IsA) at most a single type,
110but can host data for any number of API schemas. This combination of IsA and
111applied API schemas constitutes the prim's complete type signature and is used
112to construct a single \ref UsdPrimDefinition "prim definition" that provides
113all the built-in properties and fallback values for the prim.
114
115The author of an API schema has to decide on the type of API schema at the time
116of its creation by setting token-valued customData entry 'apiSchemaType' in the
117schema definition. It can be set to one of 'nonApplied', 'singleApply' or
118'multipleApply'. When unspecified, the fallback apiSchemaType for an API schema
119is 'singleApply'. An API schema can only inherit from another compatible API
120schema with matching customData["apiSchemaType"] or from "/APISchemaBase"
121directly. This is enforced by the schema code generation script 'usdGenSchema'.
122
123API schemas and non-concrete typed schemas must not provide a typeName in their
124class declaration in a schema.usda file.
125
126See \ref Usd_ExampleSchema for examples of each type of schema class.
127
128\section Usd_BuiltinAPISchemas Built-in applied API schemas
129
130In some cases an IsA schema may want to have certain API schemas always applied
131to prims of its schema type. To avoid having to manually apply these API schemas
132to all instances of these prim types we provide a few ways to specify built-in
133applied API schemas for IsA schema types. When a prim of an IsA schema type
134with built-in applied API schemas is created, all properties from the API
135schemas will also be built-in properties of the prim. The list of built-in API
136schemas can be queried from the prim type's
137\ref UsdPrimDefinition::GetAppliedAPISchemas "prim definition" and the prim will
138also return true from UsdPrim::HasAPI for all of its built-in API schemas.
139
140Additionally, for some applied API schema types, we may want the application of
141the API schema to additionally apply one or more other API schemas. We also
142provide, through the same mechanisms as we have for IsA schemas, the ability to
143specify built-in applied API schemas for single-apply API schema types. When a
144single-apply API schema with built-in API schemas is applied to a prim (or is
145included as a built-in for another type), all of its built-in API schemas are
146also applied. These built-ins nest, so an API schema can include another
147built-in API schema which itself includes yet another built-in API schema and
148all these be applied when the top level API schema is applied.
149
150\subsection Usd_SchemaDefinedBuiltinAPIs Schema defined built-in APIs
151
152The first and most straightforward way an IsA or single-apply API schema author
153can specify which applied API schemas it wants built-in is by adding them
154through the \em apiSchemas field in their schema definition like so:
155
156\code
157# Example of a concrete, typed (IsA) schema with built-in applied API schemas
158class MyCustomPrim "MyCustomPrim" (
159    inherits = </Typed>
160
161    # These listed applied API schemas will be built-in to this schema type.
162    apiSchemas = ["ExampleSingleApplyAPI", "ExampleMultiApplyAPI:foo"]
163)  {
164    # Example of a default value override for a theoretical property defined in
165    # the API schema instance "ExampleMultiApplyAPI:foo"
166    bool exampleMulti:foo:boolAttr = true
167}
168
169# Example of a single-apply API schema with built-in applied API schemas
170class "MyCustomAPI" (
171    inherits = </APISchemaBase>
172
173    # These listed applied API schemas will be built-in to this schema type and
174    # will always be applied when this schema is applied.
175    apiSchemas = ["ExampleSingleApplyAPI", "ExampleMultiApplyAPI:foo"]
176)  {
177    # Example of a default value override for a theoretical property defined in
178    # the API schema instance "ExampleMultiApplyAPI:foo". This schema will be
179    # stronger when applied than its built-in API schemas and this default value
180    # will be used for the added property.
181    bool exampleMulti:foo:boolAttr = true
182}
183\endcode
184
185The listed API schemas will be built-in to the declared schema type. For IsA
186schemas, derived types of the IsA schema will inherit its built-in API schemas
187(applied API schemas cannot inherit from each other.) Any schema can specify
188overrides to properties that would come from one of its built-in API schemas by
189declaring the property itself. This should be done carefully to avoid breaking
190conformance with the built-in schema itself (like changing the property's type)
191and is typically used for changing the default value for the property.
192\sa \ref Usd_APISchemaStrengthOrdering
193
194\subsection Usd_AutoAppliedAPISchemas Auto applied API schemas
195
196In addition to schemas being able to declare built-in applied API schemas,
197an applied API schema can specify that it should be automatically applied to
198any number of IsA or single-apply API schemas. The primary use case for this is
199when a schema author wants to extend an existing schema with properties from
200their own applied API schema without altering the existing schema itself.
201Specifying the API schema to auto apply can accomplish this goal without having
202to manually apply the API to every prim instance of a schema type (or to every
203prim instance with a specific API schema applied). A concrete example would be a
204renderer providing an API schema for its own specific render properties that can
205then be automatically applied to UsdLux light typed prims when the renderer and
206its API schema are available.
207
208An author of an API schema can specify the IsA and/or single-apply API schemas
209to which it wants to be automatically applied through the
210\em apiSchemaAutoApplyTo field in the API schema definition's customData like
211so:
212
213\code
214# Example of an applied API schema specified to auto apply to both a concrete
215# and an abstract IsA schema as well as another single-apply API schema.
216class "MyCustomAPI" (
217    inherits = </APISchemaBase>
218    customData = {
219        # These listed IsA and API schemas add this API schema to their built-in
220        # API schemas.
221        token[] apiSchemaAutoApplyTo = [
222           "MyCustomConcretePrim", "MyCustomAbstractPrim", "MyCustomAPI"]
223    }
224)  {
225    int autoApplyApiAttr = 1
226}
227\endcode
228
229The specified schema names in the \em apiSchemaAutoApplyTo field can refer to
230another single-apply API schema and to both abstract and concrete IsA schema
231types. For the IsA schema types, the applied schema will be added to the
232built-in schemas for the listed types as well as for any derived schemas of the
233listed types. Note that this customData field is only supported for single apply
234API schemas as multiple apply API schemas cannot be applied without an instance
235name.
236
237\subsection Usd_PluginAutoAppliedAPISchemas Plugin defined auto applied API schemas
238
239Lastly, it is also possible for plugins to specify additional built-in API
240schemas for other schema types outside of schema generation. This is useful if a
241client desires schema types to have built-in API schemas but doesn't want to
242force this upon all clients by changing the generated schemas themselves. An
243example use case for this would be a client pipeline that wants an available UI
244related API schema applied to all shader prim types as this is not something all
245users of these schemas may necessarily want.
246
247A plugin author can specify their additional built-in API schemas in their
248plugin's plugInfo.json file using the \em AutoApplyAPISchemas metadata like so:
249
250\code
251{
252    "Plugins": [
253        {
254            "Info": {
255                "AutoApplyAPISchemas" : {
256                    "ExistingSingleApplyAPI": {
257                        "apiSchemaAutoApplyTo": [
258                            "ExistingPrimType"
259                        ]
260                    },
261                    "ExistingMultiApplyAPI:foo": {
262                        "apiSchemaAutoApplyTo": [
263                            "ExistingPrimType", "ExistingSingleApplyAPI"
264                        ]
265                    }
266                }
267            }
268        }
269    ]
270}
271\endcode
272
273The metadata format is a dictionary of API schema names to a list of the schemas
274the plugin wants them to be applied to as a built-in API. Like with the schema
275generated \ref Usd_AutoAppliedAPISchemas "auto apply schemas", the API schemas
276will also be applied to any derived schema types of any listed IsA schemas.
277Multiple apply schemas (in addition to single apply) can also be auto applied
278using this plugin metadata as long as the fully qualified instance name for the
279mulitple apply schema is provided.
280
281\subsection Usd_APISchemaStrengthOrdering Property conflicts and API schema strength ordering
282
283Given that we encourage (or even require in the case of multi apply schemas) the
284use of namespace prefixes for API schema property names, we expect most
285properties defined in API schemas will be unique to the schema. However, there
286will always be the possibility that properties with the same name may be defined
287in multiple API schemas applied to the same prim. To account for this, there is
288a strength ordering for applied API schemas that we use to determine which
289property definition "wins" when more than one API schema can define it. Note
290that in this situation, we do not compose the competing property definitions;
291the entirety of the "winning" property definition is used and any weaker
292definitions are ignored.
293
294Firstly, the strongest opinion for a built-in property in an IsA schema's
295\ref UsdPrimDefinition "prim definition" will always come from the IsA schema
296itself. This is what allows us to override things like property default values
297from a built-in API schema.
298
299Next, any auto applied API schemas, whether defined in the
300\ref Usd_AutoAppliedAPISchemas "API schema's definition" or in a
301\ref Usd_PluginAutoAppliedAPISchemas "plugin's metadata", will be appended to
302the end of the list of built-in applied API schemas for the IsA or single-apply
303API they apply to. Since the built-in schema list is ordered strongest to
304weakest for application, this also means that <b> auto applied schemas will
305always be weaker relative to the built-in API schemas defined in the schema they
306are auto applied to</b>. When more then one API schema is auto applied to the
307same schema type, they are always sorted into alphabetical order by schema name
308before they are appended to the built-in schemas. The alphabetical ordering is
309arbitrary but deterministic as there is no provided way to indicate strength
310ordering between auto applied API schemas.
311
312Lastly, the \ref Usd_SchemaDefinedBuiltinAPIs "built-in schemas" that are
313defined in the apiSchemas metadata of the IsA schema are applied in the order
314they appear in the composed list operation of the apiSchemas field, using a
315depth first expansion of any API schema that itself has included built-in API
316schemas. This list order is strongest to weakest, so property name conflicts
317will prefer a property definition from an API schema earlier in the list.
318
319Also note that any API schemas that are applied to a prim instance in scene
320description will still have a stronger opinion on properties they define that
321are also present as built-in properties from the prim's schema type definition.
322
323\section Usd_SchemaCodeGeneration Schema Code Generation
324
325Simply run the ```usdGenSchema``` command to generate code in the current
326directory for the schema classes defined in the file named 'schema.usda'.
327
328The code generator uses \c jinja2 templates that are installed with USD.
329build.  The default schema class templates that ship with USD include the
330following files:
331
332  - <b>schemaClass.h, schemaClass.cpp, wrapSchemaClass.cpp</b>:
333    One set for each class found in schema.usda
334
335  - <b>%tokens.h, tokens.cpp, wrapTokens.cpp</b>:
336    Contains static TfTokens for use with all schema in the library.
337
338  - <b>plugInfo.json</b>:
339    Every Pxr module that contains plugins has one of these.  We add a
340    declaration for every generated schema class into this file so that
341    USD core can discover all plugin prim types cheaply and robustly.
342
343  - <b>%api.h</b>:
344    Boilerplate macro definitions for exporting symbols on various platforms.
345
346In addition to the files in schemata and tokens related files, the following
347files are edited by the script:
348
349  - <b>generatedSchema.usda</b>:
350    Processed form of schema definitions that will be consumed at runtime by
351    USD core.
352
353\parblock
354\note usdGenSchema will update existing files in the current directory
355if it detects any differences with the code it generates. Make sure these
356files are editable before running usdGenSchema
357\endparblock
358
359\parblock
360\note usdGenSchema does not update the CMakeLists.txt and module.cpp files,
361even if they are editable.  If you have added a new class(es), you must
362add them to these files yourself.
363\endparblock
364
365Various command-line options are available for customizing the code generation
366process. Run ```usdGenSchema --help``` for more details.
367
368\section Usd_NameSpacedPropertiesInCodeGen Namespaced Properties in Code Generation
369
370usdGenSchema also supports the use of namespaced properties for code generation.
371For example, float  foo:bar will generate UsdMyClass::GetFooBarAttr() and
372UsdTokens->fooBar (with a value of "foo:bar").  usdGenSchema will raise
373exceptions to avoid naming collisions in the schema API and enforces a
374One-to-One mapping of token identifiers to token values, as shown below.
375
376\code
377class MyClass "MyClass" {
378    # Generates UsdMyClass::GetFooBarAttr() and UsdTokens->fooBar with value
379    # "fooBar"
380    float fooBar
381
382    # ERROR: Naming collision in both API and tokens. Generates
383    # UsdMyClass::GetFooBarAttr() and UsdTokens->fooBar with value "foo:bar"
384    float foo:bar
385
386    # ERROR: Naming collision in tokens. Generates UsdMyClass::GetMyTokenAttr()
387    # and UsdTokens->fooBar with value "foo-bar"
388    token myToken = "foo-bar" (allowedTokens = ["foo-bar"])
389}
390\endcode
391
392\section Usd_GlobalSchemaProperties Global Schema Properties
393
394Each schema.usda file can contain a \em GLOBAL section like the following to
395provide customizations that apply to all the classes in the module:
396
397\code
398over "GLOBAL" (
399    customData = {
400        string libraryName       = "pxUsdGeom"
401        string libraryPath       = "folder/pxUsdGeom"
402        string libraryPrefix     = "PxUsdGeom"
403        string tokensPrefix      = "PxUsdGeom"
404        dictionary libraryTokens = {
405            dictionary libraryToken1 = {}
406            dictionary libraryToken2 = {
407                string value = "/non-identifier-tokenValue!"
408                string doc = """doc for libraryToken2"""
409            }
410        }
411        bool skipCodeGeneration = true
412    }
413)
414{
415\endcode
416
417Here's a short description of each datum in the global customData dictionary:
418
419  - \b libraryName - The name of the module into which the schema-generated files
420    will be installed. \b Required!
421
422  - \b libraryPath - The partial path with which to prefix '#include' statements
423    of generated files for this module. For external (non-Pixar) plugins, we
424    recommend setting libraryPath to ".", so that the headers inside src
425    directory are included in the generated files. \b Required unless
426    skipCodeGeneration is true!
427
428  - \b libraryPrefix - The prefix for all generated schema classes in the module.
429    If not specified, falls back to ProperCase(libraryName)
430
431  - \b tokensPrefix - The prefix to use for the tokens class, if it needs to be
432    different from libraryPrefix
433
434  - \b libraryTokens - a place to declare tokens meaningful to the module.
435    These tokens will be included in the module's static tokens. If
436    provided, the "doc" string will be included in the tokens documentation.
437    If provided, the "value" string will be assigned as the token's value;
438    otherwise, the token's value will be its identifier (as a TfToken).
439
440  - \anchor codeless_schema \b skipCodeGeneration - Flag that, when set to
441    true, tells schema generation that it should not generate any C++ code for
442    the classes in this module. We call a schema without any corresponding C++
443    classes a "codeless schema". Note that if skipCodeGeneration is set to true
444    for a schema module, then any other schema module that includes it will
445    also not generate any code. This is because we don't want to generate C++
446    code for classes that would possibly inherit from another C++ class that
447    doesn't exist.
448
449\section Usd_PerClassProperties Customizing Per-Class Properties
450
451\code
452class PxHairman "PxHairman" (
453    customData = {
454        string className = "Hairman"
455        string fileName = "_hairman"
456        string extraIncludes = """
457#include "pxr/usd/usdGeom/primvar.h"
458"""
459        dictionary extraPlugInfo = {
460            string customString = "metadata"
461            bool customBool = true
462            int customInt = 0
463            dictionary customDict = {
464                string customNestedString = "nested"
465            }
466        }
467        dictionary schemaTokens = {
468            dictionary schemaToken1 = {}
469            dictionary schemaToken2 = {
470                string value = "/non-identifier-tokenValue!"
471                string doc = """doc for schemaToken2"""
472            }
473        }
474        token[] fallbackTypes = ["PrimTypeName1", "PrimTypeName2"]
475    }
476)
477{
478}
479\endcode
480
481Here's a short description of each datum in the per-class customData dictionary:
482
483  - \b className - If the USD prim typeName for the schema must be different than
484    the un-prefixed class name,  then use className customData to provide the
485    class name for the C++ (which will be prefixed) and python schema classes.
486
487  - \b fileName - if specified, will be the base name for the .h and .cpp generated
488    files.  If not specified, base name falls back to  CamelCase(className)
489
490  - \b extraIncludes - if specified, will add extra include paths for files
491    required by the "custom" section of this class only. Note that this will
492    add includes to the generated header file for the class. If includes
493    are only needed in the generated implementation file(.cpp),
494    one can instead add the header includes to the custom
495    section of the cpp file specifically.
496
497  - \b extraPlugInfo - if specified, the (key, value) pairs in this dictionary
498    will be added as additional metadata for this class in the library's
499    plugInfo.json file. The values in this dictionary must be numeric types,
500    strings, booleans, or dictionaries containing these types.
501    Examples of such extraPlugInfo include
502    _providesUsdShadeConnectableAPIBehavior_, _isUsdShadeContainer_,
503    _requiresUsdShadeEncapsulation_ -- these can be used to configure
504    UsdShadeConnectableAPIBehavior for Typed or API schemas.
505
506  - \b schemaTokens - a place to declare tokens meaningful to the schema.
507    These tokens will be included in the module's static tokens. See docs
508    above for the libraryTokens entry in the global customData dictionary
509    for details about the contents of this dictionary.
510
511  - \b apiSchemaType - must only be specified for an API schema. Defaults to
512    the token 'singleApply', to indicate a single-apply API schema.
513    Can be set to 'nonApplied', to create a non-applied API schema or to
514    "multipleApply" to create a multiple-apply API schema.
515
516  - \b propertyNamespacePrefix - must only be specified on multiple apply API
517    schemas which have properties. This token, alongside the instance name,
518    will be inserted as a prefix to all properties created by this
519    multiple-apply API schema.
520
521  - \b apiSchemaAutoApplyTo - must only be specified on single apply API
522    schemas. This is a token array value that lists the names of typed schemas
523    and other single apply API schemas that this API schema will be
524    automatically applied to when the listed typed schemas are processed by the
525    \ref Usd_OM_SchemaDefinitionRegistry "schema definition registry."
526
527  - \b apiSchemaCanOnlyApplyTo - must only be specified on single and multiple
528    apply API schemas. This is a token array value that, when specified, is used
529    by UsdPrim::CanApplyAPI and the schema's generated CanApply function to
530    limit the prims to which this API schema can be validly applied to only the
531    schema types whose names are in this list.
532
533  - \b apiSchemaAllowedInstanceNames - must only be specified on multiple apply
534    API schemas. This is a token array value that, when specified, is used by
535    UsdPrim::CanApplyAPI and the schema's generated CanApply function to limit
536    the instance names that are valid to use when applying this API schema to
537    only the instance names included in this list.
538
539  - \b apiSchemaInstances - must only be specified on multiple apply API
540    schemas. This is a dictionary value that allows additional custom data
541    to be specified for specific instance names of this multiple apply API
542    schema. This dictionary can map an instance name to another dictionary value
543    containing the custom data fields that will only apply to that instance
544    name. Currently only \em apiSchemaCanOnlyApplyTo custom data can be
545    specified in these per instance name dictionaries and will take precedence
546    over the \em apiSchemaCanOnlyApplyTo custom data (specified for the entire
547    schema type) for that instance name when present. The GridCrittersAPI
548    in the \ref Usd_ExampleSchema "examples section" demonstrates how this can
549    be used.
550
551  - \b fallbackTypes - must only be specified for a concrete typed schema.
552    This is a token array value used to specify the preferred fallback schema
553    types that can be used instead when this schema isn't present.
554    This data is used by UsdStage::WriteFallbackPrimTypes to record, on a stage,
555    the \ref Usd_OM_FallbackPrimTypes "fallback prim types" metadata that USD
556    versions which lack this schema will use to choose a suitable alternative
557    schema type.
558
559\section Usd_CustomizingPerProperty Customizing Per-Property
560
561\code
562ColorFloat[] primvars:displayColor (
563    customData = {
564        string apiName = "displayColor"
565    }
566)
567\endcode
568
569Here's a short description of each datum in the per-property customData
570dictionary:
571
572  - \b apiName - Schema properties may define an 'apiName' in customData to
573    override the default generated accessor API. For example, the above spec
574    produces GetDisplayColorAttr instead of GetPrimVarsDisplayColorAttr as the
575    attribute accessor.  As a special case, if 'apiName' is set to the
576    empty string, then no accessor API will be generated.
577    Note: The actual name of the property as defined on the prim is still
578    primvars:displayColor.
579  - \b apiGetImplementation - Optionally control schema gen behavior for a property's
580    'Get' implementation. Valid values:
581    - \e generated - Generate default header and implementation (Fallback value if unspecified).
582    - \e custom - Generate default header ONLY. User must supply the implementation
583    Custom should be used sparingly, primarily as a tool for API migration
584    Given the performance expectations of Get, it is NOT appropriate to
585    add complicated validation logic in this method.
586
587\section Usd_ExampleSchema Example Schema Classes
588
589\code
590#usda 1.0
591(
592    """ This file describes an example schemata used for code generation using
593        usdGenSchema.
594    """
595    subLayers = [
596        # This is mainly needed for definition of UsdTyped.
597        @usd/schema.usda@
598    ]
599)
600
601over "GLOBAL" (
602    customData = {
603        string libraryName = "myLib"
604        string libraryPath = "componentName/myLib"
605        dictionary libraryTokens = {
606            dictionary sampleToken = {
607                string doc = "Documentation for sample token."
608            }
609        }
610    }
611) {
612
613}
614
615# Example of a non-concrete IsA schema
616# Note that non-concrete IsA schemas cannot specify a typeName in the class
617# declaration, but they are allowed to provide fallback values for attributes.
618class "MyBaseCustomPrim" (
619    doc = """Defines a non-instantiable (non-concrete) typed schema that derives
620             from MyCustomPrim. Derived schema classes can inherit from this
621             schema to add (for e.g.) geometric properties."""
622
623    # IsA schemas should derive from </Typed> or a Schema that derives from
624    # Typed.
625    #
626    # API schemas need not specify inherits. usdGenSchema sets the parent
627    # class for such schemas to UsdSchemaBase.
628    inherits = </Typed>
629    customData = {
630        string className = "MyBasePrim"
631    }
632) {
633    # Some base attributes common to all derived schemas
634    uniform double uniformScale = 1.0 (
635        doc = "A double valued uniform attribute representing scale."
636    )
637
638    float3 rotation = (0, 0, 0) (
639        doc = "A varying 3D vector in floating-pt precision representing rotation."
640    )
641
642    double3 translation = (0, 0, 0) (
643        doc = "A varying double valued 3D vector representing translation."
644    )
645}
646
647# Example of a concrete, typed (IsA) schema
648class MyCustomPrim "MyCustomPrim" (
649    doc = """Defines a custom typed (IsA) schema prim"""
650
651    inherits = </MyBaseCustomPrim>
652
653    customData = {
654        string className = "MyPrim"
655        customData = {
656            string extraIncludes = """
657                #include "pxr/base/gf/bbox3d.h"
658                #include "pxr/usd/usdGeom/primvar.h" """
659        }
660    }
661)  {
662    # Attributes with fallback values.
663    asset filePath = @/path/to/default/file@ (
664        doc = """An asset path valued attribute that points to a file on disk."""
665    )
666
667    uniform token axis = "X" (
668        allowedTokens = ["X", "Y", "Z"]
669        doc = """A token valued attribute representing an axis."""
670    )
671
672    matrix4d transform = ((1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1)) (
673        doc = """Double-precision transformation matrix, which should encode
674                 the entire local transformation for a prim.""")
675    )
676
677    # Attributes with no fallback values.
678    point3f[] points (
679        doc = """An attribute representing a list of points in 3D space."""
680    )
681
682    string[] strArray (
683        doc = """A string array valued attribute."""
684    )
685
686    string str (
687        doc = """An int valued attribute."""
688    )
689
690    # Relationships
691    rel target (
692        doc = """A relationship called target that could point to another prim
693                or a property"""
694    )
695}
696
697# Example API schema that provides an interface for manipulating a specific
698# set of attributes on a prim.
699#
700# API schemas can "declare" and provide access to properties defined by
701# collections of other IsA and API schemas, gathered into one API for
702# convenience.  They can also (more commonly, in our use, thus far), define
703# their own properties with their own fallbacks.  In this capacity,
704# the convention is to namespace each property with the API's name (camelCased),
705# for easy identification, as well as to help prevent built-in properties from
706# API schemas from unintentionally overriding built-in properties of the IsA
707# schema when applied.
708# For example...
709class "MyParamsAPI" (
710    inherits = </APISchemaBase>
711    customData = {
712        token apiSchemaType = "singleApply"
713
714        # This is an example of specifying typed schemas that this single apply
715        # schema will be automatically applied to.
716        token[] apiSchemaAutoApplyTo = ["MyCustomPrim",
717                                        "OutsidePluginCustomPrim"]
718
719        # This is an example of specifying typed schemas that this single apply
720        # API can only be applied to. Specifying this means that the generated
721        # MyParamsAPI::CanApply(prim) and prim.CanApplyAPI<MyParamsAPI>()
722        # will only return true if the prim is one of these listed types.
723        token[] apiSchemaCanOnlyApplyTo = ["MyCustomPrim",
724                                           "OutsidePluginCustomPrim",
725                                           "AnotherCustomPrim"]
726    }
727)
728{
729    double myParams:size (
730        customData = {
731            string apiName = "size"
732        }
733        doc = "double specifying the size."
734    )
735
736    uniform int myParams:numSamples (
737        customData = {
738            string apiName = "numSamples"
739        }
740        doc = "Uniform int specifying the number of samples."
741    )
742
743    double3 myParams:offset = (0, 0, 0) (
744        customData = {
745            string apiName = "offset"
746        }
747        doc = "3D offset."
748    )
749
750    # By default, all properties of IsA and API schemas are considered
751    # "builtin", i.e. not \ref UsdProperty::IsCustom() "custom".  However,
752    # one can force a schema property to be considered custom by explicitly
753    # declaring it to be so.
754    custom string info
755}
756
757# Example multiple-apply API that gives an interface to create instances of
758# "critters" on a prim.
759class "GridCrittersAPI" (
760    inherits = </APISchemaBase>
761    customData = {
762        token apiSchemaType = "multipleApply"
763        token propertyNamespacePrefix  = "critter"
764
765        # This is an example of all the ways we can specify how the schema's
766        # generated CanApply and UsdPrim::CanApplyAPI behave for this multiple
767        # apply schema. The following customData specifies that:
768        # 1. GridCrittersAPI::CanApply(prim, instanceName) will return false
769        #    if instanceName is anything but "insect" or "rodent" because of
770        #    apiSchemaAllowedInstanceNames.
771        # 2. GridCrittersAPI::CanApply(prim, "insect") will only return true
772        #    if prim.IsA<MyCustomPrim>() because this is specified in
773        #    apiSchemaInstances
774        # 3. GridCrittersAPI::CanApply(prim, "rodent") will only return true
775        #    if prim.IsA<MyCustomPrim>() or prim.IsA<AnotherCustomPrim>()
776        #    because this is specified in apiSchemaCanOnlyApplyTo and there is
777        #    no override in apiSchemaInstances
778        token[] apiSchemaAllowedInstanceNames = ["insect", "rodent"]
779        token[] apiSchemaCanOnlyApplyTo = ["MyCustomPrim",
780                                           "AnotherCustomPrim"]
781        dictionary apiSchemaInstances = {
782            dictionary insect = {
783                token[] apiSchemaCanOnlyApplyTo = ["MyCustomPrim"]
784            }
785        }
786    }
787)
788{
789    # this will be instantiated as "critter:<instance name>:xform"
790    matrix4d xform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) )
791    # this will be instantiated as "critter:<instance name>:color"
792    color4f color
793}
794\endcode
795
796See \ref Usd_Page_Datatypes for the list of all data types provided by Sdf.
797
798\section Usd_GeneratedSchemaCustomCode Adding Custom Code To Generated Schemas
799
800Custom code written after the "// --(BEGIN CUSTOM CODE)--" delimiter in the
801generated schema files will be preserved between successive usdGenSchema runs.
802Typically, this will include additional API you may want to provide on your
803schema classes.
804
805\section Usd_SchemaExtensionPhilosophy Impact on Interchange of Creating and Extending Schemas
806
807Coming soon!
808
809*/
810