Beispiel #1
0
void SelectionPlugin::onMouseButtonRelease( const MouseButtonEvent& event )
{
	if( event.button != MouseButton::Left )
		return;

	SceneDocument* sceneDocument = (SceneDocument*) editor->getDocument();
	sceneDocument->getRenderWindow()->setCursorCapture(false);

	editor->getDocument()->getWindow()->flagRedraw();

	SelectionOperation* selection = nullptr;

	if(selections->dragRectangle)
		selection = processDragSelection(event);
	else
		selection = processSelection(event);

	if( !selection ) return;

	const SelectionCollection& selected = selections->getSelections();

	// Prevent duplication of selection events.
	if( selected.isSame(selection->selections) ) 
	{
		LogDebug("Ignoring duplicated selection");
		Deallocate(selection);
		return;
	}

	selection->redo();

	UndoManager* undoManager = sceneDocument->getUndoManager();
	undoManager->registerOperation(selection);
}
void GuiRoadEditorCtrl::submitUndo( const UTF8 *name )
{
   // Grab the mission editor undo manager.
   UndoManager *undoMan = NULL;
   if ( !Sim::findObject( "EUndoManager", undoMan ) )
   {
      Con::errorf( "GuiRoadEditorCtrl::submitUndo() - EUndoManager not found!" );
      return;           
   }

   // Setup the action.
   GuiRoadEditorUndoAction *action = new GuiRoadEditorUndoAction( name );

   action->mObjId = mSelRoad->getId();
   action->mBreakAngle = mSelRoad->mBreakAngle;
   action->mMaterialName = mSelRoad->mMaterialName;
   action->mSegmentsPerBatch = mSelRoad->mSegmentsPerBatch;   
   action->mTextureLength = mSelRoad->mTextureLength;
   action->mRoadEditor = this;

   for( U32 i = 0; i < mSelRoad->mNodes.size(); i++ )
   {
      action->mNodes.push_back( mSelRoad->mNodes[i] );      
   }
      
   undoMan->addAction( action );
}
void GuiDecalEditorCtrl::deleteSelectedDecal()
{
   if ( !mSELDecal )
      return;
	
	// Grab the mission editor undo manager.
	UndoManager *undoMan = NULL;
	if ( !Sim::findObject( "EUndoManager", undoMan ) )
	{
		Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
		return;           
	}

	// Create the UndoAction.
	DIDeleteUndoAction *action = new DIDeleteUndoAction("Delete Decal");
	action->deleteDecal( *mSELDecal );
	
	action->mEditor = this;
	// Submit it.               
	undoMan->addAction( action );
	
	if ( isMethod( "onDeleteInstance" ) )
	{
		char buffer[512];
		dSprintf(buffer, 512, "%i", mSELDecal->mId);
		Con::executef( this, "onDeleteInstance", String(buffer).c_str(), mSELDecal->mDataBlock->lookupName.c_str() );
	}

   gDecalManager->removeDecal( mSELDecal );
   mSELDecal = NULL;
}
Beispiel #4
0
bool Object::destroyRenderer(qlib::uid_t uid)
{
  // get renderer ptr/check consistency
  rendtab_t::iterator i = m_rendtab.find(uid);
  if (i==m_rendtab.end())
    return false;

  RendererPtr pRend = i->second;
  ScenePtr pScene = getScene();

  if (pScene.isnull() || pRend.isnull()) {
    LOG_DPRINTLN("Object::destroyRenderer> fatal error pScene or pRend is NULL!");
    return false;
  }

  // detach renderer from the view-related resources (DL, VBO, etc)
  pRend->unloading();

  // Detach the parent scene from the renderer event source
  pRend->removeListener(pScene.get());

  // Fire the SCE_REND_REMOVING Event, before removing the renderer
  {
    MB_DPRINTLN("Object> Firing SCE_REND_REMOVING event...");
    SceneEvent ev;
    ev.setType(SceneEvent::SCE_REND_REMOVING);
    ev.setSource(getSceneID());
    ev.setTarget(pRend->getUID());
    pScene->fireSceneEvent(ev);
  }

  // remove the rend from the scene's cache list
  pScene->removeRendCache(pRend);

  // 2012/9/30
  // Detach the rend from obj HERE is very important!!
  // (This call remove the rend from object's event listener list.
  //  Otherwise, deleted ptr will remain in the listener list, and thus cause crash!!)
  qlib::uid_t objid = pRend->detachObj();
  // MB_ASSERT(objid==this->m_uid);
  
  // 2012/9/30
  // Setting scene ID to null will cause removing pRend from the scene's listener list
  // (Without this, deleted ptr will remain in scene's listener list, after clearing the UNDO data!!)
  pRend->setSceneID(qlib::invalid_uid);

  // Remove from the renderer table
  m_rendtab.erase(i);

  // Record undo/redo info
  UndoManager *pUM = pScene->getUndoMgr();
  if (pUM->isOK()) {
    ObjLoadEditInfo *pPEI = MB_NEW ObjLoadEditInfo;
    pPEI->setupRendDestroy(getUID(), pRend);
    pUM->addEditInfo(pPEI);
  }

  return true;
}
bool UndoTransaction::commit()
{
	if (!m_data)
		return false;
	TransactionData* data = static_cast<TransactionData*>(m_data.data());
	UndoManager* UM = data->UM;
	int stackLevel = data->stackLevel;

	if (!UM->undoEnabled_)
	{
		cancel();
		return false;
	}
	
	UndoObject *tmpu = UM->transactions_.at(stackLevel)->transactionObject;
	TransactionState *tmps = UM->transactions_.at(stackLevel)->transactionState;
	
	switch (m_data->m_status)
	{
		case Transaction::STATE_OPEN:
//			qDebug() << "UndoManager::commitTransaction" << data << data->transactionObject->getUName() << data->transactionState->getName() << stackLevel;
			m_data->m_status = Transaction::STATE_COMMITTED;

			// brutal for now:
			assert (stackLevel + 1 == signed(UM->transactions_.size()));
			
			if (stackLevel < signed(UM->transactions_.size()))
			{
				UM->transactions_.erase(UM->transactions_.begin() + stackLevel);
			}
				
			if (tmps->sizet() > 0) // are there any actions inside the committed transaction
			{
				if (tmps->getName().isEmpty())
					tmps->useActionName();
				UM->action(tmpu, tmps);
			} // if not just delete objects
			else
			{
				delete tmpu;
				tmpu = 0;
				delete tmps;
				tmps = 0;
			}
			return true;
			break;
		case STATE_WILLFAIL:
			return cancel();
			break;
		default:
//			qDebug() << "UndoManager::commitTransaction ** already closed **";
			// nothing
			break;
	}
	return false;
}
void GuiDecalEditorCtrl::retargetDecalDatablock( String dbFrom, String dbTo )
{
	DecalData * ptrFrom = dynamic_cast<DecalData*> ( Sim::findObject(dbFrom.c_str()) );
	DecalData * ptrTo = dynamic_cast<DecalData*> ( Sim::findObject(dbTo.c_str()) );
	
	if( !ptrFrom || !ptrTo )
		return;
	
	// Grab the mission editor undo manager.
	UndoManager *undoMan = NULL;
	if ( !Sim::findObject( "EUndoManager", undoMan ) )
	{
		Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
		return;           
	}

	// Create the UndoAction.
	DBRetargetUndoAction *action = new DBRetargetUndoAction("Retarget Decal Datablock");
	action->mEditor = this;
	action->mDBFromId = ptrFrom->getId();
	action->mDBToId = ptrTo->getId();

	Vector<DecalInstance*> mDecalQueue;
	Vector<DecalInstance *>::iterator iter;
	mDecalQueue.clear();
	const Vector<DecalSphere*> &grid = gDecalManager->getDecalDataFile()->getSphereList();
	for ( U32 i = 0; i < grid.size(); i++ )
	{
		const DecalSphere *decalSphere = grid[i];
		mDecalQueue.merge( decalSphere->mItems );
	}

	for ( iter = mDecalQueue.begin();iter != mDecalQueue.end();iter++ )
	{	
		if( !(*iter) )
			continue;

		if( (*iter)->mDataBlock->lookupName.compare( dbFrom ) == 0 )
		{
			if( (*iter)->mId != -1 )
			{
				action->retargetDecal((*iter));	
				(*iter)->mDataBlock = ptrTo;
				forceRedraw((*iter));
			}
		}
	}

	undoMan->addAction( action );
}
Beispiel #7
0
void ForestTool::_submitUndo( UndoAction *action )
{
   AssertFatal( action, "ForestTool::_submitUndo() - No undo action!" );

   // Grab the mission editor undo manager.
   UndoManager *undoMan = NULL;
   if ( !Sim::findObject( "EUndoManager", undoMan ) )
   {
      Con::errorf( "ForestTool::_submitUndo() - EUndoManager not found!" );
      return;     
   }

   undoMan->addAction( action );

   mEditor->updateCollision();
}
// ApplyChain returns true on success, false otherwise.
// Any error reporting to the user has already been done.
bool BatchCommands::ApplyChain(const wxString & filename)
{
   mFileName = filename;
   unsigned int i;
   bool res = true;

   mAbort = false;

   for (i = 0; i < mCommandChain.GetCount(); i++) {
      if (!ApplyCommandInBatchMode(mCommandChain[i], mParamsChain[i]) || mAbort) {
         res = false;
         break;
      }
   }

   mFileName.Empty();
   AudacityProject *proj = GetActiveProject();

   if (!res)
   {
      if(proj) {
         // Chain failed or was cancelled; revert to the previous state
         UndoManager *um = proj->GetUndoManager();
         proj->SetStateTo(um->GetCurrentState());
      }
      return false;
   }

   // Chain was successfully applied; save the new project state
   wxString longDesc, shortDesc;
   wxString name = gPrefs->Read(wxT("/Batch/ActiveChain"), wxEmptyString);
   if (name.IsEmpty())
   {
      longDesc = wxT("Applied batch chain");
      shortDesc = wxT("Apply chain");
   }
   else
   {
      longDesc = wxString::Format(wxT("Applied batch chain '%s'"), name.c_str());
      shortDesc = wxString::Format(wxT("Apply '%s'"), name.c_str());
   }

   if (!proj)
      return false;
   proj->PushState(longDesc, shortDesc);
   return true;
}
void GuiRiverEditorCtrl::deleteSelectedRiver( bool undoAble )
{
   AssertFatal( mSelRiver != NULL, "GuiRiverEditorCtrl::deleteSelectedRiver() - No River IS selected" );

   // Not undoAble? Just delete it.
   if ( !undoAble )
   {
      mSelRiver->deleteObject();
      mIsDirty = true;
      Con::executef( this, "onRiverSelected" );
      mSelNode = -1;

      return;
   }

   // Grab the mission editor undo manager.
   UndoManager *undoMan = NULL;
   if ( !Sim::findObject( "EUndoManager", undoMan ) )
   {
      // Couldn't find it? Well just delete the River.
      Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown() - EUndoManager not found!" );    
      return;
   }
   else
   {
      // Create the UndoAction.
      MEDeleteUndoAction *action = new MEDeleteUndoAction("Deleted River");
      action->deleteObject( mSelRiver );
      mIsDirty = true;

      // Submit it.               
      undoMan->addAction( action );
   }

   // ScriptCallback with 'NULL' parameter for no River currently selected.
   Con::executef( this, "onRiverSelected" );

   // Clear the SelectedNode (it has been deleted along with the River).  
	setSelectedNode( -1 );
   mSelNode = -1;

   // SelectedRiver is a SimObjectPtr and will be NULL automatically.
}
void ForestEditorCtrl::deleteMeshSafe( ForestItemData *mesh )
{
   UndoManager *undoMan = NULL;
   if ( !Sim::findObject( "EUndoManager", undoMan ) )
   {
      Con::errorf( "ForestEditorCtrl::deleteMeshSafe() - EUndoManager not found." );
      return;     
   }

   // CompoundUndoAction which will delete the ForestItemData, ForestItem(s), and ForestBrushElement(s).
   CompoundUndoAction *compoundAction = new CompoundUndoAction( "Delete Forest Mesh" );
    
   // Find ForestItem(s) referencing this datablock and add their deletion
   // to the undo action.
   if ( mForest )
   {      
      Vector<ForestItem> foundItems;
      mForest->getData()->getItems( mesh, &foundItems );

      ForestDeleteUndoAction *itemAction = new ForestDeleteUndoAction( mForest->getData(), this );
      itemAction->removeItem( foundItems );
      compoundAction->addAction( itemAction );
   }

   // Find ForestBrushElement(s) referencing this datablock.
   SimGroup *brushGroup = ForestBrush::getGroup();
   sKey = mesh;
   Vector<SimObject*> foundElements;   
   brushGroup->findObjectByCallback( &findMeshReferences, foundElements );   

   // Add UndoAction to delete the ForestBrushElement(s) and the ForestItemData.
   MEDeleteUndoAction *elementAction = new MEDeleteUndoAction();
   elementAction->deleteObject( foundElements );
   elementAction->deleteObject( mesh );
   
   // Add compound action to the UndoManager. Done.
   undoMan->addAction( compoundAction );

   updateCollision();
}
Beispiel #11
0
void EffectLayer::MoveAllSelectedEffects(int deltaMS, UndoManager& undo_mgr)
{
    std::unique_lock<std::recursive_mutex> locker(lock);
    for(int i=0; i<mEffects.size();i++)
    {
        if(mEffects[i]->GetSelected() == EFFECT_LT_SELECTED && mEffects[i]->GetTagged())
        {
            if( undo_mgr.GetCaptureUndo() ) {
                undo_mgr.CaptureEffectToBeMoved( mParentElement->GetName(), mIndex, mEffects[i]->GetID(),
                                                 mEffects[i]->GetStartTimeMS(), mEffects[i]->GetEndTimeMS() );
            }
            mEffects[i]->SetStartTimeMS( mEffects[i]->GetStartTimeMS() + deltaMS);
        }
        else if(mEffects[i]->GetSelected() == EFFECT_RT_SELECTED && mEffects[i]->GetTagged())
        {
            if( undo_mgr.GetCaptureUndo() ) {
                undo_mgr.CaptureEffectToBeMoved( mParentElement->GetName(), mIndex, mEffects[i]->GetID(),
                                                 mEffects[i]->GetStartTimeMS(), mEffects[i]->GetEndTimeMS() );
            }
            mEffects[i]->SetEndTimeMS( mEffects[i]->GetEndTimeMS() + deltaMS);
        }
        else if(mEffects[i]->GetSelected() == EFFECT_SELECTED && mEffects[i]->GetTagged())
        {
            if( undo_mgr.GetCaptureUndo() ) {
                undo_mgr.CaptureEffectToBeMoved( mParentElement->GetName(), mIndex, mEffects[i]->GetID(),
                                                 mEffects[i]->GetStartTimeMS(), mEffects[i]->GetEndTimeMS() );
            }
            mEffects[i]->SetStartTimeMS( mEffects[i]->GetStartTimeMS() + deltaMS);
            mEffects[i]->SetEndTimeMS( mEffects[i]->GetEndTimeMS() + deltaMS);
        }
        mEffects[i]->SetTagged(false);
    }
}
Beispiel #12
0
bool Object::registerRendererImpl(RendererPtr rrend)
{
  bool res = m_rendtab.insert(rendtab_t::value_type(rrend->getUID(), rrend)).second;
  if (!res)
    return false;

  rrend->setSceneID(getSceneID());
  rrend->attachObj(this->m_uid);

  ScenePtr pScene = getScene();
  if (pScene.isnull())
    return true;
  
  // add the new rend to the scene's cache list
  pScene->addRendCache(rrend);
  
  // The scene observes events from the new renderer
  //rrend->addPropListener(pScene.get());
  rrend->addListener(pScene.get());

  // Fire the SCE_REND_ADDED Event
  {
    MB_DPRINTLN("Object> Firing SCE_REND_ADDED event...");
    SceneEvent ev;
    ev.setType(SceneEvent::SCE_REND_ADDED);
    ev.setSource(getSceneID());
    ev.setTarget(rrend->getUID());
    pScene->fireSceneEvent(ev);
  }
  
  // Record undo/redo info
  UndoManager *pUM = pScene->getUndoMgr();
  if (pUM->isOK()) {
    ObjLoadEditInfo *pPEI = MB_NEW ObjLoadEditInfo;
    pPEI->setupRendCreate(getUID(), rrend);
    pUM->addEditInfo(pPEI);
  }

  return true;
}
Beispiel #13
0
void GuiRoadEditorCtrl::deleteSelectedRoad( bool undoAble )
{
   AssertFatal( mSelRoad != NULL, "GuiRoadEditorCtrl::deleteSelectedRoad() - No road IS selected" );

   // Not undo-able? Just delete it.
   if ( !undoAble )
   {
      DecalRoad *lastRoad = mSelRoad;

      setSelectedRoad(NULL);

      lastRoad->deleteObject();
      mIsDirty = true;

      return;
   }

   // Grab the mission editor undo manager.
   UndoManager *undoMan = NULL;
   if ( !Sim::findObject( "EUndoManager", undoMan ) )
   {
      // Couldn't find it? Well just delete the road.
      Con::errorf( "GuiRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );    
      return;
   }
   else
   {
      DecalRoad *lastRoad = mSelRoad;
      setSelectedRoad(NULL);

      // Create the UndoAction.
      MEDeleteUndoAction *action = new MEDeleteUndoAction("Deleted Road");
      action->deleteObject( lastRoad );
      mIsDirty = true;

      // Submit it.               
      undoMan->addAction( action );
   }
}
void SceneStructureWindow::SetShownScene(const ScenePtr &newScene)
{
    if (!scene.expired() && newScene == scene.lock())
        return;

    ScenePtr previous = ShownScene();
    if (previous)
    {
        disconnect(previous.get());
        Clear();
    }

    scene = newScene;
    treeWidget->SetScene(newScene);

    if (newScene)
    {
        // Now that treeWidget has scene, it also has UndoManager.
        UndoManager *undoMgr = treeWidget->GetUndoManager();
        undoButton_->setMenu(undoMgr->UndoMenu());
        redoButton_->setMenu(undoMgr->RedoMenu());
        connect(undoMgr, SIGNAL(CanUndoChanged(bool)), this, SLOT(SetUndoEnabled(bool)), Qt::UniqueConnection);
        connect(undoMgr, SIGNAL(CanRedoChanged(bool)), this, SLOT(SetRedoEnabled(bool)), Qt::UniqueConnection);
        connect(undoButton_, SIGNAL(clicked()), undoMgr, SLOT(Undo()), Qt::UniqueConnection);
        connect(redoButton_, SIGNAL(clicked()), undoMgr, SLOT(Redo()), Qt::UniqueConnection);

        Scene* s = ShownScene().get();
        connect(s, SIGNAL(EntityAcked(Entity *, entity_id_t)), SLOT(AckEntity(Entity *, entity_id_t)));
        connect(s, SIGNAL(EntityCreated(Entity *, AttributeChange::Type)), SLOT(AddEntity(Entity *)));
        connect(s, SIGNAL(EntityTemporaryStateToggled(Entity *, AttributeChange::Type)), SLOT(UpdateEntityTemporaryState(Entity *)));
        connect(s, SIGNAL(EntityRemoved(Entity *, AttributeChange::Type)), SLOT(RemoveEntity(Entity *)));
        connect(s, SIGNAL(ComponentAdded(Entity *, IComponent *, AttributeChange::Type)), SLOT(AddComponent(Entity *, IComponent *)));
        connect(s, SIGNAL(ComponentRemoved(Entity *, IComponent *, AttributeChange::Type)), SLOT(RemoveComponent(Entity *, IComponent *)));
        connect(s, SIGNAL(SceneCleared(Scene*)), SLOT(Clear()));

        Populate();
    }
}
Beispiel #15
0
void EffectLayer::DeleteSelectedEffects(UndoManager& undo_mgr)
{
    std::unique_lock<std::recursive_mutex> locker(lock);
    for (std::vector<Effect*>::iterator it = mEffects.begin(); it != mEffects.end(); it++) {
        if ((*it)->GetSelected() != EFFECT_NOT_SELECTED) {
            IncrementChangeCount((*it)->GetStartTimeMS(), (*it)->GetEndTimeMS());
            undo_mgr.CaptureEffectToBeDeleted( mParentElement->GetName(), mIndex, (*it)->GetEffectName(),
                                               (*it)->GetSettingsAsString(), (*it)->GetPaletteAsString(),
                                               (*it)->GetStartTimeMS(), (*it)->GetEndTimeMS(),
                                               (*it)->GetSelected(), (*it)->GetProtected() );
        }
    }
    mEffects.erase(std::remove_if(mEffects.begin(), mEffects.end(),ShouldDeleteSelected),mEffects.end());
}
void GuiDecalEditorCtrl::deleteDecalDatablock( String lookupName )
{
	DecalData * datablock = dynamic_cast<DecalData*> ( Sim::findObject(lookupName.c_str()) );
	if( !datablock )
		return;

	// Grab the mission editor undo manager.
	UndoManager *undoMan = NULL;
	if ( !Sim::findObject( "EUndoManager", undoMan ) )
	{
		Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
		return;           
	}

	// Create the UndoAction.
	DBDeleteUndoAction *action = new DBDeleteUndoAction("Delete Decal Datablock");
	action->mEditor = this;
	action->mDatablockId = datablock->getId();
	
	Vector<DecalInstance*> mDecalQueue;
	Vector<DecalInstance *>::iterator iter;
	mDecalQueue.clear();
	const Vector<DecalSphere*> &grid = gDecalManager->getDecalDataFile()->getSphereList();

	for ( U32 i = 0; i < grid.size(); i++ )
	{
		const DecalSphere *decalSphere = grid[i];
		mDecalQueue.merge( decalSphere->mItems );
	}

	for ( iter = mDecalQueue.begin();iter != mDecalQueue.end();iter++ )
	{	
		if( !(*iter) )
			continue;

		if( (*iter)->mDataBlock->lookupName.compare( lookupName ) == 0 )
		{
			if( (*iter)->mId != -1 )
			{
				//make sure to call onDeleteInstance as well
				if ( isMethod( "onDeleteInstance" ) )
				{
					char buffer[512];
					dSprintf(buffer, 512, "%i", (*iter)->mId);
					Con::executef( this, "onDeleteInstance", String(buffer).c_str(), (*iter)->mDataBlock->lookupName.c_str() );
				}
				
				action->deleteDecal( *(*iter) );
				
				if( mSELDecal == (*iter) )
					mSELDecal = NULL;

				if( mHLDecal == (*iter) )
					mHLDecal = NULL;
			}
			gDecalManager->removeDecal( (*iter) );
		}
	}
	
	undoMan->addAction( action );

	mCurrentDecalData = NULL;
}
Beispiel #17
0
void BatchProcessDialog::OnApplyToFiles(wxCommandEvent &event)
{
    long item = mChains->GetNextItem(-1,
                                     wxLIST_NEXT_ALL,
                                     wxLIST_STATE_SELECTED);
    if (item == -1) {
        wxMessageBox(_("No chain selected"));
        return;
    }

    wxString name = mChains->GetItemText(item);
    gPrefs->Write(wxT("/Batch/ActiveChain"), name);

    AudacityProject *project = GetActiveProject();
    if (!project->GetIsEmpty()) {
        wxMessageBox(_("Please save and close the current project first."));
        return;
    }

    wxString path = gPrefs->Read(wxT("/DefaultOpenPath"), ::wxGetCwd());
    wxString prompt =  project->GetCleanSpeechMode() ?
                       _("Select vocal file(s) for batch CleanSpeech Chain...") :
                       _("Select file(s) for batch processing...");
    wxString fileSelector = project->GetCleanSpeechMode() ?
                            _("Vocal files (*.wav;*.mp3)|*.wav;*.mp3|WAV files (*.wav)|*.wav|MP3 files (*.mp3)|*.mp3") :
                            _("All files (*.*)|*.*|WAV files (*.wav)|*.wav|AIFF files (*.aif)|*.aif|AU files (*.au)|*.au|MP3 files (*.mp3)|*.mp3|Ogg Vorbis files (*.ogg)|*.ogg|FLAC files (*.flac)|*.flac"
                             );

    FileDialog dlog(this, prompt,
                    path, wxT(""), fileSelector,
                    wxFD_OPEN | wxFD_MULTIPLE | wxRESIZE_BORDER);

    if (dlog.ShowModal() != wxID_OK) {
        return;
    }

    wxArrayString files;
    dlog.GetPaths(files);

    files.Sort();

    wxDialog d(this, wxID_ANY, GetTitle());
    ShuttleGui S(&d, eIsCreating);

    S.StartVerticalLay(false);
    {
        S.StartStatic(_("Applying..."), 1);
        {
            wxImageList *imageList = new wxImageList(9, 16);
            imageList->Add(wxIcon(empty_9x16_xpm));
            imageList->Add(wxIcon(arrow_xpm));

            S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
                       wxLC_SINGLE_SEL);
            mList = S.AddListControlReportMode();
            mList->AssignImageList(imageList, wxIMAGE_LIST_SMALL);
            mList->InsertColumn(0, _("File"), wxLIST_FORMAT_LEFT);
        }
        S.EndStatic();

        S.StartHorizontalLay(wxCENTER, false);
        {
            S.Id(wxID_CANCEL).AddButton(_("&Cancel"));
        }
        S.EndHorizontalLay();
    }
    S.EndVerticalLay();

    int i;
    for (i = 0; i < (int)files.GetCount(); i++ ) {
        mList->InsertItem(i, files[i], i == 0);
    }

    // Set the column size for the files list.
    mList->SetColumnWidth(0, wxLIST_AUTOSIZE);

    int width = mList->GetColumnWidth(0);
    wxSize sz = mList->GetClientSize();
    if (width > sz.GetWidth() && width < 500) {
        sz.SetWidth(width);
        mList->SetInitialSize(sz);
    }

    d.Layout();
    d.Fit();
    d.SetSizeHints(d.GetSize());
    d.CenterOnScreen();
    d.Move(-1, 0);
    d.Show();
    Hide();

    mBatchCommands.ReadChain(name);
    for (i = 0; i < (int)files.GetCount(); i++) {
        wxWindowDisabler wd(&d);
        if (i > 0) {
            //Clear the arrow in previous item.
            mList->SetItemImage(i - 1, 0, 0);
        }
        mList->SetItemImage(i, 1, 1);
        mList->EnsureVisible(i);

        project->OnRemoveTracks();
        project->Import(files[i]);
        project->OnSelectAll();
        if (!mBatchCommands.ApplyChain()) {
            break;
        }

        if (!d.IsShown() || mAbort) {
            break;
        }
        UndoManager *um = project->GetUndoManager();
        um->ClearStates();
    }
    project->OnRemoveTracks();
}
void GuiDecalEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event)
{ 
   if ( !mSELDecal )
      return;

   // Doing a drag copy of the decal?
   if ( event.modifier & SI_SHIFT && !mPerformedDragCopy )
   {
      mPerformedDragCopy = true;

		DecalInstance *newDecal = gDecalManager->addDecal(    mSELDecal->mPosition, 
                                                            mSELDecal->mNormal, 
                                                            0.0f, 
                                                            mSELDecal->mDataBlock, 
                                                            1.0f, 
                                                            -1, 
                                                            PermanentDecal | SaveDecal );

      newDecal->mTangent = mSELDecal->mTangent;
      newDecal->mSize = mSELDecal->mSize;
      newDecal->mTextureRectIdx = mSELDecal->mTextureRectIdx;

      // TODO: This is crazy... we should move this sort of tracking
      // inside of the decal manager... IdDecal flag maybe or just a
      // byproduct of PermanentDecal?
      //
		newDecal->mId = gDecalManager->mDecalInstanceVec.size();
		gDecalManager->mDecalInstanceVec.push_back( newDecal );

		selectDecal( newDecal );
			
		// Grab the mission editor undo manager.
		UndoManager *undoMan = NULL;
		if ( Sim::findObject( "EUndoManager", undoMan ) )
		{
			// Create the UndoAction.
			DICreateUndoAction *action = new DICreateUndoAction("Create Decal");
			action->addDecal( *mSELDecal );
			action->mEditor = this;
			undoMan->addAction( action );

			if ( isMethod( "onCreateInstance" ) )
			{
				char buffer[512];
				dSprintf( buffer, 512, "%i", mSELDecal->mId );
				Con::executef( this, "onCreateInstance", buffer, mSELDecal->mDataBlock->lookupName.c_str());
			}
		}
   }

   // Update the Gizmo.
   if (mGizmo->getSelection() != Gizmo::None)
   {
      mGizmo->on3DMouseDragged( event );

      // Pull out the Gizmo transform
      // and position.
      const MatrixF &gizmoMat = mGizmo->getTransform();
      const Point3F &gizmoPos = gizmoMat.getPosition();
      
      // Get the new projection vector.
      VectorF upVec, rightVec;
      gizmoMat.getColumn( 0, &rightVec );
      gizmoMat.getColumn( 2, &upVec );

      const Point3F &scale = mGizmo->getScale();

      // Assign the appropriate changed value back to the decal.
      if ( mGizmo->getMode() == ScaleMode )
      {
         // Save old size.
         const F32 oldSize = mSELDecal->mSize;

         // Set new size.
         mSELDecal->mSize = ( scale.x + scale.y ) * 0.5f;

         // See if the decal properly clips/projects at this size.  If not,
         // stick to the old size.
         mSELEdgeVerts.clear();
         if ( !gDecalManager->clipDecal( mSELDecal, &mSELEdgeVerts ) )
            mSELDecal->mSize = oldSize;
      }
      else if ( mGizmo->getMode() == MoveMode )
         mSELDecal->mPosition = gizmoPos;
      else if ( mGizmo->getMode() == RotateMode )
      {
         mSELDecal->mNormal = upVec;
         mSELDecal->mTangent = rightVec;
      }

      gDecalManager->notifyDecalModified( mSELDecal );

	   Con::executef( this, "syncNodeDetails" );
   }
}
void GuiDecalEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
{
   mPerformedDragCopy = false;

   if ( !isFirstResponder() )
      setFirstResponder();
	
	bool dblClick = ( event.mouseClickCount > 1 );

	// Gather selected decal information 
   RayInfo ri;
   bool hit = getRayInfo( event, &ri );

   Point3F start = event.pos;
   Point3F end = start + event.vec * 3000.0f; // use visible distance here??

   DecalInstance *pDecal = gDecalManager->raycast( start, end );
	
	if( mMode.compare("AddDecalMode") != 0 )
	{
		if ( mSELDecal )
		{
			// If our click hit the gizmo we are done.			
			if ( mGizmo->getSelection() != Gizmo::None )
			{
            mGizmo->on3DMouseDown( event );

				char returnBuffer[256];
				dSprintf(returnBuffer, sizeof(returnBuffer), "%f %f %f %f %f %f %f", 
				mSELDecal->mPosition.x, mSELDecal->mPosition.y, mSELDecal->mPosition.z, 
				mSELDecal->mTangent.x, mSELDecal->mTangent.y, mSELDecal->mTangent.z,
				mSELDecal->mSize);

				Con::executef( this, "prepGizmoTransform", Con::getIntArg(mSELDecal->mId), returnBuffer );

				return;
			}
		}

		if ( mHLDecal && pDecal == mHLDecal )
		{
			mHLDecal = NULL;            
			selectDecal( pDecal );   

			if ( isMethod( "onSelectInstance" ) )
			{
				char idBuf[512];
				dSprintf(idBuf, 512, "%i", pDecal->mId);
				Con::executef( this, "onSelectInstance", String(idBuf).c_str(), pDecal->mDataBlock->lookupName.c_str() );
			}

			return;
		}
		else if ( hit && !pDecal)
		{
			if ( dblClick )
				setMode( String("AddDecalMode"), true );

			return;
		}
	}
	else
	{
		// If we accidently hit a decal, then bail(probably an accident). If the use hits the decal twice,
		// then boot them into selection mode and select the decal.
		if ( mHLDecal && pDecal == mHLDecal )
		{
			if ( dblClick )
			{
				mHLDecal = NULL;            
				selectDecal( pDecal );   

				if ( isMethod( "onSelectInstance" ) )
				{
					char idBuf[512];
					dSprintf(idBuf, 512, "%i", pDecal->mId);
					Con::executef( this, "onSelectInstance", String(idBuf).c_str(), pDecal->mDataBlock->lookupName.c_str() );
				}
				setMode( String("SelectDecalMode"), true );
			}
			return;	
		}

		if ( hit && mCurrentDecalData ) // Create a new decal...
		{
			U8 flags = PermanentDecal | SaveDecal;

			DecalInstance *decalInst = gDecalManager->addDecal( ri.point, ri.normal, 0.0f, mCurrentDecalData, 1.0f, -1, flags );      
	      
			if ( decalInst )  
			{
				// Give the decal an id
				decalInst->mId = gDecalManager->mDecalInstanceVec.size();
				gDecalManager->mDecalInstanceVec.push_back(decalInst);

				selectDecal( decalInst );
				
				// Grab the mission editor undo manager.
				UndoManager *undoMan = NULL;
				if ( !Sim::findObject( "EUndoManager", undoMan ) )
				{
					Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
					return;           
				}

				// Create the UndoAction.
				DICreateUndoAction *action = new DICreateUndoAction("Create Decal");
				action->addDecal( *decalInst );
				
				action->mEditor = this;
				// Submit it.               
				undoMan->addAction( action );

				if ( isMethod( "onCreateInstance" ) )
				{
					char buffer[512];
					dSprintf(buffer, 512, "%i", decalInst->mId);
					Con::executef( this, "onCreateInstance", buffer, decalInst->mDataBlock->lookupName.c_str());
				}
			}

			return;
		}
	}

   if ( !mSELDecal )
      return;
}
Beispiel #20
0
void GuiRoadEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
{
   if ( !isFirstResponder() )
      setFirstResponder();

   // Get the clicked terrain position.
   Point3F tPos;
   if ( !getTerrainPos( event, tPos ) )
      return;      

   mouseLock();

   // Find any road / node at the clicked position.
   // TODO: handle overlapping roads/nodes somehow, cycle through them.
   
   DecalRoad *roadPtr = NULL;
   S32 closestNodeIdx = -1;
   F32 closestDist = F32_MAX;
   DecalRoad *closestNodeRoad = NULL;

   // First, find the closest node in any road to the clicked position.
   for ( SimSetIterator iter(mRoadSet); *iter; ++iter )
   {
      roadPtr = static_cast<DecalRoad*>( *iter );
      U32 idx;
      if ( roadPtr->getClosestNode( tPos, idx ) )
      {
         Point3F nodePos = roadPtr->getNodePosition(idx);
         F32 dist = ( nodePos - tPos ).len();
         if ( dist < closestDist )
         {
            closestNodeIdx = idx;
            closestDist = dist;
            closestNodeRoad = roadPtr;
         }
      }
   }

   //
   // Second, determine if the screen-space node rectangle
   // contains the clicked position.

   bool nodeClicked = false;
   S32 clickedNodeIdx = -1;

   if ( closestNodeIdx != -1 )
   {
      Point3F nodePos = closestNodeRoad->getNodePosition( closestNodeIdx );

      Point3F temp;
      project( nodePos, &temp );
      Point2I screenPos( temp.x, temp.y );

      RectI nodeRect( screenPos - mNodeHalfSize, mNodeHalfSize * 2 );
      
      nodeClicked = nodeRect.pointInRect( event.mousePoint );
      if ( nodeClicked )
         clickedNodeIdx = closestNodeIdx;
   }

   //
   // Determine the clickedRoad
   //
   DecalRoad *clickedRoadPtr = NULL;
   U32 insertNodeIdx = 0;

   if ( nodeClicked && (mSelRoad == NULL || closestNodeRoad == mSelRoad) )
   {
      // If a node was clicked, the owning road is always
      // considered the clicked road.
      clickedRoadPtr = closestNodeRoad;
   }
   else
   {
      // check the selected road first
      if ( mSelRoad != NULL && mSelRoad->containsPoint( tPos, &insertNodeIdx ) )
      {
         clickedRoadPtr = mSelRoad;
         nodeClicked = false;
         clickedNodeIdx = -1;
      }
      else
      {
         // Otherwise, we must ask each road if it contains
         // the clicked pos.
         for ( SimSetIterator iter(mRoadSet); *iter; ++iter )
         {
            roadPtr = static_cast<DecalRoad*>( *iter );
            if ( roadPtr->containsPoint( tPos, &insertNodeIdx ) )
            {
               clickedRoadPtr = roadPtr;
               break;            
            }
         }
      }
   }

	// shortcuts
   bool dblClick = ( event.mouseClickCount > 1 );
	if( dblClick )
   { 
		if( mMode == mSelectRoadMode )
		{
			setMode( mAddRoadMode, true );
			return;
		}
		if( mMode == mAddNodeMode )
		{
			// Delete the node attached to the cursor.
			deleteSelectedNode();
			mMode = mAddRoadMode;
			return;
		}
	}

	//this check is here in order to bounce back from deleting a whole road with ctrl+z
	//this check places the editor back into addroadmode
	if ( mMode == mAddNodeMode )
	{
      if ( !mSelRoad )
         mMode = mAddRoadMode;
	}

	if ( mMode == mSelectRoadMode )
	{
      // Did not click on a road or a node.
      if ( !clickedRoadPtr  )
      {
         setSelectedRoad( NULL );
         setSelectedNode( -1 );
         
         return;
      }

      // Clicked on a road that wasn't the currently selected road.
      if ( clickedRoadPtr != mSelRoad )
      {
         setSelectedRoad( clickedRoadPtr );
         setSelectedNode( -1 );
         return;
      }

      // Clicked on a node in the currently selected road that wasn't
      // the currently selected node.
      if ( nodeClicked )
      {
         setSelectedNode( clickedNodeIdx );
         return;
      }

      
      // Clicked a position on the currently selected road
      // that did not contain a node.
      //U32 newNode = clickedRoadPtr->insertNode( tPos, mDefaultWidth, insertNodeIdx );                  
      //setSelectedNode( newNode );
	}
   else if ( mMode == mAddRoadMode )
   {
		if ( nodeClicked && clickedRoadPtr )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				setSelectedRoad( clickedRoadPtr );
				setSelectedNode( clickedNodeIdx );

				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode;
            mSelNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx );
            mIsDirty = true;

				return;
         }
			else if ( clickedNodeIdx == clickedRoadPtr->mNodes.size() - 1 )
         {
				setSelectedRoad( clickedRoadPtr );
				setSelectedNode( clickedNodeIdx );

            mAddNodeIdx = U32_MAX;
            mMode = mAddNodeMode;
            mSelNode = mSelRoad->addNode( tPos, mDefaultWidth );
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         } 
		}

		DecalRoad *newRoad = new DecalRoad;
		

		newRoad->mMaterialName = mMaterialName;

      newRoad->registerObject();

      // Add to MissionGroup                              
      SimGroup *missionGroup;
      if ( !Sim::findObject( "MissionGroup", missionGroup ) )               
         Con::errorf( "GuiDecalRoadEditorCtrl - could not find MissionGroup to add new DecalRoad" );
      else
         missionGroup->addObject( newRoad );               

      newRoad->insertNode( tPos, mDefaultWidth, 0 );
      U32 newNode = newRoad->insertNode( tPos, mDefaultWidth, 1 );

      // Always add to the end of the road, the first node is the start.
      mAddNodeIdx = U32_MAX;
      
      setSelectedRoad( newRoad );      
      setSelectedNode( newNode );

      mMode = mAddNodeMode;

      // Disable the hover node while in addNodeMode, we
      // don't want some random node enlarged.
      mHoverNode = -1;

      // Grab the mission editor undo manager.
      UndoManager *undoMan = NULL;
      if ( !Sim::findObject( "EUndoManager", undoMan ) )
      {
         Con::errorf( "GuiRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
         return;           
      }

      // Create the UndoAction.
      MECreateUndoAction *action = new MECreateUndoAction("Create Road");
      action->addObject( newRoad );
      
      // Submit it.               
      undoMan->addAction( action );
		
		//send a callback to script after were done here if one exists
		if ( isMethod( "onRoadCreation" ) )
         Con::executef( this, "onRoadCreation" );

		return;
   }
	else if ( mMode == mAddNodeMode )
	{
		// Oops the road got deleted, maybe from an undo action?
      // Back to NormalMode.
      if ( mSelRoad )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				submitUndo( "Add Node" );
				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode;
            mSelNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx );
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         }
			else
         {
				if( clickedRoadPtr && clickedNodeIdx == clickedRoadPtr->mNodes.size() - 1 )
				{
					submitUndo( "Add Node" );
					mAddNodeIdx = U32_MAX;
					mMode = mAddNodeMode;
					mSelNode = mSelRoad->addNode( tPos, mDefaultWidth );
               mIsDirty = true;
					setSelectedNode( mSelNode );

					return;
				}
				else
				{
					submitUndo( "Insert Node" );
					// A single-click on empty space while in
					// AddNode mode means insert / add a node.
					//submitUndo( "Add Node" );
					//F32 width = mSelRoad->getNodeWidth( mSelNode );
					U32 newNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx);
               mIsDirty = true;
					setSelectedNode( newNode );

					return;
				}
         } 
      }
	}
	else if ( mMode == mInsertPointMode  && mSelRoad != NULL)
	{
		if ( clickedRoadPtr == mSelRoad )
      {
			F32 w0 = mSelRoad->getNodeWidth( insertNodeIdx );
         F32 w1 = mSelRoad->getNodeWidth( insertNodeIdx + 1 );               
         F32 width = ( w0 + w1 ) * 0.5f;

         submitUndo( "Insert Node" );
         U32 newNode = mSelRoad->insertNode( tPos, width, insertNodeIdx + 1);  
         mIsDirty = true;
         setSelectedNode( newNode );

			return;
       }
	}
	else if ( mMode == mRemovePointMode  && mSelRoad != NULL)
	{
		if ( nodeClicked && clickedRoadPtr == mSelRoad )
      {
			setSelectedNode( clickedNodeIdx );
         deleteSelectedNode();
         return;
      }
	}
	else if ( mMode == mMovePointMode )
	{
		if ( nodeClicked && clickedRoadPtr == mSelRoad )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
	else if ( mMode == mScalePointMode )
	{
		if ( nodeClicked && clickedRoadPtr == mSelRoad )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
}
void BatchProcessDialog::OnApplyToFiles(wxCommandEvent & WXUNUSED(event))
{
   long item = mChains->GetNextItem(-1,
                                    wxLIST_NEXT_ALL,
                                    wxLIST_STATE_SELECTED);
   if (item == -1) {
      wxMessageBox(_("No chain selected"));
      return;
   }

   wxString name = mChains->GetItemText(item);
   gPrefs->Write(wxT("/Batch/ActiveChain"), name);
   gPrefs->Flush();

   AudacityProject *project = GetActiveProject();
   if (!project->GetIsEmpty()) {
      wxMessageBox(_("Please save and close the current project first."));
      return;
   }

   wxString path = gPrefs->Read(wxT("/DefaultOpenPath"), ::wxGetCwd());
   wxString prompt =  _("Select file(s) for batch processing...");

   FormatList l;
   wxString filter;
   wxString all;

   Importer::Get().GetSupportedImportFormats(&l);
   for (const auto &format : l) {
      const Format *f = &format;

      wxString newfilter = f->formatName + wxT("|");
      for (size_t i = 0; i < f->formatExtensions.size(); i++) {
         if (!newfilter.Contains(wxT("*.") + f->formatExtensions[i] + wxT(";")))
            newfilter += wxT("*.") + f->formatExtensions[i] + wxT(";");
         if (!all.Contains(wxT("*.") + f->formatExtensions[i] + wxT(";")))
            all += wxT("*.") + f->formatExtensions[i] + wxT(";");
      }
      newfilter.RemoveLast(1);
      filter += newfilter;
      filter += wxT("|");
   }
   all.RemoveLast(1);
   filter.RemoveLast(1);

   wxString mask = _("All files|*|All supported files|") +
                   all + wxT("|") +
                   filter;

   wxString type = gPrefs->Read(wxT("/DefaultOpenType"),mask.BeforeFirst(wxT('|')));
   // Convert the type to the filter index
   int index = mask.First(type + wxT("|"));
   if (index == wxNOT_FOUND) {
      index = 0;
   }
   else {
      index = mask.Left(index).Freq(wxT('|')) / 2;
      if (index < 0) {
         index = 0;
      }
   }

   FileDialog dlog(this,
                   prompt,
                   path,
                   wxT(""),
                   mask,
                   wxFD_OPEN | wxFD_MULTIPLE | wxRESIZE_BORDER);

   dlog.SetFilterIndex(index);
   if (dlog.ShowModal() != wxID_OK) {
      return;
   }

   wxArrayString files;
   dlog.GetPaths(files);

   files.Sort();

   wxDialog * pD = safenew wxDialog(this, wxID_ANY, GetTitle());
   pD->SetName(pD->GetTitle());
   ShuttleGui S(pD, eIsCreating);

   S.StartVerticalLay(false);
   {
      S.StartStatic(_("Applying..."), 1);
      {
         wxImageList *imageList = new wxImageList(9, 16);
         imageList->Add(wxIcon(empty9x16_xpm));
         imageList->Add(wxIcon(arrow_xpm));

         S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
                    wxLC_SINGLE_SEL);
         mList = S.Id(CommandsListID).AddListControlReportMode();
         mList->AssignImageList(imageList, wxIMAGE_LIST_SMALL);
         mList->InsertColumn(0, _("File"), wxLIST_FORMAT_LEFT);
      }
      S.EndStatic();

      S.StartHorizontalLay(wxCENTER, false);
      {
         S.Id(wxID_CANCEL).AddButton(_("&Cancel"));
      }
      S.EndHorizontalLay();
   }
   S.EndVerticalLay();

   int i;
   for (i = 0; i < (int)files.GetCount(); i++ ) {
      mList->InsertItem(i, files[i], i == 0);
   }

   // Set the column size for the files list.
   mList->SetColumnWidth(0, wxLIST_AUTOSIZE);

   int width = mList->GetColumnWidth(0);
   wxSize sz = mList->GetClientSize();
   if (width > sz.GetWidth() && width < 500) {
      sz.SetWidth(width);
      mList->SetInitialSize(sz);
   }

   pD->Layout();
   pD->Fit();
   pD->SetSizeHints(pD->GetSize());
   pD->CenterOnScreen();
   pD->Move(-1, 0);
   pD->Show();
   Hide();

   mBatchCommands.ReadChain(name);
   for (i = 0; i < (int)files.GetCount(); i++) {
      wxWindowDisabler wd(pD);
      if (i > 0) {
         //Clear the arrow in previous item.
         mList->SetItemImage(i - 1, 0, 0);
      }
      mList->SetItemImage(i, 1, 1);
      mList->EnsureVisible(i);

      project->Import(files[i]);
      project->OnSelectAll();
      if (!mBatchCommands.ApplyChain()) {
         break;
      }

      if (!pD->IsShown() || mAbort) {
         break;
      }
      UndoManager *um = project->GetUndoManager();
      um->ClearStates();
      project->OnSelectAll();
      project->OnRemoveTracks();
   }
   project->OnRemoveTracks();

   // Under Linux an EndModal() here crashes (Bug #1221).
   // But sending a close message instead is OK.
#if !defined(__WXMAC__)
   wxCloseEvent Evt;
   Evt.SetId( wxID_OK );
   Evt.SetEventObject( this);
   ProcessWindowEvent( Evt );
#else
   EndModal(wxID_OK);
#endif 

   // Raise myself again, and the parent window with me
   Show();
}
bool PathFinderPlugin::run(ScribusDoc* doc, QString)
{
	ScribusDoc* currDoc = doc;
	if (currDoc == 0)
		currDoc = ScCore->primaryMainWindow()->doc;
	if (currDoc->m_Selection->count() <= 1)
		return true;
	
	//<<#9046
	UndoTransaction* activeTransaction = NULL;
	UndoManager* undoManager = UndoManager::instance();
	if (UndoManager::undoEnabled())
		activeTransaction = new UndoTransaction(undoManager->beginTransaction(Um::SelectionGroup, Um::IDocument, Um::PathOperation, "", Um::IPolygon));
	//>>#9046
	
	PageItem *Item1 = currDoc->m_Selection->itemAt(0);
	PageItem *Item2 = currDoc->m_Selection->itemAt(1);
	PathFinderDialog *dia = new PathFinderDialog(currDoc->scMW(), currDoc, Item1, Item2);
	if (dia->exec())
	{
		int opMode=dia->opMode;
		if (dia->keepItem1)
		{
			PageItem *newItem;
			if (dia->swapped)
			{
				newItem = new PageItem_Polygon(*Item2);
				newItem->setSelected(false);
				currDoc->Items->insert(currDoc->Items->indexOf(Item2), newItem);
			}
			else
			{
				newItem = new PageItem_Polygon(*Item1);
				newItem->setSelected(false);
				currDoc->Items->insert(currDoc->Items->indexOf(Item1), newItem);
			}
			if (UndoManager::undoEnabled())
			{
				ScItemState<PageItem*> *is = new ScItemState<PageItem*>("Create PageItem");
				is->set("CREATE_ITEM", "create_item");
				is->setItem(newItem);
				UndoObject *target = currDoc->Pages->at(Item1->OwnPage);
				undoManager->action(target, is);
			}
		}
		if (dia->keepItem2)
		{
			PageItem *newItem;
			if (dia->swapped)
			{
				newItem = new PageItem_Polygon(*Item1);
				newItem->setSelected(false);
				currDoc->Items->insert(currDoc->Items->indexOf(Item1), newItem);
			}
			else
			{
				newItem = new PageItem_Polygon(*Item2);
				newItem->setSelected(false);
				currDoc->Items->insert(currDoc->Items->indexOf(Item2), newItem);
			}
			if (UndoManager::undoEnabled())
			{
				ScItemState<PageItem*> *is = new ScItemState<PageItem*>("Create PageItem");
				is->set("CREATE_ITEM", "create_item");
				is->setItem(newItem);
				UndoObject *target = currDoc->Pages->at(Item1->OwnPage);
				undoManager->action(target, is);
			}
		}
		if (opMode != 4)
		{
			PageItem *currItem;
			QPainterPath path;
			FPointArray points;
			if (dia->targetColor == 0)
			{
				currItem = Item1;
				if (dia->swapped)
				{
					currItem = Item2;
					currItem->setXYPos(Item1->xPos(), Item1->yPos());
					currItem->setRotation(0.0);
				}
			}
			else
			{
				if (dia->swapped)
					currItem = Item1;
				else
				{
					currItem = Item2;
					currItem->setXYPos(Item1->xPos(), Item1->yPos());
					currItem->setRotation(0.0);
				}
			}
			path = dia->result;
			points.fromQPainterPath(path);
			
			//<<#9046
			FPointArray oldPOLine=currItem->PoLine;
			FPointArray oldContourLine=currItem->ContourLine;
			ScItemState<QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> > >* state = NULL;
			if (UndoManager::undoEnabled())
			{
				state = new ScItemState<QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> > >(Um::PathOperation);
				state->set("PATH_OPERATION", "path_operation");
				state->set("PATH_OP_OLD_FRAME", currItem->Frame);
				state->set("PATH_OP_OLD_CLIPEDITED", currItem->ClipEdited);
				state->set("PATH_OP_OLD_FRAMETYPE", currItem->FrameType);
				state->set("PATH_OP_OLD_OLDB2", currItem->OldB2);
				state->set("PATH_OP_OLD_OLDH2", currItem->OldH2);
				state->set("PATH_OP_NEW_FRAME", false);
				state->set("PATH_OP_NEW_CLIPEDITED", true);
				state->set("PATH_OP_NEW_FRAMETYPE", 3);
			}
			//>>#9046
			
			currItem->PoLine = points;
			currItem->Frame = false;
			currItem->ClipEdited = true;
			currItem->FrameType = 3;
			currDoc->AdjustItemSize(currItem);
			currItem->OldB2 = currItem->width();
			currItem->OldH2 = currItem->height();
			currItem->updateClip();
			currItem->ContourLine = currItem->PoLine.copy();
			
			//<<#9046
			if (UndoManager::undoEnabled())
			{
				state->set("PATH_OP_NEW_OLDB2", currItem->OldB2);
				state->set("PATH_OP_NEW_OLDH2", currItem->OldH2);
				state->setItem(QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> >(QPair<FPointArray, FPointArray>(oldPOLine, oldContourLine), QPair<FPointArray, FPointArray>(points, currItem->ContourLine)));
				undoManager->action(currItem, state);
			}
			//>>#9046
			
			currDoc->m_Selection->removeItem(currItem);
			currDoc->itemSelection_DeleteItem();
		}
		else
		{
			QPainterPath path;
			FPointArray points;
			PageItem *newItem;
			double i1x = Item1->xPos();
			double i1y = Item1->yPos();
			path = dia->result;
			if (!path.isEmpty())
			{
				points.fromQPainterPath(path);
				//<<#9046
				FPointArray oldPOLine=Item1->PoLine;
				FPointArray oldContourLine=Item1->ContourLine;
				ScItemState<QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> > >* state = NULL;
				if (UndoManager::undoEnabled())
				{
					state = new ScItemState<QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> > >(Um::PathOperation);
					state->set("PATH_OPERATION", "path_operation");
					state->set("PATH_OP_OLD_FRAME", Item1->Frame);
					state->set("PATH_OP_OLD_CLIPEDITED", Item1->ClipEdited);
					state->set("PATH_OP_OLD_FRAMETYPE", Item1->FrameType);
					state->set("PATH_OP_OLD_OLDB2", Item1->OldB2);
					state->set("PATH_OP_OLD_OLDH2", Item1->OldH2);
					state->set("PATH_OP_NEW_FRAME", false);
					state->set("PATH_OP_NEW_CLIPEDITED", true);
					state->set("PATH_OP_NEW_FRAMETYPE", 3);
				}
				//>>#9046
				Item1->PoLine = points;
				Item1->Frame = false;
				Item1->ClipEdited = true;
				Item1->FrameType = 3;
				currDoc->AdjustItemSize(Item1);
				Item1->OldB2 = Item1->width();
				Item1->OldH2 = Item1->height();
				Item1->updateClip();
				Item1->ContourLine = Item1->PoLine.copy();
				//<<#9046
				if (UndoManager::undoEnabled())
				{
					state->set("PATH_OP_NEW_OLDB2", Item1->OldB2);
					state->set("PATH_OP_NEW_OLDH2", Item1->OldH2);
					state->setItem(QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> >(QPair<FPointArray, FPointArray>(oldPOLine, oldContourLine), QPair<FPointArray, FPointArray>(Item1->PoLine, Item1->ContourLine)));
					undoManager->action(Item1, state);
				}
				//>>#9046
			}

			path = QPainterPath();
			path = dia->result1;
			if (!path.isEmpty())
			{
				points.fromQPainterPath(path);
				//<<#9046
				FPointArray oldPOLine=Item2->PoLine;
				FPointArray oldContourLine=Item2->ContourLine;
				ScItemState<QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> > >* state = NULL;
				if (UndoManager::undoEnabled())
				{
					state = new ScItemState<QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> > >(Um::PathOperation);
					state->set("PATH_OPERATION", "path_operation");
					state->set("PATH_OP_OLD_FRAME", Item2->Frame);
					state->set("PATH_OP_OLD_CLIPEDITED", Item2->ClipEdited);
					state->set("PATH_OP_OLD_FRAMETYPE", Item2->FrameType);
					state->set("PATH_OP_OLD_OLDB2", Item2->OldB2);
					state->set("PATH_OP_OLD_OLDH2", Item2->OldH2);
					state->set("PATH_OP_NEW_FRAME", false);
					state->set("PATH_OP_NEW_CLIPEDITED", true);
					state->set("PATH_OP_NEW_FRAMETYPE", 3);
				}
				//>>#9046
				Item2->setXYPos(i1x, i1y);
				Item2->setRotation(0.0);
				Item2->PoLine = points;
				Item2->Frame = false;
				Item2->ClipEdited = true;
				Item2->FrameType = 3;
				currDoc->AdjustItemSize(Item2);
				Item2->OldB2 = Item2->width();
				Item2->OldH2 = Item2->height();
				Item2->updateClip();
				Item2->ContourLine = Item2->PoLine.copy();
				//<<#9046
				if (UndoManager::undoEnabled())
				{
					state->set("PATH_OP_NEW_OLDB2", Item2->OldB2);
					state->set("PATH_OP_NEW_OLDH2", Item2->OldH2);
					state->setItem(QPair<QPair<FPointArray, FPointArray>, QPair<FPointArray, FPointArray> >(QPair<FPointArray, FPointArray>(oldPOLine, oldContourLine), QPair<FPointArray, FPointArray>(Item2->PoLine, Item2->ContourLine)));
					undoManager->action(Item2, state);
				}
				//>>#9046
			}
			
			path = QPainterPath();
			path = dia->result2;
			if (!path.isEmpty())
			{
				if (dia->targetColor == 0)
				{
					newItem = new PageItem_Polygon(*Item1);
					newItem->setXYPos(i1x, i1y);
				}
				else
				{
					newItem = new PageItem_Polygon(*Item2);
					newItem->setXYPos(i1x, i1y);
					newItem->setRotation(0.0);
				}
				currDoc->Items->append(newItem);
				newItem->setSelected(false);
				points.fromQPainterPath(path);
				newItem->PoLine = points;
				newItem->Frame = false;
				newItem->ClipEdited = true;
				newItem->FrameType = 3;
				currDoc->AdjustItemSize(newItem);
				newItem->OldB2 = newItem->width();
				newItem->OldH2 = newItem->height();
				newItem->updateClip();
				newItem->ContourLine = newItem->PoLine.copy();
				if (dia->targetColor == 2)
				{
					QString fill = dia->getOtherFillColor();
					if (fill == CommonStrings::tr_NoneColor)
						fill = CommonStrings::None;
					newItem->setFillColor(fill);
					QString stroke = dia->getOtherLineColor();
					if (stroke == CommonStrings::tr_NoneColor)
						stroke = CommonStrings::None;
					newItem->setLineColor(stroke);
				}
			}
			currDoc->m_Selection->clear();
			currDoc->view()->Deselect(true);
		}
		currDoc->changed();
		currDoc->view()->DrawNew();
	}
	delete dia;
	
	//<<#9046
	if (activeTransaction)
	{
		activeTransaction->commit();
		delete activeTransaction;
		activeTransaction = NULL;
	}
	//>>#9046
	
	return true;
}
void GuiRiverEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
{
   mGizmo->on3DMouseDown( event );

   if ( !isFirstResponder() )
      setFirstResponder();
	
	// Get the raycast collision position
   Point3F tPos;
   if ( !getStaticPos( event, tPos ) )
		return;  

   // Construct a LineSegment from the camera position to 1000 meters away in
   // the direction clicked.
   // If that segment hits the terrain, truncate the ray to only be that length.

   // We will use a LineSegment/Sphere intersection test to determine if a RiverNode
   // was clicked.   

   Point3F startPnt = event.pos;
   Point3F endPnt = event.pos + event.vec * 1000.0f;

   RayInfo ri;   

   if ( gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri) )
      endPnt = ri.point;

   River *riverPtr = NULL;
   River *clickedRiverPtr = NULL;

   // Did we click on a river? check current selection first
   U32 insertNodeIdx = -1;
   Point3F collisionPnt;
   if ( mSelRiver != NULL && mSelRiver->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) )
   {
      clickedRiverPtr = mSelRiver;
   }
   else
   {
      for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
      {
         riverPtr = static_cast<River*>( *iter );
         if ( riverPtr->collideRay( event.pos, event.vec, &insertNodeIdx, &collisionPnt ) )
         {
            clickedRiverPtr = riverPtr;
            break;
         }
      }
   }

   // Did we click on a riverNode?
   bool nodeClicked = false;   
   S32 clickedNodeIdx = -1;
   F32 clickedNodeDist = mNodeSphereRadius;

   // If we clicked on the currently selected river, only scan its nodes
   if ( mSelRiver != NULL && clickedRiverPtr == mSelRiver )
   {
      for ( U32 i = 0; i < mSelRiver->mNodes.size(); i++ )
      {
         const Point3F &nodePos = mSelRiver->mNodes[i].point;

         Point3F screenPos;
         project( nodePos, &screenPos );

         F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
         if ( dist < clickedNodeDist )
         {
            clickedNodeDist = dist;
            clickedNodeIdx = i;
            nodeClicked = true;
         }
      }
   }
   else
   {
      for ( SimSetIterator iter(mRiverSet); *iter; ++iter )
      {
         riverPtr = static_cast<River*>( *iter );
         
         for ( U32 i = 0; i < riverPtr->mNodes.size(); i++ )
         {
            const Point3F &nodePos = riverPtr->mNodes[i].point;

            Point3F screenPos;
            project( nodePos, &screenPos );

            F32 dist = ( event.mousePoint - Point2I(screenPos.x, screenPos.y) ).len();
            if ( dist < clickedNodeDist )
            {
               // we found a hit!
               clickedNodeDist = dist;
               clickedNodeIdx = i;
               nodeClicked = true;
               clickedRiverPtr = riverPtr;
            }
         }
      }
   }
	
	// shortcuts
	bool dblClick = ( event.mouseClickCount > 1 );
	if( dblClick )
   { 
		if( mMode == mSelectRiverMode )
		{
			setMode( mAddRiverMode, true );
			return;
		}
		if( mMode == mAddNodeMode )
		{
			// Delete the node attached to the cursor.
			deleteSelectedNode();
			mMode = mAddRiverMode;
			return;
		}
	}

	//this check is here in order to bounce back from deleting a whole road with ctrl+z
	//this check places the editor back into addrivermode
	if ( mMode == mAddNodeMode )
	{
      if ( !mSelRiver )
         mMode = mAddRiverMode;
	}

	if ( mMode == mSelectRiverMode )
	{
      // Did not click on a River or a node.
      if ( !clickedRiverPtr  )
      {
         setSelectedRiver( NULL );
         setSelectedNode( -1 );
         
         return;
      }

      // Clicked on a River that wasn't the currently selected River.
      if ( clickedRiverPtr != mSelRiver )
      {
         setSelectedRiver( clickedRiverPtr );
         setSelectedNode( clickedNodeIdx );
         return;
      }

     // Clicked on a node in the currently selected River that wasn't
      // the currently selected node.
      if ( nodeClicked )
      {
         setSelectedNode( clickedNodeIdx );
         return;
      }
	}
   else if ( mMode == mAddRiverMode )
   {
		if ( nodeClicked )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				setSelectedRiver( clickedRiverPtr );
				setSelectedNode( clickedNodeIdx );

				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode; 

            mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx );
            mIsDirty = true;

				return;
         }
			else if ( clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 )
         {
				setSelectedRiver( clickedRiverPtr );
				setSelectedNode( clickedNodeIdx );

            mAddNodeIdx = U32_MAX;
				mMode = mAddNodeMode;

            mSelNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal);
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         } 
		}

		if ( !isMethod( "createRiver" ) )
      {
			Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method does not exist." );
         return;
      }

      const char *res = Con::executef( this, "createRiver" );

      River *newRiver;
      if ( !Sim::findObject( res, newRiver ) )
      {
         Con::errorf( "GuiRiverEditorCtrl::on3DMouseDown - createRiver method did not return a river object." );
         return;
      }                

      // Add to MissionGroup                              
      SimGroup *missionGroup;
      if ( !Sim::findObject( "MissionGroup", missionGroup ) )               
         Con::errorf( "GuiRiverEditorCtrl - could not find MissionGroup to add new River" );
      else
         missionGroup->addObject( newRiver );

      Point3F pos( endPnt );
      pos.z += mDefaultDepth * 0.5f;

      newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 0 );
      U32 newNode = newRiver->insertNode( pos, mDefaultWidth, mDefaultDepth, mDefaultNormal, 1 );

      // Always add to the end of the road, the first node is the start.
      mAddNodeIdx = U32_MAX;
      
      setSelectedRiver( newRiver );      
      setSelectedNode( newNode );

      mMode = mAddNodeMode;

      // Disable the hover node while in addNodeMode, we
      // don't want some random node enlarged.
      mHoverNode = -1;

      // Grab the mission editor undo manager.
      UndoManager *undoMan = NULL;
      if ( !Sim::findObject( "EUndoManager", undoMan ) )
      {
         Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" );
         return;           
      }

      // Create the UndoAction.
      MECreateUndoAction *action = new MECreateUndoAction("Create MeshRoad");
      action->addObject( newRiver );

      // Submit it.               
      undoMan->addAction( action );

		return;
   }
	else if ( mMode == mAddNodeMode )
	{
		// Oops the road got deleted, maybe from an undo action?
      // Back to NormalMode.
      if ( mSelRiver )
      {
			// A double-click on a node in Normal mode means set AddNode mode.  
         if ( clickedNodeIdx == 0 )
         {
				submitUndo( "Add Node" );
				mAddNodeIdx = clickedNodeIdx;
            mMode = mAddNodeMode;
            mSelNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx );
            mIsDirty = true;
				setSelectedNode( mSelNode );

				return;
         }
			else
         {
				if( clickedRiverPtr && clickedNodeIdx == clickedRiverPtr->mNodes.size() - 1 )
				{
					submitUndo( "Add Node" );
					mAddNodeIdx = U32_MAX;
					mMode = mAddNodeMode;
					U32 newNode = mSelRiver->addNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal);  
               mIsDirty = true;
					setSelectedNode( newNode );

					return;
				}
				else
				{
					submitUndo( "Insert Node" );
					// A single-click on empty space while in
					// AddNode mode means insert / add a node.
					//submitUndo( "Add Node" );
					//F32 width = mSelRiver->getNodeWidth( mSelNode );
					U32 newNode = mSelRiver->insertNode( tPos, mDefaultWidth, mDefaultDepth, mDefaultNormal, mAddNodeIdx);
               mIsDirty = true;
					setSelectedNode( newNode );

					return;
				}
			}
		}
	}
	else if ( mMode == mInsertPointMode && mSelRiver != NULL )
	{
		if ( clickedRiverPtr == mSelRiver )
      {
			// NOTE: I guess we have to determine the if the clicked ray intersects a road but not a specific node...
         // in order to handle inserting nodes in the same way as for DecalRoad

         U32 prevNodeIdx = insertNodeIdx;
         U32 nextNodeIdx = ( prevNodeIdx + 1 > mSelRiver->mNodes.size() - 1 ) ? prevNodeIdx : prevNodeIdx + 1;

         const RiverNode &prevNode = mSelRiver->mNodes[prevNodeIdx];
         const RiverNode &nextNode = mSelRiver->mNodes[nextNodeIdx];

         F32 width = ( prevNode.width + nextNode.width ) * 0.5f;
         F32 depth = ( prevNode.depth + nextNode.depth ) * 0.5f;
         Point3F normal = ( prevNode.normal + nextNode.normal ) * 0.5f;
         normal.normalize();

         submitUndo( "Insert Node" );
         U32 newNode = mSelRiver->insertNode( collisionPnt, width, depth, normal, insertNodeIdx + 1 );
         mIsDirty = true;
         setSelectedNode( newNode );

			return;
       }
	}
	else if ( mMode == mRemovePointMode && mSelRiver != NULL )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         deleteSelectedNode();
         return;
      }
	}
	else if ( mMode == mMovePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
	else if ( mMode == mScalePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
	else if ( mMode == mRotatePointMode )
	{
		if ( nodeClicked && clickedRiverPtr == mSelRiver )
      {
			setSelectedNode( clickedNodeIdx );
         return;
      }
	}
}