Logo Search packages:      
Sourcecode: whitedune version File versions  Download package

MainWindow.cpp

/*
 * 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>
#endif

#include "stdafx.h"
#include "MainWindow.h"
#include "swt.h"
#include "resource.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 "NodeAppearance.h"
#include "NodeAudioClip.h"
#include "NodeElevationGrid.h"
#include "NodeGroup.h"
#include "NodeTransform.h"
#include "NodeCollision.h"
#include "NodeBillboard.h"
#include "NodeLOD.h"
#include "NodeSwitch.h"
#include "NodeImageTexture.h"
#include "NodeInline.h"
#include "NodeInlineLoadControl.h"
#include "NodeMaterial.h"
#include "NodeMovieTexture.h"
#include "NodeNurbsGroup.h"
#include "NodeNurbsSurface.h"
#include "NodeNurbsCurve.h"
#include "NodeShape.h"
#include "NodeScript.h"
#include "NodeSound.h"
#include "NodeSuperEllipsoid.h"
#include "NodeSuperExtrusion.h"
#include "NodeSuperShape.h"
#include "NodeNormal.h"
#include "NodeTextureCoordinate.h"
#include "NodeTimeSensor.h"
#include "NodeAnchor.h"
#include "NodeIndexedFaceSet.h"
#include "NodeIndexedLineSet.h"
#include "NodePointSet.h"
#include "NodeViewpoint.h"

#include "AboutDialog.h"
#include "AnimationDialog.h"
#include "ScriptDialog.h"
#include "ElevationGridDialog.h"
#include "NurbsPlaneDialog.h"
#include "NurbsCurveDialog.h"
#include "PreferencesDialog.h"
#include "EcmaScriptSettingsDialog.h"
#include "OutputSettingsDialog.h"
#include "PreviewSettingsDialog.h"
#include "UploadSettingsDialog.h"
#include "HelpSettingsDialog.h"
#include "TexteditSettingsDialog.h"
#include "StereoViewSettingsDialog.h"
#include "DefDialog.h"
#include "Cylinder2NurbsDialog.h"
#include "Cone2NurbsDialog.h"
#include "Sphere2NurbsDialog.h"
#include "Box2NurbsDialog.h"
#include "NurbsCurve2NurbsSurfDialog.h"
#include "URLDialog.h"
#include "ArrayDialog.h"
#include "OneFloatDialog.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_FILE_NEW,
    1,  ID_FILE_OPEN,
    2,  ID_FILE_SAVE,
    3,  ID_FILE_PREVIEW,
    BS, 0,
    4,  ID_EDIT_CUT,
    5,  ID_EDIT_COPY,
    6,  ID_EDIT_PASTE,
    7,  ID_EDIT_DELETE,
    BS, 0,
    8,  ID_VIEW_FULL_SCREEN,
    BS, 0,
    28, ID_X_SYMETRIC_NURBS,
    22, ID_COLOR_CIRCLE,
    23, ID_OBJECT_EDIT,
    25, ID_URL_EDIT,
    29, ID_ANIMATION,
    24, ID_TOGGLE_MOUSE_MODE,
    BS, 0,
    9,  ID_MOVE_MODE,
    10, ID_ROTATE_MODE,
    11, ID_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 int buttons1[] = {
    NODE_BOX,                 ID_NEW_BOX,
    NODE_SPHERE,        ID_NEW_SPHERE,
    NODE_CONE,                ID_NEW_CONE,
    NODE_CYLINDER,            ID_NEW_CYLINDER,
    NODE_INDEXED_FACE_SET,    ID_NEW_INDEXED_FACE_SET,
    NODE_INDEXED_LINE_SET,    ID_NEW_INDEXED_LINE_SET,
    NODE_POINT_SET,           ID_NEW_POINT_SET,
    NODE_ELEVATION_GRID,      ID_NEW_ELEVATION_GRID,
    NODE_EXTRUSION,           ID_NEW_EXTRUSION,
    NODE_TEXT,                ID_NEW_TEXT,
    BS,                       0,
    NODE_GROUP,               ID_NEW_GROUP,
    NODE_TRANSFORM,           ID_NEW_TRANSFORM,
    NODE_BILLBOARD,           ID_NEW_BILLBOARD,
    NODE_COLLISION,           ID_NEW_COLLISION,
    NODE_LOD,                 ID_NEW_LOD,
    NODE_SWITCH,        ID_NEW_SWITCH,
    BS,                       0,
    NODE_ANCHOR,        ID_NEW_ANCHOR,
    NODE_INLINE,        ID_NEW_INLINE,
};

static int buttons2[] = {
    NODE_SHAPE,               ID_NEW_SHAPE,
    NODE_COORDINATE,          ID_NEW_COORDINATE,
    NODE_NORMAL,        ID_NEW_NORMAL,
    NODE_COLOR,               ID_NEW_COLOR,
    NODE_TEXTURE_COORDINATE,  ID_NEW_TEXTURE_COORDINATE,
    BS,                       0,
    NODE_APPEARANCE,          ID_NEW_APPEARANCE,
    NODE_MATERIAL,            ID_NEW_MATERIAL,
    NODE_IMAGE_TEXTURE,       ID_NEW_IMAGE_TEXTURE,
    NODE_PIXEL_TEXTURE,       ID_NEW_PIXEL_TEXTURE,
    NODE_MOVIE_TEXTURE,       ID_NEW_MOVIE_TEXTURE,
    NODE_TEXTURE_TRANSFORM,   ID_NEW_TEXTURE_TRANSFORM,
    NODE_FONT_STYLE,          ID_NEW_FONT_STYLE,
    BS,                       0,
    NODE_SOUND,               ID_NEW_SOUND,
    NODE_AUDIO_CLIP,          ID_NEW_AUDIO_CLIP,
    BS,                       0,
    NODE_DIRECTIONAL_LIGHT,   ID_NEW_DIRECTIONAL_LIGHT,
    NODE_POINT_LIGHT,         ID_NEW_POINT_LIGHT,
    NODE_SPOT_LIGHT,          ID_NEW_SPOT_LIGHT,
    BS,                       0,
    NODE_FOG,                 ID_NEW_FOG,
    NODE_BACKGROUND,          ID_NEW_BACKGROUND,
    NODE_VIEWPOINT,           ID_NEW_VIEWPOINT,
    NODE_NAVIGATION_INFO,     ID_NEW_NAVIGATION_INFO,
    NODE_WORLD_INFO,          ID_NEW_WORLD_INFO
};

static int buttons3[] = {
    NODE_PROXIMITY_SENSOR,    ID_NEW_PROXIMITY_SENSOR,
    NODE_CYLINDER_SENSOR,     ID_NEW_CYLINDER_SENSOR,
    NODE_SPHERE_SENSOR,       ID_NEW_SPHERE_SENSOR,
    NODE_PLANE_SENSOR,        ID_NEW_PLANE_SENSOR,
    NODE_TIME_SENSOR,         ID_NEW_TIME_SENSOR,
    NODE_TOUCH_SENSOR,        ID_NEW_TOUCH_SENSOR,
    NODE_VISIBILITY_SENSOR,   ID_NEW_VISIBILITY_SENSOR,
    BS,                       0,
    NODE_COLOR_INTERPOLATOR,  ID_NEW_COLOR_INTERPOLATOR,
    NODE_COORDINATE_INTERPOLATOR,ID_NEW_COORDINATE_INTERPOLATOR,
    NODE_POSITION_INTERPOLATOR,     ID_NEW_POSITION_INTERPOLATOR,
    NODE_ORIENTATION_INTERPOLATOR,ID_NEW_ORIENTATION_INTERPOLATOR,
    NODE_NORMAL_INTERPOLATOR, ID_NEW_NORMAL_INTERPOLATOR,
    NODE_SCALAR_INTERPOLATOR, ID_NEW_SCALAR_INTERPOLATOR,
    BS,                       0,
    NODE_SCRIPT,        ID_NEW_SCRIPT,
    BS,                       0,
    NODE_COMMENT,       ID_NEW_COMMENT
};

static int buttonsVRML200x[] = {
    NODE_NURBS_CURVE,         ID_NEW_NURBS_CURVE,
    NODE_NURBS_GROUP,         ID_NEW_NURBS_GROUP,
    NODE_NURBS_SURFACE,       ID_NEW_NURBS_PLANE,
    NODE_NURBS_TEXTURE_SURFACE,     ID_NEW_NURBS_TEXTURE_SURFACE,
    BS,                       0,
    NODE_TRIMMED_SURFACE,       ID_NEW_TRIMMED_SURFACE,
    NODE_CONTOUR_2D,          ID_NEW_CONTOUR_2D,
    NODE_NURBS_CURVE_2D,      ID_NEW_NURBS_CURVE_2D,
    NODE_POLYLINE_2D,           ID_NEW_POLYLINE_2D,
    BS,                       0,
    NODE_COORDINATE_DEFORMER, ID_NEW_COORDINATE_DEFORMER,
    BS,                       0,
    NODE_INLINE_LOAD_CONTROL,   ID_NEW_INLINE_LOAD_CONTROL,
    BS,                       0,
    NODE_NURBS_POSITION_INTERPOLATOR, 
                                ID_NEW_NURBS_POSITION_INTERPOLATOR,
    BS,                       0,
    NODE_LOAD_SENSOR,         ID_NEW_LOAD_SENSOR
};

static int buttonsScripted[] = {
    NODE_SUPER_ELLIPSOID,     ID_NEW_SUPER_ELLIPSOID,
    NODE_SUPER_EXTRUSION,     ID_NEW_SUPER_EXTRUSION,
    NODE_SUPER_SHAPE,         ID_NEW_SUPER_SHAPE
};


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

MainWindow::MainWindow(Scene *scene, SWND wnd)
  : PanedWindow(scene, wnd, false)
{
    _parentWindow = wnd;
    _fieldView = NULL;
    _timer = NULL;
    _lenProtoMenu = 0;

    if (TheApp->is4Kids())
        _menu = swLoadMenuBar(wnd, IDR_DUNE4KIDSTYPE);
    else
        _menu = swLoadMenuBar(wnd, IDR_DUNETYPE);
    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_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()) {
        swMenuSetFlags(_menu, ID_VIEW_SCENE_TREE, SW_MENU_CHECKED, 
                       SW_MENU_CHECKED);
        _treeView->setEnabled(true);
    } else {
        if (TheApp->GetBoolPreference("ShowSceneTree", true)) {
          swMenuSetFlags(_menu, ID_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);
    } else {
        if (TheApp->GetBoolPreference("ShowFieldView", true)) {
          swMenuSetFlags(_menu, ID_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()) {
        swHideWindow(_graphView->GetWindow());
       _graphView->setEnabled(false);
    } else {
        if (TheApp->GetBoolPreference("ShowRouteView", false)) {
          swMenuSetFlags(_menu, ID_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()) {
        swHideWindow(_channelView->GetWindow());
       _channelView->setEnabled(false);
    } else {
        if (TheApp->GetBoolPreference("ShowChannelView", true)) {
          swMenuSetFlags(_menu, ID_VIEW_CHANNEL_VIEW, SW_MENU_CHECKED, 
                           SW_MENU_CHECKED);
            _channelView->setEnabled(true);
        } else {
          swHideWindow(_channelView->GetWindow());
            _channelView->setEnabled(false);
        }
    }

    _standardToolbar = LoadToolbar(_toolbarWindow, IDB_STANDARD_TOOLBAR,
                           ARRAYSIZE(standardButtons) / 2,
                           standardButtons, ID_VIEW_TOOLBAR,
                           "StandardToolbar");
    if (TheApp->is4Kids())
        _toolbarWindow->ShowToolbar(_standardToolbar, false);
    _nodeToolbar1 = LoadToolbar(_toolbarWindow, IDB_NODE_ICONS,
                        ARRAYSIZE(buttons1) / 2, buttons1,
                        ID_VIEW_NODE_TOOLBAR_1, "NodeToolbar1");
    if (TheApp->is4Kids()) {
        _toolbarWindow->ShowToolbar(_nodeToolbar1, false);
        _nodeToolbar1Enabled = false;
    } else
        _nodeToolbar1Enabled = TheApp->GetBoolPreference("NodeToolbar1", true);

    _nodeToolbar2 = LoadToolbar(_toolbarWindow, IDB_NODE_ICONS,
                        ARRAYSIZE(buttons2) / 2, buttons2,
                        ID_VIEW_NODE_TOOLBAR_2, "NodeToolbar2");
    if (TheApp->is4Kids()) {
        _toolbarWindow->ShowToolbar(_nodeToolbar2, false);
        _nodeToolbar2Enabled = false;
    } else
        _nodeToolbar2Enabled = TheApp->GetBoolPreference("NodeToolbar2", true);
    _nodeToolbar3 = LoadToolbar(_toolbarWindow, IDB_NODE_ICONS,
                        ARRAYSIZE(buttons3) / 2,
                        buttons3, ID_VIEW_NODE_TOOLBAR_3,
                        "NodeToolbar3");
    if (TheApp->is4Kids()) {
        _toolbarWindow->ShowToolbar(_nodeToolbar3, false);
        _nodeToolbar3Enabled = false;
    } else
        _nodeToolbar3Enabled = TheApp->GetBoolPreference("NodeToolbar3", true);
    _nodeToolbarVRML200x = LoadToolbar(_toolbarWindow, IDB_NODE_ICONS,
                        ARRAYSIZE(buttonsVRML200x) / 2,
                        buttonsVRML200x, ID_VIEW_NODE_TOOLBAR_VRML200X,
                        "nodeToolbarVRML200x");
    if (TheApp->is4Kids()) {
        _toolbarWindow->ShowToolbar(_nodeToolbarVRML200x, false);
        _outerPane->Layout();
        _nodeToolbarVRML200xEnabled = false;
    } else
        _nodeToolbarVRML200xEnabled = TheApp->GetBoolPreference(
                                      "nodeToolbarVRML200x", false);
    _nodeToolbarScripted = LoadToolbar(_toolbarWindow, IDB_NODE_ICONS,
                        ARRAYSIZE(buttonsScripted) / 2,
                        buttonsScripted, ID_VIEW_NODE_TOOLBAR_SCRIPTED,
                        "nodeToolbarScripted");
    if (TheApp->is4Kids()) {
        _toolbarWindow->ShowToolbar(_nodeToolbarScripted, false);
        _outerPane->Layout();
        _nodeToolbarScriptedEnabled = false;
    } else
        _nodeToolbarScriptedEnabled = TheApp->GetBoolPreference(
                                      "nodeToolbarScripted", false);
    _vcrToolbar = LoadToolbar(_toolbarWindow2, IDB_VCR_TOOLBAR,
                        ARRAYSIZE(vcrButtons) / 2, vcrButtons,
                        ID_VIEW_PLAY_TOOLBAR, "PlayToolbar");
    _outerPane->SetPane(_toolbarWindow, PW_TOP);
    _outerPane->SetPane(_toolbarWindow2, PW_BOTTOM);
    _outerPane->SetPane(_innerPane, PW_CENTER);

    _fileNewIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                 ID_FILE_NEW);
    _fileOpenIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                  ID_FILE_OPEN);
    _fileSaveIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                  ID_FILE_SAVE);
    _filePreviewIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                     ID_FILE_PREVIEW);
    _editCutIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                 ID_EDIT_CUT);
    _editCopyIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                  ID_EDIT_COPY);
    _editPasteIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                   ID_EDIT_PASTE);
    _editDeleteIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                    ID_EDIT_DELETE);
    _fullScreen_enabled=TheApp->GetBoolPreference("FullScreen", false);
    swMenuSetFlags(_menu, ID_VIEW_FULL_SCREEN, SW_MENU_RADIO_ITEM, 0);
    _fullScreenIconPos=GetIconPos(standardButtons,sizeof(standardButtons),
                                  ID_VIEW_FULL_SCREEN);
    swMenuSetFlags(_menu, ID_VIEW_FULL_SCREEN, SW_MENU_CHECKED, 0);

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

    _colorCircle_enabled=false;
    _colorCircle_active=false;
    _colorCircleHint = NULL;
    _colorCircleIconPos=GetIconPos(standardButtons,sizeof(standardButtons),
                                   ID_COLOR_CIRCLE);
    setColorCircleIcon();
    _objectEdit_enabled=false;
    _objectEditIconPos=GetIconPos(standardButtons,sizeof(standardButtons),
                                  ID_OBJECT_EDIT);
    _urlEdit_enabled=false;
    _urlEditIconPos=GetIconPos(standardButtons,sizeof(standardButtons),
                               ID_URL_EDIT);

    _animationIconPos=GetIconPos(standardButtons,sizeof(standardButtons),
                                  ID_ANIMATION);

    _x_symetricIconPos=GetIconPos(standardButtons,sizeof(standardButtons),
                                  ID_X_SYMETRIC_NURBS);
    setXSymetricNurbsIcon();
    _navigation_active=true;
    _mouseIconPos=GetIconPos(standardButtons,sizeof(standardButtons),
                             ID_TOGGLE_MOUSE_MODE);

    _inputModeStartIconPos = GetIconPos(standardButtons,sizeof(standardButtons),
                                        ID_MOVE_MODE);
    _tDimensionStartIconPos = GetIconPos(standardButtons,
                                         sizeof(standardButtons),ID_3D_MODE);
    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_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);
       }

    setTMode(_scene->getTransformMode()->tmode);
    setTDimension(_scene->getTransformMode()->tdimension);

    _t2axesStartIconPos=GetIconPos(standardButtons,sizeof(standardButtons),
                                   ID_NEAR_FAR_MODE);

    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);

    _inputDeviceGreaterIconPos=GetIconPos(standardButtons,
                                          sizeof(standardButtons),
                                          ID_INPUTDEVICE_GREATER);
    _inputDeviceLesserIconPos=GetIconPos(standardButtons,
                                         sizeof(standardButtons),
                                         ID_INPUTDEVICE_LESSER);

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

    UpdateUpload();

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

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

    _scriptEdit = NULL;
    _scriptEditorInUse = false;
    _selectedField = -1;
    _statusText[0] = 0;
}

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);
}

int MainWindow::GetIconPos(int* buttons,int length,int icon)
{
    for (int i=0;i<length;i++)
       if (buttons[2*i+1]==icon)
          return i;
    return 0;
}

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

    if (TheApp->canQuadBufferStereo())
        title += "(stereo visual) : ";
    else
        title += "(no stereo visual) : ";
    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 (swSaveFileDialog(_wnd, "Save As",
        "The Nebula Device TCL Script (.tcl)\0*.tcl\0All Files (*.*)\0*.*\0\0",
        path, 1024,".tcl")) {
      _nebulaExporter.ExportScene(path, _scene, _statusBar);
    }
}
#endif   //  #ifdef HAVE_SAND

void
MainWindow::OnCommand(int id)
{
    _statusText[0] = 0;
    switch (id) {
      case ID_FILE_OPEN:
      OnFileOpen();
      break;
      case ID_FILE_IMPORT:
      OnFileImport();
      break;
      case ID_FILE_NEW:
        if (isScriptEditorInUse())
            return;
      TheApp->OnFileNew();
      break;
      case ID_FILE_NEW_WINDOW:
      TheApp->OnFileNewWindow();
      break;
      case ID_FILE_PREVIEW:
        TheApp->OnFilePreview(_scene);
      break;
      case ID_FILE_SAVE:
      OnFileSave();
      break;
      case ID_FILE_SAVE_AS:
      OnFileSaveAs();
      break;
      case ID_FILE_EXPORT_VRML97:
        OnFileExportVRML97();
      break;
      case ID_FILE_CLOSE:
        if (isScriptEditorInUse())
            return;
      TheApp->OnFileClose(this);
      break;
      case ID_FILE_TEXT_EDIT:
        if (isScriptEditorInUse())
            return;
      TheApp->OnFileEdit(this,_scene);
      break;
      case ID_FILE_UPLOAD:
        if (!TheApp->hasUpload())
            return;
      TheApp->OnFileUpload(_scene);
      break;
      case ID_FILE_MRU_FILE1:
      case ID_FILE_MRU_FILE2:
      case ID_FILE_MRU_FILE3:
      case ID_FILE_MRU_FILE4:
#ifndef HAVE_OPEN_IN_NEW_WINDOW
        if (!TheApp->checkSaveOldWindow())
            return;
#endif
      if (OpenFileCheck(TheApp->GetRecentFile(id - ID_FILE_MRU_FILE1))) {
#ifndef HAVE_OPEN_IN_NEW_WINDOW
            TheApp->deleteOldWindow();
#endif
        }
      break;
      case ID_APP_EXIT:
        if (isScriptEditorInUse())
            return;
      TheApp->OnFileExit();
      break;
      case ID_EDIT_CUT:
#ifdef HAVE_CUT
      OnEditCut();
#endif
      break;
      case ID_EDIT_COPY:
      OnEditCopy();
      break;
      case ID_EDIT_PASTE:
      OnEditPaste();
      break;
      case ID_EDIT_DELETE:
      _scene->DeleteLastSelection();
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
      break;
      case ID_EDIT_UNDO:
      if (_scene->canUndo()) _scene->undo();
        _scene->setSelection(_scene->getRoot());
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
      break;
      case ID_EDIT_REDO:
      if (_scene->canRedo()) _scene->redo();
        _scene->setSelection(_scene->getRoot());
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
      break;
      case ID_EDIT_DEF:
        {
            if (_scene->getSelection()->getNode() != _scene->getRoot()) {
              DefDialog dlg(_wnd, _scene);
              dlg.DoModal();
                _scene->UpdateViews(NULL, UPDATE_SELECTION_NAME);
            }
        }
      break;
      case ID_OBJECT_EDIT:
        EditObject();
      break;
      case ID_URL_EDIT:
        EditUrl();
      break;
      case ID_ANIMATION:
      CreateAnimation();
      break;
      case ID_BRANCH_TO_PARENT:
        moveBranchToParent();
        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_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_REMOVE_ILLEGAL_NODES:
        removeIllegalNodes();
        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_TO_NURBS:
      toNurbs();
      break;
      case ID_TO_NURBS_CURVE:
      toNurbsCurve();
      break;
      case ID_TO_SUPER_EXTRUSION:
      toSuperExtrusion();
      break;
      case ID_TO_EXTRUSION:
      toExtrusion();
      break;
      case ID_TO_INDEXEDFACESET:
      toIndexedFaceSet();
      break;
      case ID_TO_INDEXEDLINESET:
      toIndexedLineSet();
      break;
      case ID_TO_POINTSET:
      toPointSet();
      break;
      case ID_TO_POSITION_INTERPOLATOR:
      toPositionInterpolator();
      break;
      case ID_TO_ORIENTATION_INTERPOLATOR:
      toOrientationInterpolator();
      break;
      case ID_TIME_SHIFT:
      timeShift();
      break;
      case ID_COLOR_CIRCLE:
        updateColorCircle();
      break;
      case ID_COUNT_POLYGONS:
        countPolygons();
        break;
      case ID_SET_URL:
        setPathAllURLs();
      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_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_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_X_SYMETRIC_NURBS:
        if (TheApp->GetXSymetricMode())
           TheApp->SetXSymetricMode(false);
        else
           TheApp->SetXSymetricMode(true);
        setXSymetricNurbsIcon();
      break;
      case ID_NAVIGATION_MODE:
        if (_navigation_active)
           _navigation_active=false;
        else
           _navigation_active=true;
        UpdateToolbars();
      break;
      case ID_TOGGLE_MOUSE_MODE:
        if (TheApp->GetMouseMode() == MOUSE_FLY)
           TheApp->SetMouseMode(MOUSE_EXAMINE);
        else
           TheApp->SetMouseMode(MOUSE_FLY);
        UpdateToolbars();
      break;
      case ID_FLY_MOUSE_MODE:
        TheApp->SetMouseMode(MOUSE_FLY);
        UpdateToolbars();
      break;
      case ID_EXAMINE_MOUSE_MODE:
        TheApp->SetMouseMode(MOUSE_EXAMINE);
        UpdateToolbars();
      break;
      case ID_VIEW_FULL_SCREEN:
        ToggleFullScreen();
        break;
      case ID_VIEW_SCENE_GRAPH:
      ToggleView(PW_TOP, _graphView, ID_VIEW_SCENE_GRAPH, "ShowRouteView");
        UpdateToolbars();
      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_VIEW_SCENE_TREE:
      ToggleView(PW_LEFT, _treeView, ID_VIEW_SCENE_TREE, "ShowSceneTree");
      break;
      case ID_VIEW_FIELD_VIEW:
      ToggleView(PW_RIGHT, _fieldView, ID_VIEW_FIELD_VIEW, "ShowFieldView");
      break;
      case ID_VIEW_CHANNEL_VIEW:
      ToggleView(PW_BOTTOM, _channelView, ID_VIEW_CHANNEL_VIEW,
               "ShowChannelView");
      break;
      case ID_VIEW_TOOLBAR:
      ToggleToolbar(_toolbarWindow, _standardToolbar, ID_VIEW_TOOLBAR,
                  "StandardToolbar");
      break;
      case ID_VIEW_NODE_TOOLBAR_1:
        _nodeToolbar1Enabled=!_nodeToolbar1Enabled;
      ToggleToolbar(_toolbarWindow, _nodeToolbar1, ID_VIEW_NODE_TOOLBAR_1,
                  "NodeToolbar1");
      break;
      case ID_VIEW_NODE_TOOLBAR_2:
        _nodeToolbar2Enabled=!_nodeToolbar2Enabled;
      ToggleToolbar(_toolbarWindow, _nodeToolbar2, ID_VIEW_NODE_TOOLBAR_2,
                  "NodeToolbar2");
      break;
      case ID_VIEW_NODE_TOOLBAR_3:
        _nodeToolbar3Enabled=!_nodeToolbar3Enabled;
      ToggleToolbar(_toolbarWindow, _nodeToolbar3, ID_VIEW_NODE_TOOLBAR_3,
                  "NodeToolbar3");
      break;
      case ID_VIEW_NODE_TOOLBAR_VRML200X:
        _nodeToolbarVRML200xEnabled=!_nodeToolbarVRML200xEnabled;
      ToggleToolbar(_toolbarWindow, _nodeToolbarVRML200x, 
                      ID_VIEW_NODE_TOOLBAR_VRML200X, "nodeToolbarVRML200x");
      break;
      case ID_VIEW_NODE_TOOLBAR_SCRIPTED:
        _nodeToolbarScriptedEnabled=!_nodeToolbarScriptedEnabled;
      ToggleToolbar(_toolbarWindow, _nodeToolbarScripted, 
                      ID_VIEW_NODE_TOOLBAR_SCRIPTED, "nodeToolbarScripted");
      break;
      case ID_VIEW_PLAY_TOOLBAR:
      ToggleToolbar(_toolbarWindow2, _vcrToolbar, ID_VIEW_PLAY_TOOLBAR,
                  "PlayToolbar");
      break;
      case ID_VIEW_STATUS_BAR:
      ToggleStatusbar();
      break;

      case ID_NEW_ANCHOR:
      CreateNode("Anchor");
      break;
      case ID_NEW_APPEARANCE:
      InsertNode(NODE_APPEARANCE, "Appearance");
      break;
      case ID_NEW_AUDIO_CLIP:
      InsertAudioClip();
      break;
      case ID_NEW_BACKGROUND:
      CreateNode("Background");
      break;
      case ID_NEW_BILLBOARD:
      CreateNode("Billboard");
      break;
      case ID_NEW_BOX:
      CreateGeometryNode("Box");
      break;
      case ID_NEW_COLLISION:
      CreateNode("Collision");
      break;
      case ID_NEW_COLOR:
      InsertNode(NODE_COLOR, "Color");
      break;
      case ID_NEW_COLOR_INTERPOLATOR:
      CreateNode("ColorInterpolator");
      break;
      case ID_NEW_CONE:
      CreateGeometryNode("Cone");
      break;
      case ID_NEW_CONTOUR_2D:
      InsertNode(NODE_CONTOUR_2D, "Contour2D");
      break;
      case ID_NEW_COORDINATE:
      InsertNode(NODE_COORDINATE, "Coordinate");
      break;
      case ID_NEW_COORDINATE_DEFORMER:
        CreateNode("CoordinateDeformer");
        break;
      case ID_NEW_COORDINATE_INTERPOLATOR:
      CreateNode("CoordinateInterpolator");
      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_ELEVATION_GRID:
      CreateElevationGrid();
      break;
      case ID_NEW_EXTRUSION:
      CreateGeometryNode("Extrusion");
      break;
      case ID_NEW_FOG:
      CreateNode("Fog");
      break;
      case ID_NEW_FONT_STYLE:
      InsertNode(NODE_FONT_STYLE, "FontStyle");
      break;
      case ID_NEW_GROUP:
      CreateNode("Group");
      break;
      case ID_NEW_IMAGE_TEXTURE:
      InsertImageTexture();
      break;
      case ID_NEW_INDEXED_FACE_SET:
      CreateGeometryNode("IndexedFaceSet");
      break;
      case ID_NEW_INDEXED_LINE_SET:
      CreateGeometryNode("IndexedLineSet");
      break;
      case ID_NEW_INLINE:
        InsertInline();
      break;
      case ID_NEW_LOD:
      CreateNode("LOD");
      break;
      case ID_NEW_MATERIAL:
      InsertNode(NODE_MATERIAL, "Material");
      break;
      case ID_NEW_MOVIE_TEXTURE:
        InsertMovieTexture();
      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_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_NURBS_GROUP:
      CreateNode("NurbsGroup");
      break;
      case ID_NEW_NURBS_PLANE:
      CreateNurbsPlane();
      break;
      case ID_NEW_NURBS_CURVE:
      CreateNurbsCurve();
      break;
      case ID_NEW_NURBS_TEXTURE_SURFACE:
      InsertNode(NURBS_TEXTURE_SURFACE_NODE, "NurbsTextureSurface");
      break;
      case ID_NEW_NURBS_CURVE_2D:
      InsertNode(NURBS_CONTROL_CURVE_NODE | GEOMETRY_NODE, "NurbsCurve2D");
      break;
      case ID_NEW_NURBS_POSITION_INTERPOLATOR:
      CreateNode("NurbsPositionInterpolator");
      break;
      case ID_NEW_INLINE_LOAD_CONTROL:
        InsertInline(true);
      break;
      case ID_NEW_LOAD_SENSOR:
      CreateNode("LoadSensor");
      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_ORIENTATION_INTERPOLATOR:
      CreateNode("OrientationInterpolator");
      break;
      case ID_NEW_PIXEL_TEXTURE:
      InsertNode(TEXTURE_NODE, "PixelTexture");
      break;
      case ID_NEW_PLANE_SENSOR:
      CreateNode("PlaneSensor");
      break;
      case ID_NEW_POINT_LIGHT:
      CreateNode("PointLight");
      break;
      case ID_NEW_POINT_SET:
      CreateGeometryNode("PointSet");
      break;
      case ID_NEW_POLYLINE_2D:
      InsertNode(NURBS_CONTROL_CURVE_NODE | GEOMETRY_NODE, "Polyline2D");
      break;
      case ID_NEW_POSITION_INTERPOLATOR:
      CreateNode("PositionInterpolator");
      break;
      case ID_NEW_PROXIMITY_SENSOR:
      CreateNode("ProximitySensor");
      break;
      case ID_NEW_SCALAR_INTERPOLATOR:
      CreateNode("ScalarInterpolator");
      break;
      case ID_NEW_SCRIPT:
      CreateScript();
      break;
      case ID_NEW_SHAPE:
      CreateNode("Shape");
      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_SWITCH:
      CreateNode("Switch");
      break;
      case ID_NEW_TEXT:
      CreateGeometryNode("Text");
      break;
      case ID_NEW_TEXTURE_COORDINATE:
        InsertTextureCoordinate();
      break;
      case ID_NEW_TEXTURE_TRANSFORM:
      InsertNode(NODE_TEXTURE_TRANSFORM, "TextureTransform");
      break;
      case ID_NEW_TIME_SENSOR:
      CreateNode("TimeSensor");
      break;
      case ID_NEW_TOUCH_SENSOR:
      CreateNode("TouchSensor");
      break;
      case ID_NEW_TRANSFORM:
      CreateNode("Transform");
      break;
      case ID_NEW_TRIMMED_SURFACE:
        CreateGeometryNode("TrimmedSurface");
        break;
      case ID_NEW_TUBE:
        CreateTube();
        break;
      case ID_NEW_HORN:
        CreateTube(true);
        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_VIEWPOINT:
      CreateViewpoint();
      break;
      case ID_NEW_VISIBILITY_SENSOR:
      CreateNode("VisibilitySensor");
      break;
      case ID_NEW_WORLD_INFO:
      CreateNode("WorldInfo");
      break;
      case ID_NEW_COMMENT:
      CreateNode("#");
      break;
      case ID_PLAY:
      Play();
      break;
      case ID_STOP:
      Stop();
      break;
      case ID_RECORD:
      Record();
      break;
      case ID_REWIND:
      case ID_FAST_FORWARD:
      break;
      case ID_APP_ABOUT:
        {
          AboutDialog       dlg(_wnd);
          dlg.DoModal();
        }
      break;
      case ID_APP_HELP:
        OnHelpOverview();
      break;
      case ID_APP_SELECT:
        OnHelpSelection();
      break;
      case ID_OPTIONS_SWITCH_TO_DUNE4KIDS:
          {
//            TheApp->reOpenWindow(_scene);
            break;
          }
      case ID_OPTIONS_PREFERENCES:
        {
          PreferencesDialog   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();
            UpdateUpload();
        }
      break;
      case ID_OPTIONS_HELP:
        {
          HelpSettingsDialog  dlg(_wnd);
          dlg.DoModal();
        }
      break;
      case ID_OPTIONS_TEXTEDIT:
        {
          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 {
                    char errorstring[256];
                    swLoadString(IDS_RESTART_4_STEREO, errorstring, 255);
                    swMessageBox(TheApp->mainWnd(), errorstring, "dune", 
                                 SW_MB_OK, SW_MB_WARNING);
                }                
            } else {
                TheApp->setUseStereo(false);
            }
        }
      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:
        // proto usage
        if ((id >= ID_PROTO_MRU_1) && 
              (id < ID_PROTO_MRU_1 + _scene->getNumProtoNames()))
            CreateNode((const char*)_scene->getProtoName(id-ID_PROTO_MRU_1));
    }
}

void MainWindow::updateColorCircle(void)
{
    if (_colorCircle_enabled)
       {
       _scene->RemoveView(_fieldView);
       if (_fieldView!=NULL)
          _fieldView->DeleteView();
       if (_colorCircle_active)
          {
// small memoryleak, how often can be called 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::OnHighlight(int id)
{
    char    buf[BUFSIZE];
    buf[0] = '\0';
    swLoadString(id, buf, BUFSIZE);
    char *b = strchr(buf, '\n');
    if (b) *b = '\0';
    if (id == -1)
       _statusBar->SetText(_statusText);
    else
       _statusBar->SetText(buf);
}

void
MainWindow::OnUpdate(SceneView *sender, int type, Hint *hint)
{
    switch (type) {
      case UPDATE_SELECTION:
        if (_colorCircle_active==true) {
           updateColorCircle();
           _colorCircle_enabled=false;
         setColorCircleIcon();
        }
        RefreshSelectionHelp();
        _selectedField = -1;
        clearStatusText();
      case UPDATE_ALL:
      UpdateToolbars();
        RefreshProtoMenu();
      break;
      case UPDATE_SELECTED_FIELD:
        {
        FieldUpdate* fieldUpdate=(FieldUpdate *)hint;
        _selectedField = fieldUpdate->field;
        }
        break;
      case UPDATE_ENABLE_COLOR_CIRCLE:
        {
        FieldUpdate* fieldUpdate=(FieldUpdate *)hint;
        _colorCircle_enabled=true;
        _colorCircleHint=new FieldUpdate(fieldUpdate->node,fieldUpdate->field,
                                         fieldUpdate->index);
        }
      setColorCircleIcon();
      break;
      case UPDATE_DISABLE_COLOR_CIRCLE:      
        _colorCircle_enabled=false;
      setColorCircleIcon();
      break;
      case UPDATE_CLOSE_COLOR_CIRCLE:      
        updateColorCircle();
      setColorCircleIcon();
      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);
    }
}

bool isToNurbsAllowedParent(Node *parent)
{
    if ( (parent == parent->getScene()->getRoot()) ||
         (parent->getType() == NODE_GROUP) ||
         (parent->getType() == NODE_TRANSFORM) ||
         (parent->getType() == NODE_ANCHOR) ||
         (parent->getType() == NODE_SHAPE) )
       return true;
    else
       return false;
}

//
// 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)
{
    Node       *node = _scene->getSelection()->getNode();
    int           field = _scene->getSelection()->getField();
    unsigned      i;

    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);

    swMenuSetFlags(_menu, ID_NEW_APPEARANCE, SW_MENU_DISABLED, 
      node->findValidFieldType(NODE_APPEARANCE) != -1 ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_MATERIAL, SW_MENU_DISABLED, 
      node->findValidFieldType(NODE_MATERIAL) != -1 ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_COORDINATE, SW_MENU_DISABLED, 
      node->findValidFieldType(NODE_COORDINATE) != -1 ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_NORMAL, SW_MENU_DISABLED, 
      node->findValidFieldType(NODE_NORMAL) != -1 ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_COLOR, SW_MENU_DISABLED, 
      node->findValidFieldType(NODE_COLOR) != -1 ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_TEXTURE_COORDINATE, SW_MENU_DISABLED, 
      node->findValidFieldType(TEXTURE_COORDINATE_NODE) != -1 ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_NEW_TEXTURE_TRANSFORM, SW_MENU_DISABLED, 
      node->findValidFieldType(NODE_TEXTURE_TRANSFORM) != -1 ? 0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_NEW_FONT_STYLE, SW_MENU_DISABLED, 
      node->findValidFieldType(NODE_FONT_STYLE) != -1 ? 0 : SW_MENU_DISABLED);

    for (i = 1; i < sizeof(buttons2)/(2*sizeof(int)); i++) {
      int   valid = node->findValidFieldType(buttons2[i*2]) != -1;
      swToolbarSetButtonFlags(_nodeToolbar2, i, SW_TB_DISABLED, valid ? 0 :
                        SW_TB_DISABLED);
        if (buttons2[i*2] == NODE_FONT_STYLE) 
            break;
    }
    swToolbarSetButtonFlags(_nodeToolbar2, 4, SW_TB_DISABLED,
      node->findValidFieldType(TEXTURE_COORDINATE_NODE) != -1 ? 0 : SW_TB_DISABLED);
    
    swMenuSetFlags(_menu, ID_NEW_IMAGE_TEXTURE, SW_MENU_DISABLED, 
      node->findValidFieldType(TEXTURE_NODE) != -1 ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbar2, 8, SW_TB_DISABLED,
      node->findValidFieldType(TEXTURE_NODE) != -1 ? 0 : SW_TB_DISABLED);

    swMenuSetFlags(_menu, ID_NEW_PIXEL_TEXTURE, SW_MENU_DISABLED, 
            node->findValidFieldType(TEXTURE_NODE) != -1 ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbar2, 9, SW_TB_DISABLED,
            node->findValidFieldType(TEXTURE_NODE) != -1 ? 0 : SW_TB_DISABLED);

    swMenuSetFlags(_menu, ID_NEW_MOVIE_TEXTURE, SW_MENU_DISABLED, 
      node->findValidFieldType(TEXTURE_NODE) != -1 ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbar2, 10, SW_TB_DISABLED,
      node->findValidFieldType(TEXTURE_NODE) != -1 ? 0 : SW_TB_DISABLED);
   

    swMenuSetFlags(_menu, ID_NEW_AUDIO_CLIP, SW_MENU_DISABLED, 
      node->findValidFieldType(SOUND_SOURCE_NODE) != -1 ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbar2, 15, SW_TB_DISABLED,
      node->findValidFieldType(SOUND_SOURCE_NODE) != -1 ? 0 : SW_TB_DISABLED);

    swMenuSetFlags(_menu, ID_NEW_NURBS_TEXTURE_SURFACE, SW_MENU_DISABLED, 
      node->findValidFieldType(NURBS_TEXTURE_SURFACE_NODE) != -1 ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbarVRML200x, 3, SW_TB_DISABLED,
      node->findValidFieldType(NURBS_TEXTURE_SURFACE_NODE) != -1 ? 0 : SW_TB_DISABLED);

    swMenuSetFlags(_menu, ID_NEW_CONTOUR_2D, SW_MENU_DISABLED, 
      (node->getType() == NODE_TRIMMED_SURFACE) ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbarVRML200x, 6, SW_TB_DISABLED,
      (node->getType() == NODE_TRIMMED_SURFACE) ? 0 : SW_TB_DISABLED);

    swMenuSetFlags(_menu, ID_NEW_NURBS_CURVE_2D, SW_MENU_DISABLED, 
      node->findValidFieldType(NURBS_CONTROL_CURVE_NODE) != -1 ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbarVRML200x, 7, SW_TB_DISABLED,
      node->findValidFieldType(NURBS_CONTROL_CURVE_NODE) != -1 ? 0 : SW_TB_DISABLED);

    swMenuSetFlags(_menu, ID_NEW_POLYLINE_2D, SW_MENU_DISABLED, 
      node->findValidFieldType(NURBS_CONTROL_CURVE_NODE) != -1 ? 0 : SW_MENU_DISABLED);
    swToolbarSetButtonFlags(_nodeToolbarVRML200x, 8, SW_TB_DISABLED,
      node->findValidFieldType(NURBS_CONTROL_CURVE_NODE) != -1 ? 0 : SW_TB_DISABLED);


    bool editObject_flag = false;
    bool editUrl_flag = false;
    if ((node->getType() == NODE_SCRIPT) && (!_scriptEditorInUse)) {
         editObject_flag = true;
         editUrl_flag = true;
    }
    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);

    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_EDIT_PASTE, SW_MENU_DISABLED, 
                      disablePaste ? SW_MENU_DISABLED : 0);

    int     isRoot = (node == _scene->getRoot());
    int parentIsRoot = isRoot ? 1 : (node->getParent() == _scene->getRoot());

#ifndef HAVE_CUT
    swMenuSetFlags(_menu, ID_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_EDIT_COPY, SW_MENU_DISABLED, 
                   isRoot ? SW_MENU_DISABLED : 0);
    swToolbarSetButtonFlags(_standardToolbar, _editCopyIconPos, SW_TB_DISABLED,
                        isRoot ? SW_TB_DISABLED : 0);
    swMenuSetFlags(_menu, ID_EDIT_DELETE, SW_MENU_DISABLED, 
                   isRoot ? SW_MENU_DISABLED : 0);
    swToolbarSetButtonFlags(_standardToolbar, _editDeleteIconPos, 
                            SW_TB_DISABLED, isRoot ? SW_TB_DISABLED : 0);
    swMenuSetFlags(_menu, ID_EDIT_DEF, SW_MENU_DISABLED, 
                   isRoot ? SW_MENU_DISABLED : 0);

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

    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_ARRAY, SW_MENU_DISABLED, 
                   (!isRoot) && (!node->isInvalidChildNode()) &&
                   (node->getParent()->getType() == NODE_GROUP ||
                    node->getParent()->getType() == NODE_TRANSFORM) ? 
                   0 : SW_MENU_DISABLED);

    bool canCenter = false;
    if (node->hasBoundingBox())
        if ((!isRoot) && (!parentIsRoot)) {
            Node *checkNode = node->getParent();
            if (checkNode->getType() == NODE_SHAPE) {
                checkNode = checkNode->getParent();
                if (checkNode->getType() == NODE_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_DEGREE_ELEVATE_UP, SW_MENU_DISABLED,
                   node->getType() == NODE_NURBS_CURVE ? 0 : SW_MENU_DISABLED);
    swMenuSetFlags(_menu, ID_DEGREE_ELEVATE_DOWN, SW_MENU_DISABLED,
                   node->getType() == NODE_NURBS_CURVE ? 0 : SW_MENU_DISABLED);

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

    bool toNurbs = false;
    if (node->hasParent()) {
        Node *parent = node->getParent();
        if (isToNurbsAllowedParent(parent)) {
            if (node->getType() == NODE_CYLINDER)
                toNurbs = true;
            if (node->getType() == NODE_CONE)
                toNurbs = true;
            if (node->getType() == NODE_SPHERE)
                toNurbs = true;
            if (node->getType() == NODE_BOX)
                toNurbs = true;
            if (node->getType() == NODE_NURBS_CURVE)
                toNurbs = true;
            if (node->getType() == NODE_SUPER_ELLIPSOID)
                toNurbs = true;
            if (node->getType() == NODE_SUPER_SHAPE)
                toNurbs = true;
        }
    }
    swMenuSetFlags(_menu, ID_TO_NURBS, SW_MENU_DISABLED, 
                   toNurbs ? 0 : SW_MENU_DISABLED);    

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

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

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

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

    swMenuSetFlags(_menu, ID_TO_INDEXEDLINESET, SW_MENU_DISABLED, 
                   (node->getType() == NODE_NURBS_CURVE) ||
                   (node->getType() == NODE_INDEXED_FACE_SET) ? 
                   0 : SW_MENU_DISABLED);

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

    swMenuSetFlags(_menu, ID_TO_POSITION_INTERPOLATOR, SW_MENU_DISABLED, 
                   (node->getType() == NODE_NURBS_CURVE) ? 
                   0 : SW_MENU_DISABLED);

    swMenuSetFlags(_menu, ID_TO_ORIENTATION_INTERPOLATOR, SW_MENU_DISABLED, 
                   (node->getType() == NODE_NURBS_CURVE) ? 
                   0 : SW_MENU_DISABLED);

    swToolbarSetButtonFlags(_standardToolbar, _inputDeviceGreaterIconPos, 
                            SW_TB_DISABLED, 
                            TheApp->hasInputDevices() ? 0 : SW_TB_DISABLED);
    swToolbarSetButtonFlags(_standardToolbar, _inputDeviceLesserIconPos, 
                            SW_TB_DISABLED, 
                            TheApp->hasInputDevices() ? 0 : SW_TB_DISABLED);

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

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

    bool isFly = (TheApp->GetMouseMode() == MOUSE_FLY);
    swToolbarSetButtonFlags(_standardToolbar, _mouseIconPos, SW_TB_CHECKED,
                      isFly ? SW_TB_CHECKED :  0);
    swMenuSetFlags(_menu, ID_EXAMINE_MOUSE_MODE, SW_MENU_CHECKED, 
                 isFly ? 0 : SW_MENU_CHECKED);
    swMenuSetFlags(_menu, ID_FLY_MOUSE_MODE, SW_MENU_CHECKED, 
                 isFly ? SW_MENU_CHECKED : 0);

    swMenuSetFlags(_menu, ID_NAVIGATION_MODE, SW_MENU_CHECKED,
               _navigation_active ? SW_MENU_CHECKED : 0);


}

void
MainWindow::UpdateUpload(void)
{
    swMenuSetFlags(_menu, ID_FILE_UPLOAD, SW_MENU_DISABLED, 
       TheApp->hasUpload() == 0 ? SW_MENU_DISABLED : 0);
}

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

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

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

void
MainWindow::RefreshProtoMenu()
{
    int     i;
    // 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);
    
    // delete current proto menus
    for (i = 0; i < _lenProtoMenu; i++) {
      swDeleteMenuItem(_menu, ID_PROTO_MRU_1 + i);
    }
    
    int n = _scene->getNumProtoNames();

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

    _lenProtoMenu = n;
    // insert recent-file menus
    if (n > 0) {
      for (i = 0; i < n; i++) {
          char    buf[1024];
          int     id = ID_PROTO_MRU_1 + i;
          mysnprintf(buf, 1023, "&%d %s", i + 1,
                (const char *) _scene->getProtoName(i));
          swInsertMenuItem(_menu, ID_PROTO_MRU_PLACEHOLDER, buf, id);
      }
    } else if (n==0) {
         swInsertMenuItem(_menu, ID_PROTO_MRU_PLACEHOLDER, "(no PROTOs)", 
                                 ID_PROTO_MRU_1);
         _lenProtoMenu = 1;
    }

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

void MainWindow::RefreshSelectionHelp()
{
    // insert a placeholder
    swInsertMenuItem(_menu, ID_APP_SELECT, "",
                            ID_APP_SELECT_PLACEHOLDER);

    swMenuSetFlags(_menu, ID_APP_SELECT_PLACEHOLDER, SW_MENU_DISABLED,
               SW_MENU_DISABLED);
    
    swDeleteMenuItem(_menu, ID_APP_SELECT);
    swInsertMenuItem(_menu, ID_APP_SELECT_PLACEHOLDER, (const char*)
            _scene->getSelection()->getNode()->getProto()->getName(), 
            ID_APP_SELECT);

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

void MainWindow::CreateNode(const char *type)
{
    Node       *node = _scene->createNode(type);

    _scene->execute(new MoveCommand(node, NULL, -1, _scene->getRoot(), 
                    _scene->getRootIndex()));
}

void MainWindow::CreateGeometryNode(Node * node)
{
    NodeShape      *nShape = (NodeShape *) _scene->createNode("Shape");
    NodeTransform  *nTransform = (NodeTransform *) 
                                _scene->createNode("Transform");
    NodeAppearance *nAppearance = (NodeAppearance *)
                                 _scene->createNode("Appearance");
    NodeMaterial   *nMaterial = (NodeMaterial *) _scene->createNode("Material");

    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->getRootIndex()));
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

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


void
MainWindow::CreateAnimation(void)
{
    Node *node = _scene->getSelection()->getNode();
    if (node == _scene->getRoot())
        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();
    
    bool animateSomething = false;
    for (int i = 0 ; i < eventInFields.size(); i++) 
        if (eventInIsAnimated[i]) {
            animateSomething = true;
            break;
        }

    if (animateSomething) {
        NodeTimeSensor *timeSensor = dlg.getTimeSensor();
        if (timeSensor == NULL) {
            timeSensor = (NodeTimeSensor *) _scene->createNode("TimeSensor");
            timeSensor->cycleInterval(new SFTime(dlg.getTimeSensorSeconds()));
            timeSensor->loop(new SFBool(true));
            _scene->execute(new MoveCommand(timeSensor, NULL, -1, 
                  _scene->getRoot(), _scene->getRootIndex()));
        }
        for (int i = 0 ; i < eventInFields.size(); i++) {
            if (eventInIsAnimated[i]) {
                Node* interpolator = NULL;
                switch (eventInTypes[i]) {
                  case SFCOLOR:
                    interpolator = _scene->createNode("ColorInterpolator"); 
                    break;
                  case MFVEC3F:
                    {
                    char *mfvec3finterpolator;                     
                    if ((node->getType() == NODE_NORMAL) && 
                        (eventInFields[i] == 
                         ((NodeNormal *) node)->vector_Index()))
                        mfvec3finterpolator = "NormalInterpolator";
                    else
                        mfvec3finterpolator = "CoordinateInterpolator";
                    interpolator = _scene->createNode(mfvec3finterpolator);
                    break;
                    }
                  case SFVEC3F:
                    interpolator = _scene->createNode("PositionInterpolator"); 
                    break;
                  case SFROTATION:
                    interpolator = _scene->createNode("OrientationInterpolator");
                    break;
                  case SFFLOAT:
                    interpolator = _scene->createNode("ScalarInterpolator"); 
                    break;
                }
                if (interpolator == NULL)
                    continue;
                _scene->execute(new MoveCommand(interpolator, NULL, -1, 
                      _scene->getRoot(), _scene->getRootIndex()));
                _scene->execute(new RouteCommand(timeSensor, 
                      timeSensor->fraction_changed_Index(), 
                      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_VIEW_CHANNEL_VIEW, 
                 "ShowChannelView");
    }
}

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->getRootIndex()));
    _scene->setSelection(node);
    _scene->UpdateViews(NULL, UPDATE_SELECTION);
}

bool
MainWindow::isScriptEditorInUse()
{
    if (_scriptEditorInUse) { 
        char errorstring[256];
        swLoadString(IDS_SCRIPT_EDITOR_IN_USE_ERROR, errorstring, 255);
        swMessageBox(TheApp->mainWnd(), errorstring, "dune", SW_MB_OK, 
                     SW_MB_WARNING);
    }
    return _scriptEditorInUse;
}

void
MainWindowEditorReadyCallback(void *data)
{
    MainWindow *mainWindow = (MainWindow *) data;
    mainWindow->OnEditorReadyCallback();
}

static Node* scriptEditNode; 
static int scriptEditField; 

void
MainWindow::OnEditorReadyCallback(void)
{
    if (_scriptEdit != NULL)
        delete  _scriptEdit;
    FieldUpdate* hint = new FieldUpdate(scriptEditNode, scriptEditField);
    _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
    delete hint;
    _scriptEditorInUse = false;
    UpdateToolbars();
}


void
MainWindow::EditUrl()
{
    Node       *node = _scene->getSelection()->getNode();
    if (node->getType() == NODE_SCRIPT) {
        if (_scriptEditorInUse) {
            char errorstring[256];
            swLoadString(IDS_SCRIPT_EDITOR_IN_USE_ERROR, errorstring, 255);
            swMessageBox(TheApp->mainWnd(), errorstring, "dune", SW_MB_OK, 
                         SW_MB_WARNING);
            return;
        }
        scriptEditNode = node;
        scriptEditField = ((NodeScript *)node)->getUrlField();
        _scriptEditorInUse = true;
        _scriptEdit = new ScriptEdit((NodeScript *)node, _wnd, 
                                     MainWindowEditorReadyCallback, this);
        MyString scriptName = strdup(node->getName());
        if (strlen(scriptName) == 0) {
            _scene->generateUniqueNodeName(node);
            scriptName = strdup(node->getName());
        }
        const char *scriptFilePath = strdup(_scene->getURL());
        char scriptTempFilePath[1024];
        if (strlen(scriptFilePath) == 0) {
            mysnprintf(scriptTempFilePath,1023,"http://web3d.invalid/time%lf\n",
                       swGetCurrentTime());
            scriptFilePath = scriptTempFilePath;
            _scene->setURL(scriptTempFilePath);
        }
        char* scriptEditReturn = _scriptEdit->ecmaScriptEdit();
        if (scriptEditReturn != NULL) {
            char* filename = strdup(scriptEditReturn);
            // start editor without popup of editor Window
            TheApp->OnFileEdit(this, _scene, filename);
            // find scene and node to read URL into matching field
            List<MainWindow *> windows = TheApp->getWindows();
            for (List<MainWindow *>::Iterator *wIter = windows.first(); 
                 wIter != NULL;  wIter  = wIter ->next()) {
                Scene *scene = wIter->item()->GetScene();
                const char *sceneFilePath = scene->getURL();
                if (strcmp(sceneFilePath, scriptFilePath) == 0) {
                    if (strcmp(sceneFilePath, scriptTempFilePath) == 0)
                        scene->setURL("");
                    Node *sceneNode = scene->use(scriptName);
                    if (sceneNode != NULL) {
                        ScriptEdit* scriptEdit = new ScriptEdit(
                                                 (NodeScript *)sceneNode, _wnd, 
                                                 MainWindowEditorReadyCallback, 
                                                 wIter->item());
                        scriptEdit->ecmaScriptReadEditorfile(filename);
                        /*
                        FieldUpdate* hint = new FieldUpdate(sceneNode, 
                                                            scriptEditField);
                        _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
                        delete hint;
                        scene->setSelection(sceneNode);
                        scene->UpdateViews(NULL, UPDATE_SELECTION);
                        */
                        break;
                    }
                }
            }
            _scriptEditorInUse = false;
        } else {
            _scene->setSelection(node);
            _scene->UpdateViews(NULL, UPDATE_SELECTION);
        }
    }
}

