Index: source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.h =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.h +++ source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -32,6 +32,15 @@ class ScenarioEditor : public wxFrame { public: + + //This needs to match CCamera::ProjectionType + enum class ProjectionType + { + CUSTOM, + ORTHO, + PERSPECTIVE, + }; + ScenarioEditor(wxWindow* parent); void OnClose(wxCloseEvent& event); void OnTimer(wxTimerEvent& event); @@ -48,8 +57,8 @@ void OnQuit(wxCommandEvent& event); void OnUndo(wxCommandEvent& event); void OnRedo(wxCommandEvent& event); - void OnCopy(wxCommandEvent& event); - void OnPaste(wxCommandEvent& event); + void OnCopy(wxCommandEvent& event); + void OnPaste(wxCommandEvent& event); void OnWireframe(wxCommandEvent& event); void OnMessageTrace(wxCommandEvent& event); Index: source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/Object.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/Object.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Object/Object.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -49,6 +49,7 @@ ID_ViewerBoundingBox, ID_ViewerAxesMarker, ID_ViewerPropPoints, + ID_ViewerSetProjection, ID_ViewerPlay, ID_ViewerPause, ID_ViewerSlow @@ -87,6 +88,7 @@ bool m_ViewerPolyCount; bool m_ViewerBoundingBox; bool m_ViewerAxesMarker; + ScenarioEditor::ProjectionType m_ProjectionType; int m_ViewerPropPointsMode; // 0 disabled, 1 for point markers, 2 for point markers + axes wxPanel* m_ViewerPanel; @@ -99,6 +101,7 @@ struct ObjectSidebarImpl { ObjectSidebarImpl(ScenarioEditor& scenarioEditor) : + m_ScenarioEditor(scenarioEditor), m_ObjectListBox(NULL), m_ActorViewerActive(false), m_ActorViewerEntity(L"actor|structures/fndn_1x1.xml"), m_ActorViewerAnimation("idle"), m_ActorViewerSpeed(0.f), @@ -106,6 +109,7 @@ { } + ScenarioEditor& m_ScenarioEditor; wxListBox* m_ObjectListBox; std::vector m_Objects; ObservableScopedConnection m_ToolConn; @@ -525,6 +529,7 @@ m_ViewerPolyCount = false; m_ViewerBoundingBox = false; m_ViewerAxesMarker = false; + m_ProjectionType = ScenarioEditor::ProjectionType::PERSPECTIVE; m_ViewerPropPointsMode = 0; wxSizer* mainSizer = new wxBoxSizer(wxHORIZONTAL); @@ -553,6 +558,7 @@ viewerButtonsRight->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerBoundingBox, _("Bounding Boxes")), _("Toggle bounding boxes")), wxSizerFlags().Expand()); viewerButtonsRight->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerAxesMarker, _("Axes Marker")), _("Toggle the axes marker (R=X, G=Y, B=Z)")), wxSizerFlags().Expand()); viewerButtonsRight->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerPropPoints, _("Prop Points")), _("Toggle prop points (works best in wireframe mode)")), wxSizerFlags().Expand()); + viewerButtonsRight->Add(Tooltipped(new wxButton(m_ViewerPanel, ID_ViewerSetProjection, _("Toggle Perspective")), _("Toggle between perspective and orthogonal projection in the viewer")), wxSizerFlags().Expand()); viewerButtonsSizer->Add(viewerButtonsLeft, wxSizerFlags().Expand()); viewerButtonsSizer->Add(viewerButtonsRight, wxSizerFlags().Expand()); @@ -701,6 +707,7 @@ POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"water", m_ViewerWater)); POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"stats", m_ViewerPolyCount)); POST_MESSAGE(SetViewParamB, (AtlasMessage::eRenderView::ACTOR, L"bounding_box", m_ViewerBoundingBox)); + POST_MESSAGE(SetViewParamI, (AtlasMessage::eRenderView::ACTOR, L"Set Projection", static_cast(m_ProjectionType))); POST_MESSAGE(SetViewParamI, (AtlasMessage::eRenderView::ACTOR, L"prop_points", m_ViewerPropPointsMode)); } @@ -749,6 +756,26 @@ m_ViewerPropPointsMode = (m_ViewerPropPointsMode+1) % 3; POST_MESSAGE(SetViewParamI, (AtlasMessage::eRenderView::ACTOR, L"prop_points", m_ViewerPropPointsMode)); break; + case ID_ViewerSetProjection: + const ScenarioEditor::ProjectionType oldProjectionType{m_ProjectionType}; + m_ProjectionType = + oldProjectionType == ScenarioEditor::ProjectionType::PERSPECTIVE ? + ScenarioEditor::ProjectionType::ORTHO : + ScenarioEditor::ProjectionType::PERSPECTIVE; + + const wchar_t* asText + { + m_ProjectionType == ScenarioEditor::ProjectionType::PERSPECTIVE ? + L"Set Perspective" : L"Set Orthogonal" + }; + p->m_ScenarioEditor.GetToolManager().GetCurrentTool()->OnCommand(asText, NULL); + POST_MESSAGE(SetViewParamI, + ( + AtlasMessage::eRenderView::ACTOR, + L"Set Projection", + static_cast(m_ProjectionType) + )); + break; } } @@ -783,4 +810,5 @@ EVT_BUTTON(ID_ViewerBoundingBox, ObjectBottomBar::OnViewerSetting) EVT_BUTTON(ID_ViewerAxesMarker, ObjectBottomBar::OnViewerSetting) EVT_BUTTON(ID_ViewerPropPoints, ObjectBottomBar::OnViewerSetting) + EVT_BUTTON(ID_ViewerSetProjection, ObjectBottomBar::OnViewerSetting) END_EVENT_TABLE(); Index: source/tools/atlas/AtlasUI/ScenarioEditor/Tools/ActorViewerTool.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/Tools/ActorViewerTool.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/Tools/ActorViewerTool.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -35,29 +35,30 @@ DECLARE_DYNAMIC_CLASS(ActorViewerTool); // Camera settings - float m_Distance; - float m_Angle; - float m_Elevation; + float m_Distance{20.f}; + float m_Angle{0.f}; + float m_Elevation{(float)M_PI / 6.f}; + ScenarioEditor::ProjectionType m_ProjectionType{ScenarioEditor::ProjectionType::PERSPECTIVE}; // Mouse input state int m_LastX, m_LastY; - bool m_LastIsValid; + bool m_LastIsValid{false}; public: - ActorViewerTool() : - m_Distance(20.f), m_Angle(0.f), m_Elevation((float)M_PI / 6.f), - m_LastIsValid(false) - { - } void PostLookAt() { float offset = 0.3f; // slight fudge so we turn nicely when going over the top of the unit + if (m_ProjectionType == ScenarioEditor::ProjectionType::CUSTOM) + return; + const float distance = + (m_ProjectionType == ScenarioEditor::ProjectionType::PERSPECTIVE) ? + m_Distance : 256.f; POST_MESSAGE(LookAt, (AtlasMessage::eRenderView::ACTOR, Position( - m_Distance*cos(m_Elevation)*sin(m_Angle) + offset*cos(m_Angle), - m_Distance*sin(m_Elevation), - m_Distance*cos(m_Elevation)*cos(m_Angle) - offset*sin(m_Angle)), + distance*cos(m_Elevation)*sin(m_Angle) + offset*cos(m_Angle), + distance*sin(m_Elevation), + distance*cos(m_Elevation)*cos(m_Angle) - offset*sin(m_Angle)), Position(0, 0, 0))); } @@ -68,6 +69,15 @@ SetState(&Viewing); } + void OnCommand(const wxString& command, void* WXUNUSED(userdata)) final + { + m_ProjectionType = command == L"Set Orthogonal" ? + ScenarioEditor::ProjectionType::ORTHO : + ScenarioEditor::ProjectionType::PERSPECTIVE; + PostLookAt(); + return; + } + void OnEnable() { GetScenarioEditor().GetObjectSettings().SetView(AtlasMessage::eRenderView::ACTOR); @@ -102,7 +112,12 @@ float speed = -1.f * ScenarioEditor::GetSpeedModifier(); obj->m_Distance += evt.GetWheelRotation() * speed / evt.GetWheelDelta(); - + POST_MESSAGE(SetViewParamF, + ( + AtlasMessage::eRenderView::ACTOR, + L"Set Orthogonal Scale", + obj->m_Distance / 3.f + )); camera_changed = true; } @@ -124,10 +139,19 @@ obj->m_Angle += dx * M_PI/256.f * ScenarioEditor::GetSpeedModifier(); if (evt.ButtonIsDown(wxMOUSE_BTN_LEFT)) + { obj->m_Distance += dy / 8.f * ScenarioEditor::GetSpeedModifier(); + POST_MESSAGE(SetViewParamF, + ( + AtlasMessage::eRenderView::ACTOR, + L"Set Orthogonal Scale", + obj->m_Distance / 3.f + )); + } else // evt.ButtonIsDown(wxMOUSE_BTN_RIGHT)) - obj->m_Elevation += dy * M_PI/256.f * ScenarioEditor::GetSpeedModifier(); - + { + obj->m_Elevation += dy * M_PI / 256.f * ScenarioEditor::GetSpeedModifier(); + } camera_changed = true; } else if ((evt.ButtonUp(wxMOUSE_BTN_LEFT) || evt.ButtonUp(wxMOUSE_BTN_RIGHT)) Index: source/tools/atlas/GameInterface/ActorViewer.cpp =================================================================== --- source/tools/atlas/GameInterface/ActorViewer.cpp +++ source/tools/atlas/GameInterface/ActorViewer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -542,7 +542,7 @@ Renderer::Backend::IFramebuffer* backbuffer = deviceCommandContext->GetDevice()->GetCurrentBackbuffer( - Renderer::Backend::AttachmentLoadOp::DONT_CARE, + Renderer::Backend::AttachmentLoadOp::CLEAR, Renderer::Backend::AttachmentStoreOp::STORE, Renderer::Backend::AttachmentLoadOp::CLEAR, Renderer::Backend::AttachmentStoreOp::DONT_CARE); Index: source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp +++ source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -178,6 +178,12 @@ view->SetParam(*msg->name, msg->value); } +MESSAGEHANDLER(SetViewParamF) +{ + AtlasView* view = AtlasView::GetView(msg->view); + view->SetParam(*msg->name, msg->value); +} + MESSAGEHANDLER(SetViewParamC) { AtlasView* view = AtlasView::GetView(msg->view); Index: source/tools/atlas/GameInterface/Messages.h =================================================================== --- source/tools/atlas/GameInterface/Messages.h +++ source/tools/atlas/GameInterface/Messages.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -71,6 +71,11 @@ ((std::wstring, name)) ((int, value)) ); +MESSAGE(SetViewParamF, + ((int, view)) // eRenderView + ((std::wstring, name)) + ((float, value)) + ); MESSAGE(SetViewParamC, ((int, view)) // eRenderView ((std::wstring, name)) 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) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -142,15 +142,18 @@ virtual void SetParam(const std::wstring& name, bool value); virtual void SetParam(const std::wstring& name, int value); + virtual void SetParam(const std::wstring& name, float value); virtual void SetParam(const std::wstring& name, const AtlasMessage::Color& value); void SetSpeedMultiplier(float speedMultiplier); ActorViewer& GetActorViewer(); private: - float m_SpeedMultiplier; + float m_SpeedMultiplier {1.f}; CCamera m_Camera; - ActorViewer* m_ActorViewer; + ActorViewer* m_ActorViewer {NULL}; + CCamera::ProjectionType m_ProjectionType {CCamera::ProjectionType::PERSPECTIVE}; + float m_OrthogonalScale {20.f / 3.f}; }; #endif // INCLUDED_VIEW 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) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -33,6 +33,7 @@ #include "lib/utf8.h" #include "maths/MathUtil.h" #include "ps/ConfigDB.h" +#include "ps/CLogger.h" #include "ps/Game.h" #include "ps/GameSetup/GameSetup.h" #include "ps/VideoMode.h" @@ -71,8 +72,8 @@ ////////////////////////////////////////////////////////////////////////// -AtlasViewActor::AtlasViewActor() -: m_SpeedMultiplier(1.f), m_ActorViewer(new ActorViewer()) +AtlasViewActor::AtlasViewActor(): + m_ActorViewer(new ActorViewer()) { } @@ -91,7 +92,18 @@ SViewPort vp = { 0, 0, g_xres, g_yres }; CCamera& camera = GetCamera(); camera.SetViewPort(vp); - camera.SetPerspectiveProjection(2.f, 512.f, DEGTORAD(20.f)); + switch (m_ProjectionType) + { + case CCamera::ProjectionType::ORTHO: + camera.SetOrthoProjection(-2.f, -512.f, m_OrthogonalScale); + break; + case CCamera::ProjectionType::CUSTOM: + LOGWARNING("CCamera::ProjectionType::CUSTOM not implemented."); + FALLTHROUGH; + default: //CCamera::ProjectionType::PERSPECTIVE + camera.SetPerspectiveProjection(2.f, 512.f, DEGTORAD(20.f)); + break; + } camera.UpdateFrustum(); m_ActorViewer->Render(); @@ -162,9 +174,44 @@ void AtlasViewActor::SetParam(const std::wstring& name, int value) { if (name == L"prop_points") + { m_ActorViewer->SetPropPointsMode(value); + return; + } + if (name == L"Set Projection") + { + CCamera& camera = AtlasView::GetView_Actor()->GetCamera(); + switch (value) + { + case static_cast(CCamera::ProjectionType::ORTHO): + m_ProjectionType = CCamera::ProjectionType::ORTHO; + camera.SetOrthoProjection(-2.f, -512.f, m_OrthogonalScale); + camera.UpdateFrustum(); + return; + case static_cast(CCamera::ProjectionType::CUSTOM): + LOGWARNING("CCamera::ProjectionType::CUSTOM not implemented"); + FALLTHROUGH; + default: //CCamera::ProjectionType::PERSPECTIVE: + m_ProjectionType = CCamera::ProjectionType::PERSPECTIVE; + camera.SetPerspectiveProjection(2.f, 512.f, DEGTORAD(20.f)); + camera.UpdateFrustum(); + return; + } + } } +void AtlasViewActor::SetParam(const std::wstring& name, float value) +{ + if (name == L"Set Orthogonal Scale") + { + m_OrthogonalScale = value; + if (m_ProjectionType != CCamera::ProjectionType::ORTHO) return; + CCamera &camera = AtlasView::GetView_Actor()->GetCamera(); + camera.SetOrthoProjection(-2.f, -512.f, m_OrthogonalScale); + camera.UpdateFrustum(); + return; + } +} void AtlasViewActor::SetParam(const std::wstring& UNUSED(name), const AtlasMessage::Color& UNUSED(value)) { }