summaryrefslogtreecommitdiff
path: root/scene/resources
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources')
-rw-r--r--scene/resources/bit_mask.cpp348
-rw-r--r--scene/resources/bit_mask.h8
-rw-r--r--scene/resources/dynamic_font.cpp123
-rw-r--r--scene/resources/dynamic_font.h13
-rw-r--r--scene/resources/material.cpp15
-rw-r--r--scene/resources/material.h2
-rw-r--r--scene/resources/primitive_meshes.h2
-rw-r--r--scene/resources/ray_shape.cpp23
-rw-r--r--scene/resources/ray_shape.h4
-rw-r--r--scene/resources/scene_format_text.cpp12
-rw-r--r--scene/resources/segment_shape_2d.cpp20
-rw-r--r--scene/resources/segment_shape_2d.h5
-rw-r--r--scene/resources/shape_2d.h2
-rw-r--r--scene/resources/style_box.cpp12
-rw-r--r--scene/resources/style_box.h8
-rw-r--r--scene/resources/tile_set.cpp31
-rw-r--r--scene/resources/tile_set.h17
17 files changed, 566 insertions, 79 deletions
diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp
index ea313b5a20..29ffefd9d6 100644
--- a/scene/resources/bit_mask.cpp
+++ b/scene/resources/bit_mask.cpp
@@ -42,7 +42,7 @@ void BitMap::create(const Size2 &p_size) {
zeromem(bitmask.ptrw(), bitmask.size());
}
-void BitMap::create_from_image_alpha(const Ref<Image> &p_image) {
+void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshold) {
ERR_FAIL_COND(p_image.is_null() || p_image->empty());
Ref<Image> img = p_image->duplicate();
@@ -58,8 +58,9 @@ void BitMap::create_from_image_alpha(const Ref<Image> &p_image) {
int bbyte = i / 8;
int bbit = i % 8;
- if (r[i * 2])
+ if (r[i * 2 + 1] / 255.0 > p_threshold) {
w[bbyte] |= (1 << bbit);
+ }
}
}
@@ -168,10 +169,351 @@ Dictionary BitMap::_get_data() const {
return d;
}
+Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) const {
+
+ int stepx = 0;
+ int stepy = 0;
+ int prevx = 0;
+ int prevy = 0;
+ int startx = start.x;
+ int starty = start.y;
+ int curx = startx;
+ int cury = starty;
+ unsigned int count = 0;
+ Set<Point2i> case9s;
+ Set<Point2i> case6s;
+ int i;
+ Vector<Vector2> _points;
+ do {
+ int sv = 0;
+ { //square value
+
+ /*
+ checking the 2x2 pixel grid, assigning these values to each pixel, if not transparent
+ +---+---+
+ | 1 | 2 |
+ +---+---+
+ | 4 | 8 | <- current pixel (curx,cury)
+ +---+---+
+ */
+ //NOTE: due to the way we pick points from texture, rect needs to be smaller, otherwise it goes outside 1 pixel
+ Rect2i fixed_rect = Rect2i(rect.position, rect.size - Size2i(2, 2));
+ Point2i tl = Point2i(curx - 1, cury - 1);
+ sv += (fixed_rect.has_point(tl) && get_bit(tl)) ? 1 : 0;
+ Point2i tr = Point2i(curx, cury - 1);
+ sv += (fixed_rect.has_point(tr) && get_bit(tr)) ? 2 : 0;
+ Point2i bl = Point2i(curx - 1, cury);
+ sv += (fixed_rect.has_point(bl) && get_bit(bl)) ? 4 : 0;
+ Point2i br = Point2i(curx, cury);
+ sv += (fixed_rect.has_point(br) && get_bit(br)) ? 8 : 0;
+ ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector2>());
+ }
+
+ switch (sv) {
+
+ case 1:
+ case 5:
+ case 13:
+ /* going UP with these cases:
+ 1 5 13
+ +---+---+ +---+---+ +---+---+
+ | 1 | | | 1 | | | 1 | |
+ +---+---+ +---+---+ +---+---+
+ | | | | 4 | | | 4 | 8 |
+ +---+---+ +---+---+ +---+---+
+ */
+ stepx = 0;
+ stepy = -1;
+ break;
+
+ case 8:
+ case 10:
+ case 11:
+ /* going DOWN with these cases:
+ 8 10 11
+ +---+---+ +---+---+ +---+---+
+ | | | | | 2 | | 1 | 2 |
+ +---+---+ +---+---+ +---+---+
+ | | 8 | | | 8 | | | 8 |
+ +---+---+ +---+---+ +---+---+
+ */
+ stepx = 0;
+ stepy = 1;
+ break;
+
+ case 4:
+ case 12:
+ case 14:
+ /* going LEFT with these cases:
+ 4 12 14
+ +---+---+ +---+---+ +---+---+
+ | | | | | | | | 2 |
+ +---+---+ +---+---+ +---+---+
+ | 4 | | | 4 | 8 | | 4 | 8 |
+ +---+---+ +---+---+ +---+---+
+ */
+ stepx = -1;
+ stepy = 0;
+ break;
+
+ case 2:
+ case 3:
+ case 7:
+ /* going RIGHT with these cases:
+ 2 3 7
+ +---+---+ +---+---+ +---+---+
+ | | 2 | | 1 | 2 | | 1 | 2 |
+ +---+---+ +---+---+ +---+---+
+ | | | | | | | 4 | |
+ +---+---+ +---+---+ +---+---+
+ */
+ stepx = 1;
+ stepy = 0;
+ break;
+ case 9:
+ /*
+ +---+---+
+ | 1 | |
+ +---+---+
+ | | 8 |
+ +---+---+
+ this should normally go UP, but if we already been here, we go down
+ */
+ if (case9s.has(Point2i(curx, cury))) {
+ //found, so we go down, and delete from case9s;
+ stepx = 0;
+ stepy = 1;
+ case9s.erase(Point2i(curx, cury));
+ } else {
+ //not found, we go up, and add to case9s;
+ stepx = 0;
+ stepy = -1;
+ case9s.insert(Point2i(curx, cury));
+ }
+ break;
+ case 6:
+ /*
+ 6
+ +---+---+
+ | | 2 |
+ +---+---+
+ | 4 | |
+ +---+---+
+ this normally go RIGHT, but if its coming from UP, it should go LEFT
+ */
+ if (case6s.has(Point2i(curx, cury))) {
+ //found, so we go down, and delete from case6s;
+ stepx = -1;
+ stepy = 0;
+ case6s.erase(Point2i(curx, cury));
+ } else {
+ //not found, we go up, and add to case6s;
+ stepx = 1;
+ stepy = 0;
+ case6s.insert(Point2i(curx, cury));
+ }
+ break;
+ default:
+ ERR_PRINT("this shouldn't happen.");
+ }
+ //little optimization
+ // if previous direction is same as current direction,
+ // then we should modify the last vec to current
+ curx += stepx;
+ cury += stepy;
+ if (stepx == prevx && stepy == prevy) {
+ _points[_points.size() - 1].x = (float)(curx - rect.position.x);
+ _points[_points.size() - 1].y = (float)(cury + rect.position.y);
+ } else {
+ _points.push_back(Vector2((float)(curx - rect.position.x), (float)(cury + rect.position.y)));
+ }
+
+ count++;
+ prevx = stepx;
+ prevy = stepy;
+
+ ERR_FAIL_COND_V(count > width * height, _points);
+ } while (curx != startx || cury != starty);
+ return _points;
+}
+
+static float perpendicular_distance(const Vector2 &i, const Vector2 &start, const Vector2 &end) {
+ float res;
+ float slope;
+ float intercept;
+
+ if (start.x == end.x) {
+ res = Math::absf(i.x - end.x);
+ } else if (start.y == end.y) {
+ res = Math::absf(i.y - end.y);
+ } else {
+ slope = (end.y - start.y) / (end.x - start.x);
+ intercept = start.y - (slope * start.x);
+ res = Math::absf(slope * i.x - i.y + intercept) / Math::sqrt(Math::pow(slope, 2.0f) + 1.0);
+ }
+ return res;
+}
+
+static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) {
+ if (v.size() < 3)
+ return v;
+
+ int index = -1;
+ float dist = 0;
+ //not looping first and last point
+ for (size_t i = 1, size = v.size(); i < size - 1; ++i) {
+ float cdist = perpendicular_distance(v[i], v[0], v[v.size() - 1]);
+ if (cdist > dist) {
+ dist = cdist;
+ index = static_cast<int>(i);
+ }
+ }
+ if (dist > optimization) {
+
+ Vector<Vector2> left, right;
+ left.resize(index);
+ for (int i = 0; i < index; i++) {
+ left[i] = v[i];
+ }
+ right.resize(v.size() - index);
+ for (int i = 0; i < right.size(); i++) {
+ right[i] = v[index + i];
+ }
+ Vector<Vector2> r1 = rdp(left, optimization);
+ Vector<Vector2> r2 = rdp(right, optimization);
+
+ int middle = r1.size();
+ r1.resize(r1.size() + r2.size());
+ for (int i = 0; i < r2.size(); i++) {
+ r1[middle + i] = r2[i];
+ }
+ return r1;
+ } else {
+ Vector<Vector2> ret;
+ ret.push_back(v[0]);
+ ret.push_back(v[v.size() - 1]);
+ return ret;
+ }
+}
+
+static Vector<Vector2> reduce(const Vector<Vector2> &points, const Rect2i &rect, float epsilon) {
+ int size = points.size();
+ // if there are less than 3 points, then we have nothing
+ ERR_FAIL_COND_V(size < 3, Vector<Vector2>());
+ // if there are less than 9 points (but more than 3), then we don't need to reduce it
+ if (size < 9) {
+ return points;
+ }
+
+ float maxEp = MIN(rect.size.width, rect.size.height);
+ float ep = CLAMP(epsilon, 0.0, maxEp / 2);
+ Vector<Vector2> result = rdp(points, ep);
+
+ Vector2 last = result[result.size() - 1];
+
+ if (last.y > result[0].y && last.distance_to(result[0]) < ep * 0.5f) {
+ result[0].y = last.y;
+ result.resize(result.size() - 1);
+ }
+ return result;
+}
+
+static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_pos, const Rect2i &rect) {
+
+ for (int i = p_pos.x - 1; i <= p_pos.x + 1; i++) {
+ for (int j = p_pos.y - 1; j <= p_pos.y + 1; j++) {
+
+ if (i < rect.position.x || i >= rect.position.x + rect.size.x)
+ continue;
+ if (j < rect.position.y || j >= rect.position.y + rect.size.y)
+ continue;
+
+ if (p_map->get_bit(Vector2(i, j)))
+ continue;
+
+ else if (p_src->get_bit(Vector2(i, j))) {
+ p_map->set_bit(Vector2(i, j), true);
+ fill_bits(p_src, p_map, Point2i(i, j), rect);
+ }
+ }
+ }
+}
+Vector<Vector<Vector2> > BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const {
+
+ Rect2i r = Rect2i(0, 0, width, height).clip(p_rect);
+
+ print_line("Rect: " + r);
+ Point2i from;
+ Ref<BitMap> fill;
+ fill.instance();
+ fill->create(get_size());
+
+ Vector<Vector<Vector2> > polygons;
+ for (int i = r.position.y; i < r.position.y + r.size.height; i++) {
+ for (int j = r.position.x; j < r.position.x + r.size.width; j++) {
+ if (!fill->get_bit(Point2(j, i)) && get_bit(Point2(j, i))) {
+
+ Vector<Vector2> polygon = _march_square(r, Point2i(j, i));
+ print_line("pre reduce: " + itos(polygon.size()));
+ polygon = reduce(polygon, r, p_epsilon);
+ print_line("post reduce: " + itos(polygon.size()));
+ polygons.push_back(polygon);
+ fill_bits(this, fill, Point2i(j, i), r);
+ }
+ }
+ }
+
+ return polygons;
+}
+
+void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) {
+
+ Rect2i r = Rect2i(0, 0, width, height).clip(p_rect);
+
+ Ref<BitMap> copy;
+ copy.instance();
+ copy->create(get_size());
+ copy->bitmask = bitmask;
+
+ for (int i = r.position.y; i < r.position.y + r.size.height; i++) {
+ for (int j = r.position.x; j < r.position.x + r.size.width; j++) {
+ if (copy->get_bit(Point2(j, i)))
+ continue;
+
+ bool found = false;
+
+ for (int y = i - p_pixels; y <= i + p_pixels; y++) {
+ for (int x = j - p_pixels; x <= j + p_pixels; x++) {
+
+ if (x < p_rect.position.x || x >= p_rect.position.x + p_rect.size.x)
+ continue;
+ if (y < p_rect.position.y || y >= p_rect.position.y + p_rect.size.y)
+ continue;
+
+ float d = Point2(j, i).distance_to(Point2(x, y)) - CMP_EPSILON;
+ if (d > p_pixels)
+ continue;
+
+ if (copy->get_bit(Point2(x, y))) {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+
+ if (found) {
+ set_bit(Point2(j, i), true);
+ }
+ }
+ }
+}
+
void BitMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create);
- ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image"), &BitMap::create_from_image_alpha);
+ ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image", "threshold"), &BitMap::create_from_image_alpha, DEFVAL(0.1));
ClassDB::bind_method(D_METHOD("set_bit", "position", "bit"), &BitMap::set_bit);
ClassDB::bind_method(D_METHOD("get_bit", "position"), &BitMap::get_bit);
diff --git a/scene/resources/bit_mask.h b/scene/resources/bit_mask.h
index cf126ef96b..dcd5edb4fb 100644
--- a/scene/resources/bit_mask.h
+++ b/scene/resources/bit_mask.h
@@ -44,6 +44,8 @@ class BitMap : public Resource {
int width;
int height;
+ Vector<Vector2> _march_square(const Rect2i &rect, const Point2i &start) const;
+
protected:
void _set_data(const Dictionary &p_d);
Dictionary _get_data() const;
@@ -52,7 +54,7 @@ protected:
public:
void create(const Size2 &p_size);
- void create_from_image_alpha(const Ref<Image> &p_image);
+ void create_from_image_alpha(const Ref<Image> &p_image, float p_threshold = 0.1);
void set_bit(const Point2 &p_pos, bool p_value);
bool get_bit(const Point2 &p_pos) const;
@@ -61,6 +63,10 @@ public:
Size2 get_size() const;
+ void grow_mask(int p_pixels, const Rect2 &p_rect);
+
+ Vector<Vector<Vector2> > clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon = 2.0) const;
+
BitMap();
};
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index e9d5ca969e..26e29b3ccb 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -80,6 +80,14 @@ void DynamicFontData::set_force_autohinter(bool p_force) {
void DynamicFontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_font_path", "path"), &DynamicFontData::set_font_path);
ClassDB::bind_method(D_METHOD("get_font_path"), &DynamicFontData::get_font_path);
+ ClassDB::bind_method(D_METHOD("set_hinting", "mode"), &DynamicFontData::set_hinting);
+ ClassDB::bind_method(D_METHOD("get_hinting"), &DynamicFontData::get_hinting);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting");
+
+ BIND_ENUM_CONSTANT(HINTING_NONE);
+ BIND_ENUM_CONSTANT(HINTING_LIGHT);
+ BIND_ENUM_CONSTANT(HINTING_NORMAL);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_path", PROPERTY_HINT_FILE, "*.ttf,*.otf"), "set_font_path", "get_font_path");
}
@@ -87,6 +95,7 @@ void DynamicFontData::_bind_methods() {
DynamicFontData::DynamicFontData() {
force_autohinter = false;
+ hinting = DynamicFontData::HINTING_NORMAL;
font_mem = NULL;
font_mem_size = 0;
}
@@ -186,10 +195,25 @@ Error DynamicFontAtSize::_load() {
ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER );
}*/
- error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling);
+ if (FT_HAS_COLOR(face)) {
+ int best_match = 0;
+ int diff = ABS(id.size - face->available_sizes[0].width);
+ scale_color_font = float(id.size) / face->available_sizes[0].width;
+ for (int i = 1; i < face->num_fixed_sizes; i++) {
+ int ndiff = ABS(id.size - face->available_sizes[i].width);
+ if (ndiff < diff) {
+ best_match = i;
+ diff = ndiff;
+ scale_color_font = float(id.size) / face->available_sizes[i].width;
+ }
+ }
+ error = FT_Select_Size(face, best_match);
+ } else {
+ error = FT_Set_Pixel_Sizes(face, 0, id.size * oversampling);
+ }
- ascent = (face->size->metrics.ascender >> 6) / oversampling;
- descent = (-face->size->metrics.descender >> 6) / oversampling;
+ ascent = (face->size->metrics.ascender >> 6) / oversampling * scale_color_font;
+ descent = (-face->size->metrics.descender >> 6) / oversampling * scale_color_font;
linegap = 0;
texture_flags = 0;
if (id.mipmaps)
@@ -197,8 +221,6 @@ Error DynamicFontAtSize::_load() {
if (id.filter)
texture_flags |= Texture::FLAG_FILTER;
- //print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER));
-
valid = true;
return OK;
}
@@ -286,7 +308,6 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const V
ret.x += (delta.x >> 6) / oversampling;
}
}
-
return ret;
}
@@ -328,14 +349,18 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
if (!ch->found)
continue;
-
Point2 cpos = p_pos;
cpos.x += ch->h_align;
- cpos.y -= get_ascent();
+ cpos.y -= fb->get_ascent();
cpos.y += ch->v_align;
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= fb->textures.size(), 0);
- if (ch->texture_idx != -1)
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect_uv, p_modulate, false, RID(), false);
+ if (ch->texture_idx != -1) {
+ Color modulate = p_modulate;
+ if (FT_HAS_COLOR(fb->face)) {
+ modulate.r = modulate.g = modulate.b = 1;
+ }
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size * Vector2(fb->scale_color_font, fb->scale_color_font)), fb->textures[ch->texture_idx].texture->get_rid(), ch->rect_uv, modulate, false, RID(), false);
+ }
advance = ch->advance;
used_fallback = true;
break;
@@ -356,8 +381,13 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT
cpos.y -= get_ascent();
cpos.y += c->v_align;
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), 0);
- if (c->texture_idx != -1)
- VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx].texture->get_rid(), c->rect_uv, p_modulate, false, RID(), false);
+ if (c->texture_idx != -1) {
+ Color modulate = p_modulate;
+ if (FT_HAS_COLOR(face)) {
+ modulate.r = modulate.g = modulate.b = 1;
+ }
+ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size * Vector2(scale_color_font, scale_color_font)), textures[c->texture_idx].texture->get_rid(), c->rect_uv, modulate, false, RID(), false);
+ }
advance = c->advance;
//textures[c->texture_idx].texture->draw(p_canvas_item,Vector2());
}
@@ -431,15 +461,28 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
char_map[p_char] = ch;
return;
}
- int error = FT_Load_Char(face, p_char, FT_LOAD_RENDER | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0));
+
+ int ft_hinting;
+
+ switch (font->hinting) {
+ case DynamicFontData::HINTING_NONE:
+ ft_hinting = FT_LOAD_NO_HINTING;
+ break;
+ case DynamicFontData::HINTING_LIGHT:
+ ft_hinting = FT_LOAD_TARGET_LIGHT;
+ break;
+ default:
+ ft_hinting = FT_LOAD_TARGET_NORMAL;
+ break;
+ }
+
+ int error = FT_Load_Char(face, p_char, FT_HAS_COLOR(face) ? FT_LOAD_COLOR : FT_LOAD_DEFAULT | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0) | ft_hinting);
if (!error) {
- error = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
+ error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
}
if (error) {
int advance = 0;
- //stbtt_GetCodepointHMetrics(&font->info, p_char, &advance, 0);
- //print_line("char has no bitmap: "+itos(p_char)+" but advance is "+itos(advance*scale));
Character ch;
ch.texture_idx = -1;
ch.advance = advance;
@@ -454,7 +497,6 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
int w = slot->bitmap.width;
int h = slot->bitmap.rows;
- //int p = slot->bitmap.pitch;
int yofs = slot->bitmap_top;
int xofs = slot->bitmap_left;
int advance = slot->advance.x >> 6;
@@ -470,6 +512,8 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
//find a texture to fit this...
+ int color_size = slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
+ Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
int tex_index = -1;
int tex_x = 0;
int tex_y = 0;
@@ -478,6 +522,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
CharTexture &ct = textures[i];
+ if (ct.texture->get_format() != require_format)
+ continue;
+
if (mw > ct.texture_size || mh > ct.texture_size) //too big for this texture
continue;
@@ -508,8 +555,6 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
break;
}
- //print_line("CHAR: "+String::chr(p_char)+" TEX INDEX: "+itos(tex_index)+" X: "+itos(tex_x)+" Y: "+itos(tex_y));
-
if (tex_index == -1) {
//could not find texture to fit, create one
tex_x = 0;
@@ -527,13 +572,13 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
CharTexture tex;
tex.texture_size = texsize;
- tex.imgdata.resize(texsize * texsize * 2); //grayscale alpha
+ tex.imgdata.resize(texsize * texsize * color_size);
{
//zero texture
PoolVector<uint8_t>::Write w = tex.imgdata.write();
- ERR_FAIL_COND(texsize * texsize * 2 > tex.imgdata.size());
- for (int i = 0; i < texsize * texsize * 2; i++) {
+ ERR_FAIL_COND(texsize * texsize * color_size > tex.imgdata.size());
+ for (int i = 0; i < texsize * texsize * color_size; i++) {
w[i] = 0;
}
}
@@ -555,7 +600,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- int ofs = ((i + tex_y + rect_margin) * tex.texture_size + j + tex_x + rect_margin) * 2;
+ int ofs = ((i + tex_y + rect_margin) * tex.texture_size + j + tex_x + rect_margin) * color_size;
ERR_FAIL_COND(ofs >= tex.imgdata.size());
switch (slot->bitmap.pixel_mode) {
case FT_PIXEL_MODE_MONO: {
@@ -568,7 +613,14 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
wr[ofs + 0] = 255; //grayscale as 1
wr[ofs + 1] = slot->bitmap.buffer[i * slot->bitmap.pitch + j];
break;
- // TODO: FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_BGRA
+ case FT_PIXEL_MODE_BGRA: {
+ int ofs_color = i * slot->bitmap.pitch + (j << 2);
+ wr[ofs + 2] = slot->bitmap.buffer[ofs_color + 0];
+ wr[ofs + 1] = slot->bitmap.buffer[ofs_color + 1];
+ wr[ofs + 0] = slot->bitmap.buffer[ofs_color + 2];
+ wr[ofs + 3] = slot->bitmap.buffer[ofs_color + 3];
+ } break;
+ // TODO: FT_PIXEL_MODE_LCD
default:
ERR_EXPLAIN("Font uses unsupported pixel format: " + itos(slot->bitmap.pixel_mode));
ERR_FAIL();
@@ -581,7 +633,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
//blit to image and texture
{
- Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata));
+ Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, require_format, tex.imgdata));
if (tex.texture.is_null()) {
tex.texture.instance();
@@ -599,9 +651,9 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
}
Character chr;
- chr.h_align = xofs / oversampling;
- chr.v_align = ascent - (yofs / oversampling); // + ascent - descent;
- chr.advance = advance / oversampling;
+ chr.h_align = xofs * scale_color_font / oversampling;
+ chr.v_align = ascent - (yofs * scale_color_font / oversampling); // + ascent - descent;
+ chr.advance = advance * scale_color_font / oversampling;
chr.texture_idx = tex_index;
chr.found = true;
@@ -610,8 +662,6 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
chr.rect.position /= oversampling;
chr.rect.size /= oversampling;
- //print_line("CHAR: "+String::chr(p_char)+" TEX INDEX: "+itos(tex_index)+" RECT: "+chr.rect+" X OFS: "+itos(xofs)+" Y OFS: "+itos(yofs));
-
char_map[p_char] = chr;
}
@@ -640,6 +690,7 @@ DynamicFontAtSize::DynamicFontAtSize() {
linegap = 1;
texture_flags = 0;
oversampling = font_oversampling;
+ scale_color_font = 1;
}
DynamicFontAtSize::~DynamicFontAtSize() {
@@ -722,6 +773,18 @@ void DynamicFont::set_use_filter(bool p_enable) {
_reload_cache();
}
+DynamicFontData::Hinting DynamicFontData::get_hinting() const {
+
+ return hinting;
+}
+
+void DynamicFontData::set_hinting(Hinting p_hinting) {
+
+ if (hinting == p_hinting)
+ return;
+ hinting = p_hinting;
+}
+
int DynamicFont::get_spacing(int p_type) const {
if (p_type == SPACING_TOP) {
diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h
index 92bb77bed3..db8bd87587 100644
--- a/scene/resources/dynamic_font.h
+++ b/scene/resources/dynamic_font.h
@@ -64,10 +64,20 @@ public:
}
};
+ enum Hinting {
+ HINTING_NONE,
+ HINTING_LIGHT,
+ HINTING_NORMAL
+ };
+
+ Hinting get_hinting() const;
+ void set_hinting(Hinting p_hinting);
+
private:
const uint8_t *font_mem;
int font_mem_size;
bool force_autohinter;
+ Hinting hinting;
String font_path;
Map<CacheID, DynamicFontAtSize *> size_cache;
@@ -91,6 +101,8 @@ public:
~DynamicFontData();
};
+VARIANT_ENUM_CAST(DynamicFontData::Hinting);
+
class DynamicFontAtSize : public Reference {
GDCLASS(DynamicFontAtSize, Reference)
@@ -106,6 +118,7 @@ class DynamicFontAtSize : public Reference {
float linegap;
float rect_margin;
float oversampling;
+ float scale_color_font;
uint32_t texture_flags;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 8a1978cf85..a83ef198fb 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -737,15 +737,18 @@ void SpatialMaterial::_update_shader() {
}
}
- if (features[FEATURE_REFRACTION] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //refraction not supported with triplanar
+ if (features[FEATURE_REFRACTION]) {
if (features[FEATURE_NORMAL_MAPPING]) {
code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * NORMALMAP.x + BINORMAL * NORMALMAP.y + NORMAL * NORMALMAP.z,NORMALMAP_DEPTH) );\n";
} else {
code += "\tvec3 ref_normal = NORMAL;\n";
}
-
- code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n";
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(triplanar_texture(texture_refraction,uv1_power_normal,uv1_triplanar_pos),refraction_texture_channel) * refraction;\n";
+ } else {
+ code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n";
+ }
code += "\tfloat ref_amount = 1.0 - albedo.a * albedo_tex.a;\n";
code += "\tEMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n";
code += "\tALBEDO *= 1.0 - ref_amount;\n";
@@ -1479,9 +1482,9 @@ bool SpatialMaterial::is_grow_enabled() const {
return grow_enabled;
}
-void SpatialMaterial::set_alpha_scissor_threshold(float p_treshold) {
- alpha_scissor_threshold = p_treshold;
- VS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_treshold);
+void SpatialMaterial::set_alpha_scissor_threshold(float p_threshold) {
+ alpha_scissor_threshold = p_threshold;
+ VS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold);
}
float SpatialMaterial::get_alpha_scissor_threshold() const {
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 10bbcfd642..2c297cda41 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -566,7 +566,7 @@ public:
void set_grow(float p_grow);
float get_grow() const;
- void set_alpha_scissor_threshold(float p_treshold);
+ void set_alpha_scissor_threshold(float p_threshold);
float get_alpha_scissor_threshold() const;
void set_on_top_of_alpha();
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 1eaa007bd7..94a7a055a3 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -189,7 +189,7 @@ public:
};
/**
- Similar to quadmesh but with tesselation support
+ Similar to quadmesh but with tessellation support
*/
class PlaneMesh : public PrimitiveMesh {
diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp
index 78a19050f1..a9dec3e87c 100644
--- a/scene/resources/ray_shape.cpp
+++ b/scene/resources/ray_shape.cpp
@@ -43,7 +43,10 @@ Vector<Vector3> RayShape::_gen_debug_mesh_lines() {
void RayShape::_update_shape() {
- PhysicsServer::get_singleton()->shape_set_data(get_shape(), length);
+ Dictionary d;
+ d["length"] = length;
+ d["slips_on_slope"] = slips_on_slope;
+ PhysicsServer::get_singleton()->shape_set_data(get_shape(), d);
emit_changed();
}
@@ -52,6 +55,7 @@ void RayShape::set_length(float p_length) {
length = p_length;
_update_shape();
notify_change_to_owners();
+ _change_notify("length");
}
float RayShape::get_length() const {
@@ -59,16 +63,33 @@ float RayShape::get_length() const {
return length;
}
+void RayShape::set_slips_on_slope(bool p_active) {
+
+ slips_on_slope = p_active;
+ _update_shape();
+ notify_change_to_owners();
+ _change_notify("slips_on_slope");
+}
+
+bool RayShape::get_slips_on_slope() const {
+ return slips_on_slope;
+}
+
void RayShape::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape::set_length);
ClassDB::bind_method(D_METHOD("get_length"), &RayShape::get_length);
+ ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape::set_slips_on_slope);
+ ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape::get_slips_on_slope);
+
ADD_PROPERTY(PropertyInfo(Variant::REAL, "length", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope");
}
RayShape::RayShape() :
Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_RAY)) {
set_length(1.0);
+ set_slips_on_slope(false);
}
diff --git a/scene/resources/ray_shape.h b/scene/resources/ray_shape.h
index 4bd96116fe..f11b2e7c3c 100644
--- a/scene/resources/ray_shape.h
+++ b/scene/resources/ray_shape.h
@@ -36,6 +36,7 @@ class RayShape : public Shape {
GDCLASS(RayShape, Shape);
float length;
+ bool slips_on_slope;
protected:
static void _bind_methods();
@@ -46,6 +47,9 @@ public:
void set_length(float p_length);
float get_length() const;
+ void set_slips_on_slope(bool p_active);
+ bool get_slips_on_slope() const;
+
RayShape();
};
#endif // RAY_SHAPE_H
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index 91c801c016..030b822f3b 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -1445,8 +1445,15 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
static String _valprop(const String &p_name) {
- if (p_name.find("\"") != -1 || p_name.find("=") != -1 || p_name.find(" ") != -1)
- return "\"" + p_name.c_escape_multiline() + "\"";
+ // Escape and quote strings with extended ASCII or further Unicode characters
+ // as well as '"', '=' or ' ' (32)
+ const CharType *cstr = p_name.c_str();
+ for (int i = 0; cstr[i]; i++) {
+ if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] < 33 || cstr[i] > 126) {
+ return "\"" + p_name.c_escape_multiline() + "\"";
+ }
+ }
+ // Keep as is
return p_name;
}
@@ -1506,7 +1513,6 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
title += "load_steps=" + itos(load_steps) + " ";
}
title += "format=" + itos(FORMAT_VERSION) + "";
- //title+="engine_version=\""+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"\"";
f->store_string(title);
f->store_line("]\n"); //one empty line
diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp
index 81110015b5..58027c127d 100644
--- a/scene/resources/segment_shape_2d.cpp
+++ b/scene/resources/segment_shape_2d.cpp
@@ -106,7 +106,10 @@ SegmentShape2D::SegmentShape2D() :
void RayShape2D::_update_shape() {
- Physics2DServer::get_singleton()->shape_set_data(get_rid(), length);
+ Dictionary d;
+ d["length"] = length;
+ d["slips_on_slope"] = slips_on_slope;
+ Physics2DServer::get_singleton()->shape_set_data(get_rid(), d);
emit_changed();
}
@@ -140,7 +143,11 @@ void RayShape2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape2D::set_length);
ClassDB::bind_method(D_METHOD("get_length"), &RayShape2D::get_length);
+ ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape2D::set_slips_on_slope);
+ ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape2D::get_slips_on_slope);
+
ADD_PROPERTY(PropertyInfo(Variant::REAL, "length"), "set_length", "get_length");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope");
}
void RayShape2D::set_length(real_t p_length) {
@@ -153,9 +160,20 @@ real_t RayShape2D::get_length() const {
return length;
}
+void RayShape2D::set_slips_on_slope(bool p_active) {
+
+ slips_on_slope = p_active;
+ _update_shape();
+}
+
+bool RayShape2D::get_slips_on_slope() const {
+ return slips_on_slope;
+}
+
RayShape2D::RayShape2D() :
Shape2D(Physics2DServer::get_singleton()->ray_shape_create()) {
length = 20;
+ slips_on_slope = false;
_update_shape();
}
diff --git a/scene/resources/segment_shape_2d.h b/scene/resources/segment_shape_2d.h
index 4ed30c0443..700982ac0a 100644
--- a/scene/resources/segment_shape_2d.h
+++ b/scene/resources/segment_shape_2d.h
@@ -63,6 +63,7 @@ class RayShape2D : public Shape2D {
GDCLASS(RayShape2D, Shape2D);
real_t length;
+ bool slips_on_slope;
void _update_shape();
@@ -72,6 +73,10 @@ protected:
public:
void set_length(real_t p_length);
real_t get_length() const;
+
+ void set_slips_on_slope(bool p_active);
+ bool get_slips_on_slope() const;
+
virtual void draw(const RID &p_to_rid, const Color &p_color);
virtual Rect2 get_rect() const;
diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h
index ed655b8a93..7eb0406bd8 100644
--- a/scene/resources/shape_2d.h
+++ b/scene/resources/shape_2d.h
@@ -45,7 +45,7 @@ protected:
Shape2D(const RID &p_rid);
public:
- virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return true; }
+ virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return get_rect().has_point(p_point); }
void set_custom_solver_bias(real_t p_bias);
real_t get_custom_solver_bias() const;
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index de75bb3976..626fda50df 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -101,7 +101,7 @@ StyleBox::StyleBox() {
}
}
-void StyleBoxTexture::set_texture(RES p_texture) {
+void StyleBoxTexture::set_texture(Ref<Texture> p_texture) {
if (texture == p_texture)
return;
@@ -112,12 +112,12 @@ void StyleBoxTexture::set_texture(RES p_texture) {
_change_notify("texture");
}
-RES StyleBoxTexture::get_texture() const {
+Ref<Texture> StyleBoxTexture::get_texture() const {
return texture;
}
-void StyleBoxTexture::set_normal_map(RES p_normal_map) {
+void StyleBoxTexture::set_normal_map(Ref<Texture> p_normal_map) {
if (normal_map == p_normal_map)
return;
@@ -125,7 +125,7 @@ void StyleBoxTexture::set_normal_map(RES p_normal_map) {
emit_changed();
}
-RES StyleBoxTexture::get_normal_map() const {
+Ref<Texture> StyleBoxTexture::get_normal_map() const {
return normal_map;
}
@@ -650,14 +650,14 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
style_rect = style_rect.grow(-((aa_size + 1) / 2));
}
- //adapt borders (prevent weired overlapping/glitchy drawings)
+ //adapt borders (prevent weird overlapping/glitchy drawings)
int width = MAX(style_rect.size.width, 0);
int height = MAX(style_rect.size.height, 0);
int adapted_border[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
adapt_values(MARGIN_TOP, MARGIN_BOTTOM, adapted_border, border_width, height, height, height);
adapt_values(MARGIN_LEFT, MARGIN_RIGHT, adapted_border, border_width, width, width, width);
- //adapt corners (prevent weired overlapping/glitchy drawings)
+ //adapt corners (prevent weird overlapping/glitchy drawings)
int adapted_corner[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
adapt_values(CORNER_TOP_RIGHT, CORNER_BOTTOM_RIGHT, adapted_corner, corner_radius, height, height - adapted_border[MARGIN_BOTTOM], height - adapted_border[MARGIN_TOP]);
adapt_values(CORNER_TOP_LEFT, CORNER_BOTTOM_LEFT, adapted_corner, corner_radius, height, height - adapted_border[MARGIN_BOTTOM], height - adapted_border[MARGIN_TOP]);
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index fb79aa360e..c1d84fe19f 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -112,11 +112,11 @@ public:
void set_region_rect(const Rect2 &p_region_rect);
Rect2 get_region_rect() const;
- void set_texture(RES p_texture);
- RES get_texture() const;
+ void set_texture(Ref<Texture> p_texture);
+ Ref<Texture> get_texture() const;
- void set_normal_map(RES p_normal_map);
- RES get_normal_map() const;
+ void set_normal_map(Ref<Texture> p_normal_map);
+ Ref<Texture> get_normal_map() const;
void set_draw_center(bool p_enabled);
bool is_draw_center_enabled() const;
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 3138d73caf..4463f98b07 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -57,8 +57,8 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
tile_set_modulate(id, p_value);
else if (what == "region")
tile_set_region(id, p_value);
- else if (what == "is_autotile")
- tile_set_is_autotile(id, p_value);
+ else if (what == "tile_mode")
+ tile_set_tile_mode(id, (TileMode)((int)p_value));
else if (what.left(9) == "autotile/") {
what = what.right(9);
if (what == "bitmask_mode")
@@ -174,8 +174,8 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = tile_get_modulate(id);
else if (what == "region")
r_ret = tile_get_region(id);
- else if (what == "is_autotile")
- r_ret = tile_get_is_autotile(id);
+ else if (what == "tile_mode")
+ r_ret = tile_get_tile_mode(id);
else if (what.left(9) == "autotile/") {
what = what.right(9);
if (what == "bitmask_mode")
@@ -258,13 +258,13 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial"));
p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate"));
p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region"));
- p_list->push_back(PropertyInfo(Variant::BOOL, pre + "is_autotile", PROPERTY_HINT_NONE, ""));
- if (tile_get_is_autotile(id)) {
+ p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE"));
+ if (tile_get_tile_mode(id) == AUTO_TILE) {
p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/icon_coordinate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "autotile/tile_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/spacing", PROPERTY_HINT_RANGE, "0,256,1", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/occluder_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/navpoly_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/priority_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
@@ -282,7 +282,6 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
}
void TileSet::create_tile(int p_id) {
-
ERR_FAIL_COND(tile_map.has(p_id));
tile_map[p_id] = TileData();
tile_map[p_id].autotile_data = AutotileData();
@@ -291,7 +290,6 @@ void TileSet::create_tile(int p_id) {
}
void TileSet::autotile_set_bitmask_mode(int p_id, BitmaskMode p_mode) {
-
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].autotile_data.bitmask_mode = p_mode;
_change_notify("");
@@ -375,6 +373,7 @@ void TileSet::tile_set_region(int p_id, const Rect2 &p_region) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].region = p_region;
emit_changed();
+ _change_notify("region");
}
Rect2 TileSet::tile_get_region(int p_id) const {
@@ -383,18 +382,17 @@ Rect2 TileSet::tile_get_region(int p_id) const {
return tile_map[p_id].region;
}
-void TileSet::tile_set_is_autotile(int p_id, bool p_is_autotile) {
-
+void TileSet::tile_set_tile_mode(int p_id, TileMode p_tile_mode) {
ERR_FAIL_COND(!tile_map.has(p_id));
- tile_map[p_id].is_autotile = p_is_autotile;
+ tile_map[p_id].tile_mode = p_tile_mode;
emit_changed();
- _change_notify("is_autotile");
+ _change_notify("tile_mode");
}
-bool TileSet::tile_get_is_autotile(int p_id) const {
+TileSet::TileMode TileSet::tile_get_tile_mode(int p_id) const {
- ERR_FAIL_COND_V(!tile_map.has(p_id), false);
- return tile_map[p_id].is_autotile;
+ ERR_FAIL_COND_V(!tile_map.has(p_id), SINGLE_TILE);
+ return tile_map[p_id].tile_mode;
}
void TileSet::autotile_set_icon_coordinate(int p_id, Vector2 coord) {
@@ -534,6 +532,7 @@ void TileSet::tile_set_name(int p_id, const String &p_name) {
ERR_FAIL_COND(!tile_map.has(p_id));
tile_map[p_id].name = p_name;
emit_changed();
+ _change_notify("name");
}
String TileSet::tile_get_name(int p_id) const {
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 1306e2878c..46f34b6252 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -71,6 +71,12 @@ public:
BIND_BOTTOMRIGHT = 256
};
+ enum TileMode {
+ SINGLE_TILE,
+ AUTO_TILE,
+ ANIMATED_TILE
+ };
+
struct AutotileData {
BitmaskMode bitmask_mode;
int spacing;
@@ -84,6 +90,7 @@ public:
// Default size to prevent invalid value
explicit AutotileData() :
size(64, 64),
+ spacing(0),
icon_coord(0, 0) {
bitmask_mode = BITMASK_2X2;
}
@@ -104,13 +111,13 @@ private:
Ref<NavigationPolygon> navigation_polygon;
Ref<ShaderMaterial> material;
Color modulate;
- bool is_autotile;
+ TileMode tile_mode;
AutotileData autotile_data;
// Default modulate for back-compat
explicit TileData() :
- modulate(1, 1, 1),
- is_autotile(false) {}
+ tile_mode(SINGLE_TILE),
+ modulate(1, 1, 1) {}
};
Map<int, TileData> tile_map;
@@ -146,8 +153,8 @@ public:
void tile_set_region(int p_id, const Rect2 &p_region);
Rect2 tile_get_region(int p_id) const;
- void tile_set_is_autotile(int p_id, bool p_is_autotile);
- bool tile_get_is_autotile(int p_id) const;
+ void tile_set_tile_mode(int p_id, TileMode p_tile_mode);
+ TileMode tile_get_tile_mode(int p_id) const;
void autotile_set_icon_coordinate(int p_id, Vector2 coord);
Vector2 autotile_get_icon_coordinate(int p_id) const;