/**
 * Handler for the Apply logic for this dialog. Apply the specified scaling to
 * the selected mesh entities.
 *
 * @return true if any meshes are selected, false otherwise.
 */
bool
SetScaleDialog::Apply()
{
   // Before doing anything, check to see if there are some meshes selected.
   _nullVisitor->ResetVisitedCount();
   GlobalSelectionSystem().foreachSelected(*_nullVisitor);
   if (_nullVisitor->GetVisitedCount() == 0)
   {
      // Nope. Warn and bail out.
      GenericPluginUI::WarningReportDialog(DIALOG_WARNING_TITLE,
                                           DIALOG_NOMESHES_MSG);
      return false;
   }

   // See if we're going to be affecting the S and/or T texture axis.
   bool sApply = NamedToggleWidgetActive("s_apply");
   bool tApply = NamedToggleWidgetActive("t_apply");

   if (!sApply && !tApply)
   {
      // Not affecting either, so bail out.
      return true;
   }

   // OK read the remaining info from the widgets.

   MeshEntity::SliceDesignation alignCol, alignRow;
   MeshEntity::RefSliceDescriptor refRow, refCol;
   SetScaleVisitor::SliceArgs row, col;
   SetScaleVisitor::SliceArgs *rowArgs = NULL;
   SetScaleVisitor::SliceArgs *colArgs = NULL;
   if (sApply)
   {
      // S axis is affected, so read the S info.
      row.naturalScale = NamedToggleWidgetActive("s_natural");
      if (row.naturalScale)
      {
         row.scaleOrTiles = (float)atof(NamedEntryWidgetText("s_scale"));
      }
      else
      {
         row.scaleOrTiles = (float)atof(NamedEntryWidgetText("s_tiles"));
      }
      alignCol.maxSlice = NamedToggleWidgetActive("col_max_align");
      alignCol.index = atoi(NamedEntryWidgetText("col_num_align"));
      row.alignSlice = &alignCol;
      row.refSlice = NULL;
      if (NamedToggleWidgetActive("row_ref"))
      {
         // Reference row is specified, so get that info.
         refRow.designation.maxSlice = NamedToggleWidgetActive("row_max_ref");
         refRow.designation.index = atoi(NamedEntryWidgetText("row_num_ref"));
         refRow.totalLengthOnly = NamedToggleWidgetActive("row_ref_total");
         row.refSlice = &refRow;
      }
      rowArgs = &row;
   }
   if (tApply)
   {
      // T axis is affected, so read the T info.
      col.naturalScale = NamedToggleWidgetActive("t_natural");
      if (col.naturalScale)
      {
         col.scaleOrTiles = (float)atof(NamedEntryWidgetText("t_scale"));
      }
      else
      {
         col.scaleOrTiles = (float)atof(NamedEntryWidgetText("t_tiles"));
      }
      alignRow.maxSlice = NamedToggleWidgetActive("row_max_align");
      alignRow.index = atoi(NamedEntryWidgetText("row_num_align"));
      col.alignSlice = &alignRow;
      col.refSlice = NULL;
      if (NamedToggleWidgetActive("col_ref"))
      {
         // Reference column is specified, so get that info.
         refCol.designation.maxSlice = NamedToggleWidgetActive("col_max_ref");
         refCol.designation.index = atoi(NamedEntryWidgetText("col_num_ref"));
         refCol.totalLengthOnly = NamedToggleWidgetActive("col_ref_total");
         col.refSlice = &refCol;
      }
      colArgs = &col;
   }

   // Let Radiant know the name of the operation responsible for the changes
   // that are about to happen. 
   UndoableCommand undo(_triggerCommand.c_str());

   // Apply the specified scaling to every selected mesh.
   SmartPointer<SetScaleVisitor> scaleVisitor(new SetScaleVisitor(rowArgs, colArgs));
   GlobalSelectionSystem().foreachSelected(*scaleVisitor);

   // Done!
   return true;
}
/**
 * Handler for the Apply logic for this dialog. Apply the specified equations
 * to the selected mesh entities.
 *
 * @return true if any meshes are selected, false otherwise.
 */
