<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_EVENTHANDLER_HPP
#define NAZARA_EVENTHANDLER_HPP

#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Event.hpp>

namespace Nz
{
	class EventHandler
	{
		public:
			EventHandler() = default;
			explicit EventHandler(const EventHandler&);
			EventHandler(EventHandler&&) = default;
			~EventHandler() = default;

			inline void Dispatch(const WindowEvent& event);

			EventHandler& operator=(const EventHandler&) = delete;
			EventHandler& operator=(EventHandler&&) = default;

			NazaraSignal(OnEvent, const EventHandler* /*eventHandler*/, const WindowEvent& /*event*/);
			NazaraSignal(OnGainedFocus, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnLostFocus, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnKeyPressed, const EventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
			NazaraSignal(OnKeyReleased, const EventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
			NazaraSignal(OnMouseButtonDoubleClicked, const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
			NazaraSignal(OnMouseButtonPressed, const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
			NazaraSignal(OnMouseButtonReleased, const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
			NazaraSignal(OnMouseEntered, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnMouseLeft, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnMouseMoved, const EventHandler* /*eventHandler*/, const WindowEvent::MouseMoveEvent& /*event*/);
			NazaraSignal(OnMouseWheelMoved, const EventHandler* /*eventHandler*/, const WindowEvent::MouseWheelEvent& /*event*/);
			NazaraSignal(OnMoved, const EventHandler* /*eventHandler*/, const WindowEvent::PositionEvent& /*event*/);
			NazaraSignal(OnQuit, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnResized, const EventHandler* /*eventHandler*/, const WindowEvent::SizeEvent& /*event*/);
			NazaraSignal(OnTextEntered, const EventHandler* /*eventHandler*/, const WindowEvent::TextEvent& /*event*/);
	};
}

#include <Nazara/Utility/EventHandler.inl>

#endif // NAZARA_EVENTHANDLER_HPP
<commit_msg>Utility: Make EventHandler a handled object<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_EVENTHANDLER_HPP
#define NAZARA_EVENTHANDLER_HPP

#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Event.hpp>

namespace Nz
{
	class EventHandler;

	using EventHandlerHandle = Nz::ObjectRef<EventHandler>;

	class EventHandler : public HandledObject<EventHandler>
	{
		public:
			EventHandler() = default;
			explicit EventHandler(const EventHandler&);
			EventHandler(EventHandler&&) = default;
			~EventHandler() = default;

			inline void Dispatch(const WindowEvent& event);

			EventHandler& operator=(const EventHandler&) = delete;
			EventHandler& operator=(EventHandler&&) = default;

			NazaraSignal(OnEvent, const EventHandler* /*eventHandler*/, const WindowEvent& /*event*/);
			NazaraSignal(OnGainedFocus, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnLostFocus, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnKeyPressed, const EventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
			NazaraSignal(OnKeyReleased, const EventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
			NazaraSignal(OnMouseButtonDoubleClicked, const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
			NazaraSignal(OnMouseButtonPressed, const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
			NazaraSignal(OnMouseButtonReleased, const EventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
			NazaraSignal(OnMouseEntered, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnMouseLeft, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnMouseMoved, const EventHandler* /*eventHandler*/, const WindowEvent::MouseMoveEvent& /*event*/);
			NazaraSignal(OnMouseWheelMoved, const EventHandler* /*eventHandler*/, const WindowEvent::MouseWheelEvent& /*event*/);
			NazaraSignal(OnMoved, const EventHandler* /*eventHandler*/, const WindowEvent::PositionEvent& /*event*/);
			NazaraSignal(OnQuit, const EventHandler* /*eventHandler*/);
			NazaraSignal(OnResized, const EventHandler* /*eventHandler*/, const WindowEvent::SizeEvent& /*event*/);
			NazaraSignal(OnTextEntered, const EventHandler* /*eventHandler*/, const WindowEvent::TextEvent& /*event*/);
	};
}

#include <Nazara/Utility/EventHandler.inl>

#endif // NAZARA_EVENTHANDLER_HPP
<|endoftext|>


<commit_before>#pragma once

#include "blackhole/factory.hpp"
#include "blackhole/forward.hpp"

namespace blackhole {
inline namespace v1 {
namespace experimental {
namespace sink {

/// The asynchronous sink wraps the other sink and causes log events to be written to them on a
/// separate thread.
/// Note that exceptions while writing to those sink will be hidden from the application.
/// # Parameters
///
/// The factor value maps directly into the queue capacity and equals exp2(factor). The value must
/// fit in [0; 20] range (1048576 items).
///
/// \throw std::invalid_argument on construction if the factor is greater than 20.
class asynchronous_t;

}  // namespace sink

template<>
class factory<sink::asynchronous_t> : public experimental::factory<sink_t> {
    const registry_t& registry;

public:
    constexpr explicit factory(const registry_t& registry) noexcept :
        registry(registry)
    {}

    virtual auto type() const noexcept -> const char* override;
    virtual auto from(const config::node_t& config) const -> std::unique_ptr<sink_t> override;
};

}  // namespace experimental
}  // namespace v1
}  // namespace blackhole
<commit_msg>docs: add more docs<commit_after>#pragma once

#include "blackhole/factory.hpp"
#include "blackhole/forward.hpp"

namespace blackhole {
inline namespace v1 {
namespace experimental {
namespace sink {

/// The asynchronous sink wraps the other sink and causes log events to be written to them on a
/// separate thread.
///
/// Depending on the underlying overflow policies and queues the implementation may preallocate the
/// space required to keep all item structs in the memory.
///
/// \note exceptions while writing to those sink will be hidden from the application.
///
/// # Parameters
///
/// The factor value maps directly into the queue capacity and equals exp2(factor). The value must
/// fit in [0; 20] range (1048576 items).
///
/// Overflow policy decides what action is taken when the queue is overflowed. There are currently
/// only two available policies: drop and wait. The first one will silently (or not) drop all log
/// events that weren't enqueued. The second one will block the caller thread until the queue is
/// full.
///
/// \throw std::invalid_argument on construction if the factor is greater than 20.
/// \throw std::invalid_argument on construction if the overflow policy value differs from "drop" or
///     "wait".
class asynchronous_t;

}  // namespace sink

/// Represents asynchronous sink factory.
///
/// Register an instance of this class in the registry to be able to construct asynchronous sinks
/// via config.
template<>
class factory<sink::asynchronous_t> : public experimental::factory<sink_t> {
    const registry_t& registry;

public:
    constexpr explicit factory(const registry_t& registry) noexcept :
        registry(registry)
    {}

    virtual auto type() const noexcept -> const char* override;
    virtual auto from(const config::node_t& config) const -> std::unique_ptr<sink_t> override;
};

}  // namespace experimental
}  // namespace v1
}  // namespace blackhole
<|endoftext|>


<commit_before>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/render/detail/texturing.hpp
 *
 * Copyright 2014-2017 Patrik Huber
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#ifndef EOS_TEXTURING_DETAIL_HPP
#define EOS_TEXTURING_DETAIL_HPP

#include "eos/render/Texture.hpp"

#include "glm/vec2.hpp"
#include "glm/vec3.hpp"

#include <algorithm>
#include <cmath>

/**
 * Implementations of internal functions, not part of the
 * API we expose and not meant to be used by a user.
 */
namespace eos {
namespace render {
namespace detail {

// used only in tex2D_linear_mipmap_linear
// template?
inline float clamp(float x, float a, float b)
{
    return std::max(std::min(x, b), a);
};

inline glm::vec2 texcoord_wrap(const glm::vec2& texcoords)
{
    return glm::vec2(texcoords[0] - (int)texcoords[0], texcoords[1] - (int)texcoords[1]);
};

// forward decls
glm::vec3 tex2d_linear_mipmap_linear(const glm::vec2& texcoords, const Texture& texture, float dudx,
                                     float dudy, float dvdx, float dvdy);
glm::vec3 tex2d_linear(const glm::vec2& imageTexCoord, unsigned char mipmapIndex, const Texture& texture);

inline glm::vec3 tex2d(const glm::vec2& texcoords, const Texture& texture, float dudx, float dudy, float dvdx,
                       float dvdy)
{
    return (1.0f / 255.0f) * tex2d_linear_mipmap_linear(texcoords, texture, dudx, dudy, dvdx, dvdy);
};

template <typename T, glm::precision P = glm::defaultp>
glm::tvec3<T, P> tex2d(const glm::tvec2<T, P>& texcoords, const Texture& texture, float dudx, float dudy,
                       float dvdx, float dvdy)
{
    // Todo: Change everything to GLM.
    glm::vec3 ret = (1.0f / 255.0f) * tex2d_linear_mipmap_linear(glm::vec2(texcoords[0], texcoords[1]),
                                                                 texture, dudx, dudy, dvdx, dvdy);
    return glm::tvec3<T, P>(ret[0], ret[1], ret[2]);
};

inline glm::vec3 tex2d_linear_mipmap_linear(const glm::vec2& texcoords, const Texture& texture, float dudx,
                                            float dudy, float dvdx, float dvdy)
{
    using glm::vec2;
    const float px = std::sqrt(std::pow(dudx, 2) + std::pow(dvdx, 2));
    const float py = std::sqrt(std::pow(dudy, 2) + std::pow(dvdy, 2));
    constexpr double ln2 = 0.69314718056;
    const float lambda = std::log(std::max(px, py)) / static_cast<float>(ln2);
    const unsigned char mipmapIndex1 =
        detail::clamp((int)lambda, 0.0f, std::max(texture.widthLog, texture.heightLog) - 1);
    const unsigned char mipmapIndex2 = mipmapIndex1 + 1;

    const vec2 imageTexCoord = detail::texcoord_wrap(texcoords);
    vec2 imageTexCoord1 = imageTexCoord;
    imageTexCoord1[0] *= texture.mipmaps[mipmapIndex1].width();
    imageTexCoord1[1] *= texture.mipmaps[mipmapIndex1].height();
    vec2 imageTexCoord2 = imageTexCoord;
    imageTexCoord2[0] *= texture.mipmaps[mipmapIndex2].width();
    imageTexCoord2[1] *= texture.mipmaps[mipmapIndex2].height();

    glm::vec3 color, color1, color2;
    color1 = tex2d_linear(imageTexCoord1, mipmapIndex1, texture);
    color2 = tex2d_linear(imageTexCoord2, mipmapIndex2, texture);
    float lambdaFrac = std::max(lambda, 0.0f);
    lambdaFrac = lambdaFrac - (int)lambdaFrac;
    color = (1.0f - lambdaFrac) * color1 + lambdaFrac * color2;

    return color;
};

inline glm::vec3 tex2d_linear(const glm::vec2& imageTexCoord, unsigned char mipmap_index,
                              const Texture& texture)
{
    const int x = (int)imageTexCoord[0];
    const int y = (int)imageTexCoord[1];
    const float alpha = imageTexCoord[0] - x;
    const float beta = imageTexCoord[1] - y;
    const float oneMinusAlpha = 1.0f - alpha;
    const float oneMinusBeta = 1.0f - beta;
    const float a = oneMinusAlpha * oneMinusBeta;
    const float b = alpha * oneMinusBeta;
    const float c = oneMinusAlpha * beta;
    const float d = alpha * beta;
    glm::vec3 color;

    // int pixelIndex;
    // pixelIndex = getPixelIndex_wrap(x, y, texture->mipmaps[mipmapIndex].cols,
    // texture->mipmaps[mipmapIndex].rows);
    int pixelIndexCol = x;
    if (pixelIndexCol == texture.mipmaps[mipmap_index].width())
    {
        pixelIndexCol = 0;
    }
    int pixelIndexRow = y;
    if (pixelIndexRow == texture.mipmaps[mipmap_index].height())
    {
        pixelIndexRow = 0;
    }
    // std::cout << texture.mipmaps[mipmapIndex].cols << " " << texture.mipmaps[mipmapIndex].rows << " " <<
    // texture.mipmaps[mipmapIndex].channels() << std::endl;  cv::imwrite("mm.png",
    // texture.mipmaps[mipmapIndex]);
    color[0] = a * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[0];
    color[1] = a * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[1];
    color[2] = a * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[2];

    // pixelIndex = getPixelIndex_wrap(x + 1, y, texture.mipmaps[mipmapIndex].cols,
    // texture.mipmaps[mipmapIndex].rows);
    pixelIndexCol = x + 1;
    if (pixelIndexCol == texture.mipmaps[mipmap_index].width())
    {
        pixelIndexCol = 0;
    }
    pixelIndexRow = y;
    if (pixelIndexRow == texture.mipmaps[mipmap_index].height())
    {
        pixelIndexRow = 0;
    }
    color[0] += b * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[0];
    color[1] += b * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[1];
    color[2] += b * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[2];

    // pixelIndex = getPixelIndex_wrap(x, y + 1, texture.mipmaps[mipmapIndex].cols,
    // texture.mipmaps[mipmapIndex].rows);
    pixelIndexCol = x;
    if (pixelIndexCol == texture.mipmaps[mipmap_index].width())
    {
        pixelIndexCol = 0;
    }
    pixelIndexRow = y + 1;
    if (pixelIndexRow == texture.mipmaps[mipmap_index].height())
    {
        pixelIndexRow = 0;
    }
    color[0] += c * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[0];
    color[1] += c * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[1];
    color[2] += c * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[2];

    // pixelIndex = getPixelIndex_wrap(x + 1, y + 1, texture.mipmaps[mipmapIndex].cols,
    // texture.mipmaps[mipmapIndex].rows);
    pixelIndexCol = x + 1;
    if (pixelIndexCol == texture.mipmaps[mipmap_index].width())
    {
        pixelIndexCol = 0;
    }
    pixelIndexRow = y + 1;
    if (pixelIndexRow == texture.mipmaps[mipmap_index].height())
    {
        pixelIndexRow = 0;
    }
    color[0] += d * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[0];
    color[1] += d * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[1];
    color[2] += d * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[2];

    return color;
};

} /* namespace detail */
} /* namespace render */
} /* namespace eos */

#endif /* EOS_TEXTURING_DETAIL_HPP */
<commit_msg>Removed outdated todo comment<commit_after>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/render/detail/texturing.hpp
 *
 * Copyright 2014-2017 Patrik Huber
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#ifndef EOS_TEXTURING_DETAIL_HPP
#define EOS_TEXTURING_DETAIL_HPP

#include "eos/render/Texture.hpp"

#include "glm/vec2.hpp"
#include "glm/vec3.hpp"

#include <algorithm>
#include <cmath>

/**
 * Implementations of internal functions, not part of the
 * API we expose and not meant to be used by a user.
 */
namespace eos {
namespace render {
namespace detail {

// used only in tex2D_linear_mipmap_linear
// template?
inline float clamp(float x, float a, float b)
{
    return std::max(std::min(x, b), a);
};

inline glm::vec2 texcoord_wrap(const glm::vec2& texcoords)
{
    return glm::vec2(texcoords[0] - (int)texcoords[0], texcoords[1] - (int)texcoords[1]);
};

// forward decls
glm::vec3 tex2d_linear_mipmap_linear(const glm::vec2& texcoords, const Texture& texture, float dudx,
                                     float dudy, float dvdx, float dvdy);
glm::vec3 tex2d_linear(const glm::vec2& imageTexCoord, unsigned char mipmapIndex, const Texture& texture);

inline glm::vec3 tex2d(const glm::vec2& texcoords, const Texture& texture, float dudx, float dudy, float dvdx,
                       float dvdy)
{
    return (1.0f / 255.0f) * tex2d_linear_mipmap_linear(texcoords, texture, dudx, dudy, dvdx, dvdy);
};

template <typename T, glm::precision P = glm::defaultp>
glm::tvec3<T, P> tex2d(const glm::tvec2<T, P>& texcoords, const Texture& texture, float dudx, float dudy,
                       float dvdx, float dvdy)
{
    glm::vec3 ret = (1.0f / 255.0f) * tex2d_linear_mipmap_linear(glm::vec2(texcoords[0], texcoords[1]),
                                                                 texture, dudx, dudy, dvdx, dvdy);
    return glm::tvec3<T, P>(ret[0], ret[1], ret[2]);
};

inline glm::vec3 tex2d_linear_mipmap_linear(const glm::vec2& texcoords, const Texture& texture, float dudx,
                                            float dudy, float dvdx, float dvdy)
{
    using glm::vec2;
    const float px = std::sqrt(std::pow(dudx, 2) + std::pow(dvdx, 2));
    const float py = std::sqrt(std::pow(dudy, 2) + std::pow(dvdy, 2));
    constexpr double ln2 = 0.69314718056;
    const float lambda = std::log(std::max(px, py)) / static_cast<float>(ln2);
    const unsigned char mipmapIndex1 =
        detail::clamp((int)lambda, 0.0f, std::max(texture.widthLog, texture.heightLog) - 1);
    const unsigned char mipmapIndex2 = mipmapIndex1 + 1;

    const vec2 imageTexCoord = detail::texcoord_wrap(texcoords);
    vec2 imageTexCoord1 = imageTexCoord;
    imageTexCoord1[0] *= texture.mipmaps[mipmapIndex1].width();
    imageTexCoord1[1] *= texture.mipmaps[mipmapIndex1].height();
    vec2 imageTexCoord2 = imageTexCoord;
    imageTexCoord2[0] *= texture.mipmaps[mipmapIndex2].width();
    imageTexCoord2[1] *= texture.mipmaps[mipmapIndex2].height();

    glm::vec3 color, color1, color2;
    color1 = tex2d_linear(imageTexCoord1, mipmapIndex1, texture);
    color2 = tex2d_linear(imageTexCoord2, mipmapIndex2, texture);
    float lambdaFrac = std::max(lambda, 0.0f);
    lambdaFrac = lambdaFrac - (int)lambdaFrac;
    color = (1.0f - lambdaFrac) * color1 + lambdaFrac * color2;

    return color;
};

inline glm::vec3 tex2d_linear(const glm::vec2& imageTexCoord, unsigned char mipmap_index,
                              const Texture& texture)
{
    const int x = (int)imageTexCoord[0];
    const int y = (int)imageTexCoord[1];
    const float alpha = imageTexCoord[0] - x;
    const float beta = imageTexCoord[1] - y;
    const float oneMinusAlpha = 1.0f - alpha;
    const float oneMinusBeta = 1.0f - beta;
    const float a = oneMinusAlpha * oneMinusBeta;
    const float b = alpha * oneMinusBeta;
    const float c = oneMinusAlpha * beta;
    const float d = alpha * beta;
    glm::vec3 color;

    // int pixelIndex;
    // pixelIndex = getPixelIndex_wrap(x, y, texture->mipmaps[mipmapIndex].cols,
    // texture->mipmaps[mipmapIndex].rows);
    int pixelIndexCol = x;
    if (pixelIndexCol == texture.mipmaps[mipmap_index].width())
    {
        pixelIndexCol = 0;
    }
    int pixelIndexRow = y;
    if (pixelIndexRow == texture.mipmaps[mipmap_index].height())
    {
        pixelIndexRow = 0;
    }
    // std::cout << texture.mipmaps[mipmapIndex].cols << " " << texture.mipmaps[mipmapIndex].rows << " " <<
    // texture.mipmaps[mipmapIndex].channels() << std::endl;  cv::imwrite("mm.png",
    // texture.mipmaps[mipmapIndex]);
    color[0] = a * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[0];
    color[1] = a * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[1];
    color[2] = a * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[2];

    // pixelIndex = getPixelIndex_wrap(x + 1, y, texture.mipmaps[mipmapIndex].cols,
    // texture.mipmaps[mipmapIndex].rows);
    pixelIndexCol = x + 1;
    if (pixelIndexCol == texture.mipmaps[mipmap_index].width())
    {
        pixelIndexCol = 0;
    }
    pixelIndexRow = y;
    if (pixelIndexRow == texture.mipmaps[mipmap_index].height())
    {
        pixelIndexRow = 0;
    }
    color[0] += b * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[0];
    color[1] += b * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[1];
    color[2] += b * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[2];

    // pixelIndex = getPixelIndex_wrap(x, y + 1, texture.mipmaps[mipmapIndex].cols,
    // texture.mipmaps[mipmapIndex].rows);
    pixelIndexCol = x;
    if (pixelIndexCol == texture.mipmaps[mipmap_index].width())
    {
        pixelIndexCol = 0;
    }
    pixelIndexRow = y + 1;
    if (pixelIndexRow == texture.mipmaps[mipmap_index].height())
    {
        pixelIndexRow = 0;
    }
    color[0] += c * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[0];
    color[1] += c * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[1];
    color[2] += c * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[2];

    // pixelIndex = getPixelIndex_wrap(x + 1, y + 1, texture.mipmaps[mipmapIndex].cols,
    // texture.mipmaps[mipmapIndex].rows);
    pixelIndexCol = x + 1;
    if (pixelIndexCol == texture.mipmaps[mipmap_index].width())
    {
        pixelIndexCol = 0;
    }
    pixelIndexRow = y + 1;
    if (pixelIndexRow == texture.mipmaps[mipmap_index].height())
    {
        pixelIndexRow = 0;
    }
    color[0] += d * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[0];
    color[1] += d * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[1];
    color[2] += d * texture.mipmaps[mipmap_index](pixelIndexRow, pixelIndexCol)[2];

    return color;
};

} /* namespace detail */
} /* namespace render */
} /* namespace eos */

#endif /* EOS_TEXTURING_DETAIL_HPP */
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_FRAMEWORK_MENUCONFIGURATION_HXX
#define INCLUDED_FRAMEWORK_MENUCONFIGURATION_HXX

#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/WrappedTargetException.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>

#include <framework/fwedllapi.h>

#include <cppuhelper/weak.hxx>
#include <vcl/menu.hxx>
#include <vcl/toolbox.hxx>

#define BOOKMARK_NEWMENU        OUString( "private:menu_bookmark_new" )
#define BOOKMARK_WIZARDMENU     OUString( "private:menu_bookmark_wizard" )

// Prepare for inclusion by framework and sfx
// Please consider that there is a corresponding define also in sfxsids.hrc!! (SID_SFX_START)/(SID_ADDONS)
#define FWK_SID_SFX_START 5000
#define FWK_SID_ADDONS (FWK_SID_SFX_START+1678)
#define FWK_SID_ADDONHELP (FWK_SID_SFX_START+1684)

const sal_uInt16 START_ITEMID_PICKLIST      = 4500;
const sal_uInt16 END_ITEMID_PICKLIST        = 4599;
const sal_uInt16 MAX_ITEMCOUNT_PICKLIST     =   99; // difference between START_... & END_... for picklist / must be changed too, if these values are changed!
const sal_uInt16 START_ITEMID_WINDOWLIST    = 4600;
const sal_uInt16 END_ITEMID_WINDOWLIST      = 4699;
const sal_uInt16 ITEMID_ADDONLIST           = FWK_SID_ADDONS;
const sal_uInt16 ITEMID_ADDONHELP           = FWK_SID_ADDONHELP;

namespace framework
{

class FWE_DLLPUBLIC MenuConfiguration
{
    public:
        struct Attributes
        {
            Attributes() {}
            Attributes( const OUString& aFrame, const OUString& aImageIdStr ) :
                aTargetFrame( aFrame ), aImageId( aImageIdStr ) {}

            OUString aTargetFrame;
            OUString aImageId;
            ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XDispatchProvider > xDispatchProvider;
                        sal_Int16 nStyle;
        };

        MenuConfiguration(
            // use const when giving a uno reference by reference
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext );

        virtual ~MenuConfiguration();

        ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > CreateMenuBarConfigurationFromXML(
            ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rInputStream )
            throw ( ::com::sun::star::lang::WrappedTargetException );

        PopupMenu* CreateBookmarkMenu(
                ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame,
                const OUString& aURL )
            throw ( ::com::sun::star::lang::WrappedTargetException );

        ToolBox* CreateToolBoxFromConfiguration(
            ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rInputStream )
            throw ( ::com::sun::star::lang::WrappedTargetException );

        void StoreMenuBarConfigurationToXML( ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rMenuBarConfiguration,
                      ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& rOutputStream )
            throw ( ::com::sun::star::lang::WrappedTargetException );

        void StoreToolBox( ToolBox* pToolBox,
                      ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& rOutputStream )
            throw ( ::com::sun::star::lang::WrappedTargetException );

    private:
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> m_xContext;
};

}

#endif // INCLUDED_FRAMEWORK_MENUCONFIGURATION_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#707869 Uninitialized scalar field<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_FRAMEWORK_MENUCONFIGURATION_HXX
#define INCLUDED_FRAMEWORK_MENUCONFIGURATION_HXX

#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/WrappedTargetException.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>

#include <framework/fwedllapi.h>

#include <cppuhelper/weak.hxx>
#include <vcl/menu.hxx>
#include <vcl/toolbox.hxx>

#define BOOKMARK_NEWMENU        OUString( "private:menu_bookmark_new" )
#define BOOKMARK_WIZARDMENU     OUString( "private:menu_bookmark_wizard" )

// Prepare for inclusion by framework and sfx
// Please consider that there is a corresponding define also in sfxsids.hrc!! (SID_SFX_START)/(SID_ADDONS)
#define FWK_SID_SFX_START 5000
#define FWK_SID_ADDONS (FWK_SID_SFX_START+1678)
#define FWK_SID_ADDONHELP (FWK_SID_SFX_START+1684)

const sal_uInt16 START_ITEMID_PICKLIST      = 4500;
const sal_uInt16 END_ITEMID_PICKLIST        = 4599;
const sal_uInt16 MAX_ITEMCOUNT_PICKLIST     =   99; // difference between START_... & END_... for picklist / must be changed too, if these values are changed!
const sal_uInt16 START_ITEMID_WINDOWLIST    = 4600;
const sal_uInt16 END_ITEMID_WINDOWLIST      = 4699;
const sal_uInt16 ITEMID_ADDONLIST           = FWK_SID_ADDONS;
const sal_uInt16 ITEMID_ADDONHELP           = FWK_SID_ADDONHELP;

namespace framework
{

class FWE_DLLPUBLIC MenuConfiguration
{
    public:
        struct Attributes
        {
            Attributes()
                : nStyle(0)
            {
            }

            Attributes( const OUString& aFrame, const OUString& aImageIdStr )
                : aTargetFrame(aFrame)
                , aImageId(aImageIdStr)
                , nStyle(0)
            {
            }

            OUString aTargetFrame;
            OUString aImageId;
            ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XDispatchProvider > xDispatchProvider;
            sal_Int16 nStyle;
        };

        MenuConfiguration(
            // use const when giving a uno reference by reference
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext );

        virtual ~MenuConfiguration();

        ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > CreateMenuBarConfigurationFromXML(
            ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rInputStream )
            throw ( ::com::sun::star::lang::WrappedTargetException );

        PopupMenu* CreateBookmarkMenu(
                ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame,
                const OUString& aURL )
            throw ( ::com::sun::star::lang::WrappedTargetException );

        ToolBox* CreateToolBoxFromConfiguration(
            ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rInputStream )
            throw ( ::com::sun::star::lang::WrappedTargetException );

        void StoreMenuBarConfigurationToXML( ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rMenuBarConfiguration,
                      ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& rOutputStream )
            throw ( ::com::sun::star::lang::WrappedTargetException );

        void StoreToolBox( ToolBox* pToolBox,
                      ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& rOutputStream )
            throw ( ::com::sun::star::lang::WrappedTargetException );

    private:
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> m_xContext;
};

}

#endif // INCLUDED_FRAMEWORK_MENUCONFIGURATION_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author 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 OWNER 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.

*/
#ifndef NODE_ID_HPP
#define NODE_ID_HPP

#include <algorithm>

#include <boost/cstdint.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/address.hpp"

namespace libtorrent { namespace dht
{

typedef libtorrent::big_number node_id;

// returns the distance between the two nodes
// using the kademlia XOR-metric
node_id TORRENT_EXTRA_EXPORT distance(node_id const& n1, node_id const& n2);

// returns true if: distance(n1, ref) < distance(n2, ref)
bool TORRENT_EXTRA_EXPORT compare_ref(node_id const& n1, node_id const& n2, node_id const& ref);

// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
// usefult for finding out which bucket a node belongs to
int TORRENT_EXTRA_EXPORT distance_exp(node_id const& n1, node_id const& n2);

node_id TORRENT_EXTRA_EXPORT generate_id(address const& external_ip);
node_id TORRENT_EXTRA_EXPORT generate_random_id();

bool TORRENT_EXTRA_EXPORT verify_id(node_id const& nid, address const& source_ip);

} } // namespace libtorrent::dht

#endif // NODE_ID_HPP

<commit_msg>fix dht node ID generator unit test on windows<commit_after>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * 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.
    * Neither the name of the author 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 OWNER 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.

*/
#ifndef NODE_ID_HPP
#define NODE_ID_HPP

#include <algorithm>

#include <boost/cstdint.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/address.hpp"

namespace libtorrent { namespace dht
{

typedef libtorrent::big_number node_id;

// returns the distance between the two nodes
// using the kademlia XOR-metric
node_id TORRENT_EXTRA_EXPORT distance(node_id const& n1, node_id const& n2);

// returns true if: distance(n1, ref) < distance(n2, ref)
bool TORRENT_EXTRA_EXPORT compare_ref(node_id const& n1, node_id const& n2, node_id const& ref);

// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
// usefult for finding out which bucket a node belongs to
int TORRENT_EXTRA_EXPORT distance_exp(node_id const& n1, node_id const& n2);

node_id TORRENT_EXTRA_EXPORT generate_id(address const& external_ip);
node_id TORRENT_EXTRA_EXPORT generate_random_id();
node_id TORRENT_EXTRA_EXPORT generate_id_impl(address const& ip_, boost::uint32_t r);

bool TORRENT_EXTRA_EXPORT verify_id(node_id const& nid, address const& source_ip);

} } // namespace libtorrent::dht

#endif // NODE_ID_HPP

<|endoftext|>


<commit_before>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <cassert>

#include "TTFont.hpp"
#include "core/Engine.hpp"
#include "files/FileSystem.hpp"
#include "utils/Log.hpp"
#include "utils/Utils.hpp"
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"

namespace ouzel
{
    TTFont::TTFont():
        Font()
    {
    }

    TTFont::TTFont(const std::string & filename, float fontSize, bool mipmaps, UTFChars flag)
    {
        if (!parseFont(filename, fontSize, mipmaps, flag))
        {
            Log(Log::Level::ERR) << "Failed to parse font " << filename;
        }

        kernCount = static_cast<uint16_t>(kern.size());
    }

    void TTFont::getVertices(const std::string& text,
                             const Color& color,
                             const Vector2& anchor,
                             const Vector2& scale,
                             std::vector<uint16_t>& indices,
                             std::vector<graphics::VertexPCT>& vertices,
                             std::shared_ptr<graphics::Texture>& texture)
    {
        Vector2 position;

        std::vector<uint32_t> utf32Text = utf8to32(text);

        indices.clear();
        vertices.clear();

        indices.reserve(utf32Text.size() * 6);
        vertices.reserve(utf32Text.size() * 4);

        Vector2 textCoords[4];

        size_t firstChar = 0;

        for (auto i = utf32Text.begin(); i != utf32Text.end(); ++i)
        {
            std::unordered_map<uint32_t, CharDescriptor>::iterator iter = chars.find(*i);

            if (iter != chars.end())
            {
                const CharDescriptor& f = iter->second;

                uint16_t startIndex = static_cast<uint16_t>(vertices.size());
                indices.push_back(startIndex + 0);
                indices.push_back(startIndex + 1);
                indices.push_back(startIndex + 2);

                indices.push_back(startIndex + 1);
                indices.push_back(startIndex + 3);
                indices.push_back(startIndex + 2);

                Vector2 leftTop(f.x / static_cast<float>(width),
                                f.y / static_cast<float>(height));

                Vector2 rightBottom((f.x + f.width) / static_cast<float>(width),
                                    (f.y + f.height) / static_cast<float>(height));

                textCoords[0] = Vector2(leftTop.x, rightBottom.y);
                textCoords[1] = Vector2(rightBottom.x, rightBottom.y);
                textCoords[2] = Vector2(leftTop.x, leftTop.y);
                textCoords[3] = Vector2(rightBottom.x, leftTop.y);

                vertices.push_back(graphics::VertexPCT(Vector3(position.x + f.xOffset, -position.y - f.yOffset - f.height, 0.0f),
                                                       color, textCoords[0]));
                vertices.push_back(graphics::VertexPCT(Vector3(position.x + f.xOffset + f.width, -position.y - f.yOffset - f.height, 0.0f),
                                                       color, textCoords[1]));
                vertices.push_back(graphics::VertexPCT(Vector3(position.x + f.xOffset, -position.y - f.yOffset, 0.0f),
                                                       color, textCoords[2]));
                vertices.push_back(graphics::VertexPCT(Vector3(position.x + f.xOffset + f.width, -position.y - f.yOffset, 0.0f),
                                                       color, textCoords[3]));

                if ((i + 1) != utf32Text.end())
                {
                    position.x += static_cast<float>(getKerningPair(*i, *(i + 1)));
                }

                position.x += f.xAdvance;
            }

            if (*i == static_cast<uint32_t>('\n') || // line feed
                (i + 1) == utf32Text.end()) // end of string
            {
                float lineWidth = position.x;
                position.x = 0.0f;
                position.y += lineHeight;

                for (size_t c = firstChar; c < vertices.size(); ++c)
                {
                    vertices[c].position.x -= lineWidth * anchor.x;
                }

                firstChar = vertices.size();
            }
        }

        float textHeight = position.y;

        for (size_t c = 0; c < vertices.size(); ++c)
        {
            vertices[c].position.y += textHeight * (1.0f - anchor.y);

            vertices[c].position.x *= scale.x;
            vertices[c].position.y *= scale.y;
        }

        texture = fontTexture;
    }

    int16_t TTFont::getKerningPair(uint32_t first, uint32_t second)
    {
        auto i = kern.find(std::make_pair(first, second));

        if (i != kern.end())
        {
            return i->second;
        }

        return 0;
    }

    float TTFont::getStringWidth(const std::string& text)
    {
        float total = 0.0f;

        std::vector<uint32_t> utf32Text = utf8to32(text);

        for (auto i = utf32Text.begin(); i != utf32Text.end(); ++i)
        {
            std::unordered_map<uint32_t, CharDescriptor>::iterator iter = chars.find(*i);

            if (iter != chars.end())
            {
                const CharDescriptor& f = iter->second;
                total += f.xAdvance;
            }
        }

        return total;
    }

    bool TTFont::parseFont(const std::string & filename, float fontSize, bool mipmaps, UTFChars flag)
    {
        stbtt_fontinfo font;
        std::vector<unsigned char> data;

        std::string f = ouzel::sharedEngine->getFileSystem()->getPath(filename);

        if (!ouzel::sharedEngine->getFileSystem()->readFile(f, data))
        {
            return false;
        }

        if (!stbtt_InitFont(&font, data.data(), stbtt_GetFontOffsetForIndex(data.data(), 0)))
        {
            Log(Log::Level::ERR) << "Failed to load font";
            return false;
        }

        float s = stbtt_ScaleForPixelHeight(&font, fontSize);

        int w, h, xoff, yoff;
        height = 0;
        width = 0;

        std::vector<uint16_t> glyphs;
        std::map<uint32_t, std::pair<Size2, std::vector<uint8_t>>> glyphToBitmapData;

        if (flag && UTFChars::ASCII)
        {
            for (uint16_t i = 32; i < 127; i++)
            {
                glyphs.push_back(i);
            }
        }
        if (flag && UTFChars::ASCIIPLUS)
        {
            for (uint16_t i = 128; i < 256; i++)
            {
                glyphs.push_back(i);
            }
        }

        for (uint16_t c : glyphs)
        {
            unsigned char* bitmap = stbtt_GetCodepointBitmap(&font, s, s, c, &w, &h, &xoff, &yoff);

            if (bitmap)
            {
                for (uint16_t j : glyphs)
                {
                    int kx = stbtt_GetCodepointKernAdvance(&font, j, c);
                    if (kx == 0) continue;
                    kern.emplace(std::pair<uint32_t, uint32_t>(j, c), static_cast<int16_t>(kx * s));
                }

                int advance, leftBearing;
                stbtt_GetCodepointHMetrics(&font, c, &advance, &leftBearing);
                CharDescriptor nd;
                nd.xAdvance = static_cast<int16_t>(advance * s);
                nd.height = static_cast<int16_t>(h);
                nd.width = static_cast<int16_t>(w);
                nd.xOffset = static_cast<int16_t>(leftBearing * s);
                nd.yOffset = static_cast<int16_t>(h - abs(yoff));

                std::vector<uint8_t> currentBuffer(static_cast<size_t>(h * w));
                std::copy(bitmap, bitmap + h * w, currentBuffer.begin());

                glyphToBitmapData.emplace(c, std::make_pair(Size2(static_cast<float>(w), static_cast<float>(h)), currentBuffer));
                chars.emplace(c, nd);
                height = height < static_cast<uint16_t>(h) ? static_cast<uint16_t>(h) : height;
                width += static_cast<uint16_t>(w);
            }
        }

        std::vector<std::vector<uint8_t>> scanlines(height);
        int x = 0;
        for (const auto &c : glyphToBitmapData)
        {
            uint16_t charHeight = static_cast<uint16_t>(c.second.first.height);
            uint16_t charWidth = static_cast<uint16_t>(c.second.first.width);
            chars.at(c.first).x = static_cast<int16_t>(x);
            chars.at(c.first).y = 0;
            x += charWidth;

            uint16_t extraRows = height - charHeight;
            chars.at(c.first).yOffset += extraRows;
            size_t extraSpaceSize = extraRows * charWidth;
            unsigned int charSize = charHeight * charWidth;
            std::vector<uint8_t> newCharBuffer(extraSpaceSize + charSize, 0x00);
            std::copy(c.second.second.begin(), c.second.second.begin() + charSize, newCharBuffer.data());
            assert(newCharBuffer.size() == height * charWidth);
            for (uint16_t i = 0; i < height; i++)
            {
                size_t scanlinesPreSize = scanlines[i].size();
                scanlines[i].resize(scanlinesPreSize + charWidth);
                uint8_t* bufferStart = newCharBuffer.data() + static_cast<int>(charWidth * i);
                std::copy(bufferStart, bufferStart + charWidth, scanlines[i].data() + scanlinesPreSize);
            }
        }

        std::vector<uint8_t> textureData(scanlines[0].size() * height * 4);
        for (uint16_t i = 0; i < height; i++)
        {
            for (uint32_t j = 0; j < scanlines[0].size(); j++)
            {
                uint8_t b = scanlines[i][j];
                textureData[(i * scanlines[0].size() + j) * 4 + 0] = 255;
                textureData[(i * scanlines[0].size() + j) * 4 + 1] = 255;
                textureData[(i * scanlines[0].size() + j) * 4 + 2] = 255;
                textureData[(i * scanlines[0].size() + j) * 4 + 3] = b;
            }
        }

        fontTexture = std::make_shared<graphics::Texture>();
        fontTexture->init(textureData, Size2(width, height), 0, mipmaps ? 0 : 1);
        pages = 1;
        lineHeight = fontSize;
        kernCount = static_cast<uint16_t>(kern.size());
        base = 0;

        return true;
    }
}
<commit_msg>Remove the unneeded kernCount calculation<commit_after>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <cassert>

#include "TTFont.hpp"
#include "core/Engine.hpp"
#include "files/FileSystem.hpp"
#include "utils/Log.hpp"
#include "utils/Utils.hpp"
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"

namespace ouzel
{
    TTFont::TTFont():
        Font()
    {
    }

    TTFont::TTFont(const std::string & filename, float fontSize, bool mipmaps, UTFChars flag)
    {
        if (!parseFont(filename, fontSize, mipmaps, flag))
        {
            Log(Log::Level::ERR) << "Failed to parse font " << filename;
        }
    }

    void TTFont::getVertices(const std::string& text,
                             const Color& color,
                             const Vector2& anchor,
                             const Vector2& scale,
                             std::vector<uint16_t>& indices,
                             std::vector<graphics::VertexPCT>& vertices,
                             std::shared_ptr<graphics::Texture>& texture)
    {
        Vector2 position;

        std::vector<uint32_t> utf32Text = utf8to32(text);

        indices.clear();
        vertices.clear();

        indices.reserve(utf32Text.size() * 6);
        vertices.reserve(utf32Text.size() * 4);

        Vector2 textCoords[4];

        size_t firstChar = 0;

        for (auto i = utf32Text.begin(); i != utf32Text.end(); ++i)
        {
            std::unordered_map<uint32_t, CharDescriptor>::iterator iter = chars.find(*i);

            if (iter != chars.end())
            {
                const CharDescriptor& f = iter->second;

                uint16_t startIndex = static_cast<uint16_t>(vertices.size());
                indices.push_back(startIndex + 0);
                indices.push_back(startIndex + 1);
                indices.push_back(startIndex + 2);

                indices.push_back(startIndex + 1);
                indices.push_back(startIndex + 3);
                indices.push_back(startIndex + 2);

                Vector2 leftTop(f.x / static_cast<float>(width),
                                f.y / static_cast<float>(height));

                Vector2 rightBottom((f.x + f.width) / static_cast<float>(width),
                                    (f.y + f.height) / static_cast<float>(height));

                textCoords[0] = Vector2(leftTop.x, rightBottom.y);
                textCoords[1] = Vector2(rightBottom.x, rightBottom.y);
                textCoords[2] = Vector2(leftTop.x, leftTop.y);
                textCoords[3] = Vector2(rightBottom.x, leftTop.y);

                vertices.push_back(graphics::VertexPCT(Vector3(position.x + f.xOffset, -position.y - f.yOffset - f.height, 0.0f),
                                                       color, textCoords[0]));
                vertices.push_back(graphics::VertexPCT(Vector3(position.x + f.xOffset + f.width, -position.y - f.yOffset - f.height, 0.0f),
                                                       color, textCoords[1]));
                vertices.push_back(graphics::VertexPCT(Vector3(position.x + f.xOffset, -position.y - f.yOffset, 0.0f),
                                                       color, textCoords[2]));
                vertices.push_back(graphics::VertexPCT(Vector3(position.x + f.xOffset + f.width, -position.y - f.yOffset, 0.0f),
                                                       color, textCoords[3]));

                if ((i + 1) != utf32Text.end())
                {
                    position.x += static_cast<float>(getKerningPair(*i, *(i + 1)));
                }

                position.x += f.xAdvance;
            }

            if (*i == static_cast<uint32_t>('\n') || // line feed
                (i + 1) == utf32Text.end()) // end of string
            {
                float lineWidth = position.x;
                position.x = 0.0f;
                position.y += lineHeight;

                for (size_t c = firstChar; c < vertices.size(); ++c)
                {
                    vertices[c].position.x -= lineWidth * anchor.x;
                }

                firstChar = vertices.size();
            }
        }

        float textHeight = position.y;

        for (size_t c = 0; c < vertices.size(); ++c)
        {
            vertices[c].position.y += textHeight * (1.0f - anchor.y);

            vertices[c].position.x *= scale.x;
            vertices[c].position.y *= scale.y;
        }

        texture = fontTexture;
    }

    int16_t TTFont::getKerningPair(uint32_t first, uint32_t second)
    {
        auto i = kern.find(std::make_pair(first, second));

        if (i != kern.end())
        {
            return i->second;
        }

        return 0;
    }

    float TTFont::getStringWidth(const std::string& text)
    {
        float total = 0.0f;

        std::vector<uint32_t> utf32Text = utf8to32(text);

        for (auto i = utf32Text.begin(); i != utf32Text.end(); ++i)
        {
            std::unordered_map<uint32_t, CharDescriptor>::iterator iter = chars.find(*i);

            if (iter != chars.end())
            {
                const CharDescriptor& f = iter->second;
                total += f.xAdvance;
            }
        }

        return total;
    }

    bool TTFont::parseFont(const std::string & filename, float fontSize, bool mipmaps, UTFChars flag)
    {
        stbtt_fontinfo font;
        std::vector<unsigned char> data;

        std::string f = ouzel::sharedEngine->getFileSystem()->getPath(filename);

        if (!ouzel::sharedEngine->getFileSystem()->readFile(f, data))
        {
            return false;
        }

        if (!stbtt_InitFont(&font, data.data(), stbtt_GetFontOffsetForIndex(data.data(), 0)))
        {
            Log(Log::Level::ERR) << "Failed to load font";
            return false;
        }

        float s = stbtt_ScaleForPixelHeight(&font, fontSize);

        int w, h, xoff, yoff;
        height = 0;
        width = 0;

        std::vector<uint16_t> glyphs;
        std::map<uint32_t, std::pair<Size2, std::vector<uint8_t>>> glyphToBitmapData;

        if (flag && UTFChars::ASCII)
        {
            for (uint16_t i = 32; i < 127; i++)
            {
                glyphs.push_back(i);
            }
        }
        if (flag && UTFChars::ASCIIPLUS)
        {
            for (uint16_t i = 128; i < 256; i++)
            {
                glyphs.push_back(i);
            }
        }

        for (uint16_t c : glyphs)
        {
            unsigned char* bitmap = stbtt_GetCodepointBitmap(&font, s, s, c, &w, &h, &xoff, &yoff);

            if (bitmap)
            {
                for (uint16_t j : glyphs)
                {
                    int kx = stbtt_GetCodepointKernAdvance(&font, j, c);
                    if (kx == 0) continue;
                    kern.emplace(std::pair<uint32_t, uint32_t>(j, c), static_cast<int16_t>(kx * s));
                }

                int advance, leftBearing;
                stbtt_GetCodepointHMetrics(&font, c, &advance, &leftBearing);
                CharDescriptor nd;
                nd.xAdvance = static_cast<int16_t>(advance * s);
                nd.height = static_cast<int16_t>(h);
                nd.width = static_cast<int16_t>(w);
                nd.xOffset = static_cast<int16_t>(leftBearing * s);
                nd.yOffset = static_cast<int16_t>(h - abs(yoff));

                std::vector<uint8_t> currentBuffer(static_cast<size_t>(h * w));
                std::copy(bitmap, bitmap + h * w, currentBuffer.begin());

                glyphToBitmapData.emplace(c, std::make_pair(Size2(static_cast<float>(w), static_cast<float>(h)), currentBuffer));
                chars.emplace(c, nd);
                height = height < static_cast<uint16_t>(h) ? static_cast<uint16_t>(h) : height;
                width += static_cast<uint16_t>(w);
            }
        }

        std::vector<std::vector<uint8_t>> scanlines(height);
        int x = 0;
        for (const auto &c : glyphToBitmapData)
        {
            uint16_t charHeight = static_cast<uint16_t>(c.second.first.height);
            uint16_t charWidth = static_cast<uint16_t>(c.second.first.width);
            chars.at(c.first).x = static_cast<int16_t>(x);
            chars.at(c.first).y = 0;
            x += charWidth;

            uint16_t extraRows = height - charHeight;
            chars.at(c.first).yOffset += extraRows;
            size_t extraSpaceSize = extraRows * charWidth;
            unsigned int charSize = charHeight * charWidth;
            std::vector<uint8_t> newCharBuffer(extraSpaceSize + charSize, 0x00);
            std::copy(c.second.second.begin(), c.second.second.begin() + charSize, newCharBuffer.data());
            assert(newCharBuffer.size() == height * charWidth);
            for (uint16_t i = 0; i < height; i++)
            {
                size_t scanlinesPreSize = scanlines[i].size();
                scanlines[i].resize(scanlinesPreSize + charWidth);
                uint8_t* bufferStart = newCharBuffer.data() + static_cast<int>(charWidth * i);
                std::copy(bufferStart, bufferStart + charWidth, scanlines[i].data() + scanlinesPreSize);
            }
        }

        std::vector<uint8_t> textureData(scanlines[0].size() * height * 4);
        for (uint16_t i = 0; i < height; i++)
        {
            for (uint32_t j = 0; j < scanlines[0].size(); j++)
            {
                uint8_t b = scanlines[i][j];
                textureData[(i * scanlines[0].size() + j) * 4 + 0] = 255;
                textureData[(i * scanlines[0].size() + j) * 4 + 1] = 255;
                textureData[(i * scanlines[0].size() + j) * 4 + 2] = 255;
                textureData[(i * scanlines[0].size() + j) * 4 + 3] = b;
            }
        }

        fontTexture = std::make_shared<graphics::Texture>();
        fontTexture->init(textureData, Size2(width, height), 0, mipmaps ? 0 : 1);
        pages = 1;
        lineHeight = fontSize;
        kernCount = static_cast<uint16_t>(kern.size());
        base = 0;

        return true;
    }
}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>

*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "ClientMainloop.h"
#include "WrapRoute.h"
#include <osvr/ClientKit/ClientKit.h>
#include <osvr/Client/ClientContext.h>
#include <osvr/ClientKit/InterfaceStateC.h>
#include <osvr/Common/RouteContainer.h>
#include <osvr/Util/EigenInterop.h>
#include <osvr/Util/UniquePtr.h>

// Library/third-party includes
#include <boost/program_options.hpp>
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <json/value.h>
#include <json/reader.h>

// Standard includes
#include <iostream>
#include <fstream>
#include <exception>

using std::cout;
using std::cerr;
using std::endl;

auto SETTLE_TIME = boost::posix_time::seconds(2);

class ClientMainloopThread : boost::noncopyable {
  public:
    ClientMainloopThread(osvr::clientkit::ClientContext &ctx)
        : m_run(true), m_mainloop(ctx) {
        m_thread = boost::thread([&] {
            while (m_run) {
                m_mainloop.mainloop();
                boost::this_thread::yield();
            }
        });
    }
    ~ClientMainloopThread() {
        m_run = false;
        m_thread.join();
    }
    boost::mutex &getMutex() { return m_mainloop.getMutex(); }

  private:
    volatile bool m_run;
    ClientMainloop m_mainloop;
    boost::thread m_thread;
};
int main(int argc, char *argv[]) {
    namespace po = boost::program_options;
    // clang-format off
    po::options_description desc("Options");
    desc.add_options()
        ("help", "produce help message")
        ("route", po::value<std::string>()->default_value("/me/head"), "route to calibrate")
        ;
    // clang-format on

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
    po::notify(vm);

    {
        /// Deal with command line errors or requests for help
        bool usage = false;

        if (vm.count("help")) {
            cout << "Usage: osvr_reset_yaw [options]" << endl;
            cout << desc << "\n";
            return 1;
        }
    }
    osvr::clientkit::ClientContext ctx("com.osvr.bundled.resetyaw");
    std::string const dest = vm["route"].as<std::string>();

    osvr::clientkit::Interface iface = ctx.getInterface(dest);
    {
        cout << "Starting client mainloop..." << endl;
        ClientMainloopThread client(ctx);
        cout << "Waiting a few seconds for startup..." << endl;
        boost::this_thread::sleep(SETTLE_TIME);

        cout << "\n\nPlease place your device for " << dest
             << "in its 'zero' orientation and press enter." << endl;
        std::cin.ignore();

        OSVR_OrientationState state;
        OSVR_TimeValue timestamp;
        OSVR_ReturnCode ret;
        osvr::common::RouteContainer routes;
        {
            /// briefly interrupt the client mainloop so we can get stuff done
            /// with the client state.
            boost::unique_lock<boost::mutex> lock(client.getMutex());
            routes = ctx.get()->getRoutes();
            ret = osvrGetOrientationState(iface.get(), &timestamp, &state);
            if (ret != OSVR_RETURN_SUCCESS) {
                cerr
                    << "Sorry, no orientation state available for this route - "
                       "are you sure you have a device plugged in and your "
                       "path "
                       "correct?" << endl;
                return -1;
            }
            auto quat = osvr::util::fromQuat(state);
            quat.z() = 0;
            quat.x() = 0;
            quat.normalize();
            auto correction = Eigen::AngleAxisd(quat.inverse());
            cout << correction.angle() << " about " << correction.axis()
                 << endl;

            Json::Value newLayer(Json::objectValue);
            newLayer["rotate"]["radians"] = correction.angle();
            newLayer["rotate"]["axis"] = "y";

            Json::Value origRoute;
            {
                Json::Reader reader;
                if (!reader.parse(routes.getRouteForDestination(dest),
                                  origRoute)) {
                    cerr << "Error parsing existing route!" << endl;
                    cerr << routes.getRouteForDestination(dest) << endl;
                    return -1;
                }
            }
            std::string newRoute =
                wrapRoute(origRoute, newLayer).toStyledString();
            cout << "New route: " << newRoute << endl;
            ctx.get()->sendRoute(newRoute);
            boost::this_thread::sleep(SETTLE_TIME / 2);
        }

        boost::this_thread::sleep(SETTLE_TIME);

        std::cin.ignore();
    }
    return 0;
}
<commit_msg>Working osvr_reset_yaw app<commit_after>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>

*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "ClientMainloop.h"
#include "RecomposeTransform.h"
#include "WrapRoute.h"
#include <osvr/ClientKit/ClientKit.h>
#include <osvr/Client/ClientContext.h>
#include <osvr/ClientKit/InterfaceStateC.h>
#include <osvr/Common/RouteContainer.h>
#include <osvr/Util/EigenInterop.h>
#include <osvr/Util/UniquePtr.h>

// Library/third-party includes
#include <boost/program_options.hpp>
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/chrono.hpp>
#include <json/value.h>
#include <json/reader.h>

// Standard includes
#include <iostream>
#include <fstream>
#include <exception>

using std::cout;
using std::cerr;
using std::endl;

auto SETTLE_TIME = boost::posix_time::seconds(2);

class ClientMainloopThread : boost::noncopyable {
  public:
    ClientMainloopThread(osvr::clientkit::ClientContext &ctx,
                         bool startNow = false)
        : m_run(false), m_started(false), m_mainloop(ctx) {
        if (startNow) {
            start();
        }
    }
    void start() {
        if (m_run || m_started) {
            throw std::logic_error(
                "Can't start if it's already started or if this is a re-start");
        }
        m_started = true;
        m_run = true;
        m_thread = boost::thread([&] {
            while (m_run) {
                oneLoop();
            }
        });
    }

    void oneLoop() {
        m_mainloop.mainloop();
        boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
    }

    template <typename T>
    void loopForDuration(T duration = boost::chrono::seconds(2)) {
        typedef boost::chrono::steady_clock clock;
        auto start = clock::now();
        do {
            oneLoop();
        } while (clock::now() - start < duration);
    }

    ~ClientMainloopThread() {
        m_run = false;
        m_thread.join();
    }
    boost::mutex &getMutex() { return m_mainloop.getMutex(); }

  private:
    volatile bool m_run;
    bool m_started;
    ClientMainloop m_mainloop;
    boost::thread m_thread;
};

/// @brief A flag we set in transform levels we create.
static const char FLAG_KEY[] = "resetYaw";

int main(int argc, char *argv[]) {
    namespace po = boost::program_options;
    // clang-format off
    po::options_description desc("Options");
    desc.add_options()
        ("help", "produce help message")
        ("route", po::value<std::string>()->default_value("/me/head"), "route to calibrate")
        ;
    // clang-format on

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
    po::notify(vm);

    {
        /// Deal with command line errors or requests for help
        bool usage = false;

        if (vm.count("help")) {
            cout << "Usage: osvr_reset_yaw [options]" << endl;
            cout << desc << "\n";
            return 1;
        }
    }
    osvr::clientkit::ClientContext ctx("com.osvr.bundled.resetyaw");
    std::string const dest = vm["route"].as<std::string>();

    osvr::clientkit::Interface iface = ctx.getInterface(dest);
    {

        ClientMainloopThread client(ctx);

        cout << "Running client mainloop briefly to get routes..." << endl;
        client.loopForDuration(boost::chrono::seconds(2));
        cout << "Removing any previous yaw-reset transforms..." << endl;
        Json::Value origRoute;
        {
            Json::Reader reader;
            auto routeString =
                ctx.get()->getRoutes().getRouteForDestination(dest);
            if (!reader.parse(routeString, origRoute)) {
                cerr << "Error parsing existing route!" << endl;
                cerr << routeString << endl;
                return -1;
            }
        }
        Json::Value origTransforms =
            origRoute[osvr::common::routing_keys::source()];
        Json::Value cleanTransforms =
            remove_levels_if(origTransforms, [](Json::Value const &current) {
                return current.isMember(FLAG_KEY) &&
                       current[FLAG_KEY].isBool() && current[FLAG_KEY].asBool();
            });
        origRoute[osvr::common::routing_keys::source()] = cleanTransforms;
        ctx.get()->sendRoute(origRoute.toStyledString());

        cout << "Sent cleaned route, starting again and waiting a few seconds "
                "for startup..." << endl;
        client.start();
        boost::this_thread::sleep(SETTLE_TIME);

        cout << "\n\nPlease place your device for " << dest
             << "in its 'zero' orientation and press enter." << endl;
        std::cin.ignore();

        OSVR_OrientationState state;
        OSVR_TimeValue timestamp;
        OSVR_ReturnCode ret;
        {
            /// briefly interrupt the client mainloop so we can get stuff done
            /// with the client state.
            boost::unique_lock<boost::mutex> lock(client.getMutex());
            ret = osvrGetOrientationState(iface.get(), &timestamp, &state);
            if (ret != OSVR_RETURN_SUCCESS) {
                cerr
                    << "Sorry, no orientation state available for this route - "
                       "are you sure you have a device plugged in and your "
                       "path correct?" << endl;
                std::cin.ignore();
                return -1;
            }
            auto q = osvr::util::fromQuat(state);

            // see
            // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm
            double yaw = std::atan2(2 * (q.y() * q.w() - q.x() * q.z()),
                                    1 - 2 * q.y() * q.y() - 2 * q.z() * q.z());
            cout << "Correction: " << -yaw << " radians about Y" << endl;

            Json::Value newLayer(Json::objectValue);
            newLayer["rotate"]["radians"] = -yaw;
            newLayer["rotate"]["axis"] = "y";
            newLayer[FLAG_KEY] = true;

            std::string newRoute =
                wrapRoute(origRoute, newLayer).toStyledString();
            cout << "New route: " << newRoute << endl;
            ctx.get()->sendRoute(newRoute);
            boost::this_thread::sleep(SETTLE_TIME / 2);
        }

        boost::this_thread::sleep(SETTLE_TIME);

        cout << "Press enter to exit.";
        std::cin.ignore();
    }
    return 0;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef MAPNIK_GEOMETRY_TO_WKT_HPP
#define MAPNIK_GEOMETRY_TO_WKT_HPP

// mapnik
#include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp>
#include <mapnik/geometry_wkt_generator.hpp>

// boost
#include <boost/spirit/include/karma.hpp>

namespace mapnik { namespace util {

namespace karma = boost::spirit::karma;

bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom)
{
    typedef std::back_insert_iterator<std::string> sink_type;
    sink_type sink(wkt);
    mapnik::util::wkt_generator<sink_type> generator;
    bool result = karma::generate(sink, generator, geom);
    return result;
}

}}

#endif // MAPNIK_GEOMETRY_TO_WKT_HPP
<commit_msg>fix include<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef MAPNIK_GEOMETRY_TO_WKT_HPP
#define MAPNIK_GEOMETRY_TO_WKT_HPP

// mapnik
#include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/util/vertex_iterator.hpp>
#include <mapnik/util/geometry_wkt_generator.hpp>

// boost
#include <boost/spirit/include/karma.hpp>

namespace mapnik { namespace util {

namespace karma = boost::spirit::karma;

bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom)
{
    typedef std::back_insert_iterator<std::string> sink_type;
    sink_type sink(wkt);
    wkt_generator<sink_type> generator;
    bool result = karma::generate(sink, generator, geom);
    return result;
}

}}

#endif // MAPNIK_GEOMETRY_TO_WKT_HPP
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_GAME_HANDLER_HPP
#define RJ_CORE_GAME_HANDLER_HPP

#include "game.hpp"
#include "game_window.hpp"
#include "render.hpp"
#include <rectojump/game/background/background_manager.hpp>
#include <rectojump/game/camera.hpp>
#include <rectojump/game/editor/editor.hpp>
#include <rectojump/game/game_menu/game_menu.hpp>
#include <rectojump/game/main_menu/main_menu.hpp>
#include <rectojump/game/popup_manager.hpp>
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/level_manager/level_manager.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/data_store.hpp>
#include <rectojump/shared/error_handler.hpp>

#include <mlk/containers/container_utl.h>
#include <mlk/tools/bitset.h>

namespace rj
{
	class game_handler
	{
	public:
		// type decls
		using data_store_type = data_store<sf::Texture, sf::Font>;

	private:
		game_window& m_game_window;
		error_handler& m_errorhandler;
		data_manager& m_datamgr;
		level_manager& m_lvmgr;

		data_store_type m_datastore{m_datamgr.get_all_containing_as_map_as<sf::Texture>(".png"), m_datamgr.get_all_containing_as_map_as<sf::Font>(".otf")};
		camera m_default_camera;
		render<game_handler> m_render;
		background_manager m_backgroundmgr;
		game<game_handler> m_game;
		editor<game_handler, decltype(m_game)> m_editor;
		main_menu<game_handler> m_mainmenu;
		game_menu<game_handler> m_gamemenu;
		popup_manager<game_handler> m_popupmgr;
		debug_info<game_handler, decltype(m_game)> m_debug_info;

		mlk::ebitset<state, state::num> m_current_states;

	public:
		game_handler(game_window& gw, error_handler& eh, data_manager& dm, level_manager& lm) :
			m_game_window{gw},
			m_errorhandler{eh},
			m_datamgr{dm},
			m_lvmgr{lm},
			m_default_camera{gw, {settings::get_window_size<vec2f>() / 2.f, settings::get_window_size<vec2f>()}},
			m_render{*this},
			m_backgroundmgr{m_render},
			m_game{*this},
			m_editor{*this},
			m_mainmenu{*this},
			m_gamemenu{*this},
			m_popupmgr{*this},
			m_debug_info{*this}
		{this->init();}

		void load_level(const level_id& id)
		{
			auto& lv(m_lvmgr.get_level(id));
			if(!lv.is_valid())
			{
				m_popupmgr.create_popup<popup_type::error>("Failed to load level: not a valid level");
				return;
			}

			// (de)activate right states
			this->deactivate_state(state::main_menu);
			this->activate_state(state::game);

			// load background
			m_backgroundmgr.clear();
			auto& lv_bg(lv.background);
			auto& bgshape(m_backgroundmgr.bg_shape());
			bgshape.set_startcolor(lv_bg.get_startcolor());
			bgshape.set_endcolor(lv_bg.get_endcolor());
			bgshape.set_gradient_points(lv_bg.get_pointcount());

			// load level to gameworld
			m_game.load_level(lv);
		}

		template<typename... Args>
		void render_object(Args&&... args)
		{m_game_window.draw(std::forward<Args>(args)...);}

		template<state active_state, typename On_Input, typename... Input_Type_Args>
		void add_input(On_Input&& func, Input_Type_Args&&... keys_btns)
		{
			static_assert(sizeof...(keys_btns) > 0, "at least one key/button/wheel argument needed");
			add_input_helper<(sizeof...(keys_btns) > 1), typename std::tuple_element<0, std::tuple<Input_Type_Args...>>::type, active_state, On_Input, Input_Type_Args...>
			{*this, std::forward<On_Input>(func), std::forward<Input_Type_Args>(keys_btns)...};
		}

		// getters
		auto& rendermgr() noexcept
		{return m_render;}

		auto& gamewindow() noexcept
		{return m_game_window;}

		auto& game() noexcept
		{return m_game;}

		auto& backgroundmgr() noexcept
		{return m_backgroundmgr;}

		auto& mainmenu() noexcept
		{return m_mainmenu;}

		auto& gamemenu() noexcept
		{return m_gamemenu;}

		auto& datastore() noexcept
		{return m_datastore;}

		auto& datamgr() noexcept
		{return m_datamgr;}

		auto& levelmgr() noexcept
		{return m_lvmgr;}

		auto& debuginfo() noexcept
		{return m_debug_info;}

		auto& popupmgr() noexcept
		{return m_popupmgr;}

	private:
		void init()
		{
			m_current_states |= state::main_menu;

			m_game_window.get_updater().on_update += [this](dur duration){this->update(duration);};
			m_game_window.get_updater().on_render += [this]{this->render();};

			settings::on_changed() +=
			[this]{m_game_window.set_size(settings::get_window_size());};

			m_mainmenu.mmenu_start()->get_items().on_event("editor",
			[this]
			{
				this->deactivate_state(state::main_menu);
				this->activate_state(state::editor);
				m_editor.on_activate();
			});

			this->init_errors();
			this->init_pointers();
			this->init_input();
		}

		void init_errors() noexcept
		{
			auto& font(m_datastore.get<sf::Font>("Fipps-Regular.otf"));

			// add the error instances
			m_errorhandler.create_error_instance(errors::cl_nullptr_access,
			"Something went wrong during program execution.\nPlease consider to make a bugreport at:\nhttps://github.com/Malekblubb/rectojump\n(Please attach 'log.log' and 'error.log'.)",
			font,
			[this]{this->set_only_state(state::error);});

			// TODO: add homepage here
			m_errorhandler.create_error_instance(errors::cl_data, "Some data wasn't loaded, can't run the game.\nPlease download a full release at: ",
			font,
			[this]{this->set_only_state(state::error);});

			// checking font
			if(!m_datamgr.exists_id("Fipps-Regular.otf"))
				mlk::exit_with("main font ('Fipps-Regular.otf') not loaded", EXIT_FAILURE, mlk::lerr(errors::cl_data)["rj::game_handler"]);

			// checking data
			if(!m_datamgr.exists_ids({"debug_font.png", "Fipps-Regular.otf", "arrow.png",
									  "editor_item_rect.png", "editor_item_triangle.png", "editor_item_triangles4.png",
									  "menu_side.png"}))
				mlk::lerr(errors::cl_data);
		}

		void init_pointers() noexcept
		{
			m_game.set_levelmgr(&m_lvmgr);
		}

		void init_input()
		{
			// input update
			inp::on_input_update() +=
			[this]{this->update_input();};

			// global input
			inp::on_keys_pressed(key::LShift, key::F) +=
			[this]
			{
				m_game_window.toggle_fullscreen();
				rj::settings::set_fullscreen(m_game_window.get_fullscreen());
			};

			inp::on_keys_pressed(key::LShift, key::T) +=
			[this]{m_game_window.toggle_titlebar();};

			inp::on_keys_pressed(key::LShift, key::D) +=
			[this]{this->toggle_state(state::debug_info);};

			inp::on_keys_pressed(key::LShift, key::Q) +=
			[this]{m_game_window.stop();};

			// game input
			// pause / game_menu
			auto pause_fnc(
			[this]
			{
				if(!this->is_active(state::main_menu))
					m_current_states.toggle(state::game_menu);
			});

			inp::on_key_pressed(key::Escape) += pause_fnc;
			inp::on_key_pressed(key::P) += pause_fnc;

			inp::on_key_pressed(key::D) +=
			[this]{if(!this->is_active(state::game)) return; m_game.world().c_player();};
		}

		void activate_state(state s)
		{m_current_states |= s;}

		void deactivate_state(state s)
		{m_current_states.remove(s);}

		void toggle_state(state s)
		{m_current_states.toggle(s);}

		bool is_active(state s) const
		{return m_current_states & s;}

		void set_only_state(state s)
		{
			m_current_states.remove_all();
			m_current_states |= s;
		}

		void update(dur duration)
		{
			if(this->is_active(state::error))
				return;

			m_backgroundmgr.update(duration);

			if(this->is_active(state::game) && !this->is_active(state::game_menu))
				m_game.update(duration);

			else if(this->is_active(state::editor) && !this->is_active(state::game_menu))
			{
				m_editor.update(duration);
				m_game.world().entityhandler().update(duration);
			}

			else if(this->is_active(state::main_menu))
				m_mainmenu.update(duration);

			else if(this->is_active(state::game_menu))
				m_gamemenu.update(duration);

			if(this->is_active(state::debug_info))
				m_debug_info.update(duration);

			m_popupmgr.update(duration);
		}

		void update_input()
		{
			m_editor.update_input();
		}

		void render()
		{
			if(this->is_active(state::error))
			{
				m_render(m_errorhandler.get_current_error_instance().error_text);
				return;
			}

			m_default_camera.activate();
			m_backgroundmgr.render();

			m_default_camera.activate();
			// render game when in game menu
			if(this->is_active(state::game))
				m_game.render();

			else if(this->is_active(state::editor))
				m_editor.render();

			else if(this->is_active(state::main_menu))
				m_mainmenu.render();

			if(this->is_active(state::game_menu))
			{
				m_default_camera.activate();
				m_gamemenu.render();
			}

			m_default_camera.activate();
			if(this->is_active(state::debug_info))
				m_debug_info.render();

			m_popupmgr.render();
		}

		// multi_args: true, Input_Type = key
		template<bool multi_args, typename Input_Type, state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... keys)
			{
				inp::on_keys_pressed(std::forward<Input_Type_Args>(keys)...) +=
				[&gh, func]{if(gh.is_active(s)) func();};
			}
		};

		// multi_args: false, Input_Type = key
		template<typename Input_Type, state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, Input_Type, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... k)
			{
				inp::on_key_pressed(std::forward<Input_Type_Args>(k)...) +=
				[&gh, func]{if(gh.is_active(s)) func();};
			}
		};

		// multi_args: false, Input_Type = btn
		template<state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, btn, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... b)
			{
				inp::on_btn_pressed(std::forward<Input_Type_Args>(b)...) +=
				[&gh, func](const vec2f& pos){if(gh.is_active(s)) func(pos);};
			}
		};

		// multi_args: false, Input_Type = wheel
		template<state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, wheel, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... w)
			{
				inp::on_mousewheel(std::forward<Input_Type_Args>(w)...) +=
				[&gh, func](const vec2f& pos){if(gh.is_active(s)) func(pos);};
			}
		};
	};
}

#endif // RJ_CORE_GAME_HANDLER_HPP
<commit_msg>game_handler: using ubuntu font as default error font<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_GAME_HANDLER_HPP
#define RJ_CORE_GAME_HANDLER_HPP

#include "game.hpp"
#include "game_window.hpp"
#include "render.hpp"
#include <rectojump/game/background/background_manager.hpp>
#include <rectojump/game/camera.hpp>
#include <rectojump/game/editor/editor.hpp>
#include <rectojump/game/game_menu/game_menu.hpp>
#include <rectojump/game/main_menu/main_menu.hpp>
#include <rectojump/game/popup_manager.hpp>
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/level_manager/level_manager.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/data_store.hpp>
#include <rectojump/shared/error_handler.hpp>

#include <mlk/containers/container_utl.h>
#include <mlk/tools/bitset.h>

namespace rj
{
	class game_handler
	{
	public:
		// type decls
		using data_store_type = data_store<sf::Texture, sf::Font, sf::Font>;

