diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index efc126df6..afb289bfd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -202,6 +202,7 @@ public class Config + "Lowest Quality: " + EDhApiMaxHorizontalResolution.CHUNK + "\n" + "Highest Quality: " + EDhApiMaxHorizontalResolution.BLOCK) .setPerformance(EConfigEntryPerformance.MEDIUM) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry verticalQuality = new ConfigEntry.Builder() @@ -215,7 +216,7 @@ public class Config + "Lowest Quality: " + EDhApiVerticalQuality.HEIGHT_MAP + "\n" + "Highest Quality: " + EDhApiVerticalQuality.EXTREME) .setPerformance(EConfigEntryPerformance.VERY_HIGH) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry transparency = new ConfigEntry.Builder() @@ -228,7 +229,7 @@ public class Config + EDhApiTransparency.DISABLED + ": LODs will be opaque. \n" + "") .setPerformance(EConfigEntryPerformance.MEDIUM) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry blocksToIgnore = new ConfigEntry.Builder() @@ -240,7 +241,7 @@ public class Config + EDhApiBlocksToAvoid.NON_COLLIDING + ": Only represent solid blocks in the LODs (tall grass, torches, etc. won't count for a LOD's height) \n" + "") .setPerformance(EConfigEntryPerformance.NONE) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry tintWithAvoidedBlocks = new ConfigEntry.Builder() @@ -252,7 +253,7 @@ public class Config + "False: skipped blocks will not change color of surface below them. " + "") .setPerformance(EConfigEntryPerformance.NONE) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry lodBias = new ConfigEntry.Builder() @@ -273,7 +274,7 @@ public class Config + EDhApiLodShading.DISABLED + ": All LOD sides will be rendered with the same brightness. \n" + "") .setPerformance(EConfigEntryPerformance.NONE) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry grassSideRendering = new ConfigEntry.Builder() @@ -286,7 +287,7 @@ public class Config + EDhApiGrassSideRendering.AS_DIRT + ": sides render entirely as dirt. \n" + "") .setPerformance(EConfigEntryPerformance.NONE) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry ditherDhFade = new ConfigEntry.Builder() @@ -319,7 +320,7 @@ public class Config + "0 = black \n" + "1 = normal \n" + "2 = near white") - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry saturationMultiplier = new ConfigEntry.Builder() // TODO: Make this a float (the ClassicConfigGUI doesnt support floats) @@ -330,7 +331,7 @@ public class Config + "0 = black and white \n" + "1 = normal \n" + "2 = very saturated") - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); // TODO fixme @@ -690,7 +691,7 @@ public class Config public static class Culling { public static ConfigEntry overdrawPrevention = new ConfigEntry.Builder() - .setMinDefaultMax(0.0, 0.0, 1.0) + .setMinDefaultMax(0.0, 0.0, 1.0) // TODO change -1 to auto .comment("" + "Determines how far from the camera Distant Horizons will start rendering. \n" + "Measured as a percentage of the vanilla render distance.\n" @@ -717,7 +718,7 @@ public class Config + " Tweaking the caveCullingHeight, can resolve some \n" + " of those issues. \n" + "") - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry caveCullingHeight = new ConfigEntry.Builder() @@ -725,7 +726,7 @@ public class Config .comment("" + "At what Y value should cave culling start? \n" + "Lower this value if you get walls for areas with 0 light.") - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry disableBeaconDistanceCulling = new ConfigEntry.Builder() @@ -898,6 +899,7 @@ public class Config + EDhApiDebugRendering.SHOW_BLOCK_MATERIAL + ": LODs' color will be based on their material. \n" + EDhApiDebugRendering.SHOW_OVERLAPPING_QUADS + ": LODs will be drawn with total white, but overlapping quads will be drawn with red. \n" + "") + .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .build(); public static ConfigEntry lodOnlyMode = new ConfigEntry.Builder() @@ -1064,38 +1066,38 @@ public class Config public static ConfigEntry columnBuilderDebugEnable = new ConfigEntry.Builder() .set(false) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.INSTANT_INSTANCE) .build(); public static ConfigEntry columnBuilderDebugDetailLevel = new ConfigEntry.Builder() .set((int) DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.INSTANT_INSTANCE) .build(); public static ConfigEntry columnBuilderDebugXPos = new ConfigEntry.Builder() .set(0) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.INSTANT_INSTANCE) .build(); public static ConfigEntry columnBuilderDebugZPos = new ConfigEntry.Builder() .set(0) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.INSTANT_INSTANCE) .build(); public static ConfigEntry columnBuilderDebugXRow = new ConfigEntry.Builder() .set(-1) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.INSTANT_INSTANCE) .build(); public static ConfigEntry columnBuilderDebugZRow = new ConfigEntry.Builder() .set(-1) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.INSTANT_INSTANCE) .build(); public static ConfigEntry columnBuilderDebugColumnIndex = new ConfigEntry.Builder() .set(-1) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) - .addListener(ReloadLodsConfigEventHandler.INSTANCE) + .addListener(ReloadLodsConfigEventHandler.INSTANT_INSTANCE) .build(); } @@ -1777,7 +1779,6 @@ public class Config RenderQualityPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); QuickRenderToggleConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); QuickShowWorldGenProgressConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); - RenderCacheConfigEventHandler.getInstance(); } catch (Exception e) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/ReloadLodsConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/ReloadLodsConfigEventHandler.java index b209f3de3..66653c25a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/ReloadLodsConfigEventHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/ReloadLodsConfigEventHandler.java @@ -22,13 +22,77 @@ package com.seibel.distanthorizons.core.config.eventHandlers; import com.seibel.distanthorizons.api.DhApi; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy; import com.seibel.distanthorizons.core.config.listeners.IConfigListener; +import com.seibel.distanthorizons.core.util.TimerUtil; + +import java.util.Timer; +import java.util.TimerTask; public class ReloadLodsConfigEventHandler implements IConfigListener { - public static ReloadLodsConfigEventHandler INSTANCE = new ReloadLodsConfigEventHandler(); + /** + * should be used for user facing UI options + * this allows the user a second to click through options before they're applied + */ + public static ReloadLodsConfigEventHandler DELAYED_INSTANCE = new ReloadLodsConfigEventHandler(2_000L); + /** should be used for debug options so their change can be seen instantly */ + public static ReloadLodsConfigEventHandler INSTANT_INSTANCE = new ReloadLodsConfigEventHandler(0); + + /** how long to wait in milliseconds before applying the config changes */ + private final long timeoutInMs; + private Timer cacheClearingTimer; + + + + //=============// + // constructor // + //=============// + + public ReloadLodsConfigEventHandler(long timeoutInMs) + { + this.timeoutInMs = timeoutInMs; + } + + + + //========// + // events // + //========// @Override public void onConfigValueSet() + { + if (this.timeoutInMs > 0) + { + this.refreshRenderDataAfterTimeout(); + } + else + { + clearRenderDataCache(); + } + } + + /** Calling this method multiple times will reset the timer */ + private synchronized void refreshRenderDataAfterTimeout() // synchronized to prevent potential threading issues when adding/removing the timer + { + // stop the previous timer if one exists + if (this.cacheClearingTimer != null) + { + this.cacheClearingTimer.cancel(); + } + + // create a new timer task + TimerTask timerTask = new TimerTask() + { + public void run() + { + clearRenderDataCache(); + } + }; + this.cacheClearingTimer = TimerUtil.CreateTimer("RenderCacheClearConfigTimer"); + this.cacheClearingTimer.schedule(timerTask, this.timeoutInMs); + } + + private static void clearRenderDataCache() { IDhApiRenderProxy renderProxy = DhApi.Delayed.renderProxy; if (renderProxy != null) @@ -37,4 +101,5 @@ public class ReloadLodsConfigEventHandler implements IConfigListener } } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java deleted file mode 100644 index d208f2d02..000000000 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * This file is part of the Distant Horizons mod - * licensed under the GNU LGPL v3 License. - * - * Copyright (C) 2020 James Seibel - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.seibel.distanthorizons.core.config.eventHandlers; - -import com.seibel.distanthorizons.api.DhApi; -import com.seibel.distanthorizons.api.enums.config.*; -import com.seibel.distanthorizons.api.enums.rendering.EDhApiDebugRendering; -import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency; -import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener; -import com.seibel.distanthorizons.core.config.Config; -import com.seibel.distanthorizons.core.util.TimerUtil; - -import java.util.Timer; -import java.util.TimerTask; - -/** - * Listens to the config and will automatically - * clear the current render cache if certain settings are changed.

