/*
 * Scene.h
 *
 * Copyright (C) 1999 Stephen F. White
 * 
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program (see the file "COPYING" for details); if 
 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
 * Cambridge, MA 02139, USA.
 */

#ifndef _SCENE_H
#define _SCENE_H

#ifndef _STDIO_H
#include <stdio.h>
#endif

#ifndef _ARRAY_H
#include "Array.h"
#endif

#ifndef _MAP_H
#include "Map.h"
#endif

#ifndef _STACK_H
#include "Stack.h"
#endif

#ifndef _COMMAND_LIST_H
#include "CommandList.h"
#endif

#ifndef _NODE_LIST_H
#include "NodeList.h"
#endif

#ifndef _DUNE_STRING_H
#include "MyString.h"
#endif

#ifndef _URL_H
#include "URL.h"
#endif

#ifndef _PROTO_H
#include "Proto.h"
#endif

#ifndef _DUNE_APP_H
#include "DuneApp.h"
#endif

#include "x3dFlags.h"

#include "TransformMode.h"

#include "ProtoMap.h"

#define MAX_PATH_LEN 1024

class FieldValue;
class Node;
class Path;
class FontInfo;
class NodeViewpoint;
class NodeNavigationInfo;
class NodeFog;
class SFVec3f;
class MFVec3f;
class SceneView;
class Hint;
class NodeInline;
class Element;

typedef Stack<Command *> CommandStack;

typedef Map<MyString, Node *> NodeMap;
typedef Map<MyString, int> StringMap;

class Interpolator;

enum {
     HIGHEST_SELECTION_LEVEL = 0,
     DEEPEST_SELECTION_LEVEL = -1
};

class Scene {
public:
                        Scene();
                       ~Scene();
    void                def(const char *nodeName, Node *value);
    void                def(Node *value) { _defNode = value; }
    Node               *use(const char *nodeName);
    bool                use(Node *parentNode, int parentField);
    bool                canUse(Node *parentNode, int parentField);
    void                undef(MyString nodeName);
    bool                hasAlreadyName(const char *name) { return use(name); }

    int                 addSymbol(MyString s);
    const MyString     &getSymbol(int id) const;

    void                setRoot(Node *root) { _root = root; }
    Node               *getRoot() const { return _root; }
    int                 getRootField() const { return _rootField; }

    void                setNodes(NodeList *nodes);
    const NodeList     *getNodes() const { return &_nodes; }
    void                addNodes(Node *target, int targetField, 
                                 NodeList *nodes);

    void                addMeta(const char *metaKey, const char* metaValue);

    void                scanForInlines(NodeList *nodes);
    void                readInline(NodeInline *node);

    void                scanForExternProtos(void);
    bool                readExternProto(Proto *proto);

    NodeList           *searchNodeType(int nodeType);
    void                addToNodeList(Node *node);


    const char         *parse(FILE *f, bool protoLibrary, 
                              Node *target = NULL, int targetField = -1);

    Node               *createNode(const char *nodeType);
    Node               *createNode(int nodeType);

    int                 write(int filedes, const char *url, int writeFlags = 0);
    int                 writeExtensionProtos(void);

    bool                getWriteKanimNow(void) { return _writeKanimNow; }
    int                 writeKanim(int filedes, const char* url);

    int                 writeC(int filedes, int languageFlag);
    int                 writeCDeclaration(int filedes, int languageFlag);
    int                 writeCTreeCallback(int filedes, 
                                           const char *functionName,
                                           bool callTreeCallback = true);
    int                 writeCDataFunctionsCalls(int filedes, int languageFlag);

    void                zeroNumDataFunctions(void) { _numDataFunctions = 0; }
    int                 getNumDataFunctions(void)
                           { return _numDataFunctions; }
    int                 increaseNumDataFunctions(void) 
                           { return _numDataFunctions++; }

    void                zeroNumReducedDataFunctions(void) 
                           { _numReducedDataFunctions = 0; }
    int                 getNumReducedDataFunctions(void)
                           { return _numReducedDataFunctions; }
    void                increaseNumReducedDataFunctions(void)
                           { _numReducedDataFunctions++; }

    int                 writeAc3d(int filedes, bool raven = false);
    void                collectAc3dMaterialInfo(char *name, Node *node);
    bool                hasEmptyMaterial(void);
    int                 getAc3dEmptyMaterial(void)
                           { return _ac3dEmptyMaterial; }

