Ticket #1213: 1213.8.diff

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

     
    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())
     
    556550        }
    557551    }
    558552    Pasting;
     553
     554    struct sRotating : public State
     555    {
     556        bool rotateFromCenterPoint;
     557
     558        void OnEnter(TransformObject* WXUNUSED(obj))
     559        {
     560            rotateFromCenterPoint = true;
     561        }
     562
     563        bool OnMouse(TransformObject* obj, wxMouseEvent& evt)
     564        {
     565            if (evt.RightUp())
     566            {
     567                POST_MESSAGE(ResetSelectionColor, ());
     568                SET_STATE(Waiting);
     569                return true;
     570            }
     571            else if (evt.Dragging())
     572            {
     573                bool newRotateFromCenterPointAndObjectItself = !evt.ControlDown() && !evt.ShiftDown();
     574                bool newRotateFromCenterPoint = evt.ShiftDown() || newRotateFromCenterPointAndObjectItself;
     575                if (newRotateFromCenterPoint != rotateFromCenterPoint)
     576                {
     577                    ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     578                    rotateFromCenterPoint = newRotateFromCenterPoint;
     579                }
     580
     581                Position pos(evt.GetPosition());
     582
     583                if (rotateFromCenterPoint)
     584                    POST_COMMAND(RotateObjectsFromCenterPoint, (g_SelectedObjects, pos, newRotateFromCenterPointAndObjectItself));
     585                else
     586                    POST_COMMAND(RotateObject, (g_SelectedObjects, pos));
     587
     588                return true;
     589            }
     590
     591            return false;
     592        }
     593
     594        bool OnKey(TransformObject* obj, wxKeyEvent& evt, KeyEventType type)
     595        {
     596            if (type == KEY_UP && evt.GetKeyCode() == WXK_ESCAPE)
     597            {
     598                // Cancel move action
     599                ScenarioEditor::GetCommandProc().FinaliseLastCommand();
     600                ScenarioEditor::GetCommandProc().Undo();
     601                SET_STATE(Waiting);
     602
     603                return true;
     604            }
     605
     606            return false;
     607        }
     608    }
     609    Rotating;
    559610};
    560611
    561612IMPLEMENT_DYNAMIC_CLASS(TransformObject, StateDrivenTool<TransformObject>);
  • source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp

     
    811837};
    812838END_COMMAND(MoveObjects)
    813839
     840BEGIN_COMMAND(RotateObjectsFromCenterPoint)
     841{
     842    typedef std::map<entity_id_t, CVector3D> ObjectPositionMap;
     843    typedef std::map<entity_id_t, float> ObjectAngleMap;
     844    ObjectPositionMap m_PosOld, m_PosNew;
     845    ObjectAngleMap m_AngleOld, m_AngleNew;
     846    CVector3D m_CenterPoint;
     847    float m_AngleInitialRotation;
    814848
     849    void Do()
     850    {
     851        std::vector<entity_id_t> ids = *msg->ids;
     852
     853        CVector3D minPos;
     854        CVector3D maxPos;
     855
     856        //getting min position and max position
     857        for (size_t i = 0; i < ids.size(); ++i)
     858        {
     859            entity_id_t id = ids[i];
     860
     861            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     862            if (!cmpPosition)
     863                continue;
     864
     865            CVector3D pos = cmpPosition->GetPosition();
     866
     867            m_PosOld[id] = cmpPosition->GetPosition();
     868            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     869
     870            if (i == 0) {
     871                minPos = pos;
     872                maxPos = pos;
     873                m_CenterPoint.Y = pos.Y;
     874                continue;
     875            }
     876
     877            if (pos.X < minPos.X)
     878                minPos.X = pos.X;
     879
     880            if (pos.X > maxPos.X)
     881                maxPos.X = pos.X;
     882
     883            if (pos.Z < minPos.Z)
     884                minPos.Z = pos.Z;
     885
     886            if (pos.Z > maxPos.Z)
     887                maxPos.Z = pos.Z;
     888        }
     889
     890        //Calculate objects center point
     891        m_CenterPoint.X = maxPos.X - ((maxPos.X - minPos.X) * 0.5);
     892        m_CenterPoint.Z = maxPos.Z - ((maxPos.Z - minPos.Z) * 0.5);
     893
     894        CVector3D target = msg->target->GetWorldSpace(m_CenterPoint.Y);
     895        m_AngleInitialRotation = atan2(target.X-m_CenterPoint.X, target.Z-m_CenterPoint.Z);
     896    }
     897
     898    void SetPos(ObjectPositionMap position, ObjectAngleMap angle)
     899    {
     900        ObjectPositionMap::iterator it;
     901        for (it = position.begin(); it != position.end(); ++it)
     902        {
     903            entity_id_t id = it->first;
     904            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     905            if (!cmpPosition)
     906                return;
     907
     908            // Set 2D position, ignoring height
     909            CVector3D pos = it->second;
     910            cmpPosition->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
     911
     912            if (msg->rotateObject)
     913                cmpPosition->SetYRotation(entity_angle_t::FromFloat(angle[id]));
     914
     915        }
     916
     917        for (it = position.begin(); it != position.end(); ++it)
     918            CheckObstructionAndUpdateVisual(it->first);
     919    }
     920
     921    void Redo()
     922    {
     923        SetPos(m_PosNew, m_AngleNew);
     924    }
     925
     926    void RecalculateRotation(Position newPoint)
     927    {
     928        std::vector<entity_id_t> ids = *msg->ids;
     929
     930        CVector3D target = newPoint.GetWorldSpace(m_CenterPoint.Y);
     931        float newAngle = atan2(target.X-m_CenterPoint.X, target.Z-m_CenterPoint.Z);
     932
     933        float globalAngle = m_AngleInitialRotation - newAngle;
     934
     935        //Recalculate positions
     936        for (size_t i = 0; i < ids.size(); ++i)
     937        {
     938            entity_id_t id = ids[i];
     939
     940            CVector3D pos = m_PosOld[id];
     941            float angle = atan2(pos.X - m_CenterPoint.X, pos.Z - m_CenterPoint.Z);
     942            float localAngle = angle + (globalAngle - angle);
     943            float xCos = cosf(localAngle);
     944            float xSin = sinf(localAngle);
     945
     946            pos.X -= m_CenterPoint.X;
     947            pos.Z -= m_CenterPoint.Z;
     948
     949            float newX = pos.X * xCos - pos.Z * xSin;
     950            float newZ = pos.X * xSin + pos.Z * xCos;
     951
     952            pos.X = newX + m_CenterPoint.X;
     953            pos.Z = newZ + m_CenterPoint.Z;
     954
     955            m_PosNew[id] = pos;
     956
     957            m_AngleNew[id] = m_AngleOld[id] - globalAngle;
     958        }
     959
     960        SetPos(m_PosNew, m_AngleNew);
     961    }
     962
     963    void Undo()
     964    {
     965        SetPos(m_PosOld, m_AngleOld);
     966    }
     967
     968    void MergeIntoPrevious(cRotateObjectsFromCenterPoint* prev)
     969    {
     970        // TODO: do something valid if prev unit != this unit
     971        ENSURE(*prev->msg->ids == *msg->ids);
     972        m_PosOld = prev->m_PosOld;
     973        m_AngleInitialRotation = prev->m_AngleInitialRotation;
     974        m_AngleOld = prev->m_AngleOld;
     975        m_CenterPoint = prev->m_CenterPoint;
     976
     977        RecalculateRotation(msg->target);
     978    }
     979};
     980END_COMMAND(RotateObjectsFromCenterPoint)
     981
    815982BEGIN_COMMAND(RotateObject)
    816983{
    817     float m_AngleOld, m_AngleNew;
     984    typedef std::map<entity_id_t, float> ObjectAngleMap;
     985    ObjectAngleMap m_AngleOld, m_AngleNew;
    818986
    819987    void Do()
    820988    {
    821         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    822         if (!cmpPosition)
    823             return;
     989        std::vector<entity_id_t> ids = *msg->ids;
    824990
    825         m_AngleOld = cmpPosition->GetRotation().Y.ToFloat();
    826         if (msg->usetarget)
     991        for (size_t i = 0; i < ids.size(); ++i)
    827992        {
     993            entity_id_t id = (entity_id_t)ids[i];
     994
     995            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     996            if (!cmpPosition)
     997                return;
     998
     999            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     1000
    8281001            CMatrix3D transform = cmpPosition->GetInterpolatedTransform(0.f);
    8291002            CVector3D pos = transform.GetTranslation();
    8301003            CVector3D target = msg->target->GetWorldSpace(pos.Y);
    831             m_AngleNew = atan2(target.X-pos.X, target.Z-pos.Z);
     1004            m_AngleNew[id] = atan2(target.X-pos.X, target.Z-pos.Z);
    8321005        }
    833         else
    834         {
    835             m_AngleNew = msg->angle;
    836         }
    8371006
    8381007        SetAngle(m_AngleNew);
    8391008    }
    8401009
    841     void SetAngle(float angle)
     1010    void SetAngle(ObjectAngleMap angles)
    8421011    {
    843         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    844         if (!cmpPosition)
    845             return;
     1012        ObjectAngleMap::iterator it;
     1013        for (it = angles.begin(); it != angles.end(); ++it)
     1014        {
     1015            entity_id_t id = (entity_id_t)it->first;
     1016            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     1017            if (!cmpPosition)
     1018                return;
    8461019
    847         cmpPosition->SetYRotation(entity_angle_t::FromFloat(angle));
     1020            cmpPosition->SetYRotation(entity_angle_t::FromFloat(it->second));
     1021        }
    8481022    }
    8491023
    8501024    void Redo()
     
    8601034    void MergeIntoPrevious(cRotateObject* prev)
    8611035    {
    8621036        // TODO: do something valid if prev unit != this unit
    863         ENSURE(prev->msg->id == msg->id);
     1037        ENSURE(*prev->msg->ids == *msg->ids);
    8641038        prev->m_AngleNew = m_AngleNew;
    8651039    }
    8661040};
  • source/tools/atlas/GameInterface/Messages.h

     
    581596        ((Position, pos))
    582597        );
    583598
     599COMMAND(RotateObjectsFromCenterPoint, MERGE,
     600        ((std::vector<ObjectID>, ids))
     601        ((Position, target))
     602        ((bool, rotateObject))
     603        );
     604
    584605COMMAND(RotateObject, MERGE,
    585         ((ObjectID, id))
    586         ((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
     606        ((std::vector<ObjectID>, ids))
    587607        ((Position, target))
    588         ((float, angle))
    589608        );
    590609
    591610COMMAND(DeleteObjects, NOMERGE,