6#include <simplesquirrel/simplesquirrel.hpp>
18 if (sq_gettype(
vm,
idx) != OT_STRING)
return false;
19 const SQChar *
s =
nullptr;
20 if (SQ_FAILED(sq_getstring(
vm,
idx, &
s)) || !
s)
return false;
26 const SQObjectType
t = sq_gettype(
vm,
idx);
33 if (
t == OT_INTEGER) {
35 sq_getinteger(
vm,
idx, &
v);
44 const SQInteger
top = sq_gettop(
vm);
45 sq_pushobject(
vm, instance);
46 sq_pushstring(
vm,
name.c_str(), -1);
47 if (SQ_FAILED(sq_get(
vm, -2))) {
51 sq_getstackobj(
vm, -1, &out);
57bool getNumberField(
HSQUIRRELVM vm, HSQOBJECT instance,
const std::string &
name,
float &out) {
58 const SQInteger
top = sq_gettop(
vm);
59 sq_pushobject(
vm, instance);
60 sq_pushstring(
vm,
name.c_str(), -1);
61 if (SQ_FAILED(sq_get(
vm, -2))) {
65 const bool ok = readFloatAt(
vm, -1, out);
71 const SQInteger
top = sq_gettop(
vm);
72 sq_pushobject(
vm, instance);
73 sq_pushstring(
vm,
name.c_str(), -1);
74 sq_pushfloat(
vm, SQFloat(
value));
76 if (SQ_FAILED(sq_set(
vm, -3))) {
78 sq_pushobject(
vm, instance);
79 sq_pushstring(
vm,
name.c_str(), -1);
80 sq_pushfloat(
vm, SQFloat(
value));
81 if (SQ_FAILED(sq_newslot(
vm, -3, SQFalse))) {
90std::vector<std::string> collectFieldNames(ssq::Object fieldsObj) {
91 std::vector<std::string> names;
93 if (!
vm)
return names;
94 HSQOBJECT arr = fieldsObj.getRaw();
95 if (arr._type != OT_ARRAY)
return names;
97 const SQInteger
top = sq_gettop(
vm);
98 sq_pushobject(
vm, arr);
99 const SQInteger len = sq_getsize(
vm, -1);
100 names.reserve(
size_t(std::max<SQInteger>(0, len)));
101 for (SQInteger i = 0; i < len; ++i) {
102 sq_pushinteger(
vm, i);
103 if (SQ_FAILED(sq_get(
vm, -2)))
continue;
105 if (readStringField(
vm, -1,
name)) names.push_back(
name);
113 const SQInteger
top = sq_gettop(
vm);
114 sq_pushobject(
vm, arr);
115 const SQInteger len = sq_getsize(
vm, -1);
117 return int(std::max<SQInteger>(0, len));
128 int firstEntity,
int entityCount) {
129 if (!buf)
throw Exception(
"packScriptEntityFloats: buffer is null");
130 if (slot.empty())
throw Exception(
"packScriptEntityFloats: empty slot");
134 HSQOBJECT ents = entitiesObj.getRaw();
135 if (ents._type != OT_ARRAY)
return 0;
137 const std::vector<std::string>
fields = collectFieldNames(fieldsObj);
138 if (
fields.empty())
return 0;
140 const int total = entityArrayLen(
vm, ents);
141 const int first = std::clamp(firstEntity, 0, total);
142 const int n = std::clamp(entityCount, 0, total -
first);
143 if (
n <= 0)
return 0;
145 const int floatsPer = int(
fields.size());
146 std::vector<float> tmp(
size_t(
n) *
size_t(floatsPer), 0.f);
148 const SQInteger
top = sq_gettop(
vm);
149 sq_pushobject(
vm, ents);
150 for (
int i = 0; i <
n; ++i) {
152 if (SQ_FAILED(sq_get(
vm, -2))) {
154 throw Exception(
"packScriptEntityFloats: bad entity index %d",
first + i);
156 if (sq_gettype(
vm, -1) != OT_INSTANCE) {
158 throw Exception(
"packScriptEntityFloats: entity[%d] is not an instance",
first + i);
161 sq_getstackobj(
vm, -1, &entity);
164 sq_resetobject(&comp);
165 if (!getInstanceSlot(
vm, entity, slot, comp) || comp._type != OT_INSTANCE) {
166 if (comp._type != OT_NULL) sq_release(
vm, &comp);
168 throw Exception(
"packScriptEntityFloats: missing component slot '%s'", slot.c_str());
171 for (
int f = 0;
f < floatsPer; ++
f) {
173 if (!getNumberField(
vm, comp,
fields[
size_t(
f)],
v)) {
174 sq_release(
vm, &comp);
176 throw Exception(
"packScriptEntityFloats: missing field '%s.%s'", slot.c_str(),
179 tmp[size_t(i) * size_t(floatsPer) + size_t(
f)] =
v;
181 sq_release(
vm, &comp);
186 const int needBytes = (
first +
n) * floatsPer *
int(
sizeof(
float));
187 if (buf->
getSize() < needBytes)
188 throw Exception(
"packScriptEntityFloats: buffer too small (%d < %d)", buf->
getSize(),
195 ssq::Object fieldsObj,
GpuBuffer *buf,
int entityCount) {
200 GpuBuffer *buf,
int firstEntity,
int entityCount) {
201 if (!buf)
throw Exception(
"unpackScriptEntityFloats: buffer is null");
202 if (slot.empty())
throw Exception(
"unpackScriptEntityFloats: empty slot");
203 if (entityCount <= 0)
return 0;
207 HSQOBJECT ents = entitiesObj.getRaw();
208 if (ents._type != OT_ARRAY)
return 0;
210 const std::vector<std::string>
fields = collectFieldNames(fieldsObj);
211 if (
fields.empty())
return 0;
213 const int nArr = entityArrayLen(
vm, ents);
214 const int first = std::clamp(firstEntity, 0, nArr);
215 const int n = std::clamp(entityCount, 0, nArr -
first);
216 if (
n <= 0)
return 0;
218 const int floatsPer = int(
fields.size());
219 std::vector<float> tmp(
size_t(
n) *
size_t(floatsPer), 0.f);
220 const int needBytes = (
first +
n) * floatsPer *
int(
sizeof(
float));
221 if (buf->
getSize() < needBytes)
222 throw Exception(
"unpackScriptEntityFloats: buffer too small (%d < %d)", buf->
getSize(), needBytes);
225 const SQInteger
top = sq_gettop(
vm);
226 sq_pushobject(
vm, ents);
227 for (
int i = 0; i <
n; ++i) {
229 if (SQ_FAILED(sq_get(
vm, -2))) {
231 throw Exception(
"unpackScriptEntityFloats: bad entity index %d",
first + i);
234 sq_getstackobj(
vm, -1, &entity);
237 sq_resetobject(&comp);
238 if (!getInstanceSlot(
vm, entity, slot, comp) || comp._type != OT_INSTANCE) {
239 if (comp._type != OT_NULL) sq_release(
vm, &comp);
241 throw Exception(
"unpackScriptEntityFloats: missing component slot '%s'", slot.c_str());
244 for (
int f = 0;
f < floatsPer; ++
f) {
245 const float v = tmp[size_t(i) * size_t(floatsPer) + size_t(
f)];
246 if (!setNumberField(
vm, comp,
fields[
size_t(
f)],
v)) {
247 sq_release(
vm, &comp);
249 throw Exception(
"unpackScriptEntityFloats: cannot set '%s.%s'", slot.c_str(),
253 sq_release(
vm, &comp);
struct SQVM * HSQUIRRELVM
std::vector< std::string > fields
EVENGINE_API_FOUNDATION public API.
Backend-agnostic GPU buffer for compute (storage) or CPU staging transfers. Squirrel-owned; derived c...
virtual void writeFloat32s(const float *data, int count, int startIndex=0)=0
Bulk float upload/download (one transfer). startIndex is in floats.
virtual int getSize() const =0
Byte length of the owned buffer.
virtual void readFloat32s(float *out, int count, int startIndex=0) const =0
Reads float 32 s.
Fluids module — interactive surface fluid simulation.
int unpackScriptEntityFloatsRange(ssq::Object entitiesObj, const std::string &slot, ssq::Object fieldsObj, GpuBuffer *buf, int firstEntity, int entityCount)
Unpack a contiguous buffer range into the matching stable ECS view range.
int packScriptEntityFloats(ssq::Object entitiesObj, const std::string &slot, ssq::Object fieldsObj, GpuBuffer *buf)
Pack script ECS entities' component number fields into a GpuBuffer (AoS). entities: Squirrel array of...
int unpackScriptEntityFloats(ssq::Object entitiesObj, const std::string &slot, ssq::Object fieldsObj, GpuBuffer *buf, int entityCount)
Inverse of packScriptEntityFloats; entityCount should match pack result.
int packScriptEntityFloatsRange(ssq::Object entitiesObj, const std::string &slot, ssq::Object fieldsObj, GpuBuffer *buf, int firstEntity, int entityCount)
Pack a contiguous entity range into the matching range of an existing buffer.