void
MainWindow::EditObject()
{
    Node       *node = _scene->getSelection()->getNode();
    if (node->getType() == NODE_SCRIPT) {
        if (_scriptEditorInUse) {
            char errorstring[256];
            swLoadString(IDS_SCRIPT_EDITOR_IN_USE_ERROR, errorstring, 255);
            swMessageBox(TheApp->mainWnd(), errorstring, "dune", SW_MB_OK, 
                         SW_MB_WARNING);
            return;
        }
        int field = _selectedField;
        if ((field != -1) && 
            (strcmp(node->getProto()->getField(field)->getName(), "url")==0))
            EditUrl();
        else {
            EditScript(node);
            NodeUpdate *hint= new NodeUpdate(node, NULL, 0);
            _scene->UpdateViews(NULL, UPDATE_CHANGE_INTERFACE_NODE, 
                                (Hint*) hint);
        }
    }
    _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->getRootIndex()));
}

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::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)
                                            (vDimension - 1 - j);
            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->controlPoint(
              new MFVec3f(controlPoints, uDimension * vDimension * 3));
      node->weight(new MFFloat(weights, uDimension * vDimension));
        CreateGeometryNode(node);
    }
}

void
MainWindow::CreateNurbsCurve()
{
    int           i;

    NurbsCurveDialog dlg(_wnd, 5, 2, 1);
    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++){
            controlPoints[(i*3)]   = (direction == 0 ? i : 0);
            controlPoints[(i*3)+1] = (direction == 1 ? i : 0);
            controlPoints[(i*3)+2] = (direction == 2 ? i : 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 MFVec3f(controlPoints, dimension * 3));    
        node->weight(new MFFloat(weights, dimension));
        node->knot(new MFFloat(knots, dimension + order));
        node->order(new SFInt32(order));
    
        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->getRootIndex()));
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::CreateSuperExtrusion()
{
    int           i;

    NurbsCurveDialog dlg(_wnd, 5, 2, 1);
    if (dlg.DoModal() == IDOK) {
        int         degree = dlg.getDegree();
        int         dimension = dlg.getnPoints();
        int         direction = dlg.getDirection();

        int order = degree + 1;
        
        NodeSuperExtrusion *node = (NodeSuperExtrusion *)
                                   _scene->createNode("SuperExtrusion");       
        float      *controlPoints = new float[dimension * 3];
        float      *weights = new float[dimension];
        float      *knots = new float[dimension + order]; 
        
        for (i=0; i<dimension; i++){
            controlPoints[(i*3)]   = (direction == 0 ? i : 0);
            controlPoints[(i*3)+1] = (direction == 1 ? i : 0);
            controlPoints[(i*3)+2] = (direction == 2 ? i : 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 MFVec3f(controlPoints, dimension * 3));    
        node->weight(new MFFloat(weights, dimension));
        node->knot(new MFFloat(knots, dimension + order));
        node->order(new SFInt32(order));
    
        NodeShape      *nShape = (NodeShape *) _scene->createNode("Shape");
        NodeTransform  *nTransform = (NodeTransform *) 
                                _scene->createNode("Transform");
        NodeAppearance *nAppearance = (NodeAppearance *)
                                      _scene->createNode("Appearance");
        NodeMaterial   *nMaterial = (NodeMaterial *) 
                                      _scene->createNode("Material");
        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->getRootIndex()));
        _scene->setSelection(node);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

void
MainWindow::CreateStarFish(int numberArms)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == NODE_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));
      toNurbs();
    }
}

