/** * What the scene view shows of each placeable type – symbol, name, a collider's outline. It lives * in the project like the game scale: saved, but never an undo step. */ import { describe, expect, it } from 'vitest'; import { createEmptyProject } from '../../src/core/model/Project'; import { defaultSceneVisibility, sceneVisibilityOf, shows, VISIBILITY_TYPES, visibilityParts, } from '../../src/core/model/sceneVisibility'; import { deserializeProject, serializeProject } from '../../src/core/store/serialize'; import { EditorState } from '../../src/editor/state'; function loaded() { const state = new EditorState(); state.loadProject(createEmptyProject('p', 'P'), 1); return state; } describe('scene visibility', () => { it('lists every placeable type, Behavior to Tilemap', () => { expect(VISIBILITY_TYPES).toEqual([ 'behavior', 'camera', 'clip', 'collider', 'container', 'joint', 'particles', 'rigidbody', 'sprite', 'text', 'tilemap', ]); }); it('gives a symbol switch only to types with a symbol, and an outline switch to what collides', () => { expect(visibilityParts('behavior')).toEqual(['symbol', 'label']); expect(visibilityParts('collider')).toEqual(['symbol', 'label', 'shape']); expect(visibilityParts('sprite')).toEqual(['label']); expect(visibilityParts('tilemap')).toEqual(['label', 'shape']); }); it('gives only a camera a switch for its shader, off until switched on (#299)', () => { expect(visibilityParts('camera')).toEqual(['symbol', 'label', 'shader']); expect(VISIBILITY_TYPES.filter((type) => visibilityParts(type).includes('shader'))).toEqual(['camera']); const visibility = defaultSceneVisibility(); expect(shows(visibility, 'camera', 'shader')).toBe(false); visibility.camera.shader = true; expect(shows(visibility, 'camera', 'shader')).toBe(true); visibility.sprite.shader = true; expect(shows(visibility, 'sprite', 'shader')).toBe(false); }); it('shows what it always showed in a new project and in one written before there was any', () => { for (const visibility of [ createEmptyProject('p', 'P').sceneVisibility, deserializeProject({ id: 'p', name: 'P', assets: [] }).sceneVisibility, ]) { expect(shows(visibility, 'behavior', 'symbol')).toBe(true); expect(shows(visibility, 'behavior', 'label')).toBe(true); expect(shows(visibility, 'collider', 'shape')).toBe(true); expect(shows(visibility, 'tilemap', 'shape')).toBe(true); expect(shows(visibility, 'sprite', 'label')).toBe(false); expect(shows(visibility, 'sprite', 'shape')).toBe(true); } }); it('survives a save and a load', () => { const project = createEmptyProject('p', 'P'); project.sceneVisibility.collider.shape = false; project.sceneVisibility.tilemap.shape = false; project.sceneVisibility.rigidbody.label = false; project.sceneVisibility.sprite.label = true; project.sceneVisibility.camera.shader = true; const back = deserializeProject(JSON.parse(JSON.stringify(serializeProject(project)))).sceneVisibility; expect(back.camera.shader).toBe(true); expect(back.collider.shape).toBe(false); expect(back.tilemap.shape).toBe(false); expect(back.rigidbody.label).toBe(false); expect(back.sprite.label).toBe(true); expect(back.behavior).toEqual(defaultSceneVisibility().behavior); }); it('reads untrusted JSON part by part, the rest as the defaults', () => { const read = sceneVisibilityOf({ sceneVisibility: { camera: { symbol: false, label: 'no' }, texture: { label: true }, text: 3 }, }); expect(read.camera).toEqual({ symbol: false, label: true, shape: true, shader: false }); expect(read.text).toEqual(defaultSceneVisibility().text); expect('texture' in read).toBe(false); expect(sceneVisibilityOf(null)).toEqual(defaultSceneVisibility()); }); it('never hides what a type does not have to hide', () => { const visibility = defaultSceneVisibility(); visibility.sprite.symbol = false; visibility.sprite.shape = false; expect(shows(visibility, 'sprite', 'shape')).toBe(true); visibility.behavior.shape = false; expect(shows(visibility, 'behavior', 'shape')).toBe(true); }); it('saves a switch without an undo step', () => { const state = loaded(); state.setSceneVisibility('collider', 'shape', false); expect(state.project.sceneVisibility.collider.shape).toBe(false); expect(state.saveStatus).toBe('dirty'); expect(state.commands.canUndo).toBe(false); }); it('keeps a switch flipped while playing after Stop', () => { const state = loaded(); state.enterPlay(); state.setSceneVisibility('behavior', 'label', false); expect(state.project.sceneVisibility.behavior.label).toBe(false); state.exitPlay(); expect(state.project.sceneVisibility.behavior.label).toBe(false); }); });