wrenpp/examples/math_vector/main.cpp
King_DuckZ 72da0b8d87 Fix build when std::string is a lone parameter
The "any tuple-like" thing was nice but
it was confusing when passing for example
a std::string, which is a typedef to a
tuple-like thing. Making a custom
ConstructorParameters struct is more clear
both to users and to the compiler.
2024-05-24 17:12:04 +02:00

134 lines
4.2 KiB
C++

/* Copyright 2020-2022, Michele Santullo
* This file is part of wrenpp.
*
* Wrenpp is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Wrenpp 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
*/
#include "wrenpp/def_configuration.hpp"
#include "wrenpp/vm_fun.hpp"
#include "wrenpp/callback_manager.hpp"
#include "wrenpp/class_manager.hpp"
#include <string_view>
#include <algorithm>
#include <iostream>
namespace {
constexpr std::string_view g_math_vector_src{
"foreign class MathVector {" R"script(
construct new() {}
construct new(value) {}
construct new(x, y, z) {}
foreign x
foreign y
foreign z
foreign x=(value)
foreign y=(value)
foreign z=(value)
foreign static base_x()
}
)script"};
constexpr const char g_test_script[] =
R"script(import "math_vector" for MathVector
var vec1 = MathVector.new(15.0)
var vec2 = MathVector.new(10.0, 20.0, 30.0)
var vec3 = MathVector.new()
System.print("vec1 constructed from single value: <%(vec1.x), %(vec1.y), %(vec1.z)>")
System.print("vec2 constructed from three values: <%(vec2.x), %(vec2.y), %(vec2.z)>")
System.print("vec3 default constructed: <%(vec3.x), %(vec3.y), %(vec3.z)>")
vec3.x = 3.5
vec3.y = vec2.x / vec2.z
vec3.z = vec1.x + vec2.y / 4.0
System.print("vec3 modified by scripting: <%(vec3.x), %(vec3.y), %(vec3.z)>")
var vec_base_x = MathVector.base_x()
System.print("vec_base_x modified by scripting: <%(vec_base_x.x), %(vec_base_x.y), %(vec_base_x.z)>")
)script";
template <typename T>
class Vector {
public:
Vector() = default;
explicit Vector (T value) :
m_x(value), m_y(value), m_z(value)
{}
Vector (T x, T y, T z) :
m_x(x), m_y(y), m_z(z)
{}
~Vector() noexcept = default;
T x() const { return m_x; }
T y() const { return m_y; }
T z() const { return m_z; }
void set_x(T x) { m_x = x; }
void set_y(T y) { m_y = y; }
void set_z(T z) { m_z = z; }
static Vector base_x() { return {1.0, 0.0, 0.0}; }
private:
T m_x{}, m_y{}, m_z{};
};
class MyConf : public wren::DefConfiguration {
public:
char* load_module_fn(wren::VM* vm, std::string_view module_name) {
if (module_name == "math_vector") {
constexpr const std::size_t buff_sz = g_math_vector_src.size() + 1;
char* const buff = new char[buff_sz];
std::copy(g_math_vector_src.cbegin(), g_math_vector_src.cend(), buff);
buff[buff_sz - 1] = '\0';
return buff;
}
return nullptr;
}
void load_module_complete_fn(wren::VM*, std::string_view, char* buffer) {
delete[] buffer;
}
};
} //unnamed namespace
int main() {
using wren::make_function_bindable;
using wren::make_foreign_class;
using wren::ConstructorParameters;
MyConf conf;
wren::VM vm(&conf, nullptr);
vm.callback_manager()
.add_callback(false, "math_vector", "MathVector", "x=(_)", make_function_bindable<&Vector<double>::set_x>)
.add_callback(false, "math_vector", "MathVector", "y=(_)", make_function_bindable<&Vector<double>::set_y>)
.add_callback(false, "math_vector", "MathVector", "z=(_)", make_function_bindable<&Vector<double>::set_z>)
.add_callback(false, "math_vector", "MathVector", "x", make_function_bindable<&Vector<double>::x>)
.add_callback(false, "math_vector", "MathVector", "y", make_function_bindable<&Vector<double>::y>)
.add_callback(false, "math_vector", "MathVector", "z", make_function_bindable<&Vector<double>::z>)
.add_callback(true, "math_vector", "MathVector", "base_x()", make_function_bindable<&Vector<double>::base_x>);
vm.class_manager()
.add_class_maker("math_vector", "MathVector", make_foreign_class<Vector<double>,
double, //single value constructor
ConstructorParameters<double, double, double>, //x,y,z constructor
ConstructorParameters<> //default constructor
>);
vm.interpret("main", g_test_script);
return 0;
}