Ticket #96: copypaste.diff

File copypaste.diff, 17.4 KB (added by stilz_, 10 years ago)
  • source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp

    diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp
    index 57b4734..8f1d507 100644
    a b  
    1919
    2020#include "ScenarioEditor.h"
    2121
     22#include <vector>
     23
    2224#include "wx/busyinfo.h"
    2325#include "wx/config.h"
    2426#include "wx/dir.h"
     
    2830#include "wx/image.h"
    2931#include "wx/sysopt.h"
    3032#include "wx/tooltip.h"
     33#include <sstream>
    3134
    3235#include "General/AtlasEventLoop.h"
    3336#include "General/Datafile.h"
     
    4447
    4548#include "Misc/KeyMap.h"
    4649
    47 #include "Tools/Common/Tools.h"
    4850#include "Tools/Common/Brushes.h"
    4951#include "Tools/Common/MiscState.h"
     52#include "Tools/Common/PasteObjectSettings.h"
     53#include "Tools/Common/Tools.h"
    5054
    5155static HighResTimer g_Timer;
    5256
    BEGIN_EVENT_TABLE(ScenarioEditor, wxFrame)  
    340344    EVT_MENU(ID_Quit, ScenarioEditor::OnQuit)
    341345    EVT_MENU(wxID_UNDO, ScenarioEditor::OnUndo)
    342346    EVT_MENU(wxID_REDO, ScenarioEditor::OnRedo)
     347    EVT_MENU(wxID_COPY, ScenarioEditor::OnCopy)
     348    EVT_MENU(wxID_CUT, ScenarioEditor::OnCut)
     349    EVT_MENU(wxID_PASTE, ScenarioEditor::OnPaste)
    343350
    344351    EVT_MENU(ID_Wireframe, ScenarioEditor::OnWireframe)
    345352    EVT_MENU(ID_MessageTrace, ScenarioEditor::OnMessageTrace)
    ScenarioEditor::ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterfac  
    436443    {
    437444        menuEdit->Append(wxID_UNDO, _("&Undo"));
    438445        menuEdit->Append(wxID_REDO, _("&Redo"));
     446        menuEdit->AppendSeparator();
     447        menuEdit->Append(wxID_COPY, _("&Copy"));
     448        menuEdit->Append(wxID_CUT, _("Cut"));
     449        menuEdit->Append(wxID_PASTE, _("&Paste"));
    439450    }
    440451
    441452    GetCommandProc().SetEditMenu(menuEdit);
    void ScenarioEditor::OnRedo(wxCommandEvent&)  
    622633    GetCommandProc().Redo();
    623634}
    624635
     636
     637void ScenarioEditor::OnCopy(wxCommandEvent& event)
     638{
     639    if (g_SelectedObjects.empty())
     640    {
     641        wxLogWarning(_("Nothing to copy!"));
     642        return;
     643    }
     644
     645    AtlasMessage::qGetXmlForObjects qry(g_SelectedObjects);
     646    qry.Post();
     647
     648    wxLogWarning(wxString(qry.xml.c_str()));
     649}
     650
     651void ScenarioEditor::OnCut(wxCommandEvent& event)
     652{
     653}
     654
     655void ScenarioEditor::OnPaste(wxCommandEvent& event)
     656{
     657    std::vector<PasteObjectSettings> objects;
     658
     659    PasteObjectSettings object1;
     660    object1.templateName = L"gaia/fauna_bear";
     661    object1.atlasSettings.player = 1;
     662    object1.pasteRelativePosition.type1.x = 100;
     663    object1.pasteRelativePosition.type1.y = 0;
     664    objects.push_back(object1);
     665
     666    PasteObjectSettings object2;
     667    object2.templateName = L"gaia/fauna_bear";
     668    object2.atlasSettings.player = 1;
     669    object2.pasteRelativePosition.type1.x = 0;
     670    object2.pasteRelativePosition.type1.y = 0;
     671    objects.push_back(object2);
     672
     673    GetToolManager().SetCurrentTool(_T("PasteObjects"), &objects);
     674}
     675
    625676//////////////////////////////////////////////////////////////////////////
    626677
    627678void ScenarioEditor::OnNew(wxCommandEvent& WXUNUSED(event))
  • source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.h

    diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.h b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.h
    index c3a6b38..ae054e4 100644
    a b public:  
    4848    void OnQuit(wxCommandEvent& event);
    4949    void OnUndo(wxCommandEvent& event);
    5050    void OnRedo(wxCommandEvent& event);
     51    void OnCopy(wxCommandEvent& event);
     52    void OnCut(wxCommandEvent& event);
     53    void OnPaste(wxCommandEvent& event);
    5154
    5255    void OnWireframe(wxCommandEvent& event);
    5356    void OnMessageTrace(wxCommandEvent& event);
  • new file source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/PasteObjectSettings.h

    diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/PasteObjectSettings.h b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/Common/PasteObjectSettings.h
    new file mode 100644
    index 0000000..1a4cabc
    - +  
     1/* Copyright (C) 2012 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#ifndef INCLUDED_PASTEOBJECTSETTINGS
     19#define INCLUDED_PASTEOBJECTSETTINGS
     20
     21#include <string>
     22
     23#include "GameInterface/Messages.h"
     24
     25namespace AtlasMessage
     26{
     27    struct sObjectSettings;
     28}
     29
     30struct PasteObjectSettings
     31{
     32    AtlasMessage::Position pasteRelativePosition;
     33    AtlasMessage::Position position;
     34    AtlasMessage::Position target;
     35    unsigned int actorSeed;
     36    std::wstring templateName;
     37    AtlasMessage::sObjectSettings atlasSettings;
     38};
     39
     40#endif // INCLUDED_PASTEOBJECTSETTINGS
     41
  • new file source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PasteObjects.cpp

    diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PasteObjects.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PasteObjects.cpp
    new file mode 100644
    index 0000000..dbc5919
    - +  
     1/* Copyright (C) 2013 Wildfire Games.
     2 * This file is part of 0 A.D.
     3 *
     4 * 0 A.D. is free software: you can redistribute it and/or modify
     5 * it under the terms of the GNU General Public License as published by
     6 * the Free Software Foundation, either version 2 of the License, or
     7 * (at your option) any later version.
     8 *
     9 * 0 A.D. is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 * GNU General Public License for more details.
     13 *
     14 * You should have received a copy of the GNU General Public License
     15 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16 */
     17
     18#include "precompiled.h"
     19
     20#include <vector>
     21
     22#include "ScenarioEditor/ScenarioEditor.h"
     23#include "Common/Tools.h"
     24#include "Common/Brushes.h"
     25#include "Common/MiscState.h"
     26#include "Common/ObjectSettings.h"
     27#include "Common/PasteObjectSettings.h"
     28#include "GameInterface/Messages.h"
     29
     30using AtlasMessage::Position;
     31
     32static float g_DefaultAngle = (float)(M_PI*3.0/4.0);
     33
     34
     35class PasteObjects : public StateDrivenTool<PasteObjects>
     36{
     37    DECLARE_DYNAMIC_CLASS(PasteObjects);
     38
     39    Position m_ScreenPos, m_ObjPos, m_Target;
     40    wxString m_ObjectID;
     41    unsigned int m_ActorSeed;
     42
     43    std::vector<PasteObjectSettings> m_objectsToPaste;
     44
     45public:
     46    PasteObjects()
     47    {
     48        SetState(&Waiting);
     49    }
     50
     51    void SendObjectMsg(bool preview)
     52    {
     53        int dragDistSq =
     54              (m_ScreenPos.type1.x-m_Target.type1.x)*(m_ScreenPos.type1.x-m_Target.type1.x)
     55            + (m_ScreenPos.type1.y-m_Target.type1.y)*(m_ScreenPos.type1.y-m_Target.type1.y);
     56        bool useTarget = (dragDistSq >= 16*16);
     57
     58        for (std::vector<PasteObjectSettings>::iterator it = m_objectsToPaste.begin(); it != m_objectsToPaste.end(); ++it)
     59        {
     60            PasteObjectSettings & object = *it;
     61            if (preview)
     62            {
     63                POST_MESSAGE(ObjectPreview, (object.templateName, object.atlasSettings, object.position,
     64                    useTarget, object.target, g_DefaultAngle, object.actorSeed));
     65            }
     66            else
     67            {
     68                POST_COMMAND(CreateObject, (object.templateName, object.atlasSettings, object.position,
     69                    useTarget, object.target, g_DefaultAngle, object.actorSeed));
     70                RandomizeActorSeed();
     71            }
     72        }
     73    }
     74
     75    virtual void Init(void* initData, ScenarioEditor* scenarioEditor)
     76    {
     77        StateDrivenTool<PasteObjects>::Init(initData, scenarioEditor);
     78
     79        wxASSERT(initData);
     80        m_objectsToPaste = *static_cast<std::vector<PasteObjectSettings>*>(initData);
     81        SendObjectMsg(true);
     82    }
     83
     84    void OnEnable()
     85    {
     86        RandomizeActorSeed();
     87    }
     88
     89    void OnDisable()
     90    {
     91        m_ObjectID = _T("");
     92        SendObjectMsg(true);
     93    }
     94
     95    /*
     96        Object placement:
     97        * Select unit from list
     98        * Move mouse around screen; preview of unit follows mouse
     99        * Left mouse down -> remember position, fix preview to point
     100        * Mouse move -> if moved > [limit], rotate unit to face mouse; else default orientation
     101        * Left mouse release -> finalise placement of object on map
     102
     103        * Page up/down -> rotate default orientation
     104
     105        * Escape -> cancel placement tool
     106
     107        TOOD: what happens if somebody saves while the preview is active?
     108    */
     109
     110    bool OnMouseOverride(wxMouseEvent& WXUNUSED(evt))
     111    {
     112        // This used to let the scroll-wheel rotate units, but that overrides
     113        // the camera zoom and makes navigation very awkward, so it doesn't
     114        // any more.
     115        return false;
     116    }
     117
     118    bool OnKeyOverride(wxKeyEvent& evt, KeyEventType type)
     119    {
     120        if (type == KEY_CHAR && evt.GetKeyCode() == WXK_ESCAPE)
     121        {
     122            SetState(&Disabled);
     123            return true;
     124        }
     125        else
     126            return false;
     127    }
     128
     129    void RotateTick(float dt)
     130    {
     131        int dir = 0;
     132        if (wxGetKeyState(WXK_PAGEDOWN))  ++dir; // page-down key
     133        if (wxGetKeyState(WXK_PAGEUP)) --dir; // page-up key
     134        if (dir)
     135        {
     136            float speed = M_PI/2.f * ScenarioEditor::GetSpeedModifier(); // radians per second
     137            g_DefaultAngle += (dir * dt * speed);
     138            SendObjectMsg(true);
     139        }
     140    }
     141
     142    void RandomizeActorSeed()
     143    {
     144        m_ActorSeed = (unsigned int)floor((rand() / (float)RAND_MAX) * 65535.f);
     145    }
     146
     147    struct sWaiting : public State
     148    {
     149        bool OnMouse(PasteObjects* obj, wxMouseEvent& evt)
     150        {
     151            if (obj->OnMouseOverride(evt))
     152            {
     153                return true;
     154            }
     155            else if (evt.LeftDown())
     156            {
     157                obj->m_ObjPos = obj->m_ScreenPos = obj->m_Target = Position(evt.GetPosition());
     158                obj->SendObjectMsg(true);
     159                obj->m_ObjPos = Position::Unchanged(); // make sure object is stationary even if the camera moves
     160                SET_STATE(Placing);
     161                return true;
     162            }
     163            else if (evt.Moving())
     164            {
     165                for (std::vector<PasteObjectSettings>::iterator it = obj->m_objectsToPaste.begin(); it != obj->m_objectsToPaste.end(); ++it)
     166                {
     167                    (*it).position = Position(evt.GetPosition());
     168                    (*it).position.type1.x += (*it).pasteRelativePosition.type1.x;
     169                    (*it).position.type1.y += (*it).pasteRelativePosition.type1.y;
     170                    (*it).target = (*it).position;
     171                    obj->SendObjectMsg(true);
     172                }
     173                return true;
     174            }
     175            else
     176            {
     177                return false;
     178            }
     179        }
     180
     181        bool OnKey(PasteObjects* obj, wxKeyEvent& evt, KeyEventType type)
     182        {
     183            if (type == KEY_CHAR && (evt.GetKeyCode() >= '0' && evt.GetKeyCode() <= '9'))
     184            {
     185                int playerID = evt.GetKeyCode() - '0';
     186                obj->GetScenarioEditor().GetObjectSettings().SetPlayerID(playerID);
     187                obj->GetScenarioEditor().GetObjectSettings().NotifyObservers();
     188                obj->SendObjectMsg(true);
     189                return true;
     190            }
     191            else
     192                return obj->OnKeyOverride(evt, type);
     193        }
     194        void OnTick(PasteObjects* obj, float dt)
     195        {
     196            obj->RotateTick(dt);
     197        }
     198    }
     199    Waiting;
     200
     201    struct sPlacing : public State
     202    {
     203        bool OnMouse(PasteObjects* obj, wxMouseEvent& evt)
     204        {
     205            if (obj->OnMouseOverride(evt))
     206                return true;
     207            else if (evt.LeftUp())
     208            {
     209                obj->m_Target = Position(evt.GetPosition());
     210                // Create the actual object
     211                obj->SendObjectMsg(false);
     212                // Go back to preview mode
     213                SET_STATE(Waiting);
     214                obj->m_ObjPos = obj->m_ScreenPos = obj->m_Target;
     215                obj->SendObjectMsg(true);
     216                return true;
     217            }
     218            else if (evt.Dragging())
     219            {
     220                obj->m_Target = Position(evt.GetPosition());
     221                obj->SendObjectMsg(true);
     222                return true;
     223            }
     224            else
     225                return false;
     226        }
     227        bool OnKey(PasteObjects* obj, wxKeyEvent& evt, KeyEventType type)
     228        {
     229            return obj->OnKeyOverride(evt, type);
     230        }
     231        void OnTick(PasteObjects* obj, float dt)
     232        {
     233            obj->RotateTick(dt);
     234        }
     235    }
     236    Placing;
     237};
     238
     239IMPLEMENT_DYNAMIC_CLASS(PasteObjects, StateDrivenTool<PasteObjects>);
  • source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp

    diff --git a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp
    index ea36267..12eba27 100644
    a b  
    3838#include "ps/CLogger.h"
    3939#include "ps/Game.h"
    4040#include "ps/World.h"
     41#include "ps/XML/XMLWriter.h"
    4142#include "renderer/Renderer.h"
    4243#include "renderer/WaterManager.h"
    4344#include "simulation2/Simulation2.h"
    QUERYHANDLER(GetObjectsList)  
    9596}
    9697
    9798
     99QUERYHANDLER(GetXmlForObjects)
     100{
     101    std::string xml;
     102
     103    std::vector<AtlasMessage::ObjectID> objects = *msg->objects;
     104
     105    CSimulation2 & simulation = *g_Game->GetSimulation2();
     106
     107    XML_Start();
     108    XML_Element("Entities");
     109
     110    CSimulation2::InterfaceList ents = simulation.GetEntitiesWithInterface(IID_Position);
     111    for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it)
     112    {
     113        entity_id_t uid = it->first;
     114        if (objects.end() != std::find(objects.begin(), objects.end(), uid))
     115        {
     116            XML_Element("Entity");
     117            XML_Attribute("uid", uid);
     118
     119            objects.erase(std::remove(objects.begin(), objects.end(), uid), objects.end());
     120        }
     121    }
     122
     123    xml = XML_GetOutput().EscapeToPrintableASCII();
     124
     125    std::wstring wxml(xml.begin(), xml.end());
     126
     127    msg->xml = wxml;
     128}
     129
    98130static std::vector<entity_id_t> g_Selection;
    99131typedef std::map<player_id_t, CColor> PlayerColorMap;
    100132
    MESSAGEHANDLER(ObjectPreview)  
    366398    }
    367399}
    368400
     401MESSAGEHANDLER(PasteObjectPreview)
     402{
     403    if (g_PreviewEntityID != INVALID_ENTITY)
     404    {
     405        // Update the unit's position and orientation:
     406
     407        CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), g_PreviewEntityID);
     408        if (cmpPosition)
     409        {
     410            CVector3D pos = GetUnitPos(msg->pos, cmpPosition->IsFloating());
     411            cmpPosition->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
     412
     413            float angle;
     414            if (msg->usetarget)
     415            {
     416                // Aim from pos towards msg->target
     417                CVector3D target = msg->target->GetWorldSpace(pos.Y);
     418                angle = atan2(target.X-pos.X, target.Z-pos.Z);
     419            }
     420            else
     421            {
     422                angle = msg->angle;
     423            }
     424
     425            cmpPosition->SetYRotation(entity_angle_t::FromFloat(angle));
     426        }
     427
     428        // TODO: handle random variations somehow
     429
     430        CmpPtr<ICmpVisual> cmpVisual(*g_Game->GetSimulation2(), g_PreviewEntityID);
     431        if (cmpVisual)
     432            cmpVisual->SetActorSeed(msg->actorseed);
     433
     434        CmpPtr<ICmpOwnership> cmpOwnership(*g_Game->GetSimulation2(), g_PreviewEntityID);
     435        if (cmpOwnership)
     436            cmpOwnership->SetOwner((player_id_t)msg->settings->player);
     437    }
     438}
     439
    369440BEGIN_COMMAND(CreateObject)
    370441{
    371442    CVector3D m_Pos;
  • source/tools/atlas/GameInterface/Messages.h

    diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h
    index 48ce280..2a1431b 100644
    a b QUERY(GetObjectsList,  
    320320      ((std::vector<sObjectsListItem>, objects)) // sorted by .name
    321321      );
    322322
     323QUERY(GetXmlForObjects,
     324        ((std::vector<AtlasMessage::ObjectID>, objects))
     325        ,
     326        ((std::wstring, xml))
     327        );
     328
    323329#ifndef MESSAGES_SKIP_STRUCTS
    324330struct sObjectSettings
    325331{
    MESSAGE(ObjectPreview,  
    346352        ((unsigned int, actorseed))
    347353        );
    348354
     355MESSAGE(PasteObjectPreview,
     356        ((std::wstring, id)) // or empty string => disable
     357        ((sObjectSettings, settings))
     358        ((Position, pos))
     359        ((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
     360        ((Position, target))
     361        ((float, angle))
     362        ((unsigned int, actorseed))
     363        );
     364
    349365COMMAND(CreateObject, NOMERGE,
    350366        ((std::wstring, id))
    351367        ((sObjectSettings, settings))
    MESSAGE(SetActorViewer,  
    366382        ((bool, flushcache)) // true => unload all actor files before starting the preview (because we don't have proper hotloading yet)
    367383        );
    368384
     385
    369386//////////////////////////////////////////////////////////////////////////
    370387
    371388QUERY(Exit,,); // no inputs nor outputs