<commit_before>#include <pybind11/pybind11.h>
#include <sirius.h>
#include <pybind11/stl.h>
#include <pybind11/operators.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <utility>
#include <memory>
#include "utils/json.hpp"

using namespace pybind11::literals; // to bring in the `_a` literal
namespace py = pybind11;
using namespace sirius;
using namespace geometry3d;
using json = nlohmann::json;
using nlohmann::basic_json;

//inspired by: https://github.com/mdcb/python-jsoncpp11/blob/master/extension.cpp
py::object pj_convert(json& node)
{
    switch (node.type()) {
        case json::value_t::null: {
            return py::reinterpret_borrow<py::object>(Py_None);
        }
        case json::value_t::boolean: {
            bool b(node);
            return py::bool_(b);
        }
        case json::value_t::string: {
            std::string s;
            s = static_cast<std::string const&>(node);
            return py::str(s);
        }
        case json::value_t::number_integer: {
            int i(node);
            return py::int_(i);
        }
        case json::value_t::number_unsigned: {
            unsigned int u(node);
            return py::int_(u);
        }
        case json::value_t::number_float: {
            float f(node);
            return py::float_(f);
        }
        case json::value_t::object: {
            py::dict result;
            for (auto it = node.begin(); it != node.end(); ++it) {
                json my_key(it.key());
                result[pj_convert(my_key)] = pj_convert(*it);
            }
            return result;
        }
        case json::value_t::array: {
            py::list result;
            for (auto it = node.begin(); it != node.end(); ++it) {
                result.append(pj_convert(*it));
            }
            return result;
        }
        default: {
            throw std::runtime_error("undefined json value");
            /* make compiler happy */
            return py::reinterpret_borrow<py::object>(Py_None);
        }
    }
}

std::string show_mat(const matrix3d<double>& mat)
{
  std::string str = "[";
  for (int i=0; i<2; ++i)
  {str = str +"[" + std::to_string(mat(i,0)) + "," + std::to_string(mat(i,1)) + "," + std::to_string(mat(i,2)) + "]"+"\n";}
  str = str + "[" + std::to_string(mat(2,0)) + "," + std::to_string(mat(2,1)) + "," + std::to_string(mat(2,2)) + "]"+ "]";
  return str;
}

template<class T>
std::string show_vec(const vector3d<T>& vec)
{
  std::string str = "[" + std::to_string(vec[0]) + "," + std::to_string(vec[1]) + "," + std::to_string(vec[2]) + "]";
  return str;
}

PYBIND11_MODULE(py_sirius, m){

m.def("initialize", []()
                    {
                        sirius::initialize();
                    });

m.def("finalize", []()
                  {
                      sirius::finalize();
                  });

py::class_<Parameters_input>(m, "Parameters_input")
    .def(py::init<>())
    .def_readwrite("potential_tol_", &Parameters_input::potential_tol_)
    .def_readwrite("energy_tol_", &Parameters_input::energy_tol_)
    .def_readwrite("num_dft_iter_", &Parameters_input::num_dft_iter_);

py::class_<Simulation_parameters>(m, "Simulation_parameters")
    .def(py::init<>())
    .def("pw_cutoff", &Simulation_parameters::pw_cutoff)
    .def("parameters_input",               (Parameters_input& (Simulation_parameters::*)()) &Simulation_parameters::parameters_input,
                                           py::return_value_policy::reference)
    .def("num_spin_dims",                  &Simulation_parameters::num_spin_dims)
    .def("num_mag_dims",                   &Simulation_parameters::num_mag_dims)
    .def("set_gamma_point",                &Simulation_parameters::set_gamma_point)
    .def("set_pw_cutoff",                  &Simulation_parameters::set_pw_cutoff)
    .def("set_iterative_solver_tolerance", &Simulation_parameters::set_iterative_solver_tolerance);

py::class_<Simulation_context_base, Simulation_parameters>(m, "Simulation_context_base");

py::class_<Simulation_context, Simulation_context_base>(m, "Simulation_context")
    .def(py::init<>())
    .def(py::init<std::string const&>())
    .def("initialize", &Simulation_context::initialize)
    .def("num_bands", py::overload_cast<>(&Simulation_context::num_bands, py::const_))
    .def("num_bands", py::overload_cast<int>(&Simulation_context::num_bands))
    .def("set_verbosity", &Simulation_context::set_verbosity)
    .def("create_storage_file", &Simulation_context::create_storage_file)
    .def("gvec", &Simulation_context::gvec)
    .def("fft", &Simulation_context::fft)
    .def("unit_cell", (Unit_cell& (Simulation_context::*)()) &Simulation_context::unit_cell, py::return_value_policy::reference);

py::class_<Unit_cell>(m, "Unit_cell")
    .def("add_atom_type",              static_cast<void (Unit_cell::*)(const std::string, const std::string)>(&Unit_cell::add_atom_type))
    .def("add_atom",                   static_cast<void (Unit_cell::*)(const std::string, std::vector<double>)>(&Unit_cell::add_atom))
    .def("atom_type",                  static_cast<Atom_type& (Unit_cell::*)(int)>(&Unit_cell::atom_type), py::return_value_policy::reference)
    .def("set_lattice_vectors",        static_cast<void (Unit_cell::*)(matrix3d<double>)>(&Unit_cell::set_lattice_vectors))
    .def("get_symmetry",               &Unit_cell::get_symmetry)
    .def("reciprocal_lattice_vectors", &Unit_cell::reciprocal_lattice_vectors)
    .def("generate_radial_functions",  &Unit_cell::generate_radial_functions);

py::class_<z_column_descriptor> (m, "z_column_descriptor")
    .def_readwrite("x", &z_column_descriptor::x)
    .def_readwrite("y", &z_column_descriptor::y)
    .def_readwrite("z", &z_column_descriptor::z)
    .def(py::init<int, int , std::vector<int>>());

py::class_<Gvec>(m, "Gvec")
    .def(py::init<matrix3d<double>, double, bool>())
    .def("num_gvec", &sddk::Gvec::num_gvec)
    .def("count",    &sddk::Gvec::count)
    .def("offset",   &sddk::Gvec::offset)
    .def("gvec",     &sddk::Gvec::gvec)
    .def("num_zcol", &sddk::Gvec::num_zcol)
    .def("gvec_alt", [](Gvec &obj, int idx)
                     {
                         vector3d<int> vec(obj.gvec(idx));
                         std::vector<int> retr = {vec[0], vec[1], vec[2]};
                         return retr;
                     })
    .def("index_by_gvec", [](Gvec &obj, std::vector<int> vec)
                          {
                              vector3d<int> vec3d(vec);
                              return obj.index_by_gvec(vec3d);
                          })
    .def("zcol", [](Gvec &gvec, int idx)
                 {
                     z_column_descriptor obj(gvec.zcol(idx));
                     py::dict dict("x"_a = obj.x, "y"_a = obj.y, "z"_a = obj.z);
                     return dict;
                 })
    .def("index_by_gvec", &Gvec::index_by_gvec);

py::class_<vector3d<int>>(m, "vector3d_int")
    .def(py::init<std::vector<int>>())
    .def("__call__", [](const vector3d<int> &obj, int x)
                     {
                         return obj[x];
                     })
    .def("__repr__", [](const vector3d<int> &vec)
                     {
                         return show_vec(vec);
                     })
    .def(py::init<vector3d<int>>());

py::class_<vector3d<double>>(m, "vector3d_double")
    .def(py::init<std::vector<double>>())
    .def("__call__", [](const vector3d<double> &obj, int x)
                     {
                         return obj[x];
                     })
    .def("__repr__", [](const vector3d<double> &vec)
                     {
                         return show_vec(vec);
                     })
    .def("length", &vector3d<double>::length)
    .def(py::self - py::self)
    .def(py::self * float())
    .def(py::self + py::self)
    .def(py::init<vector3d<double>>());

py::class_<matrix3d<double>>(m, "matrix3d")
    .def(py::init<std::vector<std::vector<double>>>())
    .def(py::init<>())
    .def("__call__", [](const matrix3d<double> &obj, int x, int y)
                     {
                         return obj(x,y);
                     })
    .def(py::self * py::self)
    .def("__getitem__", [](const matrix3d<double> &obj, int x, int y)
                        {
                            return obj(x,y);
                        })
    .def("__mul__", [](const matrix3d<double> & obj, vector3d<double> const& b)
                    {
                        vector3d<double> res = obj * b;
                        return res;
                    })
    .def("__repr__", [](const matrix3d<double> &mat)
                     {
                         return show_mat(mat);
                     })
    .def(py::init<matrix3d<double>>())
    .def("det", &matrix3d<double>::det);

py::class_<Potential>(m, "Potential")
    .def(py::init<Simulation_context&>())
    .def("generate", &Potential::generate)
    .def("allocate", &Potential::allocate)
    .def("save", &Potential::save)
    .def("load", &Potential::load);

py::class_<Density>(m, "Density")
    .def(py::init<Simulation_context&>())
    .def("initial_density", &Density::initial_density)
    .def("allocate", &Density::allocate)
    .def("save", &Density::save)
    .def("load", &Density::load);

py::class_<Band>(m, "Band")
    .def(py::init<Simulation_context&>())
    .def("initialize_subspace", py::overload_cast<K_point_set&, Hamiltonian&>(&Band::initialize_subspace, py::const_))
    .def("solve", &Band::solve);

py::class_<DFT_ground_state>(m, "DFT_ground_state")
    .def(py::init<K_point_set&>())
    .def("print_info", &DFT_ground_state::print_info)
    .def("initial_state", &DFT_ground_state::initial_state)
    .def("print_magnetic_moment", &DFT_ground_state::print_magnetic_moment)
    .def("total_energy", &DFT_ground_state::total_energy)
    .def("band", &DFT_ground_state::band)
    .def("density", &DFT_ground_state::density, py::return_value_policy::reference)
    .def("find", [](DFT_ground_state& dft, double potential_tol, double energy_tol, int num_dft_iter, bool write_state)
                 {
                     json js = dft.find(potential_tol, energy_tol, num_dft_iter, write_state);
                     return pj_convert(js);
                 })
    .def("k_point_set", &DFT_ground_state::k_point_set, py::return_value_policy::reference_internal)
    .def("hamiltonian", &DFT_ground_state::hamiltonian, py::return_value_policy::reference)
    .def("potential",   &DFT_ground_state::potential, py::return_value_policy::reference);

py::class_<K_point>(m, "K_point")
    .def("band_energy", py::overload_cast<int, int>(&K_point::band_energy))
    .def("vk", &K_point::vk, py::return_value_policy::reference);

py::class_<K_point_set>(m, "K_point_set")
    .def(py::init<Simulation_context&>())
    .def(py::init<Simulation_context&, std::vector<vector3d<double>>>())
    .def(py::init<Simulation_context&, vector3d<int>, vector3d<int>, bool>())
    .def(py::init<Simulation_context&, std::vector<int>, std::vector<int>, bool>())
    .def("initialize", py::overload_cast<>(&K_point_set::initialize))
    .def("num_kpoints", &K_point_set::num_kpoints)
    .def("energy_fermi", &K_point_set::energy_fermi)
    .def("get_band_energies", &K_point_set::get_band_energies, py::return_value_policy::reference)
    .def("sync_band_energies", &K_point_set::sync_band_energies)
    .def("__call__", &K_point_set::operator[], py::return_value_policy::reference)
    .def("add_kpoint", [](K_point_set &ks, std::vector<double> &v, double weight)
                       {
                           vector3d<double> vec3d(v);
                           ks.add_kpoint(&vec3d[0], weight);
                       })
    .def("add_kpoint", [](K_point_set &ks, vector3d<double> &v, double weight)
                       {
                           ks.add_kpoint(&v[0], weight);
                       });

py::class_<Hamiltonian>(m, "Hamiltonian")
    .def(py::init<Simulation_context&, Potential&>());

py::class_<Stress>(m, "Stress")
    //.def(py::init<Simulation_context&, K_point_set&, Density&, Potential&>())
    .def("calc_stress_total", &Stress::calc_stress_total, py::return_value_policy::reference_internal)
    .def("print_info", &Stress::print_info);

py::class_<Force>(m, "Force")
    //.def(py::init<Simulation_context&, Density&, Potential&, Hamiltonian&, K_point_set&>())
    .def("calc_forces_total", &Force::calc_forces_total, py::return_value_policy::reference_internal)
    .def("print_info", &Force::print_info);

py::class_<Free_atom>(m, "Free_atom")
    .def(py::init<Simulation_parameters&, std::string>())
    .def(py::init<Simulation_parameters&, int>())
    .def("ground_state", [](Free_atom& atom, double energy_tol, double charge_tol, bool rel)
                         {
                             json js = atom.ground_state(energy_tol, charge_tol, rel);
                             return pj_convert(js);
                         });

}
<commit_msg>python: call sirius::init/finalize internally on module import/exit<commit_after>#include <pybind11/pybind11.h>
#include <sirius.h>
#include <pybind11/stl.h>
#include <pybind11/operators.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <utility>
#include <memory>
#include "utils/json.hpp"

using namespace pybind11::literals; // to bring in the `_a` literal
namespace py = pybind11;
using namespace sirius;
using namespace geometry3d;
using json = nlohmann::json;
using nlohmann::basic_json;

//inspired by: https://github.com/mdcb/python-jsoncpp11/blob/master/extension.cpp
py::object pj_convert(json& node)
{
    switch (node.type()) {
        case json::value_t::null: {
            return py::reinterpret_borrow<py::object>(Py_None);
        }
        case json::value_t::boolean: {
            bool b(node);
            return py::bool_(b);
        }
        case json::value_t::string: {
            std::string s;
            s = static_cast<std::string const&>(node);
            return py::str(s);
        }
        case json::value_t::number_integer: {
            int i(node);
            return py::int_(i);
        }
        case json::value_t::number_unsigned: {
            unsigned int u(node);
            return py::int_(u);
        }
        case json::value_t::number_float: {
            float f(node);
            return py::float_(f);
        }
        case json::value_t::object: {
            py::dict result;
            for (auto it = node.begin(); it != node.end(); ++it) {
                json my_key(it.key());
                result[pj_convert(my_key)] = pj_convert(*it);
            }
            return result;
        }
        case json::value_t::array: {
            py::list result;
            for (auto it = node.begin(); it != node.end(); ++it) {
                result.append(pj_convert(*it));
            }
            return result;
        }
        default: {
            throw std::runtime_error("undefined json value");
            /* make compiler happy */
            return py::reinterpret_borrow<py::object>(Py_None);
        }
    }
}

std::string show_mat(const matrix3d<double>& mat)
{
  std::string str = "[";
  for (int i=0; i<2; ++i)
  {str = str +"[" + std::to_string(mat(i,0)) + "," + std::to_string(mat(i,1)) + "," + std::to_string(mat(i,2)) + "]"+"\n";}
  str = str + "[" + std::to_string(mat(2,0)) + "," + std::to_string(mat(2,1)) + "," + std::to_string(mat(2,2)) + "]"+ "]";
  return str;
}

template<class T>
std::string show_vec(const vector3d<T>& vec)
{
  std::string str = "[" + std::to_string(vec[0]) + "," + std::to_string(vec[1]) + "," + std::to_string(vec[2]) + "]";
  return str;
}

PYBIND11_MODULE(py_sirius, m){

// MPI_Init/Finalize
sirius::initialize();
auto atexit = py::module::import("atexit");
atexit.attr("register")(py::cpp_function([](){ sirius::finalize(); }));

py::class_<Parameters_input>(m, "Parameters_input")
    .def(py::init<>())
    .def_readwrite("potential_tol_", &Parameters_input::potential_tol_)
    .def_readwrite("energy_tol_", &Parameters_input::energy_tol_)
    .def_readwrite("num_dft_iter_", &Parameters_input::num_dft_iter_);

py::class_<Simulation_parameters>(m, "Simulation_parameters")
    .def(py::init<>())
    .def("pw_cutoff", &Simulation_parameters::pw_cutoff)
    .def("parameters_input",               (Parameters_input& (Simulation_parameters::*)()) &Simulation_parameters::parameters_input,
                                           py::return_value_policy::reference)
    .def("num_spin_dims",                  &Simulation_parameters::num_spin_dims)
    .def("num_mag_dims",                   &Simulation_parameters::num_mag_dims)
    .def("set_gamma_point",                &Simulation_parameters::set_gamma_point)
    .def("set_pw_cutoff",                  &Simulation_parameters::set_pw_cutoff)
    .def("set_iterative_solver_tolerance", &Simulation_parameters::set_iterative_solver_tolerance);

py::class_<Simulation_context_base, Simulation_parameters>(m, "Simulation_context_base");

py::class_<Simulation_context, Simulation_context_base>(m, "Simulation_context")
    .def(py::init<>())
    .def(py::init<std::string const&>())
    .def("initialize", &Simulation_context::initialize)
    .def("num_bands", py::overload_cast<>(&Simulation_context::num_bands, py::const_))
    .def("num_bands", py::overload_cast<int>(&Simulation_context::num_bands))
    .def("set_verbosity", &Simulation_context::set_verbosity)
    .def("create_storage_file", &Simulation_context::create_storage_file)
    .def("gvec", &Simulation_context::gvec)
    .def("fft", &Simulation_context::fft)
    .def("unit_cell", (Unit_cell& (Simulation_context::*)()) &Simulation_context::unit_cell, py::return_value_policy::reference);

py::class_<Unit_cell>(m, "Unit_cell")
    .def("add_atom_type",              static_cast<void (Unit_cell::*)(const std::string, const std::string)>(&Unit_cell::add_atom_type))
    .def("add_atom",                   static_cast<void (Unit_cell::*)(const std::string, std::vector<double>)>(&Unit_cell::add_atom))
    .def("atom_type",                  static_cast<Atom_type& (Unit_cell::*)(int)>(&Unit_cell::atom_type), py::return_value_policy::reference)
    .def("set_lattice_vectors",        static_cast<void (Unit_cell::*)(matrix3d<double>)>(&Unit_cell::set_lattice_vectors))
    .def("get_symmetry",               &Unit_cell::get_symmetry)
    .def("reciprocal_lattice_vectors", &Unit_cell::reciprocal_lattice_vectors)
    .def("generate_radial_functions",  &Unit_cell::generate_radial_functions);

py::class_<z_column_descriptor> (m, "z_column_descriptor")
    .def_readwrite("x", &z_column_descriptor::x)
    .def_readwrite("y", &z_column_descriptor::y)
    .def_readwrite("z", &z_column_descriptor::z)
    .def(py::init<int, int , std::vector<int>>());

py::class_<Gvec>(m, "Gvec")
    .def(py::init<matrix3d<double>, double, bool>())
    .def("num_gvec", &sddk::Gvec::num_gvec)
    .def("count",    &sddk::Gvec::count)
    .def("offset",   &sddk::Gvec::offset)
    .def("gvec",     &sddk::Gvec::gvec)
    .def("num_zcol", &sddk::Gvec::num_zcol)
    .def("gvec_alt", [](Gvec &obj, int idx)
                     {
                         vector3d<int> vec(obj.gvec(idx));
                         std::vector<int> retr = {vec[0], vec[1], vec[2]};
                         return retr;
                     })
    .def("index_by_gvec", [](Gvec &obj, std::vector<int> vec)
                          {
                              vector3d<int> vec3d(vec);
                              return obj.index_by_gvec(vec3d);
                          })
    .def("zcol", [](Gvec &gvec, int idx)
                 {
                     z_column_descriptor obj(gvec.zcol(idx));
                     py::dict dict("x"_a = obj.x, "y"_a = obj.y, "z"_a = obj.z);
                     return dict;
                 })
    .def("index_by_gvec", &Gvec::index_by_gvec);

py::class_<vector3d<int>>(m, "vector3d_int")
    .def(py::init<std::vector<int>>())
    .def("__call__", [](const vector3d<int> &obj, int x)
                     {
                         return obj[x];
                     })
    .def("__repr__", [](const vector3d<int> &vec)
                     {
                         return show_vec(vec);
                     })
    .def(py::init<vector3d<int>>());

py::class_<vector3d<double>>(m, "vector3d_double")
    .def(py::init<std::vector<double>>())
    .def("__call__", [](const vector3d<double> &obj, int x)
                     {
                         return obj[x];
                     })
    .def("__repr__", [](const vector3d<double> &vec)
                     {
                         return show_vec(vec);
                     })
    .def("length", &vector3d<double>::length)
    .def(py::self - py::self)
    .def(py::self * float())
    .def(py::self + py::self)
    .def(py::init<vector3d<double>>());

py::class_<matrix3d<double>>(m, "matrix3d")
    .def(py::init<std::vector<std::vector<double>>>())
    .def(py::init<>())
    .def("__call__", [](const matrix3d<double> &obj, int x, int y)
                     {
                         return obj(x,y);
                     })
    .def(py::self * py::self)
    .def("__getitem__", [](const matrix3d<double> &obj, int x, int y)
                        {
                            return obj(x,y);
                        })
    .def("__mul__", [](const matrix3d<double> & obj, vector3d<double> const& b)
                    {
                        vector3d<double> res = obj * b;
                        return res;
                    })
    .def("__repr__", [](const matrix3d<double> &mat)
                     {
                         return show_mat(mat);
                     })
    .def(py::init<matrix3d<double>>())
    .def("det", &matrix3d<double>::det);

py::class_<Potential>(m, "Potential")
    .def(py::init<Simulation_context&>())
    .def("generate", &Potential::generate)
    .def("allocate", &Potential::allocate)
    .def("save", &Potential::save)
    .def("load", &Potential::load);

py::class_<Density>(m, "Density")
    .def(py::init<Simulation_context&>())
    .def("initial_density", &Density::initial_density)
    .def("allocate", &Density::allocate)
    .def("save", &Density::save)
    .def("load", &Density::load);

py::class_<Band>(m, "Band")
    .def(py::init<Simulation_context&>())
    .def("initialize_subspace", py::overload_cast<K_point_set&, Hamiltonian&>(&Band::initialize_subspace, py::const_))
    .def("solve", &Band::solve);

py::class_<DFT_ground_state>(m, "DFT_ground_state")
    .def(py::init<K_point_set&>())
    .def("print_info", &DFT_ground_state::print_info)
    .def("initial_state", &DFT_ground_state::initial_state)
    .def("print_magnetic_moment", &DFT_ground_state::print_magnetic_moment)
    .def("total_energy", &DFT_ground_state::total_energy)
    .def("band", &DFT_ground_state::band)
    .def("density", &DFT_ground_state::density, py::return_value_policy::reference)
    .def("find", [](DFT_ground_state& dft, double potential_tol, double energy_tol, int num_dft_iter, bool write_state)
                 {
                     json js = dft.find(potential_tol, energy_tol, num_dft_iter, write_state);
                     return pj_convert(js);
                 })
    .def("k_point_set", &DFT_ground_state::k_point_set, py::return_value_policy::reference_internal)
    .def("hamiltonian", &DFT_ground_state::hamiltonian, py::return_value_policy::reference)
    .def("potential",   &DFT_ground_state::potential, py::return_value_policy::reference);

py::class_<K_point>(m, "K_point")
    .def("band_energy", py::overload_cast<int, int>(&K_point::band_energy))
    .def("vk", &K_point::vk, py::return_value_policy::reference);

py::class_<K_point_set>(m, "K_point_set")
    .def(py::init<Simulation_context&>())
    .def(py::init<Simulation_context&, std::vector<vector3d<double>>>())
    .def(py::init<Simulation_context&, vector3d<int>, vector3d<int>, bool>())
    .def(py::init<Simulation_context&, std::vector<int>, std::vector<int>, bool>())
    .def("initialize", py::overload_cast<>(&K_point_set::initialize))
    .def("num_kpoints", &K_point_set::num_kpoints)
    .def("energy_fermi", &K_point_set::energy_fermi)
    .def("get_band_energies", &K_point_set::get_band_energies, py::return_value_policy::reference)
    .def("sync_band_energies", &K_point_set::sync_band_energies)
    .def("__call__", &K_point_set::operator[], py::return_value_policy::reference)
    .def("add_kpoint", [](K_point_set &ks, std::vector<double> &v, double weight)
                       {
                           vector3d<double> vec3d(v);
                           ks.add_kpoint(&vec3d[0], weight);
                       })
    .def("add_kpoint", [](K_point_set &ks, vector3d<double> &v, double weight)
                       {
                           ks.add_kpoint(&v[0], weight);
                       });

py::class_<Hamiltonian>(m, "Hamiltonian")
    .def(py::init<Simulation_context&, Potential&>());

py::class_<Stress>(m, "Stress")
    //.def(py::init<Simulation_context&, K_point_set&, Density&, Potential&>())
    .def("calc_stress_total", &Stress::calc_stress_total, py::return_value_policy::reference_internal)
    .def("print_info", &Stress::print_info);

py::class_<Force>(m, "Force")
    //.def(py::init<Simulation_context&, Density&, Potential&, Hamiltonian&, K_point_set&>())
    .def("calc_forces_total", &Force::calc_forces_total, py::return_value_policy::reference_internal)
    .def("print_info", &Force::print_info);

py::class_<Free_atom>(m, "Free_atom")
    .def(py::init<Simulation_parameters&, std::string>())
    .def(py::init<Simulation_parameters&, int>())
    .def("ground_state", [](Free_atom& atom, double energy_tol, double charge_tol, bool rel)
                         {
                             json js = atom.ground_state(energy_tol, charge_tol, rel);
                             return pj_convert(js);
                         });

}
<|endoftext|>


