Added ability for multiple images to be imported as an atlas

This adds support for groups in the import system, which point to a single file.
Add property hint for saving files in file field
This commit is contained in:
Juan Linietsky 2019-04-19 15:54:33 -03:00
parent 8e652a1400
commit 04847ef5f9
35 changed files with 1818 additions and 33 deletions

View file

@ -1876,7 +1876,7 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const P
Rect2 Image::get_used_rect() const {
if (format != FORMAT_LA8 && format != FORMAT_RGBA8)
if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGBA5551)
return Rect2(Point2(), Size2(width, height));
int len = data.size();
@ -1884,17 +1884,13 @@ Rect2 Image::get_used_rect() const {
if (len == 0)
return Rect2();
//int data_size = len;
PoolVector<uint8_t>::Read r = data.read();
const unsigned char *rptr = r.ptr();
int ps = format == FORMAT_LA8 ? 2 : 4;
const_cast<Image *>(this)->lock();
int minx = 0xFFFFFF, miny = 0xFFFFFFF;
int maxx = -1, maxy = -1;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
bool opaque = rptr[(j * width + i) * ps + (ps - 1)] > 2;
bool opaque = get_pixel(i, j).a > 0.99;
if (!opaque)
continue;
if (i > maxx)
@ -1908,6 +1904,8 @@ Rect2 Image::get_used_rect() const {
}
}
const_cast<Image *>(this)->unlock();
if (maxx == -1)
return Rect2();
else

View file

@ -94,6 +94,8 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
r_path_and_type.type = value;
} else if (assign == "importer") {
r_path_and_type.importer = value;
} else if (assign == "group_file") {
r_path_and_type.group_file = value;
} else if (assign == "metadata") {
r_path_and_type.metadata = value;
} else if (assign == "valid") {
@ -294,6 +296,15 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
memdelete(f);
}
String ResourceFormatImporter::get_import_group_file(const String &p_path) const {
bool valid = true;
PathAndType pat;
_get_path_and_type(p_path, pat, &valid);
return valid?pat.group_file:String();
}
bool ResourceFormatImporter::is_import_valid(const String &p_path) const {
bool valid = true;

View file

@ -43,6 +43,7 @@ class ResourceFormatImporter : public ResourceFormatLoader {
String path;
String type;
String importer;
String group_file;
Variant metadata;
};
@ -69,6 +70,7 @@ public:
virtual bool is_import_valid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual bool is_imported(const String &p_path) const { return recognize_path(p_path); }
virtual String get_import_group_file(const String &p_path) const;
virtual bool exists(const String &p_path) const;
virtual bool can_be_imported(const String &p_path) const;
@ -120,8 +122,11 @@ public:
virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const = 0;
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const = 0;
virtual String get_option_group_file() const { return String(); }
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL, Variant *r_metadata = NULL) = 0;
virtual Error import_group_file(const String& p_group_file,const Map<String,Map<StringName, Variant> >&p_source_file_options, const Map<String,String>& p_base_paths) { return ERR_UNAVAILABLE; }
virtual bool are_import_settings_valid(const String &p_path) const { return true; }
virtual String get_import_settings_string() const { return String(); }
};

View file

@ -608,6 +608,30 @@ int ResourceLoader::get_import_order(const String &p_path) {
return 0;
}
String ResourceLoader::get_import_group_file(const String &p_path) {
String path = _path_remap(p_path);
String local_path;
if (path.is_rel_path())
local_path = "res://" + path;
else
local_path = ProjectSettings::get_singleton()->localize_path(path);
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path))
continue;
/*
if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
continue;
*/
return loader[i]->get_import_group_file(p_path);
}
return String(); //not found
}
bool ResourceLoader::is_import_valid(const String &p_path) {
String path = _path_remap(p_path);

View file

@ -81,6 +81,7 @@ public:
virtual bool is_import_valid(const String &p_path) const { return true; }
virtual bool is_imported(const String &p_path) const { return false; }
virtual int get_import_order(const String &p_path) const { return 0; }
virtual String get_import_group_file(const String &p_path) const { return ""; } //no group
virtual ~ResourceFormatLoader() {}
};
@ -155,6 +156,7 @@ public:
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
static bool is_import_valid(const String &p_path);
static String get_import_group_file(const String &p_path);
static bool is_imported(const String &p_path);
static int get_import_order(const String &p_path);

View file

@ -106,7 +106,7 @@ Size2 Transform2D::get_scale() const {
return Size2(elements[0].length(), det_sign * elements[1].length());
}
void Transform2D::set_scale(Size2 &p_scale) {
void Transform2D::set_scale(const Size2 &p_scale) {
elements[0].normalize();
elements[1].normalize();
elements[0] *= p_scale.x;

View file

@ -81,7 +81,7 @@ struct Transform2D {
real_t basis_determinant() const;
Size2 get_scale() const;
void set_scale(Size2 &p_scale);
void set_scale(const Size2 &p_scale);
_FORCE_INLINE_ const Vector2 &get_origin() const { return elements[2]; }
_FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { elements[2] = p_origin; }

View file

@ -99,6 +99,7 @@ struct Vector2 {
Vector2 operator/(const real_t &rvalue) const;
void operator/=(const real_t &rvalue);
void operator/=(const Vector2 &rvalue) { *this = *this / rvalue; }
Vector2 operator-() const;

View file

@ -88,6 +88,7 @@ enum PropertyHint {
PROPERTY_HINT_PROPERTY_OF_SCRIPT, ///< a property of a script & base
PROPERTY_HINT_OBJECT_TOO_BIG, ///< object is too big to send
PROPERTY_HINT_NODE_PATH_VALID_TYPES,
PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog
PROPERTY_HINT_MAX,
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
};

View file

@ -197,6 +197,19 @@ public:
r.reference = NULL;
}
template <class T_Other>
void reference_ptr(T_Other *p_ptr) {
if (reference == p_ptr) {
return;
}
unref();
T *r = Object::cast_to<T>(p_ptr);
if (r) {
ref_pointer(r);
}
}
Ref(const Ref &p_from) {
reference = NULL;

View file

@ -826,6 +826,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size);
}
state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * mesh->transform);
RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh);
if (mesh_data) {
@ -834,7 +836,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
// materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing
glBindVertexArray(s->array_id);
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
glVertexAttrib4f(VS::ARRAY_COLOR, mesh->modulate.r, mesh->modulate.g, mesh->modulate.b, mesh->modulate.a);
if (s->index_array_len) {
glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0);
@ -845,6 +847,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur
glBindVertexArray(0);
}
}
state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform);
} break;
case Item::Command::TYPE_MULTIMESH: {

View file

@ -0,0 +1,265 @@
#include "editor_atlas_packer.h"
void EditorAtlasPacker::_plot_triangle(Ref<BitMap> p_bitmap, Vector2i *vertices) {
int width = p_bitmap->get_size().width;
int height = p_bitmap->get_size().height;
int x[3];
int y[3];
for (int j = 0; j < 3; j++) {
x[j] = vertices[j].x;
y[j] = vertices[j].y;
}
// sort the points vertically
if (y[1] > y[2]) {
SWAP(x[1], x[2]);
SWAP(y[1], y[2]);
}
if (y[0] > y[1]) {
SWAP(x[0], x[1]);
SWAP(y[0], y[1]);
}
if (y[1] > y[2]) {
SWAP(x[1], x[2]);
SWAP(y[1], y[2]);
}
double dx_far = double(x[2] - x[0]) / (y[2] - y[0] + 1);
double dx_upper = double(x[1] - x[0]) / (y[1] - y[0] + 1);
double dx_low = double(x[2] - x[1]) / (y[2] - y[1] + 1);
double xf = x[0];
double xt = x[0] + dx_upper; // if y[0] == y[1], special case
for (int yi = y[0]; yi <= (y[2] > height - 1 ? height - 1 : y[2]); yi++) {
if (yi >= 0) {
for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < width ? xt : width - 1); xi++) {
//pixels[int(x + y * width)] = color;
p_bitmap->set_bit(Point2(xi, yi), true);
}
for (int xi = (xf < width ? int(xf) : width - 1); xi >= (xt > 0 ? xt : 0); xi--) {
p_bitmap->set_bit(Point2(xi, yi), true);
}
}
xf += dx_far;
if (yi < y[1])
xt += dx_upper;
else
xt += dx_low;
}
}
void EditorAtlasPacker::chart_pack(Vector<Chart> &charts, int &r_width, int &r_height, int p_atlas_max_size, int p_cell_resolution) {
int divide_by = MIN(64, p_cell_resolution);
Vector<PlottedBitmap> bitmaps;
int max_w = 0;
for (int i = 0; i < charts.size(); i++) {
const Chart &chart = charts[i];
//generate aabb
Rect2i aabb;
int vertex_count = chart.vertices.size();
const Vector2 *vertices = chart.vertices.ptr();
for (int j = 0; j < vertex_count; j++) {
if (j == 0) {
aabb.position = vertices[j];
} else {
aabb.expand_to(vertices[j]);
}
}
Ref<BitMap> src_bitmap;
src_bitmap.instance();
src_bitmap->create(aabb.size / divide_by);
int w = src_bitmap->get_size().width;
int h = src_bitmap->get_size().height;
//plot triangles, using divisor
for (int j = 0; j < chart.faces.size(); j++) {
Vector2i v[3];
for (int k = 0; k < 3; k++) {
Vector2 vtx = chart.vertices[chart.faces[j].vertex[k]];
vtx -= aabb.position;
vtx /= divide_by;
v[k] = vtx;
}
_plot_triangle(src_bitmap, v);
}
//src_bitmap->convert_to_image()->save_png("bitmap" + itos(i) + ".png");
//grow by 1 for each side
int bmw = src_bitmap->get_size().width + 2;
int bmh = src_bitmap->get_size().height + 2;
int heights_size = -1;
bool transpose = false;
if (chart.can_transpose && bmh > bmw) {
heights_size = bmh;
transpose = true;
} else {
heights_size = bmw;
}
max_w = MAX(max_w, heights_size);
Vector<int> top_heights;
Vector<int> bottom_heights;
top_heights.resize(heights_size);
bottom_heights.resize(heights_size);
for (int x = 0; x < heights_size; x++) {
top_heights.write[x] = -1;
bottom_heights.write[x] = 0x7FFFFFFF;
}
for (int x = 0; x < bmw; x++) {
for (int y = 0; y < bmh; y++) {
bool found_pixel = false;
for (int lx = x - 1; lx < x + 2 && !found_pixel; lx++) {
for (int ly = y - 1; ly < y + 2 && !found_pixel; ly++) {
int px = lx - 1;
if (px < 0 || px >= w)
continue;
int py = ly - 1;
if (py < 0 || py >= h)
continue;
if (src_bitmap->get_bit(Vector2(px, py))) {
found_pixel = true;
}
}
}
if (found_pixel) {
if (transpose) {
if (x > top_heights[y]) {
top_heights.write[y] = x;
}
if (x < bottom_heights[y]) {
bottom_heights.write[y] = x;
}
} else {
if (y > top_heights[x]) {
top_heights.write[x] = y;
}
if (y < bottom_heights[x]) {
bottom_heights.write[x] = y;
}
}
}
}
}
String row;
for (int j = 0; j < top_heights.size(); j++) {
row += "(" + itos(top_heights[j]) + "-" + itos(bottom_heights[j]) + "),";
}
PlottedBitmap plotted_bitmap;
plotted_bitmap.offset = aabb.position;
plotted_bitmap.top_heights = top_heights;
plotted_bitmap.bottom_heights = bottom_heights;
plotted_bitmap.chart_index = i;
plotted_bitmap.transposed = transpose;
plotted_bitmap.area = bmw * bmh;
bitmaps.push_back(plotted_bitmap);
}
bitmaps.sort();
int atlas_max_width = nearest_power_of_2_templated(p_atlas_max_size) / divide_by;
int atlas_w = nearest_power_of_2_templated(max_w);
int atlas_h;
while (true) {
atlas_h = 0;
//do a tetris
Vector<int> heights;
heights.resize(atlas_w);
for (int i = 0; i < atlas_w; i++) {
heights.write[i] = 0;
}
int *atlas_ptr = heights.ptrw();
for (int i = 0; i < bitmaps.size(); i++) {
int best_height = 0x7FFFFFFF;
int best_height_offset = -1;
int w = bitmaps[i].top_heights.size();
const int *top_heights = bitmaps[i].top_heights.ptr();
const int *bottom_heights = bitmaps[i].bottom_heights.ptr();
for (int j = 0; j < atlas_w - w; j++) {
int height = 0;
for (int k = 0; k < w; k++) {
int pixmap_h = bottom_heights[k];
if (pixmap_h == -1) {
continue; //no pixel here, anything is fine
}
int h = MAX(0, atlas_ptr[j + k] - pixmap_h);
if (h > height) {
height = h;
}
}
if (height < best_height) {
best_height = height;
best_height_offset = j;
}
}
for (int j = 0; j < w; j++) { //add
if (top_heights[j] == -1) { //unused
continue;
}
int height = best_height + top_heights[j] + 1;
atlas_ptr[j + best_height_offset] = height;
atlas_h = MAX(atlas_h, height);
}
// set
Vector2 offset = bitmaps[i].offset;
if (bitmaps[i].transposed) {
SWAP(offset.x, offset.y);
}
Vector2 final_pos = Vector2(best_height_offset * divide_by, best_height * divide_by) + Vector2(divide_by, divide_by) - offset;
charts.write[bitmaps[i].chart_index].final_offset = final_pos;
charts.write[bitmaps[i].chart_index].transposed = bitmaps[i].transposed;
}
if (atlas_h <= atlas_w * 2 || atlas_w >= atlas_max_width) {
break; //ok this one is enough
}
//try again
atlas_w *= 2;
}
r_width = atlas_w * divide_by;
r_height = atlas_h * divide_by;
}