	private:
		game_window& m_game_window;
		error_handler& m_errorhandler;
		data_manager& m_datamgr;
		level_manager& m_lvmgr;

		data_store_type m_datastore{m_datamgr.get_all_containing_as_map_as<sf::Texture>(".png"), m_datamgr.get_all_containing_as_map_as<sf::Font>(".otf"), m_datamgr.get_all_containing_as_map_as<sf::Font>(".ttf")};
		camera m_default_camera;
		render<game_handler> m_render;
		background_manager m_backgroundmgr;
		game<game_handler> m_game;
		editor<game_handler, decltype(m_game)> m_editor;
		main_menu<game_handler> m_mainmenu;
		game_menu<game_handler> m_gamemenu;
		popup_manager<game_handler> m_popupmgr;
		debug_info<game_handler, decltype(m_game)> m_debug_info;

		mlk::ebitset<state, state::num> m_current_states;

	public:
		game_handler(game_window& gw, error_handler& eh, data_manager& dm, level_manager& lm) :
			m_game_window{gw},
			m_errorhandler{eh},
			m_datamgr{dm},
			m_lvmgr{lm},
			m_default_camera{gw, {settings::get_window_size<vec2f>() / 2.f, settings::get_window_size<vec2f>()}},
			m_render{*this},
			m_backgroundmgr{m_render},
			m_game{*this},
			m_editor{*this},
			m_mainmenu{*this},
			m_gamemenu{*this},
			m_popupmgr{*this},
			m_debug_info{*this}
		{this->init();}

