diff options
27 files changed, 792 insertions, 94 deletions
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 4af3503434..8f8fce0891 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -80,7 +80,8 @@ enum { OBJECT_EXTERNAL_RESOURCE=1, OBJECT_INTERNAL_RESOURCE=2, OBJECT_EXTERNAL_RESOURCE_INDEX=3, - FORMAT_VERSION=1, + //version 2: added 64 bits support for float and int + FORMAT_VERSION=2, FORMAT_VERSION_CAN_RENAME_DEPS=1 diff --git a/core/os/input.cpp b/core/os/input.cpp index e53aa82b13..4e7b037453 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -38,7 +38,7 @@ Input *Input::get_singleton() { } void Input::set_mouse_mode(MouseMode p_mode) { - ERR_FAIL_INDEX(p_mode,3); + ERR_FAIL_INDEX(p_mode,4); OS::get_singleton()->set_mouse_mode((OS::MouseMode)p_mode); } @@ -87,6 +87,7 @@ void Input::_bind_methods() { BIND_CONSTANT( MOUSE_MODE_VISIBLE ); BIND_CONSTANT( MOUSE_MODE_HIDDEN ); BIND_CONSTANT( MOUSE_MODE_CAPTURED ); + BIND_CONSTANT( MOUSE_MODE_CONFINED ); ADD_SIGNAL( MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")) ); } diff --git a/core/os/input.h b/core/os/input.h index 82c7a80d3f..2cea154a50 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -47,7 +47,8 @@ public: enum MouseMode { MOUSE_MODE_VISIBLE, MOUSE_MODE_HIDDEN, - MOUSE_MODE_CAPTURED + MOUSE_MODE_CAPTURED, + MOUSE_MODE_CONFINED }; void set_mouse_mode(MouseMode p_mode); diff --git a/core/os/os.h b/core/os/os.h index ea03481a92..42c7c18b0c 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -131,7 +131,8 @@ public: enum MouseMode { MOUSE_MODE_VISIBLE, MOUSE_MODE_HIDDEN, - MOUSE_MODE_CAPTURED + MOUSE_MODE_CAPTURED, + MOUSE_MODE_CONFINED }; virtual void set_mouse_mode(MouseMode p_mode); diff --git a/core/ustring.cpp b/core/ustring.cpp index 478c427fb9..a0d26ea0af 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -3410,8 +3410,17 @@ String String::c_escape() const { escaped=escaped.replace("\t","\\t"); escaped=escaped.replace("\v","\\v"); escaped=escaped.replace("\'","\\'"); - escaped=escaped.replace("\"","\\\""); escaped=escaped.replace("\?","\\?"); + escaped=escaped.replace("\"","\\\""); + + return escaped; +} + +String String::c_escape_multiline() const { + + String escaped=*this; + escaped=escaped.replace("\\","\\\\"); + escaped=escaped.replace("\"","\\\""); return escaped; } diff --git a/core/ustring.h b/core/ustring.h index 426762a9e1..5665a23112 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -218,6 +218,7 @@ public: String http_escape() const; String http_unescape() const; String c_escape() const; + String c_escape_multiline() const; String c_unescape() const; String json_escape() const; String word_wrap(int p_chars_per_line) const; diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index a833a275df..1e938b4899 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -1873,7 +1873,7 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str String str=p_variant; - str="\""+str.c_escape()+"\""; + str="\""+str.c_escape_multiline()+"\""; p_store_string_func(p_store_string_ud, str ); } break; case Variant::VECTOR2: { @@ -2091,7 +2091,7 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str dict.get_key_list(&keys); keys.sort(); - p_store_string_func(p_store_string_ud,"{ "); + p_store_string_func(p_store_string_ud,"{\n"); for(List<Variant>::Element *E=keys.front();E;E=E->next()) { /* @@ -2099,14 +2099,14 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str continue; */ write(E->get(),p_store_string_func,p_store_string_ud,p_encode_res_func,p_encode_res_ud); - p_store_string_func(p_store_string_ud,":"); + p_store_string_func(p_store_string_ud,": "); write(dict[E->get()],p_store_string_func,p_store_string_ud,p_encode_res_func,p_encode_res_ud); if (E->next()) - p_store_string_func(p_store_string_ud,", "); + p_store_string_func(p_store_string_ud,",\n"); } - p_store_string_func(p_store_string_ud," }"); + p_store_string_func(p_store_string_ud,"\n}"); } break; diff --git a/main/main.cpp b/main/main.cpp index 559f5e359b..22223fe2c4 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1046,6 +1046,7 @@ Error Main::setup2() { translation_server->load_translations(); + audio_server->load_default_bus_layout(); if (use_debug_profiler && script_debugger) { script_debugger->profiling_start(); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index d1d769adf7..b230dda9cb 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -254,6 +254,25 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) // Check For Windows Messages { + case WM_SETFOCUS: + { + window_has_focus = true; + // Re-capture cursor if we're in one of the capture modes + if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) { + SetCapture(hWnd); + } + break; + } + case WM_KILLFOCUS: + { + window_has_focus = false; + + // Release capture if we're in one of the capture modes + if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) { + ReleaseCapture(); + } + break; + } case WM_ACTIVATE: // Watch For Window Activate Message { minimized = HIWORD(wParam) != 0; @@ -266,19 +285,17 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { alt_mem=false; control_mem=false; shift_mem=false; - if (mouse_mode==MOUSE_MODE_CAPTURED) { + if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) { RECT clipRect; GetClientRect(hWnd, &clipRect); ClientToScreen(hWnd, (POINT*) &clipRect.left); ClientToScreen(hWnd, (POINT*) &clipRect.right); ClipCursor(&clipRect); SetCapture(hWnd); - } } else { main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); alt_mem=false; - }; return 0; // Return To The Message Loop @@ -345,6 +362,9 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { } + // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. + if (!window_has_focus && mouse_mode==MOUSE_MODE_CAPTURED) + break; /* LPARAM extra = GetMessageExtraInfo(); if (IsPenEvent(extra)) { @@ -376,7 +396,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { mm.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/ mm.x=GET_X_LPARAM(lParam); mm.y=GET_Y_LPARAM(lParam); - + if (mouse_mode==MOUSE_MODE_CAPTURED) { Point2i c(video_mode.width/2,video_mode.height/2); @@ -410,7 +430,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { mm.relative_y=mm.y-old_y; old_x=mm.x; old_y=mm.y; - if (main_loop) + if (window_has_focus && main_loop) input->parse_input_event(event); @@ -714,9 +734,8 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { joypad->probe_joypads(); } break; case WM_SETCURSOR: { - if(LOWORD(lParam) == HTCLIENT) { - if(mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED) { + if(window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) { //Hide the cursor if(hCursor == NULL) hCursor = SetCursor(NULL); @@ -948,7 +967,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_ main_loop=NULL; outside=true; - + window_has_focus=true; WNDCLASSEXW wc; video_mode=p_desired; @@ -1326,17 +1345,17 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) { if (mouse_mode==p_mode) return; mouse_mode=p_mode; - if (p_mode==MOUSE_MODE_CAPTURED) { + if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) { RECT clipRect; GetClientRect(hWnd, &clipRect); ClientToScreen(hWnd, (POINT*) &clipRect.left); ClientToScreen(hWnd, (POINT*) &clipRect.right); ClipCursor(&clipRect); - SetCapture(hWnd); center=Point2i(video_mode.width/2,video_mode.height/2); POINT pos = { (int) center.x, (int) center.y }; ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); + if (mouse_mode==MOUSE_MODE_CAPTURED) + SetCursorPos(pos.x, pos.y); } else { ReleaseCapture(); ClipCursor(NULL); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index a5c8ecbe1b..2c8fa64f8e 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -118,6 +118,7 @@ class OS_Windows : public OS { bool control_mem; bool meta_mem; bool force_quit; + bool window_has_focus; uint32_t last_button_state; CursorShape cursor_shape; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 8baeb8bc90..38f7233c78 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -450,6 +450,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi physics_2d_server->init(); input = memnew( InputDefault ); + + window_has_focus = true; // Set focus to true at init #ifdef JOYDEV_ENABLED joypad = memnew( JoypadLinux(input)); #endif @@ -518,17 +520,21 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { if (p_mode==mouse_mode) return; - if (mouse_mode==MOUSE_MODE_CAPTURED) + if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) XUngrabPointer(x11_display, CurrentTime); - if (mouse_mode!=MOUSE_MODE_VISIBLE && p_mode==MOUSE_MODE_VISIBLE) - XUndefineCursor(x11_display,x11_window); - if (p_mode!=MOUSE_MODE_VISIBLE && mouse_mode==MOUSE_MODE_VISIBLE) { - XDefineCursor(x11_display,x11_window,null_cursor); + + // The only modes that show a cursor are VISIBLE and CONFINED + bool showCursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); + + if (showCursor) { + XUndefineCursor(x11_display,x11_window); // show cursor + } else { + XDefineCursor(x11_display,x11_window,null_cursor); // hide cursor } mouse_mode=p_mode; - if (mouse_mode==MOUSE_MODE_CAPTURED) { + if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) { while(true) { //flush pending motion events @@ -1254,6 +1260,10 @@ void OS_X11::process_xevents() { do_mouse_warp=false; + + // Is the current mouse mode one where it needs to be grabbed. + bool mouse_mode_grab = mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED; + while (XPending(x11_display) > 0) { XEvent event; XNextEvent(x11_display, &event); @@ -1272,35 +1282,45 @@ void OS_X11::process_xevents() { minimized = (visibility->state == VisibilityFullyObscured); } break; case LeaveNotify: { - - if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED) + if (main_loop && !mouse_mode_grab) main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT); if (input) input->set_mouse_in_window(false); } break; case EnterNotify: { - - if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED) + if (main_loop && !mouse_mode_grab) main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); if (input) input->set_mouse_in_window(true); } break; case FocusIn: minimized = false; + window_has_focus = true; main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); - if (mouse_mode==MOUSE_MODE_CAPTURED) { + if (mouse_mode_grab) { + // Show and update the cursor if confined and the window regained focus. + if (mouse_mode==MOUSE_MODE_CONFINED) + XUndefineCursor(x11_display, x11_window); + else if (mouse_mode==MOUSE_MODE_CAPTURED) // or re-hide it in captured mode + XDefineCursor(x11_display, x11_window, null_cursor); + XGrabPointer( - x11_display, x11_window, True, + x11_display, x11_window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime); } break; case FocusOut: + window_has_focus = false; main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); - if (mouse_mode==MOUSE_MODE_CAPTURED) { + if (mouse_mode_grab) { //dear X11, I try, I really try, but you never work, you do whathever you want. + if (mouse_mode==MOUSE_MODE_CAPTURED) { + // Show the cursor if we're in captured mode so it doesn't look weird. + XUndefineCursor(x11_display, x11_window); + } XUngrabPointer(x11_display, CurrentTime); } break; @@ -1320,7 +1340,7 @@ void OS_X11::process_xevents() { /* exit in case of a mouse button press */ last_timestamp=event.xbutton.time; - if (mouse_mode==MOUSE_MODE_CAPTURED) { + if (mouse_mode == MOUSE_MODE_CAPTURED) { event.xbutton.x=last_mouse_pos.x; event.xbutton.y=last_mouse_pos.y; } @@ -1343,7 +1363,6 @@ void OS_X11::process_xevents() { mouse_event.mouse_button.pressed=(event.type==ButtonPress); - if (event.type==ButtonPress && event.xbutton.button==1) { uint64_t diff = get_ticks_usec()/1000 - last_click_ms; @@ -1377,7 +1396,6 @@ void OS_X11::process_xevents() { // PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL // MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG. - while(true) { if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) { //this is likely the warp event since it was warped here @@ -1419,7 +1437,7 @@ void OS_X11::process_xevents() { Point2i new_center = pos; pos = last_mouse_pos + ( pos - center ); center=new_center; - do_mouse_warp=true; + do_mouse_warp=window_has_focus; // warp the cursor if we're focused in #else //Dear X11, thanks for making my life miserable @@ -1462,8 +1480,11 @@ void OS_X11::process_xevents() { last_mouse_pos=pos; // printf("rel: %d,%d\n", rel.x, rel.y ); - - input->parse_input_event( motion_event); + // Don't propagate the motion event unless we have focus + // this is so that the relative motion doesn't get messed up + // after we regain focus. + if (window_has_focus || !mouse_mode_grab) + input->parse_input_event( motion_event); } break; case KeyPress: diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 3245df32c6..3ec358f103 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -134,7 +134,7 @@ class OS_X11 : public OS_Unix { bool force_quit; bool minimized; - + bool window_has_focus; bool do_mouse_warp; const char *cursor_theme; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 958b065881..e02b2b2b41 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -118,17 +118,20 @@ bool AnimationPlayer::_get(const StringName& p_name,Variant &r_ret) const { } else if (name=="blend_times") { - Array array; - - array.resize(blend_times.size()*3); - int idx=0; + Vector<BlendKey> keys; for(Map<BlendKey, float >::Element *E=blend_times.front();E;E=E->next()) { - array.set(idx*3+0,E->key().from); - array.set(idx*3+1,E->key().to); - array.set(idx*3+2,E->get()); - idx++; + keys.ordered_insert(E->key()); } + + Array array; + for(int i=0;i<keys.size();i++) { + + array.push_back(keys[i].from); + array.push_back(keys[i].to); + array.push_back(blend_times[keys[i]]); + } + r_ret=array; } else if (name=="autoplay") { r_ret=autoplay; diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 41bae6c928..7fab651213 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -142,7 +142,7 @@ private: StringName from; StringName to; - bool operator<(const BlendKey& bk) const { return from==bk.from?to<bk.to:from<bk.from; } + bool operator<(const BlendKey& bk) const { return from==bk.from?String(to)<String(bk.to):String(from)<String(bk.from); } }; diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index a913687e7f..9719f321d6 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -32,7 +32,8 @@ #include "version.h" #include "os/dir_access.h" -#define FORMAT_VERSION 1 +//version 2: changed names for basis, rect3, poolvectors, etc. +#define FORMAT_VERSION 2 #include "version.h" #include "os/dir_access.h" @@ -1158,7 +1159,7 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant& p_variant,b static String _valprop(const String& p_name) { if (p_name.find("\"")!=-1 || p_name.find("=")!=-1 || p_name.find(" ")!=-1) - return "\""+p_name.c_escape()+"\""; + return "\""+p_name.c_escape_multiline()+"\""; return p_name; } @@ -1360,13 +1361,11 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path,const RES& p_re } if (groups.size()) { - String sgroups=" groups=[ "; + String sgroups=" groups=[\n"; for(int j=0;j<groups.size();j++) { - if (j>0) - sgroups+=", "; - sgroups+="\""+groups[j].operator String().c_escape()+"\""; + sgroups+="\""+String(groups[j]).c_escape()+"\",\n"; } - sgroups+=" ]"; + sgroups+="]"; header+=sgroups; } diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 43ab246fbc..8a8b9ebf76 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -30,6 +30,17 @@ #include "globals.h" #include "os/os.h" #include "servers/audio/effects/audio_effect_compressor.h" +#include "io/resource_loader.h" +#include "os/file_access.h" +#ifdef TOOLS_ENABLED + +#define MARK_EDITED set_edited(true); + +#else + +#define MARK_EDITED + +#endif AudioDriver *AudioDriver::singleton=NULL; AudioDriver *AudioDriver::get_singleton() { @@ -324,6 +335,9 @@ void AudioServer::set_bus_count(int p_count) { ERR_FAIL_COND(p_count<1); ERR_FAIL_INDEX(p_count,256); + + MARK_EDITED + lock(); int cb = buses.size(); @@ -390,6 +404,8 @@ void AudioServer::remove_bus(int p_index) { ERR_FAIL_INDEX(p_index,buses.size()); ERR_FAIL_COND(p_index==0); + MARK_EDITED + lock(); bus_map.erase(buses[p_index]->name); memdelete(buses[p_index]); @@ -399,6 +415,8 @@ void AudioServer::remove_bus(int p_index) { void AudioServer::add_bus(int p_at_pos) { + MARK_EDITED + if (p_at_pos>=buses.size()) { p_at_pos=-1; } else if (p_at_pos==0) { @@ -455,6 +473,8 @@ void AudioServer::move_bus(int p_bus,int p_to_pos) { ERR_FAIL_COND(p_bus<1 || p_bus>=buses.size()); ERR_FAIL_COND(p_to_pos!=-1 && (p_to_pos<1 || p_to_pos>buses.size())); + MARK_EDITED + if (p_bus==p_to_pos) return; @@ -481,6 +501,9 @@ void AudioServer::set_bus_name(int p_bus,const String& p_name) { ERR_FAIL_INDEX(p_bus,buses.size()); if (p_bus==0 && p_name!="Master") return; //bus 0 is always master + + MARK_EDITED + lock(); if (buses[p_bus]->name==p_name) { @@ -526,6 +549,9 @@ String AudioServer::get_bus_name(int p_bus) const { void AudioServer::set_bus_volume_db(int p_bus,float p_volume_db) { ERR_FAIL_INDEX(p_bus,buses.size()); + + MARK_EDITED + buses[p_bus]->volume_db=p_volume_db; } @@ -540,6 +566,8 @@ void AudioServer::set_bus_send(int p_bus,const StringName& p_send) { ERR_FAIL_INDEX(p_bus,buses.size()); + MARK_EDITED + buses[p_bus]->send=p_send; } @@ -556,6 +584,8 @@ void AudioServer::set_bus_solo(int p_bus,bool p_enable) { ERR_FAIL_INDEX(p_bus,buses.size()); + MARK_EDITED + buses[p_bus]->solo=p_enable; } @@ -572,6 +602,8 @@ void AudioServer::set_bus_mute(int p_bus,bool p_enable){ ERR_FAIL_INDEX(p_bus,buses.size()); + MARK_EDITED + buses[p_bus]->mute=p_enable; } bool AudioServer::is_bus_mute(int p_bus) const{ @@ -586,6 +618,8 @@ void AudioServer::set_bus_bypass_effects(int p_bus,bool p_enable){ ERR_FAIL_INDEX(p_bus,buses.size()); + MARK_EDITED + buses[p_bus]->bypass=p_enable; } bool AudioServer::is_bus_bypassing_effects(int p_bus) const{ @@ -618,6 +652,9 @@ void AudioServer::add_bus_effect(int p_bus,const Ref<AudioEffect>& p_effect,int ERR_FAIL_COND(p_effect.is_null()); ERR_FAIL_INDEX(p_bus,buses.size()); + MARK_EDITED + + lock(); Bus::Effect fx; @@ -641,6 +678,9 @@ void AudioServer::remove_bus_effect(int p_bus,int p_effect) { ERR_FAIL_INDEX(p_bus,buses.size()); + MARK_EDITED + + lock(); buses[p_bus]->effects.remove(p_effect); @@ -672,6 +712,9 @@ void AudioServer::swap_bus_effects(int p_bus,int p_effect,int p_by_effect) { ERR_FAIL_INDEX(p_effect,buses[p_bus]->effects.size()); ERR_FAIL_INDEX(p_by_effect,buses[p_bus]->effects.size()); + MARK_EDITED + + lock(); SWAP( buses[p_bus]->effects[p_effect], buses[p_bus]->effects[p_by_effect] ); _update_bus_effects(p_bus); @@ -682,6 +725,10 @@ void AudioServer::set_bus_effect_enabled(int p_bus,int p_effect,bool p_enabled) ERR_FAIL_INDEX(p_bus,buses.size()); ERR_FAIL_INDEX(p_effect,buses[p_bus]->effects.size()); + + MARK_EDITED + + buses[p_bus]->effects[p_effect].enabled=p_enabled; } @@ -748,8 +795,23 @@ void AudioServer::init() { if (AudioDriver::get_singleton()) AudioDriver::get_singleton()->start(); +#ifdef TOOLS_ENABLED + set_edited(false); //avoid editors from thinking this was edited +#endif } + +void AudioServer::load_default_bus_layout() { + + if (FileAccess::exists("res://default_bus_layout.tres")) { + Ref<AudioBusLayout> default_layout = ResourceLoader::load("res://default_bus_layout.tres"); + if (default_layout.is_valid()) { + set_bus_layout(default_layout); + } + } + +} + void AudioServer::finish() { for(int i=0;i<buses.size();i++) { @@ -872,6 +934,88 @@ void AudioServer::remove_callback(AudioCallback p_callback,void *p_userdata) { } +void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_state) { + + ERR_FAIL_COND(p_state.is_null() || p_state->buses.size()==0); + + lock(); + for(int i=0;i<buses.size();i++) { + memdelete(buses[i]); + } + buses.resize(p_state->buses.size()); + bus_map.clear(); + for(int i=0;i<p_state->buses.size();i++) { + Bus * bus = memnew(Bus); + if (i==0) { + bus->name="Master"; + } else { + bus->name=p_state->buses[i].name; + bus->send=p_state->buses[i].send; + } + + bus->solo=p_state->buses[i].solo; + bus->mute=p_state->buses[i].mute; + bus->bypass=p_state->buses[i].bypass; + bus->volume_db=p_state->buses[i].volume_db; + + for(int j=0;j<p_state->buses[i].effects.size();j++) { + + Ref<AudioEffect> fx = p_state->buses[i].effects[j].effect; + + if (fx.is_valid()) { + + Bus::Effect bfx; + bfx.effect=fx; + bfx.enabled=p_state->buses[i].effects[j].enabled; + bus->effects.push_back(bfx); + } + } + + bus_map[bus->name]=bus; + buses[i]=bus; + + buses[i]->channels.resize(_get_channel_count()); + for(int j=0;j<_get_channel_count();j++) { + buses[i]->channels[j].buffer.resize(buffer_size); + } + _update_bus_effects(i); + } +#ifdef TOOLS_ENABLED + set_edited(false); +#endif + unlock(); + +} + + +Ref<AudioBusLayout> AudioServer::generate_bus_layout() const { + + Ref<AudioBusLayout> state; + state.instance(); + + state->buses.resize( buses.size() ); + + for(int i=0;i<buses.size();i++) { + + state->buses[i].name=buses[i]->name; + state->buses[i].send=buses[i]->send; + state->buses[i].mute=buses[i]->mute; + state->buses[i].solo=buses[i]->solo; + state->buses[i].bypass=buses[i]->bypass; + state->buses[i].volume_db=buses[i]->volume_db; + for(int j=0;j<buses[i]->effects.size();j++) { + AudioBusLayout::Bus::Effect fx; + fx.effect=buses[i]->effects[j].effect; + fx.enabled=buses[i]->effects[j].enabled; + state->buses[i].effects.push_back(fx); + + } + } + + return state; +} + + void AudioServer::_bind_methods() { @@ -919,6 +1063,9 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(_MD("get_speaker_mode"),&AudioServer::get_speaker_mode); ClassDB::bind_method(_MD("get_mix_rate"),&AudioServer::get_mix_rate); + ClassDB::bind_method(_MD("set_state","state:AudioServerState"),&AudioServer::set_bus_layout); + ClassDB::bind_method(_MD("generate_state:AudioServerState"),&AudioServer::generate_bus_layout); + ADD_SIGNAL(MethodInfo("bus_layout_changed") ); } @@ -938,3 +1085,137 @@ AudioServer::~AudioServer() { memdelete(audio_data_lock); } +///////////////////////////////// + + + +bool AudioBusLayout::_set(const StringName& p_name, const Variant& p_value) { + + String s = p_name; + if (s.begins_with("bus/")) { + int index = s.get_slice("/",1).to_int(); + if (buses.size()<=index) { + buses.resize(index+1); + } + + Bus &bus = buses[index]; + + String what = s.get_slice("/",2); + + if (what=="name") { + bus.name=p_value; + } else if (what=="solo") { + bus.solo=p_value; + } else if (what=="mute") { + bus.mute=p_value; + } else if (what=="bypass_fx") { + bus.bypass=p_value; + } else if (what=="volume_db") { + bus.volume_db=p_value; + } else if (what=="send") { + bus.send=p_value; + } else if (what=="effect") { + int which = s.get_slice("/",3).to_int(); + if (bus.effects.size()<=which) { + bus.effects.resize(which+1); + } + + Bus::Effect &fx = bus.effects[which]; + + String fxwhat = s.get_slice("/",4); + if (fxwhat=="effect") { + fx.effect=p_value; + } else if (fxwhat=="enabled") { + fx.enabled=p_value; + } else { + return false; + } + + return true; + } else { + return false; + } + + return true; + } + + return false; + +} + +bool AudioBusLayout::_get(const StringName& p_name,Variant &r_ret) const{ + + String s = p_name; + if (s.begins_with("bus/")) { + + int index = s.get_slice("/",1).to_int(); + if (index<0 || index>=buses.size()) + return false; + + const Bus &bus = buses[index]; + + String what = s.get_slice("/",2); + + if (what=="name") { + r_ret=bus.name; + } else if (what=="solo") { + r_ret=bus.solo; + } else if (what=="mute") { + r_ret=bus.mute; + } else if (what=="bypass_fx") { + r_ret=bus.bypass; + } else if (what=="volume_db") { + r_ret=bus.volume_db; + } else if (what=="send") { + r_ret=bus.send; + } else if (what=="effect") { + int which = s.get_slice("/",3).to_int(); + if (which<0 || which>=bus.effects.size()) { + return false; + } + + const Bus::Effect &fx = bus.effects[which]; + + String fxwhat = s.get_slice("/",4); + if (fxwhat=="effect") { + r_ret=fx.effect; + } else if (fxwhat=="enabled") { + r_ret=fx.enabled; + } else { + return false; + } + + return true; + } else { + return false; + } + + return true; + } + + return false; + +} +void AudioBusLayout::_get_property_list( List<PropertyInfo> *p_list) const{ + + for(int i=0;i<buses.size();i++) { + p_list->push_back(PropertyInfo(Variant::STRING,"bus/"+itos(i)+"/name",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/solo",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/mute",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/bypass_fx",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL,"bus/"+itos(i)+"/volume_db",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL,"bus/"+itos(i)+"/send",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + + for(int j=0;j<buses[i].effects.size();j++) { + p_list->push_back(PropertyInfo(Variant::OBJECT,"bus/"+itos(i)+"/effect/"+itos(j)+"/effect",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/effect/"+itos(j)+"/enabled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + } + } +} + + +AudioBusLayout::AudioBusLayout() { + + buses.resize(1); + buses[0].name="Master"; +} diff --git a/servers/audio_server.h b/servers/audio_server.h index 9de330482b..88849bb591 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -100,7 +100,7 @@ public: }; - +class AudioBusLayout; class AudioServer : public Object { @@ -205,8 +205,6 @@ private: Set<CallbackItem> callbacks; - - friend class AudioDriver; void _driver_process(int p_frames, int32_t *p_buffer); protected: @@ -266,6 +264,7 @@ public: virtual void init(); virtual void finish(); virtual void update(); + virtual void load_default_bus_layout(); /* MISC config */ @@ -293,13 +292,64 @@ public: void add_callback(AudioCallback p_callback,void *p_userdata); void remove_callback(AudioCallback p_callback,void *p_userdata); + void set_bus_layout(const Ref<AudioBusLayout>& p_state); + Ref<AudioBusLayout> generate_bus_layout() const; + AudioServer(); virtual ~AudioServer(); }; - VARIANT_ENUM_CAST( AudioServer::SpeakerMode ) +class AudioBusLayout : public Resource { + + GDCLASS(AudioBusLayout,Resource) + +friend class AudioServer; + + struct Bus { + + StringName name; + bool solo; + bool mute; + bool bypass; + + struct Effect { + Ref<AudioEffect> effect; + bool enabled; + }; + + Vector<Effect> effects; + + float volume_db; + StringName send; + + Bus() { + solo=false; + mute=false; + bypass=false; + volume_db=0; + } + }; + + Vector<Bus> buses; + +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + +public: + + AudioBusLayout(); +}; + + + + + + typedef AudioServer AS; diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 56bb0d32b2..01f8ffa504 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -85,6 +85,7 @@ void register_server_types() { ClassDB::register_virtual_class<AudioStream>(); ClassDB::register_virtual_class<AudioStreamPlayback>(); ClassDB::register_virtual_class<AudioEffect>(); + ClassDB::register_class<AudioBusLayout>(); { //audio effects diff --git a/tools/editor/editor_audio_buses.cpp b/tools/editor/editor_audio_buses.cpp index 425477890e..6ee18f08d8 100644 --- a/tools/editor/editor_audio_buses.cpp +++ b/tools/editor/editor_audio_buses.cpp @@ -2,6 +2,8 @@ #include "editor_node.h" #include "servers/audio_server.h" #include "os/keyboard.h" +#include "io/resource_saver.h" +#include "filesystem_dock.h" void EditorAudioBus::_notification(int p_what) { @@ -390,6 +392,9 @@ void EditorAudioBus::_delete_pressed(int p_option) { if (p_option==1) { emit_signal("delete_request"); + } else if (p_option==0) { + //duplicate + emit_signal("duplicate_request",get_index()); } } @@ -598,6 +603,7 @@ void EditorAudioBus::_bind_methods() { + ADD_SIGNAL(MethodInfo("duplicate_request")); ADD_SIGNAL(MethodInfo("delete_request")); ADD_SIGNAL(MethodInfo("drop_end_request")); ADD_SIGNAL(MethodInfo("dropped")); @@ -770,6 +776,7 @@ void EditorAudioBuses::_update_buses() { } bus_hb->add_child(audio_bus); audio_bus->connect("delete_request",this,"_delete_bus",varray(audio_bus),CONNECT_DEFERRED); + audio_bus->connect("duplicate_request",this,"_duplicate_bus",varray(),CONNECT_DEFERRED); audio_bus->connect("drop_end_request",this,"_request_drop_end"); audio_bus->connect("dropped",this,"_drop_at_index",varray(),CONNECT_DEFERRED); @@ -778,10 +785,11 @@ void EditorAudioBuses::_update_buses() { } } -void EditorAudioBuses::register_editor() { +EditorAudioBuses *EditorAudioBuses::register_editor() { EditorAudioBuses * audio_buses = memnew( EditorAudioBuses ); EditorNode::get_singleton()->add_bottom_panel_item("Audio",audio_buses); + return audio_buses; } void EditorAudioBuses::_notification(int p_what) { @@ -796,6 +804,29 @@ void EditorAudioBuses::_notification(int p_what) { drop_end=NULL; } } + + if (p_what==NOTIFICATION_PROCESS) { + + //check if anything was edited + bool edited = AudioServer::get_singleton()->is_edited(); + for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) { + for(int j=0;j<AudioServer::get_singleton()->get_bus_effect_count(i);j++) { + Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(i,j); + if (effect->is_edited()) { + edited=true; + effect->set_edited(false); + } + } + } + + AudioServer::get_singleton()->set_edited(false); + + if (edited) { + + save_timer->start(); + } + } + } @@ -860,6 +891,31 @@ void EditorAudioBuses::_delete_bus(Object* p_which) { } + +void EditorAudioBuses::_duplicate_bus(int p_which) { + + int add_at_pos = p_which+1; + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Duplicate Audio Bus"); + ur->add_do_method(AudioServer::get_singleton(),"add_bus",add_at_pos); + ur->add_do_method(AudioServer::get_singleton(),"set_bus_name",add_at_pos,AudioServer::get_singleton()->get_bus_name(p_which)+" Copy"); + ur->add_do_method(AudioServer::get_singleton(),"set_bus_volume_db",add_at_pos,AudioServer::get_singleton()->get_bus_volume_db(p_which)); + ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",add_at_pos,AudioServer::get_singleton()->get_bus_send(p_which)); + ur->add_do_method(AudioServer::get_singleton(),"set_bus_solo",add_at_pos,AudioServer::get_singleton()->is_bus_solo(p_which)); + ur->add_do_method(AudioServer::get_singleton(),"set_bus_mute",add_at_pos,AudioServer::get_singleton()->is_bus_mute(p_which)); + ur->add_do_method(AudioServer::get_singleton(),"set_bus_bypass_effects",add_at_pos,AudioServer::get_singleton()->is_bus_bypassing_effects(p_which)); + for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(p_which);i++) { + + ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",add_at_pos,AudioServer::get_singleton()->get_bus_effect(p_which,i)); + ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",add_at_pos,i,AudioServer::get_singleton()->is_bus_effect_enabled(p_which,i)); + } + ur->add_undo_method(AudioServer::get_singleton(),"remove_bus",add_at_pos); + ur->add_do_method(this,"_update_buses"); + ur->add_undo_method(this,"_update_buses"); + ur->commit_action(); + +} + void EditorAudioBuses::_request_drop_end() { if (!drop_end && bus_hb->get_child_count()) { @@ -896,6 +952,103 @@ void EditorAudioBuses::_drop_at_index(int p_bus,int p_index) { ur->commit_action(); } +void EditorAudioBuses::_server_save() { + + Ref<AudioBusLayout> state = AudioServer::get_singleton()->generate_bus_layout(); + ResourceSaver::save(edited_path,state); + +} + +void EditorAudioBuses::_select_layout() { + + EditorNode::get_singleton()->get_filesystem_dock()->select_file(edited_path); +} + +void EditorAudioBuses::_save_as_layout() { + + file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_title(TTR("Save Audio Bus Layout As..")); + file_dialog->set_current_path(edited_path); + file_dialog->popup_centered_ratio(); + new_layout=false; +} + + +void EditorAudioBuses::_new_layout() { + + file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_title(TTR("Location for New Layout..")); + file_dialog->set_current_path(edited_path); + file_dialog->popup_centered_ratio(); + new_layout=true; +} + +void EditorAudioBuses::_load_layout() { + + file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_dialog->set_title(TTR("Open Audio Bus Layout")); + file_dialog->set_current_path(edited_path); + file_dialog->popup_centered_ratio(); + new_layout=false; +} + + +void EditorAudioBuses::_load_default_layout() { + + + Ref<AudioBusLayout> state = ResourceLoader::load("res://default_bus_layout.tres"); + if (state.is_null()) { + EditorNode::get_singleton()->show_warning("There is no 'res://default_bus_layout.tres' file."); + return; + } + + edited_path="res://default_bus_layout.tres"; + file->set_text(edited_path.get_file()); + AudioServer::get_singleton()->set_bus_layout(state); + _update_buses(); + EditorNode::get_singleton()->get_undo_redo()->clear_history(); + call_deferred("_select_layout"); +} + +void EditorAudioBuses::_file_dialog_callback(const String& p_string) { + + if (file_dialog->get_mode()==EditorFileDialog::MODE_OPEN_FILE) { + Ref<AudioBusLayout> state = ResourceLoader::load(p_string); + if (state.is_null()) { + EditorNode::get_singleton()->show_warning("Invalid file, not an audio bus layout."); + return; + } + + edited_path=p_string; + file->set_text(p_string.get_file()); + AudioServer::get_singleton()->set_bus_layout(state); + _update_buses(); + EditorNode::get_singleton()->get_undo_redo()->clear_history(); + call_deferred("_select_layout"); + + } else if (file_dialog->get_mode()==EditorFileDialog::MODE_SAVE_FILE) { + + if (new_layout) { + Ref<AudioBusLayout> empty_state; + empty_state.instance(); + AudioServer::get_singleton()->set_bus_layout(empty_state); + } + + Error err = ResourceSaver::save(p_string,AudioServer::get_singleton()->generate_bus_layout()); + + if (err!=OK) { + EditorNode::get_singleton()->show_warning("Error saving file: "+p_string); + return; + } + + edited_path=p_string; + file->set_text(p_string.get_file()); + _update_buses(); + EditorNode::get_singleton()->get_undo_redo()->clear_history(); + call_deferred("_select_layout"); + } + +} void EditorAudioBuses::_bind_methods() { @@ -906,6 +1059,15 @@ void EditorAudioBuses::_bind_methods() { ClassDB::bind_method("_delete_bus",&EditorAudioBuses::_delete_bus); ClassDB::bind_method("_request_drop_end",&EditorAudioBuses::_request_drop_end); ClassDB::bind_method("_drop_at_index",&EditorAudioBuses::_drop_at_index); + ClassDB::bind_method("_server_save",&EditorAudioBuses::_server_save); + ClassDB::bind_method("_select_layout",&EditorAudioBuses::_select_layout); + ClassDB::bind_method("_save_as_layout",&EditorAudioBuses::_save_as_layout); + ClassDB::bind_method("_load_layout",&EditorAudioBuses::_load_layout); + ClassDB::bind_method("_load_default_layout",&EditorAudioBuses::_load_default_layout); + ClassDB::bind_method("_new_layout",&EditorAudioBuses::_new_layout); + ClassDB::bind_method("_duplicate_bus",&EditorAudioBuses::_duplicate_bus); + + ClassDB::bind_method("_file_dialog_callback",&EditorAudioBuses::_file_dialog_callback); } EditorAudioBuses::EditorAudioBuses() @@ -917,25 +1079,38 @@ EditorAudioBuses::EditorAudioBuses() add = memnew( Button ); top_hb->add_child(add);; - add->set_text(TTR("Add")); + add->set_text(TTR("Add Bus")); add->connect("pressed",this,"_add_bus"); - Ref<ButtonGroup> bg; - bg.instance(); - buses = memnew( ToolButton ); - top_hb->add_child(buses); - buses->set_text(TTR("Buses")); - buses->set_button_group(bg); - buses->set_toggle_mode(true); - buses->set_pressed(true); - groups = memnew( ToolButton ); - top_hb->add_child(groups); - groups->set_text(TTR("Groups")); - groups->set_button_group(bg); - groups->set_toggle_mode(true); + top_hb->add_spacer(); + + file = memnew( ToolButton ); + file->set_text("default_bus_layout.tres"); + top_hb->add_child(file); + file->connect("pressed",this,"_select_layout"); + + load = memnew( Button ); + load->set_text(TTR("Load")); + top_hb->add_child(load); + load->connect("pressed",this,"_load_layout"); + + save_as = memnew( Button ); + save_as->set_text(TTR("Save As")); + top_hb->add_child(save_as); + save_as->connect("pressed",this,"_save_as_layout"); + + _default = memnew( Button ); + _default->set_text(TTR("Default")); + top_hb->add_child(_default); + _default->connect("pressed",this,"_load_default_layout"); + + _new = memnew( Button ); + _new->set_text(TTR("Create")); + top_hb->add_child(_new); + _new->connect("pressed",this,"_new_layout"); bus_scroll = memnew( ScrollContainer ); bus_scroll->set_v_size_flags(SIZE_EXPAND_FILL); @@ -945,18 +1120,73 @@ EditorAudioBuses::EditorAudioBuses() bus_hb = memnew( HBoxContainer ); bus_scroll->add_child(bus_hb); - group_scroll = memnew( ScrollContainer ); - group_scroll->set_v_size_flags(SIZE_EXPAND_FILL); - group_scroll->set_enable_h_scroll(true); - group_scroll->set_enable_v_scroll(false); - add_child(group_scroll); - group_hb = memnew( HBoxContainer ); - group_scroll->add_child(group_hb); + save_timer=memnew(Timer); + save_timer->set_wait_time(0.8); + save_timer->set_one_shot(true); + add_child(save_timer); + save_timer->connect("timeout",this,"_server_save"); - group_scroll->hide(); + set_v_size_flags(SIZE_EXPAND_FILL); - set_v_size_flags(SIZE_EXPAND_FILL); + edited_path = "res://default_bus_layout.tres"; + + file_dialog = memnew( EditorFileDialog ); + List<String> ext; + ResourceLoader::get_recognized_extensions_for_type("AudioServerState",&ext); + for (List<String>::Element *E=ext.front();E;E=E->next()) { + file_dialog->add_filter("*."+E->get()+"; Audio Bus State"); + } + add_child(file_dialog); + file_dialog->connect("file_selected",this,"_file_dialog_callback"); + + set_process(true); + +} +void EditorAudioBuses::open_layout(const String& p_path) { + + EditorNode::get_singleton()->make_bottom_panel_item_visible(this); + + Ref<AudioBusLayout> state = ResourceLoader::load(p_path); + if (state.is_null()) { + EditorNode::get_singleton()->show_warning("Invalid file, not an audio bus layout."); + return; + } + + edited_path=p_path; + file->set_text(p_path.get_file()); + AudioServer::get_singleton()->set_bus_layout(state); + _update_buses(); + EditorNode::get_singleton()->get_undo_redo()->clear_history(); + call_deferred("_select_layout"); +} + +void AudioBusesEditorPlugin::edit(Object *p_node) { + + if (p_node->cast_to<AudioBusLayout>()) { + + String path = p_node->cast_to<AudioBusLayout>()->get_path(); + if (path.is_resource_file()) { + audio_bus_editor->open_layout(path); + } + } +} + +bool AudioBusesEditorPlugin::handles(Object *p_node) const { + + return (p_node->cast_to<AudioBusLayout>()!=NULL); +} + +void AudioBusesEditorPlugin::make_visible(bool p_visible){ + + +} + +AudioBusesEditorPlugin::AudioBusesEditorPlugin(EditorAudioBuses *p_node) { + + audio_bus_editor=p_node; +} +AudioBusesEditorPlugin::~AudioBusesEditorPlugin() { } diff --git a/tools/editor/editor_audio_buses.h b/tools/editor/editor_audio_buses.h index c6621c08d8..e44f8cd579 100644 --- a/tools/editor/editor_audio_buses.h +++ b/tools/editor/editor_audio_buses.h @@ -14,6 +14,8 @@ #include "scene/gui/tree.h" #include "scene/gui/option_button.h" #include "scene/gui/panel.h" +#include "tools/editor/editor_file_dialog.h" +#include "editor_plugin.h" class EditorAudioBuses; @@ -109,36 +111,76 @@ class EditorAudioBuses : public VBoxContainer { HBoxContainer *top_hb; Button *add; - ToolButton *buses; - ToolButton *groups; ScrollContainer *bus_scroll; HBoxContainer *bus_hb; - ScrollContainer *group_scroll; - HBoxContainer *group_hb; EditorAudioBusDrop *drop_end; + Button *file; + Button *load; + Button *save_as; + Button *_default; + Button *_new; + + Timer *save_timer; + String edited_path; + void _add_bus(); void _update_buses(); void _update_bus(int p_index); void _update_sends(); void _delete_bus(Object* p_which); + void _duplicate_bus(int p_which); + void _request_drop_end(); void _drop_at_index(int p_bus,int p_index); + void _server_save(); + + void _select_layout(); + void _load_layout(); + void _save_as_layout(); + void _load_default_layout(); + void _new_layout(); + + EditorFileDialog *file_dialog; + bool new_layout; + + void _file_dialog_callback(const String& p_string); + protected: static void _bind_methods(); void _notification(int p_what); public: + void open_layout(const String& p_path); - - static void register_editor(); + static EditorAudioBuses* register_editor(); EditorAudioBuses(); }; + + +class AudioBusesEditorPlugin : public EditorPlugin { + + GDCLASS( AudioBusesEditorPlugin, EditorPlugin ); + + EditorAudioBuses *audio_bus_editor; +public: + + virtual String get_name() const { return "SampleLibrary"; } + 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); + + AudioBusesEditorPlugin(EditorAudioBuses *p_node); + ~AudioBusesEditorPlugin(); + +}; + #endif // EDITORAUDIOBUSES_H diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index e9441695ed..bd54eaceb6 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -6568,7 +6568,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( ScriptEditorPlugin(this) ) ); - EditorAudioBuses::register_editor(); + EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor(); ScriptTextEditor::register_editor(); //register one for text scripts @@ -6617,6 +6617,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( ColorRampEditorPlugin(this) ) ); add_editor_plugin( memnew( CollisionShape2DEditorPlugin(this) ) ); add_editor_plugin( memnew( TextureEditorPlugin(this) ) ); + add_editor_plugin( memnew( AudioBusesEditorPlugin(audio_bus_editor) ) ); //add_editor_plugin( memnew( MaterialEditorPlugin(this) ) ); //add_editor_plugin( memnew( MeshEditorPlugin(this) ) ); diff --git a/tools/editor/filesystem_dock.cpp b/tools/editor/filesystem_dock.cpp index 26a118521b..021d5c4eb9 100644 --- a/tools/editor/filesystem_dock.cpp +++ b/tools/editor/filesystem_dock.cpp @@ -1626,6 +1626,19 @@ void FileSystemDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) { } +void FileSystemDock::select_file(const String& p_file) { + + _go_to_dir(p_file.get_base_dir()); + for(int i=0;i<files->get_item_count();i++) { + if (files->get_item_metadata(i)==p_file) { + files->select(i); + files->ensure_current_is_visible(); + break; + } + } + +} + void FileSystemDock::_bind_methods() { ClassDB::bind_method(_MD("_update_tree"),&FileSystemDock::_update_tree); diff --git a/tools/editor/filesystem_dock.h b/tools/editor/filesystem_dock.h index a5a1df0955..73265657e5 100644 --- a/tools/editor/filesystem_dock.h +++ b/tools/editor/filesystem_dock.h @@ -201,6 +201,7 @@ public: int get_split_offset() { return split_box->get_split_offset(); } void set_split_offset(int p_offset) { split_box->set_split_offset(p_offset); } + void select_file(const String& p_file); FileSystemDock(EditorNode *p_editor); ~FileSystemDock(); diff --git a/tools/editor/icons/2x/icon_transparent.png b/tools/editor/icons/2x/icon_transparent.png Binary files differnew file mode 100644 index 0000000000..627607039b --- /dev/null +++ b/tools/editor/icons/2x/icon_transparent.png diff --git a/tools/editor/icons/icon_transparent.png b/tools/editor/icons/icon_transparent.png Binary files differnew file mode 100644 index 0000000000..07e9b52b5c --- /dev/null +++ b/tools/editor/icons/icon_transparent.png diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index ab850ba1a7..e5dce0524f 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -2431,7 +2431,7 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p } break; case Variant::COLOR: { - p_item->set_custom_bg_color(1,obj->get(p_name)); + tree->update(); //p_item->set_text(1,obj->get(p_name)); } break; @@ -3708,7 +3708,7 @@ void PropertyEditor::update_tree() { item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM ); item->set_editable( 1, !read_only ); //item->set_text(1,obj->get(p.name)); - item->set_custom_bg_color(1,obj->get(p.name)); + item->set_custom_draw(1,this,"_draw_transparency"); if (show_type_icons) item->set_icon( 0,get_icon("Color","EditorIcons") ); @@ -3856,6 +3856,25 @@ void PropertyEditor::update_tree() { } } +void PropertyEditor::_draw_transparency(Object *t, const Rect2& p_rect) { + + TreeItem *ti=t->cast_to<TreeItem>(); + if (!ti) + return; + + Color color=obj->get(ti->get_metadata(1)); + Ref<Texture> arrow=tree->get_icon("select_arrow"); + + // make a little space between consecutive color fields + Rect2 area=p_rect; + area.pos.y+=1; + area.size.height-=2; + area.size.width-=arrow->get_size().width+5; + tree->draw_texture_rect(get_icon("Transparent", "EditorIcons"), area, true); + tree->draw_rect(area, color); + +} + void PropertyEditor::_item_selected() { @@ -4366,6 +4385,7 @@ void PropertyEditor::_bind_methods() { ClassDB::bind_method( "update_tree",&PropertyEditor::update_tree); ClassDB::bind_method( "_resource_preview_done",&PropertyEditor::_resource_preview_done); ClassDB::bind_method( "refresh",&PropertyEditor::refresh); + ClassDB::bind_method( "_draw_transparency",&PropertyEditor::_draw_transparency); ClassDB::bind_method(_MD("get_drag_data_fw"), &PropertyEditor::get_drag_data_fw); ClassDB::bind_method(_MD("can_drop_data_fw"), &PropertyEditor::can_drop_data_fw); diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 900d06497f..3f8d071a01 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -245,6 +245,7 @@ friend class ProjectExportDialog; void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from); void _resource_preview_done(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud); + void _draw_transparency(Object *t, const Rect2& p_rect); UndoRedo *undo_redo; protected: |