<commit_before><commit_msg>[basefunctionset.fem-localfunctions] update * use types from base * add static error message for wrong dimensions<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>
#include <policy/policy.h>
#include <random.h>
#include <test/util/setup_common.h>
#include <txmempool.h>

#include <vector>

static void AddTx(const CTransactionRef &tx, CTxMemPool &pool)
    EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) {
    int64_t nTime = 0;
    unsigned int nHeight = 1;
    bool spendsCoinbase = false;
    unsigned int sigOpCost = 4;
    LockPoints lp;
    pool.addUnchecked(CTxMemPoolEntry(tx, 1000 * SATOSHI, nTime, nHeight,
                                      spendsCoinbase, sigOpCost, lp));
}

struct Available {
    CTransactionRef ref;
    size_t vin_left{0};
    size_t tx_count;
    Available(CTransactionRef &_ref, size_t _tx_count)
        : ref(_ref), tx_count(_tx_count) {}
};

static void ComplexMemPool(benchmark::Bench &bench) {
    int childTxs = 800;
    if (bench.complexityN() > 1) {
        childTxs = static_cast<int>(bench.complexityN());
    }

    FastRandomContext det_rand{true};
    std::vector<Available> available_coins;
    std::vector<CTransactionRef> ordered_coins;
    // Create some base transactions
    size_t tx_counter = 1;
    for (auto x = 0; x < 100; ++x) {
        CMutableTransaction tx = CMutableTransaction();
        tx.vin.resize(1);
        tx.vin[0].scriptSig = CScript() << CScriptNum(tx_counter);
        tx.vout.resize(det_rand.randrange(10) + 2);
        for (auto &out : tx.vout) {
            out.scriptPubKey = CScript() << CScriptNum(tx_counter) << OP_EQUAL;
            out.nValue = 10 * COIN;
        }
        ordered_coins.emplace_back(MakeTransactionRef(tx));
        available_coins.emplace_back(ordered_coins.back(), tx_counter++);
    }
    for (auto x = 0; x < childTxs && !available_coins.empty(); ++x) {
        CMutableTransaction tx = CMutableTransaction();
        size_t n_ancestors = det_rand.randrange(10) + 1;
        for (size_t ancestor = 0;
             ancestor < n_ancestors && !available_coins.empty(); ++ancestor) {
            size_t idx = det_rand.randrange(available_coins.size());
            Available coin = available_coins[idx];
            TxId txid = coin.ref->GetId();
            // biased towards taking just one ancestor, but maybe more
            size_t n_to_take =
                det_rand.randrange(2) == 0
                    ? 1
                    : 1 + det_rand.randrange(coin.ref->vout.size() -
                                             coin.vin_left);
            for (size_t i = 0; i < n_to_take; ++i) {
                tx.vin.emplace_back();
                tx.vin.back().prevout = COutPoint(txid, coin.vin_left++);
                tx.vin.back().scriptSig = CScript() << coin.tx_count;
            }
            if (coin.vin_left == coin.ref->vin.size()) {
                coin = available_coins.back();
                available_coins.pop_back();
            }
            tx.vout.resize(det_rand.randrange(10) + 2);
            for (auto &out : tx.vout) {
                out.scriptPubKey = CScript()
                                   << CScriptNum(tx_counter) << OP_EQUAL;
                out.nValue = 10 * COIN;
            }
        }
        ordered_coins.emplace_back(MakeTransactionRef(tx));
        available_coins.emplace_back(ordered_coins.back(), tx_counter++);
    }
    TestingSetup test_setup;
    CTxMemPool pool;
    LOCK2(cs_main, pool.cs);
    bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
        for (auto &tx : ordered_coins) {
            AddTx(tx, pool);
        }
        pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
        pool.TrimToSize(GetVirtualTransactionSize(*ordered_coins.front()));
    });
}

BENCHMARK(ComplexMemPool);
<commit_msg>[bench] Benchmark CTxMemPool::check()<commit_after>// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>
#include <policy/policy.h>
#include <random.h>
#include <test/util/setup_common.h>
#include <txmempool.h>
#include <validation.h>

#include <vector>

static void AddTx(const CTransactionRef &tx, CTxMemPool &pool)
    EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) {
    int64_t nTime = 0;
    unsigned int nHeight = 1;
    bool spendsCoinbase = false;
    unsigned int sigOpCost = 4;
    LockPoints lp;
    pool.addUnchecked(CTxMemPoolEntry(tx, 1000 * SATOSHI, nTime, nHeight,
                                      spendsCoinbase, sigOpCost, lp));
}

struct Available {
    CTransactionRef ref;
    size_t vin_left{0};
    size_t tx_count;
    Available(CTransactionRef &_ref, size_t _tx_count)
        : ref(_ref), tx_count(_tx_count) {}
};

static std::vector<CTransactionRef>
CreateOrderedCoins(FastRandomContext &det_rand, int childTxs,
                   int min_ancestors) {
    std::vector<Available> available_coins;
    std::vector<CTransactionRef> ordered_coins;
    // Create some base transactions
    size_t tx_counter = 1;
    for (auto x = 0; x < 100; ++x) {
        CMutableTransaction tx = CMutableTransaction();
        tx.vin.resize(1);
        tx.vin[0].scriptSig = CScript() << CScriptNum(tx_counter);
        tx.vout.resize(det_rand.randrange(10) + 2);
        for (auto &out : tx.vout) {
            out.scriptPubKey = CScript() << CScriptNum(tx_counter) << OP_EQUAL;
            out.nValue = 10 * COIN;
        }
        ordered_coins.emplace_back(MakeTransactionRef(tx));
        available_coins.emplace_back(ordered_coins.back(), tx_counter++);
    }
    for (auto x = 0; x < childTxs && !available_coins.empty(); ++x) {
        CMutableTransaction tx = CMutableTransaction();
        size_t n_ancestors = det_rand.randrange(10) + 1;
        for (size_t ancestor = 0;
             ancestor < n_ancestors && !available_coins.empty(); ++ancestor) {
            size_t idx = det_rand.randrange(available_coins.size());
            Available coin = available_coins[idx];
            TxId txid = coin.ref->GetId();
            // biased towards taking min_ancestors parents, but maybe more
            size_t n_to_take =
                det_rand.randrange(2) == 0
                    ? min_ancestors
                    : min_ancestors + det_rand.randrange(coin.ref->vout.size() -
                                                         coin.vin_left);
            for (size_t i = 0; i < n_to_take; ++i) {
                tx.vin.emplace_back();
                tx.vin.back().prevout = COutPoint(txid, coin.vin_left++);
                tx.vin.back().scriptSig = CScript() << coin.tx_count;
            }
            if (coin.vin_left == coin.ref->vin.size()) {
                coin = available_coins.back();
                available_coins.pop_back();
            }
            tx.vout.resize(det_rand.randrange(10) + 2);
            for (auto &out : tx.vout) {
                out.scriptPubKey = CScript()
                                   << CScriptNum(tx_counter) << OP_EQUAL;
                out.nValue = 10 * COIN;
            }
        }
        ordered_coins.emplace_back(MakeTransactionRef(tx));
        available_coins.emplace_back(ordered_coins.back(), tx_counter++);
    }
    return ordered_coins;
}

static void ComplexMemPool(benchmark::Bench &bench) {
    FastRandomContext det_rand{true};
    int childTxs = 800;
    if (bench.complexityN() > 1) {
        childTxs = static_cast<int>(bench.complexityN());
    }
    std::vector<CTransactionRef> ordered_coins =
        CreateOrderedCoins(det_rand, childTxs, /* min_ancestors */ 1);
    TestingSetup test_setup;

    CTxMemPool pool;
    LOCK2(cs_main, pool.cs);
    bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
        for (auto &tx : ordered_coins) {
            AddTx(tx, pool);
        }
        pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
        pool.TrimToSize(GetVirtualTransactionSize(*ordered_coins.front()));
    });
}

static void MempoolCheck(benchmark::Bench &bench) {
    FastRandomContext det_rand{true};
    const int childTxs =
        bench.complexityN() > 1 ? static_cast<int>(bench.complexityN()) : 2000;
    const std::vector<CTransactionRef> ordered_coins =
        CreateOrderedCoins(det_rand, childTxs, /* min_ancestors */ 5);
    const auto testing_setup =
        TestingSetup(CBaseChainParams::MAIN, {"-checkmempool=1"});
    CTxMemPool pool;
    LOCK2(cs_main, pool.cs);
    for (auto &tx : ordered_coins) {
        AddTx(tx, pool);
    }

    bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
        pool.check(testing_setup.m_node.chainman->ActiveChainstate());
    });
}

