Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from godotengine:master #149

Merged
merged 28 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
eb5839d
Add "At Start" mode for sub-emitter particles
YeldhamDev Dec 4, 2024
db63d3e
Prevent WASAPI error spam when device cannot be initialized.
allenwp Dec 6, 2024
9db804f
Jsonrpc: Convert ids to int if they are int by value
HolonProduction Dec 30, 2024
a7520fc
Add functions to get axis-aligned bounds of navigation regions
smix8 Jan 11, 2025
e6daec9
Added indirect drawing functionality to MultiMesh
Bonkahe Nov 19, 2024
cb9ee09
Android: Implement support for native dialog
syntaxerror247 Jan 3, 2025
5608f65
KTX: Add support for loading most ETC-compressed formats
BlueCube3310 Dec 17, 2024
1d2c503
Fix regression from already disconnected emission shape changed signal
paddy-exe Jan 14, 2025
2e99d84
[DisplayServer] Add missing `FEATURE_WINDOW_DRAG` flag to Windows, X1…
bruvzg Jan 14, 2025
85b066a
Merge pull request #99455 from Bonkahe/IndirectMultimeshImplementation
akien-mga Jan 14, 2025
488ee4f
Merge pull request #100950 from HolonProduction/this-time-we-are-spec…
akien-mga Jan 14, 2025
4d1cfc1
Merge pull request #101061 from syntaxerror247/first-pr-2025
akien-mga Jan 14, 2025
a69ccee
Merge pull request #101505 from smix8/region_bounds
akien-mga Jan 14, 2025
e813d30
Show tooltips for res:// and uid:// strings in ScriptEditor
larspet Dec 25, 2024
e33a95f
Always pick widest style as min width between unselected and hovered …
YeldhamDev Jan 14, 2025
ebf9681
Add Show in FileSystem right click option to SpriteFrames
Arnklit Dec 11, 2024
21fcb56
Remove unused `EditorSceneFormatImporter::_get_import_flags`
akien-mga Jan 14, 2025
1e1f54e
Merge pull request #100050 from YeldhamDev/sub_emitter_at_start
akien-mga Jan 14, 2025
9d2798d
Merge pull request #100116 from allenwp/prevent-wasapi-error-spam
akien-mga Jan 14, 2025
3394988
Merge pull request #100276 from Arnklit/spriteframes-show-in-filesystem
akien-mga Jan 14, 2025
e67e8b8
Merge pull request #100524 from BlueCube3310/ktx-etc
akien-mga Jan 14, 2025
19bb441
Merge pull request #100803 from larspet/uid-tooltip
akien-mga Jan 14, 2025
67f54bd
Merge pull request #101531 from akien-mga/scene-import-remove-unused-…
akien-mga Jan 14, 2025
ddd4527
Merge pull request #101537 from paddy-exe/fix-emission-shape-signal-r…
akien-mga Jan 14, 2025
f8724e4
Merge pull request #101538 from bruvzg/wdrag_ftr
akien-mga Jan 14, 2025
efbcfb9
Merge pull request #101541 from YeldhamDev/tab_width_fix
akien-mga Jan 14, 2025
6d3e66b
Bump version to 4.4-beta
akien-mga Jan 14, 2025
4ce466d
Merge pull request #101552 from akien-mga/4.4-beta-feature-freeze
akien-mga Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/classes/DisplayServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
<param index="3" name="callback" type="Callable" />
<description>
Shows a text dialog which uses the operating system's native look-and-feel. [param callback] should accept a single [int] parameter which corresponds to the index of the pressed button.
[b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG] feature. Supported platforms include macOS and Windows.
[b]Note:[/b] This method is implemented if the display server has the [constant FEATURE_NATIVE_DIALOG] feature. Supported platforms include macOS, Windows, and Android.
</description>
</method>
<method name="enable_for_stealing_focus">
Expand Down Expand Up @@ -1937,7 +1937,7 @@
The display server supports all features of [constant FEATURE_NATIVE_DIALOG_FILE], with the added functionality of Options and native dialog file access to [code]res://[/code] and [code]user://[/code] paths. See [method file_dialog_show] and [method file_dialog_with_options_show]. [b]Windows, macOS, Linux (X11/Wayland)[/b]
</constant>
<constant name="FEATURE_WINDOW_DRAG" value="27" enum="Feature">
The display server supports initiating window drag operation on demand. See [method window_start_drag].
The display server supports initiating window drag and resize operations on demand. See [method window_start_drag] and [method window_start_resize].
</constant>
<constant name="FEATURE_SCREEN_EXCLUDE_FROM_CAPTURE" value="28" enum="Feature">
Display server supports [constant WINDOW_FLAG_EXCLUDE_FROM_CAPTURE] window flag.
Expand Down
5 changes: 0 additions & 5 deletions doc/classes/EditorSceneFormatImporter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@
Return supported file extensions for this scene importer.
</description>
</method>
<method name="_get_import_flags" qualifiers="virtual const" deprecated="Unused by the engine, and will be removed in a future version. Implementing this has no effect.">
<return type="int" />
<description>
</description>
</method>
<method name="_get_import_options" qualifiers="virtual">
<return type="void" />
<param index="0" name="path" type="String" />
Expand Down
6 changes: 6 additions & 0 deletions doc/classes/NavigationRegion2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
Bakes the [NavigationPolygon]. If [param on_thread] is set to [code]true[/code] (default), the baking is done on a separate thread.
</description>
</method>
<method name="get_bounds" qualifiers="const">
<return type="Rect2" />
<description>
Returns the axis-aligned rectangle for the region's transformed navigation mesh.
</description>
</method>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
Expand Down
6 changes: 6 additions & 0 deletions doc/classes/NavigationRegion3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
Bakes the [NavigationMesh]. If [param on_thread] is set to [code]true[/code] (default), the baking is done on a separate thread. Baking on separate thread is useful because navigation baking is not a cheap operation. When it is completed, it automatically sets the new [NavigationMesh]. Please note that baking on separate thread may be very slow if geometry is parsed from meshes as async access to each mesh involves heavy synchronization. Also, please note that baking on a separate thread is automatically disabled on operating systems that cannot use threads (such as Web with threads disabled).
</description>
</method>
<method name="get_bounds" qualifiers="const">
<return type="AABB" />
<description>
Returns the axis-aligned bounding box for the region's transformed navigation mesh.
</description>
</method>
<method name="get_navigation_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/NavigationServer2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,13 @@
Creates a new region.
</description>
</method>
<method name="region_get_bounds" qualifiers="const">
<return type="Rect2" />
<param index="0" name="region" type="RID" />
<description>
Returns the axis-aligned rectangle for the [param region]'s transformed navigation mesh.
</description>
</method>
<method name="region_get_closest_point" qualifiers="const">
<return type="Vector2" />
<param index="0" name="region" type="RID" />
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/NavigationServer3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,13 @@
Creates a new region.
</description>
</method>
<method name="region_get_bounds" qualifiers="const">
<return type="AABB" />
<param index="0" name="region" type="RID" />
<description>
Returns the axis-aligned bounding box for the [param region]'s transformed navigation mesh.
</description>
</method>
<method name="region_get_closest_point" qualifiers="const">
<return type="Vector3" />
<param index="0" name="region" type="RID" />
Expand Down
8 changes: 7 additions & 1 deletion doc/classes/ParticleProcessMaterial.xml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@
The amount of particles to spawn from the subemitter node when the particle expires.
[b]Note:[/b] This value shouldn't exceed [member GPUParticles2D.amount] or [member GPUParticles3D.amount] defined on the [i]subemitter node[/i] (not the main node), relative to the subemitter's particle lifetime. If the number of particles is exceeded, no new particles will spawn from the subemitter until enough particles have expired.
</member>
<member name="sub_emitter_amount_at_start" type="int" setter="set_sub_emitter_amount_at_start" getter="get_sub_emitter_amount_at_start">
The amount of particles to spawn from the subemitter node when the particle spawns.
[b]Note:[/b] This value shouldn't exceed [member GPUParticles2D.amount] or [member GPUParticles3D.amount] defined on the [i]subemitter node[/i] (not the main node), relative to the subemitter's particle lifetime. If the number of particles is exceeded, no new particles will spawn from the subemitter until enough particles have expired.
</member>
<member name="sub_emitter_frequency" type="float" setter="set_sub_emitter_frequency" getter="get_sub_emitter_frequency">
The frequency at which particles should be emitted from the subemitter node. One particle will be spawned every [member sub_emitter_frequency] seconds.
[b]Note:[/b] This value shouldn't exceed [member GPUParticles2D.amount] or [member GPUParticles3D.amount] defined on the [i]subemitter node[/i] (not the main node), relative to the subemitter's particle lifetime. If the number of particles is exceeded, no new particles will spawn from the subemitter until enough particles have expired.
Expand Down Expand Up @@ -521,7 +525,9 @@
</constant>
<constant name="SUB_EMITTER_AT_COLLISION" value="3" enum="SubEmitterMode">
</constant>
<constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode">
<constant name="SUB_EMITTER_AT_START" value="4" enum="SubEmitterMode">
</constant>
<constant name="SUB_EMITTER_MAX" value="5" enum="SubEmitterMode">
Represents the size of the [enum SubEmitterMode] enum.
</constant>
<constant name="COLLISION_DISABLED" value="0" enum="CollisionMode">
Expand Down
24 changes: 24 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2559,6 +2559,7 @@
<param index="2" name="transform_format" type="int" enum="RenderingServer.MultimeshTransformFormat" />
<param index="3" name="color_format" type="bool" default="false" />
<param index="4" name="custom_data_format" type="bool" default="false" />
<param index="5" name="use_indirect" type="bool" default="false" />
<description>
</description>
</method>
Expand Down Expand Up @@ -2593,6 +2594,29 @@
Returns the [RenderingDevice] [RID] handle of the [MultiMesh], which can be used as any other buffer on the Rendering Device.
</description>
</method>
<method name="multimesh_get_command_buffer_rd_rid" qualifiers="const">
<return type="RID" />
<param index="0" name="multimesh" type="RID" />
<description>
Returns the [RenderingDevice] [RID] handle of the [MultiMesh] command buffer. This [RID] is only valid if [code]use_indirect[/code] is set to [code]true[/code] when allocating data through [method multimesh_allocate_data]. It can be used to directly modify the instance count via buffer.
The data structure is dependent on both how many surfaces the mesh contains and whether it is indexed or not, the buffer has 5 integers in it, with the last unused if the mesh is not indexed.
Each of the values in the buffer correspond to these options:
[codeblock lang=text]
Indexed:
0 - indexCount;
1 - instanceCount;
2 - firstIndex;
3 - vertexOffset;
4 - firstInstance;
Non Indexed:
0 - vertexCount;
1 - instanceCount;
2 - firstVertex;
3 - firstInstance;
4 - unused;
[/codeblock]
</description>
</method>
<method name="multimesh_get_custom_aabb" qualifiers="const">
<return type="AABB" />
<param index="0" name="multimesh" type="RID" />
Expand Down
6 changes: 5 additions & 1 deletion drivers/gles3/storage/mesh_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1518,7 +1518,7 @@ void MeshStorage::_multimesh_free(RID p_rid) {
multimesh_owner.free(p_rid);
}