		void load_level(const level_id& id)
		{
			auto& lv(m_lvmgr.get_level(id));
			if(!lv.is_valid())
			{
				m_popupmgr.create_popup<popup_type::error>("Failed to load level: not a valid level");
				return;
			}

			// (de)activate right states
			this->deactivate_state(state::main_menu);
			this->activate_state(state::game);

			// load background
			m_backgroundmgr.clear();
			auto& lv_bg(lv.background);
			auto& bgshape(m_backgroundmgr.bg_shape());
			bgshape.set_startcolor(lv_bg.get_startcolor());
			bgshape.set_endcolor(lv_bg.get_endcolor());
			bgshape.set_gradient_points(lv_bg.get_pointcount());

			// load level to gameworld
			m_game.load_level(lv);
		}

		template<typename... Args>
		void render_object(Args&&... args)
		{m_game_window.draw(std::forward<Args>(args)...);}

		template<state active_state, typename On_Input, typename... Input_Type_Args>
		void add_input(On_Input&& func, Input_Type_Args&&... keys_btns)
		{
			static_assert(sizeof...(keys_btns) > 0, "at least one key/button/wheel argument needed");
			add_input_helper<(sizeof...(keys_btns) > 1), typename std::tuple_element<0, std::tuple<Input_Type_Args...>>::type, active_state, On_Input, Input_Type_Args...>
			{*this, std::forward<On_Input>(func), std::forward<Input_Type_Args>(keys_btns)...};
		}

