diff --git a/.idea/.idea.PatchManager/.idea/.gitignore b/.idea/.idea.PatchManager/.idea/.gitignore
new file mode 100644
index 0000000..0b0518c
--- /dev/null
+++ b/.idea/.idea.PatchManager/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/modules.xml
+/.idea.PatchManager.iml
+/projectSettingsUpdater.xml
+/contentModel.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.PatchManager/.idea/.name b/.idea/.idea.PatchManager/.idea/.name
new file mode 100644
index 0000000..aee2c7b
--- /dev/null
+++ b/.idea/.idea.PatchManager/.idea/.name
@@ -0,0 +1 @@
+PatchManager
\ No newline at end of file
diff --git a/.idea/.idea.PatchManager/.idea/projectSettingsUpdater.xml b/.idea/.idea.PatchManager/.idea/projectSettingsUpdater.xml
index 4bb9f4d..ef20cb0 100644
--- a/.idea/.idea.PatchManager/.idea/projectSettingsUpdater.xml
+++ b/.idea/.idea.PatchManager/.idea/projectSettingsUpdater.xml
@@ -1,6 +1,8 @@
-
+
+
+
\ No newline at end of file
diff --git a/Runtime/PatchManager.cs b/Runtime/PatchManager.cs
index 4561000..c0855bd 100644
--- a/Runtime/PatchManager.cs
+++ b/Runtime/PatchManager.cs
@@ -30,6 +30,7 @@ public void Awake()
ModuleManager.Register(typeof(PartsModule));
ModuleManager.Register(typeof(ResourcesModule));
ModuleManager.Register(typeof(ScienceModule));
+ ModuleManager.Register(typeof(PlanetsModule));
Logging.Initialize(SWLogger);
foreach (var module in ModuleManager.Modules)
{
diff --git a/Runtime/Planets.meta b/Runtime/Planets.meta
new file mode 100644
index 0000000..2ab5008
--- /dev/null
+++ b/Runtime/Planets.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3bd5e553aee95514790c6a5d0ca966a8
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Modifiables.meta b/Runtime/Planets/Modifiables.meta
new file mode 100644
index 0000000..5ddc718
--- /dev/null
+++ b/Runtime/Planets/Modifiables.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d16c24effd80c8340bf5b36ae4cb1f6f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Modifiables/AtmosphereOverrideModifiable.cs b/Runtime/Planets/Modifiables/AtmosphereOverrideModifiable.cs
new file mode 100644
index 0000000..ded738e
--- /dev/null
+++ b/Runtime/Planets/Modifiables/AtmosphereOverrideModifiable.cs
@@ -0,0 +1,28 @@
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Modifiables;
+using PatchManager.Planets.Selectables;
+
+namespace PatchManager.Planets.Modifiables
+{
+ public class AtmosphereOverrideModifiable : JTokenModifiable
+ {
+ private AtmosphereOverrideSelectable _atmosphereOverrideSelectable;
+
+ ///
+ /// Creates a new for the given .
+ ///
+ /// The selectable to modify.
+ public AtmosphereOverrideModifiable(AtmosphereOverrideSelectable selectable) : base(selectable.AtmosphereOverrideObject, selectable.SetModified) => _atmosphereOverrideSelectable = selectable;
+
+ ///
+ public override void Set(DataValue dataValue)
+ {
+ if (dataValue.IsDeletion)
+ {
+ _atmosphereOverrideSelectable.SetDeleted();
+ return;
+ }
+ base.Set(dataValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Modifiables/AtmosphereOverrideModifiable.cs.meta b/Runtime/Planets/Modifiables/AtmosphereOverrideModifiable.cs.meta
new file mode 100644
index 0000000..246cd2e
--- /dev/null
+++ b/Runtime/Planets/Modifiables/AtmosphereOverrideModifiable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b8493a99118f5d642bc78277b421e90f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Modifiables/CelestialBodyModifiable.cs b/Runtime/Planets/Modifiables/CelestialBodyModifiable.cs
new file mode 100644
index 0000000..3a03f47
--- /dev/null
+++ b/Runtime/Planets/Modifiables/CelestialBodyModifiable.cs
@@ -0,0 +1,28 @@
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Modifiables;
+using PatchManager.Planets.Selectables;
+
+namespace PatchManager.Planets.Modifiables
+{
+ public class CelestialBodyModifiable : JTokenModifiable
+ {
+ private CelestialBodySelectable _celestialBodySelectable;
+
+ ///
+ /// Creates a new for the given .
+ ///
+ /// The selectable to modify.
+ public CelestialBodyModifiable(CelestialBodySelectable selectable) : base(selectable.DataObject, selectable.SetModified) => _celestialBodySelectable = selectable;
+
+ ///
+ public override void Set(DataValue dataValue)
+ {
+ if (dataValue.IsDeletion)
+ {
+ _celestialBodySelectable.SetDeleted();
+ return;
+ }
+ base.Set(dataValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Modifiables/CelestialBodyModifiable.cs.meta b/Runtime/Planets/Modifiables/CelestialBodyModifiable.cs.meta
new file mode 100644
index 0000000..e093a39
--- /dev/null
+++ b/Runtime/Planets/Modifiables/CelestialBodyModifiable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fc0beafcc88ee24409d36a716bf4f006
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Modifiables/GalaxyModifiable.cs b/Runtime/Planets/Modifiables/GalaxyModifiable.cs
new file mode 100644
index 0000000..2e48a82
--- /dev/null
+++ b/Runtime/Planets/Modifiables/GalaxyModifiable.cs
@@ -0,0 +1,28 @@
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Modifiables;
+using PatchManager.Planets.Selectables;
+
+namespace PatchManager.Planets.Modifiables
+{
+ public class GalaxyModifiable : JTokenModifiable
+ {
+ private GalaxySelectable _galaxySelectable;
+
+ ///
+ /// Creates a new for the given .
+ ///
+ /// The selectable to modify.
+ public GalaxyModifiable(GalaxySelectable selectable) : base(selectable.GalaxyObject, selectable.SetModified) => _galaxySelectable = selectable;
+
+ ///
+ public override void Set(DataValue dataValue)
+ {
+ if (dataValue.IsDeletion)
+ {
+ _galaxySelectable.SetDeleted();
+ return;
+ }
+ base.Set(dataValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Modifiables/GalaxyModifiable.cs.meta b/Runtime/Planets/Modifiables/GalaxyModifiable.cs.meta
new file mode 100644
index 0000000..a950bb0
--- /dev/null
+++ b/Runtime/Planets/Modifiables/GalaxyModifiable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fdda9387f4caeb74eb2cdca951eb05dd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Modifiables/VolumeCloudOverrideModifiable.cs b/Runtime/Planets/Modifiables/VolumeCloudOverrideModifiable.cs
new file mode 100644
index 0000000..f7aa67a
--- /dev/null
+++ b/Runtime/Planets/Modifiables/VolumeCloudOverrideModifiable.cs
@@ -0,0 +1,28 @@
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Modifiables;
+using PatchManager.Planets.Selectables;
+
+namespace PatchManager.Planets.Modifiables
+{
+ public class VolumeCloudOverrideModifiable : JTokenModifiable
+ {
+ private readonly VolumeCloudSelectable _volumeCloudSelectable;
+
+ ///
+ /// Creates a new for the given .
+ ///
+ /// The selectable to modify.
+ public VolumeCloudOverrideModifiable(VolumeCloudSelectable selectable) : base(selectable.VolumeCloudOverrideObject, selectable.SetModified) => _volumeCloudSelectable = selectable;
+
+ ///
+ public override void Set(DataValue dataValue)
+ {
+ if (dataValue.IsDeletion)
+ {
+ _volumeCloudSelectable.SetDeleted();
+ return;
+ }
+ base.Set(dataValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Modifiables/VolumeCloudOverrideModifiable.cs.meta b/Runtime/Planets/Modifiables/VolumeCloudOverrideModifiable.cs.meta
new file mode 100644
index 0000000..5cf42ac
--- /dev/null
+++ b/Runtime/Planets/Modifiables/VolumeCloudOverrideModifiable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: da9a67e1fe990344281261e63ee7ca2a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/OverrideManager.cs b/Runtime/Planets/OverrideManager.cs
new file mode 100644
index 0000000..c74d172
--- /dev/null
+++ b/Runtime/Planets/OverrideManager.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using JetBrains.Annotations;
+using PatchManager.Planets.Overrides;
+
+namespace PatchManager.Planets
+{
+ [PublicAPI]
+ public static class OverrideManager
+ {
+ public static Dictionary AtmosphereOverrides = new();
+ public static Dictionary Scales = new();
+ public static Dictionary VolumeCloudOverrides = new();
+ }
+}
+
diff --git a/Runtime/Planets/OverrideManager.cs.meta b/Runtime/Planets/OverrideManager.cs.meta
new file mode 100644
index 0000000..7f82285
--- /dev/null
+++ b/Runtime/Planets/OverrideManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: eb9db04c88d10c544832ef17aeb8c3f7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Overrides.meta b/Runtime/Planets/Overrides.meta
new file mode 100644
index 0000000..5df65e6
--- /dev/null
+++ b/Runtime/Planets/Overrides.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 853b57e5746286842a82e957df725cee
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Overrides/AtmosphereOverride.cs b/Runtime/Planets/Overrides/AtmosphereOverride.cs
new file mode 100644
index 0000000..dc86ce8
--- /dev/null
+++ b/Runtime/Planets/Overrides/AtmosphereOverride.cs
@@ -0,0 +1,87 @@
+using JetBrains.Annotations;
+using KSP.Game;
+using KSP.Rendering;
+using UnityEngine;
+
+namespace PatchManager.Planets.Overrides
+{
+ [PublicAPI]
+ [UsedImplicitly]
+ public struct AtmosphereOverride : IOverride
+ {
+ public string PlanetName;
+ public bool? IsGasGiant;
+ public Vector2? Exposure;
+ public float? SunAngleRadius;
+ public float? SunZenithAngle;
+ public Vector3? SolarIrradiance;
+ public float? SunDirectionExposureModifier;
+ public float? TransmittanceTint;
+ public float? NoonColorStrength;
+ public float? SunsetColorStrength;
+ public float? ColorTransitionScale;
+ public float? BottomRadius;
+ public float? AtmosphereHeight;
+ public Color? GroundAlbedo;
+ public Vector3? RayleighScattering;
+ public float? RayleighScatteringScale;
+ public float? RayleighExponentialDistribution;
+ public Vector3? MieScattering;
+ public float? MieScatteringScale;
+ public float? MieAnistropy;
+ public float? MieExponentialDistribution;
+ public float? AbsorptionScale;
+ public Vector3? Absorption;
+ public float? AbsorptionMaxDensity;
+ public Vector2? AbsorptionHeightMinMax;
+ [CanBeNull] public string TransmittanceTexture;
+ [CanBeNull] public string IrradianceTexture;
+ [CanBeNull] public string ScatteringTexture;
+
+ public void ApplyTo(AtmosphereModel atmosphereModel)
+ {
+ if (IsGasGiant.HasValue) atmosphereModel.IsGasGiant = IsGasGiant.Value;
+ if (Exposure.HasValue) atmosphereModel.Exposure = Exposure.Value;
+ if (SunAngleRadius.HasValue) atmosphereModel.SunAngleRadius = SunAngleRadius.Value;
+ if (SunZenithAngle.HasValue) atmosphereModel.SunZenithAngle = SunZenithAngle.Value;
+ if (SolarIrradiance.HasValue) atmosphereModel.SolarIrradiance = SolarIrradiance.Value;
+ if (SunDirectionExposureModifier.HasValue)
+ atmosphereModel.SunDirectionExposureModifier = SunDirectionExposureModifier.Value;
+ if (TransmittanceTint.HasValue) atmosphereModel.TransmittanceTint = TransmittanceTint.Value;
+ if (NoonColorStrength.HasValue) atmosphereModel.NoonColorStrengh = NoonColorStrength.Value;
+ if (SunsetColorStrength.HasValue) atmosphereModel.SunsetColorStrengh = SunsetColorStrength.Value;
+ if (ColorTransitionScale.HasValue) atmosphereModel.ColorTransitionScale = ColorTransitionScale.Value;
+ if (BottomRadius.HasValue) atmosphereModel.BottomRadius = BottomRadius.Value;
+ if (AtmosphereHeight.HasValue) atmosphereModel.AtmosphereHeight = AtmosphereHeight.Value;
+ if (GroundAlbedo.HasValue) atmosphereModel.GroundAlbedo = GroundAlbedo.Value;
+ if (RayleighScattering.HasValue) atmosphereModel.RayleighScattering = RayleighScattering.Value;
+ if (RayleighScatteringScale.HasValue) atmosphereModel.RayleighScatteringScale = RayleighScatteringScale.Value;
+ if (RayleighExponentialDistribution.HasValue)
+ atmosphereModel.RayleighExponentialDistribution = RayleighExponentialDistribution.Value;
+ if (MieScattering.HasValue) atmosphereModel.MieScattering = MieScattering.Value;
+ if (MieScatteringScale.HasValue) atmosphereModel.MieScatteringScale = MieScatteringScale.Value;
+ if (MieAnistropy.HasValue) atmosphereModel.MieAnisotropy = MieAnistropy.Value;
+ if (MieExponentialDistribution.HasValue)
+ atmosphereModel.MieExponentialDistribution = MieExponentialDistribution.Value;
+ if (AbsorptionScale.HasValue) atmosphereModel.AbsorptionScale = AbsorptionScale.Value;
+ if (Absorption.HasValue) atmosphereModel.Absorption = Absorption.Value;
+ if (AbsorptionHeightMinMax.HasValue) atmosphereModel.AbsorptionHeightMinMax = AbsorptionHeightMinMax.Value;
+ if (!string.IsNullOrEmpty(TransmittanceTexture))
+ {
+ GameManager.Instance.Assets.TryLoad(TransmittanceTexture,
+ asset => atmosphereModel.TransmittanceTexture = asset);
+ }
+ if (!string.IsNullOrEmpty(IrradianceTexture))
+ {
+ GameManager.Instance.Assets.TryLoad(IrradianceTexture,
+ asset => atmosphereModel.IrradianceTexture = asset);
+ }
+ if (!string.IsNullOrEmpty(ScatteringTexture))
+ {
+ GameManager.Instance.Assets.TryLoad(ScatteringTexture,
+ asset => atmosphereModel.ScatteringTexture = asset);
+ }
+ }
+ }
+}
+
diff --git a/Runtime/Planets/Overrides/AtmosphereOverride.cs.meta b/Runtime/Planets/Overrides/AtmosphereOverride.cs.meta
new file mode 100644
index 0000000..45cd5e3
--- /dev/null
+++ b/Runtime/Planets/Overrides/AtmosphereOverride.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3f528aba5c9895940aae4d8db841c82b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Overrides/CloudsDataOverride.cs b/Runtime/Planets/Overrides/CloudsDataOverride.cs
new file mode 100644
index 0000000..65a008c
--- /dev/null
+++ b/Runtime/Planets/Overrides/CloudsDataOverride.cs
@@ -0,0 +1,80 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable IdentifierTypo
+
+using JetBrains.Annotations;
+using KSP.VolumeCloud;
+using UnityEngine;
+using static PatchManager.Planets.Utility.Extensions;
+
+namespace PatchManager.Planets.Overrides
+{
+ [PublicAPI]
+ public class CloudsDataOverride : IOverride
+ {
+ public string layerName;
+ public bool? isEnable;
+ public bool? castShadow;
+ public float? bakeCloudMipmap;
+ public float? currentBakedCloudMipMap;
+ public VolumeCloudConfiguration.CloudsLayerType? cloudsType;
+ public Vector2? cloudHeightRange;
+ public float? bakedCloudHeight;
+ public Vector3? cloudsLayerRotate;
+ public bool? enableWind;
+ public Vector2? windDirection;
+ public float? movementSpeed;
+ public float? evolveSpeed;
+ public float? topOffset;
+ public bool? isFold;
+ public float? baseTexureTile;
+ public float? coverageScale;
+ public float? evanish;
+ public float? detailAmount;
+ public float? cloudsMaskBias;
+ public float? upperFalloff;
+ public float? lowerFalloff;
+ public float? detailAltitudeShift;
+ public bool? enableDetailTexture;
+ public float? detailTextureTile;
+ public float? detailStrength;
+ public float? cloudsDensity;
+ public float? normalScale;
+ public Color? scaleCloudColor = Color.white;
+
+ public void ApplyTo(VolumeCloudConfiguration.CloudsData obj)
+ {
+ isEnable.Apply(ref obj.isEnable);
+ castShadow.Apply(ref obj.castShadow);
+ bakeCloudMipmap.Apply(ref obj.bakeCloudMipmap);
+ currentBakedCloudMipMap.Apply(ref obj.currentBakedCloudMipmap);
+ cloudsType.Apply(ref obj.cloudsType);
+ cloudHeightRange.Apply(ref obj.cloudHeightRange);
+ bakedCloudHeight.Apply(ref obj.bakedCloudHeight);
+ cloudsLayerRotate.Apply(ref obj.cloudsLayerRotate);
+ enableWind.Apply(ref obj.enableWind);
+ windDirection.Apply(ref obj.windDirection);
+ movementSpeed.Apply(ref obj.movementSpeed);
+ evolveSpeed.Apply(ref obj.evolveSpeed);
+ topOffset.Apply(ref obj.topOffset);
+ isFold.Apply(ref obj.isFold);
+ if (obj is VolumeCloudConfiguration.CumulusData cumulus)
+ {
+ baseTexureTile.Apply(ref cumulus.baseTexureTile);
+ coverageScale.Apply(ref cumulus.coverageScale);
+ evanish.Apply(ref cumulus.evanish);
+ detailAmount.Apply(ref cumulus.detailAmount);
+ cloudsMaskBias.Apply(ref cumulus.cloudsMaskBias);
+ upperFalloff.Apply(ref cumulus.upperFalloff);
+ lowerFalloff.Apply(ref cumulus.lowerFalloff);
+ detailAltitudeShift.Apply(ref cumulus.detailAltitudeShift);
+ enableDetailTexture.Apply(ref cumulus.enableDetailTexture);
+ detailTextureTile.Apply(ref cumulus.detailTextureTile);
+ detailStrength.Apply(ref cumulus.detailStrength);
+ cloudsDensity.Apply(ref cumulus.cloudsDensity);
+ normalScale.Apply(ref cumulus.normalScale);
+ scaleCloudColor.Apply(ref cumulus.scaleCloudColor);
+ }
+ }
+ }
+}
+
diff --git a/Runtime/Planets/Overrides/CloudsDataOverride.cs.meta b/Runtime/Planets/Overrides/CloudsDataOverride.cs.meta
new file mode 100644
index 0000000..2a49605
--- /dev/null
+++ b/Runtime/Planets/Overrides/CloudsDataOverride.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a99547e02aad84f4db48bcdd725d3285
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Overrides/IOverride.cs b/Runtime/Planets/Overrides/IOverride.cs
new file mode 100644
index 0000000..9839e08
--- /dev/null
+++ b/Runtime/Planets/Overrides/IOverride.cs
@@ -0,0 +1,7 @@
+namespace PatchManager.Planets.Overrides
+{
+ public interface IOverride where T : class
+ {
+ public void ApplyTo(T obj);
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Overrides/IOverride.cs.meta b/Runtime/Planets/Overrides/IOverride.cs.meta
new file mode 100644
index 0000000..dc09456
--- /dev/null
+++ b/Runtime/Planets/Overrides/IOverride.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 65f3e4eaadb8a054fb4e16acc75ec496
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Overrides/VolumeCloudConfigurationOverride.cs b/Runtime/Planets/Overrides/VolumeCloudConfigurationOverride.cs
new file mode 100644
index 0000000..2d93c2e
--- /dev/null
+++ b/Runtime/Planets/Overrides/VolumeCloudConfigurationOverride.cs
@@ -0,0 +1,157 @@
+using System.Collections.Generic;
+using System.Linq;
+using JetBrains.Annotations;
+using KSP.VolumeCloud;
+using UnityEngine;
+using static PatchManager.Planets.Utility.Extensions;
+
+// ReSharper disable InconsistentNaming
+// ReSharper disable IdentifierTypo
+
+namespace PatchManager.Planets.Overrides
+{
+ [PublicAPI]
+ public class VolumeCloudConfigurationOverride : IOverride
+ {
+ public string bodyName;
+ public bool? exclusiveLayer;
+ public Vector3? CloudsRotateAll;
+ public float? planetRadius;
+ public bool? enableColorMap;
+ public bool? enableVerticalColor;
+ public float? colorMapIntensity;
+ public float? verticalColorIntensity;
+ // [CanBeNull] public Gradient ColorVertical;
+ public float? overallSize;
+ public Vector2? vortexCloudHeightRange;
+ // todo: lenticular list
+ public List cumulusList = new List();
+ // todo: cumulus index
+ public float? cloudCoverageModifier;
+ public float? detailVariationRange;
+ public bool? enableShadows;
+ public bool? enableLayerShadows;
+ public float? volumetricShadowDensity;
+ public float? volumetricShadowLodBias;
+ public float? volumetricShadowDistance;
+ public float? shadowOpacity;
+ public float? shadowMapStrength;
+ public float? layerShadowDensity;
+ public Color? ambientColor;
+ public bool? EnableCloudGI;
+ public float? cloudGIIntensity;
+ public float? cloudGITint;
+ public float? lightPenetrateDistance;
+ public float? multiScatteringScattering;
+ public float? extinctionByLightPosition;
+ public float? opticsDistanceScale;
+ public float? silverSpreadG;
+ public float? bloomStrengthG;
+ public float? silverSpreadUnderCloudG;
+ public float? bloomStrengthUnderCloudG;
+ public float? silverSpread;
+ public float? bloomStrength;
+ public float? silverSpreadUnderCloud;
+ public float? bloomStrengthUnderCloud;
+ public float? ambientScale;
+ public float? scatteringScale;
+ public float? cloudsDensityScale;
+ public bool? enableGodray;
+ public float? godrayIntensity;
+ public float? godrayVisibleDistance;
+ public float? godrayStepSize;
+ public float? sampleLightStepSize;
+ public float? sampleLightStepCount;
+ public Vector2? cloudDensityRangeEmitGodray;
+ public float? godrayAttenuation;
+ public float? godrayFadeHeight;
+ public float? godrayBlurSize;
+ public bool? IsBlurGodray;
+ public float? antiBandingAmplify;
+ public bool? useScaleCloudsOnly;
+ public float? raymarchStepSize;
+ public bool? increaseRaymarchStepByDistance;
+ public float? distanceRatio;
+ public float? maxRaymarchStepSize;
+ public bool? cullingEdgeClouds;
+ public float? cullingStrength;
+ public bool? autoMipmap;
+ public float? scaleCloudMaskNormalTileRate;
+ public float? cascadedResolutionRange;
+ public float? mipmapScale;
+ public bool? enableFadeout;
+ public float? startFadeoutHeight;
+ public float? endFadeoutHeight;
+
+ public void ApplyTo(VolumeCloudConfiguration obj)
+ {
+ exclusiveLayer.Apply(ref obj.exclusiveLayer);
+ CloudsRotateAll.Apply(ref obj.CloudsRotateAll);
+ planetRadius.Apply(ref obj.planetRadius);
+ enableColorMap.Apply(ref obj.enableColorMap);
+ enableVerticalColor.Apply(ref obj.enableVerticalColor);
+ colorMapIntensity.Apply(ref obj.colorMapIntensity);
+ verticalColorIntensity.Apply(ref obj.verticalColorIntensity);
+ overallSize.Apply(ref obj.overallSize);
+ vortexCloudHeightRange.Apply(ref obj.vortexCloudHeightRange);
+ foreach (var item in cumulusList)
+ if (obj.cumulusList.FirstOrDefault(x => x.layerName == item.layerName) is {} first) item.ApplyTo(first);
+ cloudCoverageModifier.Apply(ref obj.cloudCoverageModifier);
+ detailVariationRange.Apply(ref obj.detailVariationRange);
+ enableShadows.Apply(ref obj.enableShadows);
+ enableLayerShadows.Apply(ref obj.enableLayerShadows);
+ volumetricShadowDensity.Apply(ref obj.volumetricShadowDensity);
+ volumetricShadowLodBias.Apply(ref obj.volumetricShadowLodBias);
+ volumetricShadowDistance.Apply(ref obj.volumetricShadowDistance);
+ shadowOpacity.Apply(ref obj.shadowOpacity);
+ shadowMapStrength.Apply(ref obj.shadowMapStrength);
+ layerShadowDensity.Apply(ref obj.layerShadowDensity);
+ ambientColor.Apply(ref obj.ambientColor);
+ EnableCloudGI.Apply(ref obj.EnableCloudGI);
+ cloudGIIntensity.Apply(ref obj.cloudGIIntensity);
+ cloudGITint.Apply(ref obj.cloudGITint);
+ lightPenetrateDistance.Apply(ref obj.lightPenetrateDistance);
+ multiScatteringScattering.Apply(ref obj.multiScatteringScattering);
+ extinctionByLightPosition.Apply(ref obj.extinctionByLightPosition);
+ opticsDistanceScale.Apply(ref obj.opticsDistanceScale);
+ silverSpreadG.Apply(ref obj.silverSpreadG);
+ bloomStrengthG.Apply(ref obj.bloomStrengthG);
+ silverSpreadUnderCloudG.Apply(ref obj.silverSpreadUnderCloudG);
+ bloomStrengthUnderCloudG.Apply(ref obj.bloomStrengthUnderCloudG);
+ silverSpread.Apply(ref obj.silverSpread);
+ bloomStrength.Apply(ref obj.bloomStrength);
+ silverSpreadUnderCloud.Apply(ref obj.silverSpreadUnderCloud);
+ bloomStrengthUnderCloud.Apply(ref obj.bloomStrengthUnderCloud);
+ ambientScale.Apply(ref obj.ambinetScale);
+ scatteringScale.Apply(ref obj.scatteringScale);
+ cloudsDensityScale.Apply(ref obj.cloudsDensityScale);
+ enableGodray.Apply(ref obj.enableGodray);
+ godrayIntensity.Apply(ref obj.godrayIntensity);
+ godrayVisibleDistance.Apply(ref obj.godrayVisableDistance);
+ godrayStepSize.Apply(ref obj.godrayStepSize);
+ sampleLightStepSize.Apply(ref obj.sampleLightStepSize);
+ sampleLightStepCount.Apply(ref obj.sampleLightStepCount);
+ cloudDensityRangeEmitGodray.Apply(ref obj.cloudDensityRangeEmitGodray);
+ godrayAttenuation.Apply(ref obj.godrayAttenuation);
+ godrayFadeHeight.Apply(ref obj.godrayFadeHeight);
+ godrayBlurSize.Apply(ref obj.godrayBlurSize);
+ IsBlurGodray.Apply(ref obj.IsBlurGodray);
+ antiBandingAmplify.Apply(ref obj.antiBandingAmplify);
+ useScaleCloudsOnly.Apply(ref obj.useScaleCloudsOnly);
+ raymarchStepSize.Apply(ref obj.raymarchStepSize);
+ increaseRaymarchStepByDistance.Apply(ref obj.increaceRaymarchStepByDistance);
+ distanceRatio.Apply(ref obj.distanceRatio);
+ maxRaymarchStepSize.Apply(ref obj.maxRaymarchStepSize);
+ cullingEdgeClouds.Apply(ref obj.cullingEdgeClouds);
+ cullingStrength.Apply(ref obj.cullingStrength);
+ autoMipmap.Apply(ref obj.autoMipmap);
+ scaleCloudMaskNormalTileRate.Apply(ref obj.scaleCloudMaskNormalTileRate);
+ cascadedResolutionRange.Apply(ref obj.cascadedResolutionRange);
+ mipmapScale.Apply(ref obj.mipmapScale);
+ enableFadeout.Apply(ref obj.enableFadeout);
+ startFadeoutHeight.Apply(ref obj.startFadeoutHeight);
+ endFadeoutHeight.Apply(ref obj.endFadeoutHeight);
+ }
+ }
+}
+
diff --git a/Runtime/Planets/Overrides/VolumeCloudConfigurationOverride.cs.meta b/Runtime/Planets/Overrides/VolumeCloudConfigurationOverride.cs.meta
new file mode 100644
index 0000000..17e1239
--- /dev/null
+++ b/Runtime/Planets/Overrides/VolumeCloudConfigurationOverride.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0ab89b9370f0fdd48833a9ae261002e3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/PlanetsModule.cs b/Runtime/Planets/PlanetsModule.cs
new file mode 100644
index 0000000..683061e
--- /dev/null
+++ b/Runtime/Planets/PlanetsModule.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+using JetBrains.Annotations;
+using KSP.Game;
+using KSP.IO;
+using Newtonsoft.Json;
+using PatchManager.Shared.Modules;
+using PatchManager.Planets.Overrides;
+using UnityEngine;
+using UnityEngine.AddressableAssets;
+
+namespace PatchManager.Planets
+{
+ public class PlanetsModule : BaseModule
+ {
+ private static void RegisterAtmosphereOverride(TextAsset atmosphereOverride)
+ {
+ var atmosphere = JsonConvert.DeserializeObject(atmosphereOverride.text);
+ OverrideManager.AtmosphereOverrides[atmosphere.PlanetName] = atmosphere;
+ }
+
+ private static void RegisterVolumeCloudOverride(TextAsset volumeCloudOverride)
+ {
+ var volumeCloud = IOProvider.FromJson(volumeCloudOverride.text);
+ OverrideManager.VolumeCloudOverrides[volumeCloud.bodyName.ToLowerInvariant()] = volumeCloud;
+ }
+
+ ///
+ /// Runs when the mod is first initialized.
+ ///
+ public override void Load()
+ {
+ GameManager.Instance.Assets.LoadByLabel("atmosphere_overrides", RegisterAtmosphereOverride,
+ delegate(IList assetLocations) { Addressables.Release(assetLocations); });
+ GameManager.Instance.Assets.LoadByLabel("volume_cloud_overrides", RegisterVolumeCloudOverride,
+ delegate(IList assetLocations) { Addressables.Release(assetLocations); });
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/PlanetsModule.cs.meta b/Runtime/Planets/PlanetsModule.cs.meta
new file mode 100644
index 0000000..4e5334c
--- /dev/null
+++ b/Runtime/Planets/PlanetsModule.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 30b8274d97df87c4fa75a7a06125576c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Rulesets.meta b/Runtime/Planets/Rulesets.meta
new file mode 100644
index 0000000..8ac2f7a
--- /dev/null
+++ b/Runtime/Planets/Rulesets.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e60ec5f4ba39f2d4c8a30ca94cd399f3
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Rulesets/AtmosphereOverrideRuleset.cs b/Runtime/Planets/Rulesets/AtmosphereOverrideRuleset.cs
new file mode 100644
index 0000000..6de348f
--- /dev/null
+++ b/Runtime/Planets/Rulesets/AtmosphereOverrideRuleset.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Attributes;
+using PatchManager.SassyPatching.Interfaces;
+using PatchManager.SassyPatching.NewAssets;
+using PatchManager.Planets.Overrides;
+using PatchManager.Planets.Selectables;
+
+namespace PatchManager.Planets.Rulesets
+{
+ [PatcherRuleset("atmosphere-override","atmosphere_overrides")]
+ public class AtmosphereOverrideRuleset : IPatcherRuleSet
+ {
+ public bool Matches(string label) => label == "atmosphere_overrides";
+
+ public ISelectable ConvertToSelectable(string type, string name, string jsonData) =>
+ new AtmosphereOverrideSelectable(JObject.Parse(jsonData));
+
+ public INewAsset CreateNew(List dataValues)
+ {
+ var planetName = dataValues[0].String.ToLowerInvariant();
+ var data = new AtmosphereOverride
+ {
+ PlanetName = planetName
+ };
+ return new NewGenericAsset("atmosphere_overrides", $"atmosphere_override_{planetName}",
+ new AtmosphereOverrideSelectable(JObject.FromObject(data)));
+ }
+ }
+}
diff --git a/Runtime/Planets/Rulesets/AtmosphereOverrideRuleset.cs.meta b/Runtime/Planets/Rulesets/AtmosphereOverrideRuleset.cs.meta
new file mode 100644
index 0000000..ce8d00a
--- /dev/null
+++ b/Runtime/Planets/Rulesets/AtmosphereOverrideRuleset.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: baf197aecc8b90c4398c64fdec3051ee
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Rulesets/CelestialBodyRuleset.cs b/Runtime/Planets/Rulesets/CelestialBodyRuleset.cs
new file mode 100644
index 0000000..2f92d7b
--- /dev/null
+++ b/Runtime/Planets/Rulesets/CelestialBodyRuleset.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using KSP.Sim.Definitions;
+using Newtonsoft.Json.Linq;
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Attributes;
+using PatchManager.SassyPatching.Interfaces;
+using PatchManager.SassyPatching.NewAssets;
+using PatchManager.Planets.Selectables;
+
+namespace PatchManager.Planets.Rulesets
+{
+ [PatcherRuleset("body","celestial_bodies")]
+ public class CelestialBodyRuleset : IPatcherRuleSet
+ {
+ public bool Matches(string label) => label == "celestial_bodies";
+
+ public ISelectable ConvertToSelectable(string type, string name, string jsonData) =>
+ new CelestialBodySelectable(JObject.Parse(jsonData));
+
+ public INewAsset CreateNew(List dataValues)
+ {
+ var bodyName = dataValues[0].String;
+ var core = new CelestialBodyCore
+ {
+ version = CelestialBodyCore.CELESTIAL_BODY_SERIALIZATION_VERSION,
+ data = new CelestialBodyData
+ {
+ bodyName = bodyName
+ }
+ };
+ return new NewGenericAsset("celestial_bodies", "bodyName",
+ new CelestialBodySelectable(JObject.FromObject(core)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Rulesets/CelestialBodyRuleset.cs.meta b/Runtime/Planets/Rulesets/CelestialBodyRuleset.cs.meta
new file mode 100644
index 0000000..418dc50
--- /dev/null
+++ b/Runtime/Planets/Rulesets/CelestialBodyRuleset.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 41c8895da2477ec448567e1fbbe52adb
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Rulesets/GalaxyRuleset.cs b/Runtime/Planets/Rulesets/GalaxyRuleset.cs
new file mode 100644
index 0000000..b927bcb
--- /dev/null
+++ b/Runtime/Planets/Rulesets/GalaxyRuleset.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using KSP.Sim;
+using Newtonsoft.Json.Linq;
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Attributes;
+using PatchManager.SassyPatching.Interfaces;
+using PatchManager.SassyPatching.NewAssets;
+using PatchManager.Planets.Selectables;
+
+namespace PatchManager.Planets.Rulesets
+{
+ ///
+ [PatcherRuleset("galaxy", "GalaxyDefinition_Default")]
+ public class GalaxyRuleset : IPatcherRuleSet
+ {
+ ///
+ public bool Matches(string label) => true;
+
+ ///
+ public ISelectable ConvertToSelectable(string type, string name, string jsonData)
+ {
+ var obj = JObject.Parse(jsonData);
+ if (!obj.ContainsKey("Name") || !obj.ContainsKey("Version") || !obj.ContainsKey("CelestialBodies"))
+ return null;
+ return new GalaxySelectable(obj, type);
+
+ }
+ ///
+ public INewAsset CreateNew(List dataValues)
+ {
+ var name = dataValues[0].String;
+ var version = dataValues.Count > 1 ? dataValues[1].String : "1.0.0";
+ var def = new SerializedGalaxyDefinition
+ {
+ Name = name,
+ Version = version,
+ CelestialBodies = new List()
+ };
+ return new NewGenericAsset(name, name, new GalaxySelectable(JObject.FromObject(def), name));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Rulesets/GalaxyRuleset.cs.meta b/Runtime/Planets/Rulesets/GalaxyRuleset.cs.meta
new file mode 100644
index 0000000..baf870f
--- /dev/null
+++ b/Runtime/Planets/Rulesets/GalaxyRuleset.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fd770653019970b4fb19958ff71c9bc6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Rulesets/VolumeCloudOverrideRuleset.cs b/Runtime/Planets/Rulesets/VolumeCloudOverrideRuleset.cs
new file mode 100644
index 0000000..118457f
--- /dev/null
+++ b/Runtime/Planets/Rulesets/VolumeCloudOverrideRuleset.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Attributes;
+using PatchManager.SassyPatching.Interfaces;
+using PatchManager.SassyPatching.NewAssets;
+using PatchManager.Planets.Overrides;
+using PatchManager.Planets.Selectables;
+
+namespace PatchManager.Planets.Rulesets
+{
+ [PatcherRuleset("volume-cloud-override","volume_cloud_overrides")]
+ public class VolumeCloudOverrideRuleset : IPatcherRuleSet
+ {
+ public bool Matches(string label) => label == "volume_cloud_overrides";
+
+ public ISelectable ConvertToSelectable(string type, string name, string jsonData) => new VolumeCloudSelectable(JObject.Parse(jsonData));
+
+ public INewAsset CreateNew(List dataValues)
+ {
+ var planetName = dataValues[0].String.ToLowerInvariant();
+ var data = new VolumeCloudConfigurationOverride
+ {
+ bodyName = planetName
+ };
+ return new NewGenericAsset("volume_cloud_overrides", $"volume_cloud_override_{planetName}",
+ new VolumeCloudSelectable(JObject.FromObject(data)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Rulesets/VolumeCloudOverrideRuleset.cs.meta b/Runtime/Planets/Rulesets/VolumeCloudOverrideRuleset.cs.meta
new file mode 100644
index 0000000..2452e49
--- /dev/null
+++ b/Runtime/Planets/Rulesets/VolumeCloudOverrideRuleset.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4078d6870f426d84893ece9d0dd8a4ce
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Selectables.meta b/Runtime/Planets/Selectables.meta
new file mode 100644
index 0000000..4ff7a71
--- /dev/null
+++ b/Runtime/Planets/Selectables.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 60bc3af38d56af143b8c4fb7d5cf6a7a
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Selectables/AtmosphereOverrideSelectable.cs b/Runtime/Planets/Selectables/AtmosphereOverrideSelectable.cs
new file mode 100644
index 0000000..ab1d959
--- /dev/null
+++ b/Runtime/Planets/Selectables/AtmosphereOverrideSelectable.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Interfaces;
+using PatchManager.Planets.Modifiables;
+
+namespace PatchManager.Planets.Selectables
+{
+ public sealed class AtmosphereOverrideSelectable : BaseSelectable
+ {
+ #pragma warning disable CS0414 // Field is assigned but its value is never used
+ private bool _modified;
+ #pragma warning restore CS0414 // Field is assigned but its value is never used
+ private bool _deleted;
+
+ ///
+ /// Marks this part selectable as having been modified any level down
+ ///
+ public void SetModified()
+ {
+ _modified = true;
+ }
+
+ ///
+ /// Marks this part as goneso
+ ///
+ public void SetDeleted()
+ {
+ SetModified();
+ _deleted = true;
+ }
+
+ public readonly JObject AtmosphereOverrideObject;
+
+ public AtmosphereOverrideSelectable(JObject atmosphereOverrideObject)
+ {
+ Children = new List();
+ Classes = new List();
+ ElementType = "atmosphere_override";
+ AtmosphereOverrideObject = atmosphereOverrideObject;
+ Name = atmosphereOverrideObject["PlanetName"].Value();
+ foreach (var (key, child) in atmosphereOverrideObject)
+ {
+ Classes.Add(key);
+ }
+ }
+
+ ///
+ public override List Children { get; }
+
+ ///
+ public override string Name { get; }
+
+ ///
+ public override List Classes { get; }
+
+ public override bool MatchesClass(string @class, out DataValue classValue) =>
+ throw new Exception("Class capture selectors are not allowed on atmosphere overrides");
+
+ ///
+ public override bool IsSameAs(ISelectable other) =>
+ other is AtmosphereOverrideSelectable atmosphereOverrideSelectable && atmosphereOverrideSelectable.AtmosphereOverrideObject == AtmosphereOverrideObject;
+
+ ///
+ public override IModifiable OpenModification() => new AtmosphereOverrideModifiable(this);
+
+ public override ISelectable AddElement(string elementType) =>
+ throw new Exception("Adding elements to atmosphere overrides is not allowed");
+ ///
+ public override string Serialize() => _deleted ? "" : AtmosphereOverrideObject.ToString();
+
+ ///
+ public override DataValue GetValue() => DataValue.FromJToken(AtmosphereOverrideObject);
+ public override string ElementType { get; }
+ }
+}
+
diff --git a/Runtime/Planets/Selectables/AtmosphereOverrideSelectable.cs.meta b/Runtime/Planets/Selectables/AtmosphereOverrideSelectable.cs.meta
new file mode 100644
index 0000000..fd02921
--- /dev/null
+++ b/Runtime/Planets/Selectables/AtmosphereOverrideSelectable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d07bb5f027a0e5141922cdc0c6981e97
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Selectables/CelestialBodySelectable.cs b/Runtime/Planets/Selectables/CelestialBodySelectable.cs
new file mode 100644
index 0000000..de17918
--- /dev/null
+++ b/Runtime/Planets/Selectables/CelestialBodySelectable.cs
@@ -0,0 +1,87 @@
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Interfaces;
+using PatchManager.SassyPatching.Selectables;
+using PatchManager.Planets.Modifiables;
+
+namespace PatchManager.Planets.Selectables
+{
+ public sealed class CelestialBodySelectable : BaseSelectable
+ {
+ #pragma warning disable CS0414 // Field is assigned but its value is never used
+ private bool _modified;
+ #pragma warning restore CS0414 // Field is assigned but its value is never used
+ private bool _deleted;
+
+ ///
+ /// Marks this part selectable as having been modified any level down
+ ///
+ public void SetModified()
+ {
+ _modified = true;
+ }
+
+ ///
+ /// Marks this part as goneso
+ ///
+ public void SetDeleted()
+ {
+ SetModified();
+ _deleted = true;
+ }
+
+ public JObject CelestialBodyObject;
+ public JObject DataObject;
+
+ public CelestialBodySelectable(JObject celestialBodyObject)
+ {
+ ElementType = "celestial_body";
+ CelestialBodyObject = celestialBodyObject;
+ DataObject = (JObject)celestialBodyObject["data"];
+ Classes = new List();
+ Children = new List();
+ foreach (var subToken in DataObject)
+ {
+ Classes.Add(subToken.Key);
+ Children.Add(new JTokenSelectable(SetModified,subToken.Value,subToken.Key));
+ }
+ }
+
+ public override bool MatchesClass(string @class, out DataValue classValue)
+ {
+ classValue = null;
+ if (!MatchesClass(@class))
+ {
+ return false;
+ }
+
+ classValue = DataValue.FromJToken(DataObject[@class]);
+ return true;
+ }
+
+ public override bool IsSameAs(ISelectable other) => other is CelestialBodySelectable selectable &&
+ selectable.CelestialBodyObject == CelestialBodyObject;
+
+ public override IModifiable OpenModification() => new CelestialBodyModifiable(this);
+
+ public override ISelectable AddElement(string elementType)
+ {
+ var obj = new JObject();
+ DataObject[elementType] = obj;
+ var n = new JTokenSelectable(SetModified, obj, elementType);
+ Children.Add(n);
+ return n;
+ }
+
+ public override string Serialize() => _deleted ? "" : CelestialBodyObject.ToString();
+
+ public override DataValue GetValue() => DataValue.FromJToken(DataObject);
+
+ public override List Children { get; }
+ public override string Name => DataObject["bodyName"]!.Value();
+ public override List Classes { get; }
+ public override string ElementType { get; }
+ }
+}
+
diff --git a/Runtime/Planets/Selectables/CelestialBodySelectable.cs.meta b/Runtime/Planets/Selectables/CelestialBodySelectable.cs.meta
new file mode 100644
index 0000000..e4867d2
--- /dev/null
+++ b/Runtime/Planets/Selectables/CelestialBodySelectable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3c8001b308deab4488a65a2b4052d46f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Selectables/GalaxySelectable.cs b/Runtime/Planets/Selectables/GalaxySelectable.cs
new file mode 100644
index 0000000..b046f0e
--- /dev/null
+++ b/Runtime/Planets/Selectables/GalaxySelectable.cs
@@ -0,0 +1,122 @@
+using System.Collections.Generic;
+using KSP.Sim;
+using Newtonsoft.Json.Linq;
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Interfaces;
+using PatchManager.SassyPatching.Selectables;
+using PatchManager.Planets.Modifiables;
+
+namespace PatchManager.Planets.Selectables
+{
+ public sealed class GalaxySelectable : BaseSelectable
+ {
+ #pragma warning disable CS0414 // Field is assigned but its value is never used
+ private bool _modified;
+ #pragma warning restore CS0414 // Field is assigned but its value is never used
+ private bool _deleted;
+
+ ///
+ /// Marks this part selectable as having been modified any level down
+ ///
+ public void SetModified()
+ {
+ _modified = true;
+ }
+
+ ///
+ /// Marks this part as goneso
+ ///
+ public void SetDeleted()
+ {
+ SetModified();
+ _deleted = true;
+ }
+
+ ///
+ /// This is the object that represents the galaxy definition
+ ///
+ public readonly JObject GalaxyObject;
+ ///
+ ///
+ ///
+ ///
+ ///
+ public GalaxySelectable(JObject galaxyObject, string elementType)
+ {
+ GalaxyObject = galaxyObject;
+ ElementType = elementType;
+ Name = galaxyObject["Name"].Value();
+ Children = new List();
+ Classes = new List();
+ var bodies = (JArray)GalaxyObject["CelestialBodies"];
+ foreach (var jToken in bodies)
+ {
+ var body = (JObject)jToken;
+ var name = body["GUID"]!.Value();
+ Classes.Add(name);
+ Children.Add(new JTokenSelectable(SetModified, body, token => ((JObject)token).Value(), "planet"));
+ }
+ }
+
+ ///
+ public override List Children { get; }
+
+ ///
+ public override string Name { get; }
+
+ ///
+ public override List Classes { get; }
+
+ ///
+ public override bool MatchesClass(string @class, out DataValue classValue)
+ {
+ var bodies = (JArray)GalaxyObject["CelestialBodies"];
+ foreach (var jToken in bodies!)
+ {
+ var body = (JObject)jToken;
+ var name = body["GUID"]!.Value();
+ if (name != @class)
+ {
+ continue;
+ }
+ classValue = DataValue.FromJToken(body);
+ return true;
+ }
+ classValue = DataValue.Null;
+ return false;
+ }
+
+ ///
+ public override bool IsSameAs(ISelectable other) =>
+ other is GalaxySelectable galaxySelectable && galaxySelectable.GalaxyObject == GalaxyObject;
+
+ ///
+ public override IModifiable OpenModification() => new GalaxyModifiable(this);
+
+ ///
+ public override ISelectable AddElement(string elementType)
+ {
+ var obj = new SerializedCelestialBody
+ {
+ GUID = elementType,
+ OrbitProperties = new SerializedOrbitProperties(),
+ OrbiterProperties = new SerializedOribiterDefinition()
+ };
+ var jToken = JObject.FromObject(obj);
+ Classes.Add(elementType);
+ var selectable = new JTokenSelectable(SetModified, jToken, token => ((JObject)token).Value(), "planet");
+ Children.Add(selectable);
+ return selectable;
+ }
+
+ ///
+ public override string Serialize() => _deleted ? "" : GalaxyObject.ToString();
+
+ ///
+ public override DataValue GetValue() => DataValue.FromJToken(GalaxyObject);
+
+ ///
+ public override string ElementType { get; }
+ }
+}
+
diff --git a/Runtime/Planets/Selectables/GalaxySelectable.cs.meta b/Runtime/Planets/Selectables/GalaxySelectable.cs.meta
new file mode 100644
index 0000000..d57fd3f
--- /dev/null
+++ b/Runtime/Planets/Selectables/GalaxySelectable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 288eb2453d8b8b54596a6be096f22d74
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Selectables/VolumeCloudSelectable.cs b/Runtime/Planets/Selectables/VolumeCloudSelectable.cs
new file mode 100644
index 0000000..9da1b0e
--- /dev/null
+++ b/Runtime/Planets/Selectables/VolumeCloudSelectable.cs
@@ -0,0 +1,108 @@
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using PatchManager.SassyPatching;
+using PatchManager.SassyPatching.Interfaces;
+using PatchManager.SassyPatching.Selectables;
+using PatchManager.Planets.Modifiables;
+using PatchManager.Planets.Overrides;
+
+namespace PatchManager.Planets.Selectables
+{
+ public sealed class VolumeCloudSelectable : BaseSelectable
+ {
+ #pragma warning disable CS0414 // Field is assigned but its value is never used
+ private bool _modified;
+ #pragma warning restore CS0414 // Field is assigned but its value is never used
+ private bool _deleted;
+
+ ///
+ /// Marks this part selectable as having been modified any level down///
+ ///
+ public void SetModified()
+ {
+ _modified = true;
+ }
+
+ ///
+ /// Marks this part as goneso
+ ///
+ public void SetDeleted()
+ {
+ SetModified();
+ _deleted = true;
+ }
+
+ public readonly JObject VolumeCloudOverrideObject;
+
+ public VolumeCloudSelectable(JObject volumeCloudOverrideObject)
+ {
+ Children = new List();
+ Classes = new List();
+ ElementType = "volume_cloud_override";
+ VolumeCloudOverrideObject = volumeCloudOverrideObject;
+ Name = volumeCloudOverrideObject["bodyName"].Value();
+ foreach (var (key, child) in volumeCloudOverrideObject)
+ {
+ Classes.Add(key);
+ }
+
+ foreach (var child in (JArray)volumeCloudOverrideObject["cumulusList"])
+ {
+ var obj = (JObject)child;
+ var name = obj["layerName"]!.Value();
+ Classes.Add(name);
+ Children.Add(new JTokenSelectable(SetModified, child, name, "cloud_data"));
+ }
+ }
+
+ ///
+ public override List Children { get; }
+
+ ///
+ public override string Name { get; }
+
+ ///
+ public override List Classes { get; }
+
+ public override bool MatchesClass(string @class, out DataValue classValue)
+ {
+ foreach (var value in (JArray)VolumeCloudOverrideObject["cumulusList"]!)
+ {
+ if (((JObject)value)["layerName"]!.Value() != @class) continue;
+ classValue = DataValue.FromJToken(value);
+ return true;
+ }
+
+ classValue = DataValue.Null;
+ return false;
+ }
+
+ ///
+ public override bool IsSameAs(ISelectable other) =>
+ other is VolumeCloudSelectable volumeCloudSelectable && volumeCloudSelectable.VolumeCloudOverrideObject == VolumeCloudOverrideObject;
+
+ ///
+ public override IModifiable OpenModification() => new VolumeCloudOverrideModifiable(this);
+
+ public override ISelectable AddElement(string elementType)
+ {
+ var newLayer = new CloudsDataOverride
+ {
+ layerName = elementType
+ };
+ var obj = JObject.FromObject(newLayer);
+ ((JArray)VolumeCloudOverrideObject["cumulusList"])!.Add(obj);
+ var selectable = new JTokenSelectable(SetModified, obj, elementType, "cloud_data");
+ Children.Add(selectable);
+ Classes.Add(elementType);
+ return selectable;
+ }
+ ///
+ public override string Serialize() => _deleted ? "" : VolumeCloudOverrideObject.ToString();
+
+ ///
+ public override DataValue GetValue() => DataValue.FromJToken(VolumeCloudOverrideObject);
+ public override string ElementType { get; }
+ }
+}
+
diff --git a/Runtime/Planets/Selectables/VolumeCloudSelectable.cs.meta b/Runtime/Planets/Selectables/VolumeCloudSelectable.cs.meta
new file mode 100644
index 0000000..de49019
--- /dev/null
+++ b/Runtime/Planets/Selectables/VolumeCloudSelectable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f2e1fb14766ae8648b6a7ce857baf144
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Utility.meta b/Runtime/Planets/Utility.meta
new file mode 100644
index 0000000..b39d3f4
--- /dev/null
+++ b/Runtime/Planets/Utility.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 10aa8fe93f60d6c4daceb1a3e0617e5c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Planets/Utility/Extensions.cs b/Runtime/Planets/Utility/Extensions.cs
new file mode 100644
index 0000000..784feaa
--- /dev/null
+++ b/Runtime/Planets/Utility/Extensions.cs
@@ -0,0 +1,10 @@
+namespace PatchManager.Planets.Utility
+{
+ public static class Extensions
+ {
+ public static void Apply(this T? optional, ref T value) where T : struct
+ {
+ if (optional.HasValue) value = optional.Value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Planets/Utility/Extensions.cs.meta b/Runtime/Planets/Utility/Extensions.cs.meta
new file mode 100644
index 0000000..61237eb
--- /dev/null
+++ b/Runtime/Planets/Utility/Extensions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7bbd5a678e1094f46bd08e5bc9df1124
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/scripts.meta b/scripts.meta
new file mode 100644
index 0000000..b4940c9
--- /dev/null
+++ b/scripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8df77cd1c0647eb42b2a99b94d9ca4bc
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/scripts/build-debug.bat.meta b/scripts/build-debug.bat.meta
new file mode 100644
index 0000000..480f5c2
--- /dev/null
+++ b/scripts/build-debug.bat.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 4a7a0e4acbccb1a4caa7fdb84a555126
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/scripts/build-deploy.bat.meta b/scripts/build-deploy.bat.meta
new file mode 100644
index 0000000..3a58f41
--- /dev/null
+++ b/scripts/build-deploy.bat.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 87fc39df0da462e48b848880607a85e0
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/scripts/build-release.bat.meta b/scripts/build-release.bat.meta
new file mode 100644
index 0000000..3a3166e
--- /dev/null
+++ b/scripts/build-release.bat.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 50b54e87fd268044e91485eaebb51026
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/scripts/build-run.bat.meta b/scripts/build-run.bat.meta
new file mode 100644
index 0000000..28e95e9
--- /dev/null
+++ b/scripts/build-run.bat.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 279e34adeb4744244b47f7bdaa8f46db
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant: