summaryrefslogtreecommitdiff
path: root/scene/resources/primitive_meshes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources/primitive_meshes.cpp')
-rw-r--r--scene/resources/primitive_meshes.cpp265
1 files changed, 161 insertions, 104 deletions
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index f5ab0085f1..f038a79b8f 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -219,7 +219,7 @@ void PrimitiveMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
GDVIRTUAL_BIND(_create_mesh_array);
@@ -439,12 +439,15 @@ void CapsuleMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
+
+ ADD_LINKED_PROPERTY("radius", "height");
+ ADD_LINKED_PROPERTY("height", "radius");
}
void CapsuleMesh::set_radius(const float p_radius) {
radius = p_radius;
if (radius > height * 0.5) {
- radius = height * 0.5;
+ height = radius * 2.0;
}
_request_update();
}
@@ -456,7 +459,7 @@ float CapsuleMesh::get_radius() const {
void CapsuleMesh::set_height(const float p_height) {
height = p_height;
if (radius > height * 0.5) {
- height = radius * 2;
+ radius = height * 0.5;
}
_request_update();
}
@@ -1056,7 +1059,7 @@ void PlaneMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset"), "set_center_offset", "get_center_offset");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset");
}
void PlaneMesh::set_size(const Size2 &p_size) {
@@ -1619,6 +1622,134 @@ bool SphereMesh::get_is_hemisphere() const {
SphereMesh::SphereMesh() {}
/**
+ TorusMesh
+*/
+
+void TorusMesh::_create_mesh_array(Array &p_arr) const {
+ // set our bounding box
+
+ Vector<Vector3> points;
+ Vector<Vector3> normals;
+ Vector<float> tangents;
+ Vector<Vector2> uvs;
+ Vector<int> indices;
+
+#define ADD_TANGENT(m_x, m_y, m_z, m_d) \
+ tangents.push_back(m_x); \
+ tangents.push_back(m_y); \
+ tangents.push_back(m_z); \
+ tangents.push_back(m_d);
+
+ ERR_FAIL_COND_MSG(inner_radius == outer_radius, "Inner radius and outer radius cannot be the same.");
+
+ float min_radius = inner_radius;
+ float max_radius = outer_radius;
+
+ if (min_radius > max_radius) {
+ SWAP(min_radius, max_radius);
+ }
+
+ float radius = (max_radius - min_radius) * 0.5;
+
+ for (int i = 0; i <= rings; i++) {
+ int prevrow = (i - 1) * (ring_segments + 1);
+ int thisrow = i * (ring_segments + 1);
+ float inci = float(i) / rings;
+ float angi = inci * Math_TAU;
+
+ Vector2 normali = Vector2(-Math::sin(angi), -Math::cos(angi));
+
+ for (int j = 0; j <= ring_segments; j++) {
+ float incj = float(j) / ring_segments;
+ float angj = incj * Math_TAU;
+
+ Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj));
+ Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0);
+
+ points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x));
+ normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x));
+ ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0);
+ uvs.push_back(Vector2(inci, incj));
+
+ if (i > 0 && j > 0) {
+ indices.push_back(thisrow + j - 1);
+ indices.push_back(prevrow + j);
+ indices.push_back(prevrow + j - 1);
+
+ indices.push_back(thisrow + j - 1);
+ indices.push_back(thisrow + j);
+ indices.push_back(prevrow + j);
+ }
+ }
+ }
+
+ p_arr[RS::ARRAY_VERTEX] = points;
+ p_arr[RS::ARRAY_NORMAL] = normals;
+ p_arr[RS::ARRAY_TANGENT] = tangents;
+ p_arr[RS::ARRAY_TEX_UV] = uvs;
+ p_arr[RS::ARRAY_INDEX] = indices;
+}
+
+void TorusMesh::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &TorusMesh::set_inner_radius);
+ ClassDB::bind_method(D_METHOD("get_inner_radius"), &TorusMesh::get_inner_radius);
+
+ ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &TorusMesh::set_outer_radius);
+ ClassDB::bind_method(D_METHOD("get_outer_radius"), &TorusMesh::get_outer_radius);
+
+ ClassDB::bind_method(D_METHOD("set_rings", "rings"), &TorusMesh::set_rings);
+ ClassDB::bind_method(D_METHOD("get_rings"), &TorusMesh::get_rings);
+
+ ClassDB::bind_method(D_METHOD("set_ring_segments", "rings"), &TorusMesh::set_ring_segments);
+ ClassDB::bind_method(D_METHOD("get_ring_segments"), &TorusMesh::get_ring_segments);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_inner_radius", "get_inner_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_outer_radius", "get_outer_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "3,128,1"), "set_rings", "get_rings");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_segments", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_segments", "get_ring_segments");
+}
+
+void TorusMesh::set_inner_radius(const float p_inner_radius) {
+ inner_radius = p_inner_radius;
+ _request_update();
+}
+
+float TorusMesh::get_inner_radius() const {
+ return inner_radius;
+}
+
+void TorusMesh::set_outer_radius(const float p_outer_radius) {
+ outer_radius = p_outer_radius;
+ _request_update();
+}
+
+float TorusMesh::get_outer_radius() const {
+ return outer_radius;
+}
+
+void TorusMesh::set_rings(const int p_rings) {
+ ERR_FAIL_COND(p_rings < 3);
+ rings = p_rings;
+ _request_update();
+}
+
+int TorusMesh::get_rings() const {
+ return rings;
+}
+
+void TorusMesh::set_ring_segments(const int p_ring_segments) {
+ ERR_FAIL_COND(p_ring_segments < 3);
+ ring_segments = p_ring_segments;
+ _request_update();
+}
+
+int TorusMesh::get_ring_segments() const {
+ return ring_segments;
+}
+
+TorusMesh::TorusMesh() {}
+
+/**
PointMesh
*/
@@ -2187,12 +2318,12 @@ RibbonTrailMesh::RibbonTrailMesh() {
/* TextMesh */
/*************************************************************************/
-void TextMesh::_generate_glyph_mesh_data(uint32_t p_hash, const Glyph &p_gl) const {
- if (cache.has(p_hash)) {
+void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_gl) const {
+ if (cache.has(p_key)) {
return;
}
- GlyphMeshData &gl_data = cache[p_hash];
+ GlyphMeshData &gl_data = cache[p_key];
Dictionary d = TS->font_get_glyph_contours(p_gl.font_rid, p_gl.font_size, p_gl.index);
Vector2 origin = Vector2(p_gl.x_off, p_gl.y_off) * pixel_size;
@@ -2373,7 +2504,10 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
TS->shaped_text_set_direction(text_rid, text_direction);
String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
- TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, language);
+ TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, font->get_opentype_features(), language);
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
+ }
Array stt;
if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) {
@@ -2391,7 +2525,10 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
} else if (dirty_font) {
int spans = TS->shaped_get_span_count(text_rid);
for (int i = 0; i < spans; i++) {
- TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features);
+ TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, font->get_opentype_features());
+ }
+ for (int i = 0; i < TextServer::SPACING_MAX; i++) {
+ TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
}
dirty_font = false;
@@ -2434,11 +2571,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
continue;
}
if (glyphs[i].font_rid != RID()) {
- uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id());
- hash = hash_djb2_one_32(glyphs[i].index, hash);
-
- _generate_glyph_mesh_data(hash, glyphs[i]);
- GlyphMeshData &gl_data = cache[hash];
+ GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index);
+ _generate_glyph_mesh_data(key, glyphs[i]);
+ GlyphMeshData &gl_data = cache[key];
p_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
i_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
@@ -2493,10 +2628,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const {
continue;
}
if (glyphs[i].font_rid != RID()) {
- uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id());
- hash = hash_djb2_one_32(glyphs[i].index, hash);
-
- const GlyphMeshData &gl_data = cache[hash];
+ GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index);
+ _generate_glyph_mesh_data(key, glyphs[i]);
+ const GlyphMeshData &gl_data = cache[key];
int64_t ts = gl_data.triangles.size();
const Vector2 *ts_ptr = gl_data.triangles.ptr();
@@ -2679,10 +2813,6 @@ void TextMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &TextMesh::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &TextMesh::get_text_direction);
- ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &TextMesh::set_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &TextMesh::get_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_opentype_features"), &TextMesh::clear_opentype_features);
-
ClassDB::bind_method(D_METHOD("set_language", "language"), &TextMesh::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &TextMesh::get_language);
@@ -2701,21 +2831,21 @@ void TextMesh::_bind_methods() {
ADD_GROUP("Text", "");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1"), "set_font_size", "get_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
ADD_GROUP("Mesh", "");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1"), "set_curve_step", "get_curve_step");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater"), "set_depth", "get_depth");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1,suffix:px"), "set_curve_step", "get_curve_step");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater,suffix:m"), "set_depth", "get_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:m"), "set_width", "get_width");
- ADD_GROUP("Locale", "");
+ ADD_GROUP("BiDi", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
}
void TextMesh::_notification(int p_what) {
@@ -2732,56 +2862,6 @@ void TextMesh::_notification(int p_what) {
}
}
-bool TextMesh::_set(const StringName &p_name, const Variant &p_value) {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- int value = p_value;
- if (value == -1) {
- if (opentype_features.has(tag)) {
- opentype_features.erase(tag);
- dirty_font = true;
- _request_update();
- }
- } else {
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
- opentype_features[tag] = value;
- dirty_font = true;
- _request_update();
- }
- }
- notify_property_list_changed();
- return true;
- }
-
- return false;
-}
-
-bool TextMesh::_get(const StringName &p_name, Variant &r_ret) const {
- String str = p_name;
- if (str.begins_with("opentype_features/")) {
- String name = str.get_slicec('/', 1);
- int32_t tag = TS->name_to_tag(name);
- if (opentype_features.has(tag)) {
- r_ret = opentype_features[tag];
- return true;
- } else {
- r_ret = -1;
- return true;
- }
- }
- return false;
-}
-
-void TextMesh::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
- String name = TS->tag_to_name(*ftr);
- p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
- }
- p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
-}
-
TextMesh::TextMesh() {
primitive_type = PRIMITIVE_TRIANGLES;
text_rid = TS->create_shaped_text();
@@ -2845,7 +2925,7 @@ Ref<Font> TextMesh::get_font() const {
}
Ref<Font> TextMesh::_get_font_or_default() const {
- if (font_override.is_valid() && font_override->get_data_count() > 0) {
+ if (font_override.is_valid()) {
return font_override;
}
@@ -2952,29 +3032,6 @@ TextServer::Direction TextMesh::get_text_direction() const {
return text_direction;
}
-void TextMesh::clear_opentype_features() {
- opentype_features.clear();
- dirty_font = true;
- _request_update();
-}
-
-void TextMesh::set_opentype_feature(const String &p_name, int p_value) {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
- opentype_features[tag] = p_value;
- dirty_font = true;
- _request_update();
- }
-}
-
-int TextMesh::get_opentype_feature(const String &p_name) const {
- int32_t tag = TS->name_to_tag(p_name);
- if (!opentype_features.has(tag)) {
- return -1;
- }
- return opentype_features[tag];
-}
-
void TextMesh::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;