/*
 * MainWindow.cpp
 *
 * Copyright (C) 1999 Stephen F. White
 * 
 * Modified by Aaron Cram for SAND Dune
 *
 * 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.
 */

#include <errno.h>
#include <stdio.h>
#ifndef _WIN32
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <stdlib.h>
#endif

#include "stdafx.h"
#include "MainWindow.h"
#include "swt.h"
#include "resource.h"
#include "maxpath.h"

#include "Scene.h"
#include "Node.h"
#include "Field.h"
#include "Proto.h"
#include "Path.h"
#include "MFFloat.h"
#include "MFNode.h"
#include "MFVec3f.h"
#include "MFString.h"
#include "SFInt32.h"
#include "SFNode.h"
#include "SceneTreeView.h"
#include "Scene3DView.h"
#include "FieldView.h"
#include "SceneGraphView.h"
#include "ChannelView.h"
#include "ToolbarWindow.h"
#include "StatusBar.h"
#include "DuneApp.h"
#include "MoveCommand.h"
#include "RouteCommand.h"
#include "URL.h"

#include "X3DRigidJointNode.h"

#include "NodeAppearance.h"
#include "NodeAudioClip.h"
#include "NodeContact.h"
#include "NodeElevationGrid.h"
#include "NodeGroup.h"
#include "NodeTransform.h"
#include "NodeCollision.h"
#include "NodeCollidableShape.h"
#include "NodeBillboard.h"
#include "NodeLOD.h"
#include "NodeSwitch.h"
#include "NodeImageTexture.h"
#include "NodeCubeTexture.h"
#include "NodeHAnimHumanoid.h"
#include "NodeHAnimJoint.h"
#include "NodeInline.h"
#include "NodeInlineLoadControl.h"
#include "NodeMaterial.h"
#include "NodeMovieTexture.h"
#include "NodeNurbsGroup.h"
#include "NodeNurbsSet.h"
#include "NodeNurbsSurface.h"
#include "NodeNurbsCurve.h"
#include "NodeNurbsCurve2D.h"
#include "NodeNurbsSweptSurface.h"
#include "NodeNurbsSwungSurface.h"
#include "NodeNurbsTrimmedSurface.h"
#include "NodeShape.h"
#include "NodeScript.h"
#include "NodeSound.h"
#include "NodeSuperEllipsoid.h"
#include "NodeSuperExtrusion.h"
#include "NodeSuperShape.h"
#include "NodeSuperRevolver.h"
#include "NodeNormal.h"
#include "NodeText.h"
#include "NodeTextureCoordinate.h"
#include "NodeTextureCoordinateGenerator.h"
#include "NodeTimeSensor.h"
#include "NodeAnchor.h"
#include "NodeTriangleSet.h"
#include "NodeIndexedTriangleSet.h"
#include "NodeIndexedFaceSet.h"
#include "NodeIndexedLineSet.h"
#include "NodePointSet.h"
#include "NodeViewpoint.h"

#include "NodeGeoCoordinate.h"
#include "NodeGeoElevationGrid.h"
#include "NodeGeoLocation.h"
#include "NodeGeoLOD.h"
#include "NodeGeoMetadata.h"
#include "NodeGeoOrigin.h"
#include "NodeGeoPositionInterpolator.h"
#include "NodeGeoTouchSensor.h"
#include "NodeGeoViewpoint.h"
#include "NodeRigidBody.h"
#include "NodeRigidBodyCollection.h"
#include "NodeCollisionCollection.h"
#include "NodeVrmlCut.h"
#include "NodeVrmlScene.h"
#include "NodeBox.h"
#include "NodeCone.h"
#include "NodeCylinder.h"
#include "NodeSphere.h"
#include "NodeCollisionSensor.h"
#include "NodeParticleSystem.h"
#include "NodeCADFace.h"

#include "NodePackagedShader.h"
#include "NodeShaderProgram.h"
#include "NodeShaderPart.h"

#include "NodeVirtualSoundSource.h"

#include "NodeKambiAppearance.h"
#include "NodeKambiHeadLight.h"
#include "NodeKambiTriangulation.h"
#include "NodeText3D.h"

#include "AboutDialog.h"
#include "AnimationDialog.h"
#include "InteractionDialog.h"
#include "ScriptDialog.h"
#include "ElevationGridDialog.h"
#include "NurbsPlaneDialog.h"
#include "NurbsCurveDialog.h"
#include "PreferencesDialog.h"
#include "EcmaScriptSettingsDialog.h"
#include "InputSettingsDialog.h"
#include "OutputSettingsDialog.h"
#include "PreviewSettingsDialog.h"
#include "UploadSettingsDialog.h"
#include "HelpSettingsDialog.h"
#include "TexteditSettingsDialog.h"
#include "StereoViewSettingsDialog.h"
#include "InputDeviceSettingsDialog.h"
#include "RouteViewSettingsDialog.h"
#include "FieldPipeDialog.h"

#include "DefDialog.h"
#include "CoverDefDialog.h"
#include "Cylinder2NurbsDialog.h"
#include "Cone2NurbsDialog.h"
#include "Sphere2NurbsDialog.h"
#include "Box2NurbsDialog.h"
#include "NurbsCurve2NurbsSurfDialog.h"
#include "URLDialog.h"
#include "ArrayDialog.h"
#include "OneIntDialog.h"
#include "OneFloatDialog.h"
#include "OneTextDialog.h"
#include "TwoRadioButtonsDialog.h"
#include "WonderlandModuleExportDialog.h"
#include "CattExportDialog.h"
//#include "TimeShiftDialog.h"

#include "x3dtranslators.h"
#include "ColorCircle.h"
#include "ScriptEdit.h"


#define ARRAYSIZE(A) (sizeof(A) / sizeof(A[0]))
#define BS -1
#define BUFSIZE 1024

#define MFDouble MFFloat

static int standardButtons[] = {
    0,  ID_DUNE_FILE_NEW,
    41, ID_DUNE_FILE_NEW_X3DV,
    1,  ID_DUNE_FILE_OPEN,
    2,  ID_DUNE_FILE_SAVE,
    3,  ID_DUNE_FILE_PREVIEW,
    BS, 0,
    4,  ID_DUNE_EDIT_CUT,
    5,  ID_DUNE_EDIT_COPY,
    6,  ID_DUNE_EDIT_PASTE,
    7,  ID_DUNE_EDIT_DELETE,
    BS, 0,
    8,  ID_DUNE_VIEW_FULL_SCREEN,
    BS, 0,
    29, ID_ANIMATION,
    37, ID_INTERACTION,
    BS, 0,
    38, ID_X_ONLY,
    39, ID_Y_ONLY,
    40, ID_Z_ONLY,
    BS, 0,
    28, ID_X_SYMETRIC,
    22, ID_COLOR_CIRCLE,
    23, ID_OBJECT_EDIT,
    25, ID_URL_EDIT,
    BS, 0,
    33, ID_STAND_UP,
    BS, 0,
    34, ID_WALK_MOUSE_MODE,
    35, ID_EXAMINE_MOUSE_MODE,
    24, ID_FLY_MOUSE_MODE,
    32, ID_ROLL_MOUSE_MODE,
    30, ID_MOUSE_NAVIGATION_MODE,
    BS, 0,
    31, ID_INPUT_DEVICE_NAVIGATION_MODE,
//    36, ID_SHOW_JOINT_LIKE_HANDLES,
    9,  ID_MOVE_MODE,
    10, ID_ROTATE_MODE,
    11, ID_SCALE_MODE,
    42, ID_UNIFORM_SCALE_MODE,
    12, ID_CENTER_MODE,
    13, ID_6D_MODE,
    14, ID_6DLOCAL_MODE,
    15, ID_ROCKET_MODE,
    16, ID_HOVER_MODE,
    BS, 0,
    17, ID_3D_MODE,
    18, ID_2D_MODE,
    19, ID_1D_MODE,
    BS, 0,
    20, ID_NEAR_FAR_MODE,
    21, ID_UP_DOWN_MODE,
    BS, 0,
    26, ID_INPUTDEVICE_GREATER,
    27, ID_INPUTDEVICE_LESSER
};

static int vcrButtons[] = {
    0,  ID_REWIND,
    1,  ID_STOP,
    2,  ID_RECORD,
    3,  ID_PLAY,
    4,  ID_FAST_FORWARD
};

static NodeButton buttons1[] = {
    { VRML_BOX,                      ID_NEW_BOX,              true, true },
    { VRML_SPHERE,                   ID_NEW_SPHERE,           true, true },
    { VRML_CONE,                     ID_NEW_CONE,             true, true },
    { VRML_CYLINDER,                 ID_NEW_CYLINDER,         true, true },
    { VRML_INDEXED_FACE_SET,         ID_NEW_INDEXED_FACE_SET, true, true },
    { VRML_INDEXED_LINE_SET,         ID_NEW_INDEXED_LINE_SET, true, true },
    { VRML_POINT_SET,                ID_NEW_POINT_SET,        true, true },
    { VRML_ELEVATION_GRID,           ID_NEW_ELEVATION_GRID,   true, true },
    { VRML_EXTRUSION,                ID_NEW_EXTRUSION,        true, true },
    { VRML_TEXT,                     ID_NEW_TEXT,             true, true },
    { BS,                            0,                       true, true },
    { VRML_GROUP,                    ID_NEW_GROUP,            true, true },
    { VRML_TRANSFORM,                ID_NEW_TRANSFORM,        true, true },
    { VRML_BILLBOARD,                ID_NEW_BILLBOARD,        true, true },
    { VRML_COLLISION,                ID_NEW_COLLISION,        true, true },
    { VRML_LOD,                      ID_NEW_LOD,              true, true },
    { VRML_SWITCH,                   ID_NEW_SWITCH,           true, true },
    { BS,                            0,                       true, true },
    { VRML_ANCHOR,                   ID_NEW_ANCHOR,           true, true },
    { VRML_INLINE,                   ID_NEW_INLINE,           true, true }
};

static NodeButton buttons2[] = {
    { VRML_SHAPE,                    ID_NEW_SHAPE,              true,  true },
    { VRML_COORDINATE,               ID_NEW_COORDINATE,         false, true },
    { VRML_NORMAL,                   ID_NEW_NORMAL,             false, true },
    { VRML_COLOR,                    ID_NEW_COLOR,              false, true },
    { VRML_TEXTURE_COORDINATE,       ID_NEW_TEXTURE_COORDINATE, false, true },
    { VRML_FONT_STYLE,               ID_NEW_FONT_STYLE,         false, true },
    { BS,                            0,                         true,  true },
    { VRML_APPEARANCE,               ID_NEW_APPEARANCE,         false, true },
    { VRML_MATERIAL,                 ID_NEW_MATERIAL,           false, true },
    { VRML_IMAGE_TEXTURE,            ID_NEW_IMAGE_TEXTURE,      false, true },
    { VRML_PIXEL_TEXTURE,            ID_NEW_PIXEL_TEXTURE,      false, true },
    { VRML_MOVIE_TEXTURE,            ID_NEW_MOVIE_TEXTURE,      false, true },
    { VRML_TEXTURE_TRANSFORM,        ID_NEW_TEXTURE_TRANSFORM,  false, true },
    { BS,                            0,                         true,  true },
    { VRML_SOUND,                    ID_NEW_SOUND,              true,  true },
    { VRML_AUDIO_CLIP,               ID_NEW_AUDIO_CLIP,         false, true },
    { BS,                            0,                         true,  true },
    { VRML_DIRECTIONAL_LIGHT,        ID_NEW_DIRECTIONAL_LIGHT,  true,  true },
    { VRML_POINT_LIGHT,              ID_NEW_POINT_LIGHT,        true,  true },
    { VRML_SPOT_LIGHT,               ID_NEW_SPOT_LIGHT,         true,  true },
    { BS,                            0,                         true,  true },
    { VRML_FOG,                      ID_NEW_FOG,                true,  true },
    { VRML_BACKGROUND,               ID_NEW_BACKGROUND,         true,  true },
    { VRML_VIEWPOINT,                ID_NEW_VIEWPOINT,          true,  true },
    { VRML_NAVIGATION_INFO,          ID_NEW_NAVIGATION_INFO,    true,  true },
    { VRML_WORLD_INFO,               ID_NEW_WORLD_INFO,         true,  true }
};

static NodeButton buttons3[] = {
    { VRML_PROXIMITY_SENSOR,         ID_NEW_PROXIMITY_SENSOR,     true, true },
    { VRML_CYLINDER_SENSOR,          ID_NEW_CYLINDER_SENSOR,      true, true },
    { VRML_SPHERE_SENSOR,            ID_NEW_SPHERE_SENSOR,        true, true },
    { VRML_PLANE_SENSOR,             ID_NEW_PLANE_SENSOR,         true, true },
    { VRML_TIME_SENSOR,              ID_NEW_TIME_SENSOR,          true, true },
    { VRML_TOUCH_SENSOR,             ID_NEW_TOUCH_SENSOR,         true, true },
    { VRML_VISIBILITY_SENSOR,        ID_NEW_VISIBILITY_SENSOR,    true, true },
    { BS,                            0,                           true, true },
    { VRML_COLOR_INTERPOLATOR,       ID_NEW_COLOR_INTERPOLATOR,   true, true },
    { VRML_COORDINATE_INTERPOLATOR,  ID_NEW_COORDINATE_INTERPOLATOR, true, 
                                                                     true },
    { VRML_POSITION_INTERPOLATOR,    ID_NEW_POSITION_INTERPOLATOR, true, true },
    { VRML_ORIENTATION_INTERPOLATOR, ID_NEW_ORIENTATION_INTERPOLATOR, true, 
                                                                      true },
    { VRML_NORMAL_INTERPOLATOR,      ID_NEW_NORMAL_INTERPOLATOR,  true, true },
    { VRML_SCALAR_INTERPOLATOR,      ID_NEW_SCALAR_INTERPOLATOR,  true, true },
    { BS,                            0,                           true, true },
    { VRML_SCRIPT,                   ID_NEW_SCRIPT,               true, true },
    { BS,                            0,                           true, true },
    { VRML_COMMENT,                  ID_NEW_COMMENT,              true, true }
};

static NodeButton buttonsVRML200x[] = {
    { VRML_NURBS_CURVE,           ID_NEW_NURBS_CURVE,           true,  true },
    { VRML_NURBS_SURFACE,         ID_NEW_NURBS_PLANE,           true,  true },
    { VRML_NURBS_TEXTURE_SURFACE, ID_NEW_NURBS_TEXTURE_SURFACE, false, true },
    { BS,                         0,                            true,  true },
    { VRML_NURBS_GROUP,           ID_NEW_NURBS_GROUP,           true,  true },
    { BS,                         0,                            true,  true },
    { VRML_TRIMMED_SURFACE,       ID_NEW_TRIMMED_SURFACE,       false, true },
    { VRML_CONTOUR_2D,            ID_NEW_CONTOUR_2D,            false, true },
    { VRML_NURBS_CURVE_2D,        ID_NEW_NURBS_CURVE_2D,        false, true },
    { VRML_CONTOUR_POLYLINE_2D,   ID_NEW_CONTOUR_POLYLINE_2D,   false, true },
    { BS,                         0,                            true,  true },
    { VRML_COORDINATE_DEFORMER,   ID_NEW_COORDINATE_DEFORMER,   true,  true },
    { BS,                         0,                            true,  true },
    { VRML_NURBS_POSITION_INTERPOLATOR, ID_NEW_NURBS_POSITION_INTERPOLATOR, 
                                                                true,  true },
    { BS,                         0,                            true,  true },
    { VRML_GEO_ELEVATION_GRID,    ID_NEW_GEO_ELEVATION_GRID,    true,  true },
    { VRML_GEO_LOCATION,          ID_NEW_GEO_LOCATION,          true,  true },
    { VRML_GEO_ORIGIN,            ID_NEW_GEO_ORIGIN,            false, true },
    { VRML_GEO_LOD,               ID_NEW_GEO_LOD,               true,  true },
    { VRML_GEO_COORDINATE,        ID_NEW_GEO_COORDINATE,        false, true },
    { VRML_GEO_VIEWPOINT,         ID_NEW_GEO_VIEWPOINT,         true,  true },
    { VRML_GEO_TOUCH_SENSOR,      ID_NEW_GEO_TOUCH_SENSOR,      true,  true },
    { VRML_GEO_POSITION_INTERPOLATOR, ID_NEW_GEO_POSITION_INTERPOLATOR, 
                                                                true,  true },
    { X3D_GEO_PROXIMITY_SENSOR,   ID_NEW_GEO_PROXIMITY_SENSOR,  true,  true },
    { X3D_GEO_TRANSFORM,          ID_NEW_GEO_TRANSFORM,         true,  true },
    { X3D_GEO_METADATA,           ID_NEW_GEO_METADATA,          true,  true },
    { BS,                         0,                            true,  true },
    { VRML_INLINE_LOAD_CONTROL,   ID_NEW_INLINE_LOAD_CONTROL,   true,  true },
};

static NodeButton buttonsX3DComponents1[] = {
    { X3D_NURBS_SWEPT_SURFACE,   ID_NEW_NURBS_SWEPT_SURFACE,   false, true },
    { X3D_NURBS_SWUNG_SURFACE,   ID_NEW_NURBS_SWUNG_SURFACE,   false, true },
    { X3D_NURBS_TRIMMED_SURFACE, ID_NEW_NURBS_TRIMMED_SURFACE, false, true },
    { X3D_LINE_SET,              ID_NEW_LINE_SET,              true,  true },
    { X3D_INDEXED_TRIANGLE_STRIP_SET, 
                                 ID_NEW_INDEXED_TRIANGLE_STRIP_SET,
                                                               true,  true },
    { X3D_INDEXED_TRIANGLE_FAN_SET,  
                                 ID_NEW_INDEXED_TRIANGLE_FAN_SET,  
                                                               true,  true },
    { X3D_INDEXED_TRIANGLE_SET,  ID_NEW_INDEXED_TRIANGLE_SET,  true,  true },
    { X3D_TRIANGLE_STRIP_SET,    ID_NEW_TRIANGLE_STRIP_SET,    true,  true },
    { X3D_TRIANGLE_FAN_SET,      ID_NEW_TRIANGLE_FAN_SET,      true,  true },
    { X3D_TRIANGLE_SET,          ID_NEW_TRIANGLE_SET,          true,  true },
    { BS,                        0,                            true,  true },
    { X3D_INDEXED_QUAD_SET,      ID_NEW_INDEXED_QUAD_SET,      true,  true },
    { X3D_QUAD_SET,              ID_NEW_QUAD_SET,              true,  true },
    { BS,                        0,                            true,  true },
    { X3D_TRIANGLE_SET_2D,       ID_NEW_TRIANGLE_SET_2D,       true,  true },
    { X3D_DISK_2D,               ID_NEW_DISK_2D,               true,  true },
    { X3D_ARC_CLOSE_2D,          ID_NEW_ARC_CLOSE_2D,          true,  true },
    { X3D_CIRCLE_2D,             ID_NEW_CIRCLE_2D,             true,  true },
    { X3D_ARC_2D,                ID_NEW_ARC_2D,                true,  true },
    { X3D_POLYLINE_2D,           ID_NEW_POLYLINE_2D,           false, true },
    { X3D_POLYPOINT_2D,          ID_NEW_POLYPOINT_2D,          true,  true },
    { BS,                        0,                            true,  true },
    { X3D_STATIC_GROUP,          ID_NEW_STATIC_GROUP,          true,  true },
    { BS,                        0,                            true,  true },
    { X3D_COORDINATE_DOUBLE,     ID_NEW_COORDINATE_DOUBLE,     false, true },
    { X3D_COLOR_RGBA,            ID_NEW_COLOR_RGBA,            false, true },
    { X3D_CLIP_PLANE,            ID_NEW_CLIP_PLANE,            true,  true },
    { X3D_FOG_COORDINATE,        ID_NEW_FOG_COORDINATE,        false, true },
    { X3D_NURBS_TEXTURE_COORDINATE, 
                                 ID_NEW_NURBS_TEXTURE_COORDINATE, 
                                                               false, true },
    { BS,                        0,                            true,  true },
    { X3D_TWO_SIDED_MATERIAL,    ID_NEW_TWO_SIDED_MATERIAL,    false, true },
    { BS,                        0,                            true,  true },
    { X3D_FILL_PROPERTIES,       ID_NEW_FILL_PROPERTIES,       false, true },
    { X3D_LINE_PROPERTIES,       ID_NEW_LINE_PROPERTIES,       false, true },
    { BS,                        0,                            true,  true },
    { X3D_TEXTURE_PROPERTIES,    ID_NEW_TEXTURE_PROPERTIES,    false, true },
    { BS,                        0,                            true,  true },
    { X3D_LOCAL_FOG,             ID_NEW_LOCAL_FOG,             true,  true },
    { X3D_ORTHO_VIEWPOINT,       ID_NEW_ORTHO_VIEWPOINT,       true,  true },
    { X3D_VIEWPOINT_GROUP,       ID_NEW_VIEWPOINT_GROUP,       true,  true }
};

static NodeButton buttonsX3DComponents2[] = {
    { X3D_MULTI_TEXTURE_COORDINATE,         
                                 ID_NEW_MULTI_TEXTURE_COORDINATE,
                                                               false, true },
    { X3D_TEXTURE_COORDINATE_GENERATOR,
                                  ID_NEW_TEXTURE_COORDINATE_GENERATOR,
                                                               false, true },
    { X3D_TEXTURE_COORDINATE_3D, ID_NEW_TEXTURE_COORDINATE_3D, false, true },
    { X3D_TEXTURE_COORDINATE_4D, ID_NEW_TEXTURE_COORDINATE_4D, false, true },
    { BS,                        0,                            true,  true },
    { X3D_MULTI_TEXTURE,         ID_NEW_MULTI_TEXTURE,         false, true },
    { X3D_COMPOSED_TEXTURE_3D,   ID_NEW_COMPOSED_TEXTURE_3D,   false, true },
    { X3D_IMAGE_TEXTURE_3D,      ID_NEW_IMAGE_TEXTURE_3D,      false, true },
    { X3D_PIXEL_TEXTURE_3D,      ID_NEW_PIXEL_TEXTURE_3D,      false, true },
    { BS,                        0,                            true,  true },
    { X3D_MULTI_TEXTURE_TRANSFORM,     
                                 ID_NEW_MULTI_TEXTURE_TRANSFORM,
                                                               false, true },
    { X3D_TEXTURE_TRANSFORM_MATRIX_3D,     
                                 ID_NEW_TEXTURE_TRANSFORM_MATRIX_3D,
                                                               false, true },
    { X3D_TEXTURE_TRANSFORM_3D, ID_NEW_TEXTURE_TRANSFORM_3D,   false, true },
    { BS,                        0,                            true,  true },
    { X3D_POSITION_INTERPOLATOR_2D, 
                                 ID_NEW_POSITION_INTERPOLATOR_2D, 
                                                               true,  true },
    { X3D_COORDINATE_INTERPOLATOR_2D, 
                                 ID_NEW_COORDINATE_INTERPOLATOR_2D, 
                                                               true,  true },
    { X3D_NURBS_ORIENTATION_INTERPOLATOR,
                                 ID_NEW_NURBS_ORIENTATION_INTERPOLATOR,
                                                               true,  true },
    { X3D_NURBS_SURFACE_INTERPOLATOR, 
                                 ID_NEW_NURBS_SURFACE_INTERPOLATOR, 
                                                               true,  true },
    { X3D_SPLINE_POSITION_INTERPOLATOR,
                                 ID_NEW_SPLINE_POSITION_INTERPOLATOR,
                                                               true,  true },
    { X3D_SPLINE_POSITION_INTERPOLATOR_2D,
                                 ID_NEW_SPLINE_POSITION_INTERPOLATOR_2D,
                                                               true,  true },
    { X3D_SPLINE_SCALAR_INTERPOLATOR, 
                                 ID_NEW_SPLINE_SCALAR_INTERPOLATOR,
                                                               true,  true },
    { X3D_SQUAD_ORIENTATION_INTERPOLATOR,
                                 ID_NEW_SQUAD_ORIENTATION_INTERPOLATOR,
                                                               true,  true },
    { X3D_EASE_IN_EASE_OUT,      ID_NEW_EASE_IN_EASE_OUT,      true,  true },
    { BS,                        0,                            true,  true },
    { X3D_BOOLEAN_FILTER,        ID_NEW_BOOLEAN_FILTER,        true,  true },
    { X3D_BOOLEAN_TOGGLE,        ID_NEW_BOOLEAN_TOGGLE,        true,  true },
    { X3D_BOOLEAN_TRIGGER,       ID_NEW_BOOLEAN_TRIGGER,       true,  true },
    { X3D_INTEGER_TRIGGER,       ID_NEW_INTEGER_TRIGGER,       true,  true },
    { X3D_TIME_TRIGGER,          ID_NEW_TIME_TRIGGER,          true,  true },
    { X3D_BOOLEAN_SEQUENCER,     ID_NEW_BOOLEAN_SEQUENCER,     true,  true },
    { X3D_INTEGER_SEQUENCER,     ID_NEW_INTEGER_SEQUENCER,     true,  true },
    { BS,                        0,                            true,  true },
    { X3D_KEY_SENSOR,            ID_NEW_KEY_SENSOR,            true,  true },
    { X3D_STRING_SENSOR,         ID_NEW_STRING_SENSOR,         true,  true },
    { X3D_LOAD_SENSOR,           ID_NEW_LOAD_SENSOR,           true,  true },
    { X3D_TRANSFORM_SENSOR,      ID_NEW_TRANSFORM_SENSOR,      true,  true }
};

static NodeButton buttonsX3DComponents3[] = {
    { X3D_COMPOSED_SHADER,       ID_NEW_COMPOSED_SHADER,       false, true },
    { X3D_SHADER_PART,           ID_NEW_SHADER_PART,           false, true },
    { X3D_PACKAGED_SHADER,       ID_NEW_PACKAGED_SHADER,       false, true },
    { X3D_PROGRAM_SHADER,        ID_NEW_PROGRAM_SHADER,        false, true },
    { X3D_SHADER_PROGRAM,        ID_NEW_SHADER_PROGRAM,        false, true },
    { BS,                        0,                            true,  true },
    { X3D_FLOAT_VERTEX_ATTRIBUTE,
                                 ID_NEW_FLOAT_VERTEX_ATTRIBUTE,
                                                               false, true },
    { X3D_MATRIX_3_VERTEX_ATTRIBUTE,     
                                 ID_NEW_MATRIX_3_VERTEX_ATTRIBUTE,
                                                               false, true },
    { X3D_MATRIX_4_VERTEX_ATTRIBUTE,     
                                 ID_NEW_MATRIX_4_VERTEX_ATTRIBUTE,
                                                               false, true },
    { BS,                        0,                            true,  true },
    { X3D_LAYER_SET,             ID_NEW_LAYER_SET,             false, true },
    { X3D_LAYER,                 ID_NEW_LAYER,                 false, true },
    { X3D_VIEWPORT,              ID_NEW_VIEWPORT,              true,  true },
    { BS,                        0,                            true,  true },
    { X3D_LAYOUT_GROUP,          ID_NEW_LAYOUT_GROUP,          true,  true },
    { X3D_LAYOUT,                ID_NEW_LAYOUT,                false, true },
    { X3D_LAYOUT_LAYER,          ID_NEW_LAYOUT_LAYER,          false, true },
    { X3D_SCREEN_FONT_STYLE,     ID_NEW_SCREEN_FONT_STYLE,     false, true },
    { X3D_SCREEN_GROUP,          ID_NEW_SCREEN_GROUP,          true,  true },
    { BS,                        0,                            true,  true },
    { X3D_CAD_ASSEMBLY,          ID_NEW_CAD_ASSEMBLY,          true,  true },
    { X3D_CAD_FACE,              ID_NEW_CAD_FACE,              false, true },
    { X3D_CAD_LAYER,             ID_NEW_CAD_LAYER,             true,  true },
    { X3D_CAD_PART,              ID_NEW_CAD_PART,              true,  true },
    { BS,                        0,                            true,  true },
    { X3D_PARTICLE_SYSTEM,       ID_NEW_PARTICLE_SYSTEM,       true,  true },
    { BS,                        0,                            true,  true },
    { X3D_BOUNDED_PHYSICS_MODEL, ID_NEW_BOUNDED_PHYSICS_MODEL, false, true },
    { X3D_GRAVITY_PHYSICS_MODEL, ID_NEW_GRAVITY_PHYSICS_MODEL, false, true },
    { X3D_FORCE_PHYSICS_MODEL,   ID_NEW_FORCE_PHYSICS_MODEL,   false, true },
    { X3D_WIND_PHYSICS_MODEL,    ID_NEW_WIND_PHYSICS_MODEL,    false, true },
    { BS,                        0,                            true,  true },
    { X3D_VOLUME_EMITTER,        ID_NEW_VOLUME_EMITTER,        false, true },
    { X3D_SURFACE_EMITTER,       ID_NEW_SURFACE_EMITTER,       false, true },
    { X3D_CONE_EMITTER,          ID_NEW_CONE_EMITTER,          false, true },
    { X3D_POLYLINE_EMITTER,      ID_NEW_POLYLINE_EMITTER,      false, true },
    { X3D_POINT_EMITTER,         ID_NEW_POINT_EMITTER,         false, true },
    { X3D_EXPLOSION_EMITTER,     ID_NEW_EXPLOSION_EMITTER,     false, true }
};

static NodeButton buttonsX3DComponents4[] = {
    { X3D_RIGID_BODY_COLLECTION,   ID_NEW_RIGID_BODY_COLLECTION, true,  true },
    { X3D_RIGID_BODY,              ID_NEW_RIGID_BODY,            false, true },
    { BS,                          0,                            true,  true },
    { X3D_COLLIDABLE_SHAPE,        ID_NEW_COLLIDABLE_SHAPE,      true,  true },
    { X3D_COLLIDABLE_OFFSET,       ID_NEW_COLLIDABLE_OFFSET,     true,  true },
    { BS,                          0,                            true,  true },
    { X3D_CONTACT,                 ID_NEW_CONTACT,               true,  true },
    { BS,                          0,                            true,  true },
    { X3D_COLLISION_COLLECTION,    ID_NEW_COLLISION_COLLECTION,  false, true },
    { X3D_COLLISION_SPACE,         ID_NEW_COLLISION_SPACE,       false, true },
    { X3D_COLLISION_SENSOR,        ID_NEW_COLLISION_SENSOR,      true,  true },
    { BS,                          0,                            true,  true },
    { X3D_SLIDER_JOINT,            ID_NEW_SLIDER_JOINT,          false, true },
    { X3D_SINGLE_AXIS_HINGE_JOINT, ID_NEW_SINGLE_AXIS_HINGE_JOINT, 
                                                                 false, true },
    { X3D_DOUBLE_AXIS_HINGE_JOINT, ID_NEW_DOUBLE_AXIS_HINGE_JOINT, 
                                                                 false, true },
    { X3D_BALL_JOINT,              ID_NEW_BALL_JOINT,            false, true },
    { X3D_MOTOR_JOINT,             ID_NEW_MOTOR_JOINT,           false, true },
    { X3D_UNIVERSAL_JOINT,         ID_NEW_UNIVERSAL_JOINT,       false, true },
#ifdef HAVE_LIBODE
    { BS,                          0,                            true,  true },
    { DUNE_ODE_MOTOR_JOINT,             ID_NEW_ODE_MOTOR_JOINT,  false, true },
    { DUNE_ODE_SINGLE_AXIS_HINGE_JOINT, ID_NEW_ODE_SINGLE_AXIS_HINGE_JOINT, 
                                                                 false, true },
    { DUNE_ODE_SLIDER_JOINT,            ID_NEW_ODE_SLIDER_JOINT, false, true },
#endif
    { BS,                        0,                              true,  true },
    { X3D_PICKABLE_GROUP,        ID_NEW_PICKABLE_GROUP,          true,  true },
    { BS,                        0,                              true,  true },
    { X3D_LINE_PICK_SENSOR,      ID_NEW_LINE_PICK_SENSOR,        true,  true },
    { X3D_POINT_PICK_SENSOR,     ID_NEW_POINT_PICK_SENSOR,       true,  true },
    { X3D_PRIMITIVE_PICK_SENSOR, ID_NEW_PRIMITIVE_PICK_SENSOR,   true,  true },
    { X3D_VOLUME_PICK_SENSOR,    ID_NEW_VOLUME_PICK_SENSOR,      true,  true },
    { BS,                        0,                              true,  true },
    { X3D_HANIM_HUMANOID,        ID_NEW_HANIM_HUMANOID,          true,  true },
    { X3D_HANIM_JOINT,           ID_NEW_HANIM_JOINT,             false,  true },
    { X3D_HANIM_SEGMENT,         ID_NEW_HANIM_SEGMENT,           false,  true },
    { X3D_HANIM_DISPLACER,       ID_NEW_HANIM_DISPLACER,         false,  true },
    { X3D_HANIM_SITE,            ID_NEW_HANIM_SITE,              false,  true },
    { BS,                        0,                              true,  true },
    { X3D_COLOR_DAMPER,          ID_NEW_COLOR_DAMPER,            true,  true },
    { X3D_COORDINATE_DAMPER,     ID_NEW_COORDINATE_DAMPER,       true,  true },
    { X3D_ORIENTATION_CHASER,    ID_NEW_ORIENTATION_CHASER,      true,  true },
    { X3D_ORIENTATION_DAMPER,    ID_NEW_ORIENTATION_DAMPER,      true,  true },
    { X3D_POSITION_CHASER,       ID_NEW_POSITION_CHASER,         true,  true },
    { X3D_POSITION_CHASER_2D,    ID_NEW_POSITION_CHASER_2D,      true,  true },
    { X3D_POSITION_DAMPER,       ID_NEW_POSITION_DAMPER,         true,  true },
    { X3D_POSITION_DAMPER_2D,    ID_NEW_POSITION_DAMPER_2D,      true,  true },
    { X3D_SCALAR_CHASER,         ID_NEW_SCALAR_CHASER,           true,  true },
    { X3D_TEX_COORD_DAMPER_2D,   ID_NEW_TEX_COORD_DAMPER_2D,     true,  true },
    { BS,                        0,                              true,  true },
    { X3D_ESPDU_TRANSFORM,       ID_NEW_ESPDU_TRANSFORM,         true,  true },
    { X3D_RECEIVER_PDU,          ID_NEW_RECEIVER_PDU,            true,  true },
    { X3D_SIGNAL_PDU,            ID_NEW_SIGNAL_PDU,              true,  true },
    { X3D_TRANSMITTER_PDU,       ID_NEW_TRANSMITTER_PDU,         true,  true },
    { X3D_DIS_ENTITY_MANAGER,    ID_NEW_DIS_ENTITY_MANAGER,      true,  true },
    { X3D_DIS_ENTITY_TYPE_MAPPING, 
                                 ID_NEW_DIS_ENTITY_TYPE_MAPPING,
                                                                 true,  true }
};

static NodeButton buttonsCover[] = {
    { COVER_SKY,                   ID_NEW_COVER_SKY,              true,  true },
    { BS,0, true, true },
    { COVER_CUBE_TEXTURE,          ID_NEW_COVER_CUBE_TEXTURE,     false, true },
    { BS,                          0,                             true,  true },
#ifdef HAVE_COVER_WAVE
    { COVER_WAVE,                  ID_NEW_COVER_WAVE,             true,  true },
    { BS,                          0,                             true,  true },
#endif
    { COVER_VIRTUAL_ACOUSTICS,     ID_NEW_COVER_VIRTUAL_ACOUSTICS,
                                                                  true,  true },
    { COVER_VIRTUAL_SOUND_SOURCE,  ID_NEW_COVER_VIRTUAL_SOUND_SOURCE,
                                                                  false, true},
    { BS,                          0,                             true,  true },
    { COVER_COVER,                 ID_NEW_COVER_COVER,            true,  true },
    { COVER_SPACE_SENSOR,          ID_NEW_COVER_SPACE_SENSOR,     true,  true },
    { COVER_AR_SENSOR,             ID_NEW_COVER_AR_SENSOR,        true,  true },
    { COVER_JOYSTICK_SENSOR,       ID_NEW_COVER_JOYSTICK_SENSOR,  true,  true },
    { COVER_STEERING_WHEEL,        ID_NEW_COVER_STEERING_WHEEL,   true,  true },
    { COVER_VEHICLE,               ID_NEW_COVER_VEHICLE,          true,  true },
    { COVER_LAB_VIEW,              ID_NEW_COVER_LAB_VIEW,         true,  true },
    { BS,                          0,                             true,  true },
    { COVER_TUI_BUTTON,            ID_NEW_COVER_TUI_BUTTON,       true,  true },
    { COVER_TUI_COMBO_BOX,         ID_NEW_COVER_TUI_COMBO_BOX,    true,  true },
    { COVER_TUI_FLOAT_SLIDER,      ID_NEW_COVER_TUI_FLOAT_SLIDER, true,  true },
    { COVER_TUI_FRAME,             ID_NEW_COVER_TUI_FRAME,        true,  true },
    { COVER_TUI_LABEL,             ID_NEW_COVER_TUI_LABEL,        true,  true },
    { COVER_TUI_LIST_BOX,          ID_NEW_COVER_TUI_LIST_BOX,     true,  true },
#ifdef HAVE_COVER_TUI_MAP
    { COVER_TUI_MAP,               ID_NEW_COVER_TUI_MAP,          true,  true },
#endif
    { COVER_TUI_PROGRESS_BAR,      ID_NEW_COVER_TUI_PROGRESS_BAR, true,  true },
    { COVER_TUI_SLIDER,            ID_NEW_COVER_TUI_SLIDER,       true,  true },
    { COVER_TUI_SPLITTER,          ID_NEW_COVER_TUI_SPLITTER,     true,  true },
    { COVER_TUI_TAB,               ID_NEW_COVER_TUI_TAB,          true,  true },
    { COVER_TUI_TAB_FOLDER,        ID_NEW_COVER_TUI_TAB_FOLDER,   true,  true },
    { COVER_TUI_TOGGLE_BUTTON,     ID_NEW_COVER_TUI_TOGGLE_BUTTON, true,  true }
};

static NodeButton buttonsKambi[] = {
    { KAMBI_TEAPOT,                ID_NEW_KAMBI_TEAPOT,           true,  true },
    { KAMBI_TEXT_3D,               ID_NEW_KAMBI_TEXT_3D,          true,  true },
    { BS,                          0,                             true,  true },
    { KAMBI_KAMBI_INLINE,          ID_NEW_KAMBI_INLINE,           true,  true },
    { BS,                          0,                             true,  true },
    { KAMBI_MATRIX_TRANSFORM,      ID_NEW_KAMBI_MATRIX_TRANSFORM, true,  true },
    { BS,                          0,                             true,  true },
    { KAMBI_KAMBI_APPEARANCE,      ID_NEW_KAMBI_APPEARANCE,       false, true },
    { KAMBI_BLEND_MODE,            ID_NEW_KAMBI_BLEND_MODE,       false, true },
    { KAMBI_KAMBI_OCTREE_PROPERTIES, ID_NEW_KAMBI_OCTREE_PROPERTIES,
                                                                  false, true },
    { KAMBI_GENERATED_SHADOW_MAP,  ID_NEW_KAMBI_GENERATED_SHADOW_MAP, 
                                                                  false, true },
    { KAMBI_MULTI_GENERATED_TEXTURE_COORDINATE,
                              ID_NEW_KAMBI_MULTI_GENERATED_TEXTURE_COORDINATE,
                                                                  false, true },
    { KAMBI_PROJECTED_TEXTURE_COORDINATE,      
                                   ID_NEW_KAMBI_PROJECTED_TEXTURE_COORDINATE, 
                                                                  false, true },
    { KAMBI_RENDERED_TEXTURE,      ID_NEW_KAMBI_RENDERED_TEXTURE, false, true },
    { BS,                          0,                             true,  true },
    { KAMBI_KAMBI_NAVIGATION_INFO, ID_NEW_KAMBI_NAVIGATION_INFO,  true,  true },
    { KAMBI_KAMBI_HEAD_LIGHT,      ID_NEW_KAMBI_HEAD_LIGHT,       true,  true },
    { BS,                          0,                             true,  true },
    { KAMBI_KAMBI_TRIANGULATION,   ID_NEW_KAMBI_TRIANGULATION,    true,  true },
};

static NodeButton buttonsScripted[] = {
    { DUNE_SUPER_ELLIPSOID, ID_NEW_SUPER_ELLIPSOID, true,  true },
    { DUNE_SUPER_EXTRUSION, ID_NEW_SUPER_EXTRUSION, true,  true },
    { DUNE_SUPER_SHAPE,     ID_NEW_SUPER_SHAPE,     true,  true },
    { DUNE_SUPER_REVOLVER,  ID_NEW_SUPER_REVOLVER,  true,  true },
    { BS,                   0,                      true,  true },
    { DUNE_VRML_CUT,        ID_NEW_VRML_CUT,        false, true },
    { DUNE_VRML_SCENE,      ID_NEW_VRML_SCENE,      false, true }
};


static int standardButtons4Kids[] = {
    1,  ID_DUNE_FILE_OPEN,
    2,  ID_DUNE_FILE_SAVE,
    BS, 0,
    43, ID_TO_NURBS_4KIDS,
    29, ID_ANIMATION,
    BS, 0,
    38, ID_X_ONLY,
    39, ID_Y_ONLY,
    40, ID_Z_ONLY,
    BS, 0,
    28, ID_X_SYMETRIC,
    BS, 0,
    33, ID_STAND_UP,
    BS, 0,
    34, ID_WALK_MOUSE_MODE,
    35, ID_EXAMINE_MOUSE_MODE,
    24, ID_FLY_MOUSE_MODE,
    32, ID_ROLL_MOUSE_MODE,
    30, ID_MOUSE_NAVIGATION_MODE,
    BS, 0,
//    36, ID_SHOW_JOINT_LIKE_HANDLES,
    9,  ID_MOVE_MODE,
    10, ID_ROTATE_MODE,
    11, ID_SCALE_MODE,
    42, ID_UNIFORM_SCALE_MODE,
    12, ID_CENTER_MODE,
};

static int standardButtons4KidsWithInputDevices[] = {
    1,  ID_DUNE_FILE_OPEN,
    2,  ID_DUNE_FILE_SAVE,
    BS, 0,
    43, ID_TO_NURBS_4KIDS,
    29, ID_ANIMATION,
    BS, 0,
    38, ID_X_ONLY,
    39, ID_Y_ONLY,
    40, ID_Z_ONLY,
    BS, 0,
    28, ID_X_SYMETRIC,
    BS, 0,
    33, ID_STAND_UP,
    BS, 0,
    34, ID_WALK_MOUSE_MODE,
    35, ID_EXAMINE_MOUSE_MODE,
    24, ID_FLY_MOUSE_MODE,
    32, ID_ROLL_MOUSE_MODE,
    30, ID_MOUSE_NAVIGATION_MODE,
    BS, 0,
    31, ID_INPUT_DEVICE_NAVIGATION_MODE,
//    36, ID_SHOW_JOINT_LIKE_HANDLES,
    9,  ID_MOVE_MODE,
    10, ID_ROTATE_MODE,
    11, ID_SCALE_MODE,
    42, ID_UNIFORM_SCALE_MODE,
    12, ID_CENTER_MODE,
    13, ID_6D_MODE,
    14, ID_6DLOCAL_MODE,
    15, ID_ROCKET_MODE,
    16, ID_HOVER_MODE,
    BS, 0,
    17, ID_3D_MODE,
    18, ID_2D_MODE,
    19, ID_1D_MODE,
    BS, 0,
    20, ID_NEAR_FAR_MODE,
    21, ID_UP_DOWN_MODE,
    BS, 0,
    26, ID_INPUTDEVICE_GREATER,
    27, ID_INPUTDEVICE_LESSER
};

IconPos::IconPos(void)
{
    int size = sizeof(standardButtons);
    int *buttons = standardButtons;
    if (TheApp->is4Kids()) 
        if (TheApp->hasInputDevices()) {
            size = sizeof(standardButtons4KidsWithInputDevices);
            buttons = standardButtons4KidsWithInputDevices;
        } else {
            size = sizeof(standardButtons4Kids);
            buttons = standardButtons4Kids;
        }

    _fileNewIconPos     = GetIconPos(buttons, size, ID_DUNE_FILE_NEW);
    _fileNewX3dIconPos  = GetIconPos(buttons, size, ID_DUNE_FILE_NEW_X3DV);
    _fileOpenIconPos    = GetIconPos(buttons, size, ID_DUNE_FILE_OPEN);
    _fileSaveIconPos    = GetIconPos(buttons, size, ID_DUNE_FILE_SAVE);
    _filePreviewIconPos = GetIconPos(buttons, size, ID_DUNE_FILE_PREVIEW);

    _editCutIconPos    = GetIconPos(buttons, size, ID_DUNE_EDIT_CUT);
    _editCopyIconPos   = GetIconPos(buttons, size, ID_DUNE_EDIT_COPY);
    _editPasteIconPos  = GetIconPos(buttons, size, ID_DUNE_EDIT_PASTE);
    _editDeleteIconPos = GetIconPos(buttons, size, ID_DUNE_EDIT_DELETE);

    _fullScreenIconPos = GetIconPos(buttons, size, ID_DUNE_VIEW_FULL_SCREEN);

    _colorCircleIconPos = GetIconPos(buttons, size, ID_COLOR_CIRCLE);

    _objectEditIconPos = GetIconPos(buttons, size, ID_OBJECT_EDIT);
    _urlEditIconPos    = GetIconPos(buttons, size, ID_URL_EDIT);

    _animationIconPos = GetIconPos(buttons, size, ID_ANIMATION);
    _toNurbs4KidsIconPos = GetIconPos(buttons, size, ID_TO_NURBS_4KIDS);

    _interactionIconPos = GetIconPos(buttons, size, ID_INTERACTION);

    _x_symetricIconPos = GetIconPos(buttons, size, ID_X_SYMETRIC);

    _mouseExamineIconPos = GetIconPos(buttons, size, ID_EXAMINE_MOUSE_MODE);
    _mouseWalkIconPos    = GetIconPos(buttons, size, ID_WALK_MOUSE_MODE);
    _mouseFlyIconPos     = GetIconPos(buttons, size, ID_FLY_MOUSE_MODE);
    _mouseRollIconPos    = GetIconPos(buttons, size, ID_ROLL_MOUSE_MODE);

    _navigationMouseIconPos = GetIconPos(buttons, size, 
                                         ID_MOUSE_NAVIGATION_MODE);
    _navigationInputDeviceIconPos = GetIconPos(buttons, size,
                                               ID_INPUT_DEVICE_NAVIGATION_MODE);

    _inputModeStartIconPos = GetIconPos(buttons, size, ID_MOVE_MODE);

    _tDimensionStartIconPos = GetIconPos(buttons, size, ID_3D_MODE);

    _t2axesStartIconPos = GetIconPos(buttons, size, ID_NEAR_FAR_MODE);

    _xOnlyIconPos = GetIconPos(buttons, size, ID_X_ONLY);
    _yOnlyIconPos = GetIconPos(buttons, size, ID_Y_ONLY);
    _zOnlyIconPos = GetIconPos(buttons, size, ID_Z_ONLY);

    _inputDeviceGreaterIconPos = GetIconPos(buttons, size,
                                            ID_INPUTDEVICE_GREATER);
    _inputDeviceLesserIconPos = GetIconPos(buttons, size,
                                           ID_INPUTDEVICE_LESSER);

//    _showJointLikeHandlesIconPos = GetIconPos(buttons, size,
//                                              ID_SHOW_JOINT_LIKE_HANDLES);
}

int IconPos::GetIconPos(int* buttons, int length, int icon)
{
    if (TheApp->is4Kids() && (buttons == standardButtons))
        return -1;
    for (int i = 0; i < length; i++)
       if (buttons[2 * i + 1] == icon)
          return i;
    return -1;
}

static int
timerCB(void *data)
{
    return ((MainWindow *) data)->OnTimer();
}

// callback for MainWindow::doWithBranch(callback, data)

static bool searchVrmlCut(Node *node, void *data)
{
    if (node->getType() == DUNE_VRML_CUT) {
        MainWindow *wnd = (MainWindow *)data;
        wnd->setVrmlCutNode(node);
        return false;
    }
    return true;     
}

MainWindow::MainWindow(Scene *scene, SWND wnd)
  : PanedWindow(scene, wnd, false)
{
    _vrmlCutNode = NULL;
    _parentWindow = wnd;
    _fieldView = NULL;
    _timer = NULL;
    _fieldPipeCommand = "";
    _fieldPipeFilterNode = "";
    _fieldPipeFilterField = "";
    _showNumbers4Kids = false;

    if (TheApp->is4Kids())
        _menu = swLoadMenuBar(wnd, IDR_DUNE_4KIDS_TYPE + swGetLang());
    else if (TheApp->is4Catt())
        _menu = swLoadMenuBar(wnd, IDR_DUNE_4CATT_TYPE + swGetLang());
    else {
        _menu = swLoadMenuBar(wnd, IDR_DUNE_TYPE + swGetLang());
#ifdef HAVE_OLPC
        swDebugf("On the olpc, you better start \"dune -4kids\"\n");
#endif
     }
    RefreshProtoMenu();
    RefreshRecentFileMenu();

#ifdef HAVE_SAND
    _nebulaExporter.InitMenu(_menu);
#endif
    SWND sb = swCreateCanvas("", 0, 0, 800, 22, wnd);
    _statusBar = new StatusBar(scene, sb);
    SetPane(_statusBar, PW_BOTTOM);
    if (TheApp->GetBoolPreference("ShowStatusBar", true)) {
        swMenuSetFlags(_menu, ID_DUNE_VIEW_STATUS_BAR,
                       SW_MENU_CHECKED, SW_MENU_CHECKED);
    } else {
        swHideWindow(sb);
    }

    SWND o = swCreateCanvas("", 0, 0, 800, 400, wnd);
    _outerPane = new PanedWindow(scene, o, false);
    SetPane(_outerPane, PW_CENTER);

    SWND i = swCreateCanvas("", 0, 0, 800, 400, o);
    _innerPane = new PanedWindow(scene, i, true);

    SWND t = swCreateCanvas("", 0, 0, 800, 100, o);
    _toolbarWindow = new ToolbarWindow(scene, t, this);

    SWND t2 = swCreateCanvas("", 0, 0, 800, 100, o);
    _toolbarWindow2 = new ToolbarWindow(scene, t2, this);

    SWND c1 = swCreateCanvas("", 0, 0, 200, 400, i);
    _treeView = new SceneTreeView(scene, c1);
    _innerPane->SetPane(_treeView, PW_LEFT);
    if (TheApp->is4Kids() | TheApp->is4Catt()) {
        swMenuSetFlags(_menu, ID_DUNE_VIEW_SCENE_TREE, SW_MENU_CHECKED, 
                       SW_MENU_CHECKED);
        _treeView->setEnabled(true);
    } else {
        if (TheApp->GetBoolPreference("ShowSceneTree", true)) {
            swMenuSetFlags(_menu, ID_DUNE_VIEW_SCENE_TREE, SW_MENU_CHECKED, 
            SW_MENU_CHECKED);
            _treeView->setEnabled(true);
        } else {
            swHideWindow(_treeView->GetWindow());
            _treeView->setEnabled(false);
        }
    }

    SWND c2 = swCreateCanvas("", 200, 0, 400, 400, i);
    _S3DView = new Scene3DView(scene, c2);
    _innerPane->SetPane(_S3DView, PW_CENTER);

    SWND c3 = swCreateCanvas("", 600, 0, 300, 400, i);
    _fieldCanvas = c3;
    _fieldView = new FieldView(scene, c3);
    _innerPane->SetPane(_fieldView, PW_RIGHT);
    if (TheApp->is4Kids()) {
        swHideWindow(_fieldView->GetWindow());
        _fieldView->setEnabled(false);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_FIELD_VIEW_4_KIDS, SW_MENU_CHECKED, 
                       _showNumbers4Kids ? SW_MENU_CHECKED : 0);
    } else {
        if (TheApp->GetBoolPreference("ShowFieldView", true) ||
            TheApp->is4Catt()) {
            swMenuSetFlags(_menu, ID_DUNE_VIEW_FIELD_VIEW, SW_MENU_CHECKED, 
                           SW_MENU_CHECKED);
            _fieldView->setEnabled(true);
        } else {
            swHideWindow(_fieldView->GetWindow());
            _fieldView->setEnabled(false);
        }
    }

    SWND c4 = swCreateCanvas("", 0, 0, 800, 160, i);
    _graphView = new SceneGraphView(scene, c4);
    _innerPane->SetPane(_graphView, PW_TOP);
    if (TheApp->is4Kids() | TheApp->is4Catt()) {
        swHideWindow(_graphView->GetWindow());
       _graphView->setEnabled(false);
    } else {
        if (TheApp->GetBoolPreference("ShowRouteView", false)) {
            swMenuSetFlags(_menu, ID_DUNE_VIEW_SCENE_GRAPH, SW_MENU_CHECKED, 
                           SW_MENU_CHECKED);
            _graphView->setEnabled(true);
        } else {
            swHideWindow(_graphView->GetWindow());
            _graphView->setEnabled(false);
        }
    }

    SWND c5 = swCreateCanvas("", 0, 400, 800, 200, i);
    _channelView = new ChannelView(scene, c5);
    _innerPane->SetPane(_channelView, PW_BOTTOM);
    if (TheApp->is4Kids() | TheApp->is4Catt()) {
        swHideWindow(_channelView->GetWindow());
       _channelView->setEnabled(false);
    } else {
        if (TheApp->GetBoolPreference("ShowChannelView", true)) {
            swMenuSetFlags(_menu, ID_DUNE_VIEW_CHANNEL_VIEW, SW_MENU_CHECKED, 
                           SW_MENU_CHECKED);
            _channelView->setEnabled(true);
        } else {
            swHideWindow(_channelView->GetWindow());
            _channelView->setEnabled(false);
        }
    }

    bool olpc = TheApp->isOLPC();
    int idb_standard_toolbar = IDB_STANDARD_TOOLBAR;
    if (TheApp->getBlackAndWhiteIcons())
        idb_standard_toolbar = IDB_STANDARD_TOOLBAR_BW;

    int size = ARRAYSIZE(standardButtons);
    int *buttons = standardButtons;
    if (TheApp->is4Kids())
        if (TheApp->hasInputDevices()) {
            size = ARRAYSIZE(standardButtons4KidsWithInputDevices);
            buttons = standardButtons4KidsWithInputDevices;
        } else {
            size = ARRAYSIZE(standardButtons4Kids);
            buttons = standardButtons4Kids;
        }


    _standardToolbar = LoadToolbar(_toolbarWindow, idb_standard_toolbar,
                                   size / 2, buttons, ID_DUNE_VIEW_TOOLBAR,
                                   "StandardToolbar");
    if (TheApp->is4Catt())
        _toolbarWindow->ShowToolbar(_standardToolbar, false); 
    if (TheApp->is4Kids())
        _toolbarWindow->ShowToolbar(_standardToolbar, true); 
    int idb_node_icons = IDB_NODE_ICONS;
    if (TheApp->getBlackAndWhiteIcons())
        idb_node_icons = IDB_NODE_ICONS_BW;
     // avoid update of toolbar button after use of this button,
     // cause this button will close the window and open a new one
     swToolbarSetButtonFlags(_standardToolbar, _fileOpenIconPos, 
                             SW_TB_DONT_UPDATE, SW_TB_DONT_UPDATE);

    _nodeToolbar1 = LoadToolbar(_toolbarWindow, idb_node_icons,
                                ARRAYSIZE(buttons1), buttons1,
                                ID_DUNE_VIEW_NODE_TOOLBAR_1, "NodeToolbar1");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbar1Enabled = false;
    else
        _nodeToolbar1Enabled = TheApp->GetBoolPreference("NodeToolbar1", !olpc);
    _toolbarWindow->ShowToolbar(_nodeToolbar1, _nodeToolbar1Enabled);


    _nodeToolbar2 = LoadToolbar(_toolbarWindow, idb_node_icons,
                                ARRAYSIZE(buttons2), buttons2,
                                ID_DUNE_VIEW_NODE_TOOLBAR_2, "NodeToolbar2");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbar2Enabled = false;
    else
        _nodeToolbar2Enabled = TheApp->GetBoolPreference("NodeToolbar2", !olpc);
    _toolbarWindow->ShowToolbar(_nodeToolbar2, _nodeToolbar2Enabled);

    _nodeToolbar3 = LoadToolbar(_toolbarWindow, idb_node_icons,
                                ARRAYSIZE(buttons3), buttons3, 
                                ID_DUNE_VIEW_NODE_TOOLBAR_3, "NodeToolbar3");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbar3Enabled = false;
    else
        _nodeToolbar3Enabled = TheApp->GetBoolPreference("NodeToolbar3", !olpc);
    _toolbarWindow->ShowToolbar(_nodeToolbar3, _nodeToolbar3Enabled);

    for (int j = 0; j < ARRAYSIZE(buttonsVRML200x); j++) {
        // replace NurbsGroup icon with combined NurbsGroup/NurbsSet icon
        if (buttonsVRML200x[j].type == VRML_NURBS_GROUP) {
            buttonsVRML200x[j].type = scene->getNumberBuildinProtos() + 1;
            break;
        }
    }
    _nodeToolbarVRML200x = LoadToolbar(_toolbarWindow, idb_node_icons,
                                       ARRAYSIZE(buttonsVRML200x),
                                       buttonsVRML200x, 
                                       ID_DUNE_VIEW_NODE_TOOLBAR_VRML200X,
                                       "NodeToolbarVRML200x");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbarVRML200xEnabled = false;
    else
        _nodeToolbarVRML200xEnabled = TheApp->GetBoolPreference(
                                      "NodeToolbarVRML200x", false);
    _toolbarWindow->ShowToolbar(_nodeToolbarVRML200x, 
                                _nodeToolbarVRML200xEnabled);

    _nodeToolbarX3DComponents1 = LoadToolbar(_toolbarWindow, idb_node_icons,
                                     ARRAYSIZE(buttonsX3DComponents1),
                                     buttonsX3DComponents1, 
                                     ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_1,
                                     "NodeToolbarX3DComponents1");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbarX3DComponents1Enabled = false;
    else
        _nodeToolbarX3DComponents1Enabled = TheApp->GetBoolPreference(
                                            "NodeToolbarX3DComponents1", false);
     _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents1, 
                                 _nodeToolbarX3DComponents1Enabled);


    _nodeToolbarX3DComponents2 = LoadToolbar(_toolbarWindow, idb_node_icons,
                                     ARRAYSIZE(buttonsX3DComponents2),
                                     buttonsX3DComponents2, 
                                     ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_2,
                                     "NodeToolbarX3DComponents2");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbarX3DComponents2Enabled = false;
    else
        _nodeToolbarX3DComponents2Enabled = TheApp->GetBoolPreference(
                                            "NodeToolbarX3DComponents2", false);
     _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents2, 
                                 _nodeToolbarX3DComponents2Enabled);

    _nodeToolbarX3DComponents3 = LoadToolbar(_toolbarWindow, idb_node_icons,
                                     ARRAYSIZE(buttonsX3DComponents3),
                                     buttonsX3DComponents3, 
                                     ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_3,
                                     "NodeToolbarX3DComponents3");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbarX3DComponents3Enabled = false;
    else
        _nodeToolbarX3DComponents3Enabled = TheApp->GetBoolPreference(
                                            "NodeToolbarX3DComponents3", false);
     _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents3, 
                                 _nodeToolbarX3DComponents3Enabled);

    _nodeToolbarX3DComponents4 = LoadToolbar(_toolbarWindow, idb_node_icons,
                                     ARRAYSIZE(buttonsX3DComponents4),
                                     buttonsX3DComponents4, 
                                     ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_4,
                                     "NodeToolbarX3DComponents4");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbarX3DComponents4Enabled = false;
    else
        _nodeToolbarX3DComponents4Enabled = TheApp->GetBoolPreference(
                                            "NodeToolbarX3DComponents4", false);
     _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents4, 
                                 _nodeToolbarX3DComponents4Enabled);

    _nodeToolbarCover = LoadToolbar(_toolbarWindow, idb_node_icons,
                                    ARRAYSIZE(buttonsCover), 
                                    buttonsCover, 
                                    ID_DUNE_VIEW_NODE_TOOLBAR_COVER,
                                    "NodeToolbarCover");
    if (TheApp->is4Kids() || TheApp->is4Catt() || !TheApp->getCoverMode()) 
        _nodeToolbarCoverEnabled = false;
    else
        _nodeToolbarCoverEnabled = TheApp->GetBoolPreference("NodeToolbarCover",
                                                             !olpc);
    _toolbarWindow->ShowToolbar(_nodeToolbarCover, _nodeToolbarCoverEnabled);

    _nodeToolbarKambi = LoadToolbar(_toolbarWindow, idb_node_icons,
                                    ARRAYSIZE(buttonsKambi), 
                                    buttonsKambi, 
                                    ID_DUNE_VIEW_NODE_TOOLBAR_KAMBI,
                                    "NodeToolbarKambi");
    if (TheApp->is4Kids() || TheApp->is4Catt() || !TheApp->getKambiMode())
        _nodeToolbarKambiEnabled = false;
    else
        _nodeToolbarKambiEnabled = TheApp->GetBoolPreference("NodeToolbarKambi",
                                                             !olpc);
    _toolbarWindow->ShowToolbar(_nodeToolbarKambi, _nodeToolbarKambiEnabled);

    _nodeToolbarScripted = LoadToolbar(_toolbarWindow, idb_node_icons,
                                       ARRAYSIZE(buttonsScripted),
                                       buttonsScripted, 
                                       ID_DUNE_VIEW_NODE_TOOLBAR_SCRIPTED,
                                       "NodeToolbarScripted");
    if (TheApp->is4Kids() || TheApp->is4Catt())
        _nodeToolbarScriptedEnabled = false;
    else
        _nodeToolbarScriptedEnabled = TheApp->GetBoolPreference(
                                      "NodeToolbarScripted", false);
    _toolbarWindow->ShowToolbar(_nodeToolbarScripted, 
                                _nodeToolbarScriptedEnabled);
    _outerPane->Layout();

    int idb_vcr_toolbar = IDB_VCR_TOOLBAR;
    if (TheApp->getBlackAndWhiteIcons())
        idb_vcr_toolbar = IDB_VCR_TOOLBAR_BW;
    _vcrToolbar = LoadToolbar(_toolbarWindow2, idb_vcr_toolbar,
                              ARRAYSIZE(vcrButtons) / 2, vcrButtons,
                              ID_DUNE_VIEW_PLAY_TOOLBAR, "PlayToolbar");
    _outerPane->SetPane(_toolbarWindow, PW_TOP);
    _outerPane->SetPane(_toolbarWindow2, PW_BOTTOM);
    _outerPane->SetPane(_innerPane, PW_CENTER);

    _fullScreen_enabled = TheApp->GetBoolPreference("FullScreen", false);
    swMenuSetFlags(_menu, ID_DUNE_VIEW_FULL_SCREEN, SW_MENU_RADIO_ITEM, 0);
    swMenuSetFlags(_menu, ID_DUNE_VIEW_FULL_SCREEN, SW_MENU_CHECKED, 0);

    scene->setSelection(scene->getRoot());

    _colorCircle_enabled = false;
    _colorCircle_active = false;
    _colorCircleHint = NULL;
    setColorCircleIcon();
    _objectEdit_enabled = false;
    _urlEdit_enabled = false;
    setXSymetricNurbsIcon();
    _navigation_mouse_active = false;
    _scene->setMouseNavigationMode(_navigation_mouse_active);
    _navigation_input_device_active = false;
    _scene->setInputDeviceNavigationMode(_navigation_input_device_active);

    swMenuSetFlags(_menu, ID_EXAMINE_MOUSE_MODE, SW_MENU_RADIO_ITEM, 
                   SW_MENU_RADIO_ITEM);
    swMenuSetFlags(_menu, ID_FLY_MOUSE_MODE, SW_MENU_RADIO_ITEM, 
                   SW_MENU_RADIO_ITEM);
    swMenuSetFlags(_menu, ID_WALK_MOUSE_MODE, SW_MENU_RADIO_ITEM, 
                   SW_MENU_RADIO_ITEM);
    swMenuSetFlags(_menu, ID_ROLL_MOUSE_MODE, SW_MENU_RADIO_ITEM, 
                   SW_MENU_RADIO_ITEM);

    swMenuSetFlags(_menu, ID_MOVE_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
    swMenuSetFlags(_menu, ID_ROTATE_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
    swMenuSetFlags(_menu, ID_SCALE_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
    swMenuSetFlags(_menu, ID_UNIFORM_SCALE_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
    swMenuSetFlags(_menu, ID_CENTER_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);

    if (TheApp->getMaxNumberAxesInputDevices()>4) {
       swMenuSetFlags(_menu, ID_6DLOCAL_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
       swMenuSetFlags(_menu, ID_6D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
    } else {
       swMenuSetFlags(_menu, ID_6DLOCAL_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
       swMenuSetFlags(_menu, ID_6D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
    }

    if (TheApp->getMaxNumberAxesInputDevices()>=3)
       swMenuSetFlags(_menu, ID_ROCKET_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
    else
       swMenuSetFlags(_menu, ID_ROCKET_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);

    if (TheApp->getMaxNumberAxesInputDevices()>=2) 
       {
       swMenuSetFlags(_menu, ID_HOVER_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
       swMenuSetFlags(_menu, ID_3D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
       swMenuSetFlags(_menu, ID_2D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
       swMenuSetFlags(_menu, ID_1D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
       }
    else
       {
       swMenuSetFlags(_menu, ID_HOVER_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
       swMenuSetFlags(_menu, ID_3D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
       swMenuSetFlags(_menu, ID_2D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
       swMenuSetFlags(_menu, ID_1D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
       }
    swMenuSetFlags(_menu, ID_RECALIBRATE, SW_MENU_DISABLED, 0);
       
    setTMode(_scene->getTransformMode()->tmode);
    setTDimension(_scene->getTransformMode()->tdimension);

    if (TheApp->has2AxesInputDevices() || TheApp->has3AxesInputDevices()) {
       swMenuSetFlags(_menu, ID_NEAR_FAR_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
       swMenuSetFlags(_menu, ID_UP_DOWN_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
    } else {
       swMenuSetFlags(_menu, ID_NEAR_FAR_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
       swMenuSetFlags(_menu, ID_UP_DOWN_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
    }      

    setT2axes(_scene->getTransformMode()->t2axes);

    swMenuSetFlags(_menu, ID_DUNE_FILE_EXPORT_VRML97_COVER, SW_MENU_DISABLED, 
                   TheApp->getCoverMode() ? 0 : SW_MENU_DISABLED);

    swToolbarSetButtonFlags(_standardToolbar, _fileNewX3dIconPos, 
                            SW_TB_DISABLED, 
                            TheApp->getCoverMode() ? SW_TB_DISABLED : 0);
    swMenuSetFlags(_menu, ID_DUNE_FILE_EXPORT_X3DV, SW_MENU_DISABLED, 
                   TheApp->getCoverMode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_DUNE_FILE_EXPORT_X3D_XML, SW_MENU_DISABLED, 
                   TheApp->getCoverMode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_DUNE_FILE_EXPORT_X3D_4_WONDERLAND, 
                   SW_MENU_DISABLED, 
                   TheApp->getCoverMode() ? SW_MENU_DISABLED : 0);

    _xOnly = false;
    _yOnly = false;
    _zOnly = false;
    _scene->setXonly(_xOnly);
    _scene->setYonly(_yOnly);
    _scene->setZonly(_zOnly);

    _scriptEdit = NULL;
    _scriptEditorInUse = false;
    _shaderEdit = NULL;
    _textEditorInUse = false;
    _imageTextureEdit = NULL;
    _pixelTextureEdit = NULL;
    _imageEditorInUse = false;
    _soundEdit = NULL;
    _soundEditorInUse = false;
    _movieEdit = NULL;
    _movieEditorInUse = false;
    _selectedField = -1;
    _statusText[0] = 0;
    _searchText = "";

    scene->UpdateViews(this, UPDATE_ALL, NULL);

    UpdateToolbar(ID_DUNE_FILE_UPLOAD);
    UpdateToolbar(ID_SKIP_MATERIAL_NAME_BEFORE_FIRST_UNDERSCORE);        
    UpdateToolbar(ID_SKIP_MATERIAL_NAME_AFTER_LAST_UNDERSCORE);        

    if (TheApp->GetBoolPreference("MaximizeWindows", false)) {
        Layout(true);
        swMaximizeWindow(_wnd);
    } else 
        Layout();

    _scene->getRoot()->doWithBranch(searchVrmlCut, this);
    UpdateTitle();

    InitToolbars();
    UpdateToolbars();

    // the following method of updating cover or kambi nodes are only needed 
    // once, because the commandlineoptions -cover or -kambi are the only 
    // way to enable covermode or kambimode
    UpdateStaticMenuCoverNodes();
    UpdateStaticMenuKambiNodes();

    UpdateToolbarSelection();

    swShowWindow(_wnd);
    if (_fullScreen_enabled)
        ToggleFullScreen();
}

void
MainWindow::destroyMainWindow(void) // but keep scene
{
    Stop();
    TheApp->SetBoolPreference("MaximizeWindows", swIsMaximized(_wnd) != 0);
    delete _treeView;
    delete _S3DView;
    delete _fieldView;
    delete _graphView;
    delete _channelView;
    delete _toolbarWindow;
    delete _toolbarWindow2;
    delete _innerPane;
    delete _outerPane;
    delete _statusBar;
    delete _colorCircleHint;
}


MainWindow::~MainWindow()
{
    destroyMainWindow();
    delete _scene;
    swDestroyWindow(_parentWindow);
}

void
MainWindow::UpdateTitle()
{
    MyString title = "Dune ";
    const char *path = _scene->getPath();

    if (TheApp->canQuadBufferStereo())
        title += "(stereo visual)";
    else
        title += "(no stereo visual)";
    if (TheApp->getCoverMode())
        title += " (cover mode)"; 
    if (TheApp->getKambiMode())
        title += " (kambi mode)"; 
    title += " : ";
    if (path[0]) {
        title += path;
    } else {
        title += "Untitled";
    }

    swSetTitle(_wnd, title);
}

#ifdef HAVE_SAND
void MainWindow::OnSANDExport(void)
{
    char path[1024];
    path[0] = '\0';
    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir());
    if (swSaveFileDialog(_wnd, "Save As",
        "The Nebula Device TCL Script (.tcl)\0*.tcl;*.TCL\0All Files (*.*)\0*.*\0\0",
        path, 1024,".tcl")) {
        _nebulaExporter.ExportScene(path, _scene, _statusBar);
    }
}
#endif   //  #ifdef HAVE_SAND

// callbacks for MainWindow::doWithBranch(callback, data)

template<class NormalNode> void removeNormalsTemplate(NormalNode node)
{ 
    NormalNode normalNode = (NormalNode) node;
    Node *nnormal = normalNode->normal()->getValue();
    if (nnormal != NULL) {
        MoveCommand *command = new MoveCommand(nnormal, normalNode, 
                                               normalNode->normal_Field(), 
                                               NULL, -1);
        command->execute();
    }
}

static bool removeNormals(Node *node, void *data)
{
    if (node->getType() == VRML_INDEXED_FACE_SET) {
        NodeIndexedFaceSet *faceSet = (NodeIndexedFaceSet *) node;
        removeNormalsTemplate(faceSet);
        if (faceSet->normalIndex()->getSize()>0)
            faceSet->normalIndex(new MFInt32());
    } else if (node->getType() == VRML_ELEVATION_GRID)
        removeNormalsTemplate((NodeElevationGrid *) node);
    return true;     
}

template<class TexCoordNode> void removeTexCoordTemplate(TexCoordNode node)
{ 
    TexCoordNode texCoordNode = (TexCoordNode) node;
    Node *ntexCoord = texCoordNode->texCoord()->getValue();
    if (ntexCoord != NULL) {
        MoveCommand *command = new MoveCommand(ntexCoord, texCoordNode, 
                                               texCoordNode->texCoord_Field(), 
                                               NULL, -1);
        command->execute();
    }
}

static bool removeTextureCoordinates(Node *node, void *data)
{
    if (node->getType() == VRML_INDEXED_FACE_SET) {
        NodeIndexedFaceSet *faceSet = (NodeIndexedFaceSet *) node;
        removeTexCoordTemplate(faceSet);
        if (faceSet->texCoordIndex()->getSize()>0)
           faceSet->texCoordIndex(new MFInt32());
    } else if (node->getType() == VRML_ELEVATION_GRID)
        removeTexCoordTemplate((NodeElevationGrid *) node);
    else if (node->getType() == VRML_NURBS_SURFACE)
        removeTexCoordTemplate((NodeNurbsSurface *) node);
    else if (node->getType() == DUNE_SUPER_ELLIPSOID)
        removeTexCoordTemplate((NodeSuperEllipsoid *) node);
    return true;     
}

template<class ColorNode> void removeColorTemplate(ColorNode node)
{ 
    ColorNode colorNode = (ColorNode) node;
    Node *ncolor = colorNode->color()->getValue();
    if (ncolor != NULL) {
        MoveCommand *command = new MoveCommand(ncolor, colorNode, 
                                               colorNode->color_Field(), 
                                               NULL, -1);
        command->execute();
    }
}

static bool removeColors(Node *node, void *data)
{
    if (node->getType() == VRML_INDEXED_FACE_SET) {
        NodeIndexedFaceSet *faceSet = (NodeIndexedFaceSet *) node;
        removeColorTemplate(faceSet);
        if (faceSet->colorIndex()->getSize()>0)
           faceSet->colorIndex(new MFInt32());
    } else if (node->getType() == VRML_INDEXED_LINE_SET) {
        NodeIndexedLineSet *lineSet = (NodeIndexedLineSet *) node;
        removeColorTemplate(lineSet);
        if (lineSet->colorIndex()->getSize()>0)
           lineSet->colorIndex(new MFInt32());
    } else if (node->getType() == VRML_POINT_SET) {
        NodePointSet *pointSet = (NodePointSet *) node;
        removeColorTemplate(pointSet);
    } else if (node->getType() == VRML_ELEVATION_GRID)
        removeColorTemplate((NodeElevationGrid *) node);
    return true;     
}

static bool removeTexture(Node *node, void *data)
{
    if ((node->getType() == VRML_APPEARANCE) ||
        (node->getType() == KAMBI_KAMBI_APPEARANCE)) {
        NodeAppearance *appearanceNode = (NodeAppearance *) node;
        Node *ntexture = appearanceNode->texture()->getValue();
        if (ntexture != NULL) {
            MoveCommand *command = new MoveCommand(ntexture, 
                  appearanceNode, appearanceNode->texture_Field(), NULL, -1);
            command->execute();
        }
    }
    return true;     
}

static bool removeAppearance(Node *node, void *data)
{
    if (node->getType() == VRML_SHAPE) {
        NodeShape *shapeNode = (NodeShape *) node;
        Node *nappearance = shapeNode->appearance()->getValue();
        if (nappearance != NULL) {
            MoveCommand *command = new MoveCommand(nappearance, 
                  shapeNode, shapeNode->appearance_Field(), NULL, -1);
            command->execute();
        }
    }
    return true;     
}

static bool removeMaterial(Node *node, void *data)
{
    if ((node->getType() == VRML_APPEARANCE) ||
        (node->getType() == KAMBI_KAMBI_APPEARANCE)) {
        NodeAppearance *appearanceNode = (NodeAppearance *) node;
        Node *nmaterial = NULL;
        if (appearanceNode)
            nmaterial = appearanceNode->material()->getValue();
        if (nmaterial != NULL) {
            MoveCommand *command = new MoveCommand(nmaterial, 
                  appearanceNode, appearanceNode->material_Field(), NULL, -1);
            command->execute();
        }
    }
    return true;     
}

static bool removeDefName(Node *node, void *data)
{
    if (node->hasName()) 
        if ((!node->hasInputs()) && (!node->hasOutputs())) {
            // ignore nodes with routes
            node->setName("");
            NodeUpdate *hint= new NodeUpdate(node, NULL, 0);
            node->getScene()->UpdateViews(NULL, UPDATE_NODE_NAME, (Hint*) hint);
        }
    return true;     
}

class searchData {
public:
    searchData(const char* c, Scene *s) {
        compare = c;
        scene = s;
    }
    const char* compare;
    Scene *scene;
};

static bool searchNode(Node *node, void *data)
{
    const char *searchString = ((searchData *)data)->compare;
    const char *compareString = NULL;
    if (node->hasName()) 
        compareString = node->getName();
    if (compareString != NULL)
        if (strstr(compareString, searchString) != NULL) {
            ((searchData *)data)->scene->setSelection(node);
            ((searchData *)data)->scene->UpdateViews(NULL, UPDATE_SELECTION);
            return false;
        }
    compareString = node->getProto()->getName(node->getScene()->isX3d());
    if (compareString != NULL)
        if (strstr(compareString, searchString) != NULL) {
            ((searchData *)data)->scene->setSelection(node);
            ((searchData *)data)->scene->UpdateViews(NULL, UPDATE_SELECTION);
            return false;
        }
    return true;     
}

static bool getAllNodes(Node *node, void *data)
{
    NodeArray *nodeArray = (NodeArray *) data;
    nodeArray->append(node);
    return true;     
}

// validate callback for OneText dialog

static bool textValidate(MyString text)
{
    return true;
}

void
MainWindow::OnCommand(int id)
{
    _statusText[0] = 0;
    switch (id) {
      case ID_DUNE_FILE_OPEN:
        OnFileOpen();
        break;
      case ID_DUNE_FILE_IMPORT:
        OnFileImport();
        _scene->getRoot()->doWithBranch(searchVrmlCut, NULL);
        UpdateToolbars();
        break;
      case ID_DUNE_FILE_NEW:
        if (isEditorInUse(true))
            return;
        _vrmlCutNode = NULL;
        UpdateToolbars();
        TheApp->OnFileNew();
        break;
      case ID_DUNE_FILE_NEW_X3DV:
        if (isEditorInUse(true))
            return;
        _vrmlCutNode = NULL;
        UpdateToolbars();
        TheApp->OnFileNew(true);
        break;
      case ID_DUNE_FILE_NEW_WINDOW:
        TheApp->OnFileNewWindow();
        break;
      case ID_DUNE_FILE_PREVIEW:
        TheApp->OnFilePreview(_scene);
        break;
      case ID_DUNE_FILE_SAVE:
        OnFileSave();
        break;
      case ID_DUNE_FILE_SAVE_AS:
        OnFileSaveAs(_scene->isX3dv() ? X3DV : 0);
        break;
      case ID_DUNE_FILE_EXPORT_X3D_XML:
        OnFileExportX3DXML();
        break;
      case ID_DUNE_FILE_EXPORT_X3D_4_WONDERLAND:
        OnFileExportX3D4Wonderland();
        break;
      case ID_DUNE_FILE_EXPORT_VRML97:
        OnFileExportVRML97();
        break;
      case ID_DUNE_FILE_EXPORT_X3DV:
        OnFileExportX3DV();
        break;
      case ID_DUNE_FILE_EXPORT_VRML97_COVER:
        OnFileExportCover();
        break;
      case ID_DUNE_FILE_EXPORT_KANIM:
        OnFileExportKanim();
        break;
      case ID_DUNE_FILE_EXPORT_C_SOURCE:
        OnFileExportC();
        break;
      case ID_DUNE_FILE_EXPORT_CC_SOURCE:
        OnFileExportCC();
        break;
      case ID_DUNE_FILE_EXPORT_JAVA_SOURCE:
        OnFileExportJava();
        break;
      case ID_DUNE_FILE_EXPORT_WONDERLAND_5_MODULE:
        OnFileExportWonderlandModule();
        break;
      case ID_DUNE_FILE_EXPORT_AC3D:
        OnFileExportAc3d();
        break;
      case ID_DUNE_FILE_EXPORT_AC3D_4_RAVEN:
        OnFileExportAc3d4Raven();
        break;
      case ID_DUNE_FILE_EXPORT_GEO_CATT:
        OnFileExportCattGeo();
        break;
      case ID_DUNE_FILE_EXPORT_LDRAW_DAT:
        OnFileExportLdrawDat();
        break;
      case ID_DUNE_FILE_CLOSE:
        if (isEditorInUse(true))
            return;
        _scene->setUpdateViewsSelection(false);
        TheApp->OnFileClose(this);
        break;
      case ID_DUNE_FILE_TEXT_EDIT:
        if (isEditorInUse(true))
            return;
        _scene->setUpdateViewsSelection(false);
        TheApp->OnFileEdit(this,_scene);
        break;
      case ID_DUNE_FILE_UPLOAD:
        if (!TheApp->hasUpload())
            return;
        TheApp->OnFileUpload(_scene);
        break;
      case ID_DUNE_APP_EXIT:
        if (isEditorInUse(true))
            return;
        _scene->setUpdateViewsSelection(false);
        TheApp->OnFileExit();
        break;

      case ID_DUNE_EDIT_CUT:
#ifdef HAVE_CUT
        OnEditCut();
#endif
        break;
      case ID_DUNE_EDIT_COPY:
        OnEditCopy();
        break;
      case ID_DUNE_EDIT_COPY_BRANCH_TO_ROOT:
        OnEditCopyBranchToRoot();
        break;
      case ID_DUNE_EDIT_PASTE:
        OnEditPaste();
        break;
      case ID_DUNE_EDIT_DELETE:
        OnEditDelete();
        break;
      case ID_DUNE_EDIT_UNDO:
        if (_scene->canUndo()) _scene->undo();
        _scene->setSelection(_scene->getRoot());
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
        break;
      case ID_DUNE_EDIT_REDO:
        if (_scene->canRedo()) _scene->redo();
        _scene->setSelection(_scene->getRoot());
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
        break;
      case ID_DUNE_EDIT_DEF:
          {
            Node *selection = _scene->getSelection()->getNode();
            if (selection->getType() == VRML_COMMENT)
                break;
            if (selection != _scene->getRoot()) {
                if (TheApp->getCoverMode()) {
                    CoverDefDialog dlg(_wnd, _scene);
                    dlg.DoModal();
                } else {
                    DefDialog dlg(_wnd, _scene);
                    dlg.DoModal();
                }
                _scene->UpdateViews(NULL, UPDATE_SELECTION_NAME);
            }
          }
        break;
      case ID_DUNE_EDIT_USE:
          {
            Node *selectionNode = _scene->getSelection()->getNode();
            int selectionField = _scene->getSelection()->getField();
            if (_scene->canUse(selectionNode, selectionField))
                if (!_scene->use(selectionNode, selectionField))
                    TheApp->MessageBoxId(IDS_RESCURSIVE_USE);
          }
        break;
      case ID_DUNE_EDIT_FIND:
        OnEditFind();
        break;
      case ID_DUNE_EDIT_FIND_AGAIN:
        OnEditFindAgain();
        break;

      case ID_ANIMATION:
        CreateAnimation();
        break;
      case ID_INTERACTION:
        CreateInteraction();
        break;

      case ID_TWO_SIDED:
        {
        Node *node = _scene->getSelection()->getNode();
        node->toggleDoubleSided();
        UpdateToolbars();
        NodeUpdate *hint= new NodeUpdate(node, NULL, 0);
        _scene->UpdateViews(NULL, UPDATE_SOLID_CHANGED, (Hint*) hint);
        _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);
        }
        break;
      case ID_CHANGE_SIDE:
        _scene->getSelection()->getNode()->flipSide();
        _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);
        break;
      case ID_SKIP_MATERIAL_NAME_AFTER_LAST_UNDERSCORE:
      case ID_SKIP_MATERIAL_NAME_BEFORE_FIRST_UNDERSCORE:
        toogleMaterialName(id);
        break;
      case ID_HANDLE_SCALE:
        HandleScale();
        break;
      case ID_HANDLE_SIZE:
        HandleSize();
        break;
      case ID_HANDLE_EPSILON:
        HandleEpsilon();
        break;

      case ID_X_SYMETRIC:
        if (TheApp->GetXSymetricMode())
           TheApp->SetXSymetricMode(false);
        else
           TheApp->SetXSymetricMode(true);
        setXSymetricNurbsIcon();
        break;
      case ID_OBJECT_EDIT:
        EditObject();
        break;
      case ID_URL_EDIT:
        EditUrl();
        break;
      case ID_CHANGE_ENABLE_ANIMATION:
        changeEnableAnimation();
        break;
      case ID_CHANGE_DISABLE_ANIMATION:
        changeDisableAnimation();
        break;
      case ID_CHANGE_ANIMATION_TIME:
        changeAnimationTime();
        break;
      case ID_CHANGE_MATERIAL_DIFFUSE:
        showDiffuseColorCircle();
        break;
      case ID_CHANGE_MATERIAL_EMISSIVE:
        showEmissiveColorCircle();
        break;
      case ID_CHANGE_MATERIAL_SPECULAR:
        showSpecularColorCircle();
        break;
      case ID_CHANGE_MATERIAL_TRANSPARENCY:
        changeTransparency();
        break;
      case ID_CHANGE_MATERIAL_SHININESS:
        changeShininess();
        break;
      case ID_CHANGE_IMAGE_REPEAT:
        changeImageRepeat();
        break;
      case ID_CREATE_AT_ZERO_X:
        ToggleCreateAtZero(0);
        break;
      case ID_CREATE_AT_ZERO_Y:
        ToggleCreateAtZero(1);
        break;
      case ID_CREATE_AT_ZERO_Z:
        ToggleCreateAtZero(2);
        break;
      case ID_NEW_ONE_TEXT:
        createOneText();
        break;
      case ID_CHANGE_ONE_TEXT:
        changeOneText();
        break;

      case ID_MOVE_SIBLING_UP:
        moveSiblingUp();
        break;
      case ID_MOVE_SIBLING_DOWN:
        moveSiblingDown();
        break;
      case ID_MOVE_SIBLING_FIRST:
        moveSiblingFirst();
        break;
      case ID_MOVE_SIBLING_LAST:
        moveSiblingLast();
        break;

      case ID_BRANCH_TO_PARENT:
        moveBranchToParent();
        break;
      case ID_BRANCH_TO_TRANSFORM_SELECTION:
        moveBranchToTransformSelection();
        break;
      case ID_BRANCH_TO_GROUP:
        moveBranchTo("Group", "children");
        break;
      case ID_BRANCH_TO_TRANSFORM:
        moveBranchTo("Transform", "children");
        break;
      case ID_BRANCH_TO_COLLISION:
        moveBranchTo("Collision", "children");
        break;
      case ID_BRANCH_TO_COLLISIONPROXY:
        moveBranchTo("Collision", "proxy");
        break;
      case ID_BRANCH_TO_ANCHOR:
        moveBranchTo("Anchor", "children");
        break;
      case ID_BRANCH_TO_BILLBOARD:
        moveBranchTo("Billboard", "children");
        break;
      case ID_BRANCH_TO_LOD   :
        moveBranchTo("LOD", "level");
        break;
      case ID_BRANCH_TO_SWITCH:
        moveBranchTo("Switch", "choice");
        break;
      case ID_BRANCH_TO_INLINE:
        moveBranchToInline();
        break;
      case ID_BRANCH_TO_COLLISION_SPACE:
        moveBranchTo("CollisionSpace", "collidables");
        break;

      case ID_BRANCH_CREATE_NORMAL:
        _scene->branchCreateNormals(_scene->getSelection()->getNode());
        break;
      case ID_BRANCH_CREATE_TEXTURE_COORDINATE:
        _scene->branchCreateTextureCoordinates(
              _scene->getSelection()->getNode());
        break;
      case ID_BRANCH_CREATE_TEXTURE:
        createBranchImageTexture();
        break;
      case ID_BRANCH_CREATE_MATERIAL:
        createBranchMaterial();
        break;
      case ID_BRANCH_CREATE_APPEARANCE:
        createBranchAppearance();
        break;
      case ID_BRANCH_SET_FLIP_SIDE:
        setBranchFlipSide();
        break;
      case ID_BRANCH_SET_CONVEX:
        setBranchConvex();
        break;
      case ID_BRANCH_SET_SOLID:
        setBranchSolid();
        break;
      case ID_BRANCH_SET_TWO_SIDED:
        setBranchTwoSided();
        break;
      case ID_BRANCH_SET_CREASE_ANGLE:
        setBranchCreaseAngle();
        break;
      case ID_BRANCH_SET_TRANSPARENCY:
        setBranchTransparency();
        break;
      case ID_BRANCH_SET_SHININESS:
        setBranchShininess();
        break;
      case ID_BRANCH_CONVERT_TO_TRIANGLESET:
        branchConvertToTriangleSetUpdate();
        break;
      case ID_BRANCH_CONVERT_TO_INDEXED_TRIANGLESET:
        branchConvertToIndexedTriangleSetUpdate();
        break;
      case ID_BRANCH_CONVERT_TO_INDEXED_FACESET:
        branchConvertToIndexedFaceSetUpdate();
        break;
      case ID_BRANCH_REMOVE_NORMAL:
        doWithBranchUpdate(removeNormals, NULL);
        break;
      case ID_BRANCH_REMOVE_TEXTURE_COORDINATE:
        doWithBranchUpdate(removeTextureCoordinates, NULL);
        break;
      case ID_BRANCH_REMOVE_COLOR:
        doWithBranchUpdate(removeColors, NULL);
        break;
      case ID_BRANCH_REMOVE_TEXTURE:
        doWithBranchUpdate(removeTexture, NULL);
        break;
      case ID_BRANCH_REMOVE_MATERIAL:
        doWithBranchUpdate(removeMaterial, NULL);
        break;
      case ID_BRANCH_REMOVE_APPEARANCE:
        doWithBranch(removeAppearance, NULL);
        break;
      case ID_BRANCH_REMOVE_DEF_NAME:
        doWithBranch(removeDefName, NULL);
        _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);
        break;
      case ID_BRANCH_REMOVE_NODE:
        removeBranchNode();
        break;
      case ID_BRANCH_FIELD_PIPE:
        branchFieldPipe();
        break;
      case ID_BRANCH_BUILD_RIGID_BODY_COLLECTION:
        branchBuildRigidBodyCollection();
        break;
      case ID_BRANCH_COUNT_POLYGONS:
        countPolygons();
        break;
      case ID_BRANCH_COUNT_POLYGONS_4_CATT:
        countPolygons4catt();
        break;
      case ID_CENTER_TO_MID:
        centerToMid();
        break;
      case ID_CENTER_TO_MINX:
        centerToMin(0);
        break;
      case ID_CENTER_TO_MINY:
        centerToMin(1);
        break;
      case ID_CENTER_TO_MINZ:
        centerToMin(2);
        break;
      case ID_CENTER_TO_MAXX:
        centerToMax(0);
        break;
      case ID_CENTER_TO_MAXY:
        centerToMax(1);
        break;
      case ID_CENTER_TO_MAXZ:
        centerToMax(2);
        break;
      case ID_ARRAY:
        InsertArray();
        break;
      case ID_FLIP_X:
        flip(0);
        break;
      case ID_FLIP_Y:
        flip(1);
        break;
      case ID_FLIP_Z:
        flip(2);
        break;
      case ID_SWAP_XY:
        swap(SWAP_XY);
        break;
      case ID_SWAP_XZ:
        swap(SWAP_XZ);
        break;
      case ID_SWAP_YZ:
        swap(SWAP_YZ);
        break;
      case ID_SET_DEFAULT:
        setDefault();
        break;
      case ID_FLATTEN_X:
        flatten(0);
        break;
      case ID_FLATTEN_Y:
        flatten(1);
        break;
      case ID_FLATTEN_Z:
        flatten(2);
        break;
      case ID_FLATTEN_X_0:
        flatten(0, true);
        break;
      case ID_FLATTEN_Y_0:
        flatten(1, true);
        break;
      case ID_FLATTEN_Z_0:
        flatten(2, true);
        break;
      case ID_REMOVE_ILLEGAL_NODES:
        removeIllegalNodes();
        break;
      case ID_SET_OPTIMIZE:
        optimizeSet();
        break;
      case ID_TRIANGULATE:
        triangulate();
        break;
      case ID_DEGREE_ELEVATE_UP:
        degreeElevate(1);
        break;
      case ID_DEGREE_ELEVATE_DOWN:            
        degreeElevate(-1);
        break;
      case ID_U_DEGREE_ELEVATE_UP:            
        uDegreeElevate(1);
        break;
      case ID_U_DEGREE_ELEVATE_DOWN:
        uDegreeElevate(-1);
        break;
      case ID_V_DEGREE_ELEVATE_UP:  
        vDegreeElevate(1);
        break;
      case ID_V_DEGREE_ELEVATE_DOWN:
        vDegreeElevate(-1);
        break;
      case ID_LINEAR_UKNOT:
        linearUknot();
        break;
      case ID_LINEAR_VKNOT:
        linearVknot();
        break;
      case ID_PIPE:
        pipeField();
        break;
      case ID_TIME_SHIFT:
        timeShift();
        break;
      case ID_COLOR_CIRCLE:
        updateColorCircle();
        break;
      case ID_TOGGLE_XRAY_RENDERING:
        toggleXrayRendering();
        break;
      case ID_SET_URL:
        setPathAllURLs();
        break;
      case ID_SHOW_JOINT_LIKE_HANDLES:
        if (_scene->hasJoints())
            if (_scene->showJoints())
                _scene->setShowJoints(false);
            else
                _scene->setShowJoints(true);
        _scene->UpdateViews(NULL, UPDATE_ALL, NULL);    
        break;

      case ID_TO_NURBS:
      case ID_TO_NURBS_4KIDS:
        toNurbs();
        break;
      case ID_TO_NURBS_CURVE:
        toNurbsCurve();
        break;
      case ID_TO_SUPER_EXTRUSION:
        toSuperExtrusion();
        break;
      case ID_TO_SUPER_REVOLVER:
        toSuperRevolver();
        break;
      case ID_TO_EXTRUSION:
        toExtrusion();
        break;
      case ID_TO_INDEXED_FACESET:
        toIndexedFaceSet();
        break;
      case ID_TO_INDEXED_TRIANGLESET:
        toIndexedTriangleSet();
        break;
      case ID_TO_TRIANGLESET:
        toTriangleSet();
        break;
      case ID_TO_INDEXED_LINESET:
        toIndexedLineSet();
        break;
      case ID_TO_POINTSET:
        toPointSet();
        break;
      case ID_TO_POSITION_INTERPOLATOR:
        toPositionInterpolator();
        break;
      case ID_TO_ORIENTATION_INTERPOLATOR_XZ:
        toOrientationInterpolator(XZ_DIRECTION);
        break;
      case ID_TO_ORIENTATION_INTERPOLATOR_YZ:
        toOrientationInterpolator(YZ_DIRECTION);
        break;
      case ID_TO_ORIENTATION_INTERPOLATOR_XY:
        toOrientationInterpolator(XY_DIRECTION);
        break;

      case ID_MOVE_MODE:
        setTMode(TM_TRANSLATE);
        break;
      case ID_ROTATE_MODE:
        setTMode(TM_ROTATE);
        break;
      case ID_SCALE_MODE:
        setTMode(TM_SCALE);
        break;
      case ID_UNIFORM_SCALE_MODE:
        setTMode(TM_UNIFORM_SCALE);
        break;
      case ID_CENTER_MODE:
        setTMode(TM_CENTER);
        break;
      case ID_6D_MODE:
        setTMode(TM_6D);
        break;
      case ID_6DLOCAL_MODE:
        setTMode(TM_6DLOCAL);
        break;
      case ID_ROCKET_MODE:
        setTMode(TM_ROCKET);
        break;
      case ID_HOVER_MODE:
        setTMode(TM_HOVER);
        break;
      case ID_X_ONLY:
        _xOnly = !_xOnly;
        _scene->setXonly(_xOnly);
        UpdateToolbar(ID_X_ONLY);
        _scene->UpdateViews(NULL, UPDATE_MODE);
        break;
      case ID_Y_ONLY:
        _yOnly = !_yOnly;
        _scene->setYonly(_yOnly);
        UpdateToolbar(ID_Y_ONLY);
        _scene->UpdateViews(NULL, UPDATE_MODE);
        break;
      case ID_Z_ONLY:
        _zOnly = !_zOnly;
        _scene->setZonly(_zOnly);
        UpdateToolbar(ID_Z_ONLY);
        _scene->UpdateViews(NULL, UPDATE_MODE);
        break;
      case ID_3D_MODE:
        setTDimension(TM_3D);
        break;
      case ID_2D_MODE:
        setTDimension(TM_2D);
        break;
      case ID_1D_MODE:
        setTDimension(TM_1D);
        break;
      case ID_NEAR_FAR_MODE:
        setT2axes(TM_NEAR_FAR);
        break;
      case ID_UP_DOWN_MODE:
        setT2axes(TM_UP_DOWN);
        break;
      case ID_INPUTDEVICE_GREATER:
        TheApp->increaseInputDevice(_scene->getTransformMode());
        break;
      case ID_INPUTDEVICE_LESSER:
        TheApp->decreaseInputDevice(_scene->getTransformMode());
        break;
      case ID_INPUT_DEVICE_NAVIGATION_MODE:
        if (_navigation_input_device_active)
           _navigation_input_device_active=false;
        else
           _navigation_input_device_active=true;
        _scene->setInputDeviceNavigationMode(_navigation_input_device_active);
        UpdateToolbar(ID_INPUT_DEVICE_NAVIGATION_MODE);
        break;
      case ID_MOUSE_NAVIGATION_MODE:
        if (_navigation_mouse_active)
           _navigation_mouse_active=false;
        else
           _navigation_mouse_active=true;
        _scene->setMouseNavigationMode(_navigation_mouse_active);
        UpdateToolbar(ID_NAVIGATION_OPERATIONS);
        break;
      case ID_STAND_UP:
        _scene->standUpCamera();
        break;
      
      case ID_EXAMINE_MOUSE_MODE:
        TheApp->SetMouseMode(MOUSE_EXAMINE);
        UpdateToolbar(ID_NAVIGATION_OPERATIONS);
        break;      
      case ID_INCREASE_TURNPOINT:
        _scene->changeTurnPointDistance(2.0f);
        break;
      case ID_DECREASE_TURNPOINT:
        _scene->changeTurnPointDistance(0.5f);
        break;
      case ID_WALK_MOUSE_MODE:
        TheApp->SetMouseMode(MOUSE_WALK);
        UpdateToolbar(ID_NAVIGATION_OPERATIONS);
        break;
      case ID_FLY_MOUSE_MODE:
        TheApp->SetMouseMode(MOUSE_FLY);
        UpdateToolbar(ID_NAVIGATION_OPERATIONS);
        break;
      case ID_ROLL_MOUSE_MODE:
        TheApp->SetMouseMode(MOUSE_ROLL);
        UpdateToolbar(ID_NAVIGATION_OPERATIONS);
        break;
      case ID_RECALIBRATE:
        _scene->recalibrate();
        break;

      case ID_ROUTE_ZOOM_IN:
        _graphView->zoomIn();        
        UpdateToolbars();
        break;
      case ID_ROUTE_ZOOM_OUT:
        _graphView->zoomOut();        
        UpdateToolbars();
        break;
      case ID_ROUTE_UNZOOM:
        _graphView->unZoom();        
        UpdateToolbars();
        break;
      case ID_ROUTE_REBUILD:
        ShowView(PW_TOP, _graphView, ID_DUNE_VIEW_SCENE_GRAPH, "ShowRouteView");
        _graphView->Initialize();
        UpdateToolbars();
        break;
      case ID_ROUTE_MOVE_UP:
        ShowView(PW_TOP, _graphView, ID_DUNE_VIEW_SCENE_GRAPH, "ShowRouteView");
        _graphView->moveToTop(_scene->getSelection()->getNode());
        UpdateToolbars();
        break;
      case ID_ROUTE_MOVE_UP_ROUTES:
        ShowView(PW_TOP, _graphView, ID_DUNE_VIEW_SCENE_GRAPH, "ShowRouteView");
        _graphView->moveRoutesToTop(_scene->getSelection()->getNode());
        UpdateToolbars();
        break;

      case ID_DUNE_VIEW_FULL_SCREEN:
        ToggleFullScreen();
        break;
      case ID_DUNE_VIEW_SCENE_GRAPH:
        ToggleView(PW_TOP, _graphView, ID_DUNE_VIEW_SCENE_GRAPH, 
                   "ShowRouteView");
        UpdateToolbars();
        break;
      case ID_DUNE_VIEW_SCENE_TREE:
        ToggleView(PW_LEFT, _treeView, ID_DUNE_VIEW_SCENE_TREE, 
                   "ShowSceneTree");
        break;
      case ID_DUNE_VIEW_FIELD_VIEW:
        ToggleView(PW_RIGHT, _fieldView, ID_DUNE_VIEW_FIELD_VIEW, 
                   "ShowFieldView");
        break;
      case ID_DUNE_VIEW_FIELD_VIEW_4_KIDS:
        _showNumbers4Kids = !_showNumbers4Kids;
        UpdateNumbers4Kids();
        swMenuSetFlags(_menu, ID_DUNE_VIEW_FIELD_VIEW_4_KIDS, SW_MENU_CHECKED, 
                       _showNumbers4Kids ? SW_MENU_CHECKED : 0);
        break;
      case ID_DUNE_VIEW_CHANNEL_VIEW:
        ToggleView(PW_BOTTOM, _channelView, ID_DUNE_VIEW_CHANNEL_VIEW,
                   "ShowChannelView");
        break;
      case ID_DUNE_VIEW_TOOLBAR:
        ToggleToolbar(_toolbarWindow, _standardToolbar, ID_DUNE_VIEW_TOOLBAR,
                      "StandardToolbar");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_1:
        _nodeToolbar1Enabled = !_nodeToolbar1Enabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbar1, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_1, "NodeToolbar1");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_2:
        _nodeToolbar2Enabled=!_nodeToolbar2Enabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbar2, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_2, "NodeToolbar2");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_3:
        _nodeToolbar3Enabled = !_nodeToolbar3Enabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbar3, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_3, "NodeToolbar3");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_VRML200X:
        _nodeToolbarVRML200xEnabled = !_nodeToolbarVRML200xEnabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbarVRML200x, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_VRML200X, 
                      "NodeToolbarVRML200x");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_1:
        _nodeToolbarX3DComponents1Enabled = !_nodeToolbarX3DComponents1Enabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbarX3DComponents1, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_1, 
                      "NodeToolbarX3DComponents1");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_2:
        _nodeToolbarX3DComponents2Enabled = !_nodeToolbarX3DComponents2Enabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbarX3DComponents2, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_2, 
                      "NodeToolbarX3DComponents2");
        break;
       case ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_3:
        _nodeToolbarX3DComponents3Enabled = !_nodeToolbarX3DComponents3Enabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbarX3DComponents3, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_3, 
                      "NodeToolbarX3DComponents3");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_4:
        _nodeToolbarX3DComponents4Enabled = !_nodeToolbarX3DComponents4Enabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbarX3DComponents4, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_4, 
                      "NodeToolbarX3DComponents4");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_COVER:
        _nodeToolbarCoverEnabled = !_nodeToolbarCoverEnabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbarCover, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_COVER, "NodeToolbarCover");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_KAMBI:
        _nodeToolbarKambiEnabled = !_nodeToolbarKambiEnabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbarKambi, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_KAMBI, "NodeToolbarKambi");
        break;
      case ID_DUNE_VIEW_NODE_TOOLBAR_SCRIPTED:
        _nodeToolbarScriptedEnabled = !_nodeToolbarScriptedEnabled;
        ToggleToolbar(_toolbarWindow, _nodeToolbarScripted, 
                      ID_DUNE_VIEW_NODE_TOOLBAR_SCRIPTED, 
                      "NodeToolbarScripted");
        break;
      case ID_DUNE_VIEW_PLAY_TOOLBAR:
        ToggleToolbar(_toolbarWindow2, _vcrToolbar, ID_DUNE_VIEW_PLAY_TOOLBAR,
                      "PlayToolbar");
        break;
      case ID_DUNE_VIEW_STATUS_BAR:
        ToggleStatusbar();
        break;

      case ID_NEW_ANCHOR:
        CreateNode("Anchor");
        break;
      case ID_NEW_APPEARANCE:
        InsertNode(VRML_APPEARANCE, "Appearance");
        break;
      case ID_NEW_ARC_2D:
        CreateGeometryNode("Arc2D", true);
        break;
      case ID_NEW_ARC_CLOSE_2D:
        CreateGeometryNode("ArcClose2D");
        break;
      case ID_NEW_AUDIO_CLIP:
        InsertAudioClip();
        break;
      case ID_NEW_BACKGROUND:
        CreateNode("Background");
        break;
      case ID_NEW_BALL_JOINT:
        CreateNode("BallJoint");
        break;
      case ID_NEW_BILLBOARD:
        CreateNode("Billboard");
        break;
      case ID_NEW_BOOLEAN_FILTER:
        CreateNode("BooleanFilter");
        break;
      case ID_NEW_BOOLEAN_TOGGLE:
        CreateNode("BooleanToggle");
        break;
      case ID_NEW_BOOLEAN_TRIGGER:
        CreateNode("BooleanTrigger");
        break;
      case ID_NEW_BOOLEAN_SEQUENCER:
        CreateNode("BooleanSequencer");
        break;
      case ID_NEW_BOUNDED_PHYSICS_MODEL:
        InsertNode(PARTICLE_PHYSICS_MODEL_NODE, "BoundedPhysicsModel");
        break;
      case ID_NEW_BOX:
        CreateGeometryNode("Box");
        break;
      case ID_NEW_CAD_ASSEMBLY:
        CreateNode("CADAssembly");
        break;
      case ID_NEW_CAD_FACE:
        InsertNode(PRODUCT_STRUCTURE_CHILD_NODE, "CADFace");
        break;
      case ID_NEW_CAD_LAYER:
        CreateNode("CADLayer");
        break;
      case ID_NEW_CAD_PART:
        CreateNode("CADPart");
        break;
      case ID_NEW_CIRCLE_2D:
        CreateGeometryNode("Circle2D", true);
        break;
      case ID_NEW_CLIP_PLANE:
        CreateNode("ClipPlane");
        break;
      case ID_NEW_COLLIDABLE_OFFSET:
        CreateNode("CollidableOffset");
        break;
      case ID_NEW_COLLIDABLE_SHAPE:
        CreateNode("CollidableShape");
        break;
      case ID_NEW_COLLISION:
        CreateNode("Collision");
        break;
      case ID_NEW_COLLISION_COLLECTION:
        CreateNode("CollisionCollection");
        break;
      case ID_NEW_COLLISION_SENSOR:
        CreateNode("CollisionSensor");
        break;
      case ID_NEW_COLLISION_SPACE:
        CreateNode("CollisionSpace");
        break;
      case ID_NEW_COLOR:
        InsertNode(COLOR_NODE, "Color");
        break;
      case ID_NEW_COLOR_DAMPER:
        CreateNode("ColorDamper");
        break;
      case ID_NEW_COLOR_INTERPOLATOR:
        CreateNode("ColorInterpolator");
        break;
      case ID_NEW_COLOR_RGBA:
        InsertNode(COLOR_NODE, "ColorRGBA");
        break;
      case ID_NEW_COMPOSED_CUBE_MAP_TEXTURE:
        InsertNode(TEXTURE_NODE, "ComposedCubeMapTexture");
        break;
      case ID_NEW_COMPOSED_SHADER:
        InsertNode(SHADER_NODE, "ComposedShader");
        break;
      case ID_NEW_COMPOSED_TEXTURE_3D:
        InsertNode(TEXTURE_NODE, "ComposedTexture3D");
        break;
      case ID_NEW_CONE:
        CreateGeometryNode("Cone");
        break;
      case ID_NEW_CONE_EMITTER:
        InsertNode(PARTICLE_EMITTER_NODE, "ConeEmitter");
        break;
      case ID_NEW_CONTACT:
        CreateNode("Contact");
        break;
      case ID_NEW_CONTOUR_2D:
        InsertNode(VRML_CONTOUR_2D, "Contour2D");
        break;
      case ID_NEW_CONTOUR_POLYLINE_2D:
        if (_scene->isX3d())
            InsertNode(NURBS_CONTROL_CURVE_NODE, "ContourPolyline2D");
        else
            InsertNode(NURBS_CONTROL_CURVE_NODE, "Polyline2D");
        break;
      case ID_NEW_COORDINATE:
        InsertNode(COORDINATE_NODE, "Coordinate");
        break;
      case ID_NEW_COORDINATE_DAMPER:
        CreateNode("CoordinateDamper");
        break;
      case ID_NEW_COORDINATE_DEFORMER:
        CreateNode("CoordinateDeformer");
        break;
      case ID_NEW_COORDINATE_DOUBLE:
        InsertNode(COORDINATE_NODE, "CoordinateDouble");
        break;
      case ID_NEW_COORDINATE_INTERPOLATOR:
        CreateNode("CoordinateInterpolator");
        break;
      case ID_NEW_COORDINATE_INTERPOLATOR_2D:
        CreateNode("CoordinateInterpolator2D");
        break;
      case ID_NEW_CYLINDER:
        CreateGeometryNode("Cylinder");
        break;
      case ID_NEW_CYLINDER_SENSOR:
        CreateNode("CylinderSensor");
        break;
      case ID_NEW_DIRECTIONAL_LIGHT:
        CreateNode("DirectionalLight");
        break;
      case ID_NEW_DIS_ENTITY_MANAGER:
        CreateNode("DISEntityManager");
        break;
      case ID_NEW_DIS_ENTITY_TYPE_MAPPING:
        CreateNode("DISEntityTypeMapping");
        break;
      case ID_NEW_DISK_2D:
        CreateGeometryNode("Disk2D");
        break;
      case ID_NEW_DOUBLE_AXIS_HINGE_JOINT:
        CreateNode("DoubleAxisHingeJoint");
        break;
      case ID_NEW_EASE_IN_EASE_OUT:
        CreateNode("EaseInEaseOut");
        break;
      case ID_NEW_ELEVATION_GRID:
        CreateElevationGrid();
        break;
      case ID_NEW_ESPDU_TRANSFORM:
        CreateNode("EspduTransform");
        break;
      case ID_NEW_EXPLOSION_EMITTER:
        InsertNode(PARTICLE_EMITTER_NODE, "ExplosionEmitter");
        break;
      case ID_NEW_EXTRUSION:
        CreateGeometryNode("Extrusion");
        break;
      case ID_NEW_FILL_PROPERTIES:
        InsertNode(X3D_FILL_PROPERTIES, "FillProperties");
        break;
      case ID_NEW_FLOAT_VERTEX_ATTRIBUTE:
        InsertNode(VERTEX_ATTRIBUTE_NODE, "FloatVertexAttribute");
        break;
      case ID_NEW_FOG:
        CreateNode("Fog");
        break;
      case ID_NEW_FOG_COORDINATE:
        InsertNode(X3D_FOG_COORDINATE, "FogCoordinate");
        break;
      case ID_NEW_FONT_STYLE:
        InsertNode(FONT_STYLE_NODE, "FontStyle");
        break;
      case ID_NEW_FORCE_PHYSICS_MODEL:
        InsertNode(PARTICLE_PHYSICS_MODEL_NODE, "ForcePhysicsModel");
        break;
      case ID_NEW_GENERATED_CUBE_MAP_TEXTURE:
        InsertNode(TEXTURE_NODE, "GeneratedCubeMapTexture");
        break;
      case ID_NEW_GEO_COORDINATE:
        InsertNode(COORDINATE_NODE, "GeoCoordinate");
        break;
      case ID_NEW_GEO_ELEVATION_GRID:
        CreateGeoElevationGrid();
        break;
      case ID_NEW_GEO_LOCATION:
        CreateNode("GeoLocation");
        break;
      case ID_NEW_GEO_LOD:
        CreateNode("GeoLOD");
        break;
      case ID_NEW_GEO_METADATA:
        InsertNode(X3D_GEO_METADATA, "GeoMetadata");
        break;
      case ID_NEW_GEO_ORIGIN:
        InsertNode(VRML_GEO_ORIGIN, "GeoOrigin");
        break;
      case ID_NEW_GEO_POSITION_INTERPOLATOR:
        CreateNode("GeoPositionInterpolator");
        break;
      case ID_NEW_GEO_PROXIMITY_SENSOR:
        CreateNode("GeoProximitySensor");
        break;
      case ID_NEW_GEO_TOUCH_SENSOR:
        CreateNode("GeoTouchSensor");
        break;
      case ID_NEW_GEO_TRANSFORM:
        CreateNode("GeoTransformSensor");
        break;
      case ID_NEW_GEO_VIEWPOINT:
        CreateGeoViewpoint();
        break;
      case ID_NEW_GRAVITY_PHYSICS_MODEL:
        InsertNode(PARTICLE_PHYSICS_MODEL_NODE, "GravityPhysicsModel");
        break;
      case ID_NEW_GROUP:
        CreateNode("Group");
        break;
      case ID_NEW_HANIM_DISPLACER:
        InsertNode(X3D_HANIM_DISPLACER, "HAnimDisplacer");
        break;
      case ID_NEW_HANIM_HUMANOID:
        CreateNode("HAnimHumanoid");
        break;
      case ID_NEW_HANIM_JOINT:
        InsertHAnimJoint();
        break;
      case ID_NEW_HANIM_SEGMENT:
        InsertHAnimSegment();
        break;
      case ID_NEW_HANIM_SITE:
        InsertHAnimSite();
        break;
      case ID_NEW_IMAGE_TEXTURE:
        InsertImageTexture();
        break;
      case ID_NEW_IMAGE_CUBE_MAP_TEXTURE:
        InsertNode(TEXTURE_NODE, "ImageCubeMapTexture");
        break;
      case ID_NEW_IMAGE_TEXTURE_3D:
        InsertNode(TEXTURE_NODE, "ImageTexture3D");
        break;
      case ID_NEW_INDEXED_FACE_SET:
        CreateGeometryNode("IndexedFaceSet");
        break;
      case ID_NEW_INDEXED_LINE_SET:
        CreateGeometryNode("IndexedLineSet");
        break;
      case ID_NEW_INDEXED_QUAD_SET:
        CreateGeometryNode("IndexedQuadSet");
        break;
      case ID_NEW_INDEXED_TRIANGLE_FAN_SET:
        CreateGeometryNode("IndexedTriangleFanSet");
        break;
      case ID_NEW_INDEXED_TRIANGLE_SET:
        CreateGeometryNode("IndexedTriangleSet");
        break;
      case ID_NEW_INDEXED_TRIANGLE_STRIP_SET:
        CreateGeometryNode("IndexedTriangleStripSet");
        break;
      case ID_NEW_INLINE:
        InsertInline();
        break;
      case ID_NEW_INLINE_LOAD_CONTROL:
        InsertInline(true);
        break;
      case ID_NEW_INTEGER_SEQUENCER:
        CreateNode("IntegerSequencer");
        break;
      case ID_NEW_INTEGER_TRIGGER:
        CreateNode("IntegerTrigger");
        break;
      case ID_NEW_KEY_SENSOR:
        CreateNode("KeySensor");
        break;
      case ID_NEW_LAYER:
        InsertNode(LAYER_NODE, "Layer");
        break;
      case ID_NEW_LAYER_SET:
        InsertNode(ROOT_NODE, "LayerSet");
        break;
      case ID_NEW_LAYOUT:
        InsertNode(X3D_LAYOUT, "Layout");
        break;
      case ID_NEW_LAYOUT_GROUP:
        CreateNode("LayoutGroup");
        break;
      case ID_NEW_LAYOUT_LAYER:
        InsertNode(LAYER_NODE, "LayoutLayer");
        break;
      case ID_NEW_LOAD_SENSOR:
        CreateNode("LoadSensor");
        break;
      case ID_NEW_LINE_PICK_SENSOR:
        CreateNode("LinePickSensor");
        break;
      case ID_NEW_LINE_PROPERTIES:
        InsertNode(X3D_LINE_PROPERTIES, "LineProperties");
        break;
      case ID_NEW_LINE_SET:
        CreateGeometryNode("LineSet");
        break;
      case ID_NEW_LOCAL_FOG:
        CreateNode("LocalFog");
        break;
      case ID_NEW_LOD:
        CreateNode("LOD");
        break;
      case ID_NEW_MATERIAL:
        InsertNode(MATERIAL_NODE, "Material");
        break;
      case ID_NEW_MATRIX_3_VERTEX_ATTRIBUTE:
        InsertNode(VERTEX_ATTRIBUTE_NODE, "Matrix3VertexAttribute");
        break;
      case ID_NEW_MATRIX_4_VERTEX_ATTRIBUTE:
        InsertNode(VERTEX_ATTRIBUTE_NODE, "Matrix4VertexAttribute");
        break;
      case ID_NEW_METADATA_DOUBLE:
        InsertNode(METADATA_NODE, "MetadataDouble");
        break;
      case ID_NEW_METADATA_FLOAT:
        InsertNode(METADATA_NODE, "MetadataFloat");
        break;
      case ID_NEW_METADATA_INTEGER:
        InsertNode(METADATA_NODE, "MetadataInteger");
        break;
      case ID_NEW_METADATA_SET:
        InsertNode(METADATA_NODE, "MetadataSet");
        break;
      case ID_NEW_METADATA_STRING:
        InsertNode(METADATA_NODE, "MetadataString");
        break;
      case ID_NEW_MOTOR_JOINT:
        CreateNode("MotorJoint");
        break;
      case ID_NEW_MOVIE_TEXTURE:
        InsertMovieTexture();
        break;
      case ID_NEW_MULTI_TEXTURE:
        InsertMultiTexture();
        break;
      case ID_NEW_MULTI_TEXTURE_COORDINATE:
        InsertMultiTextureCoordinate();
        break;
      case ID_NEW_MULTI_TEXTURE_TRANSFORM:
        InsertMultiTextureTransform();
        break;
      case ID_NEW_NAVIGATION_INFO:
        CreateNode("NavigationInfo");
        break;
      case ID_NEW_NORMAL:
        InsertNormal();
        break;
      case ID_NEW_NORMAL_INTERPOLATOR:
        CreateNode("NormalInterpolator");
        break;
      case ID_NEW_NURBS_CURVE:
        CreateNurbsCurve();
        break;
      case ID_NEW_NURBS_CURVE_2D:
        CreateNurbsCurve2D();
        break;
      case ID_NEW_NURBS_GROUP:
        if (_scene->isX3d())
            CreateGeometryNode("NurbsSet");
        else
            CreateNode("NurbsGroup");
        break;
      case ID_NEW_NURBS_ORIENTATION_INTERPOLATOR:
        CreateNode("NurbsOrientationInterpolator");
        break;
      case ID_NEW_NURBS_POSITION_INTERPOLATOR:
        CreateNode("NurbsPositionInterpolator");
        break;
      // for ID_NEW_NURBS_SURFACE see ID_NEW_NURBS_PLANE
      case ID_NEW_NURBS_SURFACE_INTERPOLATOR:
        CreateNode("NurbsSurfaceInterpolator");
        break;
      case ID_NEW_NURBS_SWEPT_SURFACE:
        CreateGeometryNode("NurbsSweptSurface");
        break;
      case ID_NEW_NURBS_SWUNG_SURFACE:
        CreateGeometryNode("NurbsSwungSurface");
        break;
      case ID_NEW_NURBS_TEXTURE_COORDINATE:
        InsertNode(NURBS_TEXTURE_COORDINATE_NODE, "NurbsTextureCoordinate");
        break;
      case ID_NEW_NURBS_TEXTURE_SURFACE:
        InsertNode(NURBS_TEXTURE_COORDINATE_NODE, "NurbsTextureSurface");
        break;
      case ID_NEW_NURBS_TRIMMED_SURFACE:
        CreateGeometryNode("NurbsTrimmedSurface");
        break;
      case ID_NEW_ORIENTATION_CHASER:
        CreateNode("OrientationChaser");
        break;
      case ID_NEW_ORIENTATION_DAMPER:
        CreateNode("OrientationDamper");
        break;
      case ID_NEW_ORIENTATION_INTERPOLATOR:
        CreateNode("OrientationInterpolator");
        break;
      case ID_NEW_ORTHO_VIEWPOINT:
        CreateNode("OrthoViewpoint");
        break;
      case ID_NEW_PACKAGED_SHADER:
        InsertNode(SHADER_NODE, "PackagedShader");
        break;
      case ID_NEW_PARTICLE_SYSTEM:
        CreateNode("ParticleSystem");
        break;
      case ID_NEW_PICKABLE_GROUP:
        CreateNode("PickableGroup");
        break;
      case ID_NEW_PIXEL_TEXTURE:
        InsertNode(TEXTURE_NODE, "PixelTexture");
        break;
      case ID_NEW_PIXEL_TEXTURE_3D:
        InsertNode(TEXTURE_NODE, "PixelTexture3D");
        break;
      case ID_NEW_PLANE_SENSOR:
        CreateNode("PlaneSensor");
        break;
      case ID_NEW_POINT_EMITTER:
        InsertNode(PARTICLE_EMITTER_NODE, "PointEmitter");
        break;
      case ID_NEW_POINT_LIGHT:
        CreateNode("PointLight");
        break;
      case ID_NEW_POINT_PICK_SENSOR:
        CreateNode("PointPickSensor");
        break;
      case ID_NEW_POINT_SET:
        CreateGeometryNode("PointSet");
        break;
      case ID_NEW_POLYLINE_2D:
        if (_scene->isX3d())
            CreateGeometryNode("Polyline2D", true);
        else
            InsertNode(NURBS_CONTROL_CURVE_NODE, "Polyline2D");
        break;
      case ID_NEW_POLYLINE_EMITTER:
        InsertNode(PARTICLE_EMITTER_NODE, "PolylineEmitter");
        break;
      case ID_NEW_POLYPOINT_2D:
        CreateGeometryNode("Polypoint2D", true);
        break;
      case ID_NEW_POSITION_CHASER:
        CreateNode("PositionChaser");
        break;
      case ID_NEW_POSITION_CHASER_2D:
        CreateNode("PositionChaser2D");
        break;
      case ID_NEW_POSITION_DAMPER:
        CreateNode("PositionDamper");
        break;
      case ID_NEW_POSITION_DAMPER_2D:
        CreateNode("PositionDamper2D");
        break;
      case ID_NEW_POSITION_INTERPOLATOR:
        CreateNode("PositionInterpolator");
        break;
      case ID_NEW_POSITION_INTERPOLATOR_2D:
        CreateNode("PositionInterpolator2D");
        break;
      case ID_NEW_PRIMITIVE_PICK_SENSOR:
        CreateNode("PrimitivePickSensor");
        break;
      case ID_NEW_PROGRAM_SHADER:
        InsertNode(SHADER_NODE, "ProgramShader");
        break;
      case ID_NEW_PROXIMITY_SENSOR:
        CreateNode("ProximitySensor");
        break;
      case ID_NEW_QUAD_SET:
        CreateGeometryNode("QuadSet");
        break;
      case ID_NEW_RECEIVER_PDU:
        CreateNode("ReceiverPdu");
        break;
      case ID_NEW_RECTANGLE_2D:
        CreateGeometryNode("Rectangle2D");
        break;
      case ID_NEW_RIGID_BODY:
        InsertRigidBody();
        break;
      case ID_NEW_RIGID_BODY_COLLECTION:
        CreateNode("RigidBodyCollection");
        break;
      case ID_NEW_SCALAR_CHASER:
        CreateNode("ScalarChaser");
        break;
      case ID_NEW_SCALAR_INTERPOLATOR:
        CreateNode("ScalarInterpolator");
        break;
      case ID_NEW_SCREEN_FONT_STYLE:
        InsertNode(FONT_STYLE_NODE, "ScreenFontStyle");
        break;
      case ID_NEW_SCREEN_GROUP:
        CreateNode("ScreenGroup");
        break;
      case ID_NEW_SCRIPT:
        CreateScript();
        break;
      case ID_NEW_SHADER_PART:
        InsertNode(X3D_SHADER_PART, "ShaderPart");
        break;
      case ID_NEW_SHADER_PROGRAM:
        InsertNode(X3D_SHADER_PROGRAM, "ShaderProgram");
        break;
      case ID_NEW_SHAPE:
        CreateNode("Shape");
        break;
      case ID_NEW_SIGNAL_PDU:
        CreateNode("SignalPdu");
        break;
      case ID_NEW_SINGLE_AXIS_HINGE_JOINT:
        CreateNode("SingleAxisHingeJoint");
        break;
      case ID_NEW_SLIDER_JOINT:
        CreateNode("SliderJoint");
        break;
      case ID_NEW_SOUND:
        CreateNode("Sound");
        break;
      case ID_NEW_SPHERE:
        CreateGeometryNode("Sphere");
        break;
      case ID_NEW_SPHERE_SENSOR:
        CreateNode("SphereSensor");
        break;
      case ID_NEW_SPOT_LIGHT:
        CreateNode("SpotLight");
        break;
      case ID_NEW_SPLINE_POSITION_INTERPOLATOR:
        CreateNode("SplinePositionInterpolator");
        break;
      case ID_NEW_SPLINE_POSITION_INTERPOLATOR_2D:
        CreateNode("SplinePositionInterpolator2D");
        break;
      case ID_NEW_SPLINE_SCALAR_INTERPOLATOR:
        CreateNode("SplineScalarInterpolator");
        break;
      case ID_NEW_SQUAD_ORIENTATION_INTERPOLATOR:
        CreateNode("SquadOrientationInterpolator");
        break;
      case ID_NEW_STATIC_GROUP:
        CreateNode("StaticGroup");
        break;
      case ID_NEW_STRING_SENSOR:
        CreateNode("StringSensor");
        break;
      case ID_NEW_SURFACE_EMITTER:
        InsertNode(PARTICLE_EMITTER_NODE, "SurfaceEmitter");
        break;
      case ID_NEW_SWITCH:
        CreateNode("Switch");
        break;
      case ID_NEW_TEX_COORD_DAMPER:
        CreateNode("TexCoordDamper");
        break;
      case ID_NEW_TEX_COORD_DAMPER_2D:
        CreateNode("TexCoordDamper2D");
        break;
      case ID_NEW_TEXTURE_BACKGROUND:
        CreateGeometryNode("TextureBackground");
        break;
      case ID_NEW_TEXT:
        CreateGeometryNode("Text");
        break;
      case ID_NEW_TEXTURE_COORDINATE:
        InsertTextureCoordinate(false);
        break;
      case ID_NEW_TEXTURE_COORDINATE_3D:
        InsertNode(TEXTURE_COORDINATE_NODE, "TextureCoordinate3D");
        break;
      case ID_NEW_TEXTURE_COORDINATE_4D:
        InsertNode(TEXTURE_COORDINATE_NODE, "TextureCoordinate4D");
        break;
      case ID_NEW_TEXTURE_COORDINATE_GENERATOR:
        InsertTextureCoordinate(true);
        break;
      case ID_NEW_TEXTURE_PROPERTIES:
        InsertNode(X3D_TEXTURE_PROPERTIES, "TextureProperties");
        break;
      case ID_NEW_TEXTURE_TRANSFORM:
        InsertNode(TEXTURE_TRANSFORM_NODE, "TextureTransform");
        break;
      case ID_NEW_TEXTURE_TRANSFORM_3D:
        InsertNode(TEXTURE_TRANSFORM_NODE, "TextureTransform3D");
        break;
      case ID_NEW_TEXTURE_TRANSFORM_MATRIX_3D:
        InsertNode(TEXTURE_TRANSFORM_NODE, "TextureTransformMatrix3D");
        break;
      case ID_NEW_TIME_SENSOR:
        CreateNode("TimeSensor");
        break;
      case ID_NEW_TIME_TRIGGER:
        CreateNode("TimeTrigger");
        break;
      case ID_NEW_TOUCH_SENSOR:
        CreateNode("TouchSensor");
        break;
      case ID_NEW_TWO_SIDED_MATERIAL:
        InsertNode(MATERIAL_NODE, "TwoSidedMaterial");
        break;
      case ID_NEW_TRANSFORM:
        CreateNode("Transform");
        break;
      case ID_NEW_TRANSFORM_SENSOR:
        CreateNode("TransformSensor");
        break;
      case ID_NEW_TRANSMITTER_PDU:
        CreateNode("TransmitterPdu");
        break;
      case ID_NEW_TRIANGLE_FAN_SET:
        CreateGeometryNode("TriangleFanSet");
        break;
      case ID_NEW_TRIANGLE_SET:
        CreateGeometryNode("TriangleSet");
        break;
      case ID_NEW_TRIANGLE_SET_2D:
        CreateGeometryNode("TriangleSet2D");
        break;
      case ID_NEW_TRIANGLE_STRIP_SET:
        CreateGeometryNode("TriangleStripSet");
        break;
      case ID_NEW_UNIVERSAL_JOINT:
        CreateNode("UniversalJoint");
        break;
      case ID_NEW_VIEWPOINT:
        CreateViewpoint();
        break;
      case ID_NEW_VIEWPOINT_GROUP:
        CreateNode("ViewpointGroup");
        break;
      case ID_NEW_VIEWPORT:
        InsertNode(X3D_VIEWPORT, "Viewport");
        break;
      case ID_NEW_VISIBILITY_SENSOR:
        CreateNode("VisibilitySensor");
        break;
      case ID_NEW_VOLUME_EMITTER:
        InsertNode(PARTICLE_EMITTER_NODE, "VolumeEmitter");
        break;
      case ID_NEW_VOLUME_PICK_SENSOR:
        CreateNode("VolumePickSensor");
        break;
      case ID_NEW_WIND_PHYSICS_MODEL:
        InsertNode(PARTICLE_PHYSICS_MODEL_NODE, "WindPhysicsModel");
        break;
      case ID_NEW_WORLD_INFO:
        CreateNode("WorldInfo");
        break;

      case ID_NEW_COMMENT:
        CreateNode("#");
        break;

      case ID_NEW_TRIMMED_SURFACE:
        CreateGeometryNode("TrimmedSurface");
        break;

      case ID_NEW_COVER_COVER:
        CreateNode("COVER");
        break;
      case ID_NEW_COVER_SPACE_SENSOR:
        CreateNode("SpaceSensor");
        break;
      case ID_NEW_COVER_AR_SENSOR:
        CreateNode("ARSensor");
        break;
      case ID_NEW_COVER_STEERING_WHEEL:
        CreateNode("SteeringWheel");
        break;
      case ID_NEW_COVER_VEHICLE:
        CreateNode("Vehicle");
        break;
      case ID_NEW_COVER_JOYSTICK_SENSOR:
        CreateNode("JoystickSensor");
        break;
      case ID_NEW_COVER_LAB_VIEW:
        CreateNode("LabView");
        break;
      case ID_NEW_COVER_CUBE_TEXTURE:
        InsertCubeTexture();
        break;
      case ID_NEW_COVER_WAVE:
        InsertNode(COVER_WAVE, "Wave");
        break;
      case ID_NEW_COVER_VIRTUAL_ACOUSTICS:
        CreateVirtualAcoustics();
        break;
      case ID_NEW_COVER_VIRTUAL_SOUND_SOURCE:
        InsertVirtualSoundSource();
        break;
      case ID_NEW_COVER_SKY:
        CreateNode("Sky");
        break;
      case ID_NEW_COVER_TUI_BUTTON:
        CreateNode("TUIButton");
        break;
      case ID_NEW_COVER_TUI_COMBO_BOX:
        CreateNode("TUIComboBox");
        break;
      case ID_NEW_COVER_TUI_FLOAT_SLIDER:
        CreateNode("TUIFloatSlider");
        break;
      case ID_NEW_COVER_TUI_FRAME:
        CreateNode("TUIFrame");
        break;
      case ID_NEW_COVER_TUI_LABEL:
        CreateNode("TUILabel");
        break;
      case ID_NEW_COVER_TUI_LIST_BOX:
        CreateNode("TUIListBox");
        break;
      case ID_NEW_COVER_TUI_MAP:
        CreateNode("TUIMap");
        break;
      case ID_NEW_COVER_TUI_PROGRESS_BAR:
        CreateNode("TUIProgressBar");
        break;
      case ID_NEW_COVER_TUI_SLIDER:
        CreateNode("TUISlider");
        break;
      case ID_NEW_COVER_TUI_SPLITTER:
        CreateNode("TUISplitter");
        break;
      case ID_NEW_COVER_TUI_TAB:
        CreateNode("TUITab");
        break;
      case ID_NEW_COVER_TUI_TAB_FOLDER:
        CreateNode("TUITabFolder");
        break;
      case ID_NEW_COVER_TUI_TOGGLE_BUTTON:
        CreateNode("TUIToggleButton");
        break;

      case ID_NEW_KAMBI_TEXT_3D:
        CreateGeometryNode("Text3D");
        break;
      case ID_NEW_KAMBI_TEAPOT:
        CreateGeometryNode("Teapot");
        break;
      case ID_NEW_KAMBI_INLINE:
        CreateNode("KambiInline");
        break;
      case ID_NEW_KAMBI_MATRIX_TRANSFORM:
        CreateNode("MatrixTransform");
        break;
      case ID_NEW_KAMBI_APPEARANCE:
        InsertNode(VRML_APPEARANCE, "KambiAppearance");
        break;
      case ID_NEW_KAMBI_BLEND_MODE:
        if (_scene->getSelection()->getNode()->getType() == KAMBI_KAMBI_APPEARANCE)
            InsertNode(KAMBI_BLEND_MODE, "BlendMode");
        break;
      case ID_NEW_KAMBI_OCTREE_PROPERTIES:
        InsertNode(KAMBI_KAMBI_OCTREE_PROPERTIES, "KambiOctreeProperties");
        break;
     case ID_NEW_KAMBI_GENERATED_SHADOW_MAP:
        InsertNode(KAMBI_GENERATED_SHADOW_MAP, "GeneratedShadowMap");
        break;
      case ID_NEW_KAMBI_RENDERED_TEXTURE:
        InsertNode(TEXTURE_NODE, "RenderedTexture");
        break;
      case ID_NEW_KAMBI_MULTI_GENERATED_TEXTURE_COORDINATE:
        InsertMultiGeneratedTextureCoordinate();
        break;
      case ID_NEW_KAMBI_PROJECTED_TEXTURE_COORDINATE:
        InsertNode(TEXTURE_COORDINATE_NODE | 
                   GENERATED_TEXTURE_COORDINATE_NODE, 
                   "ProjectedTextureCoordinate");
        break;
      case ID_NEW_KAMBI_HEAD_LIGHT:
        CreateNode("KambiHeadLight");
        break;
      case ID_NEW_KAMBI_TRIANGULATION:
        CreateNode("KambiTriangulation");
        break;
      case ID_NEW_KAMBI_NAVIGATION_INFO:
        CreateNode("KambiNavigationInfo");
        break;

      case ID_NEW_ODE_MOTOR_JOINT:
        CreateNode("OdeMotorJoint");
        break;
      case ID_NEW_ODE_SINGLE_AXIS_HINGE_JOINT:
        CreateNode("OdeSingleAxisHingeJoint");
        break;
      case ID_NEW_ODE_SLIDER_JOINT:
        CreateNode("OdeSliderJoint");
        break;

      case ID_NEW_SUPER_ELLIPSOID:
        CreateGeometryNode("SuperEllipsoid");
        break;
      case ID_NEW_SUPER_EXTRUSION:
        CreateSuperExtrusion();
        break;
      case ID_NEW_SUPER_SHAPE:
        CreateGeometryNode("SuperShape");
        break;
      case ID_NEW_SUPER_REVOLVER:
        CreateSuperRevolver();
        break;

      case ID_NEW_VRML_CUT:
        if (_vrmlCutNode == NULL) {
            _vrmlCutNode = CreateNode("VrmlCut");
            UpdateToolbars();
        }
        break;
      case ID_NEW_VRML_SCENE:
        InsertVrmlScene();
        break;

      case ID_NEW_NURBS_PLANE:
        CreateNurbsPlane();
        break;
      case ID_NEW_NURBS_BOX:
        CreateGeometryNode("Box");
        toNurbs();
        break;
      case ID_NEW_NURBS_CONE:
        CreateGeometryNode("Cone");
        toNurbs();
        break;
      case ID_NEW_NURBS_CYLINDER:
        CreateGeometryNode("Cylinder");
        toNurbs();
        break;
      case ID_NEW_NURBS_SPHERE:
        CreateGeometryNode("Sphere");
        toNurbs();
        break;

      case ID_NEW_TUBE:
        CreateTube();
        break;
      case ID_NEW_HORN:
        CreateTube(true);
        break;
      case ID_NEW_TORUS:
        CreateTorus();
        break;
      case ID_NEW_STAR_FISH_0:
        CreateStarFish(0);
        break;
      case ID_NEW_STAR_FISH_1:
        CreateStarFish(1);
        break;
      case ID_NEW_STAR_FISH_2:
        CreateStarFish(2);
        break;
      case ID_NEW_STAR_FISH_3:
        CreateStarFish(3);
        break;
      case ID_NEW_STAR_FISH_4:
        CreateStarFish(4);
        break;
      case ID_NEW_STAR_FISH_5:
        CreateStarFish(5);
        break;
      case ID_NEW_STAR_FISH_6:
        CreateStarFish(6);
        break;
      case ID_NEW_STAR_FISH_7:
        CreateStarFish(7);
        break;
      case ID_NEW_STAR_FISH_8:
        CreateStarFish(8);
        break;
      case ID_NEW_FLOWER_0:
        CreateFlower(0);
        break;
      case ID_NEW_FLOWER_1:
        CreateFlower(1);
        break;
      case ID_NEW_FLOWER_2:
        CreateFlower(2);
        break;
      case ID_NEW_FLOWER_3:
        CreateFlower(3);
        break;
      case ID_NEW_FLOWER_4:
        CreateFlower(4);
        break;
      case ID_NEW_FLOWER_5:
        CreateFlower(5);
        break;
      case ID_NEW_FLOWER_6:
        CreateFlower(6);
        break;
      case ID_NEW_FLOWER_7:
        CreateFlower(7);
        break;
      case ID_NEW_FLOWER_8:
        CreateFlower(8);
        break;
      case ID_NEW_SHELL:
        CreateShell();   
        break;
      case ID_NEW_UFO:
        CreateUfo();   
       break;
      case ID_NEW_INSECT_REAR_0:
        CreateInsectRear(0);
        break;
      case ID_NEW_INSECT_REAR_1:
        CreateInsectRear(1);
        break;
      case ID_NEW_INSECT_REAR_2:
        CreateInsectRear(2);
        break;
      case ID_NEW_INSECT_REAR_3:
        CreateInsectRear(3);
        break;
      case ID_NEW_INSECT_REAR_4:
        CreateInsectRear(4);
        break;
      case ID_NEW_INSECT_REAR_5:
        CreateInsectRear(5);
        break;
      case ID_NEW_INSECT_REAR_6:
        CreateInsectRear(6);
        break;
      case ID_NEW_INSECT_REAR_7:
        CreateInsectRear(7);
        break;
      case ID_NEW_INSECT_REAR_8:
        CreateInsectRear(8);
        break;
      case ID_NEW_HALF_SPHERE:
        CreateHalfSphere();
        break;
      case ID_NEW_HEART:
        CreateHeart();
        break;
      case ID_NEW_SPINDLE:
        CreateSpindle();
        break;
      case ID_NEW_MUSHROOM_ROUND:
        CreateMushroom(false);
        break;
      case ID_NEW_MUSHROOM_SULCATE:
        CreateMushroom(true);
        break;

      case ID_NEW_CATT_EXPORT_SRC:
        CreateNode("CattExportSrc");
        break;
      case ID_NEW_CATT_EXPORT_REC:
        CreateNode("CattExportRec");
        break;
      case ID_NEW_LDRAW_DAT_EXPORT:
        CreateNode("LdrawDatExport");
        break;

      case ID_NEW_NODE_BY_NAME:
        InsertNodeByName();
        break;

      case ID_PLAY:
        Play();
        break;
      case ID_STOP:
        Stop();
        break;
      case ID_RECORD:
        Record();
        break;
      case ID_REWIND:
        _channelView->OnRewind();
        break;
      case ID_FAST_FORWARD:
        _channelView->OnFastForward();
        break;

      case ID_DUNE_APP_ABOUT:
          {
            AboutDialog dlg(_wnd);
            dlg.DoModal();
          }
        break;
      case ID_DUNE_APP_HELP:
        OnHelpOverview();
        break;
      case ID_DUNE_APP_CATT_HELP:
        OnHelpOverviewCatt();
        break;
      case ID_HELP_SELECTION:
        OnHelpSelection();
        break;
      case ID_HELP_SELECTION_COVER:
        OnHelpCoverSelection();
        break;
      case ID_OPTIONS_SWITCH_TO_DUNE4KIDS:
          {
//            TheApp->reOpenWindow(_scene);
            break;
          }

      case ID_OPTIONS_PREFERENCES:
          {
            PreferencesDialog dlg(_wnd);
            dlg.DoModal();
          }
        break;
      case ID_OPTIONS_ROUTE_VIEW:
          {
            RouteViewSettingsDialog dlg(_wnd);
            dlg.DoModal();
            if (TheApp->GetShowRoutesAtBegin())
                _graphView->Initialize();
            swInvalidateWindow(_graphView->GetWindow());
          }
        break;
      case ID_OPTIONS_INPUT:
          {
            InputSettingsDialog dlg(_wnd);
            dlg.DoModal();
          }
        break;
      case ID_OPTIONS_OUTPUT:
          {
            OutputSettingsDialog dlg(_wnd);
            dlg.DoModal();
          }
        break;
      case ID_OPTIONS_ECMA_SCRIPT:
          {
            EcmaScriptSettingsDialog dlg(_wnd);
            dlg.DoModal();
          }
        break;
      case ID_OPTIONS_PREVIEW:
          {
            PreviewSettingsDialog dlg(_wnd);
            dlg.DoModal();
          }
        break;
      case ID_OPTIONS_UPLOAD:
          {
            UploadSettingsDialog dlg(_wnd);
            dlg.DoModal();
            UpdateToolbar(ID_DUNE_FILE_UPLOAD);
          }
        break;
      case ID_OPTIONS_HELP:
          {
            HelpSettingsDialog dlg(_wnd);
            dlg.DoModal();
          }
        break;
      case ID_OPTIONS_OBJECT_EDIT:
          {
            TexteditSettingsDialog dlg(_wnd);
            dlg.DoModal();
          }
        break;
      case ID_OPTIONS_STEREO_VIEW:
          {
            bool canStereo = TheApp->canQuadBufferStereo();
            StereoViewSettingsDialog dlg(_wnd);
            dlg.DoModal();
            if (TheApp->wantStereo()) {
                if (canStereo) 
                    TheApp->setUseStereo(true);
                else
                    TheApp->MessageBoxId(IDS_RESTART_4_STEREO);
            } else {
                TheApp->setUseStereo(false);
            }
          }
        break;
      case ID_OPTIONS_INPUT_DEVICE:
          {
            InputDeviceSettingsDialog dlg(_wnd);
            dlg.DoModal();
          }          
        break;
      case ID_OPTIONS_START_NORMAL:
        TheApp->SetStartVariant("dune");
        break;
      case ID_OPTIONS_START_WITH_4KIDS:
        TheApp->SetStartVariant("4kids");
        break;
      case ID_OPTIONS_START_WITH_4CATT:
        TheApp->SetStartVariant("4catt");
        break;
      case ID_OPTIONS_START_WITH_COVER:
        TheApp->SetStartVariant("cover");
        break;
      case ID_OPTIONS_START_WITH_KAMBI:
        TheApp->SetStartVariant("kambi");
        break;
      case ID_OPTIONS_START_LANGUAGE_ENGLISH:
        TheApp->SetStartLanguage("en");
        break;
      case ID_OPTIONS_START_LANGUAGE_GERMAN:
        TheApp->SetStartLanguage("de");
        break;
      case ID_OPTIONS_START_LANGUAGE_ITALIAN:
        TheApp->SetStartLanguage("it");
        break;
      case ID_TEACHER_CORRECT_NAME:
        setName(IDS_CORRECT);
        break;
      case ID_TEACHER_WRONG_NAME:
        setName(IDS_WRONG);
        break;
      case ID_TEACHER_CORRECT_SHAPE:
        createText(IDS_CORRECT);
        break;
      case ID_TEACHER_WRONG_SHAPE:
        createText(IDS_WRONG);
        break;

#ifdef HAVE_SAND
      case ID_SAND_EXPORT:
        OnSANDExport();
        break;
      case ID_SAND_WRITEMESHES:
        _nebulaExporter.OnToggleWriteMeshes(_menu);
        break;
      case ID_SAND_RELPATHS:
        _nebulaExporter.OnToggleUseRelativePaths(_menu);
        break;
      case ID_SAND_ALPHATEST:
        _nebulaExporter.OnToggleAlphaTest(_menu);
        break;
#endif
      case ID_TEST_IN_MENU:
        testInMenu();
        break;
      default:
        // recent files
        if ((id > ID_DUNE_FILE_MRU_FIRST) && (id < ID_DUNE_FILE_MRU_LAST)) { 
#ifndef HAVE_OPEN_IN_NEW_WINDOW
            if (!TheApp->checkSaveOldWindow())
                return;
#endif
            if (TheApp->getFileDialogDir())
                chdir(TheApp->getFileDialogDir());
            int fileId = id - ID_DUNE_FILE_MRU_FILE1;
            if (OpenFileCheck(TheApp->GetRecentFile(fileId))) {
#ifndef HAVE_OPEN_IN_NEW_WINDOW
                TheApp->deleteOldWindow();
#endif
            }
        } 
        // proto usage
        if ((id >= ID_PROTO_MRU_1) && 
            (id < ID_PROTO_MRU_1 + _protoMenu.size())) 
            for (int i = 0; i < _protoMenu.size(); i++)
                if ((id == _protoMenu[i].id) && (!_protoMenu[i].disabled)) {
                    CreateNode((const char*)_protoMenu[i].protoName);
                    break;
                }
    }
}

void MainWindow::updateColorCircle(void)
{
    if (_colorCircle_enabled) {
       _scene->RemoveView(_fieldView);
       if (_fieldView != NULL)
          _fieldView->DeleteView();
       if (_colorCircle_active) {
// small memoryleak, how often can be clicked to ColorCircle icon ? 8-(
          _fieldView=new FieldView(_scene, _fieldCanvas);
          _colorCircle_active=false;
          _scene->UpdateViews(NULL, UPDATE_SELECTION);
       } else {
          _fieldView = new ColorCircle(_scene, _fieldCanvas, _colorCircleHint);
          _colorCircle_active = true;
       }
       _scene->AddView(_fieldView); 
    } 
    _innerPane->SetPane(_fieldView, PW_RIGHT);
    Layout();
    setColorCircleIcon();
}

void MainWindow::showDiffuseColorCircle(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node->getType() != VRML_MATERIAL)
        return;
    NodeMaterial *material = (NodeMaterial *) node;
    _colorCircleHint=new FieldUpdate(node, material->diffuseColor_Field(), -1);
    _colorCircle_enabled = true;
    ToggleView(PW_RIGHT, _fieldView, ID_DUNE_VIEW_FIELD_VIEW, "ShowFieldView");
    updateColorCircle();
}

void MainWindow::showEmissiveColorCircle(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node->getType() != VRML_MATERIAL)
        return;
    NodeMaterial *material = (NodeMaterial *) node;
    _colorCircleHint=new FieldUpdate(node, material->emissiveColor_Field(), -1);
    _colorCircle_enabled = true;
    ToggleView(PW_RIGHT, _fieldView, ID_DUNE_VIEW_FIELD_VIEW, "ShowFieldView");
    updateColorCircle();
}

void MainWindow::showSpecularColorCircle(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node->getType() != VRML_MATERIAL)
        return;
    NodeMaterial *material = (NodeMaterial *) node;
    _colorCircleHint=new FieldUpdate(node, material->specularColor_Field(), -1);
    _colorCircle_enabled = true;
    ToggleView(PW_RIGHT, _fieldView, ID_DUNE_VIEW_FIELD_VIEW, "ShowFieldView");
    updateColorCircle();
}


void MainWindow::changeTransparency(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node->getType() != VRML_MATERIAL)
        return;
    OneFloatDialog dlg(_wnd, IDD_TRANSPARENCY, 0.5, 0, 1);
    if (dlg.DoModal() == IDCANCEL)
        return;
    NodeMaterial *material = (NodeMaterial *)node;
    _scene->setField(material, material->transparency_Field(), 
                     new SFFloat(dlg.GetValue()));
}

void MainWindow::changeEnableAnimation(void)
{
    NodeTimeSensor *node = (NodeTimeSensor *)_scene->getSelection()->getNode();
    if (node->getType() != VRML_TIME_SENSOR)
        return;
    _scene->setField(node, node->loop_Field(), new SFBool(true));
    UpdateToolbarSelection();
}

void MainWindow::changeDisableAnimation(void)
{
    NodeTimeSensor *node = (NodeTimeSensor *)_scene->getSelection()->getNode();
    if (node->getType() != VRML_TIME_SENSOR)
        return;
    _scene->setField(node, node->loop_Field(), new SFBool(false));
    UpdateToolbarSelection();
}

void MainWindow::changeAnimationTime(void)
{
    NodeTimeSensor *node = (NodeTimeSensor *)_scene->getSelection()->getNode();
    if (node->getType() != VRML_TIME_SENSOR)
        return;
    
    OneFloatDialog dlg(_wnd, IDD_ANIMATION_TIME, 
                       node->cycleInterval()->getValue(), 0, FLT_MAX);
    if (dlg.DoModal() == IDCANCEL)
        return;
    _scene->setField(node, node->cycleInterval_Field(), 
                     new SFTime(dlg.GetValue()));
}

void MainWindow::changeShininess(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node->getType() != VRML_MATERIAL)
        return;
    OneFloatDialog dlg(_wnd, IDD_SHININESS, 0.2, 0, 1);
    if (dlg.DoModal() == IDCANCEL)
        return;
    NodeMaterial *material = (NodeMaterial *)node;
    _scene->setField(material, material->shininess_Field(), 
                     new SFFloat(dlg.GetValue()));
}

void MainWindow::changeImageRepeat(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node == NULL)
        return;
    if ((node->getType() != VRML_APPEARANCE) && 
        (node->getType() != TEXTURE_TRANSFORM_NODE))
        return;
    OneFloatDialog dlg(_wnd, IDD_IMAGE_REPEAT, 1, 0);
    if (dlg.DoModal() == IDCANCEL)
        return;
    if (node->getType() == VRML_APPEARANCE) {
        InsertNode(TEXTURE_TRANSFORM_NODE, "TextureTransform");
        node = ((NodeAppearance *)node)->textureTransform()->getValue();
    }
    float fscale = dlg.GetValue();
    NodeTextureTransform *texTrans = (NodeTextureTransform *)node;
    _scene->setField(texTrans, texTrans->scale_Field(), 
                     new SFVec2f(fscale, fscale));
}

int 
MainWindow::considerIdRanges(int id)
{
    int ret = id;
    if ((id >= ID_DUNE_FILE_MRU_FIRST) && (id <= ID_DUNE_FILE_MRU_LAST))
        ret = ID_DUNE_FILE_MRU_FILE1;
    return ret;
}

void
MainWindow::OnHighlight(int id)
{
    char buf[BUFSIZE];
    buf[0] = '\0';
    swLoadString(considerIdRanges(id), buf, BUFSIZE);
    char *b = strchr(buf, '\n');
    if (b) *b = '\0';
    if (id == -1)
       _statusBar->SetText(_statusText);
    else
       _statusBar->SetText(buf);
}

void
MainWindow::UpdateNumbers4Kids(void)
{
    Node *selectedNode = _scene->getSelection()->getNode();
    bool hasNumbers = selectedNode->hasNumbers4kids();
    bool showNumbers = hasNumbers && _showNumbers4Kids;
    bool visible = swIsVisible(_fieldView->GetWindow());
    if ((!visible && showNumbers) || (visible && !showNumbers))
        ToggleView(PW_RIGHT, _fieldView, ID_DUNE_VIEW_FIELD_VIEW, 
                   "ShowFieldView");
}

void
MainWindow::OnUpdate(SceneView *sender, int type, Hint *hint)
{
    switch (type) {
      CASE_UPDATE(UPDATE_SELECTION)
        if (_colorCircle_active == true) {
            updateColorCircle();
            _colorCircle_enabled = false;
            setColorCircleIcon();
            if (TheApp->is4Kids())
                if (swIsVisible(_fieldView->GetWindow()))
                    ToggleView(PW_RIGHT, _fieldView, ID_DUNE_VIEW_FIELD_VIEW, 
                               "ShowFieldView");

        } else if (TheApp->is4Kids()) 
            UpdateNumbers4Kids();
        RefreshHelpSelection();
        _selectedField = -1;
        clearStatusText();
        UpdateToolbarSelection();
        RefreshProtoMenu();
        break;
      CASE_UPDATE(UPDATE_ALL)
        UpdateToolbars();
        RefreshProtoMenu();
        break;
      CASE_UPDATE(UPDATE_SELECTED_FIELD)
        {
        FieldUpdate* fieldUpdate=(FieldUpdate *)hint;
        _selectedField = fieldUpdate->field;
        UpdateToolbars();
        }
        break;
      CASE_UPDATE(UPDATE_ENABLE_COLOR_CIRCLE)
        {
        FieldUpdate* fieldUpdate = (FieldUpdate *)hint;
        _colorCircle_enabled = true;
        _colorCircleHint = new FieldUpdate(fieldUpdate->node,fieldUpdate->field,
                                           fieldUpdate->index);
        }
        setColorCircleIcon();
        break;
      CASE_UPDATE(UPDATE_DISABLE_COLOR_CIRCLE)      
        _colorCircle_enabled = false;
        setColorCircleIcon();
        break;
      CASE_UPDATE(UPDATE_CLOSE_COLOR_CIRCLE)
        updateColorCircle();
        setColorCircleIcon();
        if (TheApp->is4Kids())
            if (swIsVisible(_fieldView->GetWindow()))
                ToggleView(PW_RIGHT, _fieldView, ID_DUNE_VIEW_FIELD_VIEW, 
                           "ShowFieldView");
        break;
      CASE_UPDATE(UPDATE_SOLID_CHANGED)
        if (TheApp->is4Catt())
            UpdateToolbars();
        break;
      CASE_UPDATE(UPDATE_REMOVE_NODE)
        if (((NodeUpdate *) hint)->node->getType() == DUNE_VRML_CUT)
            _vrmlCutNode = NULL;
        break;
    }
}

void
MainWindow::OnSize(int width, int height)
{
    PanedWindow::OnSize(width, height);
    if (!swIsMaximized(_wnd)) {
        swGetTotalSize(_wnd, &width, &height);
        TheApp->SetIntPreference("WindowWidth", width);
        TheApp->SetIntPreference("WindowHeight", height);
    }
}

void
MainWindow::ToggleCreateAtZero(int index)
{
        bool flag =  TheApp->getCreateAtZero(index);
        TheApp->setCreateAtZero(index, !flag);
        UpdateToolbars();
}

bool isToNurbsAllowedParent(Node *parent)
{
    if ( (parent == parent->getScene()->getRoot()) ||
         (parent->getType() == VRML_GROUP) ||
         (parent->getType() == VRML_TRANSFORM) ||
         (parent->getType() == VRML_ANCHOR) ||
         (parent->getType() == VRML_SHAPE) )
       return true;
    else
       return false;
}

bool 
MainWindow::getValidTexture(void)
{
    Node *node = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();
    bool validTexture = false;
    if (node->findFirstValidFieldType(TEXTURE_NODE) != -1)
        validTexture = true;
    if (field != -1) 
        if (node->validChildType(field, TEXTURE_NODE))
            validTexture = true;
    return validTexture;
}


void MainWindow::UpdateStaticMenuCoverNodes(void)
{
    int disabled = TheApp->getCoverMode() ? 0 : SW_MENU_DISABLED;
    swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_COVER, SW_MENU_DISABLED,  
                   disabled);   
    swMenuSetFlags(_menu, ID_NEW_COVER_SKY, SW_MENU_DISABLED, 
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_LAB_VIEW, SW_MENU_DISABLED, 
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_COVER, SW_MENU_DISABLED, 
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_SPACE_SENSOR, SW_MENU_DISABLED, 
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_AR_SENSOR, SW_MENU_DISABLED, 
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_JOYSTICK_SENSOR, SW_MENU_DISABLED, 
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_STEERING_WHEEL, SW_MENU_DISABLED, 
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_VEHICLE, SW_MENU_DISABLED, 
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_LAB_VIEW, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_VIRTUAL_ACOUSTICS, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_BUTTON, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_COMBO_BOX, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_FLOAT_SLIDER, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_FRAME, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_LABEL, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_LIST_BOX, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_MAP, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_PROGRESS_BAR, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_SLIDER, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_SPLITTER, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_TAB, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_TAB_FOLDER, SW_MENU_DISABLED,
                   disabled);
    swMenuSetFlags(_menu, ID_NEW_COVER_TUI_TOGGLE_BUTTON, SW_MENU_DISABLED,
                   disabled);
}


void MainWindow::UpdateMenuCoverNodes(void)
{
    Node *node = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();
    bool validTexture = getValidTexture();
    if (!validTexture) 
        validTexture = (node->findValidFieldType(TEXTURE_NODE) != -1);
    else
        if (!node->validChildType(field, TEXTURE_NODE))
            validTexture = false;
    swMenuSetFlags(_menu, ID_NEW_COVER_CUBE_TEXTURE, SW_MENU_DISABLED, 
                   validTexture && 
                   TheApp->getCoverMode() ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbarCover, 2, SW_TB_DISABLED,
                            validTexture &&
                            TheApp->getCoverMode() ? 0 : SW_TB_DISABLED);

#ifdef HAVE_COVER_WAVE
    bool validEffect = TheApp->getCoverMode() &&
                       (node->findValidFieldType(COVER_WAVE) != -1);
    swMenuSetFlags(_menu, ID_NEW_COVER_WAVE, SW_MENU_DISABLED, 
                   validEffect ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbarCover, 4, SW_TB_DISABLED,
                            validEffect ? 0 : SW_TB_DISABLED);
#endif

    swMenuSetFlags(_menu, ID_HELP_SELECTION_COVER, SW_MENU_DISABLED, 
                   TheApp->getCoverMode() && 
                   (node->hasCoverFields() || node->isCoverNode()) ? 
                   0 : SW_MENU_DISABLED);

    if (!TheApp->getCoverMode())
        swMenuSetFlags(_menu, ID_NEW_COVER_VIRTUAL_SOUND_SOURCE, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);

}

void MainWindow::UpdateStaticMenuKambiNodes(void)
{
    int disabled = TheApp->getKambiMode() ? 0 : SW_MENU_DISABLED;
    swMenuSetFlags(_menu, ID_NEW_KAMBI_TEAPOT, SW_MENU_DISABLED, disabled);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_TEXT_3D, SW_MENU_DISABLED, disabled);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_INLINE, SW_MENU_DISABLED, disabled);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_MATRIX_TRANSFORM, SW_MENU_DISABLED, disabled);
    swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_KAMBI, SW_MENU_DISABLED, disabled);   
    swMenuSetFlags(_menu, ID_NEW_KAMBI_HEAD_LIGHT, SW_MENU_DISABLED, disabled);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_TRIANGULATION, SW_MENU_DISABLED, disabled);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_NAVIGATION_INFO, SW_MENU_DISABLED, disabled);
}

void 
MainWindow::UpdateMenuKambiNodes(void)
{
    Node *node = _scene->getSelection()->getNode();
    bool kambi = TheApp->getKambiMode();
    swMenuSetFlags(_menu, ID_NEW_KAMBI_APPEARANCE, SW_MENU_DISABLED,
                   kambi && (node->getType() == VRML_SHAPE) ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_BLEND_MODE,  SW_MENU_DISABLED,
                   kambi && (node->getType() == KAMBI_KAMBI_APPEARANCE) ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_OCTREE_PROPERTIES,  SW_MENU_DISABLED,
                   kambi && ((node->getType() == KAMBI_KAMBI_NAVIGATION_INFO) ||
                   (node->getType() == VRML_SHAPE)) ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_GENERATED_SHADOW_MAP, SW_MENU_DISABLED,
                   kambi && ((node->getType() == KAMBI_KAMBI_APPEARANCE) ||
                   (node->getType() == VRML_APPEARANCE)) ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_KAMBI_RENDERED_TEXTURE, SW_MENU_DISABLED,
                   kambi && ((node->getType() == KAMBI_KAMBI_APPEARANCE) ||
                   (node->getType() == VRML_APPEARANCE)) ? 0 : SW_MENU_DISABLED);
}

void MainWindow::UpdateMenuVisible(void)
{

    swMenuSetFlags(_menu, ID_ROUTE_ZOOM_IN, SW_MENU_DISABLED,  
                   swIsVisible(_graphView->GetWindow()) && 
                   _graphView->canZoomIn() ? 0 : SW_MENU_DISABLED); 
    swMenuSetFlags(_menu, ID_ROUTE_ZOOM_OUT, SW_MENU_DISABLED,  
                   swIsVisible(_graphView->GetWindow()) ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_ROUTE_UNZOOM, SW_MENU_DISABLED,  
                   swIsVisible(_graphView->GetWindow()) ? 0 : SW_MENU_DISABLED);

}

void
MainWindow::UpdateObjectEdit(Node *node)
{
    bool editObject_flag = false;
    bool editUrl_flag = false;
    if (!isEditorInUse()) {
        switch (node->getType()) {
          case VRML_SCRIPT:
          case X3D_SHADER_PROGRAM:
          case X3D_PACKAGED_SHADER:
            editObject_flag = true;
          case VRML_IMAGE_TEXTURE:
          case VRML_MOVIE_TEXTURE:
          case VRML_AUDIO_CLIP:
            editUrl_flag = true;
            break;
          case X3D_SHADER_PART:
            editUrl_flag = true;
            break;
          case X3D_COMPOSED_SHADER:
            editObject_flag = true;
            break;
        }
    }
    swMenuSetFlags(_menu, ID_OBJECT_EDIT, SW_MENU_DISABLED, 
                   editObject_flag ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_standardToolbar, _objectEditIconPos, 
                            SW_TB_DISABLED, 
                            editObject_flag ? 0 : SW_TB_DISABLED);
    swMenuSetFlags(_menu, ID_URL_EDIT, SW_MENU_DISABLED, 
                   editUrl_flag ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_standardToolbar, _urlEditIconPos, SW_TB_DISABLED, 
                            editUrl_flag ? 0 : SW_TB_DISABLED);
}


//
// UpdateToolbars(void)
//
// updates all the "insert"-type buttons (eg., appearance, material, etc)
// by checking to see if the current selection contains a field which
// can hold this type.
//
// Also update menus.
//

void
MainWindow::UpdateToolbars(void)
{
    UpdateToolbarSelection();

    UpdateMenuVisible();

    swMenuSetFlags(_menu, ID_DUNE_EDIT_FIND_AGAIN, SW_MENU_DISABLED, 
                   _searchText.length() == 0 ? SW_MENU_DISABLED : 0);

    swMenuSetFlags(_menu, ID_CREATE_AT_ZERO_X, SW_MENU_CHECKED, 
                   TheApp->getCreateAtZero(0) ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_CREATE_AT_ZERO_Y, SW_MENU_CHECKED, 
                   TheApp->getCreateAtZero(1) ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_CREATE_AT_ZERO_Z, SW_MENU_CHECKED, 
                   TheApp->getCreateAtZero(2) ? SW_MENU_CHECKED : 0);

    swMenuSetFlags(_menu, ID_INPUTDEVICE_GREATER, SW_MENU_DISABLED, 
                   TheApp->hasInputDevices() ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_standardToolbar, _inputDeviceGreaterIconPos, 
                            SW_TB_DISABLED, 
                            TheApp->hasInputDevices() ? 0 : SW_TB_DISABLED);
    swMenuSetFlags(_menu, ID_INPUTDEVICE_LESSER, SW_MENU_DISABLED, 
                   TheApp->hasInputDevices() ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_standardToolbar, _inputDeviceLesserIconPos, 
                            SW_TB_DISABLED, 
                            TheApp->hasInputDevices() ? 0 : SW_TB_DISABLED);

//    swMenuSetFlags(_menu, ID_OPTIONS_STEREO_VIEW, SW_MENU_DISABLED,
//                   TheApp->canStereo() ? 0 : SW_MENU_DISABLED);

    UpdateToolbar(ID_NAVIGATION_OPERATIONS);
    
    UpdateToolbar(ID_X_ONLY);
    UpdateToolbar(ID_Y_ONLY);
    UpdateToolbar(ID_Z_ONLY);

    UpdateToolbar(ID_INPUT_DEVICE_NAVIGATION_MODE);

    UpdateMenuCoverNodes();
}

void 
MainWindow::InitToolbar(STOOLBAR toolbar, NodeButton *buttons, int count)
{
    for (int i = 0; i < count; i++) {
        buttons[i].enabled = true;
        swToolbarSetButtonFlags(toolbar, i, SW_TB_DISABLED, 0);
    }
}

void
MainWindow::InitToolbars(void)
{
    int arraySize = ARRAYSIZE(standardButtons) / 2;
    if (TheApp->is4Kids()) {
        if (TheApp->hasInputDevices())
            arraySize = ARRAYSIZE(standardButtons4KidsWithInputDevices) / 2;
        else
            arraySize = ARRAYSIZE(standardButtons4Kids) / 2;
    } else {
        InitToolbar(_nodeToolbar1, buttons1, ARRAYSIZE(buttons1));
        InitToolbar(_nodeToolbar2, buttons2, ARRAYSIZE(buttons2));
        InitToolbar(_nodeToolbar3, buttons3, ARRAYSIZE(buttons3));
        InitToolbar(_nodeToolbarVRML200x, buttonsVRML200x, 
                    ARRAYSIZE(buttonsVRML200x));
        InitToolbar(_nodeToolbarX3DComponents1, buttonsX3DComponents1, 
                    ARRAYSIZE(buttonsX3DComponents1));
        InitToolbar(_nodeToolbarX3DComponents2, buttonsX3DComponents2, 
                    ARRAYSIZE(buttonsX3DComponents2));
        InitToolbar(_nodeToolbarX3DComponents3, buttonsX3DComponents3, 
                    ARRAYSIZE(buttonsX3DComponents3));
        InitToolbar(_nodeToolbarX3DComponents4, buttonsX3DComponents4, 
                    ARRAYSIZE(buttonsX3DComponents4));
        InitToolbar(_nodeToolbarScripted, buttonsScripted, 
                    ARRAYSIZE(buttonsScripted));
        InitToolbar(_nodeToolbarCover, buttonsCover, ARRAYSIZE(buttonsCover));
        InitToolbar(_nodeToolbarKambi, buttonsKambi, ARRAYSIZE(buttonsKambi));
    }
    for (int i = 0; i < ARRAYSIZE(standardButtons) / 2; i++)
        swToolbarSetButtonFlags(_standardToolbar, i, SW_TB_DISABLED, 0);
}

void
MainWindow::UpdateToolbar(int id)
{
    switch (id) {
      case ID_X_ONLY:
        swMenuSetFlags(_menu, ID_X_ONLY, SW_MENU_CHECKED,
                       _xOnly ? SW_MENU_CHECKED : 0);
        swToolbarSetButtonFlags(_standardToolbar, _xOnlyIconPos, 
                                SW_TB_CHECKED, _xOnly ? SW_TB_CHECKED :  0);
        break;
      case ID_Y_ONLY:
        swMenuSetFlags(_menu, ID_Y_ONLY, SW_MENU_CHECKED,
                       _yOnly ? SW_MENU_CHECKED : 0);
        swToolbarSetButtonFlags(_standardToolbar, _yOnlyIconPos, 
                                SW_TB_CHECKED, _yOnly ? SW_TB_CHECKED :  0);
        break;
      case ID_Z_ONLY:
        swMenuSetFlags(_menu, ID_Z_ONLY, SW_MENU_CHECKED,
                       _zOnly ? SW_MENU_CHECKED : 0);
        swToolbarSetButtonFlags(_standardToolbar, _zOnlyIconPos, 
                                SW_TB_CHECKED, _zOnly ? SW_TB_CHECKED :  0);
        break;
     case ID_OBJECT_EDIT:
        UpdateObjectEdit(_scene->getSelection()->getNode());
        break;
      case ID_DUNE_FILE_UPLOAD:
        swMenuSetFlags(_menu, ID_DUNE_FILE_UPLOAD, SW_MENU_DISABLED, 
                      TheApp->hasUpload() == 0 ? SW_MENU_DISABLED : 0);
        break;
      case ID_INPUT_DEVICE_NAVIGATION_MODE:
        if (TheApp->getMaxNumberAxesInputDevices()>=2) { 
            swMenuSetFlags(_menu, ID_INPUT_DEVICE_NAVIGATION_MODE, 
                           SW_MENU_CHECKED, _navigation_input_device_active ? 
                           SW_MENU_CHECKED : 0);
            swToolbarSetButtonFlags(_standardToolbar, 
                                    _navigationInputDeviceIconPos, 
                                    SW_TB_CHECKED,
                                    _navigation_input_device_active ? 
                                    SW_TB_CHECKED : 0);
        } else {
            swMenuSetFlags(_menu, ID_INPUT_DEVICE_NAVIGATION_MODE, 
                           SW_MENU_DISABLED, SW_MENU_DISABLED);
            swToolbarSetButtonFlags(_standardToolbar, 
                                    _navigationInputDeviceIconPos, 
                                    SW_TB_DISABLED, SW_TB_DISABLED);
        }
        break;
      case ID_NAVIGATION_OPERATIONS:
        {    
          bool isFly = TheApp->GetMouseMode() == MOUSE_FLY;
          swMenuSetFlags(_menu, ID_FLY_MOUSE_MODE, SW_MENU_CHECKED, 
                         isFly ? SW_MENU_CHECKED : 0);
          swToolbarSetButtonFlags(_standardToolbar, _mouseFlyIconPos, 
                                  SW_TB_CHECKED, isFly ? SW_TB_CHECKED :  0);

          bool isExamine = TheApp->GetMouseMode() == MOUSE_EXAMINE;
          swMenuSetFlags(_menu, ID_EXAMINE_MOUSE_MODE, SW_MENU_CHECKED, 
                         isExamine ? SW_MENU_CHECKED : 0);
          swToolbarSetButtonFlags(_standardToolbar, _mouseExamineIconPos, 
                                  SW_TB_CHECKED, isExamine ? SW_TB_CHECKED : 0);

          bool isWalk = TheApp->GetMouseMode() == MOUSE_WALK;
          swMenuSetFlags(_menu, ID_WALK_MOUSE_MODE, SW_MENU_CHECKED, 
                         isWalk ? SW_MENU_CHECKED : 0);
          swToolbarSetButtonFlags(_standardToolbar, _mouseWalkIconPos, 
                                  SW_TB_CHECKED, isWalk ? SW_TB_CHECKED :  0);

          bool isRoll = TheApp->GetMouseMode() == MOUSE_ROLL;
          swMenuSetFlags(_menu, ID_ROLL_MOUSE_MODE, SW_MENU_CHECKED, 
                         isRoll ? SW_MENU_CHECKED : 0);
          swToolbarSetButtonFlags(_standardToolbar, _mouseRollIconPos, 
                                  SW_TB_CHECKED, isRoll ? SW_TB_CHECKED :  0);

          swMenuSetFlags(_menu, ID_MOUSE_NAVIGATION_MODE, SW_MENU_CHECKED,
                         _navigation_mouse_active ? SW_MENU_CHECKED : 0);
          swToolbarSetButtonFlags(_standardToolbar, _navigationMouseIconPos, 
                                  SW_TB_CHECKED, _navigation_mouse_active ? 
                                  SW_TB_CHECKED :  0);
          }
        break;
      case ID_SKIP_MATERIAL_NAME_BEFORE_FIRST_UNDERSCORE:
        swMenuSetFlags(_menu, ID_SKIP_MATERIAL_NAME_BEFORE_FIRST_UNDERSCORE, 
                       SW_MENU_CHECKED, 
                       TheApp->SkipMaterialNameBeforeFirstUnderscore() ? 
                       SW_MENU_CHECKED : 0);
        break;
      case ID_SKIP_MATERIAL_NAME_AFTER_LAST_UNDERSCORE:
        swMenuSetFlags(_menu, ID_SKIP_MATERIAL_NAME_AFTER_LAST_UNDERSCORE, 
                       SW_MENU_CHECKED,
                       TheApp->SkipMaterialNameAfterLastUnderscore() 
                       ? SW_MENU_CHECKED : 0);
        break;
      default:
        swDebugf("unhandled call to MainWindow::UpdateToolbar(%d)\n", id);
    }
}

bool 
MainWindow::isValidNodeType(Node* node, int field)
{
    bool valid = false;
    if (node->findFirstValidFieldType(node->getType()) != -1)
        valid = true;
    if (field != -1)
        if (node->validChildType(field, node->getType()))
            valid = true;
    return valid;
}

void
MainWindow::UpdateToolbar(STOOLBAR toolbar, Node *node, int field,
                          NodeButton *buttons, int count) 
{
    if (node == NULL)
        return;
    for (int i = 0; i < count; i++)
        if (!buttons[i].alwaysEnabled) {
            bool valid = true;
            switch (buttons[i].type) {
              case VRML_AUDIO_CLIP:
                valid = (node->getType() == VRML_SOUND);
                break;
              case X3D_BOUNDED_PHYSICS_MODEL:
              case X3D_FORCE_PHYSICS_MODEL:
              case X3D_GRAVITY_PHYSICS_MODEL:
              case X3D_WIND_PHYSICS_MODEL:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(PARTICLE_PHYSICS_MODEL_NODE) 
                        != -1;
                break;
              case VRML_CONTOUR_POLYLINE_2D:
                valid = node->findValidFieldType(NURBS_CONTROL_CURVE_NODE) != 
                        -1;
                break;
              case X3D_COLOR_RGBA:
                valid = _scene->isX3d();
                if (!valid)
                    break;
              case VRML_COLOR:
                valid = node->findValidFieldType(COLOR_NODE) != -1;
                break;
              case X3D_COORDINATE_DOUBLE:
                valid = _scene->isX3d();
                if (!valid)
                    break;
              case VRML_COORDINATE:
              case VRML_GEO_COORDINATE:
                valid = node->findValidFieldType(COORDINATE_NODE) != -1;
                break;
              case VRML_IMAGE_TEXTURE:
              case VRML_PIXEL_TEXTURE:
              case VRML_MOVIE_TEXTURE:
                valid = getValidTexture();
                if (node->getType() == VRML_SOUND)
                    valid = true;
                break;
              case VRML_TEXTURE_COORDINATE:
                valid = node->findValidFieldType(TEXTURE_COORDINATE_NODE) != -1;
                if (field != -1)
                    if (node->validChildType(field, TEXTURE_COORDINATE_NODE))
                        valid = true;
                if (!valid) {
                    valid = node->findValidFieldType(VRML_TEXTURE_COORDINATE) != -1;
                    if (field != -1)
                        if (node->validChildType(field, VRML_TEXTURE_COORDINATE))
                            valid = true;
                }
                break;
              case X3D_TEXTURE_COORDINATE_GENERATOR:
                valid = node->findValidFieldType(
                              GENERATED_TEXTURE_COORDINATE_NODE) != -1;
                if (field != -1)
                    if (node->validChildType(field, 
                                             GENERATED_TEXTURE_COORDINATE_NODE))
                        valid = true;
                 if (valid)
                     break;
              case X3D_TEXTURE_COORDINATE_3D:
              case X3D_TEXTURE_COORDINATE_4D:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(TEXTURE_COORDINATE_NODE) != -1;
                if (field != -1)
                    if (node->validChildType(field, TEXTURE_COORDINATE_NODE))
                        valid = true;
                break;
              case X3D_TEXTURE_TRANSFORM_3D:
              case X3D_TEXTURE_TRANSFORM_MATRIX_3D:
                valid = _scene->isX3d();
                if (!valid)
                    break;
              case VRML_TEXTURE_TRANSFORM:
                valid = node->findFirstValidFieldType(TEXTURE_TRANSFORM_NODE) 
                        != -1;
                if (field != -1)
                    if (node->validChildType(field, TEXTURE_TRANSFORM_NODE))
                        valid = true;
                break;
              case X3D_MULTI_TEXTURE:
                valid = _scene->isX3d() && getValidTexture() && 
                        (node->getType() != X3D_MULTI_TEXTURE);
                break;
              case X3D_MULTI_TEXTURE_COORDINATE:
                valid = _scene->isX3d() &&  
                        (node->findValidFieldType(TEXTURE_COORDINATE_NODE) != 
                         -1) && 
                        (node->getType() != X3D_MULTI_TEXTURE_COORDINATE);
                break;
              case X3D_MULTI_TEXTURE_TRANSFORM:
                valid = _scene->isX3d() &&  
                        (node->findValidFieldType(TEXTURE_TRANSFORM_NODE) != 
                         -1) && 
                        (node->getType() != X3D_MULTI_TEXTURE_TRANSFORM);
                break;
              case X3D_TWO_SIDED_MATERIAL:
                valid = _scene->isX3d();
                if (!valid)
                    break;
              case VRML_MATERIAL:
                valid = node->findValidFieldType(MATERIAL_NODE) != -1;
                break;
              case X3D_NURBS_TEXTURE_COORDINATE:
                valid = _scene->isX3d();
                if (!valid)
                    break;
              case VRML_NURBS_TEXTURE_SURFACE:
                valid = valid &&
                        node->findFirstValidFieldType(
                                    NURBS_TEXTURE_COORDINATE_NODE) != -1;
                break;
              case X3D_NURBS_TRIMMED_SURFACE:
              case X3D_NURBS_SWEPT_SURFACE:
              case X3D_NURBS_SWUNG_SURFACE:
                valid = _scene->isX3d();
                break;
              case VRML_NURBS_CURVE_2D:
                valid = (node->findFirstValidFieldType(NURBS_CONTROL_CURVE_NODE)
                         != -1);
                valid = valid || 
                        (node->findFirstValidFieldType(VRML_NURBS_CURVE_2D) != 
                         -1);
                break;
              case VRML_CONTOUR_2D:
                valid = (node->getType() == VRML_TRIMMED_SURFACE) ||
                        (node->getType() == X3D_NURBS_TRIMMED_SURFACE);
                break;
              case X3D_POLYLINE_2D:
                valid = _scene->isX3d();
                if (!valid)
                    break;
              case X3D_RIGID_BODY:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(X3D_RIGID_BODY) != -1;
                if (!valid)
                    if (node->matchNodeClass(RIGID_JOINT_NODE)) {
                        X3DRigidJointNode *joint = (X3DRigidJointNode *)node;
                        if (joint->body1()->getValue() == NULL)
                            valid = true;
                        else if (joint->body2()->getValue() == NULL)
                            valid = true; 
                    }
                    if (node->getType() == X3D_CONTACT) {
                        NodeContact *contact = (NodeContact *)node;
                        if (contact->body1()->getValue() == NULL)
                            valid = true;                            
                        else if (contact->body2()->getValue() == NULL)
                            valid = true;
                    }
                break;
              case X3D_BALL_JOINT:
              case X3D_DOUBLE_AXIS_HINGE_JOINT:
              case X3D_MOTOR_JOINT:
              case X3D_SINGLE_AXIS_HINGE_JOINT:
              case X3D_SLIDER_JOINT:
              case X3D_UNIVERSAL_JOINT:
              case DUNE_ODE_MOTOR_JOINT:
              case DUNE_ODE_SINGLE_AXIS_HINGE_JOINT:
              case DUNE_ODE_SLIDER_JOINT:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = (node->getType() == X3D_RIGID_BODY_COLLECTION);
                break;
              case X3D_COLLISION_COLLECTION:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = false;
                if (node->getType() == X3D_RIGID_BODY_COLLECTION) {
                    NodeRigidBodyCollection *coll = (NodeRigidBodyCollection *)node;
                    if (coll->collider()->getValue() == NULL)
                        valid = true;                            
                }
                if (node->getType() == X3D_COLLISION_SENSOR) {
                    NodeCollisionSensor *sensor = (NodeCollisionSensor *)node;
                    if (sensor->collidables()->getValue() == NULL)
                        valid = true;                            
                }
                break;
              case X3D_COLLISION_SPACE:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = false;
                if (node->getType() == X3D_COLLISION_COLLECTION)
                    valid = true;
                if (node->getType() == X3D_COLLISION_SPACE)
                    valid = true;
                break;
              case X3D_HANIM_JOINT:
                valid = false;
                if (node->getType() == X3D_HANIM_HUMANOID)
                    valid = true;
                if (node->getType() == X3D_HANIM_JOINT)
                    valid = true;
                break;
              case X3D_HANIM_SEGMENT:
                valid = node->findValidFieldType(buttons[i].type) != -1;
                if (node->getType() == X3D_HANIM_JOINT) {
                    NodeHAnimJoint *joint = (NodeHAnimJoint *)node;
                    if (field != joint->displacers_Field())
                        valid = true;
                }
                break;
              case X3D_HANIM_SITE:
                valid = node->findValidFieldType(buttons[i].type) != -1;
                if (node->getType() == X3D_HANIM_JOINT) {
                    NodeHAnimJoint *joint = (NodeHAnimJoint *)node;
                    if (field != joint->displacers_Field())
                        valid = true;
                }
                break;
              case X3D_CAD_FACE:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(PRODUCT_STRUCTURE_CHILD_NODE)
                        != -1;
                break;
              case X3D_COMPOSED_CUBE_MAP_TEXTURE:
              case X3D_COMPOSED_TEXTURE_3D:
              case X3D_GENERATED_CUBE_MAP_TEXTURE:
              case X3D_IMAGE_CUBE_MAP_TEXTURE:
              case X3D_IMAGE_TEXTURE_3D:
              case X3D_PIXEL_TEXTURE_3D:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = _scene->isX3d() && getValidTexture();
                break;
              case X3D_COMPOSED_SHADER:
              case X3D_PACKAGED_SHADER:
              case X3D_PROGRAM_SHADER:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(SHADER_NODE) != -1;
                break;
              case X3D_CONE_EMITTER:
              case X3D_EXPLOSION_EMITTER:
              case X3D_POINT_EMITTER:
              case X3D_POLYLINE_EMITTER:
              case X3D_SURFACE_EMITTER:
              case X3D_VOLUME_EMITTER:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(PARTICLE_EMITTER_NODE) != -1;
                break;
              case X3D_FLOAT_VERTEX_ATTRIBUTE:
              case X3D_MATRIX_3_VERTEX_ATTRIBUTE:
              case X3D_MATRIX_4_VERTEX_ATTRIBUTE:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(VERTEX_ATTRIBUTE_NODE) != -1;
                break;
              case X3D_LAYER:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(LAYER_NODE) != -1;
                break;
              case X3D_LAYER_SET:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = (_scene->getRoot() == node);
                break;
              case X3D_LAYOUT_LAYER:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(LAYER_NODE) != -1;
                break;
              case X3D_SCREEN_FONT_STYLE:
                valid = _scene->isX3d();
                if (!valid)
                    break;
              case VRML_FONT_STYLE:
                valid = node->findValidFieldType(FONT_STYLE_NODE) != -1;
                break;


// template for new X3D nodes inserted with InsertNode(_NODE, "....
/*
              case X3D_:
                valid = _scene->isX3d();
                if (!valid)
                    break;
                valid = node->findValidFieldType(_NODE) != -1;
                break;
*/

              case DUNE_VRML_CUT:
                valid = (_vrmlCutNode == NULL);
                if (node->getType() == DUNE_VRML_SCENE)
                    valid = true;
                break;
              case KAMBI_KAMBI_APPEARANCE:
                valid = node->getType() == VRML_SHAPE;
                break;
              case KAMBI_KAMBI_OCTREE_PROPERTIES:
                valid = (node->getType() == KAMBI_KAMBI_NAVIGATION_INFO) ||
                        (node->getType() == VRML_SHAPE);
                break;
              case KAMBI_RENDERED_TEXTURE:
                valid = (node->getType() == VRML_APPEARANCE) ||
                        (node->getType() == KAMBI_KAMBI_APPEARANCE);
                break;
              case KAMBI_PROJECTED_TEXTURE_COORDINATE:
                valid = (node->findValidFieldType(GENERATED_TEXTURE_COORDINATE_NODE | 
                                                  TEXTURE_COORDINATE_NODE) 
                        != -1);
                break;
              case KAMBI_MULTI_GENERATED_TEXTURE_COORDINATE:
                if (node->getType() == 
                                     KAMBI_MULTI_GENERATED_TEXTURE_COORDINATE) {
                    valid = false;
                    break;
                }
                valid = (node->findValidFieldType(GENERATED_TEXTURE_COORDINATE_NODE)
                         != -1);
                break;
              default:
                valid = node->findValidFieldType(buttons[i].type) != -1;
            }
            if (valid != buttons[i].enabled) {
                swMenuSetFlags(_menu, buttons[i].id, SW_MENU_DISABLED, 
                               valid ? 0 : SW_MENU_DISABLED);
                swToolbarSetButtonFlags(toolbar, i, SW_TB_DISABLED,
                                        valid ? 0 : SW_TB_DISABLED);
                buttons[i].enabled = valid;                
            }
        }
}

void
MainWindow::UpdateToolbarSelection(void)
{
    Node *node = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();

    UpdateToolbar(_nodeToolbar1, node, field, buttons1, ARRAYSIZE(buttons1));
    UpdateToolbar(_nodeToolbar2, node, field, buttons2, ARRAYSIZE(buttons2));
    UpdateToolbar(_nodeToolbar3, node, field, buttons3, ARRAYSIZE(buttons3));
    UpdateToolbar(_nodeToolbarVRML200x, node, field, buttonsVRML200x, 
                  ARRAYSIZE(buttonsVRML200x));
    UpdateToolbar(_nodeToolbarX3DComponents1, node, field, 
                  buttonsX3DComponents1, ARRAYSIZE(buttonsX3DComponents1));
    UpdateToolbar(_nodeToolbarX3DComponents2, node, field, 
                  buttonsX3DComponents2, ARRAYSIZE(buttonsX3DComponents2));
    UpdateToolbar(_nodeToolbarX3DComponents3, node, field, 
                  buttonsX3DComponents3, ARRAYSIZE(buttonsX3DComponents3));
    UpdateToolbar(_nodeToolbarX3DComponents4, node, field, 
                  buttonsX3DComponents4, ARRAYSIZE(buttonsX3DComponents4));
    UpdateToolbar(_nodeToolbarScripted, node, field, buttonsScripted, 
                  ARRAYSIZE(buttonsScripted));
    UpdateToolbar(_nodeToolbarCover, node, field, buttonsCover, 
                  ARRAYSIZE(buttonsCover));
    UpdateToolbar(_nodeToolbarKambi, node, field, buttonsKambi, 
                  ARRAYSIZE(buttonsKambi));
    UpdateMenuCoverNodes();
    UpdateMenuKambiNodes();

    swMenuSetFlags(_menu, ID_INTERACTION, SW_MENU_DISABLED,
                   node->supportInteraction() ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_standardToolbar, _interactionIconPos, 
                            SW_TB_DISABLED, 
                            node->supportInteraction() ? 0 : SW_TB_DISABLED);

    swMenuSetFlags(_menu, ID_ANIMATION, SW_MENU_DISABLED,
                   node->supportAnimation() ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_standardToolbar, _animationIconPos, 
                            SW_TB_DISABLED, 
                            node->supportAnimation() ? 0 : SW_TB_DISABLED);

    bool isRoot = (node == _scene->getRoot());
    static bool oldIsRoot = !isRoot;
    bool parentIsRoot = isRoot;
    if (node->hasParent())
        parentIsRoot = isRoot ? true : (node->getParent() == _scene->getRoot());

    swMenuSetFlags(_menu, ID_HELP_SELECTION_PLACEHOLDER, SW_MENU_DISABLED, 
                   isRoot ? SW_MENU_DISABLED : 0);

    if (TheApp->is4Kids()) {
        bool loop = false;
        if (node->getType() == VRML_TIME_SENSOR)
            loop = ((NodeTimeSensor *)node)->loop()->getValue();
        swMenuSetFlags(_menu, ID_CHANGE_ENABLE_ANIMATION, SW_MENU_DISABLED, 
            (node->getType() == VRML_TIME_SENSOR) && !loop ? 
            0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_DISABLE_ANIMATION, SW_MENU_DISABLED, 
            (node->getType() == VRML_TIME_SENSOR) && loop ?
            0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_ANIMATION_TIME, SW_MENU_DISABLED, 
            (node->getType() == VRML_TIME_SENSOR) ? 0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_ANIMATION_TIME, SW_MENU_DISABLED, 
            (node->getType() == VRML_TIME_SENSOR) ? 0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_MATERIAL_DIFFUSE, SW_MENU_DISABLED, 
            (node->getType() == VRML_MATERIAL) ? 0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_MATERIAL_EMISSIVE, SW_MENU_DISABLED, 
            (node->getType() == VRML_MATERIAL) ? 0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_MATERIAL_SPECULAR, SW_MENU_DISABLED, 
            (node->getType() == VRML_MATERIAL) ? 0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_MATERIAL_TRANSPARENCY, SW_MENU_DISABLED,
            (node->getType() == VRML_MATERIAL) ? 0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_MATERIAL_SHININESS, SW_MENU_DISABLED, 
            (node->getType() == VRML_MATERIAL) ? 0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_IMAGE_REPEAT, SW_MENU_DISABLED, 
            (node->getType() == VRML_APPEARANCE) || 
            (node->getType() == VRML_TEXTURE_TRANSFORM) ? 0 : SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_CHANGE_ONE_TEXT, SW_MENU_DISABLED, 
            (node->getType() == VRML_TEXT) ? 0 : SW_MENU_DISABLED);
    }

    swMenuSetFlags(_menu, ID_MOVE_SIBLING_UP, SW_MENU_DISABLED,
                   (node->getPrevSiblingIndex() == -1) ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_MOVE_SIBLING_DOWN, SW_MENU_DISABLED,
                   (node->getNextSiblingIndex() == -1) ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_MOVE_SIBLING_FIRST, SW_MENU_DISABLED,
                   (node->getPrevSiblingIndex() == -1) ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_MOVE_SIBLING_LAST, SW_MENU_DISABLED,
                   (node->getNextSiblingIndex() == -1) ? SW_MENU_DISABLED : 0);

    if (TheApp->is4Catt()) {
        swMenuSetFlags(_menu, ID_TWO_SIDED, SW_MENU_DISABLED, 
            node->hasTwoSides() ? 0 : SW_MENU_DISABLED);
        if (node->hasTwoSides())
            swMenuSetFlags(_menu, ID_TWO_SIDED, SW_MENU_CHECKED, 
                 node->isDoubleSided() ? SW_MENU_CHECKED : 0);
        else 
            swMenuSetFlags(_menu, ID_TWO_SIDED, SW_MENU_CHECKED, 0); 
        swMenuSetFlags(_menu, ID_CHANGE_SIDE, SW_MENU_DISABLED, 
            node->hasTwoSides() ? 0 : SW_MENU_DISABLED);
    }

    UpdateObjectEdit(node);

    int disablePaste = 1;
    if (TheApp->getClipboardNode()) {
        if (field == -1) {
            field = node->findValidField(TheApp->getClipboardNode());
        }
        if (field != -1) {
            disablePaste = 0;
        }
    }

    swToolbarSetButtonFlags(_standardToolbar, _editPasteIconPos, SW_TB_DISABLED,
                            disablePaste ? SW_TB_DISABLED : 0);
    swMenuSetFlags(_menu, ID_DUNE_EDIT_PASTE, SW_MENU_DISABLED, 
                   disablePaste ? SW_MENU_DISABLED : 0);

    if (isRoot != oldIsRoot) {
#ifndef HAVE_CUT
        swMenuSetFlags(_menu, ID_DUNE_EDIT_CUT, SW_MENU_DISABLED, 
                       isRoot ? SW_MENU_DISABLED : 0);
        swToolbarSetButtonFlags(_standardToolbar, _editCutIconPos, SW_TB_DISABLED,
                                isRoot ? SW_TB_DISABLED : 0);
#endif
         swMenuSetFlags(_menu, ID_DUNE_EDIT_COPY, SW_MENU_DISABLED, 
                        isRoot ? SW_MENU_DISABLED : 0);
         swToolbarSetButtonFlags(_standardToolbar, _editCopyIconPos, SW_TB_DISABLED,
                                 isRoot ? SW_TB_DISABLED : 0);
         swMenuSetFlags(_menu, ID_DUNE_EDIT_COPY_BRANCH_TO_ROOT, SW_MENU_DISABLED, 
                        isRoot ? SW_MENU_DISABLED : 0);
         swMenuSetFlags(_menu, ID_DUNE_EDIT_DELETE, SW_MENU_DISABLED, 
                        isRoot ? SW_MENU_DISABLED : 0);
         swToolbarSetButtonFlags(_standardToolbar, _editDeleteIconPos, 
                                 SW_TB_DISABLED, isRoot ? SW_TB_DISABLED : 0);
         swMenuSetFlags(_menu, ID_DUNE_EDIT_DEF, SW_MENU_DISABLED, 
                        isRoot ? SW_MENU_DISABLED : 0);
    }

    swMenuSetFlags(_menu, ID_DUNE_EDIT_USE, SW_MENU_DISABLED, 
                   !_scene->canUse(node, field) ? SW_MENU_DISABLED : 0);

    swMenuSetFlags(_menu, ID_SET_DEFAULT, SW_MENU_DISABLED, 
                   node->maySetDefault() ? 0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_FLATTEN_X, SW_MENU_DISABLED, 
                   node->canFlatten() ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_FLATTEN_Y, SW_MENU_DISABLED, 
                   node->canFlatten() ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_FLATTEN_Z, SW_MENU_DISABLED, 
                   node->canFlatten() ? 0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_FLATTEN_X_0, SW_MENU_DISABLED, 
                   node->canFlatten() ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_FLATTEN_Y_0, SW_MENU_DISABLED, 
                   node->canFlatten() ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_FLATTEN_Z_0, SW_MENU_DISABLED, 
                   node->canFlatten() ? 0 : SW_MENU_DISABLED);



    swMenuSetFlags(_menu, ID_BRANCH_TO_PARENT, SW_MENU_DISABLED, 
                   parentIsRoot || 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);

    swMenuSetFlags(_menu, ID_BRANCH_TO_TRANSFORM_SELECTION, SW_MENU_DISABLED, 
                   node->getType() == VRML_TRANSFORM ? 0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_BRANCH_TO_GROUP, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_BRANCH_TO_TRANSFORM, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_BRANCH_TO_COLLISION, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_BRANCH_TO_COLLISIONPROXY, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_BRANCH_TO_ANCHOR, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_BRANCH_TO_BILLBOARD, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_BRANCH_TO_LOD, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_BRANCH_TO_SWITCH, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);
    swMenuSetFlags(_menu, ID_BRANCH_TO_INLINE, SW_MENU_DISABLED, 
                   node->isInvalidChildNode() ? SW_MENU_DISABLED : 0);

    swMenuSetFlags(_menu, ID_ARRAY, SW_MENU_DISABLED, 
                   (node->hasParent()) && (!node->isInvalidChildNode()) &&
                   (node->getParent()->getType() == VRML_GROUP ||
                    node->getParent()->getType() == VRML_TRANSFORM) ? 
                   0 : SW_MENU_DISABLED);

    bool canCenter = false;
    if (node->hasBoundingBox())
        if ((node->hasParent()) && (!parentIsRoot)) {
            Node *checkNode = node->getParent();
            if (checkNode->getType() == VRML_SHAPE) {
                if (checkNode->hasParent()) {
                    checkNode = checkNode->getParent();
                    if (checkNode->getType() == VRML_TRANSFORM)
                        canCenter = true;
                }
            }
        }

    swMenuSetFlags(_menu, ID_CENTER_TO_MID, SW_MENU_DISABLED, 
                   canCenter ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_CENTER_TO_MAXX, SW_MENU_DISABLED, 
                   canCenter ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_CENTER_TO_MAXY, SW_MENU_DISABLED, 
                   canCenter ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_CENTER_TO_MAXZ, SW_MENU_DISABLED, 
                   canCenter ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_CENTER_TO_MINX, SW_MENU_DISABLED, 
                   canCenter ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_CENTER_TO_MINY, SW_MENU_DISABLED, 
                   canCenter ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_CENTER_TO_MINZ, SW_MENU_DISABLED, 
                   canCenter ? 0 : SW_MENU_DISABLED);


    swMenuSetFlags(_menu, ID_SET_OPTIMIZE, SW_MENU_DISABLED,
                   node->getType() == VRML_INDEXED_FACE_SET ? 
                   0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_TRIANGULATE, SW_MENU_DISABLED,
                   node->getType() == VRML_INDEXED_FACE_SET ? 
                   0 : SW_MENU_DISABLED);

    bool canDegreeElevate = false;
    switch (node->getType()) {
      case VRML_NURBS_CURVE:
      case DUNE_SUPER_EXTRUSION:
      case DUNE_SUPER_REVOLVER:
        canDegreeElevate = true;
    }
    swMenuSetFlags(_menu, ID_DEGREE_ELEVATE_UP, SW_MENU_DISABLED,
                   canDegreeElevate ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_DEGREE_ELEVATE_DOWN, SW_MENU_DISABLED,
                   canDegreeElevate ? 0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_U_DEGREE_ELEVATE_UP, SW_MENU_DISABLED,
                   node->getType() == VRML_NURBS_SURFACE ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_U_DEGREE_ELEVATE_DOWN, SW_MENU_DISABLED,
                   node->getType() == VRML_NURBS_SURFACE ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_V_DEGREE_ELEVATE_UP, SW_MENU_DISABLED,
                   node->getType() == VRML_NURBS_SURFACE ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_V_DEGREE_ELEVATE_DOWN, SW_MENU_DISABLED,
                   node->getType() == VRML_NURBS_SURFACE ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_LINEAR_UKNOT, SW_MENU_DISABLED,
                   node->getType() == VRML_NURBS_SURFACE ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_LINEAR_VKNOT, SW_MENU_DISABLED,
                   node->getType() == VRML_NURBS_SURFACE ? 0 : SW_MENU_DISABLED);

    bool canPipe = false;
    Node *fieldViewNode = NULL;
    int fieldViewField = -1;
    if (_fieldView->isFieldView()) {
        fieldViewNode = ((FieldView *)_fieldView)->GetSelectedNode();
        fieldViewField = ((FieldView *)_fieldView)->GetSelectedField();
    }
    if (fieldViewNode && (fieldViewField > -1))
        canPipe = true;
    swMenuSetFlags(_menu, ID_PIPE, SW_MENU_DISABLED, 
                   canPipe ? 0 : SW_MENU_DISABLED);

    bool toNurbs = false;
    if (node->hasParent()) {
        Node *parent = node->getParent();
        if (isToNurbsAllowedParent(parent)) {
            if (node->getType() == VRML_CYLINDER)
                toNurbs = true;
            if (node->getType() == VRML_CONE)
                toNurbs = true;
            if (node->getType() == VRML_SPHERE)
                toNurbs = true;
            if (node->getType() == VRML_BOX)
                toNurbs = true;
            if (node->getType() == VRML_NURBS_CURVE)
                toNurbs = true;
            if (node->getType() == DUNE_SUPER_ELLIPSOID)
                toNurbs = true;
            if (node->getType() == DUNE_SUPER_EXTRUSION)
                toNurbs = true;
            if (node->getType() == DUNE_SUPER_SHAPE)
                toNurbs = true;
            if (node->getType() == DUNE_SUPER_REVOLVER)
                toNurbs = true;
        }
    }
    swMenuSetFlags(_menu, ID_TO_NURBS, SW_MENU_DISABLED, 
                   toNurbs ? 0 : SW_MENU_DISABLED);    
    if (TheApp->is4Kids()) {
        swMenuSetFlags(_menu, ID_TO_NURBS_4KIDS, SW_MENU_DISABLED, 
                       toNurbs ? 0 : SW_MENU_DISABLED);    
        swToolbarSetButtonFlags(_standardToolbar, _toNurbs4KidsIconPos, 
                                SW_TB_DISABLED, 
                                toNurbs ? 0 : SW_TB_DISABLED);
    }

    swMenuSetFlags(_menu, ID_TO_NURBS_CURVE, SW_MENU_DISABLED, 
                   (node->getType() == DUNE_SUPER_EXTRUSION) || 
                   (node->getType() == DUNE_SUPER_REVOLVER) ? 
                   0 : SW_MENU_DISABLED);    

    swMenuSetFlags(_menu, ID_TO_SUPER_EXTRUSION, SW_MENU_DISABLED, 
                   node->getType() == VRML_NURBS_CURVE ? 
                   0 : SW_MENU_DISABLED);    

    swMenuSetFlags(_menu, ID_TO_SUPER_REVOLVER, SW_MENU_DISABLED, 
                   node->getType() == VRML_NURBS_CURVE ? 
                   0 : SW_MENU_DISABLED);    

    swMenuSetFlags(_menu, ID_TO_EXTRUSION, SW_MENU_DISABLED, 
                   node->canConvertToExtrusion() ? 0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_TO_INDEXED_FACESET, SW_MENU_DISABLED, 
                   node->canConvertToIndexedFaceSet() ? 0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_TO_INDEXED_TRIANGLESET, SW_MENU_DISABLED, 
                   node->canConvertToIndexedTriangleSet() ? 0 : 
                   SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_TO_TRIANGLESET, SW_MENU_DISABLED, 
                   node->canConvertToTriangleSet() ? 0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_TO_INDEXED_LINESET, SW_MENU_DISABLED, 
                   node->canConvertToIndexedLineSet() ||
                   (node->getType() == VRML_INDEXED_FACE_SET) ? 
                   0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_TO_POINTSET, SW_MENU_DISABLED, 
                   (node->getType() == VRML_INDEXED_LINE_SET) ? 
                   0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_TO_POSITION_INTERPOLATOR, SW_MENU_DISABLED, 
                   node->canConvertToPositionInterpolator() ? 
                   0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_TO_ORIENTATION_INTERPOLATOR_XZ, SW_MENU_DISABLED, 
                   node->canConvertToOrientationInterpolator() ? 
                   0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_TO_ORIENTATION_INTERPOLATOR_XY, SW_MENU_DISABLED, 
                   node->canConvertToOrientationInterpolator() ? 
                   0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_TO_ORIENTATION_INTERPOLATOR_YZ, SW_MENU_DISABLED, 
                   node->canConvertToOrientationInterpolator() ? 
                   0 : SW_MENU_DISABLED);

//    swMenuSetFlags(_menu, ID_SHOW_JOINT_LIKE_HANDLES, SW_MENU_DISABLED, 
//                   _scene->showJoints() ? 0 : SW_MENU_DISABLED);
//    swToolbarSetButtonFlags(_standardToolbar, _showJointLikeHandlesIconPos, 
//                            SW_TB_DISABLED, 
//                            _scene->showJoints() ? 0 : SW_TB_DISABLED);

    setColorCircleIcon();

    oldIsRoot = isRoot;
}



void
MainWindow::RefreshRecentFileMenu(void)
{
    int i, n = TheApp->GetNumRecentFiles();

    // insert a placeholder (if file 1 is there)
    swInsertMenuItem(_menu, ID_DUNE_FILE_MRU_FILE1, "",
                     ID_DUNE_FILE_MRU_PLACEHOLDER);
    swMenuSetFlags(_menu, ID_DUNE_FILE_MRU_PLACEHOLDER, SW_MENU_DISABLED,
                   SW_MENU_DISABLED);
    
    // delete all recent-file menus
    for (i = 0; i < 16; i++) {
        swDeleteMenuItem(_menu, ID_DUNE_FILE_MRU_FILE1 + i);
    }
    
    // insert recent-file menus
    if (n > 0) {
        for (i = 0; i < n; i++) {
            char buf[1024];
            int id = ID_DUNE_FILE_MRU_FILE1 + i;
            mysnprintf(buf, 1023, "&%d %s", i + 1,
                       (const char *) TheApp->GetRecentFile(i));
            swInsertMenuItem(_menu, ID_DUNE_FILE_MRU_PLACEHOLDER, buf, id);
        }

        // remove the placeholder
        swDeleteMenuItem(_menu, ID_DUNE_FILE_MRU_PLACEHOLDER);
    }
}

void
MainWindow::RefreshProtoMenu()
{
    // avoid extra menuitems for reduced menus 
    // under M$Windows this would add unwanted items to the menubar 
    if (TheApp->is4Kids() ||  TheApp->is4Catt())
        return;
 
    int i;
    bool hasPlaceHolder = false;
    int n = _scene->getNumProtoNames();

    // avoid overflow of MenuItem ID's
    if (n > 0xFFF)
       n = 0xFFF;

    // insert recent-file menus
    if (n > 0) {
        int menuSize = _protoMenu.size();
        for (i = 0; i < menuSize; i++)
            _protoMenu[i].disabled = true;
        for (i = 0; i < _scene->getNumProtoNames(); i++) {
            const char *protoName = _scene->getProtoName(i);
            bool found = false;
            for (int j = 0; j < _protoMenu.size(); j++) {
                if (strcmp(protoName, _protoMenu[j].protoName) == 0) {
                    found = true;
                    _protoMenu[j].disabled = false;
                    break;
                }
            }
            if (found)
                continue;

            if (!hasPlaceHolder) {
                // insert a placeholder
                swInsertMenuItem(_menu, ID_PROTO_MRU_1, " ",
                                 ID_PROTO_MRU_PLACEHOLDER);
                swMenuSetFlags(_menu, ID_PROTO_MRU_PLACEHOLDER, 
                               SW_MENU_DISABLED, SW_MENU_DISABLED);
                hasPlaceHolder = true;
            }
     
            char buf[1024];
            int id = ID_PROTO_MRU_1 + menuSize;
            mysnprintf(buf, 1023, "&%d %s", menuSize + 1, protoName);
            _protoMenu[menuSize].protoName = "";
            _protoMenu[menuSize].protoName += protoName;
            _protoMenu[menuSize].id = id;
            _protoMenu[menuSize].disabled = false;
            swInsertMenuItem(_menu, ID_PROTO_MRU_PLACEHOLDER, buf, id);
        }        
        for (i = 0; i < _protoMenu.size(); i++)
            swMenuSetFlags(_menu, _protoMenu[i].id, SW_MENU_DISABLED,
                           _protoMenu[i].disabled ? SW_MENU_DISABLED : 0);
    }

    // remove the placeholder
    if (hasPlaceHolder)
        swDeleteMenuItem(_menu, ID_PROTO_MRU_PLACEHOLDER);
}

void MainWindow::RefreshHelpSelection()
{
    // avoid extra menuitems for reduced menus 
    // under M$Windows this would add unwanted items to the menubar 
    if (TheApp->is4Kids() ||  TheApp->is4Catt())
        return;

    // insert a placeholder
    Node *node = _scene->getSelection()->getNode();
    swInsertMenuItem(_menu, ID_HELP_SELECTION, " ",
                            ID_HELP_SELECTION_PLACEHOLDER);

    swMenuSetFlags(_menu, ID_HELP_SELECTION_PLACEHOLDER, SW_MENU_DISABLED,
                   SW_MENU_DISABLED);
    
    swDeleteMenuItem(_menu, ID_HELP_SELECTION);
    swInsertMenuItem(_menu, ID_HELP_SELECTION_PLACEHOLDER,
                     (const char*) node->getProto()->getName(_scene->isX3d()), 
                     ID_HELP_SELECTION);

    // remove the placeholder
    swDeleteMenuItem(_menu, ID_HELP_SELECTION_PLACEHOLDER);
}

Node * 
MainWindow::CreateNode(Node *node)
{
    Node *selectionNode = _scene->getSelection()->getNode();
    int selectionField = _scene->getSelection()->getField();

    Node *targetNode = _scene->getRoot();
    int targetField = _scene->getRootField();

    int destField = _scene->getDestField(node, selectionNode, selectionField);
    if ((node->getType() == VRML_SHAPE) && 
        (selectionNode->getType() == X3D_COLLIDABLE_SHAPE)) {
        NodeCollidableShape *coll = (NodeCollidableShape *)selectionNode;
        if (coll->shape()->getValue() == NULL) {
            targetNode = selectionNode;
            targetField = coll->shape_Field();
        }
    } else if ((destField > -1) && (selectionNode != targetNode) && 
               (node->getType() != VRML_VIEWPOINT)) {
        targetNode = selectionNode;
        targetField = destField;
    }
    
    _scene->execute(new MoveCommand(node, NULL, -1, targetNode, targetField));
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
    return node;
}

Node *
MainWindow::CreateNode(const char *type)
{
    Node *node = _scene->createNode(type);
    if (node == NULL)
        return NULL;
    return CreateNode(node);
}

void MainWindow::CreateGeometryNode(Node * node, bool emissiveDefaultColor)
{
    Node *selection = _scene->getSelection()->getNode();
    if (selection->getType() == VRML_SHAPE) {
        NodeShape *shape = (NodeShape *)selection;
        if (shape->geometry()->getValue() == NULL) {
            MoveCommand *command = new MoveCommand(node, NULL, -1, selection, 
                                                   shape->geometry_Field());
            command->execute();                       
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
            return;
        }
    }
    if (selection->getType() == X3D_PARTICLE_SYSTEM) {
        NodeParticleSystem *shape = (NodeParticleSystem *)selection;
        if (shape->geometry()->getValue() == NULL) {
            MoveCommand *command = new MoveCommand(node, NULL, -1, selection, 
                                                   shape->geometry_Field());
            command->execute();                       
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
            return;
        }
    }
    if (node->getType() == VRML_NURBS_SURFACE) {
        if (selection->getType() == X3D_NURBS_SET) {
            NodeNurbsSet *nurbsSet = (NodeNurbsSet *)selection;
            MoveCommand *command = new MoveCommand(node, NULL, -1,
                                                   nurbsSet,
                                                   nurbsSet->geometry_Field());
            command->execute();                       
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
            return;
        }            
    }
    NodeShape *nShape = (NodeShape *) _scene->createNode("Shape");
    nShape->createNewAppearance(emissiveDefaultColor);
    nShape->geometry(new SFNode(node));
    if (selection->getType() == X3D_COLLIDABLE_SHAPE) {
        NodeCollidableShape *coll = (NodeCollidableShape *)selection;
        if (coll->shape()->getValue() == NULL) {
            MoveCommand *command = new MoveCommand(nShape, NULL, -1,
                                                   coll,
                                                   coll->shape_Field());
            command->execute();                       
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
            return;            
        }
    }            
    if (selection->getType() == X3D_CAD_FACE) {
        NodeCADFace *face = (NodeCADFace *)selection;
        if (face->shape()->getValue() == NULL) {
            MoveCommand *command = new MoveCommand(nShape, NULL, -1,
                                                   face,
                                                   face->shape_Field());
            command->execute();                       
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
            return;            
        }
    }            
    NodeTransform *nTransform = (NodeTransform *)
                                _scene->createNode("Transform");
    NodeViewpoint *camera = _scene->getCamera();
    nTransform->children(new MFNode(new NodeList(nShape)));
    Node *transformNode = CreateNode(nTransform);
    bool parentIsRoot = false;
    if (transformNode->hasParent())
        if (transformNode->getParent() == _scene->getRoot())
            parentIsRoot = true;
    if (parentIsRoot) 
        if (camera) {
            SFRotation *sfRotation = camera->orientation();
            Quaternion quad = sfRotation->getQuat();
            SFVec3f *sfPosition = camera->position();
            Vec3f *vec = new Vec3f(sfPosition->getValue()[0],
                                   sfPosition->getValue()[1], 
                                   sfPosition->getValue()[2]);
            Vec3f ten(0, 0, -10);
            *vec += ten * quad;
            nTransform->rotation(new SFRotation(*sfRotation));
            if (TheApp->getCreateAtZero(0))
                (*vec).x = 0;
            if (TheApp->getCreateAtZero(1))
                (*vec).y = 0;
            if (TheApp->getCreateAtZero(2))
                (*vec).z = 0;
            nTransform->translation(new SFVec3f(*vec));
        }
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

void MainWindow::CreateGeometryNode(const char *type, bool emissiveDefaultColor)
{
    CreateGeometryNode(_scene->createNode(type), emissiveDefaultColor);
}

void MainWindow::InsertNodeByName() 
{
    OneTextDialog dlg(_wnd, IDD_NODE_BY_NAME, "", NULL);
    if (dlg.DoModal() == IDCANCEL)
        return;
    const char* nodeName = dlg.GetValue();
    if (CreateNode(nodeName) == NULL)
        TheApp->MessageBox(IDS_UNKNOWN_NODE, nodeName);

}

Node *
MainWindow::getInsertNode(Node *node)
{
    Node *parentNode = _scene->getRoot();
    if (node->hasParent())
        parentNode = node->getParent();
    while ((parentNode->getType() != VRML_ANCHOR) &&
           (parentNode->getType() != VRML_BILLBOARD) &&
           (parentNode->getType() != VRML_COLLISION) &&
           (parentNode->getType() != VRML_GROUP) &&
           (parentNode->getType() != VRML_TRANSFORM) &&
           (parentNode->getType() != DUNE_VRML_SCENE)) {
        if (parentNode->hasParent()) {
            parentNode = parentNode->getParent();
            if (parentNode == _scene->getRoot())
                break;
        } else {
            parentNode = _scene->getRoot();
            break;
        }
    }
    return parentNode;
}
    
void
MainWindow::CreateAnimation(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node == _scene->getRoot())
        return;
    if (!node->supportAnimation())
        return;
    AnimationDialog dlg(_wnd, node);
    if (dlg.DoModal() == IDCANCEL)
        return;
    Array<int> eventInFields = dlg.getEventInFields();
    Array<int> eventInTypes = dlg.getEventInTypes();
    Array<bool> eventInIsAnimated = dlg.getEventInIsAnimated();

    Node *insertNode = getInsertNode(node);

    bool animateSomething = false;
    for (int i = 0 ; i < eventInFields.size(); i++) 
        if (eventInIsAnimated[i]) {
            animateSomething = true;
            break;
        }

    if (animateSomething) {
        _scene->setSelection(insertNode);
        NodeTimeSensor *timeSensor = dlg.getTimeSensor();
        if (timeSensor == NULL) {
            timeSensor = (NodeTimeSensor *) CreateNode("TimeSensor");
            timeSensor->cycleInterval(new SFTime(dlg.getTimeSensorSeconds()));
            timeSensor->loop(new SFBool(true));
        }
        for (int i = 0 ; i < eventInFields.size(); i++) {
            if (eventInIsAnimated[i]) {
                _scene->setSelection(insertNode);
                Node* interpolator = NULL;
                switch (eventInTypes[i]) {
                  case SFCOLOR:
                    interpolator = CreateNode("ColorInterpolator"); 
                    break;
                  case MFVEC2F:
                    interpolator = CreateNode("CoordinateInterpolator2D");
                    break;
                  case MFVEC3F:
                    {
                    const char *mfvec3finterpolator;                     
                    if ((node->getType() == VRML_NORMAL) && 
                        (eventInFields[i] == 
                         ((NodeNormal *) node)->vector_Field()))
                        mfvec3finterpolator = "NormalInterpolator";
                    else
                        mfvec3finterpolator = "CoordinateInterpolator";
                    interpolator = CreateNode(mfvec3finterpolator);
                    break;
                    }
                  case SFVEC2F:
                    interpolator = CreateNode("PositionInterpolator2D"); 
                    break;
                  case SFVEC3F:
                    interpolator = CreateNode("PositionInterpolator"); 
                    break;
                  case SFROTATION:
                    interpolator = CreateNode("OrientationInterpolator");
                    break;
                  case SFFLOAT:
                    interpolator = CreateNode("ScalarInterpolator"); 
                    break;
                }
                if (interpolator == NULL)
                    continue;
                _scene->execute(new RouteCommand(timeSensor, 
                      timeSensor->fraction_changed_Field(), 
                      interpolator,
                      interpolator->getProto()->lookupEventIn("set_fraction")));
                _scene->execute(new RouteCommand(interpolator, 
                      interpolator->getProto()->lookupEventOut("value_changed"),
                      node, eventInFields[i]));
            }
        }
    if (TheApp->is4Kids())
        ShowView(PW_BOTTOM, _channelView, ID_DUNE_VIEW_CHANNEL_VIEW, 
                 "ShowChannelView");
    }
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
 }


void
MainWindow::CreateInteraction(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node == _scene->getRoot())
        return;
    if (!node->supportInteraction())
        return;
    InteractionDialog dlg(_wnd, node);
    if (dlg.DoModal() == IDCANCEL)
        return;
    Array<RouteData> routeData = dlg.getRouteData();
    Array<bool> eventInIsInteractive = dlg.getEventInIsInteractive();
    
    bool makeInteraction = false;
    for (int i = 0 ; i < routeData.size(); i++) 
        if (eventInIsInteractive[i]) {
            makeInteraction = true;
            break;
        }

    Node *insertNode = getInsertNode(node);

    Array<Node *> alreadyUsedSensors;
    if (makeInteraction) {
        Node *dlgSensor = dlg.getSensor();
        for (int i = 0 ; i < routeData.size(); i++) {
            if (eventInIsInteractive[i]) {
                Node *sensor = NULL;
                if (dlgSensor != NULL) 
                   sensor = dlgSensor;
                else {                
                    bool x3d = _scene->isX3d();
                    for (int j = 0; j < alreadyUsedSensors.size(); j++)
                        if (strcmp(alreadyUsedSensors[j]->getProto()->
                                   getName(x3d),
                                   routeData[i].proto->getName(x3d)) == 0)
                            sensor = alreadyUsedSensors[j];
                    if (sensor == NULL) {
                        _scene->setSelection(insertNode);
                        sensor = CreateNode(routeData[i].proto->
                                                    getName(x3d)); 
                        alreadyUsedSensors.append(sensor);
                    }
                }
                _scene->execute(new RouteCommand(sensor, 
                                                 routeData[i].eventOutField,
                                                 node, 
                                                 routeData[i].eventInField));
            }
        }
    }
}

void
MainWindow::EditScript(Node* oldNode)
{
    ScriptDialog dlg(_wnd, oldNode);
    dlg.DoModal();
}

void
MainWindow::CreateScript()
{
    Node *node = new NodeScript(_scene);
    EditScript(node);
    _scene->execute(new MoveCommand(node, NULL, -1, _scene->getRoot(), 
                                    _scene->getRootField()));
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

bool
MainWindow::isEditorInUse(bool errormessage)
{
    bool editorInUse = false;
    int id = -1;

    if (_scriptEditorInUse) {
        id = IDS_SCRIPT_EDITOR_IN_USE_ERROR;
        editorInUse = true;
    }
    if (_textEditorInUse) {
        id = IDS_TEXT_EDITOR_IN_USE_ERROR;
        editorInUse = true;
    }
    if (_imageEditorInUse) { 
        id = IDS_IMAGE_EDITOR_IN_USE_ERROR;
        editorInUse = true;
    }
    if (_soundEditorInUse) { 
        id = IDS_SOUND_EDITOR_IN_USE_ERROR;
        editorInUse = true;
    }
    if (_movieEditorInUse) { 
        id = IDS_MOVIE_EDITOR_IN_USE_ERROR;
        editorInUse = true;
    }
    
    if (id != -1)
        if (errormessage)
            TheApp->MessageBoxId(id);

    return editorInUse;
}

void
MainWindowScriptEditorReadyCallback(void *data)
{
    MainWindow *mainWindow = (MainWindow *) data;
    mainWindow->OnScriptEditorReadyCallback();
}

void
MainWindow::OnScriptEditorReadyCallback(void)
{
    NodeScript *node = (NodeScript *)_scriptEdit->getNode();
    FieldUpdate* hint = new FieldUpdate(node, node->url_Field());
    _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
    delete hint;
    _scriptEditorInUse = false;
    if (_scriptEdit != NULL)
        delete  _scriptEdit;
    UpdateToolbar(ID_OBJECT_EDIT);
}

void
MainWindowTextEditorReadyCallback(void *data)
{
    MainWindow *mainWindow = (MainWindow *) data;
    mainWindow->OnTextEditorReadyCallback();
}

void
MainWindow::OnTextEditorReadyCallback(void)
{
    Node *node = _shaderEdit->getNode();
    int field = -1;
    switch(node->getType()) {
      case X3D_PACKAGED_SHADER:
        field = ((NodePackagedShader *)node)->url_Field();
        break;
      case X3D_SHADER_PROGRAM:
        field = ((NodeShaderProgram *)node)->url_Field();
        break;
      case X3D_SHADER_PART:
        field = ((NodeShaderPart *)node)->url_Field();
        break;
    }
    FieldUpdate* hint = new FieldUpdate(node, field);
    _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
    delete hint;
    _textEditorInUse = false;
    if (_shaderEdit != NULL)
        delete _shaderEdit;
    _shaderEdit = NULL;
    UpdateToolbar(ID_OBJECT_EDIT);
}

void
MainWindowImageTextureEditorReadyCallback(void *data)
{
    MainWindow *mainWindow = (MainWindow *) data;
    mainWindow->OnImageTextureEditorReadyCallback();
}

void
MainWindow::OnImageTextureEditorReadyCallback(void)
{
    NodeImageTexture *node = (NodeImageTexture *)_imageTextureEdit->getNode();
    FieldUpdate* hint = new FieldUpdate(node, node->url_Field());
    _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
    delete hint;
    _imageEditorInUse = false;
    if (_imageTextureEdit != NULL)
        delete  _imageTextureEdit;
    UpdateToolbar(ID_OBJECT_EDIT);
}

void
MainWindowSoundEditorReadyCallback(void *data)
{
    MainWindow *mainWindow = (MainWindow *) data;
    mainWindow->OnSoundEditorReadyCallback();
}

void
MainWindow::OnSoundEditorReadyCallback(void)
{
    NodeAudioClip *node = (NodeAudioClip *)_soundEdit->getNode();
    FieldUpdate* hint = new FieldUpdate(node, node->url_Field());
    _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
    delete hint;
    _soundEditorInUse = false;
    if (_soundEdit != NULL)
        delete  _soundEdit;
    UpdateToolbar(ID_OBJECT_EDIT);
}

void
MainWindowMovieEditorReadyCallback(void *data)
{
    MainWindow *mainWindow = (MainWindow *) data;
    mainWindow->OnMovieEditorReadyCallback();
}

void
MainWindow::OnMovieEditorReadyCallback(void)
{
    NodeMovieTexture *node = (NodeMovieTexture *)_movieEdit->getNode();
    FieldUpdate* hint = new FieldUpdate(node, node->url_Field());
    _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
    delete hint;
    _movieEditorInUse = false;
    if (_movieEdit != NULL)
        delete  _movieEdit;
    UpdateToolbar(ID_OBJECT_EDIT);
}

void
MainWindow::EditUrl()
{
    Node *node = _scene->getSelection()->getNode();
    switch (node->getType()) {
      case VRML_SCRIPT:
        if (isEditorInUse(true))
            return;

        _scriptEditorInUse = true;
        _scriptEdit = new ScriptEdit((NodeScript *)node, _wnd, 
                                     MainWindowScriptEditorReadyCallback, this);
        if (_scriptEdit->edit()) {
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        } else 
            _scriptEditorInUse = false;
        break;
      case X3D_SHADER_PROGRAM:
      case X3D_PACKAGED_SHADER:
      case X3D_SHADER_PART:
        if (isEditorInUse(true))
            return;

        _textEditorInUse = true;
        _shaderEdit = new ShaderEdit(node, _wnd, 
                                     MainWindowTextEditorReadyCallback, this);
        if (_shaderEdit->edit()) {
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        } else 
            _textEditorInUse = false;
        break;
      case VRML_IMAGE_TEXTURE:
        if (isEditorInUse(true))
            return;

        _imageEditorInUse = true;
        _imageTextureEdit = new ImageTextureEdit((NodeImageTexture *)node, 
              _wnd, MainWindowImageTextureEditorReadyCallback, this);
        if (_imageTextureEdit->edit(true, TheApp->is4Kids())) {
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        } else {
            _imageEditorInUse = false;
            node->update();
            _scene->UpdateViews(NULL, UPDATE_REDRAW);
        }
        break;
      case VRML_AUDIO_CLIP:
        if (isEditorInUse(true))
            return;

        _soundEditorInUse = true;
        _soundEdit = new AudioClipEdit((NodeAudioClip *)node, _wnd, 
                                       MainWindowSoundEditorReadyCallback, 
                                       this);
        if (_soundEdit->edit()) {
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        } else 
            _soundEditorInUse = false;
        break;
      case VRML_MOVIE_TEXTURE:
        if (isEditorInUse(true))
            return;

        _movieEditorInUse = true;
        _movieEdit = new MovieTextureEdit((NodeMovieTexture *)node, _wnd, 
                                          MainWindowMovieEditorReadyCallback, 
                                          this);
        if (_movieEdit->edit()) {
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        } else 
            _movieEditorInUse = false;
        break;
    }
}

void
MainWindow::EditObject()
{
    Node *node = _scene->getSelection()->getNode();
    int field = -1;
    NodeUpdate *hint = NULL;
    switch (node->getType()) {
      case VRML_SCRIPT:
      case X3D_SHADER_PROGRAM:
      case X3D_PACKAGED_SHADER:
      case X3D_COMPOSED_SHADER:
        if (_scriptEditorInUse) {
            TheApp->MessageBoxId(IDS_SCRIPT_EDITOR_IN_USE_ERROR);
            return;
        }
        field = _selectedField;
        EditScript(node);
        hint = new NodeUpdate(node, NULL, 0);
        _scene->UpdateViews(NULL, UPDATE_CHANGE_INTERFACE_NODE, (Hint*) hint);
        break;
    }
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

void
MainWindow::CreateViewpoint()
{
    NodeViewpoint *node = (NodeViewpoint *)_scene->createNode("Viewpoint");
    NodeViewpoint *camera = _scene->getCamera();

    node->fieldOfView((SFFloat *)camera->fieldOfView()->copy());
    node->jump((SFBool *)camera->jump()->copy());
    node->orientation((SFRotation *)camera->orientation()->copy());
    node->position((SFVec3f *)camera->position()->copy());
    node->description((SFString *)camera->description()->copy());
    _scene->execute(new MoveCommand(node, NULL, -1, _scene->getRoot(), 
                                    _scene->getRootField()));
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

void
MainWindow::CreateGeoViewpoint()
{
    const char *nodeName = "GeoViewpoint";
    NodeGeoViewpoint *node = (NodeGeoViewpoint *)_scene->createNode(nodeName);
    NodeViewpoint *camera = _scene->getCamera();

    node->fieldOfView((SFFloat *)camera->fieldOfView()->copy());
    node->jump((SFBool *)camera->jump()->copy());
    node->orientation((SFRotation *)camera->orientation()->copy());
    char buf[4096];
    const float *pos = camera->position()->getValue();
    mysnprintf(buf, 4095, "%g %g %g", pos[0], pos[1], pos[2]);
    node->position(new SFString(buf));
    node->description((SFString *)camera->description()->copy());
    _scene->execute(new MoveCommand(node, NULL, -1, _scene->getRoot(), 
                                    _scene->getRootField()));
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

void
MainWindow::CreateElevationGrid()
{
    ElevationGridDialog   dlg(_wnd, 5, 5);
    if (dlg.DoModal() == IDOK) {
        int width = dlg.GetWidth();
        int depth = dlg.GetDepth();
        NodeElevationGrid *node = (NodeElevationGrid *)
                                  _scene->createNode("ElevationGrid");

        float *values = new float[width * depth];
        memset(values, 0, width * depth * sizeof(float));
        node->height(new MFFloat(values, width * depth));
        node->xDimension(new SFInt32(width));
        node->zDimension(new SFInt32(depth));
        CreateGeometryNode(node);
    }
}

void
MainWindow::CreateGeoElevationGrid()
{
    ElevationGridDialog   dlg(_wnd, 5, 5);
    if (dlg.DoModal() == IDOK) {
        int width = dlg.GetWidth();
        int depth = dlg.GetDepth();
        NodeGeoElevationGrid *node = (NodeGeoElevationGrid *)
                                     _scene->createNode("GeoElevationGrid");

        float *values = new float[width * depth];
        memset(values, 0, width * depth * sizeof(float));
        node->height(new MFFloat(values, width * depth));
        node->xDimension(new SFInt32(width));
        node->zDimension(new SFInt32(depth));
        CreateGeometryNode(node);
    }
}

void
MainWindow::CreateNurbsPlane()
{
    int i, j;

    NurbsPlaneDialog   dlg(_wnd, 4, 4, 3, 3);
    if (dlg.DoModal() == IDOK) {
        int uDimension = dlg.GetWidth();
        int vDimension = dlg.GetDepth();
        int uOrder = dlg.GetUDegree() + 1;
        int vOrder = dlg.GetVDegree() + 1;
        NodeNurbsSurface *node = (NodeNurbsSurface *)
                                 _scene->createNode("NurbsSurface");

        float *controlPoints = new float[uDimension * vDimension * 3];
        float *weights = new float[uDimension * vDimension];
        float *uKnots = new float[uDimension + uOrder];
        float *vKnots = new float[vDimension + vOrder];
        // control Points in a list, first for x, second for y, third for z 
        // and so on
        for (j = 0; j < vDimension; j++) {
            for (i = 0; i < uDimension; i++) {
                controlPoints[(j*uDimension + i)*3    ] = (float) i - 0.5 *
                                                          (uDimension - 1.0);
                controlPoints[(j*uDimension + i)*3 + 1] = 0.0f;
                controlPoints[(j*uDimension + i)*3 + 2] = (float) j - 0.5 *
                                                          (vDimension - 1.0);
                weights[j*uDimension + i] = 1.0f;
            }
        }
        //make Bezier-like behaviour of spline in first control point
        // --> let splines start out of that point
        for (i = 0; i < uOrder; i++) {
            uKnots[i] = 0.0f;
        }
        for (i = 0; i < uDimension - uOrder; i++) {
            uKnots[uOrder + i] = (float) (i + 1);
        }
        for (i = 0; i < uOrder; i++) {
            uKnots[uDimension + i] = (float) (uDimension - uOrder + 1);
        }
        //Same as above for v-direction
        for (j = 0; j < vOrder; j++) {
            vKnots[j] = 0.0f;
        }
        for (j = 0; j < vDimension - vOrder; j++) {
            vKnots[vOrder + j] = (float) (j + 1);
        }
        for (j = 0; j < vOrder; j++) {
            vKnots[vDimension + j] = (float) (vDimension - vOrder + 1);
        }
        node->uDimension(new SFInt32(uDimension));
        node->vDimension(new SFInt32(vDimension));
        node->uKnot(new MFFloat(uKnots, uDimension + uOrder));
        node->vKnot(new MFFloat(vKnots, vDimension + vOrder));
        node->uOrder(new SFInt32(uOrder));
        node->vOrder(new SFInt32(vOrder));
        node->solid(new SFBool(false));
        node->ccw(new SFBool(false));
        node->createControlPoints(
              new MFVec3f(controlPoints, uDimension * vDimension * 3));
        node->weight(new MFFloat(weights, uDimension * vDimension));
        CreateGeometryNode(node);
    }
}

void
MainWindow::CreateNurbsCurve2D()
{
    int i;

    Node *selection = _scene->getSelection()->getNode();
    int selectedField = _scene->getSelection()->getField();
    int type = -1;
    bool isValid = false;
    switch (selection->getType()) {
      case X3D_NURBS_SWEPT_SURFACE:
      case X3D_NURBS_SWUNG_SURFACE:
        type = VRML_NURBS_CURVE_2D;
        break;
      case VRML_CONTOUR_2D:
        type = NURBS_CONTROL_CURVE_NODE;
        break;
    }
    if (type == -1)
        return;
    if (selectedField == -1)
        selectedField = selection->findFirstValidFieldType(type);
    if (!selection->validChildType(selectedField, type))
       return;

    OneFloatDialog dlg(_wnd, IDD_NURBS_CURVE_2D_POINTS, 7, 3);
    if (dlg.DoModal() == IDOK) {
        int dimension = dlg.GetValue();
        int degree = 3;
        int order = degree + 1;
        
        NodeNurbsCurve2D *node = (NodeNurbsCurve2D *)
                               _scene->createNode("NurbsCurve2D");       
        float *controlPoints = new float[dimension * 2];
        float *weights = new float[dimension];
        float *knots = new float[dimension + order]; 
        
        for (i=0; i < dimension; i++){
            float point = ((float) i - 0.5 * (dimension - 1.0)) / 
                          (dimension - 1.0) * 2.0;
            controlPoints[(i*2)]   = point;
            controlPoints[(i*2)+1] = 0;
            weights[i] = 1.0f;
        }
     
        for (i = 0; i < order; i++) {
            knots[i] = 0.0f;
            knots[dimension + i] = (float) (dimension - order + 1);
        }
        for (i = 0; i < dimension - order; i++) {
            knots[order + i] = (float) (i + 1);
        }
    
        node->controlPoint(new MFVec2f(controlPoints, dimension * 2));
        node->weight(new MFFloat(weights, dimension));
        node->knot(new MFFloat(knots, dimension + order));
        node->order(new SFInt32(order));
    
        _scene->execute(new MoveCommand(node, NULL, -1, 
                                        selection, selectedField));
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::CreateNurbsCurve()
{
    Node *selectedNode = _scene->getSelection()->getNode();
    int i;

    NurbsCurveDialog dlg(_wnd, 5, 2, 
                         selectedNode->getType() == X3D_NURBS_SWEPT_SURFACE);
    if (dlg.DoModal() == IDOK) {
        int degree = dlg.getDegree();
        int dimension = dlg.getnPoints();
        int direction = dlg.getDirection();

        int order = degree + 1;
        
        NodeNurbsCurve *node = (NodeNurbsCurve *)
                               _scene->createNode("NurbsCurve");       
        float *controlPoints = new float[dimension * 3];
        float *weights = new float[dimension];
        float *knots = new float[dimension + order]; 
        
        for (i=0; i<dimension; i++){
            float point = ((float) i - 0.5 * (dimension - 1.0)) / 
                          (dimension - 1.0) * 2.0;
            controlPoints[(i*3)]   = (direction == 0 ? point : 0);
            controlPoints[(i*3)+1] = (direction == 1 ? point : 0);
            controlPoints[(i*3)+2] = (direction == 2 ? point : 0);
            weights[i] = 1.0f;
        }
     
        for (i = 0; i < order; i++) {
            knots[i] = 0.0f;
            knots[dimension + i] = (float) (dimension - order + 1);
        }
        for (i = 0; i < dimension - order; i++) {
            knots[order + i] = (float) (i + 1);
        }
    
        node->createControlPoints(new MFVec3f(controlPoints, dimension * 3));
        node->weight(new MFFloat(weights, dimension));
        node->knot(new MFFloat(knots, dimension + order));
        node->order(new SFInt32(order));
    
        Node *selection = _scene->getSelection()->getNode();
        int selectedField = _scene->getSelection()->getField();
        bool isGeometry = true;
        if (selection->getType() == X3D_NURBS_SWEPT_SURFACE) {
            NodeNurbsSweptSurface *sweptSurface = (NodeNurbsSweptSurface *)
                                                  selection;
            if (selectedField == -1)
                selectedField = sweptSurface->trajectoryCurve_Field();
            if (sweptSurface->trajectoryCurve_Field() == selectedField)
                isGeometry = false;
        }
        if (isGeometry) {
            NodeShape *nShape = (NodeShape *) _scene->createNode("Shape");
            NodeTransform *nTransform = (NodeTransform *) 
                                        _scene->createNode("Transform");
            NodeAppearance *nAppearance = (NodeAppearance *)
                                          _scene->createNode("Appearance");
            NodeMaterial *nMaterial = (NodeMaterial *) 
                                      _scene->createNode("Material");
            nMaterial->emissiveColor(new SFColor(0.8, 0.8, 0.8));
            nTransform->children(new MFNode(new NodeList(nShape)));
            nShape->geometry(new SFNode(node));
            nShape->appearance(new SFNode(nAppearance));
            nAppearance->material(new SFNode(nMaterial));
            _scene->execute(new MoveCommand(nTransform, NULL, -1, 
                                            _scene->getRoot(),
                                            _scene->getRootField()));
        } else {
            _scene->execute(new MoveCommand(node, NULL, -1, 
                                            selection, selectedField));
        }
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::CreateSuperExtrusion(int numPoints)
{
    int i;

    NurbsCurveDialog dlg(_wnd, (numPoints < 2) ? 5 : numPoints, 2, 1);
    if (dlg.DoModal() == IDOK) {
        int degree = dlg.getDegree();
        int dimension = dlg.getnPoints();
        if (numPoints != -1)
            if (dimension < numPoints)
                return;
        int direction = dlg.getDirection();

        int order = degree + 1;
        
        CreateGeometryNode("SuperExtrusion");
        Node *node = _scene->getSelection()->getNode();
        if (node && (node->getType() == DUNE_SUPER_EXTRUSION)) {
            NodeSuperExtrusion *superExtrusion = (NodeSuperExtrusion *) node;
            float *controlPoints = new float[dimension * 3];
            float *weights = new float[dimension];
            float *knots = new float[dimension + order]; 
            
            for (i = 0; i < dimension; i++){
                float point = (float) i / (float) (dimension - 1.0f);
                controlPoints[(i * 3)]     = (direction == 0 ? point : 0);
                controlPoints[(i * 3) + 1] = (direction == 1 ? point : 0);
                controlPoints[(i * 3) + 2] = (direction == 2 ? point : 0);
                weights[i] = 1.0f;
            }
         
            for (i = 0; i < order; i++) {
                knots[i] = 0.0f;
                knots[dimension + i] = (float) (dimension - order + 1);
            }
            for (i = 0; i < dimension - order; i++) {
                knots[order + i] = (float) (i + 1);
            }
        
            superExtrusion->controlPoint(new MFVec3f(controlPoints, 
                                                     dimension * 3));    
            superExtrusion->weight(new MFFloat(weights, dimension));
            superExtrusion->knot(new MFFloat(knots, dimension + order));
            superExtrusion->order(new SFInt32(order));
            if (TheApp->is4Kids()) {
                float *scale = new float[dimension * 2];
                for (i = 0; i < dimension; i++){
                    scale[i * 2    ] = 1;
                    scale[i * 2 + 1] = 1;
                }
                superExtrusion->scale(new MFVec2f(scale, dimension * 2));    
            }
        }        
    }
}

void
MainWindow::CreateSuperRevolver()
{
    int i;

    int degree = 2;

    OneIntDialog dlg(_wnd, IDD_SUPER_REVOLVER_POINTS, 5, 3, INT_MAX);
    if (dlg.DoModal() == IDCANCEL)
        return;

    int dimension = dlg.GetValue();

    int order = degree + 1;
    
    CreateGeometryNode("SuperRevolver");
    Node *node = _scene->getSelection()->getNode();
    if (node && (node->getType() == DUNE_SUPER_REVOLVER)) {
        NodeSuperRevolver *superRevolver = (NodeSuperRevolver *) node;
        float *controlPoints = new float[dimension * 2];
        float *weights = new float[dimension];
        float *knots = new float[dimension + order]; 
        
        for (i = 0; i < dimension; i++) {
            controlPoints[i * 2] = 1.0f;
            controlPoints[i * 2 + 1] = i / (dimension - 1.0);
            weights[i] = 1.0f;
        }
        controlPoints[0] = 0.0f;
        controlPoints[(dimension - 1) * 2] = 0.0f;
     
        for (i = 0; i < order; i++) {
            knots[i] = 0.0f;
            knots[dimension + i] = (float) (dimension - order + 1);
        }
        for (i = 0; i < dimension - order; i++) {
            knots[order + i] = (float) (i + 1);
        }
    
        superRevolver->controlPoint(new MFVec2f(controlPoints, dimension * 2));
        superRevolver->weight(new MFFloat(weights, dimension));
        superRevolver->knot(new MFFloat(knots, dimension + order));
        superRevolver->order(new SFInt32(order));
    }
}

void
MainWindow::CreateStarFish(int numberArms)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_SHAPE)) {
        NodeSuperShape *superShape = (NodeSuperShape *) node;
        superShape->um(new SFFloat(numberArms));
        superShape->un1(new SFFloat(0.1));
        superShape->un2(new SFFloat(1.7));
        superShape->un3(new SFFloat(1.7));
        superShape->vm(new SFFloat(1.0));
        superShape->vn1(new SFFloat(0.3));
        superShape->vn2(new SFFloat(0.5));
        superShape->vn3(new SFFloat(0.5));
        if (numberArms > 4)
            superShape->uTessellation(new SFInt32(numberArms*9));
        superShape->vTessellation(new SFInt32(8));
    }
}

void
MainWindow::CreateFlower(int numberLeaves)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_SHAPE)) {
        NodeSuperShape *superShape = (NodeSuperShape *) node;
        superShape->um(new SFFloat(numberLeaves));
        superShape->un2(new SFFloat(4.0));
        superShape->un3(new SFFloat(2.0));
        superShape->vm(new SFFloat(2.0));
        superShape->vn1(new SFFloat(1.2));
        superShape->border(new SFFloat(0.0));
    }
}


void
MainWindow::CreateHeart(void)
{
    CreateGeometryNode("SuperRevolver");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_REVOLVER)) {
        NodeSuperRevolver *superRevolver = (NodeSuperRevolver *) node;
        int dimension = 5;        
        int degree = 2;
        int order = degree + 1;
        float *controlPoints = new float[dimension * 2];
        float *weights = new float[dimension];
        float *knots = new float[dimension + order]; 
        
        controlPoints[0] = 0;
        controlPoints[1] = -0.3;

        controlPoints[2] = 0.6;
        controlPoints[3] = -0.3;

        controlPoints[4] = 1;
        controlPoints[5] = 0;

        controlPoints[6] = 0.6;
        controlPoints[7] = 0.3;

        controlPoints[8] = 0;
        controlPoints[9] = 0.3;

        int i;
        for (i = 0; i < dimension; i++)
            weights[i] = 1.0f;
        for (i = 0; i < order; i++) {
            knots[i] = 0.0f;
            knots[dimension + i] = (float) (dimension - order + 1);
        }
        for (i = 0; i < dimension - order; i++) {
            knots[order + i] = (float) (i + 1);
        }
    
        superRevolver->controlPoint(new MFVec2f(controlPoints, dimension * 2));
        superRevolver->weight(new MFFloat(weights, dimension));
        superRevolver->knot(new MFFloat(knots, dimension + order));
        superRevolver->order(new SFInt32(order));

        superRevolver->m(new SFFloat(2.5));
        superRevolver->n1(new SFFloat(0.46));
        superRevolver->n2(new SFFloat(1.8));
        superRevolver->n3(new SFFloat(0.88));
    }
}

void
MainWindow::CreateSpindle(void)
{
    CreateGeometryNode("SuperRevolver");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_REVOLVER)) {
        NodeSuperRevolver *superRevolver = (NodeSuperRevolver *) node;
        int dimension = 7;        
        int degree = 2;
        int order = degree + 1;
        float *controlPoints = new float[dimension * 2];
        float *weights = new float[dimension];
        float *knots = new float[dimension + order]; 
        
        controlPoints[0] = 0;
        controlPoints[1] = -3;

        controlPoints[2] = 1;
        controlPoints[3] = -2;

        controlPoints[4] = 1;
        controlPoints[5] = -1;

        controlPoints[6] = 1;
        controlPoints[7] = 0;

        controlPoints[8] = 1;
        controlPoints[9] = 1;

        controlPoints[10] = 1;
        controlPoints[11] = 2;

        controlPoints[12] = 0;
        controlPoints[13] = 3;

        int i;
        for (i = 0; i < dimension; i++)
            weights[i] = 1.0f;
        for (i = 0; i < order; i++) {
            knots[i] = 0.0f;
            knots[dimension + i] = (float) (dimension - order + 1);
        }
        for (i = 0; i < dimension - order; i++) {
            knots[order + i] = (float) (i + 1);
        }
    
        superRevolver->controlPoint(new MFVec2f(controlPoints, dimension * 2));
        superRevolver->weight(new MFFloat(weights, dimension));
        superRevolver->knot(new MFFloat(knots, dimension + order));
        superRevolver->order(new SFInt32(order));
    }
}

void
MainWindow::CreateMushroom(bool sulcate)
{
    CreateGeometryNode("SuperRevolver");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_REVOLVER)) {
        NodeSuperRevolver *superRevolver = (NodeSuperRevolver *) node;
        int dimension = 7;        
        int degree = 2;
        int order = degree + 1;
        float *controlPoints = new float[dimension * 2];
        float *weights = new float[dimension];
        float *knots = new float[dimension + order]; 
        
        controlPoints[0] = 0;
        controlPoints[1] = 0;

        controlPoints[2] = 0.96;
        controlPoints[3] = -2.9e-2;

        controlPoints[4] = 0.40;
        controlPoints[5] = 1.3;

        controlPoints[6] = 0.69;
        controlPoints[7] = 1.65;

        controlPoints[8] = 1.71;
        controlPoints[9] = 1.21;

        controlPoints[10] = 0.94;
        controlPoints[11] = 2.14;

        controlPoints[12] = 0;
        controlPoints[13] = 2;

        int i;
        for (i = 0; i < dimension; i++)
            weights[i] = 1.0f;
        for (i = 0; i < order; i++) {
            knots[i] = 0.0f;
            knots[dimension + i] = (float) (dimension - order + 1);
        }
        for (i = 0; i < dimension - order; i++) {
            knots[order + i] = (float) (i + 1);
        }
    
        superRevolver->controlPoint(new MFVec2f(controlPoints, dimension * 2));
        superRevolver->weight(new MFFloat(weights, dimension));
        superRevolver->knot(new MFFloat(knots, dimension + order));
        superRevolver->order(new SFInt32(order));

        if (sulcate) {
            superRevolver->b(new SFFloat(0.7));
            superRevolver->m(new SFFloat(16));
            superRevolver->n1(new SFFloat(11));
            superRevolver->n2(new SFFloat(0.6));
            superRevolver->n3(new SFFloat(4.5));
        }
    }
}

void
MainWindow::CreateHalfSphere(void)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_SHAPE)) {
        NodeSuperShape *superShape = (NodeSuperShape *) node;
        superShape->border(new SFFloat(0.0));
    }
}

void
MainWindow::CreateShell(void)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_SHAPE)) {
        float shellsmooth = 0.5;
        if (TheApp->is4Kids()) {
            OneFloatDialog dlg(_wnd, IDD_SHELL_SMOOTH, 0.5, 0, 1);
            if (dlg.DoModal() == IDCANCEL)
                return;
            shellsmooth = dlg.GetValue();
        }
        NodeSuperShape *superShape = (NodeSuperShape *) node;
        superShape->ua(new SFFloat(0.74));
        superShape->ub(new SFFloat(1e4));
        superShape->um(new SFFloat(-1.08));
        superShape->un1(new SFFloat(-2.04));
        superShape->un2(new SFFloat(-7.3));
        superShape->un3(new SFFloat(0.22));
        superShape->va(new SFFloat(-3.92));
        superShape->vb(new SFFloat(-7.019999));
        superShape->vm(new SFFloat(30.86));
        superShape->vn1(new SFFloat(10.26));
        superShape->vn2(new SFFloat(-shellsmooth));
        superShape->vn3(new SFFloat(0.28));
        superShape->uTessellation(new SFInt32(16));
        superShape->vTessellation(new SFInt32(16));
    }
}

void
MainWindow::CreateUfo(void)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_SHAPE)) {
        NodeSuperShape *superShape = (NodeSuperShape *) node;
        superShape->vm(new SFFloat(1.26));
        superShape->vn1(new SFFloat(0.36));
        superShape->vn2(new SFFloat(1.2));
        superShape->vn3(new SFFloat(0.5));
        superShape->uTessellation(new SFInt32(16));
        superShape->vTessellation(new SFInt32(24));
    }
}

void
MainWindow::CreateInsectRear(int segments)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_SHAPE)) {
        NodeSuperShape *superShape = (NodeSuperShape *) node;
        superShape->vm(new SFFloat(2 * segments));
        superShape->vn1(new SFFloat(-5));
    }
}

void
MainWindow::CreateTube(bool hornFlag)
{
    CreateSuperExtrusion();
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_EXTRUSION)) {
        NodeSuperExtrusion *superExtrusion = (NodeSuperExtrusion *) node;
        superExtrusion->beginCap(new SFBool(false));
        superExtrusion->endCap(new SFBool(false));
        if (hornFlag) {
            float *scales = new float[2 * 2];
            scales[0] = 1;
            scales[1] = 1;
            scales[2] = 0;
            scales[3] = 0;
            superExtrusion->scale(new MFVec2f(scales, 2 * 2));    
        }
    }
}

void
MainWindow::CreateTorus(void)
{
    CreateSuperExtrusion(17);
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == DUNE_SUPER_EXTRUSION)) {
        NodeSuperExtrusion *superExtrusion = (NodeSuperExtrusion *) node;
        superExtrusion->beginCap(new SFBool(false));
        superExtrusion->endCap(new SFBool(false));
        int numPoints = superExtrusion->controlPoint()->getSFSize();
        float *ring = new float[numPoints * 3];
        float radius = 1.05;
        for (int i = 0; i <= (numPoints - 1); i++) {
            ring[i * 3] = radius * sin(i * 2.0f * M_PI / (numPoints - 1));
            ring[i * 3 + 1] = radius * cos(i * 2.0f * M_PI / (numPoints - 1));;
            ring[i * 3 + 2] = 0;
        }
        float maxY = 1;
        ring[0] = 0;
        ring[1] = maxY;
        ring[2] = 0;
        ring[(numPoints - 1) * 3] = 0;
        ring[(numPoints - 1) * 3 + 1] = maxY;
        ring[(numPoints - 1) * 3 + 2] = 0;
        superExtrusion->a(new SFFloat(0.5));    
        superExtrusion->controlPoint(new MFVec3f(ring, numPoints * 3));    
    }
}

//static MyString onetext;

void MainWindow::createOneText(void)
{
    CreateGeometryNode("Text");
    changeOneText();
}

void MainWindow::changeOneText(void)
{
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == VRML_TEXT)) {
        NodeText *text = (NodeText *) node;
        MyString s = text->string()->getValue(0);
        OneTextDialog dlg(_wnd, IDD_TEXT, s, textValidate);
        if (dlg.DoModal() == IDCANCEL)
            return;
        _scene->setField(text, text->string_Field(), 
                        new MFString(dlg.GetValue()));
    }
}

void
MainWindow::moveSibling(int command)
{
    Node *node = _scene->getSelection()->getNode();
    int newIndex = -1;
    int oldIndex = -1;
    switch (command) {
      case MOVE_SIBLING_UP:
        newIndex = node->getPrevSiblingIndex();
        oldIndex = newIndex + 1;
        break;
      case MOVE_SIBLING_DOWN:
        newIndex = node->getNextSiblingIndex();
        oldIndex = newIndex - 1;
        break;
      case MOVE_SIBLING_FIRST:
        if (node->getPrevSiblingIndex() != -1) {
            newIndex = 0;
            oldIndex = node->getPrevSiblingIndex() + 1;
        }
        break;
      case MOVE_SIBLING_LAST:
        if (node->getNextSiblingIndex() != -1) {
            MFNode *mfNode = (MFNode *)node->getParentFieldValue();
            newIndex = mfNode->getSize() - 1;
            oldIndex = node->getNextSiblingIndex() - 1;
        }
        break;
    }
    if (newIndex != -1) {
        node->ref();
        Node* parent = node->getParent();
        int parentField = node->getParentField();
        float oldSceneLength = 0;
        float newSceneLength = 0;
        NodeVrmlCut *vrmlCut = NULL;
        if (parent->getType() == DUNE_VRML_CUT) {
            vrmlCut = (NodeVrmlCut *)parent;
            oldSceneLength = vrmlCut->sceneLengths()->getValue(oldIndex);
            newSceneLength = vrmlCut->sceneLengths()->getValue(newIndex);
        }
        _scene->execute(new MoveCommand(node, parent, parentField, 
                                        NULL, -1));
        _scene->execute(new MoveCommand(node, NULL, -1, 
                                        parent, parentField, newIndex));
        if (parent->getType() == DUNE_VRML_CUT) {
            vrmlCut->sceneLengths()->setValue(newIndex, oldSceneLength);
            vrmlCut->sceneLengths()->setValue(oldIndex, newSceneLength);
        }
        MFNode *mfNode = (MFNode *)node->getParentFieldValue();
        _scene->setSelection(mfNode->getValue(newIndex));
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }       
}

void
MainWindow::moveBranchTo(const char* nodeName, const char* fieldName)
{
    Node *current = _scene->getSelection()->getNode();
    if (current->isInvalidChildNode())
        return;
    Node *node = InsertNode(nodeName);
    int field = node->getProto()->lookupField(fieldName);
    if (field == INVALID_INDEX)
        field = node->getProto()->lookupExposedField(fieldName);
    if (field == INVALID_INDEX) {
        TheApp->MessageBoxId(IDS_INTERNAL_ERROR);
        return;
    }
    moveBranchTo(node, field, current);
}

void 
MainWindow::moveBranchTo(Node* node, int field, Node* current)
{
    if (current == NULL)
        return;
    Node *target = current; 
    int targetField = -1;
    if (target == _scene->getRoot())
        targetField = _scene->getRootField();
    else {
        targetField = target->getParentField();
        target = target->getParent();
    }

    FieldValue  *value = target->getField(targetField);
    if (value->getType() == MFNODE) {
        MFNode *nodes = (MFNode *)value;
        bool inBranch = false;
        for (int i = 0 ; i < nodes->getSize() ; i++) {
            if (nodes->getValue(i)->isEqual(current))
                inBranch = true;
            if (inBranch)
                if (!nodes->getValue(i)->isEqual(node)) {
                    CommandList *list = new CommandList();
                    list->append(new MoveCommand(nodes->getValue(i), 
                                                 target, targetField,
                                                 node, field));
                    list->execute();
                }
        }
        _scene->setSelection(target);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void 
MainWindow::moveBranchToTransformSelection(void)
{
    Node *selection = _scene->getSelection()->getNode(); 
    if (selection->getType() != VRML_TRANSFORM)
        return;
    NodeTransform *target = (NodeTransform *)selection;
    NodeTransform *transform = target;
    int childrenField = transform->children_Field();
    //to invert a Transform the following fields see
    // ISO/IEC 19775-1:2008 10.4.4 Transform
    NodeTransform *newTransform = NULL;
    CommandList *list = new CommandList();
    const float *center = transform->center()->getValue();
    if ((center[0] != 0) || (center[1] != 0) || (center[2] != 0)) {
        newTransform = (NodeTransform *)_scene->createNode("Transform");
        newTransform->translation(new SFVec3f(center[0], 
                                              center[1],
                                              center[2]));
        list->append(new MoveCommand(newTransform, NULL, -1, 
                                     target, childrenField));
        target = newTransform;
    }
    const float *scaleOrientation = transform->scaleOrientation()->getValue();
    if (scaleOrientation[3] != 0) {
        newTransform = (NodeTransform *)_scene->createNode("Transform");
        newTransform->rotation(new SFRotation(scaleOrientation[0], 
                                              scaleOrientation[1],
                                              scaleOrientation[2],
                                              scaleOrientation[3]));
        list->append(new MoveCommand(newTransform, NULL, -1, 
                                     target, childrenField));
        target = newTransform;
    }
    const float *scale = transform->scale()->getValue();
    if ((scale[0] != 1.0f) || (scale[1] != 1.0f) || (scale[2] != 1.0f)) {
        newTransform = (NodeTransform *)_scene->createNode("Transform");
        newTransform->scale(new SFVec3f(scale[0] == 0 ? 1 : 1.0f / scale[0],
                                        scale[1] == 0 ? 1 : 1.0f / scale[1],
                                        scale[2] == 0 ? 1 : 1.0f / scale[2]));
        list->append(new MoveCommand(newTransform, NULL, -1, 
                                     target, childrenField));
        target = newTransform;
    }
    if (scaleOrientation[3] != 0) {
        newTransform = (NodeTransform *)_scene->createNode("Transform");
        newTransform->rotation(new SFRotation(scaleOrientation[0], 
                                              scaleOrientation[1],
                                              scaleOrientation[2],
                                              -scaleOrientation[3]));
        list->append(new MoveCommand(newTransform, NULL, -1, 
                                     target, childrenField));
        target = newTransform;
    }
    const float *rotation = transform->rotation()->getValue();
    if (rotation[3] != 0) {
        newTransform = (NodeTransform *)_scene->createNode("Transform");
        newTransform->rotation(new SFRotation(rotation[0], 
                                              rotation[1],
                                              rotation[2],
                                              -rotation[3]));
        list->append(new MoveCommand(newTransform, NULL, -1, 
                                     target, childrenField));
        target = newTransform;
    }
    if ((center[0] != 0) || (center[1] != 0) || (center[2] != 0)) {
        newTransform = (NodeTransform *)_scene->createNode("Transform");
        newTransform->translation(new SFVec3f(-center[0], 
                                              -center[1],
                                              -center[2]));
        list->append(new MoveCommand(newTransform, NULL, -1, 
                                     target, childrenField));
        target = newTransform;
    }
    const float *translation = transform->translation()->getValue();
    if ((translation[0] != 0) || 
        (translation[1] != 0) || 
        (translation[2] != 0)) {
        newTransform = (NodeTransform *)_scene->createNode("Transform");
        newTransform->translation(new SFVec3f(-translation[0], 
                                              -translation[1],
                                              -translation[2]));
        list->append(new MoveCommand(newTransform, NULL, -1, 
                                     target, childrenField));
        target = newTransform;
    }
    list->execute();
    moveBranchTo(target, childrenField, selection->getNextSibling());
    _scene->setSelection(selection);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

void 
MainWindow::moveBranchToInline()
{
    Node *current = _scene->getSelection()->getNode();
    if (current->isInvalidChildNode())
        return;
    char path[1024];
    path[0] = '\0';

    NodeArray allNodes;        
    doWithBranchUpdate(getAllNodes, &allNodes);

    NodeInline *newNode = (NodeInline *)InsertNode("Inline");

    Node *target = current; 
    int targetField = -1;
    if (target == _scene->getRoot())
        targetField = _scene->getRootField();
    else {
        targetField = target->getParentField();
        target = target->getParent();
    }

    FieldValue  *value = target->getField(targetField);

    // build list of nodes in branch
    Array<Node *> nodesInBranch;
    if (value->getType() == MFNODE) {
        MFNode *nodes = (MFNode *)value;
        bool inBranch = false;
        for (int i = 0 ; i < nodes->getSize() ; i++) {
            if (nodes->getValue(i)->isEqual(current))
                inBranch = true;
            if (inBranch)
                if (!nodes->getValue(i)->isEqual(newNode))
                     nodesInBranch.append(nodes->getValue(i));
        }
    }

    int i;
    for (i = 0 ; i < allNodes.size() ; i++) {
        Node *node = allNodes[i];

        // search for eventIns point outside of rest of scenegraph branch
        int numEventIns = node->getProto()->getNumEventIns();
        for (int eIn = 0; eIn < numEventIns; eIn++) {
            SocketList::Iterator *j;
            for (j = node->getInput(eIn).first(); j != NULL; j = j->next())
                if ((j != NULL) && (j->item().getNode())) {
                   bool eventIsOutside = true;
                   for (int n = 0; n < allNodes.size(); n++) {
                       if (node != allNodes[n])
                           if (j->item().getNode()->isEqual(allNodes[n])) {
                               eventIsOutside = false;
                               break;
                           }
                   }
                   if (eventIsOutside) {
                       TheApp->MessageBox(IDS_TO_INLINE_EVENT_IN_OUTSIDE,
                                          (const char *)node->getName());
                       // cleanup Inline node
                       _scene->execute(new MoveCommand(newNode,
                                                       target, targetField,
                                                       NULL, -1));
                       return;
                    }
                }
        }    

        // search for eventOuts point outside of rest of scenegraph branch
        int numEventOuts = node->getProto()->getNumEventOuts();
        for (int eOut = 0; eOut < numEventOuts; eOut++) {
            SocketList::Iterator *j;
            for (j = node->getOutput(eOut).first(); j != NULL; j = j->next())
                if ((j != NULL) && (j->item().getNode())) {
                    bool eventIsOutside = true;
                    for (int n = 0; n < allNodes.size(); n++) {
                        if (node != allNodes[n])
                            if (j->item().getNode()->isEqual(nodesInBranch[n])) {
                                eventIsOutside = false;
                                break;
                            }
                    }
                    if (eventIsOutside) {
                        TheApp->MessageBox(IDS_TO_INLINE_EVENT_OUT_OUTSIDE,
                                     (const char *)node->getName());
                        // cleanup Inline node
                        _scene->execute(new MoveCommand(newNode,
                                                        target, targetField,
                                                        NULL, -1));
                        return;
                    }
                }
        }
        // search for USED nodes (not supported yet)
        if (node->getNumParents() > 1) {
            TheApp->MessageBox(IDS_TO_INLINE_USE, (const char *)node->getName());
            // cleanup Inline node
            _scene->execute(new MoveCommand(newNode, target, targetField,
                                            NULL, -1));
            return;
        }    
    }

    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir());
    if (swSaveFileDialog(TheApp->mainWnd(), "Save As Inline",
        "Inline VRML File (.wrl)\0*.wrl;*.WRL\0All Files (*.*)\0*.*\0\0",
        path, 1024,".wrl")) {
        int f = open(path, O_WRONLY | O_CREAT,00666);  
        if (f == -1) {
            TheApp->MessageBoxPerror(path);
            // cleanup Inline node
            _scene->execute(new MoveCommand(newNode, target, targetField,
                                            NULL, -1));
            return;
        }

        if (mywritestr(f ,"#VRML V2.0 utf8\n\n") != 0) {
            TheApp->MessageBoxPerror(path);
            // cleanup Inline node
            _scene->execute(new MoveCommand(newNode, target, targetField,
                                            NULL, -1));
            return;
        }

        // write to Inline file
        for (i = 0 ; i < nodesInBranch.size() ; i++) 
            if (nodesInBranch[i]->write(f, TheApp->GetIndent()) != 0) {
                TheApp->MessageBoxPerror(path);                
                // cleanup Inline node
                _scene->execute(new MoveCommand(newNode, target, targetField,
                                                NULL, -1));
                return;
            }

        bool writeError = false;
        if (_scene->writeRouteStrings(f, 0, true) != 0)
            writeError = true;
        else if (swTruncateClose(f))
            writeError = true;
        if (writeError) {
            TheApp->MessageBoxPerror(path);
            // cleanup Inline node
            _scene->execute(new MoveCommand(newNode, target, targetField,
                                            NULL, -1));
            return;
        }

        // remove nodes from scenegraph
        for (i = 0 ; i < nodesInBranch.size() ; i++) {           
            CommandList *list = new CommandList();
            list->append(new MoveCommand(nodesInBranch[i], target, targetField,
                         NULL, -1));
            list->execute();
        }

        URL url;
        url.FromPath(path);
        newNode->url(new MFString(rewriteURL(url,url.GetDir(),
                    _scene->getURL())));
        _scene->readInline(newNode);
        _scene->setSelection(target);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    } else {
        // cleanup Inline node
         _scene->execute(new MoveCommand(newNode, target, targetField,
                                         NULL, -1));
    }
}

void                
MainWindow::moveBranchToParent(void) 
{
    Node *current = _scene->getSelection()->getNode();
    if (current->isInvalidChildNode())
        return;
    Node *target = current; 
    int targetField = -1;
    if (target == _scene->getRoot())
        return;
    target = target->getParent();
    if (target == _scene->getRoot())
        return;
    if (target->getParent() == _scene->getRoot())
       targetField = _scene->getRootField();
    else
        targetField = target->getParentField();
    target = target->getParent();
    moveBranchTo(target, targetField, current);
}

void
MainWindow::doWithBranchUpdate(DoWithNodeCallback callback, void *data)
{
    Node *node = _scene->getSelection()->getNode(); 
    doWithBranch(callback, data);
    _scene->UpdateViews(NULL, UPDATE_ALL, NULL);
    if (node->isInScene(_scene)) {
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::doWithBranch(DoWithNodeCallback callback, void *data)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL)
        node->doWithBranch(callback, data);    
}

void
MainWindow::branchConvertToTriangleSetUpdate(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    _scene->branchConvertToTriangleSet(node);
    _scene->UpdateViews(NULL, UPDATE_ALL, NULL);
    if (node->isInScene(_scene)) {
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::branchConvertToIndexedFaceSetUpdate(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    _scene->branchConvertToIndexedFaceSet(node);
    _scene->UpdateViews(NULL, UPDATE_ALL, NULL);
    if (node->isInScene(_scene)) {
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::branchConvertToIndexedTriangleSetUpdate(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    _scene->branchConvertToIndexedTriangleSet(node);
    _scene->UpdateViews(NULL, UPDATE_ALL, NULL);
    if (node->isInScene(_scene)) {
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

static bool flipSide(Node *node, void *data)
{
    // avoid double flipping of flipable node and its Coordinate node
    if (node->getNodeClass() != COORDINATE_NODE)
        node->flipSide();
    return true;     
}

void
MainWindow::setBranchFlipSide(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    node->doWithBranch(flipSide, NULL);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

static bool setSolid(Node *node, void *data)
{
    bool *isSolid = (bool *)data;
    if (node->getSolidField() != -1) {
        Scene *scene = node->getScene();
        scene->setField(node, node->getSolidField(), new SFBool(*isSolid));
    }
    return true;     
}

static bool setConvex(Node *node, void *data)
{
    bool *isConvex = (bool *)data;  
    if (node->getConvexField() != -1) {
        Scene *scene = node->getScene();
        scene->setField(node, node->getConvexField(), new SFBool(*isConvex));
    }
    return true;     
}

static bool trueFalseValidate(MyString text)
{    
    if (strcmp(text,"TRUE") == 0)
        return true;
    if (strcmp(text,"true") == 0)
        return true;
    if (strcmp(text,"FALSE") == 0)
        return true;
    if (strcmp(text,"false") == 0)
        return true;
    TheApp->MessageBoxId(IDS_TRUE_OR_FALSE);
    return false;
}

void
MainWindow::setBranchSolid(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        MyString s = "";
        OneTextDialog dlg(_wnd, IDD_SOLID, s, trueFalseValidate);
        if (dlg.DoModal() == IDCANCEL)
            return;
        bool bsolid = false;
        if ((strcmp(dlg.GetValue(), "TRUE") == 0) || 
            (strcmp(dlg.GetValue(), "true") == 0))
            bsolid = true;
        node->doWithBranch(setSolid, &bsolid);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::setBranchConvex(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        MyString s = "";
        OneTextDialog dlg(_wnd, IDD_CONVEX, s, trueFalseValidate);
        if (dlg.DoModal() == IDCANCEL)
            return;
        bool bconvex = false;
        if (strcasecmp(dlg.GetValue(), "TRUE") == 0)
            bconvex = true;
        node->doWithBranch(setConvex, &bconvex);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::setBranchTwoSided(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        TwoRadioButtonsDialog dlg(_wnd, IDD_TWO_SIDED, true);
        if (dlg.DoModal() == IDCANCEL)
            return;
        bool bsolid = dlg.GetFirstValue();
        node->doWithBranch(setSolid, &bsolid);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

static bool setCreaseAngle(Node *node, void *data)
{
    float *angle = (float *)data;
    if (node->getType() == VRML_INDEXED_FACE_SET)
        ((NodeIndexedFaceSet *) node)->creaseAngle(new SFFloat(*angle));
    else if (node->getType() == VRML_ELEVATION_GRID)
        ((NodeElevationGrid *) node)->creaseAngle(new SFFloat(*angle));
    else if (node->getType() == DUNE_SUPER_ELLIPSOID)
        ((NodeSuperEllipsoid *) node)->creaseAngle(new SFFloat(*angle));
    else if (node->getType() == DUNE_SUPER_EXTRUSION)
        ((NodeSuperExtrusion *) node)->creaseAngle(new SFFloat(*angle));
    else if (node->getType() == DUNE_SUPER_SHAPE)
        ((NodeSuperShape *) node)->creaseAngle(new SFFloat(*angle));
    else if (node->getType() == DUNE_SUPER_REVOLVER)
        ((NodeSuperRevolver *) node)->creaseAngle(new SFFloat(*angle));
    return true;     
}

void
MainWindow::setBranchCreaseAngle(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        OneFloatDialog dlg(_wnd, IDD_CREASE_ANGLE, 1.57, 0, M_PI);
        if (dlg.DoModal() == IDCANCEL)
            return;
        float angle = dlg.GetValue();
        node->doWithBranch(setCreaseAngle, &angle);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

static bool setTransparency(Node *node, void *data)
{
    float *ftransparency = (float *)data;
    if (node->getType() == VRML_MATERIAL)
        ((NodeMaterial *) node)->transparency(new SFFloat(*ftransparency));
    return true;     
}

void
MainWindow::setBranchTransparency(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        OneFloatDialog dlg(_wnd, IDD_TRANSPARENCY, 0, 0, 1);
        if (dlg.DoModal() == IDCANCEL)
            return;
        float transparency = dlg.GetValue();
        node->doWithBranch(setTransparency, &transparency);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

static bool setShininess(Node *node, void *data)
{
    float *fshininess = (float *)data;
    if (node->getType() == VRML_MATERIAL)
        ((NodeMaterial *) node)->shininess(new SFFloat(*fshininess));
    return true;     
}

void
MainWindow::setBranchShininess(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        OneFloatDialog dlg(_wnd, IDD_SHININESS, 0, 0, 1);
        if (dlg.DoModal() == IDCANCEL)
            return;
        float shininess = dlg.GetValue();
        node->doWithBranch(setShininess, &shininess);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

static bool removeNodeCallback(Node *node, void *data)
{
    char *nodeName = (char *)data;
    bool x3d = node->getScene()->isX3d();
    if (strcmp(nodeName, node->getProto()->getName(x3d)) == 0)
        if (node->hasParent()) {
            Node *parent = node->getParent();
            int parentField = node->getParentField();
            MoveCommand *command = new MoveCommand(node, parent, parentField, 
                                                   NULL, -1);
           command->execute();
        }
    return true;     
}

static bool nodeNameValidate(MyString text)
{
    return true;
}

void
MainWindow::removeBranchNode(void)
{
    MyString s = "";
    OneTextDialog dlg(_wnd, IDD_TEXT, s, nodeNameValidate);
    if (dlg.DoModal() == IDCANCEL)
        return;
    const char *nodeName = dlg.GetValue();
    doWithBranch(removeNodeCallback, (void *)nodeName);
    _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);    
}

bool
MainWindow::matchFieldPipeFilterNode(Node *node) 
{
    const char *filterNode = _fieldPipeFilterNode;
    if (node->hasName())
        if (strstr(node->getName(), filterNode) != NULL)
            return true;
    if (strstr(node->getProto()->getName(_scene->isX3d()), filterNode) != NULL)
        return true;
    return false;
}

void
MainWindow::matchFieldPipeFilterField(Node *node) 
{
    const char *fieldPart = _fieldPipeFilterField;
    if (strlen(fieldPart) > 0) {
        for (int i = 0; i < node->getProto()->getNumFields(); i++) {
            bool x3d = _scene->isX3d();
            if (strstr(node->getProto()->getField(i)->getName(x3d), 
                       fieldPart) != NULL)
                fieldPipe(node, i, _fieldPipeCommand);
        }
    }
}

static bool fieldPipeCallback(Node *node, void *data)
{
    MainWindow *wnd = (MainWindow *)data;
    if (wnd->matchFieldPipeFilterNode(node))
        wnd->matchFieldPipeFilterField(node);
    return true;     
}

void
MainWindow::branchFieldPipe(void) {
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        FieldPipeDialog dlg(_wnd, _fieldPipeFilterNode, _fieldPipeFilterField, 
                            _fieldPipeCommand);
        if (dlg.DoModal() == IDCANCEL)
            return;
        _fieldPipeCommand = dlg.GetCommand();
        _fieldPipeFilterNode = dlg.GetNodeFilter();
        _fieldPipeFilterField = dlg.GetFieldFilter();
        node->doWithBranch(fieldPipeCallback, this);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

static bool buildRigidBodyCollection(Node *node, void *data)
{
    // collect SollidableShape and CollidableOffset nodes
    NodeList *collidables = (NodeList *)data;
    if (node->hasParent()) {
        // collect only nodes in deapest branch
        if ((node->getParent()->getType() == X3D_COLLIDABLE_OFFSET) ||
            (node->getParent()->getType() == X3D_COLLIDABLE_SHAPE))
            return true;
    }
    if ((node->getType() == X3D_COLLIDABLE_OFFSET) || 
        (node->getType() == X3D_COLLIDABLE_SHAPE))
        collidables->append(node);
    return true;     
}

void
MainWindow::branchBuildRigidBodyCollection(void) {
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        NodeList collidables;
        node->doWithBranch(buildRigidBodyCollection, &collidables);
        if (collidables.size() > 0) {
            _scene->setSelection(_scene->getRoot());
            NodeRigidBodyCollection *collection = (NodeRigidBodyCollection *) 
                  _scene->createNode("RigidBodyCollection");
            int i;
            for (i = 0; i < collidables.size(); i++) {
                NodeRigidBody *rigidBody = (NodeRigidBody*) 
                                           _scene->createNode("RigidBody");
                _scene->execute(new MoveCommand(collidables[i], NULL, -1,
                                                rigidBody, 
                                                rigidBody->geometry_Field()));
                _scene->execute(new MoveCommand(rigidBody, NULL, -1, 
                                                collection, 
                                                collection->bodies_Field()));
            }
            NodeCollisionCollection *collision = (NodeCollisionCollection *) 
                  _scene->createNode("CollisionCollection");
            for (i = 0; i < collidables.size(); i++) {
                _scene->execute(new MoveCommand(collidables[i], NULL, -1,
                                                collision, 
                                                collision->collidables_Field()));
            }
            _scene->execute(new MoveCommand(collision, NULL, -1, collection, 
                                            collection->collider_Field()));
            NodeGroup *root = (NodeGroup *)_scene->getRoot();
            _scene->execute(new MoveCommand(collection, NULL, -1, 
                                            root, root->children_Field()));
            NodeCollisionSensor *sensor = (NodeCollisionSensor*) 
                                          _scene->createNode("CollisionSensor");
            _scene->execute(new MoveCommand(sensor, NULL, -1, 
                                            root, root->children_Field()));
            _scene->execute(new MoveCommand(collision, NULL, -1, sensor, 
                                            sensor->collidables_Field()));
            int eventOut = sensor->getProto()->lookupEventOut("contacts");
            int eventIn = collection->getProto()->lookupEventIn("set_contacts");
            _scene->addRoute(sensor, eventOut, collection, eventIn);
            for (i = 0; i < collidables.size(); i++)
                collidables[i]->update();
        }
        _scene->UpdateViews(NULL, UPDATE_ALL);
    }
}

void
MainWindow::HandleScale(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        OneFloatDialog dlg(_wnd, IDD_HANDLE_SCALE, 1, 0);
        if (dlg.DoModal() == IDCANCEL)
            return;
        TheApp->SetPreferenceHandleScale(dlg.GetValue());
        _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);
    }
}

void
MainWindow::HandleSize(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        OneFloatDialog dlg(_wnd, IDD_HANDLE_SIZE, 3, 0);
        if (dlg.DoModal() == IDCANCEL)
            return;
        TheApp->SetPreferenceHandleSize(dlg.GetValue());
        _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);
    }
}

void
MainWindow::HandleEpsilon(void)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL) {
        OneFloatDialog dlg(_wnd, IDD_HANDLE_EPSILON, 0.05, 0);
        if (dlg.DoModal() == IDCANCEL)
            return;
        TheApp->SetHandleEpsilon(dlg.GetValue());
        _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);
    }
}

static bool createTexture(Node *node, void *data)
{
    if ((node->getType() == VRML_APPEARANCE) ||
        (node->getType() == KAMBI_KAMBI_APPEARANCE)) {
        NodeAppearance *appearanceNode = (NodeAppearance *) node;
        // ignore Nodes with already set Texture field
        Node *texture = (Node *)data;
        if ((appearanceNode->texture()->getValue() == NULL) &&
            texture->matchNodeClass(TEXTURE_NODE)) {
            MoveCommand *command = new MoveCommand(texture, NULL, -1,
                  appearanceNode, appearanceNode->texture_Field());
            command->execute();
        }
    }
    return true;     
}

void
MainWindow::createBranchImageTexture(void)
{
    char buf[MY_MAX_PATH];

    buf[0] = '\0';
    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir());
    if (swOpenFileDialog(_wnd, "Select Image (*.jpg, *.png)",
#ifdef HAVE_LIBDEVIL
        "All Files (*.*)\0*.*\0\0",
#else
        "Image Files (*.gif, *.jpg, *.png)\0*.gif;*.jpg;*.png\0All Files (*.*)\0*.*\0\0",
#endif
                         buf, MY_MAX_PATH)) {
        NodeImageTexture *node = (NodeImageTexture *)
                                 _scene->createNode("ImageTexture");
        URL url;
        url.FromPath(buf);
        node->url(new MFString(rewriteURL(url,url.GetDir(),_scene->getURL())));
        doWithBranch(createTexture, node);
    }
}

static bool createAppearance(Node *node, void *data)
{
    if (node->getType() == VRML_SHAPE) {
        NodeShape *shapeNode = (NodeShape *) node;
        // ignore Nodes with already set Appearance field
        Node *appearance = (Node *)data;
        if ((shapeNode->appearance()->getValue() == NULL) &&
            (appearance->getType() & VRML_APPEARANCE)) {
            MoveCommand *command = new MoveCommand(appearance, NULL, -1,
                  shapeNode, shapeNode->appearance_Field());
            command->execute();
        }
    }
    return true;     
}

void
MainWindow::createBranchAppearance(void)
{
    NodeAppearance *node = (NodeAppearance *) _scene->createNode("Appearance");
    doWithBranch(createAppearance, node);
}

static bool createMaterial(Node *node, void *data)
{
    if ((node->getType() == VRML_APPEARANCE) ||
        (node->getType() == KAMBI_KAMBI_APPEARANCE)) {
        NodeAppearance *appearanceNode = (NodeAppearance *) node;
        // ignore Nodes with already set Material field
        Node *material = (Node *)data;
        if (appearanceNode && 
            (appearanceNode->material()->getValue() == NULL) &&
            (material->getType() & VRML_MATERIAL)) {
            MoveCommand *command = new MoveCommand(material, NULL, -1,
                  appearanceNode, appearanceNode->material_Field());
            command->execute();
        }
    }
    return true;     
}

void
MainWindow::createBranchMaterial(void)
{
    NodeMaterial *node = (NodeMaterial *) _scene->createNode("Material");
    doWithBranch(createMaterial, node);
}

Node*
MainWindow::getTransformForCenter() 
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != _scene->getRoot()) {
        node = node->getParent();
        if (node->getType() == VRML_SHAPE)
           if (node != _scene->getRoot()) {
               Node *shapeParent = node->getParent();
               if (shapeParent->getType() == VRML_TRANSFORM)
                   return shapeParent;

           }
    }
    return NULL;
}

void
MainWindow::centerToMid()
{
   NodeTransform *transform = (NodeTransform *) getTransformForCenter();
   if (transform != NULL) {
       Node *node = _scene->getSelection()->getNode(); 
       Vec3f min = node->getMinBoundingBox(); 
       Vec3f max = node->getMaxBoundingBox();
       Vec3f center = ((max + min) / 2.0f) * transform->rotation()->getQuat().conj();
       _scene->setField(transform, transform->center_Field(), 
                        new SFVec3f(center));
   }
}

void
MainWindow::centerToMax(int index)
{
   NodeTransform *transform = (NodeTransform *) getTransformForCenter();
   if (transform != NULL) {
       Node *node = _scene->getSelection()->getNode(); 
       Vec3f max = node->getMaxBoundingBox(); 
       Vec3f vcenter = transform->center()->getValue();
       vcenter = vcenter * transform->rotation()->getQuat().conj();
       vcenter[index] = max[index];
       vcenter = vcenter * transform->rotation()->getQuat();
       _scene->setField(transform, transform->center_Field(), 
                        new SFVec3f(vcenter));
   }
}

void 
MainWindow::centerToMin(int index)
{
   NodeTransform *transform = (NodeTransform *) getTransformForCenter();
   if (transform != NULL) {
       Node *node = _scene->getSelection()->getNode(); 
       Vec3f min = node->getMinBoundingBox(); 
       Vec3f vcenter = transform->center()->getValue();
       vcenter = vcenter * transform->rotation()->getQuat().conj();
       vcenter[index] = min[index];
       vcenter = vcenter * transform->rotation()->getQuat();
       _scene->setField(transform, transform->center_Field(), 
                        new SFVec3f(vcenter));
   }
}

void MainWindow::flip(int index)
{
    _scene->getNodes()->clearFlag(NODE_FLAG_FLIPPED);
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL)
        node->flip(index);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

void MainWindow::swap(int fromTo)
{
    _scene->getNodes()->clearFlag(NODE_FLAG_SWAPPED);
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL)
        node->swap(fromTo);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

void MainWindow::flatten(int index, bool zero)
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL)
        node->flatten(index, zero);
}

void MainWindow::setDefault()
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != NULL)
        if (node->maySetDefault())
            node->setDefault();
}

void MainWindow::InsertNewNurbsNode(Node *nurbsNode, Node* parent)
{
    bool defaultColor = false;
    if (nurbsNode != NULL) {
        // be carefull with sending delete commands to a commandlist
        // later commands which would use the place of the deleted node
        // would fail
        CommandList *list = new CommandList();
        if (isToNurbsAllowedParent(parent)) 
            _scene->DeleteSelected();
        else 
            return;
        if (parent == _scene->getRoot())
            list->append(new MoveCommand(nurbsNode, NULL, -1, 
                            _scene->getRoot(), _scene->getRootField()));
        else if (parent->getType() == VRML_GROUP)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Field()));
        else if (parent->getType() == VRML_TRANSFORM)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeTransform *)parent)->children_Field()));
        else if (parent->getType() == VRML_ANCHOR)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeAnchor *)parent)->children_Field()));
        else if (parent->getType() == VRML_SHAPE) {
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                             ((NodeShape *)parent)->geometry_Field()));
            if (defaultColor) {
                NodeAppearance *nAppearance = (NodeAppearance *)
                                              _scene->createNode("Appearance");
                NodeMaterial   *nMaterial = (NodeMaterial *) 
                                            _scene->createNode("Material");
                nAppearance->material(new SFNode(nMaterial));
                if (((NodeShape *)parent)->appearance() != NULL) {
                    list->append(new MoveCommand(
                          ((NodeShape *)parent)->appearance()->getValue(),
                          parent, ((NodeShape *)parent)->appearance_Field(), 
                               NULL, -1));
                    // the former is a delete command, so this command
                    // must be executed at once
                    _scene->execute(list);
                    list = new CommandList();
                }
                list->append(new MoveCommand(nAppearance, NULL, -1, parent,
                      ((NodeShape *)parent)->appearance_Field()));
            }
        }
        _scene->execute(list);
        _scene->setSelection(nurbsNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void MainWindow::triangulate(void) {
    Node *node =_scene->getSelection()->getNode(); 
    if (node->getType() == VRML_INDEXED_FACE_SET) {
        NodeIndexedFaceSet *faceset = (NodeIndexedFaceSet *) node;
        faceset->triangulateMesh();
        MFInt32 *mfcoordIndex = faceset->getCoordIndexFromMesh();
        if (mfcoordIndex) {
            mfcoordIndex = (MFInt32 *) mfcoordIndex->copy();
            _scene->setField(faceset, faceset->coordIndex_Field(),
                              new MFInt32(*mfcoordIndex));
        }
        NodeCoordinate *coord = (NodeCoordinate *)faceset->coord()->getValue();
        MFVec3f *mfcoord = faceset->getCoordFromMesh();
        if (coord && mfcoord) {
            mfcoord = (MFVec3f *) mfcoord->copy();
            _scene->setField(coord, coord->point_Field(), new MFVec3f(*mfcoord));
        }
        Node *normal = faceset->normal()->getValue();
        if (normal) 
            _scene->execute(new MoveCommand(normal, faceset, 
                                            faceset->normal_Field(), NULL, -1));
        _scene->setField(faceset, faceset->normalIndex_Field(), new MFInt32());

        Node *texCoord = faceset->texCoord()->getValue();
        if (texCoord) 
            _scene->execute(new MoveCommand(texCoord, faceset, 
                                            faceset->texCoord_Field(), 
                                            NULL, -1));
        _scene->setField(faceset, faceset->texCoordIndex_Field(), 
                         new MFInt32());

        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void MainWindow::optimizeSet(void) {
    Node *node =_scene->getSelection()->getNode(); 
    if (node->getType() == VRML_INDEXED_FACE_SET) {
        NodeIndexedFaceSet *faceset = (NodeIndexedFaceSet *) node;
        MFVec3f *mfVertices = new MFVec3f();
        MFInt32 *mfCoordIndex = new MFInt32();
        faceset->optimizeMesh(mfVertices, mfCoordIndex);
        NodeCoordinate *coord = (NodeCoordinate *) faceset->coord()->getValue();
        if (coord && mfVertices && mfCoordIndex) {
            coord->point(new MFVec3f(*mfVertices));
            faceset->coordIndex(new MFInt32(*mfCoordIndex));
            faceset->update();
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void MainWindow::degreeElevate(int degree)
{
    Node *node =_scene->getSelection()->getNode(); 
    int type = node->getType();
    Node *parent = node->getParent();

    Node* newNode = NULL;

    if (type == VRML_NURBS_CURVE) {
        NodeNurbsCurve *oldNode = (NodeNurbsCurve *)node;
        int newDegree = oldNode->order()->getValue() - 1 + degree;
        newNode = node->degreeElevate(newDegree);
        InsertNewNurbsNode(newNode, parent);
    } else if (type == DUNE_SUPER_EXTRUSION) {
        NodeSuperExtrusion *oldNode = (NodeSuperExtrusion *)node;
        int newDegree = oldNode->order()->getValue() - 1 + degree;
        newNode = node->degreeElevate(newDegree);
        InsertNewNurbsNode(newNode, parent);
    } else if (type == DUNE_SUPER_REVOLVER) {
        NodeSuperRevolver *oldNode = (NodeSuperRevolver *)node;
        int newDegree = oldNode->order()->getValue() - 1 + degree;
        newNode = node->degreeElevate(newDegree);
        InsertNewNurbsNode(newNode, parent);
    }
}

void MainWindow::uDegreeElevate(int degree)
{
    Node *node =_scene->getSelection()->getNode();
    int type = node->getType();
    Node *parent = node->getParent();
                          
    Node* nurbsNode = NULL;
                    
    if (type == VRML_NURBS_SURFACE) {
        NodeNurbsSurface *oldNurbs = (NodeNurbsSurface *)node;
        int newUDegree = oldNurbs->uOrder()->getValue() - 1 + degree;
        int newVDegree = oldNurbs->vOrder()->getValue() - 1;
        nurbsNode = node->degreeElevate(newUDegree, newVDegree);
        //SFRotation rot(0, 1, 0, M_PI / 2.0);
        //((NodeNurbsSurface *)nurbsNode)->rotate(rot);
        InsertNewNurbsNode(nurbsNode, parent);
    }
}

void MainWindow::vDegreeElevate(int degree)
{
    Node *node =_scene->getSelection()->getNode();
    int type = node->getType();
    Node *parent = node->getParent();
                          
    Node* nurbsNode = NULL;
                    
    if (type == VRML_NURBS_SURFACE) {
        NodeNurbsSurface *oldNurbs = (NodeNurbsSurface *)node;
        int newUDegree = oldNurbs->uOrder()->getValue() - 1;
        int newVDegree = oldNurbs->vOrder()->getValue() -1 + degree;
        nurbsNode = node->degreeElevate(newUDegree, newVDegree);
        //SFRotation rot(0, 1, 0, M_PI / 2.0);
        //((NodeNurbsSurface *)nurbsNode)->rotate(rot);
        InsertNewNurbsNode(nurbsNode, parent);
    }
}

void MainWindow::linearUknot(void)
{
    Node *node =_scene->getSelection()->getNode();
    if (node->getType() == VRML_NURBS_SURFACE) {
        NodeNurbsSurface *nurbs = (NodeNurbsSurface *)node;
        nurbs->linearUknot();
    }
}

void MainWindow::linearVknot(void)
{
    Node *node =_scene->getSelection()->getNode();
    if (node->getType() == VRML_NURBS_SURFACE) {
        NodeNurbsSurface *nurbs = (NodeNurbsSurface *)node;
        nurbs->linearVknot();
    }
}

void
MainWindow::swapDiffuseEmissiveShape(NodeShape *shape,
                                     ColorConversion conversion)
{
    SFNode *appear = shape->appearance();
    if (appear != NULL) {
        NodeAppearance *nAppearance = (NodeAppearance *) appear->getValue();
        NodeMaterial *nMaterial = NULL;
        if (nAppearance)
            nMaterial = (NodeMaterial *) nAppearance->material()->getValue(); 
        if (nMaterial != NULL) {
            switch(conversion) {
               case DIFFUSE2EMISSIVE:
                 nMaterial->diffuse2emissive();
                 break;
               case EMISSIVE2DIFFUSE:
                 nMaterial->emissive2diffuse();
                 break;
               default:
                 assert(0);
            }
        }
    }
}

void
MainWindow::toNurbs()
{
    Node *node =_scene->getSelection()->getNode(); 
    int type = node->getType();
    if (!node->hasParent())
        return;
    Node *parent = node->getParent();

    Node* nurbsNode = NULL;

    if (type == VRML_CYLINDER) {
        Cylinder2NurbsDialog dlg(_wnd, node, 4, 2, 3, 2, 2);
        if (dlg.DoModal() == IDOK) {
            int narcs = dlg.getNarcs();
            int nshell = dlg.getNshell();
            int narea  = dlg.getNarea();
            int uDegree = dlg.getuDegree();
            int vDegree = dlg.getvDegree();
            nurbsNode = node->toNurbs(nshell, narea, narcs, uDegree, vDegree);
            SFRotation rot(0, 1 , 0, M_PI / 2.0);
            ((NodeNurbsSurface *)nurbsNode)->rotate(rot);
        }
    }
    if (type == VRML_CONE) {
        Cone2NurbsDialog dlg(_wnd, node, 4, 2, 4, 2, 2);
        if (dlg.DoModal() == IDOK) {
            int narcs = dlg.getNarcs();
            int nshell = dlg.getNshell();
            int narea  = dlg.getNarea();
            int uDegree = dlg.getuDegree();
            int vDegree = dlg.getvDegree();
            nurbsNode = node->toNurbs(nshell, narea, narcs, uDegree, vDegree);
            SFRotation rot(0, 1, 0, M_PI / 2.0);
            ((NodeNurbsSurface *)nurbsNode)->rotate(rot);
        }
    }
    if (type == VRML_SPHERE) {
        Sphere2NurbsDialog dlg(_wnd, 2, 4, 2, 2);
        if (dlg.DoModal() == IDOK) {
            int narcslong = dlg.getNarcslong();
            int narcslat = dlg.getNarcslat();
            int uDegree = dlg.getuDegree();
            int vDegree = dlg.getvDegree();
            nurbsNode = node->toNurbs(narcslong,  narcslat, uDegree, vDegree);
            SFRotation rot(0, 1, 0, M_PI / 2.0);
            ((NodeNurbsSurface *)nurbsNode)->rotate(rot);
        }
    }
    if (type == VRML_BOX) {
        Box2NurbsDialog dlg(_wnd, 3, 3, 3, 2, 2);
        if (dlg.DoModal() == IDOK) {
            bool have6Planes = dlg.getHave6Planes();
            int nuAreaPoints = dlg.getNuAreaPoints();
            int uDegree = dlg.getuDegree();
            int nvAreaPoints = dlg.getNvAreaPoints();
            int vDegree = dlg.getvDegree();
            if (have6Planes) {
                nurbsNode = node->toNurbs(nuAreaPoints, uDegree, nvAreaPoints, vDegree);
                if (nurbsNode != NULL)
                    if (parent->getType() == VRML_SHAPE) {
                        // a NurbsGroup was created, need to delete Shape node
                        Node *grandParent = parent->getParent();
                        if (isToNurbsAllowedParent(parent)) {
                            _scene->setSelection(parent);
                            _scene->UpdateViews(NULL, UPDATE_SELECTION);
                            parent = grandParent;
                        } else
                            return;
                    }                
            } else {
                int nzAreaPoints;
                nzAreaPoints = dlg.getNzAreaPoints();
                nurbsNode = node->toNurbs(nuAreaPoints, uDegree, 
                                          nvAreaPoints, vDegree, nzAreaPoints);
            }
        }
    }
    if (type == VRML_NURBS_CURVE) {
        NurbsCurve2NurbsSurfDialog dlg(_wnd, node, 4, 2, 360, 
                                       NURBS_ROT_POINT_TO_POINT);
        if (dlg.DoModal() == IDOK) {
            int narcs = dlg.getNarcs();
            int pDegree = dlg.getuDegree();
            float rDegree = dlg.getrDegree();
            Vec3f P1 = dlg.getP1();
            Vec3f P2 = dlg.getP2();
            if (dlg.getFlatten())
                if (!((NodeNurbsCurve *)node)->revolveFlatten(dlg.getMethod()))
                     TheApp->PrintMessageWindowsId(
                           IDS_FLATTEN_NOT_SUPPORTED_ERROR);
            nurbsNode = node->toNurbs(narcs, pDegree, rDegree, P1, P2);
            if (nurbsNode == NULL)
                TheApp->MessageBoxId(IDS_NURBS_CURVE_CONVERT_ERROR);
            if ((dlg.getMethod() == NURBS_ROT_Y_AXIS) && dlg.getFlatten()) {
                float angle = - 0.5 * M_PI - 0.5 * DEG2RAD(rDegree);
                SFRotation rot(0, 1, 0, angle);
                ((NodeNurbsSurface *)nurbsNode)->rotate(rot);
            }
        }
    }
    if (type == DUNE_SUPER_ELLIPSOID) {
        NodeSuperEllipsoid *super = (NodeSuperEllipsoid *)node;
        int uTess = super->uTessellation()->getValue();
        if (uTess == 0)
            if (super->n2()->getValue() != 1)
                uTess = 22;
            else
                uTess = 6;
        int vTess = super->vTessellation()->getValue();
        if (vTess == 0)
            if (super->n1()->getValue() != 1)
                vTess = 20;
            else            
                vTess = 7;
        Sphere2NurbsDialog dlg(_wnd, uTess, vTess, 2, 2);
        if (dlg.DoModal() == IDOK) {
            int narcslong = dlg.getNarcslong();
            narcslong = 2 + ((narcslong - 2) / 4) * 4;
            int narcslat = dlg.getNarcslat();
            int uDegree = dlg.getuDegree();
            int vDegree = dlg.getvDegree();
            nurbsNode = node->toNurbs(narcslat,  narcslong, vDegree, uDegree);
        }
    }
    if (type == DUNE_SUPER_SHAPE) {
        NodeSuperShape *super = (NodeSuperShape *)node;
        int uTess = super->uTessellation()->getValue();
        if (uTess == 0) {
            float um = fabs(super->um()->getValue());
            uTess = 6;
            if (um * 3 > uTess)
                uTess = um * 3;
        }
        uTess = 2 + ((uTess - 2) / 4) * 4;
        int vTess = super->vTessellation()->getValue();
        if (vTess == 0) {
            vTess = 7;
            float vm = fabs(super->vm()->getValue());
            if (vm * 3 > vTess)
                vTess = vm * 3;
        } else
            vTess++;
        Sphere2NurbsDialog dlg(_wnd, uTess, vTess, 2, 2);
        if (dlg.DoModal() == IDOK) {
            int narcslong = dlg.getNarcslong();
            narcslong = 2 + ((narcslong - 2) / 4) * 4;
            int narcslat = dlg.getNarcslat();
            int uDegree = dlg.getuDegree();
            int vDegree = dlg.getvDegree();
            super->top(new SFBool(false));
            super->bottom(new SFBool(false));
            nurbsNode = super->toNurbs(narcslong, narcslat, uDegree, vDegree);
        }
    }
    if (type == DUNE_SUPER_EXTRUSION) {
        NodeSuperExtrusion *super = (NodeSuperExtrusion *)node;
        int uTess = super->superTessellation()->getValue();
        if (uTess == 0) {
            float um = fabs(super->m()->getValue());
            uTess = 6;
            if (um * 3 > uTess)
                uTess = um * 3;
        }
        uTess = 2 + ((uTess - 2) / 4) * 4;
        int vTess = super->spineTessellation()->getValue();
        if (vTess == 0)
            vTess = 8;
        Sphere2NurbsDialog dlg(_wnd, vTess, uTess, 2, 2);
        if (dlg.DoModal() == IDOK) {
            super->beginCap(new SFBool(false));
            super->endCap(new SFBool(false));
            int narcslong = dlg.getNarcslong();
            int narcslat = dlg.getNarcslat();
            narcslat = 2 + ((narcslat - 2) / 4) * 4;
            int uDegree = dlg.getuDegree();
            int vDegree = dlg.getvDegree();
            nurbsNode = node->toNurbs(narcslat, narcslong, uDegree, vDegree);
        }
    }
    if (type == DUNE_SUPER_REVOLVER) {
        NodeSuperRevolver *super = (NodeSuperRevolver *)node;
        int uTess = super->superTessellation()->getValue();
        if (uTess == 0) {
            float um = fabs(super->m()->getValue());
            uTess = 6;
            if (um * 4 > uTess)
                uTess = um * 4;
        }
        uTess = 2 + ((uTess - 2) / 4) * 4;
        int vTess = super->nurbsTessellation()->getValue();
        if (vTess == 0)
            vTess = 8;
        Sphere2NurbsDialog dlg(_wnd, uTess, vTess, 2, 2);
        if (dlg.DoModal() == IDOK) {
            super->pieceOfCake(new SFBool(false));
            int narcslong = dlg.getNarcslong();
            narcslong = 2 + ((narcslong - 2) / 4) * 4;
            int narcslat = dlg.getNarcslat();
            int uDegree = dlg.getuDegree();
            int vDegree = dlg.getvDegree();
            nurbsNode = node->toNurbs(narcslong, narcslat, uDegree, vDegree);
        }
    }

    if (nurbsNode != NULL) {
        if (!isToNurbsAllowedParent(parent)) 
            return;
        if (type == VRML_NURBS_CURVE)
            swapDiffuseEmissiveShape((NodeShape *)parent, EMISSIVE2DIFFUSE);
        _scene->replaceNode(node, nurbsNode);
        _scene->setSelection(nurbsNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }

}

void
MainWindow::toNurbsCurve()
{
    Node *node =_scene->getSelection()->getNode(); 
    int type = node->getType();
    Node *parent = node->getParent();

    Node* nurbsCurveNode = NULL;

    if (type == DUNE_SUPER_EXTRUSION)
        nurbsCurveNode = ((NodeSuperExtrusion *)node)->toNurbsCurve();
    if (type == DUNE_SUPER_REVOLVER)
        nurbsCurveNode = ((NodeSuperRevolver *)node)->toNurbsCurve();
    if (nurbsCurveNode != NULL) {
        if (!isToNurbsAllowedParent(parent)) 
            return;
        _scene->replaceNode(node, nurbsCurveNode);
        _scene->setSelection(nurbsCurveNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }

}

void
MainWindow::toSuperRevolver()
{
    Node *node =_scene->getSelection()->getNode(); 
    int type = node->getType();
    Node *parent = node->getParent();

    Node* superRevolverNode = NULL;

    if (type == VRML_NURBS_CURVE)
        superRevolverNode = ((NodeNurbsCurve *)node)->toSuperRevolver();
    if (superRevolverNode != NULL) {
        // be carefull with sending delete commands to a commandlist
        // later commands which would use the place of the deleted node
        // would fail
        if (!isToNurbsAllowedParent(parent)) 
            return;
        _scene->replaceNode(node, superRevolverNode);
        _scene->setSelection(superRevolverNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::toSuperExtrusion()
{
    Node *node =_scene->getSelection()->getNode(); 
    int type = node->getType();
    Node *parent = node->getParent();

    Node* superExtrusionNode = NULL;

    if (type == VRML_NURBS_CURVE)
        superExtrusionNode = ((NodeNurbsCurve *)node)->toSuperExtrusion();
    if (superExtrusionNode != NULL) {
        // be carefull with sending delete commands to a commandlist
        // later commands which would use the place of the deleted node
        // would fail
        if (!isToNurbsAllowedParent(parent)) 
            return;
        _scene->replaceNode(node, superExtrusionNode);
        _scene->setSelection(superExtrusionNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::toExtrusion()
{
    Node *node =_scene->getSelection()->getNode(); 

    if (node->canConvertToExtrusion()) {
        Node *extrusionNode = node->toExtrusion();
        if (extrusionNode != NULL) {
            _scene->replaceNode(node, extrusionNode);
            _scene->setSelection(extrusionNode);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::toIndexedFaceSet()
{
    Node *node =_scene->getSelection()->getNode(); 

    if (node->canConvertToIndexedFaceSet()) {
        bool wantNormals = true;
        if (node->getType() == DUNE_SUPER_ELLIPSOID)
            wantNormals = false;
        if (node->getType() == DUNE_SUPER_SHAPE)
            wantNormals = false;
        if (node->getType() == DUNE_SUPER_REVOLVER)
            wantNormals = false;
        if (node->getType() == VRML_EXTRUSION)
            wantNormals = false;
        if (node->getType() == VRML_ELEVATION_GRID)
            wantNormals = false;
        if (node->getType() == VRML_BOX)
            wantNormals = false;
/*
        if (node->getType() == VRML_CONE)
            wantNormals = false;
*/
        if (node->getType() == VRML_CYLINDER)
            wantNormals = false;
        if (node->getType() == VRML_SPHERE)
            wantNormals = false;
        int meshFlags = 0;
        if (wantNormals)
            meshFlags = MESH_WANT_NORMAL;
        Node *faceSetNode = node->toIndexedFaceSet(meshFlags);
        if (faceSetNode != NULL) {
            _scene->replaceNode(node, faceSetNode);
            _scene->setSelection(faceSetNode);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::toIndexedTriangleSet()
{
    Node *node = _scene->getSelection()->getNode(); 

    if (node->canConvertToIndexedTriangleSet()) {
        Node *triangleSetNode = node->toIndexedTriangleSet();
        if (triangleSetNode != NULL) {
            _scene->replaceNode(node, triangleSetNode);
            _scene->setSelection(triangleSetNode);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::toTriangleSet()
{
    Node *node =_scene->getSelection()->getNode(); 

    if (node->canConvertToTriangleSet()) {
        Node *triangleSetNode = node->toTriangleSet();
        if (triangleSetNode != NULL) {
            _scene->replaceNode(node, triangleSetNode);
            _scene->setSelection(triangleSetNode);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::toIndexedLineSet()
{
    Node *node =_scene->getSelection()->getNode(); 
    int type = node->getType();

    if (node->canConvertToIndexedLineSet() || (type == VRML_INDEXED_FACE_SET)) {
        Node *lineSetNode = NULL;
        if (node->canConvertToIndexedLineSet())
            lineSetNode = node->toIndexedLineSet();
        else if (type == VRML_INDEXED_FACE_SET) {
            NodeIndexedFaceSet *faceSet = (NodeIndexedFaceSet *)node;
            Node *textureCoordinate = faceSet->texCoord()->getValue();
            if (textureCoordinate)
                _scene->execute(new MoveCommand(textureCoordinate, faceSet, 
                                                faceSet->texCoord_Field(),
                                                NULL, -1));
            lineSetNode = faceSet->toIndexedLineSet();
        }
        if (lineSetNode != NULL) {
            _scene->replaceNode(node, lineSetNode);
            _scene->setSelection(lineSetNode);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::toPointSet()
{
    Node *node =_scene->getSelection()->getNode(); 
    int type = node->getType();

    if (type == VRML_INDEXED_LINE_SET) {
        Node *pointSetNode = ((NodeIndexedLineSet *)node)->toPointSet();
        if (pointSetNode != NULL) {
            _scene->replaceNode(node, pointSetNode);
            _scene->setSelection(pointSetNode);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::toPositionInterpolator()
{
    Node *node =_scene->getSelection()->getNode(); 

    if (node->canConvertToPositionInterpolator()) {
        Node *interpolator = node->toPositionInterpolator();
        if (interpolator != NULL) {
            _scene->execute(new MoveCommand(interpolator, NULL, -1, 
                                            _scene->getRoot(), 
                                            _scene->getRootField())); 
            _scene->setSelection(interpolator);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::toOrientationInterpolator(Direction direction)
{
    Node *node =_scene->getSelection()->getNode(); 

    if (node->canConvertToOrientationInterpolator()) {
        Node *interpolator = node->toOrientationInterpolator(direction);
        if (interpolator != NULL) {
            _scene->execute(new MoveCommand(interpolator, NULL, -1, 
                                            _scene->getRoot(), 
                                            _scene->getRootField())); 
            _scene->setSelection(interpolator);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::timeShift()
{
/*
    TimeShiftDialog dlg(_wnd);
    if (dlg.DoModal() == IDOK) {
          printf("%f %d\n",dlg.getFraction(),(int)dlg.getWrapAround());
    }
*/
}

void
MainWindow::setPathAllURLs()
{
    URLDialog dlg(_wnd);
    if (dlg.DoModal() == IDOK) {
        Node *node = _scene->getSelection()->getNode();
        _scene->setPathAllURL(dlg.getPath());
        _scene->UpdateViews(NULL, UPDATE_ALL, NULL);
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::InsertAudioClip()
{
    Node *current = _scene->getSelection()->getNode();
    int field = -1;
    if (current->getType() == VRML_SOUND) {
        NodeSound *sound = (NodeSound *)current;
        field = sound->source_Field();
    }
        
    if (field != -1) {

        char buf[MY_MAX_PATH];
        buf[0] = '\0';
        if (TheApp->getFileDialogDir())
            chdir(TheApp->getFileDialogDir());
        if (swOpenFileDialog(_wnd, "Select Sound Data (*.wav,*.midi)",
                             "Sound Files (*.wav, *.midi)\0*.wav;*.midi\0All Files (*.*)\0*.*\0\0",
                             buf, MY_MAX_PATH)) {

            NodeAudioClip *node = (NodeAudioClip *)
                                  _scene->createNode("AudioClip");
            URL url;
            url.FromPath(buf);
            node->url(new 
                      MFString(rewriteURL(url,url.GetDir(),_scene->getURL())));
            _scene->execute(new MoveCommand(node, NULL, -1, current, field));
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::InsertImageTexture()
{
    Node *current = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();
    if (field == -1) 
        field = current->findFirstValidFieldType(TEXTURE_NODE);
    else
        if (!current->validChildType(field, TEXTURE_NODE))
            field = -1;

    if (field != -1) {
        char buf[MY_MAX_PATH];

        buf[0] = '\0';
       if (TheApp->getFileDialogDir())
           chdir(TheApp->getFileDialogDir());
        if (swOpenFileDialog(_wnd, "Select Image (*.jpg, *.png)",
#ifdef HAVE_LIBDEVIL
            "All Files (*.*)\0*.*\0\0",
#else
            "Image Files (*.gif, *.jpg, *.png)\0*.gif;*.jpg;*.png\0All Files (*.*)\0*.*\0\0",
#endif
                             buf, MY_MAX_PATH)) {
            NodeImageTexture *node = (NodeImageTexture *)
                                     _scene->createNode("ImageTexture");
            URL url;
            url.FromPath(buf);
            node->url(new 
                      MFString(rewriteURL(url,url.GetDir(),_scene->getURL())));
            _scene->execute(new MoveCommand(node, NULL, -1, current, field));
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::InsertMultiTexture()
{
    Node *current = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();
    if (field == -1) 
        field = current->findValidFieldType(TEXTURE_NODE);
    else
        if (!current->validChildType(field, TEXTURE_NODE))
            field = -1;

    if (field != -1) {
        if (current->getType() != X3D_MULTI_TEXTURE) {
            Node *node = _scene->createNode("MultiTexture");
            _scene->execute(new MoveCommand(node, NULL, -1, current, field));
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::InsertMultiTextureCoordinate()
{
    Node *current = _scene->getSelection()->getNode();
    if (current->getType() != X3D_MULTI_TEXTURE_COORDINATE)
        InsertNode(TEXTURE_COORDINATE_NODE, "MultiTextureCoordinate");
}

void
MainWindow::InsertMultiTextureTransform()
{
    Node *current = _scene->getSelection()->getNode();
    if (current->getType() != X3D_MULTI_TEXTURE_TRANSFORM)
        InsertNode(TEXTURE_TRANSFORM_NODE, "MultiTextureTransform");
}

void
MainWindow::InsertMultiGeneratedTextureCoordinate()
{
    Node *current = _scene->getSelection()->getNode();
    if (current->getType() != KAMBI_MULTI_GENERATED_TEXTURE_COORDINATE)
        InsertNode(GENERATED_TEXTURE_COORDINATE_NODE, 
                   "MultiGeneratedTextureCoordinate");
}

void MainWindow::InsertRigidBody()
{
    Node *current = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();
    if (field == -1) 
        field = current->findFirstValidFieldType(X3D_RIGID_BODY);
    else
       if (!current->validChildType(field, X3D_RIGID_BODY))
           field = -1;
    
    if (current->matchNodeClass(RIGID_JOINT_NODE)) {
        X3DRigidJointNode *joint = (X3DRigidJointNode *)current;
        if (joint->body1()->getValue() == NULL)
            field = joint->body1_Field();
        else if (joint->body2()->getValue() == NULL)
            field = joint->body2_Field();
    }
    if (current->getType() == X3D_CONTACT) {
        NodeContact *contact = (NodeContact *)current;
        if (contact->body1()->getValue() == NULL)
            field = contact->body1_Field();
        else if (contact->body2()->getValue() == NULL)
            field = contact->body2_Field();
    }

    if (field != -1) {
        Node *node = _scene->createNode("RigidBody");
        _scene->execute(new MoveCommand(node, NULL, -1, current, field));
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::InsertVrmlScene()
{
    InsertNode(DUNE_VRML_SCENE, "VrmlScene");
    TheApp->PrintMessageWindowsId(IDS_NOW_USE_FILE_IMPORT);
}

void
MainWindow::InsertCubeTexture()
{
    Node *current = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();
    if (field == -1) 
        field = current->findValidFieldType(TEXTURE_NODE);
    else
        if (!current->validChildType(field, TEXTURE_NODE))
            field = -1;

    if (field != -1) {
        char buf[MY_MAX_PATH];

        NodeCubeTexture *node = (NodeCubeTexture *)
                                _scene->createNode("CubeTexture");
        for (int i = 0; i < 6; i++) {
            buf[0] = '\0';
            const char *message = "";
            if (i == 0)
                message = "Select XP Image (*.jpg, *.png)";
            else if (i == 1)
                message = "Select XN Image (*.jpg, *.png)";
            else if (i == 2)
                message = "Select YP Image (*.jpg, *.png)";
            else if (i == 3)
                message = "Select YN Image (*.jpg, *.png)";
            else if (i == 4)
                message = "Select ZP Image (*.jpg, *.png)";
            else if (i == 5)
                message = "Select ZN Image (*.jpg, *.png)";
            if (TheApp->getFileDialogDir())
                chdir(TheApp->getFileDialogDir());
            if (swOpenFileDialog(_wnd, message,
                "Image Files (*.jpg, *.png)\0*.jpg;*.png\0All Files (*.*)\0*.*\0\0",
                             buf, MY_MAX_PATH)) {
                URL url;
                url.FromPath(buf);
                MFString *mfString = new MFString(rewriteURL(url,url.GetDir(),
                                                             _scene->getURL()));
                if (i == 0)
                   node->urlXP(mfString);
                else if (i == 1)
                   node->urlXN(mfString);
                else if (i == 2)
                   node->urlYP(mfString);
                else if (i == 3)
                   node->urlYN(mfString);
                else if (i == 4)
                   node->urlZP(mfString);
                else if (i == 5)
                   node->urlZN(mfString);
            }
        }
        _scene->execute(new MoveCommand(node, NULL, -1, current, field));
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::InsertArray(void)
{
    ArrayDialog dlg(_wnd);
    if (dlg.DoModal() == IDOK) {
        Node *node = _scene->getSelection()->getNode();
        NodeTransform *transform = (NodeTransform *) InsertNode("Transform");
        for (int i = 1; i <= dlg.getNumberCopies(); i++) {
            NodeTransform *copyTransform = (NodeTransform *)
                                           _scene->createNode("Transform"); 
            Vec3f scale(dlg.getScale().getValue());
            Vec3f one(1,1,1);
            scale = (scale - one) * i;
            copyTransform->scale(new SFVec3f(one + scale));
            copyTransform->center(new SFVec3f(dlg.getCenter()));
            Vec3f translation(dlg.getTranslation().getValue());
            copyTransform->translation(new SFVec3f(translation * i));
            SFRotation rotation(dlg.getRotation());
            rotation.setValue(3, rotation.getValue(3) * i);
            copyTransform->rotation(new SFRotation(rotation));
            _scene->execute(new MoveCommand(copyTransform, NULL, -1, 
                                            transform,
                                            transform->children_Field()));
            _scene->execute(new MoveCommand(node, NULL, -1, copyTransform,
                                            copyTransform->children_Field()));
        }
        _scene->UpdateViews(NULL, UPDATE_ALL, NULL);    
        if (node->isInScene(_scene)) {
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }

}

void
MainWindow::InsertInline(bool withLoadControl)
{
    char buf[MY_MAX_PATH];

    buf[0] = '\0';
    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir());    
    char *fileSelectorText = getFileSelectorText();
    if (swOpenFileDialog(_wnd, "Insert Inline", fileSelectorText, buf, 
                         MY_MAX_PATH)) {
         NodeInline *node;
         if (withLoadControl)
             node = (NodeInline *)CreateNode("InlineLoadControl");
         else
             node = (NodeInline *)CreateNode("Inline");
         URL url;
         url.FromPath(buf);
         node->url(new MFString(rewriteURL(url,url.GetDir(),_scene->getURL())));
         _scene->readInline(node);
    }
    delete [] fileSelectorText;
}

void
MainWindow::InsertMovieTexture()
{
    char buf[MY_MAX_PATH];

    buf[0] = '\0';
    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir());
    if (swOpenFileDialog(_wnd, "Select movie (MPEG1) File (*.mpg, *.mpeg)",
         "MPEG1 Files (*.mpg, *.mpeg)\0*.mpg;*.mpeg\0All Files (*.*)\0*.*\0\0",
         buf, MY_MAX_PATH)) {
        Node       *current = _scene->getSelection()->getNode();
        int field = _scene->getSelection()->getField();
        if (field == -1) 
            field = current->findValidFieldType(TEXTURE_NODE);
        else
            if (!current->validChildType(field, TEXTURE_NODE))
                field = -1;

        if (field != -1) {
            NodeMovieTexture *node = (NodeMovieTexture *)
                                     _scene->createNode("MovieTexture");
            URL url;
            url.FromPath(buf);
            node->url(new 
                      MFString(rewriteURL(url,url.GetDir(),_scene->getURL())));
            _scene->execute(new MoveCommand(node, NULL, -1, current, field));
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::InsertNormal()
{
    Node *node = _scene->getSelection()->getNode();
    if (node != NULL) {
        _scene->createNormal(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::InsertTextureCoordinate(bool generator)
{
    Node *node = _scene->getSelection()->getNode();
    if (node != NULL) {
        int field = _scene->getSelection()->getField();
        if (field == -1)
            field = node->findFirstValidFieldType(TEXTURE_COORDINATE_NODE);
        else
           if (!node->validChildType(field, TEXTURE_COORDINATE_NODE))
               field = -1;
        if ((field == -1) && generator)
            field = node->findFirstValidFieldType(
                                           GENERATED_TEXTURE_COORDINATE_NODE);
        if ((field == -1) && (!TheApp->getCoverMode()) && 
            node->getType() == VRML_INDEXED_FACE_SET) {
            field = ((NodeIndexedFaceSet *)node)->texCoord_Field();
        }
        if (field == -1)
            field = node->findFirstValidFieldType(VRML_TEXTURE_COORDINATE);
        if ((field == -1) && generator)
            field = node->findFirstValidFieldType(
                                         X3D_TEXTURE_COORDINATE_GENERATOR);
        if (field != -1) {
            int type = node->getProto()->getField(field)->getType();
            // ignore Nodes with already set field
            if (type == SFNODE) { 
                SFNode *sfNode = (SFNode *) node->getField(field);
                if (sfNode->getValue() != NULL)
                    return;
            }
            Node *ntexCoord = NULL;
            if (generator) 
                ntexCoord = _scene->createNode("TextureCoordinateGenerator");
            else
                ntexCoord = _scene->createNode("TextureCoordinate");
            if (ntexCoord != NULL) {
                MoveCommand *command = new MoveCommand(ntexCoord, NULL, -1,
                                                       node, field); 
                command->execute();
                node->setTexCoordFromMesh(ntexCoord);
                _scene->UpdateViews(NULL, UPDATE_SELECTION);
            }
        }
    }
}

void
MainWindow::InsertHAnimJoint()
{
    Node *current = _scene->getSelection()->getNode();
    if (current->findValidFieldType(X3D_HANIM_JOINT) != -1)
        InsertNode(X3D_HANIM_JOINT, "HAnimJoint");
    else if (current->findValidFieldType(HANIM_CHILD_NODE) != -1)
        InsertNode(HANIM_CHILD_NODE, "HAnimJoint");
    else {    
        if (current->getType() == X3D_HANIM_HUMANOID) {
            int field = _scene->getSelection()->getField();
            NodeHAnimHumanoid *human = (NodeHAnimHumanoid *)current;
            Node *node = _scene->createNode("HAnimJoint");
            if (field != human->joints_Field())
                field = human->skeleton_Field();
            _scene->execute(new MoveCommand(node, NULL, -1, current, field));
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::InsertHAnimSegment()
{
    Node *current = _scene->getSelection()->getNode();
    if (current->findValidFieldType(X3D_HANIM_SEGMENT) != -1)
        InsertNode(X3D_HANIM_SEGMENT, "HAnimSegment");
    else {    
        if (current->getType() == X3D_HANIM_JOINT) {
            int field = _scene->getSelection()->getField();
            NodeHAnimJoint *joint = (NodeHAnimJoint *)current;
            if (field != joint->displacers_Field()) {
                Node *node = _scene->createNode("HAnimSegment");
                _scene->execute(new MoveCommand(node, NULL, -1, current, 
                                                joint->children_Field()));
                _scene->setSelection(node);
                _scene->UpdateViews(NULL, UPDATE_SELECTION);
            }
        }
    }
}

void
MainWindow::InsertHAnimSite()
{
    Node *current = _scene->getSelection()->getNode();
    if (current->findValidFieldType(X3D_HANIM_SITE) != -1)
        InsertNode(X3D_HANIM_SITE, "HAnimSite");
    else {    
        if (current->getType() == X3D_HANIM_JOINT) {
            int field = _scene->getSelection()->getField();
            NodeHAnimJoint *joint = (NodeHAnimJoint *)current;
            if (field != joint->displacers_Field()) {
                Node *node = _scene->createNode("HAnimSite");
                _scene->execute(new MoveCommand(node, NULL, -1, current, 
                                                joint->children_Field()));
                _scene->setSelection(node);
                _scene->UpdateViews(NULL, UPDATE_SELECTION);
            }
        }
    }
}

void
MainWindow::CreateVirtualAcoustics()
{
    CreateNode("VirtualAcoustics");
}

void
MainWindow::InsertVirtualSoundSource()
{
    Node *current = _scene->getSelection()->getNode();
    int field = current->findValidFieldType(COVER_VIRTUAL_SOUND_SOURCE);
    if (field != -1) {

        char buf[MY_MAX_PATH];
        buf[0] = '\0';
        if (TheApp->getFileDialogDir())
            chdir(TheApp->getFileDialogDir());
        if (swOpenFileDialog(_wnd, "Select Sound Wave File (*.wav, *.wave)",
                             "Wave Sound Files (*.wav, *.wave)\0*.wav;*.wave\0All Files (*.*)\0*.*\0\0",
                             buf, MY_MAX_PATH)) {
            NodeVirtualSoundSource *node = (NodeVirtualSoundSource *)
                  _scene->createNode("VirtualSoundSource");
            char *lastSelector = strrchr(buf, swGetPathSelector());
            char *fileName = buf;
            if (lastSelector != NULL)
                fileName = lastSelector + 1;
            node->source(new SFString(fileName));
            _scene->execute(new MoveCommand(node, NULL, -1, current, field));
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

Node*
MainWindow::InsertNode(const char *type)
{
    Node *current = _scene->getSelection()->getNode();

    int field = -1;
    if (current == _scene->getRoot())
        field = _scene->getRootField();
    else {
        field = current->getParentField();
        current = current->getParent();
    }

    Node *ret = NULL;
    if (field != -1) {
        Node *node = _scene->createNode(type);
        if (node == NULL)
            return NULL;
        if (node->matchNodeClass(RIGID_JOINT_NODE) ||
            (node->getType() == X3D_CONTACT))
            if (current->findValidField(node) == -1)
                return NULL;
        _scene->execute(new MoveCommand(node, NULL, -1, current, field));
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
        ret = node;
    }
    return ret;
}

Node*
MainWindow::InsertNode(int fieldType, const char *type)
{
    Node *current = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();
    if (fieldType == ROOT_NODE) {
        if (current == _scene->getRoot())
            field = _scene->getRootField();
        else
            return NULL;
    } else {
        if (field == -1) 
            field = current->findFirstValidFieldType(fieldType);
        else
            if (!current->validChildType(field, fieldType))
                field = -1;
    }

    Node *ret = NULL;
    if (field != -1) {
        Node *node = _scene->createNode(type);
        _scene->execute(new MoveCommand(node, NULL, -1, current, field));
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
        ret = node;
    }
    return ret;
}

void MainWindow::toggleXrayRendering()
{
    static bool xrayRendering = false;
    xrayRendering = !xrayRendering;
    swMenuSetFlags(_menu, ID_TOGGLE_XRAY_RENDERING, SW_MENU_CHECKED, 
                   xrayRendering ? SW_MENU_CHECKED  : 0);
    _scene->setXrayRendering(xrayRendering);
}

void MainWindow::ToggleFullScreen()
{
    _fullScreen_enabled=!_fullScreen_enabled;
    TheApp->SetBoolPreference("FullScreen", _fullScreen_enabled);
    swMenuSetFlags(_menu, ID_DUNE_VIEW_FULL_SCREEN, SW_MENU_CHECKED, 
                   _fullScreen_enabled ? SW_MENU_CHECKED  : 0);
    swToolbarSetButtonFlags(_standardToolbar, _fullScreenIconPos, 
                            SW_TB_CHECKED, 
                            _fullScreen_enabled ? SW_TB_CHECKED : 0);
    if (_fullScreen_enabled) {
        swHideWindow(_treeView->GetWindow());
        swHideWindow(_fieldView->GetWindow());
        swHideWindow(_graphView->GetWindow());
        swHideWindow(_channelView->GetWindow());
        swMenuSetFlags(_menu, ID_DUNE_VIEW_SCENE_TREE, SW_MENU_DISABLED, 
                       SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_SCENE_GRAPH, SW_MENU_DISABLED, 
                       SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_FIELD_VIEW, SW_MENU_DISABLED, 
                       SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_CHANNEL_VIEW, SW_MENU_DISABLED, 
                       SW_MENU_DISABLED);  
        _toolbarWindow->ShowToolbar(_nodeToolbar1, false);
        _toolbarWindow->ShowToolbar(_nodeToolbar2, false);
        _toolbarWindow->ShowToolbar(_nodeToolbar3, false);
        _toolbarWindow->ShowToolbar(_nodeToolbarVRML200x, false);
        _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents1, false);
        _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents2, false);
        _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents3, false);
        _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents4, false);
        _toolbarWindow->ShowToolbar(_nodeToolbarScripted, false);
        _toolbarWindow->ShowToolbar(_nodeToolbarCover, false);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_1, SW_MENU_DISABLED, 
                       SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_2, SW_MENU_DISABLED, 
                       SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_3, SW_MENU_DISABLED, 
                       SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_VRML200X, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_1, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_2, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_3, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_4, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_RIGID_BODY, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_SCRIPTED, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_COVER, 
                       SW_MENU_DISABLED, SW_MENU_DISABLED);
    } else {
        if (_treeView->getEnabled())
            swShowWindow(_treeView->GetWindow());
        if (_fieldView->getEnabled())
            swShowWindow(_fieldView->GetWindow());
        if (_graphView->getEnabled())
            swShowWindow(_graphView->GetWindow());
        if (_channelView->getEnabled())
            swShowWindow(_channelView->GetWindow());
        swMenuSetFlags(_menu, ID_DUNE_VIEW_SCENE_TREE, SW_MENU_DISABLED, 0);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_SCENE_GRAPH, SW_MENU_DISABLED, 0);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_FIELD_VIEW, SW_MENU_DISABLED, 0);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_CHANNEL_VIEW, SW_MENU_DISABLED, 0);  
        if (_nodeToolbar1Enabled)
            _toolbarWindow->ShowToolbar(_nodeToolbar1, true);
        if (_nodeToolbar2Enabled)
            _toolbarWindow->ShowToolbar(_nodeToolbar2, true);
        if (_nodeToolbar3Enabled)
            _toolbarWindow->ShowToolbar(_nodeToolbar3, true);
        if (_nodeToolbarVRML200xEnabled)
            _toolbarWindow->ShowToolbar(_nodeToolbarVRML200x, true);
        if (_nodeToolbarX3DComponents1Enabled)
            _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents1, true);
        if (_nodeToolbarX3DComponents2Enabled)
            _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents2, true);
        if (_nodeToolbarX3DComponents3Enabled)
            _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents3, true);
        if (_nodeToolbarX3DComponents4Enabled)
            _toolbarWindow->ShowToolbar(_nodeToolbarX3DComponents4, true);
        if (_nodeToolbarScriptedEnabled)
            _toolbarWindow->ShowToolbar(_nodeToolbarScripted, true);
        if (_nodeToolbarCoverEnabled)
            _toolbarWindow->ShowToolbar(_nodeToolbarCover, true);
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_1, SW_MENU_DISABLED,0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_2, SW_MENU_DISABLED,0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_3, SW_MENU_DISABLED,0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_VRML200X, 
                       SW_MENU_DISABLED, 0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_1, 
                       SW_MENU_DISABLED, 0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_2, 
                       SW_MENU_DISABLED, 0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_3, 
                       SW_MENU_DISABLED, 0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_X3D_COMPONENTS_4, 
                       SW_MENU_DISABLED, 0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_SCRIPTED, 
                       SW_MENU_DISABLED, 0); 
        swMenuSetFlags(_menu, ID_DUNE_VIEW_NODE_TOOLBAR_COVER, 
                       SW_MENU_DISABLED, 0); 
    }
    _innerPane->Layout();
    _outerPane->Layout();
    Layout();
}

void MainWindow::ToggleView(int direction, SceneView *view, int id,
                            const char *name)
{
    bool visible = !swIsVisible(view->GetWindow());
    view->setEnabled(visible); 
    swMenuSetFlags(_menu, id, SW_MENU_CHECKED, visible ? SW_MENU_CHECKED : 0);
    if (visible) {
        swShowWindow(view->GetWindow());
    } else {
        swHideWindow(view->GetWindow());
    }
    TheApp->SetBoolPreference(name, visible);
    _innerPane->Layout();
}

void MainWindow::ShowView(int direction, SceneView *view, int id,
                          const char *name)
{
    bool visible = !swIsVisible(view->GetWindow());
    view->setEnabled(visible); 
    swMenuSetFlags(_menu, id, SW_MENU_CHECKED, visible ? SW_MENU_CHECKED : 0);
    if (visible) {
        swShowWindow(view->GetWindow());
    }
    TheApp->SetBoolPreference(name, visible);
    _innerPane->Layout();
}

void MainWindow::ToggleToolbar(ToolbarWindow *tbWin, STOOLBAR toolbar,
                               int id, const char *name)
{
    bool visible = !swIsVisible(swToolbarGetWindow(toolbar));
    if ((id == ID_DUNE_VIEW_NODE_TOOLBAR_COVER) && !TheApp->getCoverMode())
        visible = false;    
    swMenuSetFlags(_menu, id, SW_MENU_CHECKED, visible ? SW_MENU_CHECKED : 0);
    tbWin->ShowToolbar(toolbar, visible);
    TheApp->SetBoolPreference(name, visible);
    _outerPane->Layout();
}

void MainWindow::ToggleStatusbar()
{
    SWND wnd = _statusBar->GetWindow();
    bool visible = !swIsVisible(wnd);
    _statusBar->setEnabled(visible); 
    swMenuSetFlags(_menu, ID_DUNE_VIEW_STATUS_BAR,
                   SW_MENU_CHECKED, visible ? SW_MENU_CHECKED : 0);
    if (visible) {
        swShowWindow(wnd);
    } else {
        swHideWindow(wnd);
    }
    TheApp->SetBoolPreference("ShowStatusBar", visible);
    Layout();
}

STOOLBAR
MainWindow::LoadToolbar(ToolbarWindow *tbWin, int id, int count,
                        const int *buttons, int menuid, const char *prefName)
{
    STOOLBAR toolbar;
    bool defaultPref = true;
    if (strcmp(prefName, "NodeToolbarVRML200x") == 0)
        defaultPref = false;
    if (stringncmp(prefName, "NodeToolbarX3DComponents") == 0)
        defaultPref = false;
    if (strcmp(prefName, "NodeToolbarRigidBody") == 0)
        defaultPref = false;
    if (strcmp(prefName, "NodeToolbarScripted") == 0)
        defaultPref = false;
    if (strcmp(prefName, "NodeToolbarCover") == 0)
        defaultPref = false;
    bool visible = TheApp->GetBoolPreference(prefName, defaultPref);
    toolbar = tbWin->LoadToolbar(id, count, buttons);
    tbWin->ShowToolbar(toolbar, visible);
    swMenuSetFlags(_menu, menuid, SW_MENU_CHECKED,
                   visible ? SW_MENU_CHECKED : 0);
    return toolbar;
}

STOOLBAR
MainWindow::LoadToolbar(ToolbarWindow *tbWin, int id, int count,
                        const NodeButton *buttons, int menuid, 
                        const char *prefName)
{
    int *intButtons = new int[2 * count];
    for (int i = 0; i < count; i++) {
        intButtons[i * 2] = buttons[i].type;
        intButtons[i * 2 + 1] = buttons[i].id;  
    }    
    STOOLBAR toolbar = LoadToolbar(tbWin, id, count, (const int*) intButtons, 
                                   menuid, prefName);
    delete [] intButtons;
    return toolbar;
}

void MainWindow::setColorCircleIcon()
{
    swMenuSetFlags(_menu, ID_COLOR_CIRCLE, SW_MENU_CHECKED, 
                          _colorCircle_active ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_COLOR_CIRCLE, SW_MENU_DISABLED, 
                          _colorCircle_enabled ? 0 : SW_MENU_DISABLED);
    if (_colorCircle_enabled)
       {
       swToolbarSetButtonFlags(_standardToolbar, _colorCircleIconPos, 
                               SW_TB_DISABLED, 0);
       swToolbarSetButtonFlags(_standardToolbar, _colorCircleIconPos, 
                               SW_TB_CHECKED, 
                               _colorCircle_active ? SW_TB_CHECKED : 0);
       }
    else
       {
       swToolbarSetButtonFlags(_standardToolbar, _colorCircleIconPos, 
                               SW_TB_DISABLED, SW_TB_DISABLED);
       }
}

void MainWindow::setXSymetricNurbsIcon()
{
       swMenuSetFlags(_menu, ID_X_SYMETRIC, SW_MENU_CHECKED,
                          TheApp->GetXSymetricMode() ? SW_MENU_CHECKED : 0);
       swToolbarSetButtonFlags(_standardToolbar, _x_symetricIconPos,
                               SW_TB_CHECKED, 
                               TheApp->GetXSymetricMode() ? SW_TB_CHECKED : 0);
}

void MainWindow::setTMode(TMode mode)
{
    if (_scene->getTransformMode()->tmode!=mode)
       TheApp->calibrateInputDevices();
    _scene->setTransformMode(mode);
    swMenuSetFlags(_menu, ID_MOVE_MODE, SW_MENU_CHECKED,
                   mode == TM_TRANSLATE ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_ROTATE_MODE, SW_MENU_CHECKED,
                   mode == TM_ROTATE ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_SCALE_MODE, SW_MENU_CHECKED,
                   mode == TM_SCALE ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_UNIFORM_SCALE_MODE, SW_MENU_CHECKED,
                   mode == TM_UNIFORM_SCALE ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_CENTER_MODE, SW_MENU_CHECKED,
                   mode == TM_CENTER ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_6D_MODE, SW_MENU_CHECKED,
                   mode == TM_6D ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_6DLOCAL_MODE, SW_MENU_CHECKED,
                   mode == TM_6DLOCAL ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_ROCKET_MODE, SW_MENU_CHECKED,
                   mode == TM_ROCKET ? SW_MENU_CHECKED : 0);
    swMenuSetFlags(_menu, ID_HOVER_MODE, SW_MENU_CHECKED,
                   mode == TM_HOVER ? SW_MENU_CHECKED : 0);
    int i=_inputModeStartIconPos;
    swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                            mode == TM_TRANSLATE ? SW_TB_CHECKED : 0);
    swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                            mode == TM_ROTATE ? SW_TB_CHECKED : 0);
    swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                            mode == TM_SCALE ? SW_TB_CHECKED : 0);
    swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                            mode == TM_UNIFORM_SCALE ? SW_TB_CHECKED : 0);
    swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                            mode == TM_CENTER ? SW_TB_CHECKED : 0);
    if (TheApp->getMaxNumberAxesInputDevices()>4) {
       swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                               mode == TM_6D ? SW_TB_CHECKED : 0);
       swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                               mode == TM_6DLOCAL ? SW_TB_CHECKED : 0);
    } else {
       swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_DISABLED,
                               SW_TB_DISABLED);
       swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_DISABLED,
                               SW_TB_DISABLED);
    }
    if (TheApp->getMaxNumberAxesInputDevices()>=3) 
       swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                               mode == TM_ROCKET ? SW_TB_CHECKED : 0);
    else
       swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_DISABLED,
                               SW_TB_DISABLED);
    if (TheApp->getMaxNumberAxesInputDevices()>=2) 
       swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                               mode == TM_HOVER ? SW_TB_CHECKED : 0);
    else
       swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_DISABLED,
                               SW_TB_DISABLED);
    
    setT2axes(_scene->getTransformMode()->t2axes);
    //_scene->UpdateViews(NULL, UPDATE_MODE);
}

void MainWindow::setTDimension(TDimension dim)
{
    _scene->setTransformMode(dim);
    int i=_tDimensionStartIconPos;
    if (TheApp->getMaxNumberAxesInputDevices()>=2) 
       {
       swMenuSetFlags(_menu, ID_3D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
       swMenuSetFlags(_menu, ID_2D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);
       swMenuSetFlags(_menu, ID_1D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_RADIO_ITEM);

      swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                              dim == TM_3D ? SW_TB_CHECKED : 0);
      swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                              dim == TM_2D ? SW_TB_CHECKED : 0);
      swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_CHECKED,
                              dim == TM_1D ? SW_TB_CHECKED : 0);
       }
    else
       {
       swMenuSetFlags(_menu, ID_3D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
       swMenuSetFlags(_menu, ID_2D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);
       swMenuSetFlags(_menu, ID_1D_MODE, SW_MENU_RADIO_ITEM, SW_MENU_DISABLED);

      swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_DISABLED, 
                              SW_TB_DISABLED); 
      swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_DISABLED, 
                              SW_TB_DISABLED); 
      swToolbarSetButtonFlags(_standardToolbar, i++, SW_TB_DISABLED, 
                              SW_TB_DISABLED);
       }

    _scene->UpdateViews(NULL, UPDATE_MODE);
}

void MainWindow::setT2axes(T2axes axes)
{
    _scene->setTransformMode(axes);
    bool showIcons=false;
    if ( TheApp->has2AxesInputDevices() ||
         (TheApp->has3AxesInputDevices() && 
          (_scene->getTransformMode()->tmode==TM_ROCKET)) )
         showIcons=true;
    int i=_t2axesStartIconPos;
    if (showIcons) {
       swMenuSetFlags(_menu, ID_NEAR_FAR_MODE, SW_MENU_RADIO_ITEM, 
                      axes == TM_NEAR_FAR ? SW_MENU_RADIO_ITEM : 0);
       swToolbarSetButtonFlags(_standardToolbar, i, SW_TB_DISABLED, 0);
       swToolbarSetButtonFlags(_standardToolbar, i++, 
            SW_TB_CHECKED, axes == TM_NEAR_FAR ? SW_TB_CHECKED : 0 );
    } else {
       swMenuSetFlags(_menu, ID_NEAR_FAR_MODE, SW_MENU_RADIO_ITEM, 
                      SW_MENU_DISABLED);
       swToolbarSetButtonFlags(_standardToolbar, i++, 
            SW_TB_DISABLED, SW_TB_DISABLED);
    }
    if (showIcons) {
       swMenuSetFlags(_menu, ID_UP_DOWN_MODE, SW_MENU_RADIO_ITEM, 
                      axes == TM_UP_DOWN ? SW_MENU_RADIO_ITEM : 0);
       swToolbarSetButtonFlags(_standardToolbar, i, SW_TB_DISABLED, 0);
       swToolbarSetButtonFlags(_standardToolbar, i++, 
            SW_TB_CHECKED, axes == TM_UP_DOWN ? SW_TB_CHECKED : 0 );
    } else {
       swMenuSetFlags(_menu, ID_UP_DOWN_MODE, SW_MENU_RADIO_ITEM, 
                      SW_MENU_DISABLED);
       swToolbarSetButtonFlags(_standardToolbar, i++, 
            SW_TB_DISABLED, SW_TB_DISABLED);
    }
    _scene->UpdateViews(NULL, UPDATE_MODE);
}


int MainWindow::OnTimer()
{
    if (_scene->isRunning()) {
        _scene->updateTime();
        if (_vrmlCutNode != NULL)
            ((NodeVrmlCut *)_vrmlCutNode)->updateTime();
        return TRUE;
    } else {
        return FALSE;
    }
}

void MainWindow::Play()
{
    if (_scene->isRunning()) {
        swKillTimer(_timer);
        _scene->stop();
    } else {
        _timer = swSetTimer(_wnd, 1, timerCB, this);
        _scene->start();
    }
    swToolbarSetButtonFlags(_vcrToolbar, 3, SW_TB_CHECKED,
                            _scene->isRunning() ? SW_TB_CHECKED : 0);
}

void MainWindow::Stop()
{
    if (_scene->isRunning()) {
        swKillTimer(_timer);
        _scene->stop();
        _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);
    }
    _scene->setRecording(false);
    swToolbarSetButtonFlags(_vcrToolbar, 3, SW_TB_CHECKED, 0);
    swToolbarSetButtonFlags(_vcrToolbar, 2, SW_TB_CHECKED, 0);
}

void MainWindow::Record()
{
    _scene->setRecording(!_scene->isRecording());
    swToolbarSetButtonFlags(_vcrToolbar, 2, SW_TB_CHECKED,
                            _scene->isRecording() ? SW_TB_CHECKED : 0);
}

char *
MainWindow::getFileSelectorText(void)
{
   /* use "delete" on the returned value after usage */
   StringArray descriptions;
   StringArray wildcards;
   int numFileType = 0;
   descriptions[numFileType] = "VRML (*.wrl)";
#ifdef _WIN32
   wildcards[numFileType++] = "*.wrl;*.WRL;";
#else
   wildcards[numFileType++] = "*.wrl;*.WRL;*.x3dv;*.X3DV";
#endif
#ifdef HAVE_LIBZ
   descriptions[numFileType] = "compressed VRML (*.wrz)";
   wildcards[numFileType++] = "*.wrz;*.WRZ";
#endif
   descriptions[numFileType] = "X3DV (*.x3dv)";
   wildcards[numFileType++] = "*.x3dv;*.X3DV";
#ifdef HAVE_LIBZ
   descriptions[numFileType] = "compressed X3DV (*.x3dvz)";
   wildcards[numFileType++] = "*.x3dvz;*.X3DVZ";
#endif
   descriptions[numFileType] = "X3D (*.x3d)";
   wildcards[numFileType++] = "*.x3d;*.X3D";
   int len = 0;
   int i;
   for (i = 0; i < numFileType; i++) {
      len += strlen(descriptions[i]);
      len++;
      len += strlen(wildcards[i]);
      len++;
   }
   len++;
   char *ret = new char[len];
   len = 0;
   for (i = 0; i < numFileType; i++) {
      strcpy(ret + len, descriptions[i]);
      len += strlen(descriptions[i]);
      len++;
      strcpy(ret + len, wildcards[i]);      
      len += strlen(wildcards[i]);
      len++;
   }
   ret[len] = (char) 0;
   return ret;
}

void
MainWindow::OnFileOpen()
{
#ifndef HAVE_OPEN_IN_NEW_WINDOW
    if (!TheApp->checkSaveOldWindow())
        return;
#endif
    char path[1024];
    path[0] = '\0';
    char *fileSelectorText = getFileSelectorText();
    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir());
    if (swOpenFileDialog(_wnd, "Open", fileSelectorText, path, 1024)) {
        if (OpenFileCheck(path)) {
#ifndef HAVE_OPEN_IN_NEW_WINDOW
            TheApp->deleteOldWindow();
#endif
        }
    }
    delete [] fileSelectorText;
}

//
// OpenFileCheck() -- open a file, or display a messagebox if there's a problem
//

bool
MainWindow::OpenFileCheck(const char *path)
{
    TheApp->SetBoolPreference("MaximizeWindows", swIsMaximized(_wnd) != 0);
    if (!TheApp->OpenFile(path)) {
        if (errno != 0)
            TheApp->MessageBoxPerror(path);
        return false;
    }
    return true;
}

void
MainWindow::OnFileImport()
{
    bool oldX3d = _scene->isX3d();
    Node *current = _scene->getSelection()->getNode();
    int field = _scene->getSelection()->getField();
    if (field == -1) 
        field = current->findValidFieldType(CHILD_NODE);
    else
       if (!current->validChildType(field, CHILD_NODE))
           field = -1;

    if (field == -1)
        current = NULL;

    char path[1024];

    path[0] = '\0';
    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir());    
    char *fileSelectorText = getFileSelectorText();
    if (swOpenFileDialog(_wnd, "Import", fileSelectorText, path, 1024)) {
        ImportFileCheck(path, current, field);
    }        
    delete [] fileSelectorText;
    if (oldX3d && (!_scene->isX3d()))
        _scene->setX3d();
    else if ((!oldX3d) && _scene->isX3d())             
        _scene->setVrml();

}

//
// ImportFileCheck() -- import a file, or display a messagebox if there's a problem
//

void
MainWindow::ImportFileCheck(const char *path, Node *node, int field)
{
    Node *importNode = node;
    int importField = field;
    if ((node != NULL) && (node->getType() == DUNE_VRML_SCENE))
        _scene->setImportIntoVrmlScene(true);
    else {
        importNode = NULL;
        importField = -1;
    }
    if (!TheApp->ImportFile(path,_scene, false, importNode, importField))
        TheApp->MessageBoxPerror(path);
    _scene->setImportIntoVrmlScene(false);
}

bool
MainWindow::SaveFile(const char *filepath, const char *url, int writeFlags)
{
    Node *selection = _scene->getSelection()->getNode();
    char path[1024];
    mystrncpy_secure(path,filepath,1024); 
    int f = open(path, O_WRONLY | O_CREAT, 00664);
       
    if (f==-1) {
        return false;
    } else {
        bool writeError = false;
        int flags = writeFlags;
        if (strstr(filepath, ".x3dv") != NULL)
            flags = flags | X3DV;
        else if (strstr(filepath, ".x3d") != NULL) {
            flags = flags & ~X3DV; 
            flags = flags | X3D_XML;        
        } else if (strstr(filepath, ".wrl") != NULL) {
            flags = flags & ~X3DV; 
            flags = flags & ~X3D_XML; 
        } else if (strstr(filepath, ".ac") != NULL)
            flags = flags & AC3D;
        else if (strstr(filepath, ".dat") != NULL)
            flags = flags & LDRAW_DAT;
        if (writeFlags & KANIM) {
            MyString kanimPattern = "";
            kanimPattern += url;
            OneTextDialog dlg(_wnd, IDD_KANIM_PATTERN, kanimPattern, 
                              textValidate);
            if (dlg.DoModal() == IDCANCEL)
                return false;
            kanimPattern = dlg.GetValue();
            if (_scene->writeKanim(f, kanimPattern) != 0)
                writeError = true;
        } else if (flags & AC3D) {
            if (_scene->writeAc3d(f, writeFlags & AC3D_4_RAVEN) != 0)
                writeError = true;
            else if (swTruncateClose(f))
                writeError = true;
        } else if (flags & LDRAW_DAT) {
            if (_scene->writeLdrawDat(f, path) != 0)
                writeError = true;
            else if (swTruncateClose(f))
                writeError = true;
        } else {
            if (_scene->write(f, url, flags) != 0)
                writeError = true;
            else if (swTruncateClose(f))
                writeError = true;
        }
        if (writeError) {
            TheApp->MessageBoxPerror(path);
            _scene->setSelection(selection);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
            return false;
        }
        if (!(writeFlags & TEMP_EXPORT) && 
            TheApp->GetRevisionControlCheckinFlag()) {
            char cmd[2048];
            mysnprintf(cmd, 2047, TheApp->GetRevisionControlCheckinCommand(), 
                       path);
            setStatusText(cmd);
            if (system(cmd) != 0)
                TheApp->MessageBox(IDS_REVISION_CONTROL_COMMAND_FAILED, path);
        }

    }
    _scene->setSelection(selection);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
    return true;
}

bool MainWindow::OnFileSave()
{
    const char *path = _scene->getPath();
    int writeFlags = 0;
    const char *testx3dv = strstr(path,".x3dv");
    if ((testx3dv != NULL) && 
        ((path + strlen(path) - strlen(".x3dv")) == testx3dv))
       writeFlags = X3DV;
    if (path[0] && (path[0] != '-'))
        return SaveFile(path, _scene->getURL(), writeFlags);
    else
        return OnFileSaveAs(_scene->isX3dv() ? X3DV : 0);
}

bool MainWindow::OnFileExportVRML97()
{
    return OnFileSaveAs(PURE_VRML97 | TEMP_EXPORT);
}

bool MainWindow::OnFileExportX3DV()
{
    return OnFileSaveAs(PURE_X3DV | TEMP_EXPORT);
}

bool MainWindow::OnFileExportX3DXML()
{
    return OnFileSaveAs(X3D_XML | TEMP_EXPORT);
}

bool MainWindow::OnFileExportX3D4Wonderland()
{
    return OnFileSaveAs(X3D_XML | X3D_4_WONDERLAND | TEMP_EXPORT);
}

bool MainWindow::OnFileExportCover()
{
    return OnFileSaveAs(PURE_VRML97 | COVER | TEMP_EXPORT);
}

bool MainWindow::OnFileExportKanim()
{
    return OnFileSaveAs(KANIM | TEMP_EXPORT);
}

bool MainWindow::OnFileExportC()
{
    return OnFileSaveAs(C_SOURCE | C_MESH | TEMP_EXPORT);
}

bool MainWindow::OnFileExportCC()
{
    return OnFileSaveAs(CC_SOURCE | C_MESH | TEMP_EXPORT);
}

bool MainWindow::OnFileExportJava()
{
    return OnFileSaveAs(JAVA_SOURCE | TRIANGULATE | TEMP_EXPORT);
}

bool MainWindow::OnFileExportAc3d()
{
    int ravenBits = 0;
    if (TheApp->GetAc3dExport4Raven())
        ravenBits = AC3D_4_RAVEN;
    return OnFileSaveAs(AC3D | ravenBits | TEMP_EXPORT);
}

bool MainWindow::OnFileExportAc3d4Raven()
{
    return OnFileSaveAs(AC3D | AC3D_4_RAVEN | TEMP_EXPORT);
}

bool MainWindow::OnFileExportLdrawDat()
{
    return OnFileSaveAs(LDRAW_DAT | TEMP_EXPORT);
}

bool MainWindow::OnFileSaveAs(int writeFlags)
{
    char path[1024];

    path[0] = '\0';
    if (writeFlags & (X3DV | PURE_X3DV)) {
        strcpy(path,"Untitled.x3dv");
    }
    else if (writeFlags & PURE_VRML97) 
        strcpy(path,"PureVrmlExport.wrl");
    else if (writeFlags & KANIM) 
        strcpy(path,"KanimExport.kanim");
    else if (writeFlags & C_SOURCE) 
        strcpy(path,"CExport.c");
    else if (writeFlags & CC_SOURCE) 
        strcpy(path,"C++Export.cc");
    else if (writeFlags & JAVA_SOURCE) 
        strcpy(path,"JavaExport.java");
    else if (writeFlags & AC3D) 
        strcpy(path,"Ac3dExport.ac");
    else if (writeFlags & LDRAW_DAT)
        strcpy(path,"LdrawExport.dat");
    else if (writeFlags & X3D_XML)
        strcpy(path,"Untitled.x3d");
    else
        strcpy(path,"Untitled.wrl");

    struct stat fileStat;
    int numberfile = 2;
    while (stat(path, &fileStat) == 0) {
       if (writeFlags & (X3DV | PURE_X3DV))
           mysnprintf(path, 1023, "Untitled%d.x3dv", numberfile++);
       else if (writeFlags & PURE_VRML97)
           mysnprintf(path, 1023, "PureVrmlExport%d.wrl", numberfile++);
       else if (writeFlags & KANIM)
           mysnprintf(path, 1023, "KanimExport%d.kanim", numberfile++);
       else if (writeFlags & C_SOURCE)
           mysnprintf(path, 1023, "CExport%d.c", numberfile++);
       else if (writeFlags & CC_SOURCE)
           mysnprintf(path, 1023, "C++Export%d.cc", numberfile++);
       else if (writeFlags & JAVA_SOURCE)
           mysnprintf(path, 1023, "JavaExport%d.java", numberfile++);
       else if (writeFlags & AC3D)
           mysnprintf(path, 1023, "Ac3dExport%d.ac", numberfile++);
       else if (writeFlags & LDRAW_DAT)
           mysnprintf(path, 1023, "LdrawExport%d.dat", numberfile++);
       else if (writeFlags & X3D_XML)
           mysnprintf(path, 1023, "Untitled%d.x3d", numberfile++);
       else
           mysnprintf(path, 1023, "Untitled%d.wrl", numberfile++);
    }
    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir()); 
    char *fileSelectorText = getFileSelectorText();
    bool save = false;
    if (writeFlags & (X3DV | PURE_X3DV)) {   
       if (swSaveFileDialog(_wnd, "Save As",
                            "X3DV (.x3dv)\0*.x3dv;*.X3DV\0All Files (*.*)\0*.*\0\0",
                            path, 1024, ".x3dv"))
           save = true; 
    } else if (writeFlags & KANIM) {   
       if (swSaveFileDialog(_wnd, "Save As",
                            "Kambi VRML engine's animation (.kanim)\0*.kanim;*.KANIM\0All Files (*.*)\0*.*\0\0",
                            path, 1024, ".kanim"))
           save = true; 
    } else if (writeFlags & C_SOURCE) {   
       if (swSaveFileDialog(_wnd, "Save As",
                            "C source (.c)\0*.c;*.AC\0All Files (*.*)\0*.*\0\0",
                            path, 1024, ".c"))
           save = true; 
    } else if (writeFlags & CC_SOURCE) {   
       if (swSaveFileDialog(_wnd, "Save As",
                            "C++ source (.cc)\0*.cc;*.AC\0All Files (*.*)\0*.*\0\0",
                            path, 1024, ".cc"))
           save = true; 
    } else if (writeFlags & JAVA_SOURCE) {   
       if (swSaveFileDialog(_wnd, "Save As",
                            "java source (.java)\0*.java;*.AC\0All Files (*.*)\0*.*\0\0",
                            path, 1024, ".java"))
           save = true; 
    } else if (writeFlags & AC3D) {   
       if (swSaveFileDialog(_wnd, "Save As",
                            "ac3d (.ac)\0*.ac;*.AC\0All Files (*.*)\0*.*\0\0",
                            path, 1024, ".ac"))
           save = true; 
    } else if (writeFlags & LDRAW_DAT) {   
       if (_scene->validateLdrawExport())
           if (swSaveFileDialog(_wnd, "Save As",
                               "ldraw dat (.dat)\0*.dat;*.DAT\0All Files (*.*)\0*.*\0\0",
                                path, 1024, ".dat"))
               save = true; 
    } else if (writeFlags & X3D_XML) {   
       if (swSaveFileDialog(_wnd, "Save As",
                            "x3d (.x3d)\0*.x3d;*.X3D\0All Files (*.*)\0*.*\0\0",
                            path, 1024, ".x3d"))
           save = true; 
    } else if (swSaveFileDialog(_wnd, "Save As", fileSelectorText, path, 1024,
                                ".wrl"))
        save = true; 
    delete [] fileSelectorText;
    if (save) {
        URL url;

        url.FromPath(path);
        bool x3d = _scene->isX3d();
        if (SaveFile(path, url, writeFlags)) {
            if (!(writeFlags & TEMP_EXPORT)) {
                TheApp->AddToRecentFiles(path);
                _scene->setPath(path);
                _scene->setURL(url);
                UpdateTitle();
                RefreshRecentFileMenu();
                if (x3d != _scene->isX3d())
                    _scene->UpdateViews(NULL, UPDATE_ALL);
                else
                    _scene->UpdateViews(NULL, UPDATE_REDRAW, NULL);
                return true;
            }
        } else
            TheApp->MessageBoxPerror(path);
    }
    return false;
}

bool MainWindow::OnFileExportWonderlandModule()
{
    WonderlandModuleExportDialog dlg(_wnd);
    if (dlg.DoModal() == IDCANCEL)
        return true;
    int manyClasses = 0;
    if (TheApp->GetWonderlandModuleExportManyClasses())
        manyClasses = MANY_JAVA_CLASSES;
    
    return _scene->write(1, TheApp->GetWonderlandModuleExportPath(), 
                         TEMP_SAVE | TRIANGULATE | WONDERLAND | manyClasses);
}

bool MainWindow::OnFileExportCattGeo()
{
    CattExportDialog dlg(_wnd);
    if (dlg.DoModal() == IDCANCEL)
        return true;
    
    return _scene->writeCattGeo(TheApp->GetCattExportPath());
}

/*
bool MainWindow::OnFileExportCattGeo()
{
    char path[1024];

    path[0] = '\0';
    if (TheApp->getFileDialogDir())
        chdir(TheApp->getFileDialogDir()); 
#ifdef _WIN32
    if (swOpenFileDialog(_wnd, "Select", "Catt GEO Material file(material.geo)\0material.geo\0\0", 
                         path, 1024)) {
#else
    if (swOpenFileDialog(_wnd, "Select", "Catt GEO Material file(material.geo)\0material.geo;MATERIAL.GEO\0\0", 
                         path, 1024)) {
#endif
        for (int i = strlen(path); i >=0; i--)
             if (path[i] == swGetPathSelector()) {
                 path[i + 1] = '\0';
                 break;
             }
        return _scene->writeCattGeo(path);
    }          
    return false;
}
*/

void MainWindow::OnEditCut()
{
    const Path *sel = _scene->getSelection();
    Node *node = sel->getNode();
    Node *parent = sel->getParent();
    int parentField = sel->getParentField();

    OnEditCopy();
    _scene->execute(new MoveCommand(node, parent, parentField, NULL, -1));
}

void MainWindow::OnEditCopy()
{
    Node *node = _scene->getSelection()->getNode();
    if (node) {
        if (TheApp->getClipboardNode() != NULL)
           if (!node->isEqual(TheApp->getClipboardNode()))
              TheApp->getClipboardNode()->unref();
        TheApp->setClipboardNode(node->copy());
        TheApp->getClipboardNode()->ref();
    }
}

void MainWindow::OnEditCopyBranchToRoot()
{
    Node *node = _scene->getSelection()->getNode();
    if (node && (node != _scene->getRoot())) {
        NodeArray nodeArray;
        Array<int> fieldArray;
        Array<bool> mfNodeFlagArray;
        Node *compareNode = node;
        int numNodes = 0;
        while (compareNode != _scene->getRoot()) {
            nodeArray[numNodes] = compareNode;
            int parentField = compareNode->getParentField();
            fieldArray[numNodes] = parentField;
            mfNodeFlagArray[numNodes] = true;
            if (compareNode->hasParent()) {
                compareNode = compareNode->getParent();
                if (compareNode->getField(parentField)->getType() == SFNODE)
                    mfNodeFlagArray[numNodes] = false;
            } else
                break;            
            numNodes++;
        }
        Node *currentNode = nodeArray[0]->copy();
        currentNode->ref();
        currentNode->removeChildren();
        for (int i = 1; i < numNodes; i++) {
            Node *newNode = nodeArray[i]->copy();
            newNode->ref();
            newNode->removeChildren();
            if (mfNodeFlagArray[i - 1])
                newNode->setField(fieldArray[i - 1], new MFNode(currentNode));
            else
                newNode->setField(fieldArray[i - 1], new SFNode(currentNode));
            currentNode = newNode;
        }
        if (TheApp->getClipboardNode() != NULL)
            TheApp->getClipboardNode()->unref();
        TheApp->setClipboardNode(currentNode);
    }
}

void MainWindow::OnEditPaste()
{
    Node *destNode = _scene->getSelection()->getNode();
    int destField = _scene->getSelection()->getField();
    
    if (TheApp->getClipboardNode() != NULL) {
        if (destField == -1) {
            destField = destNode->findValidField(TheApp->getClipboardNode());
        }
        if (destField != -1) {
            Node    *node = TheApp->getClipboardNode()->copy();
            TheApp->getClipboardNode()->copyChildrenTo(node);
            node->reInit();
            _scene->execute(new MoveCommand(node, NULL, -1,
                                            destNode, destField));
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void MainWindow::OnEditDelete()
{
    _scene->DeleteLastSelection();
}

void MainWindow::OnEditFindAgain()
{
    Node *node = _scene->getSelection()->getNode();

    if (node != NULL) {    
        NodeArray allNodes;
        _scene->getRoot()->doWithBranch(getAllNodes, &allNodes);
        int positionSelection = -1;
        int i;
        for (i = 0; i < allNodes.size(); i++)
            if (allNodes[i] == node) {
                positionSelection = i;
                break;
            }
        searchData data(_searchText, _scene); 
        for (i = positionSelection + 1; i < allNodes.size(); i++)
            if (!searchNode(allNodes[i], &data))
                break;
    }
}

void MainWindow::OnEditFind()
{
    Node *node = _scene->getSelection()->getNode();
    if (node != NULL) {    
        MyString s = _searchText;
        OneTextDialog dlg(_wnd, IDD_TEXT, s, textValidate);
        if (dlg.DoModal() == IDCANCEL)
            return;
        _searchText = "";
        _searchText += dlg.GetValue();
        OnEditFindAgain();
    }
    UpdateToolbars();
}

bool MainWindow::SaveModified()
{
    bool ok = true;
    char str[256], message[256], title[256];

    if (_scene->isModified()) {
        const char *path = _scene->getPath();
        swSetFocus(_wnd);
        swLoadString(IDS_DUNE, title, 256);
        swLoadString(IDS_SAVE_CHANGES, str, 256);
        if (path[0]) {
            mysnprintf(message, 255, str, path);
        } else {
            mysnprintf(message, 255, str, "Untitled");
        }
        switch (swMessageBox(_wnd, message, title, SW_MB_YESNOCANCEL,
                             SW_MB_WARNING))
        {
          case IDYES:
            ok = OnFileSave();
            break;
          case IDCANCEL:
            ok = false;
            break;
          case IDNO:
            if (TheApp->is4Kids()) {
                swLoadString(IDS_NOT_SAVED, str, 256);
                switch (swMessageBox(_wnd, str, title, SW_MB_YESNO,
                                     SW_MB_WARNING))
                {
                  case IDYES:
                    ok = OnFileSave();
                    break;
                  case IDNO:
                    break;
                }
            }
            break;
        }
    }
    return ok;
}

void
MainWindow::setStatusText(const char *str)
{
    mystrncpy_secure(_statusText, str, 256);
    OnHighlight(-1);
}

void
MainWindow::OnHelpOverview()
{
    swHelpBrowserHTML(TheApp->GetHelpBrowser(), _wnd);
}

#define CATT_DOC_URL "usage_docs/dune_commandline_de.html#catt8geo"

void
MainWindow::OnHelpOverviewCatt()
{
    char path[4096];
    char buf[4096];
    
    char *url = swGetHelpUrl(TheApp->GetHelpBrowser());
    snprintf(path, 4095, "%s", url);
    char *lastSelector = strrchr(path, swGetPathSelector());
#ifdef _WIN32
    if (lastSelector == NULL)
        lastSelector = strrchr(path, '/');
#endif
    if (lastSelector == (path + strlen(path) - 1)) {
        // selector at end
        snprintf(path, 4095, "%s%s", url, CATT_DOC_URL);
    } else {
        char *lastDot = strrchr(url, '.');
        if (lastDot == NULL) {
            // no . (as in "something.html") => url "should" be directory
            snprintf(buf, 4095, "%s/%s", path, CATT_DOC_URL);
            strcpy(path, buf);
        } else {
            if (lastSelector == NULL) {
                // no selector but dot => url "should" be file
                snprintf(path, 4095, "%s/%s", url, CATT_DOC_URL); 
            } else {
                if (lastDot > lastSelector) {
                    *lastSelector = 0;
                }
                snprintf(buf, 4095, "%s/%s", path, CATT_DOC_URL);
                strcpy(path, buf);
            }
        }    
    }
    
    swHelpBrowserPath(TheApp->GetHelpBrowser(), path, _wnd);
}

void
MainWindow::OnHelpSelection()
{
    bool x3d = _scene->isX3d();
    Node *selection = _scene->getSelection()->getNode();
    const char *component = selection->getComponentName();
    if (strcmp(component, "DIS") == 0)
        component = "dis";
    if (strcmp(component, "CubeMapTexturing") == 0)
        component = "env_texture";
    if (strcmp(component, "EnvironmentalEffects") == 0)
        component = "enveffects";
    if (strcmp(component, "EnvironmentalSensor") == 0)
        component = "envsensor";
    if (strcmp(component, "Followers") == 0)
        component = "followers";
    if (strcmp(component, "Geometry2D") == 0)
        component = "geometry2D";
    if (strcmp(component, "Geometry3D") == 0)
        component = "geometry3D";
    if (strcmp(component, "Geospatial") == 0)
        component = "geodata";
    if (strcmp(component, "Grouping") == 0)
        component = "group";
    if (strcmp(component, "H-Anim") == 0)
        component = "hanim";
    if (strcmp(component, "Interpolation") == 0)
        component = "interp";
    if (strcmp(component, "KeyDeviceSensor") == 0)
        component = "keyboard";
    if (strcmp(component, "Layering") == 0)
        component = "layering";
    if (strcmp(component, "Layout") == 0)
        component = "layout";
    if (strcmp(component, "Lighting") == 0)
        component = "lighting";
    if (strcmp(component, "Navigation") == 0)
        component = "navigation";
    if (strcmp(component, "Networking") == 0)
        component = "networking";
    if (strcmp(component, "NURBS") == 0)
        component = "nurbs";
    if (strcmp(component, "ParticleSystems") == 0)
        component = "particle_systems";
    if (strcmp(component, "Picking") == 0)
        component = "picking";
    if (strcmp(component, "PointingDeviceSensor") == 0)
        component = "pointingsensor";
    if (strcmp(component, "Rendering") == 0)
        component = "rendering";
    if (strcmp(component, "RigidBodyPhysics") == 0)
        component = "rigid_physics";
    if (strcmp(component, "Scripting") == 0)
        component = "scripting";
    if (strcmp(component, "Shaders") == 0)
        component = "shaders";
    if (strcmp(component, "Shape") == 0)
        component = "shape";
    if (strcmp(component, "Sound") == 0)
        component = "sound";
    if (strcmp(component, "Text") == 0)
        component = "text";
    if (strcmp(component, "Texturing3D") == 0)
        component = "texture3D";
    if (strcmp(component, "Texturing") == 0)
        component = "texturing";
    if (strcmp(component, "Time") == 0)
        component = "time";
    if (strcmp(component, "EventUtilities") == 0)
        component = "utils";
    
    if (strlen(component) > 0) {
        MyString path = "";
        path += "Part01/components/";
        path += component;
        path += ".html#";
        path += selection->getProto()->getName(x3d);
        swHelpBrowserX3d(TheApp->GetHelpBrowser(), (const char*) path, _wnd);
    } else 
        swHelpBrowserVRML(TheApp->GetHelpBrowser(),  
                          (const char*) selection->getProto()->getName(x3d), 
                          0, _wnd);
}

void
MainWindow::OnHelpCoverSelection()
{
    swHelpBrowserVRML(TheApp->GetHelpBrowser(),  (const char*) 
                      _scene->getSelection()->getNode()->getProto()->
                      getName(_scene->isX3d()), 1, _wnd);
}

void
MainWindow::removeIllegalNodes()
{
    Node *selection = _scene->getSelection()->getNode();
    const NodeList *nodes = _scene->getNodes();
    for (int i = 0; i < nodes->size(); i++) {
        Node *node = nodes->get(i);
        if (node->isInvalidChild() && (node != _scene->getRoot())) {
            CommandList *list = new CommandList();
            Node *parent = node->getParent();
            int parentField = node->getParentField();
            list->append(new MoveCommand(node, parent, parentField, NULL, -1));
            _scene->execute(list);
        }
    }
    _scene->setSelection(_scene->getRoot());
    _scene->UpdateViews(NULL, UPDATE_ALL, NULL);    
    if (selection->isInScene(_scene)) {
        _scene->setSelection(selection);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::countPolygons()
{
    int polygons = 0;
    int primitives = 0;
    Node *node = _scene->getSelection()->getNode();
    bool nodeFound = false;
    Node *parent = NULL;
    if (node->hasParent())
        parent = node->getParent();
    else {
        parent = _scene->getRoot();
        nodeFound = true;
    }
    for (int i = 0; i < parent->getProto()->getNumFields(); i++) {
        if (parent->getField(i)->getType() == SFNODE) {
            Node *child = ((SFNode *) parent->getField(i))->getValue(); 
            if (child) {
                if (child == node)
                    nodeFound = true;
                if (nodeFound) {
                    polygons += child->countPolygons();
                    primitives += child->countPrimitives();
                }
            }
        } else if (parent->getField(i)->getType() == MFNODE) {
                NodeList *childList = ((MFNode *) parent->getField(i))->
                                      getValues();
                if (childList) {
                    for (int j = 0; j < childList->size(); j++) {
                        Node *child = childList->get(j);
                    if (child) {
                        if (child == node)
                            nodeFound = true;
                        if (nodeFound) {
                            polygons += child->countPolygons();
                            primitives += child->countPrimitives();
                        }
                    }
                }
            }
        }
    }
    char numberPolygons[256];
    swLoadString(IDS_NUMBER_POLYGONS + swGetLang(), numberPolygons, 255);
    char numberPrimitives[256];
    swLoadString(IDS_NUMBER_PRIMITIVES + swGetLang(), numberPrimitives, 255);
    mysnprintf(_statusText, 255, "%s: %d  %s: %d",
               numberPolygons, polygons,  
               numberPrimitives, primitives);
    _statusBar->SetText(_statusText);
}

void
MainWindow::countPolygons4catt()
{
    int singleSided = 0;
    int doubleSided = 0;
    Node *node = _scene->getSelection()->getNode();
    bool nodeFound = false;
    Node *parent = NULL;
    if (node->hasParent())
        parent = node->getParent();
    else {
        parent = _scene->getRoot();
        nodeFound = true;
    }
    for (int i = 0; i < parent->getProto()->getNumFields(); i++) {
        if (parent->getField(i)->getType() == SFNODE) {
            Node *child = ((SFNode *) parent->getField(i))->getValue(); 
            if (child) {
                if (child == node)
                    nodeFound = true;
                if (nodeFound) {
                    if (child->isDoubleSided())
                        doubleSided += child->countPolygons2Sided();
                    else
                        singleSided += child->countPolygons1Sided();
                }
            }
        } else if (parent->getField(i)->getType() == MFNODE) {
                NodeList *childList = ((MFNode *) parent->getField(i))->
                                      getValues();
                if (childList) {
                    for (int j = 0; j < childList->size(); j++) {
                        Node *child = childList->get(j);
                    if (child) {
                        if (child == node)
                            nodeFound = true;
                        if (nodeFound) {
                            if (child->isDoubleSided())
                                doubleSided += child->countPolygons2Sided();
                            else
                                singleSided += child->countPolygons1Sided();
                        }
                    }
                }
            }
        }
    }

    char numberSingleSidedPolygons[256];
    swLoadString(IDS_NUMBER_SINGLE_SIDED_POLYGONS + swGetLang(), 
                 numberSingleSidedPolygons, 255);
    char numberDoubleSidedPolygons[256];
    swLoadString(IDS_NUMBER_DOUBLE_SIDED_POLYGONS + swGetLang(), 
                 numberDoubleSidedPolygons, 255);
    char numberPolygons[256];
    swLoadString(IDS_NUMBER_POLYGONS_4_CATT + swGetLang(), numberPolygons, 255);

    mysnprintf(_statusText, 255, "%s: %d  %s: %d   %s: %d",
               numberDoubleSidedPolygons, doubleSided / 2,
               numberSingleSidedPolygons, singleSided,
               numberPolygons, singleSided + doubleSided);

    _statusBar->SetText(_statusText);
}

void
MainWindow::clearStatusText()
{
    _statusText[0] = 0;
    OnHighlight(-1);
}

void
MainWindow::fieldPipe(Node *node, int field, const char *pipeCommand)
{
    static char path_out[1024];        
    swGetTempPath(path_out, ".dune_pipe_in", ".txt", 1024);
    int f_out = open(path_out, O_WRONLY | O_CREAT,00666);
    if (f_out == -1) {
        TheApp->MessageBoxPerror(path_out);
        return;
    }
    int writeError = false;
    FieldValue *value = node->getField(field);
    if (value->write4FieldPipe(f_out, 0) != 0)
        writeError = true;
    else if (swTruncateClose(f_out))
        writeError = true;
    if (writeError) {
        TheApp->MessageBoxPerror(path_out);
        return;
    }
    static char path_in[1024];        
    swGetTempPath(path_in, ".dune_pipe_out", ".txt", 1024);
#ifndef _WIN32
    static char path_err[1024];        
    swGetTempPath(path_err, ".dune_pipe_error", ".txt", 1024);
#endif
    MyString command = "";
    command += pipeCommand;
    command += " <";
    command += path_out;
    command += " >";
    command += path_in;
#ifndef _WIN32
    command += " 2>";
    command += path_err;
#endif
    if (system((const char *) command) == 0) {
        FILE* f_in = fopen(path_in, "rb");
        if ((value->getType() == MFNODE) || (value->getType() == SFNODE)) {
            _scene->backupField(node, field);
            _scene->parse(f_in, false, node, field);
            node->update();
            _scene->UpdateViews(NULL, UPDATE_ALL, NULL);
        } else {
            if (f_in == NULL)
                TheApp->MessageBoxPerror(path_out);
            else {
               bool error = false;
           
               int index = 0;
               FieldValue *newValue = value->copy();
               newValue->makeEmpty();
               while (!feof(f_in)) {
                   char line[65536];
                   if (fgets(line, 65536, f_in) == NULL)
                       break;
                   if ((line[strlen(line) - 1] == '\n') || 
                       (line[strlen(line) - 1] == '\r'))
                       line[strlen(line) - 1] = 0;
                   if ((line[strlen(line) - 1] == '\n') || 
                       (line[strlen(line) - 1] == '\r'))
                       line[strlen(line) - 1] = 0;
                   if (newValue->checkInput(line))
                       newValue->readLine(index++, line);
                   else {
                       error = true;
                       char format[256];
                       swLoadString(IDS_ERROR_IN_OUTPUT_FILE, format, 255);
                       char msg[1024];
                       mysnprintf(msg, 1023, format, index + 1, path_in);
                       TheApp->MessageBox(msg);
                       break;
                   }
                }
                fclose(f_in);
                if (!error) {
                    _scene->backupField(node, field);
                    _scene->setField(node, field, newValue);
                    node->update();
                    _scene->UpdateViews(NULL, UPDATE_ALL, NULL);
                }
            }
        }
    } else {
#ifndef _WIN32
        int readErrorMessage = false; 
        int f_err = open(path_err, O_RDONLY, 00666);
        #define MSG_LEN 1024
        char msg[MSG_LEN];
        if (f_err == 0)
            readErrorMessage = true;
        else {
            int chars = read(f_err, msg, MSG_LEN);
            if (chars == -1)
                readErrorMessage = true;
            else
                msg[chars < MSG_LEN ? chars : MSG_LEN - 1] = 0;
            close(f_err);
        }
        if (!readErrorMessage)
            TheApp->MessageBox(msg);
        else
#endif
        TheApp->MessageBoxId(IDS_PIPE_FAILED);
    }
    unlink(path_out);
    unlink(path_in);
#ifndef _WIN32
    unlink(path_err);
#endif
}

void
MainWindow::pipeField(void)
{
    Node *node = NULL;
    int field = -1;
    if (_fieldView->isFieldView()) {
        node = ((FieldView *)_fieldView)->GetSelectedNode();
        field = ((FieldView *)_fieldView)->GetSelectedField();
    }
    if (node && (field > -1)) {
        static char pipeCommand[1024];
        static bool initialise = false;
        if (!initialise) {
            pipeCommand[0] = 0;
            initialise = true;
        }
        OneTextDialog dlg(_wnd, IDD_TEXT, pipeCommand, NULL);
        if (dlg.DoModal() == IDCANCEL)
            return;
        mysnprintf(pipeCommand, 1024, "%s", (const char *)dlg.GetValue());
        fieldPipe(node, field, pipeCommand);
    }    
}

void
MainWindow::setName(int id)
{
    Node *selection = _scene->getSelection()->getNode();
    if (selection->getType() == VRML_COMMENT)
        return;
    if (selection != _scene->getRoot()) {
        char name[256];
        swLoadString(id, name, 255);
        _scene->def(_scene->getUniqueNodeName(name), selection);
        _scene->UpdateViews(NULL, UPDATE_SELECTION_NAME);
    }
}

void
MainWindow::createText(int id)
{
    CreateGeometryNode("Text");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == VRML_TEXT)) {
        char name[256];
        swLoadString(id, name, 255);
        NodeText *text = (NodeText *) node;
        text->string(new MFString(name));
    }
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

void
MainWindow::toogleMaterialName(int id)
{
    switch (id) {
      case ID_SKIP_MATERIAL_NAME_BEFORE_FIRST_UNDERSCORE:
        TheApp->SetSkipMaterialNameBeforeFirstUnderscore(
              !TheApp->SkipMaterialNameBeforeFirstUnderscore());
        break;
      case ID_SKIP_MATERIAL_NAME_AFTER_LAST_UNDERSCORE:
        TheApp->SetSkipMaterialNameAfterLastUnderscore(
              !TheApp->SkipMaterialNameAfterLastUnderscore());
        break;
    }
    UpdateToolbar(id);        
}

void
MainWindow::testInMenu()
{
    // usually this routine is unused.
    // it is only used for softwaredevelopers who want to check new 
    // things but do not want to take care about the menu mechanisms

    printf("test, only used when HAVE_TEST_IN_MENU defined in dune.rc\n");

    // in your test routine, you possibly want something like

    //    Node *node =_scene->getSelection()->getNode();
    //    int type = node->getType();
    //    if (type == VRML_NURBS_CURVE) {
    //        doSomeThingWith(node);
    //    }

    // if your test only works with VRML_NURBS_CURVE type nodes.
}
