Replace bindgins to work with extensions
This commit is contained in:
committed by
Bastiaan Olij
parent
ee70866894
commit
e4ed48976a
@@ -1,604 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* AABB.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "AABB.hpp"
|
||||
#include "Plane.hpp"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace godot {
|
||||
|
||||
bool AABB::intersects(const AABB &p_aabb) const {
|
||||
if (position.x >= (p_aabb.position.x + p_aabb.size.x))
|
||||
return false;
|
||||
if ((position.x + size.x) <= p_aabb.position.x)
|
||||
return false;
|
||||
if (position.y >= (p_aabb.position.y + p_aabb.size.y))
|
||||
return false;
|
||||
if ((position.y + size.y) <= p_aabb.position.y)
|
||||
return false;
|
||||
if (position.z >= (p_aabb.position.z + p_aabb.size.z))
|
||||
return false;
|
||||
if ((position.z + size.z) <= p_aabb.position.z)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::intersects_inclusive(const AABB &p_aabb) const {
|
||||
if (position.x > (p_aabb.position.x + p_aabb.size.x))
|
||||
return false;
|
||||
if ((position.x + size.x) < p_aabb.position.x)
|
||||
return false;
|
||||
if (position.y > (p_aabb.position.y + p_aabb.size.y))
|
||||
return false;
|
||||
if ((position.y + size.y) < p_aabb.position.y)
|
||||
return false;
|
||||
if (position.z > (p_aabb.position.z + p_aabb.size.z))
|
||||
return false;
|
||||
if ((position.z + size.z) < p_aabb.position.z)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::encloses(const AABB &p_aabb) const {
|
||||
Vector3 src_min = position;
|
||||
Vector3 src_max = position + size;
|
||||
Vector3 dst_min = p_aabb.position;
|
||||
Vector3 dst_max = p_aabb.position + p_aabb.size;
|
||||
|
||||
return (
|
||||
(src_min.x <= dst_min.x) &&
|
||||
(src_max.x > dst_max.x) &&
|
||||
(src_min.y <= dst_min.y) &&
|
||||
(src_max.y > dst_max.y) &&
|
||||
(src_min.z <= dst_min.z) &&
|
||||
(src_max.z > dst_max.z));
|
||||
}
|
||||
|
||||
Vector3 AABB::get_support(const Vector3 &p_normal) const {
|
||||
Vector3 half_extents = size * 0.5;
|
||||
Vector3 ofs = position + half_extents;
|
||||
|
||||
return Vector3(
|
||||
(p_normal.x > 0) ? -half_extents.x : half_extents.x,
|
||||
(p_normal.y > 0) ? -half_extents.y : half_extents.y,
|
||||
(p_normal.z > 0) ? -half_extents.z : half_extents.z) +
|
||||
ofs;
|
||||
}
|
||||
|
||||
Vector3 AABB::get_endpoint(int p_point) const {
|
||||
switch (p_point) {
|
||||
case 0:
|
||||
return Vector3(position.x, position.y, position.z);
|
||||
case 1:
|
||||
return Vector3(position.x, position.y, position.z + size.z);
|
||||
case 2:
|
||||
return Vector3(position.x, position.y + size.y, position.z);
|
||||
case 3:
|
||||
return Vector3(position.x, position.y + size.y, position.z + size.z);
|
||||
case 4:
|
||||
return Vector3(position.x + size.x, position.y, position.z);
|
||||
case 5:
|
||||
return Vector3(position.x + size.x, position.y, position.z + size.z);
|
||||
case 6:
|
||||
return Vector3(position.x + size.x, position.y + size.y, position.z);
|
||||
case 7:
|
||||
return Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
||||
};
|
||||
|
||||
ERR_FAIL_V(Vector3());
|
||||
}
|
||||
|
||||
bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count) const {
|
||||
Vector3 half_extents = size * 0.5;
|
||||
Vector3 ofs = position + half_extents;
|
||||
|
||||
for (int i = 0; i < p_plane_count; i++) {
|
||||
const Plane &p = p_planes[i];
|
||||
Vector3 point(
|
||||
(p.normal.x > 0) ? -half_extents.x : half_extents.x,
|
||||
(p.normal.y > 0) ? -half_extents.y : half_extents.y,
|
||||
(p.normal.z > 0) ? -half_extents.z : half_extents.z);
|
||||
point += ofs;
|
||||
if (p.is_point_over(point))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::has_point(const Vector3 &p_point) const {
|
||||
if (p_point.x < position.x)
|
||||
return false;
|
||||
if (p_point.y < position.y)
|
||||
return false;
|
||||
if (p_point.z < position.z)
|
||||
return false;
|
||||
if (p_point.x > position.x + size.x)
|
||||
return false;
|
||||
if (p_point.y > position.y + size.y)
|
||||
return false;
|
||||
if (p_point.z > position.z + size.z)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AABB::expand_to(const Vector3 &p_vector) {
|
||||
Vector3 begin = position;
|
||||
Vector3 end = position + size;
|
||||
|
||||
if (p_vector.x < begin.x)
|
||||
begin.x = p_vector.x;
|
||||
if (p_vector.y < begin.y)
|
||||
begin.y = p_vector.y;
|
||||
if (p_vector.z < begin.z)
|
||||
begin.z = p_vector.z;
|
||||
|
||||
if (p_vector.x > end.x)
|
||||
end.x = p_vector.x;
|
||||
if (p_vector.y > end.y)
|
||||
end.y = p_vector.y;
|
||||
if (p_vector.z > end.z)
|
||||
end.z = p_vector.z;
|
||||
|
||||
position = begin;
|
||||
size = end - begin;
|
||||
}
|
||||
|
||||
void AABB::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const {
|
||||
Vector3 half_extents(size.x * 0.5, size.y * 0.5, size.z * 0.5);
|
||||
Vector3 center(position.x + half_extents.x, position.y + half_extents.y, position.z + half_extents.z);
|
||||
|
||||
real_t length = p_plane.normal.abs().dot(half_extents);
|
||||
real_t distance = p_plane.distance_to(center);
|
||||
r_min = distance - length;
|
||||
r_max = distance + length;
|
||||
}
|
||||
|
||||
real_t AABB::get_longest_axis_size() const {
|
||||
real_t max_size = size.x;
|
||||
|
||||
if (size.y > max_size) {
|
||||
max_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z > max_size) {
|
||||
max_size = size.z;
|
||||
}
|
||||
|
||||
return max_size;
|
||||
}
|
||||
|
||||
real_t AABB::get_shortest_axis_size() const {
|
||||
real_t max_size = size.x;
|
||||
|
||||
if (size.y < max_size) {
|
||||
max_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z < max_size) {
|
||||
max_size = size.z;
|
||||
}
|
||||
|
||||
return max_size;
|
||||
}
|
||||
|
||||
bool AABB::smits_intersect_ray(const Vector3 &from, const Vector3 &dir, real_t t0, real_t t1) const {
|
||||
real_t divx = 1.0 / dir.x;
|
||||
real_t divy = 1.0 / dir.y;
|
||||
real_t divz = 1.0 / dir.z;
|
||||
|
||||
Vector3 upbound = position + size;
|
||||
real_t tmin, tmax, tymin, tymax, tzmin, tzmax;
|
||||
if (dir.x >= 0) {
|
||||
tmin = (position.x - from.x) * divx;
|
||||
tmax = (upbound.x - from.x) * divx;
|
||||
} else {
|
||||
tmin = (upbound.x - from.x) * divx;
|
||||
tmax = (position.x - from.x) * divx;
|
||||
}
|
||||
if (dir.y >= 0) {
|
||||
tymin = (position.y - from.y) * divy;
|
||||
tymax = (upbound.y - from.y) * divy;
|
||||
} else {
|
||||
tymin = (upbound.y - from.y) * divy;
|
||||
tymax = (position.y - from.y) * divy;
|
||||
}
|
||||
if ((tmin > tymax) || (tymin > tmax))
|
||||
return false;
|
||||
if (tymin > tmin)
|
||||
tmin = tymin;
|
||||
if (tymax < tmax)
|
||||
tmax = tymax;
|
||||
if (dir.z >= 0) {
|
||||
tzmin = (position.z - from.z) * divz;
|
||||
tzmax = (upbound.z - from.z) * divz;
|
||||
} else {
|
||||
tzmin = (upbound.z - from.z) * divz;
|
||||
tzmax = (position.z - from.z) * divz;
|
||||
}
|
||||
if ((tmin > tzmax) || (tzmin > tmax))
|
||||
return false;
|
||||
if (tzmin > tmin)
|
||||
tmin = tzmin;
|
||||
if (tzmax < tmax)
|
||||
tmax = tzmax;
|
||||
return ((tmin < t1) && (tmax > t0));
|
||||
}
|
||||
|
||||
void AABB::grow_by(real_t p_amount) {
|
||||
position.x -= p_amount;
|
||||
position.y -= p_amount;
|
||||
position.z -= p_amount;
|
||||
size.x += 2.0 * p_amount;
|
||||
size.y += 2.0 * p_amount;
|
||||
size.z += 2.0 * p_amount;
|
||||
}
|
||||
|
||||
real_t AABB::get_area() const {
|
||||
return size.x * size.y * size.z;
|
||||
}
|
||||
|
||||
bool AABB::operator==(const AABB &p_rval) const {
|
||||
return ((position == p_rval.position) && (size == p_rval.size));
|
||||
}
|
||||
bool AABB::operator!=(const AABB &p_rval) const {
|
||||
return ((position != p_rval.position) || (size != p_rval.size));
|
||||
}
|
||||
|
||||
void AABB::merge_with(const AABB &p_aabb) {
|
||||
Vector3 beg_1, beg_2;
|
||||
Vector3 end_1, end_2;
|
||||
Vector3 min, max;
|
||||
|
||||
beg_1 = position;
|
||||
beg_2 = p_aabb.position;
|
||||
end_1 = Vector3(size.x, size.y, size.z) + beg_1;
|
||||
end_2 = Vector3(p_aabb.size.x, p_aabb.size.y, p_aabb.size.z) + beg_2;
|
||||
|
||||
min.x = (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x;
|
||||
min.y = (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y;
|
||||
min.z = (beg_1.z < beg_2.z) ? beg_1.z : beg_2.z;
|
||||
|
||||
max.x = (end_1.x > end_2.x) ? end_1.x : end_2.x;
|
||||
max.y = (end_1.y > end_2.y) ? end_1.y : end_2.y;
|
||||
max.z = (end_1.z > end_2.z) ? end_1.z : end_2.z;
|
||||
|
||||
position = min;
|
||||
size = max - min;
|
||||
}
|
||||
|
||||
AABB AABB::intersection(const AABB &p_aabb) const {
|
||||
Vector3 src_min = position;
|
||||
Vector3 src_max = position + size;
|
||||
Vector3 dst_min = p_aabb.position;
|
||||
Vector3 dst_max = p_aabb.position + p_aabb.size;
|
||||
|
||||
Vector3 min, max;
|
||||
|
||||
if (src_min.x > dst_max.x || src_max.x < dst_min.x)
|
||||
return AABB();
|
||||
else {
|
||||
min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x;
|
||||
max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x;
|
||||
}
|
||||
|
||||
if (src_min.y > dst_max.y || src_max.y < dst_min.y)
|
||||
return AABB();
|
||||
else {
|
||||
min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y;
|
||||
max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y;
|
||||
}
|
||||
|
||||
if (src_min.z > dst_max.z || src_max.z < dst_min.z)
|
||||
return AABB();
|
||||
else {
|
||||
min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z;
|
||||
max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z;
|
||||
}
|
||||
|
||||
return AABB(min, max - min);
|
||||
}
|
||||
|
||||
bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const {
|
||||
Vector3 c1, c2;
|
||||
Vector3 end = position + size;
|
||||
real_t near = -1e20;
|
||||
real_t far = 1e20;
|
||||
int axis = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (p_dir[i] == 0) {
|
||||
if ((p_from[i] < position[i]) || (p_from[i] > end[i])) {
|
||||
return false;
|
||||
}
|
||||
} else { // ray not parallel to planes in this direction
|
||||
c1[i] = (position[i] - p_from[i]) / p_dir[i];
|
||||
c2[i] = (end[i] - p_from[i]) / p_dir[i];
|
||||
|
||||
if (c1[i] > c2[i]) {
|
||||
std::swap(c1, c2);
|
||||
}
|
||||
if (c1[i] > near) {
|
||||
near = c1[i];
|
||||
axis = i;
|
||||
}
|
||||
if (c2[i] < far) {
|
||||
far = c2[i];
|
||||
}
|
||||
if ((near > far) || (far < 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r_clip)
|
||||
*r_clip = c1;
|
||||
if (r_normal) {
|
||||
*r_normal = Vector3();
|
||||
(*r_normal)[axis] = p_dir[axis] ? -1 : 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const {
|
||||
real_t min = 0, max = 1;
|
||||
int axis = 0;
|
||||
real_t sign = 0;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
real_t seg_from = p_from[i];
|
||||
real_t seg_to = p_to[i];
|
||||
real_t box_begin = position[i];
|
||||
real_t box_end = box_begin + size[i];
|
||||
real_t cmin, cmax;
|
||||
real_t csign;
|
||||
|
||||
if (seg_from < seg_to) {
|
||||
if (seg_from > box_end || seg_to < box_begin)
|
||||
return false;
|
||||
real_t length = seg_to - seg_from;
|
||||
cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
|
||||
cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
|
||||
csign = -1.0;
|
||||
|
||||
} else {
|
||||
if (seg_to > box_end || seg_from < box_begin)
|
||||
return false;
|
||||
real_t length = seg_to - seg_from;
|
||||
cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
|
||||
cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
|
||||
csign = 1.0;
|
||||
}
|
||||
|
||||
if (cmin > min) {
|
||||
min = cmin;
|
||||
axis = i;
|
||||
sign = csign;
|
||||
}
|
||||
if (cmax < max)
|
||||
max = cmax;
|
||||
if (max < min)
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 rel = p_to - p_from;
|
||||
|
||||
if (r_normal) {
|
||||
Vector3 normal;
|
||||
normal[axis] = sign;
|
||||
*r_normal = normal;
|
||||
}
|
||||
|
||||
if (r_clip)
|
||||
*r_clip = p_from + rel * min;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::intersects_plane(const Plane &p_plane) const {
|
||||
Vector3 points[8] = {
|
||||
Vector3(position.x, position.y, position.z),
|
||||
Vector3(position.x, position.y, position.z + size.z),
|
||||
Vector3(position.x, position.y + size.y, position.z),
|
||||
Vector3(position.x, position.y + size.y, position.z + size.z),
|
||||
Vector3(position.x + size.x, position.y, position.z),
|
||||
Vector3(position.x + size.x, position.y, position.z + size.z),
|
||||
Vector3(position.x + size.x, position.y + size.y, position.z),
|
||||
Vector3(position.x + size.x, position.y + size.y, position.z + size.z),
|
||||
};
|
||||
|
||||
bool over = false;
|
||||
bool under = false;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (p_plane.distance_to(points[i]) > 0)
|
||||
over = true;
|
||||
else
|
||||
under = true;
|
||||
}
|
||||
|
||||
return under && over;
|
||||
}
|
||||
|
||||
Vector3 AABB::get_longest_axis() const {
|
||||
Vector3 axis(1, 0, 0);
|
||||
real_t max_size = size.x;
|
||||
|
||||
if (size.y > max_size) {
|
||||
axis = Vector3(0, 1, 0);
|
||||
max_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z > max_size) {
|
||||
axis = Vector3(0, 0, 1);
|
||||
max_size = size.z;
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
int AABB::get_longest_axis_index() const {
|
||||
int axis = 0;
|
||||
real_t max_size = size.x;
|
||||
|
||||
if (size.y > max_size) {
|
||||
axis = 1;
|
||||
max_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z > max_size) {
|
||||
axis = 2;
|
||||
max_size = size.z;
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
Vector3 AABB::get_shortest_axis() const {
|
||||
Vector3 axis(1, 0, 0);
|
||||
real_t max_size = size.x;
|
||||
|
||||
if (size.y < max_size) {
|
||||
axis = Vector3(0, 1, 0);
|
||||
max_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z < max_size) {
|
||||
axis = Vector3(0, 0, 1);
|
||||
max_size = size.z;
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
int AABB::get_shortest_axis_index() const {
|
||||
int axis = 0;
|
||||
real_t max_size = size.x;
|
||||
|
||||
if (size.y < max_size) {
|
||||
axis = 1;
|
||||
max_size = size.y;
|
||||
}
|
||||
|
||||
if (size.z < max_size) {
|
||||
axis = 2;
|
||||
max_size = size.z;
|
||||
}
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
AABB AABB::merge(const AABB &p_with) const {
|
||||
AABB aabb = *this;
|
||||
aabb.merge_with(p_with);
|
||||
return aabb;
|
||||
}
|
||||
AABB AABB::expand(const Vector3 &p_vector) const {
|
||||
AABB aabb = *this;
|
||||
aabb.expand_to(p_vector);
|
||||
return aabb;
|
||||
}
|
||||
AABB AABB::grow(real_t p_by) const {
|
||||
AABB aabb = *this;
|
||||
aabb.grow_by(p_by);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const {
|
||||
ERR_FAIL_INDEX(p_edge, 12);
|
||||
switch (p_edge) {
|
||||
case 0: {
|
||||
r_from = Vector3(position.x + size.x, position.y, position.z);
|
||||
r_to = Vector3(position.x, position.y, position.z);
|
||||
} break;
|
||||
case 1: {
|
||||
r_from = Vector3(position.x + size.x, position.y, position.z + size.z);
|
||||
r_to = Vector3(position.x + size.x, position.y, position.z);
|
||||
} break;
|
||||
case 2: {
|
||||
r_from = Vector3(position.x, position.y, position.z + size.z);
|
||||
r_to = Vector3(position.x + size.x, position.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
case 3: {
|
||||
r_from = Vector3(position.x, position.y, position.z);
|
||||
r_to = Vector3(position.x, position.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
case 4: {
|
||||
r_from = Vector3(position.x, position.y + size.y, position.z);
|
||||
r_to = Vector3(position.x + size.x, position.y + size.y, position.z);
|
||||
} break;
|
||||
case 5: {
|
||||
r_from = Vector3(position.x + size.x, position.y + size.y, position.z);
|
||||
r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
||||
} break;
|
||||
case 6: {
|
||||
r_from = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
||||
r_to = Vector3(position.x, position.y + size.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
case 7: {
|
||||
r_from = Vector3(position.x, position.y + size.y, position.z + size.z);
|
||||
r_to = Vector3(position.x, position.y + size.y, position.z);
|
||||
|
||||
} break;
|
||||
case 8: {
|
||||
r_from = Vector3(position.x, position.y, position.z + size.z);
|
||||
r_to = Vector3(position.x, position.y + size.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
case 9: {
|
||||
r_from = Vector3(position.x, position.y, position.z);
|
||||
r_to = Vector3(position.x, position.y + size.y, position.z);
|
||||
|
||||
} break;
|
||||
case 10: {
|
||||
r_from = Vector3(position.x + size.x, position.y, position.z);
|
||||
r_to = Vector3(position.x + size.x, position.y + size.y, position.z);
|
||||
|
||||
} break;
|
||||
case 11: {
|
||||
r_from = Vector3(position.x + size.x, position.y, position.z + size.z);
|
||||
r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
AABB::operator String() const {
|
||||
return String() + position + " - " + size;
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,226 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Array.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Array.hpp"
|
||||
#include "GodotGlobal.hpp"
|
||||
#include "Variant.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace godot {
|
||||
|
||||
class Object;
|
||||
|
||||
Array::Array() {
|
||||
godot::api->godot_array_new(&_godot_array);
|
||||
}
|
||||
|
||||
Array::Array(const Array &other) {
|
||||
godot::api->godot_array_new_copy(&_godot_array, &other._godot_array);
|
||||
}
|
||||
|
||||
Array &Array::operator=(const Array &other) {
|
||||
godot::api->godot_array_destroy(&_godot_array);
|
||||
godot::api->godot_array_new_copy(&_godot_array, &other._godot_array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Array::Array(const PoolByteArray &a) {
|
||||
godot::api->godot_array_new_pool_byte_array(&_godot_array, (godot_pool_byte_array *)&a);
|
||||
}
|
||||
|
||||
Array::Array(const PoolIntArray &a) {
|
||||
godot::api->godot_array_new_pool_int_array(&_godot_array, (godot_pool_int_array *)&a);
|
||||
}
|
||||
|
||||
Array::Array(const PoolRealArray &a) {
|
||||
godot::api->godot_array_new_pool_real_array(&_godot_array, (godot_pool_real_array *)&a);
|
||||
}
|
||||
|
||||
Array::Array(const PoolStringArray &a) {
|
||||
godot::api->godot_array_new_pool_string_array(&_godot_array, (godot_pool_string_array *)&a);
|
||||
}
|
||||
|
||||
Array::Array(const PoolVector2Array &a) {
|
||||
godot::api->godot_array_new_pool_vector2_array(&_godot_array, (godot_pool_vector2_array *)&a);
|
||||
}
|
||||
|
||||
Array::Array(const PoolVector3Array &a) {
|
||||
godot::api->godot_array_new_pool_vector3_array(&_godot_array, (godot_pool_vector3_array *)&a);
|
||||
}
|
||||
|
||||
Array::Array(const PoolColorArray &a) {
|
||||
godot::api->godot_array_new_pool_color_array(&_godot_array, (godot_pool_color_array *)&a);
|
||||
}
|
||||
|
||||
Variant &Array::operator[](const int idx) {
|
||||
godot_variant *v = godot::api->godot_array_operator_index(&_godot_array, idx);
|
||||
// We assume it's ok to reinterpret because the value is a pointer whose data is already owned by the array,
|
||||
// so can return a reference without constructing a Variant
|
||||
return *reinterpret_cast<Variant *>(v);
|
||||
}
|
||||
|
||||
const Variant &Array::operator[](const int idx) const {
|
||||
// Yes, I'm casting away the const... you can hate me now.
|
||||
// since the result is
|
||||
godot_variant *v = godot::api->godot_array_operator_index((godot_array *)&_godot_array, idx);
|
||||
return *reinterpret_cast<const Variant *>(v);
|
||||
}
|
||||
|
||||
void Array::append(const Variant &v) {
|
||||
godot::api->godot_array_append(&_godot_array, (godot_variant *)&v);
|
||||
}
|
||||
|
||||
void Array::clear() {
|
||||
godot::api->godot_array_clear(&_godot_array);
|
||||
}
|
||||
|
||||
int Array::count(const Variant &v) {
|
||||
return godot::api->godot_array_count(&_godot_array, (godot_variant *)&v);
|
||||
}
|
||||
|
||||
bool Array::empty() const {
|
||||
return godot::api->godot_array_empty(&_godot_array);
|
||||
}
|
||||
|
||||
void Array::erase(const Variant &v) {
|
||||
godot::api->godot_array_erase(&_godot_array, (godot_variant *)&v);
|
||||
}
|
||||
|
||||
Variant Array::front() const {
|
||||
godot_variant v = godot::api->godot_array_front(&_godot_array);
|
||||
return Variant(v);
|
||||
}
|
||||
|
||||
Variant Array::back() const {
|
||||
godot_variant v = godot::api->godot_array_back(&_godot_array);
|
||||
return Variant(v);
|
||||
}
|
||||
|
||||
int Array::find(const Variant &what, const int from) const {
|
||||
return godot::api->godot_array_find(&_godot_array, (godot_variant *)&what, from);
|
||||
}
|
||||
|
||||
int Array::find_last(const Variant &what) const {
|
||||
return godot::api->godot_array_find_last(&_godot_array, (godot_variant *)&what);
|
||||
}
|
||||
|
||||
bool Array::has(const Variant &what) const {
|
||||
return godot::api->godot_array_has(&_godot_array, (godot_variant *)&what);
|
||||
}
|
||||
|
||||
uint32_t Array::hash() const {
|
||||
return godot::api->godot_array_hash(&_godot_array);
|
||||
}
|
||||
|
||||
void Array::insert(const int pos, const Variant &value) {
|
||||
godot::api->godot_array_insert(&_godot_array, pos, (godot_variant *)&value);
|
||||
}
|
||||
|
||||
void Array::invert() {
|
||||
godot::api->godot_array_invert(&_godot_array);
|
||||
}
|
||||
|
||||
Variant Array::pop_back() {
|
||||
godot_variant v = godot::api->godot_array_pop_back(&_godot_array);
|
||||
return Variant(v);
|
||||
}
|
||||
|
||||
Variant Array::pop_front() {
|
||||
godot_variant v = godot::api->godot_array_pop_front(&_godot_array);
|
||||
return Variant(v);
|
||||
}
|
||||
|
||||
void Array::push_back(const Variant &v) {
|
||||
godot::api->godot_array_push_back(&_godot_array, (godot_variant *)&v);
|
||||
}
|
||||
|
||||
void Array::push_front(const Variant &v) {
|
||||
godot::api->godot_array_push_front(&_godot_array, (godot_variant *)&v);
|
||||
}
|
||||
|
||||
void Array::remove(const int idx) {
|
||||
godot::api->godot_array_remove(&_godot_array, idx);
|
||||
}
|
||||
|
||||
int Array::size() const {
|
||||
return godot::api->godot_array_size(&_godot_array);
|
||||
}
|
||||
|
||||
void Array::resize(const int size) {
|
||||
godot::api->godot_array_resize(&_godot_array, size);
|
||||
}
|
||||
|
||||
int Array::rfind(const Variant &what, const int from) const {
|
||||
return godot::api->godot_array_rfind(&_godot_array, (godot_variant *)&what, from);
|
||||
}
|
||||
|
||||
void Array::sort() {
|
||||
godot::api->godot_array_sort(&_godot_array);
|
||||
}
|
||||
|
||||
void Array::sort_custom(Object *obj, const String &func) {
|
||||
godot::api->godot_array_sort_custom(&_godot_array, (godot_object *)obj, (godot_string *)&func);
|
||||
}
|
||||
|
||||
int Array::bsearch(const Variant &value, const bool before) {
|
||||
return godot::api->godot_array_bsearch(&_godot_array, (godot_variant *)&value, before);
|
||||
}
|
||||
|
||||
int Array::bsearch_custom(const Variant &value, const Object *obj,
|
||||
const String &func, const bool before) {
|
||||
return godot::api->godot_array_bsearch_custom(&_godot_array, (godot_variant *)&value,
|
||||
(godot_object *)obj, (godot_string *)&func, before);
|
||||
}
|
||||
|
||||
Array Array::duplicate(const bool deep) const {
|
||||
godot_array arr = godot::core_1_1_api->godot_array_duplicate(&_godot_array, deep);
|
||||
return Array(arr);
|
||||
}
|
||||
|
||||
Variant Array::max() const {
|
||||
godot_variant v = godot::core_1_1_api->godot_array_max(&_godot_array);
|
||||
return Variant(v);
|
||||
}
|
||||
|
||||
Variant Array::min() const {
|
||||
godot_variant v = godot::core_1_1_api->godot_array_min(&_godot_array);
|
||||
return Variant(v);
|
||||
}
|
||||
|
||||
void Array::shuffle() {
|
||||
godot::core_1_1_api->godot_array_shuffle(&_godot_array);
|
||||
}
|
||||
|
||||
Array::~Array() {
|
||||
godot::api->godot_array_destroy(&_godot_array);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,710 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Basis.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Basis.hpp"
|
||||
#include "Defs.hpp"
|
||||
#include "Quat.hpp"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const Basis Basis::IDENTITY = Basis();
|
||||
const Basis Basis::FLIP_X = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1);
|
||||
const Basis Basis::FLIP_Y = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1);
|
||||
const Basis Basis::FLIP_Z = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1);
|
||||
|
||||
Basis::Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2) {
|
||||
elements[0] = row0;
|
||||
elements[1] = row1;
|
||||
elements[2] = row2;
|
||||
}
|
||||
|
||||
Basis::Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
|
||||
set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
|
||||
}
|
||||
|
||||
Basis::Basis() {
|
||||
elements[0][0] = 1;
|
||||
elements[0][1] = 0;
|
||||
elements[0][2] = 0;
|
||||
elements[1][0] = 0;
|
||||
elements[1][1] = 1;
|
||||
elements[1][2] = 0;
|
||||
elements[2][0] = 0;
|
||||
elements[2][1] = 0;
|
||||
elements[2][2] = 1;
|
||||
}
|
||||
|
||||
#define cofac(row1, col1, row2, col2) \
|
||||
(elements[row1][col1] * elements[row2][col2] - elements[row1][col2] * elements[row2][col1])
|
||||
|
||||
void Basis::invert() {
|
||||
real_t co[3] = {
|
||||
cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)
|
||||
};
|
||||
real_t det = elements[0][0] * co[0] +
|
||||
elements[0][1] * co[1] +
|
||||
elements[0][2] * co[2];
|
||||
|
||||
ERR_FAIL_COND(det == 0);
|
||||
|
||||
real_t s = 1.0 / det;
|
||||
|
||||
set(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
|
||||
co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
|
||||
co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
|
||||
}
|
||||
#undef cofac
|
||||
|
||||
bool Basis::isequal_approx(const Basis &a, const Basis &b) const {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if ((::fabs(a.elements[i][j] - b.elements[i][j]) < CMP_EPSILON) == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Basis::is_orthogonal() const {
|
||||
Basis id;
|
||||
Basis m = (*this) * transposed();
|
||||
|
||||
return isequal_approx(id, m);
|
||||
}
|
||||
|
||||
bool Basis::is_rotation() const {
|
||||
return ::fabs(determinant() - 1) < CMP_EPSILON && is_orthogonal();
|
||||
}
|
||||
|
||||
void Basis::transpose() {
|
||||
std::swap(elements[0][1], elements[1][0]);
|
||||
std::swap(elements[0][2], elements[2][0]);
|
||||
std::swap(elements[1][2], elements[2][1]);
|
||||
}
|
||||
|
||||
Basis Basis::inverse() const {
|
||||
Basis b = *this;
|
||||
b.invert();
|
||||
return b;
|
||||
}
|
||||
|
||||
Basis Basis::transposed() const {
|
||||
Basis b = *this;
|
||||
b.transpose();
|
||||
return b;
|
||||
}
|
||||
|
||||
real_t Basis::determinant() const {
|
||||
return elements[0][0] * (elements[1][1] * elements[2][2] - elements[2][1] * elements[1][2]) -
|
||||
elements[1][0] * (elements[0][1] * elements[2][2] - elements[2][1] * elements[0][2]) +
|
||||
elements[2][0] * (elements[0][1] * elements[1][2] - elements[1][1] * elements[0][2]);
|
||||
}
|
||||
|
||||
Vector3 Basis::get_axis(int p_axis) const {
|
||||
// get actual basis axis (elements is transposed for performance)
|
||||
return Vector3(elements[0][p_axis], elements[1][p_axis], elements[2][p_axis]);
|
||||
}
|
||||
void Basis::set_axis(int p_axis, const Vector3 &p_value) {
|
||||
// get actual basis axis (elements is transposed for performance)
|
||||
elements[0][p_axis] = p_value.x;
|
||||
elements[1][p_axis] = p_value.y;
|
||||
elements[2][p_axis] = p_value.z;
|
||||
}
|
||||
|
||||
void Basis::rotate(const Vector3 &p_axis, real_t p_phi) {
|
||||
*this = rotated(p_axis, p_phi);
|
||||
}
|
||||
|
||||
Basis Basis::rotated(const Vector3 &p_axis, real_t p_phi) const {
|
||||
return Basis(p_axis, p_phi) * (*this);
|
||||
}
|
||||
|
||||
void Basis::scale(const Vector3 &p_scale) {
|
||||
elements[0][0] *= p_scale.x;
|
||||
elements[0][1] *= p_scale.x;
|
||||
elements[0][2] *= p_scale.x;
|
||||
elements[1][0] *= p_scale.y;
|
||||
elements[1][1] *= p_scale.y;
|
||||
elements[1][2] *= p_scale.y;
|
||||
elements[2][0] *= p_scale.z;
|
||||
elements[2][1] *= p_scale.z;
|
||||
elements[2][2] *= p_scale.z;
|
||||
}
|
||||
|
||||
Basis Basis::scaled(const Vector3 &p_scale) const {
|
||||
Basis b = *this;
|
||||
b.scale(p_scale);
|
||||
return b;
|
||||
}
|
||||
|
||||
Vector3 Basis::get_scale() const {
|
||||
// We are assuming M = R.S, and performing a polar decomposition to extract R and S.
|
||||
// FIXME: We eventually need a proper polar decomposition.
|
||||
// As a cheap workaround until then, to ensure that R is a proper rotation matrix with determinant +1
|
||||
// (such that it can be represented by a Quat or Euler angles), we absorb the sign flip into the scaling matrix.
|
||||
// As such, it works in conjuction with get_rotation().
|
||||
real_t det_sign = determinant() > 0 ? 1 : -1;
|
||||
return det_sign * Vector3(
|
||||
Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
|
||||
Vector3(elements[0][1], elements[1][1], elements[2][1]).length(),
|
||||
Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
|
||||
}
|
||||
|
||||
// TODO: implement this directly without using quaternions to make it more efficient
|
||||
Basis Basis::slerp(Basis b, float t) const {
|
||||
ERR_FAIL_COND_V(!is_rotation(), Basis());
|
||||
ERR_FAIL_COND_V(!b.is_rotation(), Basis());
|
||||
Quat from(*this);
|
||||
Quat to(b);
|
||||
return Basis(from.slerp(to, t));
|
||||
}
|
||||
|
||||
// get_euler_xyz returns a vector containing the Euler angles in the format
|
||||
// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last
|
||||
// (following the convention they are commonly defined in the literature).
|
||||
//
|
||||
// The current implementation uses XYZ convention (Z is the first rotation),
|
||||
// so euler.z is the angle of the (first) rotation around Z axis and so on,
|
||||
//
|
||||
// And thus, assuming the matrix is a rotation matrix, this function returns
|
||||
// the angles in the decomposition R = X(a1).Y(a2).Z(a3) where Z(a) rotates
|
||||
// around the z-axis by a and so on.
|
||||
Vector3 Basis::get_euler_xyz() const {
|
||||
// Euler angles in XYZ convention.
|
||||
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
|
||||
//
|
||||
// rot = cy*cz -cy*sz sy
|
||||
// cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
|
||||
// -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
|
||||
|
||||
Vector3 euler;
|
||||
|
||||
ERR_FAIL_COND_V(is_rotation() == false, euler);
|
||||
|
||||
real_t sy = elements[0][2];
|
||||
if (sy < 1.0) {
|
||||
if (sy > -1.0) {
|
||||
// is this a pure Y rotation?
|
||||
if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
|
||||
// return the simplest form (human friendlier in editor and scripts)
|
||||
euler.x = 0;
|
||||
euler.y = atan2(elements[0][2], elements[0][0]);
|
||||
euler.z = 0;
|
||||
} else {
|
||||
euler.x = ::atan2(-elements[1][2], elements[2][2]);
|
||||
euler.y = ::asin(sy);
|
||||
euler.z = ::atan2(-elements[0][1], elements[0][0]);
|
||||
}
|
||||
} else {
|
||||
euler.x = -::atan2(elements[0][1], elements[1][1]);
|
||||
euler.y = -Math_PI / 2.0;
|
||||
euler.z = 0.0;
|
||||
}
|
||||
} else {
|
||||
euler.x = ::atan2(elements[0][1], elements[1][1]);
|
||||
euler.y = Math_PI / 2.0;
|
||||
euler.z = 0.0;
|
||||
}
|
||||
return euler;
|
||||
}
|
||||
|
||||
// set_euler_xyz expects a vector containing the Euler angles in the format
|
||||
// (ax,ay,az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// The current implementation uses XYZ convention (Z is the first rotation).
|
||||
void Basis::set_euler_xyz(const Vector3 &p_euler) {
|
||||
real_t c, s;
|
||||
|
||||
c = ::cos(p_euler.x);
|
||||
s = ::sin(p_euler.x);
|
||||
Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
|
||||
|
||||
c = ::cos(p_euler.y);
|
||||
s = ::sin(p_euler.y);
|
||||
Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
|
||||
|
||||
c = ::cos(p_euler.z);
|
||||
s = ::sin(p_euler.z);
|
||||
Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
//optimizer will optimize away all this anyway
|
||||
*this = xmat * (ymat * zmat);
|
||||
}
|
||||
|
||||
// get_euler_yxz returns a vector containing the Euler angles in the YXZ convention,
|
||||
// as in first-Z, then-X, last-Y. The angles for X, Y, and Z rotations are returned
|
||||
// as the x, y, and z components of a Vector3 respectively.
|
||||
Vector3 Basis::get_euler_yxz() const {
|
||||
// Euler angles in YXZ convention.
|
||||
// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
|
||||
//
|
||||
// rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
|
||||
// cx*sz cx*cz -sx
|
||||
// cy*sx*sz-cz*sy cy*cz*sx+sy*sz cy*cx
|
||||
|
||||
Vector3 euler;
|
||||
|
||||
ERR_FAIL_COND_V(is_rotation() == false, euler);
|
||||
|
||||
real_t m12 = elements[1][2];
|
||||
|
||||
if (m12 < 1) {
|
||||
if (m12 > -1) {
|
||||
// is this a pure X rotation?
|
||||
if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
|
||||
// return the simplest form (human friendlier in editor and scripts)
|
||||
euler.x = atan2(-m12, elements[1][1]);
|
||||
euler.y = 0;
|
||||
euler.z = 0;
|
||||
} else {
|
||||
euler.x = asin(-m12);
|
||||
euler.y = atan2(elements[0][2], elements[2][2]);
|
||||
euler.z = atan2(elements[1][0], elements[1][1]);
|
||||
}
|
||||
} else { // m12 == -1
|
||||
euler.x = Math_PI * 0.5;
|
||||
euler.y = -atan2(-elements[0][1], elements[0][0]);
|
||||
euler.z = 0;
|
||||
}
|
||||
} else { // m12 == 1
|
||||
euler.x = -Math_PI * 0.5;
|
||||
euler.y = -atan2(-elements[0][1], elements[0][0]);
|
||||
euler.z = 0;
|
||||
}
|
||||
|
||||
return euler;
|
||||
}
|
||||
|
||||
// set_euler_yxz expects a vector containing the Euler angles in the format
|
||||
// (ax,ay,az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// The current implementation uses YXZ convention (Z is the first rotation).
|
||||
void Basis::set_euler_yxz(const Vector3 &p_euler) {
|
||||
real_t c, s;
|
||||
|
||||
c = ::cos(p_euler.x);
|
||||
s = ::sin(p_euler.x);
|
||||
Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
|
||||
|
||||
c = ::cos(p_euler.y);
|
||||
s = ::sin(p_euler.y);
|
||||
Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
|
||||
|
||||
c = ::cos(p_euler.z);
|
||||
s = ::sin(p_euler.z);
|
||||
Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
//optimizer will optimize away all this anyway
|
||||
*this = ymat * xmat * zmat;
|
||||
}
|
||||
|
||||
// transposed dot products
|
||||
real_t Basis::tdotx(const Vector3 &v) const {
|
||||
return elements[0][0] * v[0] + elements[1][0] * v[1] + elements[2][0] * v[2];
|
||||
}
|
||||
real_t Basis::tdoty(const Vector3 &v) const {
|
||||
return elements[0][1] * v[0] + elements[1][1] * v[1] + elements[2][1] * v[2];
|
||||
}
|
||||
real_t Basis::tdotz(const Vector3 &v) const {
|
||||
return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2];
|
||||
}
|
||||
|
||||
bool Basis::operator==(const Basis &p_matrix) const {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (elements[i][j] != p_matrix.elements[i][j])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Basis::operator!=(const Basis &p_matrix) const {
|
||||
return (!(*this == p_matrix));
|
||||
}
|
||||
|
||||
Vector3 Basis::xform(const Vector3 &p_vector) const {
|
||||
return Vector3(
|
||||
elements[0].dot(p_vector),
|
||||
elements[1].dot(p_vector),
|
||||
elements[2].dot(p_vector));
|
||||
}
|
||||
|
||||
Vector3 Basis::xform_inv(const Vector3 &p_vector) const {
|
||||
return Vector3(
|
||||
(elements[0][0] * p_vector.x) + (elements[1][0] * p_vector.y) + (elements[2][0] * p_vector.z),
|
||||
(elements[0][1] * p_vector.x) + (elements[1][1] * p_vector.y) + (elements[2][1] * p_vector.z),
|
||||
(elements[0][2] * p_vector.x) + (elements[1][2] * p_vector.y) + (elements[2][2] * p_vector.z));
|
||||
}
|
||||
void Basis::operator*=(const Basis &p_matrix) {
|
||||
set(
|
||||
p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
|
||||
p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
|
||||
p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]));
|
||||
}
|
||||
|
||||
Basis Basis::operator*(const Basis &p_matrix) const {
|
||||
return Basis(
|
||||
p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
|
||||
p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
|
||||
p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]));
|
||||
}
|
||||
|
||||
void Basis::operator+=(const Basis &p_matrix) {
|
||||
elements[0] += p_matrix.elements[0];
|
||||
elements[1] += p_matrix.elements[1];
|
||||
elements[2] += p_matrix.elements[2];
|
||||
}
|
||||
|
||||
Basis Basis::operator+(const Basis &p_matrix) const {
|
||||
Basis ret(*this);
|
||||
ret += p_matrix;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Basis::operator-=(const Basis &p_matrix) {
|
||||
elements[0] -= p_matrix.elements[0];
|
||||
elements[1] -= p_matrix.elements[1];
|
||||
elements[2] -= p_matrix.elements[2];
|
||||
}
|
||||
|
||||
Basis Basis::operator-(const Basis &p_matrix) const {
|
||||
Basis ret(*this);
|
||||
ret -= p_matrix;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Basis::operator*=(real_t p_val) {
|
||||
elements[0] *= p_val;
|
||||
elements[1] *= p_val;
|
||||
elements[2] *= p_val;
|
||||
}
|
||||
|
||||
Basis Basis::operator*(real_t p_val) const {
|
||||
Basis ret(*this);
|
||||
ret *= p_val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Basis::operator String() const {
|
||||
String s;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (i != 0 || j != 0)
|
||||
s += ", ";
|
||||
|
||||
s += String::num(elements[i][j]);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* create / set */
|
||||
|
||||
void Basis::set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
|
||||
elements[0][0] = xx;
|
||||
elements[0][1] = xy;
|
||||
elements[0][2] = xz;
|
||||
elements[1][0] = yx;
|
||||
elements[1][1] = yy;
|
||||
elements[1][2] = yz;
|
||||
elements[2][0] = zx;
|
||||
elements[2][1] = zy;
|
||||
elements[2][2] = zz;
|
||||
}
|
||||
Vector3 Basis::get_column(int i) const {
|
||||
return Vector3(elements[0][i], elements[1][i], elements[2][i]);
|
||||
}
|
||||
|
||||
Vector3 Basis::get_row(int i) const {
|
||||
return Vector3(elements[i][0], elements[i][1], elements[i][2]);
|
||||
}
|
||||
Vector3 Basis::get_main_diagonal() const {
|
||||
return Vector3(elements[0][0], elements[1][1], elements[2][2]);
|
||||
}
|
||||
|
||||
void Basis::set_row(int i, const Vector3 &p_row) {
|
||||
elements[i][0] = p_row.x;
|
||||
elements[i][1] = p_row.y;
|
||||
elements[i][2] = p_row.z;
|
||||
}
|
||||
|
||||
Basis Basis::transpose_xform(const Basis &m) const {
|
||||
return Basis(
|
||||
elements[0].x * m[0].x + elements[1].x * m[1].x + elements[2].x * m[2].x,
|
||||
elements[0].x * m[0].y + elements[1].x * m[1].y + elements[2].x * m[2].y,
|
||||
elements[0].x * m[0].z + elements[1].x * m[1].z + elements[2].x * m[2].z,
|
||||
elements[0].y * m[0].x + elements[1].y * m[1].x + elements[2].y * m[2].x,
|
||||
elements[0].y * m[0].y + elements[1].y * m[1].y + elements[2].y * m[2].y,
|
||||
elements[0].y * m[0].z + elements[1].y * m[1].z + elements[2].y * m[2].z,
|
||||
elements[0].z * m[0].x + elements[1].z * m[1].x + elements[2].z * m[2].x,
|
||||
elements[0].z * m[0].y + elements[1].z * m[1].y + elements[2].z * m[2].y,
|
||||
elements[0].z * m[0].z + elements[1].z * m[1].z + elements[2].z * m[2].z);
|
||||
}
|
||||
|
||||
void Basis::orthonormalize() {
|
||||
ERR_FAIL_COND(determinant() == 0);
|
||||
|
||||
// Gram-Schmidt Process
|
||||
|
||||
Vector3 x = get_axis(0);
|
||||
Vector3 y = get_axis(1);
|
||||
Vector3 z = get_axis(2);
|
||||
|
||||
x.normalize();
|
||||
y = (y - x * (x.dot(y)));
|
||||
y.normalize();
|
||||
z = (z - x * (x.dot(z)) - y * (y.dot(z)));
|
||||
z.normalize();
|
||||
|
||||
set_axis(0, x);
|
||||
set_axis(1, y);
|
||||
set_axis(2, z);
|
||||
}
|
||||
|
||||
Basis Basis::orthonormalized() const {
|
||||
Basis b = *this;
|
||||
b.orthonormalize();
|
||||
return b;
|
||||
}
|
||||
|
||||
bool Basis::is_symmetric() const {
|
||||
if (::fabs(elements[0][1] - elements[1][0]) > CMP_EPSILON)
|
||||
return false;
|
||||
if (::fabs(elements[0][2] - elements[2][0]) > CMP_EPSILON)
|
||||
return false;
|
||||
if (::fabs(elements[1][2] - elements[2][1]) > CMP_EPSILON)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Basis Basis::diagonalize() {
|
||||
// I love copy paste
|
||||
|
||||
if (!is_symmetric())
|
||||
return Basis();
|
||||
|
||||
const int ite_max = 1024;
|
||||
|
||||
real_t off_matrix_norm_2 = elements[0][1] * elements[0][1] + elements[0][2] * elements[0][2] + elements[1][2] * elements[1][2];
|
||||
|
||||
int ite = 0;
|
||||
Basis acc_rot;
|
||||
while (off_matrix_norm_2 > CMP_EPSILON2 && ite++ < ite_max) {
|
||||
real_t el01_2 = elements[0][1] * elements[0][1];
|
||||
real_t el02_2 = elements[0][2] * elements[0][2];
|
||||
real_t el12_2 = elements[1][2] * elements[1][2];
|
||||
// Find the pivot element
|
||||
int i, j;
|
||||
if (el01_2 > el02_2) {
|
||||
if (el12_2 > el01_2) {
|
||||
i = 1;
|
||||
j = 2;
|
||||
} else {
|
||||
i = 0;
|
||||
j = 1;
|
||||
}
|
||||
} else {
|
||||
if (el12_2 > el02_2) {
|
||||
i = 1;
|
||||
j = 2;
|
||||
} else {
|
||||
i = 0;
|
||||
j = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the rotation angle
|
||||
real_t angle;
|
||||
if (::fabs(elements[j][j] - elements[i][i]) < CMP_EPSILON) {
|
||||
angle = Math_PI / 4;
|
||||
} else {
|
||||
angle = 0.5 * ::atan(2 * elements[i][j] / (elements[j][j] - elements[i][i]));
|
||||
}
|
||||
|
||||
// Compute the rotation matrix
|
||||
Basis rot;
|
||||
rot.elements[i][i] = rot.elements[j][j] = ::cos(angle);
|
||||
rot.elements[i][j] = -(rot.elements[j][i] = ::sin(angle));
|
||||
|
||||
// Update the off matrix norm
|
||||
off_matrix_norm_2 -= elements[i][j] * elements[i][j];
|
||||
|
||||
// Apply the rotation
|
||||
*this = rot * *this * rot.transposed();
|
||||
acc_rot = rot * acc_rot;
|
||||
}
|
||||
|
||||
return acc_rot;
|
||||
}
|
||||
|
||||
static const Basis _ortho_bases[24] = {
|
||||
Basis(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
||||
Basis(0, -1, 0, 1, 0, 0, 0, 0, 1),
|
||||
Basis(-1, 0, 0, 0, -1, 0, 0, 0, 1),
|
||||
Basis(0, 1, 0, -1, 0, 0, 0, 0, 1),
|
||||
Basis(1, 0, 0, 0, 0, -1, 0, 1, 0),
|
||||
Basis(0, 0, 1, 1, 0, 0, 0, 1, 0),
|
||||
Basis(-1, 0, 0, 0, 0, 1, 0, 1, 0),
|
||||
Basis(0, 0, -1, -1, 0, 0, 0, 1, 0),
|
||||
Basis(1, 0, 0, 0, -1, 0, 0, 0, -1),
|
||||
Basis(0, 1, 0, 1, 0, 0, 0, 0, -1),
|
||||
Basis(-1, 0, 0, 0, 1, 0, 0, 0, -1),
|
||||
Basis(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
||||
Basis(1, 0, 0, 0, 0, 1, 0, -1, 0),
|
||||
Basis(0, 0, -1, 1, 0, 0, 0, -1, 0),
|
||||
Basis(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
||||
Basis(0, 0, 1, -1, 0, 0, 0, -1, 0),
|
||||
Basis(0, 0, 1, 0, 1, 0, -1, 0, 0),
|
||||
Basis(0, -1, 0, 0, 0, 1, -1, 0, 0),
|
||||
Basis(0, 0, -1, 0, -1, 0, -1, 0, 0),
|
||||
Basis(0, 1, 0, 0, 0, -1, -1, 0, 0),
|
||||
Basis(0, 0, 1, 0, -1, 0, 1, 0, 0),
|
||||
Basis(0, 1, 0, 0, 0, 1, 1, 0, 0),
|
||||
Basis(0, 0, -1, 0, 1, 0, 1, 0, 0),
|
||||
Basis(0, -1, 0, 0, 0, -1, 1, 0, 0)
|
||||
};
|
||||
|
||||
int Basis::get_orthogonal_index() const {
|
||||
//could be sped up if i come up with a way
|
||||
Basis orth = *this;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
real_t v = orth[i][j];
|
||||
if (v > 0.5)
|
||||
v = 1.0;
|
||||
else if (v < -0.5)
|
||||
v = -1.0;
|
||||
else
|
||||
v = 0;
|
||||
|
||||
orth[i][j] = v;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 24; i++) {
|
||||
if (_ortho_bases[i] == orth)
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Basis::set_orthogonal_index(int p_index) {
|
||||
//there only exist 24 orthogonal bases in r3
|
||||
ERR_FAIL_COND(p_index >= 24);
|
||||
|
||||
*this = _ortho_bases[p_index];
|
||||
}
|
||||
|
||||
Basis::Basis(const Vector3 &p_euler) {
|
||||
set_euler(p_euler);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
|
||||
#include "Quat.hpp"
|
||||
|
||||
namespace godot {
|
||||
|
||||
Basis::Basis(const Quat &p_quat) {
|
||||
real_t d = p_quat.length_squared();
|
||||
real_t s = 2.0 / d;
|
||||
real_t xs = p_quat.x * s, ys = p_quat.y * s, zs = p_quat.z * s;
|
||||
real_t wx = p_quat.w * xs, wy = p_quat.w * ys, wz = p_quat.w * zs;
|
||||
real_t xx = p_quat.x * xs, xy = p_quat.x * ys, xz = p_quat.x * zs;
|
||||
real_t yy = p_quat.y * ys, yz = p_quat.y * zs, zz = p_quat.z * zs;
|
||||
set(1.0 - (yy + zz), xy - wz, xz + wy,
|
||||
xy + wz, 1.0 - (xx + zz), yz - wx,
|
||||
xz - wy, yz + wx, 1.0 - (xx + yy));
|
||||
}
|
||||
|
||||
Basis::Basis(const Vector3 &p_axis, real_t p_phi) {
|
||||
// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
|
||||
|
||||
Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z);
|
||||
|
||||
real_t cosine = ::cos(p_phi);
|
||||
real_t sine = ::sin(p_phi);
|
||||
|
||||
elements[0][0] = axis_sq.x + cosine * (1.0 - axis_sq.x);
|
||||
elements[0][1] = p_axis.x * p_axis.y * (1.0 - cosine) - p_axis.z * sine;
|
||||
elements[0][2] = p_axis.z * p_axis.x * (1.0 - cosine) + p_axis.y * sine;
|
||||
|
||||
elements[1][0] = p_axis.x * p_axis.y * (1.0 - cosine) + p_axis.z * sine;
|
||||
elements[1][1] = axis_sq.y + cosine * (1.0 - axis_sq.y);
|
||||
elements[1][2] = p_axis.y * p_axis.z * (1.0 - cosine) - p_axis.x * sine;
|
||||
|
||||
elements[2][0] = p_axis.z * p_axis.x * (1.0 - cosine) - p_axis.y * sine;
|
||||
elements[2][1] = p_axis.y * p_axis.z * (1.0 - cosine) + p_axis.x * sine;
|
||||
elements[2][2] = axis_sq.z + cosine * (1.0 - axis_sq.z);
|
||||
}
|
||||
|
||||
Basis::operator Quat() const {
|
||||
//commenting this check because precision issues cause it to fail when it shouldn't
|
||||
//ERR_FAIL_COND_V(is_rotation() == false, Quat());
|
||||
|
||||
real_t trace = elements[0][0] + elements[1][1] + elements[2][2];
|
||||
real_t temp[4];
|
||||
|
||||
if (trace > 0.0) {
|
||||
real_t s = ::sqrt(trace + 1.0);
|
||||
temp[3] = (s * 0.5);
|
||||
s = 0.5 / s;
|
||||
|
||||
temp[0] = ((elements[2][1] - elements[1][2]) * s);
|
||||
temp[1] = ((elements[0][2] - elements[2][0]) * s);
|
||||
temp[2] = ((elements[1][0] - elements[0][1]) * s);
|
||||
} else {
|
||||
int i = elements[0][0] < elements[1][1] ?
|
||||
(elements[1][1] < elements[2][2] ? 2 : 1) :
|
||||
(elements[0][0] < elements[2][2] ? 2 : 0);
|
||||
int j = (i + 1) % 3;
|
||||
int k = (i + 2) % 3;
|
||||
|
||||
real_t s = ::sqrt(elements[i][i] - elements[j][j] - elements[k][k] + 1.0);
|
||||
temp[i] = s * 0.5;
|
||||
s = 0.5 / s;
|
||||
|
||||
temp[3] = (elements[k][j] - elements[j][k]) * s;
|
||||
temp[j] = (elements[j][i] + elements[i][j]) * s;
|
||||
temp[k] = (elements[k][i] + elements[i][k]) * s;
|
||||
}
|
||||
|
||||
return Quat(temp[0], temp[1], temp[2], temp[3]);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,655 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* CameraMatrix.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "CameraMatrix.hpp"
|
||||
|
||||
void CameraMatrix::set_identity() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
matrix[i][j] = (i == j) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CameraMatrix::set_zero() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
matrix[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Plane CameraMatrix::xform4(const Plane &p_vec4) const {
|
||||
Plane ret;
|
||||
|
||||
ret.normal.x = matrix[0][0] * p_vec4.normal.x + matrix[1][0] * p_vec4.normal.y + matrix[2][0] * p_vec4.normal.z + matrix[3][0] * p_vec4.d;
|
||||
ret.normal.y = matrix[0][1] * p_vec4.normal.x + matrix[1][1] * p_vec4.normal.y + matrix[2][1] * p_vec4.normal.z + matrix[3][1] * p_vec4.d;
|
||||
ret.normal.z = matrix[0][2] * p_vec4.normal.x + matrix[1][2] * p_vec4.normal.y + matrix[2][2] * p_vec4.normal.z + matrix[3][2] * p_vec4.d;
|
||||
ret.d = matrix[0][3] * p_vec4.normal.x + matrix[1][3] * p_vec4.normal.y + matrix[2][3] * p_vec4.normal.z + matrix[3][3] * p_vec4.d;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) {
|
||||
if (p_flip_fov) {
|
||||
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
|
||||
}
|
||||
|
||||
real_t sine, cotangent, deltaZ;
|
||||
real_t radians = p_fovy_degrees / 2.0 * Math_PI / 180.0;
|
||||
|
||||
deltaZ = p_z_far - p_z_near;
|
||||
sine = sin(radians);
|
||||
|
||||
if ((deltaZ == 0) || (sine == 0) || (p_aspect == 0)) {
|
||||
return;
|
||||
}
|
||||
cotangent = cos(radians) / sine;
|
||||
|
||||
set_identity();
|
||||
|
||||
matrix[0][0] = cotangent / p_aspect;
|
||||
matrix[1][1] = cotangent;
|
||||
matrix[2][2] = -(p_z_far + p_z_near) / deltaZ;
|
||||
matrix[2][3] = -1;
|
||||
matrix[3][2] = -2 * p_z_near * p_z_far / deltaZ;
|
||||
matrix[3][3] = 0;
|
||||
}
|
||||
|
||||
void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist) {
|
||||
if (p_flip_fov) {
|
||||
p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect);
|
||||
}
|
||||
|
||||
real_t left, right, modeltranslation, ymax, xmax, frustumshift;
|
||||
|
||||
ymax = p_z_near * tan(p_fovy_degrees * Math_PI / 360.0f);
|
||||
xmax = ymax * p_aspect;
|
||||
frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist;
|
||||
|
||||
switch (p_eye) {
|
||||
case 1: { // left eye
|
||||
left = -xmax + frustumshift;
|
||||
right = xmax + frustumshift;
|
||||
modeltranslation = p_intraocular_dist / 2.0;
|
||||
}; break;
|
||||
case 2: { // right eye
|
||||
left = -xmax - frustumshift;
|
||||
right = xmax - frustumshift;
|
||||
modeltranslation = -p_intraocular_dist / 2.0;
|
||||
}; break;
|
||||
default: { // mono, should give the same result as set_perspective(p_fovy_degrees,p_aspect,p_z_near,p_z_far,p_flip_fov)
|
||||
left = -xmax;
|
||||
right = xmax;
|
||||
modeltranslation = 0.0;
|
||||
}; break;
|
||||
};
|
||||
|
||||
set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far);
|
||||
|
||||
// translate matrix by (modeltranslation, 0.0, 0.0)
|
||||
CameraMatrix cm;
|
||||
cm.set_identity();
|
||||
cm.matrix[3][0] = modeltranslation;
|
||||
*this = *this * cm;
|
||||
}
|
||||
|
||||
void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
|
||||
// we first calculate our base frustum on our values without taking our lens magnification into account.
|
||||
real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens;
|
||||
real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens;
|
||||
real_t f3 = (p_display_width / 4.0) / p_display_to_lens;
|
||||
|
||||
// now we apply our oversample factor to increase our FOV. how much we oversample is always a balance we strike between performance and how much
|
||||
// we're willing to sacrifice in FOV.
|
||||
real_t add = ((f1 + f2) * (p_oversample - 1.0)) / 2.0;
|
||||
f1 += add;
|
||||
f2 += add;
|
||||
f3 *= p_oversample;
|
||||
|
||||
// always apply KEEP_WIDTH aspect ratio
|
||||
f3 /= p_aspect;
|
||||
|
||||
switch (p_eye) {
|
||||
case 1: { // left eye
|
||||
set_frustum(-f2 * p_z_near, f1 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
|
||||
}; break;
|
||||
case 2: { // right eye
|
||||
set_frustum(-f1 * p_z_near, f2 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far);
|
||||
}; break;
|
||||
default: { // mono, does not apply here!
|
||||
}; break;
|
||||
};
|
||||
};
|
||||
|
||||
void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) {
|
||||
set_identity();
|
||||
|
||||
matrix[0][0] = 2.0 / (p_right - p_left);
|
||||
matrix[3][0] = -((p_right + p_left) / (p_right - p_left));
|
||||
matrix[1][1] = 2.0 / (p_top - p_bottom);
|
||||
matrix[3][1] = -((p_top + p_bottom) / (p_top - p_bottom));
|
||||
matrix[2][2] = -2.0 / (p_zfar - p_znear);
|
||||
matrix[3][2] = -((p_zfar + p_znear) / (p_zfar - p_znear));
|
||||
matrix[3][3] = 1.0;
|
||||
}
|
||||
|
||||
void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) {
|
||||
if (!p_flip_fov) {
|
||||
p_size *= p_aspect;
|
||||
}
|
||||
|
||||
set_orthogonal(-p_size / 2, +p_size / 2, -p_size / p_aspect / 2, +p_size / p_aspect / 2, p_znear, p_zfar);
|
||||
}
|
||||
|
||||
void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) {
|
||||
ERR_FAIL_COND(p_right <= p_left);
|
||||
ERR_FAIL_COND(p_top <= p_bottom);
|
||||
ERR_FAIL_COND(p_far <= p_near);
|
||||
|
||||
real_t *te = &matrix[0][0];
|
||||
real_t x = 2 * p_near / (p_right - p_left);
|
||||
real_t y = 2 * p_near / (p_top - p_bottom);
|
||||
|
||||
real_t a = (p_right + p_left) / (p_right - p_left);
|
||||
real_t b = (p_top + p_bottom) / (p_top - p_bottom);
|
||||
real_t c = -(p_far + p_near) / (p_far - p_near);
|
||||
real_t d = -2 * p_far * p_near / (p_far - p_near);
|
||||
|
||||
te[0] = x;
|
||||
te[1] = 0;
|
||||
te[2] = 0;
|
||||
te[3] = 0;
|
||||
te[4] = 0;
|
||||
te[5] = y;
|
||||
te[6] = 0;
|
||||
te[7] = 0;
|
||||
te[8] = a;
|
||||
te[9] = b;
|
||||
te[10] = c;
|
||||
te[11] = -1;
|
||||
te[12] = 0;
|
||||
te[13] = 0;
|
||||
te[14] = d;
|
||||
te[15] = 0;
|
||||
}
|
||||
|
||||
void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
|
||||
if (!p_flip_fov) {
|
||||
p_size *= p_aspect;
|
||||
}
|
||||
|
||||
set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far);
|
||||
}
|
||||
|
||||
real_t CameraMatrix::get_z_far() const {
|
||||
const real_t *matrix = (const real_t *)this->matrix;
|
||||
Plane new_plane = Plane(matrix[3] - matrix[2],
|
||||
matrix[7] - matrix[6],
|
||||
matrix[11] - matrix[10],
|
||||
matrix[15] - matrix[14]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
return new_plane.d;
|
||||
}
|
||||
real_t CameraMatrix::get_z_near() const {
|
||||
const real_t *matrix = (const real_t *)this->matrix;
|
||||
Plane new_plane = Plane(matrix[3] + matrix[2],
|
||||
matrix[7] + matrix[6],
|
||||
matrix[11] + matrix[10],
|
||||
-matrix[15] - matrix[14]);
|
||||
|
||||
new_plane.normalize();
|
||||
return new_plane.d;
|
||||
}
|
||||
|
||||
Vector2 CameraMatrix::get_viewport_half_extents() const {
|
||||
const real_t *matrix = (const real_t *)this->matrix;
|
||||
///////--- Near Plane ---///////
|
||||
Plane near_plane = Plane(matrix[3] + matrix[2],
|
||||
matrix[7] + matrix[6],
|
||||
matrix[11] + matrix[10],
|
||||
-matrix[15] - matrix[14]);
|
||||
near_plane.normalize();
|
||||
|
||||
///////--- Right Plane ---///////
|
||||
Plane right_plane = Plane(matrix[3] - matrix[0],
|
||||
matrix[7] - matrix[4],
|
||||
matrix[11] - matrix[8],
|
||||
-matrix[15] + matrix[12]);
|
||||
right_plane.normalize();
|
||||
|
||||
Plane top_plane = Plane(matrix[3] - matrix[1],
|
||||
matrix[7] - matrix[5],
|
||||
matrix[11] - matrix[9],
|
||||
-matrix[15] + matrix[13]);
|
||||
top_plane.normalize();
|
||||
|
||||
Vector3 res;
|
||||
near_plane.intersect_3(right_plane, top_plane, &res);
|
||||
|
||||
return Vector2(res.x, res.y);
|
||||
}
|
||||
|
||||
bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
|
||||
std::vector<Plane> planes = get_projection_planes(Transform());
|
||||
const Planes intersections[8][3] = {
|
||||
{ PLANE_FAR, PLANE_LEFT, PLANE_TOP },
|
||||
{ PLANE_FAR, PLANE_LEFT, PLANE_BOTTOM },
|
||||
{ PLANE_FAR, PLANE_RIGHT, PLANE_TOP },
|
||||
{ PLANE_FAR, PLANE_RIGHT, PLANE_BOTTOM },
|
||||
{ PLANE_NEAR, PLANE_LEFT, PLANE_TOP },
|
||||
{ PLANE_NEAR, PLANE_LEFT, PLANE_BOTTOM },
|
||||
{ PLANE_NEAR, PLANE_RIGHT, PLANE_TOP },
|
||||
{ PLANE_NEAR, PLANE_RIGHT, PLANE_BOTTOM },
|
||||
};
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Vector3 point;
|
||||
bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]], planes[intersections[i][2]], &point);
|
||||
ERR_FAIL_COND_V(!res, false);
|
||||
p_8points[i] = p_transform.xform(point);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) const {
|
||||
/** Fast Plane Extraction from combined modelview/projection matrices.
|
||||
* References:
|
||||
* https://web.archive.org/web/20011221205252/http://www.markmorley.com/opengl/frustumculling.html
|
||||
* https://web.archive.org/web/20061020020112/http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf
|
||||
*/
|
||||
|
||||
std::vector<Plane> planes;
|
||||
|
||||
const real_t *matrix = (const real_t *)this->matrix;
|
||||
|
||||
Plane new_plane;
|
||||
|
||||
///////--- Near Plane ---///////
|
||||
new_plane = Plane(matrix[3] + matrix[2],
|
||||
matrix[7] + matrix[6],
|
||||
matrix[11] + matrix[10],
|
||||
matrix[15] + matrix[14]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes.push_back(p_transform.xform(new_plane));
|
||||
|
||||
///////--- Far Plane ---///////
|
||||
new_plane = Plane(matrix[3] - matrix[2],
|
||||
matrix[7] - matrix[6],
|
||||
matrix[11] - matrix[10],
|
||||
matrix[15] - matrix[14]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes.push_back(p_transform.xform(new_plane));
|
||||
|
||||
///////--- Left Plane ---///////
|
||||
new_plane = Plane(matrix[3] + matrix[0],
|
||||
matrix[7] + matrix[4],
|
||||
matrix[11] + matrix[8],
|
||||
matrix[15] + matrix[12]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes.push_back(p_transform.xform(new_plane));
|
||||
|
||||
///////--- Top Plane ---///////
|
||||
new_plane = Plane(matrix[3] - matrix[1],
|
||||
matrix[7] - matrix[5],
|
||||
matrix[11] - matrix[9],
|
||||
matrix[15] - matrix[13]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes.push_back(p_transform.xform(new_plane));
|
||||
|
||||
///////--- Right Plane ---///////
|
||||
new_plane = Plane(matrix[3] - matrix[0],
|
||||
matrix[7] - matrix[4],
|
||||
matrix[11] - matrix[8],
|
||||
matrix[15] - matrix[12]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes.push_back(p_transform.xform(new_plane));
|
||||
|
||||
///////--- Bottom Plane ---///////
|
||||
new_plane = Plane(matrix[3] + matrix[1],
|
||||
matrix[7] + matrix[5],
|
||||
matrix[11] + matrix[9],
|
||||
matrix[15] + matrix[13]);
|
||||
|
||||
new_plane.normal = -new_plane.normal;
|
||||
new_plane.normalize();
|
||||
|
||||
planes.push_back(p_transform.xform(new_plane));
|
||||
|
||||
return planes;
|
||||
}
|
||||
|
||||
CameraMatrix CameraMatrix::inverse() const {
|
||||
CameraMatrix cm = *this;
|
||||
cm.invert();
|
||||
return cm;
|
||||
}
|
||||
|
||||
void CameraMatrix::invert() {
|
||||
int i, j, k;
|
||||
int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */
|
||||
real_t pvt_val; /* Value of current pivot element */
|
||||
real_t hold; /* Temporary storage */
|
||||
real_t determinat; /* Determinant */
|
||||
|
||||
determinat = 1.0;
|
||||
for (k = 0; k < 4; k++) {
|
||||
/** Locate k'th pivot element **/
|
||||
pvt_val = matrix[k][k]; /** Initialize for search **/
|
||||
pvt_i[k] = k;
|
||||
pvt_j[k] = k;
|
||||
for (i = k; i < 4; i++) {
|
||||
for (j = k; j < 4; j++) {
|
||||
if (absd(matrix[i][j]) > absd(pvt_val)) {
|
||||
pvt_i[k] = i;
|
||||
pvt_j[k] = j;
|
||||
pvt_val = matrix[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Product of pivots, gives determinant when finished **/
|
||||
determinat *= pvt_val;
|
||||
if (absd(determinat) < 1e-7) {
|
||||
return; //(false); /** Matrix is singular (zero determinant). **/
|
||||
}
|
||||
|
||||
/** "Interchange" rows (with sign change stuff) **/
|
||||
i = pvt_i[k];
|
||||
if (i != k) { /** If rows are different **/
|
||||
for (j = 0; j < 4; j++) {
|
||||
hold = -matrix[k][j];
|
||||
matrix[k][j] = matrix[i][j];
|
||||
matrix[i][j] = hold;
|
||||
}
|
||||
}
|
||||
|
||||
/** "Interchange" columns **/
|
||||
j = pvt_j[k];
|
||||
if (j != k) { /** If columns are different **/
|
||||
for (i = 0; i < 4; i++) {
|
||||
hold = -matrix[i][k];
|
||||
matrix[i][k] = matrix[i][j];
|
||||
matrix[i][j] = hold;
|
||||
}
|
||||
}
|
||||
|
||||
/** Divide column by minus pivot value **/
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (i != k)
|
||||
matrix[i][k] /= (-pvt_val);
|
||||
}
|
||||
|
||||
/** Reduce the matrix **/
|
||||
for (i = 0; i < 4; i++) {
|
||||
hold = matrix[i][k];
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (i != k && j != k)
|
||||
matrix[i][j] += hold * matrix[k][j];
|
||||
}
|
||||
}
|
||||
|
||||
/** Divide row by pivot **/
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (j != k)
|
||||
matrix[k][j] /= pvt_val;
|
||||
}
|
||||
|
||||
/** Replace pivot by reciprocal (at last we can touch it). **/
|
||||
matrix[k][k] = 1.0 / pvt_val;
|
||||
}
|
||||
|
||||
/* That was most of the work, one final pass of row/column interchange */
|
||||
/* to finish */
|
||||
for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/
|
||||
i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
|
||||
if (i != k) { /* If rows are different */
|
||||
for (j = 0; j < 4; j++) {
|
||||
hold = matrix[k][j];
|
||||
matrix[k][j] = -matrix[i][j];
|
||||
matrix[i][j] = hold;
|
||||
}
|
||||
}
|
||||
|
||||
j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */
|
||||
if (j != k) /* If columns are different */
|
||||
for (i = 0; i < 4; i++) {
|
||||
hold = matrix[i][k];
|
||||
matrix[i][k] = -matrix[i][j];
|
||||
matrix[i][j] = hold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CameraMatrix::CameraMatrix() {
|
||||
set_identity();
|
||||
}
|
||||
|
||||
CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const {
|
||||
CameraMatrix new_matrix;
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
real_t ab = 0;
|
||||
for (int k = 0; k < 4; k++)
|
||||
ab += matrix[k][i] * p_matrix.matrix[j][k];
|
||||
new_matrix.matrix[j][i] = ab;
|
||||
}
|
||||
}
|
||||
|
||||
return new_matrix;
|
||||
}
|
||||
|
||||
void CameraMatrix::set_light_bias() {
|
||||
real_t *m = &matrix[0][0];
|
||||
|
||||
m[0] = 0.5;
|
||||
m[1] = 0.0;
|
||||
m[2] = 0.0;
|
||||
m[3] = 0.0;
|
||||
m[4] = 0.0;
|
||||
m[5] = 0.5;
|
||||
m[6] = 0.0;
|
||||
m[7] = 0.0;
|
||||
m[8] = 0.0;
|
||||
m[9] = 0.0;
|
||||
m[10] = 0.5;
|
||||
m[11] = 0.0;
|
||||
m[12] = 0.5;
|
||||
m[13] = 0.5;
|
||||
m[14] = 0.5;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) {
|
||||
real_t *m = &matrix[0][0];
|
||||
|
||||
m[0] = p_rect.size.width;
|
||||
m[1] = 0.0;
|
||||
m[2] = 0.0;
|
||||
m[3] = 0.0;
|
||||
m[4] = 0.0;
|
||||
m[5] = p_rect.size.height;
|
||||
m[6] = 0.0;
|
||||
m[7] = 0.0;
|
||||
m[8] = 0.0;
|
||||
m[9] = 0.0;
|
||||
m[10] = 1.0;
|
||||
m[11] = 0.0;
|
||||
m[12] = p_rect.position.x;
|
||||
m[13] = p_rect.position.y;
|
||||
m[14] = 0.0;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
CameraMatrix::operator String() const {
|
||||
String str;
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < 4; j++)
|
||||
str += String((j > 0) ? ", " : "\n") + String::num(matrix[i][j]);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
real_t CameraMatrix::get_aspect() const {
|
||||
Vector2 vp_he = get_viewport_half_extents();
|
||||
return vp_he.x / vp_he.y;
|
||||
}
|
||||
|
||||
int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const {
|
||||
Vector3 result = xform(Vector3(1, 0, -1));
|
||||
|
||||
return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
|
||||
}
|
||||
|
||||
bool CameraMatrix::is_orthogonal() const {
|
||||
return matrix[3][3] == 1.0;
|
||||
}
|
||||
|
||||
real_t CameraMatrix::get_fov() const {
|
||||
const real_t *matrix = (const real_t *)this->matrix;
|
||||
|
||||
Plane right_plane = Plane(matrix[3] - matrix[0],
|
||||
matrix[7] - matrix[4],
|
||||
matrix[11] - matrix[8],
|
||||
-matrix[15] + matrix[12]);
|
||||
right_plane.normalize();
|
||||
|
||||
if ((matrix[8] == 0) && (matrix[9] == 0)) {
|
||||
return Math::rad2deg(acos(std::abs(right_plane.normal.x))) * 2.0;
|
||||
} else {
|
||||
// our frustum is asymmetrical need to calculate the left planes angle separately..
|
||||
Plane left_plane = Plane(matrix[3] + matrix[0],
|
||||
matrix[7] + matrix[4],
|
||||
matrix[11] + matrix[8],
|
||||
matrix[15] + matrix[12]);
|
||||
left_plane.normalize();
|
||||
|
||||
return Math::rad2deg(acos(std::abs(left_plane.normal.x))) + Math::rad2deg(acos(std::abs(right_plane.normal.x)));
|
||||
}
|
||||
}
|
||||
|
||||
void CameraMatrix::make_scale(const Vector3 &p_scale) {
|
||||
set_identity();
|
||||
matrix[0][0] = p_scale.x;
|
||||
matrix[1][1] = p_scale.y;
|
||||
matrix[2][2] = p_scale.z;
|
||||
}
|
||||
|
||||
void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) {
|
||||
Vector3 min = p_aabb.position;
|
||||
Vector3 max = p_aabb.position + p_aabb.size;
|
||||
|
||||
matrix[0][0] = 2 / (max.x - min.x);
|
||||
matrix[1][0] = 0;
|
||||
matrix[2][0] = 0;
|
||||
matrix[3][0] = -(max.x + min.x) / (max.x - min.x);
|
||||
|
||||
matrix[0][1] = 0;
|
||||
matrix[1][1] = 2 / (max.y - min.y);
|
||||
matrix[2][1] = 0;
|
||||
matrix[3][1] = -(max.y + min.y) / (max.y - min.y);
|
||||
|
||||
matrix[0][2] = 0;
|
||||
matrix[1][2] = 0;
|
||||
matrix[2][2] = 2 / (max.z - min.z);
|
||||
matrix[3][2] = -(max.z + min.z) / (max.z - min.z);
|
||||
|
||||
matrix[0][3] = 0;
|
||||
matrix[1][3] = 0;
|
||||
matrix[2][3] = 0;
|
||||
matrix[3][3] = 1;
|
||||
}
|
||||
|
||||
CameraMatrix::operator Transform() const {
|
||||
Transform tr;
|
||||
const real_t *m = &matrix[0][0];
|
||||
|
||||
tr.basis.elements[0][0] = m[0];
|
||||
tr.basis.elements[1][0] = m[1];
|
||||
tr.basis.elements[2][0] = m[2];
|
||||
|
||||
tr.basis.elements[0][1] = m[4];
|
||||
tr.basis.elements[1][1] = m[5];
|
||||
tr.basis.elements[2][1] = m[6];
|
||||
|
||||
tr.basis.elements[0][2] = m[8];
|
||||
tr.basis.elements[1][2] = m[9];
|
||||
tr.basis.elements[2][2] = m[10];
|
||||
|
||||
tr.origin.x = m[12];
|
||||
tr.origin.y = m[13];
|
||||
tr.origin.z = m[14];
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
CameraMatrix::CameraMatrix(const Transform &p_transform) {
|
||||
const Transform &tr = p_transform;
|
||||
real_t *m = &matrix[0][0];
|
||||
|
||||
m[0] = tr.basis.elements[0][0];
|
||||
m[1] = tr.basis.elements[1][0];
|
||||
m[2] = tr.basis.elements[2][0];
|
||||
m[3] = 0.0;
|
||||
m[4] = tr.basis.elements[0][1];
|
||||
m[5] = tr.basis.elements[1][1];
|
||||
m[6] = tr.basis.elements[2][1];
|
||||
m[7] = 0.0;
|
||||
m[8] = tr.basis.elements[0][2];
|
||||
m[9] = tr.basis.elements[1][2];
|
||||
m[10] = tr.basis.elements[2][2];
|
||||
m[11] = 0.0;
|
||||
m[12] = tr.origin.x;
|
||||
m[13] = tr.origin.y;
|
||||
m[14] = tr.origin.z;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
CameraMatrix::~CameraMatrix() {
|
||||
}
|
||||
@@ -1,655 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Color.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Color.hpp"
|
||||
#include "Defs.hpp"
|
||||
#include "String.hpp"
|
||||
|
||||
#include <gdnative/color.h>
|
||||
#include <cmath>
|
||||
|
||||
namespace godot {
|
||||
|
||||
#define MIN(a, b) (a < b ? a : b)
|
||||
#define MAX(a, b) (a > b ? a : b)
|
||||
|
||||
static String _to_hex(float p_val);
|
||||
|
||||
static float _parse_col(const String &p_str, int p_ofs) {
|
||||
int ig = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
int c = (int)(wchar_t)p_str[i + p_ofs];
|
||||
int v = 0;
|
||||
|
||||
if (c >= '0' && c <= '9') {
|
||||
v = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
v = c - 'a';
|
||||
v += 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
v = c - 'A';
|
||||
v += 10;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
ig += v * 16;
|
||||
else
|
||||
ig += v;
|
||||
}
|
||||
|
||||
return ig;
|
||||
}
|
||||
|
||||
uint32_t Color::to_32() const {
|
||||
uint32_t c = (uint8_t)(a * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(r * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_ARGB32() const {
|
||||
uint32_t c = (uint8_t)(a * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(r * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_ABGR32() const {
|
||||
uint32_t c = (uint8_t)(a * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(r * 255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint64_t Color::to_ABGR64() const {
|
||||
uint64_t c = (uint16_t)(a * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(b * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(g * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(r * 65535);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint64_t Color::to_ARGB64() const {
|
||||
uint64_t c = (uint16_t)(a * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(r * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(g * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(b * 65535);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t Color::to_RGBA32() const {
|
||||
uint32_t c = (uint8_t)(r * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(g * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(b * 255);
|
||||
c <<= 8;
|
||||
c |= (uint8_t)(a * 255);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint64_t Color::to_RGBA64() const {
|
||||
uint64_t c = (uint16_t)(r * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(g * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(b * 65535);
|
||||
c <<= 16;
|
||||
c |= (uint16_t)(a * 65535);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
float Color::gray() const {
|
||||
return (r + g + b) / 3.0;
|
||||
}
|
||||
|
||||
uint8_t Color::get_r8() const {
|
||||
return (uint8_t)(r * 255.0);
|
||||
}
|
||||
|
||||
uint8_t Color::get_g8() const {
|
||||
return (uint8_t)(g * 255.0);
|
||||
}
|
||||
|
||||
uint8_t Color::get_b8() const {
|
||||
return (uint8_t)(b * 255.0);
|
||||
}
|
||||
|
||||
uint8_t Color::get_a8() const {
|
||||
return (uint8_t)(a * 255.0);
|
||||
}
|
||||
|
||||
float Color::get_h() const {
|
||||
float min = MIN(r, g);
|
||||
min = MIN(min, b);
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
|
||||
float delta = max - min;
|
||||
|
||||
if (delta == 0)
|
||||
return 0;
|
||||
|
||||
float h;
|
||||
if (r == max)
|
||||
h = (g - b) / delta; // between yellow & magenta
|
||||
else if (g == max)
|
||||
h = 2 + (b - r) / delta; // between cyan & yellow
|
||||
else
|
||||
h = 4 + (r - g) / delta; // between magenta & cyan
|
||||
|
||||
h /= 6.0;
|
||||
if (h < 0)
|
||||
h += 1.0;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
float Color::get_s() const {
|
||||
float min = MIN(r, g);
|
||||
min = MIN(min, b);
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
float delta = max - min;
|
||||
return (max != 0) ? (delta / max) : 0;
|
||||
}
|
||||
|
||||
float Color::get_v() const {
|
||||
float max = MAX(r, g);
|
||||
max = MAX(max, b);
|
||||
return max;
|
||||
}
|
||||
|
||||
void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
|
||||
int i;
|
||||
float f, p, q, t;
|
||||
a = p_alpha;
|
||||
|
||||
if (p_s == 0) {
|
||||
// acp_hromatic (grey)
|
||||
r = g = b = p_v;
|
||||
return;
|
||||
}
|
||||
|
||||
p_h *= 6.0;
|
||||
p_h = ::fmod(p_h, 6);
|
||||
i = ::floor(p_h);
|
||||
|
||||
f = p_h - i;
|
||||
p = p_v * (1 - p_s);
|
||||
q = p_v * (1 - p_s * f);
|
||||
t = p_v * (1 - p_s * (1 - f));
|
||||
|
||||
switch (i) {
|
||||
case 0: // Red is the dominant color
|
||||
r = p_v;
|
||||
g = t;
|
||||
b = p;
|
||||
break;
|
||||
case 1: // Green is the dominant color
|
||||
r = q;
|
||||
g = p_v;
|
||||
b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p;
|
||||
g = p_v;
|
||||
b = t;
|
||||
break;
|
||||
case 3: // Blue is the dominant color
|
||||
r = p;
|
||||
g = q;
|
||||
b = p_v;
|
||||
break;
|
||||
case 4:
|
||||
r = t;
|
||||
g = p;
|
||||
b = p_v;
|
||||
break;
|
||||
default: // (5) Red is the dominant color
|
||||
r = p_v;
|
||||
g = p;
|
||||
b = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Color Color::darkened(const float p_amount) const {
|
||||
Color res = *this;
|
||||
res.r = res.r * (1.0f - p_amount);
|
||||
res.g = res.g * (1.0f - p_amount);
|
||||
res.b = res.b * (1.0f - p_amount);
|
||||
return res;
|
||||
}
|
||||
|
||||
Color Color::lightened(const float p_amount) const {
|
||||
Color res = *this;
|
||||
res.r = res.r + (1.0f - res.r) * p_amount;
|
||||
res.g = res.g + (1.0f - res.g) * p_amount;
|
||||
res.b = res.b + (1.0f - res.b) * p_amount;
|
||||
return res;
|
||||
}
|
||||
|
||||
Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const {
|
||||
p_h = ::fmod(p_h * 360.0f, 360.0f);
|
||||
if (p_h < 0.0)
|
||||
p_h += 360.0f;
|
||||
|
||||
const float h_ = p_h / 60.0f;
|
||||
const float c = p_v * p_s;
|
||||
const float x = c * (1.0f - ::fabs(::fmod(h_, 2.0f) - 1.0f));
|
||||
float r, g, b;
|
||||
|
||||
switch ((int)h_) {
|
||||
case 0: {
|
||||
r = c;
|
||||
g = x;
|
||||
b = 0;
|
||||
} break;
|
||||
case 1: {
|
||||
r = x;
|
||||
g = c;
|
||||
b = 0;
|
||||
} break;
|
||||
case 2: {
|
||||
r = 0;
|
||||
g = c;
|
||||
b = x;
|
||||
} break;
|
||||
case 3: {
|
||||
r = 0;
|
||||
g = x;
|
||||
b = c;
|
||||
} break;
|
||||
case 4: {
|
||||
r = x;
|
||||
g = 0;
|
||||
b = c;
|
||||
} break;
|
||||
case 5: {
|
||||
r = c;
|
||||
g = 0;
|
||||
b = x;
|
||||
} break;
|
||||
default: {
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
} break;
|
||||
}
|
||||
|
||||
const float m = p_v - c;
|
||||
return Color(m + r, m + g, m + b, p_a);
|
||||
}
|
||||
|
||||
void Color::invert() {
|
||||
r = 1.0 - r;
|
||||
g = 1.0 - g;
|
||||
b = 1.0 - b;
|
||||
}
|
||||
|
||||
void Color::contrast() {
|
||||
r = ::fmod(r + 0.5, 1.0);
|
||||
g = ::fmod(g + 0.5, 1.0);
|
||||
b = ::fmod(b + 0.5, 1.0);
|
||||
}
|
||||
Color Color::inverted() const {
|
||||
Color c = *this;
|
||||
c.invert();
|
||||
return c;
|
||||
}
|
||||
Color Color::contrasted() const {
|
||||
Color c = *this;
|
||||
c.contrast();
|
||||
return c;
|
||||
}
|
||||
|
||||
Color Color::linear_interpolate(const Color &p_b, float p_t) const {
|
||||
Color res = *this;
|
||||
|
||||
res.r += (p_t * (p_b.r - r));
|
||||
res.g += (p_t * (p_b.g - g));
|
||||
res.b += (p_t * (p_b.b - b));
|
||||
res.a += (p_t * (p_b.a - a));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Color Color::blend(const Color &p_over) const {
|
||||
Color res;
|
||||
float sa = 1.0 - p_over.a;
|
||||
res.a = a * sa + p_over.a;
|
||||
if (res.a == 0) {
|
||||
return Color(0, 0, 0, 0);
|
||||
} else {
|
||||
res.r = (r * a * sa + p_over.r * p_over.a) / res.a;
|
||||
res.g = (g * a * sa + p_over.g * p_over.a) / res.a;
|
||||
res.b = (b * a * sa + p_over.b * p_over.a) / res.a;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Color Color::to_linear() const {
|
||||
return Color(
|
||||
r < 0.04045 ? r * (1.0 / 12.92) : ::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
g < 0.04045 ? g * (1.0 / 12.92) : ::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
b < 0.04045 ? b * (1.0 / 12.92) : ::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
|
||||
a);
|
||||
}
|
||||
|
||||
Color Color::hex(uint32_t p_hex) {
|
||||
float a = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float b = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float g = (p_hex & 0xFF) / 255.0;
|
||||
p_hex >>= 8;
|
||||
float r = (p_hex & 0xFF) / 255.0;
|
||||
|
||||
return Color(r, g, b, a);
|
||||
}
|
||||
|
||||
Color Color::html(const String &p_color) {
|
||||
String color = p_color;
|
||||
if (color.length() == 0)
|
||||
return Color();
|
||||
if (color[0] == '#')
|
||||
color = color.substr(1, color.length() - 1);
|
||||
|
||||
bool alpha = false;
|
||||
|
||||
if (color.length() == 8) {
|
||||
alpha = true;
|
||||
} else if (color.length() == 6) {
|
||||
alpha = false;
|
||||
} else {
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
|
||||
int a = 255;
|
||||
if (alpha) {
|
||||
a = _parse_col(color, 0);
|
||||
if (a < 0) {
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
}
|
||||
|
||||
int from = alpha ? 2 : 0;
|
||||
|
||||
int r = _parse_col(color, from + 0);
|
||||
if (r < 0) {
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
int g = _parse_col(color, from + 2);
|
||||
if (g < 0) {
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
int b = _parse_col(color, from + 4);
|
||||
if (b < 0) {
|
||||
ERR_PRINTS(String("Invalid Color Code: ") + p_color);
|
||||
ERR_FAIL_V(Color());
|
||||
}
|
||||
|
||||
return Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
|
||||
}
|
||||
|
||||
bool Color::html_is_valid(const String &p_color) {
|
||||
String color = p_color;
|
||||
|
||||
if (color.length() == 0)
|
||||
return false;
|
||||
if (color[0] == '#')
|
||||
color = color.substr(1, color.length() - 1);
|
||||
|
||||
bool alpha = false;
|
||||
|
||||
if (color.length() == 8) {
|
||||
alpha = true;
|
||||
} else if (color.length() == 6) {
|
||||
alpha = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
int a = 255;
|
||||
if (alpha) {
|
||||
a = _parse_col(color, 0);
|
||||
if (a < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int from = alpha ? 2 : 0;
|
||||
|
||||
int r = _parse_col(color, from + 0);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
}
|
||||
int g = _parse_col(color, from + 2);
|
||||
if (g < 0) {
|
||||
return false;
|
||||
}
|
||||
int b = _parse_col(color, from + 4);
|
||||
if (b < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef CLAMP
|
||||
#define CLAMP(m_a, m_min, m_max) (((m_a) < (m_min)) ? (m_min) : (((m_a) > (m_max)) ? m_max : m_a))
|
||||
#endif
|
||||
static String _to_hex(float p_val) {
|
||||
int v = p_val * 255;
|
||||
v = CLAMP(v, 0, 255);
|
||||
String ret;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
wchar_t c[2] = { 0, 0 };
|
||||
int lv = v & 0xF;
|
||||
if (lv < 10)
|
||||
c[0] = '0' + lv;
|
||||
else
|
||||
c[0] = 'a' + lv - 10;
|
||||
|
||||
v >>= 4;
|
||||
String cs = (const wchar_t *)c;
|
||||
ret = cs + ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Color::to_html(bool p_alpha) const {
|
||||
String txt;
|
||||
txt += _to_hex(r);
|
||||
txt += _to_hex(g);
|
||||
txt += _to_hex(b);
|
||||
if (p_alpha)
|
||||
txt = _to_hex(a) + txt;
|
||||
return txt;
|
||||
}
|
||||
|
||||
Color::operator String() const {
|
||||
return String::num(r) + ", " + String::num(g) + ", " + String::num(b) + ", " + String::num(a);
|
||||
}
|
||||
|
||||
bool Color::operator<(const Color &p_color) const {
|
||||
if (r == p_color.r) {
|
||||
if (g == p_color.g) {
|
||||
if (b == p_color.b) {
|
||||
return (a < p_color.a);
|
||||
} else
|
||||
return (b < p_color.b);
|
||||
} else
|
||||
return g < p_color.g;
|
||||
} else
|
||||
return r < p_color.r;
|
||||
}
|
||||
|
||||
Color Color::operator+(const Color &p_color) const {
|
||||
return Color(
|
||||
r + p_color.r,
|
||||
g + p_color.g,
|
||||
b + p_color.b,
|
||||
a + p_color.a);
|
||||
}
|
||||
|
||||
void Color::operator+=(const Color &p_color) {
|
||||
r = r + p_color.r;
|
||||
g = g + p_color.g;
|
||||
b = b + p_color.b;
|
||||
a = a + p_color.a;
|
||||
}
|
||||
|
||||
Color Color::operator-(const Color &p_color) const {
|
||||
return Color(
|
||||
r - p_color.r,
|
||||
g - p_color.g,
|
||||
b - p_color.b,
|
||||
a - p_color.a);
|
||||
}
|
||||
|
||||
void Color::operator-=(const Color &p_color) {
|
||||
r = r - p_color.r;
|
||||
g = g - p_color.g;
|
||||
b = b - p_color.b;
|
||||
a = a - p_color.a;
|
||||
}
|
||||
|
||||
Color Color::operator*(const Color &p_color) const {
|
||||
return Color(
|
||||
r * p_color.r,
|
||||
g * p_color.g,
|
||||
b * p_color.b,
|
||||
a * p_color.a);
|
||||
}
|
||||
|
||||
Color Color::operator*(const real_t &rvalue) const {
|
||||
return Color(
|
||||
r * rvalue,
|
||||
g * rvalue,
|
||||
b * rvalue,
|
||||
a * rvalue);
|
||||
}
|
||||
|
||||
void Color::operator*=(const Color &p_color) {
|
||||
r = r * p_color.r;
|
||||
g = g * p_color.g;
|
||||
b = b * p_color.b;
|
||||
a = a * p_color.a;
|
||||
}
|
||||
|
||||
void Color::operator*=(const real_t &rvalue) {
|
||||
r = r * rvalue;
|
||||
g = g * rvalue;
|
||||
b = b * rvalue;
|
||||
a = a * rvalue;
|
||||
}
|
||||
|
||||
Color Color::operator/(const Color &p_color) const {
|
||||
return Color(
|
||||
r / p_color.r,
|
||||
g / p_color.g,
|
||||
b / p_color.b,
|
||||
a / p_color.a);
|
||||
}
|
||||
|
||||
Color Color::operator/(const real_t &rvalue) const {
|
||||
return Color(
|
||||
r / rvalue,
|
||||
g / rvalue,
|
||||
b / rvalue,
|
||||
a / rvalue);
|
||||
}
|
||||
|
||||
void Color::operator/=(const Color &p_color) {
|
||||
r = r / p_color.r;
|
||||
g = g / p_color.g;
|
||||
b = b / p_color.b;
|
||||
a = a / p_color.a;
|
||||
}
|
||||
|
||||
void Color::operator/=(const real_t &rvalue) {
|
||||
if (rvalue == 0) {
|
||||
r = 1.0;
|
||||
g = 1.0;
|
||||
b = 1.0;
|
||||
a = 1.0;
|
||||
} else {
|
||||
r = r / rvalue;
|
||||
g = g / rvalue;
|
||||
b = b / rvalue;
|
||||
a = a / rvalue;
|
||||
}
|
||||
}
|
||||
|
||||
Color Color::operator-() const {
|
||||
return Color(
|
||||
1.0 - r,
|
||||
1.0 - g,
|
||||
1.0 - b,
|
||||
1.0 - a);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,110 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Dictionary.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Dictionary.hpp"
|
||||
#include "Array.hpp"
|
||||
#include "GodotGlobal.hpp"
|
||||
#include "Variant.hpp"
|
||||
|
||||
namespace godot {
|
||||
|
||||
Dictionary::Dictionary() {
|
||||
godot::api->godot_dictionary_new(&_godot_dictionary);
|
||||
}
|
||||
|
||||
Dictionary::Dictionary(const Dictionary &other) {
|
||||
godot::api->godot_dictionary_new_copy(&_godot_dictionary, &other._godot_dictionary);
|
||||
}
|
||||
|
||||
Dictionary &Dictionary::operator=(const Dictionary &other) {
|
||||
godot::api->godot_dictionary_destroy(&_godot_dictionary);
|
||||
godot::api->godot_dictionary_new_copy(&_godot_dictionary, &other._godot_dictionary);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Dictionary::clear() {
|
||||
godot::api->godot_dictionary_clear(&_godot_dictionary);
|
||||
}
|
||||
|
||||
bool Dictionary::empty() const {
|
||||
return godot::api->godot_dictionary_empty(&_godot_dictionary);
|
||||
}
|
||||
|
||||
void Dictionary::erase(const Variant &key) {
|
||||
godot::api->godot_dictionary_erase(&_godot_dictionary, (godot_variant *)&key);
|
||||
}
|
||||
|
||||
bool Dictionary::has(const Variant &key) const {
|
||||
return godot::api->godot_dictionary_has(&_godot_dictionary, (godot_variant *)&key);
|
||||
}
|
||||
|
||||
bool Dictionary::has_all(const Array &keys) const {
|
||||
return godot::api->godot_dictionary_has_all(&_godot_dictionary, (godot_array *)&keys);
|
||||
}
|
||||
|
||||
uint32_t Dictionary::hash() const {
|
||||
return godot::api->godot_dictionary_hash(&_godot_dictionary);
|
||||
}
|
||||
|
||||
Array Dictionary::keys() const {
|
||||
godot_array a = godot::api->godot_dictionary_keys(&_godot_dictionary);
|
||||
return Array(a);
|
||||
}
|
||||
|
||||
Variant &Dictionary::operator[](const Variant &key) {
|
||||
godot_variant *v = godot::api->godot_dictionary_operator_index(&_godot_dictionary, (godot_variant *)&key);
|
||||
return *reinterpret_cast<Variant *>(v);
|
||||
}
|
||||
|
||||
const Variant &Dictionary::operator[](const Variant &key) const {
|
||||
// oops I did it again
|
||||
godot_variant *v = godot::api->godot_dictionary_operator_index((godot_dictionary *)&_godot_dictionary, (godot_variant *)&key);
|
||||
return *reinterpret_cast<Variant *>(v);
|
||||
}
|
||||
|
||||
int Dictionary::size() const {
|
||||
return godot::api->godot_dictionary_size(&_godot_dictionary);
|
||||
}
|
||||
|
||||
String Dictionary::to_json() const {
|
||||
godot_string s = godot::api->godot_dictionary_to_json(&_godot_dictionary);
|
||||
return String(s);
|
||||
}
|
||||
|
||||
Array Dictionary::values() const {
|
||||
godot_array a = godot::api->godot_dictionary_values(&_godot_dictionary);
|
||||
return Array(a);
|
||||
}
|
||||
|
||||
Dictionary::~Dictionary() {
|
||||
godot::api->godot_dictionary_destroy(&_godot_dictionary);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,208 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* GodotGlobal.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "GodotGlobal.hpp"
|
||||
|
||||
#include "String.hpp"
|
||||
|
||||
#include "Wrapped.hpp"
|
||||
|
||||
static GDCALLINGCONV void *wrapper_create(void *data, const void *type_tag, godot_object *instance) {
|
||||
godot::_Wrapped *wrapper_memory = (godot::_Wrapped *)godot::api->godot_alloc(sizeof(godot::_Wrapped));
|
||||
|
||||
if (!wrapper_memory)
|
||||
return NULL;
|
||||
wrapper_memory->_owner = instance;
|
||||
wrapper_memory->_type_tag = (size_t)type_tag;
|
||||
|
||||
return (void *)wrapper_memory;
|
||||
}
|
||||
|
||||
static GDCALLINGCONV void wrapper_destroy(void *data, void *wrapper) {
|
||||
if (wrapper)
|
||||
godot::api->godot_free(wrapper);
|
||||
}
|
||||
|
||||
namespace godot {
|
||||
|
||||
void *_RegisterState::nativescript_handle;
|
||||
int _RegisterState::language_index;
|
||||
|
||||
const godot_gdnative_core_api_struct *api = nullptr;
|
||||
const godot_gdnative_core_1_1_api_struct *core_1_1_api = nullptr;
|
||||
const godot_gdnative_core_1_2_api_struct *core_1_2_api = nullptr;
|
||||
|
||||
const godot_gdnative_ext_nativescript_api_struct *nativescript_api = nullptr;
|
||||
const godot_gdnative_ext_nativescript_1_1_api_struct *nativescript_1_1_api = nullptr;
|
||||
const godot_gdnative_ext_pluginscript_api_struct *pluginscript_api = nullptr;
|
||||
const godot_gdnative_ext_android_api_struct *android_api = nullptr;
|
||||
const godot_gdnative_ext_arvr_api_struct *arvr_api = nullptr;
|
||||
const godot_gdnative_ext_videodecoder_api_struct *videodecoder_api = nullptr;
|
||||
const godot_gdnative_ext_net_api_struct *net_api = nullptr;
|
||||
const godot_gdnative_ext_net_3_2_api_struct *net_3_2_api = nullptr;
|
||||
|
||||
const void *gdnlib = NULL;
|
||||
|
||||
void Godot::print(const String &message) {
|
||||
godot::api->godot_print((godot_string *)&message);
|
||||
}
|
||||
|
||||
void Godot::print_warning(const String &description, const String &function, const String &file, int line) {
|
||||
int len;
|
||||
|
||||
char *c_desc = description.alloc_c_string();
|
||||
char *c_func = function.alloc_c_string();
|
||||
char *c_file = file.alloc_c_string();
|
||||
|
||||
if (c_desc != nullptr && c_func != nullptr && c_file != nullptr) {
|
||||
godot::api->godot_print_warning(c_desc, c_func, c_file, line);
|
||||
};
|
||||
|
||||
if (c_desc != nullptr)
|
||||
godot::api->godot_free(c_desc);
|
||||
if (c_func != nullptr)
|
||||
godot::api->godot_free(c_func);
|
||||
if (c_file != nullptr)
|
||||
godot::api->godot_free(c_file);
|
||||
}
|
||||
|
||||
void Godot::print_error(const String &description, const String &function, const String &file, int line) {
|
||||
int len;
|
||||
|
||||
char *c_desc = description.alloc_c_string();
|
||||
char *c_func = function.alloc_c_string();
|
||||
char *c_file = file.alloc_c_string();
|
||||
|
||||
if (c_desc != nullptr && c_func != nullptr && c_file != nullptr) {
|
||||
godot::api->godot_print_error(c_desc, c_func, c_file, line);
|
||||
};
|
||||
|
||||
if (c_desc != nullptr)
|
||||
godot::api->godot_free(c_desc);
|
||||
if (c_func != nullptr)
|
||||
godot::api->godot_free(c_func);
|
||||
if (c_file != nullptr)
|
||||
godot::api->godot_free(c_file);
|
||||
}
|
||||
|
||||
void ___register_types();
|
||||
void ___init_method_bindings();
|
||||
|
||||
void Godot::gdnative_init(godot_gdnative_init_options *options) {
|
||||
godot::api = options->api_struct;
|
||||
godot::gdnlib = options->gd_native_library;
|
||||
|
||||
const godot_gdnative_api_struct *core_extension = godot::api->next;
|
||||
|
||||
while (core_extension) {
|
||||
if (core_extension->version.major == 1 && core_extension->version.minor == 1) {
|
||||
godot::core_1_1_api = (const godot_gdnative_core_1_1_api_struct *)core_extension;
|
||||
} else if (core_extension->version.major == 1 && core_extension->version.minor == 2) {
|
||||
godot::core_1_2_api = (const godot_gdnative_core_1_2_api_struct *)core_extension;
|
||||
}
|
||||
core_extension = core_extension->next;
|
||||
}
|
||||
|
||||
// now find our extensions
|
||||
for (int i = 0; i < godot::api->num_extensions; i++) {
|
||||
switch (godot::api->extensions[i]->type) {
|
||||
case GDNATIVE_EXT_NATIVESCRIPT: {
|
||||
godot::nativescript_api = (const godot_gdnative_ext_nativescript_api_struct *)godot::api->extensions[i];
|
||||
|
||||
const godot_gdnative_api_struct *extension = godot::nativescript_api->next;
|
||||
|
||||
while (extension) {
|
||||
if (extension->version.major == 1 && extension->version.minor == 1) {
|
||||
godot::nativescript_1_1_api = (const godot_gdnative_ext_nativescript_1_1_api_struct *)extension;
|
||||
}
|
||||
|
||||
extension = extension->next;
|
||||
}
|
||||
} break;
|
||||
case GDNATIVE_EXT_PLUGINSCRIPT: {
|
||||
godot::pluginscript_api = (const godot_gdnative_ext_pluginscript_api_struct *)godot::api->extensions[i];
|
||||
} break;
|
||||
case GDNATIVE_EXT_ANDROID: {
|
||||
godot::android_api = (const godot_gdnative_ext_android_api_struct *)godot::api->extensions[i];
|
||||
} break;
|
||||
case GDNATIVE_EXT_ARVR: {
|
||||
godot::arvr_api = (const godot_gdnative_ext_arvr_api_struct *)godot::api->extensions[i];
|
||||
} break;
|
||||
case GDNATIVE_EXT_VIDEODECODER: {
|
||||
godot::videodecoder_api = (const godot_gdnative_ext_videodecoder_api_struct *)godot::api->extensions[i];
|
||||
} break;
|
||||
case GDNATIVE_EXT_NET: {
|
||||
godot::net_api = (const godot_gdnative_ext_net_api_struct *)godot::api->extensions[i];
|
||||
|
||||
const godot_gdnative_api_struct *extension = godot::net_api->next;
|
||||
|
||||
while (extension) {
|
||||
if (extension->version.major == 3 && extension->version.minor == 2) {
|
||||
godot::net_3_2_api = (const godot_gdnative_ext_net_3_2_api_struct *)extension;
|
||||
}
|
||||
|
||||
extension = extension->next;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the `language_index` here since `__register_types()` makes use of it.
|
||||
godot_instance_binding_functions binding_funcs = {};
|
||||
binding_funcs.alloc_instance_binding_data = wrapper_create;
|
||||
binding_funcs.free_instance_binding_data = wrapper_destroy;
|
||||
|
||||
godot::_RegisterState::language_index = godot::nativescript_1_1_api->godot_nativescript_register_instance_binding_data_functions(binding_funcs);
|
||||
|
||||
// register these now
|
||||
___register_types();
|
||||
___init_method_bindings();
|
||||
}
|
||||
|
||||
void Godot::gdnative_terminate(godot_gdnative_terminate_options *options) {
|
||||
// reserved for future use.
|
||||
}
|
||||
|
||||
void Godot::gdnative_profiling_add_data(const char *p_signature, uint64_t p_time) {
|
||||
godot::nativescript_1_1_api->godot_nativescript_profiling_add_data(p_signature, p_time);
|
||||
}
|
||||
|
||||
void Godot::nativescript_init(void *handle) {
|
||||
godot::_RegisterState::nativescript_handle = handle;
|
||||
}
|
||||
|
||||
void Godot::nativescript_terminate(void *handle) {
|
||||
godot::nativescript_1_1_api->godot_nativescript_unregister_instance_binding_data_functions(godot::_RegisterState::language_index);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,114 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* NodePath.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "NodePath.hpp"
|
||||
#include "GodotGlobal.hpp"
|
||||
#include "String.hpp"
|
||||
|
||||
#include <gdnative/node_path.h>
|
||||
|
||||
namespace godot {
|
||||
|
||||
NodePath::NodePath() {
|
||||
String from = "";
|
||||
godot::api->godot_node_path_new(&_node_path, (godot_string *)&from);
|
||||
}
|
||||
|
||||
NodePath::NodePath(const NodePath &other) {
|
||||
String from = other;
|
||||
godot::api->godot_node_path_new(&_node_path, (godot_string *)&from);
|
||||
}
|
||||
|
||||
NodePath::NodePath(const String &from) {
|
||||
godot::api->godot_node_path_new(&_node_path, (godot_string *)&from);
|
||||
}
|
||||
|
||||
NodePath::NodePath(const char *contents) {
|
||||
String from = contents;
|
||||
godot::api->godot_node_path_new(&_node_path, (godot_string *)&from);
|
||||
}
|
||||
|
||||
String NodePath::get_name(const int idx) const {
|
||||
godot_string str = godot::api->godot_node_path_get_name(&_node_path, idx);
|
||||
return String(str);
|
||||
}
|
||||
|
||||
int NodePath::get_name_count() const {
|
||||
return godot::api->godot_node_path_get_name_count(&_node_path);
|
||||
}
|
||||
|
||||
String NodePath::get_subname(const int idx) const {
|
||||
godot_string str = godot::api->godot_node_path_get_subname(&_node_path, idx);
|
||||
return String(str);
|
||||
}
|
||||
|
||||
int NodePath::get_subname_count() const {
|
||||
return godot::api->godot_node_path_get_subname_count(&_node_path);
|
||||
}
|
||||
|
||||
bool NodePath::is_absolute() const {
|
||||
return godot::api->godot_node_path_is_absolute(&_node_path);
|
||||
}
|
||||
|
||||
bool NodePath::is_empty() const {
|
||||
return godot::api->godot_node_path_is_empty(&_node_path);
|
||||
}
|
||||
|
||||
NodePath NodePath::get_as_property_path() const {
|
||||
godot_node_path path = godot::core_1_1_api->godot_node_path_get_as_property_path(&_node_path);
|
||||
return NodePath(path);
|
||||
}
|
||||
String NodePath::get_concatenated_subnames() const {
|
||||
godot_string str = godot::api->godot_node_path_get_concatenated_subnames(&_node_path);
|
||||
return String(str);
|
||||
}
|
||||
|
||||
NodePath::operator String() const {
|
||||
godot_string str = godot::api->godot_node_path_as_string(&_node_path);
|
||||
return String(str);
|
||||
}
|
||||
|
||||
bool NodePath::operator==(const NodePath &other) {
|
||||
return godot::api->godot_node_path_operator_equal(&_node_path, &other._node_path);
|
||||
}
|
||||
|
||||
void NodePath::operator=(const NodePath &other) {
|
||||
godot::api->godot_node_path_destroy(&_node_path);
|
||||
|
||||
String other_string = (String)other;
|
||||
|
||||
godot::api->godot_node_path_new(&_node_path, (godot_string *)&other_string);
|
||||
}
|
||||
|
||||
NodePath::~NodePath() {
|
||||
godot::api->godot_node_path_destroy(&_node_path);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,203 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Plane.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Plane.hpp"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace godot {
|
||||
|
||||
void Plane::set_normal(const Vector3 &p_normal) {
|
||||
this->normal = p_normal;
|
||||
}
|
||||
|
||||
Vector3 Plane::project(const Vector3 &p_point) const {
|
||||
return p_point - normal * distance_to(p_point);
|
||||
}
|
||||
|
||||
void Plane::normalize() {
|
||||
real_t l = normal.length();
|
||||
if (l == 0) {
|
||||
*this = Plane(0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
normal /= l;
|
||||
d /= l;
|
||||
}
|
||||
|
||||
Plane Plane::normalized() const {
|
||||
Plane p = *this;
|
||||
p.normalize();
|
||||
return p;
|
||||
}
|
||||
|
||||
Vector3 Plane::get_any_point() const {
|
||||
return get_normal() * d;
|
||||
}
|
||||
|
||||
Vector3 Plane::get_any_perpendicular_normal() const {
|
||||
static const Vector3 p1 = Vector3(1, 0, 0);
|
||||
static const Vector3 p2 = Vector3(0, 1, 0);
|
||||
Vector3 p;
|
||||
|
||||
if (::fabs(normal.dot(p1)) > 0.99) // if too similar to p1
|
||||
p = p2; // use p2
|
||||
else
|
||||
p = p1; // use p1
|
||||
|
||||
p -= normal * normal.dot(p);
|
||||
p.normalize();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* intersections */
|
||||
|
||||
bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result) const {
|
||||
const Plane &p_plane0 = *this;
|
||||
Vector3 normal0 = p_plane0.normal;
|
||||
Vector3 normal1 = p_plane1.normal;
|
||||
Vector3 normal2 = p_plane2.normal;
|
||||
|
||||
real_t denom = vec3_cross(normal0, normal1).dot(normal2);
|
||||
|
||||
if (::fabs(denom) <= CMP_EPSILON)
|
||||
return false;
|
||||
|
||||
if (r_result) {
|
||||
*r_result = ((vec3_cross(normal1, normal2) * p_plane0.d) +
|
||||
(vec3_cross(normal2, normal0) * p_plane1.d) +
|
||||
(vec3_cross(normal0, normal1) * p_plane2.d)) /
|
||||
denom;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Plane::intersects_ray(Vector3 p_from, Vector3 p_dir, Vector3 *p_intersection) const {
|
||||
Vector3 segment = p_dir;
|
||||
real_t den = normal.dot(segment);
|
||||
|
||||
//printf("den is %i\n",den);
|
||||
if (::fabs(den) <= CMP_EPSILON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
real_t dist = (normal.dot(p_from) - d) / den;
|
||||
//printf("dist is %i\n",dist);
|
||||
|
||||
if (dist > CMP_EPSILON) { //this is a ray, before the emiting pos (p_from) doesnt exist
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
dist = -dist;
|
||||
*p_intersection = p_from + segment * dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Plane::intersects_segment(Vector3 p_begin, Vector3 p_end, Vector3 *p_intersection) const {
|
||||
Vector3 segment = p_begin - p_end;
|
||||
real_t den = normal.dot(segment);
|
||||
|
||||
//printf("den is %i\n",den);
|
||||
if (::fabs(den) <= CMP_EPSILON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
real_t dist = (normal.dot(p_begin) - d) / den;
|
||||
//printf("dist is %i\n",dist);
|
||||
|
||||
if (dist < -CMP_EPSILON || dist > (1.0 + CMP_EPSILON)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dist = -dist;
|
||||
*p_intersection = p_begin + segment * dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* misc */
|
||||
|
||||
bool Plane::is_almost_like(const Plane &p_plane) const {
|
||||
return (normal.dot(p_plane.normal) > _PLANE_EQ_DOT_EPSILON && ::fabs(d - p_plane.d) < _PLANE_EQ_D_EPSILON);
|
||||
}
|
||||
|
||||
Plane::operator String() const {
|
||||
// return normal.operator String() + ", " + rtos(d);
|
||||
return String(); // @Todo
|
||||
}
|
||||
|
||||
bool Plane::is_point_over(const Vector3 &p_point) const {
|
||||
return (normal.dot(p_point) > d);
|
||||
}
|
||||
|
||||
real_t Plane::distance_to(const Vector3 &p_point) const {
|
||||
return (normal.dot(p_point) - d);
|
||||
}
|
||||
|
||||
bool Plane::has_point(const Vector3 &p_point, real_t _epsilon) const {
|
||||
real_t dist = normal.dot(p_point) - d;
|
||||
dist = ::fabs(dist);
|
||||
return (dist <= _epsilon);
|
||||
}
|
||||
|
||||
Plane::Plane(const Vector3 &p_normal, real_t p_d) {
|
||||
normal = p_normal;
|
||||
d = p_d;
|
||||
}
|
||||
|
||||
Plane::Plane(const Vector3 &p_point, const Vector3 &p_normal) {
|
||||
normal = p_normal;
|
||||
d = p_normal.dot(p_point);
|
||||
}
|
||||
|
||||
Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir) {
|
||||
if (p_dir == CLOCKWISE)
|
||||
normal = (p_point1 - p_point3).cross(p_point1 - p_point2);
|
||||
else
|
||||
normal = (p_point1 - p_point2).cross(p_point1 - p_point3);
|
||||
|
||||
normal.normalize();
|
||||
d = normal.dot(p_point1);
|
||||
}
|
||||
|
||||
bool Plane::operator==(const Plane &p_plane) const {
|
||||
return normal == p_plane.normal && d == p_plane.d;
|
||||
}
|
||||
|
||||
bool Plane::operator!=(const Plane &p_plane) const {
|
||||
return normal != p_plane.normal || d != p_plane.d;
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,571 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* PoolArrays.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "PoolArrays.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "Defs.hpp"
|
||||
#include "GodotGlobal.hpp"
|
||||
#include "String.hpp"
|
||||
#include "Vector2.hpp"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
#include <gdnative/pool_arrays.h>
|
||||
|
||||
namespace godot {
|
||||
|
||||
PoolByteArray::PoolByteArray() {
|
||||
godot::api->godot_pool_byte_array_new(&_godot_array);
|
||||
}
|
||||
|
||||
PoolByteArray::PoolByteArray(const PoolByteArray &p_other) {
|
||||
godot::api->godot_pool_byte_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
}
|
||||
|
||||
PoolByteArray &PoolByteArray::operator=(const PoolByteArray &p_other) {
|
||||
godot::api->godot_pool_byte_array_destroy(&_godot_array);
|
||||
godot::api->godot_pool_byte_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PoolByteArray::PoolByteArray(const Array &array) {
|
||||
godot::api->godot_pool_byte_array_new_with_array(&_godot_array, (godot_array *)&array);
|
||||
}
|
||||
|
||||
PoolByteArray::Read PoolByteArray::read() const {
|
||||
Read read;
|
||||
read._read_access = godot::api->godot_pool_byte_array_read(&_godot_array);
|
||||
return read;
|
||||
}
|
||||
|
||||
PoolByteArray::Write PoolByteArray::write() {
|
||||
Write write;
|
||||
write._write_access = godot::api->godot_pool_byte_array_write(&_godot_array);
|
||||
return write;
|
||||
}
|
||||
|
||||
void PoolByteArray::append(const uint8_t data) {
|
||||
godot::api->godot_pool_byte_array_append(&_godot_array, data);
|
||||
}
|
||||
|
||||
void PoolByteArray::append_array(const PoolByteArray &array) {
|
||||
godot::api->godot_pool_byte_array_append_array(&_godot_array, &array._godot_array);
|
||||
}
|
||||
|
||||
int PoolByteArray::insert(const int idx, const uint8_t data) {
|
||||
return godot::api->godot_pool_byte_array_insert(&_godot_array, idx, data);
|
||||
}
|
||||
|
||||
void PoolByteArray::invert() {
|
||||
godot::api->godot_pool_byte_array_invert(&_godot_array);
|
||||
}
|
||||
|
||||
void PoolByteArray::push_back(const uint8_t data) {
|
||||
godot::api->godot_pool_byte_array_push_back(&_godot_array, data);
|
||||
}
|
||||
|
||||
void PoolByteArray::remove(const int idx) {
|
||||
godot::api->godot_pool_byte_array_remove(&_godot_array, idx);
|
||||
}
|
||||
|
||||
void PoolByteArray::resize(const int size) {
|
||||
godot::api->godot_pool_byte_array_resize(&_godot_array, size);
|
||||
}
|
||||
|
||||
void PoolByteArray::set(const int idx, const uint8_t data) {
|
||||
godot::api->godot_pool_byte_array_set(&_godot_array, idx, data);
|
||||
}
|
||||
|
||||
uint8_t PoolByteArray::operator[](const int idx) {
|
||||
return godot::api->godot_pool_byte_array_get(&_godot_array, idx);
|
||||
}
|
||||
|
||||
int PoolByteArray::size() const {
|
||||
return godot::api->godot_pool_byte_array_size(&_godot_array);
|
||||
}
|
||||
|
||||
PoolByteArray::~PoolByteArray() {
|
||||
godot::api->godot_pool_byte_array_destroy(&_godot_array);
|
||||
}
|
||||
|
||||
PoolIntArray::PoolIntArray() {
|
||||
godot::api->godot_pool_int_array_new(&_godot_array);
|
||||
}
|
||||
|
||||
PoolIntArray::PoolIntArray(const PoolIntArray &p_other) {
|
||||
godot::api->godot_pool_int_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
}
|
||||
|
||||
PoolIntArray &PoolIntArray::operator=(const PoolIntArray &p_other) {
|
||||
godot::api->godot_pool_int_array_destroy(&_godot_array);
|
||||
godot::api->godot_pool_int_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PoolIntArray::PoolIntArray(const Array &array) {
|
||||
godot::api->godot_pool_int_array_new_with_array(&_godot_array, (godot_array *)&array);
|
||||
}
|
||||
|
||||
PoolIntArray::Read PoolIntArray::read() const {
|
||||
Read read;
|
||||
read._read_access = godot::api->godot_pool_int_array_read(&_godot_array);
|
||||
return read;
|
||||
}
|
||||
|
||||
PoolIntArray::Write PoolIntArray::write() {
|
||||
Write write;
|
||||
write._write_access = godot::api->godot_pool_int_array_write(&_godot_array);
|
||||
return write;
|
||||
}
|
||||
|
||||
void PoolIntArray::append(const int data) {
|
||||
godot::api->godot_pool_int_array_append(&_godot_array, data);
|
||||
}
|
||||
|
||||
void PoolIntArray::append_array(const PoolIntArray &array) {
|
||||
godot::api->godot_pool_int_array_append_array(&_godot_array, &array._godot_array);
|
||||
}
|
||||
|
||||
int PoolIntArray::insert(const int idx, const int data) {
|
||||
return godot::api->godot_pool_int_array_insert(&_godot_array, idx, data);
|
||||
}
|
||||
|
||||
void PoolIntArray::invert() {
|
||||
godot::api->godot_pool_int_array_invert(&_godot_array);
|
||||
}
|
||||
|
||||
void PoolIntArray::push_back(const int data) {
|
||||
godot::api->godot_pool_int_array_push_back(&_godot_array, data);
|
||||
}
|
||||
|
||||
void PoolIntArray::remove(const int idx) {
|
||||
godot::api->godot_pool_int_array_remove(&_godot_array, idx);
|
||||
}
|
||||
|
||||
void PoolIntArray::resize(const int size) {
|
||||
godot::api->godot_pool_int_array_resize(&_godot_array, size);
|
||||
}
|
||||
|
||||
void PoolIntArray::set(const int idx, const int data) {
|
||||
godot::api->godot_pool_int_array_set(&_godot_array, idx, data);
|
||||
}
|
||||
|
||||
int PoolIntArray::operator[](const int idx) {
|
||||
return godot::api->godot_pool_int_array_get(&_godot_array, idx);
|
||||
}
|
||||
|
||||
int PoolIntArray::size() const {
|
||||
return godot::api->godot_pool_int_array_size(&_godot_array);
|
||||
}
|
||||
|
||||
PoolIntArray::~PoolIntArray() {
|
||||
godot::api->godot_pool_int_array_destroy(&_godot_array);
|
||||
}
|
||||
|
||||
PoolRealArray::PoolRealArray() {
|
||||
godot::api->godot_pool_real_array_new(&_godot_array);
|
||||
}
|
||||
|
||||
PoolRealArray::PoolRealArray(const PoolRealArray &p_other) {
|
||||
godot::api->godot_pool_real_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
}
|
||||
|
||||
PoolRealArray &PoolRealArray::operator=(const PoolRealArray &p_other) {
|
||||
godot::api->godot_pool_real_array_destroy(&_godot_array);
|
||||
godot::api->godot_pool_real_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PoolRealArray::Read PoolRealArray::read() const {
|
||||
Read read;
|
||||
read._read_access = godot::api->godot_pool_real_array_read(&_godot_array);
|
||||
return read;
|
||||
}
|
||||
|
||||
PoolRealArray::Write PoolRealArray::write() {
|
||||
Write write;
|
||||
write._write_access = godot::api->godot_pool_real_array_write(&_godot_array);
|
||||
return write;
|
||||
}
|
||||
|
||||
PoolRealArray::PoolRealArray(const Array &array) {
|
||||
godot::api->godot_pool_real_array_new_with_array(&_godot_array, (godot_array *)&array);
|
||||
}
|
||||
|
||||
void PoolRealArray::append(const real_t data) {
|
||||
godot::api->godot_pool_real_array_append(&_godot_array, data);
|
||||
}
|
||||
|
||||
void PoolRealArray::append_array(const PoolRealArray &array) {
|
||||
godot::api->godot_pool_real_array_append_array(&_godot_array, &array._godot_array);
|
||||
}
|
||||
|
||||
int PoolRealArray::insert(const int idx, const real_t data) {
|
||||
return godot::api->godot_pool_real_array_insert(&_godot_array, idx, data);
|
||||
}
|
||||
|
||||
void PoolRealArray::invert() {
|
||||
godot::api->godot_pool_real_array_invert(&_godot_array);
|
||||
}
|
||||
|
||||
void PoolRealArray::push_back(const real_t data) {
|
||||
godot::api->godot_pool_real_array_push_back(&_godot_array, data);
|
||||
}
|
||||
|
||||
void PoolRealArray::remove(const int idx) {
|
||||
godot::api->godot_pool_real_array_remove(&_godot_array, idx);
|
||||
}
|
||||
|
||||
void PoolRealArray::resize(const int size) {
|
||||
godot::api->godot_pool_real_array_resize(&_godot_array, size);
|
||||
}
|
||||
|
||||
void PoolRealArray::set(const int idx, const real_t data) {
|
||||
godot::api->godot_pool_real_array_set(&_godot_array, idx, data);
|
||||
}
|
||||
|
||||
real_t PoolRealArray::operator[](const int idx) {
|
||||
return godot::api->godot_pool_real_array_get(&_godot_array, idx);
|
||||
}
|
||||
|
||||
int PoolRealArray::size() const {
|
||||
return godot::api->godot_pool_real_array_size(&_godot_array);
|
||||
}
|
||||
|
||||
PoolRealArray::~PoolRealArray() {
|
||||
godot::api->godot_pool_real_array_destroy(&_godot_array);
|
||||
}
|
||||
|
||||
PoolStringArray::PoolStringArray() {
|
||||
godot::api->godot_pool_string_array_new(&_godot_array);
|
||||
}
|
||||
|
||||
PoolStringArray::PoolStringArray(const PoolStringArray &p_other) {
|
||||
godot::api->godot_pool_string_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
}
|
||||
|
||||
PoolStringArray &PoolStringArray::operator=(const PoolStringArray &p_other) {
|
||||
godot::api->godot_pool_string_array_destroy(&_godot_array);
|
||||
godot::api->godot_pool_string_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PoolStringArray::PoolStringArray(const Array &array) {
|
||||
godot::api->godot_pool_string_array_new_with_array(&_godot_array, (godot_array *)&array);
|
||||
}
|
||||
|
||||
PoolStringArray::Read PoolStringArray::read() const {
|
||||
Read read;
|
||||
read._read_access = godot::api->godot_pool_string_array_read(&_godot_array);
|
||||
return read;
|
||||
}
|
||||
|
||||
PoolStringArray::Write PoolStringArray::write() {
|
||||
Write write;
|
||||
write._write_access = godot::api->godot_pool_string_array_write(&_godot_array);
|
||||
return write;
|
||||
}
|
||||
|
||||
void PoolStringArray::append(const String &data) {
|
||||
godot::api->godot_pool_string_array_append(&_godot_array, (godot_string *)&data);
|
||||
}
|
||||
|
||||
void PoolStringArray::append_array(const PoolStringArray &array) {
|
||||
godot::api->godot_pool_string_array_append_array(&_godot_array, &array._godot_array);
|
||||
}
|
||||
|
||||
int PoolStringArray::insert(const int idx, const String &data) {
|
||||
return godot::api->godot_pool_string_array_insert(&_godot_array, idx, (godot_string *)&data);
|
||||
}
|
||||
|
||||
void PoolStringArray::invert() {
|
||||
godot::api->godot_pool_string_array_invert(&_godot_array);
|
||||
}
|
||||
|
||||
void PoolStringArray::push_back(const String &data) {
|
||||
godot::api->godot_pool_string_array_push_back(&_godot_array, (godot_string *)&data);
|
||||
}
|
||||
|
||||
void PoolStringArray::remove(const int idx) {
|
||||
godot::api->godot_pool_string_array_remove(&_godot_array, idx);
|
||||
}
|
||||
|
||||
void PoolStringArray::resize(const int size) {
|
||||
godot::api->godot_pool_string_array_resize(&_godot_array, size);
|
||||
}
|
||||
|
||||
void PoolStringArray::set(const int idx, const String &data) {
|
||||
godot::api->godot_pool_string_array_set(&_godot_array, idx, (godot_string *)&data);
|
||||
}
|
||||
|
||||
const String PoolStringArray::operator[](const int idx) {
|
||||
String s;
|
||||
godot_string str = godot::api->godot_pool_string_array_get(&_godot_array, idx);
|
||||
godot::api->godot_string_new_copy((godot_string *)&s, &str);
|
||||
godot::api->godot_string_destroy(&str);
|
||||
return s;
|
||||
}
|
||||
|
||||
int PoolStringArray::size() const {
|
||||
return godot::api->godot_pool_string_array_size(&_godot_array);
|
||||
}
|
||||
|
||||
PoolStringArray::~PoolStringArray() {
|
||||
godot::api->godot_pool_string_array_destroy(&_godot_array);
|
||||
}
|
||||
|
||||
PoolVector2Array::PoolVector2Array() {
|
||||
godot::api->godot_pool_vector2_array_new(&_godot_array);
|
||||
}
|
||||
|
||||
PoolVector2Array::PoolVector2Array(const PoolVector2Array &p_other) {
|
||||
godot::api->godot_pool_vector2_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
}
|
||||
|
||||
PoolVector2Array &PoolVector2Array::operator=(const PoolVector2Array &p_other) {
|
||||
godot::api->godot_pool_vector2_array_destroy(&_godot_array);
|
||||
godot::api->godot_pool_vector2_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PoolVector2Array::PoolVector2Array(const Array &array) {
|
||||
godot::api->godot_pool_vector2_array_new_with_array(&_godot_array, (godot_array *)&array);
|
||||
}
|
||||
|
||||
PoolVector2Array::Read PoolVector2Array::read() const {
|
||||
Read read;
|
||||
read._read_access = godot::api->godot_pool_vector2_array_read(&_godot_array);
|
||||
return read;
|
||||
}
|
||||
|
||||
PoolVector2Array::Write PoolVector2Array::write() {
|
||||
Write write;
|
||||
write._write_access = godot::api->godot_pool_vector2_array_write(&_godot_array);
|
||||
return write;
|
||||
}
|
||||
|
||||
void PoolVector2Array::append(const Vector2 &data) {
|
||||
godot::api->godot_pool_vector2_array_append(&_godot_array, (godot_vector2 *)&data);
|
||||
}
|
||||
|
||||
void PoolVector2Array::append_array(const PoolVector2Array &array) {
|
||||
godot::api->godot_pool_vector2_array_append_array(&_godot_array, &array._godot_array);
|
||||
}
|
||||
|
||||
int PoolVector2Array::insert(const int idx, const Vector2 &data) {
|
||||
return godot::api->godot_pool_vector2_array_insert(&_godot_array, idx, (godot_vector2 *)&data);
|
||||
}
|
||||
|
||||
void PoolVector2Array::invert() {
|
||||
godot::api->godot_pool_vector2_array_invert(&_godot_array);
|
||||
}
|
||||
|
||||
void PoolVector2Array::push_back(const Vector2 &data) {
|
||||
godot::api->godot_pool_vector2_array_push_back(&_godot_array, (godot_vector2 *)&data);
|
||||
}
|
||||
|
||||
void PoolVector2Array::remove(const int idx) {
|
||||
godot::api->godot_pool_vector2_array_remove(&_godot_array, idx);
|
||||
}
|
||||
|
||||
void PoolVector2Array::resize(const int size) {
|
||||
godot::api->godot_pool_vector2_array_resize(&_godot_array, size);
|
||||
}
|
||||
|
||||
void PoolVector2Array::set(const int idx, const Vector2 &data) {
|
||||
godot::api->godot_pool_vector2_array_set(&_godot_array, idx, (godot_vector2 *)&data);
|
||||
}
|
||||
|
||||
const Vector2 PoolVector2Array::operator[](const int idx) {
|
||||
Vector2 v;
|
||||
*(godot_vector2 *)&v = godot::api->godot_pool_vector2_array_get(&_godot_array, idx);
|
||||
return v;
|
||||
}
|
||||
|
||||
int PoolVector2Array::size() const {
|
||||
return godot::api->godot_pool_vector2_array_size(&_godot_array);
|
||||
}
|
||||
|
||||
PoolVector2Array::~PoolVector2Array() {
|
||||
godot::api->godot_pool_vector2_array_destroy(&_godot_array);
|
||||
}
|
||||
|
||||
PoolVector3Array::PoolVector3Array() {
|
||||
godot::api->godot_pool_vector3_array_new(&_godot_array);
|
||||
}
|
||||
|
||||
PoolVector3Array::PoolVector3Array(const PoolVector3Array &p_other) {
|
||||
godot::api->godot_pool_vector3_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
}
|
||||
|
||||
PoolVector3Array &PoolVector3Array::operator=(const PoolVector3Array &p_other) {
|
||||
godot::api->godot_pool_vector3_array_destroy(&_godot_array);
|
||||
godot::api->godot_pool_vector3_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PoolVector3Array::PoolVector3Array(const Array &array) {
|
||||
godot::api->godot_pool_vector3_array_new_with_array(&_godot_array, (godot_array *)&array);
|
||||
}
|
||||
|
||||
PoolVector3Array::Read PoolVector3Array::read() const {
|
||||
Read read;
|
||||
read._read_access = godot::api->godot_pool_vector3_array_read(&_godot_array);
|
||||
return read;
|
||||
}
|
||||
|
||||
PoolVector3Array::Write PoolVector3Array::write() {
|
||||
Write write;
|
||||
write._write_access = godot::api->godot_pool_vector3_array_write(&_godot_array);
|
||||
return write;
|
||||
}
|
||||
|
||||
void PoolVector3Array::append(const Vector3 &data) {
|
||||
godot::api->godot_pool_vector3_array_append(&_godot_array, (godot_vector3 *)&data);
|
||||
}
|
||||
|
||||
void PoolVector3Array::append_array(const PoolVector3Array &array) {
|
||||
godot::api->godot_pool_vector3_array_append_array(&_godot_array, &array._godot_array);
|
||||
}
|
||||
|
||||
int PoolVector3Array::insert(const int idx, const Vector3 &data) {
|
||||
return godot::api->godot_pool_vector3_array_insert(&_godot_array, idx, (godot_vector3 *)&data);
|
||||
}
|
||||
|
||||
void PoolVector3Array::invert() {
|
||||
godot::api->godot_pool_vector3_array_invert(&_godot_array);
|
||||
}
|
||||
|
||||
void PoolVector3Array::push_back(const Vector3 &data) {
|
||||
godot::api->godot_pool_vector3_array_push_back(&_godot_array, (godot_vector3 *)&data);
|
||||
}
|
||||
|
||||
void PoolVector3Array::remove(const int idx) {
|
||||
godot::api->godot_pool_vector3_array_remove(&_godot_array, idx);
|
||||
}
|
||||
|
||||
void PoolVector3Array::resize(const int size) {
|
||||
godot::api->godot_pool_vector3_array_resize(&_godot_array, size);
|
||||
}
|
||||
|
||||
void PoolVector3Array::set(const int idx, const Vector3 &data) {
|
||||
godot::api->godot_pool_vector3_array_set(&_godot_array, idx, (godot_vector3 *)&data);
|
||||
}
|
||||
|
||||
const Vector3 PoolVector3Array::operator[](const int idx) {
|
||||
Vector3 v;
|
||||
*(godot_vector3 *)&v = godot::api->godot_pool_vector3_array_get(&_godot_array, idx);
|
||||
return v;
|
||||
}
|
||||
|
||||
int PoolVector3Array::size() const {
|
||||
return godot::api->godot_pool_vector3_array_size(&_godot_array);
|
||||
}
|
||||
|
||||
PoolVector3Array::~PoolVector3Array() {
|
||||
godot::api->godot_pool_vector3_array_destroy(&_godot_array);
|
||||
}
|
||||
|
||||
PoolColorArray::PoolColorArray() {
|
||||
godot::api->godot_pool_color_array_new(&_godot_array);
|
||||
}
|
||||
|
||||
PoolColorArray::PoolColorArray(const PoolColorArray &p_other) {
|
||||
godot::api->godot_pool_color_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
}
|
||||
|
||||
PoolColorArray &PoolColorArray::operator=(const PoolColorArray &p_other) {
|
||||
godot::api->godot_pool_color_array_destroy(&_godot_array);
|
||||
godot::api->godot_pool_color_array_new_copy(&_godot_array, &p_other._godot_array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PoolColorArray::PoolColorArray(const Array &array) {
|
||||
godot::api->godot_pool_color_array_new_with_array(&_godot_array, (godot_array *)&array);
|
||||
}
|
||||
|
||||
PoolColorArray::Read PoolColorArray::read() const {
|
||||
Read read;
|
||||
read._read_access = godot::api->godot_pool_color_array_read(&_godot_array);
|
||||
return read;
|
||||
}
|
||||
|
||||
PoolColorArray::Write PoolColorArray::write() {
|
||||
Write write;
|
||||
write._write_access = godot::api->godot_pool_color_array_write(&_godot_array);
|
||||
return write;
|
||||
}
|
||||
|
||||
void PoolColorArray::append(const Color &data) {
|
||||
godot::api->godot_pool_color_array_append(&_godot_array, (godot_color *)&data);
|
||||
}
|
||||
|
||||
void PoolColorArray::append_array(const PoolColorArray &array) {
|
||||
godot::api->godot_pool_color_array_append_array(&_godot_array, &array._godot_array);
|
||||
}
|
||||
|
||||
int PoolColorArray::insert(const int idx, const Color &data) {
|
||||
return godot::api->godot_pool_color_array_insert(&_godot_array, idx, (godot_color *)&data);
|
||||
}
|
||||
|
||||
void PoolColorArray::invert() {
|
||||
godot::api->godot_pool_color_array_invert(&_godot_array);
|
||||
}
|
||||
|
||||
void PoolColorArray::push_back(const Color &data) {
|
||||
godot::api->godot_pool_color_array_push_back(&_godot_array, (godot_color *)&data);
|
||||
}
|
||||
|
||||
void PoolColorArray::remove(const int idx) {
|
||||
godot::api->godot_pool_color_array_remove(&_godot_array, idx);
|
||||
}
|
||||
|
||||
void PoolColorArray::resize(const int size) {
|
||||
godot::api->godot_pool_color_array_resize(&_godot_array, size);
|
||||
}
|
||||
|
||||
void PoolColorArray::set(const int idx, const Color &data) {
|
||||
godot::api->godot_pool_color_array_set(&_godot_array, idx, (godot_color *)&data);
|
||||
}
|
||||
|
||||
const Color PoolColorArray::operator[](const int idx) {
|
||||
Color v;
|
||||
*(godot_color *)&v = godot::api->godot_pool_color_array_get(&_godot_array, idx);
|
||||
return v;
|
||||
}
|
||||
|
||||
int PoolColorArray::size() const {
|
||||
return godot::api->godot_pool_color_array_size(&_godot_array);
|
||||
}
|
||||
|
||||
PoolColorArray::~PoolColorArray() {
|
||||
godot::api->godot_pool_color_array_destroy(&_godot_array);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,352 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Quat.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Quat.hpp"
|
||||
#include "Basis.hpp"
|
||||
#include "Defs.hpp"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const Quat Quat::IDENTITY = Quat();
|
||||
|
||||
// set_euler_xyz expects a vector containing the Euler angles in the format
|
||||
// (ax,ay,az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// This implementation uses XYZ convention (Z is the first rotation).
|
||||
void Quat::set_euler_xyz(const Vector3 &p_euler) {
|
||||
real_t half_a1 = p_euler.x * 0.5;
|
||||
real_t half_a2 = p_euler.y * 0.5;
|
||||
real_t half_a3 = p_euler.z * 0.5;
|
||||
|
||||
// R = X(a1).Y(a2).Z(a3) convention for Euler angles.
|
||||
// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-2)
|
||||
// a3 is the angle of the first rotation, following the notation in this reference.
|
||||
|
||||
real_t cos_a1 = ::cos(half_a1);
|
||||
real_t sin_a1 = ::sin(half_a1);
|
||||
real_t cos_a2 = ::cos(half_a2);
|
||||
real_t sin_a2 = ::sin(half_a2);
|
||||
real_t cos_a3 = ::cos(half_a3);
|
||||
real_t sin_a3 = ::sin(half_a3);
|
||||
|
||||
set(sin_a1 * cos_a2 * cos_a3 + sin_a2 * sin_a3 * cos_a1,
|
||||
-sin_a1 * sin_a3 * cos_a2 + sin_a2 * cos_a1 * cos_a3,
|
||||
sin_a1 * sin_a2 * cos_a3 + sin_a3 * cos_a1 * cos_a2,
|
||||
-sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
|
||||
}
|
||||
|
||||
// get_euler_xyz returns a vector containing the Euler angles in the format
|
||||
// (ax,ay,az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// This implementation uses XYZ convention (Z is the first rotation).
|
||||
Vector3 Quat::get_euler_xyz() const {
|
||||
Basis m(*this);
|
||||
return m.get_euler_xyz();
|
||||
}
|
||||
|
||||
// set_euler_yxz expects a vector containing the Euler angles in the format
|
||||
// (ax,ay,az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// This implementation uses YXZ convention (Z is the first rotation).
|
||||
void Quat::set_euler_yxz(const Vector3 &p_euler) {
|
||||
real_t half_a1 = p_euler.y * 0.5;
|
||||
real_t half_a2 = p_euler.x * 0.5;
|
||||
real_t half_a3 = p_euler.z * 0.5;
|
||||
|
||||
// R = Y(a1).X(a2).Z(a3) convention for Euler angles.
|
||||
// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
|
||||
// a3 is the angle of the first rotation, following the notation in this reference.
|
||||
|
||||
real_t cos_a1 = ::cos(half_a1);
|
||||
real_t sin_a1 = ::sin(half_a1);
|
||||
real_t cos_a2 = ::cos(half_a2);
|
||||
real_t sin_a2 = ::sin(half_a2);
|
||||
real_t cos_a3 = ::cos(half_a3);
|
||||
real_t sin_a3 = ::sin(half_a3);
|
||||
|
||||
set(sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3,
|
||||
sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3,
|
||||
-sin_a1 * sin_a2 * cos_a3 + cos_a1 * sin_a2 * sin_a3,
|
||||
sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3);
|
||||
}
|
||||
|
||||
// get_euler_yxz returns a vector containing the Euler angles in the format
|
||||
// (ax,ay,az), where ax is the angle of rotation around x axis,
|
||||
// and similar for other axes.
|
||||
// This implementation uses YXZ convention (Z is the first rotation).
|
||||
Vector3 Quat::get_euler_yxz() const {
|
||||
Basis m(*this);
|
||||
return m.get_euler_yxz();
|
||||
}
|
||||
|
||||
real_t Quat::length() const {
|
||||
return ::sqrt(length_squared());
|
||||
}
|
||||
|
||||
void Quat::normalize() {
|
||||
*this /= length();
|
||||
}
|
||||
|
||||
Quat Quat::normalized() const {
|
||||
return *this / length();
|
||||
}
|
||||
|
||||
bool Quat::is_normalized() const {
|
||||
return std::abs(length_squared() - 1.0) < 0.00001;
|
||||
}
|
||||
|
||||
Quat Quat::inverse() const {
|
||||
return Quat(-x, -y, -z, w);
|
||||
}
|
||||
|
||||
Quat Quat::slerp(const Quat &q, const real_t &t) const {
|
||||
Quat to1;
|
||||
real_t omega, cosom, sinom, scale0, scale1;
|
||||
|
||||
// calc cosine
|
||||
cosom = dot(q);
|
||||
|
||||
// adjust signs (if necessary)
|
||||
if (cosom < 0.0) {
|
||||
cosom = -cosom;
|
||||
to1.x = -q.x;
|
||||
to1.y = -q.y;
|
||||
to1.z = -q.z;
|
||||
to1.w = -q.w;
|
||||
} else {
|
||||
to1.x = q.x;
|
||||
to1.y = q.y;
|
||||
to1.z = q.z;
|
||||
to1.w = q.w;
|
||||
}
|
||||
|
||||
// calculate coefficients
|
||||
|
||||
if ((1.0 - cosom) > CMP_EPSILON) {
|
||||
// standard case (slerp)
|
||||
omega = ::acos(cosom);
|
||||
sinom = ::sin(omega);
|
||||
scale0 = ::sin((1.0 - t) * omega) / sinom;
|
||||
scale1 = ::sin(t * omega) / sinom;
|
||||
} else {
|
||||
// "from" and "to" quaternions are very close
|
||||
// ... so we can do a linear interpolation
|
||||
scale0 = 1.0 - t;
|
||||
scale1 = t;
|
||||
}
|
||||
// calculate final values
|
||||
return Quat(
|
||||
scale0 * x + scale1 * to1.x,
|
||||
scale0 * y + scale1 * to1.y,
|
||||
scale0 * z + scale1 * to1.z,
|
||||
scale0 * w + scale1 * to1.w);
|
||||
}
|
||||
|
||||
Quat Quat::slerpni(const Quat &q, const real_t &t) const {
|
||||
const Quat &from = *this;
|
||||
|
||||
real_t dot = from.dot(q);
|
||||
|
||||
if (::fabs(dot) > 0.9999)
|
||||
return from;
|
||||
|
||||
real_t theta = ::acos(dot),
|
||||
sinT = 1.0 / ::sin(theta),
|
||||
newFactor = ::sin(t * theta) * sinT,
|
||||
invFactor = ::sin((1.0 - t) * theta) * sinT;
|
||||
|
||||
return Quat(invFactor * from.x + newFactor * q.x,
|
||||
invFactor * from.y + newFactor * q.y,
|
||||
invFactor * from.z + newFactor * q.z,
|
||||
invFactor * from.w + newFactor * q.w);
|
||||
}
|
||||
|
||||
Quat Quat::cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const real_t &t) const {
|
||||
//the only way to do slerp :|
|
||||
real_t t2 = (1.0 - t) * t * 2;
|
||||
Quat sp = this->slerp(q, t);
|
||||
Quat sq = prep.slerpni(postq, t);
|
||||
return sp.slerpni(sq, t2);
|
||||
}
|
||||
|
||||
void Quat::get_axis_and_angle(Vector3 &r_axis, real_t &r_angle) const {
|
||||
r_angle = 2 * ::acos(w);
|
||||
r_axis.x = x / ::sqrt(1 - w * w);
|
||||
r_axis.y = y / ::sqrt(1 - w * w);
|
||||
r_axis.z = z / ::sqrt(1 - w * w);
|
||||
}
|
||||
|
||||
void Quat::set_axis_angle(const Vector3 &axis, const float angle) {
|
||||
ERR_FAIL_COND(!axis.is_normalized());
|
||||
|
||||
real_t d = axis.length();
|
||||
if (d == 0)
|
||||
set(0, 0, 0, 0);
|
||||
else {
|
||||
real_t sin_angle = ::sin(angle * 0.5);
|
||||
real_t cos_angle = ::cos(angle * 0.5);
|
||||
real_t s = sin_angle / d;
|
||||
set(axis.x * s, axis.y * s, axis.z * s,
|
||||
cos_angle);
|
||||
}
|
||||
}
|
||||
|
||||
Quat Quat::operator*(const Vector3 &v) const {
|
||||
return Quat(w * v.x + y * v.z - z * v.y,
|
||||
w * v.y + z * v.x - x * v.z,
|
||||
w * v.z + x * v.y - y * v.x,
|
||||
-x * v.x - y * v.y - z * v.z);
|
||||
}
|
||||
|
||||
Vector3 Quat::xform(const Vector3 &v) const {
|
||||
Quat q = *this * v;
|
||||
q *= this->inverse();
|
||||
return Vector3(q.x, q.y, q.z);
|
||||
}
|
||||
|
||||
Quat::operator String() const {
|
||||
return String(); // @Todo
|
||||
}
|
||||
|
||||
Quat::Quat(const Vector3 &axis, const real_t &angle) {
|
||||
real_t d = axis.length();
|
||||
if (d == 0)
|
||||
set(0, 0, 0, 0);
|
||||
else {
|
||||
real_t sin_angle = ::sin(angle * 0.5);
|
||||
real_t cos_angle = ::cos(angle * 0.5);
|
||||
real_t s = sin_angle / d;
|
||||
set(axis.x * s, axis.y * s, axis.z * s,
|
||||
cos_angle);
|
||||
}
|
||||
}
|
||||
|
||||
Quat::Quat(const Vector3 &v0, const Vector3 &v1) // shortest arc
|
||||
{
|
||||
Vector3 c = v0.cross(v1);
|
||||
real_t d = v0.dot(v1);
|
||||
|
||||
if (d < -1.0 + CMP_EPSILON) {
|
||||
x = 0;
|
||||
y = 1;
|
||||
z = 0;
|
||||
w = 0;
|
||||
} else {
|
||||
real_t s = ::sqrt((1.0 + d) * 2.0);
|
||||
real_t rs = 1.0 / s;
|
||||
|
||||
x = c.x * rs;
|
||||
y = c.y * rs;
|
||||
z = c.z * rs;
|
||||
w = s * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
real_t Quat::dot(const Quat &q) const {
|
||||
return x * q.x + y * q.y + z * q.z + w * q.w;
|
||||
}
|
||||
|
||||
real_t Quat::length_squared() const {
|
||||
return dot(*this);
|
||||
}
|
||||
|
||||
void Quat::operator+=(const Quat &q) {
|
||||
x += q.x;
|
||||
y += q.y;
|
||||
z += q.z;
|
||||
w += q.w;
|
||||
}
|
||||
|
||||
void Quat::operator-=(const Quat &q) {
|
||||
x -= q.x;
|
||||
y -= q.y;
|
||||
z -= q.z;
|
||||
w -= q.w;
|
||||
}
|
||||
|
||||
void Quat::operator*=(const Quat &q) {
|
||||
set(w * q.x + x * q.w + y * q.z - z * q.y,
|
||||
w * q.y + y * q.w + z * q.x - x * q.z,
|
||||
w * q.z + z * q.w + x * q.y - y * q.x,
|
||||
w * q.w - x * q.x - y * q.y - z * q.z);
|
||||
}
|
||||
|
||||
void Quat::operator*=(const real_t &s) {
|
||||
x *= s;
|
||||
y *= s;
|
||||
z *= s;
|
||||
w *= s;
|
||||
}
|
||||
|
||||
void Quat::operator/=(const real_t &s) {
|
||||
*this *= 1.0 / s;
|
||||
}
|
||||
|
||||
Quat Quat::operator+(const Quat &q2) const {
|
||||
const Quat &q1 = *this;
|
||||
return Quat(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w);
|
||||
}
|
||||
|
||||
Quat Quat::operator-(const Quat &q2) const {
|
||||
const Quat &q1 = *this;
|
||||
return Quat(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w);
|
||||
}
|
||||
|
||||
Quat Quat::operator*(const Quat &q2) const {
|
||||
Quat q1 = *this;
|
||||
q1 *= q2;
|
||||
return q1;
|
||||
}
|
||||
|
||||
Quat Quat::operator-() const {
|
||||
const Quat &q2 = *this;
|
||||
return Quat(-q2.x, -q2.y, -q2.z, -q2.w);
|
||||
}
|
||||
|
||||
Quat Quat::operator*(const real_t &s) const {
|
||||
return Quat(x * s, y * s, z * s, w * s);
|
||||
}
|
||||
|
||||
Quat Quat::operator/(const real_t &s) const {
|
||||
return *this * (1.0 / s);
|
||||
}
|
||||
|
||||
bool Quat::operator==(const Quat &p_quat) const {
|
||||
return x == p_quat.x && y == p_quat.y && z == p_quat.z && w == p_quat.w;
|
||||
}
|
||||
|
||||
bool Quat::operator!=(const Quat &p_quat) const {
|
||||
return x != p_quat.x || y != p_quat.y || z != p_quat.z || w != p_quat.w;
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,313 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Rect2.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Rect2.hpp"
|
||||
#include "String.hpp"
|
||||
#include "Transform2D.hpp"
|
||||
#include "Vector2.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace godot {
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (a > b ? a : b)
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (a < b ? a : b)
|
||||
#endif
|
||||
|
||||
real_t Rect2::distance_to(const Vector2 &p_point) const {
|
||||
real_t dist = 1e20;
|
||||
|
||||
if (p_point.x < position.x) {
|
||||
dist = MIN(dist, position.x - p_point.x);
|
||||
}
|
||||
if (p_point.y < position.y) {
|
||||
dist = MIN(dist, position.y - p_point.y);
|
||||
}
|
||||
if (p_point.x >= (position.x + size.x)) {
|
||||
dist = MIN(p_point.x - (position.x + size.x), dist);
|
||||
}
|
||||
if (p_point.y >= (position.y + size.y)) {
|
||||
dist = MIN(p_point.y - (position.y + size.y), dist);
|
||||
}
|
||||
|
||||
if (dist == 1e20)
|
||||
return 0;
|
||||
else
|
||||
return dist;
|
||||
}
|
||||
|
||||
Rect2 Rect2::clip(const Rect2 &p_rect) const { /// return a clipped rect
|
||||
|
||||
Rect2 new_rect = p_rect;
|
||||
|
||||
if (!intersects(new_rect))
|
||||
return Rect2();
|
||||
|
||||
new_rect.position.x = MAX(p_rect.position.x, position.x);
|
||||
new_rect.position.y = MAX(p_rect.position.y, position.y);
|
||||
|
||||
Point2 p_rect_end = p_rect.position + p_rect.size;
|
||||
Point2 end = position + size;
|
||||
|
||||
new_rect.size.x = MIN(p_rect_end.x, end.x) - new_rect.position.x;
|
||||
new_rect.size.y = MIN(p_rect_end.y, end.y) - new_rect.position.y;
|
||||
|
||||
return new_rect;
|
||||
}
|
||||
|
||||
Rect2 Rect2::merge(const Rect2 &p_rect) const { ///< return a merged rect
|
||||
|
||||
Rect2 new_rect;
|
||||
|
||||
new_rect.position.x = MIN(p_rect.position.x, position.x);
|
||||
new_rect.position.y = MIN(p_rect.position.y, position.y);
|
||||
|
||||
new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, position.x + size.x);
|
||||
new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, position.y + size.y);
|
||||
|
||||
new_rect.size = new_rect.size - new_rect.position; //make relative again
|
||||
|
||||
return new_rect;
|
||||
}
|
||||
|
||||
Rect2::operator String() const {
|
||||
return String(position) + ", " + String(size);
|
||||
}
|
||||
|
||||
bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_position, Point2 *r_normal) const {
|
||||
real_t min = 0, max = 1;
|
||||
int axis = 0;
|
||||
real_t sign = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
real_t seg_from = p_from[i];
|
||||
real_t seg_to = p_to[i];
|
||||
real_t box_begin = position[i];
|
||||
real_t box_end = box_begin + size[i];
|
||||
real_t cmin, cmax;
|
||||
real_t csign;
|
||||
|
||||
if (seg_from < seg_to) {
|
||||
if (seg_from > box_end || seg_to < box_begin)
|
||||
return false;
|
||||
real_t length = seg_to - seg_from;
|
||||
cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0;
|
||||
cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1;
|
||||
csign = -1.0;
|
||||
|
||||
} else {
|
||||
if (seg_to > box_end || seg_from < box_begin)
|
||||
return false;
|
||||
real_t length = seg_to - seg_from;
|
||||
cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0;
|
||||
cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1;
|
||||
csign = 1.0;
|
||||
}
|
||||
|
||||
if (cmin > min) {
|
||||
min = cmin;
|
||||
axis = i;
|
||||
sign = csign;
|
||||
}
|
||||
if (cmax < max)
|
||||
max = cmax;
|
||||
if (max < min)
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector2 rel = p_to - p_from;
|
||||
|
||||
if (r_normal) {
|
||||
Vector2 normal;
|
||||
normal[axis] = sign;
|
||||
*r_normal = normal;
|
||||
}
|
||||
|
||||
if (r_position)
|
||||
*r_position = p_from + rel * min;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const {
|
||||
//SAT intersection between local and transformed rect2
|
||||
|
||||
Vector2 xf_points[4] = {
|
||||
p_xform.xform(p_rect.position),
|
||||
p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y)),
|
||||
p_xform.xform(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)),
|
||||
p_xform.xform(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)),
|
||||
};
|
||||
|
||||
real_t low_limit;
|
||||
|
||||
//base rect2 first (faster)
|
||||
|
||||
if (xf_points[0].y > position.y)
|
||||
goto next1;
|
||||
if (xf_points[1].y > position.y)
|
||||
goto next1;
|
||||
if (xf_points[2].y > position.y)
|
||||
goto next1;
|
||||
if (xf_points[3].y > position.y)
|
||||
goto next1;
|
||||
|
||||
return false;
|
||||
|
||||
next1:
|
||||
|
||||
low_limit = position.y + size.y;
|
||||
|
||||
if (xf_points[0].y < low_limit)
|
||||
goto next2;
|
||||
if (xf_points[1].y < low_limit)
|
||||
goto next2;
|
||||
if (xf_points[2].y < low_limit)
|
||||
goto next2;
|
||||
if (xf_points[3].y < low_limit)
|
||||
goto next2;
|
||||
|
||||
return false;
|
||||
|
||||
next2:
|
||||
|
||||
if (xf_points[0].x > position.x)
|
||||
goto next3;
|
||||
if (xf_points[1].x > position.x)
|
||||
goto next3;
|
||||
if (xf_points[2].x > position.x)
|
||||
goto next3;
|
||||
if (xf_points[3].x > position.x)
|
||||
goto next3;
|
||||
|
||||
return false;
|
||||
|
||||
next3:
|
||||
|
||||
low_limit = position.x + size.x;
|
||||
|
||||
if (xf_points[0].x < low_limit)
|
||||
goto next4;
|
||||
if (xf_points[1].x < low_limit)
|
||||
goto next4;
|
||||
if (xf_points[2].x < low_limit)
|
||||
goto next4;
|
||||
if (xf_points[3].x < low_limit)
|
||||
goto next4;
|
||||
|
||||
return false;
|
||||
|
||||
next4:
|
||||
|
||||
Vector2 xf_points2[4] = {
|
||||
position,
|
||||
Vector2(position.x + size.x, position.y),
|
||||
Vector2(position.x, position.y + size.y),
|
||||
Vector2(position.x + size.x, position.y + size.y),
|
||||
};
|
||||
|
||||
real_t maxa = p_xform.elements[0].dot(xf_points2[0]);
|
||||
real_t mina = maxa;
|
||||
|
||||
real_t dp = p_xform.elements[0].dot(xf_points2[1]);
|
||||
maxa = MAX(dp, maxa);
|
||||
mina = MIN(dp, mina);
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points2[2]);
|
||||
maxa = MAX(dp, maxa);
|
||||
mina = MIN(dp, mina);
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points2[3]);
|
||||
maxa = MAX(dp, maxa);
|
||||
mina = MIN(dp, mina);
|
||||
|
||||
real_t maxb = p_xform.elements[0].dot(xf_points[0]);
|
||||
real_t minb = maxb;
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points[1]);
|
||||
maxb = MAX(dp, maxb);
|
||||
minb = MIN(dp, minb);
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points[2]);
|
||||
maxb = MAX(dp, maxb);
|
||||
minb = MIN(dp, minb);
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points[3]);
|
||||
maxb = MAX(dp, maxb);
|
||||
minb = MIN(dp, minb);
|
||||
|
||||
if (mina > maxb)
|
||||
return false;
|
||||
if (minb > maxa)
|
||||
return false;
|
||||
|
||||
maxa = p_xform.elements[1].dot(xf_points2[0]);
|
||||
mina = maxa;
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points2[1]);
|
||||
maxa = MAX(dp, maxa);
|
||||
mina = MIN(dp, mina);
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points2[2]);
|
||||
maxa = MAX(dp, maxa);
|
||||
mina = MIN(dp, mina);
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points2[3]);
|
||||
maxa = MAX(dp, maxa);
|
||||
mina = MIN(dp, mina);
|
||||
|
||||
maxb = p_xform.elements[1].dot(xf_points[0]);
|
||||
minb = maxb;
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points[1]);
|
||||
maxb = MAX(dp, maxb);
|
||||
minb = MIN(dp, minb);
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points[2]);
|
||||
maxb = MAX(dp, maxb);
|
||||
minb = MIN(dp, minb);
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points[3]);
|
||||
maxb = MAX(dp, maxb);
|
||||
minb = MIN(dp, minb);
|
||||
|
||||
if (mina > maxb)
|
||||
return false;
|
||||
if (minb > maxa)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,522 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* String.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "String.hpp"
|
||||
|
||||
#include "Array.hpp"
|
||||
#include "GodotGlobal.hpp"
|
||||
#include "NodePath.hpp"
|
||||
#include "PoolArrays.hpp"
|
||||
#include "Variant.hpp"
|
||||
|
||||
#include <gdnative/string.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace godot {
|
||||
|
||||
godot::CharString::~CharString() {
|
||||
godot::api->godot_char_string_destroy(&_char_string);
|
||||
}
|
||||
|
||||
int godot::CharString::length() const {
|
||||
return godot::api->godot_char_string_length(&_char_string);
|
||||
}
|
||||
|
||||
const char *godot::CharString::get_data() const {
|
||||
return godot::api->godot_char_string_get_data(&_char_string);
|
||||
}
|
||||
|
||||
String String::num(double p_num, int p_decimals) {
|
||||
return String(godot::api->godot_string_num_with_decimals(p_num, p_decimals));
|
||||
}
|
||||
|
||||
String String::num_scientific(double p_num) {
|
||||
return String(godot::api->godot_string_num_scientific(p_num));
|
||||
}
|
||||
|
||||
String String::num_real(double p_num) {
|
||||
return String(godot::api->godot_string_num_real(p_num));
|
||||
}
|
||||
|
||||
String String::num_int64(int64_t p_num, int base, bool capitalize_hex) {
|
||||
return String(godot::api->godot_string_num_int64_capitalized(p_num, base, capitalize_hex));
|
||||
}
|
||||
|
||||
String String::chr(godot_char_type p_char) {
|
||||
return String(godot::api->godot_string_chr(p_char));
|
||||
}
|
||||
|
||||
String String::md5(const uint8_t *p_md5) {
|
||||
return String(godot::api->godot_string_md5(p_md5));
|
||||
}
|
||||
|
||||
String String::hex_encode_buffer(const uint8_t *p_buffer, int p_len) {
|
||||
return String(godot::api->godot_string_hex_encode_buffer(p_buffer, p_len));
|
||||
}
|
||||
|
||||
godot::String::String() {
|
||||
godot::api->godot_string_new(&_godot_string);
|
||||
}
|
||||
|
||||
String::String(const char *contents) {
|
||||
godot::api->godot_string_new(&_godot_string);
|
||||
godot::api->godot_string_parse_utf8(&_godot_string, contents);
|
||||
}
|
||||
|
||||
String::String(const wchar_t *contents) {
|
||||
godot::api->godot_string_new_with_wide_string(&_godot_string, contents, wcslen(contents));
|
||||
}
|
||||
|
||||
String::String(const wchar_t c) {
|
||||
godot::api->godot_string_new_with_wide_string(&_godot_string, &c, 1);
|
||||
}
|
||||
|
||||
String::String(const String &other) {
|
||||
godot::api->godot_string_new_copy(&_godot_string, &other._godot_string);
|
||||
}
|
||||
|
||||
String::String(String &&other) {
|
||||
godot::api->godot_string_new_copy(&_godot_string, &other._godot_string);
|
||||
}
|
||||
|
||||
String::~String() {
|
||||
godot::api->godot_string_destroy(&_godot_string);
|
||||
}
|
||||
|
||||
wchar_t &String::operator[](const int idx) {
|
||||
return *const_cast<wchar_t *>(godot::api->godot_string_operator_index(&_godot_string, idx));
|
||||
}
|
||||
|
||||
wchar_t String::operator[](const int idx) const {
|
||||
return *godot::api->godot_string_operator_index((godot_string *)&_godot_string, idx);
|
||||
}
|
||||
|
||||
int String::length() const {
|
||||
return godot::api->godot_string_length(&_godot_string);
|
||||
}
|
||||
|
||||
void String::operator=(const String &s) {
|
||||
godot::api->godot_string_destroy(&_godot_string);
|
||||
godot::api->godot_string_new_copy(&_godot_string, &s._godot_string);
|
||||
}
|
||||
|
||||
void String::operator=(String &&s) {
|
||||
godot::api->godot_string_destroy(&_godot_string);
|
||||
godot::api->godot_string_new_copy(&_godot_string, &s._godot_string);
|
||||
}
|
||||
|
||||
bool String::operator==(const String &s) const {
|
||||
return godot::api->godot_string_operator_equal(&_godot_string, &s._godot_string);
|
||||
}
|
||||
|
||||
bool String::operator!=(const String &s) const {
|
||||
return !(*this == s);
|
||||
}
|
||||
|
||||
String String::operator+(const String &s) const {
|
||||
return String(godot::api->godot_string_operator_plus(&_godot_string, &s._godot_string));
|
||||
}
|
||||
|
||||
void String::operator+=(const String &s) {
|
||||
*this = String(godot::api->godot_string_operator_plus(&_godot_string, &s._godot_string));
|
||||
}
|
||||
|
||||
void String::operator+=(const wchar_t c) {
|
||||
String _to_be_added = String(c);
|
||||
*this = String(godot::api->godot_string_operator_plus(&_godot_string, &_to_be_added._godot_string));
|
||||
}
|
||||
|
||||
bool String::operator<(const String &s) const {
|
||||
return godot::api->godot_string_operator_less(&_godot_string, &s._godot_string);
|
||||
}
|
||||
|
||||
bool String::operator<=(const String &s) const {
|
||||
return godot::api->godot_string_operator_less(&_godot_string, &s._godot_string) ||
|
||||
(*this == s);
|
||||
}
|
||||
|
||||
bool String::operator>(const String &s) const {
|
||||
return !(*this <= s);
|
||||
}
|
||||
|
||||
bool String::operator>=(const String &s) const {
|
||||
return !(*this < s);
|
||||
}
|
||||
|
||||
String::operator NodePath() const {
|
||||
return NodePath(*this);
|
||||
}
|
||||
|
||||
const wchar_t *String::unicode_str() const {
|
||||
return godot::api->godot_string_wide_str(&_godot_string);
|
||||
}
|
||||
|
||||
char *String::alloc_c_string() const {
|
||||
godot_char_string contents = godot::api->godot_string_utf8(&_godot_string);
|
||||
|
||||
int length = godot::api->godot_char_string_length(&contents);
|
||||
|
||||
char *result = (char *)godot::api->godot_alloc(length + 1);
|
||||
|
||||
if (result) {
|
||||
memcpy(result, godot::api->godot_char_string_get_data(&contents), length + 1);
|
||||
}
|
||||
|
||||
godot::api->godot_char_string_destroy(&contents);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CharString String::utf8() const {
|
||||
CharString ret;
|
||||
|
||||
ret._char_string = godot::api->godot_string_utf8(&_godot_string);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CharString String::ascii(bool p_extended) const {
|
||||
CharString ret;
|
||||
|
||||
if (p_extended)
|
||||
ret._char_string = godot::api->godot_string_ascii_extended(&_godot_string);
|
||||
else
|
||||
ret._char_string = godot::api->godot_string_ascii(&_godot_string);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
String operator+(const char *a, const String &b) {
|
||||
return String(a) + b;
|
||||
}
|
||||
|
||||
String operator+(const wchar_t *a, const String &b) {
|
||||
return String(a) + b;
|
||||
}
|
||||
|
||||
bool String::begins_with(const String &p_string) const {
|
||||
return godot::api->godot_string_begins_with(&_godot_string, &p_string._godot_string);
|
||||
}
|
||||
|
||||
bool String::begins_with_char_array(const char *p_char_array) const {
|
||||
return godot::api->godot_string_begins_with_char_array(&_godot_string, p_char_array);
|
||||
}
|
||||
|
||||
PoolStringArray String::bigrams() const {
|
||||
godot_array arr = godot::api->godot_string_bigrams(&_godot_string);
|
||||
return Array(arr);
|
||||
}
|
||||
|
||||
String String::c_escape() const {
|
||||
return String(godot::api->godot_string_c_escape(&_godot_string));
|
||||
}
|
||||
|
||||
String String::c_unescape() const {
|
||||
return String(godot::api->godot_string_c_unescape(&_godot_string));
|
||||
}
|
||||
|
||||
String String::capitalize() const {
|
||||
return String(godot::api->godot_string_capitalize(&_godot_string));
|
||||
}
|
||||
|
||||
bool String::empty() const {
|
||||
return godot::api->godot_string_empty(&_godot_string);
|
||||
}
|
||||
|
||||
bool String::ends_with(const String &p_string) const {
|
||||
return godot::api->godot_string_ends_with(&_godot_string, &p_string._godot_string);
|
||||
}
|
||||
|
||||
void String::erase(int position, int chars) {
|
||||
godot::api->godot_string_erase(&_godot_string, position, chars);
|
||||
}
|
||||
|
||||
int String::find(String p_what, int p_from) const {
|
||||
return godot::api->godot_string_find_from(&_godot_string, p_what._godot_string, p_from);
|
||||
}
|
||||
|
||||
int String::find_last(String p_what) const {
|
||||
return godot::api->godot_string_find_last(&_godot_string, p_what._godot_string);
|
||||
}
|
||||
|
||||
int String::findn(String p_what, int p_from) const {
|
||||
return godot::api->godot_string_findn_from(&_godot_string, p_what._godot_string, p_from);
|
||||
}
|
||||
|
||||
String String::format(Variant values) const {
|
||||
return String(godot::api->godot_string_format(&_godot_string, (godot_variant *)&values));
|
||||
}
|
||||
|
||||
String String::format(Variant values, String placeholder) const {
|
||||
godot_char_string contents = godot::api->godot_string_utf8(&placeholder._godot_string);
|
||||
String new_string(godot::api->godot_string_format_with_custom_placeholder(&_godot_string, (godot_variant *)&values, godot::api->godot_char_string_get_data(&contents)));
|
||||
godot::api->godot_char_string_destroy(&contents);
|
||||
|
||||
return new_string;
|
||||
}
|
||||
|
||||
String String::get_base_dir() const {
|
||||
return String(godot::api->godot_string_get_base_dir(&_godot_string));
|
||||
}
|
||||
|
||||
String String::get_basename() const {
|
||||
return String(godot::api->godot_string_get_basename(&_godot_string));
|
||||
}
|
||||
|
||||
String String::get_extension() const {
|
||||
return String(godot::api->godot_string_get_extension(&_godot_string));
|
||||
}
|
||||
|
||||
String String::get_file() const {
|
||||
return String(godot::api->godot_string_get_file(&_godot_string));
|
||||
}
|
||||
|
||||
int String::hash() const {
|
||||
return godot::api->godot_string_hash(&_godot_string);
|
||||
}
|
||||
|
||||
int String::hex_to_int() const {
|
||||
return godot::api->godot_string_hex_to_int(&_godot_string);
|
||||
}
|
||||
|
||||
String String::insert(int position, String what) const {
|
||||
return String(godot::api->godot_string_insert(&_godot_string, position, what._godot_string));
|
||||
}
|
||||
|
||||
bool String::is_abs_path() const {
|
||||
return godot::api->godot_string_is_abs_path(&_godot_string);
|
||||
}
|
||||
|
||||
bool String::is_rel_path() const {
|
||||
return godot::api->godot_string_is_rel_path(&_godot_string);
|
||||
}
|
||||
|
||||
bool String::is_subsequence_of(String text) const {
|
||||
return godot::api->godot_string_is_subsequence_of(&_godot_string, &text._godot_string);
|
||||
}
|
||||
|
||||
bool String::is_subsequence_ofi(String text) const {
|
||||
return godot::api->godot_string_is_subsequence_ofi(&_godot_string, &text._godot_string);
|
||||
}
|
||||
|
||||
bool String::is_valid_float() const {
|
||||
return godot::api->godot_string_is_valid_float(&_godot_string);
|
||||
}
|
||||
|
||||
bool String::is_valid_html_color() const {
|
||||
return godot::api->godot_string_is_valid_html_color(&_godot_string);
|
||||
}
|
||||
|
||||
bool String::is_valid_identifier() const {
|
||||
return godot::api->godot_string_is_valid_identifier(&_godot_string);
|
||||
}
|
||||
|
||||
bool String::is_valid_integer() const {
|
||||
return godot::api->godot_string_is_numeric(&_godot_string);
|
||||
}
|
||||
|
||||
bool String::is_valid_ip_address() const {
|
||||
return godot::api->godot_string_is_valid_ip_address(&_godot_string);
|
||||
}
|
||||
|
||||
String String::json_escape() const {
|
||||
return String(godot::api->godot_string_json_escape(&_godot_string));
|
||||
}
|
||||
|
||||
String String::left(int position) const {
|
||||
return String(godot::api->godot_string_left(&_godot_string, position));
|
||||
}
|
||||
|
||||
bool String::match(String expr) const {
|
||||
return godot::api->godot_string_match(&_godot_string, &expr._godot_string);
|
||||
}
|
||||
|
||||
bool String::matchn(String expr) const {
|
||||
return godot::api->godot_string_match(&_godot_string, &expr._godot_string);
|
||||
}
|
||||
|
||||
PoolByteArray String::md5_buffer() const {
|
||||
godot_pool_byte_array arr = godot::api->godot_string_md5_buffer(&_godot_string);
|
||||
return PoolByteArray(arr);
|
||||
}
|
||||
|
||||
String String::md5_text() const {
|
||||
return String(godot::api->godot_string_md5_text(&_godot_string));
|
||||
}
|
||||
|
||||
int String::ord_at(int at) const {
|
||||
return godot::api->godot_string_ord_at(&_godot_string, at);
|
||||
}
|
||||
|
||||
String String::pad_decimals(int digits) const {
|
||||
return String(godot::api->godot_string_pad_decimals(&_godot_string, digits));
|
||||
}
|
||||
|
||||
String String::pad_zeros(int digits) const {
|
||||
return String(godot::api->godot_string_pad_zeros(&_godot_string, digits));
|
||||
}
|
||||
|
||||
String String::percent_decode() const {
|
||||
return String(godot::api->godot_string_percent_decode(&_godot_string));
|
||||
}
|
||||
|
||||
String String::percent_encode() const {
|
||||
return String(godot::api->godot_string_percent_encode(&_godot_string));
|
||||
}
|
||||
|
||||
String String::plus_file(String file) const {
|
||||
return String(godot::api->godot_string_plus_file(&_godot_string, &file._godot_string));
|
||||
}
|
||||
|
||||
String String::replace(String p_key, String p_with) const {
|
||||
return String(godot::api->godot_string_replace(&_godot_string, p_key._godot_string, p_with._godot_string));
|
||||
}
|
||||
|
||||
String String::replacen(String what, String forwhat) const {
|
||||
return String(godot::api->godot_string_replacen(&_godot_string, what._godot_string, forwhat._godot_string));
|
||||
}
|
||||
|
||||
int String::rfind(String p_what, int p_from) const {
|
||||
return godot::api->godot_string_rfind_from(&_godot_string, p_what._godot_string, p_from);
|
||||
}
|
||||
|
||||
int String::rfindn(String p_what, int p_from) const {
|
||||
return godot::api->godot_string_rfindn_from(&_godot_string, p_what._godot_string, p_from);
|
||||
}
|
||||
|
||||
String String::right(int position) const {
|
||||
return String(godot::api->godot_string_right(&_godot_string, position));
|
||||
}
|
||||
|
||||
PoolByteArray String::sha256_buffer() const {
|
||||
godot_pool_byte_array arr = godot::api->godot_string_sha256_buffer(&_godot_string);
|
||||
return PoolByteArray(arr);
|
||||
}
|
||||
|
||||
String String::sha256_text() const {
|
||||
return String(godot::api->godot_string_sha256_text(&_godot_string));
|
||||
}
|
||||
|
||||
float String::similarity(String text) const {
|
||||
return godot::api->godot_string_similarity(&_godot_string, &text._godot_string);
|
||||
}
|
||||
|
||||
// TODO Suport allow_empty
|
||||
PoolStringArray String::split(String divisor, bool /*allow_empty*/) const {
|
||||
godot_array arr = godot::api->godot_string_split(&_godot_string, &divisor._godot_string);
|
||||
return Array(arr);
|
||||
}
|
||||
|
||||
// TODO Suport allow_empty
|
||||
PoolIntArray String::split_ints(String divisor, bool /*allow_empty*/) const {
|
||||
godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
|
||||
return Array(arr);
|
||||
}
|
||||
|
||||
// TODO Suport allow_empty
|
||||
PoolRealArray String::split_floats(String divisor, bool /*allow_empty*/) const {
|
||||
// TODO The GDNative API returns godot_array, when according to the doc, it should have been godot_pool_real_array
|
||||
godot_array arr = godot::api->godot_string_split_floats(&_godot_string, &divisor._godot_string);
|
||||
Array wrapped_array(arr);
|
||||
return PoolRealArray(wrapped_array);
|
||||
}
|
||||
|
||||
String String::strip_edges(bool left, bool right) const {
|
||||
return String(godot::api->godot_string_strip_edges(&_godot_string, left, right));
|
||||
}
|
||||
|
||||
String String::substr(int from, int len) const {
|
||||
return String(godot::api->godot_string_substr(&_godot_string, from, len));
|
||||
}
|
||||
|
||||
float String::to_float() const {
|
||||
return godot::api->godot_string_to_float(&_godot_string);
|
||||
}
|
||||
|
||||
int64_t String::to_int() const {
|
||||
return godot::api->godot_string_to_int(&_godot_string);
|
||||
}
|
||||
|
||||
String String::to_lower() const {
|
||||
return String(godot::api->godot_string_to_lower(&_godot_string));
|
||||
}
|
||||
|
||||
String String::to_upper() const {
|
||||
return String(godot::api->godot_string_to_upper(&_godot_string));
|
||||
}
|
||||
|
||||
String String::xml_escape() const {
|
||||
return String(godot::api->godot_string_xml_escape(&_godot_string));
|
||||
}
|
||||
|
||||
String String::xml_unescape() const {
|
||||
return String(godot::api->godot_string_xml_unescape(&_godot_string));
|
||||
}
|
||||
|
||||
signed char String::casecmp_to(String p_str) const {
|
||||
return godot::api->godot_string_casecmp_to(&_godot_string, &p_str._godot_string);
|
||||
}
|
||||
|
||||
signed char String::nocasecmp_to(String p_str) const {
|
||||
return godot::api->godot_string_nocasecmp_to(&_godot_string, &p_str._godot_string);
|
||||
}
|
||||
|
||||
signed char String::naturalnocasecmp_to(String p_str) const {
|
||||
return godot::api->godot_string_naturalnocasecmp_to(&_godot_string, &p_str._godot_string);
|
||||
}
|
||||
|
||||
String String::dedent() const {
|
||||
godot_string s = godot::core_1_1_api->godot_string_dedent(&_godot_string);
|
||||
return String(s);
|
||||
}
|
||||
|
||||
PoolStringArray String::rsplit(const String &divisor, const bool allow_empty, const int maxsplit) const {
|
||||
godot_pool_string_array arr =
|
||||
godot::core_1_1_api->godot_string_rsplit(&_godot_string, &divisor._godot_string, allow_empty, maxsplit);
|
||||
return PoolStringArray(arr);
|
||||
}
|
||||
|
||||
String String::rstrip(const String &chars) const {
|
||||
godot_string s = godot::core_1_1_api->godot_string_rstrip(&_godot_string, &chars._godot_string);
|
||||
return String(s);
|
||||
}
|
||||
|
||||
String String::trim_prefix(const String &prefix) const {
|
||||
godot_string s = godot::core_1_1_api->godot_string_trim_prefix(&_godot_string, &prefix._godot_string);
|
||||
return String(s);
|
||||
}
|
||||
|
||||
String String::trim_suffix(const String &suffix) const {
|
||||
godot_string s = godot::core_1_1_api->godot_string_trim_suffix(&_godot_string, &suffix._godot_string);
|
||||
return String(s);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,305 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Transform.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Transform.hpp"
|
||||
|
||||
#include "Basis.hpp"
|
||||
|
||||
#include "AABB.hpp"
|
||||
#include "Plane.hpp"
|
||||
|
||||
#include "Quat.hpp"
|
||||
|
||||
namespace godot {
|
||||
|
||||
const Transform Transform::IDENTITY = Transform();
|
||||
const Transform Transform::FLIP_X = Transform(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
|
||||
const Transform Transform::FLIP_Y = Transform(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0);
|
||||
const Transform Transform::FLIP_Z = Transform(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0);
|
||||
|
||||
Transform Transform::inverse_xform(const Transform &t) const {
|
||||
Vector3 v = t.origin - origin;
|
||||
return Transform(basis.transpose_xform(t.basis),
|
||||
basis.xform(v));
|
||||
}
|
||||
|
||||
void Transform::set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) {
|
||||
basis.elements[0][0] = xx;
|
||||
basis.elements[0][1] = xy;
|
||||
basis.elements[0][2] = xz;
|
||||
basis.elements[1][0] = yx;
|
||||
basis.elements[1][1] = yy;
|
||||
basis.elements[1][2] = yz;
|
||||
basis.elements[2][0] = zx;
|
||||
basis.elements[2][1] = zy;
|
||||
basis.elements[2][2] = zz;
|
||||
origin.x = tx;
|
||||
origin.y = ty;
|
||||
origin.z = tz;
|
||||
}
|
||||
|
||||
Vector3 Transform::xform(const Vector3 &p_vector) const {
|
||||
return Vector3(
|
||||
basis.elements[0].dot(p_vector) + origin.x,
|
||||
basis.elements[1].dot(p_vector) + origin.y,
|
||||
basis.elements[2].dot(p_vector) + origin.z);
|
||||
}
|
||||
Vector3 Transform::xform_inv(const Vector3 &p_vector) const {
|
||||
Vector3 v = p_vector - origin;
|
||||
|
||||
return Vector3(
|
||||
(basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z),
|
||||
(basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z),
|
||||
(basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z));
|
||||
}
|
||||
|
||||
Plane Transform::xform(const Plane &p_plane) const {
|
||||
Vector3 point = p_plane.normal * p_plane.d;
|
||||
Vector3 point_dir = point + p_plane.normal;
|
||||
point = xform(point);
|
||||
point_dir = xform(point_dir);
|
||||
|
||||
Vector3 normal = point_dir - point;
|
||||
normal.normalize();
|
||||
real_t d = normal.dot(point);
|
||||
|
||||
return Plane(normal, d);
|
||||
}
|
||||
Plane Transform::xform_inv(const Plane &p_plane) const {
|
||||
Vector3 point = p_plane.normal * p_plane.d;
|
||||
Vector3 point_dir = point + p_plane.normal;
|
||||
point = xform_inv(point);
|
||||
point_dir = xform_inv(point_dir);
|
||||
|
||||
Vector3 normal = point_dir - point;
|
||||
normal.normalize();
|
||||
real_t d = normal.dot(point);
|
||||
|
||||
return Plane(normal, d);
|
||||
}
|
||||
|
||||
AABB Transform::xform(const AABB &p_aabb) const {
|
||||
/* define vertices */
|
||||
Vector3 x = basis.get_axis(0) * p_aabb.size.x;
|
||||
Vector3 y = basis.get_axis(1) * p_aabb.size.y;
|
||||
Vector3 z = basis.get_axis(2) * p_aabb.size.z;
|
||||
Vector3 pos = xform(p_aabb.position);
|
||||
//could be even further optimized
|
||||
AABB new_aabb;
|
||||
new_aabb.position = pos;
|
||||
new_aabb.expand_to(pos + x);
|
||||
new_aabb.expand_to(pos + y);
|
||||
new_aabb.expand_to(pos + z);
|
||||
new_aabb.expand_to(pos + x + y);
|
||||
new_aabb.expand_to(pos + x + z);
|
||||
new_aabb.expand_to(pos + y + z);
|
||||
new_aabb.expand_to(pos + x + y + z);
|
||||
return new_aabb;
|
||||
}
|
||||
AABB Transform::xform_inv(const AABB &p_aabb) const {
|
||||
/* define vertices */
|
||||
Vector3 vertices[8] = {
|
||||
Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
|
||||
Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
|
||||
Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
|
||||
Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z),
|
||||
Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z),
|
||||
Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z),
|
||||
Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z),
|
||||
Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z)
|
||||
};
|
||||
|
||||
AABB ret;
|
||||
|
||||
ret.position = xform_inv(vertices[0]);
|
||||
|
||||
for (int i = 1; i < 8; i++) {
|
||||
ret.expand_to(xform_inv(vertices[i]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Transform::affine_invert() {
|
||||
basis.invert();
|
||||
origin = basis.xform(-origin);
|
||||
}
|
||||
|
||||
Transform Transform::affine_inverse() const {
|
||||
Transform ret = *this;
|
||||
ret.affine_invert();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Transform::invert() {
|
||||
basis.transpose();
|
||||
origin = basis.xform(-origin);
|
||||
}
|
||||
|
||||
Transform Transform::inverse() const {
|
||||
// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
|
||||
// Transform::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
|
||||
Transform ret = *this;
|
||||
ret.invert();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Transform::rotate(const Vector3 &p_axis, real_t p_phi) {
|
||||
*this = rotated(p_axis, p_phi);
|
||||
}
|
||||
|
||||
Transform Transform::rotated(const Vector3 &p_axis, real_t p_phi) const {
|
||||
return Transform(Basis(p_axis, p_phi), Vector3()) * (*this);
|
||||
}
|
||||
|
||||
void Transform::rotate_basis(const Vector3 &p_axis, real_t p_phi) {
|
||||
basis.rotate(p_axis, p_phi);
|
||||
}
|
||||
|
||||
Transform Transform::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
|
||||
Transform t = *this;
|
||||
t.set_look_at(origin, p_target, p_up);
|
||||
return t;
|
||||
}
|
||||
|
||||
void Transform::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
|
||||
// Reference: MESA source code
|
||||
Vector3 v_x, v_y, v_z;
|
||||
|
||||
/* Make rotation matrix */
|
||||
|
||||
/* Z vector */
|
||||
v_z = p_eye - p_target;
|
||||
|
||||
v_z.normalize();
|
||||
|
||||
v_y = p_up;
|
||||
|
||||
v_x = v_y.cross(v_z);
|
||||
|
||||
/* Recompute Y = Z cross X */
|
||||
v_y = v_z.cross(v_x);
|
||||
|
||||
v_x.normalize();
|
||||
v_y.normalize();
|
||||
|
||||
basis.set_axis(0, v_x);
|
||||
basis.set_axis(1, v_y);
|
||||
basis.set_axis(2, v_z);
|
||||
origin = p_eye;
|
||||
}
|
||||
|
||||
Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) const {
|
||||
/* not sure if very "efficient" but good enough? */
|
||||
|
||||
Vector3 src_scale = basis.get_scale();
|
||||
Quat src_rot = basis;
|
||||
Vector3 src_loc = origin;
|
||||
|
||||
Vector3 dst_scale = p_transform.basis.get_scale();
|
||||
Quat dst_rot = p_transform.basis;
|
||||
Vector3 dst_loc = p_transform.origin;
|
||||
|
||||
Transform dst;
|
||||
dst.basis = src_rot.slerp(dst_rot, p_c);
|
||||
dst.basis.scale(src_scale.linear_interpolate(dst_scale, p_c));
|
||||
dst.origin = src_loc.linear_interpolate(dst_loc, p_c);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void Transform::scale(const Vector3 &p_scale) {
|
||||
basis.scale(p_scale);
|
||||
origin *= p_scale;
|
||||
}
|
||||
|
||||
Transform Transform::scaled(const Vector3 &p_scale) const {
|
||||
Transform t = *this;
|
||||
t.scale(p_scale);
|
||||
return t;
|
||||
}
|
||||
|
||||
void Transform::scale_basis(const Vector3 &p_scale) {
|
||||
basis.scale(p_scale);
|
||||
}
|
||||
|
||||
void Transform::translate(real_t p_tx, real_t p_ty, real_t p_tz) {
|
||||
translate(Vector3(p_tx, p_ty, p_tz));
|
||||
}
|
||||
void Transform::translate(const Vector3 &p_translation) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
origin[i] += basis.elements[i].dot(p_translation);
|
||||
}
|
||||
}
|
||||
|
||||
Transform Transform::translated(const Vector3 &p_translation) const {
|
||||
Transform t = *this;
|
||||
t.translate(p_translation);
|
||||
return t;
|
||||
}
|
||||
|
||||
void Transform::orthonormalize() {
|
||||
basis.orthonormalize();
|
||||
}
|
||||
|
||||
Transform Transform::orthonormalized() const {
|
||||
Transform _copy = *this;
|
||||
_copy.orthonormalize();
|
||||
return _copy;
|
||||
}
|
||||
|
||||
bool Transform::operator==(const Transform &p_transform) const {
|
||||
return (basis == p_transform.basis && origin == p_transform.origin);
|
||||
}
|
||||
bool Transform::operator!=(const Transform &p_transform) const {
|
||||
return (basis != p_transform.basis || origin != p_transform.origin);
|
||||
}
|
||||
|
||||
void Transform::operator*=(const Transform &p_transform) {
|
||||
origin = xform(p_transform.origin);
|
||||
basis *= p_transform.basis;
|
||||
}
|
||||
|
||||
Transform Transform::operator*(const Transform &p_transform) const {
|
||||
Transform t = *this;
|
||||
t *= p_transform;
|
||||
return t;
|
||||
}
|
||||
|
||||
Transform::operator String() const {
|
||||
return basis.operator String() + " - " + origin.operator String();
|
||||
}
|
||||
|
||||
Transform::Transform(const Basis &p_basis, const Vector3 &p_origin) {
|
||||
basis = p_basis;
|
||||
origin = p_origin;
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,332 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Transform2D.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Transform2D.hpp"
|
||||
#include "Rect2.hpp"
|
||||
#include "String.hpp"
|
||||
#include "Vector2.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const Transform2D Transform2D::IDENTITY;
|
||||
const Transform2D Transform2D::FLIP_X = Transform2D(-1, 0, 0, 1, 0, 0);
|
||||
const Transform2D Transform2D::FLIP_Y = Transform2D(1, 0, 0, -1, 0, 0);
|
||||
|
||||
Transform2D::Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) {
|
||||
elements[0][0] = xx;
|
||||
elements[0][1] = xy;
|
||||
elements[1][0] = yx;
|
||||
elements[1][1] = yy;
|
||||
elements[2][0] = ox;
|
||||
elements[2][1] = oy;
|
||||
}
|
||||
|
||||
Vector2 Transform2D::basis_xform(const Vector2 &v) const {
|
||||
return Vector2(
|
||||
tdotx(v),
|
||||
tdoty(v));
|
||||
}
|
||||
|
||||
Vector2 Transform2D::basis_xform_inv(const Vector2 &v) const {
|
||||
return Vector2(
|
||||
elements[0].dot(v),
|
||||
elements[1].dot(v));
|
||||
}
|
||||
|
||||
Vector2 Transform2D::xform(const Vector2 &v) const {
|
||||
return Vector2(
|
||||
tdotx(v),
|
||||
tdoty(v)) +
|
||||
elements[2];
|
||||
}
|
||||
Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const {
|
||||
Vector2 v = p_vec - elements[2];
|
||||
|
||||
return Vector2(
|
||||
elements[0].dot(v),
|
||||
elements[1].dot(v));
|
||||
}
|
||||
Rect2 Transform2D::xform(const Rect2 &p_rect) const {
|
||||
Vector2 x = elements[0] * p_rect.size.x;
|
||||
Vector2 y = elements[1] * p_rect.size.y;
|
||||
Vector2 position = xform(p_rect.position);
|
||||
|
||||
Rect2 new_rect;
|
||||
new_rect.position = position;
|
||||
new_rect.expand_to(position + x);
|
||||
new_rect.expand_to(position + y);
|
||||
new_rect.expand_to(position + x + y);
|
||||
return new_rect;
|
||||
}
|
||||
|
||||
void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) {
|
||||
elements[0][0] = ::cos(p_rot) * p_scale.x;
|
||||
elements[1][1] = ::cos(p_rot) * p_scale.y;
|
||||
elements[1][0] = -::sin(p_rot) * p_scale.y;
|
||||
elements[0][1] = ::sin(p_rot) * p_scale.x;
|
||||
}
|
||||
|
||||
Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const {
|
||||
Vector2 ends[4] = {
|
||||
xform_inv(p_rect.position),
|
||||
xform_inv(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)),
|
||||
xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y + p_rect.size.y)),
|
||||
xform_inv(Vector2(p_rect.position.x + p_rect.size.x, p_rect.position.y))
|
||||
};
|
||||
|
||||
Rect2 new_rect;
|
||||
new_rect.position = ends[0];
|
||||
new_rect.expand_to(ends[1]);
|
||||
new_rect.expand_to(ends[2]);
|
||||
new_rect.expand_to(ends[3]);
|
||||
|
||||
return new_rect;
|
||||
}
|
||||
|
||||
void Transform2D::invert() {
|
||||
// FIXME: this function assumes the basis is a rotation matrix, with no scaling.
|
||||
// Transform2D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that.
|
||||
std::swap(elements[0][1], elements[1][0]);
|
||||
elements[2] = basis_xform(-elements[2]);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::inverse() const {
|
||||
Transform2D inv = *this;
|
||||
inv.invert();
|
||||
return inv;
|
||||
}
|
||||
|
||||
void Transform2D::affine_invert() {
|
||||
real_t det = basis_determinant();
|
||||
ERR_FAIL_COND(det == 0);
|
||||
real_t idet = 1.0 / det;
|
||||
|
||||
std::swap(elements[0][0], elements[1][1]);
|
||||
elements[0] *= Vector2(idet, -idet);
|
||||
elements[1] *= Vector2(-idet, idet);
|
||||
|
||||
elements[2] = basis_xform(-elements[2]);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::affine_inverse() const {
|
||||
Transform2D inv = *this;
|
||||
inv.affine_invert();
|
||||
return inv;
|
||||
}
|
||||
|
||||
void Transform2D::rotate(real_t p_phi) {
|
||||
*this = Transform2D(p_phi, Vector2()) * (*this);
|
||||
}
|
||||
|
||||
real_t Transform2D::get_rotation() const {
|
||||
real_t det = basis_determinant();
|
||||
Transform2D m = orthonormalized();
|
||||
if (det < 0) {
|
||||
m.scale_basis(Size2(-1, -1));
|
||||
}
|
||||
return ::atan2(m[0].y, m[0].x);
|
||||
}
|
||||
|
||||
void Transform2D::set_rotation(real_t p_rot) {
|
||||
real_t cr = ::cos(p_rot);
|
||||
real_t sr = ::sin(p_rot);
|
||||
elements[0][0] = cr;
|
||||
elements[0][1] = sr;
|
||||
elements[1][0] = -sr;
|
||||
elements[1][1] = cr;
|
||||
}
|
||||
|
||||
Transform2D::Transform2D(real_t p_rot, const Vector2 &p_position) {
|
||||
real_t cr = ::cos(p_rot);
|
||||
real_t sr = ::sin(p_rot);
|
||||
elements[0][0] = cr;
|
||||
elements[0][1] = sr;
|
||||
elements[1][0] = -sr;
|
||||
elements[1][1] = cr;
|
||||
elements[2] = p_position;
|
||||
}
|
||||
|
||||
Size2 Transform2D::get_scale() const {
|
||||
real_t det_sign = basis_determinant() > 0 ? 1 : -1;
|
||||
return det_sign * Size2(elements[0].length(), elements[1].length());
|
||||
}
|
||||
|
||||
void Transform2D::scale(const Size2 &p_scale) {
|
||||
scale_basis(p_scale);
|
||||
elements[2] *= p_scale;
|
||||
}
|
||||
void Transform2D::scale_basis(const Size2 &p_scale) {
|
||||
elements[0][0] *= p_scale.x;
|
||||
elements[0][1] *= p_scale.y;
|
||||
elements[1][0] *= p_scale.x;
|
||||
elements[1][1] *= p_scale.y;
|
||||
}
|
||||
void Transform2D::translate(real_t p_tx, real_t p_ty) {
|
||||
translate(Vector2(p_tx, p_ty));
|
||||
}
|
||||
void Transform2D::translate(const Vector2 &p_translation) {
|
||||
elements[2] += basis_xform(p_translation);
|
||||
}
|
||||
|
||||
void Transform2D::orthonormalize() {
|
||||
// Gram-Schmidt Process
|
||||
|
||||
Vector2 x = elements[0];
|
||||
Vector2 y = elements[1];
|
||||
|
||||
x.normalize();
|
||||
y = (y - x * (x.dot(y)));
|
||||
y.normalize();
|
||||
|
||||
elements[0] = x;
|
||||
elements[1] = y;
|
||||
}
|
||||
Transform2D Transform2D::orthonormalized() const {
|
||||
Transform2D on = *this;
|
||||
on.orthonormalize();
|
||||
return on;
|
||||
}
|
||||
|
||||
bool Transform2D::operator==(const Transform2D &p_transform) const {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (elements[i] != p_transform.elements[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Transform2D::operator!=(const Transform2D &p_transform) const {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (elements[i] != p_transform.elements[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Transform2D::operator*=(const Transform2D &p_transform) {
|
||||
elements[2] = xform(p_transform.elements[2]);
|
||||
|
||||
real_t x0, x1, y0, y1;
|
||||
|
||||
x0 = tdotx(p_transform.elements[0]);
|
||||
x1 = tdoty(p_transform.elements[0]);
|
||||
y0 = tdotx(p_transform.elements[1]);
|
||||
y1 = tdoty(p_transform.elements[1]);
|
||||
|
||||
elements[0][0] = x0;
|
||||
elements[0][1] = x1;
|
||||
elements[1][0] = y0;
|
||||
elements[1][1] = y1;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::operator*(const Transform2D &p_transform) const {
|
||||
Transform2D t = *this;
|
||||
t *= p_transform;
|
||||
return t;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::scaled(const Size2 &p_scale) const {
|
||||
Transform2D copy = *this;
|
||||
copy.scale(p_scale);
|
||||
return copy;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const {
|
||||
Transform2D copy = *this;
|
||||
copy.scale_basis(p_scale);
|
||||
return copy;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::untranslated() const {
|
||||
Transform2D copy = *this;
|
||||
copy.elements[2] = Vector2();
|
||||
return copy;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::translated(const Vector2 &p_offset) const {
|
||||
Transform2D copy = *this;
|
||||
copy.translate(p_offset);
|
||||
return copy;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::rotated(real_t p_phi) const {
|
||||
Transform2D copy = *this;
|
||||
copy.rotate(p_phi);
|
||||
return copy;
|
||||
}
|
||||
|
||||
real_t Transform2D::basis_determinant() const {
|
||||
return elements[0].x * elements[1].y - elements[0].y * elements[1].x;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t p_c) const {
|
||||
//extract parameters
|
||||
Vector2 p1 = get_origin();
|
||||
Vector2 p2 = p_transform.get_origin();
|
||||
|
||||
real_t r1 = get_rotation();
|
||||
real_t r2 = p_transform.get_rotation();
|
||||
|
||||
Size2 s1 = get_scale();
|
||||
Size2 s2 = p_transform.get_scale();
|
||||
|
||||
//slerp rotation
|
||||
Vector2 v1(::cos(r1), ::sin(r1));
|
||||
Vector2 v2(::cos(r2), ::sin(r2));
|
||||
|
||||
real_t dot = v1.dot(v2);
|
||||
|
||||
dot = (dot < -1.0) ? -1.0 : ((dot > 1.0) ? 1.0 : dot); //clamp dot to [-1,1]
|
||||
|
||||
Vector2 v;
|
||||
|
||||
if (dot > 0.9995) {
|
||||
v = Vector2::linear_interpolate(v1, v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues
|
||||
} else {
|
||||
real_t angle = p_c * ::acos(dot);
|
||||
Vector2 v3 = (v2 - v1 * dot).normalized();
|
||||
v = v1 * ::cos(angle) + v3 * ::sin(angle);
|
||||
}
|
||||
|
||||
//construct matrix
|
||||
Transform2D res(::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_c));
|
||||
res.scale_basis(Vector2::linear_interpolate(s1, s2, p_c));
|
||||
return res;
|
||||
}
|
||||
|
||||
Transform2D::operator String() const {
|
||||
return String(String() + elements[0] + ", " + elements[1] + ", " + elements[2]);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,381 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* Variant.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Variant.hpp"
|
||||
|
||||
#include <gdnative/variant.h>
|
||||
|
||||
#include "CoreTypes.hpp"
|
||||
#include "Defs.hpp"
|
||||
#include "GodotGlobal.hpp"
|
||||
#include "Object.hpp"
|
||||
|
||||
namespace godot {
|
||||
|
||||
Variant::Variant() {
|
||||
godot::api->godot_variant_new_nil(&_godot_variant);
|
||||
}
|
||||
|
||||
Variant::Variant(const Variant &v) {
|
||||
godot::api->godot_variant_new_copy(&_godot_variant, &v._godot_variant);
|
||||
}
|
||||
|
||||
Variant::Variant(bool p_bool) {
|
||||
godot::api->godot_variant_new_bool(&_godot_variant, p_bool);
|
||||
}
|
||||
|
||||
Variant::Variant(signed int p_int) // real one
|
||||
{
|
||||
godot::api->godot_variant_new_int(&_godot_variant, p_int);
|
||||
}
|
||||
|
||||
Variant::Variant(unsigned int p_int) {
|
||||
godot::api->godot_variant_new_uint(&_godot_variant, p_int);
|
||||
}
|
||||
|
||||
Variant::Variant(signed short p_short) // real one
|
||||
{
|
||||
godot::api->godot_variant_new_int(&_godot_variant, (int)p_short);
|
||||
}
|
||||
|
||||
Variant::Variant(int64_t p_char) // real one
|
||||
{
|
||||
godot::api->godot_variant_new_int(&_godot_variant, p_char);
|
||||
}
|
||||
|
||||
Variant::Variant(uint64_t p_char) {
|
||||
godot::api->godot_variant_new_uint(&_godot_variant, p_char);
|
||||
}
|
||||
|
||||
Variant::Variant(float p_float) {
|
||||
godot::api->godot_variant_new_real(&_godot_variant, p_float);
|
||||
}
|
||||
|
||||
Variant::Variant(double p_double) {
|
||||
godot::api->godot_variant_new_real(&_godot_variant, p_double);
|
||||
}
|
||||
|
||||
Variant::Variant(const String &p_string) {
|
||||
godot::api->godot_variant_new_string(&_godot_variant, (godot_string *)&p_string);
|
||||
}
|
||||
|
||||
Variant::Variant(const char *const p_cstring) {
|
||||
String s = String(p_cstring);
|
||||
godot::api->godot_variant_new_string(&_godot_variant, (godot_string *)&s);
|
||||
}
|
||||
|
||||
Variant::Variant(const wchar_t *p_wstring) {
|
||||
String s = p_wstring;
|
||||
godot::api->godot_variant_new_string(&_godot_variant, (godot_string *)&s);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector2 &p_vector2) {
|
||||
godot::api->godot_variant_new_vector2(&_godot_variant, (godot_vector2 *)&p_vector2);
|
||||
}
|
||||
|
||||
Variant::Variant(const Rect2 &p_rect2) {
|
||||
godot::api->godot_variant_new_rect2(&_godot_variant, (godot_rect2 *)&p_rect2);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector3 &p_vector3) {
|
||||
godot::api->godot_variant_new_vector3(&_godot_variant, (godot_vector3 *)&p_vector3);
|
||||
}
|
||||
|
||||
Variant::Variant(const Plane &p_plane) {
|
||||
godot::api->godot_variant_new_plane(&_godot_variant, (godot_plane *)&p_plane);
|
||||
}
|
||||
|
||||
Variant::Variant(const AABB &p_aabb) {
|
||||
godot::api->godot_variant_new_aabb(&_godot_variant, (godot_aabb *)&p_aabb);
|
||||
}
|
||||
|
||||
Variant::Variant(const Quat &p_quat) {
|
||||
godot::api->godot_variant_new_quat(&_godot_variant, (godot_quat *)&p_quat);
|
||||
}
|
||||
|
||||
Variant::Variant(const Basis &p_transform) {
|
||||
godot::api->godot_variant_new_basis(&_godot_variant, (godot_basis *)&p_transform);
|
||||
}
|
||||
|
||||
Variant::Variant(const Transform2D &p_transform) {
|
||||
godot::api->godot_variant_new_transform2d(&_godot_variant, (godot_transform2d *)&p_transform);
|
||||
}
|
||||
|
||||
Variant::Variant(const Transform &p_transform) {
|
||||
godot::api->godot_variant_new_transform(&_godot_variant, (godot_transform *)&p_transform);
|
||||
}
|
||||
|
||||
Variant::Variant(const Color &p_color) {
|
||||
godot::api->godot_variant_new_color(&_godot_variant, (godot_color *)&p_color);
|
||||
}
|
||||
|
||||
Variant::Variant(const NodePath &p_path) {
|
||||
godot::api->godot_variant_new_node_path(&_godot_variant, (godot_node_path *)&p_path);
|
||||
}
|
||||
|
||||
Variant::Variant(const RID &p_rid) {
|
||||
godot::api->godot_variant_new_rid(&_godot_variant, (godot_rid *)&p_rid);
|
||||
}
|
||||
|
||||
Variant::Variant(const Object *p_object) {
|
||||
if (p_object)
|
||||
godot::api->godot_variant_new_object(&_godot_variant, p_object->_owner);
|
||||
else
|
||||
godot::api->godot_variant_new_nil(&_godot_variant);
|
||||
}
|
||||
|
||||
Variant::Variant(const Dictionary &p_dictionary) {
|
||||
godot::api->godot_variant_new_dictionary(&_godot_variant, (godot_dictionary *)&p_dictionary);
|
||||
}
|
||||
|
||||
Variant::Variant(const Array &p_array) {
|
||||
godot::api->godot_variant_new_array(&_godot_variant, (godot_array *)&p_array);
|
||||
}
|
||||
|
||||
Variant::Variant(const PoolByteArray &p_raw_array) {
|
||||
godot::api->godot_variant_new_pool_byte_array(&_godot_variant, (godot_pool_byte_array *)&p_raw_array);
|
||||
}
|
||||
|
||||
Variant::Variant(const PoolIntArray &p_int_array) {
|
||||
godot::api->godot_variant_new_pool_int_array(&_godot_variant, (godot_pool_int_array *)&p_int_array);
|
||||
}
|
||||
|
||||
Variant::Variant(const PoolRealArray &p_real_array) {
|
||||
godot::api->godot_variant_new_pool_real_array(&_godot_variant, (godot_pool_real_array *)&p_real_array);
|
||||
}
|
||||
|
||||
Variant::Variant(const PoolStringArray &p_string_array) {
|
||||
godot::api->godot_variant_new_pool_string_array(&_godot_variant, (godot_pool_string_array *)&p_string_array);
|
||||
}
|
||||
|
||||
Variant::Variant(const PoolVector2Array &p_vector2_array) {
|
||||
godot::api->godot_variant_new_pool_vector2_array(&_godot_variant, (godot_pool_vector2_array *)&p_vector2_array);
|
||||
}
|
||||
|
||||
Variant::Variant(const PoolVector3Array &p_vector3_array) {
|
||||
godot::api->godot_variant_new_pool_vector3_array(&_godot_variant, (godot_pool_vector3_array *)&p_vector3_array);
|
||||
}
|
||||
|
||||
Variant::Variant(const PoolColorArray &p_color_array) {
|
||||
godot::api->godot_variant_new_pool_color_array(&_godot_variant, (godot_pool_color_array *)&p_color_array);
|
||||
}
|
||||
|
||||
Variant &Variant::operator=(const Variant &v) {
|
||||
godot::api->godot_variant_new_copy(&_godot_variant, &v._godot_variant);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Variant::operator bool() const {
|
||||
return booleanize();
|
||||
}
|
||||
Variant::operator signed int() const {
|
||||
return godot::api->godot_variant_as_int(&_godot_variant);
|
||||
}
|
||||
Variant::operator unsigned int() const // this is the real one
|
||||
{
|
||||
return godot::api->godot_variant_as_uint(&_godot_variant);
|
||||
}
|
||||
Variant::operator signed short() const {
|
||||
return godot::api->godot_variant_as_int(&_godot_variant);
|
||||
}
|
||||
Variant::operator unsigned short() const {
|
||||
return godot::api->godot_variant_as_uint(&_godot_variant);
|
||||
}
|
||||
Variant::operator signed char() const {
|
||||
return godot::api->godot_variant_as_int(&_godot_variant);
|
||||
}
|
||||
Variant::operator unsigned char() const {
|
||||
return godot::api->godot_variant_as_uint(&_godot_variant);
|
||||
}
|
||||
Variant::operator int64_t() const {
|
||||
return godot::api->godot_variant_as_int(&_godot_variant);
|
||||
}
|
||||
Variant::operator uint64_t() const {
|
||||
return godot::api->godot_variant_as_uint(&_godot_variant);
|
||||
}
|
||||
|
||||
Variant::operator wchar_t() const {
|
||||
return godot::api->godot_variant_as_int(&_godot_variant);
|
||||
}
|
||||
|
||||
Variant::operator float() const {
|
||||
return godot::api->godot_variant_as_real(&_godot_variant);
|
||||
}
|
||||
|
||||
Variant::operator double() const {
|
||||
return godot::api->godot_variant_as_real(&_godot_variant);
|
||||
}
|
||||
Variant::operator String() const {
|
||||
godot_string s = godot::api->godot_variant_as_string(&_godot_variant);
|
||||
return String(s);
|
||||
}
|
||||
Variant::operator Vector2() const {
|
||||
godot_vector2 s = godot::api->godot_variant_as_vector2(&_godot_variant);
|
||||
return *(Vector2 *)&s;
|
||||
}
|
||||
Variant::operator Rect2() const {
|
||||
godot_rect2 s = godot::api->godot_variant_as_rect2(&_godot_variant);
|
||||
return *(Rect2 *)&s;
|
||||
}
|
||||
Variant::operator Vector3() const {
|
||||
godot_vector3 s = godot::api->godot_variant_as_vector3(&_godot_variant);
|
||||
return *(Vector3 *)&s;
|
||||
}
|
||||
Variant::operator Plane() const {
|
||||
godot_plane s = godot::api->godot_variant_as_plane(&_godot_variant);
|
||||
return *(Plane *)&s;
|
||||
}
|
||||
Variant::operator AABB() const {
|
||||
godot_aabb s = godot::api->godot_variant_as_aabb(&_godot_variant);
|
||||
return *(AABB *)&s;
|
||||
}
|
||||
Variant::operator Quat() const {
|
||||
godot_quat s = godot::api->godot_variant_as_quat(&_godot_variant);
|
||||
return *(Quat *)&s;
|
||||
}
|
||||
Variant::operator Basis() const {
|
||||
godot_basis s = godot::api->godot_variant_as_basis(&_godot_variant);
|
||||
return *(Basis *)&s;
|
||||
}
|
||||
Variant::operator Transform() const {
|
||||
godot_transform s = godot::api->godot_variant_as_transform(&_godot_variant);
|
||||
return *(Transform *)&s;
|
||||
}
|
||||
Variant::operator Transform2D() const {
|
||||
godot_transform2d s = godot::api->godot_variant_as_transform2d(&_godot_variant);
|
||||
return *(Transform2D *)&s;
|
||||
}
|
||||
|
||||
Variant::operator Color() const {
|
||||
godot_color s = godot::api->godot_variant_as_color(&_godot_variant);
|
||||
return *(Color *)&s;
|
||||
}
|
||||
Variant::operator NodePath() const {
|
||||
godot_node_path ret = godot::api->godot_variant_as_node_path(&_godot_variant);
|
||||
return NodePath(ret);
|
||||
}
|
||||
Variant::operator RID() const {
|
||||
godot_rid s = godot::api->godot_variant_as_rid(&_godot_variant);
|
||||
return *(RID *)&s;
|
||||
}
|
||||
|
||||
Variant::operator Dictionary() const {
|
||||
Dictionary ret(godot::api->godot_variant_as_dictionary(&_godot_variant));
|
||||
return ret;
|
||||
}
|
||||
|
||||
Variant::operator Array() const {
|
||||
Array ret(godot::api->godot_variant_as_array(&_godot_variant));
|
||||
return ret;
|
||||
}
|
||||
|
||||
Variant::operator PoolByteArray() const {
|
||||
godot_pool_byte_array ret = godot::api->godot_variant_as_pool_byte_array(&_godot_variant);
|
||||
return PoolByteArray(ret);
|
||||
}
|
||||
Variant::operator PoolIntArray() const {
|
||||
godot_pool_int_array ret = godot::api->godot_variant_as_pool_int_array(&_godot_variant);
|
||||
return PoolIntArray(ret);
|
||||
}
|
||||
Variant::operator PoolRealArray() const {
|
||||
godot_pool_real_array ret = godot::api->godot_variant_as_pool_real_array(&_godot_variant);
|
||||
return PoolRealArray(ret);
|
||||
}
|
||||
Variant::operator PoolStringArray() const {
|
||||
godot_pool_string_array ret = godot::api->godot_variant_as_pool_string_array(&_godot_variant);
|
||||
return PoolStringArray(ret);
|
||||
}
|
||||
Variant::operator PoolVector2Array() const {
|
||||
godot_pool_vector2_array ret = godot::api->godot_variant_as_pool_vector2_array(&_godot_variant);
|
||||
return PoolVector2Array(ret);
|
||||
}
|
||||
Variant::operator PoolVector3Array() const {
|
||||
godot_pool_vector3_array ret = godot::api->godot_variant_as_pool_vector3_array(&_godot_variant);
|
||||
return PoolVector3Array(ret);
|
||||
}
|
||||
Variant::operator PoolColorArray() const {
|
||||
godot_pool_color_array ret = godot::api->godot_variant_as_pool_color_array(&_godot_variant);
|
||||
return PoolColorArray(ret);
|
||||
}
|
||||
Variant::operator godot_object *() const {
|
||||
return godot::api->godot_variant_as_object(&_godot_variant);
|
||||
}
|
||||
|
||||
Variant::Type Variant::get_type() const {
|
||||
return static_cast<Type>(godot::api->godot_variant_get_type(&_godot_variant));
|
||||
}
|
||||
|
||||
Variant Variant::call(const String &method, const Variant **args, const int arg_count) {
|
||||
godot_variant v = godot::api->godot_variant_call(
|
||||
&_godot_variant, (godot_string *)&method, (const godot_variant **)args, arg_count, nullptr);
|
||||
return Variant(v);
|
||||
}
|
||||
|
||||
bool Variant::has_method(const String &method) {
|
||||
return godot::api->godot_variant_has_method(&_godot_variant, (godot_string *)&method);
|
||||
}
|
||||
|
||||
bool Variant::operator==(const Variant &b) const {
|
||||
return godot::api->godot_variant_operator_equal(&_godot_variant, &b._godot_variant);
|
||||
}
|
||||
|
||||
bool Variant::operator!=(const Variant &b) const {
|
||||
return !(*this == b);
|
||||
}
|
||||
|
||||
bool Variant::operator<(const Variant &b) const {
|
||||
return godot::api->godot_variant_operator_less(&_godot_variant, &b._godot_variant);
|
||||
}
|
||||
|
||||
bool Variant::operator<=(const Variant &b) const {
|
||||
return (*this < b) || (*this == b);
|
||||
}
|
||||
|
||||
bool Variant::operator>(const Variant &b) const {
|
||||
return !(*this <= b);
|
||||
}
|
||||
|
||||
bool Variant::operator>=(const Variant &b) const {
|
||||
return !(*this < b);
|
||||
}
|
||||
|
||||
bool Variant::hash_compare(const Variant &b) const {
|
||||
return godot::api->godot_variant_hash_compare(&_godot_variant, &b._godot_variant);
|
||||
}
|
||||
|
||||
bool Variant::booleanize() const {
|
||||
return godot::api->godot_variant_booleanize(&_godot_variant);
|
||||
}
|
||||
|
||||
Variant::~Variant() {
|
||||
godot::api->godot_variant_destroy(&_godot_variant);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
312
src/core/class_db.cpp
Normal file
312
src/core/class_db.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
/*************************************************************************/
|
||||
/* class_db.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace godot {
|
||||
|
||||
std::unordered_map<std::string, ClassDB::ClassInfo> ClassDB::classes;
|
||||
|
||||
MethodDefinition D_METHOD(const char *p_name) {
|
||||
return MethodDefinition(p_name);
|
||||
}
|
||||
|
||||
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1) {
|
||||
MethodDefinition method(p_name);
|
||||
method.args.push_front(p_arg1);
|
||||
return method;
|
||||
}
|
||||
|
||||
void ClassDB::add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index) {
|
||||
ERR_FAIL_COND_MSG(classes.find(p_class) == classes.end(), "Trying to add property to non-existing class.");
|
||||
|
||||
ClassInfo &info = classes[p_class];
|
||||
|
||||
ERR_FAIL_COND_MSG(info.property_setget.find(p_pinfo.name) != info.property_setget.end(), "Property already exists in class.");
|
||||
|
||||
MethodBind *setter = nullptr;
|
||||
if (p_setter) {
|
||||
setter = get_method(p_class, p_setter);
|
||||
|
||||
ERR_FAIL_COND_MSG(!setter, "Setter method not found for property.");
|
||||
|
||||
size_t exp_args = 1 + (p_index >= 0 ? 1 : 0);
|
||||
ERR_FAIL_COND_MSG(exp_args != setter->get_argument_count(), "Setter method must take a single argument.");
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(!p_getter, "Getter method must be specified.");
|
||||
|
||||
MethodBind *getter = get_method(p_class, p_getter);
|
||||
ERR_FAIL_COND_MSG(!getter, "Getter method not found for property.");
|
||||
{
|
||||
size_t exp_args = 0 + (p_index >= 0 ? 1 : 0);
|
||||
ERR_FAIL_COND_MSG(exp_args != getter->get_argument_count(), "Getter method must not take any argument.");
|
||||
}
|
||||
|
||||
info.property_list.push_back(p_pinfo);
|
||||
|
||||
PropertySetGet setget;
|
||||
setget.setter = p_setter;
|
||||
setget.getter = p_getter;
|
||||
setget._setptr = setter;
|
||||
setget._getptr = getter;
|
||||
setget.index = p_index;
|
||||
setget.type = p_pinfo.type;
|
||||
|
||||
info.property_setget[p_pinfo.name] = setget;
|
||||
}
|
||||
|
||||
MethodBind *ClassDB::get_method(const char *p_class, const char *p_method) {
|
||||
ERR_FAIL_COND_V_MSG(classes.find(p_class) == classes.end(), nullptr, "Class not found.");
|
||||
|
||||
ClassInfo *type = &classes[p_class];
|
||||
while (type) {
|
||||
std::unordered_map<std::string, MethodBind *>::iterator method = type->method_map.find(p_method);
|
||||
if (method != type->method_map.end()) {
|
||||
return method->second;
|
||||
}
|
||||
type = type->parent_ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount) {
|
||||
const char *instance_type = p_bind->get_instance_class();
|
||||
|
||||
std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(instance_type);
|
||||
if (type_it == classes.end()) {
|
||||
memdelete(p_bind);
|
||||
ERR_FAIL_V_MSG(nullptr, "Class doesn't exist.");
|
||||
}
|
||||
|
||||
ClassInfo &type = type_it->second;
|
||||
|
||||
if (type.method_map.find(method_name.name) != type.method_map.end()) {
|
||||
memdelete(p_bind);
|
||||
ERR_FAIL_V_MSG(nullptr, "Binding duplicate method.");
|
||||
}
|
||||
|
||||
if (type.virtual_methods.find(method_name.name) != type.virtual_methods.end()) {
|
||||
memdelete(p_bind);
|
||||
ERR_FAIL_V_MSG(nullptr, "Method already bound as virtual.");
|
||||
}
|
||||
|
||||
p_bind->set_name(method_name.name);
|
||||
|
||||
if (method_name.args.size() > p_bind->get_argument_count()) {
|
||||
memdelete(p_bind);
|
||||
ERR_FAIL_V_MSG(nullptr, "Method definition has more arguments than the actual method.");
|
||||
}
|
||||
|
||||
p_bind->set_hint_flags(p_flags);
|
||||
|
||||
std::vector<std::string> args;
|
||||
args.resize(method_name.args.size());
|
||||
size_t arg_index = 0;
|
||||
for (std::string arg : method_name.args) {
|
||||
args[arg_index++] = arg;
|
||||
}
|
||||
|
||||
p_bind->set_argument_names(args);
|
||||
|
||||
type.method_order.push_back(p_bind);
|
||||
type.method_map[method_name.name] = p_bind;
|
||||
|
||||
return p_bind;
|
||||
}
|
||||
|
||||
void ClassDB::add_signal(const char *p_class, const MethodInfo &p_signal) {
|
||||
std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(p_class);
|
||||
|
||||
ERR_FAIL_COND_MSG(type_it == classes.end(), "Class doesn't exist.");
|
||||
|
||||
ClassInfo &base = type_it->second;
|
||||
ClassInfo *check = &base;
|
||||
while (check) {
|
||||
ERR_FAIL_COND_MSG(check->signal_map.find(p_signal.name) != check->signal_map.end(), String("Class '" + String(p_class) + "' already has signal '" + String(p_signal.name) + "'.").utf8().get_data());
|
||||
check = check->parent_ptr;
|
||||
}
|
||||
|
||||
base.signal_map[p_signal.name] = p_signal;
|
||||
}
|
||||
|
||||
void ClassDB::bind_integer_constant(const char *p_class, const char *p_enum, const char *p_name, GDNativeInt p_constant) {
|
||||
std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(p_class);
|
||||
|
||||
ERR_FAIL_COND_MSG(type_it == classes.end(), "Class doesn't exist.");
|
||||
|
||||
ClassInfo &type = type_it->second;
|
||||
|
||||
ERR_FAIL_COND_MSG(type.constant_map.find(p_name) != type.constant_map.end(), "Constant already registered.");
|
||||
|
||||
type.constant_map[p_name] = std::pair<std::string, GDNativeInt>{ p_enum, p_constant };
|
||||
type.constant_order.push_back(p_name);
|
||||
}
|
||||
|
||||
GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, const char *p_name) {
|
||||
const char *class_name = (const char *)p_userdata;
|
||||
|
||||
std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(class_name);
|
||||
ERR_FAIL_COND_V_MSG(type_it == classes.end(), nullptr, "Class doesn't exist.");
|
||||
|
||||
ClassInfo &type = type_it->second;
|
||||
|
||||
std::unordered_map<std::string, GDNativeExtensionClassCallVirtual>::iterator method_it = type.virtual_methods.find(p_name);
|
||||
|
||||
if (method_it == type.virtual_methods.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return method_it->second;
|
||||
}
|
||||
|
||||
void ClassDB::bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call) {
|
||||
std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(p_class);
|
||||
ERR_FAIL_COND_MSG(type_it == classes.end(), "Class doesn't exist.");
|
||||
|
||||
ClassInfo &type = type_it->second;
|
||||
|
||||
ERR_FAIL_COND_MSG(type.method_map.find(p_method) != type.method_map.end(), "Method already registered as non-virtual.");
|
||||
ERR_FAIL_COND_MSG(type.virtual_methods.find(p_method) != type.virtual_methods.end(), "Virtual method already registered.");
|
||||
|
||||
type.virtual_methods[p_method] = p_call;
|
||||
}
|
||||
|
||||
void ClassDB::initialize(GDNativeInitializationLevel p_level) {
|
||||
for (const std::pair<std::string, ClassInfo> pair : classes) {
|
||||
const ClassInfo &cl = pair.second;
|
||||
if (cl.level != p_level) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GDNativeExtensionClassCreationInfo class_info = {
|
||||
nullptr, // GDNativeExtensionClassSet set_func;
|
||||
nullptr, // GDNativeExtensionClassGet get_func;
|
||||
nullptr, // GDNativeExtensionClassGetPropertyList get_property_list_func;
|
||||
nullptr, // GDNativeExtensionClassFreePropertyList free_property_list_func;
|
||||
nullptr, // GDNativeExtensionClassNotification notification_func;
|
||||
nullptr, // GDNativeExtensionClassToString to_string_func;
|
||||
nullptr, // GDNativeExtensionClassReference reference_func;
|
||||
nullptr, // GDNativeExtensionClassUnreference
|
||||
cl.constructor, // GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||
cl.destructor, // GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
||||
cl.object_instance, // GDNativeExtensionClassObjectInstance object_instance_func; /* this one is mandatory */
|
||||
&ClassDB::get_virtual_func, // GDNativeExtensionClassGetVirtual get_virtual_func;
|
||||
(void *)cl.name, //void *class_userdata;
|
||||
};
|
||||
|
||||
internal::interface->classdb_register_extension_class(internal::library, cl.name, cl.parent_name, &class_info);
|
||||
|
||||
for (MethodBind *method : cl.method_order) {
|
||||
GDNativeExtensionClassMethodInfo method_info = {
|
||||
method->get_name(), //const char *name;
|
||||
method, //void *method_userdata;
|
||||
MethodBind::bind_call, //GDNativeExtensionClassMethodCall call_func;
|
||||
MethodBind::bind_ptrcall, //GDNativeExtensionClassMethodPtrCall ptrcall_func;
|
||||
GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT, //uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */
|
||||
(uint32_t)method->get_argument_count(), //uint32_t argument_count;
|
||||
(GDNativeBool)method->has_return(), //GDNativeBool has_return_value;
|
||||
MethodBind::bind_get_argument_type, //(GDNativeExtensionClassMethodGetArgumentType) get_argument_type_func;
|
||||
MethodBind::bind_get_argument_info, //GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
|
||||
MethodBind::bind_get_argument_metadata, //GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
|
||||
method->get_hint_flags(), //uint32_t default_argument_count;
|
||||
nullptr, //GDNativeVariantPtr *default_arguments;
|
||||
};
|
||||
internal::interface->classdb_register_extension_class_method(internal::library, cl.name, &method_info);
|
||||
}
|
||||
|
||||
for (const PropertyInfo &property : cl.property_list) {
|
||||
GDNativePropertyInfo info = {
|
||||
(uint32_t)property.type, //uint32_t type;
|
||||
property.name, //const char *name;
|
||||
property.class_name, //const char *class_name;
|
||||
property.hint, // NONE //uint32_t hint;
|
||||
property.hint_string, // const char *hint_string;
|
||||
property.usage, // DEFAULT //uint32_t usage;
|
||||
};
|
||||
|
||||
const PropertySetGet &setget = cl.property_setget.find(property.name)->second;
|
||||
|
||||
internal::interface->classdb_register_extension_class_property(internal::library, cl.name, &info, setget.setter, setget.getter);
|
||||
}
|
||||
|
||||
for (const std::pair<std::string, MethodInfo> pair : cl.signal_map) {
|
||||
const MethodInfo &signal = pair.second;
|
||||
|
||||
std::vector<GDNativePropertyInfo> parameters;
|
||||
parameters.reserve(signal.arguments.size());
|
||||
|
||||
for (const PropertyInfo &par : signal.arguments) {
|
||||
parameters.push_back(GDNativePropertyInfo{
|
||||
static_cast<uint32_t>(par.type), // uint32_t type;
|
||||
par.name, // const char *name;
|
||||
par.class_name, // const char *class_name;
|
||||
par.hint, // uint32_t hint;
|
||||
par.hint_string, // const char *hint_string;
|
||||
par.usage, // uint32_t usage;
|
||||
});
|
||||
}
|
||||
|
||||
internal::interface->classdb_register_extension_class_signal(internal::library, cl.name, pair.first.c_str(), parameters.data(), parameters.size());
|
||||
}
|
||||
|
||||
for (std::string constant : cl.constant_order) {
|
||||
const std::pair<std::string, GDNativeInt> &def = cl.constant_map.find(constant)->second;
|
||||
|
||||
internal::interface->classdb_register_extension_class_integer_constant(internal::library, cl.name, def.first.c_str(), constant.c_str(), def.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassDB::deinitialize(GDNativeInitializationLevel p_level) {
|
||||
for (const std::pair<std::string, ClassInfo> pair : classes) {
|
||||
const ClassInfo &cl = pair.second;
|
||||
if (cl.level != p_level) {
|
||||
continue;
|
||||
}
|
||||
|
||||
internal::interface->classdb_unregister_extension_class(internal::library, cl.name);
|
||||
|
||||
for (MethodBind *method : cl.method_order) {
|
||||
memdelete(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************/
|
||||
/* Vector3.cpp */
|
||||
/* error_macros.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
@@ -28,94 +28,30 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Vector3.hpp"
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
|
||||
#include "String.hpp"
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Basis.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const Vector3 Vector3::ZERO = Vector3();
|
||||
const Vector3 Vector3::ONE = Vector3(1, 1, 1);
|
||||
const Vector3 Vector3::INF = Vector3(INFINITY, INFINITY, INFINITY);
|
||||
|
||||
const Vector3 Vector3::LEFT = Vector3(-1, 0, 0);
|
||||
const Vector3 Vector3::RIGHT = Vector3(1, 0, 0);
|
||||
const Vector3 Vector3::UP = Vector3(0, 1, 0);
|
||||
const Vector3 Vector3::DOWN = Vector3(0, -1, 0);
|
||||
const Vector3 Vector3::FORWARD = Vector3(0, 0, -1);
|
||||
const Vector3 Vector3::BACK = Vector3(0, 0, 1);
|
||||
|
||||
bool Vector3::operator<(const Vector3 &p_v) const {
|
||||
if (x == p_v.x) {
|
||||
if (y == p_v.y)
|
||||
return z < p_v.z;
|
||||
else
|
||||
return y < p_v.y;
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_is_warning) {
|
||||
if (p_is_warning) {
|
||||
internal::interface->print_warning(p_message, p_function, p_file, p_line);
|
||||
} else {
|
||||
return x < p_v.x;
|
||||
internal::interface->print_error(p_message, p_function, p_file, p_line);
|
||||
}
|
||||
}
|
||||
|
||||
bool Vector3::operator<=(const Vector3 &p_v) const {
|
||||
if (x == p_v.x) {
|
||||
if (y == p_v.y)
|
||||
return z <= p_v.z;
|
||||
else
|
||||
return y < p_v.y;
|
||||
} else {
|
||||
return x < p_v.x;
|
||||
}
|
||||
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_is_warning) {
|
||||
_err_print_error(p_function, p_file, p_line, p_error, "", p_is_warning);
|
||||
}
|
||||
|
||||
Vector3 Vector3::cubic_interpolate(const Vector3 &b, const Vector3 &pre_a, const Vector3 &post_b, const real_t t) const {
|
||||
Vector3 p0 = pre_a;
|
||||
Vector3 p1 = *this;
|
||||
Vector3 p2 = b;
|
||||
Vector3 p3 = post_b;
|
||||
|
||||
real_t t2 = t * t;
|
||||
real_t t3 = t2 * t;
|
||||
|
||||
Vector3 out;
|
||||
out = ((p1 * 2.0) +
|
||||
(-p0 + p2) * t +
|
||||
(p0 * 2.0 - p1 * 5.0 + p2 * 4 - p3) * t2 +
|
||||
(-p0 + p1 * 3.0 - p2 * 3.0 + p3) * t3) *
|
||||
0.5;
|
||||
return out;
|
||||
}
|
||||
|
||||
Basis Vector3::outer(const Vector3 &b) const {
|
||||
Vector3 row0(x * b.x, x * b.y, x * b.z);
|
||||
Vector3 row1(y * b.x, y * b.y, y * b.z);
|
||||
Vector3 row2(z * b.x, z * b.y, z * b.z);
|
||||
return Basis(row0, row1, row2);
|
||||
}
|
||||
|
||||
int Vector3::max_axis() const {
|
||||
return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0);
|
||||
}
|
||||
|
||||
int Vector3::min_axis() const {
|
||||
return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
|
||||
}
|
||||
|
||||
void Vector3::rotate(const Vector3 &p_axis, real_t p_phi) {
|
||||
*this = Basis(p_axis, p_phi).xform(*this);
|
||||
}
|
||||
|
||||
void Vector3::snap(real_t p_val) {
|
||||
x = Math::stepify(x, p_val);
|
||||
y = Math::stepify(y, p_val);
|
||||
z = Math::stepify(z, p_val);
|
||||
}
|
||||
|
||||
Vector3::operator String() const {
|
||||
return String::num(x) + ", " + String::num(y) + ", " + String::num(z);
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool fatal) {
|
||||
std::string fstr(fatal ? "FATAL: " : "");
|
||||
std::string err(fstr + "Index " + p_index_str + " = " + std::to_string(p_index) + " is out of bounds (" + p_size_str + " = " + std::to_string(p_size) + ").");
|
||||
_err_print_error(p_function, p_file, p_line, err.c_str(), p_message);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************/
|
||||
/* TagDP.cpp */
|
||||
/* memory.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
@@ -28,51 +28,26 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "TagDB.hpp"
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <GodotGlobal.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
namespace _TagDB {
|
||||
|
||||
std::unordered_map<size_t, size_t> parent_to;
|
||||
|
||||
void register_type(size_t type_tag, size_t base_type_tag) {
|
||||
if (type_tag == base_type_tag) {
|
||||
return;
|
||||
}
|
||||
parent_to[type_tag] = base_type_tag;
|
||||
void *Memory::alloc_static(size_t p_bytes) {
|
||||
return internal::interface->mem_alloc(p_bytes);
|
||||
}
|
||||
|
||||
bool is_type_known(size_t type_tag) {
|
||||
return parent_to.find(type_tag) != parent_to.end();
|
||||
void *Memory::realloc_static(void *p_memory, size_t p_bytes) {
|
||||
return internal::interface->mem_realloc(p_memory, p_bytes);
|
||||
}
|
||||
|
||||
void register_global_type(const char *name, size_t type_tag, size_t base_type_tag) {
|
||||
godot::nativescript_1_1_api->godot_nativescript_set_global_type_tag(godot::_RegisterState::language_index, name, (const void *)type_tag);
|
||||
|
||||
register_type(type_tag, base_type_tag);
|
||||
void Memory::free_static(void *p_ptr) {
|
||||
internal::interface->mem_free(p_ptr);
|
||||
}
|
||||
|
||||
bool is_type_compatible(size_t ask_tag, size_t have_tag) {
|
||||
if (have_tag == 0)
|
||||
return false;
|
||||
|
||||
size_t tag = have_tag;
|
||||
|
||||
while (tag != 0) {
|
||||
if (tag == ask_tag)
|
||||
return true;
|
||||
|
||||
tag = parent_to[tag];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace _TagDB
|
||||
|
||||
} // namespace godot
|
||||
|
||||
void *operator new(size_t p_size, const char *p_description) {
|
||||
return godot::Memory::alloc_static(p_size);
|
||||
}
|
||||
120
src/core/method_bind.cpp
Normal file
120
src/core/method_bind.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*************************************************************************/
|
||||
/* method_bind.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include <godot_cpp/core/method_bind.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const char *MethodBind::get_name() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
void MethodBind::set_name(const char *p_name) {
|
||||
name = p_name;
|
||||
}
|
||||
|
||||
void MethodBind::set_argument_count(int p_count) {
|
||||
argument_count = p_count;
|
||||
}
|
||||
|
||||
void MethodBind::set_const(bool p_const) {
|
||||
_is_const = p_const;
|
||||
}
|
||||
|
||||
void MethodBind::set_return(bool p_return) {
|
||||
_has_return = p_return;
|
||||
}
|
||||
|
||||
void MethodBind::set_argument_names(const std::vector<std::string> &p_names) {
|
||||
argument_names = p_names;
|
||||
}
|
||||
|
||||
std::vector<std::string> MethodBind::get_argument_names() const {
|
||||
return argument_names;
|
||||
}
|
||||
|
||||
void MethodBind::generate_argument_types(int p_count) {
|
||||
set_argument_count(p_count);
|
||||
|
||||
if (argument_types != nullptr) {
|
||||
memdelete_arr(argument_types);
|
||||
}
|
||||
|
||||
argument_types = memnew_arr(GDNativeVariantType, p_count + 1);
|
||||
|
||||
// -1 means return type.
|
||||
for (int i = -1; i < p_count; i++) {
|
||||
argument_types[i + 1] = gen_argument_type(i);
|
||||
}
|
||||
}
|
||||
|
||||
GDNativePropertyInfo MethodBind::get_argument_info(int p_argument) const {
|
||||
GDNativePropertyInfo info = gen_argument_type_info(p_argument);
|
||||
if (p_argument >= 0) {
|
||||
info.name = p_argument < (int)argument_names.size() ? argument_names[p_argument].c_str() : "";
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
GDNativeVariantType MethodBind::bind_get_argument_type(void *p_method_userdata, int32_t p_argument) {
|
||||
const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
|
||||
return bind->get_argument_type(p_argument);
|
||||
}
|
||||
|
||||
void MethodBind::bind_get_argument_info(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info) {
|
||||
const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
|
||||
*r_info = bind->get_argument_info(p_argument);
|
||||
}
|
||||
|
||||
GDNativeExtensionClassMethodArgumentMetadata MethodBind::bind_get_argument_metadata(void *p_method_userdata, int32_t p_argument) {
|
||||
const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
|
||||
return bind->get_argument_metadata(p_argument);
|
||||
}
|
||||
|
||||
void MethodBind::bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
|
||||
const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
|
||||
Variant ret = bind->call(p_instance, p_args, p_argument_count, *r_error);
|
||||
// This assumes the return value is an empty Variant, so it doesn't need to call the destructor first.
|
||||
// Since only NativeExtensionMethodBind calls this from the Godot side, it should always be the case.
|
||||
internal::interface->variant_new_copy(r_return, ret.ptr);
|
||||
}
|
||||
|
||||
void MethodBind::bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return) {
|
||||
const MethodBind *bind = reinterpret_cast<const MethodBind *>(p_method_userdata);
|
||||
bind->ptrcall(p_instance, p_args, r_return);
|
||||
}
|
||||
|
||||
MethodBind::~MethodBind() {
|
||||
if (argument_types) {
|
||||
memdelete_arr(argument_types);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************/
|
||||
/* RID.cpp */
|
||||
/* object.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
@@ -28,52 +28,27 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "RID.hpp"
|
||||
|
||||
#include <gdnative/rid.h>
|
||||
|
||||
#include "GodotGlobal.hpp"
|
||||
#include <godot_cpp/core/object.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
RID::RID() {
|
||||
godot::api->godot_rid_new(&_godot_rid);
|
||||
MethodInfo::MethodInfo() :
|
||||
flags(METHOD_FLAG_NORMAL) {}
|
||||
|
||||
MethodInfo::MethodInfo(const char *p_name) :
|
||||
name(p_name), flags(METHOD_FLAG_NORMAL) {}
|
||||
|
||||
MethodInfo::MethodInfo(Variant::Type ret) :
|
||||
flags(METHOD_FLAG_NORMAL) {
|
||||
return_val.type = ret;
|
||||
}
|
||||
|
||||
RID::RID(Object *p) {
|
||||
godot::api->godot_rid_new_with_resource(&_godot_rid, (const godot_object *)p);
|
||||
MethodInfo::MethodInfo(Variant::Type ret, const char *p_name) :
|
||||
name(p_name), flags(METHOD_FLAG_NORMAL) {
|
||||
return_val.type = ret;
|
||||
}
|
||||
|
||||
godot_rid RID::_get_godot_rid() const {
|
||||
return _godot_rid;
|
||||
}
|
||||
|
||||
int32_t RID::get_id() const {
|
||||
return godot::api->godot_rid_get_id(&_godot_rid);
|
||||
}
|
||||
|
||||
bool RID::operator==(const RID &p_other) const {
|
||||
return godot::api->godot_rid_operator_equal(&_godot_rid, &p_other._godot_rid);
|
||||
}
|
||||
|
||||
bool RID::operator!=(const RID &p_other) const {
|
||||
return !(*this == p_other);
|
||||
}
|
||||
|
||||
bool RID::operator<(const RID &p_other) const {
|
||||
return godot::api->godot_rid_operator_less(&_godot_rid, &p_other._godot_rid);
|
||||
}
|
||||
|
||||
bool RID::operator>(const RID &p_other) const {
|
||||
return !(*this < p_other) && *this != p_other;
|
||||
}
|
||||
|
||||
bool RID::operator<=(const RID &p_other) const {
|
||||
return (*this < p_other) || *this == p_other;
|
||||
}
|
||||
|
||||
bool RID::operator>=(const RID &p_other) const {
|
||||
return !(*this < p_other);
|
||||
}
|
||||
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name) :
|
||||
name(p_name), return_val(p_ret), flags(METHOD_FLAG_NORMAL) {}
|
||||
|
||||
} // namespace godot
|
||||
2
src/gen/.gitignore
vendored
2
src/gen/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
*
|
||||
!.gitignore
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************/
|
||||
/* Vector2.cpp */
|
||||
/* godot.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
@@ -28,73 +28,55 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "Vector2.hpp"
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <gdnative/vector2.h>
|
||||
#include <godot_cpp/classes/wrapped.hpp>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
#include "String.hpp"
|
||||
#include <godot_cpp/core/error_macros.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const Vector2 Vector2::ZERO = Vector2();
|
||||
const Vector2 Vector2::ONE = Vector2(1, 1);
|
||||
const Vector2 Vector2::INF = Vector2(INFINITY, INFINITY);
|
||||
namespace internal {
|
||||
|
||||
const Vector2 Vector2::LEFT = Vector2(-1, 0);
|
||||
const Vector2 Vector2::RIGHT = Vector2(1, 0);
|
||||
const Vector2 Vector2::UP = Vector2(0, -1);
|
||||
const Vector2 Vector2::DOWN = Vector2(0, 1);
|
||||
const GDNativeInterface *interface;
|
||||
GDNativeExtensionClassLibraryPtr library;
|
||||
void *token;
|
||||
|
||||
bool Vector2::operator==(const Vector2 &p_vec2) const {
|
||||
return x == p_vec2.x && y == p_vec2.y;
|
||||
} // namespace internal
|
||||
|
||||
GDNativeBool GDExtensionBinding::init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) {
|
||||
internal::interface = p_interface;
|
||||
internal::library = p_library;
|
||||
internal::token = p_library;
|
||||
|
||||
r_initialization->initialize = initialize_level;
|
||||
r_initialization->deinitialize = deinitialize_level;
|
||||
|
||||
Variant::init_bindings();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Vector2::operator!=(const Vector2 &p_vec2) const {
|
||||
return x != p_vec2.x || y != p_vec2.y;
|
||||
void GDExtensionBinding::initialize_level(void *userdata, GDNativeInitializationLevel p_level) {
|
||||
ClassDB::initialize(p_level);
|
||||
}
|
||||
|
||||
Vector2 Vector2::project(const Vector2 &p_vec) const {
|
||||
Vector2 v1 = p_vec;
|
||||
Vector2 v2 = *this;
|
||||
return v2 * (v1.dot(v2) / v2.dot(v2));
|
||||
void GDExtensionBinding::deinitialize_level(void *userdata, GDNativeInitializationLevel p_level) {
|
||||
ClassDB::deinitialize(p_level);
|
||||
}
|
||||
|
||||
Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
|
||||
return p_vec - *this * (dot(p_vec) - p_d);
|
||||
void *GDExtensionBinding::create_instance_callback(void *p_token, void *p_instance) {
|
||||
ERR_FAIL_COND_V_MSG(p_token != internal::library, nullptr, "Asking for creating instance with invalid token.");
|
||||
Wrapped *wrapped = memnew(Wrapped(p_instance));
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
Vector2 Vector2::clamped(real_t p_len) const {
|
||||
real_t l = length();
|
||||
Vector2 v = *this;
|
||||
if (l > 0 && p_len < l) {
|
||||
v /= l;
|
||||
v *= p_len;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const {
|
||||
Vector2 p0 = p_pre_a;
|
||||
Vector2 p1 = *this;
|
||||
Vector2 p2 = p_b;
|
||||
Vector2 p3 = p_post_b;
|
||||
|
||||
real_t t = p_t;
|
||||
real_t t2 = t * t;
|
||||
real_t t3 = t2 * t;
|
||||
|
||||
Vector2 out;
|
||||
out = ((p1 * 2.0) +
|
||||
(-p0 + p2) * t +
|
||||
(p0 * 2.0 - p1 * 5.0 + p2 * 4 - p3) * t2 +
|
||||
(-p0 + p1 * 3.0 - p2 * 3.0 + p3) * t3) *
|
||||
0.5;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Vector2::operator String() const {
|
||||
return String::num(x) + ", " + String::num(y);
|
||||
void GDExtensionBinding::free_instance_callback(void *p_token, void *p_instance, void *p_binding) {
|
||||
ERR_FAIL_COND_MSG(p_token != internal::library, "Asking for freeing instance with invalid token.");
|
||||
memdelete((Wrapped *)p_binding);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
267
src/variant/char_string.cpp
Normal file
267
src/variant/char_string.cpp
Normal file
@@ -0,0 +1,267 @@
|
||||
/*************************************************************************/
|
||||
/* char_string.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include <godot_cpp/variant/char_string.hpp>
|
||||
|
||||
#include <godot_cpp/core/memory.hpp>
|
||||
#include <godot_cpp/variant/node_path.hpp>
|
||||
#include <godot_cpp/variant/string.hpp>
|
||||
#include <godot_cpp/variant/string_name.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
namespace godot {
|
||||
|
||||
const char *CharString::get_data() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
CharString::CharString(const char *str, int length) :
|
||||
_data(str), _length(length) {}
|
||||
|
||||
CharString::~CharString() {
|
||||
memdelete_arr(_data);
|
||||
}
|
||||
|
||||
Char16String::Char16String(const char16_t *str, int length) :
|
||||
_data(str), _length(length) {}
|
||||
|
||||
Char16String::~Char16String() {
|
||||
memdelete_arr(_data);
|
||||
}
|
||||
|
||||
Char32String::Char32String(const char32_t *str, int length) :
|
||||
_data(str), _length(length) {}
|
||||
|
||||
Char32String::~Char32String() {
|
||||
memdelete_arr(_data);
|
||||
}
|
||||
|
||||
CharWideString::CharWideString(const wchar_t *str, int length) :
|
||||
_data(str), _length(length) {}
|
||||
|
||||
CharWideString::~CharWideString() {
|
||||
memdelete_arr(_data);
|
||||
}
|
||||
|
||||
// Custom String functions that are not part of bound API.
|
||||
// It's easier to have them written in C++ directly than in a Python script that generates them.
|
||||
|
||||
String::String(const char *from) {
|
||||
internal::interface->string_new_with_utf8_chars(ptr, from);
|
||||
}
|
||||
|
||||
String::String(const wchar_t *from) {
|
||||
internal::interface->string_new_with_wide_chars(ptr, from);
|
||||
}
|
||||
|
||||
String::String(const char16_t *from) {
|
||||
internal::interface->string_new_with_utf16_chars(ptr, from);
|
||||
}
|
||||
|
||||
String::String(const char32_t *from) {
|
||||
internal::interface->string_new_with_utf32_chars(ptr, from);
|
||||
}
|
||||
|
||||
CharString String::utf8() const {
|
||||
int size = internal::interface->string_to_utf8_chars(ptr, nullptr, 0);
|
||||
char *cstr = memnew_arr(char, size + 1);
|
||||
internal::interface->string_to_utf8_chars(ptr, cstr, size + 1);
|
||||
|
||||
cstr[size] = '\0';
|
||||
|
||||
return CharString(cstr, size + 1);
|
||||
}
|
||||
|
||||
CharString String::ascii() const {
|
||||
int size = internal::interface->string_to_latin1_chars(ptr, nullptr, 0);
|
||||
char *cstr = memnew_arr(char, size + 1);
|
||||
internal::interface->string_to_latin1_chars(ptr, cstr, size + 1);
|
||||
|
||||
cstr[size] = '\0';
|
||||
|
||||
return CharString(cstr, size + 1);
|
||||
}
|
||||
|
||||
Char16String String::utf16() const {
|
||||
int size = internal::interface->string_to_utf16_chars(ptr, nullptr, 0);
|
||||
char16_t *cstr = memnew_arr(char16_t, size + 1);
|
||||
internal::interface->string_to_utf16_chars(ptr, cstr, size + 1);
|
||||
|
||||
cstr[size] = '\0';
|
||||
|
||||
return Char16String(cstr, size + 1);
|
||||
}
|
||||
|
||||
Char32String String::utf32() const {
|
||||
int size = internal::interface->string_to_utf32_chars(ptr, nullptr, 0);
|
||||
char32_t *cstr = memnew_arr(char32_t, size + 1);
|
||||
internal::interface->string_to_utf32_chars(ptr, cstr, size + 1);
|
||||
|
||||
cstr[size] = '\0';
|
||||
|
||||
return Char32String(cstr, size + 1);
|
||||
}
|
||||
|
||||
CharWideString String::wide_string() const {
|
||||
int size = internal::interface->string_to_wide_chars(ptr, nullptr, 0);
|
||||
wchar_t *cstr = memnew_arr(wchar_t, size + 1);
|
||||
internal::interface->string_to_wide_chars(ptr, cstr, size + 1);
|
||||
|
||||
cstr[size] = '\0';
|
||||
|
||||
return CharWideString(cstr, size + 1);
|
||||
}
|
||||
|
||||
String &String::operator=(const char *p_str) {
|
||||
*this = String(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const wchar_t *p_str) {
|
||||
*this = String(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const char16_t *p_str) {
|
||||
*this = String(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const char32_t *p_str) {
|
||||
*this = String(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool String::operator==(const char *p_str) const {
|
||||
return *this == String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator==(const wchar_t *p_str) const {
|
||||
return *this == String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator==(const char16_t *p_str) const {
|
||||
return *this == String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator==(const char32_t *p_str) const {
|
||||
return *this == String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator!=(const char *p_str) const {
|
||||
return *this != String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator!=(const wchar_t *p_str) const {
|
||||
return *this != String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator!=(const char16_t *p_str) const {
|
||||
return *this != String(p_str);
|
||||
}
|
||||
|
||||
bool String::operator!=(const char32_t *p_str) const {
|
||||
return *this != String(p_str);
|
||||
}
|
||||
|
||||
bool operator==(const char *p_chr, const String &p_str) {
|
||||
return p_str == String(p_chr);
|
||||
}
|
||||
|
||||
bool operator==(const wchar_t *p_chr, const String &p_str) {
|
||||
return p_str == String(p_chr);
|
||||
}
|
||||
|
||||
bool operator==(const char16_t *p_chr, const String &p_str) {
|
||||
return p_str == String(p_chr);
|
||||
}
|
||||
|
||||
bool operator==(const char32_t *p_chr, const String &p_str) {
|
||||
return p_str == String(p_chr);
|
||||
}
|
||||
|
||||
bool operator!=(const char *p_chr, const String &p_str) {
|
||||
return !(p_str == p_chr);
|
||||
}
|
||||
|
||||
bool operator!=(const wchar_t *p_chr, const String &p_str) {
|
||||
return !(p_str == p_chr);
|
||||
}
|
||||
|
||||
bool operator!=(const char16_t *p_chr, const String &p_str) {
|
||||
return !(p_str == p_chr);
|
||||
}
|
||||
|
||||
bool operator!=(const char32_t *p_chr, const String &p_str) {
|
||||
return !(p_str == p_chr);
|
||||
}
|
||||
|
||||
String operator+(const char *p_chr, const String &p_str) {
|
||||
return String(p_chr) + p_str;
|
||||
}
|
||||
|
||||
String operator+(const wchar_t *p_chr, const String &p_str) {
|
||||
return String(p_chr) + p_str;
|
||||
}
|
||||
|
||||
String operator+(const char16_t *p_chr, const String &p_str) {
|
||||
return String(p_chr) + p_str;
|
||||
}
|
||||
|
||||
String operator+(const char32_t *p_chr, const String &p_str) {
|
||||
return String(p_chr) + p_str;
|
||||
}
|
||||
|
||||
StringName::StringName(const char *from) :
|
||||
StringName(String(from)) {}
|
||||
|
||||
StringName::StringName(const wchar_t *from) :
|
||||
StringName(String(from)) {}
|
||||
|
||||
StringName::StringName(const char16_t *from) :
|
||||
StringName(String(from)) {}
|
||||
|
||||
StringName::StringName(const char32_t *from) :
|
||||
StringName(String(from)) {}
|
||||
|
||||
NodePath::NodePath(const char *from) :
|
||||
NodePath(String(from)) {}
|
||||
|
||||
NodePath::NodePath(const wchar_t *from) :
|
||||
NodePath(String(from)) {}
|
||||
|
||||
NodePath::NodePath(const char16_t *from) :
|
||||
NodePath(String(from)) {}
|
||||
|
||||
NodePath::NodePath(const char32_t *from) :
|
||||
NodePath(String(from)) {}
|
||||
|
||||
} // namespace godot
|
||||
749
src/variant/variant.cpp
Normal file
749
src/variant/variant.cpp
Normal file
@@ -0,0 +1,749 @@
|
||||
/*************************************************************************/
|
||||
/* variant.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include <godot_cpp/variant/variant.hpp>
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include <godot_cpp/core/binder_common.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace godot {
|
||||
|
||||
GDNativeVariantFromTypeConstructorFunc Variant::from_type_constructor[Variant::VARIANT_MAX]{};
|
||||
GDNativeTypeFromVariantConstructorFunc Variant::to_type_constructor[Variant::VARIANT_MAX]{};
|
||||
|
||||
void Variant::init_bindings() {
|
||||
// Start from 1 to skip NIL.
|
||||
for (int i = 1; i < VARIANT_MAX; i++) {
|
||||
from_type_constructor[i] = internal::interface->get_variant_from_type_constructor((GDNativeVariantType)i);
|
||||
to_type_constructor[i] = internal::interface->get_variant_to_type_constructor((GDNativeVariantType)i);
|
||||
}
|
||||
|
||||
String::init_bindings();
|
||||
Vector2::init_bindings();
|
||||
Vector2i::init_bindings();
|
||||
Rect2::init_bindings();
|
||||
Rect2i::init_bindings();
|
||||
Vector3::init_bindings();
|
||||
Vector3i::init_bindings();
|
||||
Transform2D::init_bindings();
|
||||
Plane::init_bindings();
|
||||
Quaternion::init_bindings();
|
||||
AABB::init_bindings();
|
||||
Basis::init_bindings();
|
||||
Transform3D::init_bindings();
|
||||
Color::init_bindings();
|
||||
StringName::init_bindings();
|
||||
NodePath::init_bindings();
|
||||
RID::init_bindings();
|
||||
Callable::init_bindings();
|
||||
Signal::init_bindings();
|
||||
Dictionary::init_bindings();
|
||||
Array::init_bindings();
|
||||
PackedByteArray::init_bindings();
|
||||
PackedInt32Array::init_bindings();
|
||||
PackedInt64Array::init_bindings();
|
||||
PackedFloat32Array::init_bindings();
|
||||
PackedFloat64Array::init_bindings();
|
||||
PackedStringArray::init_bindings();
|
||||
PackedVector2Array::init_bindings();
|
||||
PackedVector3Array::init_bindings();
|
||||
PackedColorArray::init_bindings();
|
||||
}
|
||||
|
||||
Variant::Variant() {
|
||||
internal::interface->variant_new_nil(ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const GDNativeVariantPtr native_ptr) {
|
||||
internal::interface->variant_new_copy(ptr, native_ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Variant &other) {
|
||||
internal::interface->variant_new_copy(ptr, other.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(Variant &&other) {
|
||||
std::swap(opaque, other.opaque);
|
||||
}
|
||||
|
||||
Variant::Variant(bool v) {
|
||||
GDNativeBool encoded;
|
||||
PtrToArg<bool>::encode(v, &encoded);
|
||||
from_type_constructor[BOOL](ptr, &encoded);
|
||||
}
|
||||
|
||||
Variant::Variant(int64_t v) {
|
||||
GDNativeInt encoded;
|
||||
PtrToArg<int64_t>::encode(v, &encoded);
|
||||
from_type_constructor[INT](ptr, &encoded);
|
||||
}
|
||||
|
||||
Variant::Variant(double v) {
|
||||
double encoded;
|
||||
PtrToArg<double>::encode(v, &encoded);
|
||||
from_type_constructor[FLOAT](ptr, &encoded);
|
||||
}
|
||||
|
||||
Variant::Variant(const String &v) {
|
||||
from_type_constructor[STRING](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector2 &v) {
|
||||
from_type_constructor[VECTOR2](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector2i &v) {
|
||||
from_type_constructor[VECTOR2I](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Rect2 &v) {
|
||||
from_type_constructor[RECT2](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Rect2i &v) {
|
||||
from_type_constructor[RECT2I](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector3 &v) {
|
||||
from_type_constructor[VECTOR3](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Vector3i &v) {
|
||||
from_type_constructor[VECTOR3I](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Transform2D &v) {
|
||||
from_type_constructor[TRANSFORM2D](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Plane &v) {
|
||||
from_type_constructor[PLANE](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Quaternion &v) {
|
||||
from_type_constructor[QUATERNION](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const godot::AABB &v) {
|
||||
from_type_constructor[AABB](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Basis &v) {
|
||||
from_type_constructor[BASIS](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Transform3D &v) {
|
||||
from_type_constructor[TRANSFORM3D](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Color &v) {
|
||||
from_type_constructor[COLOR](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const StringName &v) {
|
||||
from_type_constructor[STRING_NAME](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const NodePath &v) {
|
||||
from_type_constructor[NODE_PATH](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const godot::RID &v) {
|
||||
from_type_constructor[RID](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Object *v) {
|
||||
from_type_constructor[OBJECT](ptr, v->_owner);
|
||||
}
|
||||
|
||||
Variant::Variant(const Callable &v) {
|
||||
from_type_constructor[CALLABLE](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Signal &v) {
|
||||
from_type_constructor[SIGNAL](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Dictionary &v) {
|
||||
from_type_constructor[DICTIONARY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const Array &v) {
|
||||
from_type_constructor[ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedByteArray &v) {
|
||||
from_type_constructor[PACKED_BYTE_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedInt32Array &v) {
|
||||
from_type_constructor[PACKED_INT32_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedInt64Array &v) {
|
||||
from_type_constructor[PACKED_INT64_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedFloat32Array &v) {
|
||||
from_type_constructor[PACKED_FLOAT32_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedFloat64Array &v) {
|
||||
from_type_constructor[PACKED_FLOAT64_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedStringArray &v) {
|
||||
from_type_constructor[PACKED_STRING_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedVector2Array &v) {
|
||||
from_type_constructor[PACKED_VECTOR2_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedVector3Array &v) {
|
||||
from_type_constructor[PACKED_VECTOR3_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::Variant(const PackedColorArray &v) {
|
||||
from_type_constructor[PACKED_COLOR_ARRAY](ptr, v.ptr);
|
||||
}
|
||||
|
||||
Variant::~Variant() {
|
||||
internal::interface->variant_destroy(ptr);
|
||||
}
|
||||
|
||||
Variant::operator bool() const {
|
||||
GDNativeBool result;
|
||||
to_type_constructor[BOOL](&result, ptr);
|
||||
return PtrToArg<bool>::convert(&result);
|
||||
}
|
||||
|
||||
Variant::operator int64_t() const {
|
||||
GDNativeInt result;
|
||||
to_type_constructor[INT](&result, ptr);
|
||||
return PtrToArg<int64_t>::convert(&result);
|
||||
}
|
||||
|
||||
Variant::operator int32_t() const {
|
||||
return static_cast<int32_t>(operator int64_t());
|
||||
}
|
||||
|
||||
Variant::operator uint64_t() const {
|
||||
return static_cast<uint64_t>(operator int64_t());
|
||||
}
|
||||
|
||||
Variant::operator uint32_t() const {
|
||||
return static_cast<uint32_t>(operator int64_t());
|
||||
}
|
||||
|
||||
Variant::operator double() const {
|
||||
double result;
|
||||
to_type_constructor[FLOAT](&result, ptr);
|
||||
return PtrToArg<double>::convert(&result);
|
||||
}
|
||||
|
||||
Variant::operator float() const {
|
||||
return static_cast<float>(operator double());
|
||||
}
|
||||
|
||||
Variant::operator String() const {
|
||||
String result;
|
||||
to_type_constructor[STRING](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector2() const {
|
||||
Vector2 result;
|
||||
to_type_constructor[VECTOR2](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector2i() const {
|
||||
Vector2i result;
|
||||
to_type_constructor[VECTOR2I](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Rect2() const {
|
||||
Rect2 result;
|
||||
to_type_constructor[RECT2](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Rect2i() const {
|
||||
Rect2i result;
|
||||
to_type_constructor[RECT2I](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector3() const {
|
||||
Vector3 result;
|
||||
to_type_constructor[VECTOR3](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Vector3i() const {
|
||||
Vector3i result;
|
||||
to_type_constructor[VECTOR3I](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Transform2D() const {
|
||||
Transform2D result;
|
||||
to_type_constructor[TRANSFORM2D](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Plane() const {
|
||||
Plane result;
|
||||
to_type_constructor[PLANE](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Quaternion() const {
|
||||
Quaternion result;
|
||||
to_type_constructor[QUATERNION](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator godot::AABB() const {
|
||||
godot::AABB result;
|
||||
to_type_constructor[AABB](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Basis() const {
|
||||
Basis result;
|
||||
to_type_constructor[BASIS](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Transform3D() const {
|
||||
Transform3D result;
|
||||
to_type_constructor[TRANSFORM3D](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Color() const {
|
||||
Color result;
|
||||
to_type_constructor[COLOR](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator StringName() const {
|
||||
StringName result;
|
||||
to_type_constructor[STRING_NAME](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator NodePath() const {
|
||||
NodePath result;
|
||||
to_type_constructor[NODE_PATH](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator godot::RID() const {
|
||||
godot::RID result;
|
||||
to_type_constructor[RID](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Object *() const {
|
||||
GodotObject *obj;
|
||||
to_type_constructor[OBJECT](&obj, ptr);
|
||||
return reinterpret_cast<Object *>(internal::interface->object_get_instance_binding(obj, internal::token, &Object::___binding_callbacks));
|
||||
}
|
||||
|
||||
Variant::operator Callable() const {
|
||||
Callable result;
|
||||
to_type_constructor[CALLABLE](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Signal() const {
|
||||
Signal result;
|
||||
to_type_constructor[SIGNAL](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Dictionary() const {
|
||||
Dictionary result;
|
||||
to_type_constructor[DICTIONARY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator Array() const {
|
||||
Array result;
|
||||
to_type_constructor[ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedByteArray() const {
|
||||
PackedByteArray result;
|
||||
to_type_constructor[PACKED_BYTE_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedInt32Array() const {
|
||||
PackedInt32Array result;
|
||||
to_type_constructor[PACKED_INT32_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedInt64Array() const {
|
||||
PackedInt64Array result;
|
||||
to_type_constructor[PACKED_INT64_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedFloat32Array() const {
|
||||
PackedFloat32Array result;
|
||||
to_type_constructor[PACKED_FLOAT32_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedFloat64Array() const {
|
||||
PackedFloat64Array result;
|
||||
to_type_constructor[PACKED_FLOAT64_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedStringArray() const {
|
||||
PackedStringArray result;
|
||||
to_type_constructor[PACKED_STRING_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedVector2Array() const {
|
||||
PackedVector2Array result;
|
||||
to_type_constructor[PACKED_VECTOR2_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedVector3Array() const {
|
||||
PackedVector3Array result;
|
||||
to_type_constructor[PACKED_VECTOR3_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator PackedColorArray() const {
|
||||
PackedColorArray result;
|
||||
to_type_constructor[PACKED_COLOR_ARRAY](result.ptr, ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::operator const GDNativeVariantPtr() const {
|
||||
return reinterpret_cast<const GDNativeVariantPtr>(const_cast<uint8_t(*)[GODOT_CPP_VARIANT_SIZE]>(&opaque));
|
||||
}
|
||||
|
||||
Variant::operator GDNativeVariantPtr() {
|
||||
return reinterpret_cast<const GDNativeVariantPtr>(&opaque);
|
||||
}
|
||||
|
||||
Variant &Variant::operator=(const Variant &other) {
|
||||
clear();
|
||||
internal::interface->variant_new_copy(ptr, other.ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Variant &Variant::operator=(Variant &&other) {
|
||||
std::swap(opaque, other.opaque);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Variant::operator==(const Variant &other) const {
|
||||
if (get_type() != other.get_type()) {
|
||||
return false;
|
||||
}
|
||||
bool valid = false;
|
||||
Variant result;
|
||||
evaluate(OP_EQUAL, *this, other, result, valid);
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
bool Variant::operator!=(const Variant &other) const {
|
||||
if (get_type() != other.get_type()) {
|
||||
return true;
|
||||
}
|
||||
bool valid = false;
|
||||
Variant result;
|
||||
evaluate(OP_NOT_EQUAL, *this, other, result, valid);
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
bool Variant::operator<(const Variant &other) const {
|
||||
if (get_type() != other.get_type()) {
|
||||
return get_type() < other.get_type();
|
||||
}
|
||||
bool valid = false;
|
||||
Variant result;
|
||||
evaluate(OP_LESS, *this, other, result, valid);
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
void Variant::operator=(const GDNativeVariantPtr other_ptr) {
|
||||
internal::interface->variant_destroy(ptr);
|
||||
internal::interface->variant_new_copy(ptr, other_ptr);
|
||||
}
|
||||
|
||||
void Variant::call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDNativeCallError &r_error) {
|
||||
internal::interface->variant_call(ptr, method.ptr, reinterpret_cast<const GDNativeVariantPtr *>(const_cast<Variant **>(args)), argcount, r_ret.ptr, &r_error);
|
||||
}
|
||||
|
||||
void Variant::call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDNativeCallError &r_error) {
|
||||
internal::interface->variant_call_static(static_cast<GDNativeVariantType>(type), method.ptr, reinterpret_cast<const GDNativeVariantPtr *>(const_cast<Variant **>(args)), argcount, r_ret.ptr, &r_error);
|
||||
}
|
||||
|
||||
void Variant::evaluate(const Operator &op, const Variant &a, const Variant &b, Variant &r_ret, bool &r_valid) {
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_evaluate(static_cast<GDNativeVariantOperator>(op), a.ptr, b.ptr, r_ret.ptr, &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
void Variant::set(const Variant &key, const Variant &value, bool *r_valid) {
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_set(ptr, key.ptr, value.ptr, &valid);
|
||||
if (r_valid) {
|
||||
*r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
}
|
||||
|
||||
void Variant::set_named(const StringName &name, const Variant &value, bool &r_valid) {
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_set_named(ptr, name.ptr, value.ptr, &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
void Variant::set_indexed(int64_t index, const Variant &value, bool &r_valid, bool &r_oob) {
|
||||
GDNativeBool valid, oob;
|
||||
internal::interface->variant_set_indexed(ptr, index, value.ptr, &valid, &oob);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
r_oob = PtrToArg<bool>::convert(&oob);
|
||||
}
|
||||
|
||||
void Variant::set_keyed(const Variant &key, const Variant &value, bool &r_valid) {
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_set_keyed(ptr, key.ptr, value.ptr, &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
Variant Variant::get(const Variant &key, bool *r_valid) const {
|
||||
Variant result;
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_get(ptr, key.ptr, result.ptr, &valid);
|
||||
if (r_valid) {
|
||||
*r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant Variant::get_named(const StringName &name, bool &r_valid) const {
|
||||
Variant result;
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_get_named(ptr, name.ptr, result.ptr, &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant Variant::get_indexed(int64_t index, bool &r_valid, bool &r_oob) const {
|
||||
Variant result;
|
||||
GDNativeBool valid;
|
||||
GDNativeBool oob;
|
||||
internal::interface->variant_get_indexed(ptr, index, result.ptr, &valid, &oob);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
r_oob = PtrToArg<bool>::convert(&oob);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant Variant::get_keyed(const Variant &key, bool &r_valid) const {
|
||||
Variant result;
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_get_keyed(ptr, key.ptr, result.ptr, &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Variant::in(const Variant &index, bool *r_valid) const {
|
||||
Variant result;
|
||||
bool valid;
|
||||
evaluate(OP_IN, *this, index, result, valid);
|
||||
if (r_valid) {
|
||||
*r_valid = valid;
|
||||
}
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
bool Variant::iter_init(Variant &r_iter, bool &r_valid) const {
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_iter_init(ptr, r_iter.ptr, &valid);
|
||||
return PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
bool Variant::iter_next(Variant &r_iter, bool &r_valid) const {
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_iter_next(ptr, r_iter.ptr, &valid);
|
||||
return PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
|
||||
Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
|
||||
Variant result;
|
||||
GDNativeBool valid;
|
||||
internal::interface->variant_iter_get(ptr, r_iter.ptr, result.ptr, &valid);
|
||||
r_valid = PtrToArg<bool>::convert(&valid);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant::Type Variant::get_type() const {
|
||||
return static_cast<Variant::Type>(internal::interface->variant_get_type(ptr));
|
||||
}
|
||||
|
||||
bool Variant::has_method(const StringName &method) const {
|
||||
GDNativeBool has = internal::interface->variant_has_method(ptr, method.ptr);
|
||||
return PtrToArg<bool>::convert(&has);
|
||||
}
|
||||
|
||||
bool Variant::has_key(const Variant &key, bool *r_valid) const {
|
||||
GDNativeBool valid;
|
||||
GDNativeBool has = internal::interface->variant_has_key(ptr, key.ptr, &valid);
|
||||
if (r_valid) {
|
||||
*r_valid = PtrToArg<bool>::convert(&valid);
|
||||
}
|
||||
return PtrToArg<bool>::convert(&has);
|
||||
}
|
||||
|
||||
bool Variant::has_member(Variant::Type type, const StringName &member) {
|
||||
GDNativeBool has = internal::interface->variant_has_member(static_cast<GDNativeVariantType>(type), member.ptr);
|
||||
return PtrToArg<bool>::convert(&has);
|
||||
}
|
||||
|
||||
bool Variant::hash_compare(const Variant &variant) const {
|
||||
GDNativeBool compare = internal::interface->variant_hash_compare(ptr, variant.ptr);
|
||||
return PtrToArg<bool>::convert(&compare);
|
||||
}
|
||||
|
||||
bool Variant::booleanize() const {
|
||||
GDNativeBool booleanized = internal::interface->variant_booleanize(ptr);
|
||||
return PtrToArg<bool>::convert(&booleanized);
|
||||
}
|
||||
|
||||
String Variant::stringify() const {
|
||||
String result;
|
||||
internal::interface->variant_stringify(ptr, result.ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
Variant Variant::duplicate(bool deep) const {
|
||||
Variant result;
|
||||
GDNativeBool _deep;
|
||||
PtrToArg<bool>::encode(deep, &_deep);
|
||||
internal::interface->variant_duplicate(ptr, result.ptr, _deep);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) {
|
||||
internal::interface->variant_blend(a.ptr, b.ptr, c, r_dst.ptr);
|
||||
}
|
||||
|
||||
void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst) {
|
||||
internal::interface->variant_interpolate(a.ptr, b.ptr, c, r_dst.ptr);
|
||||
}
|
||||
|
||||
String Variant::get_type_name(Variant::Type type) {
|
||||
String result;
|
||||
internal::interface->variant_get_type_name(static_cast<GDNativeVariantType>(type), result.ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Variant::can_convert(Variant::Type from, Variant::Type to) {
|
||||
GDNativeBool can;
|
||||
internal::interface->variant_can_convert(static_cast<GDNativeVariantType>(from), static_cast<GDNativeVariantType>(to));
|
||||
return PtrToArg<bool>::convert(&can);
|
||||
}
|
||||
|
||||
bool Variant::can_convert_strict(Variant::Type from, Variant::Type to) {
|
||||
GDNativeBool can;
|
||||
internal::interface->variant_can_convert_strict(static_cast<GDNativeVariantType>(from), static_cast<GDNativeVariantType>(to));
|
||||
return PtrToArg<bool>::convert(&can);
|
||||
}
|
||||
|
||||
void Variant::clear() {
|
||||
static const bool needs_deinit[Variant::VARIANT_MAX] = {
|
||||
false, //NIL,
|
||||
false, //BOOL,
|
||||
false, //INT,
|
||||
false, //FLOAT,
|
||||
true, //STRING,
|
||||
false, //VECTOR2,
|
||||
false, //VECTOR2I,
|
||||
false, //RECT2,
|
||||
false, //RECT2I,
|
||||
false, //VECTOR3,
|
||||
false, //VECTOR3I,
|
||||
true, //TRANSFORM2D,
|
||||
false, //PLANE,
|
||||
false, //QUATERNION,
|
||||
true, //AABB,
|
||||
true, //BASIS,
|
||||
true, //TRANSFORM,
|
||||
|
||||
// misc types
|
||||
false, //COLOR,
|
||||
true, //STRING_NAME,
|
||||
true, //NODE_PATH,
|
||||
false, //RID,
|
||||
true, //OBJECT,
|
||||
true, //CALLABLE,
|
||||
true, //SIGNAL,
|
||||
true, //DICTIONARY,
|
||||
true, //ARRAY,
|
||||
|
||||
// typed arrays
|
||||
true, //PACKED_BYTE_ARRAY,
|
||||
true, //PACKED_INT32_ARRAY,
|
||||
true, //PACKED_INT64_ARRAY,
|
||||
true, //PACKED_FLOAT32_ARRAY,
|
||||
true, //PACKED_FLOAT64_ARRAY,
|
||||
true, //PACKED_STRING_ARRAY,
|
||||
true, //PACKED_VECTOR2_ARRAY,
|
||||
true, //PACKED_VECTOR3_ARRAY,
|
||||
true, //PACKED_COLOR_ARRAY,
|
||||
};
|
||||
|
||||
if (unlikely(needs_deinit[get_type()])) { // Make it fast for types that don't need deinit.
|
||||
internal::interface->variant_destroy(ptr);
|
||||
}
|
||||
internal::interface->variant_new_nil(ptr);
|
||||
}
|
||||
|
||||
} // namespace godot
|
||||
Reference in New Issue
Block a user