Refactoring: rename tools/editor/ to editor/

The other subfolders of tools/ had already been moved to either
editor/, misc/ or thirdparty/, so the hiding the editor code that
deep was no longer meaningful.

(Manual redo of 49c065d29c)
This commit is contained in:
Rémi Verschelde 2017-03-18 23:45:45 +01:00
parent 9d2c0f6c6e
commit 1b0e2b0c39
1759 changed files with 31301 additions and 31301 deletions

5
editor/io_plugins/SCsub Normal file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env python
Import('env')
Export('env')
env.add_source_files(env.editor_sources, "*.cpp")

View file

@ -0,0 +1,159 @@
/*************************************************************************/
/* editor_atlas.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "editor_atlas.h"
#include "print_string.h"
struct _EditorAtlasWorkRect {
Size2i s;
Point2i p;
int idx;
_FORCE_INLINE_ bool operator<(const _EditorAtlasWorkRect& p_r) const { return s.width > p_r.s.width; };
};
struct _EditorAtlasWorkRectResult {
Vector<_EditorAtlasWorkRect> result;
int max_w;
int max_h;
};
void EditorAtlas::fit(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size) {
//super simple, almost brute force scanline stacking fitter
//it's pretty basic for now, but it tries to make sure that the aspect ratio of the
//resulting atlas is somehow square. This is necesary because video cards have limits
//on texture size (usually 2048 or 4096), so the more square a texture, the more chances
//it will work in every hardware.
// for example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a
// 256x8192 atlas (won't work anywhere).
ERR_FAIL_COND(p_rects.size()==0);
Vector<_EditorAtlasWorkRect> wrects;
wrects.resize(p_rects.size());
for(int i=0;i<p_rects.size();i++) {
wrects[i].s=p_rects[i];
wrects[i].idx=i;
}
wrects.sort();
int widest = wrects[0].s.width;
Vector<_EditorAtlasWorkRectResult> results;
for(int i=0;i<=12;i++) {
int w = 1<<i;
int max_h=0;
int max_w=0;
if ( w < widest )
continue;
Vector<int> hmax;
hmax.resize(w);
for(int j=0;j<w;j++)
hmax[j]=0;
//place them
int ofs=0;
for(int j=0;j<wrects.size();j++) {
if (ofs+wrects[j].s.width > w) {
ofs=0;
}
int from_y=0;
for(int k=0;k<wrects[j].s.width;k++) {
if (hmax[ofs+k] > from_y)
from_y=hmax[ofs+k];
}
wrects[j].p.x=ofs;
wrects[j].p.y=from_y;
int end_h = from_y+wrects[j].s.height;
int end_w = ofs+wrects[j].s.width;
for(int k=0;k<wrects[j].s.width;k++) {
hmax[ofs+k]=end_h;
}
if (end_h > max_h)
max_h=end_h;
if (end_w > max_w)
max_w=end_w;
ofs+=wrects[j].s.width;
}
_EditorAtlasWorkRectResult result;
result.result=wrects;
result.max_h=max_h;
result.max_w=max_w;
results.push_back(result);
}
//find the result with the best aspect ratio
int best=-1;
float best_aspect=1e20;
for(int i=0;i<results.size();i++) {
float h = results[i].max_h;
float w = results[i].max_w;
float aspect = h>w ? h/w : w/h;
if (aspect < best_aspect) {
best=i;
best_aspect=aspect;
}
}
r_result.resize(p_rects.size());
for(int i=0;i<p_rects.size();i++) {
r_result[ results[best].result[i].idx ]=results[best].result[i].p;
}
r_size=Size2(results[best].max_w,results[best].max_h );
}

View file

@ -0,0 +1,43 @@
/*************************************************************************/
/* editor_atlas.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_ATLAS_H
#define EDITOR_ATLAS_H
#include "math_2d.h"
#include "vector.h"
class EditorAtlas {
public:
static void fit(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size);
};
#endif // EDITOR_ATLAS_H

View file

@ -0,0 +1,357 @@
#include "editor_bitmask_import_plugin.h"
#include "io/image_loader.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_dir_dialog.h"
#include "editor/editor_node.h"
#include "editor/property_editor.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
#include "io/marshalls.h"
#include "editor/editor_settings.h"
class _EditorBitMaskImportOptions : public Object {
OBJ_TYPE(_EditorBitMaskImportOptions, Object);
public:
bool _set(const StringName& p_name, const Variant& p_value) {
return false;
}
bool _get(const StringName& p_name, Variant &r_ret) const{
return false;
}
void _get_property_list(List<PropertyInfo> *p_list) const{
}
static void _bind_methods() {
ADD_SIGNAL(MethodInfo("changed"));
}
_EditorBitMaskImportOptions() {
}
};
class EditorBitMaskImportDialog : public ConfirmationDialog {
OBJ_TYPE(EditorBitMaskImportDialog, ConfirmationDialog);
EditorBitMaskImportPlugin *plugin;
LineEdit *import_path;
LineEdit *save_path;
EditorFileDialog *file_select;
EditorDirDialog *save_select;
ConfirmationDialog *error_dialog;
PropertyEditor *option_editor;
public:
void _choose_files(const Vector<String>& p_path) {
String files;
for (int i = 0; i<p_path.size(); i++) {
if (i>0)
files += ",";
files += p_path[i];
}
import_path->set_text(files);
}
void _choose_save_dir(const String& p_path) {
save_path->set_text(p_path);
}
void _browse() {
file_select->popup_centered_ratio();
}
void _browse_target() {
save_select->popup_centered_ratio();
}
void popup_import(const String& p_path) {
popup_centered(Size2(400, 100)*EDSCALE);
if (p_path != "") {
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
ERR_FAIL_COND(!rimd.is_valid());
save_path->set_text(p_path.get_base_dir());
String src = "";
for (int i = 0; i<rimd->get_source_count(); i++) {
if (i>0)
src += ",";
src += EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
}
import_path->set_text(src);
}
}
void _import() {
Vector<String> bitmasks = import_path->get_text().split(",");
if (bitmasks.size() == 0) {
error_dialog->set_text(TTR("No bit masks to import!"));
error_dialog->popup_centered(Size2(200, 100)*EDSCALE);
}
if (save_path->get_text().strip_edges() == "") {
error_dialog->set_text(TTR("Target path is empty."));
error_dialog->popup_centered_minsize();
return;
}
if (!save_path->get_text().begins_with("res://")) {
error_dialog->set_text(TTR("Target path must be a complete resource path."));
error_dialog->popup_centered_minsize();
return;
}
if (!DirAccess::exists(save_path->get_text())) {
error_dialog->set_text(TTR("Target path must exist."));
error_dialog->popup_centered_minsize();
return;
}
for (int i = 0; i<bitmasks.size(); i++) {
Ref<ResourceImportMetadata> imd = memnew(ResourceImportMetadata);
imd->add_source(EditorImportPlugin::validate_source_path(bitmasks[i]));
String dst = save_path->get_text();
if (dst == "") {
error_dialog->set_text(TTR("Save path is empty!"));
error_dialog->popup_centered(Size2(200, 100)*EDSCALE);
}
dst = dst.plus_file(bitmasks[i].get_file().basename() + ".pbm");
Error err = plugin->import(dst, imd);
}
hide();
}
void _notification(int p_what) {
}
static void _bind_methods() {
ObjectTypeDB::bind_method("_choose_files", &EditorBitMaskImportDialog::_choose_files);
ObjectTypeDB::bind_method("_choose_save_dir", &EditorBitMaskImportDialog::_choose_save_dir);
ObjectTypeDB::bind_method("_import", &EditorBitMaskImportDialog::_import);
ObjectTypeDB::bind_method("_browse", &EditorBitMaskImportDialog::_browse);
ObjectTypeDB::bind_method("_browse_target", &EditorBitMaskImportDialog::_browse_target);
// ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
}
EditorBitMaskImportDialog(EditorBitMaskImportPlugin *p_plugin) {
plugin = p_plugin;
set_title(TTR("Import BitMasks"));
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
set_child_rect(vbc);
HBoxContainer *hbc = memnew(HBoxContainer);
vbc->add_margin_child(TTR("Source Texture(s):"), hbc);
import_path = memnew(LineEdit);
import_path->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(import_path);
Button * import_choose = memnew(Button);
import_choose->set_text(" .. ");
hbc->add_child(import_choose);
import_choose->connect("pressed", this, "_browse");
hbc = memnew(HBoxContainer);
vbc->add_margin_child(TTR("Target Path:"), hbc);
save_path = memnew(LineEdit);
save_path->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(save_path);
Button * save_choose = memnew(Button);
save_choose->set_text(" .. ");
hbc->add_child(save_choose);
save_choose->connect("pressed", this, "_browse_target");
file_select = memnew(EditorFileDialog);
file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
add_child(file_select);
file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
file_select->connect("files_selected", this, "_choose_files");
List<String> extensions;
ImageLoader::get_recognized_extensions(&extensions);
file_select->clear_filters();
for (int i = 0; i<extensions.size(); i++) {
file_select->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
}
save_select = memnew(EditorDirDialog);
add_child(save_select);
// save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
save_select->connect("dir_selected", this, "_choose_save_dir");
get_ok()->connect("pressed", this, "_import");
get_ok()->set_text(TTR("Import"));
error_dialog = memnew(ConfirmationDialog);
add_child(error_dialog);
error_dialog->get_ok()->set_text(TTR("Accept"));
// error_dialog->get_cancel()->hide();
set_hide_on_ok(false);
}
~EditorBitMaskImportDialog() {
}
};
String EditorBitMaskImportPlugin::get_name() const {
return "bitmask";
}
String EditorBitMaskImportPlugin::get_visible_name() const{
return TTR("Bit Mask");
}
void EditorBitMaskImportPlugin::import_dialog(const String& p_from){
dialog->popup_import(p_from);
}
Error EditorBitMaskImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
ERR_FAIL_COND_V(p_from->get_source_count() != 1, ERR_INVALID_PARAMETER);
Ref<ResourceImportMetadata> from = p_from;
String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
Ref<ImageTexture> it = ResourceLoader::load(src_path);
ERR_FAIL_COND_V(it.is_null(), ERR_CANT_OPEN);
Ref<BitMap> target = memnew(BitMap);
target->create_from_image_alpha(it.ptr()->get_data());
from->set_source_md5(0, FileAccess::get_md5(src_path));
from->set_editor(get_name());
target->set_import_metadata(from);
Error err = ResourceSaver::save(p_path, target);
return err;
}
EditorBitMaskImportPlugin* EditorBitMaskImportPlugin::singleton = NULL;
void EditorBitMaskImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
Vector<String> files;
List<String> valid_extensions;
ImageLoader::get_recognized_extensions(&valid_extensions);
for(int i=0;i<p_drop.size();i++) {
String extension=p_drop[i].extension().to_lower();
for (List<String>::Element *E=valid_extensions.front();E;E=E->next()) {
if (E->get()==extension) {
files.push_back(p_drop[i]);
break;
}
}
}
if (files.size()) {
import_dialog();
dialog->_choose_files(files);
dialog->_choose_save_dir(p_dest_path);
}
}
void EditorBitMaskImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
if (p_list.size() == 0)
return;
Vector<String> sources;
for (int i = 0; i<p_list.size(); i++) {
int idx;
EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(p_list[i], &idx);
if (efsd) {
for (int j = 0; j<efsd->get_source_count(idx); j++) {
String file = expand_source_path(efsd->get_source_file(idx, j));
if (sources.find(file) == -1) {
sources.push_back(file);
}
}
}
}
if (sources.size()) {
dialog->popup_import(p_list[0]);
dialog->_choose_files(sources);
dialog->_choose_save_dir(p_list[0].get_base_dir());
}
}
bool EditorBitMaskImportPlugin::can_reimport_multiple_files() const {
return true;
}
EditorBitMaskImportPlugin::EditorBitMaskImportPlugin(EditorNode* p_editor) {
singleton = this;
dialog = memnew(EditorBitMaskImportDialog(this));
p_editor->get_gui_base()->add_child(dialog);
}
EditorBitMaskExportPlugin::EditorBitMaskExportPlugin() {
}

View file

@ -0,0 +1,41 @@
#ifndef EDITOR_BITMASK_IMPORT_PLUGIN_H
#define EDITOR_BITMASK_IMPORT_PLUGIN_H
#include "editor/editor_import_export.h"
#include "scene/resources/font.h"
class EditorNode;
class EditorBitMaskImportDialog;
class EditorBitMaskImportPlugin : public EditorImportPlugin {
OBJ_TYPE(EditorBitMaskImportPlugin, EditorImportPlugin);
EditorBitMaskImportDialog *dialog;
public:
static EditorBitMaskImportPlugin *singleton;
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from = "");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
virtual void reimport_multiple_files(const Vector<String>& p_list);
virtual bool can_reimport_multiple_files() const;
EditorBitMaskImportPlugin(EditorNode* p_editor);
};
class EditorBitMaskExportPlugin : public EditorExportPlugin {
OBJ_TYPE(EditorBitMaskExportPlugin, EditorExportPlugin);
public:
EditorBitMaskExportPlugin();
};
#endif // EDITOR_SAMPLE_IMPORT_PLUGIN_H

View file

@ -0,0 +1,140 @@
/*************************************************************************/
/* editor_export_scene.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "editor_export_scene.h"
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "os/dir_access.h"
#include "os/file_access.h"
#include "editor/editor_settings.h"
#include "scene/resources/packed_scene.h"
#include "globals.h"
Vector<uint8_t> EditorSceneExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
if (!EditorImportExport::get_singleton()->get_convert_text_scenes()) {
return Vector<uint8_t>();
}
String extension = p_path.extension();
//step 1 check if scene
if (extension=="xml" || extension=="xres") {
String type = ResourceLoader::get_resource_type(p_path);
if (type!="PackedScene")
return Vector<uint8_t>();
} else if (extension!="tscn" && extension!="xscn") {
return Vector<uint8_t>();
}
//step 2 check if cached
uint64_t sd=0;
String smd5;
String gp = Globals::get_singleton()->globalize_path(p_path);
String md5=gp.md5_text();
String tmp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/");
bool valid=false;
{
//if existing, make sure it's valid
FileAccessRef f = FileAccess::open(tmp_path+"scnexp-"+md5+".txt",FileAccess::READ);
if (f) {
uint64_t d = f->get_line().strip_edges().to_int64();
sd = FileAccess::get_modified_time(p_path);
if (d==sd) {
valid=true;
} else {
String cmd5 = f->get_line().strip_edges();
smd5 = FileAccess::get_md5(p_path);
if (cmd5==smd5) {
valid=true;
}
}
}
}
if (!valid) {
//cache failed, convert
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
String copy = p_path+".convert."+extension;
// a copy will allow loading the internal resources without conflicting with opened scenes
da->copy(p_path,copy);
//@todo for tscn use something more efficient
Ref<PackedScene> copyres = ResourceLoader::load(copy,"PackedScene");
da->remove(copy);
memdelete(da);
ERR_FAIL_COND_V(!copyres.is_valid(),Vector<uint8_t>());
Error err = ResourceSaver::save(tmp_path+"scnexp-"+md5+".scn",copyres);
copyres=Ref<PackedScene>();
ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
FileAccessRef f = FileAccess::open(tmp_path+"scnexp-"+md5+".txt",FileAccess::WRITE);
if (sd==0)
sd = FileAccess::get_modified_time(p_path);
if (smd5==String())
smd5 = FileAccess::get_md5(p_path);
f->store_line(String::num(sd));
f->store_line(smd5);
f->store_line(gp); //source path for reference
}
Vector<uint8_t> ret = FileAccess::get_file_as_array(tmp_path+"scnexp-"+md5+".scn");
p_path+=".converted.scn";
return ret;
}
EditorSceneExportPlugin::EditorSceneExportPlugin()
{
}

View file

@ -0,0 +1,44 @@
/*************************************************************************/
/* editor_export_scene.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_EXPORT_SCENE_H
#define EDITOR_EXPORT_SCENE_H
#include "editor/editor_import_export.h"
class EditorSceneExportPlugin : public EditorExportPlugin {
OBJ_TYPE( EditorSceneExportPlugin, EditorExportPlugin );
public:
virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
EditorSceneExportPlugin();
};
#endif // EDITOR_EXPORT_SCENE_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,57 @@
/*************************************************************************/
/* editor_font_import_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_FONT_IMPORT_PLUGIN_H
#define EDITOR_FONT_IMPORT_PLUGIN_H
#include "editor/editor_import_export.h"
#include "scene/resources/font.h"
class EditorNode;
class EditorFontImportDialog;
class EditorFontImportPlugin : public EditorImportPlugin {
OBJ_TYPE(EditorFontImportPlugin,EditorImportPlugin);
EditorFontImportDialog *dialog;
public:
Ref<BitmapFont> generate_font(const Ref<ResourceImportMetadata>& p_from,const String& p_existing=String()); //used by editor
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
EditorFontImportPlugin(EditorNode* p_editor);
};
#endif // EDITOR_FONT_IMPORT_PLUGIN_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/*************************************************************************/
/* editor_import_collada.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_IMPORT_COLLADA_H
#define EDITOR_IMPORT_COLLADA_H
#include "editor/io_plugins/editor_scene_import_plugin.h"
class EditorSceneImporterCollada : public EditorSceneImporter {
OBJ_TYPE(EditorSceneImporterCollada,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 Ref<Animation> import_animation(const String& p_path,uint32_t p_flags);
EditorSceneImporterCollada();
};
#endif

View file

@ -0,0 +1,590 @@
/*************************************************************************/
/* editor_mesh_import_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "editor_mesh_import_plugin.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_dir_dialog.h"
#include "editor/editor_node.h"
#include "editor/property_editor.h"
#include "scene/resources/sample.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
#include "io/marshalls.h"
#include "scene/resources/surface_tool.h"
class _EditorMeshImportOptions : public Object {
OBJ_TYPE(_EditorMeshImportOptions,Object);
public:
bool generate_tangents;
bool generate_normals;
bool flip_faces;
bool smooth_shading;
bool weld_vertices;
bool import_material;
bool import_textures;
float weld_tolerance;
bool _set(const StringName& p_name, const Variant& p_value) {
String n = p_name;
if (n=="generate/tangents")
generate_tangents=p_value;
else if (n=="generate/normals")
generate_normals=p_value;
else if (n=="import/materials")
import_material=p_value;
else if (n=="import/textures")
import_textures=p_value;
else if (n=="force/flip_faces")
flip_faces=p_value;
else if (n=="force/smooth_shading")
smooth_shading=p_value;
else if (n=="force/weld_vertices")
weld_vertices=p_value;
else if (n=="force/weld_tolerance")
weld_tolerance=p_value;
else
return false;
return true;
}
bool _get(const StringName& p_name,Variant &r_ret) const{
String n = p_name;
if (n=="generate/tangents")
r_ret=generate_tangents;
else if (n=="generate/normals")
r_ret=generate_normals;
else if (n=="import/materials")
r_ret=import_material;
else if (n=="import/textures")
r_ret=import_textures;
else if (n=="force/flip_faces")
r_ret=flip_faces;
else if (n=="force/smooth_shading")
r_ret=smooth_shading;
else if (n=="force/weld_vertices")
r_ret=weld_vertices;
else if (n=="force/weld_tolerance")
r_ret=weld_tolerance;
else
return false;
return true;
}
void _get_property_list( List<PropertyInfo> *p_list) const{
p_list->push_back(PropertyInfo(Variant::BOOL,"generate/tangents"));
p_list->push_back(PropertyInfo(Variant::BOOL,"generate/normals"));
//not for nowp
//p_list->push_back(PropertyInfo(Variant::BOOL,"import/materials"));
//p_list->push_back(PropertyInfo(Variant::BOOL,"import/textures"));
p_list->push_back(PropertyInfo(Variant::BOOL,"force/flip_faces"));
p_list->push_back(PropertyInfo(Variant::BOOL,"force/smooth_shading"));
p_list->push_back(PropertyInfo(Variant::BOOL,"force/weld_vertices"));
p_list->push_back(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001"));
//p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable"));
//p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
}
static void _bind_methods() {
ADD_SIGNAL( MethodInfo("changed"));
}
_EditorMeshImportOptions() {
generate_tangents=true;
generate_normals=false;
flip_faces=false;
smooth_shading=false;
weld_vertices=true;
weld_tolerance=0.0001;
import_material=false;
import_textures=false;
}
};
class EditorMeshImportDialog : public ConfirmationDialog {
OBJ_TYPE(EditorMeshImportDialog,ConfirmationDialog);
EditorMeshImportPlugin *plugin;
LineEdit *import_path;
LineEdit *save_path;
EditorFileDialog *file_select;
EditorDirDialog *save_select;
AcceptDialog *error_dialog;
PropertyEditor *option_editor;
_EditorMeshImportOptions *options;
public:
void _choose_files(const Vector<String>& p_path) {
String files;
for(int i=0;i<p_path.size();i++) {
if (i>0)
files+=",";
files+=p_path[i];
}
/*
if (p_path.size()) {
String srctex=p_path[0];
String ipath = EditorImportDB::get_singleton()->find_source_path(srctex);
if (ipath!="")
save_path->set_text(ipath.get_base_dir());
}*/
import_path->set_text(files);
}
void _choose_save_dir(const String& p_path) {
save_path->set_text(p_path);
}
void _browse() {
file_select->popup_centered_ratio();
}
void _browse_target() {
save_select->popup_centered_ratio();
}
void popup_import(const String& p_path) {
popup_centered(Size2(400,400)*EDSCALE);
if (p_path!="") {
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
ERR_FAIL_COND(!rimd.is_valid());
save_path->set_text(p_path.get_base_dir());
List<String> opts;
rimd->get_options(&opts);
for(List<String>::Element *E=opts.front();E;E=E->next()) {
options->_set(E->get(),rimd->get_option(E->get()));
}
String src = "";
for(int i=0;i<rimd->get_source_count();i++) {
if (i>0)
src+=",";
src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
}
import_path->set_text(src);
}
}
void _import() {
Vector<String> meshes = import_path->get_text().split(",");
if (meshes.size()==0) {
error_dialog->set_text(TTR("No meshes to import!"));
error_dialog->popup_centered_minsize();
return;
}
String dst = save_path->get_text();
if (dst=="") {
error_dialog->set_text(TTR("Save path is empty!"));
error_dialog->popup_centered_minsize();
return;
}
for(int i=0;i<meshes.size();i++) {
Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
List<PropertyInfo> pl;
options->_get_property_list(&pl);
for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
Variant v;
String opt=E->get().name;
options->_get(opt,v);
imd->set_option(opt,v);
}
imd->add_source(EditorImportPlugin::validate_source_path(meshes[i]));
String file_path = dst.plus_file(meshes[i].get_file().basename()+".msh");
plugin->import(file_path,imd);
}
hide();
}
void _notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
option_editor->edit(options);
}
}
static void _bind_methods() {
ObjectTypeDB::bind_method("_choose_files",&EditorMeshImportDialog::_choose_files);
ObjectTypeDB::bind_method("_choose_save_dir",&EditorMeshImportDialog::_choose_save_dir);
ObjectTypeDB::bind_method("_import",&EditorMeshImportDialog::_import);
ObjectTypeDB::bind_method("_browse",&EditorMeshImportDialog::_browse);
ObjectTypeDB::bind_method("_browse_target",&EditorMeshImportDialog::_browse_target);
}
EditorMeshImportDialog(EditorMeshImportPlugin *p_plugin) {
plugin=p_plugin;
set_title(TTR("Single Mesh Import"));
set_hide_on_ok(false);
VBoxContainer *vbc = memnew( VBoxContainer );
add_child(vbc);
set_child_rect(vbc);
HBoxContainer *hbc = memnew( HBoxContainer );
vbc->add_margin_child(TTR("Source Mesh(es):"),hbc);
import_path = memnew( LineEdit );
import_path->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(import_path);
Button * import_choose = memnew( Button );
import_choose->set_text(" .. ");
hbc->add_child(import_choose);
import_choose->connect("pressed", this,"_browse");
hbc = memnew( HBoxContainer );
vbc->add_margin_child(TTR("Target Path:"),hbc);
save_path = memnew( LineEdit );
save_path->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(save_path);
Button * save_choose = memnew( Button );
save_choose->set_text(" .. ");
hbc->add_child(save_choose);
save_choose->connect("pressed", this,"_browse_target");
file_select = memnew( EditorFileDialog );
file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
file_select->add_filter("*.obj ; Wavefront OBJ");
add_child(file_select);
file_select->connect("files_selected", this,"_choose_files");
save_select = memnew( EditorDirDialog );
add_child(save_select);
save_select->connect("dir_selected", this,"_choose_save_dir");
get_ok()->connect("pressed", this,"_import");
get_ok()->set_text(TTR("Import"));
error_dialog = memnew( AcceptDialog );
add_child(error_dialog);
options = memnew( _EditorMeshImportOptions );
option_editor = memnew( PropertyEditor );
option_editor->hide_top_label();
vbc->add_margin_child(TTR("Options:"),option_editor,true);
}
~EditorMeshImportDialog() {
memdelete(options);
}
};
String EditorMeshImportPlugin::get_name() const {
return "mesh";
}
String EditorMeshImportPlugin::get_visible_name() const{
return TTR("Mesh");
}
void EditorMeshImportPlugin::import_dialog(const String& p_from){
dialog->popup_import(p_from);
}
Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER);
Ref<ResourceImportMetadata> from=p_from;
String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
FileAccessRef f = FileAccess::open(src_path,FileAccess::READ);
ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
Ref<Mesh> mesh;
Map<String,Ref<Material> > name_map;
if (FileAccess::exists(p_path)) {
mesh=ResourceLoader::load(p_path,"Mesh");
if (mesh.is_valid()) {
for(int i=0;i<mesh->get_surface_count();i++) {
if (!mesh->surface_get_material(i).is_valid())
continue;
String name;
if (mesh->surface_get_name(i)!="")
name=mesh->surface_get_name(i);
else
name=vformat(TTR("Surface %d"),i+1);
name_map[name]=mesh->surface_get_material(i);
}
while(mesh->get_surface_count()) {
mesh->surface_remove(0);
}
}
}
if (!mesh.is_valid())
mesh = Ref<Mesh>( memnew( Mesh ) );
bool generate_normals=from->get_option("generate/normals");
bool generate_tangents=from->get_option("generate/tangents");
bool flip_faces=from->get_option("force/flip_faces");
bool force_smooth=from->get_option("force/smooth_shading");
bool weld_vertices=from->get_option("force/weld_vertices");
float weld_tolerance=from->get_option("force/weld_tolerance");
Vector<Vector3> vertices;
Vector<Vector3> normals;
Vector<Vector2> uvs;
String name;
Ref<SurfaceTool> surf_tool = memnew( SurfaceTool) ;
surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
if (force_smooth)
surf_tool->add_smooth_group(true);
int has_index_data=false;
while(true) {
String l = f->get_line().strip_edges();
if (l.begins_with("v ")) {
//vertex
Vector<String> v = l.split(" ",false);
ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
Vector3 vtx;
vtx.x=v[1].to_float();
vtx.y=v[2].to_float();
vtx.z=v[3].to_float();
vertices.push_back(vtx);
} else if (l.begins_with("vt ")) {
//uv
Vector<String> v = l.split(" ",false);
ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA);
Vector2 uv;
uv.x=v[1].to_float();
uv.y=1.0-v[2].to_float();
uvs.push_back(uv);
} else if (l.begins_with("vn ")) {
//normal
Vector<String> v = l.split(" ",false);
ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
Vector3 nrm;
nrm.x=v[1].to_float();
nrm.y=v[2].to_float();
nrm.z=v[3].to_float();
normals.push_back(nrm);
} if (l.begins_with("f ")) {
//vertex
has_index_data=true;
Vector<String> v = l.split(" ",false);
ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
//not very fast, could be sped up
Vector<String> face[3];
face[0] = v[1].split("/");
face[1] = v[2].split("/");
ERR_FAIL_COND_V(face[0].size()==0,ERR_PARSE_ERROR);
ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR);
for(int i=2;i<v.size()-1;i++) {
face[2] = v[i+1].split("/");
ERR_FAIL_COND_V(face[0].size()!=face[2].size(),ERR_PARSE_ERROR);
for(int j=0;j<3;j++) {
int idx=j;
if (!flip_faces && idx<2) {
idx=1^idx;
}
if (face[idx].size()==3) {
int norm = face[idx][2].to_int()-1;
ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR);
surf_tool->add_normal(normals[norm]);
}
if (face[idx].size()>=2 && face[idx][1]!=String()) {
int uv = face[idx][1].to_int()-1;
ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR);
surf_tool->add_uv(uvs[uv]);
}
int vtx = face[idx][0].to_int()-1;
ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR);
Vector3 vertex = vertices[vtx];
if (weld_vertices)
vertex=vertex.snapped(weld_tolerance);
surf_tool->add_vertex(vertex);
}
face[1]=face[2];
}
} else if (l.begins_with("s ") && !force_smooth) { //smoothing
String what = l.substr(2,l.length()).strip_edges();
if (what=="off")
surf_tool->add_smooth_group(false);
else
surf_tool->add_smooth_group(true);
} else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done
if (has_index_data) {
//new object/surface
if (generate_normals || force_smooth)
surf_tool->generate_normals();
if (uvs.size() && (normals.size() || generate_normals) && generate_tangents)
surf_tool->generate_tangents();
surf_tool->index();
mesh = surf_tool->commit(mesh);
if (name=="")
name=vformat(TTR("Surface %d"),mesh->get_surface_count()-1);
mesh->surface_set_name(mesh->get_surface_count()-1,name);
name="";
surf_tool->clear();
surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
if (force_smooth)
surf_tool->add_smooth_group(true);
has_index_data=false;
if (f->eof_reached())
break;
}
if (l.begins_with("o ")) //name
name=l.substr(2,l.length()).strip_edges();
}
}
from->set_source_md5(0,FileAccess::get_md5(src_path));
from->set_editor(get_name());
mesh->set_import_metadata(from);
//re-apply materials if exist
for(int i=0;i<mesh->get_surface_count();i++) {
String n = mesh->surface_get_name(i);
if (name_map.has(n))
mesh->surface_set_material(i,name_map[n]);
}
Error err = ResourceSaver::save(p_path,mesh);
return err;
}
void EditorMeshImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
Vector<String> files;
for(int i=0;i<p_drop.size();i++) {
String ext = p_drop[i].extension().to_lower();
String file = p_drop[i].get_file();
if (ext=="obj") {
files.push_back(p_drop[i]);
}
}
if (files.size()) {
import_dialog();
dialog->_choose_files(files);
dialog->_choose_save_dir(p_dest_path);
}
}
EditorMeshImportPlugin::EditorMeshImportPlugin(EditorNode* p_editor) {
dialog = memnew( EditorMeshImportDialog(this));
p_editor->get_gui_base()->add_child(dialog);
}

