diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-04-18 19:43:44 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-04-18 19:43:44 +0100 |
commit | 6036877ac4e92da3185f21d5928bf3ed28d685b2 (patch) | |
tree | 5e5a5f6ad09e196bbecfbfec2a9a3c8f02262ca3 | |
parent | Merge branch 'openmesh-11' (diff) | |
parent | Remember selected asset id and reload/reselect resource file on change (diff) | |
download | ilt-6036877ac4e92da3185f21d5928bf3ed28d685b2.tar.bz2 ilt-6036877ac4e92da3185f21d5928bf3ed28d685b2.tar.xz ilt-6036877ac4e92da3185f21d5928bf3ed28d685b2.zip |
-rw-r--r-- | Jamroot.jam | 11 | ||||
-rw-r--r-- | application/main.cpp | 5 | ||||
-rw-r--r-- | application/resviewer.cpp | 227 | ||||
-rw-r--r-- | assetFactory/asset.cpp | 6 | ||||
-rw-r--r-- | assetFactory/asset.h | 5 | ||||
-rw-r--r-- | game/scenary/foliage.cpp | 10 | ||||
-rw-r--r-- | game/scenary/foliage.h | 2 | ||||
-rw-r--r-- | game/scenary/illuminator.cpp | 10 | ||||
-rw-r--r-- | game/scenary/illuminator.h | 2 | ||||
-rw-r--r-- | game/vehicles/railVehicleClass.cpp | 13 | ||||
-rw-r--r-- | game/vehicles/railVehicleClass.h | 2 | ||||
-rw-r--r-- | gfx/gl/sceneProvider.cpp | 2 | ||||
-rw-r--r-- | gfx/gl/sceneRenderer.cpp | 1 | ||||
-rw-r--r-- | test/testMainWindow.cpp | 2 | ||||
-rw-r--r-- | ui/gameMainWindow.cpp | 6 | ||||
-rw-r--r-- | ui/gameMainWindow.h | 9 | ||||
-rw-r--r-- | ui/mainWindow.cpp | 7 | ||||
-rw-r--r-- | ui/mainWindow.h | 5 | ||||
-rw-r--r-- | ui/window.cpp | 7 | ||||
-rw-r--r-- | ui/window.h | 5 | ||||
-rw-r--r-- | ui/windowContent.h | 2 |
21 files changed, 300 insertions, 39 deletions
diff --git a/Jamroot.jam b/Jamroot.jam index 9b589cf..8589861 100644 --- a/Jamroot.jam +++ b/Jamroot.jam @@ -12,6 +12,7 @@ pkg-config.import mxml : : <link>shared ; pkg-config.import assimp : : <link>shared ; lib pthread : : <link>shared ; lib OpenMeshCore : : <link>shared ; +lib boost_program_options : : <link>shared ; variant coverage : debug ; project i-like-trains : requirements @@ -46,15 +47,15 @@ project i-like-trains : requirements <toolset>tidy:<define>TIDY ; -exe iliketrains : - application/main.cpp - : - <library>ilt - ; +exe iliketrains : application/main.cpp : <library>ilt ; +exe resviewer : application/resviewer.cpp : <library>ilt <library>boost_program_options ; explicit main ; always main ; run iliketrains : -- : [ sequence.insertion-sort [ glob-tree-ex res : *.* ] ] : : main ; +explicit runresviewer ; +always runresviewer ; +run resviewer : -- : [ sequence.insertion-sort [ glob-tree-ex res : *.xml ] ] : : runresviewer ; lib ilt : [ glob-tree *.cpp *.?s *.t?s : application bin test thirdparty ] diff --git a/application/main.cpp b/application/main.cpp index 9120376..a0c87c0 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -36,15 +36,14 @@ #include <ui/gameMainWindow.h> #include <ui/window.h> -static const int DISPLAY_WIDTH = 1280; -static const int DISPLAY_HEIGHT = 1024; +constexpr ScreenAbsCoord DEFAULT_WINDOW_SIZE {1280, 1024}; class DummyMainApplication : public GameState, public MainApplication { public: int run() { - windows.create<MainWindow>(DISPLAY_WIDTH, DISPLAY_HEIGHT)->setContent<GameMainWindow>(); + windows.create<MainWindow>(DEFAULT_WINDOW_SIZE, "I Like Trains")->setContent<GameMainWindow>(); terrain = world.create<Terrain>(GeoData::loadFromAsciiGrid("test/fixtures/height/SD19.asc")); world.create<Water>(terrain); diff --git a/application/resviewer.cpp b/application/resviewer.cpp new file mode 100644 index 0000000..c82017b --- /dev/null +++ b/application/resviewer.cpp @@ -0,0 +1,227 @@ +#include <backends/imgui_impl_opengl3.h> +#include <backends/imgui_impl_sdl2.h> +#include <boost/program_options.hpp> +#include <game/environment.h> +#include <game/gamestate.h> +#include <game/terrain.h> +#include <gfx/gl/sceneProvider.h> +#include <gfx/gl/sceneRenderer.h> +#include <gfx/renderable.h> +#include <location.h> +#include <ui/applicationBase.h> +#include <ui/mainApplication.h> +#include <ui/mainWindow.h> + +constexpr ScreenAbsCoord DEFAULT_WINDOW_SIZE {800, 600}; +constexpr GlobalDistance TERRAIN_LIMIT = 1'000'000; +constexpr GlobalDistance TERRAIN_HEIGHT = 10'000; +constexpr RelativeDistance DEFAULT_CAMERA_DIST = 7'000; +constexpr GlobalDistance DEFAULT_CAMERA_HEIGHT = 5'000; +constexpr GlobalDistance DEFAULT_CAMERA_FOCUS = 3'000; +constexpr GlobalDistance MAX_CAMERA_HEIGHT = 10'000; +constexpr GlobalDistance MIN_CAMERA_DIST = 1'000; +constexpr GlobalDistance MAX_CAMERA_DIST = 30'000; + +class ViewerContent : public WindowContent, SceneRenderer, SceneProvider { +public: + ViewerContent(ScreenAbsCoord size, std::span<const std::filesystem::path> files) : + SceneRenderer {size, 0}, fileList(files) + { + camera.setPosition(calcCameraPosition()); + camera.lookAt({0, 0, TERRAIN_HEIGHT + cameraFocus}); + gameState->terrain = std::make_shared<Terrain>( + GeoData::createFlat({-TERRAIN_LIMIT, -TERRAIN_LIMIT}, {TERRAIN_LIMIT, TERRAIN_LIMIT}, TERRAIN_HEIGHT)); + } + +private: + [[nodiscard]] + GlobalPosition3D + calcCameraPosition() const + { + return {sincos(cameraAngle) * cameraDistance, TERRAIN_HEIGHT + cameraHeight}; + } + + void + render() override + { + SceneRenderer::render(*this); + controls(); + } + + void + tick(TickDuration tick) override + { + if (autoRotate != 0) { + cameraAngle = normalize(cameraAngle + (autoRotate * tick.count())); + camera.setPosition(calcCameraPosition()); + camera.lookAt({0, 0, TERRAIN_HEIGHT + cameraFocus}); + } + if (selectedFile) { + try { + if (const auto curmTime = std::filesystem::last_write_time(*selectedFile); curmTime != fileTime) { + location.reset(); + selectedAsset = nullptr; + gameState->assets = AssetFactory::loadXML(*selectedFile)->assets; + fileTime = curmTime; + if (!selectedAssetId.empty() && gameState->assets.contains(selectedAssetId)) { + auto asset = gameState->assets.at(selectedAssetId); + auto renderable = asset.getAs<const Renderable>(); + if (renderable) { + location = asset->createAt(position); + selectedAsset = renderable; + } + } + } + } + catch (...) { + } + } + } + + bool + handleInput(const SDL_Event & event) override + { + if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { + SceneRenderer::resize({event.window.data1, event.window.data2}); + } + + return WindowContent::handleInput(event); + } + + void + controls() + { + if (ImGui::Begin("Resource view")) { + ImGui::SetWindowSize({}); + fileSelection(); + assetSelection(); + } + ImGui::End(); + + if (ImGui::Begin("Camera")) { + ImGui::SetWindowSize({}); + if (std::max({ImGui::SliderFloat("Camera position", &cameraAngle, -pi, pi), + ImGui::SliderInt("Camera focus", &cameraFocus, 1, MAX_CAMERA_HEIGHT), + ImGui::SliderInt("Camera height", &cameraHeight, 1, MAX_CAMERA_HEIGHT), + ImGui::SliderFloat("Camera distance", &cameraDistance, MIN_CAMERA_DIST, MAX_CAMERA_DIST)})) { + camera.setPosition(calcCameraPosition()); + camera.lookAt({0, 0, TERRAIN_HEIGHT + cameraFocus}); + } + ImGui::SliderFloat("Auto rotate speed", &autoRotate, -1, 1); + } + ImGui::End(); + } + + void + fileSelection() + { + ImGui::BeginListBox("File"); + for (const auto & file : fileList) { + if (ImGui::Selectable(file.c_str(), &file == selectedFile)) { + location.reset(); + selectedAssetId.clear(); + selectedAsset = nullptr; + gameState->assets = AssetFactory::loadXML(file)->assets; + fileTime = std::filesystem::last_write_time(file); + selectedFile = &file; + } + } + ImGui::EndListBox(); + } + + void + assetSelection() + { + if (!gameState->assets.empty()) { + ImGui::BeginListBox("Asset"); + for (const auto & asset : gameState->assets) { + auto renderable = asset.second.getAs<const Renderable>(); + if (renderable) { + if (ImGui::Selectable(asset.first.c_str(), renderable == selectedAsset)) { + selectedAssetId = asset.first; + selectedAsset = renderable; + location = asset.second->createAt(position); + } + } + } + ImGui::EndListBox(); + } + } + + void + content(const SceneShader & sceneShader, const Frustum & frustum) const override + { + gameState->terrain->render(sceneShader, frustum); + if (selectedAsset) { + selectedAsset->render(sceneShader, frustum); + } + } + + void + lights(const SceneShader & sceneShader) const override + { + if (selectedAsset) { + selectedAsset->lights(sceneShader); + } + } + + void + shadows(const ShadowMapper & mapper, const Frustum & frustum) const override + { + gameState->terrain->shadows(mapper, frustum); + if (selectedAsset) { + selectedAsset->shadows(mapper, frustum); + } + } + + std::span<const std::filesystem::path> fileList; + std::filesystem::file_time_type fileTime; + const std::filesystem::path * selectedFile {}; + std::string selectedAssetId; + const Renderable * selectedAsset {}; + Location position {.pos = {0, 0, TERRAIN_HEIGHT}, .rot = {}}; + std::any location; + Angle cameraAngle {0.F}; + RelativeDistance cameraDistance {DEFAULT_CAMERA_DIST}; + GlobalDistance cameraHeight {DEFAULT_CAMERA_HEIGHT}; + GlobalDistance cameraFocus {DEFAULT_CAMERA_FOCUS}; + float autoRotate {0.F}; +}; + +int +main(int argc, char ** argv) +{ + class ResViewer : GameState, MainApplication { + public: + void + run(std::span<const std::filesystem::path> fileList) + { + windows.create<MainWindow>(DEFAULT_WINDOW_SIZE, "ILT - Resource Viewer") + ->setContent<ViewerContent>(fileList); + mainLoop(); + } + }; + + namespace po = boost::program_options; + po::options_description opts("ILT - Resource Viewer"); + std::vector<std::filesystem::path> resources; + // clang-format off + opts.add_options() + ("resource,r", po::value(&resources)->composing(), "Resource file") + ("help,h", po::value<bool>()->default_value(false)->zero_tokens(), "Help") + ; + // clang-format on + po::positional_options_description pod; + pod.add("resource", -1); + po::variables_map varmap; + po::store(po::command_line_parser(argc, argv).options(opts).positional(pod).run(), varmap); + po::notify(varmap); + + if (varmap.at("help").as<bool>()) { + std::cout << opts << '\n'; + return EXIT_SUCCESS; + } + + ResViewer {}.run(resources); + return EXIT_SUCCESS; +} diff --git a/assetFactory/asset.cpp b/assetFactory/asset.cpp index e3f5feb..0254943 100644 --- a/assetFactory/asset.cpp +++ b/assetFactory/asset.cpp @@ -7,6 +7,12 @@ Asset::persist(Persistence::PersistenceStore & store) return STORE_MEMBER(id) && STORE_MEMBER(name); } +std::any +Asset::createAt(const Location &) const +{ + return {}; +} + Asset::TexturePtr Asset::getTexture() const { diff --git a/assetFactory/asset.h b/assetFactory/asset.h index b5de056..061a7c8 100644 --- a/assetFactory/asset.h +++ b/assetFactory/asset.h @@ -2,17 +2,22 @@ #include "factoryMesh.h" #include "persistence.h" +#include <any> #include <manyPtr.h> #include <stdTypeDefs.h> class TextureAtlas; class Renderable; +class Location; class Asset : public Persistence::Persistable, public StdTypeDefs<Asset> { public: using ManyPtr = ManySharedPtr<Asset, const Renderable>; using TexturePtr = std::shared_ptr<TextureAtlas>; + /// Used only for the asset viewer + [[nodiscard]] virtual std::any createAt(const Location &) const; + std::string id; std::string name; diff --git a/game/scenary/foliage.cpp b/game/scenary/foliage.cpp index 159a078..140c4e5 100644 --- a/game/scenary/foliage.cpp +++ b/game/scenary/foliage.cpp @@ -2,6 +2,16 @@ #include "gfx/gl/sceneShader.h" #include "gfx/gl/shadowMapper.h" #include "gfx/gl/vertexArrayObject.h" +#include <location.h> + +static_assert(std::is_constructible_v<Foliage>); + +std::any +Foliage::createAt(const Location & position) const +{ + return std::make_shared<InstanceVertices<LocationVertex>::InstanceProxy>( + instances.acquire(position.getRotationTransform(), position.rot.y, position.pos)); +} bool Foliage::persist(Persistence::PersistenceStore & store) diff --git a/game/scenary/foliage.h b/game/scenary/foliage.h index 71bc734..d15a8b0 100644 --- a/game/scenary/foliage.h +++ b/game/scenary/foliage.h @@ -17,6 +17,8 @@ class Foliage : public Asset, public Renderable, public StdTypeDefs<Foliage> { glVertexArray instancePointVAO; public: + [[nodiscard]] std::any createAt(const Location &) const override; + struct LocationVertex { glm::mat3 rotation; float yaw; diff --git a/game/scenary/illuminator.cpp b/game/scenary/illuminator.cpp index f1a02b2..d8e4c4e 100644 --- a/game/scenary/illuminator.cpp +++ b/game/scenary/illuminator.cpp @@ -2,6 +2,16 @@ #include "gfx/gl/sceneShader.h" #include "gfx/gl/vertexArrayObject.h" #include "gfx/models/texture.h" // IWYU pragma: keep +#include <location.h> + +static_assert(std::is_constructible_v<Illuminator>); + +std::any +Illuminator::createAt(const Location & position) const +{ + return std::make_shared<InstanceVertices<LocationVertex>::InstanceProxy>( + instances.acquire(position.getRotationTransform(), position.pos)); +} bool Illuminator::SpotLight::persist(Persistence::PersistenceStore & store) diff --git a/game/scenary/illuminator.h b/game/scenary/illuminator.h index 47ce337..200ba40 100644 --- a/game/scenary/illuminator.h +++ b/game/scenary/illuminator.h @@ -15,6 +15,8 @@ class Illuminator : public Asset, public Renderable, public StdTypeDefs<Illumina std::optional<glVertexArray> instancesSpotLightVAO, instancesPointLightVAO; public: + [[nodiscard]] std::any createAt(const Location &) const override; + struct LightCommonVertex { RelativePosition3D position; RGB colour; diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp index 162a29a..21f01c8 100644 --- a/game/vehicles/railVehicleClass.cpp +++ b/game/vehicles/railVehicleClass.cpp @@ -17,6 +17,19 @@ RailVehicleClass::persist(Persistence::PersistenceStore & store) && STORE_HELPER(bodyMesh, Asset::MeshConstruct) && Asset::persist(store); } +std::any +RailVehicleClass::createAt(const Location & position) const +{ + return std::make_shared<InstanceVertices<LocationVertex>::InstanceProxy>(instances.acquire(LocationVertex { + .body = position.getRotationTransform(), + .front = position.getRotationTransform(), + .back = position.getRotationTransform(), + .bodyPos = position.pos, + .frontPos = {sincos(position.rot.x) * wheelBase * 0.5F, position.pos.z}, + .backPos = {sincos(position.rot.x) * wheelBase * -0.5F, position.pos.z}, + })); +} + void RailVehicleClass::postLoad() { diff --git a/game/vehicles/railVehicleClass.h b/game/vehicles/railVehicleClass.h index 6eb4ca5..ccff3e2 100644 --- a/game/vehicles/railVehicleClass.h +++ b/game/vehicles/railVehicleClass.h @@ -17,6 +17,8 @@ public: void render(const SceneShader & shader, const Frustum &) const override; void shadows(const ShadowMapper & shadowMapper, const Frustum &) const override; + [[nodiscard]] std::any createAt(const Location &) const override; + struct LocationVertex { glm::mat3 body, front, back; GlobalPosition3D bodyPos, frontPos, backPos; diff --git a/gfx/gl/sceneProvider.cpp b/gfx/gl/sceneProvider.cpp index e01532e..3681c60 100644 --- a/gfx/gl/sceneProvider.cpp +++ b/gfx/gl/sceneProvider.cpp @@ -5,7 +5,7 @@ void SceneProvider::environment(const SceneShader &, const SceneRenderer & renderer) const { renderer.setAmbientLight({0.5F, 0.5F, 0.5F}); - renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {{-quarter_pi, -quarter_pi}}, *this); + renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {{-quarter_pi, quarter_pi}}, *this); } void diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp index 5d35d01..9a4d153 100644 --- a/gfx/gl/sceneRenderer.cpp +++ b/gfx/gl/sceneRenderer.cpp @@ -71,6 +71,7 @@ SceneRenderer::resize(ScreenAbsCoord newSize) configuregdata(gIllumination, GL_RGB8, GL_RGB); glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.x, size.y); + shader.setViewPort({0, 0, size.x, size.y}); } void diff --git a/test/testMainWindow.cpp b/test/testMainWindow.cpp index 4a76044..d048682 100644 --- a/test/testMainWindow.cpp +++ b/test/testMainWindow.cpp @@ -2,7 +2,7 @@ #include <boost/test/test_tools.hpp> #include <format> -TestMainWindow::TestMainWindow() : MainWindow {1, 1, __FILE__, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN} +TestMainWindow::TestMainWindow() : MainWindow {{1, 1}, __FILE__, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN} { glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback( diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index cc74f66..dbbf8a7 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -50,15 +50,13 @@ private: GameMainSelector * gms; }; -GameMainWindow::GameMainWindow(size_t w, size_t h) : SceneRenderer {{w, h}, 0} +GameMainWindow::GameMainWindow(ScreenAbsCoord size) : SceneRenderer {size, 0} { uiComponents.create<ManualCameraController>(glm::vec2 {310'727'624, 494'018'810}); auto gms = uiComponents.create<GameMainSelector>(&camera); uiComponents.create<GameMainToolbar>(gms); } -GameMainWindow::~GameMainWindow() { } - void GameMainWindow::tick(TickDuration) { @@ -85,7 +83,7 @@ GameMainWindow::handleInput(const SDL_Event & event) } void -GameMainWindow::render() const +GameMainWindow::render() { SceneRenderer::render(*this); glEnable(GL_BLEND); diff --git a/ui/gameMainWindow.h b/ui/gameMainWindow.h index b0f1592..71b6314 100644 --- a/ui/gameMainWindow.h +++ b/ui/gameMainWindow.h @@ -3,18 +3,13 @@ #include "chronology.h" #include "gfx/gl/sceneRenderer.h" #include "windowContent.h" -#include <cstddef> class GameMainWindow : public WindowContent, SceneRenderer, public SceneProvider { public: - GameMainWindow(size_t w, size_t h); - ~GameMainWindow() override; - - NO_MOVE(GameMainWindow); - NO_COPY(GameMainWindow); + GameMainWindow(ScreenAbsCoord size); void tick(TickDuration) override; - void render() const override; + void render() override; private: bool handleInput(const SDL_Event &) override; diff --git a/ui/mainWindow.cpp b/ui/mainWindow.cpp index 73c0b5b..57dabc0 100644 --- a/ui/mainWindow.cpp +++ b/ui/mainWindow.cpp @@ -8,12 +8,7 @@ #include "backends/imgui_impl_sdl2.h" #pragma GCC diagnostic pop -MainWindow::MainWindow(size_t w, size_t h) : - MainWindow {w, h, "I Like Trains", SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL} -{ -} - -MainWindow::MainWindow(size_t w, size_t h, const std::string & title, Uint32 flags) : Window {w, h, title, flags} +MainWindow::MainWindow(ScreenAbsCoord size, const char * title, Uint32 flags) : Window {size, title, flags} { if (const auto version = gladLoadGL(reinterpret_cast<GLADloadfunc>(SDL_GL_GetProcAddress)); version < 30003) { throw std::runtime_error {std::format("Insufficient OpenGL version: {}", version)}; diff --git a/ui/mainWindow.h b/ui/mainWindow.h index fe26c5c..d2de9b3 100644 --- a/ui/mainWindow.h +++ b/ui/mainWindow.h @@ -5,12 +5,9 @@ class MainWindow : public Window { public: - MainWindow(size_t w, size_t h); + MainWindow(ScreenAbsCoord size, const char * title, Uint32 flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL); ~MainWindow() override; NO_MOVE(MainWindow); NO_COPY(MainWindow); - -protected: - MainWindow(size_t width, size_t height, const std::string & title, Uint32 flags); }; diff --git a/ui/window.cpp b/ui/window.cpp index 732e9ef..06857b2 100644 --- a/ui/window.cpp +++ b/ui/window.cpp @@ -7,10 +7,9 @@ #include "backends/imgui_impl_sdl2.h" #pragma GCC diagnostic pop -Window::Window(size_t width, size_t height, const std::string & title, Uint32 flags) : - size {static_cast<int>(width), static_cast<int>(height)}, - m_window {title.c_str(), static_cast<int>(SDL_WINDOWPOS_CENTERED), static_cast<int>(SDL_WINDOWPOS_CENTERED), size.x, - size.y, flags}, +Window::Window(ScreenAbsCoord size, const char * title, Uint32 flags) : + m_window {title, static_cast<int>(SDL_WINDOWPOS_CENTERED), static_cast<int>(SDL_WINDOWPOS_CENTERED), size.x, size.y, + flags}, glContext {m_window} { } diff --git a/ui/window.h b/ui/window.h index 62c34de..99a977f 100644 --- a/ui/window.h +++ b/ui/window.h @@ -15,7 +15,7 @@ using SDL_GLContextPtr = wrapped_ptrt<GL_Context, SDL_GL_CreateContext, SDL_GL_D class Window { public: - Window(size_t width, size_t height, const std::string & title, Uint32 flags); + Window(ScreenAbsCoord size, const char * title, Uint32 flags); virtual ~Window() = default; NO_COPY(Window); @@ -27,7 +27,7 @@ public: { glm::ivec2 size {}; SDL_GetWindowSizeInPixels(m_window, &size.x, &size.y); - content = std::make_unique<C>(size.x, size.y, std::forward<P>(p)...); + content = std::make_unique<C>(ScreenAbsCoord {size.x, size.y}, std::forward<P>(p)...); } void tick(TickDuration elapsed); @@ -39,7 +39,6 @@ public: protected: void clear(float r, float g, float b, float a) const; - const ScreenAbsCoord size; SDL_WindowPtr m_window; SDL_GLContextPtr glContext; WindowContent::Ptr content; diff --git a/ui/windowContent.h b/ui/windowContent.h index 762d1cc..34cbea3 100644 --- a/ui/windowContent.h +++ b/ui/windowContent.h @@ -14,7 +14,7 @@ public: NO_COPY(WindowContent); virtual void tick(TickDuration); - virtual void render() const = 0; + virtual void render() = 0; virtual bool handleInput(const SDL_Event & e); protected: |