		// getters
		auto& rendermgr() noexcept
		{return m_render;}

		auto& gamewindow() noexcept
		{return m_game_window;}

		auto& game() noexcept
		{return m_game;}

		auto& backgroundmgr() noexcept
		{return m_backgroundmgr;}

		auto& mainmenu() noexcept
		{return m_mainmenu;}

		auto& gamemenu() noexcept
		{return m_gamemenu;}

		auto& datastore() noexcept
		{return m_datastore;}

		auto& datamgr() noexcept
		{return m_datamgr;}

		auto& levelmgr() noexcept
		{return m_lvmgr;}

		auto& debuginfo() noexcept
		{return m_debug_info;}

		auto& popupmgr() noexcept
		{return m_popupmgr;}

	private:
		void init()
		{
			m_current_states |= state::main_menu;

			m_game_window.get_updater().on_update += [this](dur duration){this->update(duration);};
			m_game_window.get_updater().on_render += [this]{this->render();};

			settings::on_changed() +=
			[this]{m_game_window.set_size(settings::get_window_size());};

			m_mainmenu.mmenu_start()->get_items().on_event("editor",
			[this]
			{
				this->deactivate_state(state::main_menu);
				this->activate_state(state::editor);
				m_editor.on_activate();
			});

			this->init_errors();
			this->init_pointers();
			this->init_input();
		}

		void init_errors() noexcept
		{
			auto& font(m_datastore.get<sf::Font>("Ubuntu-R.ttf"));

			// add the error instances
			m_errorhandler.create_error_instance(errors::cl_nullptr_access,
			"Something went wrong during program execution.\nPlease consider to make a bugreport at:\nhttps://github.com/Malekblubb/rectojump\n(Please attach 'log.log' and 'error.log'.)",
			font,
			[this]{this->set_only_state(state::error);});

			// TODO: add homepage here
			m_errorhandler.create_error_instance(errors::cl_data, "Some data wasn't loaded, can't run the game.\nPlease download a full release at: ",
			font,
			[this]{this->set_only_state(state::error);});

			// checking font
			if(!m_datamgr.exists_id("Fipps-Regular.otf"))
				mlk::exit_with("main font ('Fipps-Regular.otf') not loaded", EXIT_FAILURE, mlk::lerr(errors::cl_data)["rj::game_handler"]);

			// checking data
			if(!m_datamgr.exists_ids({"debug_font.png", "Fipps-Regular.otf", "Ubuntu-R.ttf", "arrow.png",
									  "editor_item_rect.png", "editor_item_triangle.png", "editor_item_triangles4.png",
									  "menu_side.png"}))
				mlk::lerr(errors::cl_data);
		}

		void init_pointers() noexcept
		{
			m_game.set_levelmgr(&m_lvmgr);
		}

		void init_input()
		{
			// input update
			inp::on_input_update() +=
			[this]{this->update_input();};

			// global input
			inp::on_keys_pressed(key::LShift, key::F) +=
			[this]
			{
				m_game_window.toggle_fullscreen();
				rj::settings::set_fullscreen(m_game_window.get_fullscreen());
			};

			inp::on_keys_pressed(key::LShift, key::T) +=
			[this]{m_game_window.toggle_titlebar();};

			inp::on_keys_pressed(key::LShift, key::D) +=
			[this]{this->toggle_state(state::debug_info);};

			inp::on_keys_pressed(key::LShift, key::Q) +=
			[this]{m_game_window.stop();};

			// game input
			// pause / game_menu
			auto pause_fnc(
			[this]
			{
				if(!this->is_active(state::main_menu))
					m_current_states.toggle(state::game_menu);
			});

			inp::on_key_pressed(key::Escape) += pause_fnc;
			inp::on_key_pressed(key::P) += pause_fnc;

			inp::on_key_pressed(key::D) +=
			[this]{if(!this->is_active(state::game)) return; m_game.world().c_player();};
		}

		void activate_state(state s)
		{m_current_states |= s;}