View file

@ -0,0 +1,58 @@
/*************************************************************************/
/* editor_mesh_import_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_MESH_IMPORT_PLUGIN_H
#define EDITOR_MESH_IMPORT_PLUGIN_H
#include "editor/editor_import_export.h"
#include "scene/resources/font.h"
class EditorNode;
class EditorMeshImportDialog;
class EditorMeshImportPlugin : public EditorImportPlugin {
OBJ_TYPE(EditorMeshImportPlugin,EditorImportPlugin);
EditorMeshImportDialog *dialog;
public:
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
EditorMeshImportPlugin(EditorNode* p_editor);
};
#endif // EDITOR_MESH_IMPORT_PLUGIN_H

View file

@ -0,0 +1,923 @@
/*************************************************************************/
/* editor_sample_import_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "editor_sample_import_plugin.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_dir_dialog.h"
#include "editor/editor_node.h"
#include "editor/property_editor.h"
#include "scene/resources/sample.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
#include "io/marshalls.h"
#include "editor/editor_settings.h"
class _EditorSampleImportOptions : public Object {
OBJ_TYPE(_EditorSampleImportOptions,Object);
public:
enum CompressMode {
COMPRESS_MODE_DISABLED,
COMPRESS_MODE_RAM,
COMPRESS_MODE_DISK
};
enum CompressBitrate {
COMPRESS_64,
COMPRESS_96,
COMPRESS_128,
COMPRESS_192
};
bool force_8_bit;
bool force_mono;
bool force_rate;
float force_rate_hz;
bool edit_trim;
bool edit_normalize;
bool edit_loop;
CompressMode compress_mode;
CompressBitrate compress_bitrate;
bool _set(const StringName& p_name, const Variant& p_value) {
String n = p_name;
if (n=="force/8_bit")
force_8_bit=p_value;
else if (n=="force/mono")
force_mono=p_value;
else if (n=="force/max_rate")
force_rate=p_value;
else if (n=="force/max_rate_hz")
force_rate_hz=p_value;
else if (n=="edit/trim")
edit_trim=p_value;
else if (n=="edit/normalize")
edit_normalize=p_value;
else if (n=="edit/loop")
edit_loop=p_value;
else if (n=="compress/mode")
compress_mode=CompressMode(int(p_value));
else if (n=="compress/bitrate")
compress_bitrate=CompressBitrate(int(p_value));
else
return false;
return true;
}
bool _get(const StringName& p_name,Variant &r_ret) const{
String n = p_name;
if (n=="force/8_bit")
r_ret=force_8_bit;
else if (n=="force/mono")
r_ret=force_mono;
else if (n=="force/max_rate")
r_ret=force_rate;
else if (n=="force/max_rate_hz")
r_ret=force_rate_hz;
else if (n=="edit/trim")
r_ret=edit_trim;
else if (n=="edit/normalize")
r_ret=edit_normalize;
else if (n=="edit/loop")
r_ret=edit_loop;
else if (n=="compress/mode")
r_ret=compress_mode;
else if (n=="compress/bitrate")
r_ret=compress_bitrate;
else
return false;
return true;
}
void _get_property_list( List<PropertyInfo> *p_list) const{
p_list->push_back(PropertyInfo(Variant::BOOL,"force/8_bit"));
p_list->push_back(PropertyInfo(Variant::BOOL,"force/mono"));
p_list->push_back(PropertyInfo(Variant::BOOL,"force/max_rate"));
p_list->push_back(PropertyInfo(Variant::REAL,"force/max_rate_hz",PROPERTY_HINT_EXP_RANGE,"11025,192000,1"));
p_list->push_back(PropertyInfo(Variant::BOOL,"edit/trim"));
p_list->push_back(PropertyInfo(Variant::BOOL,"edit/normalize"));
p_list->push_back(PropertyInfo(Variant::BOOL,"edit/loop"));
p_list->push_back(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)"));
//p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
}
static void _bind_methods() {
ADD_SIGNAL( MethodInfo("changed"));
}
_EditorSampleImportOptions() {
force_8_bit=false;
force_mono=false;
force_rate=true;
force_rate_hz=44100;
edit_trim=true;
edit_normalize=true;
edit_loop=false;
compress_mode=COMPRESS_MODE_RAM;
compress_bitrate=COMPRESS_128;
}
};
class EditorSampleImportDialog : public ConfirmationDialog {
OBJ_TYPE(EditorSampleImportDialog,ConfirmationDialog);
EditorSampleImportPlugin *plugin;
LineEdit *import_path;
LineEdit *save_path;
EditorFileDialog *file_select;
EditorDirDialog *save_select;
ConfirmationDialog *error_dialog;
PropertyEditor *option_editor;
_EditorSampleImportOptions *options;
public:
void _choose_files(const Vector<String>& p_path) {
String files;
for(int i=0;i<p_path.size();i++) {
if (i>0)
files+=",";
files+=p_path[i];
}
/*
if (p_path.size()) {
String srctex=p_path[0];
String ipath = EditorImportDB::get_singleton()->find_source_path(srctex);
if (ipath!="")
save_path->set_text(ipath.get_base_dir());
}*/
import_path->set_text(files);
}
void _choose_save_dir(const String& p_path) {
save_path->set_text(p_path);
}
void _browse() {
file_select->popup_centered_ratio();
}
void _browse_target() {
save_select->popup_centered_ratio();
}
void popup_import(const String& p_path) {
popup_centered(Size2(400,400)*EDSCALE);
if (p_path!="") {
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
ERR_FAIL_COND(!rimd.is_valid());
save_path->set_text(p_path.get_base_dir());
List<String> opts;
rimd->get_options(&opts);
for(List<String>::Element *E=opts.front();E;E=E->next()) {
options->_set(E->get(),rimd->get_option(E->get()));
}
String src = "";
for(int i=0;i<rimd->get_source_count();i++) {
if (i>0)
src+=",";
src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
}
import_path->set_text(src);
}
}
void _import() {
Vector<String> samples = import_path->get_text().split(",");
if (samples.size()==0) {
error_dialog->set_text(TTR("No samples to import!"));
error_dialog->popup_centered(Size2(200,100)*EDSCALE);
}
if (save_path->get_text().strip_edges()=="") {
error_dialog->set_text(TTR("Target path is empty."));
error_dialog->popup_centered_minsize();
return;
}
if (!save_path->get_text().begins_with("res://")) {
error_dialog->set_text(TTR("Target path must be a complete resource path."));
error_dialog->popup_centered_minsize();
return;
}
if (!DirAccess::exists(save_path->get_text())) {
error_dialog->set_text(TTR("Target path must exist."));
error_dialog->popup_centered_minsize();
return;
}
for(int i=0;i<samples.size();i++) {
Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
List<PropertyInfo> pl;
options->_get_property_list(&pl);
for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
Variant v;
String opt=E->get().name;
options->_get(opt,v);
imd->set_option(opt,v);
}
imd->add_source(EditorImportPlugin::validate_source_path(samples[i]));
String dst = save_path->get_text();
if (dst=="") {
error_dialog->set_text(TTR("Save path is empty!"));
error_dialog->popup_centered(Size2(200,100)*EDSCALE);
}
dst = dst.plus_file(samples[i].get_file().basename()+".smp");
Error err = plugin->import(dst,imd);
}
hide();
}
void _notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
option_editor->edit(options);
}
}
static void _bind_methods() {
ObjectTypeDB::bind_method("_choose_files",&EditorSampleImportDialog::_choose_files);
ObjectTypeDB::bind_method("_choose_save_dir",&EditorSampleImportDialog::_choose_save_dir);
ObjectTypeDB::bind_method("_import",&EditorSampleImportDialog::_import);
ObjectTypeDB::bind_method("_browse",&EditorSampleImportDialog::_browse);
ObjectTypeDB::bind_method("_browse_target",&EditorSampleImportDialog::_browse_target);
// ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
}
EditorSampleImportDialog(EditorSampleImportPlugin *p_plugin) {
plugin=p_plugin;
set_title(TTR("Import Audio Samples"));
VBoxContainer *vbc = memnew( VBoxContainer );
add_child(vbc);
set_child_rect(vbc);
HBoxContainer *hbc = memnew( HBoxContainer );
vbc->add_margin_child(TTR("Source Sample(s):"),hbc);
import_path = memnew( LineEdit );
import_path->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(import_path);
Button * import_choose = memnew( Button );
import_choose->set_text(" .. ");
hbc->add_child(import_choose);
import_choose->connect("pressed", this,"_browse");
hbc = memnew( HBoxContainer );
vbc->add_margin_child(TTR("Target Path:"),hbc);
save_path = memnew( LineEdit );
save_path->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(save_path);
Button * save_choose = memnew( Button );
save_choose->set_text(" .. ");
hbc->add_child(save_choose);
save_choose->connect("pressed", this,"_browse_target");
file_select = memnew(EditorFileDialog);
file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
add_child(file_select);
file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
file_select->connect("files_selected", this,"_choose_files");
file_select->add_filter("*.wav ; MS Waveform");
save_select = memnew( EditorDirDialog );
add_child(save_select);
// save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
save_select->connect("dir_selected", this,"_choose_save_dir");
get_ok()->connect("pressed", this,"_import");
get_ok()->set_text(TTR("Import"));
error_dialog = memnew ( ConfirmationDialog );
add_child(error_dialog);
error_dialog->get_ok()->set_text(TTR("Accept"));
// error_dialog->get_cancel()->hide();
set_hide_on_ok(false);
options = memnew( _EditorSampleImportOptions );
option_editor = memnew( PropertyEditor );
option_editor->hide_top_label();
vbc->add_margin_child(TTR("Options:"),option_editor,true);
}
~EditorSampleImportDialog() {
memdelete(options);
}
};
String EditorSampleImportPlugin::get_name() const {
return "sample";
}
String EditorSampleImportPlugin::get_visible_name() const{
return TTR("Audio Sample");
}
void EditorSampleImportPlugin::import_dialog(const String& p_from){
dialog->popup_import(p_from);
}
Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER);
Ref<ResourceImportMetadata> from=p_from;
String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
Ref<Sample> smp = ResourceLoader::load(src_path);
ERR_FAIL_COND_V(smp.is_null(),ERR_CANT_OPEN);
float rate = smp->get_mix_rate();
bool is16 = smp->get_format()==Sample::FORMAT_PCM16;
int chans = smp->is_stereo()?2:1;
int len = smp->get_length();
Sample::LoopFormat loop= smp->get_loop_format();
int loop_beg = smp->get_loop_begin();
int loop_end = smp->get_loop_end();
print_line("Input Sample: ");
print_line("\tlen: "+itos(len));
print_line("\tchans: "+itos(chans));
print_line("\t16bits: "+itos(is16));
print_line("\trate: "+itos(rate));
print_line("\tloop: "+itos(loop));
print_line("\tloop begin: "+itos(loop_beg));
print_line("\tloop end: "+itos(loop_end));
Vector<float> data;
data.resize(len*chans);
{
DVector<uint8_t> src_data = smp->get_data();
DVector<uint8_t>::Read sr = src_data.read();
for(int i=0;i<len*chans;i++) {
float s=0;
if (is16) {
int16_t i16 = decode_uint16(&sr[i*2]);
s=i16/32767.0;
} else {
int8_t i8 = sr[i];
s=i8/127.0;
}
data[i]=s;
}
}
//apply frequency limit
bool limit_rate = from->get_option("force/max_rate");
int limit_rate_hz = from->get_option("force/max_rate_hz");
if (limit_rate && rate > limit_rate_hz) {
//resampleeee!!!
int new_data_len = len * limit_rate_hz / rate;
Vector<float> new_data;
new_data.resize( new_data_len * chans );
for(int c=0;c<chans;c++) {
for(int i=0;i<new_data_len;i++) {
//simple cubic interpolation should be enough.
float pos = float(i) * len / new_data_len;
float mu = pos-Math::floor(pos);
int ipos = int(Math::floor(pos));
float y0=data[MAX(0,ipos-1)*chans+c];
float y1=data[ipos*chans+c];
float y2=data[MIN(len-1,ipos+1)*chans+c];
float y3=data[MIN(len-1,ipos+2)*chans+c];
float mu2 = mu*mu;
float a0 = y3 - y2 - y0 + y1;
float a1 = y0 - y1 - a0;
float a2 = y2 - y0;
float a3 = y1;
float res=(a0*mu*mu2+a1*mu2+a2*mu+a3);
new_data[i*chans+c]=res;
}
}
if (loop) {
loop_beg=loop_beg*new_data_len/len;
loop_end=loop_end*new_data_len/len;
}
data=new_data;
rate=limit_rate_hz;
len=new_data_len;
}
bool normalize = from->get_option("edit/normalize");
if (normalize) {
float max=0;
for(int i=0;i<data.size();i++) {
float amp = Math::abs(data[i]);
if (amp>max)
max=amp;
}
if (max>0) {
float mult=1.0/max;
for(int i=0;i<data.size();i++) {
data[i]*=mult;
}
}
}
bool trim = from->get_option("edit/trim");
if (trim && !loop) {
int first=0;
int last=(len*chans)-1;
bool found=false;
float limit = Math::db2linear(-30);
for(int i=0;i<data.size();i++) {
float amp = Math::abs(data[i]);
if (!found && amp > limit) {
first=i;
found=true;
}
if (found && amp > limit) {
last=i;
}
}
first/=chans;
last/=chans;
if (first<last) {
Vector<float> new_data;
new_data.resize((last-first+1)*chans);
for(int i=first*chans;i<=last*chans;i++) {
new_data[i-first*chans]=data[i];
}
data=new_data;
len=data.size()/chans;
}
}
bool make_loop = from->get_option("edit/loop");
if (make_loop && !loop) {
loop=Sample::LOOP_FORWARD;
loop_beg=0;
loop_end=len;
}
int compression = from->get_option("compress/mode");
bool force_mono = from->get_option("force/mono");
if (force_mono && chans==2) {
Vector<float> new_data;
new_data.resize(data.size()/2);
for(int i=0;i<len;i++) {
new_data[i]=(data[i*2+0]+data[i*2+1])/2.0;
}
data=new_data;
chans=1;
}
bool force_8_bit = from->get_option("force/8_bit");
if (force_8_bit) {
is16=false;
}
DVector<uint8_t> dst_data;
Sample::Format dst_format;
if ( compression == _EditorSampleImportOptions::COMPRESS_MODE_RAM) {
dst_format=Sample::FORMAT_IMA_ADPCM;
if (chans==1) {
_compress_ima_adpcm(data,dst_data);
} else {
print_line("INTERLEAAVE!");
//byte interleave
Vector<float> left;
Vector<float> right;
int tlen = data.size()/2;
left.resize(tlen);
right.resize(tlen);
for(int i=0;i<tlen;i++) {
left[i]=data[i*2+0];
right[i]=data[i*2+1];
}
DVector<uint8_t> bleft;
DVector<uint8_t> bright;
_compress_ima_adpcm(left,bleft);
_compress_ima_adpcm(right,bright);
int dl = bleft.size();
dst_data.resize( dl *2 );
DVector<uint8_t>::Write w=dst_data.write();
DVector<uint8_t>::Read rl=bleft.read();
DVector<uint8_t>::Read rr=bright.read();
for(int i=0;i<dl;i++) {
w[i*2+0]=rl[i];
w[i*2+1]=rr[i];
}
}
// print_line("compressing ima-adpcm, resulting buffersize is "+itos(dst_data.size())+" from "+itos(data.size()));
} else {
dst_format=is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8;
dst_data.resize( data.size() * (is16?2:1));
{
DVector<uint8_t>::Write w = dst_data.write();
int ds=data.size();
for(int i=0;i<ds;i++) {
if (is16) {
int16_t v = CLAMP(data[i]*32767,-32768,32767);
encode_uint16(v,&w[i*2]);
} else {
int8_t v = CLAMP(data[i]*127,-128,127);
w[i]=v;
}
}
}
}
Ref<Sample> target;
if (ResourceCache::has(p_path)) {
target = Ref<Sample>( ResourceCache::get(p_path)->cast_to<Sample>() );
} else {
target = smp;
}
target->create(dst_format,chans==2?true:false,len);
target->set_data(dst_data);
target->set_mix_rate(rate);
target->set_loop_format(loop);
target->set_loop_begin(loop_beg);
target->set_loop_end(loop_end);
from->set_source_md5(0,FileAccess::get_md5(src_path));
from->set_editor(get_name());
target->set_import_metadata(from);
Error err = ResourceSaver::save(p_path,smp);
return err;
}
void EditorSampleImportPlugin::_compress_ima_adpcm(const Vector<float>& p_data,DVector<uint8_t>& dst_data) {
/*p_sample_data->data = (void*)malloc(len);
xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/
static const int16_t _ima_adpcm_step_table[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
static const int8_t _ima_adpcm_index_table[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
int datalen = p_data.size();
int datamax=datalen;
if (datalen&1)
datalen++;
dst_data.resize(datalen/2+4);
DVector<uint8_t>::Write w = dst_data.write();
int i,step_idx=0,prev=0;
uint8_t *out = w.ptr();
//int16_t xm_prev=0;
const float *in=p_data.ptr();
/* initial value is zero */
*(out++) =0;
*(out++) =0;
/* Table index initial value */
*(out++) =0;
/* unused */
*(out++) =0;
for (i=0;i<datalen;i++) {
int step,diff,vpdiff,mask;
uint8_t nibble;
int16_t xm_sample;
if (i>=datamax)
xm_sample=0;
else {
xm_sample=CLAMP(in[i]*32767.0,-32768,32767);
//if (xm_sample==32767 || xm_sample==-32768)
// printf("clippy!\n",xm_sample);
}
// xm_sample=xm_sample+xm_prev;
// xm_prev=xm_sample;
diff = (int)xm_sample - prev ;
nibble=0 ;
step = _ima_adpcm_step_table[ step_idx ];
vpdiff = step >> 3 ;
if (diff < 0) {
nibble=8;
diff=-diff ;
}
mask = 4 ;
while (mask) {
if (diff >= step) {
nibble |= mask;
diff -= step;
vpdiff += step;
}
step >>= 1 ;
mask >>= 1 ;
};
if (nibble&8)
prev-=vpdiff ;
else
prev+=vpdiff ;
if (prev > 32767) {
//printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev);
prev=32767;
} else if (prev < -32768) {
//printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev);
prev = -32768 ;
}
step_idx += _ima_adpcm_index_table[nibble];
if (step_idx< 0)
step_idx= 0 ;
else if (step_idx> 88)
step_idx= 88 ;
if (i&1) {
*out|=nibble<<4;
out++;
} else {
*out=nibble;
}
/*dataptr[i]=prev>>8;*/
}
}
EditorSampleImportPlugin* EditorSampleImportPlugin::singleton=NULL;
void EditorSampleImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
Vector<String> files;
for(int i=0;i<p_drop.size();i++) {
String ext = p_drop[i].extension().to_lower();
if (ext=="wav") {
files.push_back(p_drop[i]);
}
}
if (files.size()) {
import_dialog();
dialog->_choose_files(files);
dialog->_choose_save_dir(p_dest_path);
}
}
void EditorSampleImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
if (p_list.size()==0)
return;
Vector<String> sources;
for(int i=0;i<p_list.size();i++) {
int idx;
EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(p_list[i],&idx);
if (efsd) {
for(int j=0;j<efsd->get_source_count(idx);j++) {
String file = expand_source_path(efsd->get_source_file(idx,j));
if (sources.find(file)==-1) {
sources.push_back(file);
}
}
}
}
if (sources.size()) {
dialog->popup_import(p_list[0]);
dialog->_choose_files(sources);
dialog->_choose_save_dir(p_list[0].get_base_dir());
}
}
bool EditorSampleImportPlugin::can_reimport_multiple_files() const {
return true;
}
EditorSampleImportPlugin::EditorSampleImportPlugin(EditorNode* p_editor) {
singleton=this;
dialog = memnew( EditorSampleImportDialog(this));
p_editor->get_gui_base()->add_child(dialog);
}
Vector<uint8_t> EditorSampleExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
if (EditorImportExport::get_singleton()->sample_get_action()==EditorImportExport::SAMPLE_ACTION_NONE || p_path.extension().to_lower()!="wav") {
return Vector<uint8_t>();
}
Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
imd->add_source(EditorImportPlugin::validate_source_path(p_path));
imd->set_option("force/8_bit",false);
imd->set_option("force/mono",false);
imd->set_option("force/max_rate",true);
imd->set_option("force/max_rate_hz",EditorImportExport::get_singleton()->sample_get_max_hz());
imd->set_option("edit/trim",EditorImportExport::get_singleton()->sample_get_trim());
imd->set_option("edit/normalize",false);
imd->set_option("edit/loop",false);
imd->set_option("compress/mode",1);
String savepath = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/smpconv.smp");
Error err = EditorSampleImportPlugin::singleton->import(savepath,imd);
ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
p_path=p_path.basename()+".converted.smp";
return FileAccess::get_file_as_array(savepath);
}
EditorSampleExportPlugin::EditorSampleExportPlugin() {
}

