diff options
Diffstat (limited to 'modules/csg/csg_shape.cpp')
-rw-r--r-- | modules/csg/csg_shape.cpp | 193 |
1 files changed, 154 insertions, 39 deletions
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 4e35014459..23725c4960 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -48,18 +48,76 @@ void CSGShape::set_use_collision(bool p_enable) { PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space()); PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); + set_collision_layer(collision_layer); + set_collision_mask(collision_mask); _make_dirty(); //force update } else { PhysicsServer::get_singleton()->free(root_collision_instance); root_collision_instance = RID(); root_collision_shape.unref(); } + _change_notify(); } bool CSGShape::is_using_collision() const { return use_collision; } +void CSGShape::set_collision_layer(uint32_t p_layer) { + collision_layer = p_layer; + if (root_collision_instance.is_valid()) { + PhysicsServer::get_singleton()->body_set_collision_layer(root_collision_instance, p_layer); + } +} + +uint32_t CSGShape::get_collision_layer() const { + + return collision_layer; +} + +void CSGShape::set_collision_mask(uint32_t p_mask) { + + collision_mask = p_mask; + if (root_collision_instance.is_valid()) { + PhysicsServer::get_singleton()->body_set_collision_mask(root_collision_instance, p_mask); + } +} + +uint32_t CSGShape::get_collision_mask() const { + + return collision_mask; +} + +void CSGShape::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool CSGShape::get_collision_mask_bit(int p_bit) const { + + return get_collision_mask() & (1 << p_bit); +} + +void CSGShape::set_collision_layer_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_layer(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_layer(mask); +} + +bool CSGShape::get_collision_layer_bit(int p_bit) const { + + return get_collision_layer() & (1 << p_bit); +} + bool CSGShape::is_root_shape() const { return !parent; @@ -197,17 +255,6 @@ void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexc fvTexcOut[1] = t.y; } -void CSGShape::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) { - ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); - - int i = (iFace * 3 + iVert) * 4; - - surface.tansw[i++] = fvTangent[0]; - surface.tansw[i++] = fvTangent[1]; - surface.tansw[i++] = fvTangent[2]; - surface.tansw[i++] = fSign; -} - void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, const tbool bIsOrientationPreserving, const int iFace, const int iVert) { @@ -216,7 +263,7 @@ void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const f int i = iFace * 3 + iVert; Vector3 normal = surface.normalsw[i]; Vector3 tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]); - Vector3 bitangent = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]); + Vector3 bitangent = Vector3(-fvBiTangent[0], -fvBiTangent[1], -fvBiTangent[2]); // for some reason these are reversed, something with the coordinate system in Godot float d = bitangent.dot(normal.cross(tangent)); i *= 4; @@ -389,10 +436,10 @@ void CSGShape::_update_shape() { } // unset write access - surfaces.write[i].verticesw = PoolVector<Vector3>::Write(); - surfaces.write[i].normalsw = PoolVector<Vector3>::Write(); - surfaces.write[i].uvsw = PoolVector<Vector2>::Write(); - surfaces.write[i].tansw = PoolVector<float>::Write(); + surfaces.write[i].verticesw.release(); + surfaces.write[i].normalsw.release(); + surfaces.write[i].uvsw.release(); + surfaces.write[i].tansw.release(); if (surfaces[i].last_added == 0) continue; @@ -470,6 +517,8 @@ void CSGShape::_notification(int p_what) { PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space()); PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); + set_collision_layer(collision_layer); + set_collision_mask(collision_mask); } _make_dirty(); @@ -482,13 +531,20 @@ void CSGShape::_notification(int p_what) { } } + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + + if (parent) { + parent->_make_dirty(); + } + } + if (p_what == NOTIFICATION_EXIT_TREE) { if (parent) parent->_make_dirty(); parent = NULL; - if (use_collision && is_root_shape()) { + if (use_collision && is_root_shape() && root_collision_instance.is_valid()) { PhysicsServer::get_singleton()->free(root_collision_instance); root_collision_instance = RID(); root_collision_shape.unref(); @@ -501,6 +557,7 @@ void CSGShape::set_operation(Operation p_operation) { operation = p_operation; _make_dirty(); + update_gizmo(); } CSGShape::Operation CSGShape::get_operation() const { @@ -517,12 +574,27 @@ bool CSGShape::is_calculating_tangents() const { } void CSGShape::_validate_property(PropertyInfo &property) const { - if (is_inside_tree() && property.name.begins_with("use_collision") && !is_root_shape()) { + bool is_collision_prefixed = property.name.begins_with("collision_"); + if ((is_collision_prefixed || property.name.begins_with("use_collision")) && is_inside_tree() && !is_root_shape()) { //hide collision if not root property.usage = PROPERTY_USAGE_NOEDITOR; + } else if (is_collision_prefixed && !bool(get("use_collision"))) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; } } +Array CSGShape::get_meshes() const { + + if (root_mesh.is_valid()) { + Array arr; + arr.resize(2); + arr[0] = Transform(); + arr[1] = root_mesh; + return arr; + } + + return Array(); +} void CSGShape::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_shape"), &CSGShape::_update_shape); @@ -531,34 +603,54 @@ void CSGShape::_bind_methods() { ClassDB::bind_method(D_METHOD("set_operation", "operation"), &CSGShape::set_operation); ClassDB::bind_method(D_METHOD("get_operation"), &CSGShape::get_operation); + ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap); + ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap); + ClassDB::bind_method(D_METHOD("set_use_collision", "operation"), &CSGShape::set_use_collision); ClassDB::bind_method(D_METHOD("is_using_collision"), &CSGShape::is_using_collision); - ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap); - ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap); + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &CSGShape::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &CSGShape::get_collision_layer); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &CSGShape::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &CSGShape::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CSGShape::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CSGShape::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &CSGShape::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CSGShape::get_collision_layer_bit); ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents); ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents); + ClassDB::bind_method(D_METHOD("get_meshes"), &CSGShape::get_meshes); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "calculate_tangents"), "set_calculate_tangents", "is_calculating_tangents"); + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + BIND_ENUM_CONSTANT(OPERATION_UNION); BIND_ENUM_CONSTANT(OPERATION_INTERSECTION); BIND_ENUM_CONSTANT(OPERATION_SUBTRACTION); } CSGShape::CSGShape() { + operation = OPERATION_UNION; + parent = NULL; brush = NULL; - set_notify_local_transform(true); dirty = false; - parent = NULL; - use_collision = false; - operation = OPERATION_UNION; snap = 0.001; + use_collision = false; + collision_layer = 1; + collision_mask = 1; calculate_tangents = true; + set_notify_local_transform(true); } CSGShape::~CSGShape() { @@ -633,6 +725,7 @@ CSGBrush *CSGMesh::_build_brush() { PoolVector<bool> smooth; PoolVector<Ref<Material> > materials; PoolVector<Vector2> uvs; + Ref<Material> material = get_material(); for (int i = 0; i < mesh->get_surface_count(); i++) { @@ -669,7 +762,12 @@ CSGBrush *CSGMesh::_build_brush() { uvr_used = true; } - Ref<Material> mat = mesh->surface_get_material(i); + Ref<Material> mat; + if (material.is_valid()) { + mat = material; + } else { + mat = mesh->surface_get_material(i); + } PoolVector<int> aindices = arrays[Mesh::ARRAY_INDEX]; if (aindices.size()) { @@ -715,8 +813,8 @@ CSGBrush *CSGMesh::_build_brush() { uvw[as + j + 1] = uv[1]; uvw[as + j + 2] = uv[2]; - sw[j / 3] = !flat; - mw[j / 3] = mat; + sw[(as + j) / 3] = !flat; + mw[(as + j) / 3] = mat; } } else { int as = vertices.size(); @@ -758,8 +856,8 @@ CSGBrush *CSGMesh::_build_brush() { uvw[as + j + 1] = uv[1]; uvw[as + j + 2] = uv[2]; - sw[j / 3] = !flat; - mw[j / 3] = mat; + sw[(as + j) / 3] = !flat; + mw[(as + j) / 3] = mat; } } } @@ -775,6 +873,18 @@ void CSGMesh::_mesh_changed() { update_gizmo(); } +void CSGMesh::set_material(const Ref<Material> &p_material) { + if (material == p_material) + return; + material = p_material; + _make_dirty(); +} + +Ref<Material> CSGMesh::get_material() const { + + return material; +} + void CSGMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CSGMesh::set_mesh); @@ -782,7 +892,11 @@ void CSGMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("_mesh_changed"), &CSGMesh::_mesh_changed); + ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGMesh::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &CSGMesh::get_material); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material"); } void CSGMesh::set_mesh(const Ref<Mesh> &p_mesh) { @@ -1062,9 +1176,9 @@ CSGBrush *CSGBox::_build_brush() { for (int k = 0; k < 3; k++) { if (i < 3) - face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1); + face_points[j][(i + k) % 3] = v[k]; else - face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1); + face_points[3 - j][(i + k) % 3] = -v[k]; } } @@ -1703,11 +1817,9 @@ CSGBrush *CSGPolygon::_build_brush() { path_cache = path; - if (path_cache) { - path_cache->connect("tree_exited", this, "_path_exited"); - path_cache->connect("curve_changed", this, "_path_changed"); - path_cache = NULL; - } + path_cache->connect("tree_exited", this, "_path_exited"); + path_cache->connect("curve_changed", this, "_path_changed"); + path_cache = NULL; } curve = path->get_curve(); if (curve.is_null()) @@ -1969,6 +2081,9 @@ CSGBrush *CSGPolygon::_build_brush() { for (int i = 0; i <= splits; i++) { float ofs = i * path_interval; + if (ofs > bl) { + ofs = bl; + } if (i == splits && path_joined) { ofs = 0.0; } |