<commit_before>#ifndef containers_hh_INCLUDED
#define containers_hh_INCLUDED

#include <algorithm>
#include <utility>
#include <iterator>

namespace Kakoune
{

template<typename Factory>
struct ContainerView { Factory factory; };

template<typename Container, typename Factory>
auto operator| (Container&& container, ContainerView<Factory> view) ->
    decltype(view.factory(std::forward<Container>(container)))
{
    return view.factory(std::forward<Container>(container));
}

template<typename Container>
struct ReverseView
{
    using iterator = decltype(std::declval<Container>().rbegin());
    ReverseView(Container& container) : m_container(container) {}

    iterator begin() { return m_container.rbegin(); }
    iterator end()   { return m_container.rend(); }

private:
    Container& m_container;
};

struct ReverseFactory
{
    template<typename Container>
    ReverseView<Container> operator()(Container&& container) const
    {
        return {container};
    }
};

inline ContainerView<ReverseFactory> reverse() { return {}; }

template<typename Container, typename Filter>
struct FilterView
{
    using ContainerIt = decltype(begin(std::declval<Container>()));

    struct Iterator : std::iterator<std::forward_iterator_tag,
                                    typename ContainerIt::value_type>
    {
        Iterator(const FilterView& view, ContainerIt it, ContainerIt end)
            : m_it{std::move(it)}, m_end{std::move(end)}, m_view{view}
        {
            do_filter();
        }

        auto operator*() -> decltype(*std::declval<ContainerIt>()) { return *m_it; }
        Iterator& operator++() { ++m_it; do_filter(); return *this; }
        Iterator operator++(int) { auto copy = *this; ++(*this); return copy; }

        friend bool operator==(const Iterator& lhs, const Iterator& rhs)
        {
            return lhs.m_it == rhs.m_it;
        }

        friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
        {
            return not (lhs == rhs);
        }

        const ContainerIt& base() const { return m_it; }

    private:
        void do_filter()
        {
            while (m_it != m_end and not m_view.m_filter(*m_it))
                ++m_it;
        }

        ContainerIt m_it;
        ContainerIt m_end;
        const FilterView& m_view;
    };

    FilterView(Container& container, Filter filter)
        : m_container(container), m_filter(std::move(filter)) {}

    Iterator begin() const { return {*this, m_container.begin(), m_container.end()}; }
    Iterator end()   const { return {*this, m_container.end(), m_container.end()}; }

private:
    Container& m_container;
    Filter m_filter;
};

template<typename Filter>
struct FilterFactory
{
    template<typename Container>
    FilterView<Container, Filter> operator()(Container&& container) const { return {container, std::move(m_filter)}; }

    Filter m_filter;
};

template<typename Filter>
inline ContainerView<FilterFactory<Filter>> filter(Filter f) { return {{std::move(f)}}; }

template<typename I, typename T>
using TransformedResult = decltype(std::declval<T>()(*std::declval<I>()));

template<typename Container, typename Transform>
struct TransformView
{
    using ContainerIt = decltype(begin(std::declval<Container>()));

    struct Iterator : std::iterator<std::forward_iterator_tag,
                                    typename std::remove_reference<TransformedResult<ContainerIt, Transform>>::type>
    {
        Iterator(const TransformView& view, ContainerIt it)
            : m_it{std::move(it)}, m_view{view} {}

        auto operator*() -> TransformedResult<ContainerIt, Transform> { return m_view.m_transform(*m_it); }
        Iterator& operator++() { ++m_it; return *this; }
        Iterator operator++(int) { auto copy = *this; ++m_it; return copy; }

        friend bool operator==(const Iterator& lhs, const Iterator& rhs)
        {
            return lhs.m_it == rhs.m_it;
        }

        friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
        {
            return not (lhs == rhs);
        }

        ContainerIt base() const { return m_it; }

    private:
        ContainerIt m_it;
        const TransformView& m_view;
    };

    TransformView(Container& container, Transform transform)
        : m_container(container), m_transform(std::move(transform)) {}

    Iterator begin() const { return {*this, m_container.begin()}; }
    Iterator end()   const { return {*this, m_container.end()}; }

private:
    Container& m_container;
    Transform m_transform;
};

template<typename Transform>
struct TransformFactory
{
    template<typename Container>
    TransformView<Container, Transform> operator()(Container&& container) const { return {container, std::move(m_transform)}; }

    Transform m_transform;
};

template<typename Transform>
inline ContainerView<TransformFactory<Transform>> transform(Transform t) { return {{std::move(t)}}; }

template<typename Container1, typename Container2>
struct ConcatView
{
    using ContainerIt1 = decltype(begin(std::declval<Container1>()));
    using ContainerIt2 = decltype(begin(std::declval<Container2>()));
    using ValueType = typename ContainerIt1::value_type;

    struct Iterator : std::iterator<std::forward_iterator_tag, ValueType>
    {
        static_assert(std::is_convertible<typename ContainerIt1::value_type, ValueType>::value, "");
        static_assert(std::is_convertible<typename ContainerIt2::value_type, ValueType>::value, "");

        Iterator(ContainerIt1 it1, ContainerIt1 end1, ContainerIt2 it2)
            : m_it1(std::move(it1)), m_end1(std::move(end1)),
              m_it2(std::move(it2)) {}

        decltype(*std::declval<ContainerIt1>()) operator*() { return is2() ? *m_it2 : *m_it1; }
        Iterator& operator++() { if (is2()) ++m_it2; else ++m_it1; return *this; }
        Iterator operator++(int) { auto copy = *this; ++*this; return copy; }

        friend bool operator==(const Iterator& lhs, const Iterator& rhs)
        {
            return lhs.m_it1 == rhs.m_it1 and lhs.m_end1 == rhs.m_end1 and
                   lhs.m_it2 == rhs.m_it2;
        }

        friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
        {
            return not (lhs == rhs);
        }

    private:
        bool is2() const { return m_it1 == m_end1; }

        ContainerIt1 m_it1;
        ContainerIt1 m_end1;
        ContainerIt2 m_it2;
    };

    ConcatView(Container1& container1, Container2& container2)
        : m_container1(container1), m_container2(container2) {}

    Iterator begin() const { return {m_container1.begin(), m_container1.end(), m_container2.begin()}; }
    Iterator end()   const { return {m_container1.end(), m_container1.end(), m_container2.end()}; }

private:
    Container1& m_container1;
    Container2& m_container2;
};

template<typename Container1, typename Container2>
ConcatView<Container1, Container2> concatenated(Container1&& container1, Container2&& container2)
{
    return {container1, container2};
}

// Todo: move that into the following functions once we can remove the decltype
//       return type.
using std::begin;
using std::end;

template<typename Container, typename T>
auto find(Container&& container, const T& value) -> decltype(begin(container))
{
    return std::find(begin(container), end(container), value);
}

template<typename Container, typename T>
auto find_if(Container&& container, T op) -> decltype(begin(container))
{
    return std::find_if(begin(container), end(container), op);
}

template<typename Container, typename T>
bool contains(Container&& container, const T& value)
{
    return find(container, value) != end(container);
}

template<typename Container, typename T>
bool contains_that(Container&& container, T op)
{
    return find_if(container, op) != end(container);
}

template<typename Container, typename U>
void unordered_erase(Container&& vec, U&& value)
{
    auto it = find(vec, std::forward<U>(value));
    if (it != vec.end())
    {
        using std::swap;
        swap(vec.back(), *it);
        vec.pop_back();
    }
}

}

#endif // containers_hh_INCLUDED
<commit_msg>Correctly handle temporaries in container views<commit_after>#ifndef containers_hh_INCLUDED
#define containers_hh_INCLUDED

#include <algorithm>
#include <utility>
#include <iterator>

namespace Kakoune
{

template<typename Factory>
struct ContainerView { Factory factory; };

template<typename Container, typename Factory>
auto operator| (Container&& container, ContainerView<Factory> view) ->
    decltype(view.factory(std::forward<Container>(container)))
{
    return view.factory(std::forward<Container>(container));
}

template<typename Container>
struct ReverseView
{
    using iterator = decltype(std::declval<Container>().rbegin());

    iterator begin() { return m_container.rbegin(); }
    iterator end()   { return m_container.rend(); }

    Container m_container;
};

template<typename C>
using RemoveReference = typename std::remove_reference<C>::type;

struct ReverseFactory
{
    template<typename Container>
    ReverseView<RemoveReference<Container>> operator()(Container&& container) const
    {
        return {std::move(container)};
    }

    template<typename Container>
    ReverseView<Container&> operator()(Container& container) const
    {
        return {container};
    }
};

inline ContainerView<ReverseFactory> reverse() { return {}; }

template<typename Container, typename Filter>
struct FilterView
{
    using ContainerIt = decltype(begin(std::declval<Container>()));

    struct Iterator : std::iterator<std::forward_iterator_tag,
                                    typename ContainerIt::value_type>
    {
        Iterator(const FilterView& view, ContainerIt it, ContainerIt end)
            : m_it{std::move(it)}, m_end{std::move(end)}, m_view{view}
        {
            do_filter();
        }

        auto operator*() -> decltype(*std::declval<ContainerIt>()) { return *m_it; }
        Iterator& operator++() { ++m_it; do_filter(); return *this; }
        Iterator operator++(int) { auto copy = *this; ++(*this); return copy; }

        friend bool operator==(const Iterator& lhs, const Iterator& rhs)
        {
            return lhs.m_it == rhs.m_it;
        }

        friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
        {
            return not (lhs == rhs);
        }

        const ContainerIt& base() const { return m_it; }

    private:
        void do_filter()
        {
            while (m_it != m_end and not m_view.m_filter(*m_it))
                ++m_it;
        }

        ContainerIt m_it;
        ContainerIt m_end;
        const FilterView& m_view;
    };

    Iterator begin() const { return {*this, m_container.begin(), m_container.end()}; }
    Iterator end()   const { return {*this, m_container.end(), m_container.end()}; }

    Container m_container;
    Filter m_filter;
};

template<typename Filter>
struct FilterFactory
{
    template<typename Container>
    FilterView<Container&, Filter> operator()(Container& container) const { return {container, std::move(m_filter)}; }

    template<typename Container>
    FilterView<RemoveReference<Container>, Filter> operator()(Container&& container) const { return {std::move(container), std::move(m_filter)}; }

    Filter m_filter;
};

template<typename Filter>
inline ContainerView<FilterFactory<Filter>> filter(Filter f) { return {{std::move(f)}}; }

template<typename I, typename T>
using TransformedResult = decltype(std::declval<T>()(*std::declval<I>()));

template<typename Container, typename Transform>
struct TransformView
{
    using ContainerIt = decltype(begin(std::declval<Container>()));

    struct Iterator : std::iterator<std::forward_iterator_tag,
                                    typename std::remove_reference<TransformedResult<ContainerIt, Transform>>::type>
    {
        Iterator(const TransformView& view, ContainerIt it)
            : m_it{std::move(it)}, m_view{view} {}

        auto operator*() -> TransformedResult<ContainerIt, Transform> { return m_view.m_transform(*m_it); }
        Iterator& operator++() { ++m_it; return *this; }
        Iterator operator++(int) { auto copy = *this; ++m_it; return copy; }

        friend bool operator==(const Iterator& lhs, const Iterator& rhs)
        {
            return lhs.m_it == rhs.m_it;
        }

        friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
        {
            return not (lhs == rhs);
        }

        ContainerIt base() const { return m_it; }

    private:
        ContainerIt m_it;
        const TransformView& m_view;
    };

    Iterator begin() const { return {*this, m_container.begin()}; }
    Iterator end()   const { return {*this, m_container.end()}; }

    Container m_container;
    Transform m_transform;
};

template<typename Transform>
struct TransformFactory
{
    template<typename Container>
    TransformView<Container&, Transform> operator()(Container& container) const { return {container, std::move(m_transform)}; }

    template<typename Container>
    TransformView<RemoveReference<Container>, Transform> operator()(Container&& container) const { return {std::move(container), std::move(m_transform)}; }