void
MainWindow::CreateFlower(int numberLeaves)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == NODE_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));
      toNurbs();
    }
}

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

void
MainWindow::CreateShell(void)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    OneFloatDialog dlg(_wnd, IDD_SHELL_SMOOTH, 0.5, 0, 1);
    if (dlg.DoModal() == IDCANCEL)
        return;
    if ((node) && (node->getType() == NODE_SUPER_SHAPE)) {
        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(-dlg.GetValue()));
        superShape->vn3(new SFFloat(0.28));
        superShape->uTessellation(new SFInt32(16));
        superShape->vTessellation(new SFInt32(16));
      toNurbs();
    }
}

void
MainWindow::CreateUfo(void)
{
    CreateGeometryNode("SuperShape");
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == NODE_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));
      toNurbs();
    }
}

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

void
MainWindow::CreateTube(bool hornFlag)
{
    CreateSuperExtrusion();
    Node *node = _scene->getSelection()->getNode();
    if ((node) && (node->getType() == NODE_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::moveBranchTo(char* nodeName, 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) {
        char errorstring[256];
        swLoadString(IDS_INTERNAL_ERROR, errorstring, 255);
        swMessageBox(TheApp->mainWnd(), errorstring, "dune", SW_MB_OK, 
                     SW_MB_WARNING);
        return;
    }
    moveBranchTo(node, field, current);
}

void 
MainWindow::moveBranchTo(Node* node, int field, Node* current)
{
    Node *target = current; 
    int     targetField = -1;
    if (target == _scene->getRoot())
        targetField = _scene->getRootIndex();
    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::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->getRootIndex();
    else
        targetField = target->getParentField();
    target = target->getParent();
    moveBranchTo(target, targetField, current);
}

Node*
MainWindow::getTransformForCenter() 
{
    Node *node = _scene->getSelection()->getNode(); 
    if (node != _scene->getRoot()) {
        node = node->getParent();
        if (node->getType() == NODE_SHAPE)
           if (node != _scene->getRoot()) {
               Node *shapeParent = node->getParent();
               if (shapeParent->getType() == NODE_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(); 
       _scene->setField(transform, transform->center_Index(), 
                        new SFVec3f((max + min) / 2));
   }
}

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[index] = max[index];
       _scene->setField(transform, transform->center_Index(), 
                        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[index] = min[index];
       _scene->setField(transform, transform->center_Index(), 
                        new SFVec3f(vcenter));
   }
}

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

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->getRootIndex()));
        else if (parent->getType() == NODE_GROUP)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_TRANSFORM)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeTransform *)parent)->children_Index()));
        else if (parent->getType() == NODE_ANCHOR)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeAnchor *)parent)->children_Index()));
        else if (parent->getType() == NODE_SHAPE) {
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                             ((NodeShape *)parent)->geometry_Index()));
            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_Index(), 
                               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_Index()));
            }
        }
        _scene->execute(list);
        _scene->setSelection(nurbsNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

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

    Node* nurbsNode = NULL;

    if (type == NODE_NURBS_CURVE) {
        NodeNurbsCurve *oldNurbs = (NodeNurbsCurve *)node;
        int newDegree = oldNurbs->order()->getValue() - 1 + degree;
      nurbsNode = node->degreeElevate(newDegree);
      //SFRotation rot(0,1,0,M_PI/2.0);
      //((NodeNurbsSurface *)nurbsNode)->rotate(rot);
        InsertNewNurbsNode(nurbsNode, parent);
    }
}