    int                 writeCattGeo(char *path);
    char               *getCattGeoPath(void) { return _cattGeoPath; }
    int                 getCattGeoFileCounter(void) 
                           { return _cattGeoFileCounter; }
    int                 getAndIncCattGeoFileCounter(void) 
                           { return _cattGeoFileCounter++; }
    int                 getCattGeoCornerCounter(void) 
                           { return _cattGeoCornerCounter; }
    int                 getAndIncCattGeoCornerCounter(void) 
                           { return _cattGeoCornerCounter++; }
    int                 getAndIncCattGeoPlaneCounter(void) 
                           { return _cattGeoPlaneCounter++; }

    bool                getCattRecIsWritten(void)
                           { return _cattRecIsWritten; }
    void                setCattRecIsWritten(void)
                           { _cattRecIsWritten = true; }

    bool                getCattSrcIsWritten(void)
                           { return _cattSrcIsWritten; }
    void                setCattSrcIsWritten(void)
                           { _cattSrcIsWritten = true; }

    bool                validateLdrawExport();
    int                 writeLdrawDat(int filedes, const char *path);
    int                 getCurrentLdrawColor(void) 
                           { return _currentLdrawColor; }
    void                setCurrentLdrawColor(int c) 
                           { _currentLdrawColor = c; }


    void                deleteExtensionProtos(void);
    Proto              *getExtensionProto(Proto *proto);

    void                addProto(MyString name, Proto *value);
    Proto              *getProto(MyString name);
    void                deleteProto(MyString name);
    Proto              *getExtensionProto(MyString name);

    static bool         validRoute(Node *src, int eventOut, Node *dst, 
                                   int eventIn);
    bool                addRoute(Node *src, int eventOut, Node *dest, 
                                 int eventIn);
    void                deleteRoute(Node *src, int eventOut, Node *dest, 
                                    int eventIn);

    void                execute(Command *cmd);

    void                add(Command *change);

    void                undo();
    void                redo();

    int                 canUndo() { return !_undoStack.empty(); }
    int                 canRedo() { return !_redoStack.empty(); }

    int                 getUndoStackTop() { return _undoStack.getTop(); }

    void                startMultipleUndo();
    void                optimizeMultipleUndo();

    void                errorf(const char *fmt, ...);

    void                invalidNode(const char *nodeName);
    void                invalidField(const char *node, const char *field);

    void                reInitAll(void);

    void                backupField(Node *node, int field);
    void                backupFieldsStart(void);
    void                backupFieldsAppend(Node *node, int field);
    void                backupFieldsDone(void);
    void                setField(Node *node, int field, FieldValue *value);
    Interpolator       *findUpstreamInterpolator(Node *node, int field) const;

    void                drawScene(bool pick = false, int x = 0, int y = 0);

    Path               *pick(int x, int y);
    Path               *searchTransform(void);
    void                drawHandles(bool drawRigidBodyHandles = false);
    void                finishDrawHandles(void);
    void                drawRigidBodyHandles(void) { drawHandles(true); }
    void                drawHandlesRec(Node *node, bool drawOnlyJoints = false) 
                           const;

    void                setSelectedHandle(int handle)
                           { 
                           _isNewSelectedHandle = !isInSelectedHandles(handle);
                           _lastSelectedHandle = handle;
                           addSelectedHandle(handle);
                           }
    void                addSelectedHandle(int handle)
                           { 
                           for (int i = 0; i < _selectedHandles.size(); i++)
                               if (handle == _selectedHandles[i])
                                   return;
                           _selectedHandles.append(handle); 
                           }
    void                removeSelectedHandle(int handle)
                           {
                           for (int i = 0; i < _selectedHandles.size(); i++)
                               if (handle == _selectedHandles[i]) {
                                   _selectedHandles.remove(handle);
                                   return;
                               }
                           }
    void                removeSelectedHandles()
                           {
                           _selectedHandles.resize(0); 
                           _lastSelectedHandle = -1;
                           }
    int                 getSelectedHandlesSize() const
                           { return _selectedHandles.size(); }
    int                 getSelectedHandle(int i) const
                           { return _selectedHandles[i]; }
    bool                isInSelectedHandles(int handle) 
                           { 
                           for (int i = 0; i < _selectedHandles.size(); i++)
                               if (handle == _selectedHandles[i])
                                   return true;
                           return false;
                           }
    bool                isNewSelectedHandle(void) 
                          { return _isNewSelectedHandle; }
    int                 getLastSelectedHandle(void) 
                           { return _lastSelectedHandle; }
    bool                checkSameOrXSymetricHandle(int handle, MFVec3f *points);


