X3DAppearanceChildNode : X3DNode {
}

X3DAppearanceNode : X3DNode {
}

X3DMaterialNode : X3DAppearanceChildNode {
  # This is not actually specified anywhere (X3D XML encoding spec
  # doesn't specify containerField for abstract X3DXxxNode classes)
  # but it seems most sensible to have all X3DMaterialNode with containerField=material.
  default-container-field: material
}

X3DOneSidedMaterialNode : X3DMaterialNode {
  default-container-field: material

  SFColor  [in,out] emissiveColor           0 0 0
    range: [0, 1]
    doc: Emissive color, multiplied by the @link(EmissiveTexture), makes the shape brighter regardless of the surrounding lights. Usually used to make things glow.
  SFNode   [in,out] emissiveTexture         NULL
    range: X3DSingleTextureNode
    change: chEverything
    doc: Emissive texture is multiplied by the @link(EmissiveColor). It allows the perceived emissive factor depend on a texture, and thus vary across the surface.
  SFString [in,out] emissiveTextureMapping  ""
    doc: Determines texture coordinates used by @link(EmissiveTexture).

  SFNode   [in,out] normalTexture           NULL
    range: X3DTexture2DNode
    change: chEverything
    doc: Normalmap texture to perform bump mapping. See https://castle-engine.io/bump_mapping .
  SFString [in,out] normalTextureMapping    ""
    doc: Determines texture coordinates used by @link(NormalTexture).
  SFFloat  [in,out] normalScale             1
    range: [0,Inf)
    change: chEverything
    doc: Emphasize (when > 1) or deemphasize (< 1) the effect of @link(NormalTexture) on the model.
}

X3DShapeNode : X3DChildNode, X3DBoundedObject {
  # In X3D specificaction, appearance can be [X3DAppearanceNode].
  # But X3DAppearanceNode type is not useful, as the only possible descendant of it is Appearance,
  # so we change the type to allow Appearance.
  # This makes accessing it easier, like "Shape.Appearance.Texture := xxx".
  SFNode  [in,out] appearance NULL
    range: Appearance
    setter-before: SetAppearanceBefore
  SFNode  [in,out] geometry   NULL
    range: X3DGeometryNode
  # As Castle Game Engine extension, we allow bboxCenter/Size to be modified,
  # i.e. they are [in,out] not only [].
  SFVec3f [in,out] bboxCenter 0 0 0
    range: (-Inf,Inf)
    # Note that bboxCenter documentation string it used for generated "BBox: TBox3D" property.
    doc: """
      You can provide a manually-calculated bounding box of the shape here, for optimization purposes. Leave this field as empty (TBox3D.Empty) to let the engine calculate best bounding box automatically.

      Manually providing the bounding box makes sense if you can do it more efficiently than the engine. E.g. if the shape vertexes are animated, then the engine would have to recalcualate the perfect bounding box every frame. It is more efficient to calculate a bounding box of all possible animation frames, and store it here.

      The glTF skinned animation automatically fills this field for the affected shapes.

      @italic(Note: This property is not useful if you want to know the bounding box of a shape, calculated by the engine). This property only allows to override the automatic engine calculation.

      To read the calculated bounding box, load the nodes to TCastleScene. You can then use @link(TCastleTransform.BoundingBox Scene.BoundingBox), @link(TCastleTransform.LocalBoundingBox Scene.LocalBoundingBox), @link(TCastleTransform.WorldBoundingBox Scene.WorldBoundingBox) to know bounding box of the scene. To get bounding box of a particular shape, enumerate @link(TCastleSceneCore.Shapes) to find the correct shape (using any criteria you want -- note that the same TShapeNode may be reused multiple times), and then read @link(TShape.BoundingBox), @link(TShape.LocalBoundingBox).
      """

  SFVec3f [in,out] bboxSize -1 -1 -1
    range: [0,Inf) or -1 -1 -1

  # CASTLE GAME ENGINE EXTENSIONS:
  SFString [in,out]     shading            "DEFAULT"
    range: ["DEFAULT"|"GOURAUD"|"PHONG"|"WIREFRAME"]
    enumerated-type: TShading ShadingNames shDefault
    doc: How to display given shape.
  SFBool   [in,out]     visible            TRUE
    doc: """
Is the shape visible. Shapes that are not visible are not rendered, but otherwise are still processed (for example, hidden shapes are still used for collision detection). Toggling this is guaranteed to be ultra-fast.

Note: An alternative method to hide (and more) things in X3D is to wrap them in a @link(TSwitchNode), and toggle @link(TSwitchNode.WhichChoice) between -1 and 0. When @link(TSwitchNode.WhichChoice) is -1, the children are not processed (not rendered, and do not collide).
"""
  SFString []           collision          "DEFAULT"
    range: ["DEFAULT"|"BOX"|"NONE"]
    enumerated-type: TShapeCollision ShapeCollisionNames scDefault
    doc: How does the given shape collide. This only matters if @link(TCastleSceneCore.PreciseCollisions) is @true, otherwise the whole scene (with all shapes) collides as one big bounding box.
}