void MainWindow::uDegreeElevate(int degree)
{
    Node *node =_scene->getSelection()->getNode();
    int type = node->getType();
    Node *parent = node->getParent();
                          
    Node* nurbsNode = NULL;
                    
    if (type == NODE_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 == NODE_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::swapDiffuseEmissiveShape(NodeShape *shape,
                                     ColorConversion conversion)
{
    SFNode *appear = shape->appearance();
    if (appear != NULL) {
        NodeAppearance *nAppearance = (NodeAppearance *) appear->getValue();
        NodeMaterial *nMaterial = (NodeMaterial *) 
                                   nAppearance->material()->getValue(); 
        if (nMaterial != NULL) {
            switch(conversion) {
               case DIFFUSE2EMISSIVE:
                 nMaterial->diffuse2emissive();
                 break;
               case EMISSIVE2DIFFUSE:
                 nMaterial->emissive2diffuse();
                 break;
               default:
                 assert(1);
            }
        }
    }
}

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

    Node* nurbsNode = NULL;

    if (type == NODE_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 == NODE_CONE) {
        Cone2NurbsDialog 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 == NODE_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 == NODE_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() == NODE_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 == NODE_NURBS_CURVE) {
        NurbsCurve2NurbsSurfDialog dlg(_wnd, node, 4, 2, 360, NURBS_ROT_Y_AXIS);
        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)->flatten(dlg.getMethod()))
                     TheApp->PrintMessageWindows("This type of flatten not supported yet");
          nurbsNode = node->toNurbs(narcs, pDegree, rDegree, P1, P2);
            if (nurbsNode == NULL) {
                char errorstring[256];
                swLoadString(IDS_NURBS_CURVE_CONVERT_ERROR, errorstring, 255);
                swMessageBox(TheApp->mainWnd(), errorstring, "dune", SW_MB_OK, 
                             SW_MB_WARNING);
            }
            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 == NODE_SUPER_ELLIPSOID) {
        NodeSuperEllipsoid *super = (NodeSuperEllipsoid *)node;
        int uTess = super->uTessellation()->getValue();
        if (uTess == 0)
            uTess = 8;
        int vTess = super->vTessellation()->getValue();
        if (vTess == 0)
            vTess = 8;
        Sphere2NurbsDialog dlg(_wnd, uTess, vTess, 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);
        }
    }
    if (type == NODE_SUPER_SHAPE) {
        NodeSuperShape *super = (NodeSuperShape *)node;
        int uTess = super->uTessellation()->getValue();
        if (uTess == 0) {
            float um = fabs(super->um()->getValue());
            uTess = 8;
            if (um * 3 > uTess)
                uTess = um *3;
        }
        int vTess = super->vTessellation()->getValue();
        if (vTess == 0) {
            vTess = 8;
            float vm = fabs(super->vm()->getValue());
            if (vm * 3 > vTess)
            vTess = vm *3;
        }
        Sphere2NurbsDialog dlg(_wnd, uTess, vTess, 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);
        }
    }

    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->getRootIndex()));
        else if (parent->getType() == NODE_GROUP)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_TRANSFORM)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeTransform *)parent)->children_Index()));
        else if (parent->getType() == NODE_ANCHOR)
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                           ((NodeAnchor *)parent)->children_Index()));
        else if (parent->getType() == NODE_SHAPE) {
            list->append(new MoveCommand(nurbsNode, NULL, -1, parent, 
                             ((NodeShape *)parent)->geometry_Index()));
            if (type == NODE_NURBS_CURVE)
                swapDiffuseEmissiveShape((NodeShape *)parent, EMISSIVE2DIFFUSE);
        }
        _scene->execute(list);
        _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;

    bool defaultColor = true;
    if (type == NODE_SUPER_EXTRUSION)
        nurbsCurveNode = ((NodeSuperExtrusion *)node)->toNurbsCurve();
    if (nurbsCurveNode != 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(nurbsCurveNode, NULL, -1, 
                            _scene->getRoot(), _scene->getRootIndex()));
        else if (parent->getType() == NODE_GROUP)
            list->append(new MoveCommand(nurbsCurveNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_TRANSFORM)
            list->append(new MoveCommand(nurbsCurveNode, NULL, -1, parent, 
                           ((NodeTransform *)parent)->children_Index()));
        else if (parent->getType() == NODE_ANCHOR)
            list->append(new MoveCommand(nurbsCurveNode, NULL, -1, parent, 
                           ((NodeAnchor *)parent)->children_Index()));
        else if (parent->getType() == NODE_SHAPE) {
            list->append(new MoveCommand(nurbsCurveNode, NULL, -1, parent, 
                             ((NodeShape *)parent)->geometry_Index()));
            swapDiffuseEmissiveShape((NodeShape *)parent, DIFFUSE2EMISSIVE);
        }
        _scene->execute(list);
        _scene->setSelection(nurbsCurveNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }

}

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

    Node* superExtrusionNode = NULL;

    bool defaultColor = true;
    if (type == NODE_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
        CommandList *list = new CommandList();
        if (isToNurbsAllowedParent(parent)) 
            _scene->DeleteSelected();
        else 
            return;
        if (parent == _scene->getRoot())
            list->append(new MoveCommand(superExtrusionNode, NULL, -1, 
                            _scene->getRoot(), _scene->getRootIndex()));
        else if (parent->getType() == NODE_GROUP)
            list->append(new MoveCommand(superExtrusionNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_TRANSFORM)
            list->append(new MoveCommand(superExtrusionNode, NULL, -1, parent, 
                           ((NodeTransform *)parent)->children_Index()));
        else if (parent->getType() == NODE_ANCHOR)
            list->append(new MoveCommand(superExtrusionNode, NULL, -1, parent, 
                           ((NodeAnchor *)parent)->children_Index()));
        else if (parent->getType() == NODE_SHAPE) {
            list->append(new MoveCommand(superExtrusionNode, NULL, -1, parent, 
                             ((NodeShape *)parent)->geometry_Index()));
            swapDiffuseEmissiveShape((NodeShape *)parent, EMISSIVE2DIFFUSE);
        }
        _scene->execute(list);
        _scene->setSelection(superExtrusionNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }

}

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

    if (node->canConvertToExtrusion()) {
        Node *extrusionNode = node->toExtrusion();
        Node *parent = node->getParent();
        if (parent != NULL)
            _scene->DeleteSelected();
        if (parent == _scene->getRoot())
            _scene->execute(new MoveCommand(extrusionNode, NULL, -1, 
                            _scene->getRoot(), _scene->getRootIndex()));
        else if (parent->getType() == NODE_SHAPE)
            _scene->execute(new MoveCommand(extrusionNode, NULL, -1, parent, 
                           ((NodeShape *)parent)->geometry_Index()));
        else if (parent->getType() == NODE_GROUP)
            _scene->execute(new MoveCommand(extrusionNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_NURBS_GROUP)
            _scene->execute(new MoveCommand(extrusionNode, NULL, -1, parent, 
                           ((NodeNurbsGroup *)parent)->children_Index()));
        _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() == NODE_SUPER_ELLIPSOID)
            wantNormals = false;
        if (node->getType() == NODE_SUPER_SHAPE)
            wantNormals = false;
        if (node->getType() == NODE_EXTRUSION)
            wantNormals = false;
        if (node->getType() == NODE_ELEVATION_GRID)
            wantNormals = false;
        Node *faceSetNode = node->toIndexedFaceSet(wantNormals);
        Node *parent = node->getParent();
        if (parent != NULL)
            _scene->DeleteSelected();
        if (parent == _scene->getRoot())
            _scene->execute(new MoveCommand(faceSetNode, NULL, -1, 
                            _scene->getRoot(), _scene->getRootIndex()));
        else if (parent->getType() == NODE_SHAPE)
            _scene->execute(new MoveCommand(faceSetNode, NULL, -1, parent, 
                           ((NodeShape *)parent)->geometry_Index()));
        else if (parent->getType() == NODE_GROUP)
            _scene->execute(new MoveCommand(faceSetNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_NURBS_GROUP)
            _scene->execute(new MoveCommand(faceSetNode, NULL, -1, parent, 
                           ((NodeNurbsGroup *)parent)->children_Index()));
        _scene->setSelection(faceSetNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

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

    if ((type == NODE_NURBS_CURVE) || (type == NODE_INDEXED_FACE_SET)) {
        Node *lineSetNode = NULL;
        if (type == NODE_NURBS_CURVE)
            lineSetNode = ((NodeNurbsCurve *)node)->toIndexedLineSet();
        else if (type == NODE_INDEXED_FACE_SET)
            lineSetNode = ((NodeIndexedFaceSet *)node)->toIndexedLineSet();
        Node *parent = node->getParent();
        if (parent != NULL)
            _scene->DeleteSelected();
        if (parent == _scene->getRoot())
            _scene->execute(new MoveCommand(lineSetNode, NULL, -1, 
                            _scene->getRoot(), _scene->getRootIndex()));
        else if (parent->getType() == NODE_GROUP)
            _scene->execute(new MoveCommand(lineSetNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_NURBS_GROUP)
            _scene->execute(new MoveCommand(lineSetNode, NULL, -1, parent, 
                           ((NodeNurbsGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_SHAPE) {
            _scene->execute(new MoveCommand(lineSetNode, NULL, -1, parent, 
                           ((NodeShape *)parent)->geometry_Index()));
            swapDiffuseEmissiveShape((NodeShape *)parent, DIFFUSE2EMISSIVE);
        }
        _scene->setSelection(lineSetNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

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

    if (type == NODE_INDEXED_LINE_SET) {
        Node *pointSetNode = ((NodeIndexedLineSet *)node)->toPointSet();
        Node *parent = node->getParent();
        if (parent != NULL)
            _scene->DeleteSelected();
        if (parent == _scene->getRoot())
            _scene->execute(new MoveCommand(pointSetNode, NULL, -1, 
                            _scene->getRoot(), _scene->getRootIndex()));
        else if (parent->getType() == NODE_SHAPE)
            _scene->execute(new MoveCommand(pointSetNode, NULL, -1, parent, 
                           ((NodeShape *)parent)->geometry_Index()));
        else if (parent->getType() == NODE_GROUP)
            _scene->execute(new MoveCommand(pointSetNode, NULL, -1, parent, 
                           ((NodeGroup *)parent)->children_Index()));
        else if (parent->getType() == NODE_NURBS_GROUP)
            _scene->execute(new MoveCommand(pointSetNode, NULL, -1, parent, 
                           ((NodeNurbsGroup *)parent)->children_Index()));
        _scene->setSelection(pointSetNode);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

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

    if (type == NODE_NURBS_CURVE) {
        Node *interpolator = ((NodeNurbsCurve *)node)->toPositionInterpolator();
        _scene->execute(new MoveCommand(interpolator, NULL, -1, 
                                        _scene->getRoot(), 
                                        _scene->getRootIndex())); 
        _scene->setSelection(interpolator);
        _scene->UpdateViews(NULL, UPDATE_SELECTION);
    }
}

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

    if (type == NODE_NURBS_CURVE) {
        Node *interpolator = ((NodeNurbsCurve *)
                               node)->toOrientationInterpolator();
        _scene->execute(new MoveCommand(interpolator, NULL, -1, 
                                        _scene->getRoot(), 
                                        _scene->getRootIndex())); 
        _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) {
        _scene->setPathAllURL(dlg.getPath());
        _scene->UpdateViews(NULL, UPDATE_ALL, NULL);
    }
}

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

       char buf[FILENAME_MAX];
       buf[0] = '\0';
       if (swOpenFileDialog(_wnd, "Select Sound Data (*.wav)",
                          "Sound Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0\0",
                            buf, FILENAME_MAX)) {

          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));
      }
    }
}

void
MainWindow::InsertImageTexture()
{
    Node *current = _scene->getSelection()->getNode();
    int     field = current->findValidFieldType(TEXTURE_NODE);

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

        buf[0] = '\0';
        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, FILENAME_MAX)) {
          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));
      }
    }
}

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_Index()));
            _scene->execute(new MoveCommand(node, NULL, -1, copyTransform,
                                            copyTransform->children_Index()));
        }
    _scene->UpdateViews(NULL, UPDATE_ALL, NULL);    
    }

}

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

    buf[0] = '\0';
    if (swOpenFileDialog(_wnd, "Select VRML File (*.wrl *.wrz)",
       "VRML Files (*.wrl,*.wrz)\0*.wrl;*.wrz\0All Files (*.*)\0*.*\0\0",
       buf, FILENAME_MAX)) {

       NodeInline *node;
         if (withLoadControl)
             node = (NodeInline *)_scene->createNode("InlineLoadControl");
         else
             node = (NodeInline *)_scene->createNode("Inline");
       URL        url;
       url.FromPath(buf);
       node->url(new MFString(rewriteURL(url,url.GetDir(),_scene->getURL())));
         _scene->execute(new MoveCommand(node, NULL, -1, _scene->getRoot(), 
                                         _scene->getRootIndex()));
         _scene->readInline(node);
    }
}

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

    buf[0] = '\0';
    if (swOpenFileDialog(_wnd, "Select movie (MPEG1) File (*.mpg)",
       "MPEG1 Files (*.mpg)\0*.mpg\0All Files (*.*)\0*.*\0\0",
       buf, FILENAME_MAX)) {
      Node       *current = _scene->getSelection()->getNode();
      int       field = current->findValidFieldType(TEXTURE_NODE);

      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));
      }
    }
}

