X3DTextureCoordinateNode : X3DGeometricPropertyNode {
  # X3D XML spec doesn't specify containerField for abstract X3D classes.
  # But texCoord seems most sensible for this.
  default-container-field: texCoord
}

X3DTextureNode : X3DAppearanceChildNode {
  default-container-field: texture
}

X3DSingleTextureCoordinateNode : X3DTextureCoordinateNode {
  SFString [in,out] mapping  ""
    change: chTextureCoordinate
}

X3DSingleTextureNode : X3DTextureNode {
  # CASTLE GAME ENGINE EXTENSIONS:
  MFNode     []   effects          []
    range: Effect
    change: chEverything

  # X3DOM EXTENSIONS (https://doc.x3dom.org/author/Texturing/X3DTextureNode.html):
  # (note: X3DOM spec doesn't say if it's inputOutput or initializeOnly, below is just a guess)
  SFString   []   crossOrigin  ""
    not-slim
    change: chNone
    doc: X3DOM extension, not implemented in CGE.

  SFString   []   alphaChannel     "AUTO"
    range: ["AUTO"|"NONE"|"TEST"|"BLENDING"]
    enumerated-type: TAutoAlphaChannel AlphaToString acAuto
    change: chVisibleVRML1State
}

X3DSingleTextureTransformNode : X3DTextureTransformNode {
  SFString [in,out] mapping  ""
    # TODO is chTextureTransform enough? chTextureTransform will not free proxy?
    change: chTextureTransform
}

X3DTexture2DNode : X3DSingleTextureNode {
  SFBool []       repeatS           TRUE
    change: chTextureRendererProperties
  SFBool []       repeatT           TRUE
    change: chTextureRendererProperties
  SFNode []       textureProperties NULL
    range: TextureProperties
    change: chTextureRendererProperties
}

X3DTextureTransformNode : X3DAppearanceChildNode {
  default-container-field: textureTransform
}

ImageTexture : X3DTexture2DNode, X3DUrlObject {
  MFString [in,out] url               []
    range: [URI]
    change: chTextureImage
  SFBool   []       flipVertically    FALSE
    change: chTextureImage
}

MovieTexture : X3DTexture2DNode, X3DSoundSourceNode, X3DUrlObject {
  SFString [in,out] description       ""
  SFBool   [in,out] loop              FALSE
  SFTime   [in,out] pauseTime         0
    range: (-Inf,Inf)
    change: chTimeStopStart
  SFTime   [in,out] resumeTime        0
    range: (-Inf,Inf)
    change: chTimeStopStart
  SFFloat  [in,out] speed             1.0
    range: (-Inf,Inf)
  SFTime   [in,out] startTime         0
    range: (-Inf,Inf)
    change: chTimeStopStart
  SFTime   [in,out] stopTime          0
    range: (-Inf,Inf)
    change: chTimeStopStart
  MFString [in,out] url               []
    range: [URI]
    change: chTextureImage
  SFBool   []       flipVertically    FALSE
    change: chTextureImage
  SFTime   [out]    duration_changed
  SFTime   [out]    elapsedTime
  SFBool   [out]    isActive
  SFBool   [out]    isPaused
}

MultiTexture : X3DTextureNode {
  SFFloat  [in,out] alpha    1
    range: [0,1]
    change: chTextureRendererProperties
  SFColor  [in,out] color    1 1 1
    range: [0,1]
    change: chTextureRendererProperties
  MFString [in,out] function []
    change: chTextureRendererProperties
  MFString [in,out] mode     []
    change: chTextureRendererProperties
  MFString [in,out] source   []
    change: chTextureRendererProperties
  MFNode   [in,out] texture  []
    range: X3DSingleTextureNode
    change: chTextureRendererProperties
}

MultiTextureCoordinate : X3DTextureCoordinateNode {
  MFNode [in,out] texCoord NULL
    range: X3DSingleTextureCoordinateNode
    change: chTextureCoordinate
}