void MeshStorage::_multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
void MeshStorage::_multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data, bool p_use_indirect) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);

Expand Down Expand Up @@ -2041,6 +2041,10 @@ void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_
}
}

RID MeshStorage::_multimesh_get_command_buffer_rd_rid(RID p_multimesh) const {
ERR_FAIL_V_MSG(RID(), "GLES3 does not implement indirect multimeshes.");
}

RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const {
ERR_FAIL_V_MSG(RID(), "GLES3 does not contain a Rid for the multimesh buffer.");
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/gles3/storage/mesh_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ class MeshStorage : public RendererMeshStorage {
virtual RID _multimesh_allocate() override;
virtual void _multimesh_initialize(RID p_rid) override;
virtual void _multimesh_free(RID p_rid) override;
virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) override;
virtual int _multimesh_get_instance_count(RID p_multimesh) const override;

virtual void _multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
Expand All @@ -521,6 +521,7 @@ class MeshStorage : public RendererMeshStorage {
virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const override;
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override;
virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const override;

Expand Down
93 changes: 78 additions & 15 deletions drivers/wasapi/audio_driver_wasapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);

static bool default_output_device_changed = false;
static bool default_input_device_changed = false;
static int output_reinit_countdown = 0;
static int input_reinit_countdown = 0;

// Silence warning due to a COM API weirdness (GH-35194).
#if defined(__GNUC__) && !defined(__clang__)
Expand All @@ -134,6 +136,8 @@ class CMMNotificationClient : public IMMNotificationClient {
LONG _cRef = 1;

public:
ComPtr<IMMDeviceEnumerator> enumerator = nullptr;

CMMNotificationClient() {}
virtual ~CMMNotificationClient() {}

Expand Down Expand Up @@ -199,6 +203,9 @@ class CMMNotificationClient : public IMMNotificationClient {
static CMMNotificationClient notif_client;

Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_input, bool p_reinit, bool p_no_audio_client_3) {
// This function can be called recursively, so clean up before starting:
audio_device_finish(p_device);

WAVEFORMATEX *pwfex;
ComPtr<IMMDeviceEnumerator> enumerator = nullptr;
ComPtr<IMMDevice> output_device = nullptr;
Expand All @@ -225,21 +232,25 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
ComPtr<IMMDevice> tmp_device = nullptr;

hr = devices->Item(i, &tmp_device);
ERR_BREAK(hr != S_OK);
ERR_BREAK_MSG(hr != S_OK, "Cannot get devices item.");

ComPtr<IPropertyStore> props = nullptr;
hr = tmp_device->OpenPropertyStore(STGM_READ, &props);
ERR_BREAK(hr != S_OK);
ERR_BREAK_MSG(hr != S_OK, "Cannot open property store.");

PROPVARIANT propvar;
PropVariantInit(&propvar);

hr = props->GetValue(PKEY_Device_FriendlyNameGodot, &propvar);
ERR_BREAK(hr != S_OK);
ERR_BREAK_MSG(hr != S_OK, "Cannot get value.");

if (p_device->device_name == String(propvar.pwszVal)) {
hr = tmp_device->GetId(&strId);
ERR_BREAK(hr != S_OK);
if (unlikely(hr != S_OK)) {
PropVariantClear(&propvar);
ERR_PRINT("Cannot get device ID string.");
break;
}

found = true;
}
Expand Down Expand Up @@ -270,9 +281,14 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
}

if (notif_client.enumerator != nullptr) {
notif_client.enumerator->UnregisterEndpointNotificationCallback(&notif_client);
notif_client.enumerator = nullptr;
}
hr = enumerator->RegisterEndpointNotificationCallback(&notif_client);

if (hr != S_OK) {
if (hr == S_OK) {
notif_client.enumerator = enumerator;
} else {
ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error");
}

Expand Down Expand Up @@ -317,6 +333,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i

hr = p_device->audio_client->GetMixFormat(&pwfex);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
// From this point onward, CoTaskMemFree(pwfex) must be called before returning or pwfex will leak!

print_verbose("WASAPI: wFormatTag = " + itos(pwfex->wFormatTag));
print_verbose("WASAPI: nChannels = " + itos(pwfex->nChannels));
Expand All @@ -340,6 +357,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
print_verbose("WASAPI: closest->cbSize = " + itos(closest->cbSize));

WARN_PRINT("WASAPI: Using closest match instead");
CoTaskMemFree(pwfex);
pwfex = closest;
}
}
Expand All @@ -359,11 +377,13 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
p_device->format_tag = WAVE_FORMAT_IEEE_FLOAT;
} else {
ERR_PRINT("WASAPI: Format not supported");
CoTaskMemFree(pwfex);
ERR_FAIL_V(ERR_CANT_OPEN);
}
} else {
if (p_device->format_tag != WAVE_FORMAT_PCM && p_device->format_tag != WAVE_FORMAT_IEEE_FLOAT) {
ERR_PRINT("WASAPI: Format not supported");
CoTaskMemFree(pwfex);
ERR_FAIL_V(ERR_CANT_OPEN);
}
}
Expand All @@ -376,10 +396,28 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8);
}
hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_input ? REFTIMES_PER_SEC : 0, 0, pwfex, nullptr);
ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + ".");