View file

@ -0,0 +1,45 @@
#ifndef EDITOR_ATLAS_PACKER_H
#define EDITOR_ATLAS_PACKER_H
#include "core/math/vector2.h"
#include "core/vector.h"
#include "scene/resources/bit_map.h"
class EditorAtlasPacker {
public:
struct Chart {
Vector<Vector2> vertices;
struct Face {
int vertex[3];
};
Vector<Face> faces;
bool can_transpose;
Vector2 final_offset;
bool transposed;
};
private:
struct PlottedBitmap {
int chart_index;
Vector2i offset;
int area;
Vector<int> top_heights;
Vector<int> bottom_heights;
bool transposed;
Vector2 final_pos;
bool operator<(const PlottedBitmap &p_bm) const {
return area > p_bm.area;
}
};
static void _plot_triangle(Ref<BitMap> p_bitmap, Vector2i *vertices);
public:
static void chart_pack(Vector<Chart> &charts, int &r_width, int &r_height, int p_atlas_max_size = 2048, int p_cell_resolution = 4);
};
#endif // EDITOR_ATLAS_PACKER_H

View file

@ -43,7 +43,7 @@
EditorFileSystem *EditorFileSystem::singleton = NULL;
//the name is the version, to keep compatibility with different versions of Godot
#define CACHE_FILE_NAME "filesystem_cache5"
#define CACHE_FILE_NAME "filesystem_cache6"
void EditorFileSystemDirectory::sort_files() {
@ -241,7 +241,7 @@ void EditorFileSystem::_scan_filesystem() {
} else {
Vector<String> split = l.split("::");
ERR_CONTINUE(split.size() != 7);
ERR_CONTINUE(split.size() != 8);
String name = split[0];
String file;
@ -253,11 +253,12 @@ void EditorFileSystem::_scan_filesystem() {
fc.modification_time = split[2].to_int64();
fc.import_modification_time = split[3].to_int64();
fc.import_valid = split[4].to_int64() != 0;
fc.script_class_name = split[5].get_slice("<>", 0);
fc.script_class_extends = split[5].get_slice("<>", 1);
fc.script_class_icon_path = split[5].get_slice("<>", 2);
fc.import_group_file = split[5].strip_edges();
fc.script_class_name = split[6].get_slice("<>", 0);
fc.script_class_extends = split[6].get_slice("<>", 1);
fc.script_class_icon_path = split[6].get_slice("<>", 2);
String deps = split[6].strip_edges();
String deps = split[7].strip_edges();
if (deps.length()) {
Vector<String> dp = deps.split("<>");
for (int i = 0; i < dp.size(); i++) {
@ -318,6 +319,9 @@ void EditorFileSystem::_scan_filesystem() {
}
void EditorFileSystem::_save_filesystem_cache() {
group_file_cache.clear();
String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
FileAccess *f = FileAccess::open(fscache, FileAccess::WRITE);
@ -771,6 +775,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
fi->import_valid = fc->import_valid;
fi->script_class_name = fc->script_class_name;
fi->import_group_file = fc->import_group_file;
fi->script_class_extends = fc->script_class_extends;
fi->script_class_icon_path = fc->script_class_icon_path;
@ -784,6 +789,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
if (fc->type == String()) {
fi->type = ResourceLoader::get_resource_type(path);
fi->import_group_file = ResourceLoader::get_import_group_file(path);
//there is also the chance that file type changed due to reimport, must probably check this somehow here (or kind of note it for next time in another file?)
//note: I think this should not happen any longer..
}
@ -791,6 +797,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
} else {
fi->type = ResourceFormatImporter::get_singleton()->get_resource_type(path);
fi->import_group_file = ResourceFormatImporter::get_singleton()->get_import_group_file(path);
fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path);
fi->modified_time = 0;
fi->import_modified_time = 0;
@ -918,6 +925,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
fi->type = ResourceLoader::get_resource_type(path);
fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path);
fi->import_valid = ResourceLoader::is_import_valid(path);
fi->import_group_file = ResourceLoader::get_import_group_file(path);
{
ItemAction ia;
@ -1187,7 +1195,10 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir,
for (int i = 0; i < p_dir->files.size(); i++) {
String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path;
if (p_dir->files[i]->import_group_file != String()) {
group_file_cache.insert(p_dir->files[i]->import_group_file);
}
String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->import_group_file + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path;
s += "::";
for (int j = 0; j < p_dir->files[i]->deps.size(); j++) {
@ -1523,6 +1534,7 @@ void EditorFileSystem::update_file(const String &p_file) {
fs->files[cpos]->type = type;
fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path);
fs->files[cpos]->import_group_file = ResourceLoader::get_import_group_file(p_file);
fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
fs->files[cpos]->deps = _get_dependencies(p_file);
fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file);
@ -1534,6 +1546,168 @@ void EditorFileSystem::update_file(const String &p_file) {
_queue_update_script_classes();
}
Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector<String> &p_files) {
String importer_name;
Map<String, Map<StringName, Variant> > source_file_options;
Map<String, String> base_paths;
for (int i = 0; i < p_files.size(); i++) {
Ref<ConfigFile> config;
config.instance();
Error err = config->load(p_files[i] + ".import");
ERR_CONTINUE(err != OK);
ERR_CONTINUE(!config->has_section_key("remap", "importer"));
String file_importer_name = config->get_value("remap", "importer");
ERR_CONTINUE(file_importer_name == String());
if (importer_name != String() && importer_name != file_importer_name) {
print_line("one importer: " + importer_name + " the other: " + file_importer_name);
EditorNode::get_singleton()->show_warning(vformat(TTR("There are multiple importers for different types pointing to file %s, import aborted"), p_group_file));
ERR_FAIL_V(ERR_FILE_CORRUPT);
}
source_file_options[p_files[i]] = Map<StringName, Variant>();
importer_name = file_importer_name;
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
ERR_FAIL_COND_V(!importer.is_valid(), ERR_FILE_CORRUPT);
List<ResourceImporter::ImportOption> options;
importer->get_import_options(&options);
//set default values
for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
source_file_options[p_files[i]][E->get().option.name] = E->get().default_value;
}
if (config->has_section("params")) {
List<String> sk;
config->get_section_keys("params", &sk);
for (List<String>::Element *E = sk.front(); E; E = E->next()) {
String param = E->get();
Variant value = config->get_value("params", param);
//override with whathever is in file
source_file_options[p_files[i]][param] = value;
}
}
base_paths[p_files[i]] = ResourceFormatImporter::get_singleton()->get_import_base_path(p_files[i]);
}
ERR_FAIL_COND_V(importer_name == String(), ERR_UNCONFIGURED);
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
Error err = importer->import_group_file(p_group_file, source_file_options, base_paths);
//all went well, overwrite config files with proper remaps and md5s
for (Map<String, Map<StringName, Variant> >::Element *E = source_file_options.front(); E; E = E->next()) {
String file = E->key();
String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(file);
FileAccessRef f = FileAccess::open(file + ".import", FileAccess::WRITE);
ERR_FAIL_COND_V(!f, ERR_FILE_CANT_OPEN);
//write manually, as order matters ([remap] has to go first for performance).
f->store_line("[remap]");
f->store_line("");
f->store_line("importer=\"" + importer->get_importer_name() + "\"");
if (importer->get_resource_type() != "") {
f->store_line("type=\"" + importer->get_resource_type() + "\"");
}
Vector<String> dest_paths;
if (err == OK) {
String path = base_path + "." + importer->get_save_extension();
f->store_line("path=\"" + path + "\"");
dest_paths.push_back(path);
}
f->store_line("group_file=" + Variant(p_group_file).get_construct_string());
if (err == OK) {
f->store_line("valid=true");
} else {
f->store_line("valid=false");
}
f->store_line("[deps]\n");
f->store_line("");
f->store_line("source_file=" + Variant(file).get_construct_string());
if (dest_paths.size()) {
Array dp;
for (int i = 0; i < dest_paths.size(); i++) {
dp.push_back(dest_paths[i]);
}
f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
}
f->store_line("[params]");
f->store_line("");
//store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
List<ResourceImporter::ImportOption> options;
importer->get_import_options(&options);
//set default values
for (List<ResourceImporter::ImportOption>::Element *F = options.front(); F; F = F->next()) {
String base = F->get().option.name;
Variant v = F->get().default_value;
if (source_file_options[file].has(base)) {
v = source_file_options[file][base];
}
String value;
VariantWriter::write_to_string(v, value);
f->store_line(base + "=" + value);
}
f->close();
// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
FileAccessRef md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
ERR_FAIL_COND_V(!md5s, ERR_FILE_CANT_OPEN);
md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\"");
if (dest_paths.size()) {
md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
}
md5s->close();
EditorFileSystemDirectory *fs = NULL;
int cpos = -1;
bool found = _find_file(file, &fs, cpos);
ERR_FAIL_COND_V(!found, ERR_UNCONFIGURED);
//update modified times, to avoid reimport
fs->files[cpos]->modified_time = FileAccess::get_modified_time(file);
fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(file + ".import");
fs->files[cpos]->deps = _get_dependencies(file);
fs->files[cpos]->type = importer->get_resource_type();
fs->files[cpos]->import_valid = err == OK;
//if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it
//to reload properly
if (ResourceCache::has(file)) {
Resource *r = ResourceCache::get(file);
if (r->get_import_path() != String()) {
String dst_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(file);
r->set_import_path(dst_path);
r->set_import_last_modified_time(0);
}
}
EditorResourcePreview::get_singleton()->check_for_invalidation(file);
}
return err;
}
void EditorFileSystem::_reimport_file(const String &p_file) {
EditorFileSystemDirectory *fs = NULL;
@ -1738,6 +1912,24 @@ void EditorFileSystem::_reimport_file(const String &p_file) {
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
}
void EditorFileSystem::_find_group_files(EditorFileSystemDirectory *efd, Map<String, Vector<String> > &group_files, Set<String> &groups_to_reimport) {
int fc = efd->files.size();
const EditorFileSystemDirectory::FileInfo *const *files = efd->files.ptr();
for (int i = 0; i < fc; i++) {
if (groups_to_reimport.has(files[i]->import_group_file)) {
if (!group_files.has(files[i]->import_group_file)) {
group_files[files[i]->import_group_file] = Vector<String>();
}
group_files[files[i]->import_group_file].push_back(efd->get_file_path(i));
}
}
for (int i = 0; i < efd->get_subdir_count(); i++) {
_find_group_files(efd->get_subdir(i), group_files, groups_to_reimport);
}
}
void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
{ //check that .import folder exists
@ -1757,22 +1949,58 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
EditorProgress pr("reimport", TTR("(Re)Importing Assets"), p_files.size());
Vector<ImportFile> files;
Set<String> groups_to_reimport;
for (int i = 0; i < p_files.size(); i++) {
ImportFile ifile;
ifile.path = p_files[i];
ifile.order = ResourceFormatImporter::get_singleton()->get_import_order(p_files[i]);
files.push_back(ifile);
String group_file = ResourceFormatImporter::get_singleton()->get_import_group_file(p_files[i]);
if (group_file_cache.has(p_files[i])) {
//maybe the file itself is a group!
groups_to_reimport.insert(p_files[i]);
//groups do not belong to grups
group_file = String();
} else if (group_file != String()) {
//it's a group file, add group to import and skip this file
groups_to_reimport.insert(group_file);
} else {
//it's a regular file
ImportFile ifile;
ifile.path = p_files[i];
ifile.order = ResourceFormatImporter::get_singleton()->get_import_order(p_files[i]);
files.push_back(ifile);
}
//group may have changed, so also update group reference
EditorFileSystemDirectory *fs = NULL;
int cpos = -1;
if (_find_file(p_files[i], &fs, cpos)) {
fs->files.write[cpos]->import_group_file = group_file;
}
}
files.sort();
for (int i = 0; i < files.size(); i++) {
pr.step(files[i].path.get_file(), i);
_reimport_file(files[i].path);
}
//reimport groups
if (groups_to_reimport.size()) {
Map<String, Vector<String> > group_files;
_find_group_files(filesystem, group_files, groups_to_reimport);
for (Map<String, Vector<String> >::Element *E = group_files.front(); E; E = E->next()) {
Error err = _reimport_group(E->key(), E->get());
if (err == OK) {
_reimport_file(E->key());
}
}
}
_save_filesystem_cache();
importing = false;
if (!is_scanning()) {
@ -1793,6 +2021,63 @@ Error EditorFileSystem::_resource_import(const String &p_path) {
return OK;
}
bool EditorFileSystem::is_group_file(const String &p_path) const {
return group_file_cache.has(p_path);
}
void EditorFileSystem::_move_group_files(EditorFileSystemDirectory *efd, const String &p_group_file, const String &p_new_location) {
int fc = efd->files.size();
EditorFileSystemDirectory::FileInfo *const *files = efd->files.ptrw();
for (int i = 0; i < fc; i++) {
if (files[i]->import_group_file == p_group_file) {
files[i]->import_group_file = p_new_location;
Ref<ConfigFile> config;
config.instance();
String path = efd->get_file_path(i) + ".import";
Error err = config->load(path);
if (err != OK) {
continue;
}
if (config->has_section_key("remap", "group_file")) {
config->set_value("remap", "group_file", p_new_location);
}
List<String> sk;
config->get_section_keys("params", &sk);
for (List<String>::Element *E = sk.front(); E; E = E->next()) {
//not very clean, but should work
String param = E->get();
String value = config->get_value("params", param);
if (value == p_group_file) {
config->set_value("params", param, p_new_location);
}
}
config->save(path);
}
}
for (int i = 0; i < efd->get_subdir_count(); i++) {
_move_group_files(efd->get_subdir(i), p_group_file, p_new_location);
}
}
void EditorFileSystem::move_group_file(const String &p_path, const String &p_new_path) {
if (get_filesystem()) {
_move_group_files(get_filesystem(), p_path, p_new_path);
if (group_file_cache.has(p_path)) {
group_file_cache.erase(p_path);
group_file_cache.insert(p_new_path);
}
}
}
void EditorFileSystem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_filesystem"), &EditorFileSystem::get_filesystem);

View file

@ -56,6 +56,7 @@ class EditorFileSystemDirectory : public Object {
uint64_t modified_time;
uint64_t import_modified_time;
bool import_valid;
String import_group_file;
Vector<String> deps;
bool verified; //used for checking changes
String script_class_name;
@ -167,6 +168,7 @@ class EditorFileSystem : public Node {
uint64_t import_modification_time;
Vector<String> deps;
bool import_valid;
String import_group_file;
String script_class_name;
String script_class_extends;
String script_class_icon_path;
@ -211,6 +213,7 @@ class EditorFileSystem : public Node {
void _update_extensions();
void _reimport_file(const String &p_file);
Error _reimport_group(const String &p_group_file, const Vector<String> &p_files);
bool _test_for_reimport(const String &p_path, bool p_only_imported_files);
@ -236,6 +239,12 @@ class EditorFileSystem : public Node {
bool using_fat_32; //workaround for projects in FAT32 filesystem (pendrives, most of the time)
void _find_group_files(EditorFileSystemDirectory *efd, Map<String, Vector<String> > &group_files, Set<String> &groups_to_reimport);
void _move_group_files(EditorFileSystemDirectory *efd, const String &p_group_file, const String &p_new_location);
Set<String> group_file_cache;
protected:
void _notification(int p_what);
static void _bind_methods();
@ -260,6 +269,9 @@ public:
void update_script_classes();
bool is_group_file(const String &p_path) const;
void move_group_file(const String &p_path, const String &p_new_path);
EditorFileSystem();
~EditorFileSystem();
};

View file

@ -65,6 +65,7 @@
#include "editor/import/resource_importer_obj.h"
#include "editor/import/resource_importer_scene.h"
#include "editor/import/resource_importer_texture.h"
#include "editor/import/resource_importer_texture_atlas.h"
#include "editor/import/resource_importer_wav.h"
#include "editor/plugins/animation_blend_space_1d_editor.h"
#include "editor/plugins/animation_blend_space_2d_editor.h"
@ -5121,6 +5122,10 @@ EditorNode::EditorNode() {
import_image.instance();
ResourceFormatImporter::get_singleton()->add_importer(import_image);
Ref<ResourceImporterTextureAtlas> import_texture_atlas;
import_texture_atlas.instance();
ResourceFormatImporter::get_singleton()->add_importer(import_texture_atlas);
Ref<ResourceImporterCSVTranslation> import_csv_translation;
import_csv_translation.instance();
ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation);

View file

@ -2993,13 +2993,17 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ
EditorPropertyClassName *editor = memnew(EditorPropertyClassName);
editor->setup("Object", p_hint_text);
add_property_editor(p_path, editor);
} else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) {
} else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) {
Vector<String> extensions = p_hint_text.split(",");
bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE;
bool folder = p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_GLOBAL_DIR;
bool save = p_hint == PROPERTY_HINT_SAVE_FILE;
EditorPropertyPath *editor = memnew(EditorPropertyPath);
editor->setup(extensions, folder, global);
if (save) {
editor->set_save_mode();
}
add_property_editor(p_path, editor);
} else if (p_hint == PROPERTY_HINT_METHOD_OF_VARIANT_TYPE ||
p_hint == PROPERTY_HINT_METHOD_OF_BASE_TYPE ||

View file

@ -1257,6 +1257,10 @@ void FileSystemDock::_rename_operation_confirm() {
return;
}
if (EditorFileSystem::get_singleton()->is_group_file(old_path)) {
EditorFileSystem::get_singleton()->move_group_file(old_path, new_path);
}
//Present a more user friendly warning for name conflict
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
@ -1354,6 +1358,16 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool overw
}
}
//check groups
for (int i = 0; i < to_move.size(); i++) {
print_line("is group: " + to_move[i].path + ": " + itos(EditorFileSystem::get_singleton()->is_group_file(to_move[i].path)));
if (to_move[i].is_file && EditorFileSystem::get_singleton()->is_group_file(to_move[i].path)) {
print_line("move to: " + p_to_path.plus_file(to_move[i].path.get_file()));
EditorFileSystem::get_singleton()->move_group_file(to_move[i].path, p_to_path.plus_file(to_move[i].path.get_file()));
}
}
Map<String, String> file_renames;
Map<String, String> folder_renames;
bool is_moved = false;

View file

@ -0,0 +1,414 @@
/* XPM */
static const char * atlas_import_failed_xpm[] = {
"128 128 283 2",
" c None",
". c #FFFFFF",
"+ c #FFDADA",
"@ c #FF0000",
"# c #FFD8D8",
"$ c #FFF7F7",
"% c #FF2E2E",
"& c #FFD4D4",
"* c #FFD6D6",
"= c #FFE3E3",
"- c #FFB3B3",
"; c #FFC8C8",
"> c #FF3535",
", c #FF8D8D",
"' c #FF7878",
") c #FF6E6E",
"! c #FFB5B5",
"~ c #FF0D0D",
"{ c #FFF0F0",
"] c #FFE8E8",
"^ c #FFC2C2",
"/ c #FFEDED",
"( c #FFBBBB",
"_ c #FFB9B9",
": c #FFA4A4",
"< c #FFFEFE",
"[ c #FFD9D9",
"} c #FF9393",
"| c #FF5858",
"1 c #FF3232",
"2 c #FF7575",
"3 c #FFC9C9",
"4 c #FFFCFC",
"5 c #FFBDBD",
"6 c #FF3838",
"7 c #FF9494",
"8 c #FFE2E2",
"9 c #FFD1D1",
"0 c #FFDEDE",
"a c #FFCACA",
"b c #FF6969",
"c c #FF8484",
"d c #FFEAEA",
"e c #FFE9E9",
"f c #FF3B3B",
"g c #FFC0C0",
"h c #FF6868",
"i c #FF7373",
"j c #FFF6F6",
"k c #FFADAD",
"l c #FF5D5D",
"m c #FF2626",
"n c #FF5C5C",
"o c #FFABAB",
"p c #FFCECE",
"q c #FF7070",
"r c #FF5555",
"s c #FF1C1C",
"t c #FFF4F4",
"u c #FF8282",
"v c #FF6060",
"w c #FFE7E7",
"x c #FF9D9D",
"y c #FF5656",
"z c #FF4242",
"A c #FF9B9B",
"B c #FFD0D0",
"C c #FFF8F8",
"D c #FF6A6A",
"E c #FF5151",
"F c #FFFBFB",
"G c #FF4949",
"H c #FFCDCD",
"I c #FFDDDD",
"J c #FF9E9E",
"K c #FFF9F9",
"L c #FFDCDC",
"M c #FF8F8F",
"N c #FFCBCB",
"O c #FFF5F5",
"P c #FF4747",
"Q c #FF9C9C",
"R c #FFEEEE",
"S c #FFFAFA",
"T c #FF1616",
"U c #FF8888",
"V c #FFC5C5",
"W c #FF2222",
"X c #FF4B4B",
"Y c #FFB8B8",
"Z c #FF7F7F",
"` c #FFE6E6",
" . c #FF8080",
".. c #FFB4B4",
"+. c #FFC3C3",
"@. c #FFD2D2",
"#. c #FFD7D7",
"$. c #FFDFDF",
"%. c #FFB7B7",
"&. c #FFF1F1",
"*. c #FF6262",
"=. c #FF8A8A",
"-. c #FFA9A9",
";. c #FFAEAE",
">. c #FFAAAA",
",. c #FF8B8B",
"'. c #FF4F4F",
"). c #FFFDFD",
"!. c #FFA3A3",
"~. c #FF2A2A",
"{. c #FFCFCF",
"]. c #FF8585",
"^. c #FF7676",
"/. c #FFD3D3",
"(. c #FFD5D5",
"_. c #FF8181",
":. c #FFC6C6",
"<. c #FFDBDB",
"[. c #FF9090",
"}. c #FFAFAF",
"|. c #FFA1A1",
"1. c #FFBABA",
"2. c #FF6C6C",
"3. c #FF5F5F",
"4. c #FF3D3D",
"5. c #FF9999",
"6. c #FFE0E0",
"7. c #FF8383",
"8. c #FFEFEF",
"9. c #FFF3F3",
"0. c #FFA8A8",
"a. c #FFB6B6",
"b. c #FF9F9F",
"c. c #FF4545",
"d. c #FFE5E5",
"e. c #FFE4E4",
"f. c #FFC7C7",
"g. c #FF6565",
"h. c #FFACAC",
"i. c #FF5A5A",
"j. c #FF7272",
"k. c #FF7C7C",
"l. c #FFBFBF",
"m. c #FF7171",
"n. c #FFECEC",
"o. c #FF8989",
"p. c #FF7777",
"q. c #FFC4C4",
"r. c #FF9898",
"s. c #FF8C8C",
"t. c #FF7A7A",
"u. c #FF8E8E",
"v. c #FFF2F2",
"w. c #FF9797",
"x. c #FFC1C1",
"y. c #FFA6A6",
"z. c #FFEBEB",
"A. c #FF4040",
"B. c #EDEDED",
"C. c #000000",
"D. c #AAAAAA",
"E. c #F6F6F6",
"F. c #1C1C1C",
"G. c #888888",
"H. c #7C7C7C",
"I. c #626262",
"J. c #B3B3B3",
"K. c #2A2A2A",
"L. c #959595",
"M. c #FDFDFD",
"N. c #C5C5C5",
"O. c #666666",
"P. c #353535",
"Q. c #777777",
"R. c #DEDEDE",
"S. c #6C6C6C",
"T. c #F5F5F5",
"U. c #ADADAD",
"V. c #DDDDDD",
"W. c #D8D8D8",
"X. c #B4B4B4",
"Y. c #FAFAFA",
"Z. c #949494",
"`. c #3B3B3B",
" + c #A8A8A8",
".+ c #C8C8C8",
"++ c #D4D4D4",
"@+ c #B9B9B9",
"#+ c #2E2E2E",
"$+ c #FEFEFE",
"%+ c #BABABA",
"&+ c #FCFCFC",
"*+ c #B2B2B2",
"=+ c #CACACA",
"-+ c #696969",
";+ c #222222",
">+ c #F2F2F2",
",+ c #555555",
"'+ c #C4C4C4",
")+ c #EBEBEB",
"!+ c #727272",
"~+ c #585858",
"{+ c #0D0D0D",
"]+ c #B1B1B1",
"^+ c #E5E5E5",
"/+ c #C0C0C0",
"(+ c #8F8F8F",
"_+ c #4D4D4D",
":+ c #F4F4F4",
"<+ c #7D7D7D",
"[+ c #E4E4E4",
"}+ c #F3F3F3",
"|+ c #383838",
"1+ c #A9A9A9",
"2+ c #D6D6D6",
"3+ c #D5D5D5",
"4+ c #5F5F5F",
"5+ c #C6C6C6",
"6+ c #E2E2E2",
"7+ c #FBFBFB",
"8+ c #404040",
"9+ c #909090",
"0+ c #EEEEEE",
"a+ c #878787",
"b+ c #E8E8E8",
"c+ c #494949",
"d+ c #424242",
"e+ c #E6E6E6",
"f+ c #CFCFCF",
"g+ c #DCDCDC",
"h+ c #161616",
"i+ c #BBBBBB",
"j+ c #CCCCCC",
"k+ c #B0B0B0",
"l+ c #C7C7C7",
"m+ c #858585",
"n+ c #F8F8F8",
"o+ c #D7D7D7",
"p+ c #BDBDBD",
"q+ c #ECECEC",
"r+ c #939393",
"s+ c #A1A1A1",
"t+ c #7A7A7A",
"u+ c #4B4B4B",
"v+ c #E9E9E9",
"w+ c #717171",
"x+ c #AFAFAF",
"y+ c #454545",
"z+ c #F9F9F9",
"A+ c #DBDBDB",
"B+ c #C1C1C1",
"C+ c #707070",
"D+ c #323232",
"E+ c #9D9D9D",
"F+ c #D1D1D1",
"G+ c #6D6D6D",
"H+ c #262626",
"I+ c #6E6E6E",
"J+ c #808080",
"K+ c #BFBFBF",
"L+ c #999999",
"M+ c #F1F1F1",
"N+ c #DADADA",
"O+ c #9F9F9F",
"P+ c #8B8B8B",
"Q+ c #7F7F7F",
"R+ c #9E9E9E",
"S+ c #F0F0F0",
"T+ c #A4A4A4",
"U+ c #A5A5A5",
"V+ c #CDCDCD",
"W+ c #CBCBCB",
"X+ c #9B9B9B",
"Y+ c #D9D9D9",
"Z+ c #A0A0A0",
"`+ c #9C9C9C",
" @ c #C2C2C2",
".@ c #636363",
"+@ c #D0D0D0",
"@@ c #6A6A6A",
"#@ c #898989",
"$@ c #C3C3C3",
"%@ c #A7A7A7",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @ # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . $ % @ & . . . . . * @ + . . . . + @ # . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * @ + . . . . . . . . . . . . . ",
". . . . . . . . . . . . . ; @ > , . . . . . * @ + . . . . + @ # . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * @ + . . . . . . . . . . . . . ",
". . . . . . . . . . . . . ' ) ! ~ { . . . . * @ + . . . . + @ # . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * @ + . . . . . . . . . . . . . ",
". . . . . . . . . . . . ] @ ^ / @ ( . . . _ @ @ @ @ @ : . + @ # . . < [ } | 1 2 3 . . . . 4 5 ) 6 | 7 8 . . . . . . . . = @ - . . 9 @ 0 a b > c d . e , f | g . . . . 9 @ 0 a h % i & . . . . j k l m n o j . . . 9 @ 0 p q m r @ @ @ @ @ : . . . . . . . . . . ",
". . . . . . . . . . . . k s t . u v < . . _ @ @ @ @ @ : . + @ # . . w @ @ @ @ @ @ 5 . . . k @ @ @ @ @ % . . . . . . . . = @ - . . 9 @ x @ @ @ @ y d z @ @ @ @ * . . . 9 @ A @ @ @ @ @ B . . C D @ @ @ @ @ h C . . 9 @ x @ @ @ E @ @ @ @ @ : . . . . . . . . . . ",
". . . . . . . . . . . F G 7 . . H @ I . . . * @ + . . . . + @ # . . ] J 8 j K 0 h 6 K . . l l = F j L M . . . . . . . . = @ - . . 9 @ % N j O J @ P Q R S & T U . . . 9 @ s ^ O j V W X F . Y @ Z ` S w .@ ... . 9 @ s +.t . . * @ + . . . . . . . . . . . . . ",
". . . . . . . . . . . @.@ #.. . K 6 x . . . * @ + . . . . + @ # . . . . . . . . # @ $.. . ' M . . . . . . . . . . . . . = @ - . . 9 @ %.. . . &.@ *.4 . . . =.r . . . 9 @ -.. . . . ;.@ 0 . q 6 t . . . t f h . . 9 @ >.. . . . * @ + . . . . . . . . . . . . . ",
". . . . . . . . . . . ,.'.).. . . !.~.j . . * @ + . . . . + @ # . . . {.].P ~ @ @ @ 9 . . 8 r ^.- /.j . . . . . . . . . = @ - . . 9 @ + . . . . @ A . . . . !.~ . . . 9 @ (.. . . . # @ N . 1 _.. . . . . c s . . 9 @ (.. . . . * @ + . . . . . . . . . . . . . ",
". . . . . . . . . . { ~ @ @ @ @ @ @ @ :.. . * @ + . . . . + @ # . . ^ @ @ @ @ @ @ @ H . . . F <._ [.> }.. . . . . . . . = @ - . . 9 @ 0 . . . . @ |.. . . . : @ . . . 9 @ (.. . . . # @ N . 1 u . . . . . c s . . 9 @ 0 . . . . * @ + . . . . . . . . . . . . . ",
". . . . . . . . . . 1.@ @ @ @ @ @ @ @ ^.. . #.@ # . . . . + @ # . . 2.r $.$ < . [ @ H . . . . . . . + @ * . . . . . . . = @ - . . 9 @ 0 . . . . @ |.. . . . : @ . . . 9 @ -.. . . . ;.@ 0 . q 6 t . . . O f h . . 9 @ 0 . . . . #.@ # . . . . . . . . . . . . . ",
". . . . . . . . . < 3.4.K . . . . . 5.@ w . 6.@ ;.F . . . + @ # . . 2.n ` 4 $ + *.@ H . 4 7.@.8.4 9.k @ ^ . . . . . . . = @ - . . 9 @ 0 . . . . @ |.. . . . : @ . . . 9 @ s ^ O j V W X F . %.@ u w F ] u @ - . . 9 @ 0 . . . . 6.@ ;.F . . . . . . . . . . . . ",
". . . . . . . . . L @ 0.. . . . . . L @ o . K > @ @ @ : . + @ # . . a.@ @ @ @ @ b.@ H . F @ @ @ @ @ @ > / . . . . . . . = @ - . . 9 @ 0 . . . . @ |.. . . . : @ . . . 9 @ A @ @ @ @ @ B . . C D @ @ @ @ @ h $ . . 9 @ 0 . . . . K > @ @ @ : . . . . . . . . . . ",
". . . . . . . . . A @ ` . . . . . . < *.c.F . # ^.~.@ : . + @ # . . 4 _ *.% q N d.@ H . . e.: h % l b.e . . . . . . . . = @ - . . 9 @ 0 . . . . @ |.. . . . : @ . . . 9 @ 0 f.g.~.i /.. . . . j h.n W i.>.O . . . 9 @ 0 . . . . . # ^.~.@ : . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 @ 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 @ 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 @ 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 @ 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @ # . . + @ # . . . . . . . . . . . . . . . . . . . . j.k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ @ @ @ @ @ @ # . . . . . . . . . . + @ # . . + @ # . . . . . . . . . . . . . . . . . . . . j.k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ @ @ @ @ @ @ # . . . . . . . . . . . . . . . + @ # . . . . . . . . . . . . . . . . . . . . j.k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . . . . . . . . . . . . . . . . . + @ # . . . . . . . . . . . . . . . . . . . . j.k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . < [ } | 1 2 3 . . . . + @ # . . + @ # . . . 4 l.m.% G 5.n.. . . . &.Q z c.x O j.k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . w @ @ @ @ @ @ 5 . . . + @ # . . + @ # . . ).o.@ @ @ @ @ c./ . . $ v @ @ @ @ p.2.k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ @ @ @ @ @ U ] J 8 j K 0 h 6 K . . + @ # . . + @ # . . q.@ } w F O q.s r.. . a.@ s.d S 8 ) @ k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ @ @ @ @ @ U . . . . . . # @ $.. . + @ # . . + @ # . . t.| ).. . . . !.> < . q G C . . . d @ k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . . {.].P ~ @ @ @ 9 . . + @ # . . + @ # . . > @ @ @ @ @ @ @ @ O . % u.. . . . . y k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . ^ @ @ @ @ @ @ @ H . . + @ # . . + @ # . . 1 @ @ @ @ @ @ @ @ v.. % u.. . . . . r k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . 2.r $.$ < . [ @ H . . + @ # . . + @ # . . ^.h < . . . . . . . . q G C . . . d @ k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . 2.n ` 4 $ + *.@ H . . + @ # . . + @ # . . +.@ w.e.C S d x.y.. . a.@ s.z.S 8 ) @ k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . a.@ @ @ @ @ b.@ H . . + @ # . . + @ # . . ).M @ @ @ @ @ @ s.. . $ v @ @ @ @ ^.2.k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = @ - . . . . . 4 _ *.% q N d.@ H . . + @ # . . + @ # . . . ).f.k.6 z ' Y v.. . . &.A A.z A O j.k.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.B.C.D.B.C.D.. . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E.C.C.C.C.F.. B.C.D.B.C.D.B.C.D.. . . . C.G.. . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E.C.H.. . . . . . . B.C.D.B.C.D.. . . . C.G.. . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E.C.H.. . . . B.C.D.B.C.D.B.C.D.. . . I.C.C.C.J.B.C.C.C.K.L.M.. N.O.P.Q.R.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E.C.C.C.C.H.. B.C.D.B.C.D.B.C.D.. . . . C.G.. . B.C.S.T.U.C.V.W.C.X.Y.Z.`.E.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E.C.H.. . . . B.C.D.B.C.D.B.C.D.. . . . C.G.. . B.C. +. .+C.++@+C.C.C.C.C.R.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E.C.H.. . . . B.C.D.B.C.D.B.C.D.. . . . #+Q.$+. B.C.D.. .+C.++W.C.%+&+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E.C.H.. . . . B.C.D.B.C.D.B.C.D.. . . . *+`.C.=+B.C.D.. .+C.++. N.-+;+C.C.Y.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . B.C.D.B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y.C.>+,+R.. . '+C.C.)+. . . C.G.. . B.C.D.. . . . . . . . . . . . . . . . E.C.C.C.C.F.. B.C.D.B.C.D.. . . . . . . Y.C.>+,+R.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y.C.>+,+R.. . !+~+{+]+. . . C.G.. . B.C.D.. . . . . . . . . . . . . . . . E.C.H.. . . . . . . B.C.D.. . . . . . . Y.C.>+,+R.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y.C.>+,+R.. ^+C./+(+_+&+. I.C.C.C.J.B.C.D.:+C.C.P.<+[+. }+G.|+C.C.>+. . . E.C.H.. . . . B.C.D.B.C.D.. N.O.P.Q.R.. Y.C.>+,+R.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1+;+T.2+C.3+. . C.G.. . B.C.D.. . . T.4+Q.. 5+C.X.6+Y.. . . . E.C.C.C.C.H.. B.C.D.B.C.D.W.C.X.Y.Z.`.E.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7+8+C.C.C.C.9+. . C.G.. . B.C.D.0+a+8+C.C.|+. b+c+C.C.d+e+. . . E.C.H.. . . . B.C.D.B.C.D.@+C.C.C.C.C.R.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . f+C.g+. . J.h+>+. #+Q.$+. B.C.D.i+C.j+0+,+#+. . &+e+k+C.l+. . . E.C.H.. . . . B.C.D.B.C.D.W.C.%+&+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m+h+n+. . o+C.p+. *+`.C.=+B.C.D.q+!+{+C.C.#+. =+C.C.8+r+E.. . . E.C.H.. . . . B.C.D.B.C.D.. N.-+;+C.C.Y.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . V.4+C.s+C.U.. . . . . . . B.C.D.. . . . N.C.W.. . . B.C.D.. . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . t+u+Y.v+C.U.. . . . . . . B.C.D.. . . . N.C.W.. . . B.C.D.. . . . . . . . . . . C.G.. . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u+w+. . . . . . . . . . . B.C.D.. . . . N.C.W.. . . . . . . . . . . . . . . . . C.G.. . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . H.C.C.C.C.C.U.. N.O.P.Q.R.. B.C.D.. x+d+C.C.C.W.. . . B.C.D.B.C.C.C.K.L.M.. . . I.C.C.C.J.B.C.C.C.K.L.M.. N.O.P.Q.R.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . y+!+. v+C.U.W.C.X.Y.Z.`.E.B.C.D.2+C.x+z+(+C.W.. . . B.C.D.B.C.S.T.U.C.V.. . . . C.G.. . B.C.S.T.U.C.V.W.C.X.Y.Z.`.E.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . y+!+. v+C.U.@+C.C.C.C.C.R.B.C.D.%+C.A+. B+C.W.. . . B.C.D.B.C. +. .+C.++. . . . C.G.. . B.C. +. .+C.++@+C.C.C.C.C.R.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . y+!+. v+C.U.W.C.%+&+. . . B.C.D.2+C.k+z+9+C.W.. . . B.C.D.B.C.D.. .+C.++. . . . #+Q.$+. B.C.D.. .+C.++W.C.%+&+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . y+!+. v+C.U.. N.-+;+C.C.Y.B.C.D.. x+d+C.C.C.W.. . . B.C.D.B.C.D.. .+C.++. . . . *+`.C.=+B.C.D.. .+C.++. N.-+;+C.C.Y.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . N.C.W.. . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . N.C.W.. . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.G.. . . . . . . . . N.C.W.. . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . N.C.W.. . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.G.. . . . . . . . . N.C.W.. . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . N.C.W.. . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . B.C.D.)+C.C.C.K.C+O.K.!+B.B.C.C.C.D+E+7+. '+O.P.C+F+. B.C.C.C.,+I.C.C.C.J.. . . . x+d+C.C.C.W.. '+O.P.C+F+. . .+G+H+C.R.B.C.D.>+I+I.q+. . . :+C.C.P.<+[+. B.C.C.C.K.L.M.. x+d+C.C.C.W.. . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . B.C.D.)+C.!+T.J+C.=+g+C.]+B.C.I+E.=+C.K+W.C.]+Y.L+h+b+B.C.O.M+. . C.G.. . . . . 2+C.x+z+(+C.W.W.C.]+Y.L+h+b+N+C.O+z+. . B.C.P+4+Q+T.. . . . . . . T.4+Q.. B.C.S.T.U.C.V.2+C.x+z+(+C.W.. . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . B.C.D.)+C. +. R+C.M+S+C.T+B.C.U+. M+C.E+@+C.V.. =+C.V+B.C. +. . . C.G.. . . . . %+C.A+. B+C.W.@+C.V.. =+C.V+@+C.A+. . . B.C.C.C.R.. . . . . 0+a+8+C.C.|+. B.C. +. .+C.++%+C.A+. B+C.W.. . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . B.C.D.)+C.D.. R+C.>+S+C.T+B.C.C+E.W+C.K+W.C.*+Y.X+{+b+B.C.D.. . . #+Q.$+. . . . 2+C.k+z+9+C.W.W.C.*+Y.X+{+b+Y+C.s+z+. . B.C.Z+m+|+V.. . . . i+C.j+0+,+#+. B.C.D.. .+C.++2+C.k+z+9+C.W.. . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . B.C.D.)+C.D.. R+C.>+S+C.T+B.C.C.C.D+`+7+. @.@D+G++@. B.C.D.. . . *+`.C.=+. . . . x+d+C.C.C.W.. @.@D+G++@. . l+@@H+C.R.B.C.D.Y.#@K.2+. . . q+!+{+C.C.#+. B.C.D.. .+C.++. x+d+C.C.C.W.. . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.G.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.G.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.C.C.,+. N.O.P.Q.R.. . . . . B.C.D.)+C.C.C.K.C+O.K.!+B.B.C.C.C.D+E+7+. '+O.P.C+F+. B.C.C.C.,+I.C.C.C.J.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.O.M+. W.C.X.Y.Z.`.E.$@C.C.%@B.C.D.)+C.!+T.J+C.=+g+C.]+B.C.I+E.=+C.K+W.C.]+Y.L+h+b+B.C.O.M+. . C.G.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C. +. . @+C.C.C.C.C.R.. . . . B.C.D.)+C. +. R+C.M+S+C.T+B.C.U+. M+C.E+@+C.V.. =+C.V+B.C. +. . . C.G.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . W.C.%+&+. . . . . . . B.C.D.)+C.D.. R+C.>+S+C.T+B.C.C+E.W+C.K+W.C.*+Y.X+{+b+B.C.D.. . . #+Q.$+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . . N.-+;+C.C.Y.. . . . B.C.D.)+C.D.. R+C.>+S+C.T+B.C.C.C.D+`+7+. @.@D+G++@. B.C.D.. . . *+`.C.=+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.C.D.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "};

View file

@ -0,0 +1,382 @@
#include "resource_importer_texture_atlas.h"
#include "atlas_import_failed.xpm"
#include "core/io/image_loader.h"
#include "core/io/resource_saver.h"
#include "core/os/file_access.h"
#include "editor/editor_atlas_packer.h"
#include "scene/resources/mesh.h"
#include "scene/resources/texture.h"
String ResourceImporterTextureAtlas::get_importer_name() const {
return "texture_atlas";
}
String ResourceImporterTextureAtlas::get_visible_name() const {
return "TextureAtlas";
}
void ResourceImporterTextureAtlas::get_recognized_extensions(List<String> *p_extensions) const {
ImageLoader::get_recognized_extensions(p_extensions);
}
String ResourceImporterTextureAtlas::get_save_extension() const {
return "res";
}
String ResourceImporterTextureAtlas::get_resource_type() const {
return "Texture";
}
bool ResourceImporterTextureAtlas::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
return true;
}
int ResourceImporterTextureAtlas::get_preset_count() const {
return 0;
}
String ResourceImporterTextureAtlas::get_preset_name(int p_idx) const {
return String();
}
void ResourceImporterTextureAtlas::get_import_options(List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "atlas_file", PROPERTY_HINT_SAVE_FILE, "*.png"), ""));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_mode", PROPERTY_HINT_ENUM, "Region,Mesh2D"), 0));
}
String ResourceImporterTextureAtlas::get_option_group_file() const {
return "atlas_file";
}
Error ResourceImporterTextureAtlas::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
/* If this happens, it's because the atlas_file field was not filled, so just import a broken texture */
//use an xpm because it's size independent, the editor images are vector and size dependent
//it's a simple hack
Ref<Image> broken = memnew(Image((const char **)atlas_import_failed_xpm));
Ref<ImageTexture> broken_texture;
broken_texture.instance();
broken_texture->create_from_image(broken);
String target_file = p_save_path + ".tex";
ResourceSaver::save(target_file, broken_texture);
return OK;
}
static void _plot_triangle(Vector2 *vertices, const Vector2 &p_offset, bool p_transposed, Ref<Image> p_image, const Ref<Image> &p_src_image) {
int width = p_image->get_width();
int height = p_image->get_height();
int src_width = p_src_image->get_width();
int src_height = p_src_image->get_height();
int x[3];
int y[3];
for (int j = 0; j < 3; j++) {
x[j] = vertices[j].x;
y[j] = vertices[j].y;
}
// sort the points vertically
if (y[1] > y[2]) {
SWAP(x[1], x[2]);
SWAP(y[1], y[2]);
}
if (y[0] > y[1]) {
SWAP(x[0], x[1]);
SWAP(y[0], y[1]);
}
if (y[1] > y[2]) {
SWAP(x[1], x[2]);
SWAP(y[1], y[2]);
}
double dx_far = double(x[2] - x[0]) / (y[2] - y[0] + 1);
double dx_upper = double(x[1] - x[0]) / (y[1] - y[0] + 1);
double dx_low = double(x[2] - x[1]) / (y[2] - y[1] + 1);
double xf = x[0];
double xt = x[0] + dx_upper; // if y[0] == y[1], special case
for (int yi = y[0]; yi <= (y[2] > height - 1 ? height - 1 : y[2]); yi++) {
if (yi >= 0) {
for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < width ? xt : width - 1); xi++) {
int px = xi, py = yi;
int sx = px, sy = py;
sx = CLAMP(sx, 0, src_width);
sy = CLAMP(sy, 0, src_height);
Color color = p_src_image->get_pixel(sx, sy);
if (p_transposed) {
SWAP(px, py);
}
px += p_offset.x;
py += p_offset.y;
//may have been cropped, so don't blit what is not visible?
if (px < 0 || px >= width) {
continue;
}
if (py < 0 || py >= height) {
continue;
}
p_image->set_pixel(px, py, color);
}
for (int xi = (xf < width ? int(xf) : width - 1); xi >= (xt > 0 ? xt : 0); xi--) {
int px = xi, py = yi;
int sx = px, sy = py;
sx = CLAMP(sx, 0, src_width);
sy = CLAMP(sy, 0, src_height);
Color color = p_src_image->get_pixel(sx, sy);
if (p_transposed) {
SWAP(px, py);
}
px += p_offset.x;
py += p_offset.y;
//may have been cropped, so don't blit what is not visible?
if (px < 0 || px >= width) {
continue;
}
if (py < 0 || py >= height) {
continue;
}
p_image->set_pixel(px, py, color);
}
}
xf += dx_far;
if (yi < y[1])
xt += dx_upper;
else
xt += dx_low;
}
}
Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file, const Map<String, Map<StringName, Variant> > &p_source_file_options, const Map<String, String> &p_base_paths) {
ERR_FAIL_COND_V(p_source_file_options.size() == 0, ERR_BUG); //should never happen
Vector<EditorAtlasPacker::Chart> charts;
Vector<PackData> pack_data_files;
pack_data_files.resize(p_source_file_options.size());
int idx = 0;
for (const Map<String, Map<StringName, Variant> >::Element *E = p_source_file_options.front(); E; E = E->next(), idx++) {
PackData &pack_data = pack_data_files.write[idx];
String source = E->key();
const Map<StringName, Variant> &options = E->get();
Ref<Image> image;
image.instance();
Error err = ImageLoader::load_image(source, image);
ERR_CONTINUE(err != OK);
pack_data.image = image;
int mode = options["import_mode"];
if (mode == IMPORT_MODE_REGION) {
pack_data.is_mesh = false;
EditorAtlasPacker::Chart chart;
//clip a region from the image
Rect2 used_rect = image->get_used_rect();
pack_data.region = used_rect;
chart.vertices.push_back(used_rect.position);
chart.vertices.push_back(used_rect.position + Vector2(used_rect.size.x, 0));
chart.vertices.push_back(used_rect.position + Vector2(used_rect.size.x, used_rect.size.y));
chart.vertices.push_back(used_rect.position + Vector2(0, used_rect.size.y));
EditorAtlasPacker::Chart::Face f;
f.vertex[0] = 0;
f.vertex[1] = 1;
f.vertex[2] = 2;
chart.faces.push_back(f);
f.vertex[0] = 0;
f.vertex[1] = 2;
f.vertex[2] = 3;
chart.faces.push_back(f);
chart.can_transpose = false;
pack_data.chart_vertices.push_back(chart.vertices);
pack_data.chart_pieces.push_back(charts.size());
charts.push_back(chart);
} else {
pack_data.is_mesh = true;
Ref<BitMap> bit_map;
bit_map.instance();
bit_map->create_from_image_alpha(image);
Vector<Vector<Vector2> > polygons = bit_map->clip_opaque_to_polygons(Rect2(0, 0, image->get_width(), image->get_height()));
for (int j = 0; j < polygons.size(); j++) {
EditorAtlasPacker::Chart chart;
chart.vertices = polygons[j];
chart.can_transpose = true;
Vector<int> poly = Geometry::triangulate_polygon(polygons[j]);
for (int i = 0; i < poly.size(); i += 3) {
EditorAtlasPacker::Chart::Face f;
f.vertex[0] = poly[i + 0];
f.vertex[1] = poly[i + 1];
f.vertex[2] = poly[i + 2];
chart.faces.push_back(f);
}
pack_data.chart_pieces.push_back(charts.size());
charts.push_back(chart);
pack_data.chart_vertices.push_back(polygons[j]);
}
}
}
//pack the charts
int atlas_width, atlas_height;
EditorAtlasPacker::chart_pack(charts, atlas_width, atlas_height);
//blit the atlas
Ref<Image> new_atlas;
new_atlas.instance();
new_atlas->create(atlas_width, atlas_height, false, Image::FORMAT_RGBA8);
new_atlas->lock();
for (int i = 0; i < pack_data_files.size(); i++) {
PackData &pack_data = pack_data_files.write[i];
pack_data.image->lock();
for (int j = 0; j < pack_data.chart_pieces.size(); j++) {
const EditorAtlasPacker::Chart &chart = charts[pack_data.chart_pieces[j]];
for (int k = 0; k < chart.faces.size(); k++) {
Vector2 positions[3];
for (int l = 0; l < 3; l++) {
int vertex_idx = chart.faces[k].vertex[l];
positions[l] = chart.vertices[vertex_idx];
}
_plot_triangle(positions, chart.final_offset, chart.transposed, new_atlas, pack_data.image);
}
}
pack_data.image->unlock();
}
new_atlas->unlock();
//save the atlas
new_atlas->save_png(p_group_file);
//update cache if existing, else create
Ref<Texture> cache;
if (ResourceCache::has(p_group_file)) {
Resource *resptr = ResourceCache::get(p_group_file);
cache.reference_ptr(resptr);
} else {
Ref<ImageTexture> res_cache;
res_cache.instance();
res_cache->create_from_image(new_atlas);
res_cache->set_path(p_group_file);
cache = res_cache;
}
//save the images
idx = 0;
for (const Map<String, Map<StringName, Variant> >::Element *E = p_source_file_options.front(); E; E = E->next(), idx++) {
PackData &pack_data = pack_data_files.write[idx];
Ref<Texture> texture;
if (!pack_data.is_mesh) {
Vector2 offset = charts[pack_data.chart_pieces[0]].vertices[0] + charts[pack_data.chart_pieces[0]].final_offset;
//region
Ref<AtlasTexture> atlas_texture;
atlas_texture.instance();
atlas_texture->set_atlas(cache);
atlas_texture->set_region(Rect2(offset, pack_data.region.size));
atlas_texture->set_margin(Rect2(pack_data.region.position, Size2(pack_data.image->get_width(), pack_data.image->get_height()) - pack_data.region.size));
texture = atlas_texture;
} else {
Ref<ArrayMesh> mesh;
mesh.instance();
for (int i = 0; i < pack_data.chart_pieces.size(); i++) {
const EditorAtlasPacker::Chart &chart = charts[pack_data.chart_pieces[i]];
PoolVector<Vector2> vertices;
PoolVector<int> indices;
PoolVector<Vector2> uvs;
int vc = chart.vertices.size();
int fc = chart.faces.size();
vertices.resize(vc);
uvs.resize(vc);
indices.resize(fc * 3);
{
PoolVector<Vector2>::Write vw = vertices.write();
PoolVector<int>::Write iw = indices.write();
PoolVector<Vector2>::Write uvw = uvs.write();
for (int j = 0; j < vc; j++) {
vw[j] = chart.vertices[j];
Vector2 uv = chart.vertices[j];
if (chart.transposed) {
SWAP(uv.x, uv.y);
}
uv += chart.final_offset;
uv /= new_atlas->get_size(); //normalize uv to 0-1 range
uvw[j] = uv;
}
for (int j = 0; j < fc; j++) {
iw[j * 3 + 0] = chart.faces[j].vertex[0];
iw[j * 3 + 1] = chart.faces[j].vertex[1];
iw[j * 3 + 2] = chart.faces[j].vertex[2];
}
}
Array arrays;
arrays.resize(Mesh::ARRAY_MAX);
arrays[Mesh::ARRAY_VERTEX] = vertices;
arrays[Mesh::ARRAY_TEX_UV] = uvs;
arrays[Mesh::ARRAY_INDEX] = indices;
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arrays);
}
Ref<MeshTexture> mesh_texture;
mesh_texture.instance();
mesh_texture->set_base_texture(cache);
mesh_texture->set_image_size(pack_data.image->get_size());
mesh_texture->set_mesh(mesh);
texture = mesh_texture;
//mesh
}
String save_path = p_base_paths[E->key()] + ".res";
ResourceSaver::save(save_path, texture);
}
return OK;
}
ResourceImporterTextureAtlas::ResourceImporterTextureAtlas() {
}

