/*
 * Copyright 2009, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

namespace o3d {

typedef DrawElement[] DrawElementArray;

%[
  An Element manages DrawElements for classes inherited from Element.

  @o3dparameter material ParamMaterial The Material used by this Element.
  @o3dparameter boundingBox ParamBoundingBox The BoundingBox used by this
      Element for culling.
  @o3dparameter zSortPoint ParamFloat3 The point to sort by when rendering this
      Element in a z ordered DrawPass.
  @o3dparameter cull ParamBoolean Whether or not to attempt to cull this
     element based on whether or not its bounding box is in the view frustum.
%]
[nocpp, include="core/cross/element.h"] class Element : ParamObject {

  %[
    The Material for this element.
  %]
  [getter, setter] Material? material_;

  %[
    The BoundingBox for this element. If culling is on this bounding box will be
    tested against the view frustum of any draw context used to render this
    Element.
    Default = [[0, 0, 0], [0, 0, 0]].
  %]
  [getter, setter] BoundingBox bounding_box_;

  %[
    The z sort point for this element. If this Element is drawn by a DrawPass
    that is set to sort by z order this value will be multiplied by the
    worldViewProjection matrix to compute a z value to sort by.
    Default = [0, 0, 0].
  %]
  [getter, setter] Float3 z_sort_point;

  %[
    The priority for this element. Used to sort if this Element is drawn by a
    DrawPass that is set to sort by priority.
    Default = 0.
  %]
  [getter, setter] float priority_;

  %[
    The cull settings for this element. If true this Element will be culled
    by the bounding box above compared to the view frustum it is being rendered
    with.
    Default = false.
  %]
  [getter, setter] bool cull_;

  %[
    The current owner of this Draw Element. Pass in null to stop being owned.

    Note: Elements are referenced by the Pack they are created in and their
    owner. If the Element is removed from its Pack then setting the owner
    to null will free the Element. Or, visa versa, if you set the
    Element's owner to null then removing it from its Pack will free the
    Element.
  %]
  [getter, setter, userglue_setter] Shape? owner_;

  %[
    Gets all the DrawElements under this Element.

    Each access to this field gets the entire list so it is best to get it
    just once. For example:
    \code
    var drawElements = element.drawElements;
    for (var i = 0; i < drawElements.length; i++) {
      var drawElement = drawElements[i];
    }
    \endcode

    Note that modifications to this array [e.g. push()] will not affect
    the underlying Element, while modifications to the members of the array.
    <strong>will</strong> affect them.
  %]
  [userglue_getter, getter] DrawElementArray draw_elements_;

  %[
    Creates a DrawElement for this Element. Note that unlike
    Shape.createDrawElements and Transform.createDrawElements this one will
    create more than one element for the same material.

    \param pack pack used to manage created DrawElement.
    \param material material to use for DrawElement. If you pass null
        it will use the material on this Element. This allows you to easily
        setup the default (just draw as is) by passing null or setup a shadow
        pass by passing in a shadow material.
    \return The created draw element.
  %]
  DrawElement CreateDrawElement(Pack pack,
                                Material? material);

  %[
    Computes the intersection of a ray in the same coordinate system as
    the specified POSITION stream.
    \param position_stream_index Index of POSITION stream.
    \param cull which side of the triangles to ignore.
    \param start position of start of ray in local space.
    \param end position of end of ray. in local space.
    \return RayIntersectionInfo class. If valid() is false then something
        was wrong, Check client::GetLastError(). If intersected() is true then
        the ray intersected a something. position() is the exact point of
        intersection.
  %]
  [const, userglue] RayIntersectionInfo IntersectRay(
      int position_stream_index,
      State::Cull cull,
      Vectormath::Aos::Point3 start,
      Vectormath::Aos::Point3 end);

  %[
    Computes the bounding box in same coordinate system as the specified
    POSITION stream.
    \param position_stream_index Index of POSITION stream.
    \return The boundingbox for this element in local space.
  %]
  [const, userglue] BoundingBox GetBoundingBox(int position_stream_index);

  [verbatim=cpp_glue] %{
    void userglue_setter_owner_(
        o3d::Element* _this,
        o3d::Shape* owner) {
      _this->SetOwner(owner);
    }
    o3d::RayIntersectionInfo userglue_method_IntersectRay(
        o3d::Element* self,
        int semantic_index,
        o3d::State::Cull cull,
        const Vectormath::Aos::Point3& start,
        const Vectormath::Aos::Point3& end) {
      o3d::RayIntersectionInfo result;
      self->IntersectRay(semantic_index, cull, start, end, &result);
      return result;
    }
    o3d::BoundingBox userglue_method_GetBoundingBox(
        o3d::Element* self,
        int semantic_index) {
      o3d::BoundingBox result;
      self->GetBoundingBox(semantic_index, &result);
      return result;
    }
    o3d::DrawElementArray userglue_getter_draw_elements_(
        o3d::Element* self) {
      return self->GetDrawElements();
    }
  %}
};  // Element

}  // namespace o3d
