Ticket #1213: 1213.4.diff

File 1213.4.diff, 9.5 KB (added by trompetin17, 9 years ago)
  • source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformObject.cpp

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    300300
    301301                return true;
    302302            }
    303             else if (g_SelectedObjects.size() == 1 && ((evt.Dragging() && evt.RightIsDown()) || evt.RightDown()))
     303            else if (!g_SelectedObjects.empty() && ((evt.Dragging() && evt.RightIsDown()) || evt.RightDown()))
    304304            {
    305                 // TODO: Rotation of selections with multiple objects?
    306 
    307                 // Dragging with right mouse button -> rotate objects to look
    308                 // at mouse
    309                 Position pos(evt.GetPosition());
    310                 for (size_t i = 0; i < g_SelectedObjects.size(); ++i)
    311                     POST_COMMAND(RotateObject, (g_SelectedObjects[i], true, pos, 0.f));
    312 
     305                SET_STATE(Rotating);
    313306                return true;
    314307            }
    315308            else if (evt.Moving())
     
    555550        }
    556551    }
    557552    Pasting;
     553
     554    struct sRotating : public State
     555    {
     556        bool rotateFromCenterPoint = false;
     557        bool OnMouse(TransformObject* obj, wxMouseEvent& evt)
     558        {
     559            if (evt.RightUp())
     560            {
     561                POST_MESSAGE(UpdateVisualSelectedObjects, ());
     562                SET_STATE(Waiting);
     563                return true;
     564            }
     565            else if (evt.Dragging())
     566            {
     567                bool newRotateFromCenterPointAndObjectItself = evt.ControlDown();
     568                bool newRotateFromCenterPoint = evt.ShiftDown() || newRotateFromCenterPointAndObjectItself;
     569                if (newRotateFromCenterPoint != rotateFromCenterPoint)
     570                {
     571                    ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     572                    rotateFromCenterPoint = newRotateFromCenterPoint;
     573                }
     574
     575                Position pos(evt.GetPosition());
     576
     577                if (rotateFromCenterPoint)
     578                    POST_COMMAND(RotateObjectsFromCenterPoint, (g_SelectedObjects, pos, newRotateFromCenterPointAndObjectItself));
     579                else
     580                    POST_COMMAND(RotateObject, (g_SelectedObjects, pos));
     581
     582                return true;
     583            }
     584
     585            return false;
     586        }
     587
     588        bool OnKey(TransformObject* obj, wxKeyEvent& evt, KeyEventType type)
     589        {
     590            if (type == KEY_UP && evt.GetKeyCode() == WXK_ESCAPE)
     591            {
     592                // Cancel move action
     593                ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     594                ScenarioEditor::GetCommandProc().Undo();
     595                SET_STATE(Waiting);
     596
     597                return true;
     598            }
     599
     600            return false;
     601        }
     602    }
     603    Rotating;
    558604};
    559605
    560606IMPLEMENT_DYNAMIC_CLASS(TransformObject, StateDrivenTool<TransformObject>);
  • source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    765815};
    766816END_COMMAND(MoveObjects)
    767817
     818BEGIN_COMMAND(RotateObjectsFromCenterPoint)
     819{
     820    typedef std::map<entity_id_t, CVector3D> ObjectPositionMap;
     821    typedef std::map<entity_id_t, float> ObjectAngleMap;
     822    ObjectPositionMap m_PosOld, m_PosNew;
     823    ObjectAngleMap m_AngleOld, m_AngleNew;
     824    CVector3D m_centerPoint = CVector3D(0,0,0);
     825    float m_angleInitialRotation;
    768826
     827    void Do()
     828    {
     829        std::vector<entity_id_t> ids = *msg->ids;
     830
     831        CVector3D minPos;
     832        CVector3D maxPos;
     833
     834        //getting min position and max position
     835        for (size_t i = 0; i < ids.size(); ++i)
     836        {
     837            entity_id_t id = (entity_id_t)ids[i];
     838
     839            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     840            if (!cmpPosition)
     841                continue;
     842
     843            CVector3D pos = cmpPosition->GetPosition();
     844
     845            m_PosOld[id] = cmpPosition->GetPosition();
     846            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     847
     848            if (i == 0) {
     849                minPos = pos;
     850                maxPos = pos;
     851                m_centerPoint.Y = pos.Y;
     852                continue;
     853            }
     854
     855            if (pos.X < minPos.X)
     856                minPos.X = pos.X;
     857
     858            if (pos.X > maxPos.X)
     859                maxPos.X = pos.X;
     860
     861            if (pos.Z < minPos.Z)
     862                minPos.Z = pos.Z;
     863
     864            if (pos.Z > maxPos.Z)
     865                maxPos.Z = pos.Z;
     866        }
     867
     868        //Calculate objects center point
     869        m_centerPoint.X = maxPos.X - ((maxPos.X - minPos.X) * 0.5);
     870        m_centerPoint.Z = maxPos.Z - ((maxPos.Z - minPos.Z) * 0.5);
     871
     872        CVector3D target = msg->target->GetWorldSpace(m_centerPoint.Y);
     873        m_angleInitialRotation = atan2(target.X-m_centerPoint.X, target.Z-m_centerPoint.Z);
     874    }
     875
     876    void SetPos(ObjectPositionMap position)
     877    {
     878        ObjectPositionMap::iterator it;
     879        for (it = position.begin(); it != position.end(); ++it)
     880        {
     881            entity_id_t id = (entity_id_t)it->first;
     882            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     883            if (!cmpPosition)
     884                return;
     885
     886            // Set 2D position, ignoring height
     887            CVector3D pos = it->second;
     888            cmpPosition->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
     889
     890            if (msg->rotateObject)
     891                cmpPosition->SetYRotation(entity_angle_t::FromFloat(m_AngleNew[id]));
     892
     893        }
     894
     895        for (it = position.begin(); it != position.end(); ++it)
     896        {
     897            entity_id_t id = (entity_id_t)it->first;
     898            // Check build Constraint
     899            CheckObstructionAndUpdateVisual(id);
     900        }
     901    }
     902
     903    void Redo()
     904    {
     905        SetPos(m_PosNew);
     906    }
     907
     908    void RecalculateRotation(Position newPoint)
     909    {
     910        std::vector<entity_id_t> ids = *msg->ids;
     911
     912        CVector3D target = newPoint.GetWorldSpace(m_centerPoint.Y);
     913        float newAngle = atan2(target.X-m_centerPoint.X, target.Z-m_centerPoint.Z);
     914
     915        float globalAngle = m_angleInitialRotation - newAngle;
     916
     917        //Recalculate positions
     918        for (size_t i = 0; i < ids.size(); ++i)
     919        {
     920            entity_id_t id = (entity_id_t)ids[i];
     921
     922            CVector3D pos = m_PosOld[id];
     923            float angle = atan2(pos.X - m_centerPoint.X, pos.Z - m_centerPoint.Z);
     924            float localAngle = angle + (globalAngle - angle);
     925            float xCos = cosf(localAngle);
     926            float xSin = sinf(localAngle);
     927
     928            pos.X -= m_centerPoint.X;
     929            pos.Z -= m_centerPoint.Z;
     930
     931            float newX = pos.X * xCos - pos.Z * xSin;
     932            float newZ = pos.X * xSin + pos.Z * xCos;
     933
     934            pos.X = newX + m_centerPoint.X;
     935            pos.Z = newZ + m_centerPoint.Z;
     936
     937            m_PosNew[id] = pos;
     938
     939            float oldAngle = m_AngleOld[id];
     940            m_AngleNew[id] = oldAngle - globalAngle;
     941        }
     942
     943        SetPos(m_PosNew);
     944    }
     945
     946    void Undo()
     947    {
     948        SetPos(m_PosOld);
     949    }
     950
     951    void MergeIntoPrevious(cRotateObjectsFromCenterPoint* prev)
     952    {
     953        // TODO: do something valid if prev unit != this unit
     954        ENSURE(*prev->msg->ids == *msg->ids);
     955        m_PosOld = prev->m_PosOld;
     956        m_angleInitialRotation = prev->m_angleInitialRotation;
     957        m_AngleOld = prev->m_AngleOld;
     958        m_centerPoint = prev->m_centerPoint;
     959
     960        RecalculateRotation(msg->target);
     961    }
     962};
     963END_COMMAND(RotateObjectsFromCenterPoint)
     964
    769965BEGIN_COMMAND(RotateObject)
    770966{
    771     float m_AngleOld, m_AngleNew;
     967    typedef std::map<entity_id_t, float> ObjectAngleMap;
     968    ObjectAngleMap m_AngleOld, m_AngleNew;
    772969
    773970    void Do()
    774971    {
    775         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    776         if (!cmpPosition)
    777             return;
     972        std::vector<entity_id_t> ids = *msg->ids;
    778973
    779         m_AngleOld = cmpPosition->GetRotation().Y.ToFloat();
    780         if (msg->usetarget)
     974        for (size_t i = 0; i < ids.size(); ++i)
    781975        {
     976            entity_id_t id = (entity_id_t)ids[i];
     977
     978            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     979            if (!cmpPosition)
     980                return;
     981
     982            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     983
    782984            CMatrix3D transform = cmpPosition->GetInterpolatedTransform(0.f);
    783985            CVector3D pos = transform.GetTranslation();
    784986            CVector3D target = msg->target->GetWorldSpace(pos.Y);
    785             m_AngleNew = atan2(target.X-pos.X, target.Z-pos.Z);
     987            m_AngleNew[id] = atan2(target.X-pos.X, target.Z-pos.Z);
    786988        }
    787         else
    788         {
    789             m_AngleNew = msg->angle;
    790         }
    791989
    792990        SetAngle(m_AngleNew);
    793991    }
    794992
    795     void SetAngle(float angle)
     993    void SetAngle(ObjectAngleMap angles)
    796994    {
    797         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    798         if (!cmpPosition)
    799             return;
     995        ObjectAngleMap::iterator it;
     996        for (it = angles.begin(); it != angles.end(); ++it)
     997        {
     998            entity_id_t id = (entity_id_t)it->first;
     999            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     1000            if (!cmpPosition)
     1001                return;
    8001002
    801         cmpPosition->SetYRotation(entity_angle_t::FromFloat(angle));
     1003            cmpPosition->SetYRotation(entity_angle_t::FromFloat(it->second));
     1004        }
    8021005    }
    8031006
    8041007    void Redo()
     
    8141017    void MergeIntoPrevious(cRotateObject* prev)
    8151018    {
    8161019        // TODO: do something valid if prev unit != this unit
    817         ENSURE(prev->msg->id == msg->id);
     1020        ENSURE(*prev->msg->ids == *msg->ids);
    8181021        prev->m_AngleNew = m_AngleNew;
    8191022    }
    8201023};
  • source/tools/atlas/GameInterface/Messages.h

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    579585        ((Position, pos))
    580586        );
    581587
     588COMMAND(RotateObjectsFromCenterPoint, MERGE,
     589        ((std::vector<ObjectID>, ids))
     590        ((Position, target))
     591        ((bool, rotateObject))
     592        );
     593
    582594COMMAND(RotateObject, MERGE,
    583         ((ObjectID, id))
    584         ((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
     595        ((std::vector<ObjectID>, ids))
    585596        ((Position, target))
    586         ((float, angle))
    587597        );
    588598
    589599COMMAND(DeleteObjects, NOMERGE,