bool
GeneralFunctionDialog::Apply()
{
   // Before doing anything, check to see if there are some meshes selected.
   _nullVisitor->ResetVisitedCount();
   GlobalSelectionSystem().foreachSelected(*_nullVisitor);
   if (_nullVisitor->GetVisitedCount() == 0)
   {
      // Nope. Warn and bail out.
      GenericPluginUI::WarningReportDialog(DIALOG_WARNING_TITLE,
                                           DIALOG_NOMESHES_MSG);
      return false;
   }

   // See if we're going to be affecting the S and/or T texture axis.
   bool sApply = NamedToggleWidgetActive("s_apply");
   bool tApply = NamedToggleWidgetActive("t_apply");

   if (!sApply && !tApply)
   {
      // Not affecting either, so bail out.
      return true;
   }

   // OK read the remaining info from the widgets.

   MeshEntity::GeneralFunctionFactors s, t;
   MeshEntity::GeneralFunctionFactors *sFactors = NULL;
   MeshEntity::GeneralFunctionFactors *tFactors = NULL;
   if (sApply)
   {
      // S axis is affected, so read the S factors.
      s.oldValue = (float)atof(NamedEntryWidgetText("s_oldval"));
      s.rowDistance = (float)atof(NamedEntryWidgetText("s_rowdist"));
      s.colDistance = (float)atof(NamedEntryWidgetText("s_coldist"));
      s.rowNumber = (float)atof(NamedEntryWidgetText("s_rownum"));
      s.colNumber = (float)atof(NamedEntryWidgetText("s_colnum"));
      s.constant = (float)atof(NamedEntryWidgetText("s_constant"));
      sFactors = &s;
   }
   if (tApply)
   {
      // T axis is affected, so read the T factors.
      t.oldValue = (float)atof(NamedEntryWidgetText("t_oldval"));
      t.rowDistance = (float)atof(NamedEntryWidgetText("t_rowdist"));
      t.colDistance = (float)atof(NamedEntryWidgetText("t_coldist"));
      t.rowNumber = (float)atof(NamedEntryWidgetText("t_rownum"));
      t.colNumber = (float)atof(NamedEntryWidgetText("t_colnum"));
      t.constant = (float)atof(NamedEntryWidgetText("t_constant"));
      tFactors = &t;
   }
   MeshEntity::SliceDesignation alignRow, alignCol;
   alignRow.maxSlice = NamedToggleWidgetActive("row_max_align");
   alignRow.index = atoi(NamedEntryWidgetText("row_num_align"));
   alignCol.maxSlice = NamedToggleWidgetActive("col_max_align");
   alignCol.index = atoi(NamedEntryWidgetText("col_num_align"));
   MeshEntity::RefSliceDescriptor row, col;
   MeshEntity::RefSliceDescriptor *refRow = NULL;
   MeshEntity::RefSliceDescriptor *refCol = NULL;
   if (NamedToggleWidgetActive("row_ref"))
   {
      // Reference row is specified, so get that info.
      row.designation.maxSlice = NamedToggleWidgetActive("row_max_ref");
      row.designation.index = atoi(NamedEntryWidgetText("row_num_ref"));
      row.totalLengthOnly = NamedToggleWidgetActive("row_ref_total");
      refRow = &row;
   }
   if (NamedToggleWidgetActive("col_ref"))
   {
      // Reference column is specified, so get that info.
      col.designation.maxSlice = NamedToggleWidgetActive("col_max_ref");
      col.designation.index = atoi(NamedEntryWidgetText("col_num_ref"));
      col.totalLengthOnly = NamedToggleWidgetActive("col_ref_total");
      refCol = &col;
   }
   bool surfaceValues = NamedToggleWidgetActive("surface");

   // Let Radiant know the name of the operation responsible for the changes
   // that are about to happen.
   UndoableCommand undo(_triggerCommand.c_str());

   // Apply the specified equation to every selected mesh.
   SmartPointer<GeneralFunctionVisitor> funcVisitor(
      new GeneralFunctionVisitor(sFactors, tFactors,
                                 &alignRow, &alignCol, refRow, refCol,
                                 surfaceValues));
   GlobalSelectionSystem().foreachSelected(*funcVisitor);

   // Done!
   return true;
}
/**
 * Handler for the Apply logic for this dialog. Interrogate the selected mesh
 * entities.
 *
 * @return false if no meshes are selected, false if multiple meshes are
 *         selected along with the transfer option, true otherwise.
 */
bool
GetInfoDialog::Apply()
{
   // Before doing anything, check to see if there are some meshes selected.
   _nullVisitor->ResetVisitedCount();
   GlobalSelectionSystem().foreachSelected(*_nullVisitor);
   if (_nullVisitor->GetVisitedCount() == 0)
   {
      // Nope. Warn and bail out.
      GenericPluginUI::WarningReportDialog(DIALOG_WARNING_TITLE,
                                           DIALOG_NOMESHES_MSG);
      return false;
   }

   // If the option to transfer info to Set S/T Scale is active, then only one
   // mesh may be selected.
   bool transfer = NamedToggleWidgetActive("transfer");
   if (transfer && _nullVisitor->GetVisitedCount() != 1)
   {
      // Multiple selected. Warn and bail out.
      GenericPluginUI::ErrorReportDialog(DIALOG_ERROR_TITLE,
                                         DIALOG_MULTIMESHES_ERROR);
      return false;
   }

   // OK read the remaining info from the widgets.

   bool sApply = NamedToggleWidgetActive("s_apply");
   bool tApply = NamedToggleWidgetActive("t_apply");

   int row, col;
   int *refRow = NULL;
   int *refCol = NULL;
   MeshEntity::TexInfoCallback *rowTexInfoCallback = NULL;
   MeshEntity::TexInfoCallback *colTexInfoCallback = NULL;
   if (sApply)
   {
      // Reference row is specified, so get that info.
      row = atoi(NamedEntryWidgetText("s_ref_row"));
      refRow = &row;
      if (transfer)
      {
         // If transferring to Set S/T Scale, get that callback.
         rowTexInfoCallback = &_rowTexInfoCallback;
      }
   }
   if (tApply)
   {
      // Reference column is specified, so get that info.
      col = atoi(NamedEntryWidgetText("t_ref_col"));
      refCol = &col;
      if (transfer)
      {
         // If transferring to Set S/T Scale, get that callback.
         colTexInfoCallback = &_colTexInfoCallback;
      }
   }

   // We don't need to instantiate an UndoableCommand since we won't be making
   // any changes.

   // Interrogate every selected mesh.
   SmartPointer<GetInfoVisitor> infoVisitor(
      new GetInfoVisitor(refRow, refCol, rowTexInfoCallback, colTexInfoCallback));
   GlobalSelectionSystem().foreachSelected(*infoVisitor);

   // If we populated something in the Set S/T Scale dialog, give that dialog a
   // courtesy raise.
   if (transfer)
   {
      _setScaleDialog->Raise();
   }

   // Done!
   return true;
}