    Transform m_transform;
};

template<typename Transform>
inline ContainerView<TransformFactory<Transform>> transform(Transform t) { return {{std::move(t)}}; }

template<typename Container1, typename Container2>
struct ConcatView
{
    using ContainerIt1 = decltype(begin(std::declval<Container1>()));
    using ContainerIt2 = decltype(begin(std::declval<Container2>()));
    using ValueType = typename ContainerIt1::value_type;

    struct Iterator : std::iterator<std::forward_iterator_tag, ValueType>
    {
        static_assert(std::is_convertible<typename ContainerIt1::value_type, ValueType>::value, "");
        static_assert(std::is_convertible<typename ContainerIt2::value_type, ValueType>::value, "");

        Iterator(ContainerIt1 it1, ContainerIt1 end1, ContainerIt2 it2)
            : m_it1(std::move(it1)), m_end1(std::move(end1)),
              m_it2(std::move(it2)) {}

        decltype(*std::declval<ContainerIt1>()) operator*() { return is2() ? *m_it2 : *m_it1; }
        Iterator& operator++() { if (is2()) ++m_it2; else ++m_it1; return *this; }
        Iterator operator++(int) { auto copy = *this; ++*this; return copy; }

        friend bool operator==(const Iterator& lhs, const Iterator& rhs)
        {
            return lhs.m_it1 == rhs.m_it1 and lhs.m_end1 == rhs.m_end1 and
                   lhs.m_it2 == rhs.m_it2;
        }

        friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
        {
            return not (lhs == rhs);
        }

    private:
        bool is2() const { return m_it1 == m_end1; }

        ContainerIt1 m_it1;
        ContainerIt1 m_end1;
        ContainerIt2 m_it2;
    };

    ConcatView(Container1& container1, Container2& container2)
        : m_container1(container1), m_container2(container2) {}

    Iterator begin() const { return {m_container1.begin(), m_container1.end(), m_container2.begin()}; }
    Iterator end()   const { return {m_container1.end(), m_container1.end(), m_container2.end()}; }

private:
    Container1& m_container1;
    Container2& m_container2;
};

template<typename Container1, typename Container2>
ConcatView<Container1, Container2> concatenated(Container1&& container1, Container2&& container2)
{
    return {container1, container2};
}

// Todo: move that into the following functions once we can remove the decltype
//       return type.
using std::begin;
using std::end;

template<typename Container, typename T>
auto find(Container&& container, const T& value) -> decltype(begin(container))
{
    return std::find(begin(container), end(container), value);
}

template<typename Container, typename T>
auto find_if(Container&& container, T op) -> decltype(begin(container))
{
    return std::find_if(begin(container), end(container), op);
}

template<typename Container, typename T>
bool contains(Container&& container, const T& value)
{
    return find(container, value) != end(container);
}

template<typename Container, typename T>
bool contains_that(Container&& container, T op)
{
    return find_if(container, op) != end(container);
}

template<typename Container, typename U>
void unordered_erase(Container&& vec, U&& value)
{
    auto it = find(vec, std::forward<U>(value));
    if (it != vec.end())
    {
        using std::swap;
        swap(vec.back(), *it);
        vec.pop_back();
    }
}

}

#endif // containers_hh_INCLUDED
<|endoftext|>


<commit_before>#include "node.hpp"
#include "helpers.hpp"

#include "core/Log.h"
#include "core/opengl.hpp"

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

Node::Node() : _vao(0u), _vertices_nb(0u), _indices_nb(0u), _drawing_mode(GL_TRIANGLES), _has_indices(true), _program(nullptr), _textures(), _transform(), _children()
{
}

void
Node::render(glm::mat4 const& WVP, glm::mat4 const& parentTransform) const
{
	if (_program != nullptr)
		render(WVP, parentTransform * _transform.GetMatrix(), *_program, _set_uniforms);
}

void
Node::render(glm::mat4 const& WVP, glm::mat4 const& world, GLuint program, std::function<void (GLuint)> const& set_uniforms) const
{
	if (_vao == 0u || program == 0u)
		return;

	if (utils::opengl::debug::isSupported())
	{
		glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0u, _name.size(), _name.data());
	}

	glUseProgram(program);

	auto const normal_model_to_world = glm::transpose(glm::inverse(world));

	set_uniforms(program);

	glUniformMatrix4fv(glGetUniformLocation(program, "vertex_model_to_world"), 1, GL_FALSE, glm::value_ptr(world));
	glUniformMatrix4fv(glGetUniformLocation(program, "normal_model_to_world"), 1, GL_FALSE, glm::value_ptr(normal_model_to_world));
	glUniformMatrix4fv(glGetUniformLocation(program, "vertex_world_to_clip"), 1, GL_FALSE, glm::value_ptr(WVP));

	for (size_t i = 0u; i < _textures.size(); ++i) {
		auto const& texture = _textures[i];
		glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(i));
		glBindTexture(std::get<2>(texture), std::get<1>(texture));
		glUniform1i(glGetUniformLocation(program, std::get<0>(texture).c_str()), static_cast<GLint>(i));

		std::string texture_presence_var_name = "has_" + std::get<0>(texture);
		glUniform1i(glGetUniformLocation(program, texture_presence_var_name.c_str()), 1);
	}

	glBindVertexArray(_vao);
	if (_has_indices)
		glDrawElements(_drawing_mode, _indices_nb, GL_UNSIGNED_INT, reinterpret_cast<GLvoid const*>(0x0));
	else
		glDrawArrays(_drawing_mode, 0, _vertices_nb);
	glBindVertexArray(0u);

	for (auto const& texture : _textures) {
		glBindTexture(std::get<2>(texture), 0);
		glUniform1i(glGetUniformLocation(program, std::get<0>(texture).c_str()), 0);

		std::string texture_presence_var_name = "has_" + std::get<0>(texture);
		glUniform1i(glGetUniformLocation(program, texture_presence_var_name.c_str()), 0);
	}

	glUseProgram(0u);

	if (utils::opengl::debug::isSupported())
	{
		glPopDebugGroup();
	}
}

void
Node::set_geometry(bonobo::mesh_data const& shape)
{
	_vao = shape.vao;
	_vertices_nb = static_cast<GLsizei>(shape.vertices_nb);
	_indices_nb = static_cast<GLsizei>(shape.indices_nb);
	_drawing_mode = shape.drawing_mode;
	_has_indices = shape.ibo != 0u;
	_name = shape.name;

	if (!shape.bindings.empty()) {
		for (auto const& binding : shape.bindings)
			add_texture(binding.first, binding.second, GL_TEXTURE_2D);
	}
}

void
Node::set_program(GLuint const* const program, std::function<void (GLuint)> const& set_uniforms)
{
	if (program == nullptr)
		throw std::runtime_error("Node::set_program: program can not be null.");

	_program = program;
	_set_uniforms = set_uniforms;
}

size_t
Node::get_indices_nb() const
{
	return static_cast<size_t>(_indices_nb);
}

void
Node::set_indices_nb(size_t const& indices_nb)
{
	_indices_nb = static_cast<GLsizei>(indices_nb);
}

void
Node::add_texture(std::string const& name, GLuint tex_id, GLenum type)
{
	GLint max_combined_texture_image_units{-1};
	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);
	std::size_t const max_active_texture_count
		= (max_combined_texture_image_units > 0) ? static_cast<std::size_t>(max_combined_texture_image_units)
		                                         : 80; // OpenGL 4.x guarantees at least 80.

	if (_textures.size() >= max_active_texture_count) {
		LogWarning("Trying to add more textures to an object than supported (%llu); the texture %s with ID %u will **not** be added. If you really need that many textures, do not use the `Node` class and roll your own solution instead.",
		           max_active_texture_count, name.c_str(), tex_id);
		return;
	}
	if (tex_id == 0u) {
		LogWarning("0 is not a valid texture ID; the texture %s (with ID %u) will **not** be added.",
		           name.c_str(), tex_id);
		return;
	}

	_textures.emplace_back(name, tex_id, type);
}

void
Node::add_child(Node const* child)
{
	if (child == nullptr)
		LogError("Trying to add a nullptr as child!");
	_children.emplace_back(child);
}

size_t
Node::get_children_nb() const
{
	return _children.size();
}

Node const*
Node::get_child(size_t index) const
{
	assert(index < _children.size());
	return _children[index];
}

TRSTransformf const&
Node::get_transform() const
{
	return _transform;
}

TRSTransformf&
Node::get_transform()
{
	return _transform;
}
<commit_msg>Do not append null pointers to the children list<commit_after>#include "node.hpp"
#include "helpers.hpp"

#include "core/Log.h"
#include "core/opengl.hpp"

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

Node::Node() : _vao(0u), _vertices_nb(0u), _indices_nb(0u), _drawing_mode(GL_TRIANGLES), _has_indices(true), _program(nullptr), _textures(), _transform(), _children()
{
}

void
Node::render(glm::mat4 const& WVP, glm::mat4 const& parentTransform) const
{
	if (_program != nullptr)
		render(WVP, parentTransform * _transform.GetMatrix(), *_program, _set_uniforms);
}

void
Node::render(glm::mat4 const& WVP, glm::mat4 const& world, GLuint program, std::function<void (GLuint)> const& set_uniforms) const
{
	if (_vao == 0u || program == 0u)
		return;

	if (utils::opengl::debug::isSupported())
	{
		glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0u, _name.size(), _name.data());
	}

	glUseProgram(program);

	auto const normal_model_to_world = glm::transpose(glm::inverse(world));

	set_uniforms(program);

	glUniformMatrix4fv(glGetUniformLocation(program, "vertex_model_to_world"), 1, GL_FALSE, glm::value_ptr(world));
	glUniformMatrix4fv(glGetUniformLocation(program, "normal_model_to_world"), 1, GL_FALSE, glm::value_ptr(normal_model_to_world));
	glUniformMatrix4fv(glGetUniformLocation(program, "vertex_world_to_clip"), 1, GL_FALSE, glm::value_ptr(WVP));

	for (size_t i = 0u; i < _textures.size(); ++i) {
		auto const& texture = _textures[i];
		glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(i));
		glBindTexture(std::get<2>(texture), std::get<1>(texture));
		glUniform1i(glGetUniformLocation(program, std::get<0>(texture).c_str()), static_cast<GLint>(i));

		std::string texture_presence_var_name = "has_" + std::get<0>(texture);
		glUniform1i(glGetUniformLocation(program, texture_presence_var_name.c_str()), 1);
	}

	glBindVertexArray(_vao);
	if (_has_indices)
		glDrawElements(_drawing_mode, _indices_nb, GL_UNSIGNED_INT, reinterpret_cast<GLvoid const*>(0x0));
	else
		glDrawArrays(_drawing_mode, 0, _vertices_nb);
	glBindVertexArray(0u);

	for (auto const& texture : _textures) {
		glBindTexture(std::get<2>(texture), 0);
		glUniform1i(glGetUniformLocation(program, std::get<0>(texture).c_str()), 0);

		std::string texture_presence_var_name = "has_" + std::get<0>(texture);
		glUniform1i(glGetUniformLocation(program, texture_presence_var_name.c_str()), 0);
	}

	glUseProgram(0u);

	if (utils::opengl::debug::isSupported())
	{
		glPopDebugGroup();
	}
}

void
Node::set_geometry(bonobo::mesh_data const& shape)
{
	_vao = shape.vao;
	_vertices_nb = static_cast<GLsizei>(shape.vertices_nb);
	_indices_nb = static_cast<GLsizei>(shape.indices_nb);
	_drawing_mode = shape.drawing_mode;
	_has_indices = shape.ibo != 0u;
	_name = shape.name;

	if (!shape.bindings.empty()) {
		for (auto const& binding : shape.bindings)
			add_texture(binding.first, binding.second, GL_TEXTURE_2D);
	}
}

void
Node::set_program(GLuint const* const program, std::function<void (GLuint)> const& set_uniforms)
{
	if (program == nullptr)
		throw std::runtime_error("Node::set_program: program can not be null.");

	_program = program;
	_set_uniforms = set_uniforms;
}

size_t
Node::get_indices_nb() const
{
	return static_cast<size_t>(_indices_nb);
}

void
Node::set_indices_nb(size_t const& indices_nb)
{
	_indices_nb = static_cast<GLsizei>(indices_nb);
}