View file

@ -0,0 +1,42 @@
#ifndef RESOURCE_IMPORTER_TEXTURE_ATLAS_H
#define RESOURCE_IMPORTER_TEXTURE_ATLAS_H
#include "core/image.h"
#include "core/io/resource_importer.h"
class ResourceImporterTextureAtlas : public ResourceImporter {
GDCLASS(ResourceImporterTextureAtlas, ResourceImporter)
struct PackData {
Rect2 region;
bool is_mesh;
Vector<int> chart_pieces; //one for region, many for mesh
Vector<Vector<Vector2> > chart_vertices; //for mesh
Ref<Image> image;
};
public:
enum ImportMode {
IMPORT_MODE_REGION,
IMPORT_MODE_2D_MESH
};
virtual String get_importer_name() const;
virtual String get_visible_name() const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual String get_save_extension() const;
virtual String get_resource_type() const;
virtual int get_preset_count() const;
virtual String get_preset_name(int p_idx) const;
virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const;
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual String get_option_group_file() const;
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = NULL, Variant *r_metadata = NULL);
virtual Error import_group_file(const String &p_group_file, const Map<String, Map<StringName, Variant> > &p_source_file_options, const Map<String, String> &p_base_paths);
ResourceImporterTextureAtlas();
};
#endif // RESOURCE_IMPORTER_TEXTURE_ATLAS_H