BENCHMARK(ComplexMemPool);
BENCHMARK(MempoolCheck);
<|endoftext|>


<commit_before>#include "MMDIkSolver.h"

#include <glm/gtc/matrix_transform.hpp>

namespace saba
{
	MMDIkSolver::MMDIkSolver()
		: m_ikNode(nullptr)
		, m_ikTarget(nullptr)
		, m_iterateCount(1)
		, m_limitAngle(glm::pi<float>() * 2.0f)
		, m_enable(true)
	{
	}

	void MMDIkSolver::AddIKChain(MMDNode * node, bool isKnee)
	{
		IKChain chain;
		chain.m_node = node;
		chain.m_enableAxisLimit = isKnee;
		if (isKnee)
		{
			chain.m_limitMin = glm::vec3(glm::radians(0.5f), 0, 0);
			chain.m_limitMax = glm::vec3(glm::radians(180.0f), 0, 0);
		}
		m_chains.push_back(chain);
	}

	void MMDIkSolver::AddIKChain(
		MMDNode * node,
		bool axisLimit,
		const glm::vec3 & limixMin,
		const glm::vec3 & limitMax
	)
	{
		IKChain chain;
		chain.m_node = node;
		chain.m_enableAxisLimit = axisLimit;
		chain.m_limitMin = limixMin;
		chain.m_limitMax = limitMax;
		m_chains.push_back(chain);
	}

	void MMDIkSolver::Solve()
	{
		if (!m_enable)
		{
			return;
		}
		// Initialize IKChain
		for (auto& chain : m_chains)
		{
			if (chain.m_enableAxisLimit)
			{
				//auto angle = (chain.m_limitMax - chain.m_limitMin) * 0.5f;
				auto angle = chain.m_limitMax;
				auto r = glm::rotate(glm::quat(), angle.x, glm::vec3(1, 0, 0));
				r = glm::rotate(r, angle.y, glm::vec3(0, 1, 0));
				r = glm::rotate(r, angle.z, glm::vec3(0, 0, 1));
				chain.m_prevAngle = angle;
				auto rm = glm::mat3_cast(r) * glm::inverse(glm::mat3_cast(chain.m_node->m_rotate));
				chain.m_node->m_ikRotate = glm::quat_cast(rm);
			}
			else
			{
				chain.m_node->m_ikRotate = glm::quat();
			}

			chain.m_node->UpdateLocalMatrix();
			chain.m_node->UpdateGlobalMatrix();
		}

		for (uint32_t i = 0; i < m_iterateCount; i++)
		{
			SolveCore();
		}
	}

	namespace
	{
		float NormalizeAngle(float angle)
		{
			float ret = angle;
			while (ret >= glm::two_pi<float>())
			{
				ret -= glm::two_pi<float>();
			}
			while (ret < 0)
			{
				ret += glm::two_pi<float>();
			}

			return ret;
		}

		float DiffAngle(float a, float b)
		{
			float diff = NormalizeAngle(a) - NormalizeAngle(b);
			if (diff > glm::pi<float>())
			{
				return diff - glm::two_pi<float>();
			}
			else if (diff < -glm::pi<float>())
			{
				return diff + glm::two_pi<float>();
			}
			return diff;
		}

		float ClampAngle(float angle, float minAngle, float maxAngle)
		{
			if (minAngle == maxAngle)
			{
				return minAngle;
			}

			float ret = angle;
			while (ret < minAngle)
			{
				ret += glm::two_pi<float>();
			}
			if (ret < maxAngle)
			{
				return ret;
			}

			while (ret > maxAngle)
			{
				ret -= glm::two_pi<float>();
			}
			if (ret > minAngle)
			{
				return ret;
			}

			float minDiff = std::abs(DiffAngle(minAngle, ret));
			float maxDiff = std::abs(DiffAngle(maxAngle, ret));
			if (minDiff < maxDiff)
			{
				return minAngle;
			}
			else
			{
				return maxAngle;
			}
		}

		glm::vec3 Decompose(const glm::mat3& m, const glm::vec3& before)
		{
			glm::vec3 r;
			float sy = -m[0][2];
			const float e = 1.0e-6f;
			if ((1.0f - std::abs(sy)) < e)
			{
				r.y = std::asin(sy);
				// 180°に近いほうを探す
				float sx = std::sin(before.x);
				float sz = std::sin(before.z);
				if (std::abs(sx) < std::abs(sz))
				{
					// Xのほうが0または180
					float cx = std::cos(before.x);
					if (cx > 0)
					{
						r.x = 0;
						r.z = std::asin(-m[1][0]);
					}
					else
					{
						r.x = glm::pi<float>();
						r.z = std::asin(m[1][0]);
					}
				}
				else
				{
					float cz = std::cos(before.z);
					if (cz > 0)
					{
						r.z = 0;
						r.x = std::asin(-m[2][1]);
					}
					else
					{
						r.z = glm::pi<float>();
						r.x = std::asin(m[2][1]);
					}
				}
			}
			else
			{
				r.x = std::atan2(m[1][2], m[2][2]);
				r.y = std::asin(-m[0][2]);
				r.z = std::atan2(m[0][1], m[0][0]);
			}

			const float pi = glm::pi<float>();
			glm::vec3 tests[] =
			{
				{ r.x + pi, pi - r.y, r.z + pi },
				{ r.x + pi, pi - r.y, r.z - pi },
				{ r.x + pi, -pi - r.y, r.z + pi },
				{ r.x + pi, -pi - r.y, r.z - pi },
				{ r.x - pi, pi - r.y, r.z + pi },
				{ r.x - pi, pi - r.y, r.z - pi },
				{ r.x - pi, -pi - r.y, r.z + pi },
				{ r.x - pi, -pi - r.y, r.z - pi },
			};

			float errX = std::abs(DiffAngle(r.x, before.x));
			float errY = std::abs(DiffAngle(r.y, before.y));
			float errZ = std::abs(DiffAngle(r.z, before.z));
			float minErr = errX + errY + errZ;
			for (const auto test : tests)
			{
				float err = std::abs(DiffAngle(test.x, before.x))
					+ std::abs(DiffAngle(test.y, before.y))
					+ std::abs(DiffAngle(test.z, before.z));
				if (err < minErr)
				{
					minErr = err;
					r = test;
				}
			}
			return r;
		}
	}

	void MMDIkSolver::SolveCore()
	{
		auto ikPos =  glm::vec3(m_ikNode->m_global[3]);
		for (auto& chain : m_chains)
		{
			MMDNode* chainNode = chain.m_node;
			auto targetPos = glm::vec3(m_ikTarget->m_global[3]);

			auto invChain = glm::inverse(chain.m_node->m_global);

			auto chainIkPos = glm::vec3(invChain * glm::vec4(ikPos, 1));
			auto chainTargetPos = glm::vec3(invChain * glm::vec4(targetPos, 1));

			auto chainIkVec = glm::normalize(chainIkPos);
			auto chainTargetVec = glm::normalize(chainTargetPos);

			auto dot = glm::dot(chainTargetVec, chainIkVec);
			if ((1.0f - dot) < std::numeric_limits<float>::epsilon())
			{
				continue;
			}

			float angle = std::acos(dot);
			angle = glm::clamp(angle, -m_limitAngle, m_limitAngle);
			auto cross = glm::cross(chainTargetVec, chainIkVec);
			auto rot = glm::rotate(glm::quat(), angle, cross);

			auto chainRotM = glm::mat3_cast(chainNode->m_ikRotate)
				* glm::mat3_cast(chainNode->m_rotate)
				* glm::mat3_cast(rot);
			if (chain.m_enableAxisLimit)
			{
				auto rotXYZ = Decompose(chainRotM, chain.m_prevAngle);
				glm::vec3 clampXYZ;
				clampXYZ.x = ClampAngle(rotXYZ.x, chain.m_limitMin.x, chain.m_limitMax.x);
				clampXYZ.y = ClampAngle(rotXYZ.y, chain.m_limitMin.y, chain.m_limitMax.y);
				clampXYZ.z = ClampAngle(rotXYZ.z, chain.m_limitMin.z, chain.m_limitMax.z);

				clampXYZ = glm::clamp(clampXYZ - chain.m_prevAngle, -m_limitAngle, m_limitAngle) + chain.m_prevAngle;
				auto r = glm::rotate(glm::quat(), clampXYZ.x, glm::vec3(1, 0, 0));
				r = glm::rotate(r, clampXYZ.y, glm::vec3(0, 1, 0));
				r = glm::rotate(r, clampXYZ.z, glm::vec3(0, 0, 1));
				chainRotM = glm::mat3_cast(r);
				chain.m_prevAngle = clampXYZ;
			}

			auto ikRotM = chainRotM
				* glm::inverse(glm::mat3_cast(chainNode->m_rotate));

			chainNode->m_ikRotate = glm::quat_cast(ikRotM);

			chainNode->UpdateLocalMatrix();
			chainNode->UpdateGlobalMatrix();
		}
	}
}

<commit_msg>Limit を有効にした際の IKSolver で、回転の初期値を中間値にした 最大値、または最小値の場合、動かなくなってしまうため<commit_after>#include "MMDIkSolver.h"

#include <glm/gtc/matrix_transform.hpp>

namespace saba
{
	MMDIkSolver::MMDIkSolver()
		: m_ikNode(nullptr)
		, m_ikTarget(nullptr)
		, m_iterateCount(1)
		, m_limitAngle(glm::pi<float>() * 2.0f)
		, m_enable(true)
	{
	}

	void MMDIkSolver::AddIKChain(MMDNode * node, bool isKnee)
	{
		IKChain chain;
		chain.m_node = node;
		chain.m_enableAxisLimit = isKnee;
		if (isKnee)
		{
			chain.m_limitMin = glm::vec3(glm::radians(0.5f), 0, 0);
			chain.m_limitMax = glm::vec3(glm::radians(180.0f), 0, 0);
		}
		m_chains.push_back(chain);
	}

	void MMDIkSolver::AddIKChain(
		MMDNode * node,
		bool axisLimit,
		const glm::vec3 & limixMin,
		const glm::vec3 & limitMax
	)
	{
		IKChain chain;
		chain.m_node = node;
		chain.m_enableAxisLimit = axisLimit;
		chain.m_limitMin = limixMin;
		chain.m_limitMax = limitMax;
		m_chains.push_back(chain);
	}

	void MMDIkSolver::Solve()
	{
		if (!m_enable)
		{
			return;
		}
		// Initialize IKChain
		for (auto& chain : m_chains)
		{
			if (chain.m_enableAxisLimit)
			{
				auto angle = (chain.m_limitMax - chain.m_limitMin) * 0.5f;
				auto r = glm::rotate(glm::quat(), angle.x, glm::vec3(1, 0, 0));
				r = glm::rotate(r, angle.y, glm::vec3(0, 1, 0));
				r = glm::rotate(r, angle.z, glm::vec3(0, 0, 1));
				chain.m_prevAngle = angle;
				auto rm = glm::mat3_cast(r) * glm::inverse(glm::mat3_cast(chain.m_node->m_rotate));
				chain.m_node->m_ikRotate = glm::quat_cast(rm);
			}
			else
			{
				chain.m_node->m_ikRotate = glm::quat();
			}

			chain.m_node->UpdateLocalMatrix();
			chain.m_node->UpdateGlobalMatrix();
		}

		for (uint32_t i = 0; i < m_iterateCount; i++)
		{
			SolveCore();
		}
	}