void
Node::add_texture(std::string const& name, GLuint tex_id, GLenum type)
{
	GLint max_combined_texture_image_units{-1};
	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);
	std::size_t const max_active_texture_count
		= (max_combined_texture_image_units > 0) ? static_cast<std::size_t>(max_combined_texture_image_units)
		                                         : 80; // OpenGL 4.x guarantees at least 80.

	if (_textures.size() >= max_active_texture_count) {
		LogWarning("Trying to add more textures to an object than supported (%llu); the texture %s with ID %u will **not** be added. If you really need that many textures, do not use the `Node` class and roll your own solution instead.",
		           max_active_texture_count, name.c_str(), tex_id);
		return;
	}
	if (tex_id == 0u) {
		LogWarning("0 is not a valid texture ID; the texture %s (with ID %u) will **not** be added.",
		           name.c_str(), tex_id);
		return;
	}

	_textures.emplace_back(name, tex_id, type);
}

void
Node::add_child(Node const* child)
{
	if (child == nullptr) {
		LogWarning("Trying to add a null pointer as child: this will be discarded.");
		return;
	}

	_children.emplace_back(child);
}

size_t
Node::get_children_nb() const
{
	return _children.size();
}

Node const*
Node::get_child(size_t index) const
{
	assert(index < _children.size());
	return _children[index];
}

TRSTransformf const&
Node::get_transform() const
{
	return _transform;
}

TRSTransformf&
Node::get_transform()
{
	return _transform;
}
<|endoftext|>


<commit_before>#include <algorithm>

#include "db_single.h"
#include "log_reader.h"

namespace LeviDB {
    DBSingle::DBSingle(std::string name, Options options, SeqGenerator * seq_gen)
            : DB(std::move(name), options), _seq_gen(seq_gen) {
        std::string prefix = _name + '/';

        if (IOEnv::fileExists(_name)) {
            if (_options.error_if_exists) {
                throw Exception::invalidArgumentException("DB already exists");
            }
            // 打开现有数据库
            _file_lock.build(prefix + "lock");
            std::string data_fname = prefix + "data";
            if (!IOEnv::fileExists(data_fname)) {
                throw Exception::notFoundException("data file missing", data_fname);
            }
            std::string index_fname = prefix + "index";
            std::string keeper_fname = std::move(prefix) + "keeper";
            if (!IOEnv::fileExists(index_fname) || !IOEnv::fileExists(keeper_fname)) { // repair
                if (IOEnv::fileExists(index_fname)) {
                    IOEnv::deleteFile(index_fname);
                } else {
                    IOEnv::deleteFile(keeper_fname);
                }

                _meta.build(std::move(keeper_fname), DBSingleWeakMeta{}, "");
                _af.build(data_fname);
                _rf.build(std::move(data_fname));
                _index.build(std::move(index_fname), _seq_gen, _rf.get());
                auto it = LogReader::makeTableIteratorOffset(_rf.get());
                while (it->valid()) {
                    auto item = it->item();
                    updateKeyRange(item.first);
                    _index->insert(item.first, OffsetToData{item.second});
                    it->next();
                }
                _writer.build(_af.get());
                return;
            }
            _meta.build(std::move(keeper_fname));
            _af.build(data_fname);
            _rf.build(std::move(data_fname));
            _index.build(std::move(index_fname), _meta->immut_value()._offset, _seq_gen, _rf.get());
            _writer.build(_af.get());
        } else {
            if (!_options.create_if_missing) {
                throw Exception::notFoundException("DB not found");
            }
            // 新建数据库
            IOEnv::createDir(_name);
            _file_lock.build(prefix + "lock");
            _af.build(prefix + "data");
            _rf.build(prefix + "data");
            _index.build(prefix + "index", _seq_gen, _rf.get());
            _writer.build(_af.get());
            _meta.build(std::move(prefix) + "keeper", DBSingleWeakMeta{}, "");
        }
    }

    void DBSingle::put(const WriteOptions & options,
                       const Slice & key,
                       const Slice & value) {
        RWLockWriteGuard write_guard(_rwlock);

        uint32_t pos = _writer->calcWritePos();
        std::vector<uint8_t> bin = LogWriter::makeRecord(key, value);
        _writer->addRecord({bin.data(), bin.size()});
        updateKeyRange(key);
        _index->insert(key, OffsetToData{pos});

        _index->tryApplyPending();
        if (options.sync) _af->sync();
    };

    void DBSingle::remove(const WriteOptions & options,
                          const Slice & key) {
        RWLockWriteGuard write_guard(_rwlock);

        std::vector<uint8_t> bin = LogWriter::makeRecord(key, {});
        _writer->addDelRecord({bin.data(), bin.size()});
        _index->remove(key);

        _index->tryApplyPending();
        if (options.sync) _af->sync();
    };

    void DBSingle::write(const WriteOptions & options,
                         const std::vector<std::pair<Slice, Slice>> & kvs) {
        RWLockWriteGuard write_guard(_rwlock);

        if (options.compress) {
            assert(options.uncompress_size != 0);
            uint32_t pos = _writer->calcWritePos();
            std::vector<uint8_t> bin = LogWriter::makeCompressRecord(kvs);
            if (bin.size() <= options.uncompress_size / 8 * 7) { // worth
                _writer->addCompressRecord({bin.data(), bin.size()});
                for (const auto & kv:kvs) {
                    updateKeyRange(kv.first);
                    _index->insert(kv.first, OffsetToData{pos});
                }

                _index->tryApplyPending();
                if (options.sync) _af->sync();
                return;
            }
        }

        std::vector<std::vector<uint8_t>> group;
        group.reserve(kvs.size());
        std::transform(kvs.cbegin(), kvs.cend(), group.begin(), [](const std::pair<Slice, Slice> & kv) noexcept {
            return LogWriter::makeRecord(kv.first, kv.second);
        });

        std::vector<Slice> bkvs;
        bkvs.reserve(group.size());
        std::transform(group.cbegin(), group.cend(), bkvs.begin(),
                       [](const std::vector<uint8_t> & bkv) noexcept -> Slice {
                           return {bkv.data(), bkv.size()};
                       });

        std::vector<uint32_t> addrs = _writer->addRecords(bkvs);
        assert(kvs.size() == addrs.size());
        for (int i = 0; i < kvs.size(); ++i) {
            updateKeyRange(kvs[i].first);
            _index->insert(kvs[i].first, OffsetToData{addrs[i]});
        }

        _index->tryApplyPending();
        if (options.sync) _af->sync();
    };

    std::pair<std::string, bool>
    DBSingle::get(const ReadOptions & options, const Slice & key) const {
        RWLockReadGuard read_guard(_rwlock);
        return _index->find(key, options.sequence_number);
    };

    std::unique_ptr<Snapshot>
    DBSingle::makeSnapshot() {
        RWLockWriteGuard write_guard(_rwlock);
        _index->tryApplyPending();
        return _seq_gen->makeSnapshot();
    };

    std::unique_ptr<Iterator<Slice, std::string>>
    DBSingle::makeIterator(std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);
        return _index->makeIterator(std::move(snapshot));
    };

    std::unique_ptr<SimpleIterator<std::pair<Slice, std::string>>>
    DBSingle::makeRegexIterator(std::shared_ptr<Regex::R> regex,
                                std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);
        return _index->makeRegexIterator(std::move(regex), std::move(snapshot));
    };

    std::unique_ptr<SimpleIterator<std::pair<Slice, std::string>>>
    DBSingle::makeRegexReversedIterator(std::shared_ptr<Regex::R> regex,
                                        std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);
        return _index->makeRegexReversedIterator(std::move(regex), std::move(snapshot));
    };

    void DBSingle::tryApplyPending() {
        RWLockWriteGuard write_guard(_rwlock);
        _index->tryApplyPending();
    }

    uint64_t DBSingle::indexFileSize() const noexcept {
        RWLockReadGuard read_guard(_rwlock);
        return _index->immut_dst().immut_length();
    };

    uint64_t DBSingle::dataFileSize() const noexcept {
        RWLockReadGuard read_guard(_rwlock);
        return _af->immut_length();
    };

    void DBSingle::explicitRemove(const WriteOptions & options, const Slice & key) {
        RWLockWriteGuard write_guard(_rwlock);

        uint32_t pos = _writer->calcWritePos();
        std::vector<uint8_t> bin = LogWriter::makeRecord(key, {});
        _writer->addDelRecord({bin.data(), bin.size()});
        _index->insert(key, OffsetToData{pos});

        _index->tryApplyPending();
        if (options.sync) _af->sync();
    }

// methods below don't need lock
    Slice DBSingle::largestKey() const noexcept {
        const std::string & trailing = _meta->immut_trailing();
        uint32_t from_k_len = _meta->immut_value().from_k_len;
        uint32_t to_k_len = _meta->immut_value().to_k_len;
        return {trailing.data() + from_k_len, to_k_len};
    };

    Slice DBSingle::smallestKey() const noexcept {
        const std::string & trailing = _meta->immut_trailing();
        uint32_t from_k_len = _meta->immut_value().from_k_len;
        return {trailing.data(), from_k_len};
    };

    void DBSingle::updateKeyRange(const Slice & key) noexcept {
        if (SliceComparator{}(key, smallestKey())) { // find smaller
            std::string & trailing = _meta->mut_trailing();
            uint32_t from_k_len = _meta->immut_value().from_k_len;
            trailing.replace(trailing.begin(), trailing.begin() + from_k_len, key.data(), key.data() + key.size());
            _meta->mut_value().from_k_len = static_cast<uint32_t>(key.size());
        } else if (SliceComparator{}(largestKey(), key)) { // find larger
            std::string & trailing = _meta->mut_trailing();
            uint32_t from_k_len = _meta->immut_value().from_k_len;
            uint32_t to_k_len = _meta->immut_value().to_k_len;
            trailing.replace(trailing.begin() + from_k_len, trailing.begin() + from_k_len + to_k_len,
                             key.data(), key.data() + key.size());
            _meta->mut_value().to_k_len = static_cast<uint32_t>(key.size());
        }
    };

    bool repairDBSingle(const std::string & db_single_name, reporter_t reporter) noexcept {
        try {
            {
                RandomAccessFile rf(db_single_name + "/data");
                auto it = LogReader::makeTableRecoveryIteratorKV(&rf, reporter);

                SeqGenerator seq_gen;
                Options options{};
                options.create_if_missing = true;
                options.error_if_exists = true;
                DBSingle db(db_single_name + "_temp", options, &seq_gen);

                while (it->valid()) {
                    auto item = it->item();
                    if (item.second.back() == 1) { // del
                        db.explicitRemove(WriteOptions{}, item.first);
                    } else {
                        item.second.pop_back();
                        db.put(WriteOptions{}, item.first, item.second);
                    }
                }
            }
            if (IOEnv::fileExists(db_single_name)) {
                for (const std::string & child:IOEnv::getChildren(db_single_name)) {
                    IOEnv::deleteFile((db_single_name + '/') += child);
                }
                IOEnv::deleteDir(db_single_name);
            }
            IOEnv::renameFile(db_single_name + "_temp", db_single_name);

        } catch (const Exception & e) {
            reporter(e);
            return false;
        }
        return true;
    };
}
<commit_msg>lambda => range for<commit_after>#include "db_single.h"
#include "log_reader.h"

