// Near Infinity - An Infinity Engine Browser and Editor // Copyright (C) 2001 - 2005 Jon Olav Hauglid // See LICENSE.txt for license information package org.infinity.resource.are.viewer; import java.util.ArrayList; import java.util.List; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import org.infinity.resource.are.viewer.ViewerConstants.LayerStackingType; import org.infinity.resource.are.viewer.ViewerConstants.LayerType; /** * Manages global area viewer settings. */ public class Settings { // Default layer order on map public static final ViewerConstants.LayerStackingType[] DefaultLayerOrder = { ViewerConstants.LayerStackingType.ACTOR, ViewerConstants.LayerStackingType.ENTRANCE, ViewerConstants.LayerStackingType.AMBIENT, ViewerConstants.LayerStackingType.ANIMATION, ViewerConstants.LayerStackingType.AUTOMAP, ViewerConstants.LayerStackingType.SPAWN_POINT, ViewerConstants.LayerStackingType.PRO_TRAP, ViewerConstants.LayerStackingType.CONTAINER, ViewerConstants.LayerStackingType.REGION, ViewerConstants.LayerStackingType.DOOR, ViewerConstants.LayerStackingType.DOOR_POLY, ViewerConstants.LayerStackingType.WALL_POLY, ViewerConstants.LayerStackingType.AMBIENT_RANGE, ViewerConstants.LayerStackingType.TRANSITION }; public static final String[] LabelZoomFactor = {"Auto-fit", "25%", "33%", "50%", "100%", "200%", "300%", "400%"}; public static final double[] ItemZoomFactor = {0.0, 0.25, 1.0/3.0, 0.5, 1.0, 2.0, 3.0, 4.0}; public static final int ZoomFactorIndexAuto = 0; // points to the auto-fit zoom factor public static final int ZoomFactorIndexDefault = 4; // points to the default zoom factor (1x) // Defines stacking order of layer items on the map public static final List<ViewerConstants.LayerStackingType> ListLayerOrder = getDefaultLayerOrder(); // Indicates whether to store settings on disk public static boolean StoreVisualSettings = getDefaultStoreVisualSettings(); // Current open/closed state of door tiles and structures public static boolean DrawClosed = getDefaultDrawClosed(); // Current visibility state of overlays public static boolean DrawOverlays = getDefaultDrawOverlays(); // Current visibility state of the tile grid public static boolean DrawGrid = getDefaultDrawGrid(); // Current visibility state of ambient range items public static boolean ShowAmbientRanges = getDefaultAmbientRanges(); // Defines whether to ignore time schedules on layer items public static boolean EnableSchedules = getDefaultEnableSchedules(); // Defines whether to ignore the "Is shown" flag of background animations public static boolean OverrideAnimVisibility = getDefaultOverrideAnimVisibility(); // Bitmask that controls the collapsed/expanded state of the sidebar controls public static int SidebarControls = getDefaultSidebarControls(); // Indicates whether to show frames around real background animations all the time public static int ShowFrame = getDefaultShowFrame(); // Interpolation state of map tileset public static int InterpolationMap = getDefaultInterpolationMap(); // Interpolation state of real background animations public static int InterpolationAnim = getDefaultInterpolationAnim(); // Bitmask defining the enabled state of layer items public static int LayerFlags = getDefaultLayerFlags(); // The visibility state of real background animations (icons/still/animated) public static int ShowRealAnimations = getDefaultShowRealAnimations(); // The current time of day (in hours) public static int TimeOfDay = getDefaultTimeOfDay(); // The current zoom level of the map (as combobox item index) public static int ZoomLevel = getDefaultZoomLevel(); // The frame rate for animated overlays public static double FrameRateOverlays = getDefaultFrameRateOverlays(); // The frame rate for animated background animations public static double FrameRateAnimations = getDefaultFrameRateAnimations(); // The alpha transparency for mini map overlays (search/height/light maps), range: [0.0, 1.0] public static double MiniMapAlpha = getDefaultMiniMapAlpha(); // One of the MAP_XXX constants for minimaps public static int MiniMap = getDefaultMiniMap(); // Preferences keys for specific settings private static final String PREFS_STORESETTINGS = "StoreSettings"; private static final String PREFS_DRAWCLOSED = "DrawClosed"; private static final String PREFS_DRAWOVERLAYS = "DrawOverlays"; private static final String PREFS_DRAWGRID = "DrawGrid"; private static final String PREFS_SIDEBARCONTROLS = "SidebarControls"; private static final String PREFS_SHOWFRAME = "ShowFrame"; private static final String PREFS_SHOWAMBIENT = "ShowAmbientRanges"; private static final String PREFS_ENABLESCHEDULES = "EnableSchedules"; private static final String PREFS_OVERRIDEANIMVISIBILITY = "OverrideAnimVisibility"; private static final String PREFS_LAYERFLAGS = "LayerFlags"; private static final String PREFS_SHOWREALANIMS = "ShowRealAnimations"; private static final String PREFS_TIMEOFDAY = "TimeOfDay"; private static final String PREFS_ZOOMLEVEL = "ZoomLevel"; private static final String PREFS_LAYERZORDER_FMT = "LayerZOrder%1$d"; private static final String PREFS_INTERPOLATION_MAP = "InterpolationMap"; private static final String PREFS_INTERPOLATION_ANIMS = "InterpolationAnims"; private static final String PREFS_FRAMERATE_OVERLAYS = "FrameRateOverlays"; private static final String PREFS_FRAMERATE_ANIMS = "FrameRateAnims"; private static final String PREFS_MINIMAP_ALPHA = "MiniMapAlpha"; private static final String PREFS_MINIMAP = "MiniMap"; private static boolean SettingsLoaded = false; /** * Loads stored viewer settings from disk if available and the store settings flag is enabled. * @param force If true, overrides the store settings flag and always loads settings from disk. */ public static void loadSettings(boolean force) { if (!SettingsLoaded || force) { Preferences prefs = Preferences.userNodeForPackage(AreaViewer.class); // loading required settings StoreVisualSettings = prefs.getBoolean(PREFS_STORESETTINGS, getDefaultStoreVisualSettings()); OverrideAnimVisibility = prefs.getBoolean(PREFS_OVERRIDEANIMVISIBILITY, getDefaultOverrideAnimVisibility()); ShowFrame = prefs.getInt(PREFS_SHOWFRAME, getDefaultShowFrame()); InterpolationMap = prefs.getInt(PREFS_INTERPOLATION_MAP, getDefaultInterpolationMap()); InterpolationAnim = prefs.getInt(PREFS_INTERPOLATION_ANIMS, getDefaultInterpolationAnim()); FrameRateOverlays = prefs.getDouble(PREFS_FRAMERATE_OVERLAYS, getDefaultFrameRateOverlays()); FrameRateAnimations = prefs.getDouble(PREFS_FRAMERATE_ANIMS, getDefaultFrameRateAnimations()); MiniMapAlpha = prefs.getDouble(PREFS_MINIMAP_ALPHA, getDefaultMiniMapAlpha()); // loading layer z-order ListLayerOrder.clear(); for (int i = 0; i < ViewerConstants.LayerStackingType.values().length; i++) { int idx = prefs.getInt(String.format(PREFS_LAYERZORDER_FMT, i), -1); if (idx >= 0 && idx < ViewerConstants.LayerStackingType.values().length) { ListLayerOrder.add(ViewerConstants.LayerStackingType.values()[idx]); } else { ListLayerOrder.add(DefaultLayerOrder[i]); } } // loading optional settings if (StoreVisualSettings || force) { EnableSchedules = prefs.getBoolean(PREFS_ENABLESCHEDULES, getDefaultEnableSchedules()); DrawClosed = prefs.getBoolean(PREFS_DRAWCLOSED, getDefaultDrawClosed()); DrawOverlays = prefs.getBoolean(PREFS_DRAWOVERLAYS, getDefaultDrawOverlays()); DrawGrid = prefs.getBoolean(PREFS_DRAWGRID, getDefaultDrawGrid()); ShowAmbientRanges = prefs.getBoolean(PREFS_SHOWAMBIENT, getDefaultAmbientRanges()); SidebarControls = prefs.getInt(PREFS_SIDEBARCONTROLS, getDefaultSidebarControls()); LayerFlags = prefs.getInt(PREFS_LAYERFLAGS, getDefaultLayerFlags()); ShowRealAnimations = prefs.getInt(PREFS_SHOWREALANIMS, getDefaultShowRealAnimations()); TimeOfDay = prefs.getInt(PREFS_TIMEOFDAY, getDefaultTimeOfDay()); ZoomLevel = prefs.getInt(PREFS_ZOOMLEVEL, getDefaultZoomLevel()); MiniMap = prefs.getInt(PREFS_MINIMAP, getDefaultMiniMap()); } validateSettings(); SettingsLoaded = true; } } /** * Stores current global viewer settings on disk only if storing settings is enabled. * @param force If true, always stores settings to disk, ignoring the store settings flag. */ public static void storeSettings(boolean force) { validateSettings(); Preferences prefs = Preferences.userNodeForPackage(AreaViewer.class); // storing basic settings prefs.putBoolean(PREFS_STORESETTINGS, StoreVisualSettings); prefs.putBoolean(PREFS_OVERRIDEANIMVISIBILITY, OverrideAnimVisibility); prefs.putInt(PREFS_SHOWFRAME, ShowFrame); prefs.putInt(PREFS_INTERPOLATION_MAP, InterpolationMap); prefs.putInt(PREFS_INTERPOLATION_ANIMS, InterpolationAnim); prefs.putDouble(PREFS_FRAMERATE_OVERLAYS, FrameRateOverlays); prefs.putDouble(PREFS_FRAMERATE_ANIMS, FrameRateAnimations); prefs.putDouble(PREFS_MINIMAP_ALPHA, MiniMapAlpha); // storing layer z-order for (int i = 0; i < ListLayerOrder.size(); i++) { prefs.putInt(String.format(PREFS_LAYERZORDER_FMT, i), getLayerStackingTypeIndex(ListLayerOrder.get(i))); } // storing optional settings if (StoreVisualSettings || force) { prefs.putBoolean(PREFS_ENABLESCHEDULES, EnableSchedules); prefs.putBoolean(PREFS_DRAWCLOSED, DrawClosed); prefs.putBoolean(PREFS_DRAWOVERLAYS, DrawOverlays); prefs.putBoolean(PREFS_DRAWGRID, DrawGrid); prefs.putBoolean(PREFS_SHOWAMBIENT, ShowAmbientRanges); prefs.putInt(PREFS_SIDEBARCONTROLS, SidebarControls); prefs.putInt(PREFS_LAYERFLAGS, LayerFlags); prefs.putInt(PREFS_SHOWREALANIMS, ShowRealAnimations); prefs.putInt(PREFS_TIMEOFDAY, TimeOfDay); prefs.putInt(PREFS_ZOOMLEVEL, ZoomLevel); prefs.putInt(PREFS_MINIMAP, MiniMap); } try { prefs.flush(); } catch (BackingStoreException e) { e.printStackTrace(); } } // Makes sure that all settings are valid private static void validateSettings() { int mask = (1 << LayerManager.getLayerTypeCount()) - 1; LayerFlags &= mask; SidebarControls &= (ViewerConstants.SIDEBAR_VISUALSTATE | ViewerConstants.SIDEBAR_LAYERS | ViewerConstants.SIDEBAR_MINIMAPS); ShowRealAnimations = Math.min(Math.max(ShowRealAnimations, ViewerConstants.ANIM_SHOW_NONE), ViewerConstants.ANIM_SHOW_ANIMATED); TimeOfDay = Math.min(Math.max(TimeOfDay, ViewerConstants.TIME_0), ViewerConstants.TIME_23); ZoomLevel = Math.min(Math.max(ZoomLevel, 0), ItemZoomFactor.length - 1); InterpolationMap = Math.min(Math.max(InterpolationMap, ViewerConstants.FILTERING_AUTO), ViewerConstants.FILTERING_BILINEAR); InterpolationAnim = Math.min(Math.max(InterpolationAnim, ViewerConstants.FILTERING_AUTO), ViewerConstants.FILTERING_BILINEAR); FrameRateOverlays = Math.min(Math.max(FrameRateOverlays, 1.0), 30.0); FrameRateAnimations = Math.min(Math.max(FrameRateAnimations, 1.0), 30.0); MiniMapAlpha = Math.min(Math.max(MiniMapAlpha, 0.0), 1.0); MiniMap = Math.min(Math.max(MiniMap, ViewerConstants.MAP_NONE), ViewerConstants.MAP_HEIGHT); // validating layers z-order mask = 0; // 1. checking for duplicates int i = 0; while (i < ListLayerOrder.size()) { int bit = 1 << getLayerStackingTypeIndex(ListLayerOrder.get(i)); if ((mask & bit) != 0) { ListLayerOrder.remove(i); continue; } else { mask |= bit; } i++; } // 2. adding missing layers for (i = 0; i < ViewerConstants.LayerStackingType.values().length; i++) { int bit = 1 << i; if ((mask & bit) == 0) { ListLayerOrder.add(ViewerConstants.LayerStackingType.values()[i]); } } } public static List<ViewerConstants.LayerStackingType> getDefaultLayerOrder() { List<ViewerConstants.LayerStackingType> list = new ArrayList<ViewerConstants.LayerStackingType>(); for (int i = 0; i < DefaultLayerOrder.length; i++) { list.add(DefaultLayerOrder[i]); } return list; } public static boolean getDefaultStoreVisualSettings() { return false; } public static boolean getDefaultDrawClosed() { return false; } public static boolean getDefaultDrawOverlays() { return true; } public static boolean getDefaultDrawGrid() { return false; } public static boolean getDefaultAmbientRanges() { return false; } public static boolean getDefaultEnableSchedules() { return false; } public static boolean getDefaultOverrideAnimVisibility() { return false; } public static int getDefaultSidebarControls() { return ViewerConstants.SIDEBAR_VISUALSTATE | ViewerConstants.SIDEBAR_LAYERS | ViewerConstants.SIDEBAR_MINIMAPS; } public static int getDefaultShowFrame() { return ViewerConstants.FRAME_AUTO; } public static int getDefaultInterpolationMap() { return ViewerConstants.FILTERING_AUTO; } public static int getDefaultInterpolationAnim() { return ViewerConstants.FILTERING_AUTO; } public static int getDefaultLayerFlags() { return 0; } public static int getDefaultShowRealAnimations() { return ViewerConstants.ANIM_SHOW_NONE; } public static int getDefaultTimeOfDay() { return ViewerConstants.getHourOf(ViewerConstants.LIGHTING_DAY); } public static int getDefaultZoomLevel() { return ZoomFactorIndexDefault; } public static double getDefaultFrameRateOverlays() { return 7.5; } public static double getDefaultFrameRateAnimations() { return 15.0; } public static double getDefaultMiniMapAlpha() { return 0.5; } public static int getDefaultMiniMap() { return ViewerConstants.MAP_NONE; } // Converts values from LayerStackingType to LayerType public static LayerType stackingToLayer(LayerStackingType type) { switch (type) { case ACTOR: return LayerType.ACTOR; case AMBIENT: case AMBIENT_RANGE: return LayerType.AMBIENT; case ANIMATION: return LayerType.ANIMATION; case AUTOMAP: return LayerType.AUTOMAP; case CONTAINER: return LayerType.CONTAINER; case DOOR: return LayerType.DOOR; case DOOR_POLY: return LayerType.DOOR_POLY; case ENTRANCE: return LayerType.ENTRANCE; case PRO_TRAP: return LayerType.PRO_TRAP; case REGION: return LayerType.REGION; case SPAWN_POINT: return LayerType.SPAWN_POINT; case TRANSITION: return LayerType.TRANSITION; case WALL_POLY: return LayerType.WALL_POLY; default: return null; } } // Converts values from LayerType to LayerStackingType (ignoring AmbientRange) public static LayerStackingType layerToStacking(LayerType type) { switch (type) { case ACTOR: return LayerStackingType.ACTOR; case AMBIENT: return LayerStackingType.AMBIENT; case ANIMATION: return LayerStackingType.ANIMATION; case AUTOMAP: return LayerStackingType.AUTOMAP; case CONTAINER: return LayerStackingType.CONTAINER; case DOOR: return LayerStackingType.DOOR; case DOOR_POLY: return LayerStackingType.DOOR_POLY; case ENTRANCE: return LayerStackingType.ENTRANCE; case PRO_TRAP: return LayerStackingType.PRO_TRAP; case REGION: return LayerStackingType.REGION; case SPAWN_POINT: return LayerStackingType.SPAWN_POINT; case TRANSITION: return LayerStackingType.TRANSITION; case WALL_POLY: return LayerStackingType.WALL_POLY; default: return null; } } // Returns the index of the specified enum type public static int getLayerStackingTypeIndex(ViewerConstants.LayerStackingType type) { for (int i = 0; i < ViewerConstants.LayerStackingType.values().length; i++) { if (type == ViewerConstants.LayerStackingType.values()[i]) { return i; } } return -1; } }