File: model_path.cpp

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (160 lines) | stat: -rw-r--r-- 4,584 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//
//

#include "model_path.h"
#include "vecmath.h"

namespace scripting {
namespace api {

struct model_path_point_h {
	const model_path_h* parent = nullptr;

	vec3d point{};
	float radius = -1.0f;

	model_path_point_h() = default;

	model_path_point_h(const model_path_h* _parent, const vec3d& _point, float _radius)
	    : parent(_parent), point(_point), radius(_radius)
	{
	}

	bool isValid() const { return parent != nullptr && radius > 0.0f; }
};

ADE_OBJ(l_ModelPathPoint, model_path_point_h, "modelpathpoint", "Point in a model path");

ADE_FUNC(isValid, l_ModelPathPoint, nullptr, "Determines if the handle is valid", "boolean",
         "True if valid, false otherwise")
{
	model_path_point_h* p = nullptr;
	if (!ade_get_args(L, "o", l_ModelPathPoint.GetPtr(&p)))
		return ADE_RETURN_FALSE;

	return ade_set_args(L, "b", p->isValid());
}

ADE_VIRTVAR(Position, l_ModelPathPoint, "vector", "The current, global position of this path point.", "vector",
            "The current position of the point.")
{
	model_path_point_h* p = nullptr;
	if (!ade_get_args(L, "o", l_ModelPathPoint.GetPtr(&p)))
		return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));

	if (!p->isValid()) {
		return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
	}

	// A submodel is only valid if the object is a ship so this is safe
	auto objp  = p->parent->subsys.objh.objp();
	auto shipp = &Ships[objp->instance];

	auto pmi = model_get_instance(shipp->model_instance_num);
	auto pm = model_get(pmi->model_num);

	vec3d world_pos;
	model_instance_local_to_global_point(&world_pos, &p->point, pm, pmi, 0, &objp->orient, &objp->pos);

	return ade_set_error(L, "o", l_Vector.Set(world_pos));
}
ADE_VIRTVAR(Radius, l_ModelPathPoint, "number", "The radius of the path point.", "number", "The radius of the point.")
{
	model_path_point_h* p = nullptr;
	if (!ade_get_args(L, "o", l_ModelPathPoint.GetPtr(&p)))
		return ade_set_error(L, "f", -1.0f);

	if (!p->isValid()) {
		return ade_set_error(L, "f", -1.0f);
	}

	return ade_set_error(L, "f", p->radius);
}

model_path_h::model_path_h() = default;
model_path_h::model_path_h(const ship_subsys_h& _subsys, const model_path& _path) : subsys(_subsys)
{
	name            = _path.name;
	parent_submodel = _path.parent_submodel;

	verts.reserve(_path.nverts);
	for (auto i = 0; i < _path.nverts; ++i) {
		verts.push_back(_path.verts[i]);
	}
}
bool model_path_h::isValid() const { return subsys.isValid(); }

ADE_OBJ(l_ModelPath, model_path_h, "modelpath", "Path of a model");

ADE_FUNC(__len, l_ModelPath, nullptr, "Gets the number of points in this path", "number",
         "The number of points or 0 on error")
{
	model_path_h* p = nullptr;
	if (!ade_get_args(L, "o", l_ModelPath.GetPtr(&p)))
		return ade_set_error(L, "s", "");

	if (p == nullptr)
		return ade_set_error(L, "s", "");

	if (!p->isValid())
		return ade_set_error(L, "s", "");

	return ade_set_args(L, "i", static_cast<int>(p->verts.size()));
}

ADE_FUNC(isValid, l_ModelPath, nullptr, "Determines if the handle is valid", "boolean",
         "True if valid, false otherwise")
{
	model_path_h* p = nullptr;
	if (!ade_get_args(L, "o", l_ModelPath.GetPtr(&p)))
		return ADE_RETURN_FALSE;

	if (p == nullptr)
		return ADE_RETURN_FALSE;

	return ade_set_args(L, "b", p->isValid());
}

ADE_INDEXER(l_ModelPath, "number", "Returns the point in the path with the specified index", "modelpathpoint",
            "The point or invalid handle if index is invalid")
{
	model_path_h* p = nullptr;
	int idx;
	if (!ade_get_args(L, "oi", l_ModelPath.GetPtr(&p), &idx))
		return ade_set_error(L, "o", l_ModelPathPoint.Set(model_path_point_h()));

	if (p == nullptr)
		return ade_set_error(L, "o", l_ModelPathPoint.Set(model_path_point_h()));

	if (!p->isValid())
		return ade_set_error(L, "o", l_ModelPathPoint.Set(model_path_point_h()));

	idx = idx - 1; // Lua -> FS2

	if (idx < 0 || idx >= (int)p->verts.size()) {
		return ade_set_error(L, "o", l_ModelPathPoint.Set(model_path_point_h()));
	}

	auto& vert = p->verts[idx];

	return ade_set_args(L, "o", l_ModelPathPoint.Set(model_path_point_h(p, vert.pos, vert.radius)));
}

ADE_VIRTVAR(Name, l_ModelPath, "string", "The name of this model path", "string",
            "The name or empty string if handle is invalid")
{
	model_path_h* p = nullptr;
	if (!ade_get_args(L, "o", l_ModelPath.GetPtr(&p)))
		return ade_set_error(L, "s", "");

	if (p == nullptr)
		return ade_set_error(L, "s", "");

	if (!p->isValid())
		return ade_set_error(L, "s", "");

	return ade_set_args(L, "s", p->name.c_str());
}

} // namespace api
} // namespace scripting