namespace LeviDB {
    DBSingle::DBSingle(std::string name, Options options, SeqGenerator * seq_gen)
            : DB(std::move(name), options), _seq_gen(seq_gen) {
        std::string prefix = _name + '/';

        if (IOEnv::fileExists(_name)) {
            if (_options.error_if_exists) {
                throw Exception::invalidArgumentException("DB already exists");
            }
            // 打开现有数据库
            _file_lock.build(prefix + "lock");
            std::string data_fname = prefix + "data";
            if (!IOEnv::fileExists(data_fname)) {
                throw Exception::notFoundException("data file missing", data_fname);
            }
            std::string index_fname = prefix + "index";
            std::string keeper_fname = std::move(prefix) + "keeper";
            if (!IOEnv::fileExists(index_fname) || !IOEnv::fileExists(keeper_fname)) { // repair
                if (IOEnv::fileExists(index_fname)) {
                    IOEnv::deleteFile(index_fname);
                } else {
                    IOEnv::deleteFile(keeper_fname);
                }

                _meta.build(std::move(keeper_fname), DBSingleWeakMeta{}, "");
                _af.build(data_fname);
                _rf.build(std::move(data_fname));
                _index.build(std::move(index_fname), _seq_gen, _rf.get());
                auto it = LogReader::makeTableIteratorOffset(_rf.get());
                while (it->valid()) {
                    auto item = it->item();
                    updateKeyRange(item.first);
                    _index->insert(item.first, OffsetToData{item.second});
                    it->next();
                }
                _writer.build(_af.get());
                return;
            }
            _meta.build(std::move(keeper_fname));
            _af.build(data_fname);
            _rf.build(std::move(data_fname));
            _index.build(std::move(index_fname), _meta->immut_value()._offset, _seq_gen, _rf.get());
            _writer.build(_af.get());
        } else {
            if (!_options.create_if_missing) {
                throw Exception::notFoundException("DB not found");
            }
            // 新建数据库
            IOEnv::createDir(_name);
            _file_lock.build(prefix + "lock");
            _af.build(prefix + "data");
            _rf.build(prefix + "data");
            _index.build(prefix + "index", _seq_gen, _rf.get());
            _writer.build(_af.get());
            _meta.build(std::move(prefix) + "keeper", DBSingleWeakMeta{}, "");
        }
    }

    void DBSingle::put(const WriteOptions & options,
                       const Slice & key,
                       const Slice & value) {
        RWLockWriteGuard write_guard(_rwlock);

        uint32_t pos = _writer->calcWritePos();
        std::vector<uint8_t> bin = LogWriter::makeRecord(key, value);
        _writer->addRecord({bin.data(), bin.size()});
        updateKeyRange(key);
        _index->insert(key, OffsetToData{pos});

        _index->tryApplyPending();
        if (options.sync) _af->sync();
    };

    void DBSingle::remove(const WriteOptions & options,
                          const Slice & key) {
        RWLockWriteGuard write_guard(_rwlock);

        std::vector<uint8_t> bin = LogWriter::makeRecord(key, {});
        _writer->addDelRecord({bin.data(), bin.size()});
        _index->remove(key);

        _index->tryApplyPending();
        if (options.sync) _af->sync();
    };

    void DBSingle::write(const WriteOptions & options,
                         const std::vector<std::pair<Slice, Slice>> & kvs) {
        RWLockWriteGuard write_guard(_rwlock);

        if (options.compress) {
            assert(options.uncompress_size != 0);
            uint32_t pos = _writer->calcWritePos();
            std::vector<uint8_t> bin = LogWriter::makeCompressRecord(kvs);
            if (bin.size() <= options.uncompress_size / 8 * 7) { // worth
                _writer->addCompressRecord({bin.data(), bin.size()});
                for (const auto & kv:kvs) {
                    updateKeyRange(kv.first);
                    _index->insert(kv.first, OffsetToData{pos});
                }

                _index->tryApplyPending();
                if (options.sync) _af->sync();
                return;
            }
        }

        std::vector<std::vector<uint8_t>> group;
        group.reserve(kvs.size());
        for (const auto & kv:kvs) {
            group.emplace_back(LogWriter::makeRecord(kv.first, kv.second));
        }

        std::vector<Slice> bkvs;
        bkvs.reserve(group.size());
        for (const auto & bkv:group) {
            bkvs.emplace_back(bkv.data(), bkv.size());
        }

        std::vector<uint32_t> addrs = _writer->addRecords(bkvs);
        assert(kvs.size() == addrs.size());
        for (int i = 0; i < kvs.size(); ++i) {
            updateKeyRange(kvs[i].first);
            _index->insert(kvs[i].first, OffsetToData{addrs[i]});
        }

        _index->tryApplyPending();
        if (options.sync) _af->sync();
    };

    std::pair<std::string, bool>
    DBSingle::get(const ReadOptions & options, const Slice & key) const {
        RWLockReadGuard read_guard(_rwlock);
        return _index->find(key, options.sequence_number);
    };

    std::unique_ptr<Snapshot>
    DBSingle::makeSnapshot() {
        RWLockWriteGuard write_guard(_rwlock);
        _index->tryApplyPending();
        return _seq_gen->makeSnapshot();
    };

    std::unique_ptr<Iterator<Slice, std::string>>
    DBSingle::makeIterator(std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);
        return _index->makeIterator(std::move(snapshot));
    };

    std::unique_ptr<SimpleIterator<std::pair<Slice, std::string>>>
    DBSingle::makeRegexIterator(std::shared_ptr<Regex::R> regex,
                                std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);
        return _index->makeRegexIterator(std::move(regex), std::move(snapshot));
    };

    std::unique_ptr<SimpleIterator<std::pair<Slice, std::string>>>
    DBSingle::makeRegexReversedIterator(std::shared_ptr<Regex::R> regex,
                                        std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);
        return _index->makeRegexReversedIterator(std::move(regex), std::move(snapshot));
    };

    void DBSingle::tryApplyPending() {
        RWLockWriteGuard write_guard(_rwlock);
        _index->tryApplyPending();
    }

    uint64_t DBSingle::indexFileSize() const noexcept {
        RWLockReadGuard read_guard(_rwlock);
        return _index->immut_dst().immut_length();
    };

    uint64_t DBSingle::dataFileSize() const noexcept {
        RWLockReadGuard read_guard(_rwlock);
        return _af->immut_length();
    };

    void DBSingle::explicitRemove(const WriteOptions & options, const Slice & key) {
        RWLockWriteGuard write_guard(_rwlock);

        uint32_t pos = _writer->calcWritePos();
        std::vector<uint8_t> bin = LogWriter::makeRecord(key, {});
        _writer->addDelRecord({bin.data(), bin.size()});
        _index->insert(key, OffsetToData{pos});

        _index->tryApplyPending();
        if (options.sync) _af->sync();
    }

// methods below don't need lock
    Slice DBSingle::largestKey() const noexcept {
        const std::string & trailing = _meta->immut_trailing();
        uint32_t from_k_len = _meta->immut_value().from_k_len;
        uint32_t to_k_len = _meta->immut_value().to_k_len;
        return {trailing.data() + from_k_len, to_k_len};
    };

    Slice DBSingle::smallestKey() const noexcept {
        const std::string & trailing = _meta->immut_trailing();
        uint32_t from_k_len = _meta->immut_value().from_k_len;
        return {trailing.data(), from_k_len};
    };

    void DBSingle::updateKeyRange(const Slice & key) noexcept {
        if (SliceComparator{}(key, smallestKey())) { // find smaller
            std::string & trailing = _meta->mut_trailing();
            uint32_t from_k_len = _meta->immut_value().from_k_len;
            trailing.replace(trailing.begin(), trailing.begin() + from_k_len, key.data(), key.data() + key.size());
            _meta->mut_value().from_k_len = static_cast<uint32_t>(key.size());
        } else if (SliceComparator{}(largestKey(), key)) { // find larger
            std::string & trailing = _meta->mut_trailing();
            uint32_t from_k_len = _meta->immut_value().from_k_len;
            uint32_t to_k_len = _meta->immut_value().to_k_len;
            trailing.replace(trailing.begin() + from_k_len, trailing.begin() + from_k_len + to_k_len,
                             key.data(), key.data() + key.size());
            _meta->mut_value().to_k_len = static_cast<uint32_t>(key.size());
        }
    };

    bool repairDBSingle(const std::string & db_single_name, reporter_t reporter) noexcept {
        try {
            {
                RandomAccessFile rf(db_single_name + "/data");
                auto it = LogReader::makeTableRecoveryIteratorKV(&rf, reporter);

                SeqGenerator seq_gen;
                Options options{};
                options.create_if_missing = true;
                options.error_if_exists = true;
                DBSingle db(db_single_name + "_temp", options, &seq_gen);

                while (it->valid()) {
                    auto item = it->item();
                    if (item.second.back() == 1) { // del
                        db.explicitRemove(WriteOptions{}, item.first);
                    } else {
                        item.second.pop_back();
                        db.put(WriteOptions{}, item.first, item.second);
                    }
                }
            }
            if (IOEnv::fileExists(db_single_name)) {
                for (const std::string & child:IOEnv::getChildren(db_single_name)) {
                    IOEnv::deleteFile((db_single_name + '/') += child);
                }
                IOEnv::deleteDir(db_single_name);
            }
            IOEnv::renameFile(db_single_name + "_temp", db_single_name);

        } catch (const Exception & e) {
            reporter(e);
            return false;
        }
        return true;
    };
}
<|endoftext|>


<commit_before>#include <windows.h>
#include <atlbase.h>
#include <exdispid.h>
#include <exdisp.h>
#include <mshtml.h>
#include "resource.h"
#include "eventsink.h"

void Log(LPCWSTR format, ...);

EventSink::EventSink(HWND container)
  : ref_(1), container_(container)
{}

EventSink::~EventSink() {
  Log(L"%s\n", __FUNCTIONW__);
}

STDMETHODIMP EventSink::QueryInterface(REFIID riid, void **ppvObject) {
  const QITAB QITable[] = {
    QITABENT(EventSink, IDispatch),
    { 0 },
  };
  return QISearch(this, QITable, riid, ppvObject);
}

STDMETHODIMP_(ULONG) EventSink::AddRef() {
  return InterlockedIncrement(&ref_);
}

STDMETHODIMP_(ULONG) EventSink::Release() {
  auto cref = InterlockedDecrement(&ref_);
  if (cref == 0) {
    delete this;
  }
  return cref;
}

STDMETHODIMP EventSink::GetTypeInfoCount(__RPC__out UINT *pctinfo) {
  return E_NOTIMPL;
}

STDMETHODIMP EventSink::GetTypeInfo(UINT iTInfo,
                                    LCID lcid,
                                    __RPC__deref_out_opt ITypeInfo **ppTInfo) {
  return E_NOTIMPL;
}

STDMETHODIMP EventSink::GetIDsOfNames(__RPC__in REFIID riid,
                                      __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,
                                      __RPC__in_range(0, 16384) UINT cNames,
                                      LCID lcid,
                                      __RPC__out_ecount_full(cNames) DISPID *rgDispId) {
  return E_NOTIMPL;
}

static bool InjectScriptElement(CComQIPtr<IWebBrowser2> &wb,
                                LPCWSTR scriptText) {
  CComPtr<IDispatch> dispatch;
  if (SUCCEEDED(wb->get_Document(&dispatch))) {
    CComBSTR tagScript(L"script");
    CComBSTR tagText(L"text");
    CComBSTR tagHead(L"head");
    CComQIPtr<IHTMLDOMNode> scriptNode;
    if (CComQIPtr<IHTMLDocument2> doc = dispatch) {
      CComPtr<IHTMLElement> scriptElem;
      if (SUCCEEDED(doc->createElement(tagScript, &scriptElem))) {
        CComVariant text(scriptText);
        if (SUCCEEDED(scriptElem->setAttribute(tagText, text))) {
          scriptNode = scriptElem;
        }
      }
    }
    if (scriptNode) {
      if (CComQIPtr<IHTMLDocument3> doc = dispatch) {
        CComPtr<IHTMLElementCollection> elements;
        long num_elements = 0;
        if (SUCCEEDED(doc->getElementsByTagName(tagHead, &elements))
            && SUCCEEDED(elements->get_length(&num_elements))
            && num_elements > 0) {
          CComPtr<IDispatch> element0;
          CComVariant zero(0);
          if (SUCCEEDED(elements->item(zero, zero, &element0))) {
            if (CComQIPtr<IHTMLDOMNode> node = element0) {
              CComPtr<IHTMLDOMNode> appended;
              if (SUCCEEDED(node->appendChild(scriptNode, &appended))) {
                return true;
              }
            }
          }
        }
      }
    }
  }
  return false;
}

