Ticket #1213: 1213.diff

File 1213.diff, 9.3 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.size() > 0 && ((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())
     
    555560        }
    556561    }
    557562    Pasting;
     563
     564    struct sRotating : public State
     565    {
     566        bool rotateFromCenterPoint = false;
     567        bool OnMouse(TransformObject* obj, wxMouseEvent& evt)
     568        {
     569            if (evt.RightUp())
     570            {
     571                bool canPlaceObjectResponse = false;
     572               
     573                while (!canPlaceObjectResponse) {
     574                    AtlasMessage::qCanPlaceObject canPlaceObject;
     575                    canPlaceObject.Post();
     576                    canPlaceObjectResponse = canPlaceObject.response;
     577                    if (!canPlaceObjectResponse)
     578                    {
     579                        ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     580                        ScenarioEditor::GetCommandProc().Undo();
     581                    }
     582                }
     583                SET_STATE(Waiting);
     584                return true;
     585            }
     586            else if (evt.Dragging())
     587            {
     588                bool newRotateFromCenterPoint = wxGetKeyState(SELECTION_ADD_HOTKEY);
     589                if (newRotateFromCenterPoint != rotateFromCenterPoint)
     590                {
     591                    ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     592                    rotateFromCenterPoint = newRotateFromCenterPoint;
     593                }
     594
     595                Position pos(evt.GetPosition());
     596
     597                if (rotateFromCenterPoint)
     598                    POST_COMMAND(RotateObjectsFromCenterPoint, (g_SelectedObjects, pos));
     599                else
     600                    POST_COMMAND(RotateObject, (g_SelectedObjects, pos));
     601
     602                return true;
     603            }
     604            else
     605                return false;
     606        }
     607
     608        bool OnKey(TransformObject* obj, wxKeyEvent& evt, KeyEventType type)
     609        {
     610            if (type == KEY_UP && evt.GetKeyCode() == WXK_ESCAPE)
     611            {
     612                // Cancel move action
     613                ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     614                ScenarioEditor::GetCommandProc().Undo();
     615                SET_STATE(Waiting);
     616
     617                return true;
     618            }
     619            else
     620                return false;
     621        }
     622    }
     623    Rotating;
    558624};
    559625
    560626IMPLEMENT_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
     
    765832};
    766833END_COMMAND(MoveObjects)
    767834
     835BEGIN_COMMAND(RotateObjectsFromCenterPoint)
     836{
     837    typedef std::map<entity_id_t, CVector3D> ObjectPositionMap;
     838    ObjectPositionMap m_PosOld, m_PosNew;
     839    CVector3D m_centerPoint = CVector3D(0,0,0);
     840    float m_angleInitialRotation;
    768841
     842    void Do()
     843    {
     844        std::vector<entity_id_t> ids = *msg->ids;
     845
     846        CVector3D minPos;
     847        CVector3D maxPos;
     848
     849        //getting min position and max position
     850        for (size_t i = 0; i < ids.size(); ++i)
     851        {
     852            entity_id_t id = (entity_id_t)ids[i];
     853
     854            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     855            if (!cmpPosition)
     856                continue;
     857
     858            CVector3D pos = cmpPosition->GetPosition();
     859
     860            m_PosOld[id] = cmpPosition->GetPosition();
     861
     862            if (i == 0) {
     863                minPos = pos;
     864                maxPos = pos;
     865                m_centerPoint.Y = pos.Y;
     866                continue;
     867            }
     868
     869            if (pos.X < minPos.X)
     870                minPos.X = pos.X;
     871
     872            if (pos.X > maxPos.X)
     873                maxPos.X = pos.X;
     874
     875            if (pos.Z < minPos.Z)
     876                minPos.Z = pos.Z;
     877
     878            if (pos.Z > maxPos.Z)
     879                maxPos.Z = pos.Z;
     880        }
     881
     882        //Calculate objects center point
     883        m_centerPoint.X = maxPos.X - ((maxPos.X - minPos.X) * 0.5);
     884        m_centerPoint.Z = maxPos.Z - ((maxPos.Z - minPos.Z) * 0.5);
     885
     886        CVector3D target = msg->target->GetWorldSpace(m_centerPoint.Y);
     887        m_angleInitialRotation = atan2(target.X-m_centerPoint.X, target.Z-m_centerPoint.Z);
     888    }
     889
     890    void SetPos(ObjectPositionMap position)
     891    {
     892        ObjectPositionMap::iterator it;
     893        for (it = position.begin(); it != position.end(); ++it)
     894        {
     895            entity_id_t id = (entity_id_t)it->first;
     896            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     897            if (!cmpPosition)
     898                return;
     899
     900            // Set 2D position, ignoring height
     901            CVector3D pos = it->second;
     902            cmpPosition->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
     903        }
     904
     905        for (it = position.begin(); it != position.end(); ++it)
     906        {
     907            entity_id_t id = (entity_id_t)it->first;
     908            //Check build Constraint
     909            CheckObstructionAndUpdateVisual(id);
     910        }
     911    }
     912
     913    void Redo()
     914    {
     915        SetPos(m_PosNew);
     916    }
     917
     918    void RecalculateRotation(Position newPoint)
     919    {
     920        std::vector<entity_id_t> ids = *msg->ids;
     921
     922        CVector3D target = newPoint.GetWorldSpace(m_centerPoint.Y);
     923        float newAngle = atan2(target.X-m_centerPoint.X, target.Z-m_centerPoint.Z);
     924
     925        float globalAngle = m_angleInitialRotation - newAngle;
     926
     927        //Recalculate positions
     928        for (size_t i = 0; i < ids.size(); ++i)
     929        {
     930            entity_id_t id = (entity_id_t)ids[i];
     931
     932            CVector3D pos = m_PosOld[id];
     933            float angle = atan2(pos.X - m_centerPoint.X, pos.Z - m_centerPoint.Z);
     934            float localAngle = angle + (globalAngle - angle);
     935            float xCos = cosf(localAngle);
     936            float xSin = sinf(localAngle);
     937
     938            pos.X -= m_centerPoint.X;
     939            pos.Z -= m_centerPoint.Z;
     940
     941            float newX = pos.X * xCos - pos.Z * xSin;
     942            float newZ = pos.X * xSin + pos.Z * xCos;
     943
     944            pos.X = newX + m_centerPoint.X;
     945            pos.Z = newZ + m_centerPoint.Z;
     946
     947            m_PosNew[id] = pos;
     948        }
     949
     950        SetPos(m_PosNew);
     951    }
     952
     953    void Undo()
     954    {
     955        SetPos(m_PosOld);
     956    }
     957
     958    void MergeIntoPrevious(cRotateObjectsFromCenterPoint* prev)
     959    {
     960        // TODO: do something valid if prev unit != this unit
     961        ENSURE(*prev->msg->ids == *msg->ids);
     962        m_PosOld = prev->m_PosOld;
     963        m_angleInitialRotation = prev->m_angleInitialRotation;
     964        m_centerPoint = prev->m_centerPoint;
     965
     966        RecalculateRotation(msg->target);
     967    }
     968};
     969END_COMMAND(RotateObjectsFromCenterPoint)
     970
    769971BEGIN_COMMAND(RotateObject)
    770972{
    771     float m_AngleOld, m_AngleNew;
     973    typedef std::map<entity_id_t, float> ObjectAngleMap;
     974    ObjectAngleMap m_AngleOld, m_AngleNew;
    772975
    773976    void Do()
    774977    {
    775         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    776         if (!cmpPosition)
    777             return;
     978        std::vector<entity_id_t> ids = *msg->ids;
    778979
    779         m_AngleOld = cmpPosition->GetRotation().Y.ToFloat();
    780         if (msg->usetarget)
     980        for (size_t i = 0; i < ids.size(); ++i)
    781981        {
     982            entity_id_t id = (entity_id_t)ids[i];
     983
     984            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     985            if (!cmpPosition)
     986                return;
     987
     988            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     989
    782990            CMatrix3D transform = cmpPosition->GetInterpolatedTransform(0.f);
    783991            CVector3D pos = transform.GetTranslation();
    784992            CVector3D target = msg->target->GetWorldSpace(pos.Y);
    785             m_AngleNew = atan2(target.X-pos.X, target.Z-pos.Z);
     993            m_AngleNew[id] = atan2(target.X-pos.X, target.Z-pos.Z);
    786994        }
    787         else
    788         {
    789             m_AngleNew = msg->angle;
    790         }
    791995
    792996        SetAngle(m_AngleNew);
    793997    }
    794998
    795     void SetAngle(float angle)
     999    void SetAngle(ObjectAngleMap angles)
    7961000    {
    797         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    798         if (!cmpPosition)
    799             return;
     1001        ObjectAngleMap::iterator it;
     1002        for (it = angles.begin(); it != angles.end(); ++it)
     1003        {
     1004            entity_id_t id = (entity_id_t)it->first;
     1005            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     1006            if (!cmpPosition)
     1007                return;
    8001008
    801         cmpPosition->SetYRotation(entity_angle_t::FromFloat(angle));
     1009            cmpPosition->SetYRotation(entity_angle_t::FromFloat(it->second));
     1010        }
    8021011    }
    8031012
    8041013    void Redo()
     
    8141023    void MergeIntoPrevious(cRotateObject* prev)
    8151024    {
    8161025        // TODO: do something valid if prev unit != this unit
    817         ENSURE(prev->msg->id == msg->id);
     1026        ENSURE(*prev->msg->ids == *msg->ids);
    8181027        prev->m_AngleNew = m_AngleNew;
    8191028    }
    8201029};
  • 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
     
    579588        ((Position, pos))
    580589        );
    581590
     591COMMAND(RotateObjectsFromCenterPoint, MERGE,
     592        ((std::vector<ObjectID>, ids))
     593        ((Position, target))
     594        );
     595
    582596COMMAND(RotateObject, MERGE,
    583         ((ObjectID, id))
    584         ((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
     597        ((std::vector<ObjectID>, ids))
    585598        ((Position, target))
    586         ((float, angle))
    587599        );
    588600
    589601COMMAND(DeleteObjects, NOMERGE,