MultiTextureTransform : X3DTextureTransformNode {
  MFNode [in,out] textureTransform NULL
    range: X3DSingleTextureTransformNode
    change: chEverything
}

PixelTexture : X3DTexture2DNode {
  SFImage [in,out] image nil
    change: chTextureImage
}

TextureCoordinate : X3DSingleTextureCoordinateNode {
  MFVec2f [in,out] point    []
    range: (-Inf,Inf)
    change: chTextureCoordinate
}

TextureCoordinateGenerator : X3DSingleTextureCoordinateNode {
  SFString [in,out] mode      "SPHERE"
    change: chTextureCoordinate
    # TODO: should be defined as enum

  MFFloat  [in,out] parameter []
    change: chTextureCoordinate

  # Implementation note:
  # Note that projectedLight node is not enumerated as an active node
  # for traversing (in TTextureCoordinateGeneratorNode.DirectEnumerateActive),
  # because the light doesn't shine here. We don't want
  # to override it's transform with transformation of this
  # TextureCoordinateGenerator.
  SFNode   [in,out] projectedLight NULL
    range: SpotLight, DirectionalLight, TSpotLightNode_1, TDirectionalLightNode_1
    change: chTextureCoordinate
}

TextureProperties : X3DNode {
  default-container-field: textureProperties
  SFFloat     [in,out] anisotropicDegree   1.0
    range: [1,Inf)
    change: chTexturePropertiesNode
  SFColorRGBA [in,out] borderColor         0 0 0 0
    range: [0,1]
    change: chTexturePropertiesNode
  SFInt32     [in,out] borderWidth         0
    range: [0,1]
    change: chTexturePropertiesNode
  SFString    [in,out] boundaryModeS       "REPEAT"
    range: ["CLAMP", "CLAMP_TO_EDGE", "CLAMP_TO_BOUNDARY", "MIRRORED_REPEAT", "REPEAT"]
    enumerated-type: TBoundaryMode BoundaryModeNames bmRepeat
    change: chTexturePropertiesNode
  SFString    [in,out] boundaryModeT       "REPEAT"
    range: ["CLAMP", "CLAMP_TO_EDGE", "CLAMP_TO_BOUNDARY", "MIRRORED_REPEAT", "REPEAT"]
    enumerated-type: TBoundaryMode BoundaryModeNames bmRepeat
    change: chTexturePropertiesNode
  SFString    [in,out] boundaryModeR       "REPEAT"
    range: ["CLAMP", "CLAMP_TO_EDGE", "CLAMP_TO_BOUNDARY", "MIRRORED_REPEAT", "REPEAT"]
    enumerated-type: TBoundaryMode BoundaryModeNames bmRepeat
    change: chTexturePropertiesNode
  SFString    [in,out] magnificationFilter "DEFAULT"
    range: [see Table 18.8]
    change: chTexturePropertiesNode
  SFString    [in,out] minificationFilter  "DEFAULT"
    range: [see Table 18.9]
    change: chTexturePropertiesNode
  SFString    [in,out] textureCompression  "FASTEST"
    range: [see Table 18.10]
    change: chTexturePropertiesNode
  SFFloat     [in,out] texturePriority     0
    range: [0,1]
    change: chTexturePropertiesNode
  SFBool      []       generateMipMaps     FALSE
    change: chTexturePropertiesNode

  # CASTLE GAME ENGINE EXTENSIONS:
  SFBool     []            guiTexture  FALSE
    change: chTexturePropertiesNode
}

TextureTransform : X3DSingleTextureTransformNode {
  SFVec2f [in,out] center      0 0
    change: chTextureTransform
  SFFloat [in,out] rotation    0
    change: chTextureTransform
    angle
  SFVec2f [in,out] scale       1 1
    change: chTextureTransform
  SFVec2f [in,out] translation 0 0
    change: chTextureTransform
}