View file

@ -0,0 +1,72 @@
/*************************************************************************/
/* editor_sample_import_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_SAMPLE_IMPORT_PLUGIN_H
#define EDITOR_SAMPLE_IMPORT_PLUGIN_H
#include "editor/editor_import_export.h"
#include "scene/resources/font.h"
class EditorNode;
class EditorSampleImportDialog;
class EditorSampleImportPlugin : public EditorImportPlugin {
OBJ_TYPE(EditorSampleImportPlugin,EditorImportPlugin);
EditorSampleImportDialog *dialog;
void _compress_ima_adpcm(const Vector<float>& p_data,DVector<uint8_t>& dst_data);
public:
static EditorSampleImportPlugin *singleton;
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
virtual void reimport_multiple_files(const Vector<String>& p_list);
virtual bool can_reimport_multiple_files() const;
EditorSampleImportPlugin(EditorNode* p_editor);
};
class EditorSampleExportPlugin : public EditorExportPlugin {
OBJ_TYPE( EditorSampleExportPlugin, EditorExportPlugin);
public:
virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
EditorSampleExportPlugin();
};
#endif // EDITOR_SAMPLE_IMPORT_PLUGIN_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,200 @@
/*************************************************************************/
/* editor_scene_import_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_SCENE_IMPORT_PLUGIN_H
#define EDITOR_SCENE_IMPORT_PLUGIN_H
#include "scene/gui/dialogs.h"
#include "scene/gui/tree.h"
#include "scene/gui/label.h"
#include "scene/gui/option_button.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/file_dialog.h"
#include "scene/gui/progress_bar.h"
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
#include "scene/resources/mesh.h"
#include "editor/editor_file_system.h"
#include "editor/editor_dir_dialog.h"
#include "editor/editor_import_export.h"
#include "editor/io_plugins/editor_texture_import_plugin.h"
#include "scene/resources/animation.h"
class EditorNode;
class EditorSceneImportDialog;
class EditorSceneImporter : public Reference {
OBJ_TYPE(EditorSceneImporter,Reference );
public:
enum ImportFlags {
IMPORT_SCENE=1,
IMPORT_ANIMATION=2,
IMPORT_ANIMATION_DETECT_LOOP=4,
IMPORT_ANIMATION_OPTIMIZE=8,
IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=16,
IMPORT_ANIMATION_KEEP_VALUE_TRACKS=32,
IMPORT_GENERATE_TANGENT_ARRAYS=256,
IMPORT_FAIL_ON_MISSING_DEPENDENCIES=512
};
virtual uint32_t get_import_flags() const=0;
virtual void get_extensions(List<String> *r_extensions) const=0;
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)=0;
virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags)=0;
EditorSceneImporter();
};
/////////////////////////////////////////
//Plugin for post processing scenes or images
class EditorScenePostImport : public Reference {
OBJ_TYPE(EditorScenePostImport,Reference );
protected:
static void _bind_methods();
public:
virtual Node* post_import(Node* p_scene);
EditorScenePostImport();
};
class EditorSceneImportPlugin : public EditorImportPlugin {
OBJ_TYPE(EditorSceneImportPlugin,EditorImportPlugin);
EditorSceneImportDialog *dialog;
Vector<Ref<EditorSceneImporter> > importers;
enum TextureRole {
TEXTURE_ROLE_DEFAULT,
TEXTURE_ROLE_DIFFUSE,
TEXTURE_ROLE_NORMALMAP
};
void _find_resources(const Variant& p_var,Map<Ref<ImageTexture>,TextureRole >& image_map,int p_flags);
Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,TextureRole >& image_map);
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);
void _tag_import_paths(Node *p_scene,Node *p_node);
void _find_resources_to_merge(Node *scene, Node *node, bool p_merge_material, Map<String,Ref<Material> >&materials, bool p_merge_anims, Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes);
void _merge_found_resources(Node *scene, Node *node, bool p_merge_material, const Map<String, Ref<Material> > &materials, bool p_merge_anims, const Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes);
public:
enum SceneFlags {
SCENE_FLAG_CREATE_COLLISIONS=1<<0,
SCENE_FLAG_CREATE_PORTALS=1<<1,
SCENE_FLAG_CREATE_ROOMS=1<<2,
SCENE_FLAG_SIMPLIFY_ROOMS=1<<3,
SCENE_FLAG_CREATE_BILLBOARDS=1<<4,
SCENE_FLAG_CREATE_IMPOSTORS=1<<5,
SCENE_FLAG_CREATE_LODS=1<<6,
SCENE_FLAG_CREATE_CARS=1<<8,
SCENE_FLAG_CREATE_WHEELS=1<<9,
SCENE_FLAG_DETECT_ALPHA=1<<15,
SCENE_FLAG_DETECT_VCOLOR=1<<16,
SCENE_FLAG_CREATE_NAVMESH=1<<17,
SCENE_FLAG_DETECT_LIGHTMAP_LAYER=1<<18,
SCENE_FLAG_MERGE_KEEP_MATERIALS=1<<20,
SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS=1<<21,
SCENE_FLAG_REMOVE_NOIMP=1<<24,
SCENE_FLAG_IMPORT_ANIMATIONS=1<<25,
SCENE_FLAG_COMPRESS_GEOMETRY=1<<26,
SCENE_FLAG_GENERATE_TANGENT_ARRAYS=1<<27,
SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES=1<<28,
SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS=1<<29,
SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY=1<<30,
};
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
Error import1(const Ref<ResourceImportMetadata>& p_from,Node**r_node,List<String> *r_missing=NULL);
Error import2(Node* p_scene,const String& p_path, const Ref<ResourceImportMetadata>& p_from);
void add_importer(const Ref<EditorSceneImporter>& p_importer);
const Vector<Ref<EditorSceneImporter> >& get_importers() { return importers; }
virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
EditorSceneImportPlugin(EditorNode* p_editor=NULL);
};
class EditorSceneAnimationImportPlugin : public EditorImportPlugin {
OBJ_TYPE(EditorSceneAnimationImportPlugin,EditorImportPlugin);
public:
enum AnimationFlags {
ANIMATION_DETECT_LOOP=1,
ANIMATION_KEEP_VALUE_TRACKS=2,
ANIMATION_OPTIMIZE=4,
ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=8
};
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
EditorSceneAnimationImportPlugin(EditorNode* p_editor=NULL);
};
#endif // EDITOR_SCENE_IMPORT_PLUGIN_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,109 @@
/*************************************************************************/
/* editor_scene_importer_fbxconv.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_SCENE_IMPORTER_FBXCONV_H
#define EDITOR_SCENE_IMPORTER_FBXCONV_H
#include "editor/io_plugins/editor_scene_import_plugin.h"
#include "scene/3d/skeleton.h"
class EditorSceneImporterFBXConv : public EditorSceneImporter {
OBJ_TYPE(EditorSceneImporterFBXConv,EditorSceneImporter );
struct BoneInfo {
Skeleton *skeleton;
Transform rest;
int index;
bool has_anim_chan;
bool has_rest;
Dictionary node;
BoneInfo() {
has_rest=false;
skeleton=NULL;
index=-1;
has_anim_chan=false;
}
};
struct SurfaceInfo {
Array array;
Mesh::PrimitiveType primitive;
};
struct State {
Node *scene;
Array meshes;
Array materials;
Array nodes;
Array animations;
Map<String,BoneInfo > bones;
Map<String,Skeleton*> skeletons;
Map<String,Ref<Mesh> > mesh_cache;
Map<String,SurfaceInfo> surface_cache;
Map<String,Ref<Material> > material_cache;
Map<String,Ref<Texture> > texture_cache;
List<String> *missing_deps;
String base_path;
bool import_animations;
};
String _id(const String& p_id) const;
Transform _get_transform_mixed(const Dictionary& d, const Dictionary& dbase);
Transform _get_transform(const Dictionary& d);
Color _get_color(const Array& a);
void _detect_bones_in_nodes(State& state,const Array& p_nodes);
void _detect_bones(State& state);
Error _parse_bones(State& state,const Array &p_bones,Skeleton* p_skeleton);
void _parse_skeletons(const String& p_name,State& state, const Array &p_nodes, Skeleton*p_skeleton=NULL, int p_parent=-1);
void _add_surface(State& state,Ref<Mesh>& m,const Dictionary &part);
Error _parse_nodes(State& state,const Array &p_nodes,Node* p_base);
Error _parse_animations(State& state);
void _parse_materials(State& state);
void _parse_surfaces(State& state);
Error _parse_json(State& state,const String& p_path);
Error _parse_fbx(State &state, const String &p_path);
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,List<String> *r_missing_deps=NULL,Error* r_err=NULL);
virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags);
EditorSceneImporterFBXConv();
};
#endif // EDITOR_SCENE_IMPORTER_FBXCONV_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,172 @@
/*************************************************************************/
/* editor_texture_import_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_TEXTURE_IMPORT_PLUGIN_H
#define EDITOR_TEXTURE_IMPORT_PLUGIN_H
#include "editor/editor_import_export.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/tree.h"
#include "scene/gui/label.h"
#include "scene/gui/option_button.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/file_dialog.h"
#include "scene/gui/progress_bar.h"
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
#include "editor/editor_file_system.h"
#include "editor/editor_dir_dialog.h"
class EditorNode;
class EditorTextureImportDialog;
class EditorTextureImportPlugin : public EditorImportPlugin {
OBJ_TYPE(EditorTextureImportPlugin,EditorImportPlugin);
public:
enum Mode {
MODE_TEXTURE_2D,
MODE_TEXTURE_3D,
MODE_ATLAS,
MODE_LARGE,
MODE_MAX
};
private:
EditorNode *editor;
EditorTextureImportDialog *dialog;
static EditorTextureImportPlugin *singleton;
//used by other importers such as mesh
Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink);
void compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller);
uint32_t texture_flags_to_export_flags(uint32_t p_tex_flags) const;
public:
static EditorTextureImportPlugin *get_singleton() { return singleton; }
enum ImageFormat {
IMAGE_FORMAT_UNCOMPRESSED,
IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS,
IMAGE_FORMAT_COMPRESS_DISK_LOSSY,
IMAGE_FORMAT_COMPRESS_RAM,
};
enum ImageFlags {
IMAGE_FLAG_STREAM_FORMAT=1,
IMAGE_FLAG_FIX_BORDER_ALPHA=2,
IMAGE_FLAG_ALPHA_BIT=4, //hint for compressions that use a bit for alpha
IMAGE_FLAG_COMPRESS_EXTRA=8, // used for pvrtc2
IMAGE_FLAG_NO_MIPMAPS=16, //normal for 2D games
IMAGE_FLAG_REPEAT=32, //usually disabled in 2D
IMAGE_FLAG_FILTER=64, //almost always enabled
IMAGE_FLAG_PREMULT_ALPHA=128,//almost always enabled
IMAGE_FLAG_CONVERT_TO_LINEAR=256, //convert image to linear
IMAGE_FLAG_CONVERT_NORMAL_TO_XY=512, //convert image to linear
IMAGE_FLAG_USE_ANISOTROPY=1024, //convert image to linear
};
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
virtual Error import2(const String& p_path, const Ref<ResourceImportMetadata>& p_from,EditorExportPlatform::ImageCompression p_compr, bool p_external=false);
virtual Vector<uint8_t> custom_export(const String& p_path,const Ref<EditorExportPlatform> &p_platform);
virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
virtual void reimport_multiple_files(const Vector<String>& p_list);
virtual bool can_reimport_multiple_files() const;
EditorTextureImportPlugin(EditorNode* p_editor=NULL);
};
class EditorTextureExportPlugin : public EditorExportPlugin {
OBJ_TYPE( EditorTextureExportPlugin, EditorExportPlugin);
public:
virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
EditorTextureExportPlugin();
};
class EditorImportTextureOptions : public VBoxContainer {
OBJ_TYPE( EditorImportTextureOptions, VBoxContainer );
OptionButton *format;
VBoxContainer *quality_vb;
HSlider *quality;
Tree *flags;
Vector<TreeItem*> items;
bool updating;
void _changedp(int p_value);
void _changed();
protected:
static void _bind_methods();
void _notification(int p_what);
public:
void set_format(EditorTextureImportPlugin::ImageFormat p_format);
EditorTextureImportPlugin::ImageFormat get_format() const;
void set_flags(uint32_t p_flags);
uint32_t get_flags() const;
void set_quality(float p_quality);
float get_quality() const;
void show_2d_notice();
EditorImportTextureOptions();
};
#endif // EDITOR_TEXTURE_IMPORT_PLUGIN_H

View file

@ -0,0 +1,475 @@
/*************************************************************************/
/* editor_translation_import_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "editor_translation_import_plugin.h"
#include "scene/gui/file_dialog.h"
#include "editor/editor_dir_dialog.h"
#include "editor/editor_node.h"
#include "editor/property_editor.h"
#include "scene/resources/sample.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
#include "translation.h"
#include "compressed_translation.h"
#include "editor/project_settings.h"
class EditorTranslationImportDialog : public ConfirmationDialog {
OBJ_TYPE(EditorTranslationImportDialog,ConfirmationDialog);
EditorTranslationImportPlugin *plugin;
LineEdit *import_path;
LineEdit *save_path;
EditorFileDialog *file_select;
CheckButton *ignore_first;
CheckButton *compress;
CheckButton *add_to_project;
EditorDirDialog *save_select;
ConfirmationDialog *error_dialog;
Vector<TreeItem*> items;
Tree *columns;
public:
void _choose_file(const String& p_path) {
import_path->set_text(p_path);
FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
if (!f) {
error_dialog->set_text(TTR("Invalid source!"));
error_dialog->popup_centered(Size2(200,100)*EDSCALE);
return;
}
Vector<String> csvh = f->get_csv_line();
memdelete(f);
if (csvh.size()<2) {
error_dialog->set_text(TTR("Invalid translation source!"));
error_dialog->popup_centered(Size2(200,100)*EDSCALE);
return;
}
columns->clear();
columns->set_columns(2);
TreeItem *root = columns->create_item();
columns->set_hide_root(true);
columns->set_column_titles_visible(true);
columns->set_column_title(0,TTR("Column"));
columns->set_column_title(1,TTR("Language"));
Vector<String> langs = TranslationServer::get_all_locales();
Vector<String> names = TranslationServer::get_all_locale_names();
if (csvh[0]=="")
ignore_first->set_pressed(true);
items.clear();
for(int i=1;i<csvh.size();i++) {
TreeItem *ti = columns->create_item(root);
ti->set_editable(0,true);
ti->set_selectable(0,false);
ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
ti->set_checked(0,true);
ti->set_text(0,itos(i));
items.push_back(ti);
String lname = csvh[i].to_lower().strip_edges();
int idx=-1;
String hint;
for(int j=0;j<langs.size();j++) {
if (langs[j]==lname.substr(0,langs[j].length()).to_lower()) {
idx=j;
}
if (j>0) {
hint+=",";
}
hint+=names[j].replace(","," ");
}
ti->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
ti->set_text(1,hint);
ti->set_editable(1,true);
if (idx!=-1) {
ignore_first->set_pressed(true);
ti->set_range(1,idx);
} else {
//not found, maybe used stupid name
if (lname.begins_with("br")) //brazilian
ti->set_range(1,langs.find("pt"));
else if (lname.begins_with("ch")) //chinese
ti->set_range(1,langs.find("zh"));
else if (lname.begins_with("sp")) //spanish
ti->set_range(1,langs.find("es"));
else if (lname.begins_with("kr"))// kprean
ti->set_range(1,langs.find("ko"));
else if (i==0)
ti->set_range(1,langs.find("en"));
else
ti->set_range(1,langs.find("es"));
}
ti->set_metadata(1,names[ti->get_range(1)]);
}
}
void _choose_save_dir(const String& p_path) {
save_path->set_text(p_path);
}
void _browse() {
file_select->popup_centered_ratio();
}
void _browse_target() {
save_select->popup_centered_ratio();
}
void popup_import(const String& p_from) {
popup_centered(Size2(400,400)*EDSCALE);
if (p_from!="") {
Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
ERR_FAIL_COND(!rimd.is_valid());
ERR_FAIL_COND(rimd->get_source_count()!=1);
_choose_file(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
_choose_save_dir(p_from.get_base_dir());
String locale = rimd->get_option("locale");
bool skip_first=rimd->get_option("skip_first");
bool compressed = rimd->get_option("compress");
int idx=-1;
for(int i=0;i<items.size();i++) {
String il = TranslationServer::get_all_locales()[items[i]->get_range(1)];
if (il==locale) {
idx=i;
break;
}
}
if (idx!=-1) {
idx=rimd->get_option("index");
}
for(int i=0;i<items.size();i++) {
if (i==idx) {
Vector<String> locs = TranslationServer::get_all_locales();
for(int j=0;j<locs.size();j++) {
if (locs[j]==locale) {
items[i]->set_range(1,j);
}
}
items[i]->set_checked(0,true);
} else {
items[i]->set_checked(0,false);
}
}
ignore_first->set_pressed(skip_first);
compress->set_pressed(compressed);
}
}
void _import() {
if (items.size()==0) {
error_dialog->set_text(TTR("No items to import!"));
error_dialog->popup_centered(Size2(200,100)*EDSCALE);
}
if (!save_path->get_text().begins_with("res://")) {
error_dialog->set_text(TTR("No target path!"));
error_dialog->popup_centered(Size2(200,100)*EDSCALE);
}
EditorProgress progress("import_xl",TTR("Import Translations"),items.size());
for(int i=0;i<items.size();i++) {
progress.step(items[i]->get_metadata(1),i);
if (!items[i]->is_checked(0))
continue;
String locale = TranslationServer::get_all_locales()[items[i]->get_range(1)];
Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
imd->add_source(EditorImportPlugin::validate_source_path(import_path->get_text()));
imd->set_option("locale",locale);
imd->set_option("index",i);
imd->set_option("skip_first",ignore_first->is_pressed());
imd->set_option("compress",compress->is_pressed());
String savefile = save_path->get_text().plus_file(import_path->get_text().get_file().basename()+"."+locale+".xl");
Error err = plugin->import(savefile,imd);
if (err!=OK) {
error_dialog->set_text(TTR("Couldn't import!"));
error_dialog->popup_centered(Size2(200,100)*EDSCALE);
} else if (add_to_project->is_pressed()) {
ProjectSettings::get_singleton()->add_translation(savefile);
}
}
hide();
}
void _notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
}
}
static void _bind_methods() {
ObjectTypeDB::bind_method("_choose_file",&EditorTranslationImportDialog::_choose_file);
ObjectTypeDB::bind_method("_choose_save_dir",&EditorTranslationImportDialog::_choose_save_dir);
ObjectTypeDB::bind_method("_import",&EditorTranslationImportDialog::_import);
ObjectTypeDB::bind_method("_browse",&EditorTranslationImportDialog::_browse);
ObjectTypeDB::bind_method("_browse_target",&EditorTranslationImportDialog::_browse_target);
// ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
}
EditorTranslationImportDialog(EditorTranslationImportPlugin *p_plugin) {
plugin=p_plugin;
set_title(TTR("Import Translation"));
VBoxContainer *vbc = memnew( VBoxContainer );
add_child(vbc);
set_child_rect(vbc);
VBoxContainer *csvb = memnew( VBoxContainer );
HBoxContainer *hbc = memnew( HBoxContainer );
csvb->add_child(hbc);
vbc->add_margin_child(TTR("Source CSV:"),csvb);
import_path = memnew( LineEdit );
import_path->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(import_path);
ignore_first = memnew( CheckButton );
ignore_first->set_text(TTR("Ignore First Row"));
csvb->add_child(ignore_first);
Button * import_choose = memnew( Button );
import_choose->set_text(" .. ");
hbc->add_child(import_choose);
import_choose->connect("pressed", this,"_browse");
VBoxContainer *tcomp = memnew( VBoxContainer);
hbc = memnew( HBoxContainer );
tcomp->add_child(hbc);
vbc->add_margin_child(TTR("Target Path:"),tcomp);
save_path = memnew( LineEdit );
save_path->set_h_size_flags(SIZE_EXPAND_FILL);
hbc->add_child(save_path);
Button * save_choose = memnew( Button );
save_choose->set_text(" .. ");
hbc->add_child(save_choose);
save_choose->connect("pressed", this,"_browse_target");
compress = memnew( CheckButton);
compress->set_pressed(true);
compress->set_text(TTR("Compress"));
tcomp->add_child(compress);
add_to_project = memnew( CheckButton);
add_to_project->set_pressed(true);
add_to_project->set_text(TTR("Add to Project (engine.cfg)"));
tcomp->add_child(add_to_project);
file_select = memnew(EditorFileDialog);
file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
add_child(file_select);
file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
file_select->connect("file_selected", this,"_choose_file");
file_select->add_filter("*.csv ; Translation CSV");
save_select = memnew( EditorDirDialog );
add_child(save_select);
// save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
save_select->connect("dir_selected", this,"_choose_save_dir");
get_ok()->connect("pressed", this,"_import");
get_ok()->set_text(TTR("Import"));
error_dialog = memnew ( ConfirmationDialog );
add_child(error_dialog);
error_dialog->get_ok()->set_text(TTR("Accept"));
// error_dialog->get_cancel()->hide();
set_hide_on_ok(false);
columns = memnew( Tree );
vbc->add_margin_child(TTR("Import Languages:"),columns,true);
}
~EditorTranslationImportDialog() {
}
};
String EditorTranslationImportPlugin::get_name() const {
return "translation";
}
String EditorTranslationImportPlugin::get_visible_name() const {
return TTR("Translation");
}
void EditorTranslationImportPlugin::import_dialog(const String& p_from) {
dialog->popup_import(p_from);
}
void EditorTranslationImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
for(int i=0;i<p_drop.size();i++) {
String ext = p_drop[i].extension().to_lower();
if (ext=="csv") {
import_dialog();
dialog->_choose_file(p_drop[i]);
dialog->_choose_save_dir(p_dest_path);
break;
}
}
}
Error EditorTranslationImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from) {
Ref<ResourceImportMetadata> from = p_from;
ERR_FAIL_COND_V( from->get_source_count()!=1, ERR_INVALID_PARAMETER);
String source = EditorImportPlugin::expand_source_path( from->get_source_path(0) );
FileAccessRef f = FileAccess::open(source,FileAccess::READ);
ERR_FAIL_COND_V( !f, ERR_INVALID_PARAMETER );
bool skip_first = from->get_option("skip_first");
int index = from->get_option("index");
index+=1;
String locale = from->get_option("locale");
Ref<Translation> translation = memnew( Translation );
translation->set_locale( locale );
Vector<String> line = f->get_csv_line();
while(line.size()>1) {
if (!skip_first) {
ERR_FAIL_INDEX_V(index,line.size(),ERR_INVALID_DATA );
translation->add_message(line[0].strip_edges(),line[index]);
} else {
skip_first=false;
}
line = f->get_csv_line();
}
from->set_source_md5(0,FileAccess::get_md5(source));
from->set_editor(get_name());
String dst_path = p_path;
if (from->get_option("compress")) {
Ref<PHashTranslation> cxl = memnew( PHashTranslation );
cxl->generate( translation );
translation=cxl;
}
translation->set_import_metadata(from);
return ResourceSaver::save(dst_path,translation);
}
EditorTranslationImportPlugin::EditorTranslationImportPlugin(EditorNode* p_editor) {
dialog = memnew(EditorTranslationImportDialog(this));
p_editor->get_gui_base()->add_child(dialog);
}

View file

@ -0,0 +1,55 @@
/*************************************************************************/
/* editor_translation_import_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 EDITOR_TRANSLATION_IMPORT_PLUGIN_H
#define EDITOR_TRANSLATION_IMPORT_PLUGIN_H
#include "editor/editor_import_export.h"
#include "scene/resources/font.h"
class EditorNode;
class EditorTranslationImportDialog;
class EditorTranslationImportPlugin : public EditorImportPlugin {
OBJ_TYPE(EditorTranslationImportPlugin,EditorImportPlugin);
EditorTranslationImportDialog *dialog;
public:
virtual String get_name() const;
virtual String get_visible_name() const;
virtual void import_dialog(const String& p_from="");
virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
EditorTranslationImportPlugin(EditorNode* p_editor);
};
#endif // EDITOR_TRANSLATION_IMPORT_PLUGIN_H