void
MainWindow::InsertNormal()
{
    Node *node = InsertNode(NODE_NORMAL, "Normal");
    if (node != NULL) {
        ((NodeNormal *)node)->
              setNormalFromIndexedFaceSet();
        FieldUpdate* hint = new FieldUpdate(node, 0);
        _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
        delete hint;
    }
}

void
MainWindow::InsertTextureCoordinate()
{
    Node *node = InsertNode(TEXTURE_COORDINATE_NODE, "TextureCoordinate"); 
    if (node != NULL) {
        ((NodeTextureCoordinate *)node)->
              setTextureCoordinateFromIndexedFaceSet();
        FieldUpdate* hint = new FieldUpdate(node, 0);
        _scene->UpdateViews(NULL, UPDATE_FIELD, (Hint *) hint);
        delete hint;
    }
}


Node*
MainWindow::InsertNode(const char *type)
{
    Node       *current = _scene->getSelection()->getNode();
    int           field = -1;
    if (current == _scene->getRoot())
        field = _scene->getRootIndex();
    else {
        field = current->getParentField();
        current = current->getParent();
    }

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

Node*
MainWindow::InsertNode(int fieldType, const char *type)
{
    Node       *current = _scene->getSelection()->getNode();
    int           field = current->findValidFieldType(fieldType);

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

void MainWindow::ToggleFullScreen()
{
    _fullScreen_enabled=!_fullScreen_enabled;
    TheApp->SetBoolPreference("FullScreen", _fullScreen_enabled);
    swMenuSetFlags(_menu, ID_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_VIEW_SCENE_TREE, SW_MENU_DISABLED, 
                              SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_VIEW_SCENE_GRAPH, SW_MENU_DISABLED, 
                              SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_VIEW_FIELD_VIEW, SW_MENU_DISABLED, 
                              SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_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(_nodeToolbarScripted,false);
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_1, SW_MENU_DISABLED, 
                              SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_2, SW_MENU_DISABLED, 
                              SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_3, SW_MENU_DISABLED, 
                              SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_VRML200X, SW_MENU_DISABLED, 
                              SW_MENU_DISABLED);
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_SCRIPTED, 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_VIEW_SCENE_TREE, SW_MENU_DISABLED, 0);
        swMenuSetFlags(_menu, ID_VIEW_SCENE_GRAPH, SW_MENU_DISABLED, 0);
        swMenuSetFlags(_menu, ID_VIEW_FIELD_VIEW, SW_MENU_DISABLED, 0);
        swMenuSetFlags(_menu, ID_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 (_nodeToolbarScriptedEnabled)
            _toolbarWindow->ShowToolbar(_nodeToolbarScripted,true);
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_1, SW_MENU_DISABLED,0); 
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_2, SW_MENU_DISABLED,0); 
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_3, SW_MENU_DISABLED,0); 
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_VRML200X, SW_MENU_DISABLED,
                       0); 
        swMenuSetFlags(_menu, ID_VIEW_NODE_TOOLBAR_SCRIPTED, 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));
    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_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 (strcmp(prefName, "nodeToolbarScripted") == 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;
}

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_NURBS, 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_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_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();
      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->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);
}