    void                setTransformMode(TMode tm)
                           { _transformMode->tmode = tm; }
    void                setTransformMode(TDimension td)
                           { _transformMode->tdimension = td; }
    void                setTransformMode(T2axes t2)
                           { _transformMode->t2axes = t2; }
    TransformMode      *getTransformMode()
                           { return _transformMode; }

    void                transform(const Path *path);
    void                projectPoint(float x, float y, float z,
                                     float *wx, float *wy, float *wz);
    void                unProjectPoint(float wx, float wy, float wz,
                                       float *x, float *y, float *z);
    int                 allocateLight();
    int                 freeLight();
    int                 getNumLights() { return _numLights; }

    void                enableHeadlight();
    Path               *processHits(GLint hits, GLuint *pickBuffer);

    void                addViewpoint(Node *viewpoint);
    void                addFog(Node *fog);
    void                addBackground(Node *background);
    void                addNavigationInfo(Node *navigationInfo);

    void                setFirstNavigationInfo(void);

    void                addTimeSensor(Node *timeSensor);

    void                setHeadlight(int headlight);

    void                changeTurnPointDistance(float factor);

    void                moveCamera(float dx, float dy, float dz);
    void                walkCamera(Vec3f walk, bool forward);
    void                turnCamera(float x, float y, float z, float ang);
    void                orbitCamera(float dtheta, float dphi);
    void                rollCamera(float dtheta);
    void                standUpCamera(void);

    void                startWalking();

    NodeViewpoint      *getCamera() const;
    void                setCamera(NodeViewpoint *camera);
    void                applyCamera(void);

    NodeNavigationInfo *getNavigationInfo() const;
    void                applyNavigationInfo(void);

    void                findBindableNodes(void);

    void                addNode(Node *node);
    Node               *replaceNode(Node *oldNode, Node* newNode);
    void                removeNode(Node *node);

    MyString            getUniqueNodeName(const char *name);
    MyString            getUniqueNodeName(Node *node);
    MyString            generateUniqueNodeName(Node *node);

    MyString            generateVariableName(Node *node);

    const Path         *getSelection(void) const { return _selection; }
    void                setSelection(const Path *selection);
    void                setSelection(Node *node);

    int                 getSelectionLevel(void) { return _selectionLevel; }
    void                setSelectionLevel(int level) 
                           { _selectionLevel = level; }

    Path               *newPath(Node *node);

    void                setURL(const char *url) { _URL = url; }
    const char         *getURL(void) const { return _URL; }
    const char         *getNewURL(void) const { return _newURL; }

    void                resetWriteFlags(int flags);
    bool                isTempSave(void) const 
                           { return _writeFlags & TEMP_SAVE; }
    bool                isPureVRML97(void) const 
                           { return _writeFlags & PURE_VRML97; }
    bool                isPureX3dv(void) const
                           { return _writeFlags & PURE_X3DV; }
    bool                isX3dv(void) const
                           { return ::isX3dv(_writeFlags); }
    bool                isX3dXml(void) const
                           { return ::isX3dXml(_writeFlags); }
    bool                isX3d(void) const
                           { return ::isX3d(_writeFlags); }
    bool                isPureVRML(void) const 
                           { return isPureVRML97() || isPureX3dv(); }
    bool                converts2X3d(void) const 
                           { return _writeFlags & CONVERT2X3D; }
    bool                converts2VRML(void) const 
                           { return _writeFlags & CONVERT2VRML; }
    int                 getWriteFlags(void) { return _writeFlags; }
    void                setX3d(void);
    void                setX3dv(void);
    void                setX3dXml(void);
    void                setVrml(void);
    bool                isInvalidElement(Element *element);

    void                setPath(const char *path) { _path = path; }
    const char         *getPath() const { return _path; }

    void                setPathAllURL(const char *path);

    bool                isModified() const;
    bool                isRunning() const { return _running; }
    bool                isRecording() const { return _recording; }
    void                setRecording(bool recording) { _recording = recording; }

    void                start();
    void                stop();
    void                updateTime();
    void                updateTimeAt(double t);
    double              timeSinceStart(void);

    void                OnFieldChange(Node *node, int field, int index = -1);
    void                OnAddNode(Node *node, Node *dest, int field);
    void                OnRemoveNode(Node *node, Node *src, int field);

