diff --git a/src/renderer/src/intl/en-US.ts b/src/renderer/src/intl/en-US.ts index 29e7338..4de70a0 100644 --- a/src/renderer/src/intl/en-US.ts +++ b/src/renderer/src/intl/en-US.ts @@ -144,6 +144,8 @@ export default { primary: 'Primary', secondary: 'Secondary', border: 'Border', + planet: 'Planet', + planet_complement: "Planet's Complement", }, color_adjustment: { LIGHTEN: 'Lighten', @@ -416,6 +418,7 @@ export default { systemMapOrbitStroke: 'Orbit Lines', systemMapOrbitColor: 'Orbit Lines Color', systemMapPlanetScale: 'Planet Scale', + systemMapPlanetRingColor: 'Planet Ring Color', systemMapLabelPlanetsFont: 'Planet Name Font', systemMapLabelPlanetsFontSize: 'Planet Name Font Size', systemMapLabelPlanetsPosition: 'Planet Name Position', diff --git a/src/renderer/src/lib/SettingControl/ColorSettingControl.svelte b/src/renderer/src/lib/SettingControl/ColorSettingControl.svelte index c402e1f..7302c7d 100644 --- a/src/renderer/src/lib/SettingControl/ColorSettingControl.svelte +++ b/src/renderer/src/lib/SettingControl/ColorSettingControl.svelte @@ -24,7 +24,7 @@ .filter( // don't show dynamic colors group if no dynamic colors are allowed (group) => - !(group === 'option.color.group.dynamic' && config.allowedDynamicColors?.length === 0), + !(group === 'option.color.group.dynamic' && config.allowedDynamicColors.length === 0), ), ), ); @@ -32,7 +32,6 @@ function filterAllowedOption(option: SelectOption) { if (option.group !== 'option.color.group.dynamic') return true; - if (config.allowedDynamicColors == null) return true; return (config.allowedDynamicColors as string[]).includes(option.id); } diff --git a/src/renderer/src/lib/SettingControl/IconSettingControl.svelte b/src/renderer/src/lib/SettingControl/IconSettingControl.svelte index 269b311..ce645bc 100644 --- a/src/renderer/src/lib/SettingControl/IconSettingControl.svelte +++ b/src/renderer/src/lib/SettingControl/IconSettingControl.svelte @@ -127,7 +127,11 @@ {/if} {/if} diff --git a/src/renderer/src/lib/map/mapUtils.ts b/src/renderer/src/lib/map/mapUtils.ts index 8c222a1..02bfe43 100644 --- a/src/renderer/src/lib/map/mapUtils.ts +++ b/src/renderer/src/lib/map/mapUtils.ts @@ -1,4 +1,4 @@ -import { lab } from 'd3-color'; +import { hsl, lab } from 'd3-color'; import { interpolateRgb } from 'd3-interpolate'; import type { SVGAttributes } from 'svelte/elements'; @@ -14,12 +14,14 @@ export function resolveColor({ mapSettings, colors, countryColors: countryColorsOption, + planetColor, colorStack, resolveToOpaqueColor, }: { mapSettings: MapSettings; colors: Record; countryColors?: null | CountryColors | (CountryColors | null | undefined)[]; + planetColor?: string; colorStack: ColorSetting[]; resolveToOpaqueColor?: boolean; }): string { @@ -49,6 +51,13 @@ export function resolveColor({ colorStack: [mapSettings.borderColor, ...backgroundSettingStack], resolveToOpaqueColor, }); + } else if (colorString === 'planet') { + colorString = planetColor ?? 'rgb(0, 0, 0)'; + } else if (colorString === 'planet_complement') { + colorString = planetColor ?? 'rgb(0, 0, 0)'; + const color = hsl(colorString); + color.h = color.h > 180 ? color.h - 180 : color.h + 180; + colorString = color.formatRgb(); } else { if (colorString === 'primary') colorString = countryColors.primaryColor; if (colorString === 'secondary') colorString = countryColors.secondaryColor; @@ -201,3 +210,24 @@ export function getBackgroundColor( colorStack: [mapSettings.backgroundColor], }); } + +export function multiplyOpacity(colorSetting: ColorSetting, value: number): ColorSetting { + const opacityAdjustment = colorSetting.colorAdjustments.find( + (adjustment) => adjustment.type === 'OPACITY', + ); + if (opacityAdjustment) { + return { + ...colorSetting, + colorAdjustments: colorSetting.colorAdjustments.map((adjustment) => + adjustment === opacityAdjustment + ? { type: 'OPACITY', value: opacityAdjustment.value * value } + : adjustment, + ), + }; + } else { + return { + ...colorSetting, + colorAdjustments: [...colorSetting.colorAdjustments, { type: 'OPACITY', value }], + }; + } +} diff --git a/src/renderer/src/lib/map/solarSystemMap/SolarSystemMap.svelte b/src/renderer/src/lib/map/solarSystemMap/SolarSystemMap.svelte index cf45c61..1254921 100644 --- a/src/renderer/src/lib/map/solarSystemMap/SolarSystemMap.svelte +++ b/src/renderer/src/lib/map/solarSystemMap/SolarSystemMap.svelte @@ -15,6 +15,7 @@ getFillColorAttributes, getStrokeAttributes, getStrokeColorAttributes, + multiplyOpacity, } from '../mapUtils'; export let system: GalacticObject; @@ -493,6 +494,27 @@ if (planet.coordinate.x > 0) return angle + 180; return angle; } + + const PLANET_RING_PATTERN = ( + [ + [0.3, 0], + [0.05, 0.05], + [0.3, 0.15], + [0.1, 0.5], + [0.1, 1], + [0.02, 0.5], + [0.1, 1], + [0.1, 0.5], + [0.05, 0], + [0.2, 0.3], + [0.02, 0], + [0.05, 0.5], + ] as [number, number][] + ).map(([width, opacity], index, array) => { + const radiusMultiplier = + array.slice(0, index).reduce((total, [curWidth]) => total + curWidth, 0) + 1 + width / 2; + return { width, opacity, radiusMultiplier }; + }); {:else} + {@const radius = getPlanetRadius(planet, $mapSettings)} @@ -604,6 +627,23 @@ fill="#000000" opacity={0.5} /> + {#if planet.has_ring} + {#each PLANET_RING_PATTERN as ring} + + {/each} + {/if} {/if} {/each} {#each planets.filter((p) => isPlanetLabeled(p, $mapSettings)) as planet (planet.id)} diff --git a/src/renderer/src/lib/settings/SettingConfig.ts b/src/renderer/src/lib/settings/SettingConfig.ts index 620f1e0..7621bd1 100644 --- a/src/renderer/src/lib/settings/SettingConfig.ts +++ b/src/renderer/src/lib/settings/SettingConfig.ts @@ -58,7 +58,7 @@ export interface SettingConfigColor extends SettingConfigBase; allowedAdjustments?: ColorSettingAdjustmentType[]; - allowedDynamicColors?: ('primary' | 'secondary' | 'border')[]; + allowedDynamicColors: ('primary' | 'secondary' | 'border' | 'planet' | 'planet_complement')[]; } export interface SettingConfigStroke extends SettingConfigBase { @@ -73,6 +73,7 @@ export interface SettingConfigIcon extends SettingConfigBase; noAdvanced?: boolean; + allowedDynamicColors: SettingConfigColor['allowedDynamicColors']; } export type UnknownSettingConfig = diff --git a/src/renderer/src/lib/settings/mapSettings.ts b/src/renderer/src/lib/settings/mapSettings.ts index a324363..86cbf00 100644 --- a/src/renderer/src/lib/settings/mapSettings.ts +++ b/src/renderer/src/lib/settings/mapSettings.ts @@ -96,6 +96,7 @@ export type ColorMapSettings = | 'starScapeNebulaAccentColor' | 'starScapeNebulaColor' | 'starScapeStarsColor' + | 'systemMapPlanetRingColor' | 'unionBorderColor' | 'unownedHyperlaneColor' | 'unownedHyperRelayColor' @@ -493,6 +494,10 @@ export const defaultMapSettings: MapSettings = { systemMapLabelFleetsEnabled: true, systemMapLabelFleetsFontSize: 3, systemMapLabelFleetsPosition: 'right', + systemMapPlanetRingColor: { + color: 'planet', + colorAdjustments: [{ type: 'OPACITY', value: 0.75 }], + }, }; export const mapSettings = localStorageStore('mapSettings', defaultMapSettings); diff --git a/src/renderer/src/lib/settings/mapSettingsConfig.ts b/src/renderer/src/lib/settings/mapSettingsConfig.ts index d93b3c0..ff4c614 100644 --- a/src/renderer/src/lib/settings/mapSettingsConfig.ts +++ b/src/renderer/src/lib/settings/mapSettingsConfig.ts @@ -4,9 +4,18 @@ import { fontOptions } from './options/fontOptions'; import { glyphOptions } from './options/glyphOptions'; import { speciesOptions } from './options/speciesOptions'; import { unionOptions } from './options/unionOptions'; -import { type MapSettingConfigGroup } from './SettingConfig'; +import { type MapSettingConfigGroup, type SettingConfigColor } from './SettingConfig'; import { isColorDynamic } from './utils'; +const COUNTRY_SCOPED_DYNAMIC_COLORS: SettingConfigColor< + unknown, + unknown +>['allowedDynamicColors'][number][] = ['primary', 'secondary', 'border']; +const PLANET_SCOPED_DYNAMIC_COLORS: SettingConfigColor< + unknown, + unknown +>['allowedDynamicColors'][number][] = ['planet', 'planet_complement']; + export const mapSettingsConfig: MapSettingConfigGroup[] = [ { id: 'mapMode', @@ -54,13 +63,14 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ { id: 'borderColor', type: 'color', - allowedDynamicColors: ['primary', 'secondary'], + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS.filter((c) => c !== 'border'), hideIf: (settings) => !settings.borderStroke.enabled, }, { id: 'borderFillColor', type: 'color', hideIf: (settings) => !settings.borderStroke.enabled, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'borderFillFade', @@ -80,6 +90,7 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ id: 'sectorBorderColor', type: 'color', hideIf: (settings) => !settings.sectorBorderStroke.enabled, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'frontierBubbleThreshold', @@ -107,6 +118,7 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ type: 'color', hideIf: (settings) => !settings.sectorTypeBorderStyles || !settings.sectorBorderStroke.enabled, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'sectorFrontierBorderStroke', @@ -119,6 +131,7 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ type: 'color', hideIf: (settings) => !settings.sectorTypeBorderStyles || !settings.sectorBorderStroke.enabled, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, ], }, @@ -162,6 +175,7 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ ![settings.unionFederations, settings.unionHegemonies, settings.unionSubjects].includes( 'joinedBorders', ), + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'unionFederationsColor', @@ -208,6 +222,7 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ id: 'occupationColor', type: 'color', hideIf: (settings) => !settings.occupation, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, ], }, @@ -356,40 +371,48 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ id: 'countryCapitalIcon', type: 'icon', requiresReprocessing: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'sectorCapitalIcon', type: 'icon', requiresReprocessing: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'populatedSystemIcon', type: 'icon', requiresReprocessing: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'unpopulatedSystemIcon', type: 'icon', + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'wormholeIcon', type: 'icon', requiresReprocessing: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'gatewayIcon', type: 'icon', requiresReprocessing: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'lGateIcon', type: 'icon', requiresReprocessing: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'shroudTunnelIcon', type: 'icon', requiresReprocessing: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, ], }, @@ -406,6 +429,7 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ id: 'hyperlaneColor', type: 'color', hideIf: (settings) => !settings.hyperlaneStroke.enabled, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'unownedHyperlaneColor', @@ -424,6 +448,7 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ id: 'hyperRelayColor', type: 'color', hideIf: (settings) => !settings.hyperRelayStroke.enabled, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'unownedHyperRelayColor', @@ -711,6 +736,11 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ min: 0, step: 0.1, }, + { + id: 'systemMapPlanetRingColor', + type: 'color', + allowedDynamicColors: PLANET_SCOPED_DYNAMIC_COLORS, + }, { id: 'systemMapLabelPlanetsFont', type: 'select', @@ -773,21 +803,25 @@ export const mapSettingsConfig: MapSettingConfigGroup[] = [ id: 'systemMapCivilianFleetIcon', type: 'icon', noAdvanced: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'systemMapCivilianStationIcon', type: 'icon', noAdvanced: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'systemMapMilitaryFleetIcon', type: 'icon', noAdvanced: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'systemMapMilitaryStationIcon', type: 'icon', noAdvanced: true, + allowedDynamicColors: COUNTRY_SCOPED_DYNAMIC_COLORS, }, { id: 'systemMapLabelFleetsEnabled', diff --git a/src/renderer/src/lib/settings/options/colorOptions.ts b/src/renderer/src/lib/settings/options/colorOptions.ts index 9c7c812..a1acde1 100644 --- a/src/renderer/src/lib/settings/options/colorOptions.ts +++ b/src/renderer/src/lib/settings/options/colorOptions.ts @@ -4,4 +4,10 @@ export const colorOptions: SelectOption[] = [ { id: 'primary', name: 'option.color.primary', group: 'option.color.group.dynamic' }, { id: 'secondary', name: 'option.color.secondary', group: 'option.color.group.dynamic' }, { id: 'border', name: 'option.color.border', group: 'option.color.group.dynamic' }, + { id: 'planet', name: 'option.color.planet', group: 'option.color.group.dynamic' }, + { + id: 'planet_complement', + name: 'option.color.planet_complement', + group: 'option.color.group.dynamic', + }, ];