diff --git a/addons/lod/LICENSE.md b/addons/lod/LICENSE.md
new file mode 100644
index 0000000..149ba76
--- /dev/null
+++ b/addons/lod/LICENSE.md
@@ -0,0 +1,21 @@
+# MIT License
+
+Copyright © 2020 Hugo Locurcio and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/addons/lod/lod_cpu_particles.gd b/addons/lod/lod_cpu_particles.gd
new file mode 100644
index 0000000..e9c381e
--- /dev/null
+++ b/addons/lod/lod_cpu_particles.gd
@@ -0,0 +1,59 @@
+# Copyright © 2020 Hugo Locurcio and contributors - MIT License
+# See `LICENSE.md` included in the source distribution for details.
+extends CPUParticles
+class_name LODCPUParticles, "lod_cpu_particles.svg"
+
+# If `false`, LOD won't update anymore. This can be used for performance comparison
+# purposes.
+export var enable_lod := true
+
+# The maximum particle emitting distance in units. Past this distance, particles will no longer emit.
+export(float, 0.0, 1000.0, 0.1) var max_emit_distance := 50
+
+# The rate at which LODs will be updated (in seconds). Lower values are more reactive
+# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
+# Set this accordingly depending on your camera movement speed.
+# The default value should suit most projects already.
+# Note: Slow cameras don't need to have LOD-enabled objects update their status often.
+# This can overridden by setting the project setting `lod/refresh_rate`.
+var refresh_rate := 0.25
+
+# The LOD bias in units.
+# Positive values will decrease the detail level and improve performance.
+# Negative values will improve visual appearance at the cost of performance.
+# This can overridden by setting the project setting `lod/bias`.
+var lod_bias := 0.0
+
+# The internal refresh timer.
+var timer := 0.0
+
+
+func _ready() -> void:
+ if ProjectSettings.has_setting("lod/particle_bias"):
+ lod_bias = ProjectSettings.get_setting("lod/particle_bias")
+ if ProjectSettings.has_setting("lod/refresh_rate"):
+ refresh_rate = ProjectSettings.get_setting("lod/refresh_rate")
+
+ # Add random jitter to the timer to ensure LODs don't all swap at the same time.
+ randomize()
+ timer += rand_range(0, refresh_rate)
+
+# Despite LOD not being related to physics, we chose to run in `_physics_process()`
+# to minimize the amount of method calls per second (and therefore decrease CPU usage).
+func _physics_process(delta: float) -> void:
+ if not enable_lod:
+ return
+
+ # We need a camera to do the rest.
+ var camera := get_viewport().get_camera()
+ if camera == null:
+ return
+
+ if timer <= refresh_rate:
+ timer += delta
+ return
+
+ timer = 0.0
+
+ var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias
+ emitting = distance < max_emit_distance
diff --git a/addons/lod/lod_cpu_particles.svg b/addons/lod/lod_cpu_particles.svg
new file mode 100644
index 0000000..1972584
--- /dev/null
+++ b/addons/lod/lod_cpu_particles.svg
@@ -0,0 +1 @@
+
diff --git a/addons/lod/lod_cpu_particles.svg.import b/addons/lod/lod_cpu_particles.svg.import
new file mode 100644
index 0000000..242227c
--- /dev/null
+++ b/addons/lod/lod_cpu_particles.svg.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/lod_cpu_particles.svg-b3ece84e0440c5d32851b9105345db21.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/lod/lod_cpu_particles.svg"
+dest_files=[ "res://.import/lod_cpu_particles.svg-b3ece84e0440c5d32851b9105345db21.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=0
+flags/filter=true
+flags/mipmaps=false
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+stream=false
+size_limit=0
+detect_3d=true
+svg/scale=1.0
diff --git a/addons/lod/lod_omni_light.gd b/addons/lod/lod_omni_light.gd
new file mode 100644
index 0000000..1db23ee
--- /dev/null
+++ b/addons/lod/lod_omni_light.gd
@@ -0,0 +1,92 @@
+# Copyright © 2020 Hugo Locurcio and contributors - MIT License
+# See `LICENSE.md` included in the source distribution for details.
+extends OmniLight
+class_name LODOmniLight, "lod_omni_light.svg"
+
+# If `false`, LOD won't update anymore. This can be used for performance comparison
+# purposes.
+export var enable_lod := true
+
+# The maximum shadow distance in units. Past this distance, the shadow will be disabled.
+export(float, 0.0, 1000.0, 0.1) var shadow_max_distance := 25
+
+# The distance factor at which the shadow starts fading.
+# A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading.
+export(float, 0.0, 1.0, 0.1) var shadow_fade_start := 0.8
+
+# The maximum shadow distance in units. Past this distance, the light will be hidden.
+export(float, 0.0, 1000.0, 0.1) var light_max_distance := 50
+
+# The distance factor at which the light starts fading.
+# A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading.
+export(float, 0.0, 1.0, 0.1) var light_fade_start := 0.8
+
+# The rate at which LODs will be updated (in seconds). Lower values are more reactive
+# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
+# Set this accordingly depending on your camera movement speed.
+# The default value should suit most projects already.
+# Note: Slow cameras don't need to have LOD-enabled objects update their status often.
+# By default, lights have their LOD updated faster than other LOD nodes since their
+# light/shadow intensity needs to change as smoothly as posible.
+# This can overridden by setting the project setting `lod/light_refresh_rate`.
+var refresh_rate := 0.05
+
+# The LOD bias in units.
+# Positive values will decrease the detail level and improve performance.
+# Negative values will improve visual appearance at the cost of performance.
+# This can overridden by setting the project setting `lod/bias`.
+var lod_bias := 0.0
+
+# The internal refresh timer.
+var timer := 0.0
+
+# The light's energy when it was instanced.
+var base_light_energy := light_energy
+
+
+func _ready() -> void:
+ if ProjectSettings.has_setting("lod/light_bias"):
+ lod_bias = ProjectSettings.get_setting("lod/light_bias")
+ if ProjectSettings.has_setting("lod/light_refresh_rate"):
+ refresh_rate = ProjectSettings.get_setting("lod/light_refresh_rate")
+
+ # Add random jitter to the timer to ensure LODs don't all swap at the same time.
+ randomize()
+ timer += rand_range(0, refresh_rate)
+
+# Despite LOD not being related to physics, we chose to run in `_physics_process()`
+# to minimize the amount of method calls per second (and therefore decrease CPU usage).
+func _physics_process(delta: float) -> void:
+ if not enable_lod:
+ return
+
+ # We need a camera to do the rest.
+ var camera := get_viewport().get_camera()
+ if camera == null:
+ return
+
+ if timer <= refresh_rate:
+ timer += delta
+ return
+
+ timer = 0.0
+
+ var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias
+
+ visible = distance < light_max_distance
+ var light_fade_start_distance := light_max_distance * light_fade_start
+ if distance > light_fade_start_distance:
+ light_energy = max(0, (1 - (distance - light_fade_start_distance) / (light_max_distance - light_fade_start_distance)) * base_light_energy)
+ else:
+ # We're close enough to the light to show it at full brightness.
+ light_energy = base_light_energy
+
+ shadow_enabled = distance < shadow_max_distance
+ var shadow_fade_start_distance := shadow_max_distance * shadow_fade_start
+ var shadow_value: float
+ if distance > shadow_fade_start_distance:
+ shadow_value = min(1, (distance - shadow_fade_start_distance) / (shadow_max_distance - shadow_fade_start_distance))
+ else:
+ # We're close enough to the light to show its shadow at full darkness.
+ shadow_value = 0.0
+ shadow_color = Color(shadow_value, shadow_value, shadow_value)
diff --git a/addons/lod/lod_omni_light.svg b/addons/lod/lod_omni_light.svg
new file mode 100644
index 0000000..3835e3b
--- /dev/null
+++ b/addons/lod/lod_omni_light.svg
@@ -0,0 +1 @@
+
diff --git a/addons/lod/lod_omni_light.svg.import b/addons/lod/lod_omni_light.svg.import
new file mode 100644
index 0000000..7f1e2b9
--- /dev/null
+++ b/addons/lod/lod_omni_light.svg.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/lod_omni_light.svg-72b7ec907b4f0e08e3154232a03aab77.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/lod/lod_omni_light.svg"
+dest_files=[ "res://.import/lod_omni_light.svg-72b7ec907b4f0e08e3154232a03aab77.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=0
+flags/filter=true
+flags/mipmaps=false
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+stream=false
+size_limit=0
+detect_3d=true
+svg/scale=1.0
diff --git a/addons/lod/lod_particles.gd b/addons/lod/lod_particles.gd
new file mode 100644
index 0000000..4b9f77c
--- /dev/null
+++ b/addons/lod/lod_particles.gd
@@ -0,0 +1,59 @@
+# Copyright © 2020 Hugo Locurcio and contributors - MIT License
+# See `LICENSE.md` included in the source distribution for details.
+extends Particles
+class_name LODParticles, "lod_particles.svg"
+
+# If `false`, LOD won't update anymore. This can be used for performance comparison
+# purposes.
+export var enable_lod := true
+
+# The maximum particle emitting distance in units. Past this distance, particles will no longer emit.
+export(float, 0.0, 1000.0, 0.1) var max_emit_distance := 50
+
+# The rate at which LODs will be updated (in seconds). Lower values are more reactive
+# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
+# Set this accordingly depending on your camera movement speed.
+# The default value should suit most projects already.
+# Note: Slow cameras don't need to have LOD-enabled objects update their status often.
+# This can overridden by setting the project setting `lod/refresh_rate`.
+var refresh_rate := 0.25
+
+# The LOD bias in units.
+# Positive values will decrease the detail level and improve performance.
+# Negative values will improve visual appearance at the cost of performance.
+# This can overridden by setting the project setting `lod/bias`.
+var lod_bias := 0.0
+
+# The internal refresh timer.
+var timer := 0.0
+
+
+func _ready() -> void:
+ if ProjectSettings.has_setting("lod/particle_bias"):
+ lod_bias = ProjectSettings.get_setting("lod/particle_bias")
+ if ProjectSettings.has_setting("lod/refresh_rate"):
+ refresh_rate = ProjectSettings.get_setting("lod/refresh_rate")
+
+ # Add random jitter to the timer to ensure LODs don't all swap at the same time.
+ randomize()
+ timer += rand_range(0, refresh_rate)
+
+# Despite LOD not being related to physics, we chose to run in `_physics_process()`
+# to minimize the amount of method calls per second (and therefore decrease CPU usage).
+func _physics_process(delta: float) -> void:
+ if not enable_lod:
+ return
+
+ # We need a camera to do the rest.
+ var camera := get_viewport().get_camera()
+ if camera == null:
+ return
+
+ if timer <= refresh_rate:
+ timer += delta
+ return
+
+ timer = 0.0
+
+ var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias
+ emitting = distance < max_emit_distance
diff --git a/addons/lod/lod_particles.svg b/addons/lod/lod_particles.svg
new file mode 100644
index 0000000..e8fb92a
--- /dev/null
+++ b/addons/lod/lod_particles.svg
@@ -0,0 +1 @@
+
diff --git a/addons/lod/lod_particles.svg.import b/addons/lod/lod_particles.svg.import
new file mode 100644
index 0000000..fc73d9d
--- /dev/null
+++ b/addons/lod/lod_particles.svg.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/lod_particles.svg-86d5ee48cd8c5d9e3cfcd6fa66432a55.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/lod/lod_particles.svg"
+dest_files=[ "res://.import/lod_particles.svg-86d5ee48cd8c5d9e3cfcd6fa66432a55.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=0
+flags/filter=true
+flags/mipmaps=false
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+stream=false
+size_limit=0
+detect_3d=true
+svg/scale=1.0
diff --git a/addons/lod/lod_spatial.gd b/addons/lod/lod_spatial.gd
new file mode 100644
index 0000000..39e811c
--- /dev/null
+++ b/addons/lod/lod_spatial.gd
@@ -0,0 +1,87 @@
+# Copyright © 2020 Hugo Locurcio and contributors - MIT License
+# See `LICENSE.md` included in the source distribution for details.
+extends Spatial
+class_name LODSpatial, "lod_spatial.svg"
+
+# If `false`, LOD won't update anymore. This can be used for performance comparison
+# purposes.
+export var enable_lod := true
+
+# The maximum LOD 0 (high quality) distance in units.
+export(float, 0.0, 1000.0, 0.1) var lod_0_max_distance := 10
+
+# The maximum LOD 1 (medium quality) distance in units.
+export(float, 0.0, 1000.0, 0.1) var lod_1_max_distance := 25
+
+# The maximum LOD 2 (low quality) distance in units.
+# Past this distance, all LOD variants are hidden.
+export(float, 0.0, 1000.0, 0.1) var lod_2_max_distance := 100
+
+# The rate at which LODs will be updated (in seconds). Lower values are more reactive
+# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
+# Set this accordingly depending on your camera movement speed.
+# The default value should suit most projects already.
+# Note: Slow cameras don't need to have LOD-enabled objects update their status often.
+# This can overridden by setting the project setting `lod/refresh_rate`.
+var refresh_rate := 0.25
+
+# The LOD bias in units.
+# Positive values will decrease the detail level and improve performance.
+# Negative values will improve visual appearance at the cost of performance.
+# This can overridden by setting the project setting `lod/bias`.
+var lod_bias := 0.0
+
+# The internal refresh timer.
+var timer := 0.0
+
+
+func _ready() -> void:
+ if ProjectSettings.has_setting("lod/spatial_bias"):
+ lod_bias = ProjectSettings.get_setting("lod/spatial_bias")
+ if ProjectSettings.has_setting("lod/refresh_rate"):
+ refresh_rate = ProjectSettings.get_setting("lod/refresh_rate")
+
+ # Add random jitter to the timer to ensure LODs don't all swap at the same time.
+ randomize()
+ timer += rand_range(0, refresh_rate)
+
+
+# Despite LOD not being related to physics, we chose to run in `_physics_process()`
+# to minimize the amount of method calls per second (and therefore decrease CPU usage).
+func _physics_process(delta: float) -> void:
+ if not enable_lod:
+ return
+
+ # We need a camera to do the rest.
+ var camera := get_viewport().get_camera()
+ if camera == null:
+ return
+
+ if timer <= refresh_rate:
+ timer += delta
+ return
+
+ timer = 0.0
+
+ var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias
+ # The LOD level to choose (lower is more detailed).
+ var lod: int
+ if distance < lod_0_max_distance:
+ lod = 0
+ elif distance < lod_1_max_distance:
+ lod = 1
+ elif distance < lod_2_max_distance:
+ lod = 2
+ else:
+ # Hide the LOD object entirely.
+ lod = 3
+
+ for node in get_children():
+ # `-lod` also matches `-lod0`, `-lod1`, `-lod2`, …
+ if node.has_method("set_visible"):
+ if "-lod0" in node.name:
+ node.visible = lod == 0
+ if "-lod1" in node.name:
+ node.visible = lod == 1
+ if "-lod2" in node.name:
+ node.visible = lod == 2
diff --git a/addons/lod/lod_spatial.svg b/addons/lod/lod_spatial.svg
new file mode 100644
index 0000000..c6d4fde
--- /dev/null
+++ b/addons/lod/lod_spatial.svg
@@ -0,0 +1 @@
+
diff --git a/addons/lod/lod_spatial.svg.import b/addons/lod/lod_spatial.svg.import
new file mode 100644
index 0000000..eb0f3f3
--- /dev/null
+++ b/addons/lod/lod_spatial.svg.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/lod_spatial.svg-0f291da571b0a5b87fdce289c6370d71.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/lod/lod_spatial.svg"
+dest_files=[ "res://.import/lod_spatial.svg-0f291da571b0a5b87fdce289c6370d71.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=0
+flags/filter=true
+flags/mipmaps=false
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+stream=false
+size_limit=0
+detect_3d=true
+svg/scale=1.0
diff --git a/addons/lod/lod_spot_light.gd b/addons/lod/lod_spot_light.gd
new file mode 100644
index 0000000..63300ee
--- /dev/null
+++ b/addons/lod/lod_spot_light.gd
@@ -0,0 +1,92 @@
+# Copyright © 2020 Hugo Locurcio and contributors - MIT License
+# See `LICENSE.md` included in the source distribution for details.
+extends SpotLight
+class_name LODSpotLight, "lod_spot_light.svg"
+
+# If `false`, LOD won't update anymore. This can be used for performance comparison
+# purposes.
+export var enable_lod := true
+
+# The maximum shadow distance in units. Past this distance, the shadow will be disabled.
+export(float, 0.0, 1000.0, 0.1) var shadow_max_distance := 25
+
+# The distance factor at which the shadow starts fading.
+# A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading.
+export(float, 0.0, 1.0, 0.1) var shadow_fade_start := 0.8
+
+# The maximum shadow distance in units. Past this distance, the light will be hidden.
+export(float, 0.0, 1000.0, 0.1) var light_max_distance := 50
+
+# The distance factor at which the light starts fading.
+# A value of 0.0 will result in the smoothest transition whereas a value of 1.0 disables fading.
+export(float, 0.0, 1.0, 0.1) var light_fade_start := 0.8
+
+# The rate at which LODs will be updated (in seconds). Lower values are more reactive
+# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes.
+# Set this accordingly depending on your camera movement speed.
+# The default value should suit most projects already.
+# Note: Slow cameras don't need to have LOD-enabled objects update their status often.
+# By default, lights have their LOD updated faster than other LOD nodes since their
+# light/shadow intensity needs to change as smoothly as posible.
+# This can overridden by setting the project setting `lod/light_refresh_rate`.
+var refresh_rate := 0.05
+
+# The LOD bias in units.
+# Positive values will decrease the detail level and improve performance.
+# Negative values will improve visual appearance at the cost of performance.
+# This can overridden by setting the project setting `lod/bias`.
+var lod_bias := 0.0
+
+# The internal refresh timer.
+var timer := 0.0
+
+# The light's energy when it was instanced.
+var base_light_energy := light_energy
+
+
+func _ready() -> void:
+ if ProjectSettings.has_setting("lod/light_bias"):
+ lod_bias = ProjectSettings.get_setting("lod/light_bias")
+ if ProjectSettings.has_setting("lod/light_refresh_rate"):
+ refresh_rate = ProjectSettings.get_setting("lod/light_refresh_rate")
+
+ # Add random jitter to the timer to ensure LODs don't all swap at the same time.
+ randomize()
+ timer += rand_range(0, refresh_rate)
+
+# Despite LOD not being related to physics, we chose to run in `_physics_process()`
+# to minimize the amount of method calls per second (and therefore decrease CPU usage).
+func _physics_process(delta: float) -> void:
+ if not enable_lod:
+ return
+
+ # We need a camera to do the rest.
+ var camera := get_viewport().get_camera()
+ if camera == null:
+ return
+
+ if timer <= refresh_rate:
+ timer += delta
+ return
+
+ timer = 0.0
+
+ var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias
+
+ visible = distance < light_max_distance
+ var light_fade_start_distance := light_max_distance * light_fade_start
+ if distance > light_fade_start_distance:
+ light_energy = max(0, (1 - (distance - light_fade_start_distance) / (light_max_distance - light_fade_start_distance)) * base_light_energy)
+ else:
+ # We're close enough to the light to show it at full brightness.
+ light_energy = base_light_energy
+
+ shadow_enabled = distance < shadow_max_distance
+ var shadow_fade_start_distance := shadow_max_distance * shadow_fade_start
+ var shadow_value: float
+ if distance > shadow_fade_start_distance:
+ shadow_value = min(1, (distance - shadow_fade_start_distance) / (shadow_max_distance - shadow_fade_start_distance))
+ else:
+ # We're close enough to the light to show its shadow at full darkness.
+ shadow_value = 0.0
+ shadow_color = Color(shadow_value, shadow_value, shadow_value)
diff --git a/addons/lod/lod_spot_light.svg b/addons/lod/lod_spot_light.svg
new file mode 100644
index 0000000..34fc875
--- /dev/null
+++ b/addons/lod/lod_spot_light.svg
@@ -0,0 +1 @@
+
diff --git a/addons/lod/lod_spot_light.svg.import b/addons/lod/lod_spot_light.svg.import
new file mode 100644
index 0000000..a66d65a
--- /dev/null
+++ b/addons/lod/lod_spot_light.svg.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path="res://.import/lod_spot_light.svg-22de3bf1089e94662394255ca8159db9.stex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://addons/lod/lod_spot_light.svg"
+dest_files=[ "res://.import/lod_spot_light.svg-22de3bf1089e94662394255ca8159db9.stex" ]
+
+[params]
+
+compress/mode=0
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=0
+flags/filter=true
+flags/mipmaps=false
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+stream=false
+size_limit=0
+detect_3d=true
+svg/scale=1.0
diff --git a/addons/lod/plugin.cfg b/addons/lod/plugin.cfg
new file mode 100644
index 0000000..fbce6e7
--- /dev/null
+++ b/addons/lod/plugin.cfg
@@ -0,0 +1,7 @@
+[plugin]
+
+name="Level of Detail (LOD)"
+description="Level of Detail implementation for meshes, lights and particles."
+author="Calinou"
+version="1.0.0"
+script="plugin.gd"
diff --git a/addons/lod/plugin.gd b/addons/lod/plugin.gd
new file mode 100644
index 0000000..a824c97
--- /dev/null
+++ b/addons/lod/plugin.gd
@@ -0,0 +1,7 @@
+# Copyright © 2020 Hugo Locurcio and contributors - MIT License
+# See `LICENSE.md` included in the source distribution for details.
+#
+# This script is needed to make the `class_name` script visible in the Create New Node dialog
+# once the plugin is enabled.
+tool
+extends EditorPlugin
diff --git a/project.godot b/project.godot
index 2d2a104..1705936 100644
--- a/project.godot
+++ b/project.godot
@@ -138,6 +138,31 @@ _global_script_classes=[ {
"class": "GDDatabase",
"language": "GDScript",
"path": "res://addons/godot_db_manager/core/database.gd"
+}, {
+"base": "CPUParticles",
+"class": "LODCPUParticles",
+"language": "GDScript",
+"path": "res://addons/lod/lod_cpu_particles.gd"
+}, {
+"base": "OmniLight",
+"class": "LODOmniLight",
+"language": "GDScript",
+"path": "res://addons/lod/lod_omni_light.gd"
+}, {
+"base": "Particles",
+"class": "LODParticles",
+"language": "GDScript",
+"path": "res://addons/lod/lod_particles.gd"
+}, {
+"base": "Spatial",
+"class": "LODSpatial",
+"language": "GDScript",
+"path": "res://assets/props/lods.gd"
+}, {
+"base": "SpotLight",
+"class": "LODSpotLight",
+"language": "GDScript",
+"path": "res://addons/lod/lod_spot_light.gd"
} ]
_global_script_class_icons={
"GDDBConstants": "",
@@ -165,7 +190,12 @@ _global_script_class_icons={
"GDDBTablesHeader": "",
"GDDBTablesList": "",
"GDDBTypes": "",
-"GDDatabase": ""
+"GDDatabase": "",
+"LODCPUParticles": "res://addons/lod/lod_cpu_particles.svg",
+"LODOmniLight": "res://addons/lod/lod_omni_light.svg",
+"LODParticles": "res://addons/lod/lod_particles.svg",
+"LODSpatial": "",
+"LODSpotLight": "res://addons/lod/lod_spot_light.svg"
}
[application]
@@ -197,7 +227,7 @@ window/stretch/mode="2d"
[editor_plugins]
-enabled=PoolStringArray( "res://addons/godot_db_manager/plugin.cfg" )
+enabled=PoolStringArray( "res://addons/godot_db_manager/plugin.cfg", "res://addons/lod/plugin.cfg" )
[importer_defaults]