diff options
-rw-r--r-- | core/ustring.cpp | 15 | ||||
-rw-r--r-- | doc/classes/Tabs.xml | 20 | ||||
-rw-r--r-- | drivers/coreaudio/audio_driver_coreaudio.cpp | 202 | ||||
-rw-r--r-- | drivers/coreaudio/audio_driver_coreaudio.h | 4 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.h | 1 | ||||
-rw-r--r-- | editor/code_editor.cpp | 2 | ||||
-rw-r--r-- | main/tests/test_string.cpp | 173 | ||||
-rw-r--r-- | modules/gdscript/editor/gdscript_highlighter.cpp | 18 | ||||
-rw-r--r-- | modules/visual_script/visual_script.cpp | 20 | ||||
-rw-r--r-- | modules/visual_script/visual_script.h | 1 | ||||
-rw-r--r-- | modules/visual_script/visual_script_nodes.cpp | 14 | ||||
-rw-r--r-- | modules/visual_script/visual_script_property_selector.cpp | 56 | ||||
-rw-r--r-- | platform/android/java_glue.cpp | 2 | ||||
-rw-r--r-- | servers/physics/collision_solver_sw.cpp | 1 |
14 files changed, 395 insertions, 134 deletions
diff --git a/core/ustring.cpp b/core/ustring.cpp index 28bbe1d834..b55607946d 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -586,6 +586,8 @@ String String::camelcase_to_underscore(bool lowercase) const { bool is_upper = cstr[i] >= A && cstr[i] <= Z; bool is_number = cstr[i] >= '0' && cstr[i] <= '9'; bool are_next_2_lower = false; + bool is_next_lower = false; + bool is_next_number = false; bool was_precedent_upper = cstr[i - 1] >= A && cstr[i - 1] <= Z; bool was_precedent_number = cstr[i - 1] >= '0' && cstr[i - 1] <= '9'; @@ -593,7 +595,18 @@ String String::camelcase_to_underscore(bool lowercase) const { are_next_2_lower = cstr[i + 1] >= a && cstr[i + 1] <= z && cstr[i + 2] >= a && cstr[i + 2] <= z; } - bool should_split = ((is_upper && !was_precedent_upper && !was_precedent_number) || (was_precedent_upper && is_upper && are_next_2_lower) || (is_number && !was_precedent_number)); + if (i + 1 < this->size()) { + is_next_lower = cstr[i + 1] >= a && cstr[i + 1] <= z; + is_next_number = cstr[i + 1] >= '0' && cstr[i + 1] <= '9'; + } + + const bool a = is_upper && !was_precedent_upper && !was_precedent_number; + const bool b = was_precedent_upper && is_upper && are_next_2_lower; + const bool c = is_number && !was_precedent_number; + const bool can_break_number_letter = is_number && !was_precedent_number && is_next_lower; + const bool can_break_letter_number = !is_number && was_precedent_number && (is_next_lower || is_next_number); + + bool should_split = a || b || c || can_break_number_letter || can_break_letter_number; if (should_split) { new_string += this->substr(start_index, i - start_index) + "_"; start_index = i; diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml index fc1d0476ed..350b49513d 100644 --- a/doc/classes/Tabs.xml +++ b/doc/classes/Tabs.xml @@ -19,6 +19,7 @@ <argument index="1" name="icon" type="Texture" default="null"> </argument> <description> + Adds a new tab. </description> </method> <method name="ensure_tab_visible"> @@ -27,6 +28,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Moves the Scroll view to make the tab visible. </description> </method> <method name="get_offset_buttons_visible" qualifiers="const"> @@ -39,12 +41,14 @@ <return type="bool"> </return> <description> + Returns [code]true[/code] if select with right mouse button is enabled. </description> </method> <method name="get_tab_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the number of tabs. </description> </method> <method name="get_tab_disabled" qualifiers="const"> @@ -53,6 +57,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is disabled. </description> </method> <method name="get_tab_icon" qualifiers="const"> @@ -61,6 +66,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns the [Texture] for the tab at index [code]tab_idx[/code] or null if the tab has no [Texture]. </description> </method> <method name="get_tab_offset" qualifiers="const"> @@ -84,12 +90,14 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns the title of the tab at index [code]tab_idx[/code]. Tab titles default to the name of the indexed child node, but this can be overridden with [method set_tab_title]. </description> </method> <method name="get_tabs_rearrange_group" qualifiers="const"> <return type="int"> </return> <description> + Returns the [code]Tabs[/code] rearrange group id. </description> </method> <method name="move_tab"> @@ -109,6 +117,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Removes tab at index [code]tab_idx[/code] </description> </method> <method name="set_select_with_rmb"> @@ -117,6 +126,7 @@ <argument index="0" name="enabled" type="bool"> </argument> <description> + If [code]true[/code] enables selecting a tab with right mouse button. </description> </method> <method name="set_tab_disabled"> @@ -127,6 +137,7 @@ <argument index="1" name="disabled" type="bool"> </argument> <description> + If [code]disabled[/code] is false, hides the tab at index [code]tab_idx[/code]. Note that its title text will remain, unless also removed with [method set_tab_title]. </description> </method> <method name="set_tab_icon"> @@ -137,6 +148,7 @@ <argument index="1" name="icon" type="Texture"> </argument> <description> + Sets an icon for the tab at index [code]tab_idx[/code]. </description> </method> <method name="set_tab_title"> @@ -147,6 +159,7 @@ <argument index="1" name="title" type="String"> </argument> <description> + Sets a title for the tab at index [code]tab_idx[/code]. </description> </method> <method name="set_tabs_rearrange_group"> @@ -155,17 +168,21 @@ <argument index="0" name="group_id" type="int"> </argument> <description> + Defines rearrange group id, choose for each [code]Tabs[/code] the same value to enable tab drag between [code]Tabs[/code]. Enable drag with [code]set_drag_to_rearrange_enabled(true)[/code]. </description> </method> </methods> <members> <member name="current_tab" type="int" setter="set_current_tab" getter="get_current_tab"> + Select tab at index [code]tab_idx[/code]. </member> <member name="drag_to_rearrange_enabled" type="bool" setter="set_drag_to_rearrange_enabled" getter="get_drag_to_rearrange_enabled"> + If [code]true[/code], tabs can be rearranged with mouse drag. </member> <member name="scrolling_enabled" type="bool" setter="set_scrolling_enabled" getter="get_scrolling_enabled"> </member> <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="Tabs.TabAlign"> + The alignment of all tabs. See enum [code]TabAlign[/code] constants for details. </member> <member name="tab_close_display_policy" type="int" setter="set_tab_close_display_policy" getter="get_tab_close_display_policy" enum="Tabs.CloseButtonDisplayPolicy"> </member> @@ -210,10 +227,13 @@ </signals> <constants> <constant name="ALIGN_LEFT" value="0" enum="TabAlign"> + Align the tabs to the left. </constant> <constant name="ALIGN_CENTER" value="1" enum="TabAlign"> + Align the tabs to the center. </constant> <constant name="ALIGN_RIGHT" value="2" enum="TabAlign"> + Align the tabs to the right. </constant> <constant name="ALIGN_MAX" value="3" enum="TabAlign"> </constant> diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index cf8fb08f76..aaec63d7ff 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -95,11 +95,6 @@ Error AudioDriverCoreAudio::init() { result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &output_device_address_cb, this); ERR_FAIL_COND_V(result != noErr, FAILED); - - prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; - - result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); - ERR_FAIL_COND_V(result != noErr, FAILED); #endif AudioStreamBasicDescription strdesc; @@ -123,26 +118,6 @@ Error AudioDriverCoreAudio::init() { break; } - zeromem(&strdesc, sizeof(strdesc)); - size = sizeof(strdesc); - result = AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, &size); - ERR_FAIL_COND_V(result != noErr, FAILED); - - switch (strdesc.mChannelsPerFrame) { - case 1: // Mono - capture_channels = 1; - break; - - case 2: // Stereo - capture_channels = 2; - break; - - default: - // Unknown number of channels, default to stereo - capture_channels = 2; - break; - } - mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); zeromem(&strdesc, sizeof(strdesc)); @@ -158,11 +133,6 @@ Error AudioDriverCoreAudio::init() { result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc)); ERR_FAIL_COND_V(result != noErr, FAILED); - strdesc.mChannelsPerFrame = capture_channels; - - result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc)); - ERR_FAIL_COND_V(result != noErr, FAILED); - int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY); // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) buffer_frames = closest_power_of_2(latency * mix_rate / 1000); @@ -189,16 +159,10 @@ Error AudioDriverCoreAudio::init() { result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback)); ERR_FAIL_COND_V(result != noErr, FAILED); - zeromem(&callback, sizeof(AURenderCallbackStruct)); - callback.inputProc = &AudioDriverCoreAudio::input_callback; - callback.inputProcRefCon = this; - result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(callback)); - ERR_FAIL_COND_V(result != noErr, FAILED); - result = AudioUnitInitialize(audio_unit); ERR_FAIL_COND_V(result != noErr, FAILED); - return OK; + return capture_init(); } OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon, @@ -265,7 +229,7 @@ OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon, bufferList.mBuffers[0].mNumberChannels = ad->capture_channels; bufferList.mBuffers[0].mDataByteSize = ad->input_buf.size() * sizeof(int16_t); - OSStatus result = AudioUnitRender(ad->audio_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList); + OSStatus result = AudioUnitRender(ad->input_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList); if (result == noErr) { for (int i = 0; i < inNumberFrames * ad->capture_channels; i++) { int32_t sample = ad->input_buf[i] << 16; @@ -332,6 +296,8 @@ bool AudioDriverCoreAudio::try_lock() { } void AudioDriverCoreAudio::finish() { + capture_finish(); + if (audio_unit) { OSStatus result; @@ -375,6 +341,7 @@ void AudioDriverCoreAudio::finish() { ERR_PRINT("AudioComponentInstanceDispose failed"); } + audio_unit = NULL; unlock(); } @@ -384,20 +351,158 @@ void AudioDriverCoreAudio::finish() { } } -Error AudioDriverCoreAudio::capture_start() { +Error AudioDriverCoreAudio::capture_init() { + AudioComponentDescription desc; + zeromem(&desc, sizeof(desc)); + desc.componentType = kAudioUnitType_Output; +#ifdef OSX_ENABLED + desc.componentSubType = kAudioUnitSubType_HALOutput; +#else + desc.componentSubType = kAudioUnitSubType_RemoteIO; +#endif + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + + AudioComponent comp = AudioComponentFindNext(NULL, &desc); + ERR_FAIL_COND_V(comp == NULL, FAILED); + + OSStatus result = AudioComponentInstanceNew(comp, &input_unit); + ERR_FAIL_COND_V(result != noErr, FAILED); + +#ifdef OSX_ENABLED + AudioObjectPropertyAddress prop; + prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; + prop.mScope = kAudioObjectPropertyScopeGlobal; + prop.mElement = kAudioObjectPropertyElementMaster; + + result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); + ERR_FAIL_COND_V(result != noErr, FAILED); +#endif UInt32 flag = 1; - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); + ERR_FAIL_COND_V(result != noErr, FAILED); + flag = 0; + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + UInt32 size; +#ifdef OSX_ENABLED + AudioDeviceID deviceId; + size = sizeof(AudioDeviceID); + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + + result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, NULL, &size, &deviceId); + ERR_FAIL_COND_V(result != noErr, FAILED); + + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); + ERR_FAIL_COND_V(result != noErr, FAILED); +#endif + + AudioStreamBasicDescription strdesc; + zeromem(&strdesc, sizeof(strdesc)); + size = sizeof(strdesc); + result = AudioUnitGetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, &size); + ERR_FAIL_COND_V(result != noErr, FAILED); + + switch (strdesc.mChannelsPerFrame) { + case 1: // Mono + capture_channels = 1; + break; + + case 2: // Stereo + capture_channels = 2; + break; + + default: + // Unknown number of channels, default to stereo + capture_channels = 2; + break; + } + + mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); + + zeromem(&strdesc, sizeof(strdesc)); + strdesc.mFormatID = kAudioFormatLinearPCM; + strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; + strdesc.mChannelsPerFrame = capture_channels; + strdesc.mSampleRate = mix_rate; + strdesc.mFramesPerPacket = 1; + strdesc.mBitsPerChannel = 16; + strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; + strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; + + result = AudioUnitSetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + AURenderCallbackStruct callback; + zeromem(&callback, sizeof(AURenderCallbackStruct)); + callback.inputProc = &AudioDriverCoreAudio::input_callback; + callback.inputProcRefCon = this; + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &callback, sizeof(callback)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + result = AudioUnitInitialize(input_unit); ERR_FAIL_COND_V(result != noErr, FAILED); return OK; } +void AudioDriverCoreAudio::capture_finish() { + if (input_unit) { + lock(); + + AURenderCallbackStruct callback; + zeromem(&callback, sizeof(AURenderCallbackStruct)); + OSStatus result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(callback)); + if (result != noErr) { + ERR_PRINT("AudioUnitSetProperty failed"); + } + + result = AudioUnitUninitialize(input_unit); + if (result != noErr) { + ERR_PRINT("AudioUnitUninitialize failed"); + } + +#ifdef OSX_ENABLED + AudioObjectPropertyAddress prop; + prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; + prop.mScope = kAudioObjectPropertyScopeGlobal; + prop.mElement = kAudioObjectPropertyElementMaster; + + result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); + if (result != noErr) { + ERR_PRINT("AudioObjectRemovePropertyListener failed"); + } +#endif + + result = AudioComponentInstanceDispose(input_unit); + if (result != noErr) { + ERR_PRINT("AudioComponentInstanceDispose failed"); + } + + input_unit = NULL; + unlock(); + } +} + +Error AudioDriverCoreAudio::capture_start() { + + OSStatus result = AudioOutputUnitStart(input_unit); + if (result != noErr) { + ERR_PRINTS("AudioOutputUnitStart failed, code: " + itos(result)); + } + + return OK; +} + Error AudioDriverCoreAudio::capture_stop() { - UInt32 flag = 0; - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); - ERR_FAIL_COND_V(result != noErr, FAILED); + if (input_unit) { + OSStatus result = AudioOutputUnitStop(input_unit); + if (result != noErr) { + ERR_PRINTS("AudioOutputUnitStop failed, code: " + itos(result)); + } + } return OK; } @@ -531,12 +636,14 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { } if (found) { - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, capture ? kInputBus : kOutputBus, &deviceId, sizeof(AudioDeviceID)); + OSStatus result = AudioUnitSetProperty(capture ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); ERR_FAIL_COND(result != noErr); - // Reset audio input to keep synchronisation. - input_position = 0; - input_size = 0; + if (capture) { + // Reset audio input to keep synchronisation. + input_position = 0; + input_size = 0; + } } } @@ -580,6 +687,7 @@ String AudioDriverCoreAudio::capture_get_device() { AudioDriverCoreAudio::AudioDriverCoreAudio() { audio_unit = NULL; + input_unit = NULL; active = false; mutex = NULL; diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index d3f7c8d596..474a9e43ae 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -43,6 +43,7 @@ class AudioDriverCoreAudio : public AudioDriver { AudioComponentInstance audio_unit; + AudioComponentInstance input_unit; bool active; Mutex *mutex; @@ -83,6 +84,9 @@ class AudioDriverCoreAudio : public AudioDriver { UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); + Error capture_init(); + void capture_finish(); + public: const char *get_name() const { return "CoreAudio"; diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index b42e2dfb1f..c928f753b1 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -43,7 +43,6 @@ /* #include "shaders/blend_shape.glsl.gen.h" #include "shaders/canvas.glsl.gen.h" -#include "shaders/copy.glsl.gen.h" #include "shaders/particles.glsl.gen.h" */ diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 79c22f667a..aeb304d3b9 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1039,6 +1039,8 @@ void CodeTextEditor::delete_lines() { int to_line = text_editor->get_selection_to_line(); int from_line = text_editor->get_selection_from_line(); int count = Math::abs(to_line - from_line) + 1; + + text_editor->cursor_set_line(to_line, false); while (count) { text_editor->set_line(text_editor->cursor_get_line(), ""); text_editor->backspace_at_cursor(); diff --git a/main/tests/test_string.cpp b/main/tests/test_string.cpp index 74157d63c9..7e19c7bf3e 100644 --- a/main/tests/test_string.cpp +++ b/main/tests/test_string.cpp @@ -480,7 +480,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish % frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; //////// INTS @@ -491,7 +491,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int left padded with zeroes. format = "fish %05d frog"; @@ -500,7 +500,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 00005 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int left padded with spaces. format = "fish %5d frog"; @@ -509,7 +509,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int right padded with spaces. format = "fish %-5d frog"; @@ -518,7 +518,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int with sign (positive). format = "fish %+d frog"; @@ -527,7 +527,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish +5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Negative int. format = "fish %d frog"; @@ -536,7 +536,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish -5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Hex (lower) format = "fish %x frog"; @@ -545,7 +545,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 2d frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Hex (upper) format = "fish %X frog"; @@ -554,7 +554,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 2D frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Octal format = "fish %o frog"; @@ -563,7 +563,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 143 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ////// REALS @@ -574,7 +574,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real left-padded format = "fish %11f frog"; @@ -583,7 +583,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real right-padded format = "fish %-11f frog"; @@ -592,7 +592,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real given int. format = "fish %f frog"; @@ -601,7 +601,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.000000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with sign (positive). format = "fish %+f frog"; @@ -610,7 +610,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish +99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with 1 decimals. format = "fish %.1f frog"; @@ -619,7 +619,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 100.0 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with 12 decimals. format = "fish %.12f frog"; @@ -628,7 +628,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000000000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with no decimals. format = "fish %.f frog"; @@ -637,7 +637,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 100 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; /////// Strings. @@ -648,7 +648,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // String left-padded format = "fish %10s frog"; @@ -657,7 +657,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // String right-padded format = "fish %-10s frog"; @@ -666,7 +666,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Characters @@ -677,7 +677,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish A frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character as int. format = "fish %c frog"; @@ -686,7 +686,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish A frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Dynamic width @@ -698,7 +698,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int dynamic width format = "fish %*d frog"; @@ -708,7 +708,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Float dynamic width format = "fish %*.*f frog"; @@ -719,7 +719,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Errors @@ -730,7 +730,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "not enough arguments for format string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // More arguments than formats. format = "fish %s frog"; @@ -740,7 +740,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "not all arguments converted during string formatting" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Incomplete format. format = "fish %10"; @@ -749,7 +749,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "incomplete format" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Bad character in format string format = "fish %&f frog"; @@ -758,7 +758,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "unsupported format character" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Too many decimals. format = "fish %2.2.2f frog"; @@ -767,7 +767,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "too many decimal points in format" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // * not a number format = "fish %*f frog"; @@ -777,7 +777,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "* wants number" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character too long. format = "fish %c frog"; @@ -786,7 +786,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "%c requires number or single-character string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character bad type. format = "fish %c frog"; @@ -795,7 +795,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "%c requires number or single-character string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; return state; } @@ -819,37 +819,127 @@ bool test_29() { String ip4 = "192.168.0.1"; bool success = ip4.is_valid_ip_address(); OS::get_singleton()->print("Is valid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip4 = "192.368.0.1"; success = (!ip4.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; String ip6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; success = ip6.is_valid_ip_address(); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8:85j3:0000:0000:8a2e:0370:7334"; success = (!ip6.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8:85f345:0000:0000:8a2e:0370:7334"; success = (!ip6.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8::0:8a2e:370:7334"; success = (ip6.is_valid_ip_address()); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "::ffff:192.168.0.1"; success = (ip6.is_valid_ip_address()); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; + + return state; +}; + +bool test_30() { + bool state = true; + bool success = true; + String input = "bytes2var"; + String output = "Bytes 2 Var"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "linear2db"; + output = "Linear 2 Db"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "vector3"; + output = "Vector 3"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "sha256"; + output = "Sha 256"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "2db"; + output = "2 Db"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "PascalCase"; + output = "Pascal Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "PascalPascalCase"; + output = "Pascal Pascal Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case"; + output = "Snake Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_snake_case"; + output = "Snake Snake Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "sha256sum"; + output = "Sha 256 Sum"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "cat2dog"; + output = "Cat 2 Dog"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "function(name)"; + output = "Function(name)"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls (existing incorrect behavior): %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case_function(snake_case_arg)"; + output = "Snake Case Function(snake Case Arg)"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls (existing incorrect behavior): %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case_function( snake_case_arg )"; + output = "Snake Case Function( Snake Case Arg )"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); return state; }; @@ -887,6 +977,7 @@ TestFunc test_funcs[] = { test_27, test_28, test_29, + test_30, 0 }; diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index c199667270..e4aee842ba 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -72,6 +72,7 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ bool in_word = false; bool in_function_name = false; bool in_variable_declaration = false; + bool in_function_args = false; bool in_member_variable = false; bool in_node_path = false; bool is_hex_notation = false; @@ -220,17 +221,24 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } if (is_symbol) { - in_function_name = false; - in_member_variable = false; - if (expect_type && str[j] != ' ' && str[j] != '\t' && str[j] != ':') { + if (in_function_name) { + in_function_args = true; + } + + if (in_function_args && str[j] == ')') { + in_function_args = false; + } + + if (expect_type && prev_is_char) { expect_type = false; } + if (j > 0 && str[j] == '>' && str[j - 1] == '-') { expect_type = true; } - if (in_variable_declaration || previous_text == "(" || previous_text == ",") { + if (in_variable_declaration || in_function_args) { int k = j; // Skip space while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) { @@ -244,6 +252,8 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } in_variable_declaration = false; + in_function_name = false; + in_member_variable = false; } if (!in_node_path && in_region == -1 && str[j] == '$') { diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index ff97c21fd9..52a30baaec 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -48,20 +48,22 @@ bool VisualScriptNode::is_breakpoint() const { void VisualScriptNode::_notification(int p_what) { if (p_what == NOTIFICATION_POSTINITIALIZE) { - - int dvc = get_input_value_port_count(); - for (int i = 0; i < dvc; i++) { - Variant::Type expected = get_input_value_port_info(i).type; - Variant::CallError ce; - default_input_values.push_back(Variant::construct(expected, NULL, 0, ce, false)); - } + _update_input_ports(); } } -void VisualScriptNode::ports_changed_notify() { - +void VisualScriptNode::_update_input_ports() { default_input_values.resize(MAX(default_input_values.size(), get_input_value_port_count())); //let it grow as big as possible, we don't want to lose values on resize + int port_count = get_input_value_port_count(); + for (int i = 0; i < port_count; i++) { + Variant::Type expected = get_input_value_port_info(i).type; + Variant::CallError ce; + set_default_input_value(i, Variant::construct(expected, NULL, 0, ce, false)); + } +} +void VisualScriptNode::ports_changed_notify() { + _update_input_ports(); emit_signal("ports_changed"); } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index ea99ce4970..bd666447a3 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -52,6 +52,7 @@ class VisualScriptNode : public Resource { Array _get_default_input_values() const; void validate_input_default_values(); + void _update_input_ports(); protected: void _notification(int p_what); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 865f93a148..99748af8a1 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -3708,18 +3708,18 @@ void register_visual_script_nodes() { for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) { if (E->get().arguments.size() > 0) { - - String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + " ( "; + String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + "("; for (int j = 0; j < E->get().arguments.size(); j++) { - if (j > 0) + if (j > 0) { name += ", "; - if (E->get().arguments.size() == 1) + } + if (E->get().arguments.size() == 1) { name += Variant::get_type_name(E->get().arguments[j].type); - else + } else { name += E->get().arguments[j].name; + } } - name += ") "; - + name += ")"; VisualScriptLanguage::singleton->add_register_func(name, create_constructor_node); Pair<Variant::Type, MethodInfo> pair; pair.first = Variant::Type(i); diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index d3637939c9..e5d12cb495 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -304,31 +304,36 @@ void VisualScriptPropertySelector::_update_search() { continue; MethodInfo mi = E->get(); - String desc = mi.name.capitalize() + " ("; + String desc_arguments; + if (mi.arguments.size() > 0) { + desc_arguments = "("; + for (int i = 0; i < mi.arguments.size(); i++) { + + if (i > 0) { + desc_arguments += ", "; + } + if (mi.arguments[i].type == Variant::NIL) { + desc_arguments += "var"; + } else if (mi.arguments[i].name.find(":") != -1) { + desc_arguments += mi.arguments[i].name.get_slice(":", 1); + mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); + } else { + desc_arguments += Variant::get_type_name(mi.arguments[i].type); + } + } + desc_arguments += ")"; + } + String desc_raw = mi.name + desc_arguments; + String desc = desc_raw.capitalize().replace("( ", "("); if (search_box->get_text() != String() && name.findn(search_box->get_text()) == -1 && - desc.findn(search_box->get_text()) == -1) + desc.findn(search_box->get_text()) == -1 && + desc_raw.findn(search_box->get_text()) == -1) { continue; - - TreeItem *item = search_options->create_item(category ? category : root); - - for (int i = 0; i < mi.arguments.size(); i++) { - - if (i > 0) - desc += ", "; - - if (mi.arguments[i].type == Variant::NIL) - desc += "var"; - else if (mi.arguments[i].name.find(":") != -1) { - desc += mi.arguments[i].name.get_slice(":", 1); - mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); - } else - desc += Variant::get_type_name(mi.arguments[i].type); } - desc += ")"; - + TreeItem *item = search_options->create_item(category ? category : root); item->set_text(0, desc); item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); item->set_metadata(0, name); @@ -414,11 +419,16 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt String basic_type = Variant::get_type_name(vnode_function_call->get_basic_type()); type_name = basic_type.capitalize() + " "; } - VisualScriptBuiltinFunc *vnode_builtin_function_call = Object::cast_to<VisualScriptBuiltinFunc>(*VisualScriptLanguage::singleton->create_node_from_name(E->get())); - if (vnode_builtin_function_call != NULL) { - type_name = "Builtin "; + + Vector<String> desc = path[path.size() - 1].replace("(", "( ").replace(")", " )").replace(",", ", ").split(" "); + for (size_t i = 0; i < desc.size(); i++) { + desc.write[i] = desc[i].capitalize(); + if (desc[i].ends_with(",")) { + desc.write[i] = desc[i].replace(",", ", "); + } } - item->set_text(0, type_name + path[path.size() - 1].capitalize()); + + item->set_text(0, type_name + String("").join(desc)); item->set_icon(0, get_icon("VisualScript", "EditorIcons")); item->set_selectable(0, true); item->set_metadata(0, E->get()); diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index ad8f21785d..07e4048c12 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -883,6 +883,8 @@ static void _initialize_java_modules() { ERR_EXPLAIN("Couldn't find proper initialize function 'public static Godot.SingletonBase Class::initialize(Activity p_activity)' initializer for singleton class: " + m); ERR_CONTINUE(!initialize); } + jobject obj = env->CallStaticObjectMethod(singletonClass, initialize, _godot_instance); + env->NewGlobalRef(obj); } } } diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index 2f2f6d2908..86ef719f6f 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -31,7 +31,6 @@ #include "collision_solver_sw.h" #include "collision_solver_sat.h" -#include "collision_solver_sat.h" #include "gjk_epa.h" #define collision_solver sat_calculate_penetration |