	namespace
	{
		float NormalizeAngle(float angle)
		{
			float ret = angle;
			while (ret >= glm::two_pi<float>())
			{
				ret -= glm::two_pi<float>();
			}
			while (ret < 0)
			{
				ret += glm::two_pi<float>();
			}

			return ret;
		}

		float DiffAngle(float a, float b)
		{
			float diff = NormalizeAngle(a) - NormalizeAngle(b);
			if (diff > glm::pi<float>())
			{
				return diff - glm::two_pi<float>();
			}
			else if (diff < -glm::pi<float>())
			{
				return diff + glm::two_pi<float>();
			}
			return diff;
		}

		float ClampAngle(float angle, float minAngle, float maxAngle)
		{
			if (minAngle == maxAngle)
			{
				return minAngle;
			}

			float ret = angle;
			while (ret < minAngle)
			{
				ret += glm::two_pi<float>();
			}
			if (ret < maxAngle)
			{
				return ret;
			}

			while (ret > maxAngle)
			{
				ret -= glm::two_pi<float>();
			}
			if (ret > minAngle)
			{
				return ret;
			}

			float minDiff = std::abs(DiffAngle(minAngle, ret));
			float maxDiff = std::abs(DiffAngle(maxAngle, ret));
			if (minDiff < maxDiff)
			{
				return minAngle;
			}
			else
			{
				return maxAngle;
			}
		}

		glm::vec3 Decompose(const glm::mat3& m, const glm::vec3& before)
		{
			glm::vec3 r;
			float sy = -m[0][2];
			const float e = 1.0e-6f;
			if ((1.0f - std::abs(sy)) < e)
			{
				r.y = std::asin(sy);
				// 180°に近いほうを探す
				float sx = std::sin(before.x);
				float sz = std::sin(before.z);
				if (std::abs(sx) < std::abs(sz))
				{
					// Xのほうが0または180
					float cx = std::cos(before.x);
					if (cx > 0)
					{
						r.x = 0;
						r.z = std::asin(-m[1][0]);
					}
					else
					{
						r.x = glm::pi<float>();
						r.z = std::asin(m[1][0]);
					}
				}
				else
				{
					float cz = std::cos(before.z);
					if (cz > 0)
					{
						r.z = 0;
						r.x = std::asin(-m[2][1]);
					}
					else
					{
						r.z = glm::pi<float>();
						r.x = std::asin(m[2][1]);
					}
				}
			}
			else
			{
				r.x = std::atan2(m[1][2], m[2][2]);
				r.y = std::asin(-m[0][2]);
				r.z = std::atan2(m[0][1], m[0][0]);
			}

			const float pi = glm::pi<float>();
			glm::vec3 tests[] =
			{
				{ r.x + pi, pi - r.y, r.z + pi },
				{ r.x + pi, pi - r.y, r.z - pi },
				{ r.x + pi, -pi - r.y, r.z + pi },
				{ r.x + pi, -pi - r.y, r.z - pi },
				{ r.x - pi, pi - r.y, r.z + pi },
				{ r.x - pi, pi - r.y, r.z - pi },
				{ r.x - pi, -pi - r.y, r.z + pi },
				{ r.x - pi, -pi - r.y, r.z - pi },
			};

			float errX = std::abs(DiffAngle(r.x, before.x));
			float errY = std::abs(DiffAngle(r.y, before.y));
			float errZ = std::abs(DiffAngle(r.z, before.z));
			float minErr = errX + errY + errZ;
			for (const auto test : tests)
			{
				float err = std::abs(DiffAngle(test.x, before.x))
					+ std::abs(DiffAngle(test.y, before.y))
					+ std::abs(DiffAngle(test.z, before.z));
				if (err < minErr)
				{
					minErr = err;
					r = test;
				}
			}
			return r;
		}
	}

	void MMDIkSolver::SolveCore()
	{
		auto ikPos =  glm::vec3(m_ikNode->m_global[3]);
		for (auto& chain : m_chains)
		{
			MMDNode* chainNode = chain.m_node;
			auto targetPos = glm::vec3(m_ikTarget->m_global[3]);

			auto invChain = glm::inverse(chain.m_node->m_global);

			auto chainIkPos = glm::vec3(invChain * glm::vec4(ikPos, 1));
			auto chainTargetPos = glm::vec3(invChain * glm::vec4(targetPos, 1));

			auto chainIkVec = glm::normalize(chainIkPos);
			auto chainTargetVec = glm::normalize(chainTargetPos);

			auto dot = glm::dot(chainTargetVec, chainIkVec);
			if ((1.0f - dot) < std::numeric_limits<float>::epsilon())
			{
				continue;
			}

			float angle = std::acos(dot);
			angle = glm::clamp(angle, -m_limitAngle, m_limitAngle);
			auto cross = glm::cross(chainTargetVec, chainIkVec);
			auto rot = glm::rotate(glm::quat(), angle, cross);

			auto chainRotM = glm::mat3_cast(chainNode->m_ikRotate)
				* glm::mat3_cast(chainNode->m_rotate)
				* glm::mat3_cast(rot);
			if (chain.m_enableAxisLimit)
			{
				auto rotXYZ = Decompose(chainRotM, chain.m_prevAngle);
				glm::vec3 clampXYZ;
				clampXYZ.x = ClampAngle(rotXYZ.x, chain.m_limitMin.x, chain.m_limitMax.x);
				clampXYZ.y = ClampAngle(rotXYZ.y, chain.m_limitMin.y, chain.m_limitMax.y);
				clampXYZ.z = ClampAngle(rotXYZ.z, chain.m_limitMin.z, chain.m_limitMax.z);

				clampXYZ = glm::clamp(clampXYZ - chain.m_prevAngle, -m_limitAngle, m_limitAngle) + chain.m_prevAngle;
				auto r = glm::rotate(glm::quat(), clampXYZ.x, glm::vec3(1, 0, 0));
				r = glm::rotate(r, clampXYZ.y, glm::vec3(0, 1, 0));
				r = glm::rotate(r, clampXYZ.z, glm::vec3(0, 0, 1));
				chainRotM = glm::mat3_cast(r);
				chain.m_prevAngle = clampXYZ;
			}

			auto ikRotM = chainRotM
				* glm::inverse(glm::mat3_cast(chainNode->m_rotate));

			chainNode->m_ikRotate = glm::quat_cast(ikRotM);

			chainNode->UpdateLocalMatrix();
			chainNode->UpdateGlobalMatrix();
		}
	}
}

<|endoftext|>


<commit_before>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* the hover data code is largely inspired from the gtk redmond engine
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or(at your option ) any later version.
*
* This library is distributed  in the hope that it will be useful,
* but  WITHOUT ANY WARRANTY; without even  the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygenhoverdata.h"
#include "../oxygengtkutils.h"
#include "../config.h"

#include <gtk/gtk.h>
#include <iostream>

namespace Oxygen
{

    //________________________________________________________________________________
    void HoverData::connect( GtkWidget* widget )
    {

        #if OXYGEN_DEBUG
        std::cout << "HoverData::connect - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        // on connection, needs to check whether mouse pointer is in widget or not
        // to have the proper initial value of the hover flag
        gint xPointer,yPointer;
        gdk_window_get_pointer(widget->window,&xPointer,&yPointer, 0L);
        setHovered( widget, Gtk::gdk_rectangle_contains( &widget->allocation, xPointer, yPointer ) );

        // register callbacks
        _enterId = g_signal_connect( G_OBJECT(widget), "enter-notify-event", G_CALLBACK( enterNotifyEvent ), this );
        _leaveId = g_signal_connect( G_OBJECT(widget), "leave-notify-event", G_CALLBACK( leaveNotifyEvent ), this );
    }

    //________________________________________________________________________________
    void HoverData::disconnect( GtkWidget* widget )
    {
        #if OXYGEN_DEBUG
        std::cout << "HoverData::disconnect - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        g_signal_handler_disconnect( G_OBJECT(widget), _enterId );
        g_signal_handler_disconnect( G_OBJECT(widget), _leaveId );
    }

    //________________________________________________________________________________
    gboolean HoverData::enterNotifyEvent(GtkWidget* widget, GdkEventCrossing*, gpointer data )
    {
        #if OXYGEN_DEBUG
        std::cout << "HoverData::enterNotifyEvent - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        static_cast<HoverData*>( data )->setHovered( widget, true );
        return FALSE;
    }

    //________________________________________________________________________________
    gboolean HoverData::leaveNotifyEvent( GtkWidget* widget, GdkEventCrossing*, gpointer data )
    {
        #if OXYGEN_DEBUG
        std::cout << "HoverData::leaveNotifyEvent - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        static_cast<HoverData*>( data )->setHovered( widget, false );
        return FALSE;
    }

}
<commit_msg>Fixed comments. Properly initialize hover flag at creation.<commit_after>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* the hover data code is largely inspired from the gtk redmond engine
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or(at your option ) any later version.
*
* This library is distributed  in the hope that it will be useful,
* but  WITHOUT ANY WARRANTY; without even  the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygenhoverdata.h"
#include "../oxygengtkutils.h"
#include "../config.h"

#include <gtk/gtk.h>
#include <iostream>

namespace Oxygen
{

    //________________________________________________________________________________
    void HoverData::connect( GtkWidget* widget )
    {

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::HoverData::connect - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        // on connection, needs to check whether mouse pointer is in widget or not
        // to have the proper initial value of the hover flag
        gint xPointer,yPointer;
        gdk_window_get_pointer(widget->window,&xPointer,&yPointer, 0L);
        GdkRectangle rect = { 0, 0, widget->allocation.width, widget->allocation.height };
        setHovered( widget, Gtk::gdk_rectangle_contains( &rect, xPointer, yPointer ) );

        // register callbacks
        _enterId = g_signal_connect( G_OBJECT(widget), "enter-notify-event", G_CALLBACK( enterNotifyEvent ), this );
        _leaveId = g_signal_connect( G_OBJECT(widget), "leave-notify-event", G_CALLBACK( leaveNotifyEvent ), this );
    }

    //________________________________________________________________________________
    void HoverData::disconnect( GtkWidget* widget )
    {
        #if OXYGEN_DEBUG
        std::cout << "HoverData::disconnect - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        g_signal_handler_disconnect( G_OBJECT(widget), _enterId );
        g_signal_handler_disconnect( G_OBJECT(widget), _leaveId );
    }

    //________________________________________________________________________________
    gboolean HoverData::enterNotifyEvent(GtkWidget* widget, GdkEventCrossing*, gpointer data )
    {
        #if OXYGEN_DEBUG
        std::cout << "HoverData::enterNotifyEvent - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        static_cast<HoverData*>( data )->setHovered( widget, true );
        return FALSE;
    }

    //________________________________________________________________________________
    gboolean HoverData::leaveNotifyEvent( GtkWidget* widget, GdkEventCrossing*, gpointer data )
    {
        #if OXYGEN_DEBUG
        std::cout << "Oxygen::HoverData::leaveNotifyEvent - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        static_cast<HoverData*>( data )->setHovered( widget, false );
        return FALSE;
    }

}
<|endoftext|>