- * - * Note: if additional settings should clear the render cache, add those to this listener, don't create a new listener - */ -public class RenderCacheConfigEventHandler -{ - private static RenderCacheConfigEventHandler INSTANCE; - - - // previous values used to check if a watched setting was actually modified - private final ConfigChangeListener horizontalResolutionChangeListener; - private final ConfigChangeListener verticalQualityChangeListener; - private final ConfigChangeListener transparencyChangeListener; - private final ConfigChangeListener blocksToIgnoreChangeListener; - private final ConfigChangeListener tintWithAvoidedBlocksChangeListener; - - private final ConfigChangeListener brightnessMultiplierChangeListener; - private final ConfigChangeListener saturationMultiplierChangeListener; - private final ConfigChangeListener lodShadingChangeListener; - private final ConfigChangeListener grassSideChangeListener; - - private final ConfigChangeListener debugRenderingChangeListener; - - /** how long to wait in milliseconds before applying the config changes */ - private static final long TIMEOUT_IN_MS = 4_000L; - private Timer cacheClearingTimer; - - - - public static RenderCacheConfigEventHandler getInstance() - { - if (INSTANCE == null) - { - INSTANCE = new RenderCacheConfigEventHandler(); - } - - return INSTANCE; - } - - /** private since we only ever need one handler at a time */ - private RenderCacheConfigEventHandler() - { - this.horizontalResolutionChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.maxHorizontalResolution, (newValue) -> this.refreshRenderDataAfterTimeout()); - this.verticalQualityChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.verticalQuality, (newValue) -> this.refreshRenderDataAfterTimeout()); - this.transparencyChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.transparency, (newValue) -> this.refreshRenderDataAfterTimeout()); - this.blocksToIgnoreChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.blocksToIgnore, (newValue) -> this.refreshRenderDataAfterTimeout()); - this.tintWithAvoidedBlocksChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.tintWithAvoidedBlocks, (newValue) -> this.refreshRenderDataAfterTimeout()); - - this.brightnessMultiplierChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.brightnessMultiplier, (newValue) -> this.refreshRenderDataAfterTimeout()); - this.saturationMultiplierChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.saturationMultiplier, (newValue) -> this.refreshRenderDataAfterTimeout()); - this.lodShadingChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.lodShading, (newValue) -> this.refreshRenderDataAfterTimeout()); - this.grassSideChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.grassSideRendering, (newValue) -> this.refreshRenderDataAfterTimeout()); - - this.debugRenderingChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Debugging.debugRendering, (newValue) -> this.refreshRenderDataAfterTimeout()); - - } - - - /** Calling this method multiple times will reset the timer */ - private void refreshRenderDataAfterTimeout() - { - // stop the previous timer if one exists - if (this.cacheClearingTimer != null) - { - this.cacheClearingTimer.cancel(); - } - - // create a new timer task - TimerTask timerTask = new TimerTask() - { - public void run() - { - DhApi.Delayed.renderProxy.clearRenderDataCache(); - } - }; - this.cacheClearingTimer = TimerUtil.CreateTimer("RenderCacheClearConfigTimer"); - this.cacheClearingTimer.schedule(timerTask, TIMEOUT_IN_MS); - } - -}