Appearance : X3DAppearanceNode {
  # Note: In edition 2 of X3D XML encoding, the default-container-field of this is empty...
  # but in earlier versions, this was "appearance" and this seems more sensible,
  # Appearance node may only occur within Shape.appearance field.

  default-container-field: appearance
  SFNode [in,out] fillProperties   NULL
    range: FillProperties
    not-slim
  SFNode [in,out] lineProperties   NULL
    range: LineProperties
    doc: Properties how to display line geometry (line width and such).
  SFNode [in,out] material         NULL
    range: X3DMaterialNode
    change: chEverything
    doc: Material determines how the shape looks, and how it interacts with lighting.
    setter-before: MoveShapeAssociations
  MFNode [in,out] shaders          []
    range: X3DShaderNode
    change: chEverything
    doc: Override shaders used for rendering this shape. Instead of this, it is usually better to use @link(SetEffects) -- the effects set that way are easier, cooperate with CGE built-in rendering features, and one code is more portable to both mobile and desktop.
  SFNode [in,out] texture          NULL
    range: X3DTextureNode
    change: chEverything
    doc: Main texture used by this appearance (diffuse texture for Phong lighting model, base texture for physical lighting model, emissive texture for the unlit lighting model). @deprecated It is more flexible to set the relevant texture inside material node, like @link(TMaterialNode.DiffuseTexture), @link(TPhysicalMaterialNode.BaseTexture), @link(TAbstractOneSidedMaterialNode.EmissiveTexture TUnlitMaterialNode.EmissiveTexture).
  SFNode [in,out] textureTransform NULL
    range: X3DTextureTransformNode
    change: chEverything
    doc: Texture transformation.

  # X3D 4
  SFNode [in,out] backMaterial     NULL
    range: X3DOneSidedMaterialNode
    change: chNone
    doc: Alternative material to use for back faces (@italic(not implemented)).
  SFString   [in,out]      alphaMode     "AUTO"
    range: ["AUTO"|"OPAQUE"|"MASK"|"BLEND"]
    enumerated-type: TAlphaMode AlphaModeToString amAuto
  SFFloat    [in,out]      alphaCutoff   0.5
    range: [0,1]

  # CASTLE GAME ENGINE EXTENSIONS:
  MFNode     []            receiveShadows  []
    range: X3DPunctualLightNode
    change: chShadowMaps
  SFBool     [in,out]      shadowCaster     TRUE
    change: chShadowCasters
  SFNode     [in,out]      normalMap        NULL
    range: X3DTexture2DNode
    change: chEverything
    doc: Normal map of this appearance. See https://castle-engine.io/x3d_implementation_texturing_extensions.php#section_ext_bump_mapping . @deprecated It is better to set normal map within the material node, using the @link(TAbstractOneSidedMaterialNode.NormalTexture).
  SFNode     [in,out]      heightMap        NULL
    range: X3DTexture2DNode
    not-slim
    doc: Height map of this appearance. See https://castle-engine.io/x3d_implementation_texturing_extensions.php#section_ext_bump_mapping . @deprecated
  SFFloat    [in,out]      heightMapScale   0.01
  SFNode     [in,out]      blendMode        NULL
    range: BlendMode
    change: chEverything
    doc: Determines the exact blending equation used, in case @link(AlphaMode) indicates blending. See https://castle-engine.io/x3d_extensions.php#section_ext_blending .
  MFNode     []            effects          []
    range: Effect
    change: chEverything
    doc: Additional shader code for rendering this shape. See https://castle-engine.io/compositing_shaders.php . The shader effects they are easy to use, cooperate with CGE built-in rendering features, and one code is more portable to both mobile and desktop.
  SFString   [in,out]      alphaChannel     "AUTO"
    range: ["AUTO"|"NONE"|"TEST"|"BLENDING"]
    enumerated-type: TAutoAlphaChannel AlphaToString acAuto
}