void
MainWindow::OnFileOpen()
{
#ifndef HAVE_OPEN_IN_NEW_WINDOW
    if (!TheApp->checkSaveOldWindow())
        return;
#endif

    char    path[1024];
    path[0] = '\0';
    if (swOpenFileDialog(_wnd, "Open",
#ifdef READ_XML
# ifdef HAVE_LIBZ
           "VRML (*.wrl),compressed VRML (*.wrz),X3D (*.xml)\0*.wrl;*.wrz;*.xml\0All Files (*.*)\0*.*\0\0", 
# else
           "VRML (*.wrl),X3D (*.xml)\0*.wrl;*.xml\0All Files (*.*)\0*.*\0\0", 
# endif
#else
# ifdef HAVE_LIBZ
           "VRML (*.wrl),compressed VRML (*.wrz)\0*.wrl;*.wrz\0All Files (*.*)\0*.*\0\0", 
# else
           "VRML (*.wrl)\0*.wrl\0All Files (*.*)\0*.*\0\0", 
# endif
#endif
             path, 1024)) {
      if (OpenFileCheck(path)) {
#ifndef HAVE_OPEN_IN_NEW_WINDOW
            TheApp->deleteOldWindow();
#endif
        }
    }
}

//
// 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) {
          char    msg[1024];
          mysnprintf(msg, 1023, "%s:  %s", path, strerror(errno));
          swMessageBox(_wnd, msg, "Open", SW_MB_OK, SW_MB_WARNING);
        }
        return false;
    }
    return true;
}