		void deactivate_state(state s)
		{m_current_states.remove(s);}

		void toggle_state(state s)
		{m_current_states.toggle(s);}

		bool is_active(state s) const
		{return m_current_states & s;}

		void set_only_state(state s)
		{
			m_current_states.remove_all();
			m_current_states |= s;
		}

		void update(dur duration)
		{
			if(this->is_active(state::error))
				return;

			m_backgroundmgr.update(duration);

			if(this->is_active(state::game) && !this->is_active(state::game_menu))
				m_game.update(duration);

			else if(this->is_active(state::editor) && !this->is_active(state::game_menu))
			{
				m_editor.update(duration);
				m_game.world().entityhandler().update(duration);
			}

			else if(this->is_active(state::main_menu))
				m_mainmenu.update(duration);

			else if(this->is_active(state::game_menu))
				m_gamemenu.update(duration);

			if(this->is_active(state::debug_info))
				m_debug_info.update(duration);

			m_popupmgr.update(duration);
		}

		void update_input()
		{
			m_editor.update_input();
		}

		void render()
		{
			if(this->is_active(state::error))
			{
				m_render(m_errorhandler.get_current_error_instance().error_text);
				return;
			}

			m_default_camera.activate();
			m_backgroundmgr.render();

			m_default_camera.activate();
			// render game when in game menu
			if(this->is_active(state::game))
				m_game.render();

			else if(this->is_active(state::editor))
				m_editor.render();

			else if(this->is_active(state::main_menu))
				m_mainmenu.render();

			if(this->is_active(state::game_menu))
			{
				m_default_camera.activate();
				m_gamemenu.render();
			}

			m_default_camera.activate();
			if(this->is_active(state::debug_info))
				m_debug_info.render();

			m_popupmgr.render();
		}

		// multi_args: true, Input_Type = key
		template<bool multi_args, typename Input_Type, state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... keys)
			{
				inp::on_keys_pressed(std::forward<Input_Type_Args>(keys)...) +=
				[&gh, func]{if(gh.is_active(s)) func();};
			}
		};

		// multi_args: false, Input_Type = key
		template<typename Input_Type, state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, Input_Type, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... k)
			{
				inp::on_key_pressed(std::forward<Input_Type_Args>(k)...) +=
				[&gh, func]{if(gh.is_active(s)) func();};
			}
		};

		// multi_args: false, Input_Type = btn
		template<state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, btn, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... b)
			{
				inp::on_btn_pressed(std::forward<Input_Type_Args>(b)...) +=
				[&gh, func](const vec2f& pos){if(gh.is_active(s)) func(pos);};
			}
		};

		// multi_args: false, Input_Type = wheel
		template<state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, wheel, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... w)
			{
				inp::on_mousewheel(std::forward<Input_Type_Args>(w)...) +=
				[&gh, func](const vec2f& pos){if(gh.is_active(s)) func(pos);};
			}
		};
	};
}

#endif // RJ_CORE_GAME_HANDLER_HPP
<|endoftext|>