View file

@ -438,6 +438,8 @@ void ImportDock::_reimport() {
Error err = config->load(params->paths[i] + ".import");
ERR_CONTINUE(err != OK);
String importer_name = params->importer->get_importer_name();
if (params->checking) {
//update only what edited (checkboxes)
for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
@ -447,7 +449,7 @@ void ImportDock::_reimport() {
}
} else {
//override entirely
config->set_value("remap", "importer", params->importer->get_importer_name());
config->set_value("remap", "importer", importer_name);
config->erase_section("params");
for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
@ -455,6 +457,19 @@ void ImportDock::_reimport() {
}
}
//handle group file
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
ERR_CONTINUE(!importer.is_valid());
String group_file_property = importer->get_option_group_file();
if (group_file_property != String()) {
//can import from a group (as in, atlas)
ERR_CONTINUE(!params->values.has(group_file_property));
String group_file = params->values[group_file_property];
config->set_value("remap", "group_file", group_file);
} else {
config->set_value("remap", "group_file", Variant()); //clear group file if unused
}
config->save(params->paths[i] + ".import");
}

View file

@ -891,13 +891,13 @@ void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Colo
VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, colors, p_uvs, rid, rid_normal, p_antialiased);
}
void CanvasItem::draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map) {
void CanvasItem::draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map, const Transform2D &p_transform, const Color &p_modulate) {
ERR_FAIL_COND(p_mesh.is_null());
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
RID normal_map_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
VisualServer::get_singleton()->canvas_item_add_mesh(canvas_item, p_mesh->get_rid(), texture_rid, normal_map_rid);
VisualServer::get_singleton()->canvas_item_add_mesh(canvas_item, p_mesh->get_rid(), p_transform, p_modulate, texture_rid, normal_map_rid);
}
void CanvasItem::draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map) {
@ -1168,7 +1168,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture", "normal_map", "antialiased"), &CanvasItem::draw_colored_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_string", "font", "position", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("draw_char", "font", "position", "char", "next", "modulate"), &CanvasItem::draw_char, DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture>()));
ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map", "transform", "modulate"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture>()), DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture", "normal_map"), &CanvasItem::draw_multimesh, DEFVAL(Ref<Texture>()));
ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform);