FillProperties : X3DAppearanceChildNode {
  default-container-field: fillProperties
  SFBool  [in,out] filled     TRUE
  SFColor [in,out] hatchColor 1 1 1
    range: [0,1]
  SFBool  [in,out] hatched    TRUE
  SFInt32 [in,out] hatchStyle 1
    range: [0,Inf)
}

LineProperties : X3DAppearanceChildNode {
  default-container-field: lineProperties
  SFBool  [in,out] applied              TRUE
  SFInt32 [in,out] linetype             1
    range: [1,Inf)
  SFFloat [in,out] linewidthScaleFactor 0
    range: (-Inf,Inf)
}

Material : X3DOneSidedMaterialNode {
  default-container-field: material
  SFFloat  [in,out] ambientIntensity         0.2
    range: [0,1]
  SFNode   [in,out] ambientTexture           NULL
    range: X3DSingleTextureNode
    change: chEverything
  SFString [in,out] ambientTextureMapping    ""

  SFColor  [in,out] diffuseColor             0.8 0.8 0.8
    range: [0,1]
    doc: The primary way to control the color of object with Phong material. The object reflects light sources depending on the angle of the surface with respect to the light source. The more directly the surface faces the light, the more diffuse light reflects.
  SFNode   [in,out] diffuseTexture           NULL
    range: X3DSingleTextureNode
    change: chEverything
    doc: The primary texture to control the color of object with Phong material. The RGB channel of this texture is multiplied with @link(DiffuseColor), and alpha channel is multiplied with the opacity (1-@link(Transparency)).
  SFString [in,out] diffuseTextureMapping    ""

  SFFloat  [in,out] occlusionStrength        1
    range: [0,1]
  SFNode   [in,out] occlusionTexture         NULL
    range: X3DSingleTextureNode
    change: chEverything
  SFString [in,out] occlusionTextureMapping  ""

  SFFloat  [in,out] shininess                0.2
    range: [0,1]
  SFNode   [in,out] shininessTexture         NULL
    range: X3DSingleTextureNode
    change: chEverything
  SFString [in,out] shininessTextureMapping  ""

  SFColor  [in,out] specularColor            0 0 0
    range: [0,1]
    doc: Color of specular highlight, on shiny objects.
  SFNode   [in,out] specularTexture          NULL
    range: X3DSingleTextureNode
    change: chEverything
  SFString [in,out] specularTextureMapping   ""

  SFFloat  [in,out] transparency                    0
    range: [0,1]
    doc: Setting @name to value > 0 makes the object partially-transparent. Setting it to 1.0 makes it even invisible (but still collidable). If you want to render the object using blending (which is usually the case for partially-transparent) it is recommended to specify it explicitly using @link(TAppearanceNode.AlphaMode).

  # CASTLE GAME ENGINE EXTENSIONS:
  SFBool     [in,out]      fogImmune             FALSE
    not-slim
  SFFloat    [in,out]      mirror                0.0
    range: [0.0; 1.0]
  MFColor    [in,out]      reflSpecular          []
    not-slim
  MFColor    [in,out]      reflDiffuse           []
    not-slim
  MFColor    [in,out]      transSpecular         []
    not-slim
  MFColor    [in,out]      transDiffuse          []
    not-slim
  SFFloat    [in,out]      reflSpecularExp       1000000
    not-slim
  SFFloat    [in,out]      transSpecularExp      1000000
    not-slim
}