STDMETHODIMP EventSink::Invoke(_In_  DISPID dispIdMember,
                               _In_  REFIID riid,
                               _In_  LCID lcid,
                               _In_  WORD wFlags,
                               _In_  DISPPARAMS *pDispParams,
                               _Out_opt_  VARIANT *pVarResult,
                               _Out_opt_  EXCEPINFO *pExcepInfo,
                               _Out_opt_  UINT *puArgErr) {
  HRESULT hr = S_OK;
  switch (dispIdMember) {
  case DISPID_DOCUMENTCOMPLETE:
    if (pDispParams->cArgs == 2
        && pDispParams->rgvarg[0].vt == (VT_VARIANT | VT_BYREF)
        && pDispParams->rgvarg[0].pvarVal
        && pDispParams->rgvarg[0].pvarVal->vt == VT_BSTR
        && pDispParams->rgvarg[1].vt == VT_DISPATCH) {
      if (CComQIPtr<IWebBrowser2> wb = pDispParams->rgvarg[1].pdispVal) {
        Log(L"Received DWebBrowserEvents2.DocumentComplete: %s\n",
            pDispParams->rgvarg[0].pvarVal->bstrVal);
        LPCWSTR SuppressAlert = L"window.alert=function(){};"
                                L"window.confirm=function(){};"
                                L"window.open=function(){};"
                                L"window.close=function(){};";
        if (!InjectScriptElement(wb, SuppressAlert)) {
          Log(L"Failed to inject the script code.\n");
        }
        PostMessage(GetParent(container_),
                    WM_COMMAND,
                    MAKELONG(ID_DEBUG_SCREENSHOT_EVENT, 0),
                    0);
      }
    }
    break;
  default:
    hr = E_NOTIMPL;
    break;
  }
  return hr;
}
<commit_msg>design mode<commit_after>#include <windows.h>
#include <atlbase.h>
#include <exdispid.h>
#include <exdisp.h>
#include <mshtml.h>
#include "resource.h"
#include "eventsink.h"

void Log(LPCWSTR format, ...);

EventSink::EventSink(HWND container)
  : ref_(1), container_(container)
{}

EventSink::~EventSink() {
  Log(L"%s\n", __FUNCTIONW__);
}

STDMETHODIMP EventSink::QueryInterface(REFIID riid, void **ppvObject) {
  const QITAB QITable[] = {
    QITABENT(EventSink, IDispatch),
    { 0 },
  };
  return QISearch(this, QITable, riid, ppvObject);
}

STDMETHODIMP_(ULONG) EventSink::AddRef() {
  return InterlockedIncrement(&ref_);
}

STDMETHODIMP_(ULONG) EventSink::Release() {
  auto cref = InterlockedDecrement(&ref_);
  if (cref == 0) {
    delete this;
  }
  return cref;
}

STDMETHODIMP EventSink::GetTypeInfoCount(__RPC__out UINT *pctinfo) {
  return E_NOTIMPL;
}

STDMETHODIMP EventSink::GetTypeInfo(UINT iTInfo,
                                    LCID lcid,
                                    __RPC__deref_out_opt ITypeInfo **ppTInfo) {
  return E_NOTIMPL;
}

STDMETHODIMP EventSink::GetIDsOfNames(__RPC__in REFIID riid,
                                      __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,
                                      __RPC__in_range(0, 16384) UINT cNames,
                                      LCID lcid,
                                      __RPC__out_ecount_full(cNames) DISPID *rgDispId) {
  return E_NOTIMPL;
}

static bool InjectScriptElement(CComQIPtr<IWebBrowser2> &wb,
                                LPCWSTR scriptText) {
  CComPtr<IDispatch> dispatch;
  if (SUCCEEDED(wb->get_Document(&dispatch))) {
    CComBSTR tagScript(L"script");
    CComBSTR tagText(L"text");
    CComBSTR tagHead(L"head");
    CComQIPtr<IHTMLDOMNode> scriptNode;
    if (CComQIPtr<IHTMLDocument2> doc = dispatch) {
      CComPtr<IHTMLElement> scriptElem;
      if (SUCCEEDED(doc->createElement(tagScript, &scriptElem))) {
        CComVariant text(scriptText);
        if (SUCCEEDED(scriptElem->setAttribute(tagText, text))) {
          scriptNode = scriptElem;
        }
      }
    }
    if (scriptNode) {
      if (CComQIPtr<IHTMLDocument3> doc = dispatch) {
        CComPtr<IHTMLElementCollection> elements;
        long num_elements = 0;
        if (SUCCEEDED(doc->getElementsByTagName(tagHead, &elements))
            && SUCCEEDED(elements->get_length(&num_elements))
            && num_elements > 0) {
          CComPtr<IDispatch> element0;
          CComVariant zero(0);
          if (SUCCEEDED(elements->item(zero, zero, &element0))) {
            if (CComQIPtr<IHTMLDOMNode> node = element0) {
              CComPtr<IHTMLDOMNode> appended;
              if (SUCCEEDED(node->appendChild(scriptNode, &appended))) {
                return true;
              }
            }
          }
        }
      }
    }
  }
  return false;
}

static void SetDesignMode(CComQIPtr<IWebBrowser2> &wb, bool value) {
  CComPtr<IDispatch> dispatch;
  if (SUCCEEDED(wb->get_Document(&dispatch))) {
    if (CComQIPtr<IHTMLDocument2> doc = dispatch) {
      CComBSTR value_str(value ? L"on" : L"off");
      if (SUCCEEDED(doc->put_designMode(value_str))) {
        Log(L"designMode has been set to %s\n", BSTR(value_str));
      }
    }
  }
}

STDMETHODIMP EventSink::Invoke(_In_  DISPID dispIdMember,
                               _In_  REFIID riid,
                               _In_  LCID lcid,
                               _In_  WORD wFlags,
                               _In_  DISPPARAMS *pDispParams,
                               _Out_opt_  VARIANT *pVarResult,
                               _Out_opt_  EXCEPINFO *pExcepInfo,
                               _Out_opt_  UINT *puArgErr) {
  HRESULT hr = S_OK;
  switch (dispIdMember) {
  case DISPID_DOCUMENTCOMPLETE:
    if (pDispParams->cArgs == 2
        && pDispParams->rgvarg[0].vt == (VT_VARIANT | VT_BYREF)
        && pDispParams->rgvarg[0].pvarVal
        && pDispParams->rgvarg[0].pvarVal->vt == VT_BSTR
        && pDispParams->rgvarg[1].vt == VT_DISPATCH) {
      if (CComQIPtr<IWebBrowser2> wb = pDispParams->rgvarg[1].pdispVal) {
        Log(L"Received DWebBrowserEvents2.DocumentComplete: %s\n",
            pDispParams->rgvarg[0].pvarVal->bstrVal);
        LPCWSTR SuppressAlert = L"window.alert=function(){};"
                                L"window.confirm=function(){};"
                                L"window.open=function(){};"
                                L"window.close=function(){};";
        if (!InjectScriptElement(wb, SuppressAlert)) {
          Log(L"Failed to inject the script code.\n");
        }
        if (wcscmp(pDispParams->rgvarg[0].pvarVal->bstrVal, L"about:blank") == 0) {
          SetDesignMode(wb, true);
        }
        PostMessage(GetParent(container_),
                    WM_COMMAND,
                    MAKELONG(ID_DEBUG_SCREENSHOT_EVENT, 0),
                    0);
      }
    }
    break;
  default:
    hr = E_NOTIMPL;
    break;
  }
  return hr;
}
<|endoftext|>


<commit_before>// std
#include <vector>

// scidb
#include "SciDBAPI.h"
#include "query/Operator.h"
//#include "system/ErrorCodes.h"

// pkg
#include "fitsOperator.hh"

namespace {
    scidb::Value extractValue(scidb::OperatorParam& p) {
        typedef scidb::OperatorParamPhysicalExpression OpExpr;
        return dynamic_cast<OpExpr&>(p).getExpression()->evaluate();
    }
    int extractInt(scidb::OperatorParam& p) {
        return extractValue(p).getInt32();
    }
    std::string extractString(scidb::OperatorParam& p) {
        return extractValue(p).getString();
    }
} // anonymous namespace

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////
// FIXME: This could be a pipelined loader that doesn't just load into an array...

// Logical
class LogicalLoadFits : public scidb::LogicalOperator {
public:
    LogicalLoadFits(const std::string& logicalName, const std::string& alias)
        : scidb::LogicalOperator(logicalName, alias) {
        ADD_PARAM_CONSTANT("string"); // FITS file
        ADD_PARAM_CONSTANT("int32"); // HDU number (1=first image)
        ADD_PARAM_CONSTANT("string"); // Target array
        // No initialization needed.
    }
    virtual ~LogicalLoadFits() {}

    virtual scidb::ArrayDesc inferSchema(std::vector<scidb::ArrayDesc> s,
                                         boost::shared_ptr<scidb::Query> q) {
        typedef boost::shared_ptr<scidb::OperatorParamReference> OpParamRefP;
        using scidb::AttributeDesc;
        using scidb::AttributeID;
        using scidb::DimensionDesc;
        using scidb::TID_INT32;
        using scidb::TID_STRING;
        USER_CHECK(scidb::SCIDB_E_INVALID_OPERAND, s.size() == 0,
                   "No input array is expected");
        return scidb::ArrayDesc();

        //Not sure what to return right now.
        scidb::Attributes attrs(2);
        attrs[0] = AttributeDesc((AttributeID)0, "fitsfile",  TID_STRING, 0, 0 );
        attrs[1] = AttributeDesc((AttributeID)0, "hdu",  TID_INT32, 0, 0 );
        scidb::Dimensions dims(1);
        dims[0] = DimensionDesc("i", 0, 0, 0, 0, 2, 0);
        return scidb::ArrayDesc("loadfits", attrs, dims);

    }
};
namespace scidb {
REGISTER_LOGICAL_OPERATOR_FACTORY(LogicalLoadFits, "loadfits");
}

class PhysicalLoadFits: public scidb::PhysicalOperator {
public:
    typedef boost::shared_ptr<scidb::Array> ArrayPtr;
    typedef std::vector<ArrayPtr> ArrayVector;

    PhysicalLoadFits(const string& logicalName,
                    const string& physicalName,
                    const Parameters& parameters,
                    const scidb::ArrayDesc& schema)
        : scidb::PhysicalOperator(logicalName,
                                  physicalName,
                                  parameters,
                                  schema) {
    }

    virtual ~PhysicalLoadFits() {}

    boost::shared_ptr<scidb::Array> execute(ArrayVector& inputArrays,
                                            boost::shared_ptr<scidb::Query> ) {
        assert(inputArrays.size() == 0);
        loadFits( extractString(*_parameters[1]), // path to FITS file
                  extractInt(*_parameters[2]), // HDU number
                  extractString(*_parameters[0]) // array name
                  );
        // Not sure what to return as an array right now.
        return ArrayPtr();
    }
};

namespace scidb {
REGISTER_PHYSICAL_OPERATOR_FACTORY(PhysicalLoadFits,
                                   "loadFits", "physicalLoadFits");
}

// Physical
<commit_msg>Change load function argument order<commit_after>// std
#include <vector>

// scidb
#include "SciDBAPI.h"
#include "query/Operator.h"
//#include "system/ErrorCodes.h"

// pkg
#include "fitsOperator.hh"

namespace {
    scidb::Value extractValue(scidb::OperatorParam& p) {
        typedef scidb::OperatorParamPhysicalExpression OpExpr;
        return dynamic_cast<OpExpr&>(p).getExpression()->evaluate();
    }
    int extractInt(scidb::OperatorParam& p) {
        return extractValue(p).getInt32();
    }
    std::string extractString(scidb::OperatorParam& p) {
        return extractValue(p).getString();
    }
} // anonymous namespace

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////
// FIXME: This could be a pipelined loader that doesn't just load into an array...

// Logical
class LogicalLoadFits : public scidb::LogicalOperator {
public:
    LogicalLoadFits(const std::string& logicalName, const std::string& alias)
        : scidb::LogicalOperator(logicalName, alias) {
        ADD_PARAM_CONSTANT("string"); // FITS file
        ADD_PARAM_CONSTANT("string"); // Target array
        ADD_PARAM_CONSTANT("int32"); // HDU number (1=first image)
        // No initialization needed.
    }
    virtual ~LogicalLoadFits() {}

