CRhinoCommand::result CCommandSampleOrientOnCrv::RunCommand( const CRhinoCommandContext& context )
{
  CRhinoCommand::result rc = CRhinoCommand::success;

  CRhinoXformObjectList object_list;
  rc = SelectObjects( object_list );
  if( rc != CRhinoCommand::success )
    return rc;

  ON_Plane base_plane;
  rc = GetBasePlane( base_plane );
  if( rc != CRhinoCommand::success )
    return rc;

  const ON_Curve* path_curve = NULL;
  rc = GetPathCurve( path_curve );
  if( rc != CRhinoCommand::success )
    return rc;

  BOOL bCopy = FALSE;

  COrientOnCrvXform get;
  get.SetCommandPrompt( L"New base point on curve" );
  get.AddCommandOptionToggle( RHCMDOPTNAME(L"Copy"), RHCMDOPTVALUE(L"No"), RHCMDOPTVALUE(L"Yes"), bCopy, &bCopy );
  get.AddCommandOptionToggle( RHCMDOPTNAME(L"Perpendicular"), RHCMDOPTVALUE(L"No"), RHCMDOPTVALUE(L"Yes"), m_perp_mode, &m_perp_mode );
  get.AppendObjects( object_list );
  get.Constrain( *path_curve );
  get.AcceptNothing();
  get.SetPathCurve( path_curve );
  get.SetBasePlane( base_plane );

  for(;;)
  {
    get.EnablePerpMode( m_perp_mode );
    CRhinoGet::result res = get.GetXform();

    if( res == CRhinoGet::point )
    {
      ON_Xform xform;
      if( get.CalculateTransform(get.View()->Viewport(), get.Point(), xform) )
      {
        TransformObjects( context.m_doc, object_list, xform, TRUE );
        context.m_doc.Redraw();
      }

      if( bCopy )
        continue;
      break;
    }

    else if( res == CRhinoGet::option )
      continue;
    else if( res == CRhinoGet::nothing )
      return CRhinoCommand::nothing;
    else
      return CRhinoCommand::cancel;
  }

	return CRhinoCommand::success;
}
CRhinoCommand::result CCommandSampleMeshDir::RunCommand( const CRhinoCommandContext& context )
{
  CRhinoGetObject go;
  go.SetGeometryFilter( CRhinoObject::mesh_object | CRhinoObject::surface_object | CRhinoObject::polysrf_object | CRhinoObject::instance_reference );
  go.SetCommandPrompt( L"Select mesh, surface, or polysurface objects" );
  go.GetObjects(1,0);
  if( go.Result() != CRhinoGet::object )
    return CRhinoCommand::cancel;

  int i = 0;
  ON_SimpleArray<const CRhinoObject*> objects( go.ObjectCount() );
  for( i = 0; i < go.ObjectCount(); i++ )
    objects.Append( go.Object(i).Object() );

  ON_ClassArray<CRhinoObjRef> render_meshes;
  int count = RhinoGetRenderMeshes( objects, render_meshes, true, false );
  if( count > 0 )
  {
    CMeshDirDrawCallback callback;
    callback.m_mesh_list.Reserve( count );
    for( i = 0; i < render_meshes.Count(); i++ )
    {
      const ON_Mesh* mesh = render_meshes[i].Mesh();
      if( mesh )
        callback.m_mesh_list.AppendNew().SetMesh( mesh );
    }

    CRhinoGetOption go;
    go.SetCommandPrompt( L"Press Enter when done" );
    go.AcceptNothing();
    go.AddCommandOptionToggle( RHCMDOPTNAME(L"FaceNormals"), RHCMDOPTVALUE(L"No"), RHCMDOPTVALUE(L"Yes"), m_draw_face_normals, &m_draw_face_normals );
    go.AddCommandOptionToggle( RHCMDOPTNAME(L"VertexNormals"), RHCMDOPTVALUE(L"No"), RHCMDOPTVALUE(L"Yes"), m_draw_vertex_normals, &m_draw_vertex_normals );

    CRhinoGet::result res = CRhinoGet::nothing;
    for( ;; )
    {
      callback.m_draw_face_normals = m_draw_face_normals;
      callback.m_draw_vertex_normals = m_draw_vertex_normals;

      CRhinoView::AddDrawCallback( &callback );
      context.m_doc.Redraw( CRhinoView::regenerate_display_hint );

      res = go.GetOption();
      CRhinoView::RemoveDrawCallback( &callback );

      if( res == CRhinoGet::option )
        continue;
      break;
    }
  }

  context.m_doc.Redraw( CRhinoView::regenerate_display_hint );
  
  return CRhinoCommand::success;
}
CRhinoCommand::result CCommandSampleDrawBitmap::RunCommand( const CRhinoCommandContext& context )
{
  CRhinoCommandOptionValue enable_opts[] = { RHCMDOPTVALUE(L"Yes"), RHCMDOPTVALUE(L"No"), RHCMDOPTVALUE(L"Toggle") };
  for(;;)
  {
    bool bEnable = m_conduit.IsEnabled();
	  int current_index = bEnable ? 0 : 1;

    CRhinoGetOption go;
    go.SetCommandPrompt( L"Choose command option" );
    go.AddCommandOptionList( RHCMDOPTNAME(L"Enable"), 3, enable_opts, current_index );
    go.AcceptNothing();

    CRhinoGet::result res = go.GetOption();
    if( res == CRhinoGet::option )
    {
      const CRhinoCommandOption* option = go.Option();
      if( 0 == option )
        return CRhinoCommand::failure;

      current_index = option->m_list_option_current;
      if( 0 == current_index )
      {
        if( !bEnable )
        {
          m_conduit.Enable();
          context.m_doc.Regen();
        }
      }
      else if( 1 == current_index )
      {
        if( bEnable )
        {
          m_conduit.Disable();
          context.m_doc.Regen();
        }
      }
      else // if( 2 == current_index )
      {
        if( bEnable )
          m_conduit.Disable();
        else
          m_conduit.Enable();
        context.m_doc.Regen();
      }

      continue;
    }

    break;
  }

  return CRhinoCommand::success;
}
CRhinoCommand::result CCommandSampleTabbedDockBar::RunCommand( const CRhinoCommandContext& context )
{
  ON_UUID tabId = CSampleTabbedDockBarDialog::ID();

  if( context.IsInteractive() )
  {
    CRhinoTabbedDockBarDialog::OpenDockbarTab( tabId );
  }
  else
  {
    bool bVisible = CRhinoTabbedDockBarDialog::IsTabVisible( tabId );
 
    ON_wString str;
    str.Format( L"%s is %s. New value", LocalCommandName(), bVisible ? L"visible" : L"hidden" );
 
    CRhinoGetOption go;
    go.SetCommandPrompt( str );
    int h_option = go.AddCommandOption( RHCMDOPTNAME(L"Hide") );
    int s_option = go.AddCommandOption( RHCMDOPTNAME(L"Show") );
    int t_option = go.AddCommandOption( RHCMDOPTNAME(L"Toggle") );
    go.GetOption();
    if( go.CommandResult() != CRhinoCommand::success )
      return go.CommandResult();
 
    const CRhinoCommandOption* option = go.Option();
    if( 0 == option )
      return CRhinoCommand::failure;
 
    int option_index = option->m_option_index;

    if( h_option == option_index && bVisible )
      CRhinoTabbedDockBarDialog::ShowDockbarTab( tabId, false );
    else if( s_option == option_index && !bVisible  )
      CRhinoTabbedDockBarDialog::ShowDockbarTab( tabId, true );
    else if( t_option == option_index )
      CRhinoTabbedDockBarDialog::ShowDockbarTab( tabId, !bVisible );
  }

  return CRhinoCommand::success;
}
CRhinoCommand::result CCommandSamplePan::RunCommand( const CRhinoCommandContext& context )
{
  const CRhinoAppViewSettings& view_settings = RhinoApp().AppSettings().ViewSettings();
  double d = view_settings.m_pan_increment;
  if (view_settings.m_pan_reverse_keyboard)
    d = -d;

  CRhinoGetOption go;
  go.SetCommandPrompt(L"Select pan option");
  go.AcceptNothing();

  const int down_option_index  = go.AddCommandOption(RHCMDOPTNAME(L"Down"));
  const int left_option_index  = go.AddCommandOption(RHCMDOPTNAME(L"Left"));
  const int right_option_index = go.AddCommandOption(RHCMDOPTNAME(L"Right"));
  const int up_option_index    = go.AddCommandOption(RHCMDOPTNAME( L"Up"));
  const int in_option_index    = go.AddCommandOption(RHCMDOPTNAME(L"In"));
  const int out_option_index   = go.AddCommandOption(RHCMDOPTNAME(L"Out"));

  for(;;)
  {
    CRhinoGet::result res = go.GetOption();

    if (res != CRhinoGet::option)
      break;

    CRhinoView* view = go.View(); 
    const CRhinoCommandOption* option = go.Option();

    if (0 != view && 0 != option && 0.0 != d)
    {
      CRhinoViewport* viewport = &(view->ActiveViewport());
      if (0 != viewport && viewport->View().m_bLockedProjection)
        viewport = &(view->MainViewport());

      if (0 != viewport)
      {
        if (down_option_index == option->m_option_index)
          viewport->DownUpDolly(-d);
        else if (up_option_index == option->m_option_index)
          viewport->DownUpDolly(d);
        else if (left_option_index == option->m_option_index)
          viewport->LeftRightDolly(-d);
        else if (right_option_index == option->m_option_index)
          viewport->LeftRightDolly(d);
        else if (in_option_index == option->m_option_index)
          viewport->InOutDolly(d);
        else if (out_option_index == option->m_option_index)
          viewport->InOutDolly(-d);
      }

      view->Redraw();
      RhinoApp().SetActiveView(view);
    }
  }  
  
  return CRhinoCommand::success;
}
CRhinoCommand::result CCommandSampleMenuToggle::RunCommand( const CRhinoCommandContext& context )
{
  BOOL bVisible = SampleMenuPlugIn().IsSampleMenuVisible();
 
  ON_wString str;
  str.Format( L"%s is %s. New value", LocalCommandName(), bVisible ? L"visible" : L"hidden" );
 
  CRhinoGetOption go;
  go.SetCommandPrompt( str );
  int h_option = go.AddCommandOption( RHCMDOPTNAME(L"Hide") );
  int s_option = go.AddCommandOption( RHCMDOPTNAME(L"Show") );
  int t_option = go.AddCommandOption( RHCMDOPTNAME(L"Toggle") );
  go.GetOption();
  if( go.CommandResult() != CRhinoCommand::success )
    return go.CommandResult();
 
  const CRhinoCommandOption* option = go.Option();
  if( 0 == option )
    return CRhinoCommand::failure;
 
  int option_index = option->m_option_index;

  if( h_option == option_index && bVisible )
    SampleMenuPlugIn().HideSampleMenu();
  else if( s_option == option_index && !bVisible  )
    SampleMenuPlugIn().ShowSampleMenu();
  else if( t_option == option_index )
  {
    if( bVisible )
      SampleMenuPlugIn().HideSampleMenu();
    else
      SampleMenuPlugIn().ShowSampleMenu();
  }

  return CRhinoCommand::success;
}
CRhinoCommand::result CCommandSamplePrePostSelect::RunCommand( const CRhinoCommandContext& context )
{
  double dValue = m_dValue;
  int nValue = m_nValue;

  CRhinoGetObject go;
  go.SetGeometryFilter( CRhinoGetObject::curve_object );
  go.EnableGroupSelect( TRUE );
  go.EnableSubObjectSelect( FALSE );

  /*int d_option_index =*/ go.AddCommandOptionNumber( 
      RHCMDOPTNAME(L"Double"), &dValue, L"Double value", FALSE, 1.0, 99.9 );

  /*int n_option_index =*/ go.AddCommandOptionInteger( 
      RHCMDOPTNAME(L"Integer"), &nValue, L"Integer value", 1, 99 );

  bool bHavePreselectedObjects = false;

  for( ;; )
  {
    CRhinoGet::result res = go.GetObjects( 1, 0 );

    if( res == CRhinoGet::option )
    {
      go.EnablePreSelect( FALSE );
      go.EnableAlreadySelectedObjectSelect( true );
      go.EnableClearObjectsOnEntry( false );
      go.EnableDeselectAllBeforePostSelect( false );
      go.EnableUnselectObjectsOnExit( false );
      continue;
    }

    else if( res != CRhinoGet::object )
      return CRhinoCommand::cancel;

    if( go.ObjectsWerePreSelected() )
    {
      bHavePreselectedObjects = true;
      go.EnablePreSelect( FALSE );
      go.EnableAlreadySelectedObjectSelect( true );
      go.EnableClearObjectsOnEntry( false );
      go.EnableDeselectAllBeforePostSelect( false );
      go.EnableUnselectObjectsOnExit( false );
      continue;
    }

    break;
  }

  if( bHavePreselectedObjects )
  {
    // Normally, pre-selected objects will remain selected, when a
    // command finishes, and post-selected objects will be unselected.
    // This this way of picking, it is possible to have a combination
    // of pre-selected and post-selected. So, to make sure everything
    // "looks the same", lets unselect everything before finishing
    // the command.
    for( int i = 0; i < go.ObjectCount(); i++ )
    {
      const CRhinoObject* object = go.Object(i).Object();
      if( 0 != object )
        object->Select( false );
    }
    context.m_doc.Redraw();
  }

  int object_count = go.ObjectCount();
  m_dValue = dValue;
  m_nValue = nValue;

  RhinoApp().Print( L"Select object count = %d\n", object_count );
  RhinoApp().Print( L"Value of double = %f\n", m_dValue );
  RhinoApp().Print( L"Value of integer = %d\n", m_nValue );

  return CRhinoCommand::success;
}
CRhinoCommand::result CCommandSampleCageEdit::RunCommand( const CRhinoCommandContext& context )
{
  ON_Workspace ws;
  CRhinoCommand::result rc = CRhinoCommand::success;
 
  // Get the captive object
  CRhinoGetObject go;
  go.SetCommandPrompt( L"Select captive surface or polysurface" );
  go.SetGeometryFilter( CRhinoGetObject::surface_object | CRhinoGetObject::polysrf_object );
  go.GetObjects( 1, 1 );
  rc = go.CommandResult();
  if( CRhinoCommand::success != rc )
    return rc;
 
  const CRhinoObject* captive = go.Object(0).Object();
  if( 0 == captive )
    return CRhinoCommand::failure;
 
  // Define the control line
  ON_Line line;
  CArgsRhinoGetLine args;
  rc = RhinoGetLine( args, line );
  if( CRhinoCommand::success != rc )
    return rc;
 
  // Get the curve parameters
  int degree = 3;
  int cv_count = 4;
  for(;;)
  {
    CRhinoGetOption gl;
    gl.SetCommandPrompt( L"NURBS Parameters" );
    gl.AcceptNothing();
    int d_opt = gl.AddCommandOptionInteger( RHCMDOPTNAME(L"Degree"), &degree, L"Curve degree", 1.0, 100.0 );
    int p_opt = gl.AddCommandOptionInteger( RHCMDOPTNAME(L"PointCount"), &cv_count, L"Number of control points", 2.0, 100.0 );
    gl.GetOption();
    rc = gl.CommandResult();
    if( CRhinoCommand::success != rc )
      return rc;
 
    if( CRhinoGet::nothing == gl.Result() )
      break;
 
    if( cv_count <= degree )
    {
      if( CRhinoGet::option != gl.Result() )
        continue;
      const CRhinoCommandOption* opt = go.Option();
      if( 0 == opt )
        continue;
      if( d_opt == opt->m_option_index )
        cv_count = degree + 1;
      else 
        degree = cv_count - 1;
    }
  }
 
  // Set up morph control
  ON_MorphControl* control = new ON_MorphControl();
  control->m_varient = 1; // 1= curve
 
  // Specify the source line curve
  control->m_nurbs_curve0.Create( 3, false, 2, 2 );
  control->m_nurbs_curve0.MakeClampedUniformKnotVector();
  control->m_nurbs_curve0.SetCV( 0, line.from );
  control->m_nurbs_curve0.SetCV( 1, line.to );
 
  // Specify the destination NURBS curve
  control->m_nurbs_curve.Create( 3, false, degree + 1, cv_count );
  control->m_nurbs_curve.MakeClampedUniformKnotVector();
  double* g = ws.GetDoubleMemory( control->m_nurbs_curve.m_cv_count );
  control->m_nurbs_curve.GetGrevilleAbcissae( g );
  ON_Interval d = control->m_nurbs_curve.Domain();
  double s = 0.0;
  int i;
  for( i = 0; i < control->m_nurbs_curve.m_cv_count; i++ )
  {
    s = d.NormalizedParameterAt( g[i] );
    control->m_nurbs_curve.SetCV( i, line.PointAt(s) );
  }
 
  // Make sure domains match
  s = line.Length();
  if( s > ON_SQRT_EPSILON )
    control->m_nurbs_curve0.SetDomain( 0.0, s );
  d = control->m_nurbs_curve0.Domain();
  control->m_nurbs_curve.SetDomain( d[0], d[1] );
 
  // Create the morph control object
  CRhinoMorphControl* control_object = new CRhinoMorphControl();
  control_object->SetControl( control );
  context.m_doc.AddObject( control_object );
 
  // Set up the capture
  RhinoCaptureObject( control_object, const_cast<CRhinoObject*>(captive) );
 
  // Clean up display
  context.m_doc.UnselectAll();
 
  // Turn on the control grips
  control_object->EnableGrips( true );
  context.m_doc.Redraw( CRhinoView::mark_display_hint );
 
  return rc;
}
CRhinoCommand::result CCommandSampleConvertQuadsToTriangles::RunCommand( const CRhinoCommandContext& context )
{
  CRhinoGetObject go;
  go.SetCommandPrompt( L"Select meshes to convert" );
  go.SetGeometryFilter( CRhinoObject::mesh_object );
  if( go.GetObjects(1,0) != CRhinoGet::object )
    return CRhinoCommand::cancel;
  
  CRhinoGetOption gs;
  gs.AcceptNothing();
  gs.SetCommandPrompt( L"Delete input?" );
  gs.SetDefaultString( (m_delete_input)?L"Yes":L"No" );
  int n_index = gs.AddCommandOption( RHCMDOPTNAME(L"No") );
  int y_index = gs.AddCommandOption( RHCMDOPTNAME(L"Yes") );
  switch( gs.GetOption() )
  {
    case CRhinoGet::option:
      if( gs.Option()->m_option_index == n_index )
        m_delete_input = false;
      else
        m_delete_input = true;
      break;
    
    case CRhinoGet::string:
    case CRhinoGet::nothing:
      break;
    
    default:
      return CRhinoCommand::cancel;
  }
  
  int num_converted = 0;
  for( int i = 0; i < go.ObjectCount(); i++ )
  {
    CRhinoObjRef objref = go.Object(i);
    if( const CRhinoObject* pObject = objref.Object() )
    {
      if( const ON_Mesh* pMesh = ON_Mesh::Cast(pObject->Geometry()) )
      {
        ON_Mesh mesh(*pMesh);
        if( mesh.QuadCount() <= 0 )
          continue;
        
        if( !mesh.ConvertQuadsToTriangles() )
          continue;
        
        const CRhinoMeshObject* mesh_object = NULL;
        if( m_delete_input )
          mesh_object = context.m_doc.ReplaceObject( objref, mesh );
        else
          mesh_object = context.m_doc.AddMeshObject( mesh );
        
        if( mesh_object )
          num_converted++;
      }
    }
  }
  
  if( num_converted > 0 )
    context.m_doc.Redraw();
  
  RhinoApp().Print( L"%d meshes selected, %d meshes converted.\n", go.ObjectCount(), num_converted );
  
  return CRhinoCommand::success;
}
CRhinoCommand::result CCommandTestUVMesh::RunCommand( const CRhinoCommandContext& context )
{
  bool bDeleteInput = false;
  CRhinoGetObject go;
  go.SetCommandPrompt(L"Select untrimmed surface");
  go.AddCommandOptionInteger(RHCMDOPTNAME(L"U"), &m_U, 0, 2);
  go.AddCommandOptionInteger(RHCMDOPTNAME(L"V"), &m_V, 0, 2);
  go.AddCommandOptionToggle(RHCMDOPTNAME(L"DeleteInput"), RHCMDOPTVALUE(L"No"), RHCMDOPTVALUE(L"Yes"), bDeleteInput, &bDeleteInput);
  go.SetGeometryFilter(CRhinoGetObject::surface_object);
  go.SetGeometryAttributeFilter(CRhinoGetObject::untrimmed_surface);

  CRhinoGet::result rs = CRhinoGet::no_result;
  while (CRhinoGet::cancel != rs && CRhinoGet::nothing != rs && CRhinoGet::object != rs)
    rs = go.GetObjects(1,1);

  if (CRhinoGet::cancel == rs)
    return CRhinoCommand::cancel;
  if (0 == go.ObjectCount())
    return CRhinoCommand::failure;

  const CRhinoObject* pObj = go .Object(0).Object();
  if (0 == pObj)
    return CRhinoCommand::failure;

  const ON_BrepFace* pBrepFace = go.Object(0).Face();
  if (0 == pBrepFace)
    return CRhinoCommand::failure;

  const ON_Surface* pSurf = pBrepFace->SurfaceOf();
  if (0 == pSurf)
    return CRhinoCommand::failure;

  ON_SimpleArray<double>UArray(m_U+1);
  ON_SimpleArray<double>VArray(m_V+1);
  double UDist, VDist;
  UDist = (pSurf->Domain(0).m_t[1]-pSurf->Domain(0).m_t[0])/m_U;
  VDist = (pSurf->Domain(1).m_t[1]-pSurf->Domain(1).m_t[0])/m_V;
  int i;
  for (i=0; i <= m_U; i++)
    UArray.Append(pSurf->Domain(0).m_t[0] + i*UDist);
  for (i=0; i <= m_V; i++)
    VArray.Append(pSurf->Domain(1).m_t[0] + i*VDist);

  //If m_U or m_V are large then there can be a slight difference between
  //pSurf->Domain(0).m_t[0] + (m_U-1)*UDist and pSurf->Domain(0).m_t[1]
  //ON_MeshSurface requires it to be less than or equal to pSurf->Domain(0).m_t[1]
  //05/24/06 TimH Fix for RR21194
  double* d = UArray.Last();
  if (pSurf->Domain(0).m_t[1] < *d)
    *d = pSurf->Domain(0).m_t[1];
  d = VArray.Last();
  if (pSurf->Domain(1).m_t[1] < *d)
    *d = pSurf->Domain(1).m_t[1];

  ON_Mesh* pMeshOut = ON_MeshSurface(*pSurf, m_U+1, UArray.Array(), m_V+1, VArray.Array());

  if (0 == pMeshOut)
    return CRhinoCommand::failure;

  CRhinoMeshObject* pMeshObj = new CRhinoMeshObject(pObj->Attributes());
  if (0 == pMeshObj)
  {
    delete pMeshOut;
    return CRhinoCommand::failure;
  }
  pMeshObj->SetMesh(pMeshOut);

  if (true == bDeleteInput)
    context.m_doc.ReplaceObject(pObj, pMeshObj);
  else
    context.m_doc.AddObject(pMeshObj);

  context.m_doc.Redraw();
  return CRhinoCommand::success;
}