#include "prop_data.h" #include "../world/voxel_chunk.h" #include "prop_data_prop.h" bool PropData::get_snap_to_mesh() { return _snap_to_mesh; } void PropData::set_snap_to_mesh(bool value) { _snap_to_mesh = value; } Vector3 PropData::get_snap_axis() { return _snap_axis; } void PropData::set_snap_axis(Vector3 value) { _snap_axis = value; } Ref PropData::get_prop(const int index) const { ERR_FAIL_INDEX_V(index, _props.size(), Ref()); return _props.get(index); } void PropData::set_prop(const int index, const Ref prop) { ERR_FAIL_INDEX(index, _props.size()); _props.set(index, prop); } void PropData::add_prop(const Ref prop) { _props.push_back(prop); } void PropData::remove_prop(const int index) { ERR_FAIL_INDEX(index, _props.size()); _props.remove(index); } int PropData::get_prop_count() const { return _props.size(); } Vector PropData::get_props() { Vector r; for (int i = 0; i < _props.size(); i++) { r.push_back(_props[i].get_ref_ptr()); } return r; } void PropData::set_props(const Vector &props) { _props.clear(); for (int i = 0; i < props.size(); i++) { Ref prop = Ref(props[i]); _props.push_back(prop); } } void PropData::add_textures_into(Ref texture_packer) { ERR_FAIL_COND(!texture_packer.is_valid()); for (int i = 0; i < _props.size(); ++i) { Ref entry = _props.get(i); Ref pmesh = entry; if (pmesh.is_valid() && pmesh->get_texture().is_valid()) { texture_packer->add_texture(pmesh->get_texture()); } Ref pdataprop = entry; if (pdataprop.is_valid() && pdataprop->get_prop().is_valid()) { pdataprop->get_prop()->add_textures_into(texture_packer); } } } void PropData::add_prop_lights_into(VoxelChunk *chunk, Transform parent_transform, bool allow_snap) { ERR_FAIL_COND(!ObjectDB::instance_validate(chunk)); for (int i = 0; i < _props.size(); ++i) { Ref entry = _props.get(i); Ref pl = entry; if (pl.is_valid()) { Transform t = parent_transform * pl->get_transform(); Vector3 px = t.origin / chunk->get_voxel_scale(); Vector3i cp = chunk->get_chunk_position(); Vector3i cs = chunk->get_chunk_size(); Ref vl; vl.instance(); vl->set_world_position(px.x + cp.x * cs.x, px.y + cp.y * cs.y, px.z + cp.z * cs.z); vl->set_color(pl->get_light_color()); vl->set_size(pl->get_light_size()); chunk->add_prop_light(vl); } Ref pdataprop = entry; if (pdataprop.is_valid() && pdataprop->get_prop().is_valid()) { Ref pd = pdataprop->get_prop(); if (allow_snap) { if (pd->get_snap_to_mesh()) print_error(pd->get_name()); pd->add_prop_lights_into(chunk, get_next_snapped_prop_transform(chunk, parent_transform * pdataprop->get_transform(), pd->get_snap_to_mesh(), pd->get_snap_axis()), allow_snap); } else { pd->add_prop_lights_into(chunk, parent_transform * pdataprop->get_transform(), allow_snap); } } } } void PropData::add_prop_lights_into_bind(Node *chunk, Transform parent_transform, bool allow_snap) { VoxelChunk *c = Object::cast_to(chunk); ERR_FAIL_COND(!ObjectDB::instance_validate(c)); add_prop_lights_into(c, parent_transform, allow_snap); } void PropData::add_meshes_into(Ref mesher, Ref texture_packer, Transform parent_transform, Spatial *snap_spatial) { ERR_FAIL_COND(!mesher.is_valid()); ERR_FAIL_COND(!texture_packer.is_valid()); ERR_FAIL_COND(texture_packer->get_generated_texture_count() == 0); ERR_FAIL_COND(snap_spatial != NULL && !ObjectDB::instance_validate(snap_spatial)); Vector2 texsize = texture_packer->get_generated_texture(0)->get_size(); for (int i = 0; i < _props.size(); ++i) { Ref entry = _props.get(i); Ref pmesh = entry; if (pmesh.is_valid()) { Rect2 reg = Rect2(0, 0, 1, 1); if (pmesh->get_texture().is_valid()) { Ref at = texture_packer->get_texture(pmesh->get_texture()); reg = at->get_region(); reg.position.x /= texsize.x; reg.position.y /= texsize.y; reg.size.x /= texsize.x; reg.size.y /= texsize.y; } if (snap_spatial != NULL) mesher->add_mesh_data_resource_transform(pmesh->get_mesh(), get_next_snapped_prop_transform(snap_spatial, parent_transform * pmesh->get_transform(), pmesh->get_snap_to_mesh(), pmesh->get_snap_axis()), reg); else mesher->add_mesh_data_resource_transform(pmesh->get_mesh(), parent_transform * pmesh->get_transform(), reg); } Ref pdataprop = entry; if (pdataprop.is_valid() && pdataprop->get_prop().is_valid()) { if (snap_spatial != NULL) pdataprop->get_prop()->add_meshes_into(mesher, texture_packer, get_next_snapped_prop_transform(snap_spatial, parent_transform * pdataprop->get_transform(), pdataprop->get_snap_to_mesh(), pdataprop->get_snap_axis()), snap_spatial); else pdataprop->get_prop()->add_meshes_into(mesher, texture_packer, parent_transform * pmesh->get_transform(), snap_spatial); } } } void PropData::add_meshes_into_bind(Ref mesher, Ref texture_packer, Transform parent_transform, Node *snap_spatial) { Spatial *s = Object::cast_to(snap_spatial); ERR_FAIL_COND(s != NULL && !ObjectDB::instance_validate(s)); add_meshes_into(mesher, texture_packer, parent_transform, s); } Transform PropData::get_next_snapped_prop_transform(Spatial *s, Transform parent_transform, bool snap_to_mesh, Vector3 snap_axis) { if (snap_to_mesh) { Vector3 pos = s->to_global(parent_transform.origin); Vector3 world_snap_axis = s->to_global(parent_transform.xform(snap_axis)); Vector3 world_snap_dir = world_snap_axis - pos; world_snap_dir *= 100; PhysicsDirectSpaceState *space_state = s->get_world()->get_direct_space_state(); ERR_FAIL_COND_V(space_state == NULL, parent_transform); PhysicsDirectSpaceState::RayResult res; if (space_state->intersect_ray(pos - world_snap_dir, pos + world_snap_dir, res, Set(), 1)) { parent_transform.origin = s->to_local(res.position); } } return parent_transform; } Transform PropData::get_next_snapped_prop_transform_bind(Node *spatial, Transform parent_transform, bool snap_to_mesh, Vector3 snap_axis) { Spatial *s = Object::cast_to(spatial); ERR_FAIL_COND_V(!ObjectDB::instance_validate(s), parent_transform); return get_next_snapped_prop_transform(s, parent_transform, snap_to_mesh, snap_axis); } PropData::PropData() { _snap_to_mesh = false; _snap_axis = Vector3(0, -1, 0); } PropData::~PropData() { _props.clear(); } void PropData::_bind_methods() { ClassDB::bind_method(D_METHOD("get_snap_to_mesh"), &PropData::get_snap_to_mesh); ClassDB::bind_method(D_METHOD("set_snap_to_mesh", "value"), &PropData::set_snap_to_mesh); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_to_mesh"), "set_snap_to_mesh", "get_snap_to_mesh"); ClassDB::bind_method(D_METHOD("get_snap_axis"), &PropData::get_snap_axis); ClassDB::bind_method(D_METHOD("set_snap_axis", "value"), &PropData::set_snap_axis); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "snap_axis"), "set_snap_axis", "get_snap_axis"); ClassDB::bind_method(D_METHOD("get_prop", "index"), &PropData::get_prop); ClassDB::bind_method(D_METHOD("set_prop", "index", "spell"), &PropData::set_prop); ClassDB::bind_method(D_METHOD("add_prop", "prop"), &PropData::add_prop); ClassDB::bind_method(D_METHOD("remove_prop", "index"), &PropData::remove_prop); ClassDB::bind_method(D_METHOD("get_prop_count"), &PropData::get_prop_count); ClassDB::bind_method(D_METHOD("get_props"), &PropData::get_props); ClassDB::bind_method(D_METHOD("set_props", "props"), &PropData::set_props); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "props", PROPERTY_HINT_NONE, "17/17:PropDataEntry", PROPERTY_USAGE_DEFAULT, "PropDataEntry"), "set_props", "get_props"); ClassDB::bind_method(D_METHOD("add_textures_into", "texture_packer"), &PropData::add_textures_into); ClassDB::bind_method(D_METHOD("add_prop_lights_into", "chunk", "parent_transform", "allow_snap"), &PropData::add_prop_lights_into_bind); ClassDB::bind_method(D_METHOD("add_meshes_into", "mesher", "texture_packer", "parent_transform", "snap_spatial"), &PropData::add_meshes_into_bind); ClassDB::bind_method(D_METHOD("get_next_snapped_prop_transform", "spatial", "parent_transform", "snap_to_mesh", "snap_axis"), &PropData::get_next_snapped_prop_transform_bind); }