    virtual scidb::ArrayDesc inferSchema(std::vector<scidb::ArrayDesc> s,
                                         boost::shared_ptr<scidb::Query> q) {
        typedef boost::shared_ptr<scidb::OperatorParamReference> OpParamRefP;
        using scidb::AttributeDesc;
        using scidb::AttributeID;
        using scidb::DimensionDesc;
        using scidb::TID_INT32;
        using scidb::TID_STRING;
        USER_CHECK(scidb::SCIDB_E_INVALID_OPERAND, s.size() == 0,
                   "No input array is expected");
        return scidb::ArrayDesc();

        //Not sure what to return right now.
        scidb::Attributes attrs(2);
        attrs[0] = AttributeDesc((AttributeID)0, "fitsfile",  TID_STRING, 0, 0 );
        attrs[1] = AttributeDesc((AttributeID)0, "hdu",  TID_INT32, 0, 0 );
        scidb::Dimensions dims(1);
        dims[0] = DimensionDesc("i", 0, 0, 0, 0, 2, 0);
        return scidb::ArrayDesc("loadfits", attrs, dims);

    }
};
namespace scidb {
REGISTER_LOGICAL_OPERATOR_FACTORY(LogicalLoadFits, "loadfits");
}

class PhysicalLoadFits: public scidb::PhysicalOperator {
public:
    typedef boost::shared_ptr<scidb::Array> ArrayPtr;
    typedef std::vector<ArrayPtr> ArrayVector;

    PhysicalLoadFits(const string& logicalName,
                    const string& physicalName,
                    const Parameters& parameters,
                    const scidb::ArrayDesc& schema)
        : scidb::PhysicalOperator(logicalName,
                                  physicalName,
                                  parameters,
                                  schema) {
    }

    virtual ~PhysicalLoadFits() {}

    boost::shared_ptr<scidb::Array> execute(ArrayVector& inputArrays,
                                            boost::shared_ptr<scidb::Query> ) {
        assert(inputArrays.size() == 0);
        loadFits( extractString(*_parameters[1]), // path to FITS file
                  extractInt(*_parameters[2]), // HDU number
                  extractString(*_parameters[0]) // array name
                  );
        // Not sure what to return as an array right now.
        return ArrayPtr();
    }
};

namespace scidb {
REGISTER_PHYSICAL_OPERATOR_FACTORY(PhysicalLoadFits,
                                   "loadFits", "physicalLoadFits");
}

// Physical
<|endoftext|>


<commit_before>#ifndef FORMATION_HPP
#define FORMATION_HPP 1

#include <QString>
#include <map>

#include "structures.hpp"
#include "singleton.hpp"
#include "manager.hpp"
#include "uvmanager.hpp"

#include <iostream>

class Formation;
typedef Singleton<Manager<Formation>> FormationManager;

#define CUM CategorieUVManager::getInstance()
#define UVM UvManager::getInstance()
#define FM FormationManager::getInstance()

//! Classe des Formations
class Formation : public BaseItem {

  public:

    Formation(const QString& abbr, const QString& n)
        : BaseItem(abbr), longName(n), parent(""), nbLignes(0), nbColonnes(0),
          minCredits(0) {}

    inline const QString& getLongName() const { return longName; }
    inline bool hasParent() const { return parent != ""; }
    inline void addUv(const QString& u) { uvs.push_back(UVM->getItem(u)); }
    inline void addUv(Uv u) { uvs.push_back(u); }

    //! Retourne le parent de la formation, lève une exception s’il n’existe pas
    inline const Formation& getParent() const { return FM->getItem(parent); }

    inline const std::map<CategorieUV, int>& getRequirements() const { return requirements; }
    inline unsigned int getLignesTSH() const { return nbLignes; }
    inline unsigned int getColonnesTSH() const { return nbColonnes; }
    inline const std::vector<Uv>& getUvs() const { return uvs; }

    inline bool hasChildren() const {
        std::vector<Formation> formations = FM->iterator();
        for(auto it=formations.begin(); it!=formations.end(); it++) {
            if (it->hasParent() && (it->getParent() == *this)) {
                return true;
            }
        }
        return false;
    }

    inline void setLongName(const QString &l) { longName = l; }
    inline void setRequirements(const QString &c, unsigned int n) {
        //Vérifie si la catégorie existe
        CategorieUV cat("", "");
        try {
            cat = CUM->getItem(c);
        } catch (Exception) {
            return;
        }

        requirements[cat] = n;
    }

    inline void setParent(const QString& p) {
        //On vérifie que le parent existe
        try {
            FM->getItem(p);
        } catch (Exception) {
            return;
        }

        parent = p;
    }
    inline void setLignesTSH(unsigned int l) { nbLignes = l; }
    inline void setColonnesTSH(unsigned int c) { nbColonnes = c; }

  protected:
    QString longName;

    //! Formation parente, vide si pas de parent
    QString parent;

    //! Minimums de crédits requis par catégories
    std::map<CategorieUV, int> requirements;

    //! UVs de la formation
    std::vector<Uv> uvs;

    //! Nombre de lignes présentes dans le tableau TSH
    unsigned int nbLignes;

    //! Nombre de colonnes présentes dans le tableau TSH
    unsigned int nbColonnes;

    //! Nombre minimum de crédits à valider toutes catégories confondues
    unsigned int minCredits;

};

#endif // FORMATION_HPP
<commit_msg>Ajout constructeur par défaut pour Formation<commit_after>#ifndef FORMATION_HPP
#define FORMATION_HPP 1

#include <QString>
#include <map>

#include "structures.hpp"
#include "singleton.hpp"
#include "manager.hpp"
#include "uvmanager.hpp"

#include <iostream>

class Formation;
typedef Singleton<Manager<Formation>> FormationManager;

#define CUM CategorieUVManager::getInstance()
#define UVM UvManager::getInstance()
#define FM FormationManager::getInstance()

//! Classe des Formations
class Formation : public BaseItem {

  public:
    Formation() {}
    Formation(const QString& abbr, const QString& n)
        : BaseItem(abbr), longName(n), parent(""), nbLignes(0), nbColonnes(0),
          minCredits(0) {}

    inline const QString& getLongName() const { return longName; }
    inline bool hasParent() const { return parent != ""; }
    inline void addUv(const QString& u) { uvs.push_back(UVM->getItem(u)); }
    inline void addUv(Uv u) { uvs.push_back(u); }

    //! Retourne le parent de la formation, lève une exception s’il n’existe pas
    inline const Formation& getParent() const { return FM->getItem(parent); }

    inline const std::map<CategorieUV, int>& getRequirements() const { return requirements; }
    inline unsigned int getLignesTSH() const { return nbLignes; }
    inline unsigned int getColonnesTSH() const { return nbColonnes; }
    inline const std::vector<Uv>& getUvs() const { return uvs; }

    inline bool hasChildren() const {
        std::vector<Formation> formations = FM->iterator();
        for(auto it=formations.begin(); it!=formations.end(); it++) {
            if (it->hasParent() && (it->getParent() == *this)) {
                return true;
            }
        }
        return false;
    }

    inline void setLongName(const QString &l) { longName = l; }
    inline void setRequirements(const QString &c, unsigned int n) {
        //Vérifie si la catégorie existe
        CategorieUV cat("", "");
        try {
            cat = CUM->getItem(c);
        } catch (Exception) {
            return;
        }

        requirements[cat] = n;
    }

    inline void setParent(const QString& p) {
        //On vérifie que le parent existe
        try {
            FM->getItem(p);
        } catch (Exception) {
            return;
        }

        parent = p;
    }
    inline void setLignesTSH(unsigned int l) { nbLignes = l; }
    inline void setColonnesTSH(unsigned int c) { nbColonnes = c; }

  protected:
    QString longName;

    //! Formation parente, vide si pas de parent
    QString parent;

    //! Minimums de crédits requis par catégories
    std::map<CategorieUV, int> requirements;

    //! UVs de la formation
    std::vector<Uv> uvs;

    //! Nombre de lignes présentes dans le tableau TSH
    unsigned int nbLignes;

    //! Nombre de colonnes présentes dans le tableau TSH
    unsigned int nbColonnes;

    //! Nombre minimum de crédits à valider toutes catégories confondues
    unsigned int minCredits;

};

#endif // FORMATION_HPP
<|endoftext|>


<commit_before>#include "gl_widget.hpp"

#include <QPainter>
#include <QPaintEngine>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QCoreApplication>
#include <QtGui/QMouseEvent>
#include <QtGui/QGuiApplication>
#include <QDebug>

#include <cmath>
#include <iostream>

#include "json/assertions.h"
#include "json/value.h"
#include "json/writer.h"
#include "json/json.h"
#include "json/config.h"

#include "game_window.hpp"
#include "constants.hpp"
#include "util.hpp"

namespace
{

int constexpr kLeftDirection = 0;
int constexpr kRightDirection = 1;
int constexpr kUpDirection = 2;
int constexpr kDownDirection = 3;
int constexpr kWidth = 1024;
int constexpr kHeight = 768;

bool IsLeftButton(Qt::MouseButtons buttons)
{
  return buttons & Qt::LeftButton;
}
bool IsLeftButton(QMouseEvent const * const e)
{
  return IsLeftButton(e->button()) || IsLeftButton(e->buttons());
}

bool IsRightButton(Qt::MouseButtons buttons)
{
  return buttons & Qt::RightButton;
}
bool IsRightButton(QMouseEvent const * const e)
{
  return IsRightButton(e->button()) || IsRightButton(e->buttons());
}

} // namespace

GLWidget::GLWidget(GameWindow * mw,
                   QColor const & background,
                   size_t const & level)
  : m_mainWindow(mw),
    m_background(background),
    m_level(level)
{
  m_space = std::make_shared<Space>();

  setMinimumSize(Globals::Width, Globals::Height);
  setFocusPolicy(Qt::StrongFocus);
}

GLWidget::~GLWidget()
{
  makeCurrent();

  doneCurrent();
}

void GLWidget::initializeGL()
{
  initializeOpenGLFunctions();

  m_texturedRect = new TexturedRect();
  m_texturedRect->Initialize(this);

  Images::Instance().LoadImages();

  // Read current level parameters from a settings file.
  try
  {
    Json::Value settings;

    settings = Util::ReadJson(Globals::SettingsFileName);

    m_aliensNumber = \
        settings["Level"][std::to_string(m_level)]["AliensNumber"].asUInt();

    qDebug() << "m_aliensNumber = " << m_aliensNumber;
  }
  catch(std::exception ex) {
    qDebug() << "Can't read settings from a file!";
  }

  // Create aliens.
  for (size_t i = 1; i <= m_aliensNumber; i++) {
    m_space->AddAlien(std::make_shared<Alien>(
        100,
        QVector2D(i * 200, 600),
        100,
        100,
        Images::Instance().GetImageAlien(),
        std::make_pair(128,128)));
  }

  // Create a space ship
  m_space->SetSpaceShip(std::make_shared<SpaceShip>(
                          QVector2D(200, 600),
                          100,
                          100,
                          Images::Instance().GetImageSpaceShip(),
                          std::make_pair(128,128)));

  // Create obstacles.
  m_space->AddObstacle(std::make_shared<Obstacle>(
                         100,
                         QVector2D(200, 600),
                         Images::Instance().GetImageObstacle(),
                         std::make_pair(128,128)));

  // Create stars.
  AddStar();

  m_time.start();
}

