Ticket #1213: 1213.7.diff

File 1213.7.diff, 8.9 KB (added by trompetin17, 9 years ago)

Change Ctrl behavior

  • 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

     
    811813};
    812814END_COMMAND(MoveObjects)
    813815
     816BEGIN_COMMAND(RotateObjectsFromCenterPoint)
     817{
     818    typedef std::map<entity_id_t, CVector3D> ObjectPositionMap;
     819    typedef std::map<entity_id_t, float> ObjectAngleMap;
     820    ObjectPositionMap m_PosOld, m_PosNew;
     821    ObjectAngleMap m_AngleOld, m_AngleNew;
     822    CVector3D m_CenterPoint;
     823    float m_AngleInitialRotation;
    814824
     825    void Do()
     826    {
     827        std::vector<entity_id_t> ids = *msg->ids;
     828
     829        CVector3D minPos;
     830        CVector3D maxPos;
     831
     832        //getting min position and max position
     833        for (size_t i = 0; i < ids.size(); ++i)
     834        {
     835            entity_id_t id = ids[i];
     836
     837            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     838            if (!cmpPosition)
     839                continue;
     840
     841            CVector3D pos = cmpPosition->GetPosition();
     842
     843            m_PosOld[id] = cmpPosition->GetPosition();
     844            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     845
     846            if (i == 0) {
     847                minPos = pos;
     848                maxPos = pos;
     849                m_CenterPoint.Y = pos.Y;
     850                continue;
     851            }
     852
     853            if (pos.X < minPos.X)
     854                minPos.X = pos.X;
     855
     856            if (pos.X > maxPos.X)
     857                maxPos.X = pos.X;
     858
     859            if (pos.Z < minPos.Z)
     860                minPos.Z = pos.Z;
     861
     862            if (pos.Z > maxPos.Z)
     863                maxPos.Z = pos.Z;
     864        }
     865
     866        //Calculate objects center point
     867        m_CenterPoint.X = maxPos.X - ((maxPos.X - minPos.X) * 0.5);
     868        m_CenterPoint.Z = maxPos.Z - ((maxPos.Z - minPos.Z) * 0.5);
     869
     870        CVector3D target = msg->target->GetWorldSpace(m_CenterPoint.Y);
     871        m_AngleInitialRotation = atan2(target.X-m_CenterPoint.X, target.Z-m_CenterPoint.Z);
     872    }
     873
     874    void SetPos(ObjectPositionMap position)
     875    {
     876        ObjectPositionMap::iterator it;
     877        for (it = position.begin(); it != position.end(); ++it)
     878        {
     879            entity_id_t id = it->first;
     880            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     881            if (!cmpPosition)
     882                return;
     883
     884            // Set 2D position, ignoring height
     885            CVector3D pos = it->second;
     886            cmpPosition->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
     887
     888            if (msg->rotateObject)
     889                cmpPosition->SetYRotation(entity_angle_t::FromFloat(m_AngleNew[id]));
     890
     891        }
     892
     893        for (it = position.begin(); it != position.end(); ++it)
     894            CheckObstructionAndUpdateVisual(it->first);
     895    }
     896
     897    void Redo()
     898    {
     899        SetPos(m_PosNew);
     900    }
     901
     902    void RecalculateRotation(Position newPoint)
     903    {
     904        std::vector<entity_id_t> ids = *msg->ids;
     905
     906        CVector3D target = newPoint.GetWorldSpace(m_CenterPoint.Y);
     907        float newAngle = atan2(target.X-m_CenterPoint.X, target.Z-m_CenterPoint.Z);
     908
     909        float globalAngle = m_AngleInitialRotation - newAngle;
     910
     911        //Recalculate positions
     912        for (size_t i = 0; i < ids.size(); ++i)
     913        {
     914            entity_id_t id = ids[i];
     915
     916            CVector3D pos = m_PosOld[id];
     917            float angle = atan2(pos.X - m_CenterPoint.X, pos.Z - m_CenterPoint.Z);
     918            float localAngle = angle + (globalAngle - angle);
     919            float xCos = cosf(localAngle);
     920            float xSin = sinf(localAngle);
     921
     922            pos.X -= m_CenterPoint.X;
     923            pos.Z -= m_CenterPoint.Z;
     924
     925            float newX = pos.X * xCos - pos.Z * xSin;
     926            float newZ = pos.X * xSin + pos.Z * xCos;
     927
     928            pos.X = newX + m_CenterPoint.X;
     929            pos.Z = newZ + m_CenterPoint.Z;
     930
     931            m_PosNew[id] = pos;
     932
     933            m_AngleNew[id] = m_AngleOld[id] - globalAngle;
     934        }
     935
     936        SetPos(m_PosNew);
     937    }
     938
     939    void Undo()
     940    {
     941        SetPos(m_PosOld);
     942    }
     943
     944    void MergeIntoPrevious(cRotateObjectsFromCenterPoint* prev)
     945    {
     946        // TODO: do something valid if prev unit != this unit
     947        ENSURE(*prev->msg->ids == *msg->ids);
     948        m_PosOld = prev->m_PosOld;
     949        m_AngleInitialRotation = prev->m_AngleInitialRotation;
     950        m_AngleOld = prev->m_AngleOld;
     951        m_CenterPoint = prev->m_CenterPoint;
     952
     953        RecalculateRotation(msg->target);
     954    }
     955};
     956END_COMMAND(RotateObjectsFromCenterPoint)
     957
    815958BEGIN_COMMAND(RotateObject)
    816959{
    817     float m_AngleOld, m_AngleNew;
     960    typedef std::map<entity_id_t, float> ObjectAngleMap;
     961    ObjectAngleMap m_AngleOld, m_AngleNew;
    818962
    819963    void Do()
    820964    {
    821         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    822         if (!cmpPosition)
    823             return;
     965        std::vector<entity_id_t> ids = *msg->ids;
    824966
    825         m_AngleOld = cmpPosition->GetRotation().Y.ToFloat();
    826         if (msg->usetarget)
     967        for (size_t i = 0; i < ids.size(); ++i)
    827968        {
     969            entity_id_t id = (entity_id_t)ids[i];
     970
     971            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     972            if (!cmpPosition)
     973                return;
     974
     975            m_AngleOld[id] = cmpPosition->GetRotation().Y.ToFloat();
     976
    828977            CMatrix3D transform = cmpPosition->GetInterpolatedTransform(0.f);
    829978            CVector3D pos = transform.GetTranslation();
    830979            CVector3D target = msg->target->GetWorldSpace(pos.Y);
    831             m_AngleNew = atan2(target.X-pos.X, target.Z-pos.Z);
     980            m_AngleNew[id] = atan2(target.X-pos.X, target.Z-pos.Z);
    832981        }
    833         else
    834         {
    835             m_AngleNew = msg->angle;
    836         }
    837982
    838983        SetAngle(m_AngleNew);
    839984    }
    840985
    841     void SetAngle(float angle)
     986    void SetAngle(ObjectAngleMap angles)
    842987    {
    843         CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)msg->id);
    844         if (!cmpPosition)
    845             return;
     988        ObjectAngleMap::iterator it;
     989        for (it = angles.begin(); it != angles.end(); ++it)
     990        {
     991            entity_id_t id = (entity_id_t)it->first;
     992            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     993            if (!cmpPosition)
     994                return;
    846995
    847         cmpPosition->SetYRotation(entity_angle_t::FromFloat(angle));
     996            cmpPosition->SetYRotation(entity_angle_t::FromFloat(it->second));
     997        }
    848998    }
    849999
    8501000    void Redo()
     
    8601010    void MergeIntoPrevious(cRotateObject* prev)
    8611011    {
    8621012        // TODO: do something valid if prev unit != this unit
    863         ENSURE(prev->msg->id == msg->id);
     1013        ENSURE(*prev->msg->ids == *msg->ids);
    8641014        prev->m_AngleNew = m_AngleNew;
    8651015    }
    8661016};
  • 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,