Program Listing for File context.hpp

Return to documentation for file (libtcod/context.hpp)

/* BSD 3-Clause License
 *
 * Copyright © 2008-2025, Jice and the libtcod contributors.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#pragma once
#ifndef LIBTCOD_CONTEXT_HPP_
#define LIBTCOD_CONTEXT_HPP_
#include <array>
#include <filesystem>
#include <stdexcept>

#include "config.h"
#include "console.h"
#include "console_types.h"
#include "context.h"
#include "context_init.h"
#include "context_viewport.h"
#include "error.hpp"
#include "mouse_types.h"
#include "tileset.hpp"

namespace tcod {

class Context {
 public:
  Context() = default;

  explicit Context(const TCOD_ContextParams& params) {
#ifndef NO_SDL
    struct TCOD_Context* context = nullptr;
    check_throw_error(TCOD_context_new(&params, &context));
    context_ = ContextPtr{context};
#else
    throw std::logic_error("Libtcod not compiled with SDL support, so it can not create its own context.");
#endif  // NO_SDL
  };
  explicit Context(ContextPtr&& ptr) : context_{std::move(ptr)} {}
  explicit Context(TCOD_Context* ptr) : context_{ptr} {}

  // Copy disabled, move allowed.
  Context(const Context&) = delete;
  Context& operator=(const Context&) = delete;
  Context(Context&&) = default;
  Context& operator=(Context&&) = default;


  [[nodiscard]] auto get_renderer_type() noexcept -> TCOD_renderer_t {
    return static_cast<TCOD_renderer_t>(TCOD_context_get_renderer_type(context_.get()));
  }

  void present(const TCOD_Console& console, const TCOD_ViewportOptions& viewport) {
    tcod::check_throw_error(TCOD_context_present(context_.get(), &console, &viewport));
  }

  void present(const TCOD_Console& console) {
    tcod::check_throw_error(TCOD_context_present(context_.get(), &console, nullptr));
  }

  [[nodiscard]] auto get_sdl_window() noexcept -> struct SDL_Window* {
    return TCOD_context_get_sdl_window(context_.get());
  }

  [[nodiscard]] auto get_sdl_renderer() noexcept -> struct SDL_Renderer* {
    return TCOD_context_get_sdl_renderer(context_.get());
  }

  [[nodiscard]] auto pixel_to_tile_coordinates(const std::array<int, 2>& xy) -> std::array<int, 2> {
    std::array<int, 2> out{xy[0], xy[1]};
    tcod::check_throw_error(TCOD_context_screen_pixel_to_tile_i(context_.get(), &out[0], &out[1]));
    return out;
  }

  [[nodiscard]] auto pixel_to_tile_coordinates(const std::array<double, 2>& xy) -> std::array<double, 2> {
    std::array<double, 2> out{xy[0], xy[1]};
    tcod::check_throw_error(TCOD_context_screen_pixel_to_tile_d(context_.get(), &out[0], &out[1]));
    return out;
  }

  void convert_event_coordinates(SDL_Event& event) {
    tcod::check_throw_error(TCOD_context_convert_event_coordinates(context_.get(), &event));
  }

  void save_screenshot(const std::filesystem::path& path) {
    tcod::check_throw_error(TCOD_context_save_screenshot(context_.get(), path.string().c_str()));
  }

  void save_screenshot() { tcod::check_throw_error(TCOD_context_save_screenshot(context_.get(), nullptr)); }

  [[nodiscard]] auto new_console(int min_columns = 1, int min_rows = 1, float magnification = 1.0f) -> tcod::Console {
    int columns;
    int rows;
    if (magnification <= 0.0f) {
      throw std::invalid_argument(
          std::string("Magnification must be greater than zero. Got ") + std::to_string(magnification));
    }
    tcod::check_throw_error(TCOD_context_recommended_console_size(context_.get(), magnification, &columns, &rows));
    return tcod::Console{std::max(columns, min_columns), std::max(rows, min_rows)};
  }

  auto change_tileset(tcod::Tileset& new_tileset) -> void {
    check_throw_error(TCOD_context_change_tileset(context_.get(), new_tileset.get()));
  }

  auto set_mouse_transform(const TCOD_MouseTransform& transform) -> void {
    check_throw_error(TCOD_context_set_mouse_transform(context_.get(), &transform));
  }


  [[nodiscard]] auto get_ptr() noexcept -> ContextPtr& { return context_; }

  [[nodiscard]] auto get_ptr() const noexcept -> const ContextPtr& { return context_; }

  auto close() -> void { *this = Context(); }

 private:
  ContextPtr context_ = nullptr;
};
}  // namespace tcod
#endif  // LIBTCOD_CONTEXT_HPP_