diff --git a/package-lock.json b/package-lock.json index f2d8ee0..6ec4679 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "studio", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "studio", - "version": "2.0.0", + "version": "2.1.0", "license": "AGPL-3.0-or-later", "dependencies": { "@codemirror/autocomplete": "^6.20.3", diff --git a/package.json b/package.json index d758a8b..e54ab7d 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "wasmoon": "^1.16.0" }, "name": "studio", - "version": "2.0.0", + "version": "2.1.0", "description": "

\"Laravel

", "main": "vite.config.js", "directories": { diff --git a/resources/css/app.css b/resources/css/app.css index 8b9594a..6d974d4 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -2,6 +2,7 @@ @import './modal.css'; /* Last, so a theme can win a tie against the rules above without !important. */ @import './classic.css'; +@import './pink.css'; * { margin: 0; padding: 0; box-sizing: border-box; } diff --git a/resources/css/pink.css b/resources/css/pink.css new file mode 100644 index 0000000..0d9f46e --- /dev/null +++ b/resources/css/pink.css @@ -0,0 +1,486 @@ +html[data-theme='pink'] { + --bg: #ffe7f2; + --chrome: #ffd0e4; + --panel: #fff2f8; + --float: #fff; + --raised: #fff; + --sunken: #ffd9ea; + --deep: #ffeaf4; + --deep-2: #fff2f8; + --stage: #ffe0ee; + --slot: #fff6fa; + --pop: #fff; + --pop-hover: #ff2e88; + + --hover: #ffd7e9; + --hover-soft: #ffe6f1; + --sel-soft: #ffdcec; + + --field: #fff; + --field-alt: #fff6fa; + + --chip: #ffd9ea; + --chip-2: #ffc9e1; + --chip-3: #ffb8d7; + + --line: #ffaed2; + --line-hard: #ff5fa2; + --line-soft: #ffd0e4; + --line-deep: #ffc0dc; + --line-mid: #ff9cc8; + --line-strong: #ff5fa2; + --line-faint: #ffdcec; + + --ink-white: #fff; + --ink-max: #3d1029; + --ink-hi: #45142f; + --ink-bright: #3d1029; + --ink-mid: #4d1a36; + --ink: #4d1a36; + --ink-2: #5a2040; + --ink-body: #5a2040; + --ink-quiet: #6b2a4d; + --ink-label: #8a3a63; + --muted: #9c4573; + --muted-2: #8a3a63; + --dim: #ac5a86; + --faint: #bd7099; + --faint-2: #c882a7; + --disabled: #e8a8c8; + --disabled-2: #f0bcd6; + + --accent: #ff2e88; + --accent-hover: #ff5da4; + --accent-press: #e6006e; + --accent-ink: #fff; + --sel-bg: #ff2e88; + --sel-bg-2: #ff7ab5; + --tag-bg: #ffd0e4; + + --link: #d6006b; + --link-hi: #ff2e88; + --go: #ff2e88; + --go-hover: #ff5da4; + --go-dim: #ff9cc8; + + --danger: #d10035; + --danger-2: #e6194d; + --danger-soft: #ef5c80; + --danger-mute: #c4526f; + --danger-hot: #d10035; + --danger-btn: #e6194d; + --danger-btn-hover: #ff3866; + --danger-line: #ffb3c6; + --danger-bg: #ffe0e7; + --danger-bg-2: #fff0f3; + --ok: #00a86b; + --ok-2: #2fb886; + --ok-bg: #d8f5e8; + --warn: #d98200; + --warn-2: #e69200; + --warn-3: #b86e00; + --warn-line: #ffd9a0; + + --code: #c2185b; + --viewer: #9c27b0; + --viewer-bg: #f6e2fa; + + --radius: 12px; + --radius-sm: 8px; + + --pk-glow: 0 2px 8px rgba(255, 46, 136, 0.22); + --pk-glow-hi: 0 3px 12px rgba(255, 46, 136, 0.38); + --pk-band: linear-gradient(180deg, #ffd9ea 0%, #ffc2de 100%); + --pk-hot: linear-gradient(180deg, #ff6fae 0%, #ff2e88 55%, #e6006e 100%); + --pk-hot-hover: linear-gradient(180deg, #ff8dc0 0%, #ff4d9a 55%, #ff1a7d 100%); +} + +html[data-theme='pink'] .panel, +html[data-theme='pink'] .card, +html[data-theme='pink'] .modal, +html[data-theme='pink'] .menu-drop, +html[data-theme='pink'] .menu-pop { border-radius: 16px; } + +html[data-theme='pink'] button:focus-visible, +html[data-theme='pink'] .scope:focus-visible, +html[data-theme='pink'] .tool-btn:focus-visible { + outline: 2px solid #ff2e88; + outline-offset: 2px; +} + +html[data-theme='pink'] .btn, +html[data-theme='pink'] .team-primary, +html[data-theme='pink'] .team-foot-btn, +html[data-theme='pink'] .account-go, +html[data-theme='pink'] .arch-stamp, +html[data-theme='pink'] .update-primary, +html[data-theme='pink'] .update-later, +html[data-theme='pink'] .chat-send button, +html[data-theme='pink'] .arch-image > button, +html[data-theme='pink'] .scope-pick { + background: #fff; + border: 2px solid #ffaed2; + border-radius: 999px; + color: #4d1a36; + box-shadow: var(--pk-glow); + font-weight: 600; +} +html[data-theme='pink'] .btn:hover:not(:disabled), +html[data-theme='pink'] .team-primary:hover:not(:disabled), +html[data-theme='pink'] .team-foot-btn:hover, +html[data-theme='pink'] .account-go:hover:not(:disabled), +html[data-theme='pink'] .arch-stamp:hover:not(:disabled), +html[data-theme='pink'] .update-primary:hover:not(:disabled), +html[data-theme='pink'] .update-later:hover:not(:disabled), +html[data-theme='pink'] .chat-send button:hover:not(:disabled), +html[data-theme='pink'] .arch-image > button:hover, +html[data-theme='pink'] .scope-pick:hover { + background: #ffeaf4; + border-color: #ff2e88; + box-shadow: var(--pk-glow-hi); +} +html[data-theme='pink'] .btn:active:not(:disabled), +html[data-theme='pink'] .team-primary:active, +html[data-theme='pink'] .account-go:active { + transform: translateY(1px); + box-shadow: 0 1px 4px rgba(255, 46, 136, 0.28); +} +html[data-theme='pink'] .btn:disabled { + background: #fff6fa; + border-color: #ffd0e4; + color: #e8a8c8; + box-shadow: none; + opacity: 1; +} + +html[data-theme='pink'] .btn-go { + background: var(--pk-hot); + border-color: #e6006e; + color: #fff; + font-weight: 700; +} +html[data-theme='pink'] .btn-go:hover:not(:disabled) { background: var(--pk-hot-hover); border-color: #e6006e; } +html[data-theme='pink'] .btn-danger { color: #d10035; border-color: #ffb3c6; } +html[data-theme='pink'] .btn-danger:hover:not(:disabled) { background: #ffe0e7; border-color: #d10035; } + +html[data-theme='pink'] .card-dots, +html[data-theme='pink'] .map-move, +html[data-theme='pink'] .card-move, +html[data-theme='pink'] .card-x { + border-radius: 999px; + color: #9c4573; +} +html[data-theme='pink'] .card-dots:hover, +html[data-theme='pink'] .map-move:hover, +html[data-theme='pink'] .card-move:hover { background: #ffd7e9; color: #e6006e; } +html[data-theme='pink'] .card-x:hover { background: #ffe0e7; color: #d10035; } + +html[data-theme='pink'] input[type='text'], +html[data-theme='pink'] input[type='number'], +html[data-theme='pink'] input[type='password'], +html[data-theme='pink'] input[type='email'], +html[data-theme='pink'] input:not([type]), +html[data-theme='pink'] textarea, +html[data-theme='pink'] select, +html[data-theme='pink'] .num { + background: #fff; + border: 2px solid #ffaed2; + border-radius: 999px; + color: #4d1a36; +} +html[data-theme='pink'] textarea { border-radius: 12px; } +html[data-theme='pink'] input:focus, +html[data-theme='pink'] textarea:focus, +html[data-theme='pink'] select:focus { + border-color: #ff2e88; + box-shadow: 0 0 0 3px rgba(255, 46, 136, 0.18); +} +html[data-theme='pink'] ::placeholder { color: #c882a7; } + +html[data-theme='pink'] .snap-row input[type='checkbox'], +html[data-theme='pink'] .arch-check input[type='checkbox'] { + background: #fff; + border: 2px solid #ffaed2; + border-radius: 6px; +} +html[data-theme='pink'] .snap-row input[type='checkbox']:checked, +html[data-theme='pink'] .arch-check input[type='checkbox']:checked { + background: #ff2e88; + border-color: #e6006e; +} +html[data-theme='pink'] .snap-row input[type='checkbox']:checked::after, +html[data-theme='pink'] .arch-check input[type='checkbox']:checked::after { border-color: #fff; } +html[data-theme='pink'] .prop-check input[type='checkbox'] { accent-color: #ff2e88; } + +html[data-theme='pink'] .toolbar { + background: var(--pk-band); + border-bottom: 2px solid #ff9cc8; +} +html[data-theme='pink'] .toolbar .group { border-right: 1px dashed #ff9cc8; } +html[data-theme='pink'] .group-label { color: #9c4573; } + +html[data-theme='pink'] .tool-btn { color: #4d1a36; border: 2px solid transparent; border-radius: 10px; } +html[data-theme='pink'] .tool-btn:hover:not(:disabled) { background: #fff; border-color: #ff9cc8; } +html[data-theme='pink'] .tool-btn.active { + background: var(--pk-hot); + border-color: #e6006e; + color: #fff; +} +html[data-theme='pink'] .tool-btn:disabled { color: #e8a8c8; } + +html[data-theme='pink'] .menubar { + background: var(--pk-band); + border-bottom: 2px solid #ff9cc8; +} +html[data-theme='pink'] .menu-title { color: #4d1a36; border-radius: 999px; } +html[data-theme='pink'] .menu-title:hover, +html[data-theme='pink'] .menu-title.open { background: #ff2e88; color: #fff; } + +html[data-theme='pink'] .menu-drop, +html[data-theme='pink'] .menu-pop { + padding: 6px; + background: #fff; + border: 2px solid #ff9cc8; + box-shadow: 0 6px 20px rgba(255, 46, 136, 0.3); +} +html[data-theme='pink'] .menu-item { color: #4d1a36; border-radius: 999px; } +html[data-theme='pink'] .menu-item:hover:not(:disabled) { background: #ff2e88; color: #fff; } +html[data-theme='pink'] .menu-item:disabled { color: #e8a8c8; } +html[data-theme='pink'] .menu-tick { color: #ff2e88; font-weight: 700; } +html[data-theme='pink'] .menu-tick:not(:empty) { font-size: 0; } +html[data-theme='pink'] .menu-tick:not(:empty)::after { content: '\2740'; font-size: 11px; } +html[data-theme='pink'] .menu-item:hover .menu-tick { color: #fff; } +html[data-theme='pink'] .menu-sep { background: #ffc0dc; } +html[data-theme='pink'] .menu-pop button { border-radius: 999px; } +html[data-theme='pink'] .menu-pop button:hover { background: #ff2e88; color: #fff; } +html[data-theme='pink'] .menu-pop button.danger:hover { background: #d10035; color: #fff; } + +html[data-theme='pink'] .tabbar { background: var(--pk-band); border-bottom: 2px solid #ff9cc8; padding-top: 4px; } +html[data-theme='pink'] .tab { + background: #fff; + border: 2px solid #ffaed2; + border-bottom: none; + border-radius: 14px 14px 0 0; + color: #4d1a36; + margin-right: 3px; +} +html[data-theme='pink'] .tab:hover { background: #ffeaf4; } +html[data-theme='pink'] .tab.active { + background: var(--pk-hot); + border-color: #e6006e; + color: #fff; + font-weight: 700; + box-shadow: none; +} + +html[data-theme='pink'] .sidebar { border-left: 2px solid #ff9cc8; background: #fff2f8; } +html[data-theme='pink'] .panel.explorer { border-bottom: 2px solid #ff9cc8; } + +html[data-theme='pink'] .panel-title { + background: var(--pk-band); + border-bottom: 2px solid #ff9cc8; + color: #c2185b; + font-weight: 700; +} +html[data-theme='pink'] .panel-title::before { content: '\2740\00a0'; color: #ff2e88; } + +html[data-theme='pink'] .panel-body, +html[data-theme='pink'] .explorer-search { background: #fff; } +html[data-theme='pink'] .tree-item { color: #4d1a36; border-radius: 999px; } +html[data-theme='pink'] .tree-item:hover { background: #ffd7e9; } +html[data-theme='pink'] .tree-item.selected { background: #ff2e88; color: #fff; } +html[data-theme='pink'] .tree-item.selected .count, +html[data-theme='pink'] .tree-item.selected .flag, +html[data-theme='pink'] .tree-item.selected .clear { color: #fff; } +html[data-theme='pink'] .tree-item.is-hidden { color: #c882a7; } +html[data-theme='pink'] .props, html[data-theme='pink'] .prop-head { color: #4d1a36; } +html[data-theme='pink'] .prop-head { border-bottom: 2px dashed #ffc0dc; } + +html[data-theme='pink'] .arch-pop, +html[data-theme='pink'] .team-panel, +html[data-theme='pink'] .chat-panel, +html[data-theme='pink'] .stats-panel, +html[data-theme='pink'] .update-notice, +html[data-theme='pink'] .help-pop, +html[data-theme='pink'] .modal { + background: #fff; + border: 2px solid #ff9cc8; + border-radius: 18px; + box-shadow: 0 10px 30px rgba(255, 46, 136, 0.28); + color: #4d1a36; + overflow: hidden; +} + +html[data-theme='pink'] .team-head, +html[data-theme='pink'] .chat-head, +html[data-theme='pink'] .arch-head, +html[data-theme='pink'] .modal-head { + background: var(--pk-hot); + border-bottom: none; + color: #fff; +} +html[data-theme='pink'] .team-title, +html[data-theme='pink'] .chat-title, +html[data-theme='pink'] .arch-head h3, +html[data-theme='pink'] .modal-head h3 { color: #fff; font-weight: 700; } +html[data-theme='pink'] .team-title::before, +html[data-theme='pink'] .chat-title::before, +html[data-theme='pink'] .modal-head h3::before { content: '\2740\00a0'; } +html[data-theme='pink'] .arch-ver, +html[data-theme='pink'] .team-title-name, +html[data-theme='pink'] .modal-head p { color: #ffe0ee; } +html[data-theme='pink'] .team-title-name { border-left-color: #ffb8d7; } +html[data-theme='pink'] .team-chat { color: #fff; } +html[data-theme='pink'] .team-chat:hover, +html[data-theme='pink'] .team-chat.on { color: #fff; background: rgba(255, 255, 255, 0.28); } + +html[data-theme='pink'] .team-x, +html[data-theme='pink'] .chat-x, +html[data-theme='pink'] .arch-close, +html[data-theme='pink'] .modal-x, +html[data-theme='pink'] .help-close { + width: 22px; + height: 22px; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + border: none; + border-radius: 999px; + background: rgba(255, 255, 255, 0.85); + color: #e6006e; + font-weight: 700; + line-height: 1; +} +html[data-theme='pink'] .team-x:hover, +html[data-theme='pink'] .chat-x:hover, +html[data-theme='pink'] .arch-close:hover, +html[data-theme='pink'] .modal-x:hover, +html[data-theme='pink'] .help-close:hover { background: #fff; color: #d10035; } +html[data-theme='pink'] .arch-edit { color: #fff; } +html[data-theme='pink'] .arch-edit:hover { color: #ffe0ee; } + +html[data-theme='pink'] .help-pop h3, +html[data-theme='pink'] .help-pop h4, +html[data-theme='pink'] .script-help h4 { color: #c2185b; } +html[data-theme='pink'] .help-pop h3 { background: #fff; } +html[data-theme='pink'] .help-pop b, html[data-theme='pink'] .script-help b { color: #4d1a36; } + +html[data-theme='pink'] .modal-backdrop { background: rgba(255, 46, 136, 0.22); } +html[data-theme='pink'] .modal-foot, html[data-theme='pink'] .modal-body { background: #fff; } +html[data-theme='pink'] .modal-foot { border-top: 2px dashed #ffc0dc; } +html[data-theme='pink'] .busy { background: #fff; border: 2px solid #ff9cc8; border-radius: 18px; color: #4d1a36; } + +html[data-theme='pink'] .start { background: #ffeaf4; } +html[data-theme='pink'] .start-top { + background: var(--pk-hot); + border-bottom: 3px solid #ffd0e4; +} +html[data-theme='pink'] .start-top h1 { color: #fff; font-weight: 700; } +html[data-theme='pink'] .start-top h1::after { content: '\00a0\2740'; } +html[data-theme='pink'] .start h2 { color: #c2185b; font-weight: 700; } +html[data-theme='pink'] .start a { color: #d6006b; } +html[data-theme='pink'] .scope { color: #4d1a36; border-radius: 999px; } +html[data-theme='pink'] .scope:hover { background: #ffd7e9; } +html[data-theme='pink'] .scope.on { background: #ff2e88; color: #fff; border-left-color: #e6006e; } +html[data-theme='pink'] .scope.on .scope-count { color: #ffe0ee; } +html[data-theme='pink'] .scope-title { color: #c2185b; font-weight: 700; } +html[data-theme='pink'] .card { + background: #fff; + border: 2px solid #ffaed2; + box-shadow: var(--pk-glow); +} +html[data-theme='pink'] .card:hover { background: #fff6fa; border-color: #ff2e88; box-shadow: var(--pk-glow-hi); } +html[data-theme='pink'] .card-name { color: #c2185b; font-weight: 700; } +html[data-theme='pink'] .card-tag { background: #ff2e88; color: #fff; border-radius: 999px; } +html[data-theme='pink'] .account, html[data-theme='pink'] .start-footer { + background: #fff; + border: 2px solid #ffaed2; + border-radius: 16px; + color: #4d1a36; +} +html[data-theme='pink'] .user-face, html[data-theme='pink'] .avatar { + background: var(--pk-hot); + border: 2px solid #ffd0e4; +} +html[data-theme='pink'] .start-credit { background: #ffd9ea; border-top: 2px solid #ff9cc8; color: #8a3a63; } + +html[data-theme='pink'] .theme-try { color: #c2185b; } +html[data-theme='pink'] .theme-try:hover { color: #e6006e; } + +html[data-theme='pink'] .statusbar { + background: var(--pk-band); + border: 2px solid #ff9cc8; + color: #4d1a36; +} +html[data-theme='pink'] .credit { color: rgba(255, 255, 255, 0.9); } + +html[data-theme='pink'] .script-tab, html[data-theme='pink'] .script-help { background: #fff; } +html[data-theme='pink'] .script-bar { background: var(--pk-band); border-bottom: 2px solid #ff9cc8; } +html[data-theme='pink'] .script-help { border-left: 2px solid #ff9cc8; color: #4d1a36; } +html[data-theme='pink'] .script-help pre { + background: #fff6fa; + border: 2px solid #ffd0e4; + color: #4d1a36; +} +html[data-theme='pink'] .script-help code { background: #fff6fa; color: #c2185b; } + +html[data-theme='pink'] .drawer-handle, html[data-theme='pink'] .touch-actions { + background: #fff; + border: 2px solid #ffaed2; + color: #4d1a36; +} +html[data-theme='pink'] .mobilebar { background: var(--pk-band); border-bottom: 2px solid #ff9cc8; } +html[data-theme='pink'] .mb-btn { color: #4d1a36; } +html[data-theme='pink'] .mb-btn.active { background: #ff2e88; color: #fff; } + +html[data-theme='pink'] .role-pill, html[data-theme='pink'] .tag, html[data-theme='pink'] .card-group { + border: 2px solid #ffaed2; + border-radius: 999px; + color: #8a3a63; +} + +html[data-theme='pink'] input[type='range'] { + height: 6px; + background: #ffd0e4; + border: none; + border-radius: 999px; +} +html[data-theme='pink'] input[type='range']::-webkit-slider-thumb { + width: 16px; height: 16px; + border: 2px solid #fff; + border-radius: 999px; + background: #ff2e88; + box-shadow: var(--pk-glow); +} +html[data-theme='pink'] input[type='range']::-moz-range-thumb { + width: 16px; height: 16px; + border: 2px solid #fff; + border-radius: 999px; + background: #ff2e88; + box-shadow: var(--pk-glow); +} +html[data-theme='pink'] input[type='range']:disabled::-webkit-slider-thumb, +html[data-theme='pink'] input[type='range']:disabled::-moz-range-thumb { background: #ffb8d7; } + +html[data-theme='pink'] * { + scrollbar-width: thin; + scrollbar-color: #ff2e88 #ffe0ee; +} +html[data-theme='pink'] ::-webkit-scrollbar { width: 10px; height: 10px; } +html[data-theme='pink'] ::-webkit-scrollbar-track { background: #ffe0ee; } +html[data-theme='pink'] ::-webkit-scrollbar-thumb { + background: var(--pk-hot); + border-radius: 999px; + border: 2px solid #ffe0ee; +} +html[data-theme='pink'] ::-webkit-scrollbar-thumb:hover { background: #e6006e; } + +html[data-theme='pink'] .prop-remove { + background: #fff; + border: 2px solid #ffaed2; + border-radius: 999px; + color: #4d1a36; +} +html[data-theme='pink'] .prop-remove:hover { border-color: #ff2e88; color: #d10035; } +html[data-theme='pink'] .prop-note { color: #9c4573; } diff --git a/resources/js/studio/ScriptTab.jsx b/resources/js/studio/ScriptTab.jsx index 4fb7528..c44cef5 100644 --- a/resources/js/studio/ScriptTab.jsx +++ b/resources/js/studio/ScriptTab.jsx @@ -8,7 +8,7 @@ import { keymap } from '@codemirror/view'; import { Prec } from '@codemirror/state'; import { TrashIcon, RotateIcon, HelpIcon } from './icons'; import { ICON_NAMES } from './pluginIcons'; -import { useTheme } from './theme'; +import { isLight, useTheme } from './theme'; export const TEMPLATE = `plugin = { name = "My Plugin", @@ -143,7 +143,7 @@ export default function ScriptTab({ tab, visible, onChange, onSave, onDelete, on if (handlers.current.error !== null) setError(null); }, []); - const cmTheme = useTheme() === 'classic' ? 'light' : oneDark; + const cmTheme = isLight(useTheme()) ? 'light' : oneDark; const editor = useMemo(() => ( {scope === 'ugc' ? : ( <> - {theme !== 'classic' && ( + {theme !== 'pink' && ( )}
diff --git a/resources/js/studio/theme.js b/resources/js/studio/theme.js index c8b0efe..6ccec20 100644 --- a/resources/js/studio/theme.js +++ b/resources/js/studio/theme.js @@ -5,8 +5,11 @@ const KEY = 'studio_theme'; export const THEMES = [ ['dark', 'Vortex'], ['classic', 'Classic'], + ['pink', 'Pink'], ]; +export const isLight = (name) => name === 'classic' || name === 'pink'; + export const DEFAULT = 'dark'; const known = (name) => THEMES.some(([id]) => id === name); diff --git a/scripts/fixtures/legacy-project.json b/scripts/fixtures/legacy-project.json new file mode 100644 index 0000000..49c1b3b --- /dev/null +++ b/scripts/fixtures/legacy-project.json @@ -0,0 +1,93 @@ +{ + "project_id": "5f3b1c7a9d2e4801b6c5a4f39e0d7b21", + "parts": [ + { + "name": "Baseplate", + "position": { "x": 0.0, "y": 0.0, "z": 0.0 }, + "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 }, + "scale": { "x": 200.0, "y": 2.0, "z": 200.0 }, + "color": { "r": 0.49019608, "g": 0.49019608, "b": 0.52156866, "a": 1.0 }, + "material": "Metal", + "group": null, + "cast_shadow": false, + "anchored": false, + "can_collide": false, + "spawn_location": false, + "baseplate": true, + "truss": false, + "textures": [ + { "face": "Top", "kind": "Studs" }, + { "face": "Bottom", "kind": "Inlets" } + ] + }, + { + "name": "SpawnLocation", + "position": { "x": 0.0, "y": 2.5, "z": 0.0 }, + "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 }, + "scale": { "x": 6.0, "y": 1.0, "z": 6.0 }, + "color": { "r": 0.3019608, "g": 0.72156864, "b": 0.29411766, "a": 1.0 }, + "material": "Plastic", + "group": null, + "cast_shadow": true, + "anchored": true, + "can_collide": true, + "spawn_location": true, + "baseplate": false, + "truss": false, + "textures": [] + }, + { + "name": "Part", + "position": { "x": -8.0, "y": 4.0, "z": 3.0 }, + "rotation": { "x": 0.0, "y": 0.38268343, "z": 0.0, "w": 0.9238795 }, + "scale": { "x": 4.0, "y": 1.0, "z": 2.0 }, + "color": { "r": 0.6392157, "g": 0.63529414, "b": 0.6431373, "a": 1.0 }, + "material": "Wood", + "group": 0, + "cast_shadow": true, + "anchored": true, + "can_collide": true, + "spawn_location": false, + "baseplate": false, + "truss": false, + "textures": [] + }, + { + "name": "Part", + "position": { "x": -8.0, "y": 6.0, "z": 3.0 }, + "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 }, + "scale": { "x": 4.0, "y": 1.0, "z": 2.0 }, + "color": { "r": 0.6392157, "g": 0.63529414, "b": 0.6431373, "a": 0.5 }, + "material": "Plastic", + "group": 0, + "cast_shadow": true, + "anchored": true, + "can_collide": true, + "spawn_location": false, + "baseplate": false, + "truss": false, + "textures": [] + } + ], + "lights": [ + { + "name": "Sun", + "position": { "x": 80.0, "y": 160.0, "z": 60.0 }, + "rotation": { "x": -0.5311862, "y": 0.14004472, "z": 0.24240407, "w": 0.79934263 }, + "color": { "r": 1.0, "g": 1.0, "b": 1.0, "a": 1.0 }, + "illuminance": 10000.0, + "shadows_enabled": true + }, + { + "name": "Fill", + "position": { "x": -40.0, "y": 60.0, "z": -20.0 }, + "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 }, + "color": { "r": 0.8, "g": 0.85, "b": 1.0, "a": 1.0 }, + "illuminance": 2500.0, + "shadows_enabled": false + } + ], + "groups": [ + { "name": "Platform", "parent_group": null } + ] +} diff --git a/scripts/fixtures/studio-0-1-project.json b/scripts/fixtures/studio-0-1-project.json deleted file mode 100644 index c37e9ce..0000000 --- a/scripts/fixtures/studio-0-1-project.json +++ /dev/null @@ -1,180 +0,0 @@ -{ - "project_id": "c32819ed4aa4a42511cefa9d974e3ce3", - "parts": [ - { - "name": "Baseplate", - "position": { - "x": 0.0, - "y": -2.0, - "z": 0.0 - }, - "rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - "scale": { - "x": 255.0, - "y": 4.0, - "z": 255.0 - }, - "color": { - "r": 0.49019608, - "g": 0.49019608, - "b": 0.49019608, - "a": 1.0 - }, - "material": "Plastic", - "group": null, - "cast_shadow": true, - "anchored": true, - "can_collide": true, - "spawn_location": false, - "baseplate": true, - "truss": false, - "textures": [ - { - "face": "Top", - "kind": "Studs" - }, - { - "face": "Bottom", - "kind": "Inlets" - } - ] - }, - { - "name": "SpawnLocation", - "position": { - "x": 0.0, - "y": 0.5, - "z": 0.0 - }, - "rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - "scale": { - "x": 6.0, - "y": 1.0, - "z": 6.0 - }, - "color": { - "r": 0.29411766, - "g": 0.5921569, - "b": 0.29411766, - "a": 1.0 - }, - "material": "Plastic", - "group": null, - "cast_shadow": true, - "anchored": true, - "can_collide": true, - "spawn_location": true, - "baseplate": false, - "truss": false, - "textures": [] - }, - { - "name": "Part", - "position": { - "x": 82.0, - "y": 128.0, - "z": 194.0 - }, - "rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - "scale": { - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - "color": { - "r": 0.99999994, - "g": 0.99999994, - "b": 0.99999994, - "a": 1.0 - }, - "material": "Plastic", - "group": 0, - "cast_shadow": true, - "anchored": false, - "can_collide": true, - "spawn_location": false, - "baseplate": false, - "truss": false, - "textures": [] - }, - { - "name": "Part", - "position": { - "x": 82.0, - "y": 128.0, - "z": 194.0 - }, - "rotation": { - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 1.0 - }, - "scale": { - "x": 1.0, - "y": 1.0, - "z": 1.0 - }, - "color": { - "r": 0.99999994, - "g": 0.99999994, - "b": 0.99999994, - "a": 1.0 - }, - "material": "Plastic", - "group": 0, - "cast_shadow": true, - "anchored": false, - "can_collide": true, - "spawn_location": false, - "baseplate": false, - "truss": false, - "textures": [] - } - ], - "lights": [ - { - "name": "Light", - "position": { - "x": 50.0, - "y": 80.0, - "z": 30.0 - }, - "rotation": { - "x": -0.39447272, - "y": 0.43916786, - "z": 0.22334667, - "w": 0.775654 - }, - "color": { - "r": 0.99999994, - "g": 0.99999994, - "b": 0.99999994, - "a": 1.0 - }, - "illuminance": 10000.0, - "shadows_enabled": true - } - ], - "groups": [ - { - "name": "Model", - "parent_group": null - } - ] -} \ No newline at end of file diff --git a/scripts/project.test.mjs b/scripts/project.test.mjs index 4109f96..efb7058 100644 --- a/scripts/project.test.mjs +++ b/scripts/project.test.mjs @@ -7,10 +7,10 @@ import { newGroup } from '../resources/js/studio/groups.js'; import { withNewId } from '../resources/js/studio/ops.js'; import { DEFAULT_ILLUMINANCE } from '../resources/js/studio/lighting.js'; -// The two projects these tests are settled against, both saved by the Studio: the older one for the -// import path a map written before the format changed still takes, the current one for parity. +// A document in the shape the format had before the lighting rig became one object, written here to +// exercise the path a map saved back then still takes on the way in. const official = JSON.parse(readFileSync( - new URL('./fixtures/studio-0-1-project.json', import.meta.url), 'utf8', + new URL('./fixtures/legacy-project.json', import.meta.url), 'utf8', )); const round = (doc) => JSON.parse(JSON.stringify( @@ -21,7 +21,7 @@ test('a project the Studio wrote is recognised as one', () => { assert.equal(isProject(official), true); }); -test('a project the Studio wrote survives import and export unchanged', () => { +test('a document in the older shape survives import and export unchanged', () => { const read = fromProject(official); const parts = read.parts.map(withNewId); const groups = read.groups.map((g) => newGroup(g.name, g.slots.map((i) => parts[i]._id))); @@ -76,8 +76,12 @@ test('a group is an index into groups, and ungrouped is null', () => { assert.equal(out.parts[2].group, 0); }); -test('the light default matches what the Studio writes', () => { - assert.equal(official.lights[0].illuminance, DEFAULT_ILLUMINANCE); +test('the rig comes from the file, not from our defaults', () => { + const read = fromProject(current); + + assert.equal(read.lighting.sun_illuminance, 8000, 'what that file says'); + assert.notEqual(read.lighting.sun_illuminance, DEFAULT_ILLUMINANCE, 'and not what we would pick'); + assert.equal(read.lighting.brightness, 2000); }); test('the slab exports as a Baseplate and keeps its faces', () => { @@ -197,8 +201,8 @@ test('a part with no light carries no light keys', () => { assert.equal('point_light' in fromProject({ parts: [out] }).parts[0], false); }); -// A project the Studio saved, kept here so this is a test of the format and not of what happens to -// be on one machine. +// A project the Studio saved, kept here so this is a test of the format itself and not of what +// happens to be on one machine. const current = JSON.parse(readFileSync( new URL('./fixtures/studio-0-2-project.json', import.meta.url), 'utf8', ));