View file

@ -317,7 +317,7 @@ public:
void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_antialiased = false);
void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_antialiased = false);
void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map);
void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1));
void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map);
void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate = Color(1, 1, 1), int p_clip_w = -1);

View file

@ -635,6 +635,7 @@ void register_scene_types() {
ClassDB::register_class<StreamTexture>();
ClassDB::register_class<ImageTexture>();
ClassDB::register_class<AtlasTexture>();
ClassDB::register_class<MeshTexture>();
ClassDB::register_class<LargeTexture>();
ClassDB::register_class<CurveTexture>();
ClassDB::register_class<GradientTexture>();

View file

@ -595,6 +595,64 @@ Array BitMap::_opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) con
return result_array;
}
void BitMap::resize(const Size2& p_new_size) {
Ref<BitMap> new_bitmap;
new_bitmap.instance();
new_bitmap->create(p_new_size);
int lw = MIN(width,p_new_size.width);
int lh = MIN(height,p_new_size.height);
for(int x=0;x<lw;x++) {
for(int y=0;y<lh;y++) {
new_bitmap->set_bit(Vector2(x,y),get_bit(Vector2(x,y)));
}
}
width = new_bitmap->width;
height = new_bitmap->height;
bitmask = new_bitmap->bitmask;
}
Ref<Image> BitMap::convert_to_image() const {
Ref<Image> image;
image.instance();
image->create(width,height,false,Image::FORMAT_L8);
image->lock();
for(int i=0;i<width;i++) {
for(int j=0;j<height;j++) {
image->set_pixel( i,j,get_bit(Point2(i,j)) ? Color(1,1,1) : Color(0,0,0));
}
}
image->unlock();
return image;
}
void BitMap::blit(const Vector2& p_pos,const Ref<BitMap>& p_bitmap) {
int x = p_pos.x;
int y = p_pos.y;
int w = p_bitmap->get_size().width;
int h = p_bitmap->get_size().height;
for(int i=0;i<w;i++) {
for (int j=0;j<h;j++) {
int px = x+i;
int py = y+j;
if (px<0 || px>=width)
continue;
if (py<0 || py>=height)
continue;
if (p_bitmap->get_bit(Vector2(i,j))) {
set_bit(Vector2(x,y),true);
}
}
}
}
void BitMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create);