PhysicalMaterial : X3DOneSidedMaterialNode {
  default-container-field: material

  SFColor  [in,out] baseColor                       1 1 1
    range: [0,1]
    doc: The primary way to control the color of object with physical (PBR) material.
  SFNode   [in,out] baseTexture                     NULL
    range: X3DSingleTextureNode
    change: chEverything
    doc: The primary texture to control the color of object with physical (PBR) material. The RGB channel of this texture is multiplied with @link(BaseColor), and alpha channel is multiplied with the opacity (1-@link(Transparency)).
  SFString [in,out] baseTextureMapping              ""
    doc: Determines texture coordinates used by @link(BaseTexture).

  SFFloat  [in,out] metallic                        1
    range: [0,1]
    doc: The metalness of the material; values range from 0.0 (non-metal) to 1.0 (metal).
  SFNode   [in,out] metallicRoughnessTexture        NULL
    range: X3DSingleTextureNode
    change: chEverything
    doc: Control the @link(Metallic) and @link(Roughness) using a texture. The @italic(Blue) channel of this texture is multiplied with @link(Metallic). The @link(Green) channel is multiplied with @link(Roughness). The other channels are ignored.
  SFString [in,out] metallicRoughnessTextureMapping ""
    doc: Determines texture coordinates used by @link(MetallicRoughnessTexture).

  SFFloat  [in,out] occlusionStrength               1
    range: [0,1]
  SFNode   [in,out] occlusionTexture                NULL
    range: X3DSingleTextureNode
    change: chEverything
  SFString [in,out] occlusionTextureMapping         ""

  SFFloat  [in,out] roughness                       1
    range: [0,1]
    doc: The roughness of the material; values range from 0.0 (smooth) to 1.0 (rough).

  SFFloat  [in,out] transparency                    0
    range: [0,1]
    doc: Setting @name to value > 0 makes the object partially-transparent. Setting it to 1.0 makes it even invisible (but still collidable). If you want to render the object using blending (which is usually the case for partially-transparent) it is recommended to specify it explicitly using @link(TAppearanceNode.AlphaMode).
}

Shape : X3DShapeNode {
}

TwoSidedMaterial : X3DMaterialNode {
  SFFloat [in,out] ambientIntensity     0.2
    range: [0,1]
  SFFloat [in,out] backAmbientIntensity 0.2
    range: [0,1]
  SFColor [in,out] backDiffuseColor     0.8 0.8 0.8
    range: [0,1]
  SFColor [in,out] backEmissiveColor    0 0 0
    range: [0,1]
  SFFloat [in,out] backShininess        0.2
    range: [0,1]
  SFColor [in,out] backSpecularColor    0 0 0
    range: [0,1]
  SFFloat [in,out] backTransparency     0
    range: [0,1]
  SFColor [in,out] diffuseColor         0.8 0.8 0.8
    range: [0,1]!
  SFColor [in,out] emissiveColor        0 0 0
    range: [0,1]
  SFFloat [in,out] shininess            0.2
    range: [0,1]
  SFBool  [in,out] separateBackColor    FALSE
  SFColor [in,out] specularColor        0 0 0
    range: [0,1]
  SFFloat [in,out] transparency         0
    range: [0,1]
}

UnlitMaterial : X3DOneSidedMaterialNode {
  default-container-field: material

  # Note: emissiveColor default also changes to 1 1 1

  SFFloat [in,out] transparency             0
    range: [0,1]
    doc: Setting @name to value > 0 makes the object partially-transparent. Setting it to 1.0 makes it even invisible (but still collidable). If you want to render the object using blending (which is usually the case for partially-transparent) it is recommended to specify it explicitly using @link(TAppearanceNode.AlphaMode).
}
