mirror of
https://github.com/godotengine/godot.git
synced 2024-11-21 19:42:43 +00:00
Merge branch 'master' of https://github.com/okamstudio/godot
This commit is contained in:
commit
449bc14fb4
@ -202,7 +202,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
|
||||
|
||||
for(int i=0;i<argc;i++) {
|
||||
|
||||
args.push_back(argv[i]);
|
||||
args.push_back(String::utf8(argv[i]));
|
||||
}
|
||||
|
||||
List<String>::Element *I=args.front();
|
||||
|
@ -42,6 +42,8 @@ if (env["tools"]=="yes"):
|
||||
f = open("register_exporters.cpp","wb")
|
||||
f.write(reg_exporters_inc)
|
||||
f.write(reg_exporters)
|
||||
f.close()
|
||||
|
||||
env.Depends("#tools/editor/doc_data_compressed.h","#doc/base/classes.xml")
|
||||
env.Command("#tools/editor/doc_data_compressed.h","#doc/base/classes.xml",make_doc_header)
|
||||
|
||||
|
@ -82,8 +82,6 @@
|
||||
#include "plugins/path_2d_editor_plugin.h"
|
||||
#include "plugins/particles_editor_plugin.h"
|
||||
#include "plugins/particles_2d_editor_plugin.h"
|
||||
#include "plugins/font_editor_plugin.h"
|
||||
#include "plugins/animation_editor_plugin.h"
|
||||
#include "plugins/animation_tree_editor_plugin.h"
|
||||
#include "plugins/tile_set_editor_plugin.h"
|
||||
#include "plugins/animation_player_editor_plugin.h"
|
||||
@ -94,6 +92,7 @@
|
||||
#include "tools/editor/io_plugins/editor_sample_import_plugin.h"
|
||||
#include "tools/editor/io_plugins/editor_translation_import_plugin.h"
|
||||
|
||||
|
||||
EditorNode *EditorNode::singleton=NULL;
|
||||
|
||||
void EditorNode::_update_title() {
|
||||
@ -2130,9 +2129,28 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
|
||||
} break;
|
||||
case RUN_SETTINGS: {
|
||||
|
||||
|
||||
project_settings->popup_project_settings();
|
||||
} break;
|
||||
case RUN_PROJECT_MANAGER: {
|
||||
|
||||
if (!p_confirmed) {
|
||||
confirmation->get_ok()->set_text("Yes");
|
||||
confirmation->set_text("Open Project Manager? \n(Unsaved changes will be lost)");
|
||||
confirmation->popup_centered(Size2(300,70));
|
||||
break;
|
||||
}
|
||||
|
||||
get_scene()->quit();
|
||||
String exec = OS::get_singleton()->get_executable_path();
|
||||
|
||||
List<String> args;
|
||||
args.push_back ( "-path" );
|
||||
args.push_back (exec.get_base_dir() );
|
||||
|
||||
OS::ProcessID pid=0;
|
||||
Error err = OS::get_singleton()->execute(exec,args,false,&pid);
|
||||
ERR_FAIL_COND(err);
|
||||
} break;
|
||||
case RUN_FILE_SERVER: {
|
||||
|
||||
//file_server
|
||||
@ -3407,6 +3425,7 @@ EditorNode::EditorNode() {
|
||||
p->add_item("Redo",EDIT_REDO,KEY_MASK_CMD+KEY_MASK_SHIFT+KEY_Z);
|
||||
p->add_separator();
|
||||
p->add_item("Project Settings",RUN_SETTINGS);
|
||||
p->add_item("Project Manager",RUN_PROJECT_MANAGER);
|
||||
p->add_separator();
|
||||
p->add_item("Quit",FILE_QUIT,KEY_MASK_CMD+KEY_Q);
|
||||
|
||||
@ -3959,16 +3978,13 @@ EditorNode::EditorNode() {
|
||||
add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( EditorHelpPlugin(this) ) );
|
||||
add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) );
|
||||
//add_editor_plugin( memnew( AnimationEditorPlugin(this) ) ); - not useful anymore
|
||||
add_editor_plugin( memnew( ShaderEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( CameraEditorPlugin(this) ) );
|
||||
//add_editor_plugin( memnew( FontEditorPlugin(this) ) ); obsolete
|
||||
add_editor_plugin( memnew( SampleEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( SampleLibraryEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( ThemeEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( MultiMeshEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( AnimationTreeEditorPlugin(this) ) );
|
||||
//add_editor_plugin( memnew( GridMapEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( SamplePlayerEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( MeshLibraryEditorPlugin(this) ) );
|
||||
add_editor_plugin( memnew( StreamEditorPlugin(this) ) );
|
||||
|
@ -137,6 +137,7 @@ class EditorNode : public Node {
|
||||
RUN_PLAY_CUSTOM_SCENE,
|
||||
RUN_SCENE_SETTINGS,
|
||||
RUN_SETTINGS,
|
||||
RUN_PROJECT_MANAGER,
|
||||
RUN_FILE_SERVER,
|
||||
RUN_DEPLOY_DUMB_CLIENTS,
|
||||
SETTINGS_UPDATE_ALWAYS,
|
||||
|
@ -1,806 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* animation_editor_plugin.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 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 "animation_editor_plugin.h"
|
||||
#include "io/resource_loader.h"
|
||||
|
||||
|
||||
class AnimationEditor_TrackEditor : public Object {
|
||||
|
||||
OBJ_TYPE(AnimationEditor_TrackEditor,Object);
|
||||
|
||||
protected:
|
||||
|
||||
bool _set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
if (anim.is_null())
|
||||
return false;
|
||||
String name=p_name;
|
||||
|
||||
if (name=="track/interpolation") {
|
||||
|
||||
anim_editor->_internal_set_interpolation_type(track,Animation::InterpolationType(p_value.operator int()));
|
||||
|
||||
} else if (name.begins_with("keys/")) {
|
||||
|
||||
int key = name.get_slice("/",1).to_int();
|
||||
ERR_FAIL_INDEX_V( key,anim->track_get_key_count(track), false );
|
||||
String what = name.get_slice("/",2);
|
||||
float time = anim->track_get_key_time(track,key);
|
||||
float transition = anim->track_get_key_transition(track,key);
|
||||
|
||||
if (what=="time") {
|
||||
Variant v = anim->track_get_key_value(track,key);
|
||||
anim_editor->_internal_set_key(track,time,transition,v);
|
||||
return true;
|
||||
}
|
||||
if (what=="transition") {
|
||||
transition=p_value;
|
||||
Variant v = anim->track_get_key_value(track,key);
|
||||
anim_editor->_internal_set_key(track,time,transition,v);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch(anim->track_get_type(track)) {
|
||||
|
||||
case Animation::TYPE_TRANSFORM: {
|
||||
|
||||
Vector3 scale,loc;
|
||||
Quat rot;
|
||||
anim->transform_track_get_key(track,key,&loc,&rot,&scale);
|
||||
|
||||
|
||||
if (what=="loc") {
|
||||
loc=p_value;
|
||||
} else if (what=="scale") {
|
||||
scale=p_value;
|
||||
} else if (what=="rot") {
|
||||
rot=p_value;
|
||||
} else {
|
||||
return false; //meh
|
||||
}
|
||||
|
||||
Dictionary k;
|
||||
k["rot"]=rot;
|
||||
k["loc"]=loc;
|
||||
k["scale"]=scale;
|
||||
anim_editor->_internal_set_key(track,time,transition,k);
|
||||
|
||||
} break;
|
||||
case Animation::TYPE_METHOD: {
|
||||
|
||||
} break;
|
||||
case Animation::TYPE_VALUE: {
|
||||
|
||||
if (what=="value")
|
||||
anim_editor->_internal_set_key(track,time,transition,p_value);
|
||||
} break;
|
||||
default: { return false; }
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _get(const StringName& p_name,Variant &r_ret) const {
|
||||
|
||||
if (anim.is_null())
|
||||
return false;
|
||||
String name=p_name;
|
||||
|
||||
if (name=="track/interpolation") {
|
||||
|
||||
r_ret=anim->track_get_interpolation_type(track);
|
||||
|
||||
} else if (name.begins_with("keys/")) {
|
||||
|
||||
int key = name.get_slice("/",1).to_int();
|
||||
ERR_FAIL_INDEX_V( key,anim->track_get_key_count(track), Variant() );
|
||||
String what = name.get_slice("/",2);
|
||||
|
||||
if (what=="time") {
|
||||
r_ret=anim->track_get_key_time(track,key);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (what=="transition") {
|
||||
r_ret=anim->track_get_key_transition(track,key);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch(anim->track_get_type(track)) {
|
||||
|
||||
case Animation::TYPE_TRANSFORM: {
|
||||
|
||||
Vector3 scale,loc;
|
||||
Quat rot;
|
||||
anim->transform_track_get_key(track,key,&loc,&rot,&scale);
|
||||
|
||||
|
||||
if (what=="loc") {
|
||||
r_ret= loc;
|
||||
} else if (what=="scale") {
|
||||
r_ret= scale;
|
||||
} else if (what=="rot") {
|
||||
r_ret= rot;
|
||||
}
|
||||
|
||||
} break;
|
||||
case Animation::TYPE_METHOD: {
|
||||
|
||||
} break;
|
||||
case Animation::TYPE_VALUE: {
|
||||
|
||||
if (what=="value")
|
||||
r_ret= anim->track_get_key_value(track,key);
|
||||
} break;
|
||||
default: { return false; }
|
||||
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
void _get_property_list( List<PropertyInfo> *p_list) const {
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::INT,"track/interpolation",PROPERTY_HINT_ENUM,"Nearest,Linear,Cubic") );
|
||||
|
||||
if (anim.is_null())
|
||||
return;
|
||||
|
||||
int keycount = anim->track_get_key_count(track);
|
||||
|
||||
for(int i=0;i<keycount;i++) {
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::REAL,"keys/"+itos(i)+"/time",PROPERTY_HINT_RANGE,"0,3600,0.001") );
|
||||
p_list->push_back(PropertyInfo(Variant::REAL,"keys/"+itos(i)+"/transition",PROPERTY_HINT_EXP_EASING) );
|
||||
switch(anim->track_get_type(track)) {
|
||||
|
||||
case Animation::TYPE_TRANSFORM: {
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::VECTOR3,"keys/"+itos(i)+"/loc" ) );
|
||||
p_list->push_back(PropertyInfo(Variant::QUAT,"keys/"+itos(i)+"/rot" ) );
|
||||
p_list->push_back(PropertyInfo(Variant::VECTOR3,"keys/"+itos(i)+"/scale" ) );
|
||||
|
||||
} break;
|
||||
case Animation::TYPE_METHOD: {
|
||||
|
||||
} break;
|
||||
case Animation::TYPE_VALUE: {
|
||||
|
||||
|
||||
Variant v = anim->track_get_key_value(track,i);
|
||||
|
||||
PropertyHint hint=PROPERTY_HINT_NONE;
|
||||
String hint_string;
|
||||
if (v.get_type()==Variant::INT) {
|
||||
hint=PROPERTY_HINT_RANGE;
|
||||
hint_string="-16384,16384,1";
|
||||
} else if (v.get_type()==Variant::REAL) {
|
||||
hint=PROPERTY_HINT_RANGE;
|
||||
hint_string="-16384,16384,0.001";
|
||||
} else if (v.get_type()==Variant::OBJECT) {
|
||||
hint=PROPERTY_HINT_RESOURCE_TYPE;
|
||||
hint_string="Resource";
|
||||
}
|
||||
|
||||
|
||||
|
||||
p_list->push_back(PropertyInfo(v.get_type(),"keys/"+itos(i)+"/value",hint,hint_string ) );
|
||||
|
||||
|
||||
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
AnimationEditor *anim_editor;
|
||||
|
||||
Ref<Animation> anim;
|
||||
int track;
|
||||
AnimationEditor_TrackEditor() { }
|
||||
|
||||
};
|
||||
|
||||
|
||||
void AnimationEditor::update_anim() {
|
||||
|
||||
tracks->clear();
|
||||
key_editor->edit(NULL);
|
||||
TreeItem *root = tracks->create_item(NULL);
|
||||
|
||||
TreeItem *sel=NULL;
|
||||
int selected_track=-1;
|
||||
if (animation->has_meta("_anim_editor_selected_track_"))
|
||||
selected_track=animation->get_meta("_anim_editor_selected_track_");
|
||||
|
||||
for(int i=0;i<animation->get_track_count();i++) {
|
||||
|
||||
String path = animation->track_get_path(i);
|
||||
TreeItem *track = tracks->create_item(root);
|
||||
track->set_text(0,itos(i));
|
||||
track->set_editable(0,false);
|
||||
track->set_text(1,path);
|
||||
track->set_editable(1,true);
|
||||
track->set_metadata(0,i);
|
||||
if (selected_track==i)
|
||||
sel=track;
|
||||
|
||||
switch(animation->track_get_type(i)) {
|
||||
|
||||
case Animation::TYPE_TRANSFORM: {
|
||||
|
||||
track->set_icon(0,get_icon("Matrix","EditorIcons"));
|
||||
|
||||
} break;
|
||||
case Animation::TYPE_METHOD: {
|
||||
track->set_icon(0,get_icon("TrackMethod","EditorIcons"));
|
||||
} break;
|
||||
case Animation::TYPE_VALUE: {
|
||||
|
||||
track->set_icon(0,get_icon("TrackValue","EditorIcons"));
|
||||
} break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (sel) {
|
||||
sel->select(1);
|
||||
_update_track_keys();
|
||||
} else {
|
||||
selected_track=-1;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationEditor::_update_track_keys() {
|
||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
||||
return;
|
||||
track_editor->anim=animation;
|
||||
track_editor->track=selected_track;
|
||||
key_editor->edit(NULL);
|
||||
key_editor->edit(track_editor);
|
||||
|
||||
if (animation->track_get_type(selected_track)==Animation::TYPE_VALUE) {
|
||||
key_time->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,160);
|
||||
key_type->show();
|
||||
} else {
|
||||
key_time->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,60);
|
||||
key_type->hide();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void AnimationEditor::_track_path_changed() {
|
||||
|
||||
TreeItem *ti=tracks->get_edited();
|
||||
int track=ti->get_metadata(0);
|
||||
String path=ti->get_text(1);
|
||||
if (track<0 || track>=animation->get_track_count())
|
||||
return;
|
||||
undo_redo->create_action("Create Anim Track");
|
||||
undo_redo->add_do_method(animation.ptr(),"track_set_path",track,path);
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_set_path",track,animation->track_get_path(track));
|
||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
||||
undo_redo->commit_action();
|
||||
|
||||
}
|
||||
|
||||
void AnimationEditor::_track_selected() {
|
||||
|
||||
TreeItem *ti=tracks->get_selected();
|
||||
if(!ti)
|
||||
return;
|
||||
selected_track=ti->get_metadata(0);
|
||||
animation->set_meta("_anim_editor_selected_track_",selected_track);
|
||||
_update_track_keys();
|
||||
}
|
||||
|
||||
void AnimationEditor::_track_added() {
|
||||
|
||||
undo_redo->create_action("Create Anim Track");
|
||||
undo_redo->add_do_method(animation.ptr(),"add_track",track_type->get_selected(),-1);
|
||||
undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count());
|
||||
undo_redo->add_do_method(this,"_internal_set_selected_track",animation->get_track_count(),animation);
|
||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",selected_track,animation);
|
||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
||||
undo_redo->commit_action();
|
||||
update_anim();
|
||||
}
|
||||
|
||||
void AnimationEditor::_track_removed() {
|
||||
|
||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
||||
return;
|
||||
|
||||
undo_redo->create_action("Remove Anim Track");
|
||||
undo_redo->add_do_method(animation.ptr(),"remove_track",selected_track);
|
||||
undo_redo->add_undo_method(animation.ptr(),"add_track",animation->track_get_type(selected_track),selected_track);
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_set_path",selected_track,animation->track_get_path(selected_track));
|
||||
//todo interpolation
|
||||
for(int i=0;i<animation->track_get_key_count(selected_track);i++) {
|
||||
|
||||
Variant v = animation->track_get_key_value(selected_track,i);
|
||||
float time = animation->track_get_key_time(selected_track,i);
|
||||
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_insert_key",selected_track,time,v);
|
||||
|
||||
}
|
||||
|
||||
int old_track=selected_track;
|
||||
if (selected_track>0)
|
||||
selected_track--;
|
||||
if (selected_track<0 || selected_track>=(animation->get_track_count()-1))
|
||||
selected_track=-1;
|
||||
|
||||
undo_redo->add_do_method(this,"_internal_set_selected_track",selected_track,animation);
|
||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",old_track,animation);
|
||||
|
||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
||||
undo_redo->commit_action();
|
||||
|
||||
}
|
||||
|
||||
void AnimationEditor::_internal_set_interpolation_type(int p_track,Animation::InterpolationType p_type) {
|
||||
|
||||
undo_redo->create_action("Set Interpolation");
|
||||
undo_redo->add_do_method(animation.ptr(),"track_set_interpolation_type",p_track,p_type);
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",p_track,animation->track_get_interpolation_type(p_track));
|
||||
undo_redo->add_do_method(this,"_internal_set_selected_track",selected_track,animation);
|
||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",selected_track,animation);
|
||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
||||
undo_redo->commit_action();
|
||||
|
||||
}
|
||||
|
||||
void AnimationEditor::_internal_set_selected_track(int p_which,const Ref<Animation>& p_anim) {
|
||||
|
||||
if (is_visible() && animation==p_anim) {
|
||||
selected_track=p_which;
|
||||
animation->set_meta("_anim_editor_selected_track_",selected_track);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationEditor::_track_moved_up() {
|
||||
|
||||
|
||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
||||
return;
|
||||
|
||||
if (selected_track<(animation->get_track_count()-1)) {
|
||||
undo_redo->create_action("Move Up Track");
|
||||
undo_redo->add_do_method(animation.ptr(),"track_move_up",selected_track);
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_move_down",selected_track+1);
|
||||
undo_redo->add_do_method(this,"_internal_set_selected_track",selected_track+1,animation);
|
||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",selected_track,animation);
|
||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationEditor::_track_moved_down() {
|
||||
|
||||
|
||||
|
||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
||||
return;
|
||||
if (selected_track>0) {
|
||||
undo_redo->create_action("Move Down Track");
|
||||
undo_redo->add_do_method(animation.ptr(),"track_move_down",selected_track);
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_move_up",selected_track-1);
|
||||
undo_redo->add_do_method(this,"_internal_set_selected_track",selected_track-1,animation);
|
||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",selected_track,animation);
|
||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void AnimationEditor::_key_added() {
|
||||
|
||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
||||
return;
|
||||
|
||||
bool need_variant= animation->track_get_type(selected_track)==Animation::TYPE_VALUE;
|
||||
|
||||
Variant v;
|
||||
|
||||
if (need_variant) {
|
||||
|
||||
switch(key_type->get_selected()) {
|
||||
|
||||
case Variant::NIL: v=Variant(); break;
|
||||
case Variant::BOOL: v=false; break;
|
||||
case Variant::INT: v=0; break;
|
||||
case Variant::REAL: v=0.0; break;
|
||||
case Variant::STRING: v=""; break;
|
||||
case Variant::VECTOR2: v=Vector2(); break; // 5
|
||||
case Variant::RECT2: v=Rect2(); break;
|
||||
case Variant::VECTOR3: v=Vector3(); break;
|
||||
case Variant::PLANE: v=Plane(); break;
|
||||
case Variant::QUAT: v=Quat(); break;
|
||||
case Variant::_AABB: v=AABB(); break; //sorry naming convention fail :( not like it's used often // 10
|
||||
case Variant::MATRIX3: v=Matrix3(); break;
|
||||
case Variant::TRANSFORM: v=Transform(); break;
|
||||
case Variant::COLOR: v=Color(); break;
|
||||
case Variant::IMAGE: v=Image(); break;
|
||||
case Variant::NODE_PATH: v=NodePath(); break; // 15
|
||||
case Variant::_RID: v=RID(); break;
|
||||
case Variant::OBJECT: v=Variant(); break;
|
||||
case Variant::INPUT_EVENT: v=InputEvent(); break;
|
||||
case Variant::DICTIONARY: v=Dictionary(); break; // 20
|
||||
case Variant::ARRAY: v=Array(); break;
|
||||
case Variant::RAW_ARRAY: v=DVector<uint8_t>(); break;
|
||||
case Variant::INT_ARRAY: v=DVector<int>(); break;
|
||||
case Variant::REAL_ARRAY: v=DVector<real_t>(); break;
|
||||
case Variant::STRING_ARRAY: v=DVector<String>(); break; //25
|
||||
case Variant::VECTOR3_ARRAY: v=DVector<Vector3>(); break;
|
||||
case Variant::COLOR_ARRAY: v=DVector<Color>(); break;
|
||||
default: v=Variant(); break;
|
||||
}
|
||||
}
|
||||
|
||||
float time = key_time->get_text().to_double();
|
||||
|
||||
switch(animation->track_get_type(selected_track)) {
|
||||
case Animation::TYPE_TRANSFORM: {
|
||||
|
||||
Dictionary d;
|
||||
d["loc"]=Vector3();
|
||||
d["rot"]=Quat();
|
||||
d["scale"]=Vector3(1,1,1);
|
||||
v=d;
|
||||
|
||||
} break;
|
||||
case Animation::TYPE_VALUE: {
|
||||
//v=v
|
||||
} break;
|
||||
case Animation::TYPE_METHOD: {
|
||||
|
||||
return; //not do anything yet
|
||||
} break;
|
||||
}
|
||||
|
||||
_internal_set_key(selected_track,time,1.0,v);
|
||||
|
||||
_update_track_keys();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AnimationEditor::_internal_check_update(Ref<Animation> p_anim) {
|
||||
|
||||
if (is_visible() && p_anim==animation) {
|
||||
update_anim();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationEditor::_internal_set_key(int p_track, float p_time, float p_transition,const Variant& p_value) {
|
||||
|
||||
int prev = animation->track_find_key(p_track,p_time);
|
||||
bool existing = (prev>=0) && (animation->track_get_key_time(p_track,prev)==p_time);
|
||||
|
||||
undo_redo->create_action("Insert Key");
|
||||
|
||||
undo_redo->add_do_method(animation.ptr(),"track_insert_key",p_track,p_time,p_value,p_transition);
|
||||
if (existing)
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_insert_key",p_track,p_time,animation->track_get_key_value(p_track,existing),animation->track_get_key_transition(p_track,existing));
|
||||
else
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_remove_key",p_track,prev+1);
|
||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
||||
|
||||
undo_redo->commit_action();
|
||||
}
|
||||
|
||||
void AnimationEditor::_key_removed() {
|
||||
|
||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
||||
return;
|
||||
|
||||
String sel=key_editor->get_selected_path();
|
||||
if (sel.get_slice_count("/")<2)
|
||||
return;
|
||||
if (sel.get_slice("/",0)!="keys")
|
||||
return;
|
||||
int key = sel.get_slice("/",1).to_int();
|
||||
if (key<0 || key>=animation->track_get_key_count(selected_track))
|
||||
return;
|
||||
|
||||
|
||||
undo_redo->create_action("Remove Key");
|
||||
|
||||
Variant data = animation->track_get_key_value(selected_track,key);
|
||||
float time = animation->track_get_key_time(selected_track,key);
|
||||
undo_redo->add_do_method(animation.ptr(),"track_remove_key",selected_track,key);
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_insert_key",selected_track,time,data);
|
||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
||||
undo_redo->commit_action();
|
||||
|
||||
_update_track_keys();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AnimationEditor::edit(const Ref<Animation>& p_animation) {
|
||||
|
||||
|
||||
animation=p_animation;
|
||||
if (!animation.is_null())
|
||||
update_anim();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AnimationEditor::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_track_selected"),&AnimationEditor::_track_selected);
|
||||
ObjectTypeDB::bind_method(_MD("_track_added"),&AnimationEditor::_track_added);
|
||||
ObjectTypeDB::bind_method(_MD("_track_removed"),&AnimationEditor::_track_removed);
|
||||
ObjectTypeDB::bind_method(_MD("_track_moved_up"),&AnimationEditor::_track_moved_up);
|
||||
ObjectTypeDB::bind_method(_MD("_track_moved_down"),&AnimationEditor::_track_moved_down);
|
||||
ObjectTypeDB::bind_method(_MD("_track_path_changed"),&AnimationEditor::_track_path_changed);
|
||||
ObjectTypeDB::bind_method(_MD("_key_added"),&AnimationEditor::_key_added);
|
||||
ObjectTypeDB::bind_method(_MD("_key_removed"),&AnimationEditor::_key_removed);
|
||||
ObjectTypeDB::bind_method(_MD("_internal_check_update"),&AnimationEditor::_internal_check_update);
|
||||
ObjectTypeDB::bind_method(_MD("_internal_set_selected_track"),&AnimationEditor::_internal_set_selected_track);
|
||||
|
||||
}
|
||||
|
||||
void AnimationEditor::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_ENTER_SCENE: {
|
||||
|
||||
add_track->set_icon( get_icon("Add","EditorIcons") );
|
||||
remove_track->set_icon( get_icon("Del","EditorIcons") );
|
||||
move_up_track->set_icon( get_icon("Up","EditorIcons") );
|
||||
move_down_track->set_icon( get_icon("Down","EditorIcons") );
|
||||
time_icon->set_texture( get_icon("Time","EditorIcons") );
|
||||
|
||||
add_key->set_icon( get_icon("Add","EditorIcons") );
|
||||
remove_key->set_icon( get_icon("Del","EditorIcons") );
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
AnimationEditor::AnimationEditor() {
|
||||
|
||||
panel = memnew( Panel );
|
||||
add_child(panel);
|
||||
panel->set_area_as_parent_rect();
|
||||
|
||||
Control *left_pane = memnew( Control );
|
||||
panel->add_child(left_pane);
|
||||
left_pane->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
|
||||
left_pane->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
|
||||
|
||||
Label *l = memnew( Label );
|
||||
l->set_text("Track List:");
|
||||
l->set_pos(Point2(5,5));
|
||||
left_pane->add_child(l);
|
||||
|
||||
/*
|
||||
track_name = memnew( LineEdit );
|
||||
track_name->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,10);
|
||||
track_name->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
track_name->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,80);
|
||||
track_name->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
left_pane->add_child(track_name);
|
||||
*/
|
||||
|
||||
track_type = memnew( OptionButton );
|
||||
track_type->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,10);
|
||||
track_type->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
track_type->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,115);
|
||||
track_type->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
left_pane->add_child(track_type);
|
||||
track_type->add_item("Transform",Animation::TYPE_TRANSFORM);
|
||||
track_type->add_item("Value",Animation::TYPE_VALUE);
|
||||
track_type->add_item("Method",Animation::TYPE_METHOD);
|
||||
|
||||
|
||||
add_track = memnew( Button );
|
||||
add_track->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,110);
|
||||
add_track->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
add_track->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,90);
|
||||
add_track->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
left_pane->add_child(add_track);
|
||||
|
||||
remove_track = memnew( Button );
|
||||
remove_track->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,85);
|
||||
remove_track->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
remove_track->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,60);
|
||||
remove_track->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
left_pane->add_child(remove_track);
|
||||
|
||||
move_up_track = memnew( Button );
|
||||
move_up_track->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,55);
|
||||
move_up_track->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
move_up_track->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,30);
|
||||
move_up_track->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
left_pane->add_child(move_up_track);
|
||||
|
||||
move_down_track = memnew( Button );
|
||||
move_down_track->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,25);
|
||||
move_down_track->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
move_down_track->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
|
||||
move_down_track->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
left_pane->add_child(move_down_track);
|
||||
|
||||
tracks = memnew(Tree);
|
||||
tracks->set_columns(2);
|
||||
tracks->set_column_expand(0,false);
|
||||
tracks->set_column_min_width(0,55);
|
||||
tracks->set_column_expand(1,true);
|
||||
tracks->set_column_min_width(1,100);
|
||||
tracks->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,55);
|
||||
tracks->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
|
||||
tracks->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,10);
|
||||
tracks->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,5);
|
||||
tracks->set_hide_root(true);
|
||||
left_pane->add_child(tracks);
|
||||
|
||||
|
||||
Control *right_pane = memnew( Control );
|
||||
panel->add_child(right_pane);
|
||||
right_pane->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
|
||||
right_pane->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
|
||||
right_pane->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
|
||||
|
||||
l = memnew( Label );
|
||||
l->set_text("Track Keys:");
|
||||
l->set_pos(Point2(5,5));
|
||||
right_pane->add_child(l);
|
||||
|
||||
time_icon = memnew( TextureFrame );
|
||||
time_icon->set_pos(Point2(8,28));
|
||||
right_pane->add_child(time_icon);
|
||||
|
||||
key_time = memnew( LineEdit );
|
||||
key_time->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,24);
|
||||
key_time->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,160);
|
||||
key_time->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
key_time->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
key_time->set_text("0.0");
|
||||
right_pane->add_child(key_time);
|
||||
|
||||
key_type = memnew( OptionButton );
|
||||
key_type->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,160);
|
||||
key_type->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,60);
|
||||
key_type->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
key_type->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
right_pane->add_child(key_type);
|
||||
|
||||
for(int i=0;i<Variant::VARIANT_MAX;i++) {
|
||||
|
||||
key_type->add_item(Variant::get_type_name(Variant::Type(i)));
|
||||
}
|
||||
|
||||
add_key = memnew( Button );
|
||||
add_key->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,55);
|
||||
add_key->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,30);
|
||||
add_key->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
add_key->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
right_pane->add_child(add_key);
|
||||
|
||||
remove_key = memnew( Button );
|
||||
remove_key->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,25);
|
||||
remove_key->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
|
||||
remove_key->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
||||
remove_key->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
||||
right_pane->add_child(remove_key);
|
||||
|
||||
key_editor = memnew(PropertyEditor);
|
||||
key_editor->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,55);
|
||||
key_editor->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
|
||||
key_editor->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,10);
|
||||
key_editor->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,5);
|
||||
key_editor->hide_top_label();
|
||||
|
||||
right_pane->add_child(key_editor);
|
||||
|
||||
track_editor = memnew( AnimationEditor_TrackEditor );
|
||||
track_editor->anim_editor=this;
|
||||
selected_track=-1;
|
||||
|
||||
add_track->connect("pressed", this,"_track_added");
|
||||
remove_track->connect("pressed", this,"_track_removed");
|
||||
move_up_track->connect("pressed", this,"_track_moved_up");
|
||||
move_down_track->connect("pressed", this,"_track_moved_down");
|
||||
tracks->connect("cell_selected", this,"_track_selected");
|
||||
tracks->connect("item_edited", this,"_track_path_changed");
|
||||
add_key->connect("pressed", this,"_key_added");
|
||||
remove_key->connect("pressed", this,"_key_removed");
|
||||
}
|
||||
|
||||
AnimationEditor::~AnimationEditor() {
|
||||
|
||||
memdelete(track_editor);
|
||||
}
|
||||
|
||||
void AnimationEditorPlugin::edit(Object *p_node) {
|
||||
|
||||
animation_editor->set_undo_redo(&get_undo_redo());
|
||||
if (p_node && p_node->cast_to<Animation>()) {
|
||||
animation_editor->edit( p_node->cast_to<Animation>() );
|
||||
animation_editor->show();
|
||||
} else
|
||||
animation_editor->hide();
|
||||
}
|
||||
|
||||
bool AnimationEditorPlugin::handles(Object *p_node) const{
|
||||
|
||||
return p_node->is_type("Animation");
|
||||
}
|
||||
|
||||
void AnimationEditorPlugin::make_visible(bool p_visible){
|
||||
|
||||
if (p_visible)
|
||||
animation_editor->show();
|
||||
else
|
||||
animation_editor->hide();
|
||||
}
|
||||
|
||||
AnimationEditorPlugin::AnimationEditorPlugin(EditorNode *p_node) {
|
||||
|
||||
animation_editor = memnew( AnimationEditor );
|
||||
|
||||
p_node->get_viewport()->add_child(animation_editor);
|
||||
animation_editor->set_area_as_parent_rect();
|
||||
animation_editor->hide();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,123 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* animation_editor_plugin.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 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 ANIMATION_EDITOR_PLUGIN_H
|
||||
#define ANIMATION_EDITOR_PLUGIN_H
|
||||
|
||||
#include "scene/resources/animation.h"
|
||||
#include "scene/gui/texture_frame.h"
|
||||
#include "scene/gui/option_button.h"
|
||||
#include "tools/editor/editor_node.h"
|
||||
#include "tools/editor/property_editor.h"
|
||||
#include "undo_redo.h"
|
||||
class AnimationEditor_TrackEditor;
|
||||
|
||||
class AnimationEditor : public Control {
|
||||
|
||||
OBJ_TYPE( AnimationEditor, Control );
|
||||
|
||||
Panel *panel;
|
||||
Ref<Animation> animation;
|
||||
|
||||
Button *add_track;
|
||||
Button *remove_track;
|
||||
Button *move_up_track;
|
||||
Button *move_down_track;
|
||||
|
||||
Button *add_key;
|
||||
Button *remove_key;
|
||||
|
||||
LineEdit *key_time;
|
||||
OptionButton *track_type;
|
||||
OptionButton *key_type;
|
||||
TextureFrame *time_icon;
|
||||
|
||||
Tree *tracks;
|
||||
PropertyEditor *key_editor;
|
||||
AnimationEditor_TrackEditor *track_editor;
|
||||
int selected_track;
|
||||
|
||||
void _track_selected();
|
||||
void _track_added();
|
||||
void _track_removed();
|
||||
void _track_moved_up();
|
||||
void _track_moved_down();
|
||||
void _track_path_changed();
|
||||
|
||||
void _key_added();
|
||||
void _key_removed();
|
||||
|
||||
|
||||
void _update_track_keys();
|
||||
void update_anim();
|
||||
|
||||
UndoRedo *undo_redo;
|
||||
|
||||
void _internal_set_selected_track(int p_which,const Ref<Animation>& p_anim);
|
||||
void _internal_check_update(Ref<Animation> p_anim);
|
||||
|
||||
friend class AnimationEditor_TrackEditor;
|
||||
void _internal_set_key(int p_track, float p_time, float p_transition,const Variant& p_value);
|
||||
void _internal_set_interpolation_type(int p_track,Animation::InterpolationType p_type);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
|
||||
void edit(const Ref<Animation>& p_animation);
|
||||
|
||||
AnimationEditor();
|
||||
~AnimationEditor();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class AnimationEditorPlugin : public EditorPlugin {
|
||||
|
||||
OBJ_TYPE( AnimationEditorPlugin, EditorPlugin );
|
||||
|
||||
AnimationEditor *animation_editor;
|
||||
EditorNode *editor;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
virtual String get_name() const { return "Animation"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_node);
|
||||
virtual bool handles(Object *p_node) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
AnimationEditorPlugin(EditorNode *p_node);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,905 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* font_editor_plugin.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 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 "font_editor_plugin.h"
|
||||
#include "os/file_access.h"
|
||||
#ifdef FREETYPE_ENABLED
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#endif
|
||||
|
||||
#include "core/io/resource_saver.h"
|
||||
|
||||
void FontEditor::edit(const Ref<Font>& p_font) {
|
||||
|
||||
font=p_font;
|
||||
label->add_font_override("font",font);
|
||||
}
|
||||
|
||||
void FontEditor::_preview_text_changed(const String& p_text) {
|
||||
|
||||
label->set_text(p_text);
|
||||
}
|
||||
struct FontData {
|
||||
|
||||
Vector<uint8_t> bitmap;
|
||||
int width,height;
|
||||
int ofs_x; //ofset to center, from ABOVE
|
||||
int ofs_y; //ofset to begining, from LEFT
|
||||
int valign; //vertical alignment
|
||||
int halign;
|
||||
int advance;
|
||||
int character;
|
||||
int glyph;
|
||||
|
||||
int texture;
|
||||
// bool printable;
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct FontDataSort {
|
||||
|
||||
bool operator()(const FontData *p_A,const FontData *p_B) const {
|
||||
return p_A->height > p_B->height;
|
||||
};
|
||||
};
|
||||
|
||||
struct KerningKey {
|
||||
|
||||
CharType A,B;
|
||||
bool operator<(const KerningKey& p_k) const { return (A==p_k.A)?(B<p_k.B):(A<p_k.A); }
|
||||
|
||||
};
|
||||
|
||||
void FontEditor::_export_fnt(const String& p_name, Ref<Font> p_font) {
|
||||
|
||||
String fnt_name = p_name + ".fnt";
|
||||
FileAccess* f = FileAccess::open(fnt_name, FileAccess::WRITE);
|
||||
ERR_FAIL_COND(!f);
|
||||
|
||||
f->store_string(String("info face=\"") + p_font->get_name() + "\" size=" + String::num_real(font->get_height()) + " bold=0 italic=0 charset=\"\" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=4,4\n");
|
||||
|
||||
Vector2 size = p_font->get_texture(0)->get_size();
|
||||
f->store_string(String("common lineHeight=") + String::num(font->get_height()) + " base=" + String::num(font->get_ascent()) + " scaleW=" + String::num(size.x) + " scaleH=" + String::num(size.y) + " pages="+String::num(p_font->get_texture_count()) + " packed=0\n");
|
||||
|
||||
for (int i=0; i<p_font->get_texture_count(); i++) {
|
||||
|
||||
f->store_string(String("page id=")+String::num(i)+ " file=\""+ p_name.get_file() + "_" +String::num(i)+".png\"\n");
|
||||
};
|
||||
|
||||
f->store_string(String("chars count=")+String::num(p_font->get_character_count()) + "\n");
|
||||
|
||||
Vector<CharType> keys = p_font->get_char_keys();
|
||||
keys.sort();
|
||||
for (int i=0; i<keys.size(); i++) {
|
||||
|
||||
Font::Character c = p_font->get_character(keys[i]);
|
||||
int width = c.rect.size.x;
|
||||
if (keys[i] == 32) {
|
||||
width = c.advance;
|
||||
};
|
||||
f->store_string(String("char id=") + String::num(keys[i]) + " x=" + String::num(c.rect.pos.x) + " y=" + String::num(c.rect.pos.y) +
|
||||
" width=" + String::num(width) + " height=" + String::num(c.rect.size.y) +
|
||||
" xoffset=" + String::num(c.h_align) + " yoffset=" + String::num(c.v_align) +
|
||||
" xadvance=" + String::num(c.advance) + " page=" + String::num(c.texture_idx) +
|
||||
" chnl=0 letter=\"\"\n");
|
||||
};
|
||||
|
||||
f->close();
|
||||
|
||||
for (int i=0; i<p_font->get_texture_count(); i++) {
|
||||
|
||||
ResourceSaver::save(p_name + "_" + String::num(i) + ".png", p_font->get_texture(i));
|
||||
};
|
||||
};
|
||||
|
||||
void FontEditor::_import_fnt(const String& p_string) {
|
||||
//fnt format used by angelcode bmfont
|
||||
//http://www.angelcode.com/products/bmfont/
|
||||
|
||||
FileAccess *f = FileAccess::open(p_string,FileAccess::READ);
|
||||
|
||||
if (!f) {
|
||||
|
||||
ERR_EXPLAIN("Can't open font: "+p_string);
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
|
||||
font->clear();
|
||||
|
||||
while(true) {
|
||||
|
||||
String line=f->get_line();
|
||||
|
||||
int delimiter=line.find(" ");
|
||||
String type=line.substr(0,delimiter);
|
||||
int pos = delimiter+1;
|
||||
Map<String,String> keys;
|
||||
|
||||
while (pos < line.size() && line[pos]==' ')
|
||||
pos++;
|
||||
|
||||
|
||||
while(pos<line.size()) {
|
||||
|
||||
int eq = line.find("=",pos);
|
||||
if (eq==-1)
|
||||
break;
|
||||
String key=line.substr(pos,eq-pos);
|
||||
int end=-1;
|
||||
String value;
|
||||
if (line[eq+1]=='"') {
|
||||
end=line.find("\"",eq+2);
|
||||
if (end==-1)
|
||||
break;
|
||||
value=line.substr(eq+2,end-1-eq-1);
|
||||
pos=end+1;
|
||||
} else {
|
||||
end=line.find(" ",eq+1);
|
||||
if (end==-1)
|
||||
end=line.size();
|
||||
|
||||
value=line.substr(eq+1,end-eq);
|
||||
|
||||
pos=end;
|
||||
|
||||
}
|
||||
|
||||
while (pos<line.size() && line[pos]==' ')
|
||||
pos++;
|
||||
|
||||
|
||||
keys[key]=value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (type=="info") {
|
||||
|
||||
if (keys.has("face"))
|
||||
font->set_name(keys["face"]);
|
||||
//if (keys.has("size"))
|
||||
// font->set_height(keys["size"].to_int());
|
||||
|
||||
} else if (type=="common") {
|
||||
|
||||
if (keys.has("lineHeight"))
|
||||
font->set_height(keys["lineHeight"].to_int());
|
||||
if (keys.has("base"))
|
||||
font->set_ascent(keys["base"].to_int());
|
||||
|
||||
} else if (type=="page") {
|
||||
|
||||
if (keys.has("file")) {
|
||||
|
||||
String file = keys["file"];
|
||||
file=p_string.get_base_dir()+"/"+file;
|
||||
Ref<Texture> tex = ResourceLoader::load(file);
|
||||
if (tex.is_null()) {
|
||||
ERR_PRINT("Can't load font texture!");
|
||||
} else {
|
||||
font->add_texture(tex);
|
||||
}
|
||||
}
|
||||
} else if (type=="char") {
|
||||
|
||||
CharType idx=0;
|
||||
if (keys.has("id"))
|
||||
idx=keys["id"].to_int();
|
||||
|
||||
Rect2 rect;
|
||||
|
||||
if (keys.has("x"))
|
||||
rect.pos.x=keys["x"].to_int();
|
||||
if (keys.has("y"))
|
||||
rect.pos.y=keys["y"].to_int();
|
||||
if (keys.has("width"))
|
||||
rect.size.width=keys["width"].to_int();
|
||||
if (keys.has("height"))
|
||||
rect.size.height=keys["height"].to_int();
|
||||
|
||||
Point2 ofs;
|
||||
|
||||
if (keys.has("xoffset"))
|
||||
ofs.x=keys["xoffset"].to_int();
|
||||
if (keys.has("yoffset"))
|
||||
ofs.y=keys["yoffset"].to_int();
|
||||
|
||||
int texture=0;
|
||||
if (keys.has("page"))
|
||||
texture=keys["page"].to_int();
|
||||
int advance=-1;
|
||||
if (keys.has("xadvance"))
|
||||
advance=keys["xadvance"].to_int();
|
||||
|
||||
font->add_char(idx,texture,rect,ofs,advance);
|
||||
|
||||
} else if (type=="kerning") {
|
||||
|
||||
CharType first=0,second=0;
|
||||
int k=0;
|
||||
|
||||
if (keys.has("first"))
|
||||
first=keys["first"].to_int();
|
||||
if (keys.has("second"))
|
||||
second=keys["second"].to_int();
|
||||
if (keys.has("amount"))
|
||||
k=keys["amount"].to_int();
|
||||
|
||||
font->add_kerning_pair(first,second,-k);
|
||||
|
||||
}
|
||||
|
||||
if (f->eof_reached())
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
memdelete(f);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void FontEditor::_import_ttf(const String& p_string) {
|
||||
|
||||
#ifdef FREETYPE_ENABLED
|
||||
FT_Library library; /* handle to library */
|
||||
FT_Face face; /* handle to face object */
|
||||
|
||||
Vector<FontData*> font_data_list;
|
||||
|
||||
int error = FT_Init_FreeType( &library );
|
||||
|
||||
ERR_EXPLAIN("Error initializing FreeType.");
|
||||
ERR_FAIL_COND( error !=0 );
|
||||
|
||||
|
||||
error = FT_New_Face( library, p_string.utf8().get_data(),0,&face );
|
||||
|
||||
if ( error == FT_Err_Unknown_File_Format ) {
|
||||
ERR_EXPLAIN("Unknown font format.");
|
||||
FT_Done_FreeType( library );
|
||||
} else if ( error ) {
|
||||
|
||||
ERR_EXPLAIN("Error loading font.");
|
||||
FT_Done_FreeType( library );
|
||||
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(error);
|
||||
|
||||
|
||||
int height=0;
|
||||
int ascent=0;
|
||||
int font_spacing=0;
|
||||
|
||||
int size=font_size->get_text().to_int();
|
||||
|
||||
error = FT_Set_Char_Size(face,0,64*size,512,512);
|
||||
|
||||
if ( error ) {
|
||||
FT_Done_FreeType( library );
|
||||
ERR_EXPLAIN("Invalid font size. ");
|
||||
ERR_FAIL_COND( error );
|
||||
|
||||
}
|
||||
|
||||
error = FT_Set_Pixel_Sizes(face,0,size);
|
||||
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
|
||||
// error = FT_Set_Charmap(face,ft_encoding_unicode ); /* encoding.. */
|
||||
|
||||
|
||||
/* PRINT CHARACTERS TO INDIVIDUAL BITMAPS */
|
||||
|
||||
|
||||
// int space_size=5; //size for space, if none found.. 5!
|
||||
// int min_valign=500; //some ridiculous number
|
||||
|
||||
FT_ULong charcode;
|
||||
FT_UInt gindex;
|
||||
|
||||
int max_up=-1324345; ///gibberish
|
||||
int max_down=124232;
|
||||
|
||||
Map<KerningKey,int> kerning_map;
|
||||
|
||||
charcode = FT_Get_First_Char( face, &gindex );
|
||||
|
||||
int xsize=0;
|
||||
while ( gindex != 0 )
|
||||
{
|
||||
|
||||
bool skip=false;
|
||||
error = FT_Load_Char( face, charcode, FT_LOAD_RENDER );
|
||||
if (error) skip=true;
|
||||
else error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
|
||||
if (error) skip=true;
|
||||
|
||||
|
||||
if (!skip && (import_chars.has(charcode) && import_chars[charcode] != 0)) {
|
||||
|
||||
skip = false;
|
||||
|
||||
} else {
|
||||
if (import_option->get_selected() == 0 && charcode>127)
|
||||
skip=true;
|
||||
if (import_option->get_selected() == 1 && charcode>0xFE)
|
||||
skip=true;
|
||||
};
|
||||
|
||||
if (charcode<=32) //
|
||||
skip=true;
|
||||
|
||||
if (skip) {
|
||||
charcode=FT_Get_Next_Char(face,charcode,&gindex);
|
||||
continue;
|
||||
}
|
||||
|
||||
FontData * fdata = memnew( FontData );
|
||||
fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows );
|
||||
fdata->width=slot->bitmap.width;
|
||||
fdata->height=slot->bitmap.rows;
|
||||
fdata->character=charcode;
|
||||
fdata->glyph=FT_Get_Char_Index(face,charcode);
|
||||
if (charcode=='x')
|
||||
xsize=slot->bitmap.width;
|
||||
|
||||
|
||||
if (charcode<127) {
|
||||
if (slot->bitmap_top>max_up) {
|
||||
|
||||
max_up=slot->bitmap_top;
|
||||
}
|
||||
|
||||
|
||||
if ( (slot->bitmap_top - fdata->height)<max_down ) {
|
||||
|
||||
max_down=slot->bitmap_top - fdata->height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fdata->valign=slot->bitmap_top;
|
||||
fdata->halign=slot->bitmap_left;
|
||||
fdata->advance=(slot->advance.x+(1<<5))>>6;
|
||||
fdata->advance+=font_spacing;
|
||||
|
||||
for (int i=0;i<slot->bitmap.width;i++) {
|
||||
for (int j=0;j<slot->bitmap.rows;j++) {
|
||||
|
||||
fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
|
||||
}
|
||||
}
|
||||
|
||||
font_data_list.push_back(fdata);
|
||||
charcode=FT_Get_Next_Char(face,charcode,&gindex);
|
||||
// printf("reading char %i\n",charcode);
|
||||
}
|
||||
|
||||
/* SPACE */
|
||||
|
||||
FontData *spd = memnew( FontData );
|
||||
spd->advance=0;
|
||||
spd->character=' ';
|
||||
spd->halign=0;
|
||||
spd->valign=0;
|
||||
spd->width=0;
|
||||
spd->height=0;
|
||||
spd->ofs_x=0;
|
||||
spd->ofs_y=0;
|
||||
|
||||
if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, ft_render_mode_normal )) {
|
||||
|
||||
spd->advance = slot->advance.x>>6;
|
||||
spd->advance+=font_spacing;
|
||||
} else {
|
||||
|
||||
spd->advance=xsize;
|
||||
spd->advance+=font_spacing;
|
||||
}
|
||||
|
||||
font_data_list.push_back(spd);
|
||||
|
||||
Map<CharType, bool> exported;
|
||||
for (int i=0; i<font_data_list.size(); i++) {
|
||||
exported[font_data_list[i]->character] = true;
|
||||
};
|
||||
int missing = 0;
|
||||
for(Map<CharType,int>::Element *E=import_chars.front();E;E=E->next()) {
|
||||
CharType c = E->key();
|
||||
if (!exported.has(c)) {
|
||||
CharType str[2] = {c, 0};
|
||||
printf("** Warning: character %i (%ls) not exported\n", (int)c, str);
|
||||
++missing;
|
||||
};
|
||||
};
|
||||
printf("total %i/%i\n", missing, import_chars.size());
|
||||
|
||||
/* KERNING */
|
||||
|
||||
|
||||
for(int i=0;i<font_data_list.size();i++) {
|
||||
|
||||
for(int j=0;j<font_data_list.size();j++) {
|
||||
|
||||
FT_Vector delta;
|
||||
FT_Get_Kerning( face, font_data_list[i]->glyph,font_data_list[j]->glyph, FT_KERNING_DEFAULT, &delta );
|
||||
|
||||
if (delta.x!=0) {
|
||||
|
||||
KerningKey kpk;
|
||||
kpk.A = font_data_list[i]->character;
|
||||
kpk.B = font_data_list[j]->character;
|
||||
int kern = ((-delta.x)+(1<<5))>>6;
|
||||
|
||||
if (kern==0)
|
||||
continue;
|
||||
kerning_map[kpk]=kern;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
height=max_up-max_down;
|
||||
ascent=max_up;
|
||||
|
||||
/* FIND OUT WHAT THE FONT HEIGHT FOR THIS IS */
|
||||
|
||||
/* ADJUST THE VALIGN FOR EACH CHARACTER */
|
||||
|
||||
for (int i=0;i<(int)font_data_list.size();i++) {
|
||||
|
||||
font_data_list[i]->valign=max_up-font_data_list[i]->valign;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ADD THE SPACEBAR CHARACTER */
|
||||
/*
|
||||
FontData * fdata = new FontData;
|
||||
|
||||
fdata->character=32;
|
||||
fdata->bitmap=0;
|
||||
fdata->width=xsize;
|
||||
fdata->height=1;
|
||||
fdata->valign=0;
|
||||
|
||||
font_data_list.push_back(fdata);
|
||||
*/
|
||||
/* SORT BY HEIGHT, SO THEY FIT BETTER ON THE TEXTURE */
|
||||
|
||||
font_data_list.sort_custom<FontDataSort>();
|
||||
|
||||
int spacing=2;
|
||||
|
||||
|
||||
int use_width=256;
|
||||
int use_max_height=256;
|
||||
// int surf_idx=-1;
|
||||
|
||||
List<Size2> tex_sizes;
|
||||
// int current_texture=0;
|
||||
|
||||
Size2 first(use_width,nearest_power_of_2( font_data_list[0]->height + spacing ));
|
||||
Size2 *curtex=&tex_sizes.push_back(first)->get();
|
||||
|
||||
Point2 tex_ofs;
|
||||
|
||||
/* FIT (NOT COPY YEY) FACES IN TEXTURES */
|
||||
|
||||
int current_height=font_data_list[0]->height + spacing;
|
||||
|
||||
int font_margin=2;
|
||||
|
||||
|
||||
for(int i=0;i<font_data_list.size();i++) {
|
||||
|
||||
FontData *fd=font_data_list[i];
|
||||
|
||||
if (tex_ofs.x+fd->width >= use_width) {
|
||||
//end of column, advance a row
|
||||
tex_ofs.x=0;
|
||||
tex_ofs.y+=current_height+font_margin;
|
||||
current_height=fd->height + spacing;
|
||||
|
||||
int new_tex_h = curtex->height;
|
||||
|
||||
while( tex_ofs.y+current_height > new_tex_h ) {
|
||||
|
||||
if (curtex->height * 2 > use_max_height) {
|
||||
//oops, can't use this texture anymore..
|
||||
Size2 newtex( use_width, nearest_power_of_2( fd->height + spacing ));
|
||||
new_tex_h=newtex.height;
|
||||
curtex=&tex_sizes.push_back(newtex)->get();
|
||||
tex_ofs=Point2(0,0);
|
||||
|
||||
} else {
|
||||
|
||||
new_tex_h*=2;
|
||||
}
|
||||
}
|
||||
|
||||
curtex->height=new_tex_h;
|
||||
|
||||
}
|
||||
|
||||
fd->ofs_x=tex_ofs.x;
|
||||
fd->ofs_y=tex_ofs.y;
|
||||
fd->texture=tex_sizes.size()-1;
|
||||
|
||||
tex_ofs.x+=fd->width+font_margin;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* WRITE FACES IN TEXTURES */
|
||||
|
||||
// create textures
|
||||
|
||||
Vector<DVector<uint8_t> >image_data;
|
||||
Vector<int> image_widths;
|
||||
Vector<DVector<uint8_t>::Write> image_ptrs;
|
||||
image_ptrs.resize(tex_sizes.size());
|
||||
|
||||
for(int i=0;i<tex_sizes.size();i++) {
|
||||
|
||||
DVector<uint8_t> pixels;
|
||||
int texsize=tex_sizes[i].width * tex_sizes[i].height * 2;
|
||||
pixels.resize(texsize );
|
||||
|
||||
image_data.push_back(pixels);
|
||||
image_widths.push_back( tex_sizes[i].width );
|
||||
image_ptrs[i] = image_data[i].write();
|
||||
for(int j=0;j<texsize;j++) {
|
||||
|
||||
image_ptrs[i][j]=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//blit textures with fonts
|
||||
for(int i=0;i<font_data_list.size();i++) {
|
||||
|
||||
FontData *fd=font_data_list[i];
|
||||
|
||||
uint8_t *pixels = image_ptrs[fd->texture].ptr();
|
||||
int width = image_widths[fd->texture];
|
||||
|
||||
for(int y=0;y<fd->height;y++) {
|
||||
|
||||
const uint8_t *src = &fd->bitmap[y*fd->width];
|
||||
uint8_t *dst = &pixels[((fd->ofs_y+y)*width+fd->ofs_x)*2];
|
||||
|
||||
|
||||
for(int x=0;x<fd->width;x++) {
|
||||
|
||||
dst[x<<1]=255; //white always
|
||||
dst[(x<<1) +1]=src[x];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//unlock writing
|
||||
for(int i=0;i<image_ptrs.size();i++)
|
||||
image_ptrs[i]=DVector<uint8_t>::Write();
|
||||
|
||||
/* CREATE FONT */
|
||||
|
||||
font->clear();
|
||||
font->set_height(height);
|
||||
font->set_ascent(ascent);
|
||||
|
||||
//register texures
|
||||
for(int i=0;i<tex_sizes.size();i++) {
|
||||
Image img(tex_sizes[i].width,tex_sizes[i].height,0,Image::FORMAT_GRAYSCALE_ALPHA,image_data[i]);
|
||||
Ref<ImageTexture> tex = memnew( ImageTexture );
|
||||
tex->create_from_image(img,0); //no filter, no repeat
|
||||
font->add_texture(tex);
|
||||
//tframe->set_texture(tex);
|
||||
|
||||
}
|
||||
|
||||
//register characters
|
||||
|
||||
for(int i=0;i<font_data_list.size();i++) {
|
||||
FontData *fd=font_data_list[i];
|
||||
|
||||
font->add_char(fd->character,fd->texture,Rect2( fd->ofs_x, fd->ofs_y, fd->width, fd->height),Point2(fd->halign,fd->valign), fd->advance);
|
||||
memdelete(fd);
|
||||
}
|
||||
|
||||
for(Map<KerningKey,int>::Element *E=kerning_map.front();E;E=E->next()) {
|
||||
|
||||
font->add_kerning_pair(E->key().A,E->key().B,E->get());
|
||||
}
|
||||
|
||||
FT_Done_FreeType( library );
|
||||
#endif
|
||||
}
|
||||
|
||||
void FontEditor::_add_source() {
|
||||
|
||||
_source_file->popup_centered_ratio();
|
||||
};
|
||||
|
||||
void FontEditor::_add_source_accept(const String& p_file) {
|
||||
|
||||
FileAccess* f = FileAccess::open(p_file, FileAccess::READ);
|
||||
ERR_FAIL_COND(!f);
|
||||
|
||||
String line;
|
||||
while ( !f->eof_reached() ) {
|
||||
|
||||
line = f->get_line();
|
||||
for (int i=0; i<line.length(); i++) {
|
||||
|
||||
if (import_chars.has(line[i])) {
|
||||
import_chars[line[i]] = import_chars[line[i]] + 1;
|
||||
} else {
|
||||
import_chars[line[i]] = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void FontEditor::_export_fnt_pressed() {
|
||||
|
||||
_export_file->popup_centered_ratio();
|
||||
};
|
||||
|
||||
void FontEditor::_export_fnt_accept(const String& p_file) {
|
||||
|
||||
String name = p_file.replace(".fnt", "");
|
||||
_export_fnt(name, font);
|
||||
};
|
||||
|
||||
void FontEditor::_import_accept(const String& p_string) {
|
||||
|
||||
#ifdef FREETYPE_ENABLED
|
||||
|
||||
if (p_string.extension().nocasecmp_to("ttf")==0 || p_string.extension().nocasecmp_to("otf")==0) {
|
||||
|
||||
_import_ttf(p_string);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_string.extension().nocasecmp_to("fnt")==0) {
|
||||
|
||||
_import_fnt(p_string);
|
||||
}
|
||||
|
||||
label->add_font_override("font",font);
|
||||
label->notification(Control::NOTIFICATION_THEME_CHANGED);
|
||||
label->update();
|
||||
}
|
||||
|
||||
void FontEditor::_import() {
|
||||
|
||||
|
||||
file->popup_centered_ratio();
|
||||
}
|
||||
|
||||
void FontEditor::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method("_import",&FontEditor::_import);
|
||||
ObjectTypeDB::bind_method("_import_accept",&FontEditor::_import_accept);
|
||||
ObjectTypeDB::bind_method("_preview_text_changed",&FontEditor::_preview_text_changed);
|
||||
ObjectTypeDB::bind_method("_add_source",&FontEditor::_add_source);
|
||||
ObjectTypeDB::bind_method("_add_source_accept",&FontEditor::_add_source_accept);
|
||||
ObjectTypeDB::bind_method("_export_fnt_pressed",&FontEditor::_export_fnt_pressed);
|
||||
ObjectTypeDB::bind_method("_export_fnt_accept",&FontEditor::_export_fnt_accept);
|
||||
}
|
||||
|
||||
FontEditor::FontEditor() {
|
||||
|
||||
panel = memnew( Panel );
|
||||
add_child(panel);
|
||||
panel->set_area_as_parent_rect();
|
||||
|
||||
/*
|
||||
tframe = memnew( TextureFrame );
|
||||
|
||||
tframe->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
||||
tframe->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
|
||||
|
||||
tframe->set_begin( Point2(5, 40 ) );
|
||||
tframe->set_end( Point2(5,55 ) );
|
||||
|
||||
panel->add_child(tframe);
|
||||
*/
|
||||
|
||||
Label *l = memnew( Label );
|
||||
l->set_pos( Point2(5,13 ) );
|
||||
l->set_text("Import: ");
|
||||
|
||||
panel->add_child(l);
|
||||
|
||||
l = memnew( Label );
|
||||
l->set_pos( Point2(25,37 ) );
|
||||
l->set_text("Size: ");
|
||||
|
||||
panel->add_child(l);
|
||||
|
||||
font_size = memnew( LineEdit );
|
||||
font_size->set_text("12");
|
||||
font_size->set_pos( Point2(70,35 ) );
|
||||
font_size->set_size( Size2(40,10 ) );
|
||||
panel->add_child(font_size);
|
||||
|
||||
l = memnew( Label );
|
||||
l->set_pos( Point2(140,37 ) );
|
||||
l->set_text("Encoding: ");
|
||||
|
||||
panel->add_child(l);
|
||||
|
||||
import_option = memnew( OptionButton );
|
||||
import_option->add_item("Ascii");
|
||||
import_option->add_item("Latin");
|
||||
import_option->add_item("Full Unicode");
|
||||
import_option->select(1);
|
||||
|
||||
import_option->set_pos( Point2( 215,35 ) );
|
||||
import_option->set_size( Point2( 100,12 ) );
|
||||
|
||||
panel->add_child(import_option);
|
||||
|
||||
Button* import = memnew( Button );
|
||||
import->set_text("Import:..");
|
||||
import->set_begin( Point2(80,35) );
|
||||
import->set_end( Point2(10,45) );
|
||||
|
||||
import->set_anchor( MARGIN_LEFT, ANCHOR_END );
|
||||
import->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
||||
|
||||
panel->add_child(import);
|
||||
|
||||
Button* add_source = memnew( Button );
|
||||
add_source->set_text("Add Source...");
|
||||
add_source->set_begin( Point2(180,35) );
|
||||
add_source->set_end( Point2(90,45) );
|
||||
add_source->set_anchor( MARGIN_LEFT, ANCHOR_END );
|
||||
add_source->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
||||
|
||||
panel->add_child(add_source);
|
||||
|
||||
file = memnew( FileDialog );
|
||||
file->set_access(FileDialog::ACCESS_FILESYSTEM);
|
||||
|
||||
_source_file = memnew( FileDialog );
|
||||
_source_file->set_access(FileDialog::ACCESS_FILESYSTEM);
|
||||
_source_file->set_mode(FileDialog::MODE_OPEN_FILE);
|
||||
_source_file->connect("file_selected", this, "_add_source_accept");
|
||||
panel->add_child( _source_file );
|
||||
|
||||
Button* export_fnt = memnew(Button);
|
||||
export_fnt->set_text("Export fnt");
|
||||
export_fnt->set_begin(Point2(80, 65));
|
||||
export_fnt->set_end(Point2(10, 75));
|
||||
export_fnt->set_anchor( MARGIN_LEFT, ANCHOR_END );
|
||||
export_fnt->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
||||
export_fnt->connect("pressed", this, "_export_fnt_pressed");
|
||||
panel->add_child( export_fnt );
|
||||
|
||||
_export_file = memnew(FileDialog);
|
||||
_export_file->set_access(FileDialog::ACCESS_FILESYSTEM);
|
||||
_export_file->set_mode(FileDialog::MODE_SAVE_FILE);
|
||||
_export_file->connect("file_selected", this, "_export_fnt_accept");
|
||||
panel->add_child(_export_file);
|
||||
|
||||
l = memnew( Label );
|
||||
l->set_pos( Point2(5,65 ) );
|
||||
l->set_text("Preview Text: ");
|
||||
|
||||
panel->add_child(l);
|
||||
|
||||
preview_text = memnew( LineEdit );
|
||||
preview_text->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
||||
preview_text->set_begin( Point2(25,85 ) );
|
||||
preview_text->set_end( Point2(10,95 ) );
|
||||
panel->add_child(preview_text);
|
||||
preview_text->connect("text_changed", this,"_preview_text_changed");
|
||||
preview_text->set_text("The quick brown fox jumped over the lazy dog.");
|
||||
|
||||
l = memnew( Label );
|
||||
l->set_pos( Point2(5,115 ) );
|
||||
l->set_text("Preview: ");
|
||||
|
||||
panel->add_child(l);
|
||||
|
||||
label = memnew( Label );
|
||||
label->set_autowrap(true);
|
||||
|
||||
label->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
||||
label->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
|
||||
|
||||
label->set_begin( Point2(5, 135 ) );
|
||||
label->set_end( Point2(5,5 ) );
|
||||
|
||||
label->set_text("The quick brown fox jumped over the lazy dog.");
|
||||
label->set_align( Label::ALIGN_CENTER );
|
||||
|
||||
panel->add_child(label);
|
||||
|
||||
#ifdef FREETYPE_ENABLED
|
||||
|
||||
file->add_filter("*.ttf");
|
||||
file->add_filter("*.otf");
|
||||
#endif
|
||||
file->add_filter("*.fnt ; AngelCode BMFont");
|
||||
|
||||
file->set_mode(FileDialog::MODE_OPEN_FILE);
|
||||
panel->add_child( file );
|
||||
|
||||
import->connect("pressed", this,"_import");
|
||||
file->connect("file_selected", this,"_import_accept");
|
||||
add_source->connect("pressed", this, "_add_source");
|
||||
}
|
||||
|
||||
void FontEditorPlugin::edit(Object *p_node) {
|
||||
|
||||
if (p_node && p_node->cast_to<Font>()) {
|
||||
font_editor->edit( p_node->cast_to<Font>() );
|
||||
font_editor->show();
|
||||
} else
|
||||
font_editor->hide();
|
||||
}
|
||||
|
||||
bool FontEditorPlugin::handles(Object *p_node) const{
|
||||
|
||||
return p_node->is_type("Font");
|
||||
}
|
||||
|
||||
void FontEditorPlugin::make_visible(bool p_visible){
|
||||
|
||||
if (p_visible)
|
||||
font_editor->show();
|
||||
else
|
||||
font_editor->hide();
|
||||
}
|
||||
|
||||
FontEditorPlugin::FontEditorPlugin(EditorNode *p_node) {
|
||||
|
||||
font_editor = memnew( FontEditor );
|
||||
|
||||
p_node->get_viewport()->add_child(font_editor);
|
||||
font_editor->set_area_as_parent_rect();
|
||||
font_editor->hide();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,100 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* font_editor_plugin.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2014 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 FONT_EDITOR_PLUGIN_H
|
||||
#define FONT_EDITOR_PLUGIN_H
|
||||
|
||||
#include "scene/resources/font.h"
|
||||
#include "scene/gui/texture_frame.h"
|
||||
#include "scene/gui/option_button.h"
|
||||
#include "tools/editor/editor_node.h"
|
||||
|
||||
|
||||
class FontEditor : public Control {
|
||||
|
||||
OBJ_TYPE( FontEditor, Control );
|
||||
|
||||
Panel *panel;
|
||||
LineEdit *font_size;
|
||||
//TextureFrame *tframe; //for debug
|
||||
Label *label;
|
||||
LineEdit *preview_text;
|
||||
FileDialog *file;
|
||||
FileDialog* _source_file;
|
||||
FileDialog* _export_file;
|
||||
OptionButton *import_option;
|
||||
|
||||
Ref<Font> font;
|
||||
|
||||
Map<CharType, int> import_chars;
|
||||
|
||||
void _export_fnt(const String& p_name, Ref<Font> p_font);
|
||||
void _export_fnt_pressed();
|
||||
void _export_fnt_accept(const String& p_file);
|
||||
|
||||
void _import_ttf(const String& p_string);
|
||||
void _import_fnt(const String& p_string);
|
||||
void _preview_text_changed(const String& p_text);
|
||||
|
||||
void _add_source();
|
||||
void _add_source_accept(const String& p_file);
|
||||
|
||||
void _import_accept(const String&);
|
||||
void _import();
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void edit(const Ref<Font>& p_font);
|
||||
|
||||
FontEditor();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class FontEditorPlugin : public EditorPlugin {
|
||||
|
||||
OBJ_TYPE( FontEditorPlugin, EditorPlugin );
|
||||
|
||||
FontEditor *font_editor;
|
||||
EditorNode *editor;
|
||||
|
||||
public:
|
||||
|
||||
virtual String get_name() const { return "Font"; }
|
||||
bool has_main_screen() const { return false; }
|
||||
virtual void edit(Object *p_node);
|
||||
virtual bool handles(Object *p_node) const;
|
||||
virtual void make_visible(bool p_visible);
|
||||
|
||||
FontEditorPlugin(EditorNode *p_node);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // FONT_EDITOR_PLUGIN_H
|
Loading…
Reference in New Issue
Block a user