void
MainWindow::OnFileImport()
{
    char    path[1024];

    path[0] = '\0';
    if (swOpenFileDialog(_wnd, "Import",
#ifdef READ_XML
# ifdef HAVE_LIBZ
           "VRML (*.wrl),compressed VRML (*.wrz),X3D (*.xml)\0*.wrl;*.wrz;*.xml\0All Files (*.*)\0*.*\0\0", 
# else
           "VRML (*.wrl),X3D (*.xml)\0*.wrl;*.xml\0All Files (*.*)\0*.*\0\0", 
# endif
#else
# ifdef HAVE_LIBZ
           "VRML (*.wrl),compressed VRML (*.wrz)\0*.wrl;*.wrz\0All Files (*.*)\0*.*\0\0", 
# else
           "VRML (*.wrl)\0*.wrl\0All Files (*.*)\0*.*\0\0", 
# endif
#endif
             path, 1024)) {
      ImportFileCheck(path);
    }
}

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

void
MainWindow::ImportFileCheck(const char *path)
{
    if (!TheApp->ImportFile(path,_scene)) {
      char  msg[1024];
      mysnprintf(msg, 1023, "%s:  %s", path, strerror(errno));
      swMessageBox(_wnd, msg, "Import", SW_MB_OK, SW_MB_WARNING);
    }
}