if (p_reinit) {
// In case we're trying to re-initialize the device, prevent throwing this error on the console,
// otherwise if there is currently no device available this will spam the console.
if (hr != S_OK) {
print_verbose("WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + ".");
CoTaskMemFree(pwfex);
return ERR_CANT_OPEN;
}
} else {
if (unlikely(hr != S_OK)) {
CoTaskMemFree(pwfex);
ERR_FAIL_V_MSG(ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + ".");
}
}

UINT32 max_frames;
hr = p_device->audio_client->GetBufferSize(&max_frames);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
if (unlikely(hr != S_OK)) {
CoTaskMemFree(pwfex);
ERR_FAIL_V(ERR_CANT_OPEN);
}

// Due to WASAPI Shared Mode we have no control of the buffer size
if (!p_input) {
Expand Down Expand Up @@ -453,7 +491,10 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
} else {
hr = p_device->audio_client->GetService(IID_IAudioRenderClient, (void **)&p_device->render_client);
}
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
if (unlikely(hr != S_OK)) {
CoTaskMemFree(pwfex);
ERR_FAIL_V(ERR_CANT_OPEN);
}

// Free memory
CoTaskMemFree(pwfex);
Expand All @@ -464,6 +505,11 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
Error AudioDriverWASAPI::init_output_device(bool p_reinit) {
Error err = audio_device_init(&audio_output, false, p_reinit);
if (err != OK) {
// We've tried to init the device, but have failed. Time to clean up.
Error finish_err = finish_output_device();
if (finish_err != OK) {
ERR_PRINT("WASAPI: finish_output_device error after failed output audio_device_init");
}
return err;
}

Expand Down Expand Up @@ -504,6 +550,11 @@ Error AudioDriverWASAPI::init_output_device(bool p_reinit) {
Error AudioDriverWASAPI::init_input_device(bool p_reinit) {
Error err = audio_device_init(&audio_input, true, p_reinit);
if (err != OK) {
// We've tried to init the device, but have failed. Time to clean up.
Error finish_err = finish_input_device();
if (finish_err != OK) {
ERR_PRINT("WASAPI: finish_input_device error after failed input audio_device_init");
}
return err;
}

Expand Down Expand Up @@ -826,9 +877,15 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
}

if (!ad->audio_output.audio_client) {
Error err = ad->init_output_device(true);
if (err == OK) {
ad->start();
if (output_reinit_countdown < 1) {
Error err = ad->init_output_device(true);
if (err == OK) {
ad->start();
} else {
output_reinit_countdown = 1000;
}
} else {
output_reinit_countdown--;
}

avail_frames = 0;
Expand Down Expand Up @@ -899,9 +956,15 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
}

if (!ad->audio_input.audio_client) {
Error err = ad->init_input_device(true);
if (err == OK) {
ad->input_start();
if (input_reinit_countdown < 1) {
Error err = ad->init_input_device(true);
if (err == OK) {
ad->input_start();
} else {
input_reinit_countdown = 1000;
}
} else {
input_reinit_countdown--;
}
}
}
Expand Down
Loading