summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/variant_op.cpp319
-rw-r--r--doc/base/classes.xml2
-rw-r--r--tools/collada/collada.cpp25
-rw-r--r--tools/collada/collada.h2
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp4
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.cpp75
-rw-r--r--tools/export/blender25/io_scene_dae/export_dae.py10
7 files changed, 168 insertions, 269 deletions
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 6065094da7..9f706e75cf 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -861,7 +861,6 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
} break;
//logic
case OP_AND: {
-
bool l = p_a.booleanize(r_valid);
if (!r_valid)
return;
@@ -969,6 +968,30 @@ Variant Variant::get_named(const StringName& p_index, bool *r_valid) const {
return get(p_index.operator String(),r_valid);
}
+
+#define DEFAULT_OP_ARRAY_CMD(m_name, m_type, skip_test, cmd)\
+ case m_name: {\
+ skip_test;\
+\
+ if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {\
+ int index = p_index;\
+ m_type *arr=reinterpret_cast<m_type* >(_data._mem);\
+\
+ if (index<0)\
+ index += arr->size();\
+ if (index>=0 && index<arr->size()) {\
+ valid=true;\
+ cmd;\
+ }\
+ }\
+ } break;
+
+#define DEFAULT_OP_DVECTOR_SET(m_name, dv_type, skip_cond)\
+ DEFAULT_OP_ARRAY_CMD(m_name, DVector<dv_type>, if(skip_cond) return;, arr->set(index, p_value);return)
+
+#define DEFAULT_OP_DVECTOR_GET(m_name, dv_type)\
+ DEFAULT_OP_ARRAY_CMD(m_name, const DVector<dv_type>, 0, return arr->get(index))
+
void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) {
static bool _dummy=false;
@@ -989,7 +1012,10 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
int idx=p_index;
String *str=reinterpret_cast<String*>(_data._mem);
- if (idx <0 || idx>=str->length())
+ int len = str->length();
+ if (idx<0)
+ idx += len;
+ if (idx<0 || idx>=len)
return;
String chr;
@@ -1003,7 +1029,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
return;
}
- *str = str->substr(0,idx)+chr+str->substr(idx+1,str->length());
+ *str = str->substr(0,idx)+chr+str->substr(idx+1, len);
valid=true;
return;
@@ -1018,6 +1044,8 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
// scalar index
int idx=p_index;
+ if (idx<0)
+ idx += 2;
if (idx>=0 && idx<2) {
Vector2 *v=reinterpret_cast<Vector2*>(_data._mem);
@@ -1076,6 +1104,8 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
int index = p_index;
+ if (index<0)
+ index += 3;
if (index>=0 && index<3) {
Matrix32 *v=_data._matrix32;
@@ -1112,6 +1142,8 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
//scalar index
int idx=p_index;
+ if (idx<0)
+ idx += 3;
if (idx>=0 && idx<3) {
Vector3 *v=reinterpret_cast<Vector3*>(_data._mem);
@@ -1246,6 +1278,8 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
int index = p_index;
+ if (index<0)
+ index += 3;
if (index>=0 && index<3) {
Matrix3 *v=_data._matrix3;
@@ -1284,6 +1318,8 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
int index = p_index;
+ if (index<0)
+ index += 4;
if (index>=0 && index<4) {
Transform *v=_data._transform;
valid=true;
@@ -1372,6 +1408,8 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
} else if (p_index.get_type()==Variant::INT) {
int idx = p_index;
+ if (idx<0)
+ idx += 4;
if (idx>=0 || idx<4) {
Color *v=reinterpret_cast<Color*>(_data._mem);
(*v)[idx]=p_value;
@@ -1786,145 +1824,14 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
valid=true; //always valid, i guess? should this really be ok?
return;
} break; // 20
- case ARRAY: {
-
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- Array *arr=reinterpret_cast<Array* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- (*arr)[index]=p_value;
- return;
- }
- }
-
- } break;
- case RAW_ARRAY: {
-
- if (p_value.type!=Variant::REAL && p_value.type!=Variant::INT)
- return;
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- DVector<uint8_t> *arr=reinterpret_cast<DVector<uint8_t>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- arr->set(index,p_value);
- return;
- }
- }
-
- } break;
- case INT_ARRAY: {
- if (p_value.type!=Variant::REAL && p_value.type!=Variant::INT)
- return;
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- DVector<int> *arr=reinterpret_cast<DVector<int>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- arr->set(index,p_value);
- return;
- }
- }
- } break;
- case REAL_ARRAY: {
-
- if (p_value.type!=Variant::REAL && p_value.type!=Variant::INT)
- return;
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- DVector<real_t> *arr=reinterpret_cast<DVector<real_t>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- arr->set(index,p_value);
- return;
- }
- }
-
- } break;
- case STRING_ARRAY: {
-
- if (p_value.type!=Variant::STRING)
- return;
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- DVector<String> *arr=reinterpret_cast<DVector<String>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- arr->set(index,p_value);
- return;
- }
- }
-
- } break; //25
- case VECTOR2_ARRAY: {
-
- if (p_value.type!=Variant::VECTOR2)
- return;
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- DVector<Vector2> *arr=reinterpret_cast<DVector<Vector2>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- arr->set(index,p_value);
- return;
- }
- }
-
- } break;
- case VECTOR3_ARRAY: {
-
- if (p_value.type!=Variant::VECTOR3)
- return;
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- DVector<Vector3> *arr=reinterpret_cast<DVector<Vector3>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- arr->set(index,p_value);
- return;
- }
- }
-
- } break;
- case COLOR_ARRAY: {
-
- if (p_value.type!=Variant::COLOR)
- return;
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- DVector<Color> *arr=reinterpret_cast<DVector<Color>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- arr->set(index,p_value);
- return;
- }
- }
- } break;
+ DEFAULT_OP_ARRAY_CMD(ARRAY, Array, ;, (*arr)[index]=p_value;return)
+ DEFAULT_OP_DVECTOR_SET(RAW_ARRAY, uint8_t, p_value.type != Variant::REAL && p_value.type != Variant::INT)
+ DEFAULT_OP_DVECTOR_SET(INT_ARRAY, int, p_value.type != Variant::REAL && p_value.type != Variant::INT)
+ DEFAULT_OP_DVECTOR_SET(REAL_ARRAY, real_t, p_value.type != Variant::REAL && p_value.type != Variant::INT)
+ DEFAULT_OP_DVECTOR_SET(STRING_ARRAY, String, p_value.type != Variant::STRING) // 25
+ DEFAULT_OP_DVECTOR_SET(VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2)
+ DEFAULT_OP_DVECTOR_SET(VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3)
+ DEFAULT_OP_DVECTOR_SET(COLOR_ARRAY, Color, p_value.type != Variant::COLOR)
default: return;
}
@@ -1950,6 +1857,8 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
int idx=p_index;
const String *str=reinterpret_cast<const String*>(_data._mem);
+ if (idx<0)
+ idx += str->length();
if (idx >=0 && idx<str->length()) {
valid=true;
@@ -1963,6 +1872,8 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
// scalar index
int idx=p_index;
+ if (idx<0)
+ idx += 2;
if (idx>=0 && idx<2) {
const Vector2 *v=reinterpret_cast<const Vector2*>(_data._mem);
@@ -2008,6 +1919,8 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
//scalar index
int idx=p_index;
+ if (idx<0)
+ idx += 3;
if (idx>=0 && idx<3) {
const Vector3 *v=reinterpret_cast<const Vector3*>(_data._mem);
@@ -2038,6 +1951,8 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
int index = p_index;
+ if (index<0)
+ index += 3;
if (index>=0 && index<3) {
const Matrix32 *v=_data._matrix32;
@@ -2133,7 +2048,8 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
int index = p_index;
-
+ if (index<0)
+ index += 3;
if (index>=0 && index<3) {
const Matrix3 *v=_data._matrix3;
@@ -2163,7 +2079,8 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
int index = p_index;
-
+ if (index<0)
+ index += 4;
if (index>=0 && index<4) {
const Transform *v=_data._transform;
valid=true;
@@ -2227,6 +2144,8 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
} else if (p_index.get_type()==Variant::INT) {
int idx = p_index;
+ if (idx<0)
+ idx += 4;
if (idx>=0 || idx<4) {
const Color *v=reinterpret_cast<const Color*>(_data._mem);
valid=true;
@@ -2489,110 +2408,14 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
return *res;
}
} break; // 20
- case ARRAY: {
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- const Array *arr=reinterpret_cast<const Array* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- return (*arr)[index];
- }
- }
-
- } break;
- case RAW_ARRAY: {
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- const DVector<uint8_t> *arr=reinterpret_cast<const DVector<uint8_t>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- return arr->get(index);
- }
- }
-
- } break;
- case INT_ARRAY: {
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- const DVector<int> *arr=reinterpret_cast<const DVector<int>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- return arr->get(index);
- }
- }
- } break;
- case REAL_ARRAY: {
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- const DVector<real_t> *arr=reinterpret_cast<const DVector<real_t>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- return arr->get(index);
- }
- }
-
- } break;
- case STRING_ARRAY: {
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- const DVector<String> *arr=reinterpret_cast<const DVector<String>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- return arr->get(index);
- }
- }
-
- } break; //25
- case VECTOR2_ARRAY: {
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- const DVector<Vector2> *arr=reinterpret_cast<const DVector<Vector2>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- return arr->get(index);
- }
- }
-
- } break;
- case VECTOR3_ARRAY: {
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- const DVector<Vector3> *arr=reinterpret_cast<const DVector<Vector3>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- return arr->get(index);
- }
- }
-
- } break;
- case COLOR_ARRAY: {
-
- if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) {
-
- int index = p_index;
- const DVector<Color> *arr=reinterpret_cast<const DVector<Color>* >(_data._mem);
-
- if (index >=0 && index <arr->size()) {
- valid=true;
- return arr->get(index);
- }
- }
- } break;
+ DEFAULT_OP_ARRAY_CMD(ARRAY, const Array, 0, return (*arr)[index])
+ DEFAULT_OP_DVECTOR_GET(RAW_ARRAY, uint8_t)
+ DEFAULT_OP_DVECTOR_GET(INT_ARRAY, int)
+ DEFAULT_OP_DVECTOR_GET(REAL_ARRAY, real_t)
+ DEFAULT_OP_DVECTOR_GET(STRING_ARRAY, String)
+ DEFAULT_OP_DVECTOR_GET(VECTOR2_ARRAY, Vector2)
+ DEFAULT_OP_DVECTOR_GET(VECTOR3_ARRAY, Vector3)
+ DEFAULT_OP_DVECTOR_GET(COLOR_ARRAY, Color)
default: return Variant();
}
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 1beda5f2d0..9b8940bc50 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -4349,7 +4349,7 @@
Generic array datatype.
</brief_description>
<description>
- Generic array, contains several elements of any type, accessible by numerical index starting at 0. Arrays are always passed by reference.
+ Generic array, contains several elements of any type, accessible by numerical index starting at 0. Negative indices can be used to count from the right, like in Python. Arrays are always passed by reference.
</description>
<methods>
<method name="append">
diff --git a/tools/collada/collada.cpp b/tools/collada/collada.cpp
index 8f40ec1469..f0fde20dfc 100644
--- a/tools/collada/collada.cpp
+++ b/tools/collada/collada.cpp
@@ -482,6 +482,24 @@ Transform Collada::_read_transform(XMLParser& parser) {
return _read_transform_from_array(array);
}
+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())
@@ -1664,6 +1682,8 @@ Collada::Node* Collada::_parse_visual_scene_node(XMLParser& parser) {
Vector<Node::XForm> xform_list;
Vector<Node*> children;
+
+ String empty_draw_type="";
Node *node=NULL;
@@ -1771,7 +1791,9 @@ Collada::Node* Collada::_parse_visual_scene_node(XMLParser& parser) {
xform_list.push_back(xf);
- } else if (section=="technique" || section=="extra") {
+ } 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
@@ -1817,6 +1839,7 @@ Collada::Node* Collada::_parse_visual_scene_node(XMLParser& parser) {
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) {
diff --git a/tools/collada/collada.h b/tools/collada/collada.h
index 8983b8faf0..01934a1e76 100644
--- a/tools/collada/collada.h
+++ b/tools/collada/collada.h
@@ -403,6 +403,7 @@ public:
String name;
String id;
+ String empty_draw_type;
bool noname;
Vector<XForm> xform_list;
Transform default_transform;
@@ -635,6 +636,7 @@ private: // private stuff
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=NULL);
diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp
index f008c4a736..f0aec113d1 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -355,6 +355,10 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
p_parent->add_child(node);
node->set_owner(scene);
+ if (p_node->empty_draw_type!="") {
+ node->set_meta("empty_draw_type", Variant(p_node->empty_draw_type));
+ }
+
for(int i=0;i<p_node->children.size();i++) {
Error err = _create_scene(p_node->children[i],node);
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
index 594d3f5bcd..f346306f61 100644
--- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
@@ -41,6 +41,10 @@
#include "scene/3d/physics_body.h"
#include "scene/3d/portal.h"
#include "scene/3d/vehicle_body.h"
+#include "scene/resources/sphere_shape.h"
+#include <scene/resources/box_shape.h>
+#include <scene/resources/ray_shape.h>
+#include <scene/resources/plane_shape.h>
#include "tools/editor/create_dialog.h"
#include "os/os.h"
@@ -1685,28 +1689,61 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
mi->set_baked_light_texture_id(layer);
}
- if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) {
+ if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly")) {
if (isroot)
return p_node;
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- Node * col = mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col,NULL);
-
- col->set_name(_fixstr(name,"colonly"));
- col->cast_to<Spatial>()->set_transform(mi->get_transform());
- p_node->replace_by(col);
- memdelete(p_node);
- p_node=col;
-
- StaticBody *sb = col->cast_to<StaticBody>();
- CollisionShape *colshape = memnew( CollisionShape);
- colshape->set_shape(sb->get_shape(0));
- colshape->set_name("shape");
- sb->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
-
+
+ if (p_node->cast_to<MeshInstance>()) {
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ Node * col = mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col,NULL);
+
+ col->set_name(_fixstr(name,"colonly"));
+ col->cast_to<Spatial>()->set_transform(mi->get_transform());
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node=col;
+
+ StaticBody *sb = col->cast_to<StaticBody>();
+ CollisionShape *colshape = memnew( CollisionShape);
+ colshape->set_shape(sb->get_shape(0));
+ colshape->set_name("shape");
+ sb->add_child(colshape);
+ colshape->set_owner(p_node->get_owner());
+ } else if (p_node->has_meta("empty_draw_type")) {
+ String empty_draw_type = String(p_node->get_meta("empty_draw_type"));
+ print_line(empty_draw_type);
+ StaticBody *sb = memnew( StaticBody);
+ sb->set_name(_fixstr(name,"colonly"));
+ sb->cast_to<Spatial>()->set_transform(p_node->cast_to<Spatial>()->get_transform());
+ p_node->replace_by(sb);
+ memdelete(p_node);
+ CollisionShape *colshape = memnew( CollisionShape);
+ if (empty_draw_type == "CUBE") {
+ BoxShape *boxShape = memnew( BoxShape);
+ boxShape->set_extents(Vector3(1, 1, 1));
+ colshape->set_shape(boxShape);
+ colshape->set_name("BoxShape");
+ } else if (empty_draw_type == "SINGLE_ARROW") {
+ RayShape *rayShape = memnew( RayShape);
+ rayShape->set_length(1);
+ colshape->set_shape(rayShape);
+ colshape->set_name("RayShape");
+ sb->cast_to<Spatial>()->rotate_x(Math_PI / 2);
+ } else if (empty_draw_type == "IMAGE") {
+ PlaneShape *planeShape = memnew( PlaneShape);
+ colshape->set_shape(planeShape);
+ colshape->set_name("PlaneShape");
+ } else {
+ SphereShape *sphereShape = memnew( SphereShape);
+ sphereShape->set_radius(1);
+ colshape->set_shape(sphereShape);
+ colshape->set_name("SphereShape");
+ }
+ sb->add_child(colshape);
+ colshape->set_owner(sb->get_owner());
+ }
} else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS &&_teststr(name,"col") && p_node->cast_to<MeshInstance>()) {
diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py
index cdd845e384..3bb440ffe5 100644
--- a/tools/export/blender25/io_scene_dae/export_dae.py
+++ b/tools/export/blender25/io_scene_dae/export_dae.py
@@ -1104,6 +1104,14 @@ class DaeExporter:
self.writel(S_NODES,il,'<instance_light url="#'+lightid+'"/>')
+ def export_empty_node(self,node,il):
+
+ self.writel(S_NODES,4,'<extra>')
+ self.writel(S_NODES,5,'<technique profile="GODOT">')
+ self.writel(S_NODES,6,'<empty_draw_type>'+node.empty_draw_type+'</empty_draw_type>')
+ self.writel(S_NODES,5,'</technique>')
+ self.writel(S_NODES,4,'</extra>')
+
def export_curve(self,curve):
@@ -1264,6 +1272,8 @@ class DaeExporter:
self.export_camera_node(node,il)
elif (node.type=="LAMP"):
self.export_lamp_node(node,il)
+ elif (node.type=="EMPTY"):
+ self.export_empty_node(node,il)
for x in node.children:
self.export_node(x,il)