Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions src/SolarSystemModelsColors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,77 @@ const SolarSystemModelsColors = {
default: "#1e293b",
projector: "#e8eaf6",
}),

// ── Sky / background ──────────────────────────────────────────────────────

orbitAreaBackgroundColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "orbitAreaBackground", {
default: "#0a0a18",
projector: "#edf0f5",
}),

// ── Zodiac ring decorations ────────────────────────────────────────────────

zodiacTickColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "zodiacTick", {
default: "#888899",
projector: "#555566",
}),
zodiacLabelColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "zodiacLabel", {
default: "#aabbcc",
projector: "#334455",
}),
zodiacBorderColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "zodiacBorder", {
default: "#555577",
projector: "#9999bb",
}),
zodiacDividerColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "zodiacDivider", {
default: "#444455",
projector: "#9999bb",
}),

// ── Constellation decorations ──────────────────────────────────────────────

constellationLineColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "constellationLine", {
default: "#4d6080",
projector: "#99aacc",
}),
constellationStarColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "constellationStar", {
default: "#aabbdd",
projector: "#556677",
}),

// ── Ptolemaic reference geometry ──────────────────────────────────────────

sunOrbitReferenceColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "sunOrbitReference", {
default: "#333355",
projector: "#99aabb",
}),

// ── Configurations timeline ────────────────────────────────────────────────

timelineBackgroundColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "timelineBackground", {
default: "#0d1117",
projector: "#f0f4f8",
}),
timelineBorderColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "timelineBorder", {
default: "#334466",
projector: "#aabbcc",
}),
timelineEventColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "timelineEvent", {
default: "#446688",
projector: "#334466",
}),
timelineSelectedColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "timelineSelected", {
default: "#223355",
projector: "#ccd8e8",
}),
timelineCursorColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "timelineCursor", {
default: "#aabbcc",
projector: "#334466",
}),
timelineLabelColorProperty: new ProfileColorProperty(SolarSystemModelsNamespace, "timelineLabel", {
default: "#9999bb",
projector: "#445566",
}),
};

export default SolarSystemModelsColors;
5 changes: 3 additions & 2 deletions src/common/ZodiacConstellationNode.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Shape } from "scenerystack/kite";
import { Node, Path } from "scenerystack/scenery";
import SolarSystemModelsColors from "../SolarSystemModelsColors.js";
import { ECLIPTIC_CONSTELLATIONS } from "./ZodiacConstellationsData.js";