void GLWidget::paintGL()
{
  int const elapsed = m_time.elapsed();
  Update(elapsed / 1000.0f);

  QPainter painter;
  painter.begin(this);
  painter.beginNativePainting();

  glClearColor(m_background.redF(), m_background.greenF(), m_background.blueF(), 1.0f);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glFrontFace(GL_CW);
  glCullFace(GL_BACK);
  glEnable(GL_CULL_FACE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  CheckHitAlien();

  SpaceShipBulletsLogic();

  AlienBulletsLogic();

  Render();

  RenderSpaceShip();

  RenderBullet();

  RenderObstacle();

  /// Set to zero if it reaches the 1.0 .
  if (m_period < 1.0)
  {
    m_period += 0.001f;
  }
  else
  {
    m_period = 0.0f;
    for (auto it = m_random.begin() ; it != m_random.end(); ++it)
    {
      *it = std::make_pair(Random(0,1), Random(0,1));
    }
  }

  // Generate a parameter for a star.
  // transperancy is a value between 0.0 and 1.0 .
  float transperancy = static_cast<float>(sin(m_period * 2 * PI));

  RenderStar(transperancy);
  glDisable(GL_CULL_FACE);
  glDisable(GL_BLEND);
  painter.endNativePainting();

  if (elapsed != 0)
  {
    QString framesPerSecond;
    framesPerSecond.setNum(m_frames / (elapsed / 1000.0), 'f', 2);
    painter.setPen(Qt::white);
    painter.drawText(20, 40, framesPerSecond + " fps");
  }
  painter.end();

  if (!(m_frames % 100))
  {
    m_time.start();
    m_frames = 0;
  }
  ++m_frames;
  update();
}

void GLWidget::resizeGL(int w, int h)
{
  m_screenSize.setWidth(w);
  m_screenSize.setHeight(h);
}

void GLWidget::Update(float elapsedSeconds)
{
  float const kSpeed = 20.0f; // pixels per second.

  if (m_directions[kUpDirection])
  {
    m_space->GetSpaceShip()->IncreaseY(kSpeed * elapsedSeconds);
  }
  if (m_directions[kDownDirection])
  {
    m_space->GetSpaceShip()->DecreaseY(kSpeed * elapsedSeconds);
  }
  if (m_directions[kLeftDirection])
  {
    m_space->GetSpaceShip()->DecreaseX(kSpeed * elapsedSeconds);
  }
  if (m_directions[kRightDirection])
  {
    m_space->GetSpaceShip()->IncreaseX(kSpeed * elapsedSeconds);
  }
}

void GLWidget::Render()
{
  for (auto alien : m_space->GetAliens()) {
    m_texturedRect->Render(alien->GetTexture(),
                           alien->GetPosition(),
                           QSize(128, 128),
                           m_screenSize,
                           1.0);
  }
}

void GLWidget::RenderSpaceShip()
{
  m_texturedRect->Render(m_space->GetSpaceShip()->GetTexture(),
                         m_space->GetSpaceShip()->GetPosition(),
                         QSize(128, 128),
                         m_screenSize,
                         1.0);
}

void GLWidget::RenderBullet()
{
  for (auto bullet : m_space->GetSpaceShipBullets()) {
    m_texturedRect->Render(bullet->GetTexture(),
                           bullet->GetPosition(),
                           QSize(128, 128),
                           m_screenSize,
                           1.0);
  }
  for (auto bullet : m_space->GetAlienBullets()) {
    m_texturedRect->Render(bullet->GetTexture(),
                           bullet->GetPosition(),
                           QSize(128, 128),
                           m_screenSize,
                           1.0);
  }
}

void GLWidget::RenderObstacle()
{
  for (auto obstacle : m_space->GetObstacles()) {
    m_texturedRect->Render(obstacle->GetTexture(),
                           obstacle->GetPosition(),
                           QSize(128, 128),
                           m_screenSize,
                           1.0);
  }
}

void GLWidget::RenderStar(float blend)
{
  int i=0;

  for (auto it = m_space->GetStars().begin();
       it != m_space->GetStars().end() || i <m_random.size();
       ++it, i++)
  {
    m_texturedRect->Render(
          (*it)->GetTexture(),
          QVector2D(m_random.at(i).first*kWidth, m_random.at(i).second*kHeight),
          QSize(16, 16),
          m_screenSize,
          blend);
  }
}

void GLWidget::AddStar()
{
  m_space->AddStar(std::make_shared<Star>(
                     QVector2D(200, 600),
                     Images::Instance().GetImageStar(),
                     std::make_pair(128,128)));
  m_random.push_back(std::make_pair(Random(0,1), Random(0,1)));
}

void GLWidget::CheckHitSpaceShip()
{
  QVector2D positionSpaceShip = m_space->GetSpaceShip()->GetPosition();
  TSize sizeSpaceShip = m_space->GetSpaceShip()->GetSize();
  Box2D spaceShipBox = Box2D::createBox(Point2D(positionSpaceShip.x(), positionSpaceShip.y()),
                                        Point2D(positionSpaceShip.x()+sizeSpaceShip.first, positionSpaceShip.y()+sizeSpaceShip.second));
  for (auto bullet : m_space->GetAlienBullets())
  {
      QVector2D position = bullet->GetPosition();
      TSize size = bullet->GetSize();
      Box2D bulletBox = Box2D::createBox(Point2D(position.x(), position.y()), Point2D(position.x()+size.first, position.y()+size.second));
      // If two boxes are not intersected with each other
      // then return false.
      if(Box2D::checkBoxes(spaceShipBox,bulletBox))
          KillSpaceShip(bullet->GetDamage());
  }
}

void GLWidget::KillSpaceShip(uint damage)
{
    uint health = m_space->GetSpaceShip()->GetHealth();
    if((health-damage) > 0)
    {
        m_space->GetSpaceShip()->SetHealth(health-damage);
    }
    else
    {
        //emit signal Game Over
        qDebug() << "Game Over!!!!!!!!!!!!!!!!!!!!!!!!!";
    }
}

void GLWidget::CheckHitAlien()
{
    std::list<TBulletPtr> & lstBullet = m_space->GetSpaceShipBullets();
    std::list<TAlienPtr> & lstAlien = m_space->GetAliens();
    for (auto itAlien = begin(lstAlien); itAlien != end(lstAlien);)
    {
        QVector2D positionAlien = (*itAlien)->GetPosition();
        TSize sizeAlien = (*itAlien)->GetSize();
        Box2D alienBox = Box2D::createBox(Point2D(positionAlien.x(), positionAlien.y()),
                                              Point2D(positionAlien.x()+sizeAlien.first, positionAlien.y()+sizeAlien.second));
        bool flag = false;
        for (auto it = begin(lstBullet); it != end(lstBullet); ++it)
        {
            QVector2D position = (*it)->GetPosition();
            TSize size = (*it)->GetSize();
            Box2D bulletBox = Box2D::createBox(Point2D(position.x(), position.y()), Point2D(position.x()+size.first, position.y()+size.second));
            // If two boxes are not intersected with each other
            // then return false.
            if(Box2D::checkBoxes(alienBox,bulletBox))
            {
                it = lstBullet.erase(it);
                flag = true;
                break;
            }
        }
        if(flag)
        {
            itAlien = lstAlien.erase(itAlien);
             //Add vzriv
        }
        else
        {
            ++itAlien;
        }
    }
}

void GLWidget::mousePressEvent(QMouseEvent * e)
{
  QGLWidget::mousePressEvent(e);

  int const px = L2D(e->x());
  int const py = L2D(e->y());
  if (IsLeftButton(e))
  {
    // ...
  }
}

void GLWidget::mouseDoubleClickEvent(QMouseEvent * e)
{
  QGLWidget::mouseDoubleClickEvent(e);

  int const px = L2D(e->x());
  int const py = L2D(e->y());
  if (IsRightButton(e))
  {
    // ...
  }
}

void GLWidget::mouseMoveEvent(QMouseEvent * e)
{
  QGLWidget::mouseMoveEvent(e);

  int const px = L2D(e->x());
  int const py = L2D(e->y());
  if (IsLeftButton(e))
  {
    // ...
  }
}

void GLWidget::mouseReleaseEvent(QMouseEvent * e)
{
  QGLWidget::mouseReleaseEvent(e);

  int const px = L2D(e->x());
  int const py = L2D(e->y());
  if (IsLeftButton(e))
  {
    // ...
  }
}

void GLWidget::wheelEvent(QWheelEvent * e)
{
  QGLWidget::wheelEvent(e);

  int const delta = e->delta();
  int const px = L2D(e->x());
  int const py = L2D(e->y());
  // ...
}

void GLWidget::keyPressEvent(QKeyEvent * e)
{
  if (e->key() == Qt::Key_Up)
    m_directions[kUpDirection] = true;
  else if (e->key() == Qt::Key_Down)
    m_directions[kDownDirection] = true;
  else if (e->key() == Qt::Key_Left)
    m_directions[kLeftDirection] = true;
  else if (e->key() == Qt::Key_Right)
    m_directions[kRightDirection] = true;
  else if (e->key() == Qt::Key_Space)
  {
    std::shared_ptr<Bullet> bullet = std::make_shared<Bullet>(
        m_space->GetSpaceShip()->GetPosition(),
        Images::Instance().GetImageBullet(),
        100,
        std::make_pair(128,128));

    m_space->AddSpaceShipBullet(bullet);
  }
}

void GLWidget::keyReleaseEvent(QKeyEvent * e)
{
  if (e->key() == Qt::Key_Up)
    m_directions[kUpDirection] = false;
  else if (e->key() == Qt::Key_Down)
    m_directions[kDownDirection] = false;
  else if (e->key() == Qt::Key_Left)
    m_directions[kLeftDirection] = false;
  else if (e->key() == Qt::Key_Right)
    m_directions[kRightDirection] = false;
}

double GLWidget::Random(double min, double max)
{
  std::uniform_real_distribution<double> distribution(min, max);

  double number = distribution(m_generator);

  return number;
}

void GLWidget::SpaceShipBulletsLogic()
{
  // Loop over space ship bullets and delete it if needed.
  std::list<TBulletPtr> & lst = m_space->GetSpaceShipBullets();

  for (auto it = begin(lst); it != end(lst);)
  {
    (*it)->IncreaseY(100);

    if ((*it)->GetPosition().y() > Globals::Height)
    {
      it = lst.erase(it);
    }
    else
    {
      ++it;
    }
  }

  // Check if needed.
//  qDebug() << "lst.size() = " << lst.size();
}
void GLWidget::AlienBulletsLogic()
{
  // Loop over space ship bullets and delete it if needed.
  std::list<TBulletPtr> & lst = m_space->GetAlienBullets();

  for (auto it = begin(lst); it != end(lst);)
  {
    (*it)->DecreaseX(100);

    if ((*it)->GetPosition().y() < 0.0f)
    {
      it = lst.erase(it);
    }
    else
    {
      ++it;
    }
  }

  // Check if needed.
//  qDebug() << "lst.size() = " << lst.size();
}
<commit_msg>delete comment<commit_after>#include "gl_widget.hpp"

#include <QPainter>
#include <QPaintEngine>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QCoreApplication>
#include <QtGui/QMouseEvent>
#include <QtGui/QGuiApplication>
#include <QDebug>

#include <cmath>
#include <iostream>

#include "json/assertions.h"
#include "json/value.h"
#include "json/writer.h"
#include "json/json.h"
#include "json/config.h"

#include "game_window.hpp"
#include "constants.hpp"
#include "util.hpp"

namespace
{

int constexpr kLeftDirection = 0;
int constexpr kRightDirection = 1;
int constexpr kUpDirection = 2;
int constexpr kDownDirection = 3;
int constexpr kWidth = 1024;
int constexpr kHeight = 768;

bool IsLeftButton(Qt::MouseButtons buttons)
{
  return buttons & Qt::LeftButton;
}
bool IsLeftButton(QMouseEvent const * const e)
{
  return IsLeftButton(e->button()) || IsLeftButton(e->buttons());
}

bool IsRightButton(Qt::MouseButtons buttons)
{
  return buttons & Qt::RightButton;
}
bool IsRightButton(QMouseEvent const * const e)
{
  return IsRightButton(e->button()) || IsRightButton(e->buttons());
}

} // namespace

GLWidget::GLWidget(GameWindow * mw,
                   QColor const & background,
                   size_t const & level)
  : m_mainWindow(mw),
    m_background(background),
    m_level(level)
{
  m_space = std::make_shared<Space>();

  setMinimumSize(Globals::Width, Globals::Height);
  setFocusPolicy(Qt::StrongFocus);
}

GLWidget::~GLWidget()
{
  makeCurrent();

  doneCurrent();
}

void GLWidget::initializeGL()
{
  initializeOpenGLFunctions();

  m_texturedRect = new TexturedRect();
  m_texturedRect->Initialize(this);

  Images::Instance().LoadImages();

  // Read current level parameters from a settings file.
  try
  {
    Json::Value settings;

    settings = Util::ReadJson(Globals::SettingsFileName);

    m_aliensNumber = \
        settings["Level"][std::to_string(m_level)]["AliensNumber"].asUInt();

    qDebug() << "m_aliensNumber = " << m_aliensNumber;
  }
  catch(std::exception ex) {
    qDebug() << "Can't read settings from a file!";
  }

  // Create aliens.
  for (size_t i = 1; i <= m_aliensNumber; i++) {
    m_space->AddAlien(std::make_shared<Alien>(
        100,
        QVector2D(i * 200, 600),
        100,
        100,
        Images::Instance().GetImageAlien(),
        std::make_pair(128,128)));
  }

  // Create a space ship
  m_space->SetSpaceShip(std::make_shared<SpaceShip>(
                          QVector2D(200, 600),
                          100,
                          100,
                          Images::Instance().GetImageSpaceShip(),
                          std::make_pair(128,128)));

  // Create obstacles.
  m_space->AddObstacle(std::make_shared<Obstacle>(
                         100,
                         QVector2D(200, 600),
                         Images::Instance().GetImageObstacle(),
                         std::make_pair(128,128)));

  // Create stars.
  AddStar();

  m_time.start();
}

void GLWidget::paintGL()
{
  int const elapsed = m_time.elapsed();
  Update(elapsed / 1000.0f);

  QPainter painter;
  painter.begin(this);
  painter.beginNativePainting();

  glClearColor(m_background.redF(), m_background.greenF(), m_background.blueF(), 1.0f);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glFrontFace(GL_CW);
  glCullFace(GL_BACK);
  glEnable(GL_CULL_FACE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  CheckHitAlien();

  SpaceShipBulletsLogic();

  AlienBulletsLogic();

  Render();

  RenderSpaceShip();

  RenderBullet();

  RenderObstacle();

  /// Set to zero if it reaches the 1.0 .
  if (m_period < 1.0)
  {
    m_period += 0.001f;
  }
  else
  {
    m_period = 0.0f;
    for (auto it = m_random.begin() ; it != m_random.end(); ++it)
    {
      *it = std::make_pair(Random(0,1), Random(0,1));
    }
  }

  // Generate a parameter for a star.
  // transperancy is a value between 0.0 and 1.0 .
  float transperancy = static_cast<float>(sin(m_period * 2 * PI));

  RenderStar(transperancy);
  glDisable(GL_CULL_FACE);
  glDisable(GL_BLEND);
  painter.endNativePainting();

  if (elapsed != 0)
  {
    QString framesPerSecond;
    framesPerSecond.setNum(m_frames / (elapsed / 1000.0), 'f', 2);
    painter.setPen(Qt::white);
    painter.drawText(20, 40, framesPerSecond + " fps");
  }
  painter.end();

  if (!(m_frames % 100))
  {
    m_time.start();
    m_frames = 0;
  }
  ++m_frames;
  update();
}

void GLWidget::resizeGL(int w, int h)
{
  m_screenSize.setWidth(w);
  m_screenSize.setHeight(h);
}

void GLWidget::Update(float elapsedSeconds)
{
  float const kSpeed = 20.0f; // pixels per second.

  if (m_directions[kUpDirection])
  {
    m_space->GetSpaceShip()->IncreaseY(kSpeed * elapsedSeconds);
  }
  if (m_directions[kDownDirection])
  {
    m_space->GetSpaceShip()->DecreaseY(kSpeed * elapsedSeconds);
  }
  if (m_directions[kLeftDirection])
  {
    m_space->GetSpaceShip()->DecreaseX(kSpeed * elapsedSeconds);
  }
  if (m_directions[kRightDirection])
  {
    m_space->GetSpaceShip()->IncreaseX(kSpeed * elapsedSeconds);
  }
}

void GLWidget::Render()
{
  for (auto alien : m_space->GetAliens()) {
    m_texturedRect->Render(alien->GetTexture(),
                           alien->GetPosition(),
                           QSize(128, 128),
                           m_screenSize,
                           1.0);
  }
}

void GLWidget::RenderSpaceShip()
{
  m_texturedRect->Render(m_space->GetSpaceShip()->GetTexture(),
                         m_space->GetSpaceShip()->GetPosition(),
                         QSize(128, 128),
                         m_screenSize,
                         1.0);
}

void GLWidget::RenderBullet()
{
  for (auto bullet : m_space->GetSpaceShipBullets()) {
    m_texturedRect->Render(bullet->GetTexture(),
                           bullet->GetPosition(),
                           QSize(128, 128),
                           m_screenSize,
                           1.0);
  }
  for (auto bullet : m_space->GetAlienBullets()) {
    m_texturedRect->Render(bullet->GetTexture(),
                           bullet->GetPosition(),
                           QSize(128, 128),
                           m_screenSize,
                           1.0);
  }
}

void GLWidget::RenderObstacle()
{
  for (auto obstacle : m_space->GetObstacles()) {
    m_texturedRect->Render(obstacle->GetTexture(),
                           obstacle->GetPosition(),
                           QSize(128, 128),
                           m_screenSize,
                           1.0);
  }
}

void GLWidget::RenderStar(float blend)
{
  int i=0;

  for (auto it = m_space->GetStars().begin();
       it != m_space->GetStars().end() || i <m_random.size();
       ++it, i++)
  {
    m_texturedRect->Render(
          (*it)->GetTexture(),
          QVector2D(m_random.at(i).first*kWidth, m_random.at(i).second*kHeight),
          QSize(16, 16),
          m_screenSize,
          blend);
  }
}

void GLWidget::AddStar()
{
  m_space->AddStar(std::make_shared<Star>(
                     QVector2D(200, 600),
                     Images::Instance().GetImageStar(),
                     std::make_pair(128,128)));
  m_random.push_back(std::make_pair(Random(0,1), Random(0,1)));
}

void GLWidget::CheckHitSpaceShip()
{
  QVector2D positionSpaceShip = m_space->GetSpaceShip()->GetPosition();
  TSize sizeSpaceShip = m_space->GetSpaceShip()->GetSize();
  Box2D spaceShipBox = Box2D::createBox(Point2D(positionSpaceShip.x(), positionSpaceShip.y()),
                                        Point2D(positionSpaceShip.x()+sizeSpaceShip.first, positionSpaceShip.y()+sizeSpaceShip.second));
  for (auto bullet : m_space->GetAlienBullets())
  {
      QVector2D position = bullet->GetPosition();
      TSize size = bullet->GetSize();
      Box2D bulletBox = Box2D::createBox(Point2D(position.x(), position.y()), Point2D(position.x()+size.first, position.y()+size.second));
      // If two boxes are not intersected with each other
      // then return false.
      if(Box2D::checkBoxes(spaceShipBox,bulletBox))
          KillSpaceShip(bullet->GetDamage());
  }
}

void GLWidget::KillSpaceShip(uint damage)
{
    uint health = m_space->GetSpaceShip()->GetHealth();
    if((health-damage) > 0)
    {
        m_space->GetSpaceShip()->SetHealth(health-damage);
    }
    else
    {
        //emit signal Game Over
        qDebug() << "Game Over!!!!!!!!!!!!!!!!!!!!!!!!!";
    }
}

void GLWidget::CheckHitAlien()
{
    std::list<TBulletPtr> & lstBullet = m_space->GetSpaceShipBullets();
    std::list<TAlienPtr> & lstAlien = m_space->GetAliens();
    for (auto itAlien = begin(lstAlien); itAlien != end(lstAlien);)
    {
        QVector2D positionAlien = (*itAlien)->GetPosition();
        TSize sizeAlien = (*itAlien)->GetSize();
        Box2D alienBox = Box2D::createBox(Point2D(positionAlien.x(), positionAlien.y()),
                                              Point2D(positionAlien.x()+sizeAlien.first, positionAlien.y()+sizeAlien.second));
        bool flag = false;
        for (auto it = begin(lstBullet); it != end(lstBullet); ++it)
        {
            QVector2D position = (*it)->GetPosition();
            TSize size = (*it)->GetSize();
            Box2D bulletBox = Box2D::createBox(Point2D(position.x(), position.y()), Point2D(position.x()+size.first, position.y()+size.second));
            // If two boxes are not intersected with each other
            // then return false.
            if(Box2D::checkBoxes(alienBox,bulletBox))
            {
                it = lstBullet.erase(it);
                flag = true;
                break;
            }
        }
        if(flag)
        {
            itAlien = lstAlien.erase(itAlien);
        }
        else
        {
            ++itAlien;
        }
    }
}

void GLWidget::mousePressEvent(QMouseEvent * e)
{
  QGLWidget::mousePressEvent(e);

  int const px = L2D(e->x());
  int const py = L2D(e->y());
  if (IsLeftButton(e))
  {
    // ...
  }
}

void GLWidget::mouseDoubleClickEvent(QMouseEvent * e)
{
  QGLWidget::mouseDoubleClickEvent(e);

  int const px = L2D(e->x());
  int const py = L2D(e->y());
  if (IsRightButton(e))
  {
    // ...
  }
}

void GLWidget::mouseMoveEvent(QMouseEvent * e)
{
  QGLWidget::mouseMoveEvent(e);

  int const px = L2D(e->x());
  int const py = L2D(e->y());
  if (IsLeftButton(e))
  {
    // ...
  }
}

void GLWidget::mouseReleaseEvent(QMouseEvent * e)
{
  QGLWidget::mouseReleaseEvent(e);

  int const px = L2D(e->x());
  int const py = L2D(e->y());
  if (IsLeftButton(e))
  {
    // ...
  }
}

void GLWidget::wheelEvent(QWheelEvent * e)
{
  QGLWidget::wheelEvent(e);

  int const delta = e->delta();
  int const px = L2D(e->x());
  int const py = L2D(e->y());
  // ...
}

void GLWidget::keyPressEvent(QKeyEvent * e)
{
  if (e->key() == Qt::Key_Up)
    m_directions[kUpDirection] = true;
  else if (e->key() == Qt::Key_Down)
    m_directions[kDownDirection] = true;
  else if (e->key() == Qt::Key_Left)
    m_directions[kLeftDirection] = true;
  else if (e->key() == Qt::Key_Right)
    m_directions[kRightDirection] = true;
  else if (e->key() == Qt::Key_Space)
  {
    std::shared_ptr<Bullet> bullet = std::make_shared<Bullet>(
        m_space->GetSpaceShip()->GetPosition(),
        Images::Instance().GetImageBullet(),
        100,
        std::make_pair(128,128));

    m_space->AddSpaceShipBullet(bullet);
  }
}

void GLWidget::keyReleaseEvent(QKeyEvent * e)
{
  if (e->key() == Qt::Key_Up)
    m_directions[kUpDirection] = false;
  else if (e->key() == Qt::Key_Down)
    m_directions[kDownDirection] = false;
  else if (e->key() == Qt::Key_Left)
    m_directions[kLeftDirection] = false;
  else if (e->key() == Qt::Key_Right)
    m_directions[kRightDirection] = false;
}

double GLWidget::Random(double min, double max)
{
  std::uniform_real_distribution<double> distribution(min, max);

  double number = distribution(m_generator);

  return number;
}

void GLWidget::SpaceShipBulletsLogic()
{
  // Loop over space ship bullets and delete it if needed.
  std::list<TBulletPtr> & lst = m_space->GetSpaceShipBullets();

  for (auto it = begin(lst); it != end(lst);)
  {
    (*it)->IncreaseY(100);

    if ((*it)->GetPosition().y() > Globals::Height)
    {
      it = lst.erase(it);
    }
    else
    {
      ++it;
    }
  }

  // Check if needed.
//  qDebug() << "lst.size() = " << lst.size();
}
void GLWidget::AlienBulletsLogic()
{
  // Loop over space ship bullets and delete it if needed.
  std::list<TBulletPtr> & lst = m_space->GetAlienBullets();

  for (auto it = begin(lst); it != end(lst);)
  {
    (*it)->DecreaseX(100);

    if ((*it)->GetPosition().y() < 0.0f)
    {
      it = lst.erase(it);
    }
    else
    {
      ++it;
    }
  }

  // Check if needed.
//  qDebug() << "lst.size() = " << lst.size();
}
<|endoftext|>