Ticket #1213: 1213.3.diff

File 1213.3.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())
     
    555549        }
    556550    }
    557551    Pasting;
     552
     553    struct sRotating : public State
     554    {
     555        bool rotateFromCenterPoint = false;
     556        bool OnMouse(TransformObject* obj, wxMouseEvent& evt)
     557        {
     558            if (evt.RightUp())
     559            {
     560                SET_STATE(Waiting);
     561                return true;
     562            }
     563            else if (evt.Dragging())
     564            {
     565                bool newRotateFromCenterPointAndObjectItself = evt.ControlDown();
     566                bool newRotateFromCenterPoint = evt.ShiftDown() || newRotateFromCenterPointAndObjectItself;
     567                if (newRotateFromCenterPoint != rotateFromCenterPoint)
     568                {
     569                    ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     570                    rotateFromCenterPoint = newRotateFromCenterPoint;
     571                }
     572
     573                Position pos(evt.GetPosition());
     574
     575                if (rotateFromCenterPoint)
     576                    POST_COMMAND(RotateObjectsFromCenterPoint, (g_SelectedObjects, pos, newRotateFromCenterPointAndObjectItself));
     577                else
     578                    POST_COMMAND(RotateObject, (g_SelectedObjects, pos));
     579
     580                return true;
     581            }
     582
     583            return false;
     584        }
     585
     586        bool OnKey(TransformObject* obj, wxKeyEvent& evt, KeyEventType type)
     587        {
     588            if (type == KEY_UP && evt.GetKeyCode() == WXK_ESCAPE)
     589            {
     590                // Cancel move action
     591                ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     592                ScenarioEditor::GetCommandProc().Undo();
     593                SET_STATE(Waiting);
     594
     595                return true;
     596            }
     597
     598            return false;
     599        }
     600    }
     601    Rotating;
    558602};
    559603
    560604IMPLEMENT_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
     
    765803};
    766804END_COMMAND(MoveObjects)
    767805
     806BEGIN_COMMAND(RotateObjectsFromCenterPoint)
     807{
     808    typedef std::map<entity_id_t, CVector3D> ObjectPositionMap;
     809    typedef std::map<entity_id_t, float> ObjectAngleMap;
     810    ObjectPositionMap m_PosOld, m_PosNew;
     811    ObjectAngleMap m_AngleOld, m_AngleNew;
     812    CVector3D m_centerPoint = CVector3D(0,0,0);
     813    float m_angleInitialRotation;
    768814
     815    void Do()
     816    {
     817        std::vector<entity_id_t> ids = *msg->ids;
     818
     819        CVector3D minPos;
     820        CVector3D maxPos;
     821
     822        //getting min position and max position
     823        for (size_t i = 0; i < ids.size(); ++i)
     824        {
     825            entity_id_t id = (entity_id_t)ids[i];
     826
     827            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     828            if (!cmpPosition)
     829                continue;
     830
     831            CVector3D pos = cmpPosition->GetPosition();
     832
     833            m_PosOld[id] = cmpPosition->GetPosition();
     834            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     835
     836            if (i == 0) {
     837                minPos = pos;
     838                maxPos = pos;
     839                m_centerPoint.Y = pos.Y;
     840                continue;
     841            }
     842
     843            if (pos.X < minPos.X)
     844                minPos.X = pos.X;
     845
     846            if (pos.X > maxPos.X)
     847                maxPos.X = pos.X;
     848
     849            if (pos.Z < minPos.Z)
     850                minPos.Z = pos.Z;
     851
     852            if (pos.Z > maxPos.Z)
     853                maxPos.Z = pos.Z;
     854        }
     855
     856        //Calculate objects center point
     857        m_centerPoint.X = maxPos.X - ((maxPos.X - minPos.X) * 0.5);
     858        m_centerPoint.Z = maxPos.Z - ((maxPos.Z - minPos.Z) * 0.5);
     859
     860        CVector3D target = msg->target->GetWorldSpace(m_centerPoint.Y);
     861        m_angleInitialRotation = atan2(target.X-m_centerPoint.X, target.Z-m_centerPoint.Z);
     862    }
     863
     864    void SetPos(ObjectPositionMap position)
     865    {
     866        ObjectPositionMap::iterator it;
     867        for (it = position.begin(); it != position.end(); ++it)
     868        {
     869            entity_id_t id = (entity_id_t)it->first;
     870            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     871            if (!cmpPosition)
     872                return;
     873
     874            // Set 2D position, ignoring height
     875            CVector3D pos = it->second;
     876            cmpPosition->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
     877
     878            if (msg->rotateObject)
     879                cmpPosition->SetYRotation(entity_angle_t::FromFloat(m_AngleNew[id]));
     880
     881        }
     882
     883        for (it = position.begin(); it != position.end(); ++it)
     884        {
     885            entity_id_t id = (entity_id_t)it->first;
     886            // Check build Constraint
     887            CheckObstructionAndUpdateVisual(id);
     888        }
     889    }
     890
     891    void Redo()
     892    {
     893        SetPos(m_PosNew);
     894    }
     895
     896    void RecalculateRotation(Position newPoint)
     897    {
     898        std::vector<entity_id_t> ids = *msg->ids;
     899
     900        CVector3D target = newPoint.GetWorldSpace(m_centerPoint.Y);
     901        float newAngle = atan2(target.X-m_centerPoint.X, target.Z-m_centerPoint.Z);
     902
     903        float globalAngle = m_angleInitialRotation - newAngle;
     904
     905        //Recalculate positions
     906        for (size_t i = 0; i < ids.size(); ++i)
     907        {
     908            entity_id_t id = (entity_id_t)ids[i];
     909
     910            CVector3D pos = m_PosOld[id];
     911            float angle = atan2(pos.X - m_centerPoint.X, pos.Z - m_centerPoint.Z);
     912            float localAngle = angle + (globalAngle - angle);
     913            float xCos = cosf(localAngle);
     914            float xSin = sinf(localAngle);
     915
     916            pos.X -= m_centerPoint.X;
     917            pos.Z -= m_centerPoint.Z;
     918
     919            float newX = pos.X * xCos - pos.Z * xSin;
     920            float newZ = pos.X * xSin + pos.Z * xCos;
     921
     922            pos.X = newX + m_centerPoint.X;
     923            pos.Z = newZ + m_centerPoint.Z;
     924
     925            m_PosNew[id] = pos;
     926
     927            float oldAngle = m_AngleOld[id];
     928            m_AngleNew[id] = oldAngle - globalAngle;
     929        }
     930
     931        SetPos(m_PosNew);
     932    }
     933
     934    void Undo()
     935    {
     936        SetPos(m_PosOld);
     937    }
     938
     939    void MergeIntoPrevious(cRotateObjectsFromCenterPoint* prev)
     940    {
     941        // TODO: do something valid if prev unit != this unit
     942        ENSURE(*prev->msg->ids == *msg->ids);
     943        m_PosOld = prev->m_PosOld;
     944        m_angleInitialRotation = prev->m_angleInitialRotation;
     945        m_AngleOld = prev->m_AngleOld;
     946        m_centerPoint = prev->m_centerPoint;
     947
     948        RecalculateRotation(msg->target);
     949    }
     950};
     951END_COMMAND(RotateObjectsFromCenterPoint)
     952
    769953BEGIN_COMMAND(RotateObject)
    770954{
    771     float m_AngleOld, m_AngleNew;
     955    typedef std::map<entity_id_t, float> ObjectAngleMap;
     956    ObjectAngleMap m_AngleOld, m_AngleNew;
    772957
    773958    void Do()
    774959    {
    775         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    776         if (!cmpPosition)
    777             return;
     960        std::vector<entity_id_t> ids = *msg->ids;
    778961
    779         m_AngleOld = cmpPosition->GetRotation().Y.ToFloat();
    780         if (msg->usetarget)
     962        for (size_t i = 0; i < ids.size(); ++i)
    781963        {
     964            entity_id_t id = (entity_id_t)ids[i];
     965
     966            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     967            if (!cmpPosition)
     968                return;
     969
     970            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     971
    782972            CMatrix3D transform = cmpPosition->GetInterpolatedTransform(0.f);
    783973            CVector3D pos = transform.GetTranslation();
    784974            CVector3D target = msg->target->GetWorldSpace(pos.Y);
    785             m_AngleNew = atan2(target.X-pos.X, target.Z-pos.Z);
     975            m_AngleNew[id] = atan2(target.X-pos.X, target.Z-pos.Z);
    786976        }
    787         else
    788         {
    789             m_AngleNew = msg->angle;
    790         }
    791977
    792978        SetAngle(m_AngleNew);
    793979    }
    794980
    795     void SetAngle(float angle)
     981    void SetAngle(ObjectAngleMap angles)
    796982    {
    797         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    798         if (!cmpPosition)
    799             return;
     983        ObjectAngleMap::iterator it;
     984        for (it = angles.begin(); it != angles.end(); ++it)
     985        {
     986            entity_id_t id = (entity_id_t)it->first;
     987            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     988            if (!cmpPosition)
     989                return;
    800990
    801         cmpPosition->SetYRotation(entity_angle_t::FromFloat(angle));
     991            cmpPosition->SetYRotation(entity_angle_t::FromFloat(it->second));
     992        }
    802993    }
    803994
    804995    void Redo()
     
    8141005    void MergeIntoPrevious(cRotateObject* prev)
    8151006    {
    8161007        // TODO: do something valid if prev unit != this unit
    817         ENSURE(prev->msg->id == msg->id);
     1008        ENSURE(*prev->msg->ids == *msg->ids);
    8181009        prev->m_AngleNew = m_AngleNew;
    8191010    }
    8201011};
  • 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
     
    579583        ((Position, pos))
    580584        );
    581585
     586COMMAND(RotateObjectsFromCenterPoint, MERGE,
     587        ((std::vector<ObjectID>, ids))
     588        ((Position, target))
     589        ((bool, rotateObject))
     590        );
     591
    582592COMMAND(RotateObject, MERGE,
    583         ((ObjectID, id))
    584         ((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
     593        ((std::vector<ObjectID>, ids))
    585594        ((Position, target))
    586         ((float, angle))
    587595        );
    588596
    589597COMMAND(DeleteObjects, NOMERGE,