// Radius at which constellation stars are drawn (in pixels) — inside the
Expand Down Expand Up @@ -44,7 +45,7 @@ export class ZodiacConstellationNode extends Node {
}
}
const linesPath = new Path(linesShape, {
stroke: "#556688",
stroke: SolarSystemModelsColors.constellationLineColorProperty,
lineWidth: 0.5,
opacity: 0.6,
});
Expand All @@ -61,7 +62,7 @@ export class ZodiacConstellationNode extends Node {
}
}
const starsPath = new Path(starsShape, {
fill: "#aabbdd",
fill: SolarSystemModelsColors.constellationStarColorProperty,
stroke: null,
opacity: 0.7,
});
Expand Down
13 changes: 9 additions & 4 deletions src/configurations/view/ConfigurationsScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class ConfigurationsScreenView extends ScreenView {
this.mvt = buildMvt(model.semimajorAxis1Property.value, model.semimajorAxis2Property.value);

const a11y = StringManager.getInstance().getConfigurationsA11yStrings();
const s = StringManager.getInstance().getConfigurationsStrings();

// ── Background ──────────────────────────────────────────────────────────
const background = new Rectangle(0, 0, this.layoutBounds.width, this.layoutBounds.height, {
Expand All @@ -63,7 +64,7 @@ export class ConfigurationsScreenView extends ScreenView {

// ── Orbit area background ───────────────────────────────────────────────
const orbitAreaBg = new Rectangle(0, 0, ORBIT_AREA_SIZE, this.layoutBounds.height, {
fill: "#060d1a",
fill: SolarSystemModelsColors.orbitAreaBackgroundColorProperty,
});
this.addChild(orbitAreaBg);

Expand Down Expand Up @@ -176,19 +177,23 @@ export class ConfigurationsScreenView extends ScreenView {
orbit2Circle.shape = Shape.circle(center.x, center.y, r2);

// Labels at top of orbit circles
orbitLabel1.string = `${a1.toFixed(2)} AU`;
const au = s.auStringProperty.value;
orbitLabel1.string = `${a1.toFixed(2)} ${au}`;
orbitLabel1.centerX = center.x;
orbitLabel1.bottom = center.y - r1 - 4;

orbitLabel2.string = `${a2.toFixed(2)} AU`;
orbitLabel2.string = `${a2.toFixed(2)} ${au}`;
orbitLabel2.centerX = center.x;
orbitLabel2.bottom = center.y - r2 - 4;

// Update planet node positions to use new MVT
updateSunPos();
};

Multilink.multilink([model.semimajorAxis1Property, model.semimajorAxis2Property] as const, updateOrbits);
Multilink.multilink(
[model.semimajorAxis1Property, model.semimajorAxis2Property, s.auStringProperty] as const,
() => updateOrbits(),
);

// ── Zodiac strip at bottom ──────────────────────────────────────────────
const zodiacStrip = new ConfigurationsZodiacStrip(model);
Expand Down
68 changes: 39 additions & 29 deletions src/configurations/view/ConfigurationsTimeReadout.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Multilink } from "scenerystack/axon";
import { DerivedProperty } from "scenerystack/axon";
import { Text, VBox } from "scenerystack/scenery";
import { PhetFont } from "scenerystack/scenery-phet";
import { SolarSystemModelsPanel } from "../../common/SolarSystemModelsPanel.js";
import { StringManager } from "../../i18n/StringManager.js";
import SolarSystemModelsColors from "../../SolarSystemModelsColors.js";
import { PANEL_WIDTH } from "../../SolarSystemModelsConstants.js";
import { DAYS_PER_YEAR, PANEL_WIDTH } from "../../SolarSystemModelsConstants.js";
import type { ConfigurationsModel } from "../model/ConfigurationsModel.js";

const READOUT_FONT = new PhetFont(13);
Expand All @@ -14,39 +14,49 @@ const FONT_OPTS = {
maxWidth: PANEL_WIDTH - 24,
} as const;

const DAYS_PER_YEAR = 365.24;

export class ConfigurationsTimeReadout extends SolarSystemModelsPanel {
public constructor(model: ConfigurationsModel) {
StringManager.getInstance().getConfigurationsStrings();
const s = StringManager.getInstance().getConfigurationsStrings();

const timeText = new Text("", FONT_OPTS);
const synodicText = new Text("", FONT_OPTS);
const configText = new Text("", FONT_OPTS);
const countdownText = new Text("", FONT_OPTS);

Multilink.multilink([model.timeProperty, model.synodicPeriodProperty], (time, synodic) => {
const absTime = Math.abs(time);
const totalDays = absTime * DAYS_PER_YEAR;
const yrs = Math.floor(absTime);
const days = totalDays - yrs * DAYS_PER_YEAR;
const sign = time < 0 ? "-" : "";
timeText.string = `${sign}${absTime.toFixed(3)} yr (${sign}${yrs} yr, ${sign}${days.toFixed(1)} d)`;
synodicText.string = `Synodic: ${synodic.toFixed(3)} yr`;
});
const timeStringProperty = new DerivedProperty(
[model.timeProperty, s.yearsStringProperty, s.daysStringProperty] as const,
(time, yr, d) => {
const absTime = Math.abs(time);
const totalDays = absTime * DAYS_PER_YEAR;
const yrs = Math.floor(absTime);
const days = totalDays - yrs * DAYS_PER_YEAR;
const sign = time < 0 ? "-" : "";
return `${sign}${absTime.toFixed(3)} ${yr} (${sign}${yrs} ${yr}, ${sign}${days.toFixed(1)} ${d})`;
},
);

model.currentConfigurationProperty.link((cfg) => {
configText.string = cfg.length > 0 ? cfg : "";
});
const synodicStringProperty = new DerivedProperty(
[model.synodicPeriodProperty, s.synodicPeriodStringProperty, s.yearsStringProperty] as const,
(synodic, label, yr) => `${label} ${synodic.toFixed(3)} ${yr}`,
);

model.countdownRemainingProperty.link((remaining) => {
if (remaining > 0) {
const countdownStringProperty = new DerivedProperty(
[
model.countdownRemainingProperty,
s.pausedForStringProperty,
s.secondStringProperty,
s.secondsStringProperty,
] as const,
(remaining, pausedFor, second, seconds) => {
if (remaining <= 0) return "";
const secs = Math.ceil(remaining);
const unit = secs === 1 ? "second" : "seconds";
countdownText.string = `Paused for ${secs} more ${unit}`;
} else {
countdownText.string = "";
}
const unit = secs === 1 ? second : seconds;
return pausedFor.replace("{0}", String(secs)).replace("{1}", unit);
},
);

const timeText = new Text(timeStringProperty, FONT_OPTS);
const synodicText = new Text(synodicStringProperty, FONT_OPTS);
const configText = new Text("", FONT_OPTS);
const countdownText = new Text(countdownStringProperty, FONT_OPTS);

model.currentConfigurationProperty.link((cfg) => {
configText.string = cfg;
});

const content = new VBox({
Expand Down
25 changes: 20 additions & 5 deletions src/configurations/view/ConfigurationsTimeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Shape } from "scenerystack/kite";
import { DragListener, Node, Path, Rectangle, Text } from "scenerystack/scenery";
import { PhetFont } from "scenerystack/scenery-phet";
import { Tandem } from "scenerystack/tandem";
import SolarSystemModelsColors from "../../SolarSystemModelsColors.js";
import { CONFIGURATIONS_TIMELINE_HEIGHT, CONFIGURATIONS_TIMELINE_WIDTH } from "../../SolarSystemModelsConstants.js";
import type { ConfigurationsModel } from "../model/ConfigurationsModel.js";

Expand Down Expand Up @@ -46,24 +47,38 @@ export class ConfigurationsTimeline extends Node {
public constructor(model: ConfigurationsModel) {
super();

const bg = new Rectangle(0, 0, W, H, { fill: "#0d1117", stroke: "#334466", lineWidth: 1 });
const bg = new Rectangle(0, 0, W, H, {
fill: SolarSystemModelsColors.timelineBackgroundColorProperty,
stroke: SolarSystemModelsColors.timelineBorderColorProperty,
lineWidth: 1,
});
this.addChild(bg);

const eventLayer = new Path(null, { stroke: "#446688", lineWidth: 1 });
const eventLayer = new Path(null, {
stroke: SolarSystemModelsColors.timelineEventColorProperty,
lineWidth: 1,
});
this.addChild(eventLayer);

const selectedEventBg = new Rectangle(0, 0, W, 18, { fill: "#223355", visible: false });
const selectedEventBg = new Rectangle(0, 0, W, 18, {
fill: SolarSystemModelsColors.timelineSelectedColorProperty,
visible: false,
});
this.addChild(selectedEventBg);

const cursorLine = new Path(new Shape().moveTo(0, H / 2).lineTo(W, H / 2), {
stroke: "#aabbcc",
stroke: SolarSystemModelsColors.timelineCursorColorProperty,
lineWidth: 1.5,
});
this.addChild(cursorLine);

const labelPool: Text[] = [];
for (let i = 0; i < 20; i++) {
const t = new Text("", { font: new PhetFont(9), fill: "#9999bb", maxWidth: W - 8 });
const t = new Text("", {
font: new PhetFont(9),
fill: SolarSystemModelsColors.timelineLabelColorProperty,
maxWidth: W - 8,
});
t.visible = false;
labelPool.push(t);
this.addChild(t);
Expand Down
45 changes: 24 additions & 21 deletions src/configurations/view/ConfigurationsZodiacStrip.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
import { Multilink } from "scenerystack/axon";
import { Circle, Node, Rectangle, Text } from "scenerystack/scenery";
import { PhetFont } from "scenerystack/scenery-phet";
import { StringManager } from "../../i18n/StringManager.js";
import SolarSystemModelsColors from "../../SolarSystemModelsColors.js";
import type { ConfigurationsModel } from "../model/ConfigurationsModel.js";

const STRIP_WIDTH = 600;
const STRIP_HEIGHT = 60;
const TWO_PI = 2 * Math.PI;

const ZODIAC_SIGNS = [
"Aries",
"Taurus",
"Gemini",
"Cancer",
"Leo",
"Virgo",
"Libra",
"Scorpius",
"Sagittarius",
"Capricorn",
"Aquarius",
"Pisces",
];

function mod(x: number, m: number): number {
return ((x % m) + m) % m;
}
Expand All @@ -31,20 +17,36 @@ export class ConfigurationsZodiacStrip extends Node {
public constructor(model: ConfigurationsModel) {
super();

const z = StringManager.getInstance().getZodiacStrings();
const ZODIAC_SIGN_PROPS = [
z.ariesStringProperty,
z.taurusStringProperty,
z.geminiStringProperty,
z.cancerStringProperty,
z.leoStringProperty,
z.virgoStringProperty,
z.libraStringProperty,
z.scorpiusStringProperty,
z.sagittariusStringProperty,
z.capricornStringProperty,
z.aquariusStringProperty,
z.piscesStringProperty,
];

// Band background
const band = new Rectangle(0, 0, STRIP_WIDTH, STRIP_HEIGHT, {
fill: SolarSystemModelsColors.zodiacBandColorProperty,
stroke: "#555577",
stroke: SolarSystemModelsColors.zodiacBorderColorProperty,
lineWidth: 1,
});
this.addChild(band);

// 12 sign labels
const segW = STRIP_WIDTH / 12;
for (let i = 0; i < 12; i++) {
const label = new Text(ZODIAC_SIGNS[i] ?? "", {
const label = new Text(ZODIAC_SIGN_PROPS[i]!, {
font: new PhetFont(9),
fill: "#9999bb",
fill: SolarSystemModelsColors.zodiacLabelColorProperty,
maxWidth: segW - 4,
});
label.centerX = (i + 0.5) * segW;
Expand All @@ -53,7 +55,9 @@ export class ConfigurationsZodiacStrip extends Node {

// Divider
if (i > 0) {
const divider = new Rectangle(i * segW, 0, 1, STRIP_HEIGHT, { fill: "#445" });
const divider = new Rectangle(i * segW, 0, 1, STRIP_HEIGHT, {
fill: SolarSystemModelsColors.zodiacDividerColorProperty,
});
this.addChild(divider);
}
}
Expand Down Expand Up @@ -89,8 +93,7 @@ export class ConfigurationsZodiacStrip extends Node {
sunMarker.centerX = mod((sunLong * STRIP_WIDTH) / TWO_PI, STRIP_WIDTH);
planetMarker.centerX = mod((planetLong * STRIP_WIDTH) / TWO_PI, STRIP_WIDTH);

const labelStr = `${Math.abs(elongDeg).toFixed(1)}° ${elongLabel}`;
elongText.string = labelStr;
elongText.string = `${Math.abs(elongDeg).toFixed(1)}° ${elongLabel}`;
},
);
}
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/StringManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ export class StringManager {
return stringProperties.a11y.configurations;
}

public getZodiacStrings() {
return stringProperties.zodiac;
}

public getPreferences() {
return stringProperties.preferences;
}
Expand Down
Loading
Loading