Index: source/graphics/CinemaManager.cpp =================================================================== --- source/graphics/CinemaManager.cpp +++ source/graphics/CinemaManager.cpp @@ -114,13 +114,13 @@ for (const std::pair& p : cmpCinemaManager->GetPaths()) { DrawSpline(p.second, CColor(0.2f, 0.2f, 1.f, 0.9f), 100, true); - DrawNodes(p.second, CColor(0.5f, 1.0f, 0.f, 1.0f)); + DrawNodes(p.second, CColor(0.1f, 1.0f, 0.0f, 1.0f)); if (p.second.GetTargetSpline().GetAllNodes().empty()) continue; - DrawSpline(p.second.GetTargetSpline(), CColor(1.0f, 0.2f, 0.2f, 0.9f), 100, true); - DrawNodes(p.second.GetTargetSpline(), CColor(1.0f, 0.5f, 0.f, 1.0f)); + DrawSpline(p.second.GetTargetSpline(), CColor(1.0f, 0.4f, 0.4f, 0.9f), 128, true); + DrawNodes(p.second.GetTargetSpline(), CColor(1.0f, 0.1f, 0.0f, 1.0f)); } } @@ -200,8 +200,9 @@ #warning TODO : implement CCinemaPath on GLES #else + glDisable(GL_DEPTH_TEST); glEnable(GL_POINT_SMOOTH); - glPointSize(5.0f); + glPointSize(7.0f); glColor4f(nodeColor.r, nodeColor.g, nodeColor.b, nodeColor.a); glBegin(GL_POINTS); @@ -211,6 +212,7 @@ glEnd(); glPointSize(1.0f); glDisable(GL_POINT_SMOOTH); + glEnable(GL_DEPTH_TEST); #endif } Index: source/maths/NUSpline.cpp =================================================================== --- source/maths/NUSpline.cpp +++ source/maths/NUSpline.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -216,20 +216,19 @@ } //Inserts node before position -void TNSpline::InsertNode(const int index, const CFixedVector3D& pos, const CFixedVector3D& rotation, fixed timePeriod) +void TNSpline::InsertNode(const int index, const CFixedVector3D& pos, const CFixedVector3D& UNUSED(rotation), fixed timePeriod) { - if (NodeCount >= MAX_SPLINE_NODES || index < NodeCount - 1) + if (NodeCount >= MAX_SPLINE_NODES || index < 0 || index > NodeCount - 1) return; + if (NodeCount == 0) MaxDistance = fixed::Zero(); else - { - Node[NodeCount-1].Distance = timePeriod; - Node[NodeCount-1].Rotation = rotation; - MaxDistance += Node[NodeCount-1].Distance; - } + MaxDistance += timePeriod; + SplineData temp; temp.Position = pos; + temp.Distance = timePeriod; Node.insert(Node.begin() + index, temp); ++NodeCount; } @@ -241,9 +240,7 @@ return; MaxDistance -= Node[index].Distance; - MaxDistance -= Node[index-1].Distance; - Node[index-1].Distance = fixed::Zero(); - Node.erase(Node.begin() + index, Node.begin() + index + 1); + Node.erase(Node.begin() + index); --NodeCount; } Index: source/ps/GameSetup/GameSetup.cpp =================================================================== --- source/ps/GameSetup/GameSetup.cpp +++ source/ps/GameSetup/GameSetup.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -230,6 +230,13 @@ g_Renderer.RenderTextOverlays(); + // If we're in Atlas game view, render special tools + if (g_AtlasGameLoop && g_AtlasGameLoop->view) + { + g_AtlasGameLoop->view->DrawCinemaPathTool(); + ogl_WarnIfError(); + } + if (g_Game && g_Game->IsGameStarted()) g_Game->GetView()->GetCinema()->Render(); Index: source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -571,6 +571,7 @@ toolbar->AddToolButton(_("Smooth"), _("Smooth terrain elevation"), _T("smoothelevation.png"), _T("SmoothElevation"), _T("")/*_T("TerrainSidebar")*/); toolbar->AddToolButton(_("Flatten"), _("Flatten terrain elevation"), _T("flattenelevation.png"), _T("FlattenElevation"), _T("")/*_T("TerrainSidebar")*/); toolbar->AddToolButton(_("Paint Terrain"), _("Paint terrain texture"), _T("paintterrain.png"), _T("PaintTerrain"), _T("")/*_T("TerrainSidebar")*/); + toolbar->AddToolButton(_("Move"), _("Move cinema path nodes"), _T("movepath.png"), _T("TransformPath"), _T("")/*_T("CinemaSidebar")*/); return toolbar; } Index: source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformPath.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformPath.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformPath.cpp @@ -0,0 +1,169 @@ +/* Copyright (C) 2017 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "ScenarioEditor/ScenarioEditor.h" +#include "Common/Tools.h" +#include "Common/Brushes.h" +#include "Common/MiscState.h" +#include "Common/ObjectSettings.h" +#include "GameInterface/Messages.h" +#include +#include +#include +#include + +using AtlasMessage::Position; + +class TransformPath : public StateDrivenTool +{ + DECLARE_DYNAMIC_CLASS(TransformPath); + + wxPoint m_StartPoint; + AtlasMessage::sCinemaPathNode node; + int axis; + +public: + TransformPath() + { + SetState(&Waiting); + } + + void OnDisable() + { + POST_MESSAGE(ClearPathNodePreview, ); + } + + struct sWaiting : public State + { + bool OnMouse(TransformPath* obj, wxMouseEvent& evt) + { + if (evt.LeftDown()) + { + ScenarioEditor::GetCommandProc().FinaliseLastCommand(); + + AtlasMessage::qPickPathNode query(Position(evt.GetPosition())); + query.Post(); + + obj->node = query.node; + if (obj->node.index != -1) + SET_STATE(WaitingAxis); + return true; + } + else + return false; + } + } + Waiting; + + struct sWaitingAxis : public State + { + bool OnMouse(TransformPath* obj, wxMouseEvent& evt) + { + if (evt.LeftDown()) + { + AtlasMessage::qPickAxis query(obj->node, Position(evt.GetPosition())); + query.Post(); + + obj->axis = query.axis; + if (query.axis != -1) + { + obj->m_StartPoint = evt.GetPosition(); + SET_STATE(Dragging); + } + return true; + } + else if (evt.LeftUp()) + { + if (obj->axis != -1) + return false; + + AtlasMessage::qPickPathNode query(Position(evt.GetPosition())); + query.Post(); + + obj->node = query.node; + if (obj->node.index == -1) + SET_STATE(Waiting); + return true; + } + else + return false; + } + + bool OnKey(TransformPath* obj, wxKeyEvent& evt, KeyEventType type) + { + if (type != KEY_UP) + return false; + switch (evt.GetKeyCode()) + { + case WXK_INSERT: + POST_COMMAND(AddPathNode, (obj->node)); + return true; + case WXK_DELETE: + POST_COMMAND(DeletePathNode, (obj->node)); + obj->node.index = -1; + return true; + case WXK_ESCAPE: + POST_MESSAGE(ClearPathNodePreview, ); + SET_STATE(Waiting); + return true; + default: + return false; + } + } + } + WaitingAxis; + + struct sDragging : public State + { + bool OnMouse(TransformPath* obj, wxMouseEvent& evt) + { + if (evt.LeftUp()) + { + obj->axis = -1; + SET_STATE(WaitingAxis); + return true; + } + else if (evt.Dragging()) + { + POST_COMMAND(MovePathNode, (obj->node, obj->axis, Position(obj->m_StartPoint), Position(evt.GetPosition()))); + obj->m_StartPoint = evt.GetPosition(); + return true; + } + else + return false; + } + + bool OnKey(TransformPath* obj, wxKeyEvent& evt, KeyEventType type) + { + if (type != KEY_UP) + return false; + if (evt.GetKeyCode() == WXK_ESCAPE) + { + POST_MESSAGE(ClearPathNodePreview, ); + SET_STATE(Waiting); + return true; + } + else + return false; + } + } + Dragging; +}; + +IMPLEMENT_DYNAMIC_CLASS(TransformPath, StateDrivenTool); Index: source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp +++ source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp @@ -19,6 +19,8 @@ #include "MessageHandler.h" #include "../CommandProc.h" +#include "../GameLoop.h" +#include "../View.h" #include "graphics/Camera.h" #include "graphics/CinemaManager.h" #include "graphics/GameView.h" @@ -28,6 +30,8 @@ #include "ps/Filesystem.h" #include "maths/MathUtil.h" #include "maths/Quaternion.h" +#include "maths/Vector2D.h" +#include "maths/Vector3D.h" #include "lib/res/graphics/ogl_tex.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpCinemaManager.h" @@ -35,6 +39,7 @@ namespace AtlasMessage { +const float MINIMAL_SCREEN_DISTANCE = 5; sCinemaPath ConstructCinemaPath(const CCinemaPath* source) { @@ -279,9 +284,319 @@ }; END_COMMAND(SetCinemaPathsDrawing) +CVector3D GetNearestPointToScreenCoords(CVector3D base, CVector3D dir, CVector2D screen, float lower = -1e5, float upper = 1e5) +{ + // It uses a ternary search, because an intersection of cylinders is the complex task + for (int i = 0; i < 64; ++i) + { + float delta = (upper - lower) / 3.0; + float middle1 = lower + delta, middle2 = lower + 2.0f * delta; + CVector3D p1 = base + dir * middle1, p2 = base + dir * middle2; + CVector2D s1, s2; + g_Game->GetView()->GetCamera()->GetScreenCoordinates(p1, s1.X, s1.Y); + g_Game->GetView()->GetCamera()->GetScreenCoordinates(p2, s2.X, s2.Y); + if ((s1 - screen).Length() < (s2 - screen).Length()) + upper = middle2; + else + lower = middle1; + } + return base + dir * upper; +} + +BEGIN_COMMAND(AddPathNode) +{ + void Do() + { + int index = msg->node->index; + CStrW name = msg->node->name; + if (index < 0) + return; + + CmpPtr cmpCinemaManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); + if (!cmpCinemaManager || !cmpCinemaManager->HasPath(name)) + return; + + CCinemaPath path = cmpCinemaManager->GetPaths().find(name)->second; + if (!msg->node->targetNode) + { + if (index >= (int)path.GetAllNodes().size()) + return; + } + else + { + if (index >= (int)path.GetTargetSpline().GetAllNodes().size()) + return; + } + + CCinemaData data = *path.GetData(); + TNSpline positionSpline = path; + TNSpline targetSpline = path.GetTargetSpline(); + TNSpline& spline = msg->node->targetNode ? targetSpline : positionSpline; + + CVector3D focus = g_Game->GetView()->GetCamera()->GetFocus(); + CFixedVector3D target( + fixed::FromFloat(focus.X), + fixed::FromFloat(focus.Y), + fixed::FromFloat(focus.Z) + ); + spline.InsertNode(index, target, CFixedVector3D(), fixed::FromInt(1)); + + spline.BuildSpline(); + path = CCinemaPath(data, positionSpline, targetSpline); + cmpCinemaManager->DeletePath(name); + cmpCinemaManager->AddPath(path); + } + + void Redo() + { + } + + void Undo() + { + } +}; +END_COMMAND(AddPathNode) + +BEGIN_COMMAND(DeletePathNode) +{ + void Do() + { + int index = msg->node->index; + CStrW name = msg->node->name; + if (index < 0) + return; + + CmpPtr cmpCinemaManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); + if (!cmpCinemaManager || !cmpCinemaManager->HasPath(name)) + return; + + CCinemaPath path = cmpCinemaManager->GetPaths().find(name)->second; + if (!msg->node->targetNode) + { + if (index >= (int)path.GetAllNodes().size()) + return; + } + else + { + if (index >= (int)path.GetTargetSpline().GetAllNodes().size()) + return; + } + + + CCinemaData data = *path.GetData(); + TNSpline positionSpline = path; + TNSpline targetSpline = path.GetTargetSpline(); + TNSpline& spline = msg->node->targetNode ? targetSpline : positionSpline; + if (spline.GetAllNodes().size() <= 1) + return; + + spline.RemoveNode(index); + spline.BuildSpline(); + path = CCinemaPath(data, positionSpline, targetSpline); + cmpCinemaManager->DeletePath(name); + cmpCinemaManager->AddPath(path); + + g_AtlasGameLoop->view->SetParam(L"movetool", false); + } + + void Redo() + { + } + + void Undo() + { + } +}; +END_COMMAND(DeletePathNode) + +BEGIN_COMMAND(MovePathNode) +{ + void Do() + { + int index = msg->node->index; + int axis = msg->axis; + CStrW name = msg->node->name; + + if (index < 0 || axis < 0) + return; + + CmpPtr cmpCinemaManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); + if (!cmpCinemaManager || !cmpCinemaManager->HasPath(name)) + return; + + CCinemaPath path = cmpCinemaManager->GetPaths().find(name)->second; + if (!msg->node->targetNode) + { + if (index >= (int)path.GetAllNodes().size()) + return; + } + else + { + if (index >= (int)path.GetTargetSpline().GetAllNodes().size()) + return; + } + + + CCinemaData data = *path.GetData(); + TNSpline positionSpline = path; + TNSpline targetSpline = path.GetTargetSpline(); + TNSpline& spline = msg->node->targetNode ? targetSpline : positionSpline; + + // Get shift of the tool by the cursor movement + CFixedVector3D pos = spline.GetAllNodes()[index].Position; + CVector3D position( + pos.X.ToFloat(), + pos.Y.ToFloat(), + pos.Z.ToFloat() + ); + CVector3D axisDirection(axis & 1, axis & 2, axis & 4); + CVector2D from, to; + msg->from->GetScreenSpace(from.X, from.Y); + msg->to->GetScreenSpace(to.X, to.Y); + CVector3D shift( + GetNearestPointToScreenCoords(position, axisDirection, to) - + GetNearestPointToScreenCoords(position, axisDirection, from) + ); + + // Change, rebuild and update the path + position += shift; + pos += CFixedVector3D( + fixed::FromFloat(shift.X), + fixed::FromFloat(shift.Y), + fixed::FromFloat(shift.Z) + ); + spline.UpdateNodePos(index, pos); + spline.BuildSpline(); + path = CCinemaPath(data, positionSpline, targetSpline); + cmpCinemaManager->DeletePath(name); + cmpCinemaManager->AddPath(path); + + // Update visual tool coordinates + g_AtlasGameLoop->view->SetParam(L"movetool_x", position.X); + g_AtlasGameLoop->view->SetParam(L"movetool_y", position.Y); + g_AtlasGameLoop->view->SetParam(L"movetool_z", position.Z); + } + + void Redo() + { + } + + void Undo() + { + } +}; +END_COMMAND(MovePathNode) + QUERYHANDLER(GetCinemaPaths) { msg->paths = GetCurrentPaths(); } +bool isPathNodePicked(const TNSpline& spline, const CVector2D& cursor, AtlasMessage::sCinemaPathNode& node, bool targetNode) +{ + for (size_t i = 0; i < spline.GetAllNodes().size(); ++i) + { + const SplineData& data = spline.GetAllNodes()[i]; + CVector3D position( + data.Position.X.ToFloat(), + data.Position.Y.ToFloat(), + data.Position.Z.ToFloat() + ); + CVector2D screen_pos; + g_Game->GetView()->GetCamera()->GetScreenCoordinates(position, screen_pos.X, screen_pos.Y); + if ((screen_pos - cursor).Length() < MINIMAL_SCREEN_DISTANCE) + { + node.index = i; + node.targetNode = targetNode; + g_AtlasGameLoop->view->SetParam(L"movetool", true); + g_AtlasGameLoop->view->SetParam(L"movetool_x", position.X); + g_AtlasGameLoop->view->SetParam(L"movetool_y", position.Y); + g_AtlasGameLoop->view->SetParam(L"movetool_z", position.Z); + return true; + } + } + return false; +} + +QUERYHANDLER(PickPathNode) +{ + AtlasMessage::sCinemaPathNode node; + CmpPtr cmpCinemaManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); + if (!cmpCinemaManager) + { + msg->node = node; + return; + } + + CVector2D cursor; + msg->pos->GetScreenSpace(cursor.X, cursor.Y); + + for (const std::pair& it : cmpCinemaManager->GetPaths()) + { + const CCinemaPath& path = it.second; + if (isPathNodePicked(path, cursor, node, false) || isPathNodePicked(path.GetTargetSpline(), cursor, node, true)) + { + node.name = path.GetName(); + msg->node = node; + return; + } + } + msg->node = node; + g_AtlasGameLoop->view->SetParam(L"movetool", false); +} + +bool isAxisPicked(CVector3D base, CVector3D direction, float length, CVector2D cursor) +{ + CVector3D position = GetNearestPointToScreenCoords(base, direction, cursor, 0, length); + CVector2D screen_position; + g_Game->GetView()->GetCamera()->GetScreenCoordinates(position, screen_position.X, screen_position.Y); + return (cursor - screen_position).Length() < MINIMAL_SCREEN_DISTANCE; +} + +QUERYHANDLER(PickAxis) +{ + msg->axis = -1; + int index = msg->node->index; + + if (index < 0) + return; + + CmpPtr cmpCinemaManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); + if (!cmpCinemaManager || !cmpCinemaManager->HasPath(msg->node->name)) + return; + + const CCinemaPath& path = cmpCinemaManager->GetPaths().find(msg->node->name)->second; + if (!msg->node->targetNode) + { + if (index >= (int)path.GetAllNodes().size()) + return; + } + else + { + if (index >= (int)path.GetTargetSpline().GetAllNodes().size()) + return; + } + + const TNSpline& spline = msg->node->targetNode ? path.GetTargetSpline() : path; + CFixedVector3D pos = spline.GetAllNodes()[index].Position; + CVector3D position(pos.X.ToFloat(), pos.Y.ToFloat(), pos.Z.ToFloat()); + CVector3D camera = g_Game->GetView()->GetCamera()->GetOrientation().GetTranslation(); + float scale = (position - camera).Length() / 10.0; + + CVector2D cursor; + msg->pos->GetScreenSpace(cursor.X, cursor.Y); + if (isAxisPicked(position, CVector3D(1, 0, 0), scale, cursor)) + msg->axis = 1; + else if (isAxisPicked(position, CVector3D(0, 1, 0), scale, cursor)) + msg->axis = 2; + else if (isAxisPicked(position, CVector3D(0, 0, 1), scale, cursor)) + msg->axis = 4; +} + +MESSAGEHANDLER(ClearPathNodePreview) +{ + msg->GetType(); + g_AtlasGameLoop->view->SetParam(L"movetool", false); +} + } Index: source/tools/atlas/GameInterface/Messages.h =================================================================== --- source/tools/atlas/GameInterface/Messages.h +++ source/tools/atlas/GameInterface/Messages.h @@ -654,6 +654,34 @@ ((AtlasMessage::sCameraInfo, info)) ); +QUERY(PickPathNode, + ((Position, pos)) + , + ((AtlasMessage::sCinemaPathNode, node)) + ); + +QUERY(PickAxis, + ((AtlasMessage::sCinemaPathNode, node)) + ((Position, pos)) + , + ((int, axis)) + ); + +COMMAND(AddPathNode, NOMERGE, + ((AtlasMessage::sCinemaPathNode, node)) + ); + +COMMAND(DeletePathNode, NOMERGE, + ((AtlasMessage::sCinemaPathNode, node)) + ); + +COMMAND(MovePathNode, NOMERGE, + ((AtlasMessage::sCinemaPathNode, node)) + ((int, axis)) + ((Position, from)) + ((Position, to)) + ); + COMMAND(AddCinemaPath, NOMERGE, ((std::wstring, pathName))); COMMAND(DeleteCinemaPath, NOMERGE, ((std::wstring, pathName))); @@ -672,6 +700,8 @@ ((bool, lines)) ); +MESSAGE(ClearPathNodePreview,); + ////////////////////////////////////////////////////////////////////////// enum eTriggerListType Index: source/tools/atlas/GameInterface/SharedTypes.h =================================================================== --- source/tools/atlas/GameInterface/SharedTypes.h +++ source/tools/atlas/GameInterface/SharedTypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -119,6 +119,15 @@ }; SHAREABLE_STRUCT(sCinemaPath); +struct sCinemaPathNode +{ + std::wstring name; + int index; + bool targetNode; + sCinemaPathNode() : index(-1), targetNode(false) {} +}; +SHAREABLE_STRUCT(sCinemaPathNode); + struct eCinemaEventMode { enum { SMOOTH, SELECT, IMMEDIATE_PATH, RESET }; }; struct sCameraInfo Index: source/tools/atlas/GameInterface/View.h =================================================================== --- source/tools/atlas/GameInterface/View.h +++ source/tools/atlas/GameInterface/View.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -40,6 +40,7 @@ virtual ~AtlasView(); virtual void Update(float UNUSED(realFrameLength)) { }; virtual void Render() { }; + virtual void DrawCinemaPathTool() { }; virtual void DrawOverlays() { }; virtual CCamera& GetCamera() = 0; virtual CSimulation2* GetSimulation2() { return NULL; } @@ -49,6 +50,7 @@ virtual void SetParam(const std::wstring& name, bool value); virtual void SetParam(const std::wstring& name, int value); + virtual void SetParam(const std::wstring& UNUSED(name), float UNUSED(value)) {} virtual void SetParam(const std::wstring& name, const AtlasMessage::Color& value); virtual void SetParam(const std::wstring& name, const std::wstring& value); @@ -86,12 +88,14 @@ virtual ~AtlasViewGame(); virtual void Update(float realFrameLength); virtual void Render(); + virtual void DrawCinemaPathTool(); virtual void DrawOverlays(); virtual CCamera& GetCamera(); virtual CSimulation2* GetSimulation2(); virtual bool WantsHighFramerate(); virtual void SetParam(const std::wstring& name, bool value); + virtual void SetParam(const std::wstring& name, float value); virtual void SetParam(const std::wstring& name, const std::wstring& value); void SetSpeedMultiplier(float speedMultiplier); @@ -115,6 +119,8 @@ } SBandboxVertex; std::vector m_BandboxArray; + bool m_DrawMoveTool; + CVector3D m_MoveTool; }; ////////////////////////////////////////////////////////////////////////// Index: source/tools/atlas/GameInterface/View.cpp =================================================================== --- source/tools/atlas/GameInterface/View.cpp +++ source/tools/atlas/GameInterface/View.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -171,7 +171,7 @@ ////////////////////////////////////////////////////////////////////////// AtlasViewGame::AtlasViewGame() - : m_SpeedMultiplier(0.f), m_IsTesting(false) + : m_SpeedMultiplier(0.f), m_IsTesting(false), m_DrawMoveTool(false) { ENSURE(g_Game); } @@ -229,6 +229,41 @@ Atlas_GLSwapBuffers((void*)g_AtlasGameLoop->glCanvas); } +void AtlasViewGame::DrawCinemaPathTool() +{ + if (!m_DrawMoveTool) + return; + CVector3D focus = m_MoveTool; + CVector3D camera = GetCamera().GetOrientation().GetTranslation(); + float scale = (focus - camera).Length() / 10.0; + + glDisable(GL_DEPTH_TEST); + glLineWidth(1.6f); + glEnable(GL_LINE_SMOOTH); + + glColor3f(1.0f, 0.0f, 0.0f); + glBegin(GL_LINE_STRIP); + glVertex3fv(focus.GetFloatArray()); + glVertex3fv((focus + CVector3D(scale, 0, 0)).GetFloatArray()); + glEnd(); + + glColor3f(0.0f, 1.0f, 0.0f); + glBegin(GL_LINE_STRIP); + glVertex3fv(focus.GetFloatArray()); + glVertex3fv((focus + CVector3D(0, scale, 0)).GetFloatArray()); + glEnd(); + + glColor3f(0.0f, 0.0f, 1.0f); + glBegin(GL_LINE_STRIP); + glVertex3fv(focus.GetFloatArray()); + glVertex3fv((focus + CVector3D(0, 0, scale)).GetFloatArray()); + glEnd(); + + glDisable(GL_LINE_SMOOTH); + glLineWidth(1.0f); + glEnable(GL_DEPTH_TEST); +} + void AtlasViewGame::DrawOverlays() { #if CONFIG2_GLES @@ -276,6 +311,18 @@ { if (name == L"priorities") g_Renderer.SetDisplayTerrainPriorities(value); + else if (name == L"movetool") + m_DrawMoveTool = value; +} + +void AtlasViewGame::SetParam(const std::wstring& name, float value) +{ + if (name == L"movetool_x") + m_MoveTool.X = value; + else if (name == L"movetool_y") + m_MoveTool.Y = value; + else if (name == L"movetool_z") + m_MoveTool.Z = value; } void AtlasViewGame::SetParam(const std::wstring& name, const std::wstring& value)