<commit_before>// Project specific
#include <Game.hpp>
#include <Utility/DynamicLoader/Include/DynamicLoader.hpp>
/// Engine
// Core
#include <DoremiEngine/Core/Include/DoremiEngine.hpp>
#include <DoremiEngine/Core/Include/Subsystem/EngineModuleEnum.hpp>
#include <DoremiEngine/Core/Include/SharedContext.hpp>
// Physics
#include <DoremiEngine/Physics/Include/CharacterControlManager.hpp>
#include <DoremiEngine/Physics/Include/PhysicsModule.hpp>
#include <DoremiEngine/Physics/Include/RigidBodyManager.hpp>
#include <DoremiEngine/Physics/Include/FluidManager.hpp>
// AI
#include <DoremiEngine/AI/Include/AIModule.hpp>
#include <DoremiEngine/AI/Include/Interface/SubModule/PotentialFieldSubModule.hpp>
#include <DoremiEngine/AI/Include/Interface/PotentialField/PotentialFieldActor.hpp>
// GRAPHICS
#include <DoremiEngine/Graphic/Include/GraphicModule.hpp>
#include <DoremiEngine/Graphic/Include/Interface/Manager/DirectXManager.hpp>

// Inputmodule
#include <DoremiEngine/Input/Include/InputModule.hpp>

/// Game
// handlers
#include <Doremi/Core/Include/InterpolationHandler.hpp>
#include <Doremi/Core/Include/EventHandler/EventHandlerClient.hpp>
#include <Doremi/Core/Include/PlayerHandlerClient.hpp>
#include <Doremi/Core/Include/EntityComponent/EntityHandlerClient.hpp>
#include <Doremi/Core/Include/AudioHandler.hpp>
#include <Doremi/Core/Include/InputHandlerClient.hpp>
#include <Doremi/Core/Include/MenuClasses/MainMenuHandler.hpp>
#include <Doremi/Core/Include/NetworkEventSender.hpp>
#include <Doremi/Core/Include/CameraHandler.hpp>
#include <Doremi/Core/Include/PositionCorrectionHandler.hpp>
#include <Doremi/Core/Include/Handler/StateHandler.hpp>
#include <Doremi/Core/Include/PlayerSpawnerHandler.hpp>
#include <Doremi/Core/Include/TimeHandler.hpp>
#include <Doremi/Core/Include/MenuClasses/ServerBrowserHandler.hpp>
#include <Doremi/Core/Include/SkeletalInformationHandler.hpp>

// Managers
#include <Doremi/Core/Include/Manager/GraphicManager.hpp>
#include <Doremi/Core/Include/Manager/SkeletalAnimationCoreManager.hpp>
#include <Doremi/Core/Include/Network/NetworkManagerClient.hpp>
#include <Doremi/Core/Include/Manager/MovementManagerClient.hpp>
#include <Doremi/Core/Include/Manager/AudioManager.hpp>
#include <Doremi/Core/Include/Manager/AI/AIPathManager.hpp>
#include <Doremi/Core/Include/Manager/CharacterControlSyncManager.hpp>
#include <Doremi/Core/Include/Manager/RigidTransformSyncManager.hpp>
#include <Doremi/Core/Include/Manager/JumpManager.hpp>
#include <Doremi/Core/Include/SkyBoxHandler.hpp>
#include <Doremi/Core/Include/Manager/GravityManager.hpp>
#include <Doremi/Core/Include/Manager/PressureParticleGraphicManager.hpp>
#include <Doremi/Core/Include/Manager/PressureParticleManager.hpp>
#include <Doremi/Core/Include/Manager/LightManager.hpp>
#include <Doremi/Core/Include/Manager/TriggerManager.hpp>
#include <Doremi/Core/Include/Manager/ExtraDrainSyncManager.hpp>
#include <Doremi/Core/Include/Manager/GroundEffectManagerClient.hpp>
// Components
#include <Doremi/Core/Include/EntityComponent/Components/PhysicsMaterialComponent.hpp>
#include <Doremi/Core/Include/EntityComponent/Components/RigidBodyComponent.hpp>
#include <Doremi/Core/Include/EntityComponent/Components/PotentialFieldComponent.hpp>
#include <Doremi/Core/Include/EntityComponent/Components/PlatformPatrolComponent.hpp>
// Events
#include <Doremi/Core/Include/EventHandler/Events/ChangeMenuState.hpp>
// Other stuff
#include <Doremi/Core/Include/TemplateCreator.hpp>
#include <Doremi/Core/Include/LevelLoaderClient.hpp>
#include <Doremi/Core/Include/EntityComponent/EntityFactory.hpp>
#include <Doremi/Core/Include/ScreenSpaceDrawer.hpp>

// Timer
#include <Doremi/Core/Include/Timing/TimerManager.hpp>
#include <Utility/Utilities/Include/Chrono/Timer.hpp>

// Third party

// Standard libraries
#include <exception>
#include <chrono>
#include <vector>
#include <iostream> //TODOLH remove once all the functionality is implemented in the menusystem

namespace Doremi
{
    using namespace Core;
    GameMain::GameMain() : m_sharedContext(nullptr), m_gameRunning(true) {}

    GameMain::~GameMain()
    {
        for(auto& manager : m_managers)
        {
            delete manager;
        }
        m_managers.clear();

        for(auto& manager : m_graphicalManagers)
        {
            delete manager;
        }
        m_graphicalManagers.clear();
    }

    void GameMain::Initialize()
    {
        TIME_FUNCTION_START

        using namespace Core;
        const DoremiEngine::Core::SharedContext& sharedContext = InitializeEngine(DoremiEngine::Core::EngineModuleEnum::ALL);
        m_sharedContext = &sharedContext;
        m_sharedContext->GetInputModule().SetExitFunction(std::bind(&GameMain::Stop, this));

        /* This starts the physics handler. Should not be done here, but since this is the general
        code dump, it'll work for now TODOJB*/
        EventHandlerClient::StartupEventHandlerClient();
        EntityHandlerClient::StartupEntityHandlerClient(sharedContext);
        PlayerHandlerClient::StartPlayerHandlerClient(sharedContext);
        InterpolationHandler::StartInterpolationHandler(sharedContext);
        AudioHandler::StartAudioHandler(sharedContext); // Needs to be stareted after event handler
        StateHandler::StartStateHandler(sharedContext);
        CameraHandler::StartCameraHandler(sharedContext);
        PositionCorrectionHandler::StartPositionCorrectionHandler(sharedContext);
        EntityFactory::StartupEntityFactory(sharedContext);
        PlayerSpawnerHandler::StartupPlayerSpawnerHandler(sharedContext);
        SkyBoxHandler::StartupSkyBoxHandler(sharedContext);
        ServerBrowserHandler::StartupServerBrowserHandler(sharedContext);
        SkeletalInformationHandler::StartSkeletalInformationHandler(sharedContext);

        // Initialize 2d drawer class
        m_screenRes = m_sharedContext->GetGraphicModule().GetSubModuleManager().GetDirectXManager().GetScreenResolution();
        m_screenSpaceDrawer = new ScreenSpaceDrawer(sharedContext, m_screenRes);

        // Create manager & add manager to list of managers
        AddToGraphicalManagerList(new PressureParticleGraphicManager(sharedContext));
        AddToGraphicalManagerList(new GraphicManager(sharedContext));
        AddToGraphicalManagerList(new SkeletalAnimationCoreManager(sharedContext));
        AddToManagerList(new AudioManager(sharedContext));
        NetworkManagerClient* t_netManager = new NetworkManagerClient(sharedContext);
        AddToManagerList(t_netManager);
        AddToServerBrowserList(t_netManager);
        AddToManagerList(new RigidTransformSyncManager(sharedContext));
        AddToManagerList(new PressureParticleManager(sharedContext));
        AddToManagerList(new LightManager(sharedContext));
        AddToManagerList(new JumpManager(sharedContext));
        AddToManagerList(new GravityManager(sharedContext));
        AddToManagerList(new MovementManagerClient(sharedContext)); // Must be after gravity/jump
        AddToManagerList(new CharacterControlSyncManager(sharedContext)); // Must be after movement
        AddToManagerList(new TriggerManager(sharedContext)); // TODOKO should only be needed on server
        AddToManagerList(new ExtraDrainSyncManager(sharedContext));
        AddToGraphicalManagerList(new GroundEffectManagerClient(sharedContext));

        MainMenuHandler::StartMainMenuHandler(sharedContext, m_screenRes);
        MainMenuHandler::GetInstance()->Initialize();

        TemplateCreator::GetInstance()->CreateTemplatesForClient(sharedContext);
        // BuildWorld(sharedContext);

        AudioHandler::GetInstance()->SetupContinuousRecording();
        AudioHandler::GetInstance()->StartContinuousRecording();
        AudioHandler::GetInstance()->SetupRepeatableRecording();

        TIME_FUNCTION_STOP
    }

    void GameMain::AddToManagerList(Manager* p_manager) { m_managers.push_back(p_manager); }

    void GameMain::AddToServerBrowserList(Manager* p_manager) { m_serverBrowserManagers.push_back(p_manager); }

    void GameMain::AddToGraphicalManagerList(Manager* p_manager) { m_graphicalManagers.push_back(p_manager); }

    void GameMain::BuildWorld(const DoremiEngine::Core::SharedContext& sharedContext)
    {
        // TIME_FUNCTION_START
        // Core::EntityFactory& t_entityFactory = *Core::EntityFactory::GetInstance();
        // Core::LevelLoaderClient t_levelLoader(sharedContext);

        // t_levelLoader.LoadLevel("Levels/IntroScene.drm");

        ////// Create platforms
        ////for(size_t i = 0; i < 1; i++)
        ////{
        ////    int entityID = t_entityFactory.CreateEntity(Blueprints::PlatformEntity, DirectX::XMFLOAT3(-165.75f, 4.6f, -103.74f), XMFLOAT4(0, 0, 0,
        /// 1));
        ////    DirectX::XMFLOAT3 position = DirectX::XMFLOAT3(-165.75f, 4.6f, -103.74f); // why not pass as parameter in above method?
        ////    DirectX::XMFLOAT4 orientation = XMFLOAT4(0, 0, 0, 1);

        ////    Core::PlatformPatrolComponent* t_platformPatrolComponent =
        ////        Core::EntityHandler::GetInstance().GetComponentFromStorage<Core::PlatformPatrolComponent>(entityID);
        ////    t_platformPatrolComponent->startPosition = position;
        ////    t_platformPatrolComponent->endPosition = DirectX::XMFLOAT3(position.x, position.y + 140, position.z);
        ////}

        //// Create an enemy spawner (only necessary to keep entityIDs aligned with server)
        // TIME_FUNCTION_STOP
    }

    void GameMain::Run()
    {
        TIME_FUNCTION_START
        // TODOCM remove for better timer
        // GameLoop is not currently set
        TimeHandler* t_timeHandler = TimeHandler::GetInstance();

        t_timeHandler->PreviousClock = std::chrono::high_resolution_clock::now();

        while(m_gameRunning)
        {
            // Tick time
            t_timeHandler->Tick();

            // Loop as many update-steps we will take this frame
            while(m_gameRunning && t_timeHandler->ShouldUpdateFrame())
            {
                // Update game based on state
                Update(t_timeHandler->UpdateStepLen);

                // Update interpolation transforms from snapshots
                Core::InterpolationHandler::GetInstance()->UpdateInterpolationTransforms();

                // Deliver events
                static_cast<Core::EventHandlerClient*>(Core::EventHandler::GetInstance())->DeliverEvents();

                // Update accumulator and gametime
                t_timeHandler->UpdateAccumulatorAndGameTime();
            }

            // Update alpha usd for inteprolation
            double alpha = t_timeHandler->GetFrameAlpha();

            // Interpolate the frames here
            Core::InterpolationHandler::GetInstance()->InterpolateFrame(alpha);

            // Update camera after we update positions
            CameraHandler::GetInstance()->UpdateDraw();

            Draw(t_timeHandler->Frame);
        }
        TIME_FUNCTION_STOP
    }

