mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Address review: playable PLAY/NEXT, visible rename editor, accurate copy
- PLAY and NEXT continue into the following scenes, so they stay enabled while any scene in the project has a shot, not only the selected one. - Renaming a shot drops the number and ellipsis so the editor is no longer hidden; qa-scene-controls checks a long rename stays visible. - PLAY, NEXT, EDIT DETAILS and SHARE SCENE tooltips describe what the buttons do, translated in every shipped language. - The primary actions and the file row keep a hover state. - Docs: the EXPORT rename in DIRECTOR-SHARING and the playback button states in CURRENT-STATE are accurate. - Test the voice "authoring" alias through set_panel_open.
This commit is contained in:
1 parent
8de75b172a
commit
5a80facf8d
14 files changed
+129
-34
No files matched your search
@@ -3013,13 +3013,13 @@
|
||||
"Replace the selected shot with the current view": "Sustituye el plano seleccionado por la vista actual",
|
||||
"Click a shot to select it, double-click to rename.": "Haz clic en un plano para seleccionarlo y doble clic para cambiarle el nombre.",
|
||||
"scene|PLAY": "REPROD.",
|
||||
"Play the whole scene from its first shot": "Reproduce toda la escena desde su primer plano",
|
||||
"Stop playback (Esc)": "Detén la reproducción (Esc)",
|
||||
"Play only the shot after the selected one": "Reproduce solo el plano posterior al seleccionado",
|
||||
"SAVE & SHARE": "GUARDAR Y COMPARTIR",
|
||||
"Download every scene as a JSON file you can import later": "Descarga todas las escenas como un archivo JSON que puedes importar más tarde",
|
||||
"Load scenes from an exported JSON file": "Carga escenas desde un archivo JSON exportado",
|
||||
"Download the timing log of the last play": "Descarga el registro de tiempos de la última reproducción",
|
||||
"Edit the scene title and description": "Edita el título y la descripción de la escena",
|
||||
"Share this scene as a link or file": "Comparte esta escena como enlace o archivo"
|
||||
"Play from this scene through the rest of the project": "Reproduce desde esta escena hasta el resto del proyecto",
|
||||
"Play the shot after the selected one, moving on to the next scene when needed": "Reproduce el plano posterior al seleccionado y pasa a la siguiente escena si hace falta",
|
||||
"Edit anchors, data packs and shot details": "Edita anclas, paquetes de datos y detalles de los planos",
|
||||
"Download this scene as JSON or an asset bundle": "Descarga esta escena como JSON o como paquete de recursos"
|
||||
}
|
||||
@@ -3082,13 +3082,13 @@
|
||||
"Replace the selected shot with the current view": "Заменить выбранный кадр текущим видом",
|
||||
"Click a shot to select it, double-click to rename.": "Щёлкните кадр, чтобы выбрать его, дважды — чтобы переименовать.",
|
||||
"scene|PLAY": "ПУСК",
|
||||
"Play the whole scene from its first shot": "Воспроизвести всю сцену с первого кадра",
|
||||
"Stop playback (Esc)": "Остановить воспроизведение (Esc)",
|
||||
"Play only the shot after the selected one": "Воспроизвести только кадр после выбранного",
|
||||
"SAVE & SHARE": "СОХРАНИТЬ И ПОДЕЛИТЬСЯ",
|
||||
"Download every scene as a JSON file you can import later": "Скачать все сцены файлом JSON для последующего импорта",
|
||||
"Load scenes from an exported JSON file": "Загрузить сцены из экспортированного файла JSON",
|
||||
"Download the timing log of the last play": "Скачать журнал таймингов последнего воспроизведения",
|
||||
"Edit the scene title and description": "Изменить название и описание сцены",
|
||||
"Share this scene as a link or file": "Поделиться сценой ссылкой или файлом"
|
||||
"Play from this scene through the rest of the project": "Воспроизвести с этой сцены и далее по всему проекту",
|
||||
"Play the shot after the selected one, moving on to the next scene when needed": "Воспроизвести кадр после выбранного, при необходимости перейдя к следующей сцене",
|
||||
"Edit anchors, data packs and shot details": "Изменить якоря, пакеты данных и параметры кадров",
|
||||
"Download this scene as JSON or an asset bundle": "Скачать эту сцену в формате JSON или архивом ресурсов"
|
||||
}
|
||||
@@ -2875,13 +2875,13 @@
|
||||
"Replace the selected shot with the current view": "用当前视角替换所选镜头",
|
||||
"Click a shot to select it, double-click to rename.": "单击镜头即可选中,双击可重命名。",
|
||||
"scene|PLAY": "播放",
|
||||
"Play the whole scene from its first shot": "从第一个镜头开始播放整个场景",
|
||||
"Stop playback (Esc)": "停止播放(Esc)",
|
||||
"Play only the shot after the selected one": "仅播放所选镜头的下一个镜头",
|
||||
"SAVE & SHARE": "保存与分享",
|
||||
"Download every scene as a JSON file you can import later": "将所有场景下载为 JSON 文件,以便日后导入",
|
||||
"Load scenes from an exported JSON file": "从导出的 JSON 文件加载场景",
|
||||
"Download the timing log of the last play": "下载上次播放的计时日志",
|
||||
"Edit the scene title and description": "编辑场景标题和描述",
|
||||
"Share this scene as a link or file": "以链接或文件形式分享此场景"
|
||||
"Play from this scene through the rest of the project": "从此场景开始播放项目中的其余场景",
|
||||
"Play the shot after the selected one, moving on to the next scene when needed": "播放所选镜头的下一个镜头,必要时进入下一个场景",
|
||||
"Edit anchors, data packs and shot details": "编辑锚点、数据包和镜头详情",
|
||||
"Download this scene as JSON or an asset bundle": "将此场景下载为 JSON 或资源包"
|
||||
}
|
||||
@@ -2875,13 +2875,13 @@
|
||||
"Replace the selected shot with the current view": "用當前視角替換所選鏡頭",
|
||||
"Click a shot to select it, double-click to rename.": "單擊鏡頭即可選中,雙擊可重命名。",
|
||||
"scene|PLAY": "播放",
|
||||
"Play the whole scene from its first shot": "從第一個鏡頭開始播放整個場景",
|
||||
"Stop playback (Esc)": "停止播放(Esc)",
|
||||
"Play only the shot after the selected one": "僅播放所選鏡頭的下一個鏡頭",
|
||||
"SAVE & SHARE": "保存與分享",
|
||||
"Download every scene as a JSON file you can import later": "將所有場景下載為 JSON 文件,以便日後導入",
|
||||
"Load scenes from an exported JSON file": "從導出的 JSON 文件加載場景",
|
||||
"Download the timing log of the last play": "下載上次播放的計時日誌",
|
||||
"Edit the scene title and description": "編輯場景標題和描述",
|
||||
"Share this scene as a link or file": "以鏈接或文件形式分享此場景"
|
||||
"Play from this scene through the rest of the project": "從此場景開始播放項目中的其餘場景",
|
||||
"Play the shot after the selected one, moving on to the next scene when needed": "播放所選鏡頭的下一個鏡頭,必要時進入下一個場景",
|
||||
"Edit anchors, data packs and shot details": "編輯錨點、數據包和鏡頭詳情",
|
||||
"Download this scene as JSON or an asset bundle": "將此場景下載為 JSON 或資源包"
|
||||
}
|
||||
@@ -220,7 +220,11 @@ export class SceneControls {
|
||||
const shots = scene?.shots ?? [];
|
||||
presentSceneButtons(this.elements, running, state.hasRun, {
|
||||
hasScene: !!scene,
|
||||
shotCount: shots.length,
|
||||
// PLAY and NEXT run on into the following scenes.
|
||||
playableShots: (state.scenes ?? []).reduce(
|
||||
(total, item) => total + (item.shots?.length ?? 0),
|
||||
0,
|
||||
),
|
||||
hasSelectedShot: shots.some((shot) => shot.id === state.selectedShotId),
|
||||
});
|
||||
this.elements.panel?.classList.toggle('has-shots', shots.length > 0);
|
||||
|
||||
@@ -184,7 +184,16 @@ test('Authoring disables idle actions that would do nothing', () => {
|
||||
assert.equal(f.elements.update.disabled, true);
|
||||
assert.equal(f.elements.start.disabled, false);
|
||||
|
||||
// PLAY and NEXT run on into the following scenes, so an empty selected
|
||||
// scene beside one with shots keeps them available.
|
||||
f.state.scenes[0].shots = [];
|
||||
f.state.scenes.push({ id: 'scene-b', title: 'B', shots: [{ id: 'b1' }] });
|
||||
f.owner.setButtons(false);
|
||||
assert.equal(f.elements.start.disabled, false);
|
||||
assert.equal(f.elements.next.disabled, false);
|
||||
assert.equal(f.elements.update.disabled, true);
|
||||
|
||||
f.state.scenes.pop();
|
||||
f.owner.setButtons(false);
|
||||
assert.equal(f.elements.start.disabled, true);
|
||||
assert.equal(f.elements.next.disabled, true);
|
||||
|
||||
@@ -173,22 +173,24 @@ export function presentSceneSelection(element, selectedShotId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Everything but STOP is off while a scene plays. Otherwise a button is off
|
||||
* when it would do nothing: DELETE and CAPTURE SHOT without a scene, UPDATE
|
||||
* SHOT without a selected shot, PLAY and NEXT on a scene with no shots.
|
||||
* While a scene plays, the authoring and file actions here are off and STOP
|
||||
* is on. Otherwise a button is off when it would do nothing: DELETE and
|
||||
* CAPTURE SHOT without a scene, UPDATE SHOT without a selected shot, PLAY and
|
||||
* NEXT when no scene in the project has a shot (both continue into the
|
||||
* following scenes).
|
||||
*/
|
||||
export function presentSceneButtons(
|
||||
elements,
|
||||
running,
|
||||
hasRun,
|
||||
{ hasScene = true, shotCount = 1, hasSelectedShot = true } = {},
|
||||
{ hasScene = true, playableShots = 1, hasSelectedShot = true } = {},
|
||||
) {
|
||||
const idleOff = {
|
||||
delete: !hasScene,
|
||||
capture: !hasScene,
|
||||
update: !hasSelectedShot,
|
||||
start: shotCount === 0,
|
||||
next: shotCount === 0,
|
||||
start: playableShots === 0,
|
||||
next: playableShots === 0,
|
||||
};
|
||||
for (const name of [
|
||||
'start',
|
||||
|
||||
@@ -181,8 +181,12 @@ export function mountSceneSharing(
|
||||
bar.dataset.directorAuthoring = '';
|
||||
bar.className = 'scene-controls';
|
||||
const entries = [
|
||||
[t('EDIT DETAILS'), t('Edit the scene title and description'), edit],
|
||||
[t('SHARE SCENE'), t('Share this scene as a link or file'), share],
|
||||
[t('EDIT DETAILS'), t('Edit anchors, data packs and shot details'), edit],
|
||||
[
|
||||
t('SHARE SCENE'),
|
||||
t('Download this scene as JSON or an asset bundle'),
|
||||
share,
|
||||
],
|
||||
];
|
||||
const removers = [];
|
||||
for (const [text, title, fn] of entries) {
|
||||
|
||||
@@ -223,6 +223,14 @@ html:not([lang='en']) #scene-panel .scene-controls .scene-btn {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Keep the shared hover on the restyled actions. */
|
||||
#scene-panel .scene-btn-primary:hover:not(:disabled),
|
||||
#scene-panel .scene-file-controls .scene-btn:hover:not(:disabled) {
|
||||
color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
background: color-mix(in srgb, var(--accent) 16%, transparent);
|
||||
}
|
||||
|
||||
.scene-shot-hint {
|
||||
margin: 0 0 8px;
|
||||
font-size: 11px;
|
||||
@@ -311,6 +319,16 @@ html:not([lang='en']) #scene-panel .scene-controls .scene-btn {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* While renaming, the label holds only the editor at full width. */
|
||||
.scene-shot-label:has(.scene-shot-rename) {
|
||||
overflow: visible;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.scene-shot-label:has(.scene-shot-rename)::before {
|
||||
content: none;
|
||||
}
|
||||
|
||||
/* Shots are numbered 01, 02… in playback order. */
|
||||
.scene-shot-label::before {
|
||||
content: counter(scene-shot, decimal-leading-zero);
|
||||
|
||||
@@ -166,9 +166,9 @@
|
||||
<p class="scene-shot-hint" data-i18n>Click a shot to select it, double-click to rename.</p>
|
||||
<p class="scene-step-heading" data-i18n>PREVIEW</p>
|
||||
<div class="scene-controls">
|
||||
<button id="scene-start-btn" type="button" class="gev-action-button scene-btn scene-btn-primary" title="Play the whole scene from its first shot" data-i18n-title data-i18n-runtime>PLAY</button>
|
||||
<button id="scene-start-btn" type="button" class="gev-action-button scene-btn scene-btn-primary" title="Play from this scene through the rest of the project" data-i18n-title data-i18n-runtime>PLAY</button>
|
||||
<button id="scene-stop-btn" type="button" class="gev-action-button gev-action-button--danger scene-btn scene-btn-danger" title="Stop playback (Esc)" data-i18n data-i18n-title>STOP</button>
|
||||
<button id="scene-next-btn" type="button" class="gev-action-button scene-btn" title="Play only the shot after the selected one" data-i18n data-i18n-title>NEXT</button>
|
||||
<button id="scene-next-btn" type="button" class="gev-action-button scene-btn" title="Play the shot after the selected one, moving on to the next scene when needed" data-i18n data-i18n-title>NEXT</button>
|
||||
</div>
|
||||
<p class="scene-step-heading" data-i18n>SAVE & SHARE</p>
|
||||
<div class="scene-controls scene-file-controls">
|
||||
|
||||
@@ -3931,3 +3931,26 @@ test('analyst-only lookup distinguishes duplicate names and uses canonical aircr
|
||||
assert.equal(plane.ok, true);
|
||||
assert.equal(plane.latitude, 36, 'canonical ID resolves the current position, not old coordinates');
|
||||
});
|
||||
|
||||
test('set_panel_open accepts the Authoring name for the scene panel', async () => {
|
||||
const calls = [];
|
||||
const runner = createGevActionRunner({
|
||||
viewer: {
|
||||
clock: { onTick: { addEventListener: () => () => {} } },
|
||||
scene: { canvas: { addEventListener() {}, removeEventListener() {} } },
|
||||
camera: {
|
||||
moveEnd: { addEventListener() {} },
|
||||
positionWC: Cesium.Cartesian3.fromDegrees(-97.7, 30.2, 1000),
|
||||
},
|
||||
},
|
||||
styleManager: {
|
||||
setPanelCollapsed: (...args) => calls.push(args),
|
||||
},
|
||||
dataManager: { layers: new Map(), isEnabled: () => false, getAll: () => [] },
|
||||
});
|
||||
for (const panel of ['authoring', 'Authoring', 'scenes']) {
|
||||
const result = await runner('set_panel_open', { panelId: panel, open: true });
|
||||
assert.equal(result.panelId, 'scene-panel');
|
||||
}
|
||||
assert.deepEqual(calls.at(-1), ['scene-panel', false, { explicit: true }]);
|
||||
});
|
||||
Reference in new issue
Block a user