diff --git a/.gitignore b/.gitignore index a5b45a1ae1b..fbb3ba6cb42 100644 --- a/.gitignore +++ b/.gitignore @@ -280,4 +280,4 @@ cscope.files cscope.out cscope.in.out cscope.po.out -godot.creator.user.wd3476 +godot.creator.* diff --git a/LOGO_LICENSE.md b/LOGO_LICENSE.md new file mode 100644 index 00000000000..2858712f186 --- /dev/null +++ b/LOGO_LICENSE.md @@ -0,0 +1,2 @@ +Godot Logo (c) Andrea CalabrĂ³, distributed under the terms of the CC By License: +https://creativecommons.org/licenses/by/3.0/legalcode \ No newline at end of file diff --git a/bin/tests/test_gui.cpp b/bin/tests/test_gui.cpp index 8822febdeb1..c404623872e 100644 --- a/bin/tests/test_gui.cpp +++ b/bin/tests/test_gui.cpp @@ -109,6 +109,9 @@ public: frame->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END ); frame->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END ); frame->set_end( Point2(0,0) ); + + Ref t = memnew( Theme ); + frame->set_theme(t); get_root()->add_child( frame ); diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 128bc94989c..26b1dac6f11 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -457,9 +457,9 @@ void _OS::set_icon(const Image& p_icon) { OS::get_singleton()->set_icon(p_icon); } -Dictionary _OS::get_date() const { +Dictionary _OS::get_date(bool utc) const { - OS::Date date = OS::get_singleton()->get_date(); + OS::Date date = OS::get_singleton()->get_date(utc); Dictionary dated; dated["year"]=date.year; dated["month"]=date.month; @@ -470,9 +470,9 @@ Dictionary _OS::get_date() const { } -Dictionary _OS::get_time() const { +Dictionary _OS::get_time(bool utc) const { - OS::Time time = OS::get_singleton()->get_time(); + OS::Time time = OS::get_singleton()->get_time(utc); Dictionary timed; timed["hour"]=time.hour; timed["minute"]=time.min; @@ -480,6 +480,15 @@ Dictionary _OS::get_time() const { return timed; } + +Dictionary _OS::get_time_zone_info() const { + OS::TimeZoneInfo info = OS::get_singleton()->get_time_zone_info(); + Dictionary infod; + infod["bias"] = info.bias; + infod["name"] = info.name; + return infod; +} + uint64_t _OS::get_unix_time() const { return OS::get_singleton()->get_unix_time(); @@ -774,8 +783,9 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_cmdline_args"),&_OS::get_cmdline_args); ObjectTypeDB::bind_method(_MD("get_main_loop"),&_OS::get_main_loop); - ObjectTypeDB::bind_method(_MD("get_date"),&_OS::get_date); - ObjectTypeDB::bind_method(_MD("get_time"),&_OS::get_time); + ObjectTypeDB::bind_method(_MD("get_date","utc"),&_OS::get_date,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("get_time","utc"),&_OS::get_time,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("get_time_zone_info"),&_OS::get_time_zone_info); ObjectTypeDB::bind_method(_MD("get_unix_time"),&_OS::get_unix_time); ObjectTypeDB::bind_method(_MD("set_icon"),&_OS::set_icon); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 05f54dd64c3..74f29c23e86 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -204,8 +204,9 @@ public: void set_use_file_access_save_and_swap(bool p_enable); void set_icon(const Image& p_icon); - Dictionary get_date() const; - Dictionary get_time() const; + Dictionary get_date(bool utc) const; + Dictionary get_time(bool utc) const; + Dictionary get_time_zone_info() const; uint64_t get_unix_time() const; int get_static_memory_usage() const; diff --git a/core/color.cpp b/core/color.cpp index ba4751dc2f3..32f3df6d4bc 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -161,7 +161,7 @@ void Color::invert() { r=1.0-r; g=1.0-g; - g=1.0-b; + b=1.0-b; } void Color::contrast() { diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h index 0985f3cfe72..113199869bc 100644 --- a/core/command_queue_mt.h +++ b/core/command_queue_mt.h @@ -34,6 +34,7 @@ #include "os/mutex.h" #include "os/memory.h" #include "simple_type.h" +#include "print_string.h" /** @author Juan Linietsky */ @@ -174,7 +175,7 @@ class CommandQueueMT { R* ret; SyncSemaphore *sync; - virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; } + virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); print_line("post"); sync->in_use=false; ; } }; template @@ -675,6 +676,7 @@ public: if (sync) sync->post(); ss->sem->wait(); + print_line("wait"); } template diff --git a/core/globals.cpp b/core/globals.cpp index 23d8c16ace0..8a7d66b68af 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -339,7 +339,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) { //try to load settings in ascending through dirs shape! //tries to open pack, but only first time - if (first_time && _load_resource_pack(current_dir+"/data.pck")) { + if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.pcz") )) { if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) { _load_settings("res://override.cfg"); @@ -1396,6 +1396,13 @@ Globals::Globals() { va.push_back(joyb); set("input/ui_accept",va); + va=Array(); + key.key.scancode=KEY_SPACE; + va.push_back(key); + joyb.joy_button.button_index=JOY_BUTTON_3; + va.push_back(joyb); + set("input/ui_select",va); + va=Array(); key.key.scancode=KEY_ESCAPE; va.push_back(key); @@ -1460,6 +1467,7 @@ Globals::Globals() { custom_prop_info["display/orientation"]=PropertyInfo(Variant::STRING,"display/orientation",PROPERTY_HINT_ENUM,"landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor"); custom_prop_info["render/mipmap_policy"]=PropertyInfo(Variant::INT,"render/mipmap_policy",PROPERTY_HINT_ENUM,"Allow,Allow For Po2,Disallow"); custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); + custom_prop_info["physics_2d/thread_model"]=PropertyInfo(Variant::INT,"physics_2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); set("display/emulate_touchscreen",false); using_datapack=false; diff --git a/core/image.cpp b/core/image.cpp index 04b39054891..037018519e3 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1124,6 +1124,7 @@ void Image::create( const char ** p_xpm ) { } #define DETECT_ALPHA_MAX_TRESHOLD 254 #define DETECT_ALPHA_MIN_TRESHOLD 2 + #define DETECT_ALPHA( m_value )\ { \ uint8_t value=m_value;\ @@ -1136,6 +1137,82 @@ void Image::create( const char ** p_xpm ) { }\ } +#define DETECT_NON_ALPHA( m_value )\ +{ \ + uint8_t value=m_value;\ + if (value>0) {\ + \ + detected=true;\ + break;\ + }\ +} + + +bool Image::is_invisible() const { + + if (format==FORMAT_GRAYSCALE || + format==FORMAT_RGB || + format==FORMAT_INDEXED) + return false; + + int len = data.size(); + + if (len==0) + return true; + + if (format >= FORMAT_YUV_422 && format <= FORMAT_YUV_444) + return false; + + int w,h; + _get_mipmap_offset_and_size(1,len,w,h); + + DVector::Read r = data.read(); + const unsigned char *data_ptr=r.ptr(); + + bool detected=false; + + switch(format) { + case FORMAT_INTENSITY: { + + for(int i=0;i>1);i++) { + DETECT_NON_ALPHA(data_ptr[(i<<1)+1]); + } + + } break; + case FORMAT_RGBA: { + + for(int i=0;i<(len>>2);i++) { + DETECT_NON_ALPHA(data_ptr[(i<<2)+3]) + } + + } break; + case FORMAT_INDEXED: { + + return false; + } break; + case FORMAT_INDEXED_ALPHA: { + + return false; + } break; + case FORMAT_PVRTC2_ALPHA: + case FORMAT_PVRTC4_ALPHA: + case FORMAT_BC2: + case FORMAT_BC3: { + detected=true; + } break; + default: {} + } + + return !detected; +} + Image::AlphaMode Image::detect_alpha() const { if (format==FORMAT_GRAYSCALE || @@ -1746,6 +1823,10 @@ Error Image::_decompress_bc() { return OK; } +bool Image::is_compressed() const { + return format>=FORMAT_BC1; +} + Image Image::decompressed() const { @@ -1998,7 +2079,7 @@ void Image::blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& } -Image (*Image::_png_mem_loader_func)(const uint8_t*)=NULL; +Image (*Image::_png_mem_loader_func)(const uint8_t*,int)=NULL; void (*Image::_image_compress_bc_func)(Image *)=NULL; void (*Image::_image_compress_pvrtc2_func)(Image *)=NULL; void (*Image::_image_compress_pvrtc4_func)(Image *)=NULL; @@ -2167,7 +2248,7 @@ void Image::fix_alpha_edges() { } -Image::Image(const uint8_t* p_png) { +Image::Image(const uint8_t* p_png,int p_len) { width=0; height=0; @@ -2175,7 +2256,7 @@ Image::Image(const uint8_t* p_png) { format=FORMAT_GRAYSCALE; if (_png_mem_loader_func) { - *this = _png_mem_loader_func(p_png); + *this = _png_mem_loader_func(p_png,p_len); } } diff --git a/core/image.h b/core/image.h index ddb5e88ebff..8ce4f22dc12 100644 --- a/core/image.h +++ b/core/image.h @@ -94,7 +94,7 @@ public: /* INTERPOLATE GAUSS */ }; - static Image (*_png_mem_loader_func)(const uint8_t* p_png); + static Image (*_png_mem_loader_func)(const uint8_t* p_png,int p_size); static void (*_image_compress_bc_func)(Image *); static void (*_image_compress_pvrtc2_func)(Image *); static void (*_image_compress_pvrtc4_func)(Image *); @@ -305,6 +305,7 @@ public: }; AlphaMode detect_alpha() const; + bool is_invisible() const; void put_indexed_pixel(int p_x, int p_y, uint8_t p_idx,int p_mipmap=0); uint8_t get_indexed_pixel(int p_x, int p_y,int p_mipmap=0) const; @@ -335,6 +336,7 @@ public: Image compressed(int p_mode); /* from the Image::CompressMode enum */ Error decompress(); Image decompressed() const; + bool is_compressed() const; void fix_alpha_edges(); void premultiply_alpha(); @@ -349,7 +351,7 @@ public: Image get_rect(const Rect2& p_area) const; static void set_compress_bc_func(void (*p_compress_func)(Image *)); - Image(const uint8_t* p_mem_png); + Image(const uint8_t* p_mem_png, int p_len=-1); Image(const char **p_xpm); ~Image(); diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index 2880c4ebdab..83da55fc614 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -74,6 +74,14 @@ bool FileAccessMemory::file_exists(const String& p_name) { } +Error FileAccessMemory::open_custom(const uint8_t* p_data, int p_len) { + + data=(uint8_t*)p_data; + length=p_len; + pos=0; + return OK; +} + Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) { ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND); diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index 5a9ec2b3c63..8c58a8a8ced 100644 --- a/core/io/file_access_memory.h +++ b/core/io/file_access_memory.h @@ -44,6 +44,7 @@ public: static void register_file(String p_name, Vector p_data); static void cleanup(); + virtual Error open_custom(const uint8_t* p_data, int p_len); ///< open a file virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 7a1b6454bd1..ab2eb3b3f2b 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -31,6 +31,7 @@ #include "file_access_zip.h" #include "core/os/file_access.h" +#include "core/os/copymem.h" ZipArchive* ZipArchive::instance = NULL; @@ -103,9 +104,17 @@ static int godot_testerror(voidpf opaque, voidpf stream) { return f->get_error()!=OK?1:0; }; +static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) { + return memalloc(items * size); }; +static void godot_free(voidpf opaque, voidpf address) { + + memfree(address); +}; + +}; // extern "C" void ZipArchive::close_handle(unzFile p_file) const { @@ -125,6 +134,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const { ERR_FAIL_COND_V(!f, NULL); zlib_filefunc_def io; + zeromem(&io, sizeof(io)); io.opaque = f; io.zopen_file = godot_open; @@ -136,9 +146,13 @@ unzFile ZipArchive::get_file_handle(String p_file) const { io.zclose_file = godot_close; io.zerror_file = godot_testerror; + io.alloc_mem = godot_alloc; + io.free_mem = godot_free; + unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io); ERR_FAIL_COND_V(!pkg, NULL); - unzGoToFilePos(pkg, &file.file_pos); + int unz_err = unzGoToFilePos(pkg, &file.file_pos); + ERR_FAIL_COND_V(unz_err != UNZ_OK, NULL); if (unzOpenCurrentFile(pkg) != UNZ_OK) { unzClose(pkg); @@ -150,7 +164,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const { bool ZipArchive::try_open_pack(const String& p_name) { - //printf("opening pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); + //printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); if (p_name.extension().nocasecmp_to("zip") != 0 && p_name.extension().nocasecmp_to("pcz") != 0) return false; @@ -198,7 +212,8 @@ bool ZipArchive::try_open_pack(const String& p_name) { files[fname] = f; uint8_t md5[16]={0,0,0,0,0,0,0,0 , 0,0,0,0,0,0,0,0}; - PackedData::get_singleton()->add_path(p_name, fname, 0, 0, md5, this); + PackedData::get_singleton()->add_path(p_name, fname, 1, 0, md5, this); + //printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str()); if ((i+1) &r_buffer) const { @@ -108,10 +108,29 @@ Variant PacketPeer::_bnd_get_var() const { return var; }; +Error PacketPeer::_put_packet(const DVector &p_buffer) { + return put_packet_buffer(p_buffer); +} +DVector PacketPeer::_get_packet() const { + + DVector raw; + last_get_error=get_packet_buffer(raw); + return raw; +} + +Error PacketPeer::_get_packet_error() const { + + return last_get_error; +} + + void PacketPeer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_var"),&PacketPeer::_bnd_get_var); ObjectTypeDB::bind_method(_MD("put_var", "var:var"),&PacketPeer::put_var); + ObjectTypeDB::bind_method(_MD("get_packet"),&PacketPeer::_get_packet); + ObjectTypeDB::bind_method(_MD("put_packet:Error", "buffer"),&PacketPeer::_put_packet); + ObjectTypeDB::bind_method(_MD("get_packet_error:Error"),&PacketPeer::_get_packet_error); ObjectTypeDB::bind_method(_MD("get_available_packet_count"),&PacketPeer::get_available_packet_count); }; diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index 3448ebde1b8..76d1eb22b57 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -41,6 +41,14 @@ class PacketPeer : public Reference { static void _bind_methods(); + + Error _put_packet(const DVector &p_buffer); + DVector _get_packet() const; + Error _get_packet_error() const; + + + mutable Error last_get_error; + public: virtual int get_available_packet_count() const=0; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 03b6c9759b3..22d89840ae5 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -214,6 +214,7 @@ RES ResourceLoader::load(const String &p_path,const String& p_type_hint,bool p_n Ref ResourceLoader::load_import_metadata(const String &p_path) { + String local_path; if (p_path.is_rel_path()) local_path="res://"+p_path; diff --git a/core/math/math_2d.h b/core/math/math_2d.h index ac315fddb75..5e6cefd114d 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -226,6 +226,29 @@ struct Rect2 { return true; } + inline float distance_to(const Vector2& p_point) const { + + float dist = 1e20; + + if (p_point.x < pos.x) { + dist=MIN(dist,pos.x-p_point.x); + } + if (p_point.y < pos.y) { + dist=MIN(dist,pos.y-p_point.y); + } + if (p_point.x >= (pos.x+size.x) ) { + dist=MIN(p_point.x-(pos.x+size.x),dist); + } + if (p_point.y >= (pos.y+size.y) ) { + dist=MIN(p_point.y-(pos.y+size.y),dist); + } + + if (dist==1e20) + return 0; + else + return dist; + } + _FORCE_INLINE_ bool intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const; bool intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos=NULL, Point2* r_normal=NULL) const; diff --git a/core/message_queue.cpp b/core/message_queue.cpp index cfbdb37b888..489939ee658 100644 --- a/core/message_queue.cpp +++ b/core/message_queue.cpp @@ -324,6 +324,7 @@ int MessageQueue::get_max_buffer_usage() const { void MessageQueue::flush() { + if (buffer_max_usedtype!=TYPE_NOTIFICATION) - read_pos+=sizeof(Variant)*message->args; + advance+=sizeof(Variant)*message->args; message->~Message(); - _THREAD_SAFE_UNLOCK_ + _THREAD_SAFE_LOCK_ + read_pos+=advance; } - _THREAD_SAFE_LOCK_ + buffer_end=0; // reset buffer _THREAD_SAFE_UNLOCK_ diff --git a/core/object.cpp b/core/object.cpp index 1a51e79a9f2..83a6dada802 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -995,12 +995,44 @@ Variant Object::get_meta(const String& p_name) const { return metadata[p_name]; } + Array Object::_get_property_list_bind() const { List lpi; get_property_list(&lpi); return convert_property_list(&lpi); } + +Array Object::_get_method_list_bind() const { + + List ml; + get_method_list(&ml); + Array ret; + + for(List::Element *E=ml.front();E;E=E->next()) { + + Dictionary d; + d["name"]=E->get().name; + d["args"]=convert_property_list(&E->get().arguments); + Array da; + for(int i=0;iget().default_arguments.size();i++) + da.push_back(E->get().default_arguments[i]); + d["default_args"]=da; + d["flags"]=E->get().flags; + d["id"]=E->get().id; + Dictionary r; + r["type"]=E->get().return_val.type; + r["hint"]=E->get().return_val.hint; + r["hint_string"]=E->get().return_val.hint_string; + d["return_type"]=r; + //va.push_back(d); + ret.push_back(d); + } + + return ret; + +} + DVector Object::_get_meta_list_bind() const { DVector _metaret; @@ -1319,7 +1351,7 @@ Error Object::connect(const StringName& p_signal, Object *p_to_object, const Str if (!s) { bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal); if (!signal_is_valid) { - ERR_EXPLAIN("Attempt to connect to nonexistent signal: "+p_signal); + ERR_EXPLAIN("Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_method+"'"); ERR_FAIL_COND_V(!signal_is_valid,ERR_INVALID_PARAMETER); } signal_map[p_signal]=Signal(); @@ -1439,6 +1471,7 @@ void Object::_bind_methods() { ObjectTypeDB::bind_method(_MD("set","property","value"),&Object::_set_bind); ObjectTypeDB::bind_method(_MD("get","property"),&Object::_get_bind); ObjectTypeDB::bind_method(_MD("get_property_list"),&Object::_get_property_list_bind); + ObjectTypeDB::bind_method(_MD("get_method_list"),&Object::_get_method_list_bind); ObjectTypeDB::bind_method(_MD("notification","what"),&Object::notification,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_instance_ID"),&Object::get_instance_ID); diff --git a/core/object.h b/core/object.h index fc64b91412c..8d1f8ebc5a5 100644 --- a/core/object.h +++ b/core/object.h @@ -54,6 +54,7 @@ enum PropertyHint { PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc" PROPERTY_HINT_EXP_EASING, /// exponential easing funciton (Math::ease) PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer) + PROPERTY_HINT_SPRITE_FRAME, PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer) PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) PROPERTY_HINT_ALL_FLAGS, @@ -448,6 +449,7 @@ protected: DVector _get_meta_list_bind() const; Array _get_property_list_bind() const; + Array _get_method_list_bind() const; public: //should be protected, but bug in clang++ static void initialize_type(); diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index 83d3155b036..b4c02ddbced 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -31,7 +31,20 @@ void MainLoop::_bind_methods() { - ObjectTypeDB::bind_method("input_event",&MainLoop::input_event); + ObjectTypeDB::bind_method(_MD("input_event","ev"),&MainLoop::input_event); + ObjectTypeDB::bind_method(_MD("input_text","text"),&MainLoop::input_text); + ObjectTypeDB::bind_method(_MD("init"),&MainLoop::init); + ObjectTypeDB::bind_method(_MD("iteration","delta"),&MainLoop::iteration); + ObjectTypeDB::bind_method(_MD("idle","delta"),&MainLoop::idle); + ObjectTypeDB::bind_method(_MD("finish"),&MainLoop::finish); + + BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"ev")) ); + BIND_VMETHOD( MethodInfo("_input_text",PropertyInfo(Variant::STRING,"text")) ); + BIND_VMETHOD( MethodInfo("_initialize") ); + BIND_VMETHOD( MethodInfo("_iteration",PropertyInfo(Variant::REAL,"delta")) ); + BIND_VMETHOD( MethodInfo("_idle",PropertyInfo(Variant::REAL,"delta")) ); + BIND_VMETHOD( MethodInfo("_finalize") ); + BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN); BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT); @@ -58,13 +71,15 @@ MainLoop::~MainLoop() void MainLoop::input_text( const String& p_text ) { + if (get_script_instance()) + get_script_instance()->call("_input_text",p_text); } void MainLoop::input_event( const InputEvent& p_event ) { if (get_script_instance()) - get_script_instance()->call("input_event",p_event); + get_script_instance()->call("_input_event",p_event); } @@ -74,13 +89,13 @@ void MainLoop::init() { set_script(init_script.get_ref_ptr()); if (get_script_instance()) - get_script_instance()->call("init"); + get_script_instance()->call("_initialize"); } bool MainLoop::iteration(float p_time) { if (get_script_instance()) - return get_script_instance()->call("iteration",p_time); + return get_script_instance()->call("_iteration",p_time); return false; @@ -88,14 +103,14 @@ bool MainLoop::iteration(float p_time) { bool MainLoop::idle(float p_time) { if (get_script_instance()) - return get_script_instance()->call("idle",p_time); + return get_script_instance()->call("_idle",p_time); return false; } void MainLoop::finish() { if (get_script_instance()) { - get_script_instance()->call("finish"); + get_script_instance()->call("_finalize"); set_script(RefPtr()); //clear script } diff --git a/core/os/memory.cpp b/core/os/memory.cpp index 617e40e92a4..1d9ac4e3028 100644 --- a/core/os/memory.cpp +++ b/core/os/memory.cpp @@ -112,13 +112,6 @@ size_t Memory::get_dynamic_mem_usage() { return MemoryPoolDynamic::get_singleton()->get_total_usage(); } -void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description) { - - void *failptr=0; - ERR_FAIL_COND_V( check < p_size , failptr); /** bug, or strange compiler, most likely */ - - return p_pointer; -} diff --git a/core/os/memory.h b/core/os/memory.h index 4497fcc200d..0a35c93fdba 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -236,11 +236,11 @@ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_de #endif -_FORCE_INLINE_ void postinitialize_handler(void *) {} +_ALWAYS_INLINE_ void postinitialize_handler(void *) {} template -_FORCE_INLINE_ T *_post_initialize(T *p_obj) { +_ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { postinitialize_handler(p_obj); return p_obj; @@ -249,19 +249,26 @@ _FORCE_INLINE_ T *_post_initialize(T *p_obj) { #ifdef DEBUG_MEMORY_ENABLED #define memnew(m_class) _post_initialize(new(__FILE__":"__STR(__LINE__)", memnew type: "__STR(m_class)) m_class) -#define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),__FILE__":"__STR(__LINE__)", type: "__STR(m_class)) m_class) #else #define memnew(m_class) _post_initialize(new("") m_class) -#define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),"") m_class) #endif +_ALWAYS_INLINE_ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description) { +// void *failptr=0; +// ERR_FAIL_COND_V( check < p_size , failptr); /** bug, or strange compiler, most likely */ + + return p_pointer; +} + + #define memnew_allocator(m_class,m_allocator) _post_initialize(new(m_allocator::alloc) m_class) +#define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),"") m_class) -_FORCE_INLINE_ bool predelete_handler(void *) { return true; } +_ALWAYS_INLINE_ bool predelete_handler(void *) { return true; } template void memdelete(T *p_class) { diff --git a/core/os/os.h b/core/os/os.h index 2f9957c2f83..0230a75ca08 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -244,9 +244,15 @@ public: int min; int sec; }; - - virtual Date get_date() const=0; - virtual Time get_time() const=0; + + struct TimeZoneInfo { + int bias; + String name; + }; + + virtual Date get_date(bool local=false) const=0; + virtual Time get_time(bool local=false) const=0; + virtual TimeZoneInfo get_time_zone_info() const=0; virtual uint64_t get_unix_time() const; virtual void delay_usec(uint32_t p_usec) const=0; diff --git a/core/reference.h b/core/reference.h index 544da41044d..65f31f78f3d 100644 --- a/core/reference.h +++ b/core/reference.h @@ -294,6 +294,9 @@ public: reference=NULL; } + void instance() { + ref( memnew( T )); + } Ref() { diff --git a/core/variant.cpp b/core/variant.cpp index d7817ac2689..034dc2b4fca 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -302,8 +302,8 @@ bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) { case COLOR: { static const Type valid[] = { - //STRING, - //INT, + STRING, + INT, NIL, }; @@ -1653,6 +1653,10 @@ Variant::operator Color() const { if (type==COLOR) return *reinterpret_cast(_data._mem); + else if (type==STRING) + return Color::html( operator String() ); + else if (type==INT) + return Color::hex( operator int() ); else return Color(); } diff --git a/core/variant_call.cpp b/core/variant_call.cpp index c48336d2ffb..2f7e0205dc7 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -285,6 +285,36 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM1R(String,pad_decimals); VCALL_LOCALMEM1R(String,pad_zeros); + static void _call_String_to_ascii(Variant& r_ret,Variant& p_self,const Variant** p_args) { + + String *s = reinterpret_cast(p_self._data._mem); + CharString charstr = s->ascii(); + + ByteArray retval; + size_t len = charstr.length(); + retval.resize(len); + ByteArray::Write w = retval.write(); + copymem(w.ptr(), charstr.ptr(), len); + w = DVector::Write(); + + r_ret = retval; + } + + static void _call_String_to_utf8(Variant& r_ret,Variant& p_self,const Variant** p_args) { + + String *s = reinterpret_cast(p_self._data._mem); + CharString charstr = s->utf8(); + + ByteArray retval; + size_t len = charstr.length(); + retval.resize(len); + ByteArray::Write w = retval.write(); + copymem(w.ptr(), charstr.ptr(), len); + w = DVector::Write(); + + r_ret = retval; + } + VCALL_LOCALMEM0R(Vector2,normalized); VCALL_LOCALMEM0R(Vector2,length); @@ -1215,9 +1245,10 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC0(STRING,STRING,String,capitalize,varray()); ADDFUNC2(STRING,STRING_ARRAY,String,split,STRING,"divisor",BOOL,"allow_empty",varray(true)); ADDFUNC2(STRING,REAL_ARRAY,String,split_floats,STRING,"divisor",BOOL,"allow_empty",varray(true)); - ADDFUNC0(STRING,STRING,String,to_upper,varray()); + ADDFUNC0(STRING,STRING,String,to_upper,varray()); ADDFUNC0(STRING,STRING,String,to_lower,varray()); + ADDFUNC1(STRING,STRING,String,left,INT,"pos",varray()); ADDFUNC1(STRING,STRING,String,right,INT,"pos",varray()); ADDFUNC0(STRING,STRING,String,strip_edges,varray()); @@ -1249,6 +1280,10 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC1(STRING,STRING,String,pad_decimals,INT,"digits",varray()); ADDFUNC1(STRING,STRING,String,pad_zeros,INT,"digits",varray()); + ADDFUNC0(STRING,STRING,String,to_ascii,varray()); + ADDFUNC0(STRING,STRING,String,to_utf8,varray()); + + ADDFUNC0(VECTOR2,VECTOR2,Vector2,normalized,varray()); ADDFUNC0(VECTOR2,REAL,Vector2,length,varray()); ADDFUNC0(VECTOR2,REAL,Vector2,atan2,varray()); diff --git a/core/vector.h b/core/vector.h index 04018b9f788..b93d9a0deab 100644 --- a/core/vector.h +++ b/core/vector.h @@ -104,7 +104,7 @@ public: template - int find(T_val& p_val) const; + int find(const T_val& p_val) const; void set(int p_index,T p_elem); T get(int p_index) const; @@ -221,7 +221,7 @@ void Vector::_copy_on_write() { } template template -int Vector::find(T_val& p_val) const { +int Vector::find(const T_val &p_val) const { int ret = -1; if (size() == 0) diff --git a/demos/2d/motion/engine.cfg b/demos/2d/motion/engine.cfg index 064de6b331e..29c4d0da203 100644 --- a/demos/2d/motion/engine.cfg +++ b/demos/2d/motion/engine.cfg @@ -2,3 +2,13 @@ name="Motion Test" main_scene="res://motion.scn" + +<<<<<<< HEAD +======= +[display] + +width=800 +height=600 +stretch_mode="2d" +stretch_aspect="keep" +>>>>>>> ab99671bb835a5fe24a092ec34afe1ad862ac254 diff --git a/demos/2d/space_shooter/asteroid.gd b/demos/2d/space_shooter/asteroid.gd new file mode 100644 index 00000000000..f21b9777bb6 --- /dev/null +++ b/demos/2d/space_shooter/asteroid.gd @@ -0,0 +1,49 @@ + +extends Area2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +const SPEED=-200 +const Y_RANDOM=10 + +var points=1 + + +var speed_y=0.0 + +func _process(delta): + + translate( Vector2(SPEED,speed_y) * delta ) + +func _ready(): + # Initialization here + speed_y=rand_range(-Y_RANDOM,Y_RANDOM) + pass + +var destroyed=false + +func destroy(): + if (destroyed): + return + destroyed=true + get_node("anim").play("explode") + set_process(false) + get_node("sfx").play("sound_explode") + #accum points + get_node("/root/game_state").points+=1 + +func is_enemy(): + return not destroyed + + +func _on_visibility_enter_screen(): + set_process(true) + #make it spin! + get_node("anim").play("spin") + + +func _on_visibility_exit_screen(): + queue_free() + pass # replace with function body diff --git a/demos/2d/space_shooter/asteroid.scn b/demos/2d/space_shooter/asteroid.scn new file mode 100644 index 00000000000..b881725ea42 Binary files /dev/null and b/demos/2d/space_shooter/asteroid.scn differ diff --git a/demos/2d/space_shooter/bg_gradient.png b/demos/2d/space_shooter/bg_gradient.png new file mode 100644 index 00000000000..3e71976dc6f Binary files /dev/null and b/demos/2d/space_shooter/bg_gradient.png differ diff --git a/demos/2d/space_shooter/big_star.png b/demos/2d/space_shooter/big_star.png new file mode 100644 index 00000000000..7726a7aa12a Binary files /dev/null and b/demos/2d/space_shooter/big_star.png differ diff --git a/demos/2d/space_shooter/enemy1.gd b/demos/2d/space_shooter/enemy1.gd new file mode 100644 index 00000000000..051798742a9 --- /dev/null +++ b/demos/2d/space_shooter/enemy1.gd @@ -0,0 +1,37 @@ + +extends Area2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +const SPEED=-200 + +func _process(delta): + get_parent().translate(Vector2(SPEED*delta,0)) + + +var destroyed=false + +func is_enemy(): + return not destroyed + + +func destroy(): + if (destroyed): + return + destroyed=true + get_node("anim").play("explode") + set_process(false) + get_node("sfx").play("sound_explode") + #accum points + get_node("/root/game_state").points+=5 + +func _on_visibility_enter_screen(): + set_process(true) + get_node("anim").play("zigzag") + get_node("anim").seek(randf()*2.0) #make it start from any pos + +func _on_visibility_exit_screen(): + queue_free() + diff --git a/demos/2d/space_shooter/enemy1.png b/demos/2d/space_shooter/enemy1.png new file mode 100644 index 00000000000..242d8f0055d Binary files /dev/null and b/demos/2d/space_shooter/enemy1.png differ diff --git a/demos/2d/space_shooter/enemy1.scn b/demos/2d/space_shooter/enemy1.scn new file mode 100644 index 00000000000..14298f0a599 Binary files /dev/null and b/demos/2d/space_shooter/enemy1.scn differ diff --git a/demos/2d/space_shooter/enemy2.gd b/demos/2d/space_shooter/enemy2.gd new file mode 100644 index 00000000000..4f632a053d8 --- /dev/null +++ b/demos/2d/space_shooter/enemy2.gd @@ -0,0 +1,56 @@ + +extends Area2D + +# member variables here, example: +# var a=2 +# var b="textvar" +const SPEED=-220 +const SHOOT_INTERVAL=1 +var shoot_timeout=0 + +func _process(delta): + translate( Vector2(SPEED*delta,0) ) + shoot_timeout-=delta + + if (shoot_timeout<0): + + shoot_timeout=SHOOT_INTERVAL + + #instance a shot + var shot = preload("res://enemy_shot.scn").instance() + #set pos as "shoot_from" Position2D node + shot.set_pos( get_node("shoot_from").get_global_pos() ) + #add it to parent, so it has world coordinates + get_parent().add_child(shot) + +var destroyed=false + +func is_enemy(): + return not destroyed + +func destroy(): + if (destroyed): + return + destroyed=true + get_node("anim").play("explode") + set_process(false) + get_node("sfx").play("sound_explode") + #accum points + get_node("/root/game_state").points+=10 + +func _ready(): + set_fixed_process(true) + # Initialization here + pass + + + + +func _on_visibility_enter_screen(): + set_process(true) + pass # replace with function body + + +func _on_visibility_exit_screen(): + queue_free() + pass # replace with function body diff --git a/demos/2d/space_shooter/enemy2.png b/demos/2d/space_shooter/enemy2.png new file mode 100644 index 00000000000..5b63033696d Binary files /dev/null and b/demos/2d/space_shooter/enemy2.png differ diff --git a/demos/2d/space_shooter/enemy2.scn b/demos/2d/space_shooter/enemy2.scn new file mode 100644 index 00000000000..1d31f9c30e5 Binary files /dev/null and b/demos/2d/space_shooter/enemy2.scn differ diff --git a/demos/2d/space_shooter/enemy_shot.gd b/demos/2d/space_shooter/enemy_shot.gd new file mode 100644 index 00000000000..238d24e4a2c --- /dev/null +++ b/demos/2d/space_shooter/enemy_shot.gd @@ -0,0 +1,32 @@ + +extends Area2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +const SPEED = -800 + +func _process(delta): + translate(Vector2(delta*SPEED,0)) + +func _ready(): + # Initialization here + set_process(true) + + +var hit=false + +func is_enemy(): + return true + +func _hit_something(): + if (hit): + return + hit=true + set_process(false) + get_node("anim").play("splash") + +func _on_visibility_exit_screen(): + queue_free() + diff --git a/demos/2d/space_shooter/enemy_shot.png b/demos/2d/space_shooter/enemy_shot.png new file mode 100644 index 00000000000..04287211a93 Binary files /dev/null and b/demos/2d/space_shooter/enemy_shot.png differ diff --git a/demos/2d/space_shooter/enemy_shot.scn b/demos/2d/space_shooter/enemy_shot.scn new file mode 100644 index 00000000000..13f5ae89e5f Binary files /dev/null and b/demos/2d/space_shooter/enemy_shot.scn differ diff --git a/demos/2d/space_shooter/engine.cfg b/demos/2d/space_shooter/engine.cfg new file mode 100644 index 00000000000..8047cebdd3b --- /dev/null +++ b/demos/2d/space_shooter/engine.cfg @@ -0,0 +1,22 @@ +[application] + +name="Simple Shooter" +main_scene="res://main_menu.scn" +icon="res://icon.png" + +[autoload] + +game_state="res://game_state.gd" + +[display] + +width=1024 +height=600 + +[input] + +move_up=[key(Up)] +move_down=[key(Down)] +move_left=[key(Left)] +move_right=[key(Right)] +shoot=[key(Space)] diff --git a/demos/2d/space_shooter/explosion.scn b/demos/2d/space_shooter/explosion.scn new file mode 100644 index 00000000000..4edcf709cb4 Binary files /dev/null and b/demos/2d/space_shooter/explosion.scn differ diff --git a/demos/2d/space_shooter/fire.png b/demos/2d/space_shooter/fire.png new file mode 100644 index 00000000000..1c68c362133 Binary files /dev/null and b/demos/2d/space_shooter/fire.png differ diff --git a/demos/2d/space_shooter/game_state.gd b/demos/2d/space_shooter/game_state.gd new file mode 100644 index 00000000000..26ef086f14c --- /dev/null +++ b/demos/2d/space_shooter/game_state.gd @@ -0,0 +1,24 @@ +extends Node + + +var points = 0 +var max_points = 0 + + +func _ready(): + var f = File.new() + #load high score + if (f.open("user://highscore",File.READ)==OK): + + max_points=f.get_var() + + + +func game_over(): + if (points>max_points): + max_points=points + #save high score + var f = File.new() + f.open("user://highscore",File.WRITE) + f.store_var(max_points) + \ No newline at end of file diff --git a/demos/2d/space_shooter/icon.png b/demos/2d/space_shooter/icon.png new file mode 100644 index 00000000000..1df2bf5d9d3 Binary files /dev/null and b/demos/2d/space_shooter/icon.png differ diff --git a/demos/2d/space_shooter/level.scn b/demos/2d/space_shooter/level.scn new file mode 100644 index 00000000000..12a679f8b66 Binary files /dev/null and b/demos/2d/space_shooter/level.scn differ diff --git a/demos/2d/space_shooter/level_tiles.res b/demos/2d/space_shooter/level_tiles.res new file mode 100644 index 00000000000..8712b8c7990 Binary files /dev/null and b/demos/2d/space_shooter/level_tiles.res differ diff --git a/demos/2d/space_shooter/level_tiles.scn b/demos/2d/space_shooter/level_tiles.scn new file mode 100644 index 00000000000..3fb91d8cb30 Binary files /dev/null and b/demos/2d/space_shooter/level_tiles.scn differ diff --git a/demos/2d/space_shooter/main_menu.gd b/demos/2d/space_shooter/main_menu.gd new file mode 100644 index 00000000000..52221aba1b8 --- /dev/null +++ b/demos/2d/space_shooter/main_menu.gd @@ -0,0 +1,20 @@ + +extends Control + +# member variables here, example: +# var a=2 +# var b="textvar" + +func _ready(): + + get_node("score").set_text( "HIGH SCORE: "+str( get_node("/root/game_state").max_points ) ) + # Initialization here + pass + + + + +func _on_play_pressed(): + get_node("/root/game_state").points=0 + get_tree().change_scene("res://level.scn") + pass # replace with function body diff --git a/demos/2d/space_shooter/main_menu.scn b/demos/2d/space_shooter/main_menu.scn new file mode 100644 index 00000000000..b87cc5d3a8b Binary files /dev/null and b/demos/2d/space_shooter/main_menu.scn differ diff --git a/demos/2d/space_shooter/meteorite.png b/demos/2d/space_shooter/meteorite.png new file mode 100644 index 00000000000..92fb4387df9 Binary files /dev/null and b/demos/2d/space_shooter/meteorite.png differ diff --git a/demos/2d/space_shooter/parallax.scn b/demos/2d/space_shooter/parallax.scn new file mode 100644 index 00000000000..f67277dc015 Binary files /dev/null and b/demos/2d/space_shooter/parallax.scn differ diff --git a/demos/2d/space_shooter/rail.gd b/demos/2d/space_shooter/rail.gd new file mode 100644 index 00000000000..803a09fe846 --- /dev/null +++ b/demos/2d/space_shooter/rail.gd @@ -0,0 +1,26 @@ + +extends Node2D + + +const SPEED=200 +# member variables here, example: +# var a=2 +# var b="textvar" + +func stop(): + set_process(false) + +var offset=0 + + +func _process(delta): + + offset+=delta*SPEED + set_pos(Vector2(offset,0)) + +func _ready(): + set_process(true) + # Initialization here + + + diff --git a/demos/2d/space_shooter/ship.gd b/demos/2d/space_shooter/ship.gd new file mode 100644 index 00000000000..fa444868a43 --- /dev/null +++ b/demos/2d/space_shooter/ship.gd @@ -0,0 +1,88 @@ + +extends Area2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +const SPEED = 200 + +var screen_size + +var prev_shooting=false + +func _process(delta): + + var motion = Vector2() + if Input.is_action_pressed("move_up"): + motion+=Vector2(0,-1) + if Input.is_action_pressed("move_down"): + motion+=Vector2(0,1) + if Input.is_action_pressed("move_left"): + motion+=Vector2(-1,0) + if Input.is_action_pressed("move_right"): + motion+=Vector2(1,0) + var shooting = Input.is_action_pressed("shoot") + + var pos = get_pos() + + pos+=motion*delta*SPEED + if (pos.x<0): + pos.x=0 + if (pos.x>screen_size.x): + pos.x=screen_size.x + if (pos.y<0): + pos.y=0 + if (pos.y>screen_size.y): + pos.y=screen_size.y + + set_pos(pos) + + if (shooting and not prev_shooting): + # just pressed + var shot = preload("res://shot.scn").instance() + #use the position3d as reference + shot.set_pos( get_node("shootfrom").get_global_pos() ) + #put it two parents above, so it is not moved by us + get_node("../..").add_child(shot) + #play sound + get_node("sfx").play("shoot") + + + prev_shooting = shooting + + #update points counter + get_node("../hud/score_points").set_text( str(get_node("/root/game_state").points) ) + +func _ready(): + # Initialization here + screen_size = get_viewport().get_rect().size + set_process(true) + pass + +var killed=false + +func _hit_something(): + if (killed): + return + killed=true + get_node("anim").play("explode") + get_node("sfx").play("sound_explode") + get_node("../hud/game_over").show() + get_node("/root/game_state").game_over() + get_parent().stop() + set_process(false) + + +func _on_ship_body_enter( body ): + _hit_something() + + +func _on_ship_area_enter( area ): + if (area.has_method("is_enemy") and area.is_enemy()): + _hit_something() + + +func _on_back_to_menu_pressed(): + get_tree().change_scene("res://main_menu.scn") + pass # replace with function body diff --git a/demos/2d/space_shooter/ship.png b/demos/2d/space_shooter/ship.png new file mode 100644 index 00000000000..a36b8339032 Binary files /dev/null and b/demos/2d/space_shooter/ship.png differ diff --git a/demos/2d/space_shooter/ship.scn b/demos/2d/space_shooter/ship.scn new file mode 100644 index 00000000000..82c710eda78 Binary files /dev/null and b/demos/2d/space_shooter/ship.scn differ diff --git a/demos/2d/space_shooter/shoot.png b/demos/2d/space_shooter/shoot.png new file mode 100644 index 00000000000..6e80ddab935 Binary files /dev/null and b/demos/2d/space_shooter/shoot.png differ diff --git a/demos/2d/space_shooter/shot.gd b/demos/2d/space_shooter/shot.gd new file mode 100644 index 00000000000..813587d6705 --- /dev/null +++ b/demos/2d/space_shooter/shot.gd @@ -0,0 +1,47 @@ + +extends Area2D + +# member variables here, example: +# var a=2 +# var b="textvar" + +const SPEED = 800 + +func _process(delta): + translate(Vector2(delta*SPEED,0)) + +func _ready(): + # Initialization here + set_process(true) + pass + +var hit=false + +func _hit_something(): + if (hit): + return + hit=true + set_process(false) + get_node("anim").play("splash") + +func _on_visibility_exit_screen(): + queue_free() + pass # replace with function body + + + +func _on_shot_area_enter( area ): + #hit an enemy or asteroid + if (area.has_method("destroy")): + #duck typing at it's best + area.destroy() + _hit_something() + + + pass + + +func _on_shot_body_enter( body ): + #hit the tilemap + _hit_something() + pass # replace with function body diff --git a/demos/2d/space_shooter/shot.scn b/demos/2d/space_shooter/shot.scn new file mode 100644 index 00000000000..64c8c25ebe6 Binary files /dev/null and b/demos/2d/space_shooter/shot.scn differ diff --git a/demos/2d/space_shooter/small_star.png b/demos/2d/space_shooter/small_star.png new file mode 100644 index 00000000000..71c3c531cd8 Binary files /dev/null and b/demos/2d/space_shooter/small_star.png differ diff --git a/demos/2d/space_shooter/sound_explode.wav b/demos/2d/space_shooter/sound_explode.wav new file mode 100644 index 00000000000..229c85399c6 Binary files /dev/null and b/demos/2d/space_shooter/sound_explode.wav differ diff --git a/demos/2d/space_shooter/sound_shoot.wav b/demos/2d/space_shooter/sound_shoot.wav new file mode 100644 index 00000000000..ad74f328cb4 Binary files /dev/null and b/demos/2d/space_shooter/sound_shoot.wav differ diff --git a/demos/2d/space_shooter/tile.png b/demos/2d/space_shooter/tile.png new file mode 100644 index 00000000000..d8f41d16f66 Binary files /dev/null and b/demos/2d/space_shooter/tile.png differ diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 4acac957c84..efc92c5d9f0 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -4394,7 +4394,7 @@ void RasterizerGLES2::begin_shadow_map( RID p_light_instance, int p_shadow_pass } -void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_projection) { +void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint) { camera_transform=p_world; if (current_rt && current_rt_vflip) { @@ -4402,10 +4402,11 @@ void RasterizerGLES2::set_camera(const Transform& p_world,const CameraMatrix& p_ } camera_transform_inverse=camera_transform.inverse(); camera_projection=p_projection; - camera_plane = Plane( camera_transform.origin, camera_transform.basis.get_axis(2) ); + camera_plane = Plane( camera_transform.origin, -camera_transform.basis.get_axis(2) ); camera_z_near=camera_projection.get_z_near(); camera_z_far=camera_projection.get_z_far(); camera_projection.get_viewport_size(camera_vp_size.x,camera_vp_size.y); + camera_ortho=p_ortho_hint; } void RasterizerGLES2::add_light( RID p_light_instance ) { @@ -4768,8 +4769,11 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD e->geometry_cmp=p_geometry_cmp; e->material=m; e->instance=p_instance; - //e->depth=camera_plane.distance_to(p_world->origin); - e->depth=camera_transform.origin.distance_to(p_instance->transform.origin); + if (camera_ortho) { + e->depth=camera_plane.distance_to(p_instance->transform.origin); + } else { + e->depth=camera_transform.origin.distance_to(p_instance->transform.origin); + } e->owner=p_owner; e->light_type=0; e->additive=false; @@ -5214,7 +5218,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material DEBUG_TEST_ERROR("Material arameters"); if (p_material->shader_cache->uses_time) { - material_shader.set_uniform(MaterialShaderGLES2::TIME,Math::fmod(last_time,300.0)); + material_shader.set_uniform(MaterialShaderGLES2::TIME,Math::fmod(last_time,shader_time_rollback)); draw_next_frame=true; } //if uses TIME - draw_next_frame=true @@ -9219,7 +9223,7 @@ void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItemMaterial *mat } if (shader->uses_time) { - canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0)); + canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,shader_time_rollback)); draw_next_frame=true; } //if uses TIME - draw_next_frame=true @@ -10796,6 +10800,7 @@ void RasterizerGLES2::init() { current_rt=NULL; current_vd=NULL; current_debug=VS::SCENARIO_DEBUG_DISABLED; + camera_ortho=false; glGenBuffers(1,&gui_quad_buffer); glBindBuffer(GL_ARRAY_BUFFER,gui_quad_buffer); @@ -10814,6 +10819,8 @@ void RasterizerGLES2::init() { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);// unbind #endif + shader_time_rollback = GLOBAL_DEF("rasterizer/shader_time_rollback",300); + using_canvas_bg=false; _update_framebuffer(); DEBUG_TEST_ERROR("Initializing"); diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index 1821b1a7503..d337ecfb640 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -1052,6 +1052,7 @@ class RasterizerGLES2 : public Rasterizer { float camera_z_near; float camera_z_far; Size2 camera_vp_size; + bool camera_ortho; Set extensions; bool texscreen_copied; bool texscreen_used; @@ -1273,6 +1274,7 @@ class RasterizerGLES2 : public Rasterizer { Environment *current_env; VS::ScenarioDebugMode current_debug; RID overdraw_material; + float shader_time_rollback; mutable MaterialShaderGLES2 material_shader; @@ -1588,7 +1590,7 @@ public: virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass ); - virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection); + virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint); virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index 2e1488ff9d5..2a4720b07b6 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -31,6 +31,8 @@ #include "print_string.h" #include "os/os.h" + + void ImageLoaderPNG::_read_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) { FileAccess *f = (FileAccess*)png_get_io_ptr(png_ptr); @@ -253,6 +255,7 @@ void ImageLoaderPNG::get_recognized_extensions(List *p_extensions) const struct PNGReadStatus { int offset; + int size; const unsigned char *image; }; @@ -261,17 +264,26 @@ static void user_read_data(png_structp png_ptr,png_bytep data, png_size_t p_leng PNGReadStatus *rstatus; rstatus=(PNGReadStatus*)png_get_io_ptr(png_ptr); - memcpy(data,&rstatus->image[rstatus->offset],p_length); - rstatus->offset+=p_length; + int to_read=p_length; + if (rstatus->size>=0) { + to_read = MIN( p_length, rstatus->size - rstatus->offset); + } + memcpy(data,&rstatus->image[rstatus->offset],to_read); + rstatus->offset+=to_read; + + if (to_read& p_data) { + int len = p_data.size(); DVector::Read r = p_data.read(); ERR_FAIL_COND_V(r[0]!='P' || r[1]!='N' || r[2]!='G' || r[3]!=' ',Image()); - return _load_mem_png(&r[4]); + return _load_mem_png(&r[4],len-4); } @@ -424,6 +437,7 @@ static DVector _lossless_pack_png(const Image& p_image) { ImageLoaderPNG::ImageLoaderPNG() { + Image::_png_mem_loader_func=_load_mem_png; Image::lossless_unpacker=_lossless_unpack_png; Image::lossless_packer=_lossless_pack_png; diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index 7acfd041eeb..8413a7eae18 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -40,7 +40,10 @@ class ImageLoaderPNG : public ImageFormatLoader { static void _read_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length); + public: + + static Error _load_image(void *rf_up,png_rw_ptr p_func,Image *p_image); virtual Error load_image(Image *p_image,FileAccess *f); virtual void get_recognized_extensions(List *p_extensions) const; diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index d558aadc8ee..8ba56490d79 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -218,10 +218,14 @@ uint64_t OS_Unix::get_unix_time() const { }; -OS::Date OS_Unix::get_date() const { +OS::Date OS_Unix::get_date(bool utc) const { time_t t=time(NULL); - struct tm *lt=localtime(&t); + struct tm *lt; + if (utc) + lt=gmtime(&t); + else + lt=localtime(&t); Date ret; ret.year=1900+lt->tm_year; ret.month=(Month)lt->tm_mon; @@ -231,17 +235,47 @@ OS::Date OS_Unix::get_date() const { return ret; } -OS::Time OS_Unix::get_time() const { - +OS::Time OS_Unix::get_time(bool utc) const { time_t t=time(NULL); - struct tm *lt=localtime(&t); + struct tm *lt; + if (utc) + lt=gmtime(&t); + else + lt=localtime(&t); Time ret; ret.hour=lt->tm_hour; ret.min=lt->tm_min; ret.sec=lt->tm_sec; + get_time_zone_info(); return ret; } - + +OS::TimeZoneInfo OS_Unix::get_time_zone_info() const { + time_t t = time(NULL); + struct tm *lt = localtime(&t); + char name[16]; + strftime(name, 16, "%Z", lt); + name[15] = 0; + TimeZoneInfo ret; + ret.name = name; + + char bias_buf[16]; + strftime(bias_buf, 16, "%z", lt); + int bias; + bias_buf[15] = 0; + sscanf(bias_buf, "%d", &bias); + + // convert from ISO 8601 (1 minute=1, 1 hour=100) to minutes + int hour = (int)bias / 100; + int minutes = bias % 100; + if (bias < 0) + ret.bias = hour * 60 - minutes; + else + ret.bias = hour * 60 + minutes; + + return ret; +} + void OS_Unix::delay_usec(uint32_t p_usec) const { usleep(p_usec); diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 65df1139567..8bb57eda129 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -88,8 +88,9 @@ public: virtual String get_name(); - virtual Date get_date() const; - virtual Time get_time() const; + virtual Date get_date(bool utc) const; + virtual Time get_time(bool utc) const; + virtual TimeZoneInfo get_time_zone_info() const; virtual uint64_t get_unix_time() const; diff --git a/godot_logo.svg b/godot_logo.svg new file mode 100644 index 00000000000..98dcddfd2bf --- /dev/null +++ b/godot_logo.svg @@ -0,0 +1,134 @@ + +image/svg+xml \ No newline at end of file diff --git a/main/main.cpp b/main/main.cpp index f826b362124..15f969f466a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -98,6 +98,9 @@ static int video_driver_idx=-1; static int audio_driver_idx=-1; static String locale; +static bool init_maximized=false; +static int init_screen=-1; + static String unescape_cmdline(const String& p_str) { return p_str.replace("%20"," "); @@ -384,7 +387,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas } else if (I->get()=="-e" || I->get()=="-editor") { // fonud editor editor=true; - + init_maximized=true; } else if (I->get()=="-nowindow") { // fullscreen OS::get_singleton()->set_no_window_mode(true); @@ -789,6 +792,13 @@ Error Main::setup2() { show_logo=false; #endif + if (init_screen!=-1) { + OS::get_singleton()->set_current_screen(init_screen); + } + if (init_maximized) { + OS::get_singleton()->set_window_maximized(true); + } + if (show_logo) { //boot logo! String boot_logo_path=GLOBAL_DEF("application/boot_splash",String()); bool boot_logo_scale=GLOBAL_DEF("application/boot_splash_fullsize",true); @@ -1320,8 +1330,8 @@ bool Main::iteration() { double step=(double)ticks_elapsed / 1000000.0; float frame_slice=1.0/OS::get_singleton()->get_iterations_per_second(); - //if (time_accum+step < frame_slice) - // return false; +// if (time_accum+step < frame_slice) +// return false; frame+=ticks_elapsed; @@ -1356,6 +1366,8 @@ bool Main::iteration() { message_queue->flush(); PhysicsServer::get_singleton()->step(frame_slice*time_scale); + + Physics2DServer::get_singleton()->end_sync(); Physics2DServer::get_singleton()->step(frame_slice*time_scale); time_accum-=frame_slice; @@ -1378,6 +1390,8 @@ bool Main::iteration() { SpatialSound2DServer::get_singleton()->update( step*time_scale ); + VisualServer::get_singleton()->sync(); //sync if still drawing from previous frames. + if (OS::get_singleton()->can_draw()) { if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) { @@ -1390,8 +1404,6 @@ bool Main::iteration() { OS::get_singleton()->frames_drawn++; force_redraw_requested = false; } - } else { - VisualServer::get_singleton()->flush(); // flush visual commands } if (AudioServer::get_singleton()) diff --git a/makerel.bat b/makerel.bat new file mode 100644 index 00000000000..7db76e1dd77 --- /dev/null +++ b/makerel.bat @@ -0,0 +1 @@ +"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" && c:\python27\scons p=windows target=debug_release tools=no diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java index 4f42a1a82b4..9b9b1ab2ada 100644 --- a/platform/android/java/src/com/android/godot/Godot.java +++ b/platform/android/java/src/com/android/godot/Godot.java @@ -747,7 +747,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC //} } break; case MotionEvent.ACTION_POINTER_UP: { - final int indexPointUp = event.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; + final int indexPointUp = event.getActionIndex(); final int pointer_idx = event.getPointerId(indexPointUp); GodotLib.touch(4,pointer_idx,evcount,arr); //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx)); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 80953df85f6..612148418b1 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -163,7 +163,8 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_ // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); input = memnew( InputDefault ); diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 41892d23b42..7a5a55653f1 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -37,6 +37,7 @@ #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" #include "servers/audio/audio_server_sw.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include "servers/visual/rasterizer.h" diff --git a/platform/iphone/game_center.h b/platform/iphone/game_center.h index 1f4820a3c28..8f180d16383 100644 --- a/platform/iphone/game_center.h +++ b/platform/iphone/game_center.h @@ -51,6 +51,12 @@ public: Error post_score(Variant p_score); Error award_achievement(Variant p_params); + void reset_achievements(); + void request_achievements(); + void request_achievement_descriptions(); + Error show_game_center(Variant p_params); + + void game_center_closed(); int get_pending_event_count(); Variant pop_pending_event(); diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm index fd1e5f3be77..79c056776d5 100644 --- a/platform/iphone/game_center.mm +++ b/platform/iphone/game_center.mm @@ -32,6 +32,7 @@ extern "C" { #import +#import "app_delegate.h" }; GameCenter* GameCenter::instance = NULL; @@ -42,6 +43,10 @@ void GameCenter::_bind_methods() { ObjectTypeDB::bind_method(_MD("post_score"),&GameCenter::post_score); ObjectTypeDB::bind_method(_MD("award_achievement"),&GameCenter::award_achievement); + ObjectTypeDB::bind_method(_MD("reset_achievements"),&GameCenter::reset_achievements); + ObjectTypeDB::bind_method(_MD("request_achievements"),&GameCenter::request_achievements); + ObjectTypeDB::bind_method(_MD("request_achievement_descriptions"),&GameCenter::request_achievement_descriptions); + ObjectTypeDB::bind_method(_MD("show_game_center"),&GameCenter::show_game_center); ObjectTypeDB::bind_method(_MD("get_pending_event_count"),&GameCenter::get_pending_event_count); ObjectTypeDB::bind_method(_MD("pop_pending_event"),&GameCenter::pop_pending_event); @@ -50,23 +55,41 @@ void GameCenter::_bind_methods() { Error GameCenter::connect() { + //if this class isn't available, game center isn't implemented + if ((NSClassFromString(@"GKLocalPlayer")) == nil) { + GameCenter::get_singleton()->connected = false; + return ERR_UNAVAILABLE; + } + GKLocalPlayer* player = [GKLocalPlayer localPlayer]; - [player authenticateWithCompletionHandler:^(NSError* error) { + ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE); - Dictionary ret; - ret["type"] = "authentication"; - if (player.isAuthenticated) { - ret["result"] = "ok"; - GameCenter::get_singleton()->connected = true; - } else { - ret["result"] = "error"; - ret["error_code"] = error.code; - ret["error_description"] = [error.localizedDescription UTF8String]; - GameCenter::get_singleton()->connected = false; - }; + ViewController *root_controller=(ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; + ERR_FAIL_COND_V(!root_controller, FAILED); + + //this handler is called serveral times. first when the view needs to be shown, then again after the view is cancelled or the user logs in. or if the user's already logged in, it's called just once to confirm they're authenticated. This is why no result needs to be specified in the presentViewController phase. in this case, more calls to this function will follow. + player.authenticateHandler = (^(UIViewController *controller, NSError *error) { + if (controller) { + [root_controller presentViewController:controller animated:YES completion:nil]; + } + else { + Dictionary ret; + ret["type"] = "authentication"; + if (player.isAuthenticated) { + ret["result"] = "ok"; + GameCenter::get_singleton()->connected = true; + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + ret["error_description"] = [error.localizedDescription UTF8String]; + GameCenter::get_singleton()->connected = false; + }; + + pending_events.push_back(ret); + }; + + }); - pending_events.push_back(ret); - }]; return OK; }; @@ -85,7 +108,9 @@ Error GameCenter::post_score(Variant p_score) { GKScore* reporter = [[[GKScore alloc] initWithCategory:cat_str] autorelease]; reporter.value = score; - [reporter reportScoreWithCompletionHandler:^(NSError* error) { + ERR_FAIL_COND_V([GKScore respondsToSelector:@selector(reportScores)], ERR_UNAVAILABLE); + + [GKScore reportScores:@[reporter] withCompletionHandler:^(NSError* error) { Dictionary ret; ret["type"] = "post_score"; @@ -114,8 +139,15 @@ Error GameCenter::award_achievement(Variant p_params) { GKAchievement* achievement = [[[GKAchievement alloc] initWithIdentifier: name_str] autorelease]; ERR_FAIL_COND_V(!achievement, FAILED); + ERR_FAIL_COND_V([GKAchievement respondsToSelector:@selector(reportAchievements)], ERR_UNAVAILABLE); + achievement.percentComplete = progress; - [achievement reportAchievementWithCompletionHandler:^(NSError* error) { + achievement.showsCompletionBanner = NO; + if (params.has("show_completion_banner")) { + achievement.showsCompletionBanner = params["show_completion_banner"] ? YES : NO; + } + + [GKAchievement reportAchievements:@[achievement] withCompletionHandler:^(NSError *error) { Dictionary ret; ret["type"] = "award_achievement"; @@ -132,6 +164,168 @@ Error GameCenter::award_achievement(Variant p_params) { return OK; }; +void GameCenter::request_achievement_descriptions() { + + [GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:^(NSArray *descriptions, NSError *error) { + + Dictionary ret; + ret["type"] = "achievement_descriptions"; + if (error == nil) { + ret["result"] = "ok"; + StringArray names; + StringArray titles; + StringArray unachieved_descriptions; + StringArray achieved_descriptions; + IntArray maximum_points; + Array hidden; + Array replayable; + + for (int i=0; i<[descriptions count]; i++) { + + GKAchievementDescription* description = [descriptions objectAtIndex:i]; + + const char* str = [description.identifier UTF8String]; + names.push_back(String::utf8(str != NULL ? str : "")); + + str = [description.title UTF8String]; + titles.push_back(String::utf8(str != NULL ? str : "")); + + str = [description.unachievedDescription UTF8String]; + unachieved_descriptions.push_back(String::utf8(str != NULL ? str : "")); + + str = [description.achievedDescription UTF8String]; + achieved_descriptions.push_back(String::utf8(str != NULL ? str : "")); + + maximum_points.push_back(description.maximumPoints); + + hidden.push_back(description.hidden == YES); + + replayable.push_back(description.replayable == YES); + } + + ret["names"] = names; + ret["titles"] = titles; + ret["unachieved_descriptions"] = unachieved_descriptions; + ret["achieved_descriptions"] = achieved_descriptions; + ret["maximum_points"] = maximum_points; + ret["hidden"] = hidden; + ret["replayable"] = replayable; + + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + }; + + pending_events.push_back(ret); + }]; +}; + + +void GameCenter::request_achievements() { + + [GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) { + + Dictionary ret; + ret["type"] = "achievements"; + if (error == nil) { + ret["result"] = "ok"; + StringArray names; + RealArray percentages; + + for (int i=0; i<[achievements count]; i++) { + + GKAchievement* achievement = [achievements objectAtIndex:i]; + const char* str = [achievement.identifier UTF8String]; + names.push_back(String::utf8(str != NULL ? str : "")); + + percentages.push_back(achievement.percentComplete); + } + + ret["names"] = names; + ret["progress"] = percentages; + + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + }; + + pending_events.push_back(ret); + }]; +}; + +void GameCenter::reset_achievements() { + + [GKAchievement resetAchievementsWithCompletionHandler:^(NSError *error) + { + Dictionary ret; + ret["type"] = "reset_achievements"; + if (error == nil) { + ret["result"] = "ok"; + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + }; + + pending_events.push_back(ret); + }]; +}; + +Error GameCenter::show_game_center(Variant p_params) { + + ERR_FAIL_COND_V(!NSProtocolFromString(@"GKGameCenterControllerDelegate"), FAILED); + + Dictionary params = p_params; + + GKGameCenterViewControllerState view_state = GKGameCenterViewControllerStateDefault; + if (params.has("view")) { + String view_name = params["view"]; + if (view_name == "default") { + view_state = GKGameCenterViewControllerStateDefault; + } + else if (view_name == "leaderboards") { + view_state = GKGameCenterViewControllerStateLeaderboards; + } + else if (view_name == "achievements") { + view_state = GKGameCenterViewControllerStateAchievements; + } + else if (view_name == "challenges") { + view_state = GKGameCenterViewControllerStateChallenges; + } + else { + return ERR_INVALID_PARAMETER; + } + } + + GKGameCenterViewController *controller = [[GKGameCenterViewController alloc] init]; + ERR_FAIL_COND_V(!controller, FAILED); + + ViewController *root_controller=(ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; + ERR_FAIL_COND_V(!root_controller, FAILED); + + controller.gameCenterDelegate = root_controller; + controller.viewState = view_state; + if (view_state == GKGameCenterViewControllerStateLeaderboards) { + controller.leaderboardIdentifier = nil; + if (params.has("leaderboard_name")) { + String name = params["leaderboard_name"]; + NSString* name_str = [[[NSString alloc] initWithUTF8String:name.utf8().get_data()] autorelease]; + controller.leaderboardIdentifier = name_str; + } + } + + [root_controller presentViewController: controller animated: YES completion:nil]; + + return OK; +}; + +void GameCenter::game_center_closed() { + + Dictionary ret; + ret["type"] = "show_game_center"; + ret["result"] = "ok"; + pending_events.push_back(ret); +} + int GameCenter::get_pending_event_count() { return pending_events.size(); diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm index 55185aa49d2..3309fd08201 100755 --- a/platform/iphone/gl_view.mm +++ b/platform/iphone/gl_view.mm @@ -352,8 +352,9 @@ static void clear_touches() { // Generate IDs for a framebuffer object and a color renderbuffer UIScreen* mainscr = [UIScreen mainScreen]; printf("******** screen size %i, %i\n", (int)mainscr.currentMode.size.width, (int)mainscr.currentMode.size.height); - if (mainscr.currentMode.size.width == 640 || mainscr.currentMode.size.width == 960) // modern iphone, can go to 640x960 - self.contentScaleFactor = 2.0; + float minPointSize = MIN(mainscr.bounds.size.width, mainscr.bounds.size.height); + float minScreenSize = MIN(mainscr.currentMode.size.width, mainscr.currentMode.size.height); + self.contentScaleFactor = minScreenSize / minPointSize; glGenFramebuffersOES(1, &viewFramebuffer); glGenRenderbuffersOES(1, &viewRenderbuffer); diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm index 1d40b1762ec..e3ba6bbd73c 100644 --- a/platform/iphone/in_app_store.mm +++ b/platform/iphone/in_app_store.mm @@ -210,7 +210,7 @@ Error InAppStore::request_product_info(Variant p_params) { receipt_to_send = [receipt description]; } Dictionary receipt_ret; - receipt_ret["receipt"] = String::utf8([receipt_to_send UTF8String]); + receipt_ret["receipt"] = String::utf8(receipt_to_send != nil ? [receipt_to_send UTF8String] : ""); receipt_ret["sdk"] = sdk_version; ret["receipt"] = receipt_ret; diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index bf85ecc9dd9..ade1c292a43 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -136,7 +136,8 @@ void OSIPhone::initialize(const VideoMode& p_desired,int p_video_driver,int p_au // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); input = memnew( InputDefault ); diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 721db36f411..844f0675529 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -38,6 +38,7 @@ #include "servers/visual/rasterizer.h" #include "servers/physics/physics_server_sw.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include "servers/audio/audio_server_sw.h" #include "servers/audio/sample_manager_sw.h" #include "servers/spatial_sound/spatial_sound_server_sw.h" diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h index 9432aebd97a..0cee2f6fbf5 100644 --- a/platform/iphone/view_controller.h +++ b/platform/iphone/view_controller.h @@ -27,8 +27,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #import +#import -@interface ViewController : UIViewController { +@interface ViewController : UIViewController { }; diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm index a5ca689e616..bc9950979ef 100644 --- a/platform/iphone/view_controller.mm +++ b/platform/iphone/view_controller.mm @@ -124,10 +124,15 @@ int add_cmdline(int p_argc, char** p_args) { } }; - - (BOOL)prefersStatusBarHidden { return YES; } +- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController*) gameCenterViewController { + //[gameCenterViewController dismissViewControllerAnimated:YES completion:^{GameCenter::get_singleton()->game_center_closed();}];//version for signaling when overlay is completely gone + GameCenter::get_singleton()->game_center_closed(); + [gameCenterViewController dismissViewControllerAnimated:YES completion:nil]; +} + @end diff --git a/platform/nacl/os_nacl.cpp b/platform/nacl/os_nacl.cpp index ffa9915256d..b282209d722 100644 --- a/platform/nacl/os_nacl.cpp +++ b/platform/nacl/os_nacl.cpp @@ -240,10 +240,14 @@ MainLoop *OSNacl::get_main_loop() const { return main_loop; }; -OS::Date OSNacl::get_date() const { +OS::Date OSNacl::get_date(bool utc) const { time_t t=time(NULL); - struct tm *lt=localtime(&t); + struct tm *lt; + if (utc) + lt=gmtime(&t); + else + lt=localtime(&t); Date ret; ret.year=lt->tm_year; ret.month=(Month)lt->tm_mon; @@ -254,10 +258,14 @@ OS::Date OSNacl::get_date() const { return ret; }; -OS::Time OSNacl::get_time() const { +OS::Time OSNacl::get_time(bool utc) const { time_t t=time(NULL); - struct tm *lt=localtime(&t); + struct tm *lt; + if (utc) + lt=gmtime(&t); + else + lt=localtime(&t); Time ret; ret.hour=lt->tm_hour; ret.min=lt->tm_min; @@ -265,6 +273,32 @@ OS::Time OSNacl::get_time() const { return ret; }; +OS::TimeZoneInfo OS_Unix::get_time_zone_info() const { + time_t t = time(NULL); + struct tm *lt = localtime(&t); + char name[16]; + strftime(name, 16, "%Z", lt); + name[15] = 0; + TimeZoneInfo ret; + ret.name = name; + + char bias_buf[16]; + strftime(bias_buf, 16, "%z", lt); + int bias; + bias_buf[15] = 0; + sscanf(bias_buf, "%d", &bias); + + // convert from ISO 8601 (1 minute=1, 1 hour=100) to minutes + int hour = (int)bias / 100; + int minutes = bias % 100; + if (bias < 0) + ret.bias = hour * 60 - minutes; + else + ret.bias = hour * 60 + minutes; + + return ret; +}; + void OSNacl::delay_usec(uint32_t p_usec) const { //usleep(p_usec); diff --git a/platform/nacl/os_nacl.h b/platform/nacl/os_nacl.h index 1150b12edd4..e033abb68db 100644 --- a/platform/nacl/os_nacl.h +++ b/platform/nacl/os_nacl.h @@ -137,8 +137,8 @@ public: virtual MainLoop *get_main_loop() const; - virtual Date get_date() const; - virtual Time get_time() const; + virtual Date get_date(bool utc) const; + virtual Time get_time(bool utc) const; virtual void delay_usec(uint32_t p_usec) const; virtual uint64_t get_ticks_usec() const; diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 1e9a7e89e80..144037b1cbe 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -44,6 +44,7 @@ #include "drivers/rtaudio/audio_driver_rtaudio.h" #include "drivers/alsa/audio_driver_alsa.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include "platform/osx/audio_driver_osx.h" #include diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index eb2a12cdefa..e2ff8d11160 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1015,7 +1015,8 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); input = memnew( InputDefault ); diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 298fa3bc789..0fe4f9f3b56 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -201,6 +201,12 @@ def configure(env): env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED']) env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE']) + elif (env["target"]=="debug_release"): + + env.Append(CCFLAGS=['/Zi','/Od']) + env.Append(LINKFLAGS=['/DEBUG']) + env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS']) + env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup']) elif (env["target"]=="debug"): diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 13507197788..ec9e17c4f01 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1177,7 +1177,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_ physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); if (!is_no_window_mode_enabled()) { @@ -1375,6 +1375,9 @@ void OS_Windows::finalize() { physics_2d_server->finish(); memdelete(physics_2d_server); + joystick_change_queue.clear(); + monitor_info.clear(); + } void OS_Windows::finalize_core() { @@ -1826,10 +1829,14 @@ String OS_Windows::get_name() { return "Windows"; } -OS::Date OS_Windows::get_date() const { +OS::Date OS_Windows::get_date(bool utc) const { SYSTEMTIME systemtime; - GetSystemTime(&systemtime); + if (utc) + GetSystemTime(&systemtime); + else + GetLocalTime(&systemtime); + Date date; date.day=systemtime.wDay; date.month=Month(systemtime.wMonth); @@ -1838,10 +1845,13 @@ OS::Date OS_Windows::get_date() const { date.dst=false; return date; } -OS::Time OS_Windows::get_time() const { +OS::Time OS_Windows::get_time(bool utc) const { SYSTEMTIME systemtime; - GetLocalTime(&systemtime); + if (utc) + GetSystemTime(&systemtime); + else + GetLocalTime(&systemtime); Time time; time.hour=systemtime.wHour; @@ -1850,6 +1860,23 @@ OS::Time OS_Windows::get_time() const { return time; } +OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { + TIME_ZONE_INFORMATION info; + bool daylight = false; + if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) + daylight = true; + + TimeZoneInfo ret; + if (daylight) { + ret.name = info.DaylightName; + } else { + ret.name = info.StandardName; + } + + ret.bias = info.Bias; + return ret; +} + uint64_t OS_Windows::get_unix_time() const { FILETIME ft; @@ -2052,7 +2079,7 @@ String OS_Windows::get_executable_path() const { wchar_t bufname[4096]; GetModuleFileNameW(NULL,bufname,4096); String s= bufname; - print_line("EXEC PATHP¨®: "+s); + print_line("EXEC PATHP??: "+s); return s; } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 2e3700da6ae..31e030d02eb 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -45,6 +45,7 @@ #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" #include "drivers/unix/ip_unix.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include @@ -258,8 +259,9 @@ public: virtual String get_name(); - virtual Date get_date() const; - virtual Time get_time() const; + virtual Date get_date(bool utc) const; + virtual Time get_time(bool utc) const; + virtual TimeZoneInfo get_time_zone_info() const; virtual uint64_t get_unix_time() const; virtual bool can_draw() const; diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp index 21a77b89cb7..3e06d9d59b9 100644 --- a/platform/winrt/os_winrt.cpp +++ b/platform/winrt/os_winrt.cpp @@ -442,10 +442,14 @@ String OSWinrt::get_name() { return "WinRT"; } -OS::Date OSWinrt::get_date() const { +OS::Date OSWinrt::get_date(bool utc) const { SYSTEMTIME systemtime; - GetSystemTime(&systemtime); + if (utc) + GetSystemTime(&systemtime); + else + GetLocalTime(&systemtime); + Date date; date.day=systemtime.wDay; date.month=Month(systemtime.wMonth); @@ -454,10 +458,13 @@ OS::Date OSWinrt::get_date() const { date.dst=false; return date; } -OS::Time OSWinrt::get_time() const { +OS::Time OSWinrt::get_time(bool utc) const { SYSTEMTIME systemtime; - GetSystemTime(&systemtime); + if (utc) + GetSystemTime(&systemtime); + else + GetLocalTime(&systemtime); Time time; time.hour=systemtime.wHour; @@ -466,11 +473,28 @@ OS::Time OSWinrt::get_time() const { return time; } +OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { + TIME_ZONE_INFORMATION info; + bool daylight = false; + if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) + daylight = true; + + TimeZoneInfo ret; + if (daylight) { + ret.name = info.DaylightName; + } else { + ret.name = info.StandardName; + } + + ret.bias = info.Bias; + return ret; +} + uint64_t OSWinrt::get_unix_time() const { FILETIME ft; SYSTEMTIME st; - GetSystemTime(&st); + GetSystemTime(&systemtime); SystemTimeToFileTime(&st, &ft); SYSTEMTIME ep; diff --git a/platform/winrt/os_winrt.h b/platform/winrt/os_winrt.h index 68236309a97..b69feccae9a 100644 --- a/platform/winrt/os_winrt.h +++ b/platform/winrt/os_winrt.h @@ -198,8 +198,9 @@ public: virtual String get_name(); - virtual Date get_date() const; - virtual Time get_time() const; + virtual Date get_date(bool utc) const; + virtual Time get_time(bool utc) const; + virtual TimeZoneInfo get_time_zone_info() const; virtual uint64_t get_unix_time() const; virtual bool can_draw() const; diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 85714c46bb3..ff85e286db3 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -111,9 +111,9 @@ def configure(env): if (env["target"]=="release"): if (env["debug_release"]=="yes"): - env.Append(CCFLAGS=['-g2','-fomit-frame-pointer']) + env.Append(CCFLAGS=['-g2']) else: - env.Append(CCFLAGS=['-O2','-ffast-math','-fomit-frame-pointer']) + env.Append(CCFLAGS=['-O3','-ffast-math']) elif (env["target"]=="release_debug"): diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 28427fa2f03..f8c570a5c04 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -35,6 +35,7 @@ #include "print_string.h" #include "servers/physics/physics_server_sw.h" + #include "X11/Xutil.h" #include "X11/Xatom.h" @@ -426,7 +427,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); input = memnew( InputDefault ); diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 0036485f3f6..261a54dd254 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -45,6 +45,7 @@ #include "drivers/alsa/audio_driver_alsa.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include #include diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 312b04d4141..e350a34013c 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -149,11 +149,11 @@ void AnimatedSprite::_notification(int p_what) { Size2i s; s = texture->get_size(); - Point2i ofs=offset; + Point2 ofs=offset; if (centered) ofs-=s/2; - Rect2i dst_rect(ofs,s); + Rect2 dst_rect(ofs,s); if (hflip) dst_rect.size.x=-dst_rect.size.x; @@ -284,7 +284,7 @@ Rect2 AnimatedSprite::get_item_rect() const { return Node2D::get_item_rect(); Size2i s = t->get_size(); - Point2i ofs=offset; + Point2 ofs=offset; if (centered) ofs-=s/2; @@ -329,7 +329,7 @@ void AnimatedSprite::_bind_methods() { ADD_SIGNAL(MethodInfo("frame_changed")); ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); - ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered")); ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h")); diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 827256c2fa5..f9e79e25bcb 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -52,6 +52,17 @@ bool Area2D::is_gravity_a_point() const{ return gravity_is_point; } +void Area2D::set_gravity_distance_scale(real_t p_scale){ + + gravity_distance_scale=p_scale; + Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE,p_scale); + +} + +real_t Area2D::get_gravity_distance_scale() const{ + return gravity_distance_scale; +} + void Area2D::set_gravity_vector(const Vector2& p_vec){ gravity_vec=p_vec; @@ -535,6 +546,39 @@ uint32_t Area2D::get_layer_mask() const { return layer_mask; } +void Area2D::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask|=1<area_crea set_gravity(98);; set_gravity_vector(Vector2(0,1)); gravity_is_point=false; + gravity_distance_scale=0; linear_damp=0.1; angular_damp=1; locked=false; diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 0c064f54cd7..f5a88390e76 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -49,6 +49,7 @@ private: Vector2 gravity_vec; real_t gravity; bool gravity_is_point; + real_t gravity_distance_scale; real_t linear_damp; real_t angular_damp; uint32_t collision_mask; @@ -132,6 +133,9 @@ public: void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; + void set_gravity_distance_scale(real_t p_scale); + real_t get_gravity_distance_scale() const; + void set_gravity_vector(const Vector2& p_vec); Vector2 get_gravity_vector() const; @@ -159,6 +163,12 @@ public: void set_layer_mask(uint32_t p_mask); uint32_t get_layer_mask() const; + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + void set_layer_mask_bit(int p_bit, bool p_value); + bool get_layer_mask_bit(int p_bit) const; + Array get_overlapping_bodies() const; //function for script Array get_overlapping_areas() const; //function for script diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 70b88a66117..49683da2265 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -81,43 +81,47 @@ Matrix32 Camera2D::get_camera_transform() { if (!first) { - if (centered) { + if (anchor_mode==ANCHOR_MODE_DRAG_CENTER) { - if (h_drag_enabled) { - camera_pos.x = MIN( camera_pos.x, (new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT])); - camera_pos.x = MAX( camera_pos.x, (new_camera_pos.x - screen_size.x * 0.5 * drag_margin[MARGIN_LEFT])); - } else { + if (h_drag_enabled) { + camera_pos.x = MIN( camera_pos.x, (new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT])); + camera_pos.x = MAX( camera_pos.x, (new_camera_pos.x - screen_size.x * 0.5 * drag_margin[MARGIN_LEFT])); + } else { - if (h_ofs<0) { - camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT] * h_ofs; - } else { - camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_LEFT] * h_ofs; - } - } + if (h_ofs<0) { + camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT] * h_ofs; + } else { + camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_LEFT] * h_ofs; + } + } - if (v_drag_enabled) { + if (v_drag_enabled) { - camera_pos.y = MIN( camera_pos.y, (new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM])); - camera_pos.y = MAX( camera_pos.y, (new_camera_pos.y - screen_size.y * 0.5 * drag_margin[MARGIN_TOP])); + camera_pos.y = MIN( camera_pos.y, (new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM])); + camera_pos.y = MAX( camera_pos.y, (new_camera_pos.y - screen_size.y * 0.5 * drag_margin[MARGIN_TOP])); - } else { + } else { - if (v_ofs<0) { - camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_TOP] * v_ofs; - } else { - camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM] * v_ofs; - } - } + if (v_ofs<0) { + camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_TOP] * v_ofs; + } else { + camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM] * v_ofs; + } + } + } else if (anchor_mode==ANCHOR_MODE_FIXED_TOP_LEFT){ + + camera_pos=new_camera_pos; } + if (smoothing>0.0) { float c = smoothing*get_fixed_process_delta_time(); smoothed_camera_pos = ((new_camera_pos-smoothed_camera_pos)*c)+smoothed_camera_pos; ret_camera_pos=smoothed_camera_pos; -// camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing; + // camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing; } else { ret_camera_pos=smoothed_camera_pos=camera_pos; @@ -132,7 +136,7 @@ Matrix32 Camera2D::get_camera_transform() { } - Point2 screen_offset = (centered ? (screen_size * 0.5 * zoom) : Point2()); + Point2 screen_offset = (anchor_mode==ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2()); float angle = get_global_transform().get_rotation(); if(rotating){ @@ -267,15 +271,15 @@ Vector2 Camera2D::get_offset() const{ return offset; } -void Camera2D::set_centered(bool p_centered){ +void Camera2D::set_anchor_mode(AnchorMode p_anchor_mode){ - centered=p_centered; + anchor_mode=p_anchor_mode; _update_scroll(); } -bool Camera2D::is_centered() const { +Camera2D::AnchorMode Camera2D::get_anchor_mode() const { - return centered; + return anchor_mode; } void Camera2D::set_rotating(bool p_rotating){ @@ -439,8 +443,8 @@ void Camera2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_offset","offset"),&Camera2D::set_offset); ObjectTypeDB::bind_method(_MD("get_offset"),&Camera2D::get_offset); - ObjectTypeDB::bind_method(_MD("set_centered","centered"),&Camera2D::set_centered); - ObjectTypeDB::bind_method(_MD("is_centered"),&Camera2D::is_centered); + ObjectTypeDB::bind_method(_MD("set_anchor_mode","anchor_mode"),&Camera2D::set_anchor_mode); + ObjectTypeDB::bind_method(_MD("get_anchor_mode"),&Camera2D::get_anchor_mode); ObjectTypeDB::bind_method(_MD("set_rotating","rotating"),&Camera2D::set_rotating); ObjectTypeDB::bind_method(_MD("is_rotating"),&Camera2D::is_rotating); @@ -487,7 +491,7 @@ void Camera2D::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_offset"),_SCS("get_offset")); - ADD_PROPERTY( PropertyInfo(Variant::BOOL,"centered"),_SCS("set_centered"),_SCS("is_centered")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"anchor_mode",PROPERTY_HINT_ENUM,"Fixed TopLeft,Drag Center"),_SCS("set_anchor_mode"),_SCS("get_anchor_mode")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"rotating"),_SCS("set_rotating"),_SCS("is_rotating")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"current"),_SCS("_set_current"),_SCS("is_current")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"smoothing"),_SCS("set_follow_smoothing"),_SCS("get_follow_smoothing") ); @@ -507,6 +511,8 @@ void Camera2D::_bind_methods() { ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin/bottom",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_BOTTOM); + BIND_CONSTANT( ANCHOR_MODE_DRAG_CENTER ); + BIND_CONSTANT( ANCHOR_MODE_FIXED_TOP_LEFT ); } @@ -514,7 +520,7 @@ Camera2D::Camera2D() { - centered=true; + anchor_mode=ANCHOR_MODE_DRAG_CENTER; rotating=false; current=false; limit[MARGIN_LEFT]=-10000000; diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 8975a2584b8..79d84f48d0c 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -36,6 +36,12 @@ class Camera2D : public Node2D { OBJ_TYPE( Camera2D, Node2D ); +public: + + enum AnchorMode { + ANCHOR_MODE_FIXED_TOP_LEFT, + ANCHOR_MODE_DRAG_CENTER + }; protected: Point2 camera_pos; @@ -49,7 +55,7 @@ protected: RID canvas; Vector2 offset; Vector2 zoom; - bool centered; + AnchorMode anchor_mode; bool rotating; bool current; float smoothing; @@ -77,8 +83,8 @@ public: void set_offset(const Vector2& p_offset); Vector2 get_offset() const; - void set_centered(bool p_centered); - bool is_centered() const; + void set_anchor_mode(AnchorMode p_anchor_mode); + AnchorMode get_anchor_mode() const; void set_rotating(bool p_rotating); bool is_rotating() const; @@ -120,4 +126,6 @@ public: Camera2D(); }; +VARIANT_ENUM_CAST(Camera2D::AnchorMode); + #endif // CAMERA_2D_H diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp index 5a02501816e..5db0e0a9fc6 100644 --- a/scene/2d/navigation2d.cpp +++ b/scene/2d/navigation2d.cpp @@ -91,9 +91,13 @@ void Navigation2D::_navpoly_link(int p_id) { } else { if (C->get().B!=NULL) { - print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); + ConnectionPending pending; + pending.polygon=&p; + pending.edge=j; + p.edges[j].P=C->get().pending.push_back(pending); + continue; + //print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); } - ERR_CONTINUE(C->get().B!=NULL); //wut C->get().B=&p; C->get().B_edge=j; @@ -133,7 +137,12 @@ void Navigation2D::_navpoly_unlink(int p_id) { EdgeKey ek(edges[i].point,edges[next].point); Map::Element *C=connections.find(ek); ERR_CONTINUE(!C); - if (C->get().B) { + + if (edges[i].P) { + C->get().pending.erase(edges[i].P); + edges[i].P=NULL; + + } else if (C->get().B) { //disconnect C->get().B->edges[C->get().B_edge].C=NULL; @@ -149,6 +158,20 @@ void Navigation2D::_navpoly_unlink(int p_id) { C->get().B=NULL; C->get().B_edge=-1; + if (C->get().pending.size()) { + //reconnect if something is pending + ConnectionPending cp = C->get().pending.front()->get(); + C->get().pending.pop_front(); + + C->get().B=cp.polygon; + C->get().B_edge=cp.edge; + C->get().A->edges[C->get().A_edge].C=cp.polygon; + C->get().A->edges[C->get().A_edge].C_edge=cp.edge; + cp.polygon->edges[cp.edge].C=C->get().A; + cp.polygon->edges[cp.edge].C_edge=C->get().A_edge; + cp.polygon->edges[cp.edge].P=NULL; + } + } else { connections.erase(C); //erase diff --git a/scene/2d/navigation2d.h b/scene/2d/navigation2d.h index 829b0f544b8..231f1e8c638 100644 --- a/scene/2d/navigation2d.h +++ b/scene/2d/navigation2d.h @@ -41,7 +41,13 @@ class Navigation2D : public Node2D { struct NavMesh; + struct Polygon; + struct ConnectionPending { + + Polygon *polygon; + int edge; + }; struct Polygon { @@ -49,7 +55,8 @@ class Navigation2D : public Node2D { Point point; Polygon *C; //connection int C_edge; - Edge() { C=NULL; C_edge=-1; } + List::Element *P; + Edge() { C=NULL; C_edge=-1; P=NULL; } }; Vector edges; @@ -72,6 +79,9 @@ class Navigation2D : public Node2D { int A_edge; Polygon *B; int B_edge; + + List pending; + Connection() { A=NULL; B=NULL; A_edge=-1; B_edge=-1;} }; diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index 39d747c436c..f0b7c2be600 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -503,19 +503,6 @@ void Particles2D::_notification(int p_what) { if (!local_space) invxform=get_global_transform().affine_inverse(); - int col_count=0; - float last=-1; - ColorPhase cphase[MAX_COLOR_PHASES]; - - for(int i=0;i ptime) - break; - cpos++; - } - - cpos--; - Color color; - //could be faster.. - if (cpos==-1) - color=Color(1,1,1,1); - else { - if (cpos==col_count-1) - color=cphase[cpos].color; - else { - float diff = (cphase[cpos+1].pos-cphase[cpos].pos); - if (diff>0) - color=cphase[cpos].color.linear_interpolate(cphase[cpos+1].color, (ptime - cphase[cpos].pos) / diff ); - else - color=cphase[cpos+1].color; - } + + if(color_ramp.is_valid()) + { + color = color_ramp->get_color_at_offset(ptime); + } else + { + color = default_color; } @@ -813,6 +782,27 @@ Ref Particles2D::get_texture() const { return texture; } +void Particles2D::set_color(const Color& p_color) { + + default_color = p_color; +} + +Color Particles2D::get_color() const { + + return default_color; +} + + +void Particles2D::set_color_ramp(const Ref& p_color_ramp) { + + color_ramp=p_color_ramp; +} + +Ref Particles2D::get_color_ramp() const { + + return color_ramp; +} + void Particles2D::set_emissor_offset(const Point2& p_offset) { emissor_offset=p_offset; @@ -834,40 +824,76 @@ bool Particles2D::is_using_local_space() const { return local_space; } - +//Deprecated. Converts color phases to color ramp void Particles2D::set_color_phases(int p_phases) { - ERR_FAIL_INDEX(p_phases,MAX_COLOR_PHASES+1); - color_phase_count=p_phases; + //Create color ramp if we have 2 or more phases. + //Otherwise first phase phase will be assigned to default color. + if(p_phases > 1 && color_ramp.is_null()) + { + color_ramp = Ref(memnew (ColorRamp())); + } + if(color_ramp.is_valid()) + { + color_ramp->get_points().resize(p_phases); + } } +//Deprecated. int Particles2D::get_color_phases() const { - return color_phase_count; + if(color_ramp.is_valid()) + { + return color_ramp->get_points_count(); + } + return 0; } +//Deprecated. Converts color phases to color ramp void Particles2D::set_color_phase_color(int p_phase,const Color& p_color) { ERR_FAIL_INDEX(p_phase,MAX_COLOR_PHASES); - color_phases[p_phase].color=p_color; - + if(color_ramp.is_valid()) + { + if(color_ramp->get_points_count() > p_phase) + color_ramp->set_color(p_phase, p_color); + } else + { + if(p_phase == 0) + default_color = p_color; + } } + +//Deprecated. Color Particles2D::get_color_phase_color(int p_phase) const { ERR_FAIL_INDEX_V(p_phase,MAX_COLOR_PHASES,Color()); - return color_phases[p_phase].color; + if(color_ramp.is_valid()) + { + return color_ramp->get_color(p_phase); + } + return Color(0,0,0,1); } +//Deprecated. Converts color phases to color ramp void Particles2D::set_color_phase_pos(int p_phase,float p_pos) { ERR_FAIL_INDEX(p_phase,MAX_COLOR_PHASES); ERR_FAIL_COND(p_pos<0.0 || p_pos>1.0); - color_phases[p_phase].pos=p_pos; - + if(color_ramp.is_valid() && color_ramp->get_points_count() > p_phase) + { + return color_ramp->set_offset(p_phase, p_pos); + } } + +//Deprecated. float Particles2D::get_color_phase_pos(int p_phase) const { ERR_FAIL_INDEX_V(p_phase,MAX_COLOR_PHASES,0); - return color_phases[p_phase].pos; + if(color_ramp.is_valid()) + { + return color_ramp->get_offset(p_phase); + } + return 0; } void Particles2D::set_emission_half_extents(const Vector2& p_extents) { @@ -997,6 +1023,12 @@ void Particles2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_texture:Texture","texture"),&Particles2D::set_texture); ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&Particles2D::get_texture); + ObjectTypeDB::bind_method(_MD("set_color","color"),&Particles2D::set_color); + ObjectTypeDB::bind_method(_MD("get_color"),&Particles2D::get_color); + + ObjectTypeDB::bind_method(_MD("set_color_ramp:ColorRamp","color_ramp"),&Particles2D::set_color_ramp); + ObjectTypeDB::bind_method(_MD("get_color_ramp:ColorRamp"),&Particles2D::get_color_ramp); + ObjectTypeDB::bind_method(_MD("set_emissor_offset","offset"),&Particles2D::set_emissor_offset); ObjectTypeDB::bind_method(_MD("get_emissor_offset"),&Particles2D::get_emissor_offset); @@ -1055,7 +1087,6 @@ void Particles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_v_frames"),_SCS("get_v_frames")); - for(int i=0;i particles; - int color_phase_count; - struct ColorPhase { - Color color; - float pos; - } color_phases[MAX_COLOR_PHASES]; struct AttractorCache { @@ -161,6 +157,9 @@ private: Ref texture; + //If no color ramp is set then default color is used. Created as simple alternative to color_ramp. + Color default_color; + Ref color_ramp; void testee(int a, int b, int c, int d, int e); void _process_particles(float p_delta); @@ -230,6 +229,12 @@ public: void set_texture(const Ref& p_texture); Ref get_texture() const; + void set_color(const Color& p_color); + Color get_color() const; + + void set_color_ramp(const Ref& p_texture); + Ref get_color_ramp() const; + void set_emissor_offset(const Point2& p_offset); Point2 get_emissor_offset() const; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 3d2917d8439..c30921eb69e 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -85,6 +85,14 @@ void PhysicsBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody2D::get_layer_mask); ObjectTypeDB::bind_method(_MD("set_collision_mask","mask"),&PhysicsBody2D::set_collision_mask); ObjectTypeDB::bind_method(_MD("get_collision_mask"),&PhysicsBody2D::get_collision_mask); + + + ObjectTypeDB::bind_method(_MD("set_collision_mask_bit","bit","value"),&PhysicsBody2D::set_collision_mask_bit); + ObjectTypeDB::bind_method(_MD("get_collision_mask_bit","bit"),&PhysicsBody2D::get_collision_mask_bit); + + ObjectTypeDB::bind_method(_MD("set_layer_mask_bit","bit","value"),&PhysicsBody2D::set_layer_mask_bit); + ObjectTypeDB::bind_method(_MD("get_layer_mask_bit","bit"),&PhysicsBody2D::get_layer_mask_bit); + ObjectTypeDB::bind_method(_MD("_set_layers","mask"),&PhysicsBody2D::_set_layers); ObjectTypeDB::bind_method(_MD("_get_layers"),&PhysicsBody2D::_get_layers); ObjectTypeDB::bind_method(_MD("set_one_way_collision_direction","dir"),&PhysicsBody2D::set_one_way_collision_direction); @@ -122,6 +130,37 @@ uint32_t PhysicsBody2D::get_collision_mask() const { return collision_mask; } +void PhysicsBody2D::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask|=1<body_create(p_mode), false) { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 03f95959b67..b70fdd59cf3 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -61,6 +61,13 @@ public: void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + void set_layer_mask_bit(int p_bit, bool p_value); + bool get_layer_mask_bit(int p_bit) const; + void add_collision_exception_with(Node* p_node); //must be physicsbody void remove_collision_exception_with(Node* p_node); diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 0c0a0d78229..0485033691c 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -82,7 +82,7 @@ void Sprite::_notification(int p_what) { } - Point2i ofs=offset; + Point2 ofs=offset; if (centered) ofs-=s/2; @@ -265,7 +265,7 @@ Rect2 Sprite::get_item_rect() const { s=s/Point2(hframes,vframes); } - Point2i ofs=offset; + Point2 ofs=offset; if (centered) ofs-=s/2; @@ -320,7 +320,7 @@ void Sprite::_bind_methods() { ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v")); ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); @@ -413,11 +413,11 @@ void ViewportSprite::_notification(int p_what) { src_rect.size=s; - Point2i ofs=offset; + Point2 ofs=offset; if (centered) ofs-=s/2; - Rect2i dst_rect(ofs,s); + Rect2 dst_rect(ofs,s); texture->draw_rect_region(ci,dst_rect,src_rect,modulate); } break; @@ -505,7 +505,7 @@ Rect2 ViewportSprite::get_item_rect() const { Size2i s; s = texture->get_size(); - Point2i ofs=offset; + Point2 ofs=offset; if (centered) ofs-=s/2; diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index d49ffff729b..a00946a07a5 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -52,6 +52,17 @@ bool Area::is_gravity_a_point() const{ return gravity_is_point; } +void Area::set_gravity_distance_scale(real_t p_scale){ + + gravity_distance_scale=p_scale; + PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE,p_scale); + +} + +real_t Area::get_gravity_distance_scale() const{ + return gravity_distance_scale; +} + void Area::set_gravity_vector(const Vector3& p_vec){ gravity_vec=p_vec; @@ -214,27 +225,56 @@ void Area::_clear_monitoring() { } ERR_FAIL_COND(locked); - Map bmcopy = body_map; - body_map.clear(); - //disconnect all monitored stuff + { + Map bmcopy = body_map; + body_map.clear(); + //disconnect all monitored stuff - for (Map::Element *E=bmcopy.front();E;E=E->next()) { + for (Map::Element *E=bmcopy.front();E;E=E->next()) { - Object *obj = ObjectDB::get_instance(E->key()); - Node *node = obj ? obj->cast_to() : NULL; - ERR_CONTINUE(!node); - if (!E->get().in_tree) - continue; + Object *obj = ObjectDB::get_instance(E->key()); + Node *node = obj ? obj->cast_to() : NULL; + ERR_CONTINUE(!node); + if (!E->get().in_tree) + continue; - for(int i=0;iget().shapes.size();i++) { + for(int i=0;iget().shapes.size();i++) { - emit_signal(SceneStringNames::get_singleton()->body_exit_shape,E->key(),node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape); + emit_signal(SceneStringNames::get_singleton()->body_exit_shape,E->key(),node,E->get().shapes[i].body_shape,E->get().shapes[i].area_shape); + } + + emit_signal(SceneStringNames::get_singleton()->body_exit,obj); + + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree); } - emit_signal(SceneStringNames::get_singleton()->body_exit,obj); + } - node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_body_enter_tree); - node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree); + { + + Map bmcopy = area_map; + area_map.clear(); + //disconnect all monitored stuff + + for (Map::Element *E=bmcopy.front();E;E=E->next()) { + + Object *obj = ObjectDB::get_instance(E->key()); + Node *node = obj ? obj->cast_to() : NULL; + ERR_CONTINUE(!node); + if (!E->get().in_tree) + continue; + + for(int i=0;iget().shapes.size();i++) { + + emit_signal(SceneStringNames::get_singleton()->area_exit_shape,E->key(),node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape); + } + + emit_signal(SceneStringNames::get_singleton()->area_exit,obj); + + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree); + } } } @@ -260,12 +300,129 @@ void Area::set_enable_monitoring(bool p_enable) { if (monitoring) { PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),this,"_body_inout"); + PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(),this,"_area_inout"); } else { PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),NULL,StringName()); + PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(),NULL,StringName()); _clear_monitoring(); + } } + +void Area::_area_enter_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = obj ? obj->cast_to() : NULL; + ERR_FAIL_COND(!node); + + Map::Element *E=area_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(E->get().in_tree); + + E->get().in_tree=true; + emit_signal(SceneStringNames::get_singleton()->area_enter,node); + for(int i=0;iget().shapes.size();i++) { + + emit_signal(SceneStringNames::get_singleton()->area_enter_shape,p_id,node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape); + } + +} + +void Area::_area_exit_tree(ObjectID p_id) { + + Object *obj = ObjectDB::get_instance(p_id); + Node *node = obj ? obj->cast_to() : NULL; + ERR_FAIL_COND(!node); + Map::Element *E=area_map.find(p_id); + ERR_FAIL_COND(!E); + ERR_FAIL_COND(!E->get().in_tree); + E->get().in_tree=false; + emit_signal(SceneStringNames::get_singleton()->area_exit,node); + for(int i=0;iget().shapes.size();i++) { + + emit_signal(SceneStringNames::get_singleton()->area_exit_shape,p_id,node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape); + } + +} + +void Area::_area_inout(int p_status,const RID& p_area, int p_instance, int p_area_shape,int p_self_shape) { + + + bool area_in = p_status==PhysicsServer::AREA_BODY_ADDED; + ObjectID objid=p_instance; + + Object *obj = ObjectDB::get_instance(objid); + Node *node = obj ? obj->cast_to() : NULL; + + Map::Element *E=area_map.find(objid); + + ERR_FAIL_COND(!area_in && !E); + + locked=true; + + if (area_in) { + if (!E) { + + E = area_map.insert(objid,AreaState()); + E->get().rc=0; + E->get().in_tree=node && node->is_inside_tree(); + if (node) { + node->connect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree,make_binds(objid)); + node->connect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree,make_binds(objid)); + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_enter,node); + + } + } + + } + E->get().rc++; + if (node) + E->get().shapes.insert(AreaShapePair(p_area_shape,p_self_shape)); + + + if (!node || E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_enter_shape,objid,node,p_area_shape,p_self_shape); + } + + } else { + + E->get().rc--; + + if (node) + E->get().shapes.erase(AreaShapePair(p_area_shape,p_self_shape)); + + bool eraseit=false; + + if (E->get().rc==0) { + + if (node) { + node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree); + node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree); + if (E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_exit,obj); + } + + } + + eraseit=true; + + } + if (!node || E->get().in_tree) { + emit_signal(SceneStringNames::get_singleton()->area_exit_shape,objid,obj,p_area_shape,p_self_shape); + } + + if (eraseit) + area_map.erase(E); + + } + + locked=false; + + +} + bool Area::is_monitoring_enabled() const { return monitoring; @@ -291,17 +448,85 @@ Array Area::get_overlapping_bodies() const { return ret; } +void Area::set_monitorable(bool p_enable) { + + if (locked) { + ERR_EXPLAIN("This function can't be used during the in/out signal."); + } + ERR_FAIL_COND(locked); + + if (p_enable==monitorable) + return; + + monitorable=p_enable; + + PhysicsServer::get_singleton()->area_set_monitorable(get_rid(),monitorable); +} + +bool Area::is_monitorable() const { + + return monitorable; +} + + +Array Area::get_overlapping_areas() const { + + ERR_FAIL_COND_V(!monitoring,Array()); + Array ret; + ret.resize(area_map.size()); + int idx=0; + for (const Map::Element *E=area_map.front();E;E=E->next()) { + Object *obj = ObjectDB::get_instance(E->key()); + if (!obj) { + ret.resize( ret.size() -1 ); //ops + } else { + ret[idx++]=obj; + } + + } + + return ret; +} + +bool Area::overlaps_area(Node* p_area) const { + + ERR_FAIL_NULL_V(p_area,false); + const Map::Element *E=area_map.find(p_area->get_instance_ID()); + if (!E) + return false; + return E->get().in_tree; + + + +} + +bool Area::overlaps_body(Node* p_body) const{ + + ERR_FAIL_NULL_V(p_body,false); + const Map::Element *E=body_map.find(p_body->get_instance_ID()); + if (!E) + return false; + return E->get().in_tree; + +} + void Area::_bind_methods() { ObjectTypeDB::bind_method(_MD("_body_enter_tree","id"),&Area::_body_enter_tree); ObjectTypeDB::bind_method(_MD("_body_exit_tree","id"),&Area::_body_exit_tree); + ObjectTypeDB::bind_method(_MD("_area_enter_tree","id"),&Area::_area_enter_tree); + ObjectTypeDB::bind_method(_MD("_area_exit_tree","id"),&Area::_area_exit_tree); + ObjectTypeDB::bind_method(_MD("set_space_override_mode","enable"),&Area::set_space_override_mode); ObjectTypeDB::bind_method(_MD("get_space_override_mode"),&Area::get_space_override_mode); ObjectTypeDB::bind_method(_MD("set_gravity_is_point","enable"),&Area::set_gravity_is_point); ObjectTypeDB::bind_method(_MD("is_gravity_a_point"),&Area::is_gravity_a_point); + ObjectTypeDB::bind_method(_MD("set_gravity_distance_scale","distance_scale"),&Area::set_gravity_distance_scale); + ObjectTypeDB::bind_method(_MD("get_gravity_distance_scale"),&Area::get_gravity_distance_scale); + ObjectTypeDB::bind_method(_MD("set_gravity_vector","vector"),&Area::set_gravity_vector); ObjectTypeDB::bind_method(_MD("get_gravity_vector"),&Area::get_gravity_vector); @@ -314,13 +539,21 @@ void Area::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority); ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority); + ObjectTypeDB::bind_method(_MD("set_monitorable","enable"),&Area::set_monitorable); + ObjectTypeDB::bind_method(_MD("is_monitorable"),&Area::is_monitorable); + ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area::set_enable_monitoring); ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled); ObjectTypeDB::bind_method(_MD("get_overlapping_bodies"),&Area::get_overlapping_bodies); + ObjectTypeDB::bind_method(_MD("get_overlapping_areas"),&Area::get_overlapping_areas); + + ObjectTypeDB::bind_method(_MD("overlaps_body:PhysicsBody","body"),&Area::overlaps_body); + ObjectTypeDB::bind_method(_MD("overlaps_area:Area","area"),&Area::overlaps_area); ObjectTypeDB::bind_method(_MD("_body_inout"),&Area::_body_inout); + ObjectTypeDB::bind_method(_MD("_area_inout"),&Area::_area_inout); ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape"))); @@ -328,13 +561,20 @@ void Area::_bind_methods() { ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body"))); ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body"))); + ADD_SIGNAL( MethodInfo("area_enter_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape"))); + ADD_SIGNAL( MethodInfo("area_exit_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape"))); + ADD_SIGNAL( MethodInfo("area_enter",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"))); + ADD_SIGNAL( MethodInfo("area_exit",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"))); + ADD_PROPERTY( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density")); ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable")); } @@ -345,11 +585,13 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru locked=false; set_gravity_vector(Vector3(0,-1,0)); gravity_is_point=false; + gravity_distance_scale=0; density=0.1; priority=0; monitoring=false; set_ray_pickable(false); set_enable_monitoring(true); + set_monitorable(true); } diff --git a/scene/3d/area.h b/scene/3d/area.h index 493c71c5955..fa7500c47c8 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -49,9 +49,11 @@ private: Vector3 gravity_vec; real_t gravity; bool gravity_is_point; + real_t gravity_distance_scale; real_t density; int priority; bool monitoring; + bool monitorable; bool locked; @@ -83,6 +85,36 @@ private: }; Map body_map; + + + void _area_inout(int p_status,const RID& p_area, int p_instance, int p_area_shape,int p_self_shape); + + void _area_enter_tree(ObjectID p_id); + void _area_exit_tree(ObjectID p_id); + + struct AreaShapePair { + + int area_shape; + int self_shape; + bool operator<(const AreaShapePair& p_sp) const { + if (area_shape==p_sp.area_shape) + return self_shape < p_sp.self_shape; + else + return area_shape < p_sp.area_shape; + } + + AreaShapePair() {} + AreaShapePair(int p_bs, int p_as) { area_shape=p_bs; self_shape=p_as; } + }; + + struct AreaState { + + int rc; + bool in_tree; + VSet shapes; + }; + + Map area_map; void _clear_monitoring(); @@ -98,6 +130,9 @@ public: void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; + void set_gravity_distance_scale(real_t p_scale); + real_t get_gravity_distance_scale() const; + void set_gravity_vector(const Vector3& p_vec); Vector3 get_gravity_vector() const; @@ -113,7 +148,14 @@ public: void set_enable_monitoring(bool p_enable); bool is_monitoring_enabled() const; + void set_monitorable(bool p_enable); + bool is_monitorable() const; + Array get_overlapping_bodies() const; + Array get_overlapping_areas() const; //function for script + + bool overlaps_area(Node* p_area) const; + bool overlaps_body(Node* p_body) const; Area(); diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index 48820706dd2..bfa8add09ca 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -85,9 +85,14 @@ void Navigation::_navmesh_link(int p_id) { } else { if (C->get().B!=NULL) { - print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); + ConnectionPending pending; + pending.polygon=&p; + pending.edge=j; + p.edges[j].P=C->get().pending.push_back(pending); + continue; + //print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); } - ERR_CONTINUE(C->get().B!=NULL); //wut + //ERR_CONTINUE(C->get().B!=NULL); //wut C->get().B=&p; C->get().B_edge=j; @@ -126,8 +131,13 @@ void Navigation::_navmesh_unlink(int p_id) { EdgeKey ek(edges[i].point,edges[next].point); Map::Element *C=connections.find(ek); + ERR_CONTINUE(!C); - if (C->get().B) { + + if (edges[i].P) { + C->get().pending.erase(edges[i].P); + edges[i].P=NULL; + } else if (C->get().B) { //disconnect C->get().B->edges[C->get().B_edge].C=NULL; @@ -143,6 +153,20 @@ void Navigation::_navmesh_unlink(int p_id) { C->get().B=NULL; C->get().B_edge=-1; + if (C->get().pending.size()) { + //reconnect if something is pending + ConnectionPending cp = C->get().pending.front()->get(); + C->get().pending.pop_front(); + + C->get().B=cp.polygon; + C->get().B_edge=cp.edge; + C->get().A->edges[C->get().A_edge].C=cp.polygon; + C->get().A->edges[C->get().A_edge].C_edge=cp.edge; + cp.polygon->edges[cp.edge].C=C->get().A; + cp.polygon->edges[cp.edge].C_edge=C->get().A_edge; + cp.polygon->edges[cp.edge].P=NULL; + } + } else { connections.erase(C); //erase diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index 0f7f67571f1..f8434aaf724 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -42,6 +42,13 @@ class Navigation : public Spatial { struct NavMesh; + struct Polygon; + + struct ConnectionPending { + + Polygon *polygon; + int edge; + }; struct Polygon { @@ -50,7 +57,8 @@ class Navigation : public Spatial { Point point; Polygon *C; //connection int C_edge; - Edge() { C=NULL; C_edge=-1; } + List::Element *P; + Edge() { C=NULL; C_edge=-1; P=NULL; } }; Vector edges; @@ -72,6 +80,9 @@ class Navigation : public Spatial { int A_edge; Polygon *B; int B_edge; + + List pending; + Connection() { A=NULL; B=NULL; A_edge=-1; B_edge=-1;} }; diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 9c69520a85b..c672d0e94f2 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -626,10 +626,11 @@ void Spatial::rotate_z(float p_radians){ void Spatial::translate(const Vector3& p_offset){ Transform t =get_transform(); - t.origin+=p_offset; + t.translate(p_offset); set_transform(t); } + void Spatial::scale(const Vector3& p_ratio){ Transform t =get_transform(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 4952f742df6..e9da95f3fb6 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -580,7 +580,7 @@ void Sprite3D::_bind_methods() { ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture")); ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); @@ -727,7 +727,7 @@ void AnimatedSprite3D::_bind_methods(){ ObjectTypeDB::bind_method(_MD("get_frame"),&AnimatedSprite3D::get_frame); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_SIGNAL(MethodInfo("frame_changed")); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 4949b33c475..74ae2c0d559 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -223,7 +223,7 @@ void AnimationPlayer::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { - stop_all(); + //stop_all(); clear_caches(); } break; } @@ -967,14 +967,16 @@ String AnimationPlayer::get_current_animation() const { } -void AnimationPlayer::stop() { +void AnimationPlayer::stop(bool p_reset) { Playback &c=playback; c.blend.clear(); - c.current.from=NULL; + if (p_reset) { + c.current.from=NULL; + } _set_process(false); queued.clear(); - playing = false; + playing = false; } void AnimationPlayer::stop_all() { @@ -1211,7 +1213,7 @@ void AnimationPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_default_blend_time"),&AnimationPlayer::get_default_blend_time); ObjectTypeDB::bind_method(_MD("play","name","custom_blend","custom_speed","from_end"),&AnimationPlayer::play,DEFVAL(""),DEFVAL(-1),DEFVAL(1.0),DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("stop"),&AnimationPlayer::stop); + ObjectTypeDB::bind_method(_MD("stop","reset"),&AnimationPlayer::stop,DEFVAL(true)); ObjectTypeDB::bind_method(_MD("stop_all"),&AnimationPlayer::stop_all); ObjectTypeDB::bind_method(_MD("is_playing"),&AnimationPlayer::is_playing); ObjectTypeDB::bind_method(_MD("set_current_animation","anim"),&AnimationPlayer::set_current_animation); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 8d7d6d04e06..3fddc283ae0 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -260,7 +260,7 @@ public: void play(const StringName& p_name=StringName(),float p_custom_blend=-1,float p_custom_scale=1.0,bool p_from_end=false); void queue(const StringName& p_name); void clear_queue(); - void stop(); + void stop(bool p_reset=true); bool is_playing() const; String get_current_animation() const; void set_current_animation(const String& p_anim); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index dff23777666..8b6f433c9c2 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -148,6 +148,7 @@ void BaseButton::_input_event(InputEvent p_event) { update(); } } break; + case InputEvent::ACTION: case InputEvent::JOYSTICK_BUTTON: case InputEvent::KEY: { diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 5b837d699c5..b465db5c80a 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -97,6 +97,13 @@ void Button::_notification(int p_what) { } break; } + + if (has_focus()) { + + Ref style = get_stylebox("focus"); + style->draw(ci,Rect2(Point2(),size)); + } + Ref style = get_stylebox("normal" ); Ref font=get_font("font"); Ref _icon; @@ -134,11 +141,7 @@ void Button::_notification(int p_what) { _icon->draw(ci,Point2(style->get_offset().x, Math::floor( (size.height-_icon->get_height())/2.0 ) ),is_disabled()?Color(1,1,1,0.4):Color(1,1,1) ); } - if (has_focus()) { - Ref style = get_stylebox("focus"); - style->draw(ci,Rect2(Point2(),size)); - } } } diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/color_ramp_edit.cpp new file mode 100644 index 00000000000..382c0dc1031 --- /dev/null +++ b/scene/gui/color_ramp_edit.cpp @@ -0,0 +1,368 @@ +#include "color_ramp_edit.h" +#include "os/keyboard.h" + +ColorRampEdit::ColorRampEdit(){ + grabbed=-1; + grabbing=false; + set_focus_mode(FOCUS_ALL); + + popup = memnew( PopupPanel ); + picker = memnew( ColorPicker ); + popup->add_child(picker); + popup->set_child_rect(picker); + add_child(popup); + + checker = Ref(memnew( ImageTexture )); + checker->create_from_image( Image(checker_bg_png),ImageTexture::FLAG_REPEAT ); +} + +int ColorRampEdit::_get_point_from_pos(int x) { + int result = -1; + int total_w = get_size().width-get_size().height-3; + for(int i=0;iget_combined_minimum_size().height+10); + picker->set_color(points[grabbed].color); + popup->set_pos(get_global_pos()-Vector2(ms.width-get_size().width,ms.height)); + popup->set_size(ms); + popup->popup(); +} + +ColorRampEdit::~ColorRampEdit() { + +} + +void ColorRampEdit::_input_event(const InputEvent& p_event) { + + if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) { + + points.remove(grabbed); + grabbed=-1; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + + //Show color picker on double click. + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.doubleclick && p_event.mouse_button.pressed) { + grabbed=_get_point_from_pos(p_event.mouse_button.x); + _show_color_picker(); + accept_event(); + } + + //Delete point on right click + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==2 && p_event.mouse_button.pressed) { + grabbed=_get_point_from_pos(p_event.mouse_button.x); + if(grabbed != -1) + { + points.remove(grabbed); + grabbed=-1; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + + update(); + int x = p_event.mouse_button.x; + int total_w = get_size().width-get_size().height-3; + + //Check if color selector was clicked. + if (x>total_w+3) { + _show_color_picker(); + return; + } + + grabbing=true; + + grabbed=_get_point_from_pos(x); + //grab or select + if (grabbed!=-1) { + return; + } + + //insert + ColorRamp::Point newPoint; + newPoint.offset=CLAMP(x/float(total_w),0,1); + + ColorRamp::Point prev; + ColorRamp::Point next; + + int pos=-1; + for(int i=0;iconnect("color_changed",this,"_color_changed"); + } + if (p_what==NOTIFICATION_DRAW) { + + int w = get_size().x; + int h = get_size().y; + + if (w == 0 || h == 0) + return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size + + int total_w = get_size().width-get_size().height-3; + + //Draw checker pattern for ramp + _draw_checker(0,0, total_w, h); + + //Draw color ramp + ColorRamp::Point prev; + prev.offset=0; + if(points.size() == 0) + prev.color=Color(0,0,0); //Draw black rectangle if we have no points + else + prev.color = points[0].color; //Extend color of first point to the beginning. + + for(int i=-1;i points; + Vector colors; + points.push_back(Vector2(prev.offset*total_w,h)); + points.push_back(Vector2(prev.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,h)); + colors.push_back(prev.color); + colors.push_back(prev.color); + colors.push_back(next.color); + colors.push_back(next.color); + draw_primitive(points,colors,Vector()); + prev=next; + } + + //Draw point markers + for(int i=0;i backPoints; + backPoints.push_back(Vector2(x, y)); + backPoints.push_back(Vector2(x, y+h)); + backPoints.push_back(Vector2(x+w, y+h)); + backPoints.push_back(Vector2(x+w, y)); + Vector colorPoints; + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + Vector uvPoints; + //Draw checker pattern pixel-perfect and scale it by 2. + uvPoints.push_back(Vector2(x, y)); + uvPoints.push_back(Vector2(x, y+h*.5f/checker->get_height())); + uvPoints.push_back(Vector2(x+w*.5f/checker->get_width(), y+h*.5f/checker->get_height())); + uvPoints.push_back(Vector2(x+w*.5f/checker->get_width(), y)); + draw_polygon(backPoints, colorPoints, uvPoints, checker); +} + +Size2 ColorRampEdit::get_minimum_size() const { + + return Vector2(0,16); +} + +void ColorRampEdit::_color_changed(const Color& p_color) { + + if (grabbed==-1) + return; + points[grabbed].color=p_color; + update(); + emit_signal("ramp_changed"); + +} + +void ColorRampEdit::set_ramp(const Vector& p_offsets,const Vector& p_colors) { + + ERR_FAIL_COND(p_offsets.size()!=p_colors.size()); + points.clear(); + for(int i=0;i ColorRampEdit::get_offsets() const { + Vector ret; + for(int i=0;i ColorRampEdit::get_colors() const { + Vector ret; + for(int i=0;i& p_points) { + if(points.size() != p_points.size()) + grabbed = -1; + points.clear(); + points = p_points; +} + +Vector& ColorRampEdit::get_points() { + return points; +} + +void ColorRampEdit::_bind_methods() { + ObjectTypeDB::bind_method(_MD("_input_event"),&ColorRampEdit::_input_event); + ObjectTypeDB::bind_method(_MD("_color_changed"),&ColorRampEdit::_color_changed); + ADD_SIGNAL(MethodInfo("ramp_changed")); +} diff --git a/scene/gui/color_ramp_edit.h b/scene/gui/color_ramp_edit.h new file mode 100644 index 00000000000..91292eed0db --- /dev/null +++ b/scene/gui/color_ramp_edit.h @@ -0,0 +1,52 @@ +#ifndef SCENE_GUI_COLOR_RAMP_EDIT_H_ +#define SCENE_GUI_COLOR_RAMP_EDIT_H_ + +#include "scene/gui/popup.h" +#include "scene/gui/color_picker.h" +#include "scene/resources/color_ramp.h" +#include "scene/resources/default_theme/theme_data.h" + +#define POINT_WIDTH 8 + +class ColorRampEdit : public Control { + + OBJ_TYPE(ColorRampEdit,Control); + + PopupPanel *popup; + ColorPicker *picker; + + Ref checker; + + bool grabbing; + int grabbed; + Vector points; + + void _draw_checker(int x, int y, int w, int h); + void _color_changed(const Color& p_color); + int _get_point_from_pos(int x); + void _show_color_picker(); + +protected: + void _input_event(const InputEvent& p_event); + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_ramp(const Vector& p_offsets,const Vector& p_colors); + Vector get_offsets() const; + Vector get_colors() const; + void set_points(Vector& p_points); + Vector& get_points(); + virtual Size2 get_minimum_size() const; + + ColorRampEdit(); + virtual ~ColorRampEdit(); +}; + +/*class ColorRampEditPanel : public Panel +{ + OBJ_TYPE(ColorRampEditPanel, Panel ); +};*/ + + +#endif /* SCENE_GUI_COLOR_RAMP_EDIT_H_ */ diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 22559c238c7..2367c03e994 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -548,15 +548,18 @@ void Control::_notification(int p_notification) { Control * parent = get_parent()->cast_to(); //make children reference them theme - if (parent && data.theme.is_null() && parent->data.theme_owner) + + if (parent && data.theme.is_null() && parent->data.theme_owner) { _propagate_theme_changed(parent->data.theme_owner); + } } break; case NOTIFICATION_UNPARENTED: { //make children unreference the theme - if (data.theme.is_null() && data.theme_owner) + if (data.theme.is_null() && data.theme_owner) { _propagate_theme_changed(NULL); + } } break; case NOTIFICATION_MOVED_IN_PARENT: { diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index 214d874675f..105f66f3681 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -40,7 +40,8 @@ void GridContainer::_notification(int p_what) { Set col_expanded; Set row_expanded; - int sep=get_constant("separation"); + int hsep=get_constant("hseparation"); + int vsep=get_constant("vseparation"); int idx=0; int max_row=0; @@ -97,8 +98,8 @@ void GridContainer::_notification(int p_what) { expand_rows++; } - ms.height+=sep*max_row; - ms.width+=sep*max_col; + ms.height+=vsep*max_row; + ms.width+=hsep*max_col; int row_expand = expand_rows?(size.y-ms.y)/expand_rows:0; int col_expand = expand_cols?(size.x-ms.x)/expand_cols:0; @@ -119,7 +120,7 @@ void GridContainer::_notification(int p_what) { if (col==0) { col_ofs=0; if (row>0 && row_minh.has(row-1)) - row_ofs+=row_minh[row-1]+sep+(row_expanded.has(row-1)?row_expand:0); + row_ofs+=row_minh[row-1]+vsep+(row_expanded.has(row-1)?row_expand:0); } Size2 s; @@ -140,7 +141,7 @@ void GridContainer::_notification(int p_what) { //print_line("col: "+itos(col)+" row: "+itos(row)+" rect: "+Rect2(p,s)); if (col_minw.has(col)) { - col_ofs+=col_minw[col]+sep+(col_expanded.has(col)?col_expand:0); + col_ofs+=col_minw[col]+hsep+(col_expanded.has(col)?col_expand:0); } idx++; @@ -178,7 +179,8 @@ Size2 GridContainer::get_minimum_size() const { Map col_minw; Map row_minh; - int sep=get_constant("separation"); + int hsep=get_constant("hseparation"); + int vsep=get_constant("vseparation"); int idx=0; int max_row=0; @@ -216,8 +218,8 @@ Size2 GridContainer::get_minimum_size() const { ms.height+=E->get(); } - ms.height+=sep*max_row; - ms.width+=sep*max_col; + ms.height+=vsep*max_row; + ms.width+=hsep*max_col; return ms; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp new file mode 100644 index 00000000000..2fd4d810de0 --- /dev/null +++ b/scene/gui/item_list.cpp @@ -0,0 +1,1048 @@ +#include "item_list.h" +#include "os/os.h" +#include "globals.h" + + +void ItemList::add_item(const String& p_item,const Ref& p_texture,bool p_selectable) { + + Item item; + item.icon=p_texture; + item.text=p_item; + item.selectable=p_selectable; + item.selected=false; + item.disabled=false; + items.push_back(item); + + update(); + shape_changed=true; + +} + +void ItemList::add_icon_item(const Ref& p_item,bool p_selectable){ + + Item item; + item.icon=p_item; + //item.text=p_item; + item.selectable=p_selectable; + item.selected=false; + item.disabled=false; + items.push_back(item); + + update(); + shape_changed=true; + +} + +void ItemList::set_item_text(int p_idx,const String& p_text){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].text=p_text; + update(); + shape_changed=true; + +} + +String ItemList::get_item_text(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),String()); + return items[p_idx].text; + +} + +void ItemList::set_item_tooltip(int p_idx,const String& p_tooltip){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].tooltip=p_tooltip; + update(); + shape_changed=true; + +} + +String ItemList::get_item_tooltip(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),String()); + return items[p_idx].tooltip; + +} + +void ItemList::set_item_icon(int p_idx,const Ref& p_icon){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].icon=p_icon; + update(); + shape_changed=true; + + +} +Ref ItemList::get_item_icon(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),Ref()); + + return items[p_idx].icon; + +} + + +void ItemList::set_item_tag_icon(int p_idx,const Ref& p_tag_icon){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].tag_icon=p_tag_icon; + update(); + shape_changed=true; + + +} +Ref ItemList::get_item_tag_icon(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),Ref()); + + return items[p_idx].tag_icon; + +} + +void ItemList::set_item_selectable(int p_idx,bool p_selectable){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].selectable=p_selectable; + + +} + + +bool ItemList::is_item_selectable(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),false); + return items[p_idx].selectable; +} + +void ItemList::set_item_disabled(int p_idx,bool p_disabled){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].disabled=p_disabled; + + +} + + +bool ItemList::is_item_disabled(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),false); + return items[p_idx].disabled; +} + + +void ItemList::set_item_metadata(int p_idx,const Variant& p_metadata){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + items[p_idx].metadata=p_metadata; + update(); + shape_changed=true; + +} + +Variant ItemList::get_item_metadata(int p_idx) const{ + + ERR_FAIL_INDEX_V(p_idx,items.size(),Variant()); + return items[p_idx].metadata; + +} +void ItemList::select(int p_idx,bool p_single){ + + ERR_FAIL_INDEX(p_idx,items.size()); + + if (p_single || select_mode==SELECT_SINGLE) { + + if (!items[p_idx].selectable) { + return; + } + + for(int i=0;i bg = get_stylebox("bg"); + pos-=bg->get_offset(); + pos.y+=scroll_bar->get_val(); + + int closest = -1; + int closest_dist=0x7FFFFFFF; + + for(int i=0;i=0 && currentset_val( scroll_bar->get_val()-scroll_bar->get_page()/8 ); + + } + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_WHEEL_DOWN && p_event.mouse_button.pressed) { + + scroll_bar->set_val( scroll_bar->get_val()+scroll_bar->get_page()/8 ); + + } + + if (p_event.is_pressed() && items.size()>0) { + if (p_event.is_action("ui_up")) { + + if (search_string!="") { + + uint64_t now = OS::get_singleton()->get_ticks_msec(); + uint64_t diff = now-search_time_msec; + + if (diffget("gui/incr_search_max_interval_msec"))*2) { + + for(int i=current-1;i>=0;i--) { + + if (items[i].text.begins_with(search_string)) { + + set_current(i); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + + + break; + } + } + accept_event(); + return; + } + } + + if (current>=current_columns) { + set_current(current-current_columns); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + } + } else if (p_event.is_action("ui_down")) { + + if (search_string!="") { + + uint64_t now = OS::get_singleton()->get_ticks_msec(); + uint64_t diff = now-search_time_msec; + + if (diffget("gui/incr_search_max_interval_msec"))*2) { + + for(int i=current+1;i0;i--) { + if (current-current_columns*i >=0 ) { + set_current( current- current_columns*i); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + break; + } + } + } else if (p_event.is_action("ui_page_down")) { + + search_string=""; //any mousepress cancels + + for(int i=4;i>0;i--) { + if (current+current_columns*i < items.size() ) { + set_current( current+ current_columns*i); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + + break; + } + } + } else if (p_event.is_action("ui_left")) { + + search_string=""; //any mousepress cancels + + if (current%current_columns!=0) { + set_current(current-1); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + + } + } else if (p_event.is_action("ui_right")) { + + search_string=""; //any mousepress cancels + + if (current%current_columns!=(current_columns-1)) { + set_current(current+1); + ensure_current_is_visible(); + if (select_mode==SELECT_SINGLE) { + emit_signal("item_selected",current); + } + accept_event(); + + } + } else if (p_event.is_action("ui_cancel")) { + search_string=""; + } else if (p_event.is_action("ui_select")) { + + + if (select_mode==SELECT_MULTI && current>=0 && current=0 && currentget_ticks_msec(); + uint64_t diff = now-search_time_msec; + uint64_t max_interval = uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000)); + search_time_msec = now; + + if (diff>max_interval) { + search_string=""; + } + + search_string+=String::chr(p_event.key.unicode); + for(int i=0;i=0 && current <=items.size()) { + + Rect2 r = items[current].rect_cache; + int from = scroll_bar->get_val(); + int to = from + scroll_bar->get_page(); + + if (r.pos.y < from) { + scroll_bar->set_val(r.pos.y); + } else if (r.pos.y+r.size.y > to) { + scroll_bar->set_val(r.pos.y+r.size.y - (to-from)); + } + } +} + +void ItemList::_notification(int p_what) { + + if (p_what==NOTIFICATION_RESIZED) { + shape_changed=true; + update(); + } + + if (p_what==NOTIFICATION_DRAW) { + + VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + Ref bg = get_stylebox("bg"); + + int mw = scroll_bar->get_minimum_size().x; + scroll_bar->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,mw+bg->get_margin(MARGIN_RIGHT)); + scroll_bar->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,bg->get_margin(MARGIN_RIGHT)); + scroll_bar->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,bg->get_margin(MARGIN_TOP)); + scroll_bar->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,bg->get_margin(MARGIN_BOTTOM)); + + + Size2 size = get_size(); + + float page = size.height-bg->get_minimum_size().height; + int width = size.width - mw - bg->get_minimum_size().width; + scroll_bar->set_page(page); + + draw_style_box(bg,Rect2(Point2(),size)); + + int hseparation = get_constant("hseparation"); + int vseparation = get_constant("vseparation"); + int icon_margin = get_constant("icon_margin"); + int line_separation = get_constant("line_separation"); + + Ref sbsel = has_focus()?get_stylebox("selected_focus"):get_stylebox("selected"); + Ref cursor = has_focus()?get_stylebox("cursor"):get_stylebox("cursor_unfocused"); + + Ref font = get_font("font"); + Color guide_color = get_color("guide_color"); + Color font_color = get_color("font_color"); + int font_height = font->get_height(); + Vector line_size_cache; + Vector line_limit_cache; + + if (max_text_lines) { + line_size_cache.resize(max_text_lines); + line_limit_cache.resize(max_text_lines); + } + + if (has_focus()) { + VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(),true); + draw_style_box(get_stylebox("bg_focus"),Rect2(Point2(),size)); + VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(),false); + } + + if (shape_changed) { + + //1- compute item minimum sizes + for(int i=0;iget_size(); + if (min_icon_size.x!=0) + minsize.x = MAX(minsize.x,min_icon_size.x); + if (min_icon_size.y!=0) + minsize.y = MAX(minsize.y,min_icon_size.y); + + if (items[i].text!="") { + if (icon_mode==ICON_MODE_TOP) { + minsize.y+=icon_margin; + } else { + minsize.x+=icon_margin; + } + } + } + + if (items[i].text!="") { + + Size2 s = font->get_string_size(items[i].text); + //s.width=MIN(s.width,fixed_column_width); + + + + if (icon_mode==ICON_MODE_TOP) { + minsize.x=MAX(minsize.x,s.width); + if (max_text_lines>0) { + minsize.y+=(font_height+line_separation)*max_text_lines; + } else { + minsize.y+=s.height; + } + + } else { + minsize.y=MAX(minsize.y,s.height); + minsize.x+=s.width; + } + } + + + + items[i].rect_cache.size=minsize; + if (fixed_column_width>0) + items[i].rect_cache.size.x=fixed_column_width; + + } + + int fit_size = size.x - bg->get_minimum_size().width - mw; + + //2-attempt best fit + current_columns = 0x7FFFFFFF; + if (max_columns>0) + current_columns=max_columns; + + + while(true) { + //repeat util all fits + //print_line("try with "+itos(current_columns)); + bool all_fit=true; + Vector2 ofs; + int col=0; + int max_h=0; + separators.clear();; + for(int i=0;i1 && items[i].rect_cache.size.width+ofs.x > fit_size) { + //went past + current_columns=MAX(col,1); + all_fit=false; + break; + } + + items[i].rect_cache.pos=ofs; + max_h=MAX(max_h,items[i].rect_cache.size.y); + ofs.x+=items[i].rect_cache.size.x; + //print_line("item "+itos(i)+" ofs "+rtos(items[i].rect_cache.size.x)); + if (col>0) + ofs.x+=hseparation; + col++; + if (col==current_columns) { + + if (iset_max(max); + //print_line("max: "+rtos(max)+" page "+rtos(page)); + if (max<=page) { + scroll_bar->set_val(0); + scroll_bar->hide(); + } else { + scroll_bar->show(); + } + break; + } + } + + + shape_changed=false; + } + + + + Vector2 base_ofs = bg->get_offset(); + base_ofs.y-=int(scroll_bar->get_val()); + + Rect2 clip(Point2(),size-bg->get_minimum_size()+Vector2(0,scroll_bar->get_val())); + + for(int i=0;iget_margin(MARGIN_LEFT); + r.size.x+=sbsel->get_margin(MARGIN_LEFT)+sbsel->get_margin(MARGIN_RIGHT); + r.pos.y-=sbsel->get_margin(MARGIN_TOP); + r.size.y+=sbsel->get_margin(MARGIN_TOP)+sbsel->get_margin(MARGIN_BOTTOM); + + draw_style_box(sbsel,r); + + } + + + Vector2 text_ofs; + if (items[i].icon.is_valid()) { + + Vector2 icon_ofs; + if (min_icon_size!=Vector2()) { + icon_ofs = (min_icon_size - items[i].icon->get_size())/2; + } + + if (icon_mode==ICON_MODE_TOP) { + draw_texture(items[i].icon,icon_ofs+items[i].rect_cache.pos+Vector2(items[i].rect_cache.size.width/2-items[i].icon->get_width()/2,0).floor()+base_ofs); + text_ofs.y = MAX(items[i].icon->get_height(),min_icon_size.y)+icon_margin; + } else { + draw_texture(items[i].icon,icon_ofs+items[i].rect_cache.pos+Vector2(0,items[i].rect_cache.size.height/2-items[i].icon->get_height()/2).floor()+base_ofs); + text_ofs.x = MAX(items[i].icon->get_width(),min_icon_size.x)+icon_margin; + } + } + + if (items[i].tag_icon.is_valid()) { + + draw_texture(items[i].tag_icon,items[i].rect_cache.pos+base_ofs); + } + + if (items[i].text!="") { + + int max_len=-1; + + Vector2 size = font->get_string_size(items[i].text); + if (fixed_column_width) + max_len=fixed_column_width; + else + max_len=size.x; + + if (icon_mode==ICON_MODE_TOP && max_text_lines>0) { + + int ss = items[i].text.length(); + float ofs=0; + int line=0; + for(int j=0;j<=ss;j++) { + + int cs = jget_char_size(items[i].text[j],items[i].text[j+1]).x:0; + if (ofs+cs>max_len || j==ss) { + line_limit_cache[line]=j; + line_size_cache[line]=ofs; + line++; + ofs=0; + if (line>=max_text_lines) + break; + } else { + ofs+=cs; + } + + } + + line=0; + ofs=0; + + text_ofs.y+=font->get_ascent(); + text_ofs=text_ofs.floor(); + text_ofs+=base_ofs; + text_ofs+=items[i].rect_cache.pos; + + for(int j=0;j=max_text_lines) + break; + } + ofs+=font->draw_char(get_canvas_item(),text_ofs+Vector2(ofs+(max_len-line_size_cache[line])/2,line*(font_height+line_separation)).floor(),items[i].text[j],items[i].text[j+1],font_color); + } + + //special multiline mode + } else { + + if (fixed_column_width>0) + size.x=MIN(size.x,fixed_column_width); + + if (icon_mode==ICON_MODE_TOP) { + text_ofs.x+=(items[i].rect_cache.size.width-size.x)/2; + } else { + text_ofs.y+=(items[i].rect_cache.size.height-size.y)/2; + } + + text_ofs.y+=font->get_ascent(); + text_ofs=text_ofs.floor(); + text_ofs+=base_ofs; + text_ofs+=items[i].rect_cache.pos; + + draw_string(font,text_ofs,items[i].text,font_color,max_len+1); + } + + + } + + if (select_mode==SELECT_MULTI && i==current) { + + Rect2 r=rcache; + r.pos+=base_ofs; + draw_style_box(cursor,r); + + } + } + + for(int i=0;iget_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color); + } + + } +} + +void ItemList::_scroll_changed(double) { + update(); +} + + +String ItemList::get_tooltip(const Point2& p_pos) const { + + Vector2 pos=p_pos; + Ref bg = get_stylebox("bg"); + pos-=bg->get_offset(); + pos.y+=scroll_bar->get_val(); + + int closest = -1; + int closest_dist=0x7FFFFFFF; + + for(int i=0;i()),DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("add_icon_item","icon:Texture","selectable"),&ItemList::add_icon_item,DEFVAL(true)); + + ObjectTypeDB::bind_method(_MD("set_item_text","idx","text"),&ItemList::set_item_text); + ObjectTypeDB::bind_method(_MD("get_item_text","idx"),&ItemList::get_item_text); + + ObjectTypeDB::bind_method(_MD("set_item_icon","idx","icon:Texture"),&ItemList::set_item_icon); + ObjectTypeDB::bind_method(_MD("get_item_icon:Tedture","idx"),&ItemList::get_item_icon); + + ObjectTypeDB::bind_method(_MD("set_item_selectable","idx","selectable"),&ItemList::set_item_selectable); + ObjectTypeDB::bind_method(_MD("is_item_selectable","idx"),&ItemList::is_item_selectable); + + ObjectTypeDB::bind_method(_MD("set_item_disabled","idx","disabled"),&ItemList::set_item_disabled); + ObjectTypeDB::bind_method(_MD("is_item_disabled","idx"),&ItemList::is_item_disabled); + + ObjectTypeDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip); + ObjectTypeDB::bind_method(_MD("get_item_tooltip","idx"),&ItemList::get_item_tooltip); + + ObjectTypeDB::bind_method(_MD("select","idx","single"),&ItemList::select,DEFVAL(true)); + ObjectTypeDB::bind_method(_MD("unselect","idx"),&ItemList::unselect); + ObjectTypeDB::bind_method(_MD("is_selected","idx"),&ItemList::is_selected); + + ObjectTypeDB::bind_method(_MD("get_item_count"),&ItemList::get_item_count); + ObjectTypeDB::bind_method(_MD("remove_item","idx"),&ItemList::remove_item); + + ObjectTypeDB::bind_method(_MD("clear"),&ItemList::clear); + + ObjectTypeDB::bind_method(_MD("set_fixed_column_width","width"),&ItemList::set_fixed_column_width); + ObjectTypeDB::bind_method(_MD("get_fixed_column_width"),&ItemList::get_fixed_column_width); + + ObjectTypeDB::bind_method(_MD("set_max_text_lines","lines"),&ItemList::set_max_text_lines); + ObjectTypeDB::bind_method(_MD("get_max_text_lines"),&ItemList::get_max_text_lines); + + ObjectTypeDB::bind_method(_MD("set_max_columns","amount"),&ItemList::set_max_columns); + ObjectTypeDB::bind_method(_MD("get_max_columns"),&ItemList::get_max_columns); + + ObjectTypeDB::bind_method(_MD("set_select_mode","mode"),&ItemList::set_select_mode); + ObjectTypeDB::bind_method(_MD("get_select_mode"),&ItemList::get_select_mode); + + ObjectTypeDB::bind_method(_MD("set_icon_mode","mode"),&ItemList::set_icon_mode); + ObjectTypeDB::bind_method(_MD("get_icon_mode"),&ItemList::get_icon_mode); + + ObjectTypeDB::bind_method(_MD("set_min_icon_size","size"),&ItemList::set_min_icon_size); + ObjectTypeDB::bind_method(_MD("get_min_icon_size"),&ItemList::get_min_icon_size); + + ObjectTypeDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible); + + ObjectTypeDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed); + ObjectTypeDB::bind_method(_MD("_input_event"),&ItemList::_input_event); + + BIND_CONSTANT( ICON_MODE_TOP ); + BIND_CONSTANT( ICON_MODE_LEFT ); + BIND_CONSTANT( SELECT_SINGLE ); + BIND_CONSTANT( SELECT_MULTI ); + + ADD_SIGNAL( MethodInfo("item_selected",PropertyInfo(Variant::INT,"index"))); + ADD_SIGNAL( MethodInfo("multi_selected",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::BOOL,"selected"))); + ADD_SIGNAL( MethodInfo("item_activated",PropertyInfo(Variant::INT,"index"))); +} + + + +ItemList::ItemList() { + + current=-1; + + select_mode=SELECT_SINGLE; + icon_mode=ICON_MODE_LEFT; + + fixed_column_width=0; + max_text_lines=1; + max_columns=1; + + scroll_bar = memnew( VScrollBar ); + add_child(scroll_bar); + + shape_changed=true; + scroll_bar->connect("value_changed",this,"_scroll_changed"); + + set_focus_mode(FOCUS_ALL); + current_columns=1; + search_time_msec=0; + +} + +ItemList::~ItemList() { + +} + diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h new file mode 100644 index 00000000000..6bbb416970c --- /dev/null +++ b/scene/gui/item_list.h @@ -0,0 +1,132 @@ +#ifndef ITEMLIST_H +#define ITEMLIST_H + +#include "scene/gui/control.h" +#include "scene/gui/scroll_bar.h" + +class ItemList : public Control { + + OBJ_TYPE( ItemList, Control ); +public: + + enum IconMode { + ICON_MODE_TOP, + ICON_MODE_LEFT + }; + + enum SelectMode { + SELECT_SINGLE, + SELECT_MULTI + }; +private: + struct Item { + + Ref icon; + Ref tag_icon; + String text; + bool selectable; + bool selected; + bool disabled; + Variant metadata; + String tooltip; + + Rect2 rect_cache; + }; + + int current; + + bool shape_changed; + + Vector items; + Vector separators; + + SelectMode select_mode; + IconMode icon_mode; + VScrollBar *scroll_bar; + + uint64_t search_time_msec; + String search_string; + + int current_columns; + int fixed_column_width; + int max_text_lines; + int max_columns; + Size2 min_icon_size; + + void _scroll_changed(double); + void _input_event(const InputEvent& p_event); +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void add_item(const String& p_item,const Ref& p_texture=Ref(),bool p_selectable=true); + void add_icon_item(const Ref& p_item,bool p_selectable=true); + + void set_item_text(int p_idx,const String& p_text); + String get_item_text(int p_idx) const; + + void set_item_icon(int p_idx,const Ref& p_icon); + Ref get_item_icon(int p_idx) const; + + void set_item_selectable(int p_idx,bool p_selectable); + bool is_item_selectable(int p_idx) const; + + void set_item_disabled(int p_idx,bool p_disabled); + bool is_item_disabled(int p_idx) const; + + void set_item_metadata(int p_idx,const Variant& p_metadata); + Variant get_item_metadata(int p_idx) const; + + void set_item_tag_icon(int p_idx,const Ref& p_tag_icon); + Ref get_item_tag_icon(int p_idx) const; + + void set_item_tooltip(int p_idx,const String& p_tooltip); + String get_item_tooltip(int p_idx) const; + + void select(int p_idx,bool p_single=true); + void unselect(int p_idx); + bool is_selected(int p_idx) const; + + void set_current(int p_current); + int get_current() const; + + + int get_item_count() const; + void remove_item(int p_idx); + + void clear(); + + void set_fixed_column_width(int p_size); + int get_fixed_column_width() const; + + void set_max_text_lines(int p_amount); + int get_max_text_lines() const; + + void set_max_columns(int p_amount); + int get_max_columns() const; + + void set_select_mode(SelectMode p_mode); + SelectMode get_select_mode() const; + + void set_icon_mode(IconMode p_mode); + IconMode get_icon_mode() const; + + void set_min_icon_size(const Size2& p_size); + Size2 get_min_icon_size() const; + + void ensure_current_is_visible(); + + + virtual String get_tooltip(const Point2& p_pos) const; + + ItemList(); + ~ItemList(); +}; + +VARIANT_ENUM_CAST(ItemList::SelectMode); +VARIANT_ENUM_CAST(ItemList::IconMode); + + +#endif // ITEMLIST_H diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index c73af744266..5ce7e2e0d31 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -84,6 +84,48 @@ void Popup::_fix_size() { } +void Popup::set_as_minsize() { + + Size2 total_minsize; + + for(int i=0;icast_to(); + if (!c) + continue; + if (c->is_hidden()) + continue; + + Size2 minsize = c->get_combined_minimum_size(); + + for(int j=0;j<2;j++) { + + Margin m_beg = Margin(0+j); + Margin m_end = Margin(2+j); + + float margin_begin = c->get_margin(m_beg); + float margin_end = c->get_margin(m_end); + AnchorType anchor_begin = c->get_anchor(m_beg); + AnchorType anchor_end = c->get_anchor(m_end); + + if (anchor_begin == ANCHOR_BEGIN) + minsize[j]+=margin_begin; + if (anchor_end == ANCHOR_END) + minsize[j]+=margin_end; + + } + + print_line(String(c->get_type())+": "+minsize); + + total_minsize.width = MAX( total_minsize.width, minsize.width ); + total_minsize.height = MAX( total_minsize.height, minsize.height ); + } + + set_size(total_minsize); + +} + + void Popup::popup_centered_minsize(const Size2& p_minsize) { diff --git a/scene/gui/popup.h b/scene/gui/popup.h index c2de6c8cf7d..6c72a3c82b2 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -62,6 +62,7 @@ public: void popup_centered_ratio(float p_screen_ratio=0.75); void popup_centered(const Size2& p_size=Size2()); void popup_centered_minsize(const Size2& p_minsize=Size2()); + void set_as_minsize(); virtual void popup(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 987a2ed800c..7a607786ee0 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -58,7 +58,7 @@ RichTextLabel::Item *RichTextLabel::_get_next_item(Item* p_item) { } -void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref &p_base_font,const Color &p_base_color,const Point2i& p_click_pos,Item **r_click_item,int *r_click_char,bool *r_outside) { +void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref &p_base_font,const Color &p_base_color,const Point2i& p_click_pos,Item **r_click_item,int *r_click_char,bool *r_outside,int p_char_count) { RID ci; if (r_outside) @@ -80,6 +80,7 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p int line=0; int spaces=0; + if (p_mode!=PROCESS_CACHE) { ERR_FAIL_INDEX(line,l.offset_caches.size()); @@ -89,6 +90,7 @@ void RichTextLabel::_process_line(int &y, int p_width, int p_line, ProcessMode p if (p_mode==PROCESS_CACHE) { l.offset_caches.clear(); l.height_caches.clear(); + l.char_count=0; } int wofs=margin; @@ -216,6 +218,8 @@ if (m_height > line_height) {\ underline=true; } + } else if (p_mode==PROCESS_CACHE) { + l.char_count+=text->text.length(); } rchar=0; @@ -326,18 +330,23 @@ if (m_height > line_height) {\ } } - int cw; + int cw=0; + + bool visible = visible_characters<0 || p_char_countget_char_size(c[i],c[i+1]).x; draw_rect(Rect2(pofs,y,cw,lh),selection_bg); - font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],selection_fg); + if (visible) + font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],selection_fg); } else { - cw=font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],color); + if (visible) + cw=font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],color); } + p_char_count++; if (c[i]=='\t') { cw=tab_size*font->get_char_size(' ').width; } @@ -371,6 +380,8 @@ if (m_height > line_height) {\ lh=0; if (p_mode!=PROCESS_CACHE) lh = line(it); @@ -383,9 +394,12 @@ if (m_height > line_height) {\ ENSURE_WIDTH( img->image->get_width() ); - if (p_mode==PROCESS_DRAW) { + bool visible = visible_characters<0 || p_char_countimage->draw(ci,Point2(wofs,y+lh-font->get_descent()-img->image->get_height())); } + p_char_count++; ADVANCE( img->image->get_width() ); CHECK_HEIGHT( (img->image->get_height()+font->get_descent()) ); @@ -556,11 +570,13 @@ void RichTextLabel::_notification(int p_what) { //todo, change to binary search int from_line = 0; + int total_chars = 0; while (from_line=ofs) break; from_line++; + total_chars+=lines[from_line].char_count; } if (from_line>=lines.size()) @@ -572,7 +588,8 @@ void RichTextLabel::_notification(int p_what) { while (y space_caches; int height_cache; int height_accum_cache; + int char_count; - Line() { from=NULL; } + Line() { from=NULL; char_count=0; } }; @@ -223,10 +224,10 @@ private: Selection selection; + int visible_characters; - - void _process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref &p_base_font,const Color &p_base_color,const Point2i& p_click_pos=Point2i(),Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL); + void _process_line(int &y, int p_width, int p_line, ProcessMode p_mode,const Ref &p_base_font,const Color &p_base_color,const Point2i& p_click_pos=Point2i(),Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL,int p_char_count=0); void _find_click(const Point2i& p_click,Item **r_click_item=NULL,int *r_click_char=NULL,bool *r_outside=NULL); @@ -246,6 +247,8 @@ private: bool use_bbcode; String bbcode; + + protected: void _notification(int p_what); @@ -304,6 +307,10 @@ public: void set_bbcode(const String& p_bbcode); String get_bbcode() const; + void set_visible_characters(int p_visible); + int get_visible_characters() const; + int get_total_character_count() const; + RichTextLabel(); ~RichTextLabel(); }; diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index d02c833be91..d7ee7a6b863 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -345,6 +345,7 @@ void SplitContainer::_input_event(const InputEvent& p_event) { expand_ofs=drag_ofs+((vertical?mm.y:mm.x)-drag_from); queue_sort(); + emit_signal("dragged",get_split_offset()); } } @@ -431,11 +432,13 @@ void SplitContainer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_dragger_visible","visible"),&SplitContainer::set_dragger_visible); ObjectTypeDB::bind_method(_MD("is_dragger_visible"),&SplitContainer::is_dragger_visible); + ADD_SIGNAL( MethodInfo("dragged",PropertyInfo(Variant::INT,"offset"))); ADD_PROPERTY( PropertyInfo(Variant::INT,"split/offset"),_SCS("set_split_offset"),_SCS("get_split_offset")); ADD_PROPERTY( PropertyInfo(Variant::INT,"split/collapsed"),_SCS("set_collapsed"),_SCS("is_collapsed")); ADD_PROPERTY( PropertyInfo(Variant::INT,"split/dragger_visible"),_SCS("set_dragger_visible"),_SCS("is_dragger_visible")); + } SplitContainer::SplitContainer(bool p_vertical) { diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 1db4998a271..3ed182c0178 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -88,7 +88,22 @@ void TabContainer::_input_event(const InputEvent& p_event) { Ref font = get_font("font"); Ref incr = get_icon("increment"); Ref decr = get_icon("decrement"); + Ref menu = get_icon("menu"); + Ref menu_hl = get_icon("menu_hl"); + if (popup && pos.x>get_size().width-menu->get_width()) { + + + emit_signal("pre_popup_pressed"); + Vector2 pp_pos = get_global_pos(); + pp_pos.x+=get_size().width; + pp_pos.x-=popup->get_size().width; + pp_pos.y+=menu->get_height(); + + popup->set_global_pos( pp_pos ); + popup->popup();; + return; + } pos.x-=tabs_ofs_cache; int idx=0; @@ -116,17 +131,17 @@ void TabContainer::_input_event(const InputEvent& p_event) { String s = c->has_meta("_tab_name")?String(XL_MESSAGE(String(c->get_meta("_tab_name")))):String(c->get_name()); int tab_width=font->get_string_size(s).width; - if (c->has_meta("_tab_icon")) { - Ref icon = c->get_meta("_tab_icon"); - if (icon.is_valid()) { - tab_width+=icon->get_width(); - if (s!="") - tab_width+=get_constant("hseparation"); + if (c->has_meta("_tab_icon")) { + Ref icon = c->get_meta("_tab_icon"); + if (icon.is_valid()) { + tab_width+=icon->get_width(); + if (s!="") + tab_width+=get_constant("hseparation"); - } - } + } + } - if (idx==current) { + if (idx==current) { tab_width+=tab_fg->get_minimum_size().width; } else { @@ -163,7 +178,7 @@ void TabContainer::_input_event(const InputEvent& p_event) { if (found!=-1) { - set_current_tab(found); + set_current_tab(found); } } @@ -194,7 +209,9 @@ void TabContainer::_notification(int p_what) { Ref incr = get_icon("increment"); Ref incr_hl = get_icon("increment_hilite"); Ref decr = get_icon("decrement"); - Ref decr_hl = get_icon("decrement_hilite"); + Ref decr_hl = get_icon("decrement_hilite"); + Ref menu = get_icon("menu"); + Ref menu_hl = get_icon("menu_hl"); Ref font = get_font("font"); Color color_fg = get_color("font_color_fg"); Color color_bg = get_color("font_color_bg"); @@ -209,6 +226,7 @@ void TabContainer::_notification(int p_what) { Size2 top_size = Size2( size.width, top_margin ); + int w=0; int idx=0; for(int i=0;iget_width(); if (s!="") - w+=get_constant("hseparation"); + w+=get_constant("hseparation"); } } @@ -245,14 +263,18 @@ void TabContainer::_notification(int p_what) { int ofs; int limit=get_size().width; + if (popup) { + top_size.width-=menu->get_width(); + limit-=menu->get_width(); + } - if (w<=get_size().width) { + if (w<=limit) { switch(align) { case ALIGN_LEFT: ofs = side_margin; break; - case ALIGN_CENTER: ofs = (int(top_size.width) - w)/2; break; - case ALIGN_RIGHT: ofs = int(top_size.width) - w - side_margin; break; + case ALIGN_CENTER: ofs = (int(limit) - w)/2; break; + case ALIGN_RIGHT: ofs = int(limit) - w - side_margin; break; }; tab_display_ofs=0; @@ -364,6 +386,15 @@ void TabContainer::_notification(int p_what) { incr->draw(ci,Point2(limit+incr->get_width(),vofs),Color(1,1,1,notdone?1.0:0.5)); } + if (popup) { + int from = get_size().width-menu->get_width(); + + if (mouse_x_cache > from) + menu_hl->draw(get_canvas_item(),Size2(from,0)); + else + menu->draw(get_canvas_item(),Size2(from,0)); + } + panel->draw(ci, Rect2( 0, top_size.height, size.width, size.height-top_size.height)); } break; @@ -465,6 +496,48 @@ int TabContainer::get_current_tab() const { return current; } +Control* TabContainer::get_tab_control(int p_idx) const { + + int idx=0; + + + for(int i=0;icast_to(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + if (idx==p_idx) { + return c; + + } + idx++; + } + + return NULL; +} +Control* TabContainer::get_current_tab_control() const { + + int idx=0; + + + for(int i=0;icast_to(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + if (idx==current) { + return c; + + } + idx++; + } + + return NULL; +} void TabContainer::remove_child_notify(Node *p_child) { @@ -635,12 +708,25 @@ Size2 TabContainer::get_minimum_size() const { return ms; } +void TabContainer::set_popup(Node *p_popup) { + ERR_FAIL_NULL(p_popup); + popup=p_popup->cast_to(); + update(); +} + +Popup* TabContainer::get_popup() const { + return popup; +} + + void TabContainer::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&TabContainer::_input_event); ObjectTypeDB::bind_method(_MD("get_tab_count"),&TabContainer::get_tab_count); ObjectTypeDB::bind_method(_MD("set_current_tab","tab_idx"),&TabContainer::set_current_tab); ObjectTypeDB::bind_method(_MD("get_current_tab"),&TabContainer::get_current_tab); + ObjectTypeDB::bind_method(_MD("get_current_tab_control:Control"),&TabContainer::get_current_tab_control); + ObjectTypeDB::bind_method(_MD("get_tab_control:Control","idx"),&TabContainer::get_tab_control); ObjectTypeDB::bind_method(_MD("set_tab_align","align"),&TabContainer::set_tab_align); ObjectTypeDB::bind_method(_MD("get_tab_align"),&TabContainer::get_tab_align); ObjectTypeDB::bind_method(_MD("set_tabs_visible","visible"),&TabContainer::set_tabs_visible); @@ -649,10 +735,13 @@ void TabContainer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_tab_title","tab_idx"),&TabContainer::get_tab_title); ObjectTypeDB::bind_method(_MD("set_tab_icon","tab_idx","icon:Texture"),&TabContainer::set_tab_icon); ObjectTypeDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&TabContainer::get_tab_icon); + ObjectTypeDB::bind_method(_MD("set_popup","popup:Popup"),&TabContainer::set_popup); + ObjectTypeDB::bind_method(_MD("get_popup:Popup"),&TabContainer::get_popup); ObjectTypeDB::bind_method(_MD("_child_renamed_callback"),&TabContainer::_child_renamed_callback); ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab"))); + ADD_SIGNAL(MethodInfo("pre_popup_pressed")); ADD_PROPERTY( PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM,"Left,Center,Right"), _SCS("set_tab_align"), _SCS("get_tab_align") ); ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab") ); @@ -669,5 +758,6 @@ TabContainer::TabContainer() { mouse_x_cache=0; align=ALIGN_CENTER; tabs_visible=true; + popup=NULL; } diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 43314b026d6..602d248b466 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -31,7 +31,7 @@ #include "scene/gui/control.h" - +#include "scene/gui/popup.h" class TabContainer : public Control { OBJ_TYPE( TabContainer, Control ); @@ -55,6 +55,8 @@ private: TabAlign align; Control *_get_tab(int idx) const; int _get_top_margin() const; + Popup *popup; + protected: @@ -85,10 +87,17 @@ public: void set_current_tab(int p_current); int get_current_tab() const; + Control* get_tab_control(int p_idx) const; + Control* get_current_tab_control() const; + virtual Size2 get_minimum_size() const; virtual void get_translatable_strings(List *p_strings) const; + void set_popup(Node *p_popup); + Popup* get_popup() const; + + TabContainer(); }; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 0c15f99509f..c497bc5363f 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -3601,6 +3601,10 @@ TextEdit::TextEdit() { set_focus_mode(FOCUS_ALL); _update_caches(); cache.size=Size2(1,1); + cache.row_height=1; + cache.line_spacing=1; + cache.line_number_w=1; + tab_size=4; text.set_tab_size(tab_size); text.clear(); diff --git a/scene/io/resource_format_wav.cpp b/scene/io/resource_format_wav.cpp index b246eb66f53..7c90a4b3cd0 100644 --- a/scene/io/resource_format_wav.cpp +++ b/scene/io/resource_format_wav.cpp @@ -150,10 +150,10 @@ RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_ frames/=format_channels; frames/=(format_bits>>3); - print_line("chunksize: "+itos(chunksize)); + /*print_line("chunksize: "+itos(chunksize)); print_line("channels: "+itos(format_channels)); print_line("bits: "+itos(format_bits)); - +*/ sample->create( (format_bits==8) ? Sample::FORMAT_PCM8 : Sample::FORMAT_PCM16, (format_channels==2)?true:false, diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 5c60b9fbff5..2530e3a36fd 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -641,6 +641,7 @@ void Node::_add_child_nocheck(Node* p_child,const StringName& p_name) { p_child->data.pos=data.children.size(); data.children.push_back( p_child ); p_child->data.parent=this; + p_child->notification(NOTIFICATION_PARENTED); if (data.tree) { p_child->_set_tree(data.tree); @@ -649,7 +650,6 @@ void Node::_add_child_nocheck(Node* p_child,const StringName& p_name) { /* Notify */ //recognize childs created in this node constructor p_child->data.parent_owned=data.in_constructor; - p_child->notification(NOTIFICATION_PARENTED); add_child_notify(p_child); @@ -840,6 +840,28 @@ bool Node::has_node(const NodePath& p_path) const { return _get_node(p_path)!=NULL; } + +Node* Node::find_node(const String& p_mask,bool p_recursive,bool p_owned) const { + + Node * const*cptr = data.children.ptr(); + int ccount = data.children.size(); + for(int i=0;idata.owner) + continue; + if (cptr[i]->data.name.operator String().match(p_mask)) + return cptr[i]; + + if (!p_recursive) + continue; + + Node* ret = cptr[i]->find_node(p_mask,true,p_owned); + if (ret) + return ret; + } + return NULL; + +} + Node *Node::get_parent() const { return data.parent; @@ -1807,6 +1829,7 @@ void Node::_bind_methods() { ObjectTypeDB::bind_method(_MD("has_node","path"),&Node::has_node); ObjectTypeDB::bind_method(_MD("get_node:Node","path"),&Node::get_node); ObjectTypeDB::bind_method(_MD("get_parent:Parent"),&Node::get_parent); + ObjectTypeDB::bind_method(_MD("find_node:Node","mask","recursive","owned"),&Node::get_node,DEFVAL(true),DEFVAL(true)); ObjectTypeDB::bind_method(_MD("has_node_and_resource","path"),&Node::has_node_and_resource); ObjectTypeDB::bind_method(_MD("get_node_and_resource","path"),&Node::_get_node_and_resource); diff --git a/scene/main/node.h b/scene/main/node.h index be32c4e7261..a89a6abf33a 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -114,6 +114,7 @@ private: Node *_get_node(const NodePath& p_path) const; + void _validate_child_name(Node *p_name); void _propagate_reverse_notification(int p_notification); @@ -186,6 +187,7 @@ public: Node *get_child(int p_index) const; bool has_node(const NodePath& p_path) const; Node *get_node(const NodePath& p_path) const; + Node* find_node(const String& p_mask,bool p_recursive=true,bool p_owned=true) const; bool has_node_and_resource(const NodePath& p_path) const; Node *get_node_and_resource(const NodePath& p_path,RES& r_res) const; diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index 584b40337f6..1664a9bea12 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -1108,6 +1108,9 @@ void SceneTree::_bind_methods() { ADD_SIGNAL( MethodInfo("node_removed",PropertyInfo( Variant::OBJECT, "node") ) ); ADD_SIGNAL( MethodInfo("screen_resized") ); + ADD_SIGNAL( MethodInfo("idle_frame")); + ADD_SIGNAL( MethodInfo("fixed_frame")); + BIND_CONSTANT( GROUP_CALL_DEFAULT ); BIND_CONSTANT( GROUP_CALL_REVERSE ); BIND_CONSTANT( GROUP_CALL_REALTIME ); @@ -1166,8 +1169,7 @@ SceneTree::SceneTree() { edited_scene_root=NULL; #endif - ADD_SIGNAL( MethodInfo("idle_frame")); - ADD_SIGNAL( MethodInfo("fixed_frame")); + } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 687410d1926..717ed93b16a 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -66,6 +66,7 @@ #include "scene/gui/file_dialog.h" #include "scene/gui/dialogs.h" #include "scene/gui/tree.h" +#include "scene/gui/item_list.h" #include "scene/gui/text_edit.h" #include "scene/gui/texture_button.h" #include "scene/gui/separator.h" @@ -170,6 +171,7 @@ #include "scene/resources/audio_stream.h" #include "scene/resources/gibberish_stream.h" #include "scene/resources/bit_mask.h" +#include "scene/resources/color_ramp.h" #include "scene/scene_string_names.h" @@ -327,7 +329,7 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); - + ObjectTypeDB::register_type(); #ifndef ADVANCED_GUI_DISABLED @@ -335,6 +337,7 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); ObjectTypeDB::register_virtual_type(); @@ -565,6 +568,7 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp index 506b34fbf61..6317780bd31 100644 --- a/scene/resources/audio_stream_resampled.cpp +++ b/scene/resources/audio_stream_resampled.cpp @@ -230,6 +230,51 @@ bool AudioStreamResampled::mix(int32_t *p_dest, int p_frames) { case 4: read=_resample<4>(p_dest,todo,increment); break; case 6: read=_resample<6>(p_dest,todo,increment); break; } +#if 1 + //end of stream, fadeout + int remaining = p_frames-todo; + if (remaining && todo>0) { + + //print_line("fadeout"); + for(int c=0;c>8; + uint32_t mul = (todo-i) * 256 /todo; + //print_line("mul: "+itos(i)+" "+itos(mul)); + p_dest[i*channels+c]=samp*mul; + } + + } + + } + +#else + int remaining = p_frames-todo; + if (remaining && todo>0) { + + + for(int c=0;c>8; + + for(int i=0;irb_todo) read=rb_todo; @@ -316,6 +361,16 @@ AudioStreamResampled::AudioStreamResampled() { rb=NULL; offset=0; read_buf=NULL; + rb_read_pos=0; + rb_write_pos=0; + + rb_bits=0; + rb_len=0; + rb_mask=0; + read_buff_len=0; + channels=0; + mix_rate=0; + } AudioStreamResampled::~AudioStreamResampled() { diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp new file mode 100644 index 00000000000..97d3fafd588 --- /dev/null +++ b/scene/resources/color_ramp.cpp @@ -0,0 +1,117 @@ +/* + * color_ramp.h + */ + +#include "color_ramp.h" + +//setter and getter names for property serialization +#define COLOR_RAMP_GET_OFFSETS "get_offsets" +#define COLOR_RAMP_GET_COLORS "get_colors" +#define COLOR_RAMP_SET_OFFSETS "set_offsets" +#define COLOR_RAMP_SET_COLORS "set_colors" + +ColorRamp::ColorRamp() { + //Set initial color ramp transition from black to white + points.resize(2); + points[0].color = Color(0,0,0,1); + points[0].offset = 0; + points[1].color = Color(1,1,1,1); + points[1].offset = 1; + is_sorted = true; +} + +ColorRamp::~ColorRamp() { + +} + +void ColorRamp::_bind_methods() { + + ObjectTypeDB::bind_method(_MD(COLOR_RAMP_SET_OFFSETS,"offsets"),&ColorRamp::set_offsets); + ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offsets); + + ObjectTypeDB::bind_method(_MD(COLOR_RAMP_SET_COLORS,"colors"),&ColorRamp::set_colors); + ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_COLORS),&ColorRamp::get_colors); + + ADD_PROPERTY( PropertyInfo(Variant::REAL,"offsets"),_SCS(COLOR_RAMP_SET_OFFSETS),_SCS(COLOR_RAMP_GET_OFFSETS) ); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"colors"),_SCS(COLOR_RAMP_SET_COLORS),_SCS(COLOR_RAMP_GET_COLORS) ); +} + +Vector ColorRamp::get_offsets() const { + Vector offsets; + offsets.resize(points.size()); + for(int i = 0; i < points.size(); i++) + { + offsets[i] = points[i].offset; + } + return offsets; +} + +Vector ColorRamp::get_colors() const { + Vector colors; + colors.resize(points.size()); + for(int i = 0; i < points.size(); i++) + { + colors[i] = points[i].color; + } + return colors; +} + +void ColorRamp::set_offsets(const Vector& p_offsets) { + points.resize(p_offsets.size()); + for(int i = 0; i < points.size(); i++) + { + points[i].offset = p_offsets[i]; + } + is_sorted = false; +} + +void ColorRamp::set_colors(const Vector& p_colors) { + if(points.size()& ColorRamp::get_points() { + return points; +} + +void ColorRamp::set_points(Vector& p_points) { + points = p_points; + is_sorted = false; +} + +void ColorRamp::set_offset(int pos, const float offset) { + if(points.size() <= pos) + points.resize(pos + 1); + points[pos].offset = offset; + is_sorted = false; +} + +float ColorRamp::get_offset(int pos) const { + if(points.size() > pos) + return points[pos].offset; + return 0; //TODO: Maybe throw some error instead? +} + +void ColorRamp::set_color(int pos, const Color& color) { + if(points.size() <= pos) + { + points.resize(pos + 1); + is_sorted = false; + } + points[pos].color = color; +} + +Color ColorRamp::get_color(int pos) const { + if(points.size() > pos) + return points[pos].color; + return Color(0,0,0,1); //TODO: Maybe throw some error instead? +} + +int ColorRamp::get_points_count() const { + return points.size(); +} diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h new file mode 100644 index 00000000000..8f6ba2c3e5a --- /dev/null +++ b/scene/resources/color_ramp.h @@ -0,0 +1,98 @@ +/* + * color_ramp.h + */ + +#ifndef SCENE_RESOURCES_COLOR_RAMP_H_ +#define SCENE_RESOURCES_COLOR_RAMP_H_ + +#include "resource.h" + +class ColorRamp: public Resource { + OBJ_TYPE( ColorRamp, Resource ); + OBJ_SAVE_TYPE( ColorRamp ); + +public: + struct Point { + + float offset; + Color color; + bool operator<(const Point& p_ponit) const { + return offset points; + bool is_sorted; + +protected: + static void _bind_methods(); + +public: + ColorRamp(); + virtual ~ColorRamp(); + + void set_points(Vector& points); + Vector& get_points(); + + void set_offset(int pos, const float offset); + float get_offset(int pos) const; + + void set_color(int pos, const Color& color); + Color get_color(int pos) const; + + void set_offsets(const Vector& offsets); + Vector get_offsets() const; + + void set_colors(const Vector& colors); + Vector get_colors() const; + + _FORCE_INLINE_ Color get_color_at_offset(float p_offset) { + + if (points.empty()) + return Color(0,0,0,1); + + if(!is_sorted) + { + points.sort(); + is_sorted = true; + } + + //binary search + int low = 0; + int high = points.size() -1; + int middle; + + while( low <= high ) + { + middle = ( low + high ) / 2; + Point& point = points[middle]; + if( point.offset > p_offset ) { + high = middle - 1; //search low end of array + } else if ( point.offset < p_offset) { + low = middle + 1; //search high end of array + } else { + return point.color; + } + } + + //return interpolated value + if (points[middle].offset>p_offset) + { + middle--; + } + int first=middle; + int second=middle+1; + if(second>=points.size()) + return points[points.size()-1].color; + if(first<0) + return points[0].color; + Point& pointFirst = points[first]; + Point& pointSecond = points[second]; + return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset-pointFirst.offset)/(pointSecond.offset - pointFirst.offset)); + } + + int get_points_count() const; +}; + +#endif /* SCENE_RESOURCES_COLOR_RAMP_H_ */ diff --git a/scene/resources/default_theme/checker_bg.png b/scene/resources/default_theme/checker_bg.png new file mode 100644 index 00000000000..0674f9da260 Binary files /dev/null and b/scene/resources/default_theme/checker_bg.png differ diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 2fddafc07bd..9a9048e3e5f 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -574,7 +574,7 @@ void make_default_theme() { // Tree Ref tree_selected = make_stylebox( selection_png,4,4,4,4,8,0,8,0); - Ref tree_selected_oof = make_stylebox( selection_oof_png,4,4,4,4,8,0,8,0); + Ref tree_selected_oof = make_stylebox( selection_oof_png,4,4,4,4,8,0,8,0); t->set_stylebox("bg","Tree", make_stylebox( tree_bg_png,4,4,4,5) ); t->set_stylebox("bg_focus","Tree", focus ); @@ -605,12 +605,31 @@ void make_default_theme() { t->set_color("guide_color","Tree", Color(0,0,0,0.1) ); t->set_constant("hseparation","Tree",4); - t->set_constant("vseparation","Tree",2); + t->set_constant("vseparation","Tree",4); t->set_constant("guide_width","Tree",2); t->set_constant("item_margin","Tree",12); t->set_constant("button_margin","Tree",4); + // ItemList + Ref item_selected = make_stylebox( selection_png,4,4,4,4,8,2,8,2); + Ref item_selected_oof = make_stylebox( selection_oof_png,4,4,4,4,8,2,8,2); + + t->set_stylebox("bg","ItemList", make_stylebox( tree_bg_png,4,4,4,5) ); + t->set_stylebox("bg_focus","ItemList", focus ); + t->set_constant("hseparation","ItemList",4); + t->set_constant("vseparation","ItemList",2); + t->set_constant("icon_margin","ItemList",4); + t->set_constant("line_separation","ItemList",2); + t->set_font("font","ItemList", default_font ); + t->set_color("font_color","ItemList", control_font_color_low ); + t->set_color("font_color_selected","ItemList", control_font_color_pressed ); + t->set_color("guide_color","ItemList", Color(0,0,0,0.1) ); + t->set_stylebox("selected","ItemList", item_selected_oof ); + t->set_stylebox("selected_focus","ItemList", item_selected ); + t->set_stylebox("cursor","ItemList", focus ); + t->set_stylebox("cursor_unfocused","ItemList", focus ); + // TextEdit @@ -636,6 +655,8 @@ void make_default_theme() { t->set_icon("increment_hilite","TabContainer",make_icon( scroll_button_right_hl_png)); t->set_icon("decrement","TabContainer",make_icon( scroll_button_left_png)); t->set_icon("decrement_hilite","TabContainer",make_icon( scroll_button_left_hl_png)); + t->set_icon("menu","TabContainer",make_icon( tab_menu_png)); + t->set_icon("menu_hilite","TabContainer",make_icon( tab_menu_hl_png)); t->set_font("font","TabContainer", default_font ); @@ -692,7 +713,6 @@ void make_default_theme() { // FileDialog t->set_icon("folder","FileDialog",make_icon(icon_folder_png)); - t->set_color("files_disabled","FileDialog",Color(0,0,0,0.7)); @@ -754,7 +774,8 @@ void make_default_theme() { t->set_constant("separation","HBoxContainer",4); t->set_constant("separation","VBoxContainer",4); t->set_constant("margin","MarginContainer",8); - t->set_constant("separation","GridContainer",4); + t->set_constant("hseparation","GridContainer",4); + t->set_constant("vseparation","GridContainer",4); t->set_constant("separation","HSplitContainer",12); t->set_constant("separation","VSplitContainer",12); t->set_constant("autohide","HSplitContainer",1); diff --git a/scene/resources/default_theme/tab_menu.png b/scene/resources/default_theme/tab_menu.png new file mode 100644 index 00000000000..c5659da11b0 Binary files /dev/null and b/scene/resources/default_theme/tab_menu.png differ diff --git a/scene/resources/default_theme/tab_menu_hl.png b/scene/resources/default_theme/tab_menu_hl.png new file mode 100644 index 00000000000..6f68502c07d Binary files /dev/null and b/scene/resources/default_theme/tab_menu_hl.png differ diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 78e210239df..291931a0153 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -49,6 +49,11 @@ static const unsigned char checked_png[]={ }; +static const unsigned char checker_bg_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b,0xe,0x1b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xd,0x1c,0x1b,0x52,0x41,0x72,0xa4,0x0,0x0,0x0,0x24,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0xfc,0xf,0x4,0xc,0x48,0xa0,0xa1,0xa1,0x1,0xca,0x82,0x0,0x26,0x28,0x8d,0x13,0x50,0xae,0x80,0xb1,0xbe,0xbe,0x7e,0x60,0xdd,0xc0,0xc0,0x0,0x0,0x78,0x11,0x9,0x87,0x2b,0xa,0xe1,0x69,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char close_png[]={ 0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x1,0x14,0x3,0xf4,0x10,0x33,0xed,0x0,0x0,0x1,0x53,0x49,0x44,0x41,0x54,0x38,0xcb,0xcd,0x92,0xbd,0x4e,0x5b,0x41,0x10,0x85,0xbf,0xd9,0x9d,0xfd,0xb9,0xd7,0xb2,0xb9,0x81,0x8e,0x26,0xf4,0x69,0x53,0x50,0x44,0xa2,0x74,0x3,0xd,0xd,0x48,0x48,0xf4,0x3c,0x16,0x8f,0xc1,0x23,0xf0,0x0,0xf4,0x8e,0x90,0x11,0x96,0x25,0xa2,0x10,0x45,0x4a,0x9c,0x6b,0x4f,0xa,0xf6,0x4a,0xe6,0xc6,0x4e,0xb,0x47,0x5a,0xed,0xee,0x9c,0xd9,0xd1,0x99,0xb3,0x3,0x6f,0xd,0xd9,0x70,0xd7,0x72,0xfe,0xd3,0xe3,0x42,0xd9,0x5b,0xc0,0xba,0xa0,0xef,0x3d,0xfe,0xe0,0x9c,0x3b,0x35,0xb3,0x21,0xf0,0x1d,0xf8,0x5d,0xe2,0xd,0xf0,0xd9,0x39,0xf7,0xc5,0xcc,0xee,0x81,0x5f,0x9b,0xd4,0x4,0xe7,0xdc,0x65,0xd3,0x34,0x3f,0x53,0x4a,0x73,0xe0,0x18,0xd8,0x2b,0xeb,0x78,0x38,0x1c,0x3e,0xe5,0x9c,0x7f,0x38,0xe7,0x2e,0xd7,0xd4,0xfc,0x23,0xf1,0x30,0xc6,0x38,0x4b,0x29,0x59,0x8,0xe1,0x1e,0xb8,0x0,0x2e,0xea,0xba,0x7e,0xa8,0xaa,0xca,0x42,0x8,0x33,0xe0,0x70,0x5b,0x1,0x80,0x1d,0x60,0xac,0xaa,0x93,0x9c,0xb3,0xa9,0xea,0x63,0x8c,0x71,0x36,0x18,0xc,0x4c,0x55,0x27,0xc0,0xb8,0xe4,0xfc,0xd7,0xd4,0x5d,0xe0,0x5c,0x55,0xa7,0x39,0x67,0xcb,0x39,0x9b,0xf7,0x7e,0xa,0x9c,0x17,0xee,0x95,0xf1,0xba,0xa5,0x90,0x17,0x11,0x6f,0xf6,0x62,0xb6,0x88,0xb8,0x9e,0xe1,0x5b,0xd1,0x0,0x27,0x75,0x5d,0x3f,0x14,0xd9,0xd3,0x4e,0x49,0xf1,0xe4,0xa4,0xe4,0x6c,0x44,0x10,0x91,0xa3,0xd1,0x68,0xf4,0x54,0x55,0x55,0xd7,0xf3,0x19,0x70,0xa6,0xaa,0x93,0x94,0x92,0xc5,0x18,0xe7,0x22,0x72,0xb4,0x6e,0xe2,0xab,0x16,0xbc,0xf7,0x7,0x8b,0xc5,0x42,0x97,0xcb,0xe5,0xbc,0x6d,0xdb,0x2b,0xe0,0x16,0xa0,0x6d,0xdb,0x67,0xe7,0xdc,0xb5,0x88,0x24,0x11,0xd9,0xef,0x5a,0xeb,0x4f,0x62,0x37,0x48,0xe3,0xd5,0x6a,0xf5,0x15,0xb8,0x3,0x9e,0xb,0x37,0x2,0x3e,0x89,0xc8,0x47,0x33,0xbb,0x1,0xbe,0xad,0x4f,0x63,0xff,0x17,0xc2,0x16,0x73,0xb5,0x70,0xc2,0xbb,0xc2,0x5f,0x47,0xa5,0x56,0x8a,0x30,0xdd,0x7d,0xae,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; @@ -374,6 +379,16 @@ static const unsigned char tab_current_png[]={ }; +static const unsigned char tab_menu_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0x6,0xd,0x3,0x2c,0x7,0xf7,0x85,0x69,0x73,0x0,0x0,0x0,0x1d,0x69,0x54,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x0,0x0,0x0,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x64,0x2e,0x65,0x7,0x0,0x0,0x0,0x54,0x49,0x44,0x41,0x54,0x38,0xcb,0xed,0x92,0xb1,0xd,0xc0,0x20,0x10,0x3,0x8f,0xec,0x63,0x65,0xff,0x2d,0x40,0x1e,0xe8,0xd3,0x50,0x24,0xd1,0x83,0x48,0x97,0x2,0xb7,0xb6,0x4f,0xd6,0xeb,0x61,0xeb,0x67,0xb2,0x5d,0xbe,0x66,0x4a,0x12,0x88,0x19,0x40,0xd2,0xa3,0x73,0x24,0x99,0x6,0x64,0x90,0xe8,0x1e,0xd3,0x5,0x7d,0x45,0x3,0x74,0xf3,0x3,0xb0,0xa4,0x73,0x9,0xf0,0x82,0x30,0x2a,0xaf,0x1c,0xb5,0xda,0xae,0xfb,0xbd,0xe6,0xba,0x0,0x22,0x30,0x1e,0x2c,0xd7,0x21,0xa8,0x0,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char tab_menu_hl_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdf,0x6,0xd,0x3,0x2c,0x15,0x4,0x3c,0x18,0x3b,0x0,0x0,0x0,0x1d,0x69,0x54,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x0,0x0,0x0,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x64,0x2e,0x65,0x7,0x0,0x0,0x0,0x58,0x49,0x44,0x41,0x54,0x38,0xcb,0x63,0x60,0x18,0x5,0x83,0xc,0xbc,0x7c,0xf9,0x92,0x91,0x54,0x35,0x8c,0x58,0x14,0xfc,0xc7,0x67,0x80,0xb8,0xb8,0x38,0x8a,0x1e,0x26,0x2c,0x6a,0x2e,0x32,0x30,0x30,0x60,0x33,0xe4,0x3f,0x54,0x8e,0x1,0xaf,0xb,0xa0,0xae,0xb8,0xc8,0xc0,0xc0,0xa0,0x8b,0x24,0xff,0x9f,0x81,0x81,0xe1,0xb2,0xb8,0xb8,0xb8,0x3e,0x51,0x6,0xa0,0x19,0xc2,0x80,0x4b,0x33,0x31,0x81,0x7a,0xe1,0xe5,0xcb,0x97,0x17,0x46,0x93,0x17,0x7e,0x0,0x0,0xa,0x9a,0x1f,0x34,0xff,0x99,0xf7,0x75,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char toggle_off_png[]={ 0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x20,0x8,0x6,0x0,0x0,0x0,0xa2,0x9d,0x7e,0x84,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x26,0x0,0x26,0x0,0x26,0x59,0xf,0xde,0x74,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0x17,0x2,0x16,0xe9,0x0,0x17,0x60,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x45,0x49,0x44,0x41,0x54,0x68,0x81,0xed,0x99,0x5f,0x4f,0xd3,0x50,0x18,0x87,0x9f,0xb3,0x96,0xb5,0xcc,0x3a,0xa6,0xac,0x6d,0xa,0x91,0x84,0x5b,0x8d,0x7e,0x21,0x60,0x2c,0x5c,0x1a,0x63,0xe2,0x27,0x31,0x31,0xc6,0x4b,0x32,0xa7,0x7e,0x20,0x84,0x6b,0x6f,0xc,0x90,0x6d,0x32,0xca,0x6c,0xb0,0x24,0x75,0xc7,0x8b,0xba,0xb9,0x35,0xdd,0x84,0xec,0xe0,0x26,0xed,0x73,0xd7,0xf7,0xed,0xce,0x7b,0x7e,0xbf,0xbe,0x67,0x7f,0xde,0x41,0x4e,0x4e,0xa6,0x11,0x89,0xeb,0x12,0x50,0x1,0x2c,0x40,0x4b,0xc9,0xff,0xaf,0x48,0xe0,0x27,0x10,0x0,0x3e,0x70,0x39,0x48,0xe8,0x89,0x1b,0x2b,0xc0,0x33,0xe0,0x11,0x60,0x72,0xb7,0xc,0x8,0x81,0xaf,0xc0,0x67,0xa6,0x18,0x60,0x1,0x1b,0x4f,0x1e,0x3f,0x7d,0x6d,0x57,0xed,0x65,0x40,0x48,0x64,0xfc,0x72,0x95,0x8,0x10,0x8,0x74,0x5d,0x67,0x69,0x49,0x47,0xd3,0x92,0xdb,0x50,0x4b,0x14,0x45,0xf2,0xf8,0xe4,0xf8,0xc7,0xe1,0xd1,0xc1,0x2b,0xe0,0xcb,0x68,0x2e,0x59,0x59,0x7,0xc,0xbb,0x6a,0x97,0xce,0xba,0x67,0x4,0x41,0x80,0xec,0xf7,0x91,0x8a,0x1d,0x10,0x8,0x44,0xa1,0x80,0x51,0x2c,0x52,0x2a,0xdd,0xa3,0x58,0x2c,0x2a,0x5d,0x3f,0x89,0x69,0x9a,0x62,0x7d,0x6d,0xbd,0x74,0x78,0x74,0x60,0x90,0xd0,0x9c,0x66,0xbd,0x0,0x8,0x82,0xef,0x54,0x2a,0xf,0x70,0x6c,0x7,0xa1,0xf8,0x24,0x48,0x24,0xed,0x4e,0x1b,0xdf,0x3f,0xc7,0x30,0x4c,0xa5,0x6b,0xa7,0x11,0x86,0x21,0x96,0x65,0x41,0xca,0x91,0x4e,0xed,0x3d,0x29,0x25,0xb2,0x2f,0x71,0x1d,0x97,0x30,0xc,0x39,0x6d,0x9d,0x2a,0xdd,0x90,0xe7,0x7a,0xb8,0x8e,0xcb,0x79,0xb7,0xab,0xbc,0xbb,0x6e,0x4a,0x61,0x52,0x62,0x70,0xf6,0x55,0x8b,0x87,0xdf,0x6b,0x4a,0xe6,0x2e,0x1e,0xa6,0x18,0x90,0x15,0x32,0x6f,0xc0,0xed,0x7e,0xfe,0xcc,0x80,0x65,0x59,0xd4,0xf7,0x6a,0x63,0xb1,0xc6,0x7e,0x93,0x20,0x8,0x78,0xf1,0xf2,0xf9,0x58,0xfc,0xed,0x9b,0x77,0xa9,0xb1,0xeb,0xb0,0xb0,0x6,0xc,0xc4,0x7f,0x78,0xff,0x9,0x80,0x9d,0xdd,0x2d,0xea,0x7b,0xb5,0xa1,0xb0,0x34,0x81,0xd7,0x15,0x3d,0xca,0xc2,0x1a,0x0,0xd0,0x6c,0x7c,0xa4,0xd7,0xeb,0x1,0xb1,0x11,0x3b,0xbb,0x5b,0xc3,0xdc,0xe8,0x13,0x1f,0x8,0x4f,0x8b,0xfd,0x8d,0x85,0x36,0x60,0x1a,0xaa,0x3a,0x60,0xa1,0xdf,0x4,0x6b,0xf5,0x6d,0xca,0xe5,0x32,0xe5,0x72,0x79,0xec,0xe9,0xab,0x24,0x69,0x80,0x9,0xac,0xdc,0x4a,0xa5,0x1b,0xd2,0xd8,0x6f,0x2,0xb1,0x9,0xb5,0xfa,0xf6,0x58,0x6c,0x6,0x56,0x88,0x35,0xe,0x49,0x1e,0x81,0x10,0xb8,0x98,0xb5,0x8a,0xa,0x82,0x20,0x98,0xd8,0xd2,0x33,0xb4,0xff,0x5,0xb1,0xc6,0x21,0xb,0x7d,0x4,0xfe,0x5,0xb9,0x1,0xf3,0xde,0xc0,0xbc,0x99,0x68,0x80,0x88,0xa7,0x16,0x78,0xae,0xa7,0xbc,0xa8,0xe7,0x7a,0xc3,0xa1,0xc8,0xbc,0x49,0xfd,0x1e,0x20,0x84,0x40,0x14,0x4,0xad,0x76,0xb,0xc7,0x76,0xd8,0xdc,0xd8,0x54,0x5a,0x54,0x22,0x69,0xb5,0x5b,0x88,0x82,0x98,0xbb,0x9,0x69,0x6,0x48,0x0,0xcb,0xba,0x8f,0xef,0xfb,0xb7,0xf2,0x9b,0xfd,0xcf,0x44,0xc8,0x40,0xd3,0x34,0xa5,0x6b,0xa7,0x61,0x9a,0x26,0x51,0x14,0x41,0xca,0x70,0x2f,0x69,0x40,0x4,0x5c,0x75,0xbe,0x75,0x2e,0xed,0xaa,0xbd,0xbc,0xfa,0x70,0xf5,0x4e,0xcd,0x4,0x81,0x2b,0x62,0x8d,0xa3,0x5b,0x19,0x63,0x8d,0x6c,0x4c,0x85,0x4f,0x6,0x89,0xcc,0xff,0x2f,0x90,0x93,0x93,0x93,0x6d,0x7e,0x1,0x6b,0xe,0xc1,0xdb,0xd6,0xe0,0xc4,0xba,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 862669ecd8e..90598ee789e 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -36,7 +36,7 @@ Shader::Mode Shader::get_mode() const { - return (Mode)VisualServer::get_singleton()->shader_get_mode(shader); + return mode; } void Shader::set_code( const String& p_vertex, const String& p_fragment, const String& p_light,int p_fragment_ofs,int p_light_ofs) { @@ -203,6 +203,7 @@ void Shader::_bind_methods() { Shader::Shader(Mode p_mode) { + mode=p_mode; shader = VisualServer::get_singleton()->shader_create(VS::ShaderMode(p_mode)); params_cache_dirty=true; } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index c5ef3777f7d..b805cbec96f 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -37,8 +37,18 @@ class Shader : public Resource { OBJ_TYPE(Shader,Resource); OBJ_SAVE_TYPE( Shader ); RES_BASE_EXTENSION("shd"); - RID shader; +public: + enum Mode { + + MODE_MATERIAL, + MODE_CANVAS_ITEM, + MODE_POST_PROCESS, + MODE_MAX + }; +private: + RID shader; + Mode mode; Dictionary _get_code(); void _set_code(const Dictionary& p_string); @@ -55,15 +65,10 @@ class Shader : public Resource { protected: + static void _bind_methods(); public: - enum Mode { - MODE_MATERIAL, - MODE_CANVAS_ITEM, - MODE_POST_PROCESS, - MODE_MAX - }; //void set_mode(Mode p_mode); Mode get_mode() const; diff --git a/servers/audio/sample_manager_sw.cpp b/servers/audio/sample_manager_sw.cpp index 49ca5369ae8..9195136a5de 100644 --- a/servers/audio/sample_manager_sw.cpp +++ b/servers/audio/sample_manager_sw.cpp @@ -135,7 +135,7 @@ void SampleManagerMallocSW::sample_set_data(RID p_sample, const DVector ERR_EXPLAIN("Sample buffer size does not match sample size."); - print_line("len bytes: "+itos(s->length_bytes)+" bufsize: "+itos(buff_size)); + //print_line("len bytes: "+itos(s->length_bytes)+" bufsize: "+itos(buff_size)); ERR_FAIL_COND(s->length_bytes!=buff_size); DVector::Read buffer_r=p_buffer.read(); const uint8_t *src = buffer_r.ptr(); diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp index e009bd52cb9..3eb96fb6817 100644 --- a/servers/physics/area_pair_sw.cpp +++ b/servers/physics/area_pair_sw.cpp @@ -93,3 +93,72 @@ AreaPairSW::~AreaPairSW() { body->remove_constraint(this); area->remove_constraint(this); } + +//////////////////////////////////////////////////// + + + +bool Area2PairSW::setup(float p_step) { + +// bool result = area_a->test_collision_mask(area_b) && CollisionSolverSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this); + bool result = CollisionSolverSW::solve_static(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),NULL,this); + + if (result!=colliding) { + + if (result) { + + if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + area_b->add_area_to_query(area_a,shape_a,shape_b); + + if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + area_a->add_area_to_query(area_b,shape_b,shape_a); + + } else { + + if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + area_b->remove_area_from_query(area_a,shape_a,shape_b); + + if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + area_a->remove_area_from_query(area_b,shape_b,shape_a); + } + + colliding=result; + + } + + return false; //never do any post solving +} + +void Area2PairSW::solve(float p_step) { + + +} + + +Area2PairSW::Area2PairSW(AreaSW *p_area_a,int p_shape_a, AreaSW *p_area_b,int p_shape_b) { + + + area_a=p_area_a; + area_b=p_area_b; + shape_a=p_shape_a; + shape_b=p_shape_b; + colliding=false; + area_a->add_constraint(this); + area_b->add_constraint(this); + +} + +Area2PairSW::~Area2PairSW() { + + if (colliding) { + + if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + area_b->remove_area_from_query(area_a,shape_a,shape_b); + + if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + area_a->remove_area_from_query(area_b,shape_b,shape_a); + } + + area_a->remove_constraint(this); + area_b->remove_constraint(this); +} diff --git a/servers/physics/area_pair_sw.h b/servers/physics/area_pair_sw.h index 1c219a05fdf..4f8087280a3 100644 --- a/servers/physics/area_pair_sw.h +++ b/servers/physics/area_pair_sw.h @@ -49,5 +49,23 @@ public: ~AreaPairSW(); }; + +class Area2PairSW : public ConstraintSW { + + AreaSW *area_a; + AreaSW *area_b; + int shape_a; + int shape_b; + bool colliding; +public: + + bool setup(float p_step); + void solve(float p_step); + + Area2PairSW(AreaSW *p_area_a,int p_shape_a, AreaSW *p_area_b,int p_shape_b); + ~Area2PairSW(); +}; + + #endif // AREA_PAIR__SW_H diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp index de241c948b2..83be80f8160 100644 --- a/servers/physics/area_sw.cpp +++ b/servers/physics/area_sw.cpp @@ -31,6 +31,7 @@ #include "body_sw.h" AreaSW::BodyKey::BodyKey(BodySW *p_body, uint32_t p_body_shape,uint32_t p_area_shape) { rid=p_body->get_self(); instance_id=p_body->get_instance_id(); body_shape=p_body_shape; area_shape=p_area_shape; } +AreaSW::BodyKey::BodyKey(AreaSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape) { rid=p_body->get_self(); instance_id=p_body->get_instance_id(); body_shape=p_body_shape; area_shape=p_area_shape; } void AreaSW::_shapes_changed() { @@ -57,6 +58,7 @@ void AreaSW::set_space(SpaceSW *p_space) { } monitored_bodies.clear(); + monitored_areas.clear(); _set_space(p_space); } @@ -76,11 +78,32 @@ void AreaSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) { monitor_callback_method=p_method; monitored_bodies.clear(); + monitored_areas.clear(); + _shape_changed(); } +void AreaSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) { + + + if (p_id==area_monitor_callback_id) { + area_monitor_callback_method=p_method; + return; + } + + _unregister_shapes(); + + area_monitor_callback_id=p_id; + area_monitor_callback_method=p_method; + + monitored_bodies.clear(); + monitored_areas.clear(); + + _shape_changed(); + +} void AreaSW::set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode) { @@ -98,6 +121,7 @@ void AreaSW::set_param(PhysicsServer::AreaParameter p_param, const Variant& p_va case PhysicsServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break; case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break; case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; + case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break; case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; case PhysicsServer::AREA_PARAM_DENSITY: density=p_value; ; break; case PhysicsServer::AREA_PARAM_PRIORITY: priority=p_value; ; break; @@ -113,6 +137,7 @@ Variant AreaSW::get_param(PhysicsServer::AreaParameter p_param) const { case PhysicsServer::AREA_PARAM_GRAVITY: return gravity; case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; case PhysicsServer::AREA_PARAM_DENSITY: return density; case PhysicsServer::AREA_PARAM_PRIORITY: return priority; @@ -132,6 +157,15 @@ void AreaSW::_queue_monitor_update() { } +void AreaSW::set_monitorable(bool p_monitorable) { + + if (monitorable==p_monitorable) + return; + + monitorable=p_monitorable; + _set_static(!monitorable); +} + void AreaSW::call_queries() { if (monitor_callback_id && !monitored_bodies.empty()) { @@ -166,6 +200,41 @@ void AreaSW::call_queries() { monitored_bodies.clear(); + if (area_monitor_callback_id && !monitored_areas.empty()) { + + + Variant res[5]; + Variant *resptr[5]; + for(int i=0;i<5;i++) + resptr[i]=&res[i]; + + Object *obj = ObjectDB::get_instance(area_monitor_callback_id); + if (!obj) { + monitored_areas.clear(); + area_monitor_callback_id=0; + return; + } + + + + for (Map::Element *E=monitored_areas.front();E;E=E->next()) { + + if (E->get().state==0) + continue; //nothing happened + + res[0]=E->get().state>0 ? PhysicsServer::AREA_BODY_ADDED : PhysicsServer::AREA_BODY_REMOVED; + res[1]=E->key().rid; + res[2]=E->key().instance_id; + res[3]=E->key().body_shape; + res[4]=E->key().area_shape; + + + Variant::CallError ce; + obj->call(area_monitor_callback_method,(const Variant**)resptr,5,ce); + } + } + + monitored_areas.clear(); //get_space()->area_remove_from_monitor_query_list(&monitor_query_list); } @@ -177,11 +246,14 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move gravity=9.80665; gravity_vector=Vector3(0,-1,0); gravity_is_point=false; + gravity_distance_scale=0; point_attenuation=1; density=0.1; priority=0; set_ray_pickable(false); monitor_callback_id=0; + area_monitor_callback_id=0; + monitorable=false; } diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h index 87843b93c92..26d6a177db8 100644 --- a/servers/physics/area_sw.h +++ b/servers/physics/area_sw.h @@ -45,13 +45,18 @@ class AreaSW : public CollisionObjectSW{ float gravity; Vector3 gravity_vector; bool gravity_is_point; + float gravity_distance_scale; float point_attenuation; float density; int priority; + bool monitorable; ObjectID monitor_callback_id; StringName monitor_callback_method; + ObjectID area_monitor_callback_id; + StringName area_monitor_callback_method; + SelfList monitor_query_list; SelfList moved_list; @@ -78,6 +83,8 @@ class AreaSW : public CollisionObjectSW{ _FORCE_INLINE_ BodyKey() {} BodyKey(BodySW *p_body, uint32_t p_body_shape,uint32_t p_area_shape); + BodyKey(AreaSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape); + }; struct BodyState { @@ -89,6 +96,7 @@ class AreaSW : public CollisionObjectSW{ }; Map monitored_bodies; + Map monitored_areas; //virtual void shape_changed_notify(ShapeSW *p_shape); //virtual void shape_deleted_notify(ShapeSW *p_shape); @@ -107,9 +115,15 @@ public: void set_monitor_callback(ObjectID p_id, const StringName& p_method); _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id; } + void set_area_monitor_callback(ObjectID p_id, const StringName& p_method); + _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id; } + _FORCE_INLINE_ void add_body_to_query(BodySW *p_body, uint32_t p_body_shape,uint32_t p_area_shape); _FORCE_INLINE_ void remove_body_from_query(BodySW *p_body, uint32_t p_body_shape,uint32_t p_area_shape); + _FORCE_INLINE_ void add_area_to_query(AreaSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape); + _FORCE_INLINE_ void remove_area_from_query(AreaSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape); + void set_param(PhysicsServer::AreaParameter p_param, const Variant& p_value); Variant get_param(PhysicsServer::AreaParameter p_param) const; @@ -125,6 +139,9 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } + _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; } + _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; } + _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } @@ -138,8 +155,8 @@ public: _FORCE_INLINE_ void remove_constraint( ConstraintSW* p_constraint) { constraints.erase(p_constraint); } _FORCE_INLINE_ const Set& get_constraints() const { return constraints; } - - + void set_monitorable(bool p_monitorable); + _FORCE_INLINE_ bool is_monitorable() const { return monitorable; } void set_transform(const Transform& p_transform); @@ -168,6 +185,26 @@ void AreaSW::remove_body_from_query(BodySW *p_body, uint32_t p_body_shape,uint32 } +void AreaSW::add_area_to_query(AreaSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape) { + + + BodyKey bk(p_area,p_area_shape,p_self_shape); + monitored_areas[bk].inc(); + if (!monitor_query_list.in_list()) + _queue_monitor_update(); + + +} +void AreaSW::remove_area_from_query(AreaSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape) { + + + BodyKey bk(p_area,p_area_shape,p_self_shape); + monitored_areas[bk].dec(); + if (!monitor_query_list.in_list()) + _queue_monitor_update(); +} + + diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 1cc0b763a44..5a528ecf94d 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -362,9 +362,12 @@ void BodySW::set_space(SpaceSW *p_space){ void BodySW::_compute_area_gravity(const AreaSW *p_area) { if (p_area->is_gravity_point()) { - - gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); - + if(p_area->get_gravity_distance_scale() > 0) { + Vector3 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin(); + gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale()+1, 2) ); + } else { + gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); + } } else { gravity += p_area->get_gravity_vector() * p_area->get_gravity(); } diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 03d5b7afa16..521ffae0eab 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -394,6 +394,14 @@ Transform PhysicsServerSW::area_get_transform(RID p_area) const { return area->get_transform(); }; +void PhysicsServerSW::area_set_monitorable(RID p_area,bool p_monitorable) { + + AreaSW *area = area_owner.get(p_area); + ERR_FAIL_COND(!area); + + area->set_monitorable(p_monitorable); +} + void PhysicsServerSW::area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method) { AreaSW *area = area_owner.get(p_area); @@ -423,6 +431,14 @@ bool PhysicsServerSW::area_is_ray_pickable(RID p_area) const{ } +void PhysicsServerSW::area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method) { + + + AreaSW *area = area_owner.get(p_area); + ERR_FAIL_COND(!area); + + area->set_area_monitor_callback(p_receiver?p_receiver->get_instance_ID():0,p_method); +} /* BODY API */ diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index de2a24a3781..80007b84998 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -128,7 +128,10 @@ public: virtual void area_set_ray_pickable(RID p_area,bool p_enable); virtual bool area_is_ray_pickable(RID p_area) const; + virtual void area_set_monitorable(RID p_area,bool p_monitorable); + virtual void area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method); + virtual void area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method); /* BODY API */ diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index a7465c57b9f..d329a10f049 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -503,15 +503,18 @@ void* SpaceSW::_broadphase_pair(CollisionObjectSW *A,int p_subindex_A,CollisionO if (type_A==CollisionObjectSW::TYPE_AREA) { - - ERR_FAIL_COND_V(type_B!=CollisionObjectSW::TYPE_BODY,NULL); AreaSW *area=static_cast(A); - BodySW *body=static_cast(B); + if (type_B==CollisionObjectSW::TYPE_AREA) { + AreaSW *area_b=static_cast(B); + Area2PairSW *area2_pair = memnew(Area2PairSW(area_b,p_subindex_B,area,p_subindex_A) ); + return area2_pair; + } else { - AreaPairSW *area_pair = memnew(AreaPairSW(body,p_subindex_B,area,p_subindex_A) ); - - return area_pair; + BodySW *body=static_cast(B); + AreaPairSW *area_pair = memnew(AreaPairSW(body,p_subindex_B,area,p_subindex_A) ); + return area_pair; + } } else { diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index dad1891b77f..1a41cda4829 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -120,6 +120,7 @@ void Area2DSW::set_param(Physics2DServer::AreaParameter p_param, const Variant& case Physics2DServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; + case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break; case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break; @@ -136,6 +137,7 @@ Variant Area2DSW::get_param(Physics2DServer::AreaParameter p_param) const { case Physics2DServer::AREA_PARAM_GRAVITY: return gravity; case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; case Physics2DServer::AREA_PARAM_LINEAR_DAMP: return linear_damp; case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp; @@ -248,6 +250,7 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this), gravity=9.80665; gravity_vector=Vector2(0,-1); gravity_is_point=false; + gravity_distance_scale=0; point_attenuation=1; angular_damp=1.0; diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 4a54a337ed3..6d99764c680 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -46,6 +46,7 @@ class Area2DSW : public CollisionObject2DSW{ float gravity; Vector2 gravity_vector; bool gravity_is_point; + float gravity_distance_scale; float point_attenuation; float linear_damp; float angular_damp; @@ -139,6 +140,9 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } + _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; } + _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; } + _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index ccce058f136..38835c9a82e 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -383,9 +383,12 @@ void Body2DSW::set_space(Space2DSW *p_space){ void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) { if (p_area->is_gravity_point()) { - - gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); - + if(p_area->get_gravity_distance_scale() > 0) { + Vector2 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin(); + gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale()+1, 2) ); + } else { + gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); + } } else { gravity += p_area->get_gravity_vector() * p_area->get_gravity(); } diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 08d871be69b..b446f4928a8 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -30,7 +30,7 @@ #include "broad_phase_2d_basic.h" #include "broad_phase_2d_hash_grid.h" #include "collision_solver_2d_sw.h" - +#include "globals.h" RID Physics2DServerSW::shape_create(ShapeType p_shape) { Shape2DSW *shape=NULL; @@ -261,7 +261,7 @@ Physics2DDirectSpaceState* Physics2DServerSW::space_get_direct_state(RID p_space Space2DSW *space = space_owner.get(p_space); ERR_FAIL_COND_V(!space,NULL); - if (/*doing_sync ||*/ space->is_locked()) { + if ((using_threads && !doing_sync) || space->is_locked()) { ERR_EXPLAIN("Space state is inaccesible right now, wait for iteration or fixed process notification."); ERR_FAIL_V(NULL); @@ -733,7 +733,7 @@ void Physics2DServerSW::body_set_layer_mask(RID p_body, uint32_t p_flags) { }; -uint32_t Physics2DServerSW::body_get_layer_mask(RID p_body, uint32_t p_flags) const { +uint32_t Physics2DServerSW::body_get_layer_mask(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -750,7 +750,7 @@ void Physics2DServerSW::body_set_collision_mask(RID p_body, uint32_t p_flags) { }; -uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body, uint32_t p_flags) const { +uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -1196,7 +1196,7 @@ void Physics2DServerSW::set_active(bool p_active) { void Physics2DServerSW::init() { - doing_sync=true; + doing_sync=false; last_step=0.001; iterations=8;// 8? stepper = memnew( Step2DSW ); @@ -1228,6 +1228,7 @@ void Physics2DServerSW::step(float p_step) { void Physics2DServerSW::sync() { + doing_sync=true; }; void Physics2DServerSW::flush_queries() { @@ -1235,7 +1236,7 @@ void Physics2DServerSW::flush_queries() { if (!active) return; - doing_sync=true; + for( Set::Element *E=active_spaces.front();E;E=E->next()) { Space2DSW *space=(Space2DSW *)E->get(); @@ -1244,6 +1245,10 @@ void Physics2DServerSW::flush_queries() { }; +void Physics2DServerSW::end_sync() { + doing_sync=false; +} + void Physics2DServerSW::finish() { @@ -1283,6 +1288,7 @@ Physics2DServerSW::Physics2DServerSW() { island_count=0; active_objects=0; collision_pairs=0; + using_threads=int(Globals::get_singleton()->get("physics_2d/thread_model"))==2; }; diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 341df2fdc91..6e875701b87 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -51,6 +51,8 @@ friend class Physics2DDirectSpaceStateSW; int active_objects; int collision_pairs; + bool using_threads; + Step2DSW *stepper; Set active_spaces; @@ -179,10 +181,10 @@ public: virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const; virtual void body_set_layer_mask(RID p_body, uint32_t p_mask); - virtual uint32_t body_get_layer_mask(RID p_body, uint32_t p_mask) const; + virtual uint32_t body_get_layer_mask(RID p_body) const; virtual void body_set_collision_mask(RID p_body, uint32_t p_mask); - virtual uint32_t body_get_collision_mask(RID p_body, uint32_t p_mask) const; + virtual uint32_t body_get_collision_mask(RID p_) const; virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value); virtual float body_get_param(RID p_body, BodyParameter p_param) const; @@ -248,8 +250,9 @@ public: virtual void set_active(bool p_active); virtual void init(); virtual void step(float p_step); - virtual void sync(); + virtual void sync(); virtual void flush_queries(); + virtual void end_sync(); virtual void finish(); int get_process_info(ProcessInfo p_info); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp new file mode 100644 index 00000000000..c5f023f162a --- /dev/null +++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp @@ -0,0 +1,169 @@ +#include "physics_2d_server_wrap_mt.h" + +#include "os/os.h" + +void Physics2DServerWrapMT::thread_exit() { + + exit=true; +} + +void Physics2DServerWrapMT::thread_step(float p_delta) { + + physics_2d_server->step(p_delta); + step_sem->post(); + +} + +void Physics2DServerWrapMT::_thread_callback(void *_instance) { + + Physics2DServerWrapMT *vsmt = reinterpret_cast(_instance); + + + vsmt->thread_loop(); +} + +void Physics2DServerWrapMT::thread_loop() { + + server_thread=Thread::get_caller_ID(); + + OS::get_singleton()->make_rendering_thread(); + + physics_2d_server->init(); + + exit=false; + step_thread_up=true; + while(!exit) { + // flush commands one by one, until exit is requested + command_queue.wait_and_flush_one(); + } + + command_queue.flush_all(); // flush all + + physics_2d_server->finish(); + +} + + +/* EVENT QUEUING */ + + +void Physics2DServerWrapMT::step(float p_step) { + + if (create_thread) { + + command_queue.push( this, &Physics2DServerWrapMT::thread_step,p_step); + } else { + + command_queue.flush_all(); //flush all pending from other threads + physics_2d_server->step(p_step); + } +} + +void Physics2DServerWrapMT::sync() { + + if (step_sem) { + if (first_frame) + first_frame=false; + else + step_sem->wait(); //must not wait if a step was not issued + } + physics_2d_server->sync();; +} + +void Physics2DServerWrapMT::flush_queries(){ + + physics_2d_server->flush_queries(); +} + +void Physics2DServerWrapMT::end_sync() { + + physics_2d_server->end_sync();; +} + +void Physics2DServerWrapMT::init() { + + if (create_thread) { + + step_sem = Semaphore::create(); + print_line("CREATING PHYSICS 2D THREAD"); + //OS::get_singleton()->release_rendering_thread(); + if (create_thread) { + thread = Thread::create( _thread_callback, this ); + print_line("STARTING PHYISICS 2D THREAD"); + } + while(!step_thread_up) { + OS::get_singleton()->delay_usec(1000); + } + print_line("DONE PHYSICS 2D THREAD"); + } else { + + physics_2d_server->init(); + } + +} + +void Physics2DServerWrapMT::finish() { + + + if (thread) { + + command_queue.push( this, &Physics2DServerWrapMT::thread_exit); + Thread::wait_to_finish( thread ); + memdelete(thread); + +/* + shape_free_cached_ids(); + area_free_cached_ids(); + body_free_cached_ids(); + pin_joint_free_cached_ids(); + groove_joint_free_cached_ids(); + damped_string_free_cached_ids(); +*/ + thread=NULL; + } else { + physics_2d_server->finish(); + } + + if (step_sem) + memdelete(step_sem); + +} + + +Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer* p_contained,bool p_create_thread) : command_queue(p_create_thread) { + + physics_2d_server=p_contained; + create_thread=p_create_thread; + thread=NULL; + step_sem=NULL; + step_pending=0; + step_thread_up=false; + alloc_mutex=Mutex::create(); + + shape_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + area_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + body_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + pin_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + groove_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + damped_spring_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + + if (!p_create_thread) { + server_thread=Thread::get_caller_ID(); + } else { + server_thread=0; + } + + main_thread = Thread::get_caller_ID(); + first_frame=true; +} + + +Physics2DServerWrapMT::~Physics2DServerWrapMT() { + + memdelete(physics_2d_server); + memdelete(alloc_mutex); + //finish(); + +} + + diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h new file mode 100644 index 00000000000..0ddc8f16ec4 --- /dev/null +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -0,0 +1,297 @@ +#ifndef PHYSICS2DSERVERWRAPMT_H +#define PHYSICS2DSERVERWRAPMT_H + + +#include "servers/physics_2d_server.h" +#include "command_queue_mt.h" +#include "os/thread.h" +#include "globals.h" + +#ifdef DEBUG_SYNC +#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__)); +#else +#define SYNC_DEBUG +#endif + + +class Physics2DServerWrapMT : public Physics2DServer { + + mutable Physics2DServer *physics_2d_server; + + mutable CommandQueueMT command_queue; + + static void _thread_callback(void *_instance); + void thread_loop(); + + Thread::ID server_thread; + Thread::ID main_thread; + volatile bool exit; + Thread *thread; + volatile bool step_thread_up; + bool create_thread; + + Semaphore *step_sem; + int step_pending; + void thread_step(float p_delta); + void thread_flush(); + + void thread_exit(); + + Mutex*alloc_mutex; + bool first_frame; + + int shape_pool_max_size; + List shape_id_pool; + int area_pool_max_size; + List area_id_pool; + int body_pool_max_size; + List body_id_pool; + int pin_joint_pool_max_size; + List pin_joint_id_pool; + int groove_joint_pool_max_size; + List groove_joint_id_pool; + int damped_spring_joint_pool_max_size; + List damped_spring_joint_id_pool; + + +public: + +#define ServerName Physics2DServer +#define ServerNameWrapMT Physics2DServerWrapMT +#define server_name physics_2d_server +#include "servers/server_wrap_mt_common.h" + + //FUNC1RID(shape,ShapeType); todo fix + FUNC1R(RID,shape_create,ShapeType); + FUNC2(shape_set_data,RID,const Variant& ); + FUNC2(shape_set_custom_solver_bias,RID,real_t ); + + FUNC1RC(ShapeType,shape_get_type,RID ); + FUNC1RC(Variant,shape_get_data,RID); + FUNC1RC(real_t,shape_get_custom_solver_bias,RID); + + + //these work well, but should be used from the main thread only + bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) { + + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); + return physics_2d_server->shape_collide(p_shape_A,p_xform_A,p_motion_A,p_shape_B,p_xform_B,p_motion_B,r_results,p_result_max,r_result_count); + } + + /* SPACE API */ + + FUNC0R(RID,space_create); + FUNC2(space_set_active,RID,bool); + FUNC1RC(bool,space_is_active,RID); + + FUNC3(space_set_param,RID,SpaceParameter,real_t); + FUNC2RC(real_t,space_get_param,RID,SpaceParameter); + + // this function only works on fixed process, errors and returns null otherwise + Physics2DDirectSpaceState* space_get_direct_state(RID p_space) { + + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),NULL); + return physics_2d_server->space_get_direct_state(p_space); + } + + + /* AREA API */ + + //FUNC0RID(area); + FUNC0R(RID,area_create); + + FUNC2(area_set_space,RID,RID); + FUNC1RC(RID,area_get_space,RID); + + FUNC2(area_set_space_override_mode,RID,AreaSpaceOverrideMode); + FUNC1RC(AreaSpaceOverrideMode,area_get_space_override_mode,RID); + + FUNC3(area_add_shape,RID,RID,const Matrix32&); + FUNC3(area_set_shape,RID,int,RID); + FUNC3(area_set_shape_transform,RID,int,const Matrix32&); + + FUNC1RC(int,area_get_shape_count,RID); + FUNC2RC(RID,area_get_shape,RID,int); + FUNC2RC(Matrix32,area_get_shape_transform,RID,int); + FUNC2(area_remove_shape,RID,int); + FUNC1(area_clear_shapes,RID); + + FUNC2(area_attach_object_instance_ID,RID,ObjectID); + FUNC1RC(ObjectID,area_get_object_instance_ID,RID); + + FUNC3(area_set_param,RID,AreaParameter,const Variant&); + FUNC2(area_set_transform,RID,const Matrix32&); + + FUNC2RC(Variant,area_get_param,RID,AreaParameter); + FUNC1RC(Matrix32,area_get_transform,RID); + + FUNC2(area_set_collision_mask,RID,uint32_t); + FUNC2(area_set_layer_mask,RID,uint32_t); + + FUNC2(area_set_monitorable,RID,bool); + FUNC2(area_set_pickable,RID,bool); + + FUNC3(area_set_monitor_callback,RID,Object*,const StringName&); + FUNC3(area_set_area_monitor_callback,RID,Object*,const StringName&); + + + /* BODY API */ + + //FUNC2RID(body,BodyMode,bool); + FUNC2R(RID,body_create,BodyMode,bool) + + FUNC2(body_set_space,RID,RID); + FUNC1RC(RID,body_get_space,RID); + + FUNC2(body_set_mode,RID,BodyMode); + FUNC1RC(BodyMode,body_get_mode,RID); + + + FUNC3(body_add_shape,RID,RID,const Matrix32&); + FUNC3(body_set_shape,RID,int,RID); + FUNC3(body_set_shape_transform,RID,int,const Matrix32&); + FUNC3(body_set_shape_metadata,RID,int,const Variant&); + + FUNC1RC(int,body_get_shape_count,RID); + FUNC2RC(Matrix32,body_get_shape_transform,RID,int); + FUNC2RC(Variant,body_get_shape_metadata,RID,int); + FUNC2RC(RID,body_get_shape,RID,int); + + FUNC3(body_set_shape_as_trigger,RID,int,bool); + FUNC2RC(bool,body_is_shape_set_as_trigger,RID,int); + + FUNC2(body_remove_shape,RID,int); + FUNC1(body_clear_shapes,RID); + + FUNC2(body_attach_object_instance_ID,RID,uint32_t); + FUNC1RC(uint32_t,body_get_object_instance_ID,RID); + + FUNC2(body_set_continuous_collision_detection_mode,RID,CCDMode); + FUNC1RC(CCDMode,body_get_continuous_collision_detection_mode,RID); + + FUNC2(body_set_layer_mask,RID,uint32_t); + FUNC1RC(uint32_t,body_get_layer_mask,RID); + + FUNC2(body_set_collision_mask,RID,uint32_t); + FUNC1RC(uint32_t,body_get_collision_mask,RID); + + + FUNC3(body_set_param,RID,BodyParameter,float); + FUNC2RC(float,body_get_param,RID,BodyParameter); + + + FUNC3(body_set_state,RID,BodyState,const Variant&); + FUNC2RC(Variant,body_get_state,RID,BodyState); + + FUNC2(body_set_applied_force,RID,const Vector2&); + FUNC1RC(Vector2,body_get_applied_force,RID); + + FUNC2(body_set_applied_torque,RID,float); + FUNC1RC(float,body_get_applied_torque,RID); + + FUNC3(body_apply_impulse,RID,const Vector2&,const Vector2&); + FUNC2(body_set_axis_velocity,RID,const Vector2&); + + FUNC2(body_add_collision_exception,RID,RID); + FUNC2(body_remove_collision_exception,RID,RID); + FUNC2S(body_get_collision_exceptions,RID,List*); + + FUNC2(body_set_max_contacts_reported,RID,int); + FUNC1RC(int,body_get_max_contacts_reported,RID); + + FUNC2(body_set_one_way_collision_direction,RID,const Vector2&); + FUNC1RC(Vector2,body_get_one_way_collision_direction,RID); + + FUNC2(body_set_one_way_collision_max_depth,RID,float); + FUNC1RC(float,body_get_one_way_collision_max_depth,RID); + + + FUNC2(body_set_contacts_reported_depth_treshold,RID,float); + FUNC1RC(float,body_get_contacts_reported_depth_treshold,RID); + + FUNC2(body_set_omit_force_integration,RID,bool); + FUNC1RC(bool,body_is_omitting_force_integration,RID); + + FUNC4(body_set_force_integration_callback,RID ,Object *,const StringName& ,const Variant& ); + + + bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) { + return physics_2d_server->body_collide_shape(p_body,p_body_shape,p_shape,p_shape_xform,p_motion,r_results,p_result_max,r_result_count); + } + + FUNC2(body_set_pickable,RID,bool); + + bool body_test_motion(RID p_body,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL) { + + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); + return physics_2d_server->body_test_motion(p_body,p_motion,p_margin,r_result); + } + + /* JOINT API */ + + + FUNC3(joint_set_param,RID,JointParam,real_t); + FUNC2RC(real_t,joint_get_param,RID,JointParam); + + + ///FUNC3RID(pin_joint,const Vector2&,RID,RID); + ///FUNC5RID(groove_joint,const Vector2&,const Vector2&,const Vector2&,RID,RID); + ///FUNC4RID(damped_spring_joint,const Vector2&,const Vector2&,RID,RID); + + FUNC3R(RID,pin_joint_create,const Vector2&,RID,RID); + FUNC5R(RID,groove_joint_create,const Vector2&,const Vector2&,const Vector2&,RID,RID); + FUNC4R(RID,damped_spring_joint_create,const Vector2&,const Vector2&,RID,RID); + + FUNC3(damped_string_joint_set_param,RID,DampedStringParam,real_t); + FUNC2RC(real_t,damped_string_joint_get_param,RID,DampedStringParam); + + FUNC1RC(JointType,joint_get_type,RID); + + + /* MISC */ + + + FUNC1(free,RID); + FUNC1(set_active,bool); + + virtual void init(); + virtual void step(float p_step); + virtual void sync(); + virtual void end_sync(); + virtual void flush_queries(); + virtual void finish(); + + int get_process_info(ProcessInfo p_info) { + return physics_2d_server->get_process_info(p_info); + } + + Physics2DServerWrapMT(Physics2DServer* p_contained,bool p_create_thread); + ~Physics2DServerWrapMT(); + + + template + static Physics2DServer* init_server() { + + int tm = GLOBAL_DEF("physics_2d/thread_model",1); + if (tm==0) //single unsafe + return memnew( T ); + else if (tm==1) //single saef + return memnew( Physics2DServerWrapMT( memnew( T ), false )); + else //single unsafe + return memnew( Physics2DServerWrapMT( memnew( T ), true )); + + + } + +#undef ServerNameWrapMT +#undef ServerName +#undef server_name + +}; + +#ifdef DEBUG_SYNC +#undef DEBUG_SYNC +#endif +#undef SYNC_DEBUG + +#endif // PHYSICS2DSERVERWRAPMT_H diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 279ad0d7421..b9d15d6e350 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -657,6 +657,7 @@ void Physics2DServer::_bind_methods() { BIND_CONSTANT( AREA_PARAM_GRAVITY ); BIND_CONSTANT( AREA_PARAM_GRAVITY_VECTOR ); BIND_CONSTANT( AREA_PARAM_GRAVITY_IS_POINT ); + BIND_CONSTANT( AREA_PARAM_GRAVITY_DISTANCE_SCALE ); BIND_CONSTANT( AREA_PARAM_GRAVITY_POINT_ATTENUATION ); BIND_CONSTANT( AREA_PARAM_LINEAR_DAMP); BIND_CONSTANT( AREA_PARAM_ANGULAR_DAMP); @@ -713,7 +714,7 @@ void Physics2DServer::_bind_methods() { Physics2DServer::Physics2DServer() { - ERR_FAIL_COND( singleton!=NULL ); + //ERR_FAIL_COND( singleton!=NULL ); singleton=this; } diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 5411228c0fd..b24496880e3 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -306,6 +306,7 @@ public: AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, + AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, AREA_PARAM_LINEAR_DAMP, AREA_PARAM_ANGULAR_DAMP, @@ -405,10 +406,10 @@ public: virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const=0; virtual void body_set_layer_mask(RID p_body, uint32_t p_mask)=0; - virtual uint32_t body_get_layer_mask(RID p_body, uint32_t p_mask) const=0; + virtual uint32_t body_get_layer_mask(RID p_body) const=0; virtual void body_set_collision_mask(RID p_body, uint32_t p_mask)=0; - virtual uint32_t body_get_collision_mask(RID p_body, uint32_t p_mask) const=0; + virtual uint32_t body_get_collision_mask(RID p_body) const=0; // common body variables enum BodyParameter { @@ -539,6 +540,7 @@ public: virtual void step(float p_step)=0; virtual void sync()=0; virtual void flush_queries()=0; + virtual void end_sync()=0; virtual void finish()=0; enum ProcessInfo { diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index 4feb1b5269d..e02601af416 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -681,6 +681,7 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT( AREA_PARAM_GRAVITY ); BIND_CONSTANT( AREA_PARAM_GRAVITY_VECTOR ); BIND_CONSTANT( AREA_PARAM_GRAVITY_IS_POINT ); + BIND_CONSTANT( AREA_PARAM_GRAVITY_DISTANCE_SCALE ); BIND_CONSTANT( AREA_PARAM_GRAVITY_POINT_ATTENUATION ); BIND_CONSTANT( AREA_PARAM_DENSITY ); BIND_CONSTANT( AREA_PARAM_PRIORITY ); diff --git a/servers/physics_server.h b/servers/physics_server.h index ffb462af22a..f66ea590b82 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -298,6 +298,7 @@ public: AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, + AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, AREA_PARAM_DENSITY, AREA_PARAM_PRIORITY @@ -338,7 +339,10 @@ public: virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const=0; virtual Transform area_get_transform(RID p_area) const=0; + virtual void area_set_monitorable(RID p_area,bool p_monitorable)=0; + virtual void area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method)=0; + virtual void area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method)=0; virtual void area_set_ray_pickable(RID p_area,bool p_enable)=0; virtual bool area_is_ray_pickable(RID p_area) const=0; diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h new file mode 100644 index 00000000000..cbb75129d01 --- /dev/null +++ b/servers/server_wrap_mt_common.h @@ -0,0 +1,700 @@ + +#define FUNC0R(m_r,m_type)\ + virtual m_r m_type() { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type();\ + }\ + } + + +#define FUNCRID(m_type)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create() { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create();\ + }\ + } + +#define FUNC1RID(m_type,m_arg1)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1);\ + }\ + } + +#define FUNC2RID(m_type,m_arg1,m_arg2)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1,m_arg2 p2) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,p2,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1,p2);\ + }\ + } + +#define FUNC3RID(m_type,m_arg1,m_arg2,m_arg3)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1,m_arg2 p2,m_arg3 p3) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,p2,p3,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1,p2,p3);\ + }\ + } + + +#define FUNC4RID(m_type,m_arg1,m_arg2,m_arg3,m_arg4)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1,m_arg2 p2,m_arg3 p3,m_arg4 p4) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,p2,p3,p4,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1,p2,p3,p4);\ + }\ + } + + +#define FUNC5RID(m_type,m_arg1,m_arg2,m_arg3,m_arg4,m_arg5)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1,m_arg2 p2,m_arg3 p3,m_arg4 p4,m_arg5 p5) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,p2,p3,p4,p5,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1,p2,p3,p4,p5);\ + }\ + } + +#define FUNC0RC(m_r,m_type)\ + virtual m_r m_type() const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type();\ + }\ + } + + +#define FUNC0(m_type)\ + virtual void m_type() { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type);\ + } else {\ + server_name->m_type();\ + }\ + } + +#define FUNC0C(m_type)\ + virtual void m_type() const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type);\ + } else {\ + server_name->m_type();\ + }\ + } + + +#define FUNC0S(m_type)\ + virtual void m_type() { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type);\ + } else {\ + server_name->m_type();\ + }\ + } + +#define FUNC0SC(m_type)\ + virtual void m_type() const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type);\ + } else {\ + server_name->m_type();\ + }\ + } + + +/////////////////////////////////////////////// + + +#define FUNC1R(m_r,m_type,m_arg1)\ + virtual m_r m_type(m_arg1 p1) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1);\ + }\ + } + +#define FUNC1RC(m_r,m_type,m_arg1)\ + virtual m_r m_type(m_arg1 p1) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1);\ + }\ + } + + +#define FUNC1S(m_type,m_arg1)\ + virtual void m_type(m_arg1 p1) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1);\ + } else {\ + server_name->m_type(p1);\ + }\ + } + +#define FUNC1SC(m_type,m_arg1)\ + virtual void m_type(m_arg1 p1) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1);\ + } else {\ + server_name->m_type(p1);\ + }\ + } + + +#define FUNC1(m_type,m_arg1)\ + virtual void m_type(m_arg1 p1) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1);\ + } else {\ + server_name->m_type(p1);\ + }\ + } + +#define FUNC1C(m_type,m_arg1)\ + virtual void m_type(m_arg1 p1) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1);\ + } else {\ + server_name->m_type(p1);\ + }\ + } + + + + +#define FUNC2R(m_r,m_type,m_arg1, m_arg2)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2);\ + }\ + } + +#define FUNC2RC(m_r,m_type,m_arg1, m_arg2)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2);\ + }\ + } + + +#define FUNC2S(m_type,m_arg1, m_arg2)\ + virtual void m_type(m_arg1 p1, m_arg2 p2) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2);\ + } else {\ + server_name->m_type(p1, p2);\ + }\ + } + +#define FUNC2SC(m_type,m_arg1, m_arg2)\ + virtual void m_type(m_arg1 p1, m_arg2 p2) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2);\ + } else {\ + server_name->m_type(p1, p2);\ + }\ + } + + +#define FUNC2(m_type,m_arg1, m_arg2)\ + virtual void m_type(m_arg1 p1, m_arg2 p2) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2);\ + } else {\ + server_name->m_type(p1, p2);\ + }\ + } + +#define FUNC2C(m_type,m_arg1, m_arg2)\ + virtual void m_type(m_arg1 p1, m_arg2 p2) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2);\ + } else {\ + server_name->m_type(p1, p2);\ + }\ + } + + + + +#define FUNC3R(m_r,m_type,m_arg1, m_arg2, m_arg3)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3);\ + }\ + } + +#define FUNC3RC(m_r,m_type,m_arg1, m_arg2, m_arg3)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3,&ret);\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3);\ + }\ + } + + +#define FUNC3S(m_type,m_arg1, m_arg2, m_arg3)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3);\ + } else {\ + server_name->m_type(p1, p2, p3);\ + }\ + } + +#define FUNC3SC(m_type,m_arg1, m_arg2, m_arg3)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3);\ + } else {\ + server_name->m_type(p1, p2, p3);\ + }\ + } + + +#define FUNC3(m_type,m_arg1, m_arg2, m_arg3)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3);\ + } else {\ + server_name->m_type(p1, p2, p3);\ + }\ + } + +#define FUNC3C(m_type,m_arg1, m_arg2, m_arg3)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3);\ + } else {\ + server_name->m_type(p1, p2, p3);\ + }\ + } + + + + +#define FUNC4R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4);\ + }\ + } + +#define FUNC4RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4);\ + }\ + } + + +#define FUNC4S(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4);\ + } else {\ + server_name->m_type(p1, p2, p3, p4);\ + }\ + } + +#define FUNC4SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4);\ + } else {\ + server_name->m_type(p1, p2, p3, p4);\ + }\ + } + + +#define FUNC4(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4);\ + } else {\ + server_name->m_type(p1, p2, p3, p4);\ + }\ + } + +#define FUNC4C(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4);\ + } else {\ + server_name->m_type(p1, p2, p3, p4);\ + }\ + } + + + + +#define FUNC5R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + +#define FUNC5RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + + +#define FUNC5S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + +#define FUNC5SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + + +#define FUNC5(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + +#define FUNC5C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + + + + +#define FUNC6R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + +#define FUNC6RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6,&ret);\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + + +#define FUNC6S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + +#define FUNC6SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + + +#define FUNC6(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + +#define FUNC6C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + + + + +#define FUNC7R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + +#define FUNC7RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + + +#define FUNC7S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + +#define FUNC7SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + + +#define FUNC7(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + +#define FUNC7C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 79365f7db6e..50336e07f4b 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -502,7 +502,7 @@ public: virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug)=0; virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass )=0; - virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection)=0; + virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint)=0; virtual void add_light( RID p_light_instance )=0; ///< all "add_light" calls happen before add_geometry calls diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp index 8db1cbf6e50..e32f47b3d8e 100644 --- a/servers/visual/rasterizer_dummy.cpp +++ b/servers/visual/rasterizer_dummy.cpp @@ -1497,7 +1497,7 @@ void RasterizerDummy::begin_shadow_map( RID p_light_instance, int p_shadow_pass } -void RasterizerDummy::set_camera(const Transform& p_world,const CameraMatrix& p_projection) { +void RasterizerDummy::set_camera(const Transform& p_world, const CameraMatrix& p_projection, bool p_ortho_hint) { } diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h index 318cf6ff993..cc3c1724a4a 100644 --- a/servers/visual/rasterizer_dummy.h +++ b/servers/visual/rasterizer_dummy.h @@ -679,7 +679,7 @@ public: virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug); virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass ); - virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection); + virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint); virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index a547da9b61b..3fc90fd46d5 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -6302,7 +6302,7 @@ void VisualServerRaster::_render_no_camera(Viewport *p_viewport,Camera *p_camera else environment=p_scenario->fallback_environment; - rasterizer->set_camera(Transform(),CameraMatrix()); + rasterizer->set_camera(Transform(),CameraMatrix(),false); rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug); rasterizer->set_viewport(viewport_rect); rasterizer->end_scene(); @@ -6318,7 +6318,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S /* STEP 1 - SETUP CAMERA */ CameraMatrix camera_matrix; - + bool ortho=false; + switch(p_camera->type) { case Camera::ORTHOGONAL: { @@ -6330,6 +6331,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S p_camera->vaspect ); + ortho=true; } break; case Camera::PERSPECTIVE: { @@ -6341,12 +6343,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S p_camera->vaspect ); + ortho=false; } break; } - rasterizer->set_camera(p_camera->transform, camera_matrix); + rasterizer->set_camera(p_camera->transform, camera_matrix,ortho); Vector planes = camera_matrix.get_projection_planes(p_camera->transform); @@ -7358,7 +7361,7 @@ void VisualServerRaster::_draw_cursors_and_margins() { rasterizer->canvas_end_rect(); }; -void VisualServerRaster::flush() { +void VisualServerRaster::sync() { //do none } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index f3b94b73df8..e2940c216be 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1237,7 +1237,7 @@ public: /* EVENT QUEUING */ virtual void draw(); - virtual void flush(); + virtual void sync(); virtual void init(); virtual void finish(); diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp index a044981bbbb..19dff3d36c7 100644 --- a/servers/visual/visual_server_wrap_mt.cpp +++ b/servers/visual/visual_server_wrap_mt.cpp @@ -96,16 +96,19 @@ void VisualServerWrapMT::thread_loop() { /* EVENT QUEUING */ -void VisualServerWrapMT::flush() { +void VisualServerWrapMT::sync() { if (create_thread) { + /* TODO: sync with the thread */ + + /* ERR_FAIL_COND(!draw_mutex); draw_mutex->lock(); draw_pending++; //cambiar por un saferefcount draw_mutex->unlock(); - - command_queue.push( this, &VisualServerWrapMT::thread_flush); + */ + //command_queue.push( this, &VisualServerWrapMT::thread_flush); } else { command_queue.flush_all(); //flush all pending from other threads @@ -118,15 +121,16 @@ void VisualServerWrapMT::draw() { if (create_thread) { + /* TODO: Make it draw ERR_FAIL_COND(!draw_mutex); draw_mutex->lock(); draw_pending++; //cambiar por un saferefcount draw_mutex->unlock(); command_queue.push( this, &VisualServerWrapMT::thread_draw); + */ } else { - command_queue.flush_all(); //flush all pending from other threads visual_server->draw(); } } @@ -187,8 +191,8 @@ VisualServerWrapMT::VisualServerWrapMT(VisualServer* p_contained,bool p_create_t draw_pending=0; draw_thread_up=false; alloc_mutex=Mutex::create(); - texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",20); - mesh_pool_max_size=GLOBAL_DEF("render/thread_meshes_prealloc",20); + texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",5); + mesh_pool_max_size=GLOBAL_DEF("core/rid_pool_prealloc",20); if (!p_create_thread) { server_thread=Thread::get_caller_ID(); } else { diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 3d972438270..6719342a6a6 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -79,554 +79,10 @@ class VisualServerWrapMT : public VisualServer { public: -#define FUNC0R(m_r,m_type)\ - virtual m_r m_type() { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type();\ - }\ - } - -#define FUNCRID(m_type)\ - int m_type##allocn() {\ - for(int i=0;im_type##_create() );\ - }\ - return 0;\ - }\ - void m_type##_free_cached_ids() {\ - while (m_type##_id_pool.size()) {\ - free(m_type##_id_pool.front()->get());\ - m_type##_id_pool.pop_front();\ - }\ - }\ - virtual RID m_type##_create() { \ - if (Thread::get_caller_ID()!=server_thread) {\ - RID rid;\ - alloc_mutex->lock();\ - if (m_type##_id_pool.size()==0) {\ - int ret;\ - command_queue.push_and_ret( this, &VisualServerWrapMT::m_type##allocn,&ret);\ - }\ - rid=m_type##_id_pool.front()->get();\ - m_type##_id_pool.pop_front();\ - alloc_mutex->unlock();\ - return rid;\ - } else {\ - return visual_server->m_type##_create();\ - }\ - } - -#define FUNC0RC(m_r,m_type)\ - virtual m_r m_type() const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type();\ - }\ - } - - -#define FUNC0(m_type)\ - virtual void m_type() { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type);\ - } else {\ - visual_server->m_type();\ - }\ - } - -#define FUNC0C(m_type)\ - virtual void m_type() const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type);\ - } else {\ - visual_server->m_type();\ - }\ - } - - -#define FUNC0S(m_type)\ - virtual void m_type() { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type);\ - } else {\ - visual_server->m_type();\ - }\ - } - -#define FUNC0SC(m_type)\ - virtual void m_type() const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type);\ - } else {\ - visual_server->m_type();\ - }\ - } - - -/////////////////////////////////////////////// - - -#define FUNC1R(m_r,m_type,m_arg1)\ - virtual m_r m_type(m_arg1 p1) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1);\ - }\ - } - -#define FUNC1RC(m_r,m_type,m_arg1)\ - virtual m_r m_type(m_arg1 p1) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1);\ - }\ - } - - -#define FUNC1S(m_type,m_arg1)\ - virtual void m_type(m_arg1 p1) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1);\ - } else {\ - visual_server->m_type(p1);\ - }\ - } - -#define FUNC1SC(m_type,m_arg1)\ - virtual void m_type(m_arg1 p1) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1);\ - } else {\ - visual_server->m_type(p1);\ - }\ - } - - -#define FUNC1(m_type,m_arg1)\ - virtual void m_type(m_arg1 p1) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1);\ - } else {\ - visual_server->m_type(p1);\ - }\ - } - -#define FUNC1C(m_type,m_arg1)\ - virtual void m_type(m_arg1 p1) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1);\ - } else {\ - visual_server->m_type(p1);\ - }\ - } - - - - -#define FUNC2R(m_r,m_type,m_arg1, m_arg2)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2);\ - }\ - } - -#define FUNC2RC(m_r,m_type,m_arg1, m_arg2)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2);\ - }\ - } - - -#define FUNC2S(m_type,m_arg1, m_arg2)\ - virtual void m_type(m_arg1 p1, m_arg2 p2) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2);\ - } else {\ - visual_server->m_type(p1, p2);\ - }\ - } - -#define FUNC2SC(m_type,m_arg1, m_arg2)\ - virtual void m_type(m_arg1 p1, m_arg2 p2) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2);\ - } else {\ - visual_server->m_type(p1, p2);\ - }\ - } - - -#define FUNC2(m_type,m_arg1, m_arg2)\ - virtual void m_type(m_arg1 p1, m_arg2 p2) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2);\ - } else {\ - visual_server->m_type(p1, p2);\ - }\ - } - -#define FUNC2C(m_type,m_arg1, m_arg2)\ - virtual void m_type(m_arg1 p1, m_arg2 p2) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2);\ - } else {\ - visual_server->m_type(p1, p2);\ - }\ - } - - - - -#define FUNC3R(m_r,m_type,m_arg1, m_arg2, m_arg3)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3);\ - }\ - } - -#define FUNC3RC(m_r,m_type,m_arg1, m_arg2, m_arg3)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3,&ret);\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3);\ - }\ - } - - -#define FUNC3S(m_type,m_arg1, m_arg2, m_arg3)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3);\ - } else {\ - visual_server->m_type(p1, p2, p3);\ - }\ - } - -#define FUNC3SC(m_type,m_arg1, m_arg2, m_arg3)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3);\ - } else {\ - visual_server->m_type(p1, p2, p3);\ - }\ - } - - -#define FUNC3(m_type,m_arg1, m_arg2, m_arg3)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3);\ - } else {\ - visual_server->m_type(p1, p2, p3);\ - }\ - } - -#define FUNC3C(m_type,m_arg1, m_arg2, m_arg3)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3);\ - } else {\ - visual_server->m_type(p1, p2, p3);\ - }\ - } - - - - -#define FUNC4R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - -#define FUNC4RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - - -#define FUNC4S(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - -#define FUNC4SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - - -#define FUNC4(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - -#define FUNC4C(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - - - - -#define FUNC5R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - -#define FUNC5RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - - -#define FUNC5S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - -#define FUNC5SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - - -#define FUNC5(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - -#define FUNC5C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - - - - -#define FUNC6R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - -#define FUNC6RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6,&ret);\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - - -#define FUNC6S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - -#define FUNC6SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - - -#define FUNC6(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - -#define FUNC6C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - - - - -#define FUNC7R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - -#define FUNC7RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - - -#define FUNC7S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - -#define FUNC7SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - - -#define FUNC7(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - -#define FUNC7C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - - - +#define ServerName VisualServer +#define ServerNameWrapMT VisualServerWrapMT +#define server_name visual_server +#include "servers/server_wrap_mt_common.h" //FUNC0R(RID,texture_create); FUNCRID(texture); @@ -1225,7 +681,7 @@ public: virtual void init(); virtual void finish(); virtual void draw(); - virtual void flush(); + virtual void sync(); FUNC0RC(bool,has_changed); /* RENDER INFO */ @@ -1242,7 +698,15 @@ public: VisualServerWrapMT(VisualServer* p_contained,bool p_create_thread); ~VisualServerWrapMT(); +#undef ServerName +#undef ServerNameWrapMT +#undef server_name + }; +#ifdef DEBUG_SYNC +#undef DEBUG_SYNC +#endif +#undef SYNC_DEBUG #endif diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 78320f277e1..25e6a68469c 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -554,7 +554,7 @@ void VisualServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("mesh_add_surface_from_planes"),&VisualServer::mesh_add_surface_from_planes); ObjectTypeDB::bind_method(_MD("draw"),&VisualServer::draw); - ObjectTypeDB::bind_method(_MD("flush"),&VisualServer::flush); + ObjectTypeDB::bind_method(_MD("sync"),&VisualServer::sync); ObjectTypeDB::bind_method(_MD("free"),&VisualServer::free); ObjectTypeDB::bind_method(_MD("set_default_clear_color"),&VisualServer::set_default_clear_color); diff --git a/servers/visual_server.h b/servers/visual_server.h index c1c2ef4fd3c..ef63907e345 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -1097,7 +1097,7 @@ public: /* EVENT QUEUING */ virtual void draw()=0; - virtual void flush()=0; + virtual void sync()=0; virtual bool has_changed() const=0; virtual void init()=0; virtual void finish()=0; diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index 63ab186a38b..bb6f7e9a6f7 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -44,11 +44,207 @@ */ +class AnimationCurveEdit : public Control { + OBJ_TYPE( AnimationCurveEdit, Control ); +public: + enum Mode { + MODE_DISABLED, + MODE_SINGLE, + MODE_MULTIPLE + }; +private: + + Set multiples; + float transition; + Mode mode; + + void _notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + + + RID ci = get_canvas_item(); + + Size2 s = get_size(); + Rect2 r(Point2(),s); + + //r=r.grow(3); + Ref sb = get_stylebox("normal","LineEdit"); + sb->draw(ci,r); + r.size-=sb->get_minimum_size(); + r.pos+=sb->get_offset(); + //VisualServer::get_singleton()->canvas_item_add + + Ref f = get_font("font","Label"); + r=r.grow(-2); + Color color = get_color("font_color","Label"); + + int points = 48; + if (mode==MODE_MULTIPLE) { + + int max_draw = 16; + Color mcolor=color; + mcolor.a*=0.3; + + Set::Element *E=multiples.front(); + for(int j=0;j<16;j++) { + + if (!E) + break; + + float prev=1.0; + float exp=E->get(); + bool flip=false;//hint_text=="attenuation"; + + + for(int i=1;i<=points;i++) { + + float ifl = i/float(points); + float iflp = (i-1)/float(points); + + float h = 1.0-Math::ease(ifl,exp); + + if (flip) { + ifl=1.0-ifl; + iflp=1.0-iflp; + } + + VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),mcolor); + prev=h; + } + + E=E->next(); + } + } + + float exp=transition; + if (mode!=MODE_DISABLED) { + + + float prev=1.0; + + bool flip=false;//hint_text=="attenuation"; + + + for(int i=1;i<=points;i++) { + + float ifl = i/float(points); + float iflp = (i-1)/float(points); + + float h = 1.0-Math::ease(ifl,exp); + + if (flip) { + ifl=1.0-ifl; + iflp=1.0-iflp; + } + + VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),color); + prev=h; + } + } + + String txt=String::num(exp,2); + if (mode==MODE_DISABLED) { + txt="Disabled"; + } else if (mode==MODE_MULTIPLE) { + txt+=" - All Selection"; + } + + f->draw(ci,Point2(10,10+f->get_ascent()),txt,color); + + } + } + + void _input_event(const InputEvent& p_ev) { + if (p_ev.type==InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) { + + if (mode==MODE_DISABLED) + return; + + float rel = p_ev.mouse_motion.relative_x; + if (rel==0) + return; + + bool flip=false; + + if (flip) + rel=-rel; + + float val = transition; + if (val==0) + return; + bool sg = val < 0; + val = Math::absf(val); + + val = Math::log(val)/Math::log(2); + //logspace + val+=rel*0.05; + // + + val = Math::pow(2,val); + if (sg) + val=-val; + + transition=val; + update(); + //emit_signal("variant_changed"); + emit_signal("transition_changed",transition); + } + } + +public: + + static void _bind_methods() { + + // ObjectTypeDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj); + ObjectTypeDB::bind_method("_input_event",&AnimationCurveEdit::_input_event); + ADD_SIGNAL(MethodInfo("transition_changed")); + } + + void set_mode(Mode p_mode) { + + mode=p_mode; + update(); + } + + void clear_multiples() { multiples.clear(); update();} + void set_multiple(float p_transition) { + + multiples.insert(p_transition); + } + + void set_transition(float p_transition) { + transition=p_transition; + update(); + } + + float get_transition() const { + return transition; + } + + void force_transition(float p_value) { + if (mode==MODE_DISABLED) + return; + transition=p_value; + emit_signal("transition_changed",p_value); + update(); + } + + AnimationCurveEdit() { + + transition=1.0; + set_default_cursor_shape(CURSOR_HSPLIT); + mode=MODE_DISABLED; + } + +}; + class AnimationKeyEdit : public Object { OBJ_TYPE(AnimationKeyEdit,Object); public: bool setting; + bool hidden; static void _bind_methods() { @@ -56,12 +252,12 @@ public: ObjectTypeDB::bind_method("_key_ofs_changed",&AnimationKeyEdit::_key_ofs_changed); } - PopupDialog *ke_dialog; + //PopupDialog *ke_dialog; void _update_obj(const Ref &p_anim) { if (setting) return; - if (!ke_dialog->is_visible()) + if (hidden) return; if (!(animation==p_anim)) return; @@ -69,7 +265,7 @@ public: } void _key_ofs_changed(const Ref &p_anim,float from, float to) { - if (!ke_dialog->is_visible()) + if (hidden) return; if (!(animation==p_anim)) return; @@ -408,8 +604,8 @@ public: } break; } - if (animation->track_get_type(track)!=Animation::TYPE_METHOD) - p_list->push_back( PropertyInfo( Variant::REAL, "easing", PROPERTY_HINT_EXP_EASING)); + //if (animation->track_get_type(track)!=Animation::TYPE_METHOD) + // p_list->push_back( PropertyInfo( Variant::REAL, "easing", PROPERTY_HINT_EXP_EASING)); } UndoRedo *undo_redo; @@ -425,7 +621,7 @@ public: _change_notify(); } - AnimationKeyEdit() { key_ofs=0; track=-1; setting=false; } + AnimationKeyEdit() { hidden=true; key_ofs=0; track=-1; setting=false; } }; @@ -610,6 +806,8 @@ void AnimationKeyEditor::_menu_track(int p_type) { selection=new_selection; track_editor->update(); + _edit_if_single_selection(); + } @@ -689,8 +887,31 @@ void AnimationKeyEditor::_menu_track(int p_type) { optimize_dialog->popup_centered(Size2(250,180)); } break; + case CURVE_SET_LINEAR: { + curve_edit->force_transition(1.0); + } break; + case CURVE_SET_IN: { + curve_edit->force_transition(4.0); + + } break; + case CURVE_SET_OUT: { + + curve_edit->force_transition(0.25); + } break; + case CURVE_SET_INOUT: { + curve_edit->force_transition(-4); + + } break; + case CURVE_SET_OUTIN: { + + curve_edit->force_transition(-0.25); + } break; + case CURVE_SET_CONSTANT: { + + curve_edit->force_transition(0); + } break; } @@ -774,6 +995,7 @@ void AnimationKeyEditor::_track_editor_draw() { h_scroll->hide(); menu_track->set_disabled(true); edit_button->set_disabled(true); + key_editor_tab->hide(); move_up_button->set_disabled(true); move_down_button->set_disabled(true); remove_button->set_disabled(true); @@ -785,6 +1007,8 @@ void AnimationKeyEditor::_track_editor_draw() { move_up_button->set_disabled(false); move_down_button->set_disabled(false); remove_button->set_disabled(false); + if (edit_button->is_pressed()) + key_editor_tab->show(); te_drawing=true; @@ -1000,8 +1224,13 @@ void AnimationKeyEditor::_track_editor_draw() { } } + Color sep_color=color; + color.a*=0.5; + for(int i=0;iget_val() + i; if (idx>=animation->get_track_count()) break; @@ -1090,6 +1319,7 @@ void AnimationKeyEditor::_track_editor_draw() { float key_hofs = -Math::floor(type_icon[tt]->get_height()/2); int kc=animation->track_get_key_count(idx); + bool first=true; for(int i=0;itrack_get_key_time(idx,i); if (timekeys_to) + if (time>keys_to) { + + if (first && i>0 && animation->track_get_key_value(idx,i)==animation->track_get_key_value(idx,i-1)) { + //draw whole line + te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(settings_limit,y+h/2),color); + } + break; + } + float x = key_hofs + name_limit + (time-keys_from)*zoom_scale; Ref tex = type_icon[tt]; @@ -1116,7 +1354,22 @@ void AnimationKeyEditor::_track_editor_draw() { if (mouse_over.over==MouseOver::OVER_KEY && mouse_over.track==idx && mouse_over.over_key==i) tex=type_hover; + Variant value = animation->track_get_key_value(idx,i); + if (first && i>0 && value==animation->track_get_key_value(idx,i-1)) { + + te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(x,y+h/2),color); + } + + if (itrack_get_key_value(idx,i+1)) { + float x_n = key_hofs + name_limit + (animation->track_get_key_time(idx,i+1)-keys_from)*zoom_scale; + + x_n = MIN( x_n, settings_limit); + te->draw_line(ofs+Point2(x_n,y+h/2),ofs+Point2(x,y+h/2),color); + + } + te->draw_texture(tex,ofs+Point2(x,y+key_vofs).floor()); + first=false; } } @@ -1226,7 +1479,9 @@ void AnimationKeyEditor::_clear_selection_for_anim(const Ref& p_anim) if (!(animation==p_anim)) return; - selection.clear(); + //selection.clear(); + _clear_selection(); + } void AnimationKeyEditor::_select_at_anim(const Ref& p_anim,int p_track,float p_pos){ @@ -1244,6 +1499,7 @@ void AnimationKeyEditor::_select_at_anim(const Ref& p_anim,int p_trac ki.pos=p_pos; selection.insert(sk,ki); + } @@ -1283,6 +1539,83 @@ PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) { } +void AnimationKeyEditor::_curve_transition_changed(float p_what) { + + if (selection.size()==0) + return; + if (selection.size()==1) + undo_redo->create_action("Edit Node Curve",true); + else + undo_redo->create_action("Edit Selection Curve",true); + + for(Map::Element *E=selection.front();E;E=E->next()) { + + int track = E->key().track; + int key = E->key().key; + float prev_val = animation->track_get_key_transition(track,key); + undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",track,key,p_what); + undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",track,key,prev_val); + } + + undo_redo->commit_action(); + +} + +void AnimationKeyEditor::_toggle_edit_curves() { + + if (edit_button->is_pressed()) + key_editor_tab->show(); + else + key_editor_tab->hide(); +} + + +bool AnimationKeyEditor::_edit_if_single_selection() { + + if (selection.size()!=1) { + + if (selection.size()==0) { + curve_edit->set_mode(AnimationCurveEdit::MODE_DISABLED); + print_line("disable"); + } else { + + curve_edit->set_mode(AnimationCurveEdit::MODE_MULTIPLE); + curve_edit->set_transition(1.0); + curve_edit->clear_multiples(); + //add all + for(Map::Element *E=selection.front();E;E=E->next()) { + + curve_edit->set_multiple(animation->track_get_key_transition(E->key().track,E->key().key)); + } + print_line("multiple"); + + } + return false; + } + curve_edit->set_mode(AnimationCurveEdit::MODE_SINGLE); + print_line("regular"); + + int idx = selection.front()->key().track; + int key = selection.front()->key().key; + { + + key_edit->animation=animation; + key_edit->track=idx; + key_edit->key_ofs=animation->track_get_key_time(idx,key); + key_edit->hint=_find_hint_for_track(idx); + key_edit->notify_change(); + + curve_edit->set_transition(animation->track_get_key_transition(idx,key)); + + /*key_edit_dialog->set_size( Size2( 200,200) ); + key_edit_dialog->set_pos( track_editor->get_global_pos() + ofs + mpos +Point2(-100,20)); + key_edit_dialog->popup();*/ + + } + + return true; + +} void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { @@ -1364,9 +1697,12 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key)); } + undo_redo->add_do_method(this,"_clear_selection_for_anim",animation); + undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation); undo_redo->commit_action(); - selection.clear(); + //selection.clear(); accept_event(); + _edit_if_single_selection(); } } else if (animation.is_valid() && animation->get_track_count()>0) { @@ -1552,20 +1888,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { } - if (mb.mod.command || edit_button->is_pressed()) { - key_edit->animation=animation; - key_edit->track=idx; - key_edit->key_ofs=animation->track_get_key_time(idx,key); - key_edit->hint=_find_hint_for_track(idx); - - key_edit->notify_change(); - - key_edit_dialog->set_size( Size2( 200,200) ); - key_edit_dialog->set_pos( track_editor->get_global_pos() + ofs + mpos +Point2(-100,20)); - key_edit_dialog->popup(); - - } SelectedKey sk; sk.track=idx; @@ -1577,7 +1900,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (!mb.mod.shift && !selection.has(sk)) - selection.clear(); + _clear_selection(); selection.insert(sk,ki); @@ -1588,7 +1911,10 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { selected_track=idx; track_editor->update(); - + if (_edit_if_single_selection() && mb.mod.command) { + edit_button->set_pressed(true); + key_editor_tab->show(); + } } else { //button column int ofsx = size.width - mpos.x; @@ -1824,7 +2150,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (from_track>to_track) { if (!click.shift) - selection.clear(); + _clear_selection(); + _edit_if_single_selection(); break; } @@ -1842,12 +2169,13 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (from_track > tracks_to || to_track < tracks_from) { if (!click.shift) - selection.clear(); + _clear_selection(); + _edit_if_single_selection(); break; } if (!click.shift) - selection.clear(); + _clear_selection(); int higher_track=0x7FFFFFFF; @@ -1880,6 +2208,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { } + _edit_if_single_selection(); + } break; case ClickOver::CLICK_MOVE_KEYS: { @@ -1891,8 +2221,9 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (!click.shift) { KeyInfo ki=selection[click.selk]; - selection.clear(); + _clear_selection(); selection[click.selk]=ki; + _edit_if_single_selection(); } break; @@ -2007,6 +2338,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { } undo_redo->commit_action(); + _edit_if_single_selection(); } break; default: {} @@ -2348,20 +2680,33 @@ void AnimationKeyEditor::_notification(int p_what) { optimize_dialog->connect("confirmed",this,"_animation_optimize"); menu_track->get_popup()->add_child(tpp); - menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions"); - menu_track->get_popup()->add_separator(); + //menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions"); + //menu_track->get_popup()->add_separator(); menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE); + curve_linear->set_icon(get_icon("CurveLinear","EditorIcons")); + curve_in->set_icon(get_icon("CurveIn","EditorIcons")); + curve_out->set_icon(get_icon("CurveOut","EditorIcons")); + curve_inout->set_icon(get_icon("CurveInOut","EditorIcons")); + curve_outin->set_icon(get_icon("CurveOutIn","EditorIcons")); + curve_constant->set_icon(get_icon("CurveConstant","EditorIcons")); - + curve_linear->connect("pressed",this,"_menu_track",varray(CURVE_SET_LINEAR)); + curve_in->connect("pressed",this,"_menu_track",varray(CURVE_SET_IN)); + curve_out->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUT)); + curve_inout->connect("pressed",this,"_menu_track",varray(CURVE_SET_INOUT)); + curve_outin->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUTIN)); + curve_constant->connect("pressed",this,"_menu_track",varray(CURVE_SET_CONSTANT)); move_up_button->set_icon(get_icon("MoveUp","EditorIcons")); move_down_button->set_icon(get_icon("MoveDown","EditorIcons")); remove_button->set_icon(get_icon("Remove","EditorIcons")); edit_button->set_icon(get_icon("EditKey","EditorIcons")); + edit_button->connect("pressed",this,"_toggle_edit_curves"); loop->set_icon(get_icon("Loop","EditorIcons")); + curve_edit->connect("transition_changed",this,"_curve_transition_changed"); //edit_button->add_color_override("font_color",get_color("font_color","Tree")); //edit_button->add_color_override("font_color_hover",get_color("font_color","Tree")); @@ -2456,6 +2801,17 @@ void AnimationKeyEditor::_update_menu() { updating=false; } +void AnimationKeyEditor::_clear_selection() { + + selection.clear(); + key_edit->animation=Ref(); + key_edit->track=0; + key_edit->key_ofs=0; + key_edit->hint=PropertyInfo(); + key_edit->notify_change(); + +} + void AnimationKeyEditor::set_animation(const Ref& p_anim) { @@ -2466,11 +2822,12 @@ void AnimationKeyEditor::set_animation(const Ref& p_anim) { animation->connect("changed",this,"_update_paths"); timeline_pos=0; - selection.clear(); + _clear_selection(); _update_paths(); _update_menu(); selected_track=-1; + _edit_if_single_selection(); } void AnimationKeyEditor::set_root(Node *p_root) { @@ -2591,6 +2948,7 @@ void AnimationKeyEditor::insert_transform_key(Spatial *p_node,const String& p_su id.value=p_xform; id.type=Animation::TYPE_TRANSFORM; id.query="node '"+p_node->get_name()+"'"; + id.advance=false; //dialog insert @@ -2643,6 +3001,7 @@ void AnimationKeyEditor::insert_node_value_key(Node* p_node, const String& p_pro id.value=p_value; id.type=Animation::TYPE_VALUE; id.query="property '"+p_property+"'"; + id.advance=false; //dialog insert _query_insert(id); @@ -2650,7 +3009,7 @@ void AnimationKeyEditor::insert_node_value_key(Node* p_node, const String& p_pro } -void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant& p_value) { +void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant& p_value,bool p_advance) { ERR_FAIL_COND(!root); //let's build a node path @@ -2696,6 +3055,7 @@ void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant id.value=p_value; id.type=Animation::TYPE_VALUE; id.query="property '"+p_property+"'"; + id.advance=p_advance; //dialog insert _query_insert(id); @@ -2928,13 +3288,31 @@ void AnimationKeyEditor::_insert_delay() { undo_redo->create_action("Anim Insert"); int last_track = animation->get_track_count(); + bool advance=false; while(insert_data.size()) { + if (insert_data.front()->get().advance) + advance=true; last_track=_confirm_insert(insert_data.front()->get(),last_track); insert_data.pop_front(); } undo_redo->commit_action(); + + if (advance) { + float step = animation->get_step(); + if (step==0) + step=1; + + float pos=timeline_pos; + + pos=Math::stepify(pos+step,step); + if (pos>animation->get_length()) + pos=animation->get_length(); + timeline_pos=pos; + track_pos->update(); + emit_signal("timeline_changed",pos); + } insert_queue=false; } @@ -3122,12 +3500,15 @@ void AnimationKeyEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_animation"),&AnimationKeyEditor::set_animation); ObjectTypeDB::bind_method(_MD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize); + ObjectTypeDB::bind_method(_MD("_curve_transition_changed"),&AnimationKeyEditor::_curve_transition_changed); + ObjectTypeDB::bind_method(_MD("_toggle_edit_curves"),&AnimationKeyEditor::_toggle_edit_curves); ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) ); ADD_SIGNAL( MethodInfo("keying_changed" ) ); ADD_SIGNAL( MethodInfo("timeline_changed", PropertyInfo(Variant::REAL,"pos") ) ); ADD_SIGNAL( MethodInfo("animation_len_changed", PropertyInfo(Variant::REAL,"len") ) ); + ADD_SIGNAL( MethodInfo("key_edited", PropertyInfo(Variant::INT,"track"), PropertyInfo(Variant::INT,"key") ) ); } @@ -3219,12 +3600,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h hb->add_child( memnew( VSeparator ) ); - edit_button = memnew( ToolButton ); - edit_button->set_toggle_mode(true); - edit_button->set_focus_mode(FOCUS_NONE); - edit_button->set_disabled(true); - hb->add_child(edit_button); - edit_button->set_tooltip("Enable editing of individual keys by clicking them."); move_up_button = memnew( ToolButton ); hb->add_child(move_up_button); @@ -3247,6 +3622,15 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h remove_button->set_disabled(true); remove_button->set_tooltip("Remove selected track."); + hb->add_child(memnew( VSeparator )); + + edit_button = memnew( ToolButton ); + edit_button->set_toggle_mode(true); + edit_button->set_focus_mode(FOCUS_NONE); + edit_button->set_disabled(true); + + hb->add_child(edit_button); + edit_button->set_tooltip("Enable editing of individual keys by clicking them."); optimize_dialog = memnew( ConfirmationDialog ); add_child(optimize_dialog); @@ -3297,7 +3681,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h // menu->get_popup()->connect("item_pressed",this,"_menu_callback"); ec = memnew (Control); - ec->set_custom_minimum_size(Size2(0,50)); + ec->set_custom_minimum_size(Size2(0,150)); add_child(ec); ec->set_v_size_flags(SIZE_EXPAND_FILL); @@ -3313,6 +3697,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h track_editor->set_focus_mode(Control::FOCUS_ALL); track_editor->set_h_size_flags(SIZE_EXPAND_FILL); + track_pos = memnew( Control ); track_pos->set_area_as_parent_rect(); track_pos->set_ignore_mouse(true); @@ -3325,6 +3710,56 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h v_scroll->connect("value_changed",this,"_scroll_changed"); v_scroll->set_val(0); + key_editor_tab = memnew(TabContainer); + hb->add_child(key_editor_tab); + key_editor_tab->set_custom_minimum_size(Size2(200,0)); + + key_editor = memnew( PropertyEditor ); + key_editor->set_area_as_parent_rect(); + key_editor->hide_top_label(); + key_editor->set_name("Key"); + key_editor_tab->add_child(key_editor); + + key_edit = memnew( AnimationKeyEdit ); + key_edit->undo_redo=undo_redo; + //key_edit->ke_dialog=key_edit_dialog; + key_editor->edit(key_edit); + type_menu = memnew( PopupMenu ); + add_child(type_menu); + for(int i=0;iadd_item(Variant::get_type_name(Variant::Type(i)),i); + type_menu->connect("item_pressed",this,"_create_value_item"); + + VBoxContainer *curve_vb = memnew( VBoxContainer ); + curve_vb->set_name("Transition"); + HBoxContainer *curve_hb = memnew( HBoxContainer ); + curve_vb->add_child(curve_hb); + + curve_linear = memnew( ToolButton ); + curve_linear->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_linear); + curve_in = memnew( ToolButton ); + curve_in->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_in); + curve_out = memnew( ToolButton ); + curve_out->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_out); + curve_inout = memnew( ToolButton ); + curve_inout->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_inout); + curve_outin = memnew( ToolButton ); + curve_outin->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_outin); + curve_constant = memnew( ToolButton ); + curve_constant->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_constant); + + + curve_edit = memnew( AnimationCurveEdit ); + curve_vb->add_child(curve_edit); + curve_edit->set_v_size_flags(SIZE_EXPAND_FILL); + key_editor_tab->add_child(curve_vb); + h_scroll = memnew( HScrollBar ); h_scroll->connect("value_changed",this,"_scroll_changed"); add_child(h_scroll); @@ -3340,7 +3775,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h add_child(track_menu); track_menu->connect("item_pressed",this,"_track_menu_selected"); - + key_editor_tab->hide(); last_idx =1; @@ -3359,24 +3794,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h timeline_pos=0; - key_edit_dialog = memnew( PopupDialog ); - key_editor = memnew( PropertyEditor ); - add_child(key_edit_dialog); - key_editor->set_area_as_parent_rect(); - key_editor->hide_top_label(); - for(int i=0;i<4;i++) - key_editor->set_margin(Margin(i),5); - key_edit_dialog->add_child(key_editor); - - key_edit = memnew( AnimationKeyEdit ); - key_edit->undo_redo=undo_redo; - key_edit->ke_dialog=key_edit_dialog; - key_editor->edit(key_edit); - type_menu = memnew( PopupMenu ); - add_child(type_menu); - for(int i=0;iadd_item(Variant::get_type_name(Variant::Type(i)),i); - type_menu->connect("item_pressed",this,"_create_value_item"); keying=false; insert_frame=0; insert_query=false; diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h index 885d46cf6c5..35053fb6a34 100644 --- a/tools/editor/animation_editor.h +++ b/tools/editor/animation_editor.h @@ -37,6 +37,7 @@ #include "scene/gui/scroll_bar.h" #include "scene/gui/tool_button.h" #include "scene/gui/file_dialog.h" +#include "scene/gui/tab_container.h" #include "scene/resources/animation.h" #include "scene/animation/animation_cache.h" @@ -46,6 +47,7 @@ class AnimationKeyEdit; +class AnimationCurveEdit; class AnimationKeyEditor : public VBoxContainer { @@ -86,7 +88,13 @@ class AnimationKeyEditor : public VBoxContainer { TRACK_MENU_SET_ALL_TRANS_OUTIN, TRACK_MENU_NEXT_STEP, TRACK_MENU_PREV_STEP, - TRACK_MENU_OPTIMIZE + TRACK_MENU_OPTIMIZE, + CURVE_SET_LINEAR, + CURVE_SET_IN, + CURVE_SET_OUT, + CURVE_SET_INOUT, + CURVE_SET_OUTIN, + CURVE_SET_CONSTANT }; struct MouseOver { @@ -169,6 +177,14 @@ class AnimationKeyEditor : public VBoxContainer { ToolButton *move_down_button; ToolButton *remove_button; + ToolButton *curve_linear; + ToolButton *curve_in; + ToolButton *curve_out; + ToolButton *curve_inout; + ToolButton *curve_outin; + ToolButton *curve_constant; + + ConfirmationDialog *optimize_dialog; SpinBox *optimize_linear_error; SpinBox *optimize_angular_error; @@ -183,11 +199,11 @@ class AnimationKeyEditor : public VBoxContainer { Control *track_editor; Control *track_pos; + TabContainer *key_editor_tab; ConfirmationDialog *scale_dialog; SpinBox *scale; - PopupDialog *key_edit_dialog; PropertyEditor *key_editor; Ref animation; @@ -203,6 +219,7 @@ class AnimationKeyEditor : public VBoxContainer { AnimationKeyEdit *key_edit; + AnimationCurveEdit *curve_edit; bool inserting; @@ -220,6 +237,7 @@ class AnimationKeyEditor : public VBoxContainer { int track_idx; Variant value; String query; + bool advance; };/* insert_data;*/ bool insert_query; @@ -254,7 +272,7 @@ class AnimationKeyEditor : public VBoxContainer { void _scale(); - + void _clear_selection(); //void _browse_path(); @@ -270,12 +288,15 @@ class AnimationKeyEditor : public VBoxContainer { void _clear_selection_for_anim(const Ref& p_anim); void _select_at_anim(const Ref& p_anim,int p_track,float p_pos); + void _curve_transition_changed(float p_what); PropertyInfo _find_hint_for_track(int p_idx); void _create_value_item(int p_type); void _pane_drag(const Point2& p_delta); + bool _edit_if_single_selection(); + void _toggle_edit_curves(); void _animation_len_update(); void _root_removed(); @@ -296,7 +317,7 @@ public: void set_anim_pos(float p_pos); void insert_node_value_key(Node* p_node, const String& p_property,const Variant& p_value,bool p_only_if_exists=false); - void insert_value_key(const String& p_property,const Variant& p_value); + void insert_value_key(const String& p_property, const Variant& p_value, bool p_advance); void insert_transform_key(Spatial *p_node,const String& p_sub,const Transform& p_xform); AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_history, EditorSelection *p_selection); diff --git a/tools/editor/create_dialog.cpp b/tools/editor/create_dialog.cpp index f5bef2580d0..c0f35a4ac2b 100644 --- a/tools/editor/create_dialog.cpp +++ b/tools/editor/create_dialog.cpp @@ -230,6 +230,11 @@ void CreateDialog::_notification(int p_what) { connect("confirmed",this,"_confirmed"); _update_search(); } + if (p_what==NOTIFICATION_EXIT_TREE) { + + disconnect("confirmed",this,"_confirmed"); + + } if (p_what==NOTIFICATION_VISIBILITY_CHANGED) { diff --git a/tools/editor/editor_dir_dialog.cpp b/tools/editor/editor_dir_dialog.cpp index 5e6bad41aa9..a8421acff86 100644 --- a/tools/editor/editor_dir_dialog.cpp +++ b/tools/editor/editor_dir_dialog.cpp @@ -43,6 +43,7 @@ void EditorDirDialog::_update_dir(TreeItem* p_item) { da->list_dir_begin(); String p=da->get_next(); + List dirs; bool ishidden; bool show_hidden = EditorSettings::get_singleton()->get("file_dialog/show_hidden_files"); @@ -52,16 +53,22 @@ void EditorDirDialog::_update_dir(TreeItem* p_item) { if (show_hidden || !ishidden) { if (da->current_is_dir() && !p.begins_with(".")) { - TreeItem *ti = tree->create_item(p_item); - ti->set_text(0,p); - ti->set_icon(0,get_icon("Folder","EditorIcons")); - ti->set_collapsed(true); + dirs.push_back(p); } } - p=da->get_next(); } + dirs.sort(); + + for(List::Element *E=dirs.front();E;E=E->next()) { + TreeItem *ti = tree->create_item(p_item); + ti->set_text(0,E->get()); + ti->set_icon(0,get_icon("Folder","EditorIcons")); + ti->set_collapsed(true); + + } + memdelete(da); updating=false; diff --git a/tools/editor/editor_file_dialog.cpp b/tools/editor/editor_file_dialog.cpp new file mode 100644 index 00000000000..b1bbd71f7b3 --- /dev/null +++ b/tools/editor/editor_file_dialog.cpp @@ -0,0 +1,1366 @@ +#include "editor_file_dialog.h" +#include "scene/gui/label.h" +#include "scene/gui/center_container.h" +#include "print_string.h" +#include "os/keyboard.h" +#include "editor_resource_preview.h" +#include "editor_settings.h" +#include "scene/gui/margin_container.h" +EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func=NULL; +EditorFileDialog::GetIconFunc EditorFileDialog::get_large_icon_func=NULL; + +EditorFileDialog::RegisterFunc EditorFileDialog::register_func=NULL; +EditorFileDialog::RegisterFunc EditorFileDialog::unregister_func=NULL; + + +VBoxContainer *EditorFileDialog::get_vbox() { + return vbox; + +} + +void EditorFileDialog::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_TREE) { + + mode_thumbnails->set_icon(get_icon("FileThumbnail","EditorIcons")); + mode_list->set_icon(get_icon("FileList","EditorIcons")); + dir_prev->set_icon(get_icon("ArrowLeft","EditorIcons")); + dir_next->set_icon(get_icon("ArrowRight","EditorIcons")); + dir_up->set_icon(get_icon("ArrowUp","EditorIcons")); + favorite->set_icon(get_icon("Favorites","EditorIcons")); + + fav_up->set_icon(get_icon("MoveUp","EditorIcons")); + fav_down->set_icon(get_icon("MoveDown","EditorIcons")); + fav_rm->set_icon(get_icon("RemoveSmall","EditorIcons")); + + } + if (p_what==NOTIFICATION_PROCESS) { + + if (preview_waiting) { + preview_wheel_timeout-=get_process_delta_time(); + if (preview_wheel_timeout<=0) { + preview_wheel_index++; + if (preview_wheel_index>=8) + preview_wheel_index=0; + Ref frame = get_icon("WaitPreview"+itos(preview_wheel_index+1),"EditorIcons"); + preview->set_texture(frame); + preview_wheel_timeout=0.1; + } + } + } + + if (p_what==NOTIFICATION_DRAW) { + + //RID ci = get_canvas_item(); + //get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size())); + } +} + +void EditorFileDialog::set_enable_multiple_selection(bool p_enable) { + + item_list->set_select_mode(p_enable?ItemList::SELECT_MULTI:ItemList::SELECT_SINGLE); + +}; + +Vector EditorFileDialog::get_selected_files() const { + + Vector list; + for(int i=0;iget_item_count();i++) { + if (item_list->is_selected(i)) + list.push_back(item_list->get_item_text(i)); + } + return list; + +}; + +void EditorFileDialog::update_dir() { + + dir->set_text(dir_access->get_current_dir()); +} + +void EditorFileDialog::_dir_entered(String p_dir) { + + + dir_access->change_dir(p_dir); + file->set_text(""); + invalidate(); + update_dir(); + _push_history(); + + +} + +void EditorFileDialog::_file_entered(const String& p_file) { + + _action_pressed(); +} + +void EditorFileDialog::_save_confirm_pressed() { + String f=dir_access->get_current_dir().plus_file(file->get_text()); + _save_to_recent(); + emit_signal("file_selected",f); + hide(); +} + +void EditorFileDialog::_post_popup() { + + ConfirmationDialog::_post_popup(); + if (invalidated) { + update_file_list(); + invalidated=false; + } + if (mode==MODE_SAVE_FILE) + file->grab_focus(); + else + item_list->grab_focus(); + + if (is_visible() && get_current_file()!="") + _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); + + if (is_visible()) { + Ref folder = get_icon("folder","FileDialog"); + recent->clear(); + + + bool res = access==ACCESS_RESOURCES; + Vector recentd = EditorSettings::get_singleton()->get_recent_dirs(); + for(int i=0;iadd_item(name,folder); + recent->set_item_metadata( recent->get_item_count()-1,recentd[i]); + } + + local_history.clear(); + local_history_pos=-1; + _push_history(); + + _update_favorites(); + } + +} + +void EditorFileDialog::_thumbnail_result(const String& p_path,const Ref& p_preview, const Variant& p_udata) { + + if (display_mode==DISPLAY_LIST || p_preview.is_null()) + return; + + for(int i=0;iget_item_count();i++) { + Dictionary d = item_list->get_item_metadata(i); + String pname = d["path"]; + if (pname==p_path) { + item_list->set_item_icon(i,p_preview); + item_list->set_item_tag_icon(i,Ref()); + } + } +} + +void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref& p_preview, const Variant& p_udata) { + + set_process(false); + preview_waiting=false; + + if (p_preview.is_valid() && get_current_path()==p_path) { + + + preview->set_texture(p_preview); + if (display_mode==DISPLAY_THUMBNAILS) { + preview_vb->hide(); + } else { + preview_vb->show(); + } + + } else { + preview_vb->hide(); + preview->set_texture(Ref()); + + } + +} + +void EditorFileDialog::_request_single_thumbnail(const String& p_path) { + + EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",p_path); + print_line("want file "+p_path); + set_process(true); + preview_waiting=true; + preview_wheel_timeout=0; + +} + +void EditorFileDialog::_action_pressed() { + + if (mode==MODE_OPEN_FILES) { + + + String fbase=dir_access->get_current_dir(); + + DVector files; + for(int i=0;iget_item_count();i++) { + if (item_list->is_selected(i)) + files.push_back( fbase.plus_file(item_list->get_item_text(i) )); + } + + if (files.size()) { + _save_to_recent(); + emit_signal("files_selected",files); + hide(); + } + + return; + } + + String f=dir_access->get_current_dir().plus_file(file->get_text()); + + if (mode==MODE_OPEN_FILE && dir_access->file_exists(f)) { + _save_to_recent(); + emit_signal("file_selected",f); + hide(); + } + + if (mode==MODE_OPEN_DIR) { + + + String path=dir_access->get_current_dir(); + /*if (tree->get_selected()) { + Dictionary d = tree->get_selected()->get_metadata(0); + if (d["dir"]) { + path=path+"/"+String(d["name"]); + } + }*/ + path=path.replace("\\","/"); + _save_to_recent(); + emit_signal("dir_selected",path); + hide(); + } + + if (mode==MODE_SAVE_FILE) { + + bool valid=false; + + if (filter->get_selected()==filter->get_item_count()-1) { + valid=true; //match none + } else if (filters.size()>1 && filter->get_selected()==0) { + // match all filters + for (int i=0;iget_selected(); + if (filters.size()>1) + idx--; + if (idx>=0 && idx0) { + String str = (flt.get_slice(",",0).strip_edges()); + f+=str.substr(1, str.length()-1); + _request_single_thumbnail(get_current_dir().plus_file(f.get_file())); + file->set_text(f.get_file()); + valid=true; + } + } else { + valid=true; + } + } + + + if (!valid) { + + exterr->popup_centered_minsize(Size2(250,80)); + return; + + } + + if (dir_access->file_exists(f)) { + confirm_save->set_text("File Exists, Overwrite?"); + confirm_save->popup_centered(Size2(200,80)); + } else { + + _save_to_recent(); + emit_signal("file_selected",f); + hide(); + } + } +} + +void EditorFileDialog::_cancel_pressed() { + + file->set_text(""); + invalidate(); + hide(); +} + +void EditorFileDialog::_item_selected(int p_item) { + + int current = p_item; + if (current<0 || current>=item_list->get_item_count()) + return; + + Dictionary d=item_list->get_item_metadata(current); + + if (!d["dir"]) { + + file->set_text(d["name"]); + _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); + } +} + +void EditorFileDialog::_push_history() { + + local_history.resize(local_history_pos+1); + String new_path = dir_access->get_current_dir(); + if (local_history.size()==0 || new_path!=local_history[local_history_pos]) { + local_history.push_back(new_path); + local_history_pos++; + dir_prev->set_disabled(local_history_pos==0); + dir_next->set_disabled(true); + } + +} +void EditorFileDialog::_item_dc_selected(int p_item) { + + + int current = p_item; + if (current<0 || current>=item_list->get_item_count()) + return; + + Dictionary d=item_list->get_item_metadata(current); + + if (d["dir"]) { + + print_line("change dir: "+String(d["name"])); + dir_access->change_dir(d["name"]); + if (mode==MODE_OPEN_FILE || mode==MODE_OPEN_FILES || mode==MODE_OPEN_DIR) + file->set_text(""); + call_deferred("_update_file_list"); + call_deferred("_update_dir"); + + _push_history(); + + + } else { + + _action_pressed(); + } +} + + + +void EditorFileDialog::update_file_list() { + + + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + Ref folder_thumbnail; + Ref file_thumbnail; + + item_list->clear(); + + if (display_mode==DISPLAY_THUMBNAILS) { + + item_list->set_max_columns(0); + item_list->set_icon_mode(ItemList::ICON_MODE_TOP); + item_list->set_fixed_column_width(thumbnail_size*3/2); + item_list->set_max_text_lines(2); + item_list->set_min_icon_size(Size2(thumbnail_size,thumbnail_size)); + + if (!has_icon("ResizedFolder","EditorIcons")) { + Ref folder = get_icon("FolderBig","EditorIcons"); + Image img = folder->get_data(); + img.resize(thumbnail_size,thumbnail_size); + Ref resized_folder = Ref( memnew( ImageTexture)); + resized_folder->create_from_image(img,0); + Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder); + } + + folder_thumbnail = get_icon("ResizedFolder","EditorIcons"); + + if (!has_icon("ResizedFile","EditorIcons")) { + Ref file = get_icon("FileBig","EditorIcons"); + Image img = file->get_data(); + img.resize(thumbnail_size,thumbnail_size); + Ref resized_file = Ref( memnew( ImageTexture)); + resized_file->create_from_image(img,0); + Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file); + } + + file_thumbnail = get_icon("ResizedFile","EditorIcons"); + + preview_vb->hide(); + + } else { + + item_list->set_icon_mode(ItemList::ICON_MODE_LEFT); + item_list->set_max_columns(1); + item_list->set_max_text_lines(1); + item_list->set_fixed_column_width(0); + item_list->set_min_icon_size(Size2()); + if (preview->get_texture().is_valid()) + preview_vb->show(); + + } + + + dir_access->list_dir_begin(); + + + Ref folder = get_icon("folder","FileDialog"); + List files; + List dirs; + + bool isdir; + bool ishidden; + bool show_hidden = show_hidden_files; + String item; + + while ((item=dir_access->get_next(&isdir))!="") { + + ishidden = dir_access->current_is_hidden(); + + if (show_hidden || !ishidden) { + if (!isdir) + files.push_back(item); + else + dirs.push_back(item); + } + } + + dirs.sort_custom(); + files.sort_custom(); + + while(!dirs.empty()) { + + if (dirs.front()->get()!=".") { + item_list->add_item(dirs.front()->get()+"/"); + if (display_mode==DISPLAY_THUMBNAILS) { + + item_list->set_item_icon(item_list->get_item_count()-1,folder_thumbnail); + } else { + + item_list->set_item_icon(item_list->get_item_count()-1,folder); + } + + Dictionary d; + d["name"]=dirs.front()->get(); + d["path"]=String(); + d["dir"]=true; + item_list->set_item_metadata( item_list->get_item_count() -1, d); + } + dirs.pop_front(); + + } + + dirs.clear(); + + List patterns; + // build filter + if (filter->get_selected()==filter->get_item_count()-1) { + + // match all + } else if (filters.size()>1 && filter->get_selected()==0) { + // match all filters + for (int i=0;iget_selected(); + if (filters.size()>1) + idx--; + + if (idx>=0 && idxget_current_dir(); + + + while(!files.empty()) { + + bool match=patterns.empty(); + + for(List::Element *E=patterns.front();E;E=E->next()) { + + if (files.front()->get().matchn(E->get())) { + + match=true; + break; + } + } + + if (match) { + //TreeItem *ti=tree->create_item(root); + //ti->set_text(0,files.front()->get()); + item_list->add_item(files.front()->get()); + + if (get_icon_func) { + + Ref icon = get_icon_func(base_dir.plus_file(files.front()->get())); + //ti->set_icon(0,icon); + if (display_mode==DISPLAY_THUMBNAILS) { + + item_list->set_item_icon(item_list->get_item_count()-1,file_thumbnail); + item_list->set_item_tag_icon(item_list->get_item_count()-1,icon); + } else { + item_list->set_item_icon(item_list->get_item_count()-1,icon); + } + } + + if (mode==MODE_OPEN_DIR) { + //disabled mode? + //ti->set_custom_color(0,get_color("files_disabled")); + //ti->set_selectable(0,false); + } + Dictionary d; + d["name"]=files.front()->get(); + d["dir"]=false; + String fullpath = base_dir.plus_file(files.front()->get()); + + if (display_mode==DISPLAY_THUMBNAILS) { + EditorResourcePreview::get_singleton()->queue_resource_preview(fullpath,this,"_thumbnail_result",fullpath); + } + d["path"]=base_dir.plus_file(files.front()->get()); + //ti->set_metadata(0,d); + item_list->set_item_metadata(item_list->get_item_count()-1,d); + + if (file->get_text()==files.front()->get()) + item_list->set_current(item_list->get_item_count()-1); + } + + files.pop_front(); + } + + if (favorites->get_current()>=0) { + favorites->unselect(favorites->get_current()); + } + + favorite->set_pressed(false); + fav_up->set_disabled(true); + fav_down->set_disabled(true); + for(int i=0;iget_item_count();i++) { + if (favorites->get_item_metadata(i)==base_dir) { + favorites->select(i); + favorite->set_pressed(true); + if (i>0) { + fav_up->set_disabled(false); + } + if (iget_item_count()-1) { + fav_down->set_disabled(false); + } + break; + } + + } + // ?? + //if (tree->get_root() && tree->get_root()->get_children()) + // tree->get_root()->get_children()->select(0); + + files.clear(); + +} + +void EditorFileDialog::_filter_selected(int) { + + update_file_list(); +} + +void EditorFileDialog::update_filters() { + + filter->clear(); + + if (filters.size()>1) { + String all_filters; + + const int max_filters=5; + + for(int i=0;i0) + all_filters+=","; + all_filters+=flt; + } + + if (max_filtersadd_item("All Recognized ( "+all_filters+" )"); + } + for(int i=0;iadd_item(desc+" ( "+flt+" )"); + else + filter->add_item("( "+flt+" )"); + } + + filter->add_item("All Files (*)"); + +} + +void EditorFileDialog::clear_filters() { + + filters.clear(); + update_filters(); + invalidate(); +} +void EditorFileDialog::add_filter(const String& p_filter) { + + filters.push_back(p_filter); + update_filters(); + invalidate(); + +} + +String EditorFileDialog::get_current_dir() const { + + return dir->get_text(); +} +String EditorFileDialog::get_current_file() const { + + return file->get_text(); +} +String EditorFileDialog::get_current_path() const { + + return dir->get_text().plus_file(file->get_text()); +} +void EditorFileDialog::set_current_dir(const String& p_dir) { + + dir_access->change_dir(p_dir); + update_dir(); + invalidate(); + //_push_history(); + + +} +void EditorFileDialog::set_current_file(const String& p_file) { + + file->set_text(p_file); + update_dir(); + invalidate(); + int lp = p_file.find_last("."); + if (lp!=-1) { + file->select(0,lp); + file->grab_focus(); + } + + if (is_visible()) + _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); + + +} +void EditorFileDialog::set_current_path(const String& p_path) { + + if (!p_path.size()) + return; + int pos=MAX( p_path.find_last("/"), p_path.find_last("\\") ); + if (pos==-1) { + + set_current_file(p_path); + } else { + + String dir=p_path.substr(0,pos); + String file=p_path.substr(pos+1,p_path.length()); + set_current_dir(dir); + set_current_file(file); + } +} + + +void EditorFileDialog::set_mode(Mode p_mode) { + + mode=p_mode; + switch(mode) { + + case MODE_OPEN_FILE: get_ok()->set_text("Open"); set_title("Open a File"); makedir->hide(); break; + case MODE_OPEN_FILES: get_ok()->set_text("Open"); set_title("Open File(s)"); makedir->hide(); break; + case MODE_SAVE_FILE: get_ok()->set_text("Save"); set_title("Save a File"); makedir->show(); break; + case MODE_OPEN_DIR: get_ok()->set_text("Open"); set_title("Open a Directory"); makedir->show(); break; + } + + if (mode==MODE_OPEN_FILES) { + item_list->set_select_mode(ItemList::SELECT_MULTI); + } else { + item_list->set_select_mode(ItemList::SELECT_SINGLE); + } +} + +EditorFileDialog::Mode EditorFileDialog::get_mode() const { + + return mode; +} + +void EditorFileDialog::set_access(Access p_access) { + + ERR_FAIL_INDEX(p_access,3); + if (access==p_access) + return; + memdelete( dir_access ); + switch(p_access) { + case ACCESS_FILESYSTEM: { + + dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + } break; + case ACCESS_RESOURCES: { + + dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); + } break; + case ACCESS_USERDATA: { + + dir_access = DirAccess::create(DirAccess::ACCESS_USERDATA); + } break; + } + access=p_access; + _update_drives(); + invalidate(); + update_filters(); + update_dir(); +} + +void EditorFileDialog::invalidate() { + + if (is_visible()) { + update_file_list(); + invalidated=false; + } else { + invalidated=true; + } + +} + +EditorFileDialog::Access EditorFileDialog::get_access() const{ + + return access; +} + +void EditorFileDialog::_make_dir_confirm() { + + + Error err = dir_access->make_dir( makedirname->get_text() ); + if (err==OK) { + dir_access->change_dir(makedirname->get_text()); + invalidate(); + update_filters(); + update_dir(); + _push_history(); + + } else { + mkdirerr->popup_centered_minsize(Size2(250,50)); + } +} + + +void EditorFileDialog::_make_dir() { + + makedialog->popup_centered_minsize(Size2(250,80)); + makedirname->grab_focus(); + +} + +void EditorFileDialog::_select_drive(int p_idx) { + + String d = drives->get_item_text(p_idx); + dir_access->change_dir(d); + file->set_text(""); + invalidate(); + update_dir(); + _push_history(); + + +} + +void EditorFileDialog::_update_drives() { + + + int dc = dir_access->get_drive_count(); + if (dc==0 || access!=ACCESS_FILESYSTEM) { + drives->hide(); + } else { + drives->clear(); + drives->show(); + + for(int i=0;iget_drive_count();i++) { + String d = dir_access->get_drive(i); + drives->add_item(dir_access->get_drive(i)); + } + + drives->select(dir_access->get_current_drive()); + + } +} + + +void EditorFileDialog::_favorite_selected(int p_idx) { + + Vector favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + ERR_FAIL_INDEX(p_idx,favorited.size()); + + dir_access->change_dir(favorited[p_idx]); + file->set_text(""); + invalidate(); + update_dir(); + _push_history(); +} + +void EditorFileDialog::_favorite_move_up(){ + + int current = favorites->get_current(); + + if (current>0 && currentget_item_count()) { + Vector favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + + int a_idx=favorited.find(String(favorites->get_item_metadata(current-1))); + int b_idx=favorited.find(String(favorites->get_item_metadata(current))); + + if (a_idx==-1 || b_idx==-1) + return; + SWAP(favorited[a_idx],favorited[b_idx]); + + EditorSettings::get_singleton()->set_favorite_dirs(favorited); + + _update_favorites(); + update_file_list(); + + } +} +void EditorFileDialog::_favorite_move_down(){ + + int current = favorites->get_current(); + + if (current>=0 && currentget_item_count()-1) { + Vector favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + + int a_idx=favorited.find(String(favorites->get_item_metadata(current+1))); + int b_idx=favorited.find(String(favorites->get_item_metadata(current))); + + if (a_idx==-1 || b_idx==-1) + return; + SWAP(favorited[a_idx],favorited[b_idx]); + + EditorSettings::get_singleton()->set_favorite_dirs(favorited); + + _update_favorites(); + update_file_list(); + + } +} + + +void EditorFileDialog::_update_favorites() { + + bool res = access==ACCESS_RESOURCES; + + String current = get_current_dir(); + Ref star = get_icon("Favorites","EditorIcons"); + favorites->clear(); + + favorite->set_pressed(false); + + + Vector favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + for(int i=0;iadd_item(name,star); + favorites->set_item_metadata( favorites->get_item_count()-1,favorited[i]); + + if (setthis) { + favorite->set_pressed(true); + favorites->set_current(favorites->get_item_count()-1); + } + } + + +} + +void EditorFileDialog::_favorite_toggled(bool p_toggle) { + bool res = access==ACCESS_RESOURCES; + + String cd = get_current_dir(); + + Vector favorited = EditorSettings::get_singleton()->get_favorite_dirs(); + + bool found = false; + for(int i=0;iset_pressed(false); + } else { + favorited.push_back(cd); + favorite->set_pressed(true); + } + + EditorSettings::get_singleton()->set_favorite_dirs(favorited); + + _update_favorites(); + +} + +void EditorFileDialog::_recent_selected(int p_idx) { + + Vector recentd = EditorSettings::get_singleton()->get_recent_dirs(); + ERR_FAIL_INDEX(p_idx,recentd.size()); + + dir_access->change_dir(recent->get_item_metadata(p_idx)); + update_file_list(); + update_dir(); + _push_history(); +} + +void EditorFileDialog::_go_up() { + + dir_access->change_dir(".."); + update_file_list(); + update_dir(); + _push_history(); + +} + +void EditorFileDialog::_go_back(){ + + if (local_history_pos<=0) { + return; + } + + local_history_pos--; + dir_access->change_dir(local_history[local_history_pos]); + update_file_list(); + update_dir(); + + dir_prev->set_disabled(local_history_pos==0); + dir_next->set_disabled(local_history_pos==local_history.size()-1); +} +void EditorFileDialog::_go_forward(){ + + if (local_history_pos==local_history.size()-1) { + return; + } + + local_history_pos++; + dir_access->change_dir(local_history[local_history_pos]); + update_file_list(); + update_dir(); + + dir_prev->set_disabled(local_history_pos==0); + dir_next->set_disabled(local_history_pos==local_history.size()-1); + +} + +bool EditorFileDialog::default_show_hidden_files=true; + +void EditorFileDialog::set_display_mode(DisplayMode p_mode) { + + if (display_mode==p_mode) + return; + if (p_mode==DISPLAY_THUMBNAILS) { + mode_list->set_pressed(false); + mode_thumbnails->set_pressed(true); + } else { + mode_thumbnails->set_pressed(false); + mode_list->set_pressed(true); + } + display_mode=p_mode; + invalidate();; +} + +EditorFileDialog::DisplayMode EditorFileDialog::get_display_mode() const{ + + return display_mode; +} + + + +void EditorFileDialog::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_item_selected"),&EditorFileDialog::_item_selected); + ObjectTypeDB::bind_method(_MD("_item_db_selected"),&EditorFileDialog::_item_dc_selected); + ObjectTypeDB::bind_method(_MD("_dir_entered"),&EditorFileDialog::_dir_entered); + ObjectTypeDB::bind_method(_MD("_file_entered"),&EditorFileDialog::_file_entered); + ObjectTypeDB::bind_method(_MD("_action_pressed"),&EditorFileDialog::_action_pressed); + ObjectTypeDB::bind_method(_MD("_cancel_pressed"),&EditorFileDialog::_cancel_pressed); + ObjectTypeDB::bind_method(_MD("_filter_selected"),&EditorFileDialog::_filter_selected); + ObjectTypeDB::bind_method(_MD("_save_confirm_pressed"),&EditorFileDialog::_save_confirm_pressed); + + ObjectTypeDB::bind_method(_MD("clear_filters"),&EditorFileDialog::clear_filters); + ObjectTypeDB::bind_method(_MD("add_filter","filter"),&EditorFileDialog::add_filter); + ObjectTypeDB::bind_method(_MD("get_current_dir"),&EditorFileDialog::get_current_dir); + ObjectTypeDB::bind_method(_MD("get_current_file"),&EditorFileDialog::get_current_file); + ObjectTypeDB::bind_method(_MD("get_current_path"),&EditorFileDialog::get_current_path); + ObjectTypeDB::bind_method(_MD("set_current_dir","dir"),&EditorFileDialog::set_current_dir); + ObjectTypeDB::bind_method(_MD("set_current_file","file"),&EditorFileDialog::set_current_file); + ObjectTypeDB::bind_method(_MD("set_current_path","path"),&EditorFileDialog::set_current_path); + ObjectTypeDB::bind_method(_MD("set_mode","mode"),&EditorFileDialog::set_mode); + ObjectTypeDB::bind_method(_MD("get_mode"),&EditorFileDialog::get_mode); + ObjectTypeDB::bind_method(_MD("get_vbox:VBoxContainer"),&EditorFileDialog::get_vbox); + ObjectTypeDB::bind_method(_MD("set_access","access"),&EditorFileDialog::set_access); + ObjectTypeDB::bind_method(_MD("get_access"),&EditorFileDialog::get_access); + ObjectTypeDB::bind_method(_MD("set_show_hidden_files"),&EditorFileDialog::set_show_hidden_files); + ObjectTypeDB::bind_method(_MD("is_showing_hidden_files"),&EditorFileDialog::is_showing_hidden_files); + ObjectTypeDB::bind_method(_MD("_select_drive"),&EditorFileDialog::_select_drive); + ObjectTypeDB::bind_method(_MD("_make_dir"),&EditorFileDialog::_make_dir); + ObjectTypeDB::bind_method(_MD("_make_dir_confirm"),&EditorFileDialog::_make_dir_confirm); + ObjectTypeDB::bind_method(_MD("_update_file_list"),&EditorFileDialog::update_file_list); + ObjectTypeDB::bind_method(_MD("_update_dir"),&EditorFileDialog::update_dir); + ObjectTypeDB::bind_method(_MD("_thumbnail_done"),&EditorFileDialog::_thumbnail_done); + ObjectTypeDB::bind_method(_MD("set_display_mode","mode"),&EditorFileDialog::set_display_mode); + ObjectTypeDB::bind_method(_MD("get_display_mode"),&EditorFileDialog::get_display_mode); + ObjectTypeDB::bind_method(_MD("_thumbnail_result"),&EditorFileDialog::_thumbnail_result); + + ObjectTypeDB::bind_method(_MD("_recent_selected"),&EditorFileDialog::_recent_selected); + ObjectTypeDB::bind_method(_MD("_go_back"),&EditorFileDialog::_go_back); + ObjectTypeDB::bind_method(_MD("_go_forward"),&EditorFileDialog::_go_forward); + ObjectTypeDB::bind_method(_MD("_go_up"),&EditorFileDialog::_go_up); + + ObjectTypeDB::bind_method(_MD("_favorite_toggled"),&EditorFileDialog::_favorite_toggled); + ObjectTypeDB::bind_method(_MD("_favorite_selected"),&EditorFileDialog::_favorite_selected); + ObjectTypeDB::bind_method(_MD("_favorite_move_up"),&EditorFileDialog::_favorite_move_up); + ObjectTypeDB::bind_method(_MD("_favorite_move_down"),&EditorFileDialog::_favorite_move_down); + + ObjectTypeDB::bind_method(_MD("invalidate"),&EditorFileDialog::invalidate); + + ADD_SIGNAL(MethodInfo("file_selected",PropertyInfo( Variant::STRING,"path"))); + ADD_SIGNAL(MethodInfo("files_selected",PropertyInfo( Variant::STRING_ARRAY,"paths"))); + ADD_SIGNAL(MethodInfo("dir_selected",PropertyInfo( Variant::STRING,"dir"))); + + BIND_CONSTANT( MODE_OPEN_FILE ); + BIND_CONSTANT( MODE_OPEN_FILES ); + BIND_CONSTANT( MODE_OPEN_DIR ); + BIND_CONSTANT( MODE_SAVE_FILE ); + + BIND_CONSTANT( ACCESS_RESOURCES ); + BIND_CONSTANT( ACCESS_USERDATA ); + BIND_CONSTANT( ACCESS_FILESYSTEM ); + +} + + +void EditorFileDialog::set_show_hidden_files(bool p_show) { + show_hidden_files=p_show; + invalidate(); +} + +bool EditorFileDialog::is_showing_hidden_files() const { + return show_hidden_files; +} + +void EditorFileDialog::set_default_show_hidden_files(bool p_show) { + default_show_hidden_files=p_show; +} + +void EditorFileDialog::_save_to_recent() { + + String dir = get_current_dir(); + Vector recent = EditorSettings::get_singleton()->get_recent_dirs(); + + const int max=20; + int count=0; + bool res=dir.begins_with("res://"); + + for(int i=0;imax)) { + recent.remove(i); + i--; + } else { + count++; + } + } + + recent.insert(0,dir); + + EditorSettings::get_singleton()->set_recent_dirs(recent); + + +} + +EditorFileDialog::EditorFileDialog() { + + show_hidden_files=true; + display_mode=DISPLAY_THUMBNAILS; + local_history_pos=0; + + VBoxContainer *vbc = memnew( VBoxContainer ); + add_child(vbc); + set_child_rect(vbc); + + mode=MODE_SAVE_FILE; + set_title("Save a File"); + + HBoxContainer *pathhb = memnew( HBoxContainer ); + + dir_prev = memnew( ToolButton ); + dir_next = memnew( ToolButton ); + dir_up = memnew( ToolButton ); + + pathhb->add_child(dir_prev); + pathhb->add_child(dir_next); + pathhb->add_child(dir_up); + + dir_prev->connect("pressed",this,"_go_back"); + dir_next->connect("pressed",this,"_go_forward"); + dir_up->connect("pressed",this,"_go_up"); + + dir = memnew(LineEdit); + pathhb->add_child(dir); + dir->set_h_size_flags(SIZE_EXPAND_FILL); + + favorite = memnew( ToolButton ); + favorite->set_toggle_mode(true); + favorite->connect("toggled",this,"_favorite_toggled"); + pathhb->add_child(favorite); + + mode_thumbnails = memnew( ToolButton ); + mode_thumbnails->connect("pressed",this,"set_display_mode",varray(DISPLAY_THUMBNAILS)); + mode_thumbnails->set_toggle_mode(true); + mode_thumbnails->set_pressed(true); + pathhb->add_child(mode_thumbnails); + mode_list = memnew( ToolButton ); + mode_list->connect("pressed",this,"set_display_mode",varray(DISPLAY_LIST)); + mode_list->set_toggle_mode(true); + pathhb->add_child(mode_list); + + drives = memnew( OptionButton ); + pathhb->add_child(drives); + drives->connect("item_selected",this,"_select_drive"); + + makedir = memnew( Button ); + makedir->set_text("Create Folder"); + makedir->connect("pressed",this,"_make_dir"); + pathhb->add_child(makedir); + + list_hb = memnew( HBoxContainer ); + + vbc->add_margin_child("Path:",pathhb); + vbc->add_child(list_hb); + list_hb->set_v_size_flags(SIZE_EXPAND_FILL); + + VBoxContainer *fav_vb = memnew( VBoxContainer ); + list_hb->add_child(fav_vb); + HBoxContainer *fav_hb = memnew( HBoxContainer ); + fav_vb->add_child(fav_hb); + fav_hb->add_child(memnew(Label("Favorites:"))); + fav_hb->add_spacer(); + fav_up = memnew( ToolButton ); + fav_hb->add_child(fav_up); + fav_up->connect("pressed",this,"_favorite_move_up"); + fav_down = memnew( ToolButton ); + fav_hb->add_child(fav_down); + fav_down->connect("pressed",this,"_favorite_move_down"); + fav_rm = memnew( ToolButton ); + fav_hb->add_child(fav_rm); + fav_rm->hide(); // redundant + + MarginContainer *fav_mv = memnew( MarginContainer ); + fav_vb->add_child(fav_mv); + fav_mv->set_v_size_flags(SIZE_EXPAND_FILL); + favorites = memnew( ItemList ); + fav_mv->add_child(favorites); + favorites->connect("item_selected",this,"_favorite_selected"); + + recent = memnew( ItemList ); + fav_vb->add_margin_child("Recent:",recent,true); + recent->connect("item_selected",this,"_recent_selected"); + + VBoxContainer *item_vb = memnew( VBoxContainer ); + list_hb->add_child(item_vb); + item_vb->set_h_size_flags(SIZE_EXPAND_FILL); + + item_list = memnew( ItemList ); + item_list->set_v_size_flags(SIZE_EXPAND_FILL); + item_vb->add_margin_child("Directories & Files:",item_list,true); + + HBoxContainer* filter_hb = memnew( HBoxContainer ); + item_vb->add_child(filter_hb); + + VBoxContainer *filter_vb = memnew( VBoxContainer ); + filter_hb->add_child(filter_vb); + filter_vb->set_h_size_flags(SIZE_EXPAND_FILL); + + preview_vb = memnew( VBoxContainer ); + filter_hb->add_child(preview_vb); + CenterContainer *prev_cc = memnew( CenterContainer ); + preview_vb->add_margin_child("Preview:",prev_cc); + preview = memnew( TextureFrame ); + prev_cc->add_child(preview); + preview_vb->hide(); + + + file = memnew(LineEdit); + //add_child(file); + filter_vb->add_margin_child("File:",file); + + + filter = memnew( OptionButton ); + //add_child(filter); + filter_vb->add_margin_child("Filter:",filter); + filter->set_clip_text(true);//too many extensions overflow it + + dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); + access=ACCESS_RESOURCES; + _update_drives(); + + + connect("confirmed", this,"_action_pressed"); + //cancel->connect("pressed", this,"_cancel_pressed"); + item_list->connect("item_selected", this,"_item_selected",varray(),CONNECT_DEFERRED); + item_list->connect("item_activated", this,"_item_db_selected",varray()); + dir->connect("text_entered", this,"_dir_entered"); + file->connect("text_entered", this,"_file_entered"); + filter->connect("item_selected", this,"_filter_selected"); + + + confirm_save = memnew( ConfirmationDialog ); + confirm_save->set_as_toplevel(true); + add_child(confirm_save); + + + confirm_save->connect("confirmed", this,"_save_confirm_pressed"); + + makedialog = memnew( ConfirmationDialog ); + makedialog->set_title("Create Folder"); + VBoxContainer *makevb= memnew( VBoxContainer ); + makedialog->add_child(makevb); + makedialog->set_child_rect(makevb); + makedirname = memnew( LineEdit ); + makevb->add_margin_child("Name:",makedirname); + add_child(makedialog); + makedialog->register_text_enter(makedirname); + makedialog->connect("confirmed",this,"_make_dir_confirm"); + mkdirerr = memnew( AcceptDialog ); + mkdirerr->set_text("Could not create folder."); + add_child(mkdirerr); + + exterr = memnew( AcceptDialog ); + exterr->set_text("Must use a valid extension."); + add_child(exterr); + + + //update_file_list(); + update_filters(); + update_dir(); + + set_hide_on_ok(false); + vbox=vbc; + + + invalidated=true; + if (register_func) + register_func(this); + + preview_wheel_timeout=0; + preview_wheel_index=0; + preview_waiting=false; + +} + + +EditorFileDialog::~EditorFileDialog() { + + if (unregister_func) + unregister_func(this); + memdelete(dir_access); +} + + +void EditorLineEditFileChooser::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_browse"),&EditorLineEditFileChooser::_browse); + ObjectTypeDB::bind_method(_MD("_chosen"),&EditorLineEditFileChooser::_chosen); + ObjectTypeDB::bind_method(_MD("get_button:Button"),&EditorLineEditFileChooser::get_button); + ObjectTypeDB::bind_method(_MD("get_line_edit:LineEdit"),&EditorLineEditFileChooser::get_line_edit); + ObjectTypeDB::bind_method(_MD("get_file_dialog:EditorFileDialog"),&EditorLineEditFileChooser::get_file_dialog); + +} + +void EditorLineEditFileChooser::_chosen(const String& p_text){ + + line_edit->set_text(p_text); + line_edit->emit_signal("text_entered",p_text); +} + +void EditorLineEditFileChooser::_browse() { + + dialog->popup_centered_ratio(); +} + +EditorLineEditFileChooser::EditorLineEditFileChooser() { + + line_edit = memnew( LineEdit ); + add_child(line_edit); + line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + button = memnew( Button ); + button->set_text(" .. "); + add_child(button); + button->connect("pressed",this,"_browse"); + dialog = memnew( EditorFileDialog); + add_child(dialog); + dialog->connect("file_selected",this,"_chosen"); + dialog->connect("dir_selected",this,"_chosen"); + dialog->connect("files_selected",this,"_chosen"); + +} diff --git a/tools/editor/editor_file_dialog.h b/tools/editor/editor_file_dialog.h new file mode 100644 index 00000000000..6cfd9705169 --- /dev/null +++ b/tools/editor/editor_file_dialog.h @@ -0,0 +1,245 @@ +/*************************************************************************/ +/* file_dialog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 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 EDITORFILEDIALOG_H +#define EDITORFILEDIALOG_H + +#include "scene/gui/dialogs.h" +#include "scene/gui/item_list.h" +#include "scene/gui/line_edit.h" +#include "scene/gui/option_button.h" +#include "scene/gui/dialogs.h" +#include "os/dir_access.h" +#include "scene/gui/box_container.h" +#include "scene/gui/texture_frame.h" +#include "scene/gui/tool_button.h" +/** + @author Juan Linietsky +*/ +class EditorFileDialog : public ConfirmationDialog { + + OBJ_TYPE( EditorFileDialog, ConfirmationDialog ); + +public: + + enum DisplayMode { + DISPLAY_THUMBNAILS, + DISPLAY_LIST + }; + + + enum Access { + ACCESS_RESOURCES, + ACCESS_USERDATA, + ACCESS_FILESYSTEM + }; + + + enum Mode { + MODE_OPEN_FILE, + MODE_OPEN_FILES, + MODE_OPEN_DIR, + MODE_SAVE_FILE, + }; + + typedef Ref (*GetIconFunc)(const String&); + typedef void (*RegisterFunc)(EditorFileDialog*); + + static GetIconFunc get_icon_func; + static GetIconFunc get_large_icon_func; + static RegisterFunc register_func; + static RegisterFunc unregister_func; + +private: + + ConfirmationDialog *makedialog; + LineEdit *makedirname; + + Button *makedir; + Access access; + //Button *action; + VBoxContainer *vbox; + Mode mode; + LineEdit *dir; + + ToolButton *dir_prev; + ToolButton *dir_next; + ToolButton *dir_up; + + OptionButton *drives; + ItemList *item_list; + TextureFrame *preview; + VBoxContainer *preview_vb; + HBoxContainer *list_hb; + LineEdit *file; + AcceptDialog *mkdirerr; + AcceptDialog *exterr; + OptionButton *filter; + DirAccess *dir_access; + ConfirmationDialog *confirm_save; + ToolButton *mode_thumbnails; + ToolButton *mode_list; + + + ToolButton *favorite; + + ToolButton *fav_up; + ToolButton *fav_down; + ToolButton *fav_rm; + + ItemList *favorites; + ItemList *recent; + + Vector local_history; + int local_history_pos; + void _push_history(); + + Vector filters; + + bool preview_waiting; + int preview_wheel_index; + float preview_wheel_timeout; + static bool default_show_hidden_files; + bool show_hidden_files; + DisplayMode display_mode; + + bool invalidated; + + void update_dir(); + void update_file_list(); + void update_filters(); + + void _update_favorites(); + void _favorite_toggled(bool p_toggle); + void _favorite_selected(int p_idx); + void _favorite_move_up(); + void _favorite_move_down(); + + + + void _recent_selected(int p_idx); + + void _item_selected(int p_item); + void _item_dc_selected(int p_item); + + void _select_drive(int p_idx); + void _dir_entered(String p_dir); + void _file_entered(const String& p_file); + void _action_pressed(); + void _save_confirm_pressed(); + void _cancel_pressed(); + void _filter_selected(int); + void _make_dir(); + void _make_dir_confirm(); + + void _update_drives(); + + void _go_up(); + void _go_back(); + void _go_forward(); + + virtual void _post_popup(); + + void _save_to_recent(); + //callback funtion is callback(String p_path,Ref preview,Variant udata) preview null if could not load + + void _thumbnail_result(const String& p_path,const Ref& p_preview, const Variant& p_udata); + void _thumbnail_done(const String& p_path,const Ref& p_preview, const Variant& p_udata); + void _request_single_thumbnail(const String& p_path); + +protected: + + void _notification(int p_what); + static void _bind_methods(); + //bind helpers +public: + + void clear_filters(); + void add_filter(const String& p_filter); + + void set_enable_multiple_selection(bool p_enable); + Vector get_selected_files() const; + + String get_current_dir() const; + String get_current_file() const; + String get_current_path() const; + void set_current_dir(const String& p_dir); + void set_current_file(const String& p_file); + void set_current_path(const String& p_path); + + void set_display_mode(DisplayMode p_mode); + DisplayMode get_display_mode() const; + + void set_mode(Mode p_mode); + Mode get_mode() const; + + VBoxContainer *get_vbox(); + LineEdit *get_line_edit() { return file; } + + void set_access(Access p_access); + Access get_access() const; + + void set_show_hidden_files(bool p_show); + bool is_showing_hidden_files() const; + + static void set_default_show_hidden_files(bool p_show); + + void invalidate(); + + EditorFileDialog(); + ~EditorFileDialog(); + +}; + +class EditorLineEditFileChooser : public HBoxContainer { + + OBJ_TYPE( EditorLineEditFileChooser, HBoxContainer ); + Button *button; + LineEdit *line_edit; + EditorFileDialog *dialog; + + void _chosen(const String& p_text); + void _browse(); +protected: + static void _bind_methods(); +public: + + Button *get_button() { return button; } + LineEdit *get_line_edit() { return line_edit; } + EditorFileDialog *get_file_dialog() { return dialog; } + + EditorLineEditFileChooser(); +}; + +VARIANT_ENUM_CAST( EditorFileDialog::Mode ); +VARIANT_ENUM_CAST( EditorFileDialog::Access ); +VARIANT_ENUM_CAST( EditorFileDialog::DisplayMode ); + +#endif // EDITORFILEDIALOG_H diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index 8e96123c36d..d741087a9f6 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -33,7 +33,7 @@ #include "os/file_access.h" #include "editor_node.h" #include "io/resource_saver.h" - +#include "editor_settings.h" EditorFileSystem *EditorFileSystem::singleton=NULL; @@ -357,7 +357,9 @@ void EditorFileSystem::_scan_scenes() { String project=Globals::get_singleton()->get_resource_path(); - FileAccess *f =FileAccess::open(project+"/.fscache",FileAccess::READ); + + String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache"); + FileAccess *f =FileAccess::open(fscache,FileAccess::READ); if (f) { //read the disk cache @@ -470,7 +472,9 @@ void EditorFileSystem::_scan_scenes() { //save back the findings - f=FileAccess::open(project+"/.fscache",FileAccess::WRITE); +// String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache"); + + f=FileAccess::open(fscache,FileAccess::WRITE); _save_type_cache_fs(scandir,f); f->close(); memdelete(f); @@ -989,6 +993,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_path(const String& p_path) { void EditorFileSystem::_resource_saved(const String& p_path){ + print_line("resource saved: "+p_path); EditorFileSystem::get_singleton()->update_file(p_path); } diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 56b813344ab..373c8aba737 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -54,7 +54,7 @@ #include "register_exporters.h" #include "bind/core_bind.h" #include "io/zip_io.h" - +#include "io/config_file.h" // plugins #include "plugins/sprite_frames_editor_plugin.h" @@ -91,6 +91,7 @@ #include "plugins/polygon_2d_editor_plugin.h" #include "plugins/navigation_polygon_editor_plugin.h" #include "plugins/light_occluder_2d_editor_plugin.h" +#include "plugins/color_ramp_editor_plugin.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" @@ -99,6 +100,7 @@ #include "tools/editor/io_plugins/editor_translation_import_plugin.h" #include "tools/editor/io_plugins/editor_mesh_import_plugin.h" +#include "plugins/editor_preview_plugins.h" EditorNode *EditorNode::singleton=NULL; @@ -320,6 +322,11 @@ void EditorNode::_fs_changed() { E->get()->invalidate(); } + + for(Set::Element *E=editor_file_dialogs.front();E;E=E->next()) { + + E->get()->invalidate(); + } } void EditorNode::_sources_changed(bool p_exist) { @@ -386,7 +393,7 @@ void EditorNode::edit_node(Node *p_node) { void EditorNode::open_resource(const String& p_type) { - file->set_mode(FileDialog::MODE_OPEN_FILE); + file->set_mode(EditorFileDialog::MODE_OPEN_FILE); List extensions; ResourceLoader::get_recognized_extensions_for_type(p_type,&extensions); @@ -718,6 +725,96 @@ void EditorNode::_save_edited_subresources(Node* scene,Map& processed, } +void EditorNode::_find_node_types(Node* p_node, int&count_2d, int&count_3d) { + + if (p_node->is_type("Viewport") || (p_node!=get_edited_scene() && p_node->get_owner()!=get_edited_scene())) + return; + + if (p_node->is_type("CanvasItem")) + count_2d++; + else if (p_node->is_type("Spatial")) + count_3d++; + + for(int i=0;iget_child_count();i++) + _find_node_types(p_node->get_child(i),count_2d,count_3d); + +} + + +void EditorNode::_save_scene_with_preview(String p_file) { + + int c2d=0; + int c3d=0; + + EditorProgress save("save","Saving Scene",4); + save.step("Analyzing",0); + _find_node_types(get_edited_scene(),c2d,c3d); + + RID viewport; + bool is2d; + if (c3dget_viewport(); + is2d=true; + } else { + viewport=SpatialEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_viewport(); + is2d=false; + + } + save.step("Creating Thumbnail",1); + //current view? + int screen =-1; + for(int i=0;iviewport_queue_screen_capture(viewport); + save.step("Creating Thumbnail",2); + save.step("Creating Thumbnail",3); + Image img = VS::get_singleton()->viewport_get_screen_capture(viewport); + int preview_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");; + int width,height; + if (img.get_width() > preview_size && img.get_width() >= img.get_height()) { + + width=preview_size; + height = img.get_height() * preview_size / img.get_width(); + } else if (img.get_height() > preview_size && img.get_height() >= img.get_width()) { + + height=preview_size; + width = img.get_width() * preview_size / img.get_height(); + } else { + + width=img.get_width(); + height=img.get_height(); + } + + img.convert(Image::FORMAT_RGB); + img.resize(width,height); + + String pfile = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/last_scene_preview.png"); + img.save_png(pfile); + Vector imgdata = FileAccess::get_file_as_array(pfile); + + print_line("img data is "+itos(imgdata.size())); + + if (scene_import_metadata.is_null()) + scene_import_metadata = Ref( memnew( ResourceImportMetadata ) ); + scene_import_metadata->set_option("thumbnail",imgdata); + + //tamanio tel thumbnail + if (screen!=-1) { + _editor_select(screen); + } + save.step("Saving Scene",4); + _save_scene(p_file); + +} + + void EditorNode::_save_scene(String p_file) { Node *scene = edited_scene; @@ -1016,7 +1113,9 @@ void EditorNode::_dialog_action(String p_file) { if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { - _save_scene(p_file); + //_save_scene(p_file); + _save_scene_with_preview(p_file); + } } break; @@ -1024,7 +1123,8 @@ void EditorNode::_dialog_action(String p_file) { case FILE_SAVE_AND_RUN: { if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { - _save_scene(p_file); + //_save_scene(p_file); + _save_scene_with_preview(p_file); _run(false); } } break; @@ -1177,7 +1277,8 @@ void EditorNode::_dialog_action(String p_file) { if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { - _save_scene(p_file); + //_save_scene(p_file); + _save_scene_with_preview(p_file); } } break; @@ -1276,7 +1377,7 @@ void EditorNode::_edit_current() { object_menu->set_disabled(false); resources_dock->add_resource(Ref(current_res)); - top_pallete->set_current_tab(1); + //top_pallete->set_current_tab(1); } @@ -1293,7 +1394,7 @@ void EditorNode::_edit_current() { scene_tree_dock->set_selected(current_node); object_menu->get_popup()->clear(); - top_pallete->set_current_tab(0); + //top_pallete->set_current_tab(0); } @@ -1505,7 +1606,8 @@ void EditorNode::_run(bool p_current,const String& p_custom) { return; } - _save_scene(scene->get_filename()); + //_save_scene(scene->get_filename()); + _save_scene_with_preview(scene->get_filename()); } } @@ -1608,7 +1710,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { //print_tree(); - file->set_mode(FileDialog::MODE_OPEN_FILE); + file->set_mode(EditorFileDialog::MODE_OPEN_FILE); //not for now? List extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions); @@ -1659,7 +1761,8 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { Node *scene = edited_scene; if (scene && scene->get_filename()!="") { - _save_scene(scene->get_filename()); + //_save_scene(scene->get_filename()); + _save_scene_with_preview(scene->get_filename()); return; }; // fallthrough to save_as @@ -1678,7 +1781,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { break; } - file->set_mode(FileDialog::MODE_SAVE_FILE); + file->set_mode(EditorFileDialog::MODE_SAVE_FILE); bool relpaths = (scene->has_meta("__editor_relpaths__") && scene->get_meta("__editor_relpaths__").operator bool()); @@ -1761,7 +1864,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { bool relpaths = (scene->has_meta("__editor_relpaths__") && scene->get_meta("__editor_relpaths__").operator bool()); - file->set_mode(FileDialog::MODE_SAVE_FILE); + file->set_mode(EditorFileDialog::MODE_SAVE_FILE); file->set_current_path(cpath); file->set_title("Save Translatable Strings"); @@ -1810,7 +1913,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { break; } - file->set_mode(FileDialog::MODE_SAVE_FILE); + file->set_mode(EditorFileDialog::MODE_SAVE_FILE); List extensions; Ref sd = memnew( PackedScene ); @@ -2805,7 +2908,7 @@ Error EditorNode::load_scene(const String& p_scene) { prev_scene->set_disabled(previous_scenes.size()==0); opening_prev=false; - top_pallete->set_current_tab(0); //always go to scene + //top_pallete->set_current_tab(0); //always go to scene push_item(new_scene); @@ -2838,9 +2941,9 @@ void EditorNode::_instance_request(const String& p_path){ request_instance_scene(p_path); } -void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value) { +void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value,bool p_advance) { - animation_editor->insert_value_key(p_keyed,p_value); + animation_editor->insert_value_key(p_keyed,p_value,p_advance); } void EditorNode::_transform_keyed(Object *sp,const String& p_sub,const Transform& p_key) { @@ -2878,15 +2981,15 @@ void EditorNode::_update_keying() { void EditorNode::_close_messages() { // left_split->set_dragger_visible(false); - old_split_ofs = left_split->get_split_offset(); - left_split->set_split_offset(0); + old_split_ofs = center_split->get_split_offset(); + center_split->set_split_offset(0); // scene_root_parent->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_END,0); } void EditorNode::_show_messages() { // left_split->set_dragger_visible(true); - left_split->set_split_offset(old_split_ofs); + center_split->set_split_offset(old_split_ofs); // scene_root_parent->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_END,log->get_margin(MARGIN_TOP)); } @@ -3132,6 +3235,7 @@ void EditorNode::register_editor_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); //ObjectTypeDB::register_type(); @@ -3230,6 +3334,17 @@ void EditorNode::_bind_methods() { ObjectTypeDB::bind_method("_sources_changed",&EditorNode::_sources_changed); ObjectTypeDB::bind_method("_fs_changed",&EditorNode::_fs_changed); + ObjectTypeDB::bind_method("_dock_select_draw",&EditorNode::_dock_select_draw); + ObjectTypeDB::bind_method("_dock_select_input",&EditorNode::_dock_select_input); + ObjectTypeDB::bind_method("_dock_pre_popup",&EditorNode::_dock_pre_popup); + ObjectTypeDB::bind_method("_dock_split_dragged",&EditorNode::_dock_split_dragged); + ObjectTypeDB::bind_method("_save_docks",&EditorNode::_save_docks); + ObjectTypeDB::bind_method("_dock_popup_exit",&EditorNode::_dock_popup_exit); + ObjectTypeDB::bind_method("_dock_move_left",&EditorNode::_dock_move_left); + ObjectTypeDB::bind_method("_dock_move_right",&EditorNode::_dock_move_right); + + + ObjectTypeDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin); ObjectTypeDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin); @@ -3282,6 +3397,16 @@ void EditorNode::_file_dialog_unregister(FileDialog *p_dialog){ singleton->file_dialogs.erase(p_dialog); } +void EditorNode::_editor_file_dialog_register(EditorFileDialog *p_dialog) { + + singleton->editor_file_dialogs.insert(p_dialog); +} + +void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog){ + + singleton->editor_file_dialogs.erase(p_dialog); +} + Vector EditorNode::_init_callbacks; Error EditorNode::export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after) { @@ -3300,6 +3425,329 @@ void EditorNode::show_warning(const String& p_text) { warning->popup_centered_minsize(); } +void EditorNode::_dock_select_input(const InputEvent& p_input) { + + if (p_input.type==InputEvent::MOUSE_BUTTON || p_input.type==InputEvent::MOUSE_MOTION) { + + Vector2 point(p_input.mouse_motion.x,p_input.mouse_motion.y); + + int nrect = -1; + for(int i=0;iupdate(); + dock_select_rect_over=nrect; + + } + + + if (nrect==-1) + return; + + if (p_input.type==InputEvent::MOUSE_BUTTON && p_input.mouse_button.button_index==1 && p_input.mouse_button.pressed && dock_popup_selected!=nrect) { + Control *dock = dock_slot[dock_popup_selected]->get_current_tab_control(); + if (dock) { + dock_slot[dock_popup_selected]->remove_child(dock); + } + if (dock_slot[dock_popup_selected]->get_tab_count()==0) { + dock_slot[dock_popup_selected]->hide(); + + } else { + + dock_slot[dock_popup_selected]->set_current_tab(0); + } + + print_line("performing reparent"); + dock_slot[nrect]->add_child(dock); + dock_popup_selected=nrect; + dock_slot[nrect]->set_current_tab(dock_slot[nrect]->get_tab_count()-1); + dock_slot[nrect]->show(); + dock_select->update(); + + VSplitContainer*splits[DOCK_SLOT_MAX/2]={ + left_l_vsplit, + left_r_vsplit, + right_l_vsplit, + right_r_vsplit, + }; + + for(int i=0;i<4;i++) { + bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count(); + if (in_use) + splits[i]->show(); + else + splits[i]->hide(); + } + + _save_docks(); + } + } +} + +void EditorNode::_dock_popup_exit() { + + dock_select_rect_over=-1; + dock_select->update(); +} + +void EditorNode::_dock_pre_popup(int p_which) { + + + dock_popup_selected=p_which; +} + +void EditorNode::_dock_move_left() { + + if (dock_popup_selected<0 || dock_popup_selected>=DOCK_SLOT_MAX) + return; + Control *current = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab() ); + Control *prev = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab()-1 ); + if (!current || !prev) + return; + dock_slot[dock_popup_selected]->move_child(current,prev->get_index()); + dock_slot[dock_popup_selected]->set_current_tab( dock_slot[dock_popup_selected]->get_current_tab()-1 ); + dock_select->update(); + _save_docks(); + + +} + +void EditorNode::_dock_move_right() { + + Control *current = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab() ); + Control *next = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab()+1 ); + if (!current || !next) + return; + dock_slot[dock_popup_selected]->move_child(next,current->get_index()); + dock_slot[dock_popup_selected]->set_current_tab( dock_slot[dock_popup_selected]->get_current_tab()+1 ); + dock_select->update(); + _save_docks(); +} + +void EditorNode::_dock_select_draw(){ + Size2 s = dock_select->get_size(); + s.y/=2.0; + s.x/=6.0; + + Color used=Color(0.6,0.6,0.6,0.8); + Color used_selected=Color(0.8,0.8,0.8,0.8); + Color tab_selected=Color(1,1,1,1); + Color unused=used; + unused.a=0.4; + Color unusable=unused; + unusable.a=0.1; + + Rect2 unr(s.x*2,0,s.x*2,s.y*2); + unr.pos+=Vector2(2,5); + unr.size-=Vector2(4,7); + + dock_select->draw_rect(unr,unusable); + + dock_tab_move_left->set_disabled(true); + dock_tab_move_right->set_disabled(true); + + if (dock_popup_selected!=-1 && dock_slot[dock_popup_selected]->get_tab_count()) { + + dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected]->get_current_tab()==0); + dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected]->get_current_tab()>=dock_slot[dock_popup_selected]->get_tab_count()-1); + } + + for(int i=0;idraw_rect(r,used_selected); + } else if (dock_slot[i]->get_child_count()==0) { + dock_select->draw_rect(r,unused); + } else { + + dock_select->draw_rect(r,used); + } + + for(int j=0;jget_child_count());j++) { + int xofs = (r.size.width/3)*j; + Color c = used; + if (i==dock_popup_selected && (dock_slot[i]->get_current_tab()>3 || dock_slot[i]->get_current_tab()==j)) + c=tab_selected; + dock_select->draw_rect(Rect2(2+ofs.x+xofs,ofs.y,r.size.width/3-1,3),c); + } + + } +} + +void EditorNode::_save_docks() { + + Ref config; + config.instance(); + + for(int i=0;iget_tab_count();j++) { + String name = dock_slot[i]->get_tab_control(j)->get_name(); + if (names!="") + names+=","; + names+=name; + } + + if (names!="") { + config->set_value("docks","dock_"+itos(i+1),names); + } + } + + VSplitContainer*splits[DOCK_SLOT_MAX/2]={ + left_l_vsplit, + left_r_vsplit, + right_l_vsplit, + right_r_vsplit, + }; + + for(int i=0;iis_visible()) { + config->set_value("docks","dock_split_"+itos(i+1),splits[i]->get_split_offset()); + } + } + + + config->save(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg")); + +} + +void EditorNode::_dock_split_dragged(int ofs) { + + dock_drag_timer->start(); +} + +void EditorNode::_load_docks() { + + Ref config; + config.instance(); + Error err = config->load(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg")); + if (err!=OK) { + return; //no config + } + + for(int i=0;ihas_section_key("docks","dock_"+itos(i+1))) + continue; + + Vector names = String(config->get_value("docks","dock_"+itos(i+1))).split(","); + + for(int j=0;jhas_node(name)) + continue; + node=dock_slot[k]->get_node(name)->cast_to(); + if (!node) + continue; + atidx=k; + break; + } + if (atidx==-1) //well, it's not anywhere + continue; + + if (atidx==j) { + node->raise(); + continue; + } + + + dock_slot[atidx]->remove_child(node); + + if (dock_slot[atidx]->get_tab_count()==0) { + dock_slot[atidx]->hide(); + + } + dock_slot[i]->add_child(node); + dock_slot[i]->show(); + } + + } + + VSplitContainer*splits[DOCK_SLOT_MAX/2]={ + left_l_vsplit, + left_r_vsplit, + right_l_vsplit, + right_r_vsplit, + }; + + for(int i=0;ihas_section_key("docks","dock_split_"+itos(i+1))) + continue; + + int ofs = config->get_value("docks","dock_split_"+itos(i+1)); + splits[i]->set_split_offset(ofs); + } + + for(int i=0;iget_tab_count() || dock_slot[i*2+1]->get_tab_count(); + if (in_use) + splits[i]->show(); + else + splits[i]->hide(); + } + + for(int i=0;iis_hidden() && dock_slot[i]->get_tab_count()) { + dock_slot[i]->set_current_tab(0); + } + } + +} EditorNode::EditorNode() { @@ -3334,6 +3782,11 @@ EditorNode::EditorNode() { FileDialog::register_func=_file_dialog_register; FileDialog::unregister_func=_file_dialog_unregister; + EditorFileDialog::get_icon_func=_file_dialog_get_icon; + EditorFileDialog::register_func=_editor_file_dialog_register; + EditorFileDialog::unregister_func=_editor_file_dialog_unregister; + + editor_import_export = memnew( EditorImportExport ); add_child(editor_import_export); @@ -3358,6 +3811,9 @@ EditorNode::EditorNode() { editor_register_icons(theme); editor_register_fonts(theme); + //theme->set_icon("folder","EditorFileDialog",Theme::get_default()->get_icon("folder","EditorFileDialog")); + //theme->set_color("files_disabled","EditorFileDialog",Color(0,0,0,0.7)); + String global_font = EditorSettings::get_singleton()->get("global/font"); if (global_font!="") { Ref fnt = ResourceLoader::load(global_font); @@ -3376,6 +3832,8 @@ EditorNode::EditorNode() { theme->set_stylebox("EditorFocus","EditorStyles",focus_sbt); + resource_preview = memnew( EditorResourcePreview ); + add_child(resource_preview); progress_dialog = memnew( ProgressDialog ); gui_base->add_child(progress_dialog); @@ -3391,18 +3849,124 @@ EditorNode::EditorNode() { menu_hb = memnew( HBoxContainer ); main_vbox->add_child(menu_hb); - main_split = memnew( HSplitContainer ); - main_vbox->add_child(main_split); - main_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); + //left + left_l_hsplit = memnew( HSplitContainer ); + main_vbox->add_child(left_l_hsplit); + + left_l_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL); + + left_l_vsplit = memnew( VSplitContainer ); + left_l_hsplit->add_child(left_l_vsplit); + dock_slot[DOCK_SLOT_LEFT_UL]=memnew( TabContainer ); + left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]); + dock_slot[DOCK_SLOT_LEFT_BL]=memnew( TabContainer ); + left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]); + left_l_vsplit->hide(); + dock_slot[DOCK_SLOT_LEFT_UL]->hide(); + dock_slot[DOCK_SLOT_LEFT_BL]->hide(); + + left_r_hsplit = memnew( HSplitContainer ); + left_l_hsplit->add_child(left_r_hsplit); + left_r_vsplit = memnew( VSplitContainer ); + left_r_hsplit->add_child(left_r_vsplit); + dock_slot[DOCK_SLOT_LEFT_UR]=memnew( TabContainer ); + left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UR]); + dock_slot[DOCK_SLOT_LEFT_BR]=memnew( TabContainer ); + left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BR]); + //left_r_vsplit->hide(); + //dock_slot[DOCK_SLOT_LEFT_UR]->hide(); + //dock_slot[DOCK_SLOT_LEFT_BR]->hide(); - left_split = memnew( VSplitContainer ); - main_split->add_child(left_split); - left_split->set_h_size_flags(Control::SIZE_EXPAND_FILL); - left_split->set_collapsed(false); + main_hsplit = memnew( HSplitContainer ); + left_r_hsplit->add_child(main_hsplit); + //main_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); + + center_split = memnew( VSplitContainer ); + main_hsplit->add_child(center_split); + center_split->set_h_size_flags(Control::SIZE_EXPAND_FILL); + center_split->set_collapsed(false); + + right_hsplit = memnew( HSplitContainer ); + main_hsplit->add_child(right_hsplit); + + right_l_vsplit = memnew( VSplitContainer ); + right_hsplit->add_child(right_l_vsplit); + dock_slot[DOCK_SLOT_RIGHT_UL]=memnew( TabContainer ); + right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UL]); + dock_slot[DOCK_SLOT_RIGHT_BL]=memnew( TabContainer ); + right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BL]); + + right_r_vsplit = memnew( VSplitContainer ); + right_hsplit->add_child(right_r_vsplit); + dock_slot[DOCK_SLOT_RIGHT_UR]=memnew( TabContainer ); + right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]); + dock_slot[DOCK_SLOT_RIGHT_BR]=memnew( TabContainer ); + right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]); + right_r_vsplit->hide(); + //dock_slot[DOCK_SLOT_RIGHT_UL]->hide(); + //dock_slot[DOCK_SLOT_RIGHT_BL]->hide(); + + left_l_vsplit->connect("dragged",this,"_dock_split_dragged"); + left_r_vsplit->connect("dragged",this,"_dock_split_dragged"); + right_l_vsplit->connect("dragged",this,"_dock_split_dragged"); + right_r_vsplit->connect("dragged",this,"_dock_split_dragged"); + + + dock_select_popoup = memnew( PopupPanel ); + gui_base->add_child(dock_select_popoup); + VBoxContainer *dock_vb = memnew( VBoxContainer ); + dock_select_popoup->add_child(dock_vb); + + HBoxContainer *dock_hb = memnew( HBoxContainer); + dock_tab_move_left = memnew( ToolButton ); + dock_tab_move_left->set_icon(theme->get_icon("Back","EditorIcons")); + dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE); + dock_tab_move_left->connect("pressed",this,"_dock_move_left"); + //dock_tab_move_left->set_h_size_flags(Control::SIZE_EXPAND_FILL); + dock_hb->add_child(dock_tab_move_left); + dock_hb->add_spacer(); + dock_tab_move_right = memnew( ToolButton ); + dock_tab_move_right->set_icon(theme->get_icon("Forward","EditorIcons")); + dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE); + dock_tab_move_right->connect("pressed",this,"_dock_move_right"); + + //dock_tab_move_right->set_h_size_flags(Control::SIZE_EXPAND_FILL); + dock_hb->add_child(dock_tab_move_right); + dock_vb->add_child(dock_hb); + + dock_select = memnew( Control ); + dock_select->set_custom_minimum_size(Size2(128,64)); + dock_select->connect("input_event",this,"_dock_select_input"); + dock_select->connect("draw",this,"_dock_select_draw"); + dock_select->connect("mouse_exit",this,"_dock_popup_exit"); + dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL); + dock_vb->add_child(dock_select); + + + dock_select_popoup->set_child_rect(dock_vb); + dock_select_popoup->set_as_minsize(); + dock_select_rect_over=-1; + dock_popup_selected=-1; + //dock_select_popoup->set_(Size2(20,20)); + + for(int i=0;iset_custom_minimum_size(Size2(250,250)); + dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL); + dock_slot[i]->set_popup(dock_select_popoup); + dock_slot[i]->connect("pre_popup_pressed",this,"_dock_pre_popup",varray(i)); + + //dock_slot[i]->set_tab_align(TabContainer::ALIGN_LEFT); + } + + dock_drag_timer = memnew( Timer ); + add_child(dock_drag_timer); + dock_drag_timer->set_wait_time(0.5); + dock_drag_timer->set_one_shot(true); + dock_drag_timer->connect("timeout",this,"_save_docks"); top_split = memnew( VSplitContainer ); - left_split->add_child(top_split); + center_split->add_child(top_split); top_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); top_split->set_collapsed(true); @@ -3473,6 +4037,7 @@ EditorNode::EditorNode() { animation_panel=pc; animation_panel->hide(); + HBoxContainer *animation_hb = memnew( HBoxContainer); animation_vb->add_child(animation_hb); @@ -3770,45 +4335,47 @@ EditorNode::EditorNode() { - editor_hsplit = memnew( HSplitContainer ); - main_split->add_child(editor_hsplit); - editor_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL); + //editor_hsplit = memnew( HSplitContainer ); + //main_split->add_child(editor_hsplit); + //editor_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL); - editor_vsplit = memnew( VSplitContainer ); - editor_hsplit->add_child(editor_vsplit); + //editor_vsplit = memnew( VSplitContainer ); + //editor_hsplit->add_child(editor_vsplit); - top_pallete = memnew( TabContainer ); + //top_pallete = memnew( TabContainer ); scene_tree_dock = memnew( SceneTreeDock(this,scene_root,editor_selection,editor_data) ); scene_tree_dock->set_name("Scene"); - top_pallete->add_child(scene_tree_dock); + //top_pallete->add_child(scene_tree_dock); + dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scene_tree_dock); resources_dock = memnew( ResourcesDock(this) ); resources_dock->set_name("Resources"); - top_pallete->add_child(resources_dock); - top_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL); + //top_pallete->add_child(resources_dock); + dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(resources_dock); + //top_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL); - Control *editor_spacer = memnew( Control ); + /*Control *editor_spacer = memnew( Control ); editor_spacer->set_custom_minimum_size(Size2(260,200)); editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor_vsplit->add_child( editor_spacer ); editor_spacer->add_child( top_pallete ); - top_pallete->set_area_as_parent_rect(); + top_pallete->set_area_as_parent_rect();*/ - prop_pallete = memnew( TabContainer ); + //prop_pallete = memnew( TabContainer ); - prop_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL); + //prop_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL); - editor_spacer = memnew( Control ); + /*editor_spacer = memnew( Control ); editor_spacer->set_custom_minimum_size(Size2(260,200)); editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL); editor_vsplit->add_child( editor_spacer ); editor_spacer->add_child( prop_pallete ); - prop_pallete->set_area_as_parent_rect(); + prop_pallete->set_area_as_parent_rect();*/ VBoxContainer *prop_editor_base = memnew( VBoxContainer ); prop_editor_base->set_name("Inspector"); // Properties? - prop_pallete->add_child(prop_editor_base); + dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(prop_editor_base); HBoxContainer *prop_editor_hb = memnew( HBoxContainer ); prop_editor_base->add_child(prop_editor_hb); @@ -3850,14 +4417,15 @@ EditorNode::EditorNode() { scenes_dock = memnew( ScenesDock(this) ); scenes_dock->set_name("FileSystem"); - prop_pallete->add_child(scenes_dock); + dock_slot[DOCK_SLOT_LEFT_BR]->add_child(scenes_dock); + //prop_pallete->add_child(scenes_dock); scenes_dock->connect("open",this,"open_request"); scenes_dock->connect("instance",this,"_instance_request"); log = memnew( EditorLog ); - left_split->add_child(log); + center_split->add_child(log); log->connect("close_request",this,"_close_messages"); log->connect("show_request",this,"_show_messages"); //left_split->set_dragger_visible(false); @@ -3873,7 +4441,7 @@ EditorNode::EditorNode() { animation_vb->add_child(animation_editor); - left_split->connect("resized",this,"_vp_resized"); + center_split->connect("resized",this,"_vp_resized"); animation_editor->hide(); @@ -4031,7 +4599,7 @@ EditorNode::EditorNode() { file_templates->add_filter("*.tpz ; Template Package"); - file = memnew( FileDialog ); + file = memnew( EditorFileDialog ); gui_base->add_child(file); file->set_current_dir("res://"); @@ -4105,8 +4673,9 @@ EditorNode::EditorNode() { editor_import_export->add_import_plugin( Ref( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_TEXTURE_2D) ))); - editor_import_export->add_import_plugin( Ref( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_TEXTURE_3D) ))); editor_import_export->add_import_plugin( Ref( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_ATLAS) ))); + editor_import_export->add_import_plugin( Ref( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_LARGE) ))); + editor_import_export->add_import_plugin( Ref( memnew(EditorTextureImportPlugin(this,EditorTextureImportPlugin::MODE_TEXTURE_3D) ))); Ref _scene_import = memnew(EditorSceneImportPlugin(this) ); Ref _collada_import = memnew( EditorSceneImporterCollada); _scene_import->add_importer(_collada_import); @@ -4157,10 +4726,19 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) ); add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) ); add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) ); + add_editor_plugin( memnew( ColorRampEditorPlugin(this) ) ); for(int i=0;iadd_preview_generator( Ref( memnew(EditorTexturePreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorPackedScenePreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorMaterialPreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorScriptPreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorSamplePreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorMeshPreviewPlugin ))); + circle_step_msec=OS::get_singleton()->get_ticks_msec(); circle_step_frame=OS::get_singleton()->get_frames_drawn();; circle_step=0; @@ -4268,12 +4846,15 @@ EditorNode::EditorNode() { Node::set_human_readable_collision_renaming(true); + + // Ref it = gui_base->get_icon("logo","Icons"); // OS::get_singleton()->set_icon( it->get_data() ); for(int i=0;i<_init_callbacks.size();i++) _init_callbacks[i](); + _load_docks(); } diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 76e82b5a6b6..2ef9332c844 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -78,7 +78,7 @@ #include "tools/editor/editor_plugin.h" #include "fileserver/editor_file_server.h" - +#include "editor_resource_preview.h" @@ -94,6 +94,8 @@ typedef void (*EditorNodeInitCallback)(); + + class EditorNode : public Node { OBJ_TYPE( EditorNode, Node ); @@ -168,7 +170,17 @@ class EditorNode : public Node { OBJECT_METHOD_BASE=500 }; - + enum DockSlot { + DOCK_SLOT_LEFT_UL, + DOCK_SLOT_LEFT_BL, + DOCK_SLOT_LEFT_UR, + DOCK_SLOT_LEFT_BR, + DOCK_SLOT_RIGHT_UL, + DOCK_SLOT_RIGHT_BL, + DOCK_SLOT_RIGHT_UR, + DOCK_SLOT_RIGHT_BR, + DOCK_SLOT_MAX + }; Node *edited_scene; //scene being edited @@ -179,8 +191,22 @@ class EditorNode : public Node { Control* scene_root_parent; Control *gui_base; VBoxContainer *main_vbox; - HSplitContainer *main_split; - VSplitContainer *left_split; + + + + HSplitContainer *left_l_hsplit; + VSplitContainer *left_l_vsplit; + HSplitContainer *left_r_hsplit; + VSplitContainer *left_r_vsplit; + HSplitContainer *main_hsplit; + HSplitContainer *right_hsplit; + VSplitContainer *right_l_vsplit; + VSplitContainer *right_r_vsplit; + + VSplitContainer *center_split; + + + int old_split_ofs; VSplitContainer *top_split; HBoxContainer *bottom_hb; @@ -190,8 +216,9 @@ class EditorNode : public Node { TextureButton *anim_close; Panel *menu_panel; - HSplitContainer *editor_hsplit; - VSplitContainer *editor_vsplit; + + //HSplitContainer *editor_hsplit; + //VSplitContainer *editor_vsplit; HBoxContainer *menu_hb; Control *viewport; MenuButton *file_menu; @@ -238,7 +265,7 @@ class EditorNode : public Node { EditorSettingsDialog *settings_config_dialog; RunSettingsDialog *run_settings_dialog; ProjectSettings *project_settings; - FileDialog *file; + EditorFileDialog *file; FileDialog *file_templates; FileDialog *file_export; FileDialog *file_export_lib; @@ -249,8 +276,8 @@ class EditorNode : public Node { String current_path; MenuButton *update_menu; ToolButton *sources_button; - TabContainer *prop_pallete; - TabContainer *top_pallete; + //TabContainer *prop_pallete; + //TabContainer *top_pallete; String defer_load_scene; String defer_translatable; String defer_optimize; @@ -277,6 +304,16 @@ class EditorNode : public Node { ProgressDialog *progress_dialog; BackgroundProgress *progress_hb; + TabContainer *dock_slot[DOCK_SLOT_MAX]; + Rect2 dock_select_rect[DOCK_SLOT_MAX]; + int dock_select_rect_over; + PopupPanel *dock_select_popoup; + Control *dock_select; + ToolButton *dock_tab_move_left; + ToolButton *dock_tab_move_right; + int dock_popup_selected; + Timer *dock_drag_timer; + String _tmp_import_path; EditorImportExport *editor_import_export; @@ -304,6 +341,7 @@ class EditorNode : public Node { EditorSelection *editor_selection; ProjectExport *project_export; ProjectExportDialog *project_export_settings; + EditorResourcePreview *resource_preview; EditorFileServer *file_server; @@ -348,7 +386,7 @@ class EditorNode : public Node { void _instance_request(const String& p_path); - void _property_keyed(const String& p_keyed,const Variant& p_value); + void _property_keyed(const String& p_keyed, const Variant& p_value, bool p_advance); void _transform_keyed(Object *sp,const String& p_sub,const Transform& p_key); void _update_keying(); @@ -381,11 +419,15 @@ class EditorNode : public Node { String import_reload_fn; Set file_dialogs; + Set editor_file_dialogs; + Map > icon_type_cache; static Ref _file_dialog_get_icon(const String& p_path); static void _file_dialog_register(FileDialog *p_dialog); static void _file_dialog_unregister(FileDialog *p_dialog); + static void _editor_file_dialog_register(EditorFileDialog *p_dialog); + static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog); void _cleanup_scene(); @@ -394,6 +436,9 @@ class EditorNode : public Node { bool _find_and_save_edited_subresources(Object *obj,Map& processed,int32_t flags); void _save_edited_subresources(Node* scene,Map& processed,int32_t flags); + void _find_node_types(Node* p_node, int&count_2d, int&count_3d); + void _save_scene_with_preview(String p_file); + struct ExportDefer { String platform; @@ -409,6 +454,16 @@ class EditorNode : public Node { bool _find_scene_in_use(Node* p_node,const String& p_path) const; + void _dock_select_input(const InputEvent& p_input); + void _dock_move_left(); + void _dock_move_right(); + void _dock_select_draw(); + void _dock_pre_popup(int p_which); + void _dock_split_dragged(int ofs); + void _dock_popup_exit(); + + void _save_docks(); + void _load_docks(); protected: void _notification(int p_what); diff --git a/tools/editor/editor_resource_preview.cpp b/tools/editor/editor_resource_preview.cpp new file mode 100644 index 00000000000..f684b49a2cc --- /dev/null +++ b/tools/editor/editor_resource_preview.cpp @@ -0,0 +1,261 @@ +#include "editor_resource_preview.h" +#include "editor_settings.h" +#include "os/file_access.h" +#include "io/resource_loader.h" +#include "io/resource_saver.h" +#include "globals.h" + + +Ref EditorResourcePreviewGenerator::generate_from_path(const String& p_path) { + + RES res = ResourceLoader::load(p_path); + if (!res.is_valid()) + return res; + return generate(res); +} + +EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() { + + +} + + +EditorResourcePreview* EditorResourcePreview::singleton=NULL; + + +void EditorResourcePreview::_thread_func(void *ud) { + + EditorResourcePreview *erp=(EditorResourcePreview*)ud; + erp->_thread(); + +} + + +void EditorResourcePreview::_preview_ready(const String& p_str,const Ref& p_texture,ObjectID id,const StringName& p_func,const Variant& p_ud) { + + //print_line("preview is ready"); + preview_mutex->lock(); + + Item item; + item.order=order++; + item.preview=p_texture; + cache[p_str]=item; + + Object *recv = ObjectDB::get_instance(id); + if (recv) { + recv->call_deferred(p_func,p_str,p_texture,p_ud); + } + + preview_mutex->unlock(); +} + +Ref EditorResourcePreview::_generate_preview(const QueueItem& p_item,const String& cache_base) { + + String type = ResourceLoader::get_resource_type(p_item.path); + //print_line("resource type is: "+type); + + if (type=="") + return Ref(); //could not guess type + + Ref generated; + + for(int i=0;ihandles(type)) + continue; + generated = preview_generators[i]->generate_from_path(p_item.path); + + break; + } + + if (generated.is_valid()) { + //print_line("was generated"); + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + //wow it generated a preview... save cache + ResourceSaver::save(cache_base+".png",generated); + FileAccess *f=FileAccess::open(cache_base+".txt",FileAccess::WRITE); + f->store_line(itos(thumbnail_size)); + f->store_line(itos(FileAccess::get_modified_time(p_item.path))); + f->store_line(FileAccess::get_md5(p_item.path)); + memdelete(f); + } else { + //print_line("was not generated"); + + } + + return generated; +} + +void EditorResourcePreview::_thread() { + + //print_line("begin thread"); + while(!exit) { + + //print_line("wait for semaphore"); + preview_sem->wait(); + preview_mutex->lock(); + + //print_line("blue team go"); + + if (queue.size()) { + + + + QueueItem item = queue.front()->get(); + queue.pop_front(); + preview_mutex->unlock(); + + Ref texture; + + //print_line("pop from queue "+item.path); + + uint64_t modtime = FileAccess::get_modified_time(item.path); + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + + if (cache.has(item.path)) { + //already has it because someone loaded it, just let it know it's ready + call_deferred("_preview_ready",item.path,cache[item.path].preview,item.id,item.function,item.userdata); + + } else { + + + String temp_path=EditorSettings::get_singleton()->get_settings_path().plus_file("tmp"); + String cache_base = Globals::get_singleton()->globalize_path(item.path).md5_text(); + cache_base = temp_path.plus_file("resthumb-"+cache_base); + + //does not have it, try to load a cached thumbnail + + String file = cache_base+".txt"; + //print_line("cachetxt at "+file); + FileAccess *f=FileAccess::open(file,FileAccess::READ); + if (!f) { + + //print_line("generate because not cached"); + + //generate + texture=_generate_preview(item,cache_base); + } else { + + int tsize = f->get_line().to_int64(); + uint64_t last_modtime = f->get_line().to_int64(); + + bool cache_valid = true; + + if (tsize!=thumbnail_size) { + cache_valid=false; + memdelete(f); + } else if (last_modtime!=modtime) { + + String last_md5 = f->get_line(); + String md5 = FileAccess::get_md5(item.path); + memdelete(f); + + if (last_md5!=md5) { + + cache_valid=false; + } else { + //update modified time + + f=FileAccess::open(file,FileAccess::WRITE); + f->store_line(itos(modtime)); + f->store_line(md5); + memdelete(f); + } + } else { + memdelete(f); + } + + if (cache_valid) { + + texture = ResourceLoader::load(cache_base+".png","ImageTexture",true); + if (!texture.is_valid()) { + //well fuck + cache_valid=false; + } + } + + if (!cache_valid) { + + texture=_generate_preview(item,cache_base); + } + + } + + //print_line("notify of preview ready"); + call_deferred("_preview_ready",item.path,texture,item.id,item.function,item.userdata); + + } + + } else { + preview_mutex->unlock(); + } + + } +} + + + + +void EditorResourcePreview::queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) { + + ERR_FAIL_NULL(p_receiver); + preview_mutex->lock(); + if (cache.has(p_path)) { + cache[p_path].order=order++; + p_receiver->call_deferred(p_receiver_func,p_path,cache[p_path].preview,p_userdata); + preview_mutex->unlock(); + return; + + } + + //print_line("send to thread "+p_path); + QueueItem item; + item.function=p_receiver_func; + item.id=p_receiver->get_instance_ID(); + item.path=p_path; + item.userdata=p_userdata; + + queue.push_back(item); + preview_mutex->unlock(); + preview_sem->post(); + +} + +void EditorResourcePreview::add_preview_generator(const Ref& p_generator) { + + preview_generators.push_back(p_generator); +} + +EditorResourcePreview* EditorResourcePreview::get_singleton() { + + return singleton; +} + +void EditorResourcePreview::_bind_methods() { + + ObjectTypeDB::bind_method("_preview_ready",&EditorResourcePreview::_preview_ready); +} + +EditorResourcePreview::EditorResourcePreview() { + singleton=this; + preview_mutex = Mutex::create(); + preview_sem = Semaphore::create(); + order=0; + exit=false; + + thread = Thread::create(_thread_func,this); +} + + +EditorResourcePreview::~EditorResourcePreview() +{ + + exit=true; + preview_sem->post(); + Thread::wait_to_finish(thread); + memdelete(thread); + memdelete(preview_mutex); + memdelete(preview_sem); + + +} + diff --git a/tools/editor/editor_resource_preview.h b/tools/editor/editor_resource_preview.h new file mode 100644 index 00000000000..aadae755970 --- /dev/null +++ b/tools/editor/editor_resource_preview.h @@ -0,0 +1,95 @@ +#ifndef EDITORRESOURCEPREVIEW_H +#define EDITORRESOURCEPREVIEW_H + +#include "scene/main/node.h" +#include "os/semaphore.h" +#include "os/thread.h" +#include "scene/resources/texture.h" + +/* make previews for: +*packdscene +*wav +*image +*mesh +-font +*script +*material +-shader +-shader graph? +-navigation mesh +-collision? +-occluder polygon +-navigation polygon +-tileset +-curve and curve2D +*/ + + +class EditorResourcePreviewGenerator : public Reference { + + OBJ_TYPE(EditorResourcePreviewGenerator,Reference ); + +public: + + virtual bool handles(const String& p_type) const=0; + virtual Ref generate(const RES& p_from)=0; + virtual Ref generate_from_path(const String& p_path); + + EditorResourcePreviewGenerator(); +}; + + +class EditorResourcePreview : public Node { + + OBJ_TYPE(EditorResourcePreview,Node); + + + static EditorResourcePreview* singleton; + + struct QueueItem { + String path; + ObjectID id; + StringName function; + Variant userdata; + }; + + List queue; + + Mutex *preview_mutex; + Semaphore *preview_sem; + Thread *thread; + bool exit; + + struct Item { + Ref preview; + int order; + }; + + int order; + + Map cache; + + void _preview_ready(const String& p_str,const Ref& p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud); + Ref _generate_preview(const QueueItem& p_item, const String &cache_base); + + static void _thread_func(void *ud); + void _thread(); + + Vector > preview_generators; +protected: + + static void _bind_methods(); +public: + + static EditorResourcePreview* get_singleton(); + + //callback funtion is callback(String p_path,Ref preview,Variant udata) preview null if could not load + void queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata); + + void add_preview_generator(const Ref& p_generator); + + EditorResourcePreview(); + ~EditorResourcePreview(); +}; + +#endif // EDITORRESOURCEPREVIEW_H diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index f49d3b496d4..361a86b88ef 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -224,6 +224,28 @@ void EditorSettings::create() { dir->change_dir(".."); } + if (dir->change_dir("config")!=OK) { + dir->make_dir("config"); + } else { + + dir->change_dir(".."); + } + + dir->change_dir("config"); + + String pcp=Globals::get_singleton()->get_resource_path(); + if (pcp.ends_with("/")) + pcp=config_path.substr(0,pcp.size()-1); + pcp=pcp.get_file()+"-"+pcp.md5_text(); + + if (dir->change_dir(pcp)) { + dir->make_dir(pcp); + } else { + dir->change_dir(".."); + } + + dir->change_dir(".."); + // path at least is validated, so validate config file @@ -244,6 +266,7 @@ void EditorSettings::create() { } singleton->config_file_path=config_file_path; + singleton->project_config_path=pcp; singleton->settings_path=config_path+"/"+config_dir; if (OS::get_singleton()->is_stdout_verbose()) { @@ -251,7 +274,7 @@ void EditorSettings::create() { print_line("EditorSettings: Load OK!"); } - + singleton->load_favorites(); singleton->scan_plugins(); return; @@ -448,6 +471,8 @@ void EditorSettings::_load_defaults() { set("text_editor/create_signal_callbacks",true); set("file_dialog/show_hidden_files", false); + set("file_dialog/thumbnail_size", 64); + hints["file_dialog/thumbnail_size"]=PropertyInfo(Variant::INT,"file_dialog/thumbnail_size",PROPERTY_HINT_RANGE,"32,128,16"); set("animation/autorename_animation_tracks",true); set("animation/confirm_insert_track",true); @@ -646,6 +671,71 @@ void EditorSettings::set_plugin_enabled(const String& p_plugin, bool p_enabled) } +void EditorSettings::set_favorite_dirs(const Vector& p_favorites) { + + favorite_dirs=p_favorites; + FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"),FileAccess::WRITE); + if (f) { + for(int i=0;istore_line(favorite_dirs[i]); + memdelete(f); + } + +} + +Vector EditorSettings::get_favorite_dirs() const { + + return favorite_dirs; +} + + +void EditorSettings::set_recent_dirs(const Vector& p_recent) { + + recent_dirs=p_recent; + FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"),FileAccess::WRITE); + if (f) { + for(int i=0;istore_line(recent_dirs[i]); + memdelete(f); + } +} + +Vector EditorSettings::get_recent_dirs() const { + + return recent_dirs; +} + +String EditorSettings::get_project_settings_path() const { + + + return get_settings_path().plus_file("config").plus_file(project_config_path); +} + + +void EditorSettings::load_favorites() { + + FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"),FileAccess::READ); + if (f) { + String line = f->get_line().strip_edges(); + while(line!="") { + favorite_dirs.push_back(line); + line = f->get_line().strip_edges(); + } + memdelete(f); + } + + f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"),FileAccess::READ); + if (f) { + String line = f->get_line().strip_edges(); + while(line!="") { + recent_dirs.push_back(line); + line = f->get_line().strip_edges(); + } + memdelete(f); + } + +} + void EditorSettings::_bind_methods() { diff --git a/tools/editor/editor_settings.h b/tools/editor/editor_settings.h index 1594719a928..6b7e6eb9892 100644 --- a/tools/editor/editor_settings.h +++ b/tools/editor/editor_settings.h @@ -88,6 +88,11 @@ private: void _load_defaults(); + String project_config_path; + + Vector favorite_dirs; + Vector recent_dirs; + protected: static void _bind_methods(); @@ -102,6 +107,7 @@ public: static EditorSettings *get_singleton(); void erase(String p_var); String get_settings_path() const; + String get_project_settings_path() const; const Map& get_plugins() const { return plugins; } @@ -125,6 +131,14 @@ public: void add_property_hint(const PropertyInfo& p_hint); + void set_favorite_dirs(const Vector& p_favorite_dirs); + Vector get_favorite_dirs() const; + + void set_recent_dirs(const Vector& p_recent_dirs); + Vector get_recent_dirs() const; + + void load_favorites(); + EditorSettings(); ~EditorSettings(); diff --git a/tools/editor/editor_sub_scene.cpp b/tools/editor/editor_sub_scene.cpp index 49385daeaaa..2a6eba2554a 100644 --- a/tools/editor/editor_sub_scene.cpp +++ b/tools/editor/editor_sub_scene.cpp @@ -215,7 +215,7 @@ EditorSubScene::EditorSubScene() { tree->set_v_size_flags(SIZE_EXPAND_FILL); vb->add_margin_child("Import From Node:",tree)->set_v_size_flags(SIZE_EXPAND_FILL); - file_dialog = memnew( FileDialog ); + file_dialog = memnew( EditorFileDialog ); List extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions); @@ -224,7 +224,7 @@ EditorSubScene::EditorSubScene() { file_dialog->add_filter("*."+E->get()); } - file_dialog->set_mode(FileDialog::MODE_OPEN_FILE); + file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); add_child(file_dialog); file_dialog->connect("file_selected",this,"_path_selected"); diff --git a/tools/editor/editor_sub_scene.h b/tools/editor/editor_sub_scene.h index 9d78dab2a24..dfd6c531e2c 100644 --- a/tools/editor/editor_sub_scene.h +++ b/tools/editor/editor_sub_scene.h @@ -31,7 +31,7 @@ #include "scene/gui/dialogs.h" #include "scene/gui/tree.h" -#include "scene/gui/file_dialog.h" +#include "tools/editor/editor_file_dialog.h" class EditorSubScene : public ConfirmationDialog { @@ -42,7 +42,7 @@ class EditorSubScene : public ConfirmationDialog { Tree *tree; Node *scene; - FileDialog *file_dialog; + EditorFileDialog *file_dialog; void _fill_tree(Node* p_node,TreeItem *p_parent); void _reown(Node* p_node,List *p_to_reown); diff --git a/tools/editor/groups_editor.cpp b/tools/editor/groups_editor.cpp index ed76f545624..2e82854014c 100644 --- a/tools/editor/groups_editor.cpp +++ b/tools/editor/groups_editor.cpp @@ -39,6 +39,9 @@ void GroupsEditor::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { connect("confirmed", this,"_close"); } + if (p_what==NOTIFICATION_EXIT_TREE) { + disconnect("confirmed", this,"_close"); + } } void GroupsEditor::_close() { diff --git a/tools/editor/icons/icon_arrow_left.png b/tools/editor/icons/icon_arrow_left.png new file mode 100644 index 00000000000..b72ac2a10d5 Binary files /dev/null and b/tools/editor/icons/icon_arrow_left.png differ diff --git a/tools/editor/icons/icon_arrow_left_disabled.png b/tools/editor/icons/icon_arrow_left_disabled.png new file mode 100644 index 00000000000..f1f9d0f988d Binary files /dev/null and b/tools/editor/icons/icon_arrow_left_disabled.png differ diff --git a/tools/editor/icons/icon_arrow_right.png b/tools/editor/icons/icon_arrow_right.png new file mode 100644 index 00000000000..d0a48b01acc Binary files /dev/null and b/tools/editor/icons/icon_arrow_right.png differ diff --git a/tools/editor/icons/icon_arrow_right_disabled.png b/tools/editor/icons/icon_arrow_right_disabled.png new file mode 100644 index 00000000000..840cd0da0a3 Binary files /dev/null and b/tools/editor/icons/icon_arrow_right_disabled.png differ diff --git a/tools/editor/icons/icon_arrow_up.png b/tools/editor/icons/icon_arrow_up.png new file mode 100644 index 00000000000..10aac0e0f65 Binary files /dev/null and b/tools/editor/icons/icon_arrow_up.png differ diff --git a/tools/editor/icons/icon_arrow_up_disabled.png b/tools/editor/icons/icon_arrow_up_disabled.png new file mode 100644 index 00000000000..fb46aa13735 Binary files /dev/null and b/tools/editor/icons/icon_arrow_up_disabled.png differ diff --git a/tools/editor/icons/icon_back_disabled.png b/tools/editor/icons/icon_back_disabled.png new file mode 100644 index 00000000000..31aab496e26 Binary files /dev/null and b/tools/editor/icons/icon_back_disabled.png differ diff --git a/tools/editor/icons/icon_color_ramp.png b/tools/editor/icons/icon_color_ramp.png new file mode 100644 index 00000000000..9031b5ec53e Binary files /dev/null and b/tools/editor/icons/icon_color_ramp.png differ diff --git a/tools/editor/icons/icon_curve_constant.png b/tools/editor/icons/icon_curve_constant.png new file mode 100644 index 00000000000..cdeac1785e7 Binary files /dev/null and b/tools/editor/icons/icon_curve_constant.png differ diff --git a/tools/editor/icons/icon_curve_in.png b/tools/editor/icons/icon_curve_in.png new file mode 100644 index 00000000000..2db202632e0 Binary files /dev/null and b/tools/editor/icons/icon_curve_in.png differ diff --git a/tools/editor/icons/icon_curve_in_out.png b/tools/editor/icons/icon_curve_in_out.png new file mode 100644 index 00000000000..f4cb5934969 Binary files /dev/null and b/tools/editor/icons/icon_curve_in_out.png differ diff --git a/tools/editor/icons/icon_curve_linear.png b/tools/editor/icons/icon_curve_linear.png new file mode 100644 index 00000000000..9467dc97a37 Binary files /dev/null and b/tools/editor/icons/icon_curve_linear.png differ diff --git a/tools/editor/icons/icon_curve_out.png b/tools/editor/icons/icon_curve_out.png new file mode 100644 index 00000000000..c91ade6f4a7 Binary files /dev/null and b/tools/editor/icons/icon_curve_out.png differ diff --git a/tools/editor/icons/icon_curve_out_in.png b/tools/editor/icons/icon_curve_out_in.png new file mode 100644 index 00000000000..6499fa753ea Binary files /dev/null and b/tools/editor/icons/icon_curve_out_in.png differ diff --git a/tools/editor/icons/icon_favorites.png b/tools/editor/icons/icon_favorites.png index da4713d032c..4a3b575f95c 100644 Binary files a/tools/editor/icons/icon_favorites.png and b/tools/editor/icons/icon_favorites.png differ diff --git a/tools/editor/icons/icon_file_big.png b/tools/editor/icons/icon_file_big.png new file mode 100644 index 00000000000..887a4ee05c1 Binary files /dev/null and b/tools/editor/icons/icon_file_big.png differ diff --git a/tools/editor/icons/icon_file_list.png b/tools/editor/icons/icon_file_list.png new file mode 100644 index 00000000000..e5e9213e61f Binary files /dev/null and b/tools/editor/icons/icon_file_list.png differ diff --git a/tools/editor/icons/icon_file_thumbnail.png b/tools/editor/icons/icon_file_thumbnail.png new file mode 100644 index 00000000000..c32be5e8f8c Binary files /dev/null and b/tools/editor/icons/icon_file_thumbnail.png differ diff --git a/tools/editor/icons/icon_folder_big.png b/tools/editor/icons/icon_folder_big.png new file mode 100644 index 00000000000..988e070f984 Binary files /dev/null and b/tools/editor/icons/icon_folder_big.png differ diff --git a/tools/editor/icons/icon_item_list.png b/tools/editor/icons/icon_item_list.png new file mode 100644 index 00000000000..f930e7ecaac Binary files /dev/null and b/tools/editor/icons/icon_item_list.png differ diff --git a/tools/editor/icons/icon_key_next.png b/tools/editor/icons/icon_key_next.png new file mode 100644 index 00000000000..759008d0649 Binary files /dev/null and b/tools/editor/icons/icon_key_next.png differ diff --git a/tools/editor/icons/icon_pause.png b/tools/editor/icons/icon_pause.png index e63661353c7..7c0a57003ea 100644 Binary files a/tools/editor/icons/icon_pause.png and b/tools/editor/icons/icon_pause.png differ diff --git a/tools/editor/icons/icon_play.png b/tools/editor/icons/icon_play.png index 08cce495a94..d2bd9d310c1 100644 Binary files a/tools/editor/icons/icon_play.png and b/tools/editor/icons/icon_play.png differ diff --git a/tools/editor/icons/icon_play_backwards.png b/tools/editor/icons/icon_play_backwards.png new file mode 100644 index 00000000000..8dff5f20e36 Binary files /dev/null and b/tools/editor/icons/icon_play_backwards.png differ diff --git a/tools/editor/icons/icon_play_start.png b/tools/editor/icons/icon_play_start.png new file mode 100644 index 00000000000..5b085aa1eda Binary files /dev/null and b/tools/editor/icons/icon_play_start.png differ diff --git a/tools/editor/icons/icon_play_start_backwards.png b/tools/editor/icons/icon_play_start_backwards.png new file mode 100644 index 00000000000..09afac637c4 Binary files /dev/null and b/tools/editor/icons/icon_play_start_backwards.png differ diff --git a/tools/editor/icons/icon_remove.png b/tools/editor/icons/icon_remove.png index 10e56d5bb8a..f0f814e3043 100644 Binary files a/tools/editor/icons/icon_remove.png and b/tools/editor/icons/icon_remove.png differ diff --git a/tools/editor/icons/icon_remove_small.png b/tools/editor/icons/icon_remove_small.png new file mode 100644 index 00000000000..e0903689cf1 Binary files /dev/null and b/tools/editor/icons/icon_remove_small.png differ diff --git a/tools/editor/icons/icon_stop.png b/tools/editor/icons/icon_stop.png index fd568b61a8f..0fd43b403a1 100644 Binary files a/tools/editor/icons/icon_stop.png and b/tools/editor/icons/icon_stop.png differ diff --git a/tools/editor/icons/icon_tab_menu.png b/tools/editor/icons/icon_tab_menu.png new file mode 100644 index 00000000000..29edd02f016 Binary files /dev/null and b/tools/editor/icons/icon_tab_menu.png differ diff --git a/tools/editor/icons/icon_wait_no_preview.png b/tools/editor/icons/icon_wait_no_preview.png new file mode 100644 index 00000000000..5d20cd99ece Binary files /dev/null and b/tools/editor/icons/icon_wait_no_preview.png differ diff --git a/tools/editor/icons/icon_wait_preview_1.png b/tools/editor/icons/icon_wait_preview_1.png new file mode 100644 index 00000000000..0aab42e04aa Binary files /dev/null and b/tools/editor/icons/icon_wait_preview_1.png differ diff --git a/tools/editor/icons/icon_wait_preview_2.png b/tools/editor/icons/icon_wait_preview_2.png new file mode 100644 index 00000000000..f476b9ce1ff Binary files /dev/null and b/tools/editor/icons/icon_wait_preview_2.png differ diff --git a/tools/editor/icons/icon_wait_preview_3.png b/tools/editor/icons/icon_wait_preview_3.png new file mode 100644 index 00000000000..2775d1ef43c Binary files /dev/null and b/tools/editor/icons/icon_wait_preview_3.png differ diff --git a/tools/editor/icons/icon_wait_preview_4.png b/tools/editor/icons/icon_wait_preview_4.png new file mode 100644 index 00000000000..2eaa86fec93 Binary files /dev/null and b/tools/editor/icons/icon_wait_preview_4.png differ diff --git a/tools/editor/icons/icon_wait_preview_5.png b/tools/editor/icons/icon_wait_preview_5.png new file mode 100644 index 00000000000..6590644bc1d Binary files /dev/null and b/tools/editor/icons/icon_wait_preview_5.png differ diff --git a/tools/editor/icons/icon_wait_preview_6.png b/tools/editor/icons/icon_wait_preview_6.png new file mode 100644 index 00000000000..307e4123108 Binary files /dev/null and b/tools/editor/icons/icon_wait_preview_6.png differ diff --git a/tools/editor/icons/icon_wait_preview_7.png b/tools/editor/icons/icon_wait_preview_7.png new file mode 100644 index 00000000000..b0edc94d93c Binary files /dev/null and b/tools/editor/icons/icon_wait_preview_7.png differ diff --git a/tools/editor/icons/icon_wait_preview_8.png b/tools/editor/icons/icon_wait_preview_8.png new file mode 100644 index 00000000000..67a2f48ec3e Binary files /dev/null and b/tools/editor/icons/icon_wait_preview_8.png differ diff --git a/tools/editor/io_plugins/editor_font_import_plugin.cpp b/tools/editor/io_plugins/editor_font_import_plugin.cpp index 375333ddf69..10a38775290 100644 --- a/tools/editor/io_plugins/editor_font_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_font_import_plugin.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "editor_font_import_plugin.h" #include "scene/gui/dialogs.h" -#include "scene/gui/file_dialog.h" +#include "tools/editor/editor_file_dialog.h" #include "tools/editor/editor_node.h" #include "os/file_access.h" #include "editor_atlas.h" @@ -379,8 +379,8 @@ class EditorFontImportDialog : public ConfirmationDialog { OBJ_TYPE(EditorFontImportDialog, ConfirmationDialog); - LineEditFileChooser *source; - LineEditFileChooser *dest; + EditorLineEditFileChooser *source; + EditorLineEditFileChooser *dest; SpinBox *font_size; LineEdit *test_string; ColorPickerButton *test_color; @@ -612,9 +612,9 @@ public: hbc->add_child(vbr); vbr->set_h_size_flags(SIZE_EXPAND_FILL); - source = memnew( LineEditFileChooser ); - source->get_file_dialog()->set_access(FileDialog::ACCESS_FILESYSTEM); - source->get_file_dialog()->set_mode(FileDialog::MODE_OPEN_FILE); + source = memnew( EditorLineEditFileChooser ); + source->get_file_dialog()->set_access(EditorFileDialog::ACCESS_FILESYSTEM); + source->get_file_dialog()->set_mode(EditorFileDialog::MODE_OPEN_FILE); source->get_file_dialog()->add_filter("*.ttf;TrueType"); source->get_file_dialog()->add_filter("*.otf;OpenType"); source->get_line_edit()->connect("text_entered",this,"_src_changed"); @@ -626,7 +626,7 @@ public: font_size->set_max(256); font_size->set_val(16); font_size->connect("value_changed",this,"_font_size_changed"); - dest = memnew( LineEditFileChooser ); + dest = memnew( EditorLineEditFileChooser ); // List fl; Ref font= memnew(Font); diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp index 7d6f400ccc4..2e5a6f8a819 100644 --- a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp @@ -1,6 +1,6 @@ #include "editor_mesh_import_plugin.h" -#include "scene/gui/file_dialog.h" +#include "tools/editor/editor_file_dialog.h" #include "tools/editor/editor_dir_dialog.h" #include "tools/editor/editor_node.h" #include "tools/editor/property_editor.h" @@ -126,7 +126,7 @@ class EditorMeshImportDialog : public ConfirmationDialog { LineEdit *import_path; LineEdit *save_path; - FileDialog *file_select; + EditorFileDialog *file_select; EditorDirDialog *save_select; ConfirmationDialog *error_dialog; PropertyEditor *option_editor; @@ -300,16 +300,16 @@ public: save_choose->connect("pressed", this,"_browse_target"); - file_select = memnew(FileDialog); - file_select->set_access(FileDialog::ACCESS_FILESYSTEM); + file_select = memnew(EditorFileDialog); + file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM); add_child(file_select); - file_select->set_mode(FileDialog::MODE_OPEN_FILES); + file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES); file_select->connect("files_selected", this,"_choose_files"); file_select->add_filter("*.obj ; Wavefront OBJ"); save_select = memnew( EditorDirDialog ); add_child(save_select); - // save_select->set_mode(FileDialog::MODE_OPEN_DIR); + // save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR); save_select->connect("dir_selected", this,"_choose_save_dir"); get_ok()->connect("pressed", this,"_import"); diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp index fa472ed0336..9491f957c39 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "editor_sample_import_plugin.h" -#include "scene/gui/file_dialog.h" +#include "tools/editor/editor_file_dialog.h" #include "tools/editor/editor_dir_dialog.h" #include "tools/editor/editor_node.h" #include "tools/editor/property_editor.h" @@ -171,7 +171,7 @@ class EditorSampleImportDialog : public ConfirmationDialog { LineEdit *import_path; LineEdit *save_path; - FileDialog *file_select; + EditorFileDialog *file_select; EditorDirDialog *save_select; ConfirmationDialog *error_dialog; PropertyEditor *option_editor; @@ -363,16 +363,16 @@ public: save_choose->connect("pressed", this,"_browse_target"); - file_select = memnew(FileDialog); - file_select->set_access(FileDialog::ACCESS_FILESYSTEM); + file_select = memnew(EditorFileDialog); + file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM); add_child(file_select); - file_select->set_mode(FileDialog::MODE_OPEN_FILES); + 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(FileDialog::MODE_OPEN_DIR); + // save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR); save_select->connect("dir_selected", this,"_choose_save_dir"); get_ok()->connect("pressed", this,"_import"); diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp index 2ce5f3a5a76..99dcf4ed289 100644 --- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_scene_import_plugin.cpp @@ -162,8 +162,8 @@ class EditorSceneImportDialog : public ConfirmationDialog { LineEdit *save_path; LineEdit *script_path; Tree *import_options; - FileDialog *file_select; - FileDialog *script_select; + EditorFileDialog *file_select; + EditorFileDialog *script_select; EditorDirDialog *save_select; OptionButton *texture_action; @@ -1079,19 +1079,19 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce vbc->set_v_size_flags(SIZE_EXPAND_FILL); vbc->add_margin_child("Options:",import_options,true); - file_select = memnew(FileDialog); - file_select->set_access(FileDialog::ACCESS_FILESYSTEM); + file_select = memnew(EditorFileDialog); + file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM); add_child(file_select); - file_select->set_mode(FileDialog::MODE_OPEN_FILE); + file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE); file_select->connect("file_selected", this,"_choose_file"); save_select = memnew(EditorDirDialog); add_child(save_select); - //save_select->set_mode(FileDialog::MODE_SAVE_FILE); + //save_select->set_mode(EditorFileDialog::MODE_SAVE_FILE); save_select->connect("dir_selected", this,"_choose_save_file"); get_ok()->connect("pressed", this,"_import"); @@ -1140,7 +1140,7 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce script_choose->connect("pressed", this,"_browse_script"); - script_select = memnew(FileDialog); + script_select = memnew(EditorFileDialog); add_child(script_select); for(int i=0;iset_mode(FileDialog::MODE_OPEN_FILE); + script_select->set_mode(EditorFileDialog::MODE_OPEN_FILE); script_select->connect("file_selected", this,"_choose_script"); diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 3add30d81e4..4f7ec1839ab 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -144,6 +144,8 @@ void EditorImportTextureOptions::_changed() { void EditorImportTextureOptions::_bind_methods() { + print_line("bind toptions"); + ObjectTypeDB::bind_method("_changed",&EditorImportTextureOptions::_changed); ObjectTypeDB::bind_method("_changedp",&EditorImportTextureOptions::_changedp); @@ -219,7 +221,6 @@ EditorImportTextureOptions::EditorImportTextureOptions() { fname++; } - add_margin_child("Texture Options",flags,true); notice_for_2d = memnew( Label ); @@ -247,17 +248,20 @@ class EditorTextureImportDialog : public ConfirmationDialog { LineEdit *import_path; LineEdit *save_path; - FileDialog *file_select; - FileDialog *save_file_select; + EditorFileDialog *file_select; + EditorFileDialog *save_file_select; EditorDirDialog *save_select; OptionButton *texture_action; ConfirmationDialog *error_dialog; CheckButton *crop_source; + SpinBox *size; bool atlas; + bool large; EditorTextureImportPlugin *plugin; void _choose_files(const Vector& p_path); + void _choose_file(const String& p_path); void _choose_save_dir(const String& p_path); void _browse(); void _browse_target(); @@ -272,7 +276,7 @@ public: Error import(const String& p_from, const String& p_to, const String& p_preset); void popup_import(const String &p_from=String()); - EditorTextureImportDialog(EditorTextureImportPlugin *p_plugin=NULL,bool p_2d=false,bool p_atlas=false); + EditorTextureImportDialog(EditorTextureImportPlugin *p_plugin=NULL,bool p_2d=false,bool p_atlas=false,bool p_large=false); }; @@ -301,6 +305,15 @@ void EditorTextureImportDialog::_choose_files(const Vector& p_path) { import_path->set_text(files); } + + + +void EditorTextureImportDialog::_choose_file(const String& p_path) { + + + import_path->set_text(p_path); + +} void EditorTextureImportDialog::_choose_save_dir(const String& p_path) { save_path->set_text(p_path); @@ -336,7 +349,7 @@ void EditorTextureImportDialog::_import() { } - if (!atlas && !DirAccess::exists(save_path->get_text())) { + if (!atlas && !large && !DirAccess::exists(save_path->get_text())) { error_dialog->set_text("Target path must exist."); error_dialog->popup_centered_minsize(); return; @@ -362,6 +375,8 @@ void EditorTextureImportDialog::_import() { imd->set_option("flags",texture_options->get_flags()); imd->set_option("quality",texture_options->get_quality()); imd->set_option("atlas",true); + imd->set_option("atlas_size",int(size->get_val())); + imd->set_option("large",false); imd->set_option("crop",crop_source->is_pressed()); Error err = plugin->import(dst_file,imd); @@ -372,7 +387,38 @@ void EditorTextureImportDialog::_import() { return; } + } else if (large) { //atlas + if (files.size()!=1) { + + error_dialog->set_text("Only one file is required for large texture"); + error_dialog->popup_centered(Size2(200,100)); + return; + + } + String dst_file = dst_path; + //dst_file=dst_file.basename()+".tex"; + Ref imd = memnew( ResourceImportMetadata ); + //imd->set_editor(); + for(int i=0;iadd_source(EditorImportPlugin::validate_source_path(files[i])); + } + imd->set_option("format",texture_options->get_format()); + imd->set_option("flags",texture_options->get_flags()); + imd->set_option("quality",texture_options->get_quality()); + imd->set_option("atlas",false); + imd->set_option("large",true); + imd->set_option("large_cell_size",int(size->get_val())); + imd->set_option("crop",crop_source->is_pressed()); + + Error err = plugin->import(dst_file,imd); + if (err) { + + error_dialog->set_text("Error importing: "+dst_file.get_file()); + error_dialog->popup_centered(Size2(200,100)); + return; + + } } else { @@ -387,6 +433,8 @@ void EditorTextureImportDialog::_import() { imd->set_option("flags",texture_options->get_flags()); imd->set_option("quality",texture_options->get_quality()); imd->set_option("atlas",false); + imd->set_option("large",false); + Error err = plugin->import(dst_file,imd); if (err) { @@ -408,7 +456,7 @@ void EditorTextureImportDialog::_browse() { void EditorTextureImportDialog::_browse_target() { - if (atlas) { + if (atlas || large) { save_file_select->popup_centered_ratio(); } else { save_select->popup_centered_ratio(); @@ -424,7 +472,7 @@ void EditorTextureImportDialog::popup_import(const String& p_from) { Ref rimd = ResourceLoader::load_import_metadata(p_from); ERR_FAIL_COND(!rimd.is_valid()); - if (plugin->get_mode()==EditorTextureImportPlugin::MODE_ATLAS) + if (plugin->get_mode()==EditorTextureImportPlugin::MODE_ATLAS || plugin->get_mode()==EditorTextureImportPlugin::MODE_LARGE) save_path->set_text(p_from); else save_path->set_text(p_from.get_base_dir()); @@ -474,6 +522,7 @@ void EditorTextureImportDialog::_bind_methods() { ObjectTypeDB::bind_method("_choose_files",&EditorTextureImportDialog::_choose_files); + ObjectTypeDB::bind_method("_choose_file",&EditorTextureImportDialog::_choose_file); ObjectTypeDB::bind_method("_choose_save_dir",&EditorTextureImportDialog::_choose_save_dir); ObjectTypeDB::bind_method("_import",&EditorTextureImportDialog::_import); ObjectTypeDB::bind_method("_browse",&EditorTextureImportDialog::_browse); @@ -481,21 +530,25 @@ void EditorTextureImportDialog::_bind_methods() { // ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) ); } -EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* p_plugin, bool p_2d, bool p_atlas) { +EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* p_plugin, bool p_2d, bool p_atlas,bool p_large) { atlas=p_atlas; + large=p_large; plugin=p_plugin; set_title("Import Textures"); - texture_options = memnew( EditorImportTextureOptions );; - VBoxContainer *vbc = texture_options; + + VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); set_child_rect(vbc); VBoxContainer *source_vb=memnew(VBoxContainer); - vbc->add_margin_child("Source Texture(s):",source_vb); + if (large) + vbc->add_margin_child("Source Texture:",source_vb); + else + vbc->add_margin_child("Source Texture(s):",source_vb); HBoxContainer *hbc = memnew( HBoxContainer ); source_vb->add_child(hbc); @@ -510,6 +563,7 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* if (!p_atlas) crop_source->hide(); + Button * import_choose = memnew( Button ); import_choose->set_text(" .. "); hbc->add_child(import_choose); @@ -519,6 +573,19 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* hbc = memnew( HBoxContainer ); vbc->add_margin_child("Target Path:",hbc); + size = memnew( SpinBox ); + size->set_min(128); + size->set_max(16384); + + if (p_atlas) { + size->set_val(2048); + vbc->add_margin_child("Max Texture size:",size); + } else { + size->set_val(256); + vbc->add_margin_child("Cell Size:",size); + } + + save_path = memnew( LineEdit ); save_path->set_h_size_flags(SIZE_EXPAND_FILL); hbc->add_child(save_path); @@ -529,32 +596,39 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* save_choose->connect("pressed", this,"_browse_target"); - file_select = memnew(FileDialog); - file_select->set_access(FileDialog::ACCESS_FILESYSTEM); + file_select = memnew(EditorFileDialog); + file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM); add_child(file_select); - file_select->set_mode(FileDialog::MODE_OPEN_FILES); + if (!large) + file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES); + else + file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE); file_select->connect("files_selected", this,"_choose_files"); + file_select->connect("file_selected", this,"_choose_file"); - save_file_select = memnew(FileDialog); - save_file_select->set_access(FileDialog::ACCESS_RESOURCES); + save_file_select = memnew(EditorFileDialog); + save_file_select->set_access(EditorFileDialog::ACCESS_RESOURCES); add_child(save_file_select); - save_file_select->set_mode(FileDialog::MODE_SAVE_FILE); + save_file_select->set_mode(EditorFileDialog::MODE_SAVE_FILE); save_file_select->clear_filters(); - save_file_select->add_filter("*.tex;Base Atlas Texture"); + if (large) + save_file_select->add_filter("*.ltex;Large Texture"); + else + save_file_select->add_filter("*.tex;Base Atlas Texture"); save_file_select->connect("file_selected", this,"_choose_save_dir"); save_select = memnew( EditorDirDialog ); add_child(save_select); -// save_select->set_mode(FileDialog::MODE_OPEN_DIR); +// 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("Import"); //move stuff up - for(int i=0;i<4;i++) - vbc->move_child( vbc->get_child( vbc->get_child_count() -1), 0); + //for(int i=0;i<4;i++) + // vbc->move_child( vbc->get_child( vbc->get_child_count() -1), 0); error_dialog = memnew ( ConfirmationDialog ); add_child(error_dialog); @@ -563,13 +637,24 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* set_hide_on_ok(false); + texture_options = memnew( EditorImportTextureOptions );; + vbc->add_child(texture_options); + texture_options->set_v_size_flags(SIZE_EXPAND_FILL); + if (atlas) { texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER); texture_options->set_quality(0.7); texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY); - texture_options->show_2d_notice(); + //texture_options->show_2d_notice(); set_title("Import Textures for Atlas (2D)"); + } else if (large) { + + texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER); + texture_options->set_quality(0.7); + texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS); + texture_options->show_2d_notice(); + set_title("Import Large Textures (2D)"); } else if (p_2d) { @@ -615,12 +700,17 @@ String EditorTextureImportPlugin::get_name() const { return "texture_atlas"; } break; + case MODE_LARGE: { + + return "texture_large"; + } break; } return ""; } + String EditorTextureImportPlugin::get_visible_name() const { switch(mode) { @@ -635,7 +725,11 @@ String EditorTextureImportPlugin::get_visible_name() const { } break; case MODE_ATLAS: { - return "Atlas Texture"; + return "2D Atlas Texture"; + } break; + case MODE_LARGE: { + + return "2D Large Texture"; } break; } @@ -733,6 +827,135 @@ Error EditorTextureImportPlugin::import(const String& p_path, const Ref &texture,int format, float quality,int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,int shrink) { + + + if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS || format==IMAGE_FORMAT_COMPRESS_DISK_LOSSY) { + + Image image=texture->get_data(); + ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA); + + bool has_alpha=image.detect_alpha(); + if (!has_alpha && image.get_format()==Image::FORMAT_RGBA) { + + image.convert(Image::FORMAT_RGB); + + } + + if (image.get_format()==Image::FORMAT_RGBA && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) { + + image.fix_alpha_edges(); + } + + if (image.get_format()==Image::FORMAT_RGBA && flags&IMAGE_FLAG_PREMULT_ALPHA) { + + image.premultiply_alpha(); + } + + if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) { + image.normalmap_to_xy(); + } + + //if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) { + + // image.srgb_to_linear(); + //} + + if (shrink>1) { + + int orig_w=image.get_width(); + int orig_h=image.get_height(); + image.resize(orig_w/shrink,orig_h/shrink); + texture->create_from_image(image,tex_flags); + texture->set_size_override(Size2(orig_w,orig_h)); + + + } else { + + texture->create_from_image(image,tex_flags); + } + + + if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS) { + texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSLESS); + } else { + texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY); + } + + + + texture->set_lossy_storage_quality(quality); + + + } else { + + + Image image=texture->get_data(); + ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA); + + + bool has_alpha=image.detect_alpha(); + if (!has_alpha && image.get_format()==Image::FORMAT_RGBA) { + + image.convert(Image::FORMAT_RGB); + + } + + if (image.get_format()==Image::FORMAT_RGBA && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) { + + image.fix_alpha_edges(); + } + + if (image.get_format()==Image::FORMAT_RGBA && flags&IMAGE_FLAG_PREMULT_ALPHA) { + + image.premultiply_alpha(); + } + + if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) { + image.normalmap_to_xy(); + } + + //if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) { +// + // print_line("CONVERT BECAUSE: "+itos(flags)); + // image.srgb_to_linear(); + //} + + int orig_w=image.get_width(); + int orig_h=image.get_height(); + + if (shrink>1) { + image.resize(orig_w/shrink,orig_h/shrink); + texture->create_from_image(image,tex_flags); + texture->set_size_override(Size2(orig_w,orig_h)); + } + + if (!(flags&IMAGE_FLAG_NO_MIPMAPS)) { + image.generate_mipmaps(); + + } + + if (format!=IMAGE_FORMAT_UNCOMPRESSED) { + + compress_image(p_compr,image,flags&IMAGE_FLAG_COMPRESS_EXTRA); + } + + + texture->create_from_image(image,tex_flags); + + + if (shrink>1 || (format!=IMAGE_FORMAT_UNCOMPRESSED && (image.get_width()!=orig_w || image.get_height()!=orig_h))) { + texture->set_size_override(Size2(orig_w,orig_h)); + } + + //uint32_t save_flags=ResourceSaver::FLAG_COMPRESS; + } + + return OK; +} + + Error EditorTextureImportPlugin::import2(const String& p_path, const Ref& p_from,EditorExportPlatform::ImageCompression p_compr, bool p_external){ @@ -744,8 +967,11 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref texture; Vector > atlases; bool atlas = from->get_option("atlas"); + bool large = from->get_option("large"); int flags=from->get_option("flags"); + int format=from->get_option("format"); + float quality=from->get_option("quality"); uint32_t tex_flags=0; @@ -765,7 +991,80 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Refhas_option("shrink")) shrink=from->get_option("shrink"); - if (atlas) { + if (large) { + ERR_FAIL_COND_V(from->get_source_count()!=1,ERR_INVALID_PARAMETER); + + String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0)); + + + int cell_size=from->get_option("large_cell_size"); + ERR_FAIL_COND_V(cell_size<128 || cell_size>16384,ERR_CANT_OPEN); + + EditorProgress pg("ltex","Import Large Texture",3); + + pg.step("Load Source Image",0); + Image img; + Error err = ImageLoader::load_image(src_path,&img); + if (err) { + return err; + } + + pg.step("Slicing",1); + + Map pieces; + for(int i=0;i existing; + if (ResourceCache::has(p_path)) { + existing = ResourceCache::get(p_path); + } + + if (existing.is_valid()) { + existing->clear(); + } else { + existing = Ref(memnew( LargeTexture )); + } + + existing->set_size(Size2(img.get_width(),img.get_height())); + pg.step("Inserting",2); + + for (Map::Element *E=pieces.front();E;E=E->next()) { + + Ref imgtex = Ref( memnew( ImageTexture ) ); + imgtex->create_from_image(E->get(),tex_flags); + _process_texture_data(imgtex,format,quality,flags,p_compr,tex_flags,shrink); + existing->add_piece(E->key(),imgtex); + } + + if (!p_external) { + from->set_editor(get_name()); + existing->set_path(p_path); + existing->set_import_metadata(from); + } + pg.step("Saving",3); + + err = ResourceSaver::save(p_path,existing); + if (err!=OK) { + EditorNode::add_io_error("Couldn't save large texture: "+p_path); + return err; + } + + return OK; + + + } else if (atlas) { //prepare atlas! Vector< Image > sources; @@ -897,8 +1196,6 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Refget_option("format"); - float quality=from->get_option("quality"); if (!p_external) { from->set_editor(get_name()); @@ -932,7 +1229,11 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Refget_data(); @@ -989,13 +1290,6 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Refset_lossy_storage_quality(quality); - Error err = ResourceSaver::save(p_path,texture); - - if (err!=OK) { - EditorNode::add_io_error("Couldn't save converted texture: "+p_path); - return err; - } - } else { @@ -1058,15 +1352,20 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Refset_size_override(Size2(orig_w,orig_h)); } - uint32_t save_flags=ResourceSaver::FLAG_COMPRESS; + compress=true; - Error err = ResourceSaver::save(p_path,texture,save_flags); - if (err!=OK) { - EditorNode::add_io_error("Couldn't save converted texture: "+p_path); - return err; - } } +#endif + uint32_t save_flags=0; + if (compress) + save_flags=ResourceSaver::FLAG_COMPRESS; + + Error err = ResourceSaver::save(p_path,texture,save_flags); + if (err!=OK) { + EditorNode::add_io_error("Couldn't save converted texture: "+p_path); + return err; + } return OK; } @@ -1255,14 +1554,14 @@ Vector EditorTextureImportPlugin::custom_export(const String& p_path, c } -EditorTextureImportPlugin *EditorTextureImportPlugin::singleton[3]={NULL,NULL,NULL}; +EditorTextureImportPlugin *EditorTextureImportPlugin::singleton[EditorTextureImportPlugin::MODE_MAX]={NULL,NULL,NULL,NULL}; EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor, Mode p_mode) { singleton[p_mode]=this; editor=p_editor; - mode=p_mode; - dialog = memnew( EditorTextureImportDialog(this,p_mode==MODE_TEXTURE_2D || p_mode==MODE_ATLAS,p_mode==MODE_ATLAS) ); + mode=p_mode; + dialog = memnew( EditorTextureImportDialog(this,p_mode==MODE_TEXTURE_2D || p_mode==MODE_ATLAS || p_mode==MODE_LARGE,p_mode==MODE_ATLAS,p_mode==MODE_LARGE) ); editor->get_gui_base()->add_child(dialog); } diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h index 5cd36e838ee..02d09d9e173 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.h +++ b/tools/editor/io_plugins/editor_texture_import_plugin.h @@ -56,7 +56,9 @@ public: enum Mode { MODE_TEXTURE_2D, MODE_TEXTURE_3D, - MODE_ATLAS + MODE_ATLAS, + MODE_LARGE, + MODE_MAX }; @@ -65,10 +67,10 @@ private: Mode mode; EditorNode *editor; EditorTextureImportDialog *dialog; - static EditorTextureImportPlugin *singleton[3]; + static EditorTextureImportPlugin *singleton[MODE_MAX]; //used by other importers such as mesh - + Error _process_texture_data(Ref &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,int shrink); void compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller); public: diff --git a/tools/editor/io_plugins/editor_translation_import_plugin.cpp b/tools/editor/io_plugins/editor_translation_import_plugin.cpp index 6d59b52fb58..d152d71af44 100644 --- a/tools/editor/io_plugins/editor_translation_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_translation_import_plugin.cpp @@ -47,7 +47,7 @@ class EditorTranslationImportDialog : public ConfirmationDialog { LineEdit *import_path; LineEdit *save_path; - FileDialog *file_select; + EditorFileDialog *file_select; CheckButton *ignore_first; CheckButton *compress; CheckButton *add_to_project; @@ -347,16 +347,16 @@ public: add_to_project->set_text("Add to Project (engine.cfg)"); tcomp->add_child(add_to_project); - file_select = memnew(FileDialog); - file_select->set_access(FileDialog::ACCESS_FILESYSTEM); + file_select = memnew(EditorFileDialog); + file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM); add_child(file_select); - file_select->set_mode(FileDialog::MODE_OPEN_FILE); + 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(FileDialog::MODE_OPEN_DIR); + // save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR); save_select->connect("dir_selected", this,"_choose_save_dir"); get_ok()->connect("pressed", this,"_import"); diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index fee2f4f977a..05b12543d2f 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -28,7 +28,8 @@ /*************************************************************************/ #include "animation_player_editor_plugin.h" #include "io/resource_loader.h" - +#include "os/keyboard.h" +#include "tools/editor/editor_settings.h" void AnimationPlayerEditor::_node_removed(Node *p_node) { @@ -97,15 +98,21 @@ void AnimationPlayerEditor::_notification(int p_what) { duplicate_anim->set_icon( get_icon("Duplicate","EditorIcons") ); autoplay->set_icon( get_icon("AutoPlay","EditorIcons") ); load_anim->set_icon( get_icon("Folder","EditorIcons") ); - remove_anim->set_icon( get_icon("Del","EditorIcons") ); + remove_anim->set_icon( get_icon("Remove","EditorIcons") ); edit_anim->set_icon( get_icon("Edit","EditorIcons") ); blend_anim->set_icon( get_icon("Blend","EditorIcons") ); - play->set_icon( get_icon("Play","EditorIcons") ); + play->set_icon( get_icon("PlayStart","EditorIcons") ); + play_from->set_icon( get_icon("Play","EditorIcons") ); + play_bw->set_icon( get_icon("PlayStartBackwards","EditorIcons") ); + play_bw_from->set_icon( get_icon("PlayBackwards","EditorIcons") ); + autoplay_icon=get_icon("AutoPlay","EditorIcons"); stop->set_icon( get_icon("Stop","EditorIcons") ); resource_edit_anim->set_icon( get_icon("EditResource","EditorIcons") ); pin->set_normal_texture(get_icon("Pin","EditorIcons") ); pin->set_pressed_texture( get_icon("PinPressed","EditorIcons") ); + tool_anim->set_icon(get_icon("Tools","EditorIcons")); + tool_anim->get_popup()->connect("item_pressed",this,"_animation_tool_menu"); blend_editor.next->connect("text_changed",this,"_blend_editor_next_changed"); @@ -180,9 +187,82 @@ void AnimationPlayerEditor::_play_pressed() { //unpause //pause->set_pressed(false); } + +void AnimationPlayerEditor::_play_from_pressed() { + + String current; + if (animation->get_selected()>=0 && animation->get_selected()get_item_count()) { + + current = animation->get_item_text( animation->get_selected() ); + } + + if (current!="") { + + float time = player->get_current_animation_pos(); + + if (current==player->get_current_animation() && player->is_playing()) { + + player->stop(); //so it wont blend with itself + } + + player->play( current ); + player->seek(time); + } + + //unstop + stop->set_pressed(false); + //unpause + //pause->set_pressed(false); +} + + +void AnimationPlayerEditor::_play_bw_pressed() { + + String current; + if (animation->get_selected()>=0 && animation->get_selected()get_item_count()) { + + current = animation->get_item_text( animation->get_selected() ); + } + + if (current!="") { + + if (current==player->get_current_animation()) + player->stop(); //so it wont blend with itself + player->play(current,-1,-1,true); + } + + //unstop + stop->set_pressed(false); + //unpause + //pause->set_pressed(false); +} + +void AnimationPlayerEditor::_play_bw_from_pressed() { + + String current; + if (animation->get_selected()>=0 && animation->get_selected()get_item_count()) { + + current = animation->get_item_text( animation->get_selected() ); + } + + if (current!="") { + + float time = player->get_current_animation_pos(); + if (current==player->get_current_animation()) + player->stop(); //so it wont blend with itself + + player->play(current,-1,-1,true); + player->seek(time); + } + + //unstop + stop->set_pressed(false); + //unpause + //pause->set_pressed(false); +} void AnimationPlayerEditor::_stop_pressed() { - player->stop(); + player->stop(false); play->set_pressed(false); stop->set_pressed(true); //pause->set_pressed(false); @@ -275,7 +355,7 @@ void AnimationPlayerEditor::_animation_rename() { } void AnimationPlayerEditor::_animation_load() { ERR_FAIL_COND(!player); - file->set_mode( FileDialog::MODE_OPEN_FILE ); + file->set_mode( EditorFileDialog::MODE_OPEN_FILE ); file->clear_filters(); List extensions; @@ -598,6 +678,9 @@ void AnimationPlayerEditor::_update_player() { stop->set_disabled(animlist.size()==0); play->set_disabled(animlist.size()==0); + play_bw->set_disabled(animlist.size()==0); + play_bw_from->set_disabled(animlist.size()==0); + play_from->set_disabled(animlist.size()==0); autoplay->set_disabled(animlist.size()==0); duplicate_anim->set_disabled(animlist.size()==0); rename_anim->set_disabled(animlist.size()==0); @@ -877,11 +960,108 @@ void AnimationPlayerEditor::_hide_anim_editors() { } } + +void AnimationPlayerEditor::_animation_tool_menu(int p_option) { + + switch(p_option) { + + case TOOL_COPY_ANIM: { + + if (!animation->get_item_count()) { + error_dialog->set_text("ERROR: No animation to copy!"); + error_dialog->popup_centered_minsize(); + return; + } + + String current = animation->get_item_text(animation->get_selected()); + Ref anim = player->get_animation(current); + //editor->edit_resource(anim); + EditorSettings::get_singleton()->set_resource_clipboard(anim); + + } break; + case TOOL_PASTE_ANIM: { + + Ref anim = EditorSettings::get_singleton()->get_resource_clipboard(); + if (!anim.is_valid()) { + error_dialog->set_text("ERROR: No animation resource on clipboard!"); + error_dialog->popup_centered_minsize(); + return; + } + + String name = anim->get_name(); + if (name=="") { + name="Pasted Animation"; + } + + int idx=1; + String base = name; + while (player->has_animation(name)) { + + idx++; + name=base+" "+itos(idx); + } + + undo_redo->create_action("Paste Animation"); + undo_redo->add_do_method(player,"add_animation",name,anim); + undo_redo->add_undo_method(player,"remove_animation",name); + undo_redo->add_do_method(this,"_animation_player_changed",player); + undo_redo->add_undo_method(this,"_animation_player_changed",player); + undo_redo->commit_action(); + + _select_anim_by_name(name); + + + } break; + case TOOL_EDIT_RESOURCE: { + + if (!animation->get_item_count()) { + error_dialog->set_text("ERROR: No animation to edit!"); + error_dialog->popup_centered_minsize(); + return; + } + + String current = animation->get_item_text(animation->get_selected()); + Ref anim = player->get_animation(current); + editor->edit_resource(anim); + + } break; + + } +} + +void AnimationPlayerEditor::_unhandled_key_input(const InputEvent& p_ev) { + + if (is_visible() && p_ev.type==InputEvent::KEY && p_ev.key.pressed && !p_ev.key.echo && !p_ev.key.mod.alt && !p_ev.key.mod.control && !p_ev.key.mod.meta) { + + switch(p_ev.key.scancode) { + + case KEY_A: { + if (!p_ev.key.mod.shift) + _play_bw_from_pressed(); + else + _play_bw_pressed(); + } break; + case KEY_S: { + _stop_pressed(); + } break; + case KEY_D: { + if (!p_ev.key.mod.shift) + _play_from_pressed(); + else + _play_pressed(); + } break; + } + } +} + void AnimationPlayerEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&AnimationPlayerEditor::_input_event); ObjectTypeDB::bind_method(_MD("_node_removed"),&AnimationPlayerEditor::_node_removed); ObjectTypeDB::bind_method(_MD("_play_pressed"),&AnimationPlayerEditor::_play_pressed); + ObjectTypeDB::bind_method(_MD("_play_from_pressed"),&AnimationPlayerEditor::_play_from_pressed); + ObjectTypeDB::bind_method(_MD("_play_bw_pressed"),&AnimationPlayerEditor::_play_bw_pressed); + ObjectTypeDB::bind_method(_MD("_play_bw_from_pressed"),&AnimationPlayerEditor::_play_bw_from_pressed); ObjectTypeDB::bind_method(_MD("_stop_pressed"),&AnimationPlayerEditor::_stop_pressed); ObjectTypeDB::bind_method(_MD("_autoplay_pressed"),&AnimationPlayerEditor::_autoplay_pressed); ObjectTypeDB::bind_method(_MD("_pause_pressed"),&AnimationPlayerEditor::_pause_pressed); @@ -908,6 +1088,8 @@ void AnimationPlayerEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_hide_anim_editors"),&AnimationPlayerEditor::_hide_anim_editors); ObjectTypeDB::bind_method(_MD("_animation_duplicate"),&AnimationPlayerEditor::_animation_duplicate); ObjectTypeDB::bind_method(_MD("_blend_editor_next_changed"),&AnimationPlayerEditor::_blend_editor_next_changed); + ObjectTypeDB::bind_method(_MD("_unhandled_key_input"),&AnimationPlayerEditor::_unhandled_key_input); + ObjectTypeDB::bind_method(_MD("_animation_tool_menu"),&AnimationPlayerEditor::_animation_tool_menu); @@ -935,47 +1117,56 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { add_child(hb); - add_anim = memnew( Button ); + add_anim = memnew( ToolButton ); add_anim->set_tooltip("Create new animation in player."); hb->add_child(add_anim); - - load_anim = memnew( Button ); + load_anim = memnew( ToolButton ); load_anim->set_tooltip("Load an animation from disk."); hb->add_child(load_anim); - duplicate_anim = memnew( Button ); + duplicate_anim = memnew( ToolButton ); hb->add_child(duplicate_anim); duplicate_anim->set_tooltip("Duplicate Animation"); + rename_anim = memnew( ToolButton ); + hb->add_child(rename_anim); + rename_anim->set_tooltip("Rename Animation"); + + remove_anim = memnew( ToolButton ); + + hb->add_child(remove_anim); + remove_anim->set_tooltip("Remove Animation"); + + animation = memnew( OptionButton ); hb->add_child(animation); animation->set_h_size_flags(SIZE_EXPAND_FILL); animation->set_tooltip("Display list of animations in player."); - autoplay = memnew( Button ); + autoplay = memnew( ToolButton ); hb->add_child(autoplay); autoplay->set_tooltip("Autoplay On Load"); - rename_anim = memnew( Button ); - hb->add_child(rename_anim); - rename_anim->set_tooltip("Rename Animation"); - remove_anim = memnew( Button ); - - hb->add_child(remove_anim); - remove_anim->set_tooltip("Remove Animation"); - - blend_anim = memnew( Button ); + blend_anim = memnew( ToolButton ); hb->add_child(blend_anim); blend_anim->set_tooltip("Edit Target Blend Times"); + tool_anim = memnew( MenuButton); + //tool_anim->set_flat(false); + tool_anim->set_tooltip("Animation Tools"); + tool_anim->get_popup()->add_item("Copy Animation",TOOL_COPY_ANIM); + tool_anim->get_popup()->add_item("Paste Animation",TOOL_PASTE_ANIM); + //tool_anim->get_popup()->add_separator(); + //tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM); + hb->add_child(tool_anim); - edit_anim = memnew( Button ); + edit_anim = memnew( ToolButton ); edit_anim->set_toggle_mode(true); hb->add_child(edit_anim); edit_anim->set_tooltip("Open animation editor.\nProperty editor will displays all editable keys too."); @@ -984,15 +1175,29 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { hb = memnew (HBoxContainer); add_child(hb); - play = memnew( Button ); - play->set_tooltip("Play selected animation."); + play_bw_from = memnew( ToolButton ); + play_bw_from->set_tooltip("Play backwards selected animation from current pos. (A)"); + hb->add_child(play_bw_from); - hb->add_child(play); + play_bw = memnew( ToolButton ); + play_bw->set_tooltip("Play backwards selected animation from end. (Shift+A)"); + hb->add_child(play_bw); - stop = memnew( Button ); + stop = memnew( ToolButton ); stop->set_toggle_mode(true); hb->add_child(stop); - play->set_tooltip("Stop animation playback."); + stop->set_tooltip("Stop animation playback. (S)"); + + play = memnew( ToolButton ); + play->set_tooltip("Play selected animation from start. (Shift+D)"); + hb->add_child(play); + + + play_from = memnew( ToolButton ); + play_from->set_tooltip("Play selected animation from current pos. (D)"); + hb->add_child(play_from); + + //pause = memnew( Button ); //pause->set_toggle_mode(true); @@ -1024,9 +1229,10 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { resource_edit_anim= memnew( Button ); hb->add_child(resource_edit_anim); + resource_edit_anim->hide(); - file = memnew(FileDialog); + file = memnew(EditorFileDialog); add_child(file); name_dialog = memnew( ConfirmationDialog ); @@ -1074,7 +1280,10 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { autoplay->connect("pressed", this,"_autoplay_pressed"); autoplay->set_toggle_mode(true); - play->connect("pressed", this,"_play_pressed"); + play->connect("pressed", this,"_play_pressed"); + play_from->connect("pressed", this,"_play_from_pressed"); + play_bw->connect("pressed", this,"_play_bw_pressed"); + play_bw_from->connect("pressed", this,"_play_bw_from_pressed"); stop->connect("pressed", this,"_stop_pressed"); //pause->connect("pressed", this,"_pause_pressed"); add_anim->connect("pressed", this,"_animation_new"); @@ -1104,6 +1313,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { renaming=false; last_active=false; + + set_process_unhandled_key_input(true); } diff --git a/tools/editor/plugins/animation_player_editor_plugin.h b/tools/editor/plugins/animation_player_editor_plugin.h index 380dfd19036..9f0413088d7 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.h +++ b/tools/editor/plugins/animation_player_editor_plugin.h @@ -49,10 +49,19 @@ class AnimationPlayerEditor : public VBoxContainer { EditorNode *editor; AnimationPlayer *player; + enum { + TOOL_COPY_ANIM, + TOOL_PASTE_ANIM, + TOOL_EDIT_RESOURCE + }; OptionButton *animation; Button *stop; Button *play; + Button *play_from; + Button *play_bw; + Button *play_bw_from; + // Button *pause; Button *add_anim; Button *autoplay; @@ -63,6 +72,7 @@ class AnimationPlayerEditor : public VBoxContainer { Button *load_anim; Button *blend_anim; Button *remove_anim; + MenuButton *tool_anim; TextureButton *pin; Label *nodename; SpinBox *frame; @@ -74,7 +84,7 @@ class AnimationPlayerEditor : public VBoxContainer { Ref autoplay_icon; bool last_active; - FileDialog *file; + EditorFileDialog *file; struct BlendEditor { @@ -95,6 +105,9 @@ class AnimationPlayerEditor : public VBoxContainer { void _select_anim_by_name(const String& p_anim); void _play_pressed(); + void _play_from_pressed(); + void _play_bw_pressed(); + void _play_bw_from_pressed(); void _autoplay_pressed(); void _stop_pressed(); void _pause_pressed(); @@ -126,6 +139,8 @@ class AnimationPlayerEditor : public VBoxContainer { void _animation_key_editor_seek(float p_pos); void _animation_key_editor_anim_len_changed(float p_new); + void _unhandled_key_input(const InputEvent& p_ev); + void _animation_tool_menu(int p_option); AnimationPlayerEditor(); protected: diff --git a/tools/editor/plugins/animation_tree_editor_plugin.cpp b/tools/editor/plugins/animation_tree_editor_plugin.cpp index 2df9377daf3..382bc447264 100644 --- a/tools/editor/plugins/animation_tree_editor_plugin.cpp +++ b/tools/editor/plugins/animation_tree_editor_plugin.cpp @@ -1193,7 +1193,7 @@ void AnimationTreeEditor::_add_menu_item(int p_item) { } else if (p_item == MENU_IMPORT_ANIMATIONS) { file_op = MENU_IMPORT_ANIMATIONS; - file_dialog->set_mode(FileDialog::MODE_OPEN_FILE); + file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); file_dialog->popup_centered_ratio(); } else { @@ -1458,7 +1458,7 @@ AnimationTreeEditor::AnimationTreeEditor() { edit_check->hide();; edit_check->connect("pressed", this,"_edit_dialog_changed"); - file_dialog = memnew( FileDialog ); + file_dialog = memnew( EditorFileDialog ); file_dialog->set_enable_multiple_selection(true); file_dialog->set_current_dir(Globals::get_singleton()->get_resource_path()); add_child(file_dialog); diff --git a/tools/editor/plugins/animation_tree_editor_plugin.h b/tools/editor/plugins/animation_tree_editor_plugin.h index beb67c71966..bd29530c7ae 100644 --- a/tools/editor/plugins/animation_tree_editor_plugin.h +++ b/tools/editor/plugins/animation_tree_editor_plugin.h @@ -79,7 +79,7 @@ class AnimationTreeEditor : public Control { Button *edit_button; Button *filter_button; CheckButton *edit_check; - FileDialog* file_dialog; + EditorFileDialog* file_dialog; int file_op; void _popup_edit_dialog(); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index fef5890f11f..f2738f0a62c 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -150,8 +150,56 @@ void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) { _tool_select(TOOL_MOVE); if (p_ev.key.pressed && !p_ev.key.echo && p_ev.key.scancode==KEY_E) _tool_select(TOOL_ROTATE); - if (p_ev.key.pressed && !p_ev.key.echo && p_ev.key.scancode==KEY_V && drag==DRAG_ALL && can_move_pivot) - drag=DRAG_PIVOT; + if (p_ev.key.pressed && !p_ev.key.echo && p_ev.key.scancode==KEY_V && drag==DRAG_NONE && can_move_pivot) { + if (p_ev.key.mod.shift) { + //move drag pivot + drag=DRAG_PIVOT; + } else if (!Input::get_singleton()->is_mouse_button_pressed(0)) { + + List &selection = editor_selection->get_selected_node_list(); + + Vector2 mouse_pos = viewport->get_local_mouse_pos(); + if (selection.size() && viewport->get_rect().has_point(mouse_pos)) { + //just in case, make it work if over viewport + mouse_pos=transform.affine_inverse().xform(mouse_pos); + mouse_pos=snap_point(mouse_pos); + + undo_redo->create_action("Move Pivot"); + + for(List::Element *E=selection.front();E;E=E->next()) { + + Node2D *n2d = E->get()->cast_to(); + + if (n2d && n2d->edit_has_pivot()) { + + Vector2 offset = n2d->edit_get_pivot(); + Vector2 gpos = n2d->get_global_pos(); + + Vector2 motion_ofs = gpos-mouse_pos; + + undo_redo->add_do_method(n2d,"set_global_pos",mouse_pos); + undo_redo->add_do_method(n2d,"edit_set_pivot",offset+n2d->get_global_transform().affine_inverse().basis_xform(motion_ofs)); + undo_redo->add_undo_method(n2d,"set_global_pos",gpos); + undo_redo->add_undo_method(n2d,"edit_set_pivot",offset); + for(int i=0;iget_child_count();i++) { + Node2D *n2dc = n2d->get_child(i)->cast_to(); + if (!n2dc) + continue; + + undo_redo->add_do_method(n2dc,"set_global_pos",n2dc->get_global_pos()); + undo_redo->add_undo_method(n2dc,"set_global_pos",n2dc->get_global_pos()); + + } + + } + + } + + undo_redo->commit_action(); + } + + } + } } @@ -1685,7 +1733,7 @@ void CanvasItemEditor::_viewport_draw() { viewport->draw_line(endpoints[i],endpoints[(i+1)%4],c,2); } - if (single && (tool==TOOL_SELECT || tool == TOOL_MOVE)) { //kind of sucks + if (single && (tool==TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE)) { //kind of sucks if (canvas_item->cast_to()) { @@ -2854,7 +2902,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(select_button); select_button->connect("pressed",this,"_tool_select",make_binds(TOOL_SELECT)); select_button->set_pressed(true); - select_button->set_tooltip("Select Mode (Q)\n"+keycode_get_string(KEY_MASK_CMD)+"Drag: Rotate\nAlt+Drag: Move\nPress 'v' to Move Pivot (while moving)"); + select_button->set_tooltip("Select Mode (Q)\n"+keycode_get_string(KEY_MASK_CMD)+"Drag: Rotate\nAlt+Drag: Move\nPress 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)."); move_button = memnew( ToolButton ); move_button->set_toggle_mode(true); diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp index a533c6aa1e9..8eea7231269 100644 --- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp @@ -380,6 +380,7 @@ void CollisionPolygon2DEditor::_bind_methods() { CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) { + node=NULL; canvas_item_editor=NULL; editor=p_editor; undo_redo = editor->get_undo_redo(); diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_editor_plugin.cpp index de40727f1b0..381cfd74aba 100644 --- a/tools/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_editor_plugin.cpp @@ -533,6 +533,7 @@ void CollisionPolygonEditor::_bind_methods() { CollisionPolygonEditor::CollisionPolygonEditor(EditorNode *p_editor) { + node=NULL; editor=p_editor; undo_redo = editor->get_undo_redo(); diff --git a/tools/editor/plugins/color_ramp_editor_plugin.cpp b/tools/editor/plugins/color_ramp_editor_plugin.cpp new file mode 100644 index 00000000000..df505354020 --- /dev/null +++ b/tools/editor/plugins/color_ramp_editor_plugin.cpp @@ -0,0 +1,83 @@ +/* + * color_ramp_editor_plugin.cpp + */ + +#include "color_ramp_editor_plugin.h" + +ColorRampEditorPlugin::ColorRampEditorPlugin(EditorNode *p_node) { + + editor=p_node; + ramp_editor = memnew( ColorRampEdit ); + + add_custom_control(CONTAINER_CANVAS_EDITOR_BOTTOM,ramp_editor); + //add_custom_control(CONTAINER_SPATIAL_EDITOR_BOTTOM,ramp_editor); + ramp_editor->set_custom_minimum_size(Size2(100, 48)); + ramp_editor->hide(); + ramp_editor->connect("ramp_changed", this, "ramp_changed"); +} + +void ColorRampEditorPlugin::edit(Object *p_object) { + + ColorRamp* color_ramp = p_object->cast_to(); + if (!color_ramp) + return; + color_ramp_ref = Ref(color_ramp); + ramp_editor->set_points(color_ramp_ref->get_points()); +} + +bool ColorRampEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("ColorRamp"); +} + +void ColorRampEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + ramp_editor->show(); + } else { + ramp_editor->hide(); + } + +} + +void ColorRampEditorPlugin::_ramp_changed() { + + if(color_ramp_ref.is_valid()) + { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + + //Not sure if I should convert this data to DVector + Vector new_offsets=ramp_editor->get_offsets(); + Vector new_colors=ramp_editor->get_colors(); + Vector old_offsets=color_ramp_ref->get_offsets(); + Vector old_colors=color_ramp_ref->get_colors(); + + if (old_offsets.size()!=new_offsets.size()) + ur->create_action("Add/Remove Color Ramp Point"); + else + ur->create_action("Modify Color Ramp",true); + ur->add_do_method(this,"undo_redo_color_ramp",new_offsets,new_colors); + ur->add_undo_method(this,"undo_redo_color_ramp",old_offsets,old_colors); + ur->commit_action(); + + //color_ramp_ref->set_points(ramp_editor->get_points()); + } +} + +void ColorRampEditorPlugin::_undo_redo_color_ramp(const Vector& offsets, + const Vector& colors) { + + color_ramp_ref->set_offsets(offsets); + color_ramp_ref->set_colors(colors); + ramp_editor->set_points(color_ramp_ref->get_points()); + ramp_editor->update(); +} + +ColorRampEditorPlugin::~ColorRampEditorPlugin(){ +} + +void ColorRampEditorPlugin::_bind_methods() { + ObjectTypeDB::bind_method(_MD("ramp_changed"),&ColorRampEditorPlugin::_ramp_changed); + ObjectTypeDB::bind_method(_MD("undo_redo_color_ramp","offsets","colors"),&ColorRampEditorPlugin::_undo_redo_color_ramp); +} diff --git a/tools/editor/plugins/color_ramp_editor_plugin.h b/tools/editor/plugins/color_ramp_editor_plugin.h new file mode 100644 index 00000000000..e39a5d65fe5 --- /dev/null +++ b/tools/editor/plugins/color_ramp_editor_plugin.h @@ -0,0 +1,37 @@ +/* + * color_ramp_editor_plugin.h + */ + +#ifndef TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ +#define TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/gui/color_ramp_edit.h" + +class ColorRampEditorPlugin : public EditorPlugin { + + OBJ_TYPE( ColorRampEditorPlugin, EditorPlugin ); + + Ref color_ramp_ref; + ColorRampEdit *ramp_editor; + EditorNode *editor; + +protected: + static void _bind_methods(); + void _ramp_changed(); + void _undo_redo_color_ramp(const Vector& offsets, const Vector& colors); + +public: + virtual String get_name() const { return "ColorRamp"; } + 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); + + ColorRampEditorPlugin(EditorNode *p_node); + ~ColorRampEditorPlugin(); + +}; + +#endif /* TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ */ diff --git a/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp b/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp index 7d243b8a65d..c1184850833 100644 --- a/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp +++ b/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp @@ -269,8 +269,8 @@ void MeshLibraryEditor::_bind_methods() { MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) { - file = memnew( FileDialog ); - file->set_mode(FileDialog::MODE_OPEN_FILE); + file = memnew( EditorFileDialog ); + file->set_mode(EditorFileDialog::MODE_OPEN_FILE); //not for now? List extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions); diff --git a/tools/editor/plugins/cube_grid_theme_editor_plugin.h b/tools/editor/plugins/cube_grid_theme_editor_plugin.h index 70ccef2add8..583ddf6e148 100644 --- a/tools/editor/plugins/cube_grid_theme_editor_plugin.h +++ b/tools/editor/plugins/cube_grid_theme_editor_plugin.h @@ -42,7 +42,7 @@ class MeshLibraryEditor : public Control { EditorNode *editor; MenuButton *menu; ConfirmationDialog *cd; - FileDialog *file; + EditorFileDialog *file; int to_erase; enum { diff --git a/tools/editor/plugins/editor_preview_plugins.cpp b/tools/editor/plugins/editor_preview_plugins.cpp new file mode 100644 index 00000000000..a77ba9a605d --- /dev/null +++ b/tools/editor/plugins/editor_preview_plugins.cpp @@ -0,0 +1,777 @@ +#include "editor_preview_plugins.h" +#include "io/resource_loader.h" +#include "tools/editor/editor_settings.h" +#include "io/file_access_memory.h" +#include "os/os.h" +#include "scene/resources/material.h" +#include "scene/resources/sample.h" +#include "scene/resources/mesh.h" + +bool EditorTexturePreviewPlugin::handles(const String& p_type) const { + + return ObjectTypeDB::is_type(p_type,"ImageTexture"); +} + +Ref EditorTexturePreviewPlugin::generate(const RES& p_from) { + + Ref tex =p_from; + Image img = tex->get_data(); + if (img.empty()) + return Ref(); + + img.clear_mipmaps(); + + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + if (img.is_compressed()) { + if (img.decompress()!=OK) + return Ref(); + } else if (img.get_format()!=Image::FORMAT_RGB && img.get_format()!=Image::FORMAT_RGB) { + img.convert(Image::FORMAT_RGBA); + } + + int width,height; + if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) { + + width=thumbnail_size; + height = img.get_height() * thumbnail_size / img.get_width(); + } else if (img.get_height() > thumbnail_size && img.get_height() >= img.get_width()) { + + height=thumbnail_size; + width = img.get_width() * thumbnail_size / img.get_height(); + } else { + + width=img.get_width(); + height=img.get_height(); + } + + img.resize(width,height); + + Ref ptex = Ref( memnew( ImageTexture )); + + ptex->create_from_image(img,0); + return ptex; + +} + +EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() { + + +} + +/////////////////////////////////////////////////////////////////////////// + + +Ref EditorPackedScenePreviewPlugin::_gen_from_imd(Ref p_imd) { + + if (p_imd.is_null()) { + return Ref(); + } + + if (!p_imd->has_option("thumbnail")) + return Ref(); + + Variant tn = p_imd->get_option("thumbnail"); + //print_line(Variant::get_type_name(tn.get_type())); + DVector thumbnail = tn; + + int len = thumbnail.size(); + if (len==0) + return Ref(); + + + DVector::Read r = thumbnail.read(); + + Image img(r.ptr(),len); + if (img.empty()) + return Ref(); + + Ref ptex = Ref( memnew( ImageTexture )); + ptex->create_from_image(img,0); + return ptex; + +} + +bool EditorPackedScenePreviewPlugin::handles(const String& p_type) const { + + return ObjectTypeDB::is_type(p_type,"PackedScene"); +} +Ref EditorPackedScenePreviewPlugin::generate(const RES& p_from) { + + Ref imd = p_from->get_import_metadata(); + return _gen_from_imd(imd); +} + +Ref EditorPackedScenePreviewPlugin::generate_from_path(const String& p_path) { + + Ref imd = ResourceLoader::load_import_metadata(p_path); + return _gen_from_imd(imd); +} + +EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() { + +} + +////////////////////////////////////////////////////////////////// + +bool EditorMaterialPreviewPlugin::handles(const String& p_type) const { + + return ObjectTypeDB::is_type(p_type,"Material"); //any material +} + +Ref EditorMaterialPreviewPlugin::generate(const RES& p_from) { + + Ref material = p_from; + ERR_FAIL_COND_V(material.is_null(),Ref()); + + VS::get_singleton()->mesh_surface_set_material(sphere,0,material->get_rid()); + + VS::get_singleton()->viewport_queue_screen_capture(viewport); + VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture +// print_line("queue capture!"); + Image img; + + int timeout=1000; + while(timeout) { + //print_line("try capture?"); + OS::get_singleton()->delay_usec(10); + img = VS::get_singleton()->viewport_get_screen_capture(viewport); + if (!img.empty()) + break; + timeout--; + } + + //print_line("captured!"); + VS::get_singleton()->mesh_surface_set_material(sphere,0,RID()); + + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + img.resize(thumbnail_size,thumbnail_size); + + Ref ptex = Ref( memnew( ImageTexture )); + ptex->create_from_image(img,0); + return ptex; +} + +EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() { + + scenario = VS::get_singleton()->scenario_create(); + + viewport = VS::get_singleton()->viewport_create(); + VS::get_singleton()->viewport_set_as_render_target(viewport,true); + VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED); + VS::get_singleton()->viewport_set_scenario(viewport,scenario); + VS::ViewportRect vr; + vr.x=0; + vr.y=0; + vr.width=128; + vr.height=128; + VS::get_singleton()->viewport_set_rect(viewport,vr); + + camera = VS::get_singleton()->camera_create(); + VS::get_singleton()->viewport_attach_camera(viewport,camera); + VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3))); + VS::get_singleton()->camera_set_perspective(camera,45,0.1,10); + + light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL); + light_instance = VS::get_singleton()->instance_create2(light,scenario); + VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0))); + + light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL); + VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7)); + VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0)); + light_instance2 = VS::get_singleton()->instance_create2(light2,scenario); + + VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1))); + + sphere = VS::get_singleton()->mesh_create(); + sphere_instance = VS::get_singleton()->instance_create2(sphere,scenario); + + int lats=32; + int lons=32; + float radius=1.0; + + DVector vertices; + DVector normals; + DVector uvs; + DVector tangents; + Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5); + + for(int i = 1; i <= lats; i++) { + double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats); + double z0 = Math::sin(lat0); + double zr0 = Math::cos(lat0); + + double lat1 = Math_PI * (-0.5 + (double) i / lats); + double z1 = Math::sin(lat1); + double zr1 = Math::cos(lat1); + + for(int j = lons; j >= 1; j--) { + + double lng0 = 2 * Math_PI * (double) (j - 1) / lons; + double x0 = Math::cos(lng0); + double y0 = Math::sin(lng0); + + double lng1 = 2 * Math_PI * (double) (j) / lons; + double x1 = Math::cos(lng1); + double y1 = Math::sin(lng1); + + + Vector3 v[4]={ + Vector3(x1 * zr0, z0, y1 *zr0), + Vector3(x1 * zr1, z1, y1 *zr1), + Vector3(x0 * zr1, z1, y0 *zr1), + Vector3(x0 * zr0, z0, y0 *zr0) + }; + +#define ADD_POINT(m_idx) \ + normals.push_back(v[m_idx]);\ + vertices.push_back(v[m_idx]*radius);\ + { Vector2 uv(Math::atan2(v[m_idx].x,v[m_idx].z),Math::atan2(-v[m_idx].y,v[m_idx].z));\ + uv/=Math_PI;\ + uv*=4.0;\ + uv=uv*0.5+Vector2(0.5,0.5);\ + uvs.push_back(uv);\ + }\ + { Vector3 t = tt.xform(v[m_idx]);\ + tangents.push_back(t.x);\ + tangents.push_back(t.y);\ + tangents.push_back(t.z);\ + tangents.push_back(1.0);\ + } + + + + ADD_POINT(0); + ADD_POINT(1); + ADD_POINT(2); + + ADD_POINT(2); + ADD_POINT(3); + ADD_POINT(0); + } + } + + Array arr; + arr.resize(VS::ARRAY_MAX); + arr[VS::ARRAY_VERTEX]=vertices; + arr[VS::ARRAY_NORMAL]=normals; + arr[VS::ARRAY_TANGENT]=tangents; + arr[VS::ARRAY_TEX_UV]=uvs; + VS::get_singleton()->mesh_add_surface(sphere,VS::PRIMITIVE_TRIANGLES,arr); + +} + +EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() { + + VS::get_singleton()->free(sphere); + VS::get_singleton()->free(sphere_instance); + VS::get_singleton()->free(viewport); + VS::get_singleton()->free(light); + VS::get_singleton()->free(light_instance); + VS::get_singleton()->free(light2); + VS::get_singleton()->free(light_instance2); + VS::get_singleton()->free(camera); + VS::get_singleton()->free(scenario); + +} + +/////////////////////////////////////////////////////////////////////////// + +static bool _is_text_char(CharType c) { + + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; +} + +bool EditorScriptPreviewPlugin::handles(const String& p_type) const { + + return ObjectTypeDB::is_type(p_type,"Script"); +} + +Ref EditorScriptPreviewPlugin::generate(const RES& p_from) { + + + Ref