View file

@ -64,9 +64,13 @@ public:
int get_true_bit_count() const;
Size2 get_size() const;
void resize(const Size2& p_new_size);
void grow_mask(int p_pixels, const Rect2 &p_rect);
void blit(const Vector2& p_pos,const Ref<BitMap>& p_bitmap);
Ref<Image> convert_to_image() const;
Vector<Vector<Vector2> > clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon = 2.0) const;
BitMap();

View file

@ -34,6 +34,7 @@
#include "core/io/image_loader.h"
#include "core/method_bind_ext.gen.inc"
#include "core/os/os.h"
#include "mesh.h"
#include "scene/resources/bit_map.h"
Size2 Texture::get_size() const {
@ -1133,6 +1134,138 @@ AtlasTexture::AtlasTexture() {
filter_clip = false;
}
/////////////////////////////////////////
int MeshTexture::get_width() const {
return size.width;
}
int MeshTexture::get_height() const {
return size.height;
}
RID MeshTexture::get_rid() const {
return RID();
}
bool MeshTexture::has_alpha() const {
return false;
}
void MeshTexture::set_flags(uint32_t p_flags) {
}
uint32_t MeshTexture::get_flags() const {
return 0;
}
void MeshTexture::set_mesh(const Ref<Mesh> &p_mesh) {
mesh = p_mesh;
}
Ref<Mesh> MeshTexture::get_mesh() const {
return mesh;
}
void MeshTexture::set_image_size(const Size2 &p_size) {
size = p_size;
}
Size2 MeshTexture::get_image_size() const {
return size;
}
void MeshTexture::set_base_texture(const Ref<Texture> &p_texture) {
base_texture = p_texture;
}
Ref<Texture> MeshTexture::get_base_texture() const {
return base_texture;
}
void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const {
if (mesh.is_null() || base_texture.is_null()) {
return;
}
Transform2D xform;
xform.set_origin(p_pos);
if (p_transpose) {
SWAP(xform.elements[0][1], xform.elements[1][0]);
SWAP(xform.elements[0][0], xform.elements[1][1]);
}
RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid);
}
void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const {
if (mesh.is_null() || base_texture.is_null()) {
return;
}
Transform2D xform;
Vector2 origin = p_rect.position;
if (p_rect.size.x < 0) {
origin.x += size.x;
}
if (p_rect.size.y < 0) {
origin.y += size.y;
}
xform.set_origin(origin);
xform.set_scale(p_rect.size / size);
if (p_transpose) {
SWAP(xform.elements[0][1], xform.elements[1][0]);
SWAP(xform.elements[0][0], xform.elements[1][1]);
}
RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid);
}
void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const {
if (mesh.is_null() || base_texture.is_null()) {
return;
}
Transform2D xform;
Vector2 origin = p_rect.position;
if (p_rect.size.x < 0) {
origin.x += size.x;
}
if (p_rect.size.y < 0) {
origin.y += size.y;
}
xform.set_origin(origin);
xform.set_scale(p_rect.size / size);
if (p_transpose) {
SWAP(xform.elements[0][1], xform.elements[1][0]);
SWAP(xform.elements[0][0], xform.elements[1][1]);
}
RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid);
}
bool MeshTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const {
r_rect = p_rect;
r_src_rect = p_src_rect;
return true;
}
bool MeshTexture::is_pixel_opaque(int p_x, int p_y) const {
return true;
}
void MeshTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MeshTexture::set_mesh);
ClassDB::bind_method(D_METHOD("get_mesh"), &MeshTexture::get_mesh);
ClassDB::bind_method(D_METHOD("set_image_size", "size"), &MeshTexture::set_image_size);
ClassDB::bind_method(D_METHOD("get_image_size"), &MeshTexture::get_image_size);
ClassDB::bind_method(D_METHOD("set_base_texture", "texture"), &MeshTexture::set_base_texture);
ClassDB::bind_method(D_METHOD("get_base_texture"), &MeshTexture::get_base_texture);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_base_texture", "get_base_texture");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "image_size", PROPERTY_HINT_RANGE, "0,16384,1"), "set_image_size", "get_image_size");
}
MeshTexture::MeshTexture() {
}
//////////////////////////////////////////
int LargeTexture::get_width() const {

View file

@ -293,6 +293,49 @@ public:
AtlasTexture();
};
class Mesh;
class MeshTexture : public Texture {
GDCLASS(MeshTexture, Texture);
RES_BASE_EXTENSION("meshtex");
Ref<Texture> base_texture;
Ref<Mesh> mesh;
Size2i size;
protected:
static void _bind_methods();
public:
virtual int get_width() const;
virtual int get_height() const;
virtual RID get_rid() const;
virtual bool has_alpha() const;
virtual void set_flags(uint32_t p_flags);
virtual uint32_t get_flags() const;
void set_mesh(const Ref<Mesh> &p_mesh);
Ref<Mesh> get_mesh() const;
void set_image_size(const Size2 &p_size);
Size2 get_image_size() const;
void set_base_texture(const Ref<Texture> &p_texture);
Ref<Texture> get_base_texture() const;
virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const;
virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const;
virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const;
virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const;
bool is_pixel_opaque(int p_x, int p_y) const;
MeshTexture();
};
class LargeTexture : public Texture {
GDCLASS(LargeTexture, Texture);

View file

@ -789,6 +789,8 @@ public:
RID mesh;
RID texture;
RID normal_map;
Transform2D transform;
Color modulate;
CommandMesh() { type = TYPE_MESH; }
};

