diff options
Diffstat (limited to 'editor/import')
22 files changed, 3461 insertions, 232 deletions
diff --git a/editor/import/SCsub b/editor/import/SCsub index 2b1e889fb0..359d04e5df 100644 --- a/editor/import/SCsub +++ b/editor/import/SCsub @@ -1,5 +1,5 @@ #!/usr/bin/env python -Import('env') +Import("env") env.add_source_files(env.editor_sources, "*.cpp") diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp new file mode 100644 index 0000000000..9e49fa9066 --- /dev/null +++ b/editor/import/collada.cpp @@ -0,0 +1,2582 @@ +/*************************************************************************/ +/* collada.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "collada.h" + +#include <stdio.h> + +//#define DEBUG_DEFAULT_ANIMATION +//#define DEBUG_COLLADA +#ifdef DEBUG_COLLADA +#define COLLADA_PRINT(m_what) print_line(m_what) +#else +#define COLLADA_PRINT(m_what) +#endif + +#define COLLADA_IMPORT_SCALE_SCENE + +/* HELPERS */ + +String Collada::Effect::get_texture_path(const String &p_source, Collada &state) const { + + const String &image = p_source; + ERR_FAIL_COND_V(!state.state.image_map.has(image), ""); + return state.state.image_map[image].path; +} + +Transform Collada::get_root_transform() const { + + Transform unit_scale_transform; +#ifndef COLLADA_IMPORT_SCALE_SCENE + unit_scale_transform.scale(Vector3(state.unit_scale, state.unit_scale, state.unit_scale)); +#endif + return unit_scale_transform; +} + +void Collada::Vertex::fix_unit_scale(Collada &state) { +#ifdef COLLADA_IMPORT_SCALE_SCENE + vertex *= state.state.unit_scale; +#endif +} + +static String _uri_to_id(const String &p_uri) { + + if (p_uri.begins_with("#")) + return p_uri.substr(1, p_uri.size() - 1); + else + return p_uri; +} + +/** HELPER FUNCTIONS **/ + +Transform Collada::fix_transform(const Transform &p_transform) { + + Transform tr = p_transform; + +#ifndef NO_UP_AXIS_SWAP + + if (state.up_axis != Vector3::AXIS_Y) { + + for (int i = 0; i < 3; i++) + SWAP(tr.basis[1][i], tr.basis[state.up_axis][i]); + for (int i = 0; i < 3; i++) + SWAP(tr.basis[i][1], tr.basis[i][state.up_axis]); + + SWAP(tr.origin[1], tr.origin[state.up_axis]); + + tr.basis[state.up_axis][0] = -tr.basis[state.up_axis][0]; + tr.basis[state.up_axis][1] = -tr.basis[state.up_axis][1]; + tr.basis[0][state.up_axis] = -tr.basis[0][state.up_axis]; + tr.basis[1][state.up_axis] = -tr.basis[1][state.up_axis]; + tr.origin[state.up_axis] = -tr.origin[state.up_axis]; + } +#endif + + //tr.scale(Vector3(state.unit_scale.unit_scale.unit_scale)); + return tr; + //return state.matrix_fix * p_transform; +} + +static Transform _read_transform_from_array(const Vector<float> &array, int ofs = 0) { + + Transform tr; + // i wonder why collada matrices are transposed, given that's opposed to opengl.. + tr.basis.elements[0][0] = array[0 + ofs]; + tr.basis.elements[0][1] = array[1 + ofs]; + tr.basis.elements[0][2] = array[2 + ofs]; + tr.basis.elements[1][0] = array[4 + ofs]; + tr.basis.elements[1][1] = array[5 + ofs]; + tr.basis.elements[1][2] = array[6 + ofs]; + tr.basis.elements[2][0] = array[8 + ofs]; + tr.basis.elements[2][1] = array[9 + ofs]; + tr.basis.elements[2][2] = array[10 + ofs]; + tr.origin.x = array[3 + ofs]; + tr.origin.y = array[7 + ofs]; + tr.origin.z = array[11 + ofs]; + return tr; +} + +/* STRUCTURES */ + +Transform Collada::Node::compute_transform(Collada &state) const { + + Transform xform; + + for (int i = 0; i < xform_list.size(); i++) { + + Transform xform_step; + const XForm &xf = xform_list[i]; + switch (xf.op) { + + case XForm::OP_ROTATE: { + if (xf.data.size() >= 4) { + + xform_step.rotate(Vector3(xf.data[0], xf.data[1], xf.data[2]), Math::deg2rad(xf.data[3])); + } + } break; + case XForm::OP_SCALE: { + + if (xf.data.size() >= 3) { + + xform_step.scale(Vector3(xf.data[0], xf.data[1], xf.data[2])); + } + + } break; + case XForm::OP_TRANSLATE: { + + if (xf.data.size() >= 3) { + + xform_step.origin = Vector3(xf.data[0], xf.data[1], xf.data[2]); + } + + } break; + case XForm::OP_MATRIX: { + + if (xf.data.size() >= 16) { + xform_step = _read_transform_from_array(xf.data, 0); + } + + } break; + default: { + } + } + + xform = xform * xform_step; + } + +#ifdef COLLADA_IMPORT_SCALE_SCENE + xform.origin *= state.state.unit_scale; +#endif + return xform; +} + +Transform Collada::Node::get_transform() const { + + return default_transform; +} + +Transform Collada::Node::get_global_transform() const { + + if (parent) + return parent->get_global_transform() * default_transform; + else + return default_transform; +} + +Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) const { + + ERR_FAIL_COND_V(keys.size() == 0, Vector<float>()); + int i = 0; + + for (i = 0; i < keys.size(); i++) { + + if (keys[i].time > p_time) + break; + } + + if (i == 0) + return keys[0].data; + if (i == keys.size()) + return keys[keys.size() - 1].data; + + switch (keys[i].interp_type) { + + case INTERP_BEZIER: //wait for bezier + case INTERP_LINEAR: { + + float c = (p_time - keys[i - 1].time) / (keys[i].time - keys[i - 1].time); + + if (keys[i].data.size() == 16) { + //interpolate a matrix + Transform src = _read_transform_from_array(keys[i - 1].data); + Transform dst = _read_transform_from_array(keys[i].data); + + Transform interp = c < 0.001 ? src : src.interpolate_with(dst, c); + + Vector<float> ret; + ret.resize(16); + Transform tr; + // i wonder why collada matrices are transposed, given that's opposed to opengl.. + ret.write[0] = interp.basis.elements[0][0]; + ret.write[1] = interp.basis.elements[0][1]; + ret.write[2] = interp.basis.elements[0][2]; + ret.write[4] = interp.basis.elements[1][0]; + ret.write[5] = interp.basis.elements[1][1]; + ret.write[6] = interp.basis.elements[1][2]; + ret.write[8] = interp.basis.elements[2][0]; + ret.write[9] = interp.basis.elements[2][1]; + ret.write[10] = interp.basis.elements[2][2]; + ret.write[3] = interp.origin.x; + ret.write[7] = interp.origin.y; + ret.write[11] = interp.origin.z; + ret.write[12] = 0; + ret.write[13] = 0; + ret.write[14] = 0; + ret.write[15] = 1; + + return ret; + } else { + + Vector<float> dest; + dest.resize(keys[i].data.size()); + for (int j = 0; j < dest.size(); j++) { + + dest.write[j] = keys[i].data[j] * c + keys[i - 1].data[j] * (1.0 - c); + } + return dest; + //interpolate one by one + } + } break; + } + + ERR_FAIL_V(Vector<float>()); +} + +void Collada::_parse_asset(XMLParser &parser) { + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String name = parser.get_node_name(); + + if (name == "up_axis") { + + parser.read(); + if (parser.get_node_data() == "X_UP") + state.up_axis = Vector3::AXIS_X; + if (parser.get_node_data() == "Y_UP") + state.up_axis = Vector3::AXIS_Y; + if (parser.get_node_data() == "Z_UP") + state.up_axis = Vector3::AXIS_Z; + + COLLADA_PRINT("up axis: " + parser.get_node_data()); + } else if (name == "unit") { + + state.unit_scale = parser.get_attribute_value("meter").to_double(); + COLLADA_PRINT("unit scale: " + rtos(state.unit_scale)); + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "asset") + break; //end of <asset> + } +} + +void Collada::_parse_image(XMLParser &parser) { + + String id = parser.get_attribute_value("id"); + + if (!(state.import_flags & IMPORT_FLAG_SCENE)) { + if (!parser.is_empty()) + parser.skip_section(); + return; + } + + Image image; + + if (state.version < State::Version(1, 4, 0)) { + /* <1.4 */ + String path = parser.get_attribute_value("source").strip_edges(); + if (path.find("://") == -1 && path.is_rel_path()) { + // path is relative to file being loaded, so convert to a resource path + image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path.percent_decode())); + } + } else { + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String name = parser.get_node_name(); + + if (name == "init_from") { + + parser.read(); + String path = parser.get_node_data().strip_edges().percent_decode(); + + if (path.find("://") == -1 && path.is_rel_path()) { + // path is relative to file being loaded, so convert to a resource path + path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path)); + + } else if (path.find("file:///") == 0) { + path = path.replace_first("file:///", ""); + path = ProjectSettings::get_singleton()->localize_path(path); + } + + image.path = path; + + } else if (name == "data") { + + ERR_PRINT("COLLADA Embedded image data not supported!"); + + } else if (name == "extra" && !parser.is_empty()) + parser.skip_section(); + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "image") + break; //end of <asset> + } + } + + state.image_map[id] = image; +} + +void Collada::_parse_material(XMLParser &parser) { + + if (!(state.import_flags & IMPORT_FLAG_SCENE)) { + if (!parser.is_empty()) + parser.skip_section(); + return; + } + + Material material; + + String id = parser.get_attribute_value("id"); + if (parser.has_attribute("name")) + material.name = parser.get_attribute_value("name"); + + if (state.version < State::Version(1, 4, 0)) { + /* <1.4 */ + ERR_PRINT("Collada Materials < 1.4 are not supported (yet)"); + } else { + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT && parser.get_node_name() == "instance_effect") { + + material.instance_effect = _uri_to_id(parser.get_attribute_value("url")); + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "material") + break; //end of <asset> + } + } + + state.material_map[id] = material; +} + +//! reads floats from inside of xml element until end of xml element +Vector<float> Collada::_read_float_array(XMLParser &parser) { + + if (parser.is_empty()) + return Vector<float>(); + + Vector<String> splitters; + splitters.push_back(" "); + splitters.push_back("\n"); + splitters.push_back("\r"); + splitters.push_back("\t"); + + Vector<float> array; + while (parser.read() == OK) { + // TODO: check for comments inside the element + // and ignore them. + + if (parser.get_node_type() == XMLParser::NODE_TEXT) { + // parse float data + String str = parser.get_node_data(); + array = str.split_floats_mk(splitters, false); + //array=str.split_floats(" ",false); + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) + break; // end parsing text + } + + return array; +} + +Vector<String> Collada::_read_string_array(XMLParser &parser) { + + if (parser.is_empty()) + return Vector<String>(); + + Vector<String> array; + while (parser.read() == OK) { + // TODO: check for comments inside the element + // and ignore them. + + if (parser.get_node_type() == XMLParser::NODE_TEXT) { + // parse String data + String str = parser.get_node_data(); + array = str.split_spaces(); + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) + break; // end parsing text + } + + return array; +} + +Transform Collada::_read_transform(XMLParser &parser) { + + if (parser.is_empty()) + return Transform(); + + Vector<String> array; + while (parser.read() == OK) { + // TODO: check for comments inside the element + // and ignore them. + + if (parser.get_node_type() == XMLParser::NODE_TEXT) { + // parse float data + String str = parser.get_node_data(); + array = str.split_spaces(); + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) + break; // end parsing text + } + + ERR_FAIL_COND_V(array.size() != 16, Transform()); + Vector<float> farr; + farr.resize(16); + for (int i = 0; i < 16; i++) { + farr.write[i] = array[i].to_double(); + } + + return _read_transform_from_array(farr); +} + +String Collada::_read_empty_draw_type(XMLParser &parser) { + + String empty_draw_type = ""; + + if (parser.is_empty()) + return empty_draw_type; + + while (parser.read() == OK) { + if (parser.get_node_type() == XMLParser::NODE_TEXT) { + empty_draw_type = parser.get_node_data(); + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END) + break; // end parsing text + } + return empty_draw_type; +} + +Variant Collada::_parse_param(XMLParser &parser) { + + if (parser.is_empty()) + return Variant(); + + String from = parser.get_node_name(); + Variant data; + + while (parser.read() == OK) { + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "float") { + + parser.read(); + if (parser.get_node_type() == XMLParser::NODE_TEXT) { + + data = parser.get_node_data().to_double(); + } + } else if (parser.get_node_name() == "float2") { + + Vector<float> v2 = _read_float_array(parser); + + if (v2.size() >= 2) { + + data = Vector2(v2[0], v2[1]); + } + } else if (parser.get_node_name() == "float3") { + + Vector<float> v3 = _read_float_array(parser); + + if (v3.size() >= 3) { + + data = Vector3(v3[0], v3[1], v3[2]); + } + } else if (parser.get_node_name() == "float4") { + + Vector<float> v4 = _read_float_array(parser); + + if (v4.size() >= 4) { + + data = Color(v4[0], v4[1], v4[2], v4[3]); + } + } else if (parser.get_node_name() == "sampler2D") { + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "source") { + + parser.read(); + + if (parser.get_node_type() == XMLParser::NODE_TEXT) { + + data = parser.get_node_data(); + } + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "sampler2D") + break; + } + } else if (parser.get_node_name() == "surface") { + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "init_from") { + + parser.read(); + + if (parser.get_node_type() == XMLParser::NODE_TEXT) { + + data = parser.get_node_data(); + } + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "surface") + break; + } + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == from) + break; + } + + COLLADA_PRINT("newparam ending " + parser.get_node_name()); + return data; +} + +void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String &id) { + + if (!(state.import_flags & IMPORT_FLAG_SCENE)) { + if (!parser.is_empty()) + parser.skip_section(); + return; + } + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + // first come the tags we descend, but ignore the top-levels + + COLLADA_PRINT("node name: " + parser.get_node_name()); + + if (!parser.is_empty() && (parser.get_node_name() == "profile_COMMON" || parser.get_node_name() == "technique" || parser.get_node_name() == "extra")) { + + _parse_effect_material(parser, effect, id); // try again + + } else if (parser.get_node_name() == "newparam") { + String name = parser.get_attribute_value("sid"); + Variant value = _parse_param(parser); + effect.params[name] = value; + COLLADA_PRINT("param: " + name + " value:" + String(value)); + + } else if (parser.get_node_name() == "constant" || + parser.get_node_name() == "lambert" || + parser.get_node_name() == "phong" || + parser.get_node_name() == "blinn") { + + COLLADA_PRINT("shade model: " + parser.get_node_name()); + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String what = parser.get_node_name(); + + if (what == "emission" || + what == "diffuse" || + what == "specular" || + what == "reflective") { + + // color or texture types + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "color") { + + Vector<float> colorarr = _read_float_array(parser); + COLLADA_PRINT("colorarr size: " + rtos(colorarr.size())); + + if (colorarr.size() >= 3) { + + // alpha strangely not alright? maybe it needs to be multiplied by value as a channel intensity + Color color(colorarr[0], colorarr[1], colorarr[2], 1.0); + if (what == "diffuse") + effect.diffuse.color = color; + if (what == "specular") + effect.specular.color = color; + if (what == "emission") + effect.emission.color = color; + + COLLADA_PRINT(what + " color: " + color); + } + + } else if (parser.get_node_name() == "texture") { + + String sampler = parser.get_attribute_value("texture"); + if (!effect.params.has(sampler)) { + ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data()); + } else { + String surface = effect.params[sampler]; + + if (!effect.params.has(surface)) { + ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + id).utf8().get_data()); + } else { + String uri = effect.params[surface]; + + if (what == "diffuse") { + effect.diffuse.texture = uri; + } else if (what == "specular") { + effect.specular.texture = uri; + } else if (what == "emission") { + effect.emission.texture = uri; + } else if (what == "bump") { + if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") { + WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported."); + } + + effect.bump.texture = uri; + } + + COLLADA_PRINT(what + " texture: " + uri); + } + } + } else if (!parser.is_empty()) + parser.skip_section(); + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == what) + break; + } + + } else if (what == "shininess") { + effect.shininess = _parse_param(parser); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && (parser.get_node_name() == "constant" || + parser.get_node_name() == "lambert" || + parser.get_node_name() == "phong" || + parser.get_node_name() == "blinn")) + break; + } + } else if (parser.get_node_name() == "double_sided" || parser.get_node_name() == "show_double_sided") { // colladamax / google earth + + // 3DS Max / Google Earth double sided extension + parser.read(); + effect.found_double_sided = true; + effect.double_sided = parser.get_node_data().to_int(); + COLLADA_PRINT("double sided: " + itos(parser.get_node_data().to_int())); + } else if (parser.get_node_name() == "unshaded") { + parser.read(); + effect.unshaded = parser.get_node_data().to_int(); + } else if (parser.get_node_name() == "bump") { + + // color or texture types + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "texture") { + + String sampler = parser.get_attribute_value("texture"); + if (!effect.params.has(sampler)) { + ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data()); + } else { + String surface = effect.params[sampler]; + + if (!effect.params.has(surface)) { + ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + id).utf8().get_data()); + } else { + String uri = effect.params[surface]; + + if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") { + WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported."); + } + + effect.bump.texture = uri; + COLLADA_PRINT(" bump: " + uri); + } + } + } else if (!parser.is_empty()) + parser.skip_section(); + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "bump") + break; + } + + } else if (!parser.is_empty()) + parser.skip_section(); + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && + (parser.get_node_name() == "effect" || + parser.get_node_name() == "profile_COMMON" || + parser.get_node_name() == "technique" || + parser.get_node_name() == "extra")) + break; + } +} + +void Collada::_parse_effect(XMLParser &parser) { + + if (!(state.import_flags & IMPORT_FLAG_SCENE)) { + if (!parser.is_empty()) + parser.skip_section(); + return; + } + + String id = parser.get_attribute_value("id"); + + Effect effect; + if (parser.has_attribute("name")) + effect.name = parser.get_attribute_value("name"); + _parse_effect_material(parser, effect, id); + + state.effect_map[id] = effect; + + COLLADA_PRINT("Effect ID:" + id); +} + +void Collada::_parse_camera(XMLParser &parser) { + + if (!(state.import_flags & IMPORT_FLAG_SCENE)) { + if (!parser.is_empty()) + parser.skip_section(); + return; + } + + String id = parser.get_attribute_value("id"); + + state.camera_data_map[id] = CameraData(); + CameraData &camera = state.camera_data_map[id]; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String name = parser.get_node_name(); + + if (name == "perspective") { + + camera.mode = CameraData::MODE_PERSPECTIVE; + } else if (name == "orthographic") { + + camera.mode = CameraData::MODE_ORTHOGONAL; + } else if (name == "xfov") { + + parser.read(); + camera.perspective.x_fov = parser.get_node_data().to_double(); + + } else if (name == "yfov") { + + parser.read(); + camera.perspective.y_fov = parser.get_node_data().to_double(); + } else if (name == "xmag") { + + parser.read(); + camera.orthogonal.x_mag = parser.get_node_data().to_double(); + + } else if (name == "ymag") { + + parser.read(); + camera.orthogonal.y_mag = parser.get_node_data().to_double(); + } else if (name == "aspect_ratio") { + + parser.read(); + camera.aspect = parser.get_node_data().to_double(); + + } else if (name == "znear") { + + parser.read(); + camera.z_near = parser.get_node_data().to_double(); + + } else if (name == "zfar") { + + parser.read(); + camera.z_far = parser.get_node_data().to_double(); + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "camera") + break; //end of <asset> + } + + COLLADA_PRINT("Camera ID:" + id); +} + +void Collada::_parse_light(XMLParser &parser) { + + if (!(state.import_flags & IMPORT_FLAG_SCENE)) { + if (!parser.is_empty()) + parser.skip_section(); + return; + } + + String id = parser.get_attribute_value("id"); + + state.light_data_map[id] = LightData(); + LightData &light = state.light_data_map[id]; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String name = parser.get_node_name(); + + if (name == "ambient") { + + light.mode = LightData::MODE_AMBIENT; + } else if (name == "directional") { + + light.mode = LightData::MODE_DIRECTIONAL; + } else if (name == "point") { + + light.mode = LightData::MODE_OMNI; + } else if (name == "spot") { + + light.mode = LightData::MODE_SPOT; + } else if (name == "color") { + + parser.read(); + Vector<float> colorarr = _read_float_array(parser); + COLLADA_PRINT("colorarr size: " + rtos(colorarr.size())); + + if (colorarr.size() >= 4) { + // alpha strangely not alright? maybe it needs to be multiplied by value as a channel intensity + Color color(colorarr[0], colorarr[1], colorarr[2], 1.0); + light.color = color; + } + + } else if (name == "constant_attenuation") { + + parser.read(); + light.constant_att = parser.get_node_data().to_double(); + } else if (name == "linear_attenuation") { + + parser.read(); + light.linear_att = parser.get_node_data().to_double(); + } else if (name == "quadratic_attenuation") { + + parser.read(); + light.quad_att = parser.get_node_data().to_double(); + } else if (name == "falloff_angle") { + + parser.read(); + light.spot_angle = parser.get_node_data().to_double(); + + } else if (name == "falloff_exponent") { + + parser.read(); + light.spot_exp = parser.get_node_data().to_double(); + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "light") + break; //end of <asset> + } + + COLLADA_PRINT("Light ID:" + id); +} + +void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_name) { + + if (!(state.import_flags & IMPORT_FLAG_SCENE)) { + if (!parser.is_empty()) + parser.skip_section(); + return; + } + + //load everything into a pre dictionary + + state.curve_data_map[p_id] = CurveData(); + + CurveData &curvedata = state.curve_data_map[p_id]; + curvedata.name = p_name; + + COLLADA_PRINT("curve name: " + p_name); + + String current_source; + // handles geometry node and the curve children in this loop + // read sources with arrays and accessor for each curve + if (parser.is_empty()) { + return; + } + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String section = parser.get_node_name(); + + if (section == "source") { + + String id = parser.get_attribute_value("id"); + curvedata.sources[id] = CurveData::Source(); + current_source = id; + COLLADA_PRINT("source data: " + id); + + } else if (section == "float_array" || section == "array") { + // create a new array and read it. + if (curvedata.sources.has(current_source)) { + + curvedata.sources[current_source].array = _read_float_array(parser); + COLLADA_PRINT("section: " + current_source + " read " + itos(curvedata.sources[current_source].array.size()) + " values."); + } + } else if (section == "Name_array") { + // create a new array and read it. + if (curvedata.sources.has(current_source)) { + + curvedata.sources[current_source].sarray = _read_string_array(parser); + COLLADA_PRINT("section: " + current_source + " read " + itos(curvedata.sources[current_source].array.size()) + " values."); + } + + } else if (section == "technique_common") { + //skip it + } else if (section == "accessor") { // child of source (below a technique tag) + + if (curvedata.sources.has(current_source)) { + curvedata.sources[current_source].stride = parser.get_attribute_value("stride").to_int(); + COLLADA_PRINT("section: " + current_source + " stride " + itos(curvedata.sources[current_source].stride)); + } + } else if (section == "control_vertices") { + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "input") { + + String semantic = parser.get_attribute_value("semantic"); + String source = _uri_to_id(parser.get_attribute_value("source")); + + curvedata.control_vertices[semantic] = source; + + COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) + break; + } + + } else if (!parser.is_empty()) { + + parser.skip_section(); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "spline") + break; + } +} + +void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name) { + + if (!(state.import_flags & IMPORT_FLAG_SCENE)) { + if (!parser.is_empty()) + parser.skip_section(); + return; + } + + //load everything into a pre dictionary + + state.mesh_data_map[p_id] = MeshData(); + + MeshData &meshdata = state.mesh_data_map[p_id]; + meshdata.name = p_name; + + COLLADA_PRINT("mesh name: " + p_name); + + String current_source; + // handles geometry node and the mesh children in this loop + // read sources with arrays and accessor for each mesh + if (parser.is_empty()) { + return; + } + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String section = parser.get_node_name(); + + if (section == "source") { + + String id = parser.get_attribute_value("id"); + meshdata.sources[id] = MeshData::Source(); + current_source = id; + COLLADA_PRINT("source data: " + id); + + } else if (section == "float_array" || section == "array") { + // create a new array and read it. + if (meshdata.sources.has(current_source)) { + + meshdata.sources[current_source].array = _read_float_array(parser); + COLLADA_PRINT("section: " + current_source + " read " + itos(meshdata.sources[current_source].array.size()) + " values."); + } + } else if (section == "technique_common") { + //skip it + } else if (section == "accessor") { // child of source (below a technique tag) + + if (meshdata.sources.has(current_source)) { + meshdata.sources[current_source].stride = parser.get_attribute_value("stride").to_int(); + COLLADA_PRINT("section: " + current_source + " stride " + itos(meshdata.sources[current_source].stride)); + } + } else if (section == "vertices") { + + MeshData::Vertices vert; + String id = parser.get_attribute_value("id"); + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "input") { + + String semantic = parser.get_attribute_value("semantic"); + String source = _uri_to_id(parser.get_attribute_value("source")); + + vert.sources[semantic] = source; + + COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) + break; + } + + meshdata.vertices[id] = vert; + + } else if (section == "triangles" || section == "polylist" || section == "polygons") { + + bool polygons = (section == "polygons"); + if (polygons) { + WARN_PRINT("Primitive type \"polygons\" is not well supported (concave shapes may fail). To ensure that the geometry is properly imported, please re-export using \"triangles\" or \"polylist\"."); + } + MeshData::Primitives prim; + + if (parser.has_attribute("material")) + prim.material = parser.get_attribute_value("material"); + prim.count = parser.get_attribute_value("count").to_int(); + prim.vertex_size = 0; + int last_ref = 0; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "input") { + + String semantic = parser.get_attribute_value("semantic"); + String source = _uri_to_id(parser.get_attribute_value("source")); + + if (semantic == "TEXCOORD") { + /* + if (parser.has_attribute("set"))// a texcoord + semantic+=parser.get_attribute_value("set"); + else + semantic="TEXCOORD0";*/ + semantic = "TEXCOORD" + itos(last_ref++); + } + int offset = parser.get_attribute_value("offset").to_int(); + + MeshData::Primitives::SourceRef sref; + sref.source = source; + sref.offset = offset; + prim.sources[semantic] = sref; + prim.vertex_size = MAX(prim.vertex_size, offset + 1); + + COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source + " offset: " + itos(offset)); + + } else if (parser.get_node_name() == "p") { //indices + + Vector<float> values = _read_float_array(parser); + if (polygons) { + + ERR_CONTINUE(prim.vertex_size == 0); + prim.polygons.push_back(values.size() / prim.vertex_size); + int from = prim.indices.size(); + prim.indices.resize(from + values.size()); + for (int i = 0; i < values.size(); i++) + prim.indices.write[from + i] = values[i]; + + } else if (prim.vertex_size > 0) { + prim.indices = values; + } + + COLLADA_PRINT("read " + itos(values.size()) + " index values"); + + } else if (parser.get_node_name() == "vcount") { // primitive + + Vector<float> values = _read_float_array(parser); + prim.polygons = values; + COLLADA_PRINT("read " + itos(values.size()) + " polygon values"); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) + break; + } + + meshdata.primitives.push_back(prim); + + } else if (parser.get_node_name() == "double_sided") { + + parser.read(); + meshdata.found_double_sided = true; + meshdata.double_sided = parser.get_node_data().to_int(); + + } else if (parser.get_node_name() == "polygons") { + ERR_PRINT("Primitive type \"polygons\" not supported, re-export using \"polylist\" or \"triangles\"."); + } else if (!parser.is_empty()) { + + parser.skip_section(); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "mesh") + break; + } +} + +void Collada::_parse_skin_controller(XMLParser &parser, String p_id) { + + state.skin_controller_data_map[p_id] = SkinControllerData(); + SkinControllerData &skindata = state.skin_controller_data_map[p_id]; + + skindata.base = _uri_to_id(parser.get_attribute_value("source")); + + String current_source; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String section = parser.get_node_name(); + + if (section == "bind_shape_matrix") { + + skindata.bind_shape = _read_transform(parser); +#ifdef COLLADA_IMPORT_SCALE_SCENE + skindata.bind_shape.origin *= state.unit_scale; + +#endif + COLLADA_PRINT("skeleton bind shape transform: " + skindata.bind_shape); + + } else if (section == "source") { + + String id = parser.get_attribute_value("id"); + skindata.sources[id] = SkinControllerData::Source(); + current_source = id; + COLLADA_PRINT("source data: " + id); + + } else if (section == "float_array" || section == "array") { + // create a new array and read it. + if (skindata.sources.has(current_source)) { + + skindata.sources[current_source].array = _read_float_array(parser); + COLLADA_PRINT("section: " + current_source + " read " + itos(skindata.sources[current_source].array.size()) + " values."); + } + } else if (section == "Name_array" || section == "IDREF_array") { + // create a new array and read it. + + if (section == "IDREF_array") + skindata.use_idrefs = true; + if (skindata.sources.has(current_source)) { + + skindata.sources[current_source].sarray = _read_string_array(parser); + if (section == "IDREF_array") { + Vector<String> sa = skindata.sources[current_source].sarray; + for (int i = 0; i < sa.size(); i++) + state.idref_joints.insert(sa[i]); + } + COLLADA_PRINT("section: " + current_source + " read " + itos(skindata.sources[current_source].array.size()) + " values."); + } + } else if (section == "technique_common") { + //skip it + } else if (section == "accessor") { // child of source (below a technique tag) + + if (skindata.sources.has(current_source)) { + + int stride = 1; + if (parser.has_attribute("stride")) + stride = parser.get_attribute_value("stride").to_int(); + + skindata.sources[current_source].stride = stride; + COLLADA_PRINT("section: " + current_source + " stride " + itos(skindata.sources[current_source].stride)); + } + + } else if (section == "joints") { + + SkinControllerData::Joints joint; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "input") { + + String semantic = parser.get_attribute_value("semantic"); + String source = _uri_to_id(parser.get_attribute_value("source")); + + joint.sources[semantic] = source; + + COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) + break; + } + + skindata.joints = joint; + + } else if (section == "vertex_weights") { + + SkinControllerData::Weights weights; + + weights.count = parser.get_attribute_value("count").to_int(); + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "input") { + + String semantic = parser.get_attribute_value("semantic"); + String source = _uri_to_id(parser.get_attribute_value("source")); + + int offset = parser.get_attribute_value("offset").to_int(); + + SkinControllerData::Weights::SourceRef sref; + sref.source = source; + sref.offset = offset; + weights.sources[semantic] = sref; + + COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source + " offset: " + itos(offset)); + + } else if (parser.get_node_name() == "v") { //indices + + Vector<float> values = _read_float_array(parser); + weights.indices = values; + COLLADA_PRINT("read " + itos(values.size()) + " index values"); + + } else if (parser.get_node_name() == "vcount") { // weightsitive + + Vector<float> values = _read_float_array(parser); + weights.sets = values; + COLLADA_PRINT("read " + itos(values.size()) + " polygon values"); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) + break; + } + + skindata.weights = weights; + } + /* + else if (!parser.is_empty()) + parser.skip_section(); + */ + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "skin") + break; + } + + /* STORE REST MATRICES */ + + Vector<Transform> rests; + ERR_FAIL_COND(!skindata.joints.sources.has("JOINT")); + ERR_FAIL_COND(!skindata.joints.sources.has("INV_BIND_MATRIX")); + + String joint_arr = skindata.joints.sources["JOINT"]; + String ibm = skindata.joints.sources["INV_BIND_MATRIX"]; + + ERR_FAIL_COND(!skindata.sources.has(joint_arr)); + ERR_FAIL_COND(!skindata.sources.has(ibm)); + + SkinControllerData::Source &joint_source = skindata.sources[joint_arr]; + SkinControllerData::Source &ibm_source = skindata.sources[ibm]; + + ERR_FAIL_COND(joint_source.sarray.size() != ibm_source.array.size() / 16); + + for (int i = 0; i < joint_source.sarray.size(); i++) { + + String name = joint_source.sarray[i]; + Transform xform = _read_transform_from_array(ibm_source.array, i * 16); //<- this is a mistake, it must be applied to vertices + xform.affine_invert(); // inverse for rest, because it's an inverse +#ifdef COLLADA_IMPORT_SCALE_SCENE + xform.origin *= state.unit_scale; +#endif + skindata.bone_rest_map[name] = xform; + } +} + +void Collada::_parse_morph_controller(XMLParser &parser, String p_id) { + + state.morph_controller_data_map[p_id] = MorphControllerData(); + MorphControllerData &morphdata = state.morph_controller_data_map[p_id]; + + morphdata.mesh = _uri_to_id(parser.get_attribute_value("source")); + morphdata.mode = parser.get_attribute_value("method"); + String current_source; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String section = parser.get_node_name(); + + if (section == "source") { + + String id = parser.get_attribute_value("id"); + morphdata.sources[id] = MorphControllerData::Source(); + current_source = id; + COLLADA_PRINT("source data: " + id); + + } else if (section == "float_array" || section == "array") { + // create a new array and read it. + if (morphdata.sources.has(current_source)) { + + morphdata.sources[current_source].array = _read_float_array(parser); + COLLADA_PRINT("section: " + current_source + " read " + itos(morphdata.sources[current_source].array.size()) + " values."); + } + } else if (section == "Name_array" || section == "IDREF_array") { + // create a new array and read it. + + /* + if (section=="IDREF_array") + morphdata.use_idrefs=true; + */ + if (morphdata.sources.has(current_source)) { + + morphdata.sources[current_source].sarray = _read_string_array(parser); + /* + if (section=="IDREF_array") { + Vector<String> sa = morphdata.sources[current_source].sarray; + for(int i=0;i<sa.size();i++) + state.idref_joints.insert(sa[i]); + }*/ + COLLADA_PRINT("section: " + current_source + " read " + itos(morphdata.sources[current_source].array.size()) + " values."); + } + } else if (section == "technique_common") { + //skip it + } else if (section == "accessor") { // child of source (below a technique tag) + + if (morphdata.sources.has(current_source)) { + + int stride = 1; + if (parser.has_attribute("stride")) + stride = parser.get_attribute_value("stride").to_int(); + + morphdata.sources[current_source].stride = stride; + COLLADA_PRINT("section: " + current_source + " stride " + itos(morphdata.sources[current_source].stride)); + } + + } else if (section == "targets") { + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "input") { + + String semantic = parser.get_attribute_value("semantic"); + String source = _uri_to_id(parser.get_attribute_value("source")); + + morphdata.targets[semantic] = source; + + COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section) + break; + } + } + /* + else if (!parser.is_empty()) + parser.skip_section(); + */ + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "morph") + break; + } + + if (morphdata.targets.has("MORPH_WEIGHT")) { + + state.morph_name_map[morphdata.targets["MORPH_WEIGHT"]] = p_id; + } +} + +void Collada::_parse_controller(XMLParser &parser) { + + String id = parser.get_attribute_value("id"); + + if (parser.is_empty()) { + return; + } + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String section = parser.get_node_name(); + + if (section == "skin") { + _parse_skin_controller(parser, id); + } else if (section == "morph") { + _parse_morph_controller(parser, id); + } + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "controller") + break; + } +} + +Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) { + + String type = parser.get_node_name(); + NodeGeometry *geom = memnew(NodeGeometry); + geom->controller = type == "instance_controller"; + geom->source = _uri_to_id(parser.get_attribute_value_safe("url")); + + if (parser.is_empty()) //nothing else to parse... + return geom; + // try to find also many materials and skeletons! + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "instance_material") { + + String symbol = parser.get_attribute_value("symbol"); + String target = _uri_to_id(parser.get_attribute_value("target")); + + NodeGeometry::Material mat; + mat.target = target; + geom->material_map[symbol] = mat; + COLLADA_PRINT("uses material: '" + target + "' on primitive'" + symbol + "'"); + } else if (parser.get_node_name() == "skeleton") { + + parser.read(); + String uri = _uri_to_id(parser.get_node_data()); + if (uri != "") { + geom->skeletons.push_back(uri); + } + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == type) + break; + } + + if (geom->controller) { + + if (geom->skeletons.empty()) { + //XSI style + + if (state.skin_controller_data_map.has(geom->source)) { + SkinControllerData *skin = &state.skin_controller_data_map[geom->source]; + //case where skeletons reference bones with IDREF (XSI) + ERR_FAIL_COND_V(!skin->joints.sources.has("JOINT"), geom); + String joint_arr = skin->joints.sources["JOINT"]; + ERR_FAIL_COND_V(!skin->sources.has(joint_arr), geom); + Collada::SkinControllerData::Source &joint_source = skin->sources[joint_arr]; + geom->skeletons = joint_source.sarray; //quite crazy, but should work. + } + } + } + + return geom; +} + +Collada::Node *Collada::_parse_visual_instance_camera(XMLParser &parser) { + + NodeCamera *cam = memnew(NodeCamera); + cam->camera = _uri_to_id(parser.get_attribute_value_safe("url")); + + if (state.up_axis == Vector3::AXIS_Z) //collada weirdness + cam->post_transform.basis.rotate(Vector3(1, 0, 0), -Math_PI * 0.5); + + if (parser.is_empty()) //nothing else to parse... + return cam; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "instance_camera") + break; + } + + return cam; +} + +Collada::Node *Collada::_parse_visual_instance_light(XMLParser &parser) { + + NodeLight *cam = memnew(NodeLight); + cam->light = _uri_to_id(parser.get_attribute_value_safe("url")); + + if (state.up_axis == Vector3::AXIS_Z) //collada weirdness + cam->post_transform.basis.rotate(Vector3(1, 0, 0), -Math_PI * 0.5); + + if (parser.is_empty()) //nothing else to parse... + return cam; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "instance_light") + break; + } + + return cam; +} + +Collada::Node *Collada::_parse_visual_node_instance_data(XMLParser &parser) { + + String instance_type = parser.get_node_name(); + + if (instance_type == "instance_geometry" || instance_type == "instance_controller") { + return _parse_visual_instance_geometry(parser); + } else if (instance_type == "instance_camera") { + + return _parse_visual_instance_camera(parser); + } else if (instance_type == "instance_light") { + return _parse_visual_instance_light(parser); + } + + if (parser.is_empty()) //nothing else to parse... + return nullptr; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == instance_type) + break; + } + + return nullptr; +} + +Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) { + + String name; + + String id = parser.get_attribute_value_safe("id"); + + bool found_name = false; + + if (id == "") { + + id = "%NODEID%" + itos(Math::rand()); + + } else { + found_name = true; + } + + Vector<Node::XForm> xform_list; + Vector<Node *> children; + + String empty_draw_type = ""; + + Node *node = nullptr; + + name = parser.has_attribute("name") ? parser.get_attribute_value_safe("name") : parser.get_attribute_value_safe("id"); + if (name == "") { + + name = id; + } else { + found_name = true; + } + + if ((parser.has_attribute("type") && parser.get_attribute_value("type") == "JOINT") || state.idref_joints.has(name)) { + // handle a bone + + NodeJoint *joint = memnew(NodeJoint); + + if (parser.has_attribute("sid")) { //bones may not have sid + joint->sid = parser.get_attribute_value("sid"); + //state.bone_map[joint->sid]=joint; + } else if (state.idref_joints.has(name)) { + joint->sid = name; //kind of a cheat but.. + } else if (parser.has_attribute("name")) { + joint->sid = parser.get_attribute_value_safe("name"); + } + + if (joint->sid != "") { + state.sid_to_node_map[joint->sid] = id; + } + + node = joint; + } + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String section = parser.get_node_name(); + + if (section == "translate") { + Node::XForm xf; + if (parser.has_attribute("sid")) { + xf.id = parser.get_attribute_value("sid"); + } + xf.op = Node::XForm::OP_TRANSLATE; + + Vector<float> xlt = _read_float_array(parser); + xf.data = xlt; + xform_list.push_back(xf); + + } else if (section == "rotate") { + Node::XForm xf; + if (parser.has_attribute("sid")) { + xf.id = parser.get_attribute_value("sid"); + } + xf.op = Node::XForm::OP_ROTATE; + + Vector<float> rot = _read_float_array(parser); + xf.data = rot; + + xform_list.push_back(xf); + + } else if (section == "scale") { + Node::XForm xf; + if (parser.has_attribute("sid")) { + xf.id = parser.get_attribute_value("sid"); + } + + xf.op = Node::XForm::OP_SCALE; + + Vector<float> scale = _read_float_array(parser); + + xf.data = scale; + + xform_list.push_back(xf); + + } else if (section == "matrix") { + Node::XForm xf; + if (parser.has_attribute("sid")) { + xf.id = parser.get_attribute_value("sid"); + } + xf.op = Node::XForm::OP_MATRIX; + + Vector<float> matrix = _read_float_array(parser); + + xf.data = matrix; + String mtx; + for (int i = 0; i < matrix.size(); i++) + mtx += " " + rtos(matrix[i]); + + xform_list.push_back(xf); + + } else if (section == "visibility") { + Node::XForm xf; + if (parser.has_attribute("sid")) { + xf.id = parser.get_attribute_value("sid"); + } + xf.op = Node::XForm::OP_VISIBILITY; + + Vector<float> visible = _read_float_array(parser); + + xf.data = visible; + + xform_list.push_back(xf); + + } else if (section == "empty_draw_type") { + empty_draw_type = _read_empty_draw_type(parser); + } else if (section == "technique" || section == "extra") { + + } else if (section != "node") { + //usually what defines the type of node + if (section.begins_with("instance_")) { + + if (!node) { + + node = _parse_visual_node_instance_data(parser); + + } else { + ERR_PRINT("Multiple instance_* not supported."); + } + } + + } else { + + /* Found a child node!! what to do..*/ + + Node *child = _parse_visual_scene_node(parser); + children.push_back(child); + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "node") + break; + } + + if (!node) { + + node = memnew(Node); //generic node, nothing of relevance found + } + + node->noname = !found_name; + node->xform_list = xform_list; + node->children = children; + for (int i = 0; i < children.size(); i++) { + node->children[i]->parent = node; + } + + node->name = name; + node->id = id; + node->empty_draw_type = empty_draw_type; + + if (node->children.size() == 1) { + if (node->children[0]->noname && !node->noname) { + node->children[0]->name = node->name; + node->name = node->name + "-base"; + } + } + + node->default_transform = node->compute_transform(*this); + state.scene_map[id] = node; + + return node; +} + +void Collada::_parse_visual_scene(XMLParser &parser) { + + String id = parser.get_attribute_value("id"); + + if (parser.is_empty()) { + return; + } + + state.visual_scene_map[id] = VisualScene(); + VisualScene &vscene = state.visual_scene_map[id]; + + if (parser.has_attribute("name")) + vscene.name = parser.get_attribute_value("name"); + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String section = parser.get_node_name(); + + if (section == "node") { + vscene.root_nodes.push_back(_parse_visual_scene_node(parser)); + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "visual_scene") + break; + } + + COLLADA_PRINT("Scene ID:" + id); +} + +void Collada::_parse_animation(XMLParser &parser) { + + if (!(state.import_flags & IMPORT_FLAG_ANIMATION)) { + if (!parser.is_empty()) + parser.skip_section(); + + return; + } + + Map<String, Vector<float>> float_sources; + Map<String, Vector<String>> string_sources; + Map<String, int> source_strides; + Map<String, Map<String, String>> samplers; + Map<String, Vector<String>> source_param_names; + Map<String, Vector<String>> source_param_types; + + String id = ""; + if (parser.has_attribute("id")) + id = parser.get_attribute_value("id"); + + String current_source; + String current_sampler; + Vector<String> channel_sources; + Vector<String> channel_targets; + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String name = parser.get_node_name(); + if (name == "source") { + + current_source = parser.get_attribute_value("id"); + source_param_names[current_source] = Vector<String>(); + source_param_types[current_source] = Vector<String>(); + + } else if (name == "float_array") { + + if (current_source != "") { + float_sources[current_source] = _read_float_array(parser); + } + + } else if (name == "Name_array") { + + if (current_source != "") { + string_sources[current_source] = _read_string_array(parser); + } + } else if (name == "accessor") { + + if (current_source != "" && parser.has_attribute("stride")) { + source_strides[current_source] = parser.get_attribute_value("stride").to_int(); + } + } else if (name == "sampler") { + + current_sampler = parser.get_attribute_value("id"); + samplers[current_sampler] = Map<String, String>(); + } else if (name == "param") { + + if (parser.has_attribute("name")) + source_param_names[current_source].push_back(parser.get_attribute_value("name")); + else + source_param_names[current_source].push_back(""); + + if (parser.has_attribute("type")) + source_param_types[current_source].push_back(parser.get_attribute_value("type")); + else + source_param_types[current_source].push_back(""); + + } else if (name == "input") { + + if (current_sampler != "") { + + samplers[current_sampler][parser.get_attribute_value("semantic")] = parser.get_attribute_value("source"); + } + + } else if (name == "channel") { + + channel_sources.push_back(parser.get_attribute_value("source")); + channel_targets.push_back(parser.get_attribute_value("target")); + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation") + break; //end of <asset> + } + + for (int i = 0; i < channel_sources.size(); i++) { + + String source = _uri_to_id(channel_sources[i]); + String target = channel_targets[i]; + ERR_CONTINUE(!samplers.has(source)); + Map<String, String> &sampler = samplers[source]; + + ERR_CONTINUE(!sampler.has("INPUT")); //no input semantic? wtf? + String input_id = _uri_to_id(sampler["INPUT"]); + COLLADA_PRINT("input id is " + input_id); + ERR_CONTINUE(!float_sources.has(input_id)); + + ERR_CONTINUE(!sampler.has("OUTPUT")); + String output_id = _uri_to_id(sampler["OUTPUT"]); + ERR_CONTINUE(!float_sources.has(output_id)); + + ERR_CONTINUE(!source_param_names.has(output_id)); + + Vector<String> &names = source_param_names[output_id]; + + for (int l = 0; l < names.size(); l++) { + + String name = names[l]; + + Vector<float> &time_keys = float_sources[input_id]; + int key_count = time_keys.size(); + + AnimationTrack track; //begin crating track + track.id = id; + + track.keys.resize(key_count); + + for (int j = 0; j < key_count; j++) { + track.keys.write[j].time = time_keys[j]; + state.animation_length = MAX(state.animation_length, time_keys[j]); + } + + //now read actual values + + int stride = 1; + + if (source_strides.has(output_id)) + stride = source_strides[output_id]; + int output_len = stride / names.size(); + + ERR_CONTINUE(output_len == 0); + ERR_CONTINUE(!float_sources.has(output_id)); + + Vector<float> &output = float_sources[output_id]; + + ERR_CONTINUE_MSG((output.size() / stride) != key_count, "Wrong number of keys in output."); + + for (int j = 0; j < key_count; j++) { + track.keys.write[j].data.resize(output_len); + for (int k = 0; k < output_len; k++) + track.keys.write[j].data.write[k] = output[l + j * stride + k]; //super weird but should work: + } + + if (sampler.has("INTERPOLATION")) { + + String interp_id = _uri_to_id(sampler["INTERPOLATION"]); + ERR_CONTINUE(!string_sources.has(interp_id)); + Vector<String> &interps = string_sources[interp_id]; + ERR_CONTINUE(interps.size() != key_count); + + for (int j = 0; j < key_count; j++) { + if (interps[j] == "BEZIER") + track.keys.write[j].interp_type = AnimationTrack::INTERP_BEZIER; + else + track.keys.write[j].interp_type = AnimationTrack::INTERP_LINEAR; + } + } + + if (sampler.has("IN_TANGENT") && sampler.has("OUT_TANGENT")) { + //bezier control points.. + String intangent_id = _uri_to_id(sampler["IN_TANGENT"]); + ERR_CONTINUE(!float_sources.has(intangent_id)); + Vector<float> &intangents = float_sources[intangent_id]; + + ERR_CONTINUE(intangents.size() != key_count * 2 * names.size()); + + String outangent_id = _uri_to_id(sampler["OUT_TANGENT"]); + ERR_CONTINUE(!float_sources.has(outangent_id)); + Vector<float> &outangents = float_sources[outangent_id]; + ERR_CONTINUE(outangents.size() != key_count * 2 * names.size()); + + for (int j = 0; j < key_count; j++) { + track.keys.write[j].in_tangent = Vector2(intangents[j * 2 * names.size() + 0 + l * 2], intangents[j * 2 * names.size() + 1 + l * 2]); + track.keys.write[j].out_tangent = Vector2(outangents[j * 2 * names.size() + 0 + l * 2], outangents[j * 2 * names.size() + 1 + l * 2]); + } + } + + if (target.find("/") != -1) { //transform component + track.target = target.get_slicec('/', 0); + track.param = target.get_slicec('/', 1); + if (track.param.find(".") != -1) + track.component = track.param.get_slice(".", 1).to_upper(); + track.param = track.param.get_slice(".", 0); + if (names.size() > 1 && track.component == "") { + //this is a guess because the collada spec is ambiguous here... + //i suppose if you have many names (outputs) you can't use a component and i should abide to that. + track.component = name; + } + } else { + track.target = target; + } + + state.animation_tracks.push_back(track); + + if (!state.referenced_tracks.has(target)) + state.referenced_tracks[target] = Vector<int>(); + + state.referenced_tracks[target].push_back(state.animation_tracks.size() - 1); + + if (id != "") { + if (!state.by_id_tracks.has(id)) + state.by_id_tracks[id] = Vector<int>(); + + state.by_id_tracks[id].push_back(state.animation_tracks.size() - 1); + } + + COLLADA_PRINT("loaded animation with " + itos(key_count) + " keys"); + } + } +} + +void Collada::_parse_animation_clip(XMLParser &parser) { + + if (!(state.import_flags & IMPORT_FLAG_ANIMATION)) { + if (!parser.is_empty()) + parser.skip_section(); + + return; + } + + AnimationClip clip; + + if (parser.has_attribute("name")) + clip.name = parser.get_attribute_value("name"); + else if (parser.has_attribute("id")) + clip.name = parser.get_attribute_value("id"); + if (parser.has_attribute("start")) + clip.begin = parser.get_attribute_value("start").to_double(); + if (parser.has_attribute("end")) + clip.end = parser.get_attribute_value("end").to_double(); + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String name = parser.get_node_name(); + if (name == "instance_animation") { + + String url = _uri_to_id(parser.get_attribute_value("url")); + clip.tracks.push_back(url); + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation_clip") + break; //end of <asset> + } + + state.animation_clips.push_back(clip); +} + +void Collada::_parse_scene(XMLParser &parser) { + + if (parser.is_empty()) { + return; + } + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String name = parser.get_node_name(); + + if (name == "instance_visual_scene") { + + state.root_visual_scene = _uri_to_id(parser.get_attribute_value("url")); + } else if (name == "instance_physics_scene") { + + state.root_physics_scene = _uri_to_id(parser.get_attribute_value("url")); + } + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "scene") + break; //end of <asset> + } +} + +void Collada::_parse_library(XMLParser &parser) { + + if (parser.is_empty()) { + return; + } + + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + String name = parser.get_node_name(); + COLLADA_PRINT("library name is: " + name); + if (name == "image") { + + _parse_image(parser); + } else if (name == "material") { + + _parse_material(parser); + } else if (name == "effect") { + + _parse_effect(parser); + } else if (name == "camera") { + + _parse_camera(parser); + } else if (name == "light") { + + _parse_light(parser); + } else if (name == "geometry") { + + String id = parser.get_attribute_value("id"); + String name2 = parser.get_attribute_value_safe("name"); + while (parser.read() == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "mesh") { + state.mesh_name_map[id] = (name2 != "") ? name2 : id; + _parse_mesh_geometry(parser, id, name2); + } else if (parser.get_node_name() == "spline") { + state.mesh_name_map[id] = (name2 != "") ? name2 : id; + _parse_curve_geometry(parser, id, name2); + } else if (!parser.is_empty()) + parser.skip_section(); + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "geometry") + break; + } + + } else if (name == "controller") { + + _parse_controller(parser); + } else if (name == "animation") { + + _parse_animation(parser); + } else if (name == "animation_clip") { + + _parse_animation_clip(parser); + } else if (name == "visual_scene") { + + COLLADA_PRINT("visual scene"); + _parse_visual_scene(parser); + } else if (!parser.is_empty()) + parser.skip_section(); + + } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name().begins_with("library_")) + break; //end of <asset> + } +} + +void Collada::_joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner) { + + if (p_node->type == Node::TYPE_JOINT) { + + NodeJoint *nj = static_cast<NodeJoint *>(p_node); + nj->owner = p_owner; + + for (int i = 0; i < nj->children.size(); i++) { + + _joint_set_owner(nj->children.write[i], p_owner); + } + } +} + +void Collada::_create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton) { + + Node *node = *p_node; + + if (node->type == Node::TYPE_JOINT) { + + if (!p_skeleton) { + + // ohohohoohoo it's a joint node, time to work! + NodeSkeleton *sk = memnew(NodeSkeleton); + *p_node = sk; + sk->children.push_back(node); + sk->parent = node->parent; + node->parent = sk; + p_skeleton = sk; + } + + NodeJoint *nj = static_cast<NodeJoint *>(node); + nj->owner = p_skeleton; + } else { + p_skeleton = nullptr; + } + + for (int i = 0; i < node->children.size(); i++) { + _create_skeletons(&node->children.write[i], p_skeleton); + } +} + +bool Collada::_remove_node(Node *p_parent, Node *p_node) { + + for (int i = 0; i < p_parent->children.size(); i++) { + + if (p_parent->children[i] == p_node) { + p_parent->children.remove(i); + return true; + } + if (_remove_node(p_parent->children[i], p_node)) + return true; + } + + return false; +} + +void Collada::_remove_node(VisualScene *p_vscene, Node *p_node) { + + for (int i = 0; i < p_vscene->root_nodes.size(); i++) { + if (p_vscene->root_nodes[i] == p_node) { + + p_vscene->root_nodes.remove(i); + return; + } + if (_remove_node(p_vscene->root_nodes[i], p_node)) + return; + } + + ERR_PRINT("ERROR: Not found node to remove?"); +} + +void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) { + + if (p_node->type == Node::TYPE_GEOMETRY) { + + NodeGeometry *gnode = static_cast<NodeGeometry *>(p_node); + if (gnode->controller) { + + // recount skeletons used + Set<NodeSkeleton *> skeletons; + + for (int i = 0; i < gnode->skeletons.size(); i++) { + + String nodeid = gnode->skeletons[i]; + + ERR_CONTINUE(!state.scene_map.has(nodeid)); //weird, it should have it... + +#ifdef NO_SAFE_CAST + NodeJoint *nj = static_cast<NodeJoint *>(state.scene_map[nodeid]); +#else + NodeJoint *nj = dynamic_cast<NodeJoint *>(state.scene_map[nodeid]); +#endif + ERR_CONTINUE(!nj); //broken collada + ERR_CONTINUE(!nj->owner); //weird, node should have a skeleton owner + + skeletons.insert(nj->owner); + } + + if (skeletons.size() > 1) { + + //do the merger!! + Set<NodeSkeleton *>::Element *E = skeletons.front(); + NodeSkeleton *base = E->get(); + + for (E = E->next(); E; E = E->next()) { + + NodeSkeleton *merged = E->get(); + _remove_node(p_vscene, merged); + for (int i = 0; i < merged->children.size(); i++) { + + _joint_set_owner(merged->children[i], base); + base->children.push_back(merged->children[i]); + merged->children[i]->parent = base; + } + + merged->children.clear(); //take children from it + memdelete(merged); + } + } + } + } + + for (int i = 0; i < p_node->children.size(); i++) { + _merge_skeletons(p_vscene, p_node->children[i]); + } +} + +void Collada::_merge_skeletons2(VisualScene *p_vscene) { + + for (Map<String, SkinControllerData>::Element *E = state.skin_controller_data_map.front(); E; E = E->next()) { + + SkinControllerData &cd = E->get(); + + NodeSkeleton *skeleton = nullptr; + + for (Map<String, Transform>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) { + + String name; + + if (!state.sid_to_node_map.has(F->key())) { + continue; + } + + name = state.sid_to_node_map[F->key()]; + + ERR_CONTINUE(!state.scene_map.has(name)); + + Node *node = state.scene_map[name]; + ERR_CONTINUE(node->type != Node::TYPE_JOINT); + + NodeSkeleton *sk = nullptr; + + while (node && !sk) { + + if (node->type == Node::TYPE_SKELETON) { + sk = static_cast<NodeSkeleton *>(node); + } + node = node->parent; + } + + ERR_CONTINUE(!sk); + + if (!skeleton) { + skeleton = sk; + continue; + } + + if (skeleton != sk) { + //whoa.. wtf, merge. + _remove_node(p_vscene, sk); + for (int i = 0; i < sk->children.size(); i++) { + + _joint_set_owner(sk->children[i], skeleton); + skeleton->children.push_back(sk->children[i]); + sk->children[i]->parent = skeleton; + } + + sk->children.clear(); //take children from it + memdelete(sk); + } + } + } +} + +bool Collada::_optimize_skeletons(VisualScene *p_vscene, Node *p_node) { + + Node *node = p_node; + + if (node->type == Node::TYPE_SKELETON && node->parent && node->parent->type == Node::TYPE_NODE && node->parent->children.size() == 1) { + //replace parent by this... + Node *parent = node->parent; + + //i wonder if this is alright.. i think it is since created skeleton (first joint) is already animated by bone.. + node->id = parent->id; + node->name = parent->name; + node->xform_list = parent->xform_list; + node->default_transform = parent->default_transform; + + state.scene_map[node->id] = node; + node->parent = parent->parent; + + if (parent->parent) { + Node *gp = parent->parent; + bool found = false; + for (int i = 0; i < gp->children.size(); i++) { + + if (gp->children[i] == parent) { + gp->children.write[i] = node; + found = true; + break; + } + } + if (!found) { + ERR_PRINT("BUG"); + } + } else { + + bool found = false; + + for (int i = 0; i < p_vscene->root_nodes.size(); i++) { + + if (p_vscene->root_nodes[i] == parent) { + + p_vscene->root_nodes.write[i] = node; + found = true; + break; + } + } + if (!found) { + ERR_PRINT("BUG"); + } + } + + parent->children.clear(); + memdelete(parent); + return true; + } + + for (int i = 0; i < node->children.size(); i++) { + + if (_optimize_skeletons(p_vscene, node->children[i])) + return false; //stop processing, go up + } + + return false; +} + +bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, List<Node *> *p_mgeom) { + + // Bind Shape Matrix scales the bones and makes them gigantic, so the matrix then shrinks the model? + // Solution: apply the Bind Shape Matrix to the VERTICES, and if the object comes scaled, it seems to be left alone! + + if (p_node->type == Node::TYPE_GEOMETRY) { + + NodeGeometry *ng = static_cast<NodeGeometry *>(p_node); + if (ng->ignore_anim) + return false; //already made child of skeleton and processeg + + if (ng->controller && ng->skeletons.size()) { + + String nodeid = ng->skeletons[0]; + + ERR_FAIL_COND_V(!state.scene_map.has(nodeid), false); //weird, it should have it... +#ifdef NO_SAFE_CAST + NodeJoint *nj = static_cast<NodeJoint *>(state.scene_map[nodeid]); +#else + NodeJoint *nj = dynamic_cast<NodeJoint *>(state.scene_map[nodeid]); +#endif + ERR_FAIL_COND_V(!nj, false); + ERR_FAIL_COND_V(!nj->owner, false); //weird, node should have a skeleton owner + + NodeSkeleton *sk = nj->owner; + + Node *p = sk->parent; + bool node_is_parent_of_skeleton = false; + + while (p) { + if (p == p_node) { + node_is_parent_of_skeleton = true; + break; + } + p = p->parent; // try again + } + + ERR_FAIL_COND_V(node_is_parent_of_skeleton, false); + + //this should be correct + ERR_FAIL_COND_V(!state.skin_controller_data_map.has(ng->source), false); + SkinControllerData &skin = state.skin_controller_data_map[ng->source]; + Transform skel_inv = sk->get_global_transform().affine_inverse(); + p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it + + //make rests relative to the skeleton (they seem to be always relative to world) + for (Map<String, Transform>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) { + + E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton + state.bone_rest_map[E->key()] = E->get(); // make it remember where the bone is globally, now that it's relative + } + + //but most exporters seem to work only if i do this.. + //p_node->default_transform = p_node->get_global_transform(); + + //p_node->default_transform=Transform(); //this seems to be correct, because bind shape makes the object local to the skeleton + p_node->ignore_anim = true; // collada may animate this later, if it does, then this is not supported (redo your original asset and don't animate the base mesh) + p_node->parent = sk; + //sk->children.push_back(0,p_node); //avoid INFINITE loop + p_mgeom->push_back(p_node); + return true; + } + } + + for (int i = 0; i < p_node->children.size(); i++) { + + if (_move_geometry_to_skeletons(p_vscene, p_node->children[i], p_mgeom)) { + p_node->children.remove(i); + i--; + } + } + + return false; +} + +void Collada::_find_morph_nodes(VisualScene *p_vscene, Node *p_node) { + + if (p_node->type == Node::TYPE_GEOMETRY) { + + NodeGeometry *nj = static_cast<NodeGeometry *>(p_node); + + if (nj->controller) { + + String base = nj->source; + + while (base != "" && !state.mesh_data_map.has(base)) { + + if (state.skin_controller_data_map.has(base)) { + + SkinControllerData &sk = state.skin_controller_data_map[base]; + base = sk.base; + } else if (state.morph_controller_data_map.has(base)) { + + state.morph_ownership_map[base] = nj->id; + break; + } else { + ERR_FAIL_MSG("Invalid scene."); + } + } + } + } + + for (int i = 0; i < p_node->children.size(); i++) { + + _find_morph_nodes(p_vscene, p_node->children[i]); + } +} + +void Collada::_optimize() { + + for (Map<String, VisualScene>::Element *E = state.visual_scene_map.front(); E; E = E->next()) { + + VisualScene &vs = E->get(); + for (int i = 0; i < vs.root_nodes.size(); i++) { + _create_skeletons(&vs.root_nodes.write[i]); + } + + for (int i = 0; i < vs.root_nodes.size(); i++) { + _merge_skeletons(&vs, vs.root_nodes[i]); + } + + _merge_skeletons2(&vs); + + for (int i = 0; i < vs.root_nodes.size(); i++) { + _optimize_skeletons(&vs, vs.root_nodes[i]); + } + + for (int i = 0; i < vs.root_nodes.size(); i++) { + + List<Node *> mgeom; + if (_move_geometry_to_skeletons(&vs, vs.root_nodes[i], &mgeom)) { + vs.root_nodes.remove(i); + i--; + } + + while (!mgeom.empty()) { + + Node *n = mgeom.front()->get(); + n->parent->children.push_back(n); + mgeom.pop_front(); + } + } + + for (int i = 0; i < vs.root_nodes.size(); i++) { + _find_morph_nodes(&vs, vs.root_nodes[i]); + } + } +} + +int Collada::get_uv_channel(String p_name) { + + if (!channel_map.has(p_name)) { + + ERR_FAIL_COND_V(channel_map.size() == 2, 0); + + channel_map[p_name] = channel_map.size(); + } + + return channel_map[p_name]; +} + +Error Collada::load(const String &p_path, int p_flags) { + + Ref<XMLParser> parserr = memnew(XMLParser); + XMLParser &parser = *parserr.ptr(); + Error err = parser.open(p_path); + ERR_FAIL_COND_V_MSG(err, err, "Cannot open Collada file '" + p_path + "'."); + + state.local_path = ProjectSettings::get_singleton()->localize_path(p_path); + state.import_flags = p_flags; + /* Skip headers */ + while ((err = parser.read()) == OK) { + + if (parser.get_node_type() == XMLParser::NODE_ELEMENT) { + + if (parser.get_node_name() == "COLLADA") { + break; + } else if (!parser.is_empty()) + parser.skip_section(); // unknown section, likely headers + } + } + + ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CORRUPT, "Corrupted Collada file '" + p_path + "'."); + + /* Start loading Collada */ + + { + //version + String version = parser.get_attribute_value("version"); + state.version.major = version.get_slice(".", 0).to_int(); + state.version.minor = version.get_slice(".", 1).to_int(); + state.version.rev = version.get_slice(".", 2).to_int(); + COLLADA_PRINT("Collada VERSION: " + version); + } + + while ((err = parser.read()) == OK) { + + /* Read all the main sections.. */ + + if (parser.get_node_type() != XMLParser::NODE_ELEMENT) + continue; //no idea what this may be, but skipping anyway + + String section = parser.get_node_name(); + + COLLADA_PRINT("section: " + section); + + if (section == "asset") { + _parse_asset(parser); + + } else if (section.begins_with("library_")) { + + _parse_library(parser); + } else if (section == "scene") { + + _parse_scene(parser); + } else if (!parser.is_empty()) { + parser.skip_section(); // unknown section, likely headers + } + } + + _optimize(); + return OK; +} + +Collada::Collada() { +} diff --git a/editor/import/collada.h b/editor/import/collada.h new file mode 100644 index 0000000000..b74332fb22 --- /dev/null +++ b/editor/import/collada.h @@ -0,0 +1,647 @@ +/*************************************************************************/ +/* collada.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef COLLADA_H +#define COLLADA_H + +#include "core/io/xml_parser.h" +#include "core/map.h" +#include "core/project_settings.h" +#include "scene/resources/material.h" + +class Collada { +public: + enum ImportFlags { + IMPORT_FLAG_SCENE = 1, + IMPORT_FLAG_ANIMATION = 2 + }; + + struct Image { + + String path; + }; + + struct Material { + + String name; + String instance_effect; + }; + + struct Effect { + + String name; + Map<String, Variant> params; + + struct Channel { + + int uv_idx; + String texture; + Color color; + Channel() { uv_idx = 0; } + }; + + Channel diffuse, specular, emission, bump; + float shininess; + bool found_double_sided; + bool double_sided; + bool unshaded; + + String get_texture_path(const String &p_source, Collada &state) const; + + Effect() { + diffuse.color = Color(1, 1, 1, 1); + double_sided = true; + found_double_sided = false; + shininess = 40; + unshaded = false; + } + }; + + struct CameraData { + + enum Mode { + MODE_PERSPECTIVE, + MODE_ORTHOGONAL + }; + + Mode mode; + + union { + struct { + float x_fov; + float y_fov; + } perspective; + struct { + float x_mag; + float y_mag; + } orthogonal; + }; + + float aspect; + float z_near; + float z_far; + + CameraData() : + mode(MODE_PERSPECTIVE), + aspect(1), + z_near(0.1), + z_far(100) { + perspective.x_fov = 0; + perspective.y_fov = 0; + } + }; + + struct LightData { + + enum Mode { + MODE_AMBIENT, + MODE_DIRECTIONAL, + MODE_OMNI, + MODE_SPOT + }; + + Mode mode; + + Color color; + + float constant_att; + float linear_att; + float quad_att; + + float spot_angle; + float spot_exp; + + LightData() : + mode(MODE_AMBIENT), + color(Color(1, 1, 1, 1)), + constant_att(0), + linear_att(0), + quad_att(0), + spot_angle(45), + spot_exp(1) { + } + }; + + struct MeshData { + + String name; + struct Source { + + Vector<float> array; + int stride; + }; + + Map<String, Source> sources; + + struct Vertices { + + Map<String, String> sources; + }; + + Map<String, Vertices> vertices; + + struct Primitives { + + struct SourceRef { + + String source; + int offset; + }; + + String material; + Map<String, SourceRef> sources; + Vector<float> polygons; + Vector<float> indices; + int count; + int vertex_size; + }; + + Vector<Primitives> primitives; + + bool found_double_sided; + bool double_sided; + + MeshData() { + found_double_sided = false; + double_sided = true; + } + }; + + struct CurveData { + + String name; + bool closed; + + struct Source { + + Vector<String> sarray; + Vector<float> array; + int stride; + }; + + Map<String, Source> sources; + + Map<String, String> control_vertices; + + CurveData() { + + closed = false; + } + }; + struct SkinControllerData { + + String base; + bool use_idrefs; + + Transform bind_shape; + + struct Source { + + Vector<String> sarray; //maybe for names + Vector<float> array; + int stride; + Source() { + stride = 1; + } + }; + + Map<String, Source> sources; + + struct Joints { + + Map<String, String> sources; + } joints; + + struct Weights { + + struct SourceRef { + + String source; + int offset; + }; + + String material; + Map<String, SourceRef> sources; + Vector<float> sets; + Vector<float> indices; + int count; + } weights; + + Map<String, Transform> bone_rest_map; + + SkinControllerData() { use_idrefs = false; } + }; + + struct MorphControllerData { + + String mesh; + String mode; + + struct Source { + + int stride; + Vector<String> sarray; //maybe for names + Vector<float> array; + Source() { stride = 1; } + }; + + Map<String, Source> sources; + + Map<String, String> targets; + MorphControllerData() {} + }; + + struct Vertex { + + int idx; + Vector3 vertex; + Vector3 normal; + Vector3 uv; + Vector3 uv2; + Plane tangent; + Color color; + int uid; + struct Weight { + int bone_idx; + float weight; + bool operator<(const Weight w) const { return weight > w.weight; } //heaviest first + }; + + Vector<Weight> weights; + + void fix_weights() { + + weights.sort(); + if (weights.size() > 4) { + //cap to 4 and make weights add up 1 + weights.resize(4); + float total = 0; + for (int i = 0; i < 4; i++) + total += weights[i].weight; + if (total) + for (int i = 0; i < 4; i++) + weights.write[i].weight /= total; + } + } + + void fix_unit_scale(Collada &state); + + bool operator<(const Vertex &p_vert) const { + + if (uid == p_vert.uid) { + if (vertex == p_vert.vertex) { + if (normal == p_vert.normal) { + if (uv == p_vert.uv) { + if (uv2 == p_vert.uv2) { + + if (!weights.empty() || !p_vert.weights.empty()) { + + if (weights.size() == p_vert.weights.size()) { + + for (int i = 0; i < weights.size(); i++) { + if (weights[i].bone_idx != p_vert.weights[i].bone_idx) + return weights[i].bone_idx < p_vert.weights[i].bone_idx; + + if (weights[i].weight != p_vert.weights[i].weight) + return weights[i].weight < p_vert.weights[i].weight; + } + } else { + return weights.size() < p_vert.weights.size(); + } + } + + return (color < p_vert.color); + } else + return (uv2 < p_vert.uv2); + } else + return (uv < p_vert.uv); + } else + return (normal < p_vert.normal); + } else + return vertex < p_vert.vertex; + } else + return uid < p_vert.uid; + } + + Vertex() { + uid = 0; + idx = 0; + } + }; + struct Node { + + enum Type { + + TYPE_NODE, + TYPE_JOINT, + TYPE_SKELETON, //this bone is not collada, it's added afterwards as optimization + TYPE_LIGHT, + TYPE_CAMERA, + TYPE_GEOMETRY + }; + + struct XForm { + + enum Op { + OP_ROTATE, + OP_SCALE, + OP_TRANSLATE, + OP_MATRIX, + OP_VISIBILITY + }; + + String id; + Op op; + Vector<float> data; + }; + + Type type; + + String name; + String id; + String empty_draw_type; + bool noname; + Vector<XForm> xform_list; + Transform default_transform; + Transform post_transform; + Vector<Node *> children; + + Node *parent; + + Transform compute_transform(Collada &state) const; + Transform get_global_transform() const; + Transform get_transform() const; + + bool ignore_anim; + + Node() { + noname = false; + type = TYPE_NODE; + parent = nullptr; + ignore_anim = false; + } + virtual ~Node() { + for (int i = 0; i < children.size(); i++) + memdelete(children[i]); + }; + }; + + struct NodeSkeleton : public Node { + + NodeSkeleton() { type = TYPE_SKELETON; } + }; + + struct NodeJoint : public Node { + + NodeSkeleton *owner; + String sid; + NodeJoint() { + type = TYPE_JOINT; + owner = nullptr; + } + }; + + struct NodeGeometry : public Node { + + bool controller; + String source; + + struct Material { + String target; + }; + + Map<String, Material> material_map; + Vector<String> skeletons; + + NodeGeometry() { type = TYPE_GEOMETRY; } + }; + + struct NodeCamera : public Node { + + String camera; + + NodeCamera() { type = TYPE_CAMERA; } + }; + + struct NodeLight : public Node { + + String light; + + NodeLight() { type = TYPE_LIGHT; } + }; + + struct VisualScene { + + String name; + Vector<Node *> root_nodes; + + ~VisualScene() { + for (int i = 0; i < root_nodes.size(); i++) + memdelete(root_nodes[i]); + } + }; + + struct AnimationClip { + + String name; + float begin; + float end; + Vector<String> tracks; + + AnimationClip() { + begin = 0; + end = 1; + } + }; + + struct AnimationTrack { + + String id; + String target; + String param; + String component; + bool property; + + enum InterpolationType { + INTERP_LINEAR, + INTERP_BEZIER + }; + + struct Key { + + enum Type { + TYPE_FLOAT, + TYPE_MATRIX + }; + + float time; + Vector<float> data; + Point2 in_tangent; + Point2 out_tangent; + InterpolationType interp_type; + + Key() { interp_type = INTERP_LINEAR; } + }; + + Vector<float> get_value_at_time(float p_time) const; + + Vector<Key> keys; + + AnimationTrack() { property = false; } + }; + + /****************/ + /* IMPORT STATE */ + /****************/ + + struct State { + + int import_flags; + + float unit_scale; + Vector3::Axis up_axis; + bool z_up; + + struct Version { + + int major, minor, rev; + + bool operator<(const Version &p_ver) const { return (major == p_ver.major) ? ((minor == p_ver.minor) ? (rev < p_ver.rev) : minor < p_ver.minor) : major < p_ver.major; } + Version(int p_major = 0, int p_minor = 0, int p_rev = 0) { + major = p_major; + minor = p_minor; + rev = p_rev; + } + } version; + + Map<String, CameraData> camera_data_map; + Map<String, MeshData> mesh_data_map; + Map<String, LightData> light_data_map; + Map<String, CurveData> curve_data_map; + + Map<String, String> mesh_name_map; + Map<String, String> morph_name_map; + Map<String, String> morph_ownership_map; + Map<String, SkinControllerData> skin_controller_data_map; + Map<String, MorphControllerData> morph_controller_data_map; + + Map<String, Image> image_map; + Map<String, Material> material_map; + Map<String, Effect> effect_map; + + Map<String, VisualScene> visual_scene_map; + Map<String, Node *> scene_map; + Set<String> idref_joints; + Map<String, String> sid_to_node_map; + //Map<String,NodeJoint*> bone_map; + + Map<String, Transform> bone_rest_map; + + String local_path; + String root_visual_scene; + String root_physics_scene; + + Vector<AnimationClip> animation_clips; + Vector<AnimationTrack> animation_tracks; + Map<String, Vector<int>> referenced_tracks; + Map<String, Vector<int>> by_id_tracks; + + float animation_length; + + State() : + import_flags(0), + unit_scale(1.0), + up_axis(Vector3::AXIS_Y), + animation_length(0) { + } + } state; + + Error load(const String &p_path, int p_flags = 0); + + Collada(); + + Transform fix_transform(const Transform &p_transform); + + Transform get_root_transform() const; + + int get_uv_channel(String p_name); + +private: // private stuff + Map<String, int> channel_map; + + void _parse_asset(XMLParser &parser); + void _parse_image(XMLParser &parser); + void _parse_material(XMLParser &parser); + void _parse_effect_material(XMLParser &parser, Effect &effect, String &id); + void _parse_effect(XMLParser &parser); + void _parse_camera(XMLParser &parser); + void _parse_light(XMLParser &parser); + void _parse_animation_clip(XMLParser &parser); + + void _parse_mesh_geometry(XMLParser &parser, String p_id, String p_name); + void _parse_curve_geometry(XMLParser &parser, String p_id, String p_name); + + void _parse_skin_controller(XMLParser &parser, String p_id); + void _parse_morph_controller(XMLParser &parser, String p_id); + void _parse_controller(XMLParser &parser); + + Node *_parse_visual_instance_geometry(XMLParser &parser); + Node *_parse_visual_instance_camera(XMLParser &parser); + Node *_parse_visual_instance_light(XMLParser &parser); + + Node *_parse_visual_node_instance_data(XMLParser &parser); + Node *_parse_visual_scene_node(XMLParser &parser); + void _parse_visual_scene(XMLParser &parser); + + void _parse_animation(XMLParser &parser); + void _parse_scene(XMLParser &parser); + void _parse_library(XMLParser &parser); + + Variant _parse_param(XMLParser &parser); + Vector<float> _read_float_array(XMLParser &parser); + Vector<String> _read_string_array(XMLParser &parser); + Transform _read_transform(XMLParser &parser); + String _read_empty_draw_type(XMLParser &parser); + + void _joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner); + void _create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton = nullptr); + void _find_morph_nodes(VisualScene *p_vscene, Node *p_node); + bool _remove_node(Node *p_parent, Node *p_node); + void _remove_node(VisualScene *p_vscene, Node *p_node); + void _merge_skeletons2(VisualScene *p_vscene); + void _merge_skeletons(VisualScene *p_vscene, Node *p_node); + bool _optimize_skeletons(VisualScene *p_vscene, Node *p_node); + + bool _move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, List<Node *> *p_mgeom); + + void _optimize(); +}; + +#endif // COLLADA_H diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 3cc6e7a50c..697ddfba96 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -31,14 +31,14 @@ #include "editor_import_collada.h" #include "core/os/os.h" -#include "editor/collada/collada.h" #include "editor/editor_node.h" -#include "scene/3d/camera.h" -#include "scene/3d/light.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/path.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "editor/import/collada.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/light_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/path_3d.h" +#include "scene/3d/skeleton_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" #include "scene/resources/packed_scene.h" @@ -47,18 +47,18 @@ struct ColladaImport { Collada collada; - Spatial *scene; + Node3D *scene; Vector<Ref<Animation>> animations; struct NodeMap { //String path; - Spatial *node; + Node3D *node; int bone; List<int> anim_tracks; NodeMap() { - node = NULL; + node = nullptr; bone = -1; } }; @@ -76,17 +76,17 @@ struct ColladaImport { Map<String, Ref<ArrayMesh>> mesh_cache; Map<String, Ref<Curve3D>> curve_cache; Map<String, Ref<Material>> material_cache; - Map<Collada::Node *, Skeleton *> skeleton_map; + Map<Collada::Node *, Skeleton3D *> skeleton_map; - Map<Skeleton *, Map<String, int>> skeleton_bone_map; + Map<Skeleton3D *, Map<String, int>> skeleton_bone_map; Set<String> valid_animated_nodes; Vector<int> valid_animated_properties; Map<String, bool> bones_with_animation; - Error _populate_skeleton(Skeleton *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent); + Error _populate_skeleton(Skeleton3D *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent); Error _create_scene_skeletons(Collada::Node *p_node); - Error _create_scene(Collada::Node *p_node, Spatial *p_parent); + Error _create_scene(Collada::Node *p_node, Node3D *p_parent); Error _create_resources(Collada::Node *p_node, bool p_use_compression); Error _create_material(const String &p_target); Error _create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<ArrayMesh>> p_morph_meshes = Vector<Ref<ArrayMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false); @@ -110,7 +110,7 @@ struct ColladaImport { } }; -Error ColladaImport::_populate_skeleton(Skeleton *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent) { +Error ColladaImport::_populate_skeleton(Skeleton3D *p_skeleton, Collada::Node *p_node, int &r_bone, int p_parent) { if (p_node->type != Collada::Node::TYPE_JOINT) return OK; @@ -174,7 +174,7 @@ Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) { if (p_node->type == Collada::Node::TYPE_SKELETON) { - Skeleton *sk = memnew(Skeleton); + Skeleton3D *sk = memnew(Skeleton3D); int bone = 0; for (int i = 0; i < p_node->children.size(); i++) { @@ -193,15 +193,15 @@ Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) { return OK; } -Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { +Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) { - Spatial *node = NULL; + Node3D *node = nullptr; switch (p_node->type) { case Collada::Node::TYPE_NODE: { - node = memnew(Spatial); + node = memnew(Node3D); } break; case Collada::Node::TYPE_JOINT: { @@ -223,7 +223,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { if (!bool(GLOBAL_DEF("collada/use_ambient", false))) return OK; //well, it's an ambient light.. - Light *l = memnew(DirectionalLight); + Light3D *l = memnew(DirectionalLight3D); //l->set_color(Light::COLOR_AMBIENT,ld.color); //l->set_color(Light::COLOR_DIFFUSE,Color(0,0,0)); //l->set_color(Light::COLOR_SPECULAR,Color(0,0,0)); @@ -232,7 +232,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { } else if (ld.mode == Collada::LightData::MODE_DIRECTIONAL) { //well, it's an ambient light.. - Light *l = memnew(DirectionalLight); + Light3D *l = memnew(DirectionalLight3D); /* if (found_ambient) //use it here l->set_color(Light::COLOR_AMBIENT,ambient); @@ -243,12 +243,12 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { node = l; } else { - Light *l; + Light3D *l; if (ld.mode == Collada::LightData::MODE_OMNI) - l = memnew(OmniLight); + l = memnew(OmniLight3D); else { - l = memnew(SpotLight); + l = memnew(SpotLight3D); //l->set_parameter(Light::PARAM_SPOT_ANGLE,ld.spot_angle); //l->set_parameter(Light::PARAM_SPOT_ATTENUATION,ld.spot_exp); } @@ -262,13 +262,13 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { } else { - node = memnew(Spatial); + node = memnew(Node3D); } } break; case Collada::Node::TYPE_CAMERA: { Collada::NodeCamera *cam = static_cast<Collada::NodeCamera *>(p_node); - Camera *camera = memnew(Camera); + Camera3D *camera = memnew(Camera3D); if (collada.state.camera_data_map.has(cam->camera)) { @@ -280,12 +280,12 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { if (cd.orthogonal.y_mag) { - camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT); + camera->set_keep_aspect_mode(Camera3D::KEEP_HEIGHT); camera->set_orthogonal(cd.orthogonal.y_mag * 2.0, cd.z_near, cd.z_far); } else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) { - camera->set_keep_aspect_mode(Camera::KEEP_WIDTH); + camera->set_keep_aspect_mode(Camera3D::KEEP_WIDTH); camera->set_orthogonal(cd.orthogonal.x_mag * 2.0, cd.z_near, cd.z_far); } @@ -314,17 +314,17 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { if (collada.state.curve_data_map.has(ng->source)) { - node = memnew(Path); + node = memnew(Path3D); } else { //mesh since nothing else - node = memnew(MeshInstance); - //Object::cast_to<MeshInstance>(node)->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true); + node = memnew(MeshInstance3D); + //Object::cast_to<MeshInstance3D>(node)->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true); } } break; case Collada::Node::TYPE_SKELETON: { ERR_FAIL_COND_V(!skeleton_map.has(p_node), ERR_CANT_CREATE); - Skeleton *sk = skeleton_map[p_node]; + Skeleton3D *sk = skeleton_map[p_node]; node = sk; } break; } @@ -536,7 +536,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me /* NORMAL SOURCE */ - const Collada::MeshData::Source *normal_src = NULL; + const Collada::MeshData::Source *normal_src = nullptr; int normal_ofs = 0; if (p.sources.has("NORMAL")) { @@ -547,7 +547,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me normal_src = &meshdata.sources[normal_source_id]; } - const Collada::MeshData::Source *binormal_src = NULL; + const Collada::MeshData::Source *binormal_src = nullptr; int binormal_ofs = 0; if (p.sources.has("TEXBINORMAL")) { @@ -558,7 +558,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me binormal_src = &meshdata.sources[binormal_source_id]; } - const Collada::MeshData::Source *tangent_src = NULL; + const Collada::MeshData::Source *tangent_src = nullptr; int tangent_ofs = 0; if (p.sources.has("TEXTANGENT")) { @@ -569,7 +569,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me tangent_src = &meshdata.sources[tangent_source_id]; } - const Collada::MeshData::Source *uv_src = NULL; + const Collada::MeshData::Source *uv_src = nullptr; int uv_ofs = 0; if (p.sources.has("TEXCOORD0")) { @@ -580,7 +580,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me uv_src = &meshdata.sources[uv_source_id]; } - const Collada::MeshData::Source *uv2_src = NULL; + const Collada::MeshData::Source *uv2_src = nullptr; int uv2_ofs = 0; if (p.sources.has("TEXCOORD1")) { @@ -591,7 +591,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me uv2_src = &meshdata.sources[uv2_source_id]; } - const Collada::MeshData::Source *color_src = NULL; + const Collada::MeshData::Source *color_src = nullptr; int color_ofs = 0; if (p.sources.has("COLOR")) { @@ -614,7 +614,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me if (p_skin_controller) { - const Collada::SkinControllerData::Source *weight_src = NULL; + const Collada::SkinControllerData::Source *weight_src = nullptr; int weight_ofs = 0; if (p_skin_controller->weights.sources.has("WEIGHT")) { @@ -922,10 +922,10 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me if (has_weights) { Vector<float> weights; Vector<int> bones; - weights.resize(VS::ARRAY_WEIGHTS_SIZE); - bones.resize(VS::ARRAY_WEIGHTS_SIZE); + weights.resize(RS::ARRAY_WEIGHTS_SIZE); + bones.resize(RS::ARRAY_WEIGHTS_SIZE); //float sum=0.0; - for (int l = 0; l < VS::ARRAY_WEIGHTS_SIZE; l++) { + for (int l = 0; l < RS::ARRAY_WEIGHTS_SIZE; l++) { if (l < vertex_array[k].weights.size()) { weights.write[l] = vertex_array[k].weights[l].weight; bones.write[l] = vertex_array[k].weights[l].bone_idx; @@ -963,7 +963,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me //////////////////////////// Array d = surftool->commit_to_arrays(); - d.resize(VS::ARRAY_MAX); + d.resize(RS::ARRAY_MAX); Array mr; @@ -1010,12 +1010,12 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres if (p_node->type == Collada::Node::TYPE_GEOMETRY && node_map.has(p_node->id)) { - Spatial *node = node_map[p_node->id].node; + Node3D *node = node_map[p_node->id].node; Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry *>(p_node); - if (Object::cast_to<Path>(node)) { + if (Object::cast_to<Path3D>(node)) { - Path *path = Object::cast_to<Path>(node); + Path3D *path = Object::cast_to<Path3D>(node); if (curve_cache.has(ng->source)) { @@ -1047,7 +1047,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres const Collada::CurveData::Source &interps = cd.sources[cd.control_vertices["INTERPOLATION"]]; ERR_FAIL_COND_V(interps.stride != 1, ERR_INVALID_DATA); - const Collada::CurveData::Source *tilts = NULL; + const Collada::CurveData::Source *tilts = nullptr; if (cd.control_vertices.has("TILT") && cd.sources.has(cd.control_vertices["TILT"])) tilts = &cd.sources[cd.control_vertices["TILT"]]; @@ -1083,16 +1083,16 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres } } - if (Object::cast_to<MeshInstance>(node)) { + if (Object::cast_to<MeshInstance3D>(node)) { Collada::NodeGeometry *ng2 = static_cast<Collada::NodeGeometry *>(p_node); - MeshInstance *mi = Object::cast_to<MeshInstance>(node); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(node); ERR_FAIL_COND_V(!mi, ERR_BUG); - Collada::SkinControllerData *skin = NULL; - Collada::MorphControllerData *morph = NULL; + Collada::SkinControllerData *skin = nullptr; + Collada::MorphControllerData *morph = nullptr; String meshid; Transform apply_xform; Vector<int> bone_remap; @@ -1114,7 +1114,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres String skname = skeletons[0]; ERR_FAIL_COND_V(!node_map.has(skname), ERR_INVALID_DATA); NodeMap nmsk = node_map[skname]; - Skeleton *sk = Object::cast_to<Skeleton>(nmsk.node); + Skeleton3D *sk = Object::cast_to<Skeleton3D>(nmsk.node); ERR_FAIL_COND_V(!sk, ERR_INVALID_DATA); ERR_FAIL_COND_V(!skeleton_bone_map.has(sk), ERR_INVALID_DATA); Map<String, int> &bone_remap_map = skeleton_bone_map[sk]; @@ -1173,7 +1173,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres Ref<ArrayMesh> mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid2]; mesh->set_name(meshdata.name); - Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, NULL, Vector<Ref<ArrayMesh>>(), false); + Error err = _create_mesh_surfaces(false, mesh, ng2->material_map, meshdata, apply_xform, bone_remap, skin, nullptr, Vector<Ref<ArrayMesh>>(), false); ERR_FAIL_COND_V(err, err); morphs.push_back(mesh); @@ -1265,7 +1265,7 @@ Error ColladaImport::load(const String &p_path, int p_flags, bool p_force_make_t ERR_FAIL_COND_V(!collada.state.visual_scene_map.has(collada.state.root_visual_scene), ERR_INVALID_DATA); Collada::VisualScene &vs = collada.state.visual_scene_map[collada.state.root_visual_scene]; - scene = memnew(Spatial); // root + scene = memnew(Node3D); // root //determine what's going on with the lights for (int i = 0; i < vs.root_nodes.size(); i++) { @@ -1530,7 +1530,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones String path = scene->get_path_to(nm.node); if (nm.bone >= 0) { - Skeleton *sk = static_cast<Skeleton *>(nm.node); + Skeleton3D *sk = static_cast<Skeleton3D *>(nm.node); String name = sk->get_bone_name(nm.bone); path = path + ":" + name; } @@ -1621,7 +1621,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones if (nm.bone >= 0) { //make bone transform relative to rest (in case of skeleton) - Skeleton *sk = Object::cast_to<Skeleton>(nm.node); + Skeleton3D *sk = Object::cast_to<Skeleton3D>(nm.node); if (sk) { xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform; @@ -1662,7 +1662,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones NodeMap &nm = node_map[E->key()]; String path = scene->get_path_to(nm.node); ERR_CONTINUE(nm.bone < 0); - Skeleton *sk = static_cast<Skeleton *>(nm.node); + Skeleton3D *sk = static_cast<Skeleton3D *>(nm.node); String name = sk->get_bone_name(nm.bone); path = path + ":" + name; @@ -1777,7 +1777,7 @@ Node *EditorSceneImporterCollada::import_scene(const String &p_path, uint32_t p_ Error err = state.load(p_path, flags, p_flags & EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_flags & EditorSceneImporter::IMPORT_USE_COMPRESSION); - ERR_FAIL_COND_V_MSG(err != OK, NULL, "Cannot load scene from file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, nullptr, "Cannot load scene from file '" + p_path + "'."); if (state.missing_textures.size()) { diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h index 822a6450be..932a064e76 100644 --- a/editor/import/editor_import_collada.h +++ b/editor/import/editor_import_collada.h @@ -40,7 +40,7 @@ class EditorSceneImporterCollada : public EditorSceneImporter { public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = NULL, Error *r_err = NULL); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr); virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); EditorSceneImporterCollada(); diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index 4383b1b084..be4679b6d3 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -52,7 +52,7 @@ public: virtual int get_import_order() const; virtual void get_import_options(List<ImportOption> *r_options, int p_preset) const; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) 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, Variant *r_metadata = NULL); + 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, Variant *r_metadata = nullptr); }; #endif //EDITOR_IMPORT_PLUGIN_H diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index 398fc9ff49..6ad2aa4142 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -37,9 +37,9 @@ #include "core/os/file_access.h" #include "core/os/os.h" #include "modules/regex/regex.h" -#include "scene/3d/bone_attachment.h" -#include "scene/3d/camera.h" -#include "scene/3d/mesh_instance.h" +#include "scene/3d/bone_attachment_3d.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/mesh_instance_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/surface_tool.h" @@ -1266,7 +1266,7 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b } Vector<uint8_t> data; - const uint8_t *data_ptr = NULL; + const uint8_t *data_ptr = nullptr; int data_size = 0; if (d.has("uri")) { @@ -1307,7 +1307,7 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b if (mimetype.findn("png") != -1) { //is a png - ERR_FAIL_COND_V(Image::_png_mem_loader_func == NULL, ERR_UNAVAILABLE); + ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, ERR_UNAVAILABLE); const Ref<Image> img = Image::_png_mem_loader_func(data_ptr, data_size); @@ -1323,7 +1323,7 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b if (mimetype.findn("jpeg") != -1) { //is a jpg - ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == NULL, ERR_UNAVAILABLE); + ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, ERR_UNAVAILABLE); const Ref<Image> img = Image::_jpg_mem_loader_func(data_ptr, data_size); @@ -2108,7 +2108,7 @@ Error EditorSceneImporterGLTF::_create_skeletons(GLTFState &state) { GLTFSkeleton &gltf_skeleton = state.skeletons.write[skel_i]; - Skeleton *skeleton = memnew(Skeleton); + Skeleton3D *skeleton = memnew(Skeleton3D); gltf_skeleton.godot_skeleton = skeleton; // Make a unique name, no gltf node represents this skeleton @@ -2485,12 +2485,12 @@ void EditorSceneImporterGLTF::_assign_scene_names(GLTFState &state) { } } -BoneAttachment *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &state, Skeleton *skeleton, const GLTFNodeIndex node_index) { +BoneAttachment3D *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &state, Skeleton3D *skeleton, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; const GLTFNode *bone_node = state.nodes[gltf_node->parent]; - BoneAttachment *bone_attachment = memnew(BoneAttachment); + BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D); print_verbose("glTF: Creating bone attachment for: " + gltf_node->name); ERR_FAIL_COND_V(!bone_node->joint, nullptr); @@ -2500,12 +2500,12 @@ BoneAttachment *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &st return bone_attachment; } -MeshInstance *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { +MeshInstance3D *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->mesh, state.meshes.size(), nullptr); - MeshInstance *mi = memnew(MeshInstance); + MeshInstance3D *mi = memnew(MeshInstance3D); print_verbose("glTF: Creating mesh for: " + gltf_node->name); GLTFMesh &mesh = state.meshes.write[gltf_node->mesh]; @@ -2522,12 +2522,12 @@ MeshInstance *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, return mi; } -Camera *EditorSceneImporterGLTF::_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { +Camera3D *EditorSceneImporterGLTF::_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->camera, state.cameras.size(), nullptr); - Camera *camera = memnew(Camera); + Camera3D *camera = memnew(Camera3D); print_verbose("glTF: Creating camera for: " + gltf_node->name); const GLTFCamera &c = state.cameras[gltf_node->camera]; @@ -2540,26 +2540,26 @@ Camera *EditorSceneImporterGLTF::_generate_camera(GLTFState &state, Node *scene_ return camera; } -Spatial *EditorSceneImporterGLTF::_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { +Node3D *EditorSceneImporterGLTF::_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; - Spatial *spatial = memnew(Spatial); + Node3D *spatial = memnew(Node3D); print_verbose("glTF: Creating spatial for: " + gltf_node->name); return spatial; } -void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index) { +void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) { const GLTFNode *gltf_node = state.nodes[node_index]; - Spatial *current_node = nullptr; + Node3D *current_node = nullptr; // Is our parent a skeleton - Skeleton *active_skeleton = Object::cast_to<Skeleton>(scene_parent); + Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(scene_parent); if (gltf_node->skeleton >= 0) { - Skeleton *skeleton = state.skeletons[gltf_node->skeleton].godot_skeleton; + Skeleton3D *skeleton = state.skeletons[gltf_node->skeleton].godot_skeleton; if (active_skeleton != skeleton) { ERR_FAIL_COND_MSG(active_skeleton != nullptr, "glTF: Generating scene detected direct parented Skeletons"); @@ -2577,7 +2577,7 @@ void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene // If we have an active skeleton, and the node is node skinned, we need to create a bone attachment if (current_node == nullptr && active_skeleton != nullptr && gltf_node->skin < 0) { - BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index); + BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index); scene_parent->add_child(bone_attachment); bone_attachment->set_owner(scene_root); @@ -2776,7 +2776,7 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye const GLTFNode *node = state.nodes[E->key()]; if (node->skeleton >= 0) { - const Skeleton *sk = Object::cast_to<Skeleton>(state.scene_nodes.find(node_index)->get()); + const Skeleton3D *sk = Object::cast_to<Skeleton3D>(state.scene_nodes.find(node_index)->get()); ERR_FAIL_COND(sk == nullptr); const String path = ap->get_parent()->get_path_to(sk); @@ -2853,7 +2853,7 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye xform.basis.set_quat_scale(rot, scale); xform.origin = pos; - const Skeleton *skeleton = state.skeletons[node->skeleton].godot_skeleton; + const Skeleton3D *skeleton = state.skeletons[node->skeleton].godot_skeleton; const int bone_idx = skeleton->find_bone(node->name); xform = skeleton->get_bone_rest(bone_idx).affine_inverse() * xform; @@ -2922,7 +2922,7 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye ap->add_animation(name, animation); } -void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Spatial *scene_root) { +void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Node3D *scene_root) { for (GLTFNodeIndex node_i = 0; node_i < state.nodes.size(); ++node_i) { const GLTFNode *node = state.nodes[node_i]; @@ -2930,12 +2930,12 @@ void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Spatial const GLTFSkinIndex skin_i = node->skin; Map<GLTFNodeIndex, Node *>::Element *mi_element = state.scene_nodes.find(node_i); - MeshInstance *mi = Object::cast_to<MeshInstance>(mi_element->get()); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->get()); ERR_FAIL_COND(mi == nullptr); const GLTFSkeletonIndex skel_i = state.skins[node->skin].skeleton; const GLTFSkeleton &gltf_skeleton = state.skeletons[skel_i]; - Skeleton *skeleton = gltf_skeleton.godot_skeleton; + Skeleton3D *skeleton = gltf_skeleton.godot_skeleton; ERR_FAIL_COND(skeleton == nullptr); mi->get_parent()->remove_child(mi); @@ -2949,9 +2949,9 @@ void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Spatial } } -Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, const int p_bake_fps) { +Node3D *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, const int p_bake_fps) { - Spatial *root = memnew(Spatial); + Node3D *root = memnew(Node3D); // scene_name is already unique root->set_name(state.scene_name); @@ -2985,19 +2985,19 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla //text file Error err = _parse_glb(p_path, state); if (err) - return NULL; + return nullptr; } else { //text file Error err = _parse_json(p_path, state); if (err) - return NULL; + return nullptr; } - ERR_FAIL_COND_V(!state.json.has("asset"), NULL); + ERR_FAIL_COND_V(!state.json.has("asset"), nullptr); Dictionary asset = state.json["asset"]; - ERR_FAIL_COND_V(!asset.has("version"), NULL); + ERR_FAIL_COND_V(!asset.has("version"), nullptr); String version = asset["version"]; @@ -3008,83 +3008,83 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla /* STEP 0 PARSE SCENE */ Error err = _parse_scenes(state); if (err != OK) - return NULL; + return nullptr; /* STEP 1 PARSE NODES */ err = _parse_nodes(state); if (err != OK) - return NULL; + return nullptr; /* STEP 2 PARSE BUFFERS */ err = _parse_buffers(state, p_path.get_base_dir()); if (err != OK) - return NULL; + return nullptr; /* STEP 3 PARSE BUFFER VIEWS */ err = _parse_buffer_views(state); if (err != OK) - return NULL; + return nullptr; /* STEP 4 PARSE ACCESSORS */ err = _parse_accessors(state); if (err != OK) - return NULL; + return nullptr; /* STEP 5 PARSE IMAGES */ err = _parse_images(state, p_path.get_base_dir()); if (err != OK) - return NULL; + return nullptr; /* STEP 6 PARSE TEXTURES */ err = _parse_textures(state); if (err != OK) - return NULL; + return nullptr; /* STEP 7 PARSE TEXTURES */ err = _parse_materials(state); if (err != OK) - return NULL; + return nullptr; /* STEP 9 PARSE SKINS */ err = _parse_skins(state); if (err != OK) - return NULL; + return nullptr; /* STEP 10 DETERMINE SKELETONS */ err = _determine_skeletons(state); if (err != OK) - return NULL; + return nullptr; /* STEP 11 CREATE SKELETONS */ err = _create_skeletons(state); if (err != OK) - return NULL; + return nullptr; /* STEP 12 CREATE SKINS */ err = _create_skins(state); if (err != OK) - return NULL; + return nullptr; /* STEP 13 PARSE MESHES (we have enough info now) */ err = _parse_meshes(state); if (err != OK) - return NULL; + return nullptr; /* STEP 14 PARSE CAMERAS */ err = _parse_cameras(state); if (err != OK) - return NULL; + return nullptr; /* STEP 15 PARSE ANIMATIONS */ err = _parse_animations(state); if (err != OK) - return NULL; + return nullptr; /* STEP 16 ASSIGN SCENE NAMES */ _assign_scene_names(state); /* STEP 17 MAKE SCENE! */ - Spatial *scene = _generate_scene(state, p_bake_fps); + Node3D *scene = _generate_scene(state, p_bake_fps); return scene; } diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h index 9f354fde2d..d127a87782 100644 --- a/editor/import/editor_scene_importer_gltf.h +++ b/editor/import/editor_scene_importer_gltf.h @@ -32,12 +32,12 @@ #define EDITOR_SCENE_IMPORTER_GLTF_H #include "editor/import/resource_importer_scene.h" -#include "scene/3d/skeleton.h" -#include "scene/3d/spatial.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" class AnimationPlayer; -class BoneAttachment; -class MeshInstance; +class BoneAttachment3D; +class MeshInstance3D; class EditorSceneImporterGLTF : public EditorSceneImporter { @@ -192,7 +192,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Vector<GLTFNodeIndex> roots; // The created Skeleton for the scene - Skeleton *godot_skeleton; + Skeleton3D *godot_skeleton; // Set of unique bone names for the skeleton Set<String> unique_names; @@ -395,15 +395,15 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Error _parse_animations(GLTFState &state); - BoneAttachment *_generate_bone_attachment(GLTFState &state, Skeleton *skeleton, const GLTFNodeIndex node_index); - MeshInstance *_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); - Camera *_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); - Spatial *_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); + BoneAttachment3D *_generate_bone_attachment(GLTFState &state, Skeleton3D *skeleton, const GLTFNodeIndex node_index); + MeshInstance3D *_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); + Camera3D *_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); + Node3D *_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index); - void _generate_scene_node(GLTFState &state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index); - Spatial *_generate_scene(GLTFState &state, const int p_bake_fps); + void _generate_scene_node(GLTFState &state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index); + Node3D *_generate_scene(GLTFState &state, const int p_bake_fps); - void _process_mesh_instances(GLTFState &state, Spatial *scene_root); + void _process_mesh_instances(GLTFState &state, Node3D *scene_root); void _assign_scene_names(GLTFState &state); @@ -415,7 +415,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = NULL, Error *r_err = NULL); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr); virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); EditorSceneImporterGLTF(); diff --git a/editor/import/resource_importer_bitmask.h b/editor/import/resource_importer_bitmask.h index dd95cb687a..927fac566e 100644 --- a/editor/import/resource_importer_bitmask.h +++ b/editor/import/resource_importer_bitmask.h @@ -51,7 +51,7 @@ public: 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 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(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 = nullptr, Variant *r_metadata = nullptr); ResourceImporterBitMap(); ~ResourceImporterBitMap(); diff --git a/editor/import/resource_importer_csv.h b/editor/import/resource_importer_csv.h index 2030dd1f99..7aa48f68de 100644 --- a/editor/import/resource_importer_csv.h +++ b/editor/import/resource_importer_csv.h @@ -49,7 +49,7 @@ public: 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 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(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 = nullptr, Variant *r_metadata = nullptr); ResourceImporterCSV(); }; diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h index ec33d6aa16..742f6b8f60 100644 --- a/editor/import/resource_importer_csv_translation.h +++ b/editor/import/resource_importer_csv_translation.h @@ -49,7 +49,7 @@ public: 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 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(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 = nullptr, Variant *r_metadata = nullptr); ResourceImporterCSVTranslation(); }; diff --git a/editor/import/resource_importer_image.h b/editor/import/resource_importer_image.h index 6ad77eec1b..abb74d0665 100644 --- a/editor/import/resource_importer_image.h +++ b/editor/import/resource_importer_image.h @@ -50,7 +50,7 @@ public: 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 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(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 = nullptr, Variant *r_metadata = nullptr); ResourceImporterImage(); }; diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index d472070808..a4cbc81b26 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -259,7 +259,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const Ref<Image> image; image.instance(); - Error err = ImageLoader::load_image(p_source_file, image, NULL, false, 1.0); + Error err = ImageLoader::load_image(p_source_file, image, nullptr, false, 1.0); if (err != OK) return err; @@ -383,7 +383,7 @@ const char *ResourceImporterLayeredTexture::compression_formats[] = { "etc", "etc2", "pvrtc", - NULL + nullptr }; String ResourceImporterLayeredTexture::get_import_settings_string() const { @@ -438,7 +438,7 @@ bool ResourceImporterLayeredTexture::are_import_settings_valid(const String &p_p return valid; } -ResourceImporterLayeredTexture *ResourceImporterLayeredTexture::singleton = NULL; +ResourceImporterLayeredTexture *ResourceImporterLayeredTexture::singleton = nullptr; ResourceImporterLayeredTexture::ResourceImporterLayeredTexture() { diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 6a6bc89a81..40e5c9023e 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -114,7 +114,7 @@ public: void _save_tex(const Vector<Ref<Image> > &p_images, const String &p_to_path, int p_compress_mode, Image::CompressMode p_vram_compression, bool p_mipmaps); - 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(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 = nullptr, Variant *r_metadata = nullptr); void update_imports(); diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index fb1782cb65..6a6eadfa5c 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -32,8 +32,8 @@ #include "core/io/resource_saver.h" #include "core/os/file_access.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/spatial.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" #include "scene/resources/mesh.h" #include "scene/resources/surface_tool.h" @@ -428,14 +428,14 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in if (r_err) { *r_err = err; } - return NULL; + return nullptr; } - Spatial *scene = memnew(Spatial); + Node3D *scene = memnew(Node3D); for (List<Ref<Mesh>>::Element *E = meshes.front(); E; E = E->next()) { - MeshInstance *mi = memnew(MeshInstance); + MeshInstance3D *mi = memnew(MeshInstance3D); mi->set_mesh(E->get()); mi->set_name(E->get()->get_name()); scene->add_child(mi); @@ -502,7 +502,7 @@ Error ResourceImporterOBJ::import(const String &p_source_file, const String &p_s List<Ref<Mesh>> meshes; - Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["optimize_mesh"], p_options["scale_mesh"], p_options["offset_mesh"], NULL); + Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], p_options["optimize_mesh"], p_options["scale_mesh"], p_options["offset_mesh"], nullptr); ERR_FAIL_COND_V(err != OK, err); ERR_FAIL_COND_V(meshes.size() != 1, ERR_BUG); diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h index 678be45106..7485e60f7b 100644 --- a/editor/import/resource_importer_obj.h +++ b/editor/import/resource_importer_obj.h @@ -40,7 +40,7 @@ class EditorOBJImporter : public EditorSceneImporter { public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); EditorOBJImporter(); @@ -62,7 +62,7 @@ public: 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 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(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 = nullptr, Variant *r_metadata = nullptr); ResourceImporterOBJ(); }; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 94a6fee6b7..b5766a48a0 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -32,19 +32,19 @@ #include "core/io/resource_saver.h" #include "editor/editor_node.h" -#include "scene/3d/collision_shape.h" -#include "scene/3d/mesh_instance.h" -#include "scene/3d/navigation.h" -#include "scene/3d/physics_body.h" -#include "scene/3d/vehicle_body.h" +#include "scene/3d/collision_shape_3d.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/navigation_3d.h" +#include "scene/3d/physics_body_3d.h" +#include "scene/3d/vehicle_body_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/animation.h" -#include "scene/resources/box_shape.h" +#include "scene/resources/box_shape_3d.h" #include "scene/resources/packed_scene.h" -#include "scene/resources/ray_shape.h" +#include "scene/resources/ray_shape_3d.h" #include "scene/resources/resource_format_text.h" -#include "scene/resources/sphere_shape.h" -#include "scene/resources/world_margin_shape.h" +#include "scene/resources/sphere_shape_3d.h" +#include "scene/resources/world_margin_shape_3d.h" uint32_t EditorSceneImporter::get_import_flags() const { @@ -72,7 +72,7 @@ Node *EditorSceneImporter::import_scene(const String &p_path, uint32_t p_flags, return get_script_instance()->call("_import_scene", p_path, p_flags, p_bake_fps); } - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) { @@ -81,7 +81,7 @@ Ref<Animation> EditorSceneImporter::import_animation(const String &p_path, uint3 return get_script_instance()->call("_import_animation", p_path, p_flags); } - ERR_FAIL_V(NULL); + ERR_FAIL_V(nullptr); } //for documenters, these functions are useful when an importer calls an external conversion helper (like, fbx2gltf), @@ -276,15 +276,15 @@ static String _fixstr(const String &p_what, const String &p_str) { return what; } -static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape>> &r_shape_list, bool p_convex) { +static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape3D>> &r_shape_list, bool p_convex) { if (!p_convex) { - Ref<Shape> shape = mesh->create_trimesh_shape(); + Ref<Shape3D> shape = mesh->create_trimesh_shape(); r_shape_list.push_back(shape); } else { - Vector<Ref<Shape>> cd = mesh->convex_decompose(); + Vector<Ref<Shape3D>> cd = mesh->convex_decompose(); if (cd.size()) { for (int i = 0; i < cd.size(); i++) { r_shape_list.push_back(cd[i]); @@ -293,7 +293,7 @@ static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape>> &r_shape_lis } } -Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, LightBakeMode p_light_bake_mode) { +Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape3D>>> &collision_map, LightBakeMode p_light_bake_mode) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { @@ -311,12 +311,12 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> if (!isroot && _teststr(name, "noimp")) { memdelete(p_node); - return NULL; + return nullptr; } - if (Object::cast_to<MeshInstance>(p_node)) { + if (Object::cast_to<MeshInstance3D>(p_node)) { - MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); Ref<ArrayMesh> m = mi->get_mesh(); @@ -344,7 +344,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> if (p_light_bake_mode != LIGHT_BAKE_DISABLED) { - mi->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true); + mi->set_flag(GeometryInstance3D::FLAG_USE_BAKED_LIGHT, true); } } @@ -377,12 +377,12 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> if (isroot) return p_node; - MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); if (mi) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape>> shapes; + List<Ref<Shape3D>> shapes; String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; @@ -400,11 +400,11 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> fixed_name = _fixstr(name, "convcolonly"); } - ERR_FAIL_COND_V(fixed_name == String(), NULL); + ERR_FAIL_COND_V(fixed_name == String(), nullptr); if (shapes.size()) { - StaticBody *col = memnew(StaticBody); + StaticBody3D *col = memnew(StaticBody3D); col->set_transform(mi->get_transform()); col->set_name(fixed_name); p_node->replace_by(col); @@ -412,9 +412,9 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> p_node = col; int idx = 0; - for (List<Ref<Shape>>::Element *E = shapes.front(); E; E = E->next()) { + for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E->get()); col->add_child(cshape); @@ -427,55 +427,55 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> } else if (p_node->has_meta("empty_draw_type")) { String empty_draw_type = String(p_node->get_meta("empty_draw_type")); - StaticBody *sb = memnew(StaticBody); + StaticBody3D *sb = memnew(StaticBody3D); sb->set_name(_fixstr(name, "colonly")); - Object::cast_to<Spatial>(sb)->set_transform(Object::cast_to<Spatial>(p_node)->get_transform()); + Object::cast_to<Node3D>(sb)->set_transform(Object::cast_to<Node3D>(p_node)->get_transform()); p_node->replace_by(sb); memdelete(p_node); - p_node = NULL; - CollisionShape *colshape = memnew(CollisionShape); + p_node = nullptr; + CollisionShape3D *colshape = memnew(CollisionShape3D); if (empty_draw_type == "CUBE") { - BoxShape *boxShape = memnew(BoxShape); + BoxShape3D *boxShape = memnew(BoxShape3D); boxShape->set_extents(Vector3(1, 1, 1)); colshape->set_shape(boxShape); - colshape->set_name("BoxShape"); + colshape->set_name("BoxShape3D"); } else if (empty_draw_type == "SINGLE_ARROW") { - RayShape *rayShape = memnew(RayShape); + RayShape3D *rayShape = memnew(RayShape3D); rayShape->set_length(1); colshape->set_shape(rayShape); - colshape->set_name("RayShape"); - Object::cast_to<Spatial>(sb)->rotate_x(Math_PI / 2); + colshape->set_name("RayShape3D"); + Object::cast_to<Node3D>(sb)->rotate_x(Math_PI / 2); } else if (empty_draw_type == "IMAGE") { - WorldMarginShape *world_margin_shape = memnew(WorldMarginShape); + WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D); colshape->set_shape(world_margin_shape); - colshape->set_name("WorldMarginShape"); + colshape->set_name("WorldMarginShape3D"); } else { - SphereShape *sphereShape = memnew(SphereShape); + SphereShape3D *sphereShape = memnew(SphereShape3D); sphereShape->set_radius(1); colshape->set_shape(sphereShape); - colshape->set_name("SphereShape"); + colshape->set_name("SphereShape3D"); } sb->add_child(colshape); colshape->set_owner(sb->get_owner()); } - } else if (_teststr(name, "rigid") && Object::cast_to<MeshInstance>(p_node)) { + } else if (_teststr(name, "rigid") && Object::cast_to<MeshInstance3D>(p_node)) { if (isroot) return p_node; - MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape>> shapes; + List<Ref<Shape3D>> shapes; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else { _gen_shape_list(mesh, shapes, true); } - RigidBody *rigid_body = memnew(RigidBody); + RigidBody3D *rigid_body = memnew(RigidBody3D); rigid_body->set_name(_fixstr(name, "rigid")); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); @@ -486,9 +486,9 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> mi->set_owner(rigid_body->get_owner()); int idx = 0; - for (List<Ref<Shape>>::Element *E = shapes.front(); E; E = E->next()) { + for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E->get()); rigid_body->add_child(cshape); @@ -498,14 +498,14 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> } } - } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<MeshInstance>(p_node)) { + } else if ((_teststr(name, "col") || (_teststr(name, "convcol"))) && Object::cast_to<MeshInstance3D>(p_node)) { - MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - List<Ref<Shape>> shapes; + List<Ref<Shape3D>> shapes; String fixed_name; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; @@ -530,15 +530,15 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> } if (shapes.size()) { - StaticBody *col = memnew(StaticBody); + StaticBody3D *col = memnew(StaticBody3D); col->set_name("static_collision"); mi->add_child(col); col->set_owner(mi->get_owner()); int idx = 0; - for (List<Ref<Shape>>::Element *E = shapes.front(); E; E = E->next()) { + for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E->get()); col->add_child(cshape); @@ -550,22 +550,22 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> } } - } else if (_teststr(name, "navmesh") && Object::cast_to<MeshInstance>(p_node)) { + } else if (_teststr(name, "navmesh") && Object::cast_to<MeshInstance3D>(p_node)) { if (isroot) return p_node; - MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); Ref<ArrayMesh> mesh = mi->get_mesh(); - ERR_FAIL_COND_V(mesh.is_null(), NULL); - NavigationRegion *nmi = memnew(NavigationRegion); + ERR_FAIL_COND_V(mesh.is_null(), nullptr); + NavigationRegion3D *nmi = memnew(NavigationRegion3D); nmi->set_name(_fixstr(name, "navmesh")); Ref<NavigationMesh> nmesh = memnew(NavigationMesh); nmesh->create_from_mesh(mesh); nmi->set_navigation_mesh(nmesh); - Object::cast_to<Spatial>(nmi)->set_transform(mi->get_transform()); + Object::cast_to<Node3D>(nmi)->set_transform(mi->get_transform()); p_node->replace_by(nmi); memdelete(p_node); p_node = nmi; @@ -575,8 +575,8 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> return p_node; Node *owner = p_node->get_owner(); - Spatial *s = Object::cast_to<Spatial>(p_node); - VehicleBody *bv = memnew(VehicleBody); + Node3D *s = Object::cast_to<Node3D>(p_node); + VehicleBody3D *bv = memnew(VehicleBody3D); String n = _fixstr(p_node->get_name(), "vehicle"); bv->set_name(n); p_node->replace_by(bv); @@ -595,8 +595,8 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> return p_node; Node *owner = p_node->get_owner(); - Spatial *s = Object::cast_to<Spatial>(p_node); - VehicleWheel *bv = memnew(VehicleWheel); + Node3D *s = Object::cast_to<Node3D>(p_node); + VehicleWheel3D *bv = memnew(VehicleWheel3D); String n = _fixstr(p_node->get_name(), "wheel"); bv->set_name(n); p_node->replace_by(bv); @@ -609,16 +609,16 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> p_node = bv; - } else if (Object::cast_to<MeshInstance>(p_node)) { + } else if (Object::cast_to<MeshInstance3D>(p_node)) { //last attempt, maybe collision inside the mesh data - MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); Ref<ArrayMesh> mesh = mi->get_mesh(); if (!mesh.is_null()) { - List<Ref<Shape>> shapes; + List<Ref<Shape3D>> shapes; if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(mesh->get_name(), "col")) { @@ -632,15 +632,15 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> } if (shapes.size()) { - StaticBody *col = memnew(StaticBody); + StaticBody3D *col = memnew(StaticBody3D); col->set_name("static_collision"); p_node->add_child(col); col->set_owner(p_node->get_owner()); int idx = 0; - for (List<Ref<Shape>>::Element *E = shapes.front(); E; E = E->next()) { + for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { - CollisionShape *cshape = memnew(CollisionShape); + CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(E->get()); col->add_child(cshape); @@ -934,14 +934,14 @@ void ResourceImporterScene::_find_meshes(Node *p_node, Map<Ref<ArrayMesh>, Trans List<PropertyInfo> pi; p_node->get_property_list(&pi); - MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_node); if (mi) { Ref<ArrayMesh> mesh = mi->get_mesh(); if (mesh.is_valid() && !meshes.has(mesh)) { - Spatial *s = mi; + Node3D *s = mi; Transform transform; while (s) { transform = transform * s->get_transform(); @@ -1141,7 +1141,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, int p_preset) const { - r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_type", PROPERTY_HINT_TYPE_STRING, "Node"), "Spatial")); + r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_type", PROPERTY_HINT_TYPE_STRING, "Node"), "Node3D")); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/root_name"), "Scene Root")); List<String> script_extentions; @@ -1229,7 +1229,7 @@ Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporte break; } - ERR_FAIL_COND_V(!importer.is_valid(), NULL); + ERR_FAIL_COND_V(!importer.is_valid(), nullptr); List<String> missing; Error err; @@ -1261,7 +1261,7 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito break; } - ERR_FAIL_COND_V(!importer.is_valid(), NULL); + ERR_FAIL_COND_V(!importer.is_valid(), nullptr); return importer->import_animation(p_path, p_flags, p_bake_fps); } @@ -1327,13 +1327,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p String root_type = p_options["nodes/root_type"]; root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class. - Ref<Script> root_script = NULL; + Ref<Script> root_script = nullptr; if (ScriptServer::is_global_class(root_type)) { root_script = ResourceLoader::load(ScriptServer::get_global_class_path(root_type)); root_type = ScriptServer::get_global_class_base(root_type); } - if (root_type != "Spatial") { + if (root_type != "Node3D") { Node *base_node = Object::cast_to<Node>(ClassDB::instance(root_type)); if (base_node) { @@ -1348,9 +1348,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p scene->set_script(Variant(root_script)); } - if (Object::cast_to<Spatial>(scene)) { + if (Object::cast_to<Node3D>(scene)) { float root_scale = p_options["nodes/root_scale"]; - Object::cast_to<Spatial>(scene)->scale(Vector3(root_scale, root_scale, root_scale)); + Object::cast_to<Node3D>(scene)->scale(Vector3(root_scale, root_scale, root_scale)); } if (p_options["nodes/root_name"] != "Scene Root") @@ -1368,7 +1368,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p float anim_optimizer_maxang = p_options["animation/optimizer/max_angle"]; int light_bake_mode = p_options["meshes/light_baking"]; - Map<Ref<Mesh>, List<Ref<Shape>>> collision_map; + Map<Ref<Mesh>, List<Ref<Shape3D>>> collision_map; scene = _fix_node(scene, scene, collision_map, LightBakeMode(light_bake_mode)); @@ -1533,7 +1533,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p return OK; } -ResourceImporterScene *ResourceImporterScene::singleton = NULL; +ResourceImporterScene *ResourceImporterScene::singleton = nullptr; ResourceImporterScene::ResourceImporterScene() { singleton = this; @@ -1550,10 +1550,10 @@ Node *EditorSceneImporterESCN::import_scene(const String &p_path, uint32_t p_fla Error error; Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error); - ERR_FAIL_COND_V_MSG(!ps.is_valid(), NULL, "Cannot load scene as text resource from path '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(!ps.is_valid(), nullptr, "Cannot load scene as text resource from path '" + p_path + "'."); Node *scene = ps->instance(); - ERR_FAIL_COND_V(!scene, NULL); + ERR_FAIL_COND_V(!scene, nullptr); return scene; } diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 6d1043eb28..f48f181951 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -34,7 +34,7 @@ #include "core/io/resource_importer.h" #include "scene/resources/animation.h" #include "scene/resources/mesh.h" -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" class Material; @@ -66,7 +66,7 @@ public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); EditorSceneImporter() {} @@ -147,14 +147,14 @@ public: void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_animations_as_text, bool p_keep_animations, bool p_make_materials, bool p_materials_as_text, bool p_keep_materials, bool p_make_meshes, bool p_meshes_as_text, Map<Ref<Animation>, Ref<Animation>> &p_animations, Map<Ref<Material>, Ref<Material>> &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh>> &p_meshes); - Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape>>> &collision_map, LightBakeMode p_light_bake_mode); + Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh>, List<Ref<Shape3D>>> &collision_map, LightBakeMode p_light_bake_mode); void _create_clips(Node *scene, const Array &p_clips, bool p_bake_all); void _filter_anim_tracks(Ref<Animation> anim, Set<String> &keep); void _filter_tracks(Node *scene, const String &p_text); void _optimize_animations(Node *scene, float p_max_lin_error, float p_max_ang_error, float p_max_angle); - 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(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 = nullptr, Variant *r_metadata = nullptr); Node *import_scene_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); Ref<Animation> import_animation_from_other_importer(EditorSceneImporter *p_exception, const String &p_path, uint32_t p_flags, int p_bake_fps); @@ -168,7 +168,7 @@ class EditorSceneImporterESCN : public EditorSceneImporter { public: virtual uint32_t get_import_flags() const; virtual void get_extensions(List<String> *r_extensions) const; - virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL); + virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr); virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps); }; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 0090d30b9c..f8ed9304b6 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -36,7 +36,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" -void ResourceImporterTexture::_texture_reimport_roughness(const Ref<StreamTexture> &p_tex, const String &p_normal_path, VS::TextureDetectRoughnessChannel p_channel) { +void ResourceImporterTexture::_texture_reimport_roughness(const Ref<StreamTexture> &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { MutexLock lock(singleton->mutex); @@ -424,7 +424,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String String normal_map = p_options["roughness/src_normal"]; Ref<Image> normal_image; - Image::RoughnessChannel roughness_channel; + Image::RoughnessChannel roughness_channel = Image::ROUGHNESS_CHANNEL_R; if (mipmaps && roughness > 1 && FileAccess::exists(normal_map)) { normal_image.instance(); @@ -434,7 +434,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } Ref<Image> image; image.instance(); - Error err = ImageLoader::load_image(p_source_file, image, NULL, hdr_as_srgb, scale); + Error err = ImageLoader::load_image(p_source_file, image, nullptr, hdr_as_srgb, scale); if (err != OK) return err; @@ -575,7 +575,7 @@ const char *ResourceImporterTexture::compression_formats[] = { "etc", "etc2", "pvrtc", - NULL + nullptr }; String ResourceImporterTexture::get_import_settings_string() const { @@ -630,7 +630,7 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path) co return valid; } -ResourceImporterTexture *ResourceImporterTexture::singleton = NULL; +ResourceImporterTexture *ResourceImporterTexture::singleton = nullptr; ResourceImporterTexture::ResourceImporterTexture() { diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index ed0fe1be89..e1c71ff1b8 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -35,7 +35,7 @@ #include "core/io/resource_importer.h" #include "core/os/file_access.h" #include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class StreamTexture; @@ -63,16 +63,16 @@ protected: int flags; String normal_path_for_roughness; - VS::TextureDetectRoughnessChannel channel_for_roughness; + RS::TextureDetectRoughnessChannel channel_for_roughness; MakeInfo() { flags = 0; - channel_for_roughness = VS::TEXTURE_DETECT_ROUGNHESS_R; + channel_for_roughness = RS::TEXTURE_DETECT_ROUGNHESS_R; } }; Map<StringName, MakeInfo> make_flags; - static void _texture_reimport_roughness(const Ref<StreamTexture> &p_tex, const String &p_normal_path, VisualServer::TextureDetectRoughnessChannel p_channel); + static void _texture_reimport_roughness(const Ref<StreamTexture> &p_tex, const String &p_normal_path, RenderingServer::TextureDetectRoughnessChannel p_channel); static void _texture_reimport_3d(const Ref<StreamTexture> &p_tex); static void _texture_reimport_normal(const Ref<StreamTexture> &p_tex); @@ -104,7 +104,7 @@ public: 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 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(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 = nullptr, Variant *r_metadata = nullptr); void update_imports(); diff --git a/editor/import/resource_importer_texture_atlas.h b/editor/import/resource_importer_texture_atlas.h index a36cae5872..c61fa5c040 100644 --- a/editor/import/resource_importer_texture_atlas.h +++ b/editor/import/resource_importer_texture_atlas.h @@ -63,7 +63,7 @@ public: 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(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 = nullptr, Variant *r_metadata = nullptr); 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(); diff --git a/editor/import/resource_importer_wav.h b/editor/import/resource_importer_wav.h index 6df5b88b13..bc2f023e6b 100644 --- a/editor/import/resource_importer_wav.h +++ b/editor/import/resource_importer_wav.h @@ -162,7 +162,7 @@ public: } } - 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(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 = nullptr, Variant *r_metadata = nullptr); ResourceImporterWAV(); }; |