    void GameMain::UpdateGame(double p_deltaTime)
    {
        TIME_FUNCTION_START

        size_t length = m_managers.size();
        PlayerHandler::GetInstance()->Update(p_deltaTime);
        // AudioHandler::GetInstance()->Update(p_deltaTime);
        // Have all managers update
        for(size_t i = 0; i < length; i++)
        {
            Doremi::Core::TimerManager::GetInstance().StartTimer(m_managers.at(i)->GetName());
            m_managers.at(i)->Update(p_deltaTime);
            Doremi::Core::TimerManager::GetInstance().StopTimer(m_managers.at(i)->GetName());
        }

        CameraHandler::GetInstance()->UpdateInput(p_deltaTime);

        // PlayerHandler::GetInstance()->UpdateAddRemoveObjects();

        TIME_FUNCTION_STOP
    }

    void GameMain::UpdateServerBrowser(double p_deltaTime)
    {
        TIME_FUNCTION_START

        size_t length = m_serverBrowserManagers.size();
        PlayerHandler::GetInstance()->Update(p_deltaTime);

        // Have all managers update
        for(size_t i = 0; i < length; i++)
        {
            Doremi::Core::TimerManager::GetInstance().StartTimer(m_managers.at(i)->GetName());
            m_serverBrowserManagers.at(i)->Update(p_deltaTime);
            Doremi::Core::TimerManager::GetInstance().StopTimer(m_managers.at(i)->GetName());
        }

        TIME_FUNCTION_STOP
    }

    void GameMain::Update(double p_deltaTime)
    {
        TIME_FUNCTION_START
        static_cast<PlayerHandlerClient*>(Core::PlayerHandler::GetInstance())->UpdatePlayerInputs();

        AudioHandler::GetInstance()->Update(p_deltaTime);

        Core::DoremiGameStates t_state = Core::StateHandler::GetInstance()->GetState();

        switch(t_state)
        {
            case Core::DoremiGameStates::MAINMENU:
            {
                // Update Menu Logic
                MainMenuHandler::GetInstance()->Update(p_deltaTime);
                break;
            }
            case Core::DoremiGameStates::SERVER_BROWSER:
            {
                // TODOCM maybe only run network manager
                UpdateServerBrowser(p_deltaTime);

                ServerBrowserHandler::GetInstance()->Update(p_deltaTime);

                break;
            }
            case Core::DoremiGameStates::OPTIONS:
            {
                std::cout << "You clicked options button. It has no effect. State changed back to MAINMENU" << std::endl;
                // State is changed with events TODOXX should be removed from here once options is implemented
                Core::ChangeMenuState* menuEvent = new Core::ChangeMenuState();
                menuEvent->state = Core::DoremiGameStates::MAINMENU;
                Core::EventHandler::GetInstance()->BroadcastEvent(menuEvent);
                break;
            }
            case Core::DoremiGameStates::RUNGAME:
            {
                // Update Game logic
                UpdateGame(p_deltaTime);
                break;
            }
            case Core::DoremiGameStates::PAUSE:
            {
                // Update Pause Screen
                break;
            }

            case Core::DoremiGameStates::EXIT:
            {
                m_gameRunning = false;
                break;
            }
            default:
            {
                break;
            }
        }
        TIME_FUNCTION_STOP
    }

    void GameMain::DrawGame(double p_deltaTime)
    {
        TIME_FUNCTION_START
        const size_t length = m_graphicalManagers.size();
        for(size_t i = 0; i < length; i++)
        {
            Doremi::Core::TimerManager::GetInstance().StartTimer(m_graphicalManagers.at(i)->GetName());
            m_graphicalManagers.at(i)->Update(p_deltaTime);
            Doremi::Core::TimerManager::GetInstance().StopTimer(m_graphicalManagers.at(i)->GetName());
        }

        SkyBoxHandler::GetInstance()->Draw();
        TIME_FUNCTION_STOP
    }

    void GameMain::Draw(double p_deltaTime)
    {
        TIME_FUNCTION_START
        /** TODOLH Detta ska flyttas till en function som i updaten*/
        Core::DoremiGameStates t_state = Core::StateHandler::GetInstance()->GetState();
        m_sharedContext->GetGraphicModule().GetSubModuleManager().GetDirectXManager().BeginDraw();
        switch(t_state)
        {
            case Core::DoremiGameStates::RUNGAME:
                // Draw Game
                DrawGame(p_deltaTime);
                break;
            default:
                break;
        }

        // WE always draw 2d stuff
        m_screenSpaceDrawer->Draw();

        m_sharedContext->GetGraphicModule().GetSubModuleManager().GetDirectXManager().EndDraw();
        TIME_FUNCTION_STOP
    }

    void GameMain::Start()
    {
        try
        {
            TIME_FUNCTION_START
            Initialize();
            Run();
            TIME_FUNCTION_STOP
        }
        catch(...)
        {
            printf("Gamemain start exception.\n");
        }
        Doremi::Core::TimerManager::GetInstance().DumpData(*m_sharedContext);
    }

    void GameMain::Stop()
    {
        Core::ChangeMenuState* menuEvent = new Core::ChangeMenuState();
        menuEvent->state = Core::DoremiGameStates::EXIT;
        Core::EventHandler::GetInstance()->BroadcastEvent(menuEvent);
    }
}<commit_msg>Fixed copy paste error for managertiming<commit_after>// Project specific
#include <Game.hpp>
#include <Utility/DynamicLoader/Include/DynamicLoader.hpp>
/// Engine
// Core
#include <DoremiEngine/Core/Include/DoremiEngine.hpp>
#include <DoremiEngine/Core/Include/Subsystem/EngineModuleEnum.hpp>
#include <DoremiEngine/Core/Include/SharedContext.hpp>
// Physics
#include <DoremiEngine/Physics/Include/CharacterControlManager.hpp>
#include <DoremiEngine/Physics/Include/PhysicsModule.hpp>
#include <DoremiEngine/Physics/Include/RigidBodyManager.hpp>
#include <DoremiEngine/Physics/Include/FluidManager.hpp>
// AI
#include <DoremiEngine/AI/Include/AIModule.hpp>
#include <DoremiEngine/AI/Include/Interface/SubModule/PotentialFieldSubModule.hpp>
#include <DoremiEngine/AI/Include/Interface/PotentialField/PotentialFieldActor.hpp>
// GRAPHICS
#include <DoremiEngine/Graphic/Include/GraphicModule.hpp>
#include <DoremiEngine/Graphic/Include/Interface/Manager/DirectXManager.hpp>

// Inputmodule
#include <DoremiEngine/Input/Include/InputModule.hpp>

/// Game
// handlers
#include <Doremi/Core/Include/InterpolationHandler.hpp>
#include <Doremi/Core/Include/EventHandler/EventHandlerClient.hpp>
#include <Doremi/Core/Include/PlayerHandlerClient.hpp>
#include <Doremi/Core/Include/EntityComponent/EntityHandlerClient.hpp>
#include <Doremi/Core/Include/AudioHandler.hpp>
#include <Doremi/Core/Include/InputHandlerClient.hpp>
#include <Doremi/Core/Include/MenuClasses/MainMenuHandler.hpp>
#include <Doremi/Core/Include/NetworkEventSender.hpp>
#include <Doremi/Core/Include/CameraHandler.hpp>
#include <Doremi/Core/Include/PositionCorrectionHandler.hpp>
#include <Doremi/Core/Include/Handler/StateHandler.hpp>
#include <Doremi/Core/Include/PlayerSpawnerHandler.hpp>
#include <Doremi/Core/Include/TimeHandler.hpp>
#include <Doremi/Core/Include/MenuClasses/ServerBrowserHandler.hpp>
#include <Doremi/Core/Include/SkeletalInformationHandler.hpp>

// Managers
#include <Doremi/Core/Include/Manager/GraphicManager.hpp>
#include <Doremi/Core/Include/Manager/SkeletalAnimationCoreManager.hpp>
#include <Doremi/Core/Include/Network/NetworkManagerClient.hpp>
#include <Doremi/Core/Include/Manager/MovementManagerClient.hpp>
#include <Doremi/Core/Include/Manager/AudioManager.hpp>
#include <Doremi/Core/Include/Manager/AI/AIPathManager.hpp>
#include <Doremi/Core/Include/Manager/CharacterControlSyncManager.hpp>
#include <Doremi/Core/Include/Manager/RigidTransformSyncManager.hpp>
#include <Doremi/Core/Include/Manager/JumpManager.hpp>
#include <Doremi/Core/Include/SkyBoxHandler.hpp>
#include <Doremi/Core/Include/Manager/GravityManager.hpp>
#include <Doremi/Core/Include/Manager/PressureParticleGraphicManager.hpp>
#include <Doremi/Core/Include/Manager/PressureParticleManager.hpp>
#include <Doremi/Core/Include/Manager/LightManager.hpp>
#include <Doremi/Core/Include/Manager/TriggerManager.hpp>
#include <Doremi/Core/Include/Manager/ExtraDrainSyncManager.hpp>
#include <Doremi/Core/Include/Manager/GroundEffectManagerClient.hpp>
// Components
#include <Doremi/Core/Include/EntityComponent/Components/PhysicsMaterialComponent.hpp>
#include <Doremi/Core/Include/EntityComponent/Components/RigidBodyComponent.hpp>
#include <Doremi/Core/Include/EntityComponent/Components/PotentialFieldComponent.hpp>
#include <Doremi/Core/Include/EntityComponent/Components/PlatformPatrolComponent.hpp>
// Events
#include <Doremi/Core/Include/EventHandler/Events/ChangeMenuState.hpp>
// Other stuff
#include <Doremi/Core/Include/TemplateCreator.hpp>
#include <Doremi/Core/Include/LevelLoaderClient.hpp>
#include <Doremi/Core/Include/EntityComponent/EntityFactory.hpp>
#include <Doremi/Core/Include/ScreenSpaceDrawer.hpp>

// Timer
#include <Doremi/Core/Include/Timing/TimerManager.hpp>
#include <Utility/Utilities/Include/Chrono/Timer.hpp>

// Third party

// Standard libraries
#include <exception>
#include <chrono>
#include <vector>
#include <iostream> //TODOLH remove once all the functionality is implemented in the menusystem

namespace Doremi
{
    using namespace Core;
    GameMain::GameMain() : m_sharedContext(nullptr), m_gameRunning(true) {}

    GameMain::~GameMain()
    {
        for(auto& manager : m_managers)
        {
            delete manager;
        }
        m_managers.clear();

        for(auto& manager : m_graphicalManagers)
        {
            delete manager;
        }
        m_graphicalManagers.clear();
    }