bool
MainWindow::SaveFile(const char *filepath, const char *url, bool pureVRML97)
{
    char path[1024];
#ifdef WRITE_XML
    if (swIsXML(filepath))
       swGetTempPath(path,"to_xml",".wrl",1024);
    else
#endif
       mystrncpy_secure(path,filepath,1024); 
    int f = open(path, O_WRONLY | O_CREAT, 00664);
       
    if (f==-1) {
      char  msg[1024];
      mysnprintf(msg,1023,"%s:  %s", path, strerror(errno));
      swMessageBox(_wnd, msg, "Save", SW_MB_OK, SW_MB_WARNING);
      return false;
    } else {
      if (_scene->write(f, url, false, pureVRML97)<0) {
         char     msg[1024];
         mysnprintf(msg,1023,"%s:  %s", path, strerror(errno));
         swMessageBox(_wnd, msg, "Save", SW_MB_OK, SW_MB_WARNING);
         return false;
        }
#ifndef _WIN32
        ftruncate(f,lseek(f,0,SEEK_CUR));
#else
      _chsize(f, tell(f));
#endif
      close(f);
#ifdef WRITE_XML
        if (swIsXML(filepath))
           return vrml2x3d(path,(char*)filepath);
        else
#endif
         return true;
    }
}

void MainWindow::OnFileSave()
{
    const char    *path = _scene->getPath();
    if (path[0]) {
      SaveFile(path, _scene->getURL());
    } else {
      OnFileSaveAs();
    }
}

void MainWindow::OnFileExportVRML97()
{
    OnFileSaveAs(true);
}

void MainWindow::OnFileSaveAs(bool pureVRML97)
{
    char    path[1024];

    path[0] = '\0';
    if (swSaveFileDialog(_wnd, "Save As",
#ifdef WRITE_XML
             "VRML (.wrl),X3D (.xml)\0*.wrl;*.xml\0All Files (*.*)\0*.*\0\0",
#else
             "VRML (.wrl)\0*.wrl\0All Files (*.*)\0*.*\0\0",
#endif
                path, 1024,".wrl")) {

      URL         url;

      url.FromPath(path);
      if (SaveFile(path, url, pureVRML97)) {
            if (!pureVRML97) {
              TheApp->AddToRecentFiles(path);
              _scene->setPath(path);
              _scene->setURL(url);
              UpdateTitle();
            }
      } 
    }
}

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::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();
            node->reInit();
          _scene->execute(new MoveCommand(node, NULL, -1,
                                  destNode, destField));
      }
    }
}

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

    if (_scene->isModified()) {
      const char  *path = _scene->getPath();
      swSetFocus(_wnd);
      swLoadString(ID_SAVE_CHANGES, str, 256);
      swLoadString(ID_SAVE_CHANGES_TITLE, title, 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:
          OnFileSave();
          break;
        case IDCANCEL:
          ok = false;
          break;
        case IDNO:
          break;
      }
    }
    return ok;
}

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

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

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

void
MainWindow::removeIllegalNodes()
{
    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);    
}

void
MainWindow::countPolygons()
{
    Node *node = _scene->getSelection()->getNode();
    mysnprintf(_statusText, 255, "%s: %d  %s: %d",
               "number of polygons", node->countPolygons(),  
               "number of primitives", node->countPrimitives());
    _statusBar->SetText(_statusText);
}

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

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 == NODE_NURBS_CURVE) {
    //        doSomeThingWith(node);
    //    }

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

Generated by  Doxygen 1.6.0   Back to index