View file

@ -829,7 +829,7 @@ void VisualServerCanvas::canvas_item_add_set_transform(RID p_item, const Transfo
canvas_item->commands.push_back(tr);
}
void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture, RID p_normal_map) {
void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture, RID p_normal_map) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@ -839,6 +839,8 @@ void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID
m->mesh = p_mesh;
m->texture = p_texture;
m->normal_map = p_normal_map;
m->transform = p_transform;
m->modulate = p_modulate;
canvas_item->commands.push_back(m);
}

View file

@ -197,7 +197,7 @@ public:
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID());
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false);
void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID());
void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal);
void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);

View file

@ -600,7 +600,7 @@ public:
BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
BIND7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)
BIND10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID)
BIND4(canvas_item_add_mesh, RID, const RID &, RID, RID)
BIND6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID)
BIND4(canvas_item_add_multimesh, RID, RID, RID, RID)
BIND4(canvas_item_add_particles, RID, RID, RID, RID)
BIND2(canvas_item_add_set_transform, RID, const Transform2D &)

View file

@ -518,7 +518,7 @@ public:
FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)
FUNC10(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID)
FUNC4(canvas_item_add_mesh, RID, const RID &, RID, RID)
FUNC6(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID)
FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID)
FUNC4(canvas_item_add_particles, RID, RID, RID, RID)
FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)

View file

@ -898,7 +898,7 @@ public:
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false) = 0;
virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map) = 0;
virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0;