/* scene.h
  Copyright (C) 2005,2006,2007 Eugene K. Ressler, Jr.

This file is part of Sketch, a small, simple system for making
3d drawings with LaTeX and the PSTricks or TikZ package.

Sketch is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

Sketch is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Sketch; see the file COPYING.txt.  If not, see
http://www.gnu.org/copyleft */

#ifndef __SCENE_H
#define __SCENE_H

#include "opts.h"
#include "error.h"
#include "geometry.h"
#include "expr.h"
#include "bsp.h"
#include "dynarray.h"
#include "global.h"

typedef struct point_list_3d_t
{
 DYNAMIC_2D_ARRAY_FIELDS (POINT_3D, v, n_pts);
}
POINT_LIST_3D;

DECLARE_DYNAMIC_2D_ARRAY_PROTOS (POINT_LIST_3D, POINT_3D, FLOAT,
                                point_list_3d, v, n_pts)
    typedef struct transform_list_t
    {
      DYNAMIC_2D_ARRAY_FIELDS (TRANSFORM, xf, n_xfs);
    }
TRANSFORM_LIST;

DECLARE_DYNAMIC_2D_ARRAY_PROTOS (TRANSFORM_LIST, TRANSFORM, FLOAT,
                                transform_list, xf, n_xfs)
// object_type_str[] definition in scene.c must match!
    typedef enum object_type_t
    {
      O_BASE,
      O_TAG_DEF,
      O_OPTS_DEF,
      O_SCALAR_DEF,
      O_POINT_DEF,
      O_VECTOR_DEF,
      O_TRANSFORM_DEF,
      O_DOTS,
      O_LINE,
      O_CURVE,
      O_POLYGON,
      O_SPECIAL,
      O_SWEEP,
      O_REPEAT,
      O_COMPOUND,
    }
OBJECT_TYPE;

#define is_drawable(P)  ((P)->tag >= O_DOTS)

    extern char *object_type_str[];

#define BASE_OBJECT_FIELDS  \
 struct object_t *sibling; \
 OBJECT_TYPE tag

    typedef struct object_t
    {
      BASE_OBJECT_FIELDS;
    }
OBJECT;

    typedef OBJECT TAG_DEF;
    OBJECT *new_tag_def (void);

    typedef struct opts_def_t
    {
      BASE_OBJECT_FIELDS;
      OPTS *opts;
    }
OPTS_DEF;

    OBJECT *new_opts_def (char *opts_str, SRC_LINE line);

    typedef struct scalar_def_t
    {
      BASE_OBJECT_FIELDS;
      FLOAT val;
    }
SCALAR_DEF;

    OBJECT *new_scalar_def (FLOAT val);

    typedef struct point_def_t
    {
      BASE_OBJECT_FIELDS;
      POINT_3D p;
    }
POINT_DEF;

    OBJECT *new_point_def (POINT_3D p);

    typedef struct vector_def_t
    {
      BASE_OBJECT_FIELDS;
      VECTOR_3D v;
    }
VECTOR_DEF;

    OBJECT *new_vector_def (VECTOR_3D v);

    typedef struct transform_def_t
    {
      BASE_OBJECT_FIELDS;
      TRANSFORM xf;
    }
TRANSFORM_DEF;

    OBJECT *new_transform_def (TRANSFORM xf);

    typedef struct dots_t
    {
      BASE_OBJECT_FIELDS;
      OPTS *opts;
      POINT_LIST_3D pts[1];
    }
DOTS_OBJECT;

    OBJECT *new_dots (OPTS * opts, OBJECT * pts);

    typedef struct line_object_t
    {
      BASE_OBJECT_FIELDS;
      OPTS *opts;
      POINT_LIST_3D pts[1];
    }
LINE_OBJECT;

    OBJECT *new_line (OPTS * opts, OBJECT * pts);

    typedef struct curve_t
    {
      BASE_OBJECT_FIELDS;
      OPTS *opts;
      POINT_LIST_3D pts[1];
    }
CURVE_OBJECT;

    OBJECT *new_curve (OPTS * opts, OBJECT * pts);

    typedef struct polygon_t
    {
      BASE_OBJECT_FIELDS;
      OPTS *opts;
      int border_p;
      POINT_LIST_3D pts[1];
    }
POLYGON_OBJECT;

    OBJECT *new_polygon (OPTS * opts, OBJECT * pts);

    typedef struct special_t
    {
      BASE_OBJECT_FIELDS;
      char *code;
      OPTS *opts;
      POINT_LIST_3D pts[1];
    }
SPECIAL_OBJECT;

    OBJECT *new_special (char *code, OPTS * opts, OBJECT * pts,
                         SRC_LINE line);

    typedef struct sweep_t
    {
      BASE_OBJECT_FIELDS;
      OPTS *opts;
      int n_slices;
      int closed_p;
      TRANSFORM_LIST xforms[1];
      OBJECT *swept;
    }
SWEEP_OBJECT;

    OBJECT *new_sweep (OPTS * opts, int n_slices, int closed_p, OBJECT * xfs,
                       OBJECT * swept);

    typedef struct repeat_t
    {
      BASE_OBJECT_FIELDS;
      int n;
      TRANSFORM_LIST xforms[1];
      OBJECT *repeated;
    }
REPEAT_OBJECT;

    OBJECT *new_repeat (int n, OBJECT * xfs, OBJECT * repeated);

    typedef struct compound_t
    {
      BASE_OBJECT_FIELDS;
      TRANSFORM xform;
      OBJECT *child;
    }
COMPOUND_OBJECT;

    OBJECT *new_compound (TRANSFORM xform, OBJECT * child);

    OBJECT *copy_drawable (OBJECT * obj);
    OBJECT *cat_objects (OBJECT * lft, OBJECT * rgt);
    OBJECT *sibling_reverse (OBJECT * obj);
    OBJECT *object_from_expr (EXPR_VAL * val);

    OBJECT *flat_scene (OBJECT * obj, GLOBAL_ENV * env);
    OBJECT *hsr_scene_with_bsp (OBJECT * scene);
    OBJECT *hsr_scene_with_depth_sort (OBJECT * scene);
    void get_extent (OBJECT * obj, BOX_3D * e, int *n_obj);
    int xy_overlap_p (OBJECT * obj, BOX_3D * e);

#endif