    void GameMain::Initialize()
    {
        TIME_FUNCTION_START

        using namespace Core;
        const DoremiEngine::Core::SharedContext& sharedContext = InitializeEngine(DoremiEngine::Core::EngineModuleEnum::ALL);
        m_sharedContext = &sharedContext;
        m_sharedContext->GetInputModule().SetExitFunction(std::bind(&GameMain::Stop, this));

        /* This starts the physics handler. Should not be done here, but since this is the general
        code dump, it'll work for now TODOJB*/
        EventHandlerClient::StartupEventHandlerClient();
        EntityHandlerClient::StartupEntityHandlerClient(sharedContext);
        PlayerHandlerClient::StartPlayerHandlerClient(sharedContext);
        InterpolationHandler::StartInterpolationHandler(sharedContext);
        AudioHandler::StartAudioHandler(sharedContext); // Needs to be stareted after event handler
        StateHandler::StartStateHandler(sharedContext);
        CameraHandler::StartCameraHandler(sharedContext);
        PositionCorrectionHandler::StartPositionCorrectionHandler(sharedContext);
        EntityFactory::StartupEntityFactory(sharedContext);
        PlayerSpawnerHandler::StartupPlayerSpawnerHandler(sharedContext);
        SkyBoxHandler::StartupSkyBoxHandler(sharedContext);
        ServerBrowserHandler::StartupServerBrowserHandler(sharedContext);
        SkeletalInformationHandler::StartSkeletalInformationHandler(sharedContext);

        // Initialize 2d drawer class
        m_screenRes = m_sharedContext->GetGraphicModule().GetSubModuleManager().GetDirectXManager().GetScreenResolution();
        m_screenSpaceDrawer = new ScreenSpaceDrawer(sharedContext, m_screenRes);

        // Create manager & add manager to list of managers
        AddToGraphicalManagerList(new PressureParticleGraphicManager(sharedContext));
        AddToGraphicalManagerList(new GraphicManager(sharedContext));
        AddToGraphicalManagerList(new SkeletalAnimationCoreManager(sharedContext));
        AddToManagerList(new AudioManager(sharedContext));
        NetworkManagerClient* t_netManager = new NetworkManagerClient(sharedContext);
        AddToManagerList(t_netManager);
        AddToServerBrowserList(t_netManager);
        AddToManagerList(new RigidTransformSyncManager(sharedContext));
        AddToManagerList(new PressureParticleManager(sharedContext));
        AddToManagerList(new LightManager(sharedContext));
        AddToManagerList(new JumpManager(sharedContext));
        AddToManagerList(new GravityManager(sharedContext));
        AddToManagerList(new MovementManagerClient(sharedContext)); // Must be after gravity/jump
        AddToManagerList(new CharacterControlSyncManager(sharedContext)); // Must be after movement
        AddToManagerList(new TriggerManager(sharedContext)); // TODOKO should only be needed on server
        AddToManagerList(new ExtraDrainSyncManager(sharedContext));
        AddToGraphicalManagerList(new GroundEffectManagerClient(sharedContext));

        MainMenuHandler::StartMainMenuHandler(sharedContext, m_screenRes);
        MainMenuHandler::GetInstance()->Initialize();

        TemplateCreator::GetInstance()->CreateTemplatesForClient(sharedContext);
        // BuildWorld(sharedContext);

        AudioHandler::GetInstance()->SetupContinuousRecording();
        AudioHandler::GetInstance()->StartContinuousRecording();
        AudioHandler::GetInstance()->SetupRepeatableRecording();

        TIME_FUNCTION_STOP
    }

    void GameMain::AddToManagerList(Manager* p_manager) { m_managers.push_back(p_manager); }

    void GameMain::AddToServerBrowserList(Manager* p_manager) { m_serverBrowserManagers.push_back(p_manager); }

    void GameMain::AddToGraphicalManagerList(Manager* p_manager) { m_graphicalManagers.push_back(p_manager); }

    void GameMain::BuildWorld(const DoremiEngine::Core::SharedContext& sharedContext)
    {
        // TIME_FUNCTION_START
        // Core::EntityFactory& t_entityFactory = *Core::EntityFactory::GetInstance();
        // Core::LevelLoaderClient t_levelLoader(sharedContext);

        // t_levelLoader.LoadLevel("Levels/IntroScene.drm");

        ////// Create platforms
        ////for(size_t i = 0; i < 1; i++)
        ////{
        ////    int entityID = t_entityFactory.CreateEntity(Blueprints::PlatformEntity, DirectX::XMFLOAT3(-165.75f, 4.6f, -103.74f), XMFLOAT4(0, 0, 0,
        /// 1));
        ////    DirectX::XMFLOAT3 position = DirectX::XMFLOAT3(-165.75f, 4.6f, -103.74f); // why not pass as parameter in above method?
        ////    DirectX::XMFLOAT4 orientation = XMFLOAT4(0, 0, 0, 1);

        ////    Core::PlatformPatrolComponent* t_platformPatrolComponent =
        ////        Core::EntityHandler::GetInstance().GetComponentFromStorage<Core::PlatformPatrolComponent>(entityID);
        ////    t_platformPatrolComponent->startPosition = position;
        ////    t_platformPatrolComponent->endPosition = DirectX::XMFLOAT3(position.x, position.y + 140, position.z);
        ////}

        //// Create an enemy spawner (only necessary to keep entityIDs aligned with server)
        // TIME_FUNCTION_STOP
    }

    void GameMain::Run()
    {
        TIME_FUNCTION_START
        // TODOCM remove for better timer
        // GameLoop is not currently set
        TimeHandler* t_timeHandler = TimeHandler::GetInstance();

        t_timeHandler->PreviousClock = std::chrono::high_resolution_clock::now();

        while(m_gameRunning)
        {
            // Tick time
            t_timeHandler->Tick();

            // Loop as many update-steps we will take this frame
            while(m_gameRunning && t_timeHandler->ShouldUpdateFrame())
            {
                // Update game based on state
                Update(t_timeHandler->UpdateStepLen);

                // Update interpolation transforms from snapshots
                Core::InterpolationHandler::GetInstance()->UpdateInterpolationTransforms();

                // Deliver events
                static_cast<Core::EventHandlerClient*>(Core::EventHandler::GetInstance())->DeliverEvents();

                // Update accumulator and gametime
                t_timeHandler->UpdateAccumulatorAndGameTime();
            }

            // Update alpha usd for inteprolation
            double alpha = t_timeHandler->GetFrameAlpha();

            // Interpolate the frames here
            Core::InterpolationHandler::GetInstance()->InterpolateFrame(alpha);

            // Update camera after we update positions
            CameraHandler::GetInstance()->UpdateDraw();

            Draw(t_timeHandler->Frame);
        }
        TIME_FUNCTION_STOP
    }

    void GameMain::UpdateGame(double p_deltaTime)
    {
        TIME_FUNCTION_START

        size_t length = m_managers.size();
        PlayerHandler::GetInstance()->Update(p_deltaTime);
        // AudioHandler::GetInstance()->Update(p_deltaTime);
        // Have all managers update
        for(size_t i = 0; i < length; i++)
        {
            Doremi::Core::TimerManager::GetInstance().StartTimer(m_managers.at(i)->GetName());
            m_managers.at(i)->Update(p_deltaTime);
            Doremi::Core::TimerManager::GetInstance().StopTimer(m_managers.at(i)->GetName());
        }

        CameraHandler::GetInstance()->UpdateInput(p_deltaTime);

        // PlayerHandler::GetInstance()->UpdateAddRemoveObjects();

        TIME_FUNCTION_STOP
    }

    void GameMain::UpdateServerBrowser(double p_deltaTime)
    {
        TIME_FUNCTION_START

        size_t length = m_serverBrowserManagers.size();
        PlayerHandler::GetInstance()->Update(p_deltaTime);

        // Have all managers update
        for(size_t i = 0; i < length; i++)
        {
            Doremi::Core::TimerManager::GetInstance().StartTimer(m_serverBrowserManagers.at(i)->GetName());
            m_serverBrowserManagers.at(i)->Update(p_deltaTime);
            Doremi::Core::TimerManager::GetInstance().StopTimer(m_serverBrowserManagers.at(i)->GetName());
        }

        TIME_FUNCTION_STOP
    }

    void GameMain::Update(double p_deltaTime)
    {
        TIME_FUNCTION_START
        static_cast<PlayerHandlerClient*>(Core::PlayerHandler::GetInstance())->UpdatePlayerInputs();

        AudioHandler::GetInstance()->Update(p_deltaTime);

        Core::DoremiGameStates t_state = Core::StateHandler::GetInstance()->GetState();

        switch(t_state)
        {
            case Core::DoremiGameStates::MAINMENU:
            {
                // Update Menu Logic
                MainMenuHandler::GetInstance()->Update(p_deltaTime);
                break;
            }
            case Core::DoremiGameStates::SERVER_BROWSER:
            {
                // TODOCM maybe only run network manager
                UpdateServerBrowser(p_deltaTime);

                ServerBrowserHandler::GetInstance()->Update(p_deltaTime);

                break;
            }
            case Core::DoremiGameStates::OPTIONS:
            {
                std::cout << "You clicked options button. It has no effect. State changed back to MAINMENU" << std::endl;
                // State is changed with events TODOXX should be removed from here once options is implemented
                Core::ChangeMenuState* menuEvent = new Core::ChangeMenuState();
                menuEvent->state = Core::DoremiGameStates::MAINMENU;
                Core::EventHandler::GetInstance()->BroadcastEvent(menuEvent);
                break;
            }
            case Core::DoremiGameStates::RUNGAME:
            {
                // Update Game logic
                UpdateGame(p_deltaTime);
                break;
            }
            case Core::DoremiGameStates::PAUSE:
            {
                // Update Pause Screen
                break;
            }

            case Core::DoremiGameStates::EXIT:
            {
                m_gameRunning = false;
                break;
            }
            default:
            {
                break;
            }
        }
        TIME_FUNCTION_STOP
    }

    void GameMain::DrawGame(double p_deltaTime)
    {
        TIME_FUNCTION_START
        const size_t length = m_graphicalManagers.size();
        for(size_t i = 0; i < length; i++)
        {
            Doremi::Core::TimerManager::GetInstance().StartTimer(m_graphicalManagers.at(i)->GetName());
            m_graphicalManagers.at(i)->Update(p_deltaTime);
            Doremi::Core::TimerManager::GetInstance().StopTimer(m_graphicalManagers.at(i)->GetName());
        }

        SkyBoxHandler::GetInstance()->Draw();
        TIME_FUNCTION_STOP
    }

    void GameMain::Draw(double p_deltaTime)
    {
        TIME_FUNCTION_START
        /** TODOLH Detta ska flyttas till en function som i updaten*/
        Core::DoremiGameStates t_state = Core::StateHandler::GetInstance()->GetState();
        m_sharedContext->GetGraphicModule().GetSubModuleManager().GetDirectXManager().BeginDraw();
        switch(t_state)
        {
            case Core::DoremiGameStates::RUNGAME:
                // Draw Game
                DrawGame(p_deltaTime);
                break;
            default:
                break;
        }

        // WE always draw 2d stuff
        m_screenSpaceDrawer->Draw();

        m_sharedContext->GetGraphicModule().GetSubModuleManager().GetDirectXManager().EndDraw();
        TIME_FUNCTION_STOP
    }

    void GameMain::Start()
    {
        try
        {
            TIME_FUNCTION_START
            Initialize();
            Run();
            TIME_FUNCTION_STOP
        }
        catch(...)
        {
            printf("Gamemain start exception.\n");
        }
        Doremi::Core::TimerManager::GetInstance().DumpData(*m_sharedContext);
    }

    void GameMain::Stop()
    {
        Core::ChangeMenuState* menuEvent = new Core::ChangeMenuState();
        menuEvent->state = Core::DoremiGameStates::EXIT;
        Core::EventHandler::GetInstance()->BroadcastEvent(menuEvent);
    }
}<|endoftext|>