    void                OnAddNodeSceneGraph(Node *node, Node *dest, int field);

    void                AddView(SceneView *view);
    void                RemoveView(SceneView *view);
    void                UpdateViews(SceneView *sender, int type,
                                    Hint *hint = NULL);
    void                setUpdateViewsSelection(bool flag) 
                           { _canUpdateViewsSelection = flag; }

    void                DeleteSelected();
    void                DeleteSelectedAppend(CommandList* list);
    void                selectNext();
    int                 OnDragOver(Node *src, Node *srcParent, int srcField, 
                                   Node *dest, int destField, int modifiers);
    int                 OnDrop(Node *src, Node *srcParent, int srcField, 
                               Node *dest, int destField, int effect);

    bool                Download(const URL &url, MyString *path);
    FontInfo           *LoadGLFont(const char *fontName, const char *style);
    int                 getNumProtoNames(void) { return _numProtoNames; }
    bool                addProtoName(MyString name);
    void                deleteProtoName(MyString name);
    MyString            getProtoName(int i) { return _protoNames[i]; }
    void                addProtoDefinition(void);
    void                addToProtoDefinition(char* string);
    void                setNestedProto(void);                      

    int                 writeExternProto(int f, const char* protoName);

    MyString            createRouteString(const char *fromNodeName,
                                          const char *fromFieldName,
                                          const char *toNodeName,
                                          const char *toFieldName);
    void                addRouteString(MyString string);
    void                addEndRouteString(MyString string);
    int                 writeRouteStrings(int filedes, int indent, 
                                          bool end = false);
    void                changeRoutes(Node *toNode, int toField, 
                                     Node *fromNode, int fromField, 
                                     bool fromX3d);

    int                 writeComponents(int filedes);

    void                setHasFocus(void)    {_hasFocus=true;}
    void                deleteHasFocus(void) {_hasFocus=false;}
    bool                getHasFocus(void)    
                           {
                           if (TheApp->dontCareFocus())
                               return true;
                           else
                               return _hasFocus;
                           }  
    void                setMouseNavigationMode(bool flag) 
                           {_navigationMouseMode=flag;}
    bool                getMouseNavigationMode() 
                           {return _navigationMouseMode;}
    void                setInputDeviceNavigationMode(bool flag) 
                           {_navigationInputDeviceMode=flag;}
    bool                getInputDeviceNavigationMode() 
                           {return _navigationInputDeviceMode;}

    void                setViewOfLastSelection(SceneView* view);
    SceneView          *getViewOfLastSelection(void);
    void                deleteLastSelection(void);
    void                DeleteLastSelection(void);

    void                makeSimilarName(Node *node, const char *name);

    void                updateURLs(Node* node);

    void                saveProtoStatus(void);
    void                restoreProtoStatus(void);

    void                setErrorLineNumber(int lineno) 
                           { _errorLineNumber = lineno ;}
    int                 getErrorLineNumber(void) { return _errorLineNumber; }

    /* 
     * a extra modifiedflag is needed to signal possible changes 
     * (e.g. from the file -> Textedit menupoint)
     */
    void                setExtraModifiedFlag(void) { _extraModifiedFlag=true; }
    StringArray        *getAllNodeNames(void);
    void                draw3dCursor(int x, int y);
    void                use3dCursor(bool flag) { _use3dCursor = flag; }
    bool                use3dCursor(void);
    bool                setPrefix(char* prefix);
    MyString            getNodeWithPrefix(const MyString &nodeType);
    bool                hasExternProtoWarning(void) 
                           { return _externProtoWarning; }
    void                setExternProtoWarning(bool flag) 
                           { _externProtoWarning = flag; }
    bool                belongsToNodeWithExternProto(const char *protoName);
    int                 writeIndexedFaceSet(int f, Node* node);
    int                 writeIndexedTriangleSet(int f, Node* node);
    int                 writeTriangleSet(int f, Node* node);
    int                 writeTriangles(int f, Node* node);
    int                 writeIndexedLineSet(int f, Node* node);
    bool                getXSymetricMode() 
                           { return TheApp->GetXSymetricMode(); }
    bool                isParsing(void) { return _isParsing; }
    int                 getNumberBuildinProtos(void) 
                           { return _numberBuildinProtos; }
    void                addDelayedWriteNode(Node *node) 
                           { _delayedWriteNodes.append(node); }
    void                recalibrate(void);
    bool                hasJoints(void) { return _hasJoints; }
    void                setHasJoints(void) { _hasJoints = true; }
    bool                showJoints(void) { return _showJoints; }
    void                setShowJoints(bool flag) 
                           { if (_hasJoints)_showJoints = flag; }
    int                 getNumInteractiveProtos(int type)
                           { return getInteractiveProtos(type)->size(); }
    Proto              *getInteractiveProto(int type, int i)
                           { return (*getInteractiveProtos(type))[i]; }
    void                setXrayRendering(bool flag)
                           { _xrayRendering = flag; }
    int                 getDestField(Node* src, Node *dest, int destField);

    void                setXonly(bool flag) { _xOnly = flag; } 
    void                setYonly(bool flag) { _yOnly = flag; } 
    void                setZonly(bool flag) { _zOnly = flag; } 
    bool                getXonly(void) { return _xOnly; }
    bool                getYonly(void) { return _yOnly; }
    bool                getZonly(void) { return _zOnly; }
    int                 getConstrain(void);
    Vec3f               constrainVec(Vec3f vec);

    void                setTurnPoint(void);

    NodeList            getTimeSensors(void) { return _timeSensors; }

    void                setImportIntoVrmlScene(bool f) { _importIntoVrmlScene = f; }
    bool                getImportIntoVrmlScene(void) { return _importIntoVrmlScene; }

    void                convertProtos2X3d(void);
    void                convertProtos2Vrml(void);

    void                setRigidBodyHandleNode(Node *node) 
                           { _rigidBodyHandleNode = node; }

    Node               *convertToIndexedFaceSet(Node* node);
    Node               *convertToTriangleSet(Node* node);
    Node               *convertToIndexedTriangleSet(Node* node);
    Node               *convertToIndexedLineSet(Node* node);

    void                branchConvertToTriangleSet(Node *node);
    void                branchConvertToIndexedTriangleSet(Node *node);
    void                branchConvertToIndexedFaceSet(Node *node);
    void                branchConvertToTriangles(Node *node, bool targetHasCcw);
    void                branchCreateNormals(Node *node);
    void                createNormal(Node *node);
    void                branchCreateTextureCoordinates(Node *node);
    void                createTextureCoordinate(Node *node);

protected:
    int                 writeExtensionProtos(int f, int flag);
    ProtoArray         *getInteractiveProtos(int type); 
    void                buildInteractiveProtos(void);

protected:
    NodeMap             _nodeMap;
    Node               *_root;
    int                 _rootField;
    StringMap           _symbols;
    Array<MyString>     _symbolList;
    Array<MyString>     _protoNames;
    int                 _numProtoNames;
    int                 _statusNumProtoNames;
    Array<MyString>     _protoDefinitions;
    Array<bool>         _isNestedProto;
    int                 _numProtoDefinitions;
    int                 _statusNumProtoDefinitions;
    ProtoMap            _protos;

    CommandStack        _undoStack;
    CommandStack        _redoStack;

    int                 _multipleUndoTop;
    CommandList        *_backupCommandList;
    int                 _numLights;
    NodeList            _viewpoints;
    NodeList            _navigationinfos;
    NodeList            _backgrounds;
    NodeList            _fogs;
    Stack<Node *>       _fogStack;

    NodeList            _timeSensors;

    int                 _headlight;
    bool                _headlightIsSet;

    NodeList            _nodes;

    const Path         *_selection;
    Array<int>          _selectedHandles;
    int                 _lastSelectedHandle;
    bool                _isNewSelectedHandle;

    TransformMode      *_transformMode;

    int                 _selectionLevel;

    MyString            _URL;
    const char         *_newURL;
    int                 _writeFlags;

    int                 _numSymbols;

    bool                _running;
    double              _timeStart;
    bool                _recording;

    Command            *_unmodified;
    bool                _extraModifiedFlag;

    bool                _setViewpoint;
    NodeViewpoint      *_defaultViewpoint;
    NodeViewpoint      *_currentViewpoint;

    bool                _setNavigationInfo;
    NodeNavigationInfo *_defaultNavigationInfo;
    NodeNavigationInfo *_currentNavigationInfo;

    NodeFog            *_currentFog;

    List<SceneView *>   _views;
    bool                _canUpdateViewsSelection;

    MyString            _compileErrors;
    Array<FontInfo *>   _fonts;

    MyString            _path;

    List<MyString>      _routeList;
    List<MyString>      _endRouteList;

    /* when picking several objects which one click, which one is selected ? */
    int                 _selectlevel;

    /* current scene is in mouse focus ? */
    bool                _hasFocus;

    bool                _xOnly;
    bool                _yOnly;
    bool                _zOnly;

    bool                _navigationMouseMode;
    bool                _navigationInputDeviceMode;

    SceneView          *_viewOfLastSelection;
    bool                _selection_is_in_scene;

    GLUquadricObj      *_obj3dCursor;
    bool                _use3dCursor;
    int                 _errorLineNumber;

    Array<const char *> _nodesWithExternProto;
    Array<const char *> _nodesForceExternProtoWrite;
    bool                _externProtoWarning;
    int                 _numberBuildinProtos;

    bool                _isParsing;

    // temporary nodes to write (e.g. Interpolators for PureVRML Export)
    Array<Node *>       _delayedWriteNodes;

    bool                _hasJoints;
    bool                _showJoints;

    ProtoArray          _interactiveSFBoolProtos;
    ProtoArray          _interactiveSFRotationProtos;
    ProtoArray          _interactiveSFTimeProtos;
    ProtoArray          _interactiveSFVec3fProtos; 
    ProtoArray          _emptyProtoArray; 

    bool                _xrayRendering;

    Vec3f               _turnPointPos;
    Quaternion          _turnPointRot;

    double              _oldWalkTime;

    Node               *_defNode;
    Array<Proto *>      _writtenExtensionProtos;
    bool                _importIntoVrmlScene;

    int                 _numDataFunctions;
    int                 _numReducedDataFunctions;

    bool                _writeKanimNow;

    StringMap           _ac3dMaterialIndexMap;
    NodeArray           _ac3dMaterialNodeArray;
    StringArray         _ac3dMaterialNameArray;
    int                 _ac3dEmptyMaterial;

    int                 _cattGeoFileCounter;
    int                 _cattGeoCornerCounter;
    int                 _cattGeoPlaneCounter;
    char               *_cattGeoPath;

    bool                _cattRecIsWritten;
    bool                _cattSrcIsWritten;

    int                 _currentLdrawColor;

    int                 _variableCounter;

    NodeList            _nodeList;

    Node               *_rigidBodyHandleNode;

    Array<const char*>  _metaKeys;
    Array<const char*>  _metaValues;
};

enum {
    UPDATE_ALL = 0,
    UPDATE_SELECTION,
    UPDATE_FIELD,
    UPDATE_ADD_NODE,
    UPDATE_REMOVE_NODE,
    UPDATE_CHANGE_INTERFACE_NODE,
    UPDATE_ADD_ROUTE,
    UPDATE_DELETE_ROUTE,
    UPDATE_MODE,
    UPDATE_TIME,
    UPDATE_START_FIELD_EDIT,
    UPDATE_STOP_FIELD_EDIT,
    UPDATE_ENABLE_COLOR_CIRCLE,
    UPDATE_DISABLE_COLOR_CIRCLE,
    UPDATE_CLOSE_COLOR_CIRCLE,
    UPDATE_SELECTED_FIELD,
    UPDATE_SELECTION_NAME,
    UPDATE_NODE_NAME,
    UPDATE_ADD_NODE_SCENE_GRAPH_VIEW,
    UPDATE_REDRAW,
    UPDATE_PREVIEW,
    UPDATE_SOLID_CHANGED
};

enum {
    RENDER_PASS_GEOMETRY,
    RENDER_PASS_NON_TRANSPARENT,
    RENDER_PASS_TRANSPARENT
};

class Hint {
};

class FieldUpdate : public Hint {
public:
                    FieldUpdate(Node *n, int f, int i = -1)
                    { node = n; field = f; index = i; }

    Node           *node;
    int             field;
    int             index;
};

class NodeUpdate : public Hint {
public:
                    NodeUpdate(Node *n, Node *p, int f)
                    { node = n; parent = p, field = f; }

    Node           *node;
    Node           *parent;
    int             field;
};

class RouteUpdate : public Hint {
public:
                    RouteUpdate(Node *s, int out, Node *d, int in)
                    { src = s; eventOut = out; dest = d; eventIn = in; }

    Node           *src;
    Node           *dest;
    int             eventOut;
    int             eventIn;
};

void BackupRoutesRec(Node *node, CommandList *list);

#endif // _SCENE_H

