diff --git a/src/Globals.d.ts b/src/Globals.d.ts index 409bbc069..18d15f00f 100644 --- a/src/Globals.d.ts +++ b/src/Globals.d.ts @@ -1,3 +1,7 @@ declare module '*.css'; type Modify = Omit & R; + +type RemoveIndex = { + [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K]; +}; diff --git a/src/PythonConverter/PythonConverterService.tsx b/src/PythonConverter/PythonConverterService.tsx index 68bf1eb4b..9852aabdc 100644 --- a/src/PythonConverter/PythonConverterService.tsx +++ b/src/PythonConverter/PythonConverterService.tsx @@ -1,7 +1,7 @@ import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react'; import * as Comlink from 'comlink'; import { createGenericContext } from '../services/GenericContext'; -import { IPythonWorker } from './PythonWorker'; +import { PythonWorker } from './PythonWorker'; import { EditorJson } from '../ThreeEditor/js/EditorJson'; import { SimulationInputFiles } from '../types/ResponseTypes'; @@ -17,13 +17,15 @@ export interface PythonConverterProps { onLoad?: (pyodide: any) => void; } -export interface IPythonConverter { - convertJSON: (editorJson: EditorJson) => Promise>; +export interface PythonConverterContext { + convertJSON: ( + editorJson: EditorJson + ) => Promise, string>>; isConverterReady: boolean; } const [usePythonConverter, PythonConverterContextProvider] = - createGenericContext(); + createGenericContext(); const PYODIDE_LOADED = 'PYODIDE_LOADED'; @@ -32,10 +34,10 @@ const PYODIDE_LOADED = 'PYODIDE_LOADED'; * There can be only one instance of PythonConverter in the whole application. */ const PythonConverter = (props: PythonConverterProps) => { - const workerRef = useRef>(); + const workerRef = useRef>(); useEffect(() => { - workerRef.current = Comlink.wrap( + workerRef.current = Comlink.wrap( new Worker(new URL('./PythonWorker.ts', import.meta.url)) ); workerRef.current.initPyodide( @@ -70,7 +72,7 @@ const PythonConverter = (props: PythonConverterProps) => { return await workerRef.current!.convertJSON(editorJSON); }; - const value: IPythonConverter = { + const value: PythonConverterContext = { convertJSON, isConverterReady }; diff --git a/src/PythonConverter/PythonWorker.ts b/src/PythonConverter/PythonWorker.ts index 6ab126e1c..ebf37e96a 100644 --- a/src/PythonConverter/PythonWorker.ts +++ b/src/PythonConverter/PythonWorker.ts @@ -7,12 +7,14 @@ import { EditorJson } from '../ThreeEditor/js/EditorJson'; // CND method is suggested in https://pyodide.org/en/stable/usage/downloading-and-deploying.html importScripts('https://cdn.jsdelivr.net/pyodide/v0.21.3/full/pyodide.js'); -export interface IPythonWorker { +export interface PythonWorker { initPyodide: (onReady: () => void) => void; close: () => void; runPython: (string: string) => T; checkConverter: () => boolean; - convertJSON: (editorJson: EditorJson) => Promise>; + convertJSON: ( + editorJson: EditorJson + ) => Promise, string>>; } const pythonConverterCode = ` @@ -36,7 +38,7 @@ def checkIfConverterReady(): checkIfConverterReady() `; -class PythonWorkerBase implements IPythonWorker { +class PythonWorkerBase implements PythonWorker { readonly isPythonWorker: true = true; async initPyodide(onReady: () => void) { const pyodide = await self.loadPyodide(); diff --git a/src/ThreeEditor/CSG/CSGWorker.ts b/src/ThreeEditor/CSG/CSGWorker.ts index 5be3027f5..78db78501 100644 --- a/src/ThreeEditor/CSG/CSGWorker.ts +++ b/src/ThreeEditor/CSG/CSGWorker.ts @@ -1,11 +1,7 @@ import * as Comlink from 'comlink'; import * as THREE from 'three'; -export interface IZoneWorker { - parse: (json: string) => unknown; -} - -class ZoneWorker implements IZoneWorker { +export class ZoneWorker { readonly isCSGWorker: true = true; async parse(json: string) { console.log('CSGWorker', await new THREE.ObjectLoader().parseAsync(JSON.parse(json))); diff --git a/src/ThreeEditor/Simulation/Base/SimZone.ts b/src/ThreeEditor/Simulation/Base/SimZone.ts index 234ede661..b30a23f26 100644 --- a/src/ThreeEditor/Simulation/Base/SimZone.ts +++ b/src/ThreeEditor/Simulation/Base/SimZone.ts @@ -1,7 +1,7 @@ import * as THREE from 'three'; import { SimulationMesh } from './SimulationMesh'; -import { SimulationPropertiesType } from '../../../types/SimProperties'; -import { ISimulationSceneChild, SimulationSceneContainer } from './SimulationScene'; +import { SimulationPropertiesType } from '../../../types/SimulationProperties'; +import { SimulationSceneChild, SimulationSceneContainer } from './SimulationScene'; import { Editor } from '../../js/Editor'; import SimulationMaterial, { SimulationMaterialJSON } from '../Materials/SimulationMaterial'; @@ -39,7 +39,7 @@ const _get_default = (material: SimulationMaterial) => { export abstract class SimulationZone extends SimulationMesh - implements SimulationPropertiesType, ISimulationSceneChild + implements SimulationPropertiesType, SimulationSceneChild { editor: Editor; parent: SimulationSceneContainer | null = null; diff --git a/src/ThreeEditor/Simulation/Base/SimulationElement.ts b/src/ThreeEditor/Simulation/Base/SimulationElement.ts index 86a101a5e..641e4feb6 100644 --- a/src/ThreeEditor/Simulation/Base/SimulationElement.ts +++ b/src/ThreeEditor/Simulation/Base/SimulationElement.ts @@ -1,7 +1,7 @@ import * as THREE from 'three'; import { Editor } from '../../js/Editor'; -import { SimulationPropertiesType } from '../../../types/SimProperties'; -import { ISimulationSceneChild, SimulationSceneContainer } from './SimulationScene'; +import { SimulationPropertiesType } from '../../../types/SimulationProperties'; +import { SimulationSceneChild, SimulationSceneContainer } from './SimulationScene'; /** * This is the base class for all simulation elements. @@ -10,7 +10,7 @@ import { ISimulationSceneChild, SimulationSceneContainer } from './SimulationSce */ export abstract class SimulationElement extends THREE.Object3D - implements SimulationPropertiesType, ISimulationSceneChild + implements SimulationPropertiesType, SimulationSceneChild { editor: Editor; parent: SimulationSceneContainer | null = null; diff --git a/src/ThreeEditor/Simulation/Base/SimulationMesh.ts b/src/ThreeEditor/Simulation/Base/SimulationMesh.ts index 8f32e66a4..de1f95b54 100644 --- a/src/ThreeEditor/Simulation/Base/SimulationMesh.ts +++ b/src/ThreeEditor/Simulation/Base/SimulationMesh.ts @@ -1,7 +1,7 @@ import * as THREE from 'three'; import { Editor } from '../../js/Editor'; -import { ISimulationSceneChild, SimulationSceneContainer } from './SimulationScene'; -import { SimulationPropertiesType } from '../../../types/SimProperties'; +import { SimulationSceneChild, SimulationSceneContainer } from './SimulationScene'; +import { SimulationPropertiesType } from '../../../types/SimulationProperties'; import { SimulationElement } from './SimulationElement'; /** @@ -12,7 +12,7 @@ export abstract class SimulationMesh< TMaterial extends THREE.Material = THREE.MeshBasicMaterial > extends THREE.Mesh - implements SimulationPropertiesType, ISimulationSceneChild, SimulationElement + implements SimulationPropertiesType, SimulationSceneChild, SimulationElement { editor: Editor; parent: SimulationSceneContainer | null = null; diff --git a/src/ThreeEditor/Simulation/Base/SimulationPoints.ts b/src/ThreeEditor/Simulation/Base/SimulationPoints.ts index 875a9e14f..fd54aba70 100644 --- a/src/ThreeEditor/Simulation/Base/SimulationPoints.ts +++ b/src/ThreeEditor/Simulation/Base/SimulationPoints.ts @@ -1,7 +1,7 @@ import * as THREE from 'three'; import { Editor } from '../../js/Editor'; -import { SimulationPropertiesType } from '../../../types/SimProperties'; -import { ISimulationSceneChild, SimulationSceneContainer } from './SimulationScene'; +import { SimulationPropertiesType } from '../../../types/SimulationProperties'; +import { SimulationSceneChild, SimulationSceneContainer } from './SimulationScene'; import { SimulationElement } from './SimulationElement'; /** @@ -9,7 +9,7 @@ import { SimulationElement } from './SimulationElement'; */ export abstract class SimulationPoints extends THREE.Points - implements SimulationPropertiesType, ISimulationSceneChild, SimulationElement + implements SimulationPropertiesType, SimulationSceneChild, SimulationElement { private static _detectPointsMaterial: THREE.PointsMaterial = new THREE.PointsMaterial({ color: new THREE.Color('cyan'), diff --git a/src/ThreeEditor/Simulation/Base/SimulationScene.ts b/src/ThreeEditor/Simulation/Base/SimulationScene.ts index 79aad7996..56e53b319 100644 --- a/src/ThreeEditor/Simulation/Base/SimulationScene.ts +++ b/src/ThreeEditor/Simulation/Base/SimulationScene.ts @@ -1,10 +1,10 @@ import * as THREE from 'three'; -import { SimulationPropertiesType } from '../../../types/SimProperties'; +import { SimulationPropertiesType } from '../../../types/SimulationProperties'; import { Editor } from '../../js/Editor'; import { UniqueChildrenNames, getNextFreeName } from '../../../util/Name/Name'; import { SimulationElement } from './SimulationElement'; -export interface ISimulationSceneChild extends THREE.Object3D { +export interface SimulationSceneChild extends THREE.Object3D { parent: SimulationSceneContainer | null; name: string; type: string; @@ -15,7 +15,7 @@ export interface ISimulationSceneChild extends THREE.Object3D { /** * This is the base class for groups of simulation elements. */ -export abstract class SimulationSceneContainer +export abstract class SimulationSceneContainer extends SimulationElement implements SimulationPropertiesType, UniqueChildrenNames { @@ -40,7 +40,8 @@ export abstract class SimulationSceneContainer> { + // toJSON(): Array> { TODO: Make it work for all SimulationSceneContainers. + toJSON(): Object { return this.children.map(child => child.toJSON()); } } diff --git a/src/ThreeEditor/Simulation/Detectors/DetectManager.ts b/src/ThreeEditor/Simulation/Detectors/DetectManager.ts index 4543348ff..955736044 100644 --- a/src/ThreeEditor/Simulation/Detectors/DetectManager.ts +++ b/src/ThreeEditor/Simulation/Detectors/DetectManager.ts @@ -2,7 +2,7 @@ import { Signal } from 'signals'; import * as THREE from 'three'; import { Editor } from '../../js/Editor'; import { SimulationSceneContainer } from '../Base/SimulationScene'; -import { SimulationPropertiesType } from '../../../types/SimProperties'; +import { SimulationPropertiesType } from '../../../types/SimulationProperties'; import { DetectFilter, FilterJSON } from '../Scoring/DetectFilter'; import { DetectGeometry, DetectGeometryJSON, isDetectGeometry } from './DetectGeometry'; import { SimulationZone } from '../Base/SimZone'; diff --git a/src/ThreeEditor/Simulation/Figures/FigureScene.ts b/src/ThreeEditor/Simulation/Figures/FigureScene.ts index d4ee7e630..6531de743 100644 --- a/src/ThreeEditor/Simulation/Figures/FigureScene.ts +++ b/src/ThreeEditor/Simulation/Figures/FigureScene.ts @@ -2,7 +2,7 @@ import * as THREE from 'three'; import { Editor } from '../../js/Editor'; import { generateSimulationInfo } from '../../../util/AdditionalGeometryData'; import { BasicFigure } from './BasicFigures'; -import { SimulationPropertiesType } from '../../../types/SimProperties'; +import { SimulationPropertiesType } from '../../../types/SimulationProperties'; import { UniqueChildrenNames, getNextFreeName } from '../../../util/Name/Name'; export class FigureScene diff --git a/src/ThreeEditor/Simulation/Zones/BooleanZone.ts b/src/ThreeEditor/Simulation/Zones/BooleanZone.ts index 0a1186942..f98b4a867 100644 --- a/src/ThreeEditor/Simulation/Zones/BooleanZone.ts +++ b/src/ThreeEditor/Simulation/Zones/BooleanZone.ts @@ -1,7 +1,7 @@ import { Signal } from 'signals'; import * as THREE from 'three'; import { debounce } from 'throttle-debounce'; -import { IZoneWorker } from '../../CSG/CSGWorker'; +import { ZoneWorker } from '../../CSG/CSGWorker'; import * as Comlink from 'comlink'; import { Editor } from '../../js/Editor'; import CSG from '../../js/libs/csg/three-csg'; @@ -44,7 +44,7 @@ export class BooleanZone extends SimulationZone { return this._unionOperations; } - worker?: Comlink.Remote; + worker?: Comlink.Remote; readonly debouncedUpdatePreview = debounce(200, () => this.updatePreview(), { atBegin: false }); constructor(editor: Editor, name?: string) { diff --git a/src/ThreeEditor/Simulation/Zones/ZoneManager.ts b/src/ThreeEditor/Simulation/Zones/ZoneManager.ts index 1617fcfaf..5897ca0d9 100644 --- a/src/ThreeEditor/Simulation/Zones/ZoneManager.ts +++ b/src/ThreeEditor/Simulation/Zones/ZoneManager.ts @@ -1,12 +1,12 @@ import * as Comlink from 'comlink'; import { Signal } from 'signals'; import * as THREE from 'three'; -import { SimulationPropertiesType } from '../../../types/SimProperties'; +import { SimulationPropertiesType } from '../../../types/SimulationProperties'; import { SimulationSceneContainer } from '../Base/SimulationScene'; import { Editor } from '../../js/Editor'; import { WorldZone, WorldZoneJSON } from './WorldZone/WorldZone'; import { BooleanZone, BooleanZoneJSON } from './BooleanZone'; -import { IZoneWorker } from '../../CSG/CSGWorker'; +import { ZoneWorker } from '../../CSG/CSGWorker'; interface ZoneManagerJSON { uuid: string; @@ -42,7 +42,7 @@ export class ZoneManager extends THREE.Scene implements SimulationPropertiesType readonly notScalable = true; editor: Editor; - worker: Comlink.Remote; + worker: Comlink.Remote; worldZone: WorldZone; zoneContainer: ZoneContainer; @@ -66,7 +66,7 @@ export class ZoneManager extends THREE.Scene implements SimulationPropertiesType light.position.set(15, 15, 15); this.add(light); this.add(this.zoneContainer); - this.worker = Comlink.wrap( + this.worker = Comlink.wrap( new Worker(new URL('../../CSG/CSGWorker.ts', import.meta.url)) ); this.editor = editor; diff --git a/src/ThreeEditor/components/Select/ParticleSelect.tsx b/src/ThreeEditor/components/Select/ParticleSelect.tsx index 80b971071..9f9c614ad 100644 --- a/src/ThreeEditor/components/Select/ParticleSelect.tsx +++ b/src/ThreeEditor/components/Select/ParticleSelect.tsx @@ -1,19 +1,19 @@ import React from 'react'; import { AutoCompleteSelect } from '../../../util/genericComponents/AutoCompleteSelect'; -export interface IParticleType { +export interface ParticleType { id: number; name: string; } export interface ParticleSelectProps { onChange?: (event: React.SyntheticEvent, newValue: number) => void; - particles: IParticleType[]; + particles: readonly ParticleType[]; value?: number; } export function ParticleSelect(props: ParticleSelectProps) { - const getOptionLabel = ({ id, name }: IParticleType) => { + const getOptionLabel = ({ id, name }: ParticleType) => { return `[${id}] ${name}`; }; diff --git a/src/ThreeEditor/components/Sidebar/SidebarTree/SidebarTreeItem.tsx b/src/ThreeEditor/components/Sidebar/SidebarTree/SidebarTreeItem.tsx index b269e33e0..42c7e395c 100644 --- a/src/ThreeEditor/components/Sidebar/SidebarTree/SidebarTreeItem.tsx +++ b/src/ThreeEditor/components/Sidebar/SidebarTree/SidebarTreeItem.tsx @@ -8,7 +8,7 @@ import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import VisibilityIcon from '@mui/icons-material/Visibility'; import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import { Editor } from '../../../js/Editor'; -import { SimulationPropertiesType } from '../../../../types/SimProperties'; +import { SimulationPropertiesType } from '../../../../types/SimulationProperties'; import { NodeModel, TreeMethods } from '@minoru/react-dnd-treeview/dist/types'; import { canChangeName, diff --git a/src/ThreeEditor/components/Sidebar/properties/category/BeamConfiguration.tsx b/src/ThreeEditor/components/Sidebar/properties/category/BeamConfiguration.tsx index 8d8fb25c9..4379fa794 100644 --- a/src/ThreeEditor/components/Sidebar/properties/category/BeamConfiguration.tsx +++ b/src/ThreeEditor/components/Sidebar/properties/category/BeamConfiguration.tsx @@ -1,20 +1,20 @@ import { Button, Divider, Stack, ToggleButton, ToggleButtonGroup } from '@mui/material'; import { ChangeEvent } from 'react'; import { Object3D } from 'three'; -import { SetValueCommand } from '../../../../js/commands/SetValueCommand'; -import { Editor } from '../../../../js/Editor'; +import { PARTICLE_TYPES } from '../../../../../types/Particle'; +import { useSmartWatchEditorState } from '../../../../../util/hooks/signals'; import { - Beam, BEAM_SOURCE_TYPE, - isBeam, - SadType, + Beam, SAD_TYPE, + SIGMA_TYPE, + SadType, SigmaType, - SIGMA_TYPE + isBeam } from '../../../../Simulation/Physics/Beam'; -import { useSmartWatchEditorState } from '../../../../../util/hooks/signals'; -import { PARTICLE_TYPES } from '../../../../../types/Particle'; -import { IParticleType, ParticleSelect } from '../../../Select/ParticleSelect'; +import { Editor } from '../../../../js/Editor'; +import { SetValueCommand } from '../../../../js/commands/SetValueCommand'; +import { ParticleSelect } from '../../../Select/ParticleSelect'; import { NumberPropertyField, PropertyField, @@ -305,7 +305,7 @@ function BeamConfigurationFields(props: { editor: Editor; object: Beam }) { /> setValueCommand({ ...watchedObject.particleData, id: v }, 'particleData') diff --git a/src/ThreeEditor/components/Sidebar/properties/category/ObjectPlacement.tsx b/src/ThreeEditor/components/Sidebar/properties/category/ObjectPlacement.tsx index 59e6147c1..70201db0a 100644 --- a/src/ThreeEditor/components/Sidebar/properties/category/ObjectPlacement.tsx +++ b/src/ThreeEditor/components/Sidebar/properties/category/ObjectPlacement.tsx @@ -2,9 +2,9 @@ import { Euler, MathUtils, Vector3 } from 'three'; import { SetValueCommand } from '../../../../js/commands/SetValueCommand'; import { Editor } from '../../../../js/Editor'; import { Vector3PropertyField } from '../fields/PropertyField'; -import { SimulationPropertiesType } from '../../../../../types/SimProperties'; +import { SimulationPropertiesType } from '../../../../../types/SimulationProperties'; import { Beam, isBeam } from '../../../../Simulation/Physics/Beam'; -import { isWorldZone, WorldZone } from '../../../../Simulation/Zones/WorldZone/WorldZone'; +import { isWorldZone } from '../../../../Simulation/Zones/WorldZone/WorldZone'; import { isDetectGeometry } from '../../../../Simulation/Detectors/DetectGeometry'; import { SetDetectPositionCommand } from '../../../../js/commands/SetDetectPositionCommand'; import { SetPositionCommand } from '../../../../js/commands/SetPositionCommand'; @@ -12,12 +12,9 @@ import { SetRotationCommand } from '../../../../js/commands/SetRotationCommand'; import { SetBeamDirectionCommand } from '../../../../js/commands/SetBeamDirectionCommand'; import { PropertiesCategory } from './PropertiesCategory'; import { useSmartWatchEditorState } from '../../../../../util/hooks/signals'; -import { ISimulationSceneChild } from '../../../../Simulation/Base/SimulationScene'; +import { SimulationElement } from '../../../../Simulation/Base/SimulationElement'; -export function ObjectPlacement(props: { - editor: Editor; - object: ISimulationSceneChild | Beam | WorldZone; -}) { +export function ObjectPlacement(props: { editor: Editor; object: SimulationElement }) { const { object, editor } = props; const { state: watchedObject } = useSmartWatchEditorState(editor, object); diff --git a/src/ThreeEditor/components/Sidebar/properties/category/RangeModulatorConfiguration.tsx b/src/ThreeEditor/components/Sidebar/properties/category/RangeModulatorConfiguration.tsx index 7596712ac..7cf6cfdb2 100644 --- a/src/ThreeEditor/components/Sidebar/properties/category/RangeModulatorConfiguration.tsx +++ b/src/ThreeEditor/components/Sidebar/properties/category/RangeModulatorConfiguration.tsx @@ -2,13 +2,6 @@ import { Editor } from '../../../../js/Editor'; import { PropertiesCategory } from './PropertiesCategory'; export function BeamModifiersConfiguration(props: { editor: Editor }) { - const { editor } = props; - - // const { state: watchedObject } = useSmartWatchEditorState(editor, object); - - // const setValue = (key: string, value: any) => - // editor.execute(new SetValueCommand(editor, watchedObject.object, key, value)); - return ( {/* diff --git a/src/ThreeEditor/components/Sidebar/properties/fields/PropertyField.tsx b/src/ThreeEditor/components/Sidebar/properties/fields/PropertyField.tsx index 8d5a7bdc6..bbabfad2c 100644 --- a/src/ThreeEditor/components/Sidebar/properties/fields/PropertyField.tsx +++ b/src/ThreeEditor/components/Sidebar/properties/fields/PropertyField.tsx @@ -122,7 +122,7 @@ export function NumberInput(props: { }, []); useEffect(() => { - (inputRef.current as any).onChange((event: any) => { + inputRef.current.onChange((event: any) => { props.onChange(parseFloat(event.target.value)); }); }, [props]); @@ -162,7 +162,7 @@ export function ColorInput(props: { value: string; onChange: (value: number) => }, []); useEffect(() => { - (inputRef.current as any).onChange(() => { + inputRef.current.onChange(() => { props.onChange(inputRef.current.getHexValue()); }); }, [props]); @@ -412,7 +412,7 @@ export function ModifiersOutliner(props: { }, []); useEffect(() => { - (inputRef.current as any).onChange(() => { + inputRef.current.onChange(() => { props.onChange(inputRef.current.getValue()); }); inputRef.current.setOptions(props.options); @@ -526,7 +526,7 @@ export function DifferentialConfiguration(props: { } = inputRef.current; inputRef.current.group.updateFields.forEach(field => { - (field as any).onChange(() => { + field.onChange(() => { const keywordSelect = keywordSelectField.getValue(); const lowerLimit = lowerLimitField.getValue(); const upperLimit = upperLimitField.getValue(); @@ -545,7 +545,7 @@ export function DifferentialConfiguration(props: { }); inputRef.current.group.deleteFields.forEach(field => { - (field as any).onClick(() => { + field.onClick(() => { props.onDelete(); }); }); @@ -598,7 +598,7 @@ export function RulesOutliner(props: { }, []); useEffect(() => { - (inputRef.current as any).onChange(() => { + inputRef.current.onChange(() => { props.onChange(inputRef.current.getValue()); }); inputRef.current.setOptions(props.options); @@ -728,7 +728,7 @@ export function RulesConfiguration(props: { const { keywordSelectField, operatorSelectField, idSelectField } = inputRef.current; inputRef.current.group.updateFields.forEach(field => { - (field as any).onChange(() => { + field.onChange(() => { const keywordSelect = keywordSelectField.getValue(); const operatorSelect = operatorSelectField.getValue(); const idSelect = idSelectField.getValue(); @@ -743,7 +743,7 @@ export function RulesConfiguration(props: { }); inputRef.current.group.deleteFields.forEach(field => { - (field as any).onClick(() => { + field.onClick(() => { props.onDelete(); }); }); diff --git a/src/ThreeEditor/js/Command.js b/src/ThreeEditor/js/Command.js index db8c8e51b..0e2d0bb54 100644 --- a/src/ThreeEditor/js/Command.js +++ b/src/ThreeEditor/js/Command.js @@ -9,6 +9,7 @@ * @property {string} name * @property {Editor} editor * @property {SimulationElement} [object] + * */ export class Command { id; diff --git a/src/ThreeEditor/js/commands/ChangeObjectOrderCommand.ts b/src/ThreeEditor/js/commands/ChangeObjectOrderCommand.ts index 8db162dea..a074c3d72 100644 --- a/src/ThreeEditor/js/commands/ChangeObjectOrderCommand.ts +++ b/src/ThreeEditor/js/commands/ChangeObjectOrderCommand.ts @@ -58,8 +58,8 @@ export class ChangeObjectOrderCommand extends Command { fromJSON(json: { object: { object: { uuid: string } }; oldIndex: number; newIndex: number }) { super.fromJSON(json); - - this.object = this.editor.objectByUuid(json.object.object.uuid); + const newObject = this.editor.objectByUuid(json.object.object.uuid); + if (newObject) this.object = newObject; this.oldIndex = json.oldIndex; this.newIndex = json.newIndex; } diff --git a/src/ThreeEditor/js/libs/ui.js b/src/ThreeEditor/js/libs/ui.js index a96ce2c74..a380e75aa 100644 --- a/src/ThreeEditor/js/libs/ui.js +++ b/src/ThreeEditor/js/libs/ui.js @@ -1,162 +1,189 @@ class UIElement { + /** + * @param {*} callback */ + onKeyUp + /** + * @param {*} callback */ + onKeyDown + /** + * @param {*} callback */ + onKeyDown + /** + * @param {*} callback */ + onMouseOver + /** + * @param {*} callback */ + onMouseOut + /** + * @param {*} callback */ + onClick + /** + * @param {*} callback */ + onDblClick + /** + * @param {*} callback */ + onChange + /** + * @param {*} callback */ + onInput - constructor(dom) { + constructor(dom) { - this.dom = dom; + this.dom = dom; - } + } - add() { + add() { - for (let i = 0; i < arguments.length; i++) { + for (let i = 0; i < arguments.length; i++) { - const argument = arguments[i]; + const argument = arguments[i]; - if (argument instanceof UIElement) { + if (argument instanceof UIElement) { - this.dom.appendChild(argument.dom); + this.dom.appendChild(argument.dom); - } else { + } else { - console.error('UIElement:', argument, 'is not an instance of UIElement.'); + console.error('UIElement:', argument, 'is not an instance of UIElement.'); - } + } - } + } - return this; + return this; - } + } - remove() { + remove() { - for (let i = 0; i < arguments.length; i++) { + for (let i = 0; i < arguments.length; i++) { - const argument = arguments[i]; + const argument = arguments[i]; - if (argument instanceof UIElement) { + if (argument instanceof UIElement) { - this.dom.removeChild(argument.dom); + this.dom.removeChild(argument.dom); - } else { + } else { - console.error('UIElement:', argument, 'is not an instance of UIElement.'); + console.error('UIElement:', argument, 'is not an instance of UIElement.'); - } + } - } + } - return this; + return this; - } + } - clear() { + clear() { - while (this.dom.children.length) { + while (this.dom.children.length) { - this.dom.removeChild(this.dom.lastChild); + this.dom.removeChild(this.dom.lastChild); - } + } - } + } - setId(id) { + setId(id) { - this.dom.id = id; + this.dom.id = id; - return this; + return this; - } + } - getId() { + getId() { - return this.dom.id; + return this.dom.id; - } + } - setClass(name) { + setClass(name) { - this.dom.className = name; + this.dom.className = name; - return this; + return this; - } + } - addClass(name) { + addClass(name) { - this.dom.classList.add(name); + this.dom.classList.add(name); - return this; + return this; - } + } - removeClass(name) { + removeClass(name) { - this.dom.classList.remove(name); + this.dom.classList.remove(name); - return this; + return this; - } + } - setStyle(style, array) { + setStyle(style, array) { - for (let i = 0; i < array.length; i++) { + for (let i = 0; i < array.length; i++) { - this.dom.style[style] = array[i]; + this.dom.style[style] = array[i]; - } + } - return this; + return this; - } + } - setDisabled(value) { + setDisabled(value) { - this.dom.disabled = value; + this.dom.disabled = value; - return this; + return this; - } + } - setTextContent(value) { + setTextContent(value) { - this.dom.textContent = value; + this.dom.textContent = value; - return this; + return this; - } + } - setInnerHTML(value) { + setInnerHTML(value) { - this.dom.innerHTML = value; + this.dom.innerHTML = value; - } + } - getIndexOfChild(element) { + getIndexOfChild(element) { - return Array.prototype.indexOf.call(this.dom.children, element.dom); + return Array.prototype.indexOf.call(this.dom.children, element.dom); - } + } } // properties const properties = ['position', 'left', 'top', 'right', 'bottom', 'width', 'height', 'border', 'borderLeft', - 'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'verticalAlign', 'color', - 'background', 'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor', 'zIndex']; + 'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'verticalAlign', 'color', + 'background', 'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor', 'zIndex']; properties.forEach(function (property) { - const method = 'set' + property.substr(0, 1).toUpperCase() + property.substr(1, property.length); + const method = 'set' + property.substr(0, 1).toUpperCase() + property.substr(1, property.length); - UIElement.prototype[method] = function () { + UIElement.prototype[method] = function () { - this.setStyle(property, arguments); + this.setStyle(property, arguments); - return this; + return this; - }; + }; }); @@ -166,1122 +193,1132 @@ const events = ['KeyUp', 'KeyDown', 'MouseOver', 'MouseOut', 'Click', 'DblClick' events.forEach(function (event) { - const method = 'on' + event; + const method = 'on' + event; - UIElement.prototype[method] = function (callback) { + UIElement.prototype[method] = function (callback) { - this.dom[method.toLowerCase()] = callback.bind(this); + this.dom[method.toLowerCase()] = callback.bind(this); - return this; + return this; - }; + }; }); + + class UISpan extends UIElement { - constructor() { + constructor() { - super(document.createElement('span')); + super(document.createElement('span')); - } + } } + class UIDiv extends UIElement { - constructor() { + constructor() { - super(document.createElement('div')); + super(document.createElement('div')); - } + } } + class UIRow extends UIDiv { - constructor() { + constructor() { - super(); + super(); - this.dom.className = 'Row'; + this.dom.className = 'Row'; - } + } } + class UIPanel extends UIDiv { - constructor() { + constructor() { - super(); + super(); - this.dom.className = 'Panel'; + this.dom.className = 'Panel'; - } + } } + class UIText extends UISpan { - constructor(text) { + constructor(text) { - super(); + super(); - this.dom.className = 'Text'; - this.dom.style.cursor = 'default'; - this.dom.style.display = 'inline-block'; + this.dom.className = 'Text'; + this.dom.style.cursor = 'default'; + this.dom.style.display = 'inline-block'; - this.setValue(text); + this.setValue(text); - } + } - getValue() { + getValue() { - return this.dom.textContent; + return this.dom.textContent; - } + } - setValue(value) { + setValue(value) { - if (value !== undefined) { + if (value !== undefined) { - this.dom.textContent = value; + this.dom.textContent = value; - } + } - return this; + return this; - } + } } + class UIInput extends UIElement { - constructor(text) { + constructor(text) { - super(document.createElement('input')); + super(document.createElement('input')); - this.dom.className = 'Input'; - this.dom.style.padding = '2px'; - this.dom.style.border = '1px solid transparent'; + this.dom.className = 'Input'; + this.dom.style.padding = '2px'; + this.dom.style.border = '1px solid transparent'; - this.dom.setAttribute('autocomplete', 'off'); + this.dom.setAttribute('autocomplete', 'off'); - this.dom.addEventListener('keydown', function (event) { + this.dom.addEventListener('keydown', function (event) { - event.stopPropagation(); + event.stopPropagation(); - }, false); + }, false); - this.setValue(text); + this.setValue(text); - } + } - getValue() { + getValue() { - return this.dom.value; + return this.dom.value; - } + } - setValue(value) { + setValue(value) { - this.dom.value = value; + this.dom.value = value; - return this; + return this; - } + } } + class UITextArea extends UIElement { - constructor() { + constructor() { - super(document.createElement('textarea')); + super(document.createElement('textarea')); - this.dom.className = 'TextArea'; - this.dom.style.padding = '2px'; - this.dom.spellcheck = false; + this.dom.className = 'TextArea'; + this.dom.style.padding = '2px'; + this.dom.spellcheck = false; - this.dom.setAttribute('autocomplete', 'off'); + this.dom.setAttribute('autocomplete', 'off'); - this.dom.addEventListener('keydown', (event) => { + this.dom.addEventListener('keydown', (event) => { - event.stopPropagation(); + event.stopPropagation(); - if (event.keyCode === 9) { + if (event.keyCode === 9) { - event.preventDefault(); + event.preventDefault(); - const cursor = this.dom.selectionStart; + const cursor = this.dom.selectionStart; - this.dom.value = this.dom.value.substring(0, cursor) + '\t' + this.dom.value.substring(cursor); - this.dom.selectionStart = cursor + 1; - this.dom.selectionEnd = this.dom.selectionStart; + this.dom.value = this.dom.value.substring(0, cursor) + '\t' + this.dom.value.substring(cursor); + this.dom.selectionStart = cursor + 1; + this.dom.selectionEnd = this.dom.selectionStart; - } + } - }, false); + }, false); - } + } - getValue() { + getValue() { - return this.dom.value; + return this.dom.value; - } + } - setValue(value) { + setValue(value) { - this.dom.value = value; + this.dom.value = value; - return this; + return this; - } + } } + class UISelect extends UIElement { - constructor() { + constructor() { - super(document.createElement('select')); + super(document.createElement('select')); - this.dom.className = 'Select'; - this.dom.style.padding = '2px'; + this.dom.className = 'Select'; + this.dom.style.padding = '2px'; - this.dom.setAttribute('autocomplete', 'off'); + this.dom.setAttribute('autocomplete', 'off'); - } + } - setMultiple(boolean) { + setMultiple(boolean) { - this.dom.multiple = boolean; + this.dom.multiple = boolean; - return this; + return this; - } + } - setOptions(options) { + setOptions(options) { - const selected = this.dom.value; + const selected = this.dom.value; - while (this.dom.children.length > 0) { + while (this.dom.children.length > 0) { - this.dom.removeChild(this.dom.firstChild); + this.dom.removeChild(this.dom.firstChild); - } + } - for (const key in options) { + for (const key in options) { - const option = document.createElement('option'); - option.value = key; - option.innerHTML = options[key]; - this.dom.appendChild(option); + const option = document.createElement('option'); + option.value = key; + option.innerHTML = options[key]; + this.dom.appendChild(option); - } + } - this.dom.value = selected; + this.dom.value = selected; - return this; + return this; - } + } - getValue() { + getValue() { - return this.dom.value; + return this.dom.value; - } + } - setValue(value) { + setValue(value) { - value = String(value); + value = String(value); - if (this.dom.value !== value) { + if (this.dom.value !== value) { - this.dom.value = value; + this.dom.value = value; - } + } - return this; + return this; - } + } } + class UICheckbox extends UIElement { - constructor(boolean) { + constructor(boolean) { - super(document.createElement('input')); + super(document.createElement('input')); - this.dom.className = 'Checkbox'; - this.dom.type = 'checkbox'; + this.dom.className = 'Checkbox'; + this.dom.type = 'checkbox'; - this.setValue(boolean); + this.setValue(boolean); - } + } - getValue() { + getValue() { - return this.dom.checked; + return this.dom.checked; - } + } - setValue(value) { + setValue(value) { - if (value !== undefined) { + if (value !== undefined) { - this.dom.checked = value; + this.dom.checked = value; - } + } - return this; + return this; - } + } } class UIColor extends UIElement { - constructor() { + constructor() { - super(document.createElement('input')); + super(document.createElement('input')); - this.dom.className = 'Color'; - this.dom.style.width = '32px'; - this.dom.style.height = '16px'; - this.dom.style.border = '0px'; - this.dom.style.padding = '2px'; - this.dom.style.backgroundColor = 'transparent'; + this.dom.className = 'Color'; + this.dom.style.width = '32px'; + this.dom.style.height = '16px'; + this.dom.style.border = '0px'; + this.dom.style.padding = '2px'; + this.dom.style.backgroundColor = 'transparent'; - this.dom.setAttribute('autocomplete', 'off'); + this.dom.setAttribute('autocomplete', 'off'); - try { + try { - this.dom.type = 'color'; - this.dom.value = '#ffffff'; + this.dom.type = 'color'; + this.dom.value = '#ffffff'; - } catch (exception) { } + } catch (exception) { } - } + } - getValue() { + getValue() { - return this.dom.value; + return this.dom.value; - } + } - getHexValue() { + getHexValue() { - return parseInt(this.dom.value.substr(1), 16); + return parseInt(this.dom.value.substr(1), 16); - } + } - setValue(value) { + setValue(value) { - this.dom.value = value; + this.dom.value = value; - return this; + return this; - } + } - setHexValue(hex) { + setHexValue(hex) { - this.dom.value = '#' + ('000000' + hex.toString(16)).slice(- 6); + this.dom.value = '#' + ('000000' + hex.toString(16)).slice(- 6); - return this; + return this; - } + } } class UINumber extends UIElement { - constructor(number) { + constructor(number) { - super(document.createElement('input')); + super(document.createElement('input')); - this.dom.style.cursor = 'ns-resize'; - this.dom.className = 'Number'; - this.dom.value = '0.00'; + this.dom.style.cursor = 'ns-resize'; + this.dom.className = 'Number'; + this.dom.value = '0.00'; - this.dom.setAttribute('autocomplete', 'off'); + this.dom.setAttribute('autocomplete', 'off'); - this.value = 0; + this.value = 0; - this.min = - Infinity; - this.max = Infinity; + this.min = - Infinity; + this.max = Infinity; - this.precision = 2; - this.step = 1; - this.unit = ''; - this.nudge = 0.01; + this.precision = 2; + this.step = 1; + this.unit = ''; + this.nudge = 0.01; - this.setValue(number); + this.setValue(number); - const scope = this; + const scope = this; - const changeEvent = document.createEvent('HTMLEvents'); - changeEvent.initEvent('change', true, true); + const changeEvent = document.createEvent('HTMLEvents'); + changeEvent.initEvent('change', true, true); - let distance = 0; - let onMouseDownValue = 0; + let distance = 0; + let onMouseDownValue = 0; - const pointer = { x: 0, y: 0 }; - const prevPointer = { x: 0, y: 0 }; + const pointer = { x: 0, y: 0 }; + const prevPointer = { x: 0, y: 0 }; - function onMouseDown(event) { + function onMouseDown(event) { - event.preventDefault(); + event.preventDefault(); - distance = 0; + distance = 0; - onMouseDownValue = scope.value; + onMouseDownValue = scope.value; - prevPointer.x = event.clientX; - prevPointer.y = event.clientY; + prevPointer.x = event.clientX; + prevPointer.y = event.clientY; - document.addEventListener('mousemove', onMouseMove, false); - document.addEventListener('mouseup', onMouseUp, false); + document.addEventListener('mousemove', onMouseMove, false); + document.addEventListener('mouseup', onMouseUp, false); - } + } - function onMouseMove(event) { + function onMouseMove(event) { - const currentValue = scope.value; + const currentValue = scope.value; - pointer.x = event.clientX; - pointer.y = event.clientY; + pointer.x = event.clientX; + pointer.y = event.clientY; - distance += (pointer.x - prevPointer.x) - (pointer.y - prevPointer.y); + distance += (pointer.x - prevPointer.x) - (pointer.y - prevPointer.y); - let value = onMouseDownValue + (distance / (event.shiftKey ? 5 : 50)) * scope.step; - value = Math.min(scope.max, Math.max(scope.min, value)); + let value = onMouseDownValue + (distance / (event.shiftKey ? 5 : 50)) * scope.step; + value = Math.min(scope.max, Math.max(scope.min, value)); - if (currentValue !== value) { + if (currentValue !== value) { - scope.setValue(value); - scope.dom.dispatchEvent(changeEvent); + scope.setValue(value); + scope.dom.dispatchEvent(changeEvent); - } + } - prevPointer.x = event.clientX; - prevPointer.y = event.clientY; + prevPointer.x = event.clientX; + prevPointer.y = event.clientY; - } + } - function onMouseUp() { + function onMouseUp() { - document.removeEventListener('mousemove', onMouseMove, false); - document.removeEventListener('mouseup', onMouseUp, false); + document.removeEventListener('mousemove', onMouseMove, false); + document.removeEventListener('mouseup', onMouseUp, false); - if (Math.abs(distance) < 2) { + if (Math.abs(distance) < 2) { - scope.dom.focus(); - scope.dom.select(); + scope.dom.focus(); + scope.dom.select(); - } + } - } + } - function onTouchStart(event) { + function onTouchStart(event) { - if (event.touches.length === 1) { + if (event.touches.length === 1) { - distance = 0; + distance = 0; - onMouseDownValue = scope.value; + onMouseDownValue = scope.value; - prevPointer.x = event.touches[0].pageX; - prevPointer.y = event.touches[0].pageY; + prevPointer.x = event.touches[0].pageX; + prevPointer.y = event.touches[0].pageY; - document.addEventListener('touchmove', onTouchMove, false); - document.addEventListener('touchend', onTouchEnd, false); + document.addEventListener('touchmove', onTouchMove, false); + document.addEventListener('touchend', onTouchEnd, false); - } + } - } + } - function onTouchMove(event) { + function onTouchMove(event) { - const currentValue = scope.value; + const currentValue = scope.value; - pointer.x = event.touches[0].pageX; - pointer.y = event.touches[0].pageY; + pointer.x = event.touches[0].pageX; + pointer.y = event.touches[0].pageY; - distance += (pointer.x - prevPointer.x) - (pointer.y - prevPointer.y); + distance += (pointer.x - prevPointer.x) - (pointer.y - prevPointer.y); - let value = onMouseDownValue + (distance / (event.shiftKey ? 5 : 50)) * scope.step; - value = Math.min(scope.max, Math.max(scope.min, value)); + let value = onMouseDownValue + (distance / (event.shiftKey ? 5 : 50)) * scope.step; + value = Math.min(scope.max, Math.max(scope.min, value)); - if (currentValue !== value) { + if (currentValue !== value) { - scope.setValue(value); - scope.dom.dispatchEvent(changeEvent); + scope.setValue(value); + scope.dom.dispatchEvent(changeEvent); - } + } - prevPointer.x = event.touches[0].pageX; - prevPointer.y = event.touches[0].pageY; + prevPointer.x = event.touches[0].pageX; + prevPointer.y = event.touches[0].pageY; - } + } - function onTouchEnd(event) { + function onTouchEnd(event) { - if (event.touches.length === 0) { + if (event.touches.length === 0) { - document.removeEventListener('touchmove', onTouchMove, false); - document.removeEventListener('touchend', onTouchEnd, false); + document.removeEventListener('touchmove', onTouchMove, false); + document.removeEventListener('touchend', onTouchEnd, false); - } + } - } + } - function onChange() { + function onChange() { - scope.setValue(scope.dom.value); + scope.setValue(scope.dom.value); - } + } - function onFocus() { + function onFocus() { - scope.dom.style.backgroundColor = ''; - scope.dom.style.cursor = ''; + scope.dom.style.backgroundColor = ''; + scope.dom.style.cursor = ''; - } + } - function onBlur() { + function onBlur() { - scope.dom.style.backgroundColor = 'transparent'; - scope.dom.style.cursor = 'ns-resize'; + scope.dom.style.backgroundColor = 'transparent'; + scope.dom.style.cursor = 'ns-resize'; - } + } - function onKeyDown(event) { + function onKeyDown(event) { - event.stopPropagation(); + event.stopPropagation(); - switch (event.keyCode) { + switch (event.keyCode) { - case 13: // enter - scope.dom.blur(); - break; + case 13: // enter + scope.dom.blur(); + break; - case 38: // up - event.preventDefault(); - scope.setValue(scope.getValue() + scope.nudge); - scope.dom.dispatchEvent(changeEvent); - break; + case 38: // up + event.preventDefault(); + scope.setValue(scope.getValue() + scope.nudge); + scope.dom.dispatchEvent(changeEvent); + break; - case 40: // down - event.preventDefault(); - scope.setValue(scope.getValue() - scope.nudge); - scope.dom.dispatchEvent(changeEvent); - break; + case 40: // down + event.preventDefault(); + scope.setValue(scope.getValue() - scope.nudge); + scope.dom.dispatchEvent(changeEvent); + break; - default: - break; + default: + break; - } + } - } + } - onBlur(); + onBlur(); - this.dom.addEventListener('keydown', onKeyDown, false); - this.dom.addEventListener('mousedown', onMouseDown, false); - this.dom.addEventListener('touchstart', onTouchStart, false); - this.dom.addEventListener('change', onChange, false); - this.dom.addEventListener('focus', onFocus, false); - this.dom.addEventListener('blur', onBlur, false); + this.dom.addEventListener('keydown', onKeyDown, false); + this.dom.addEventListener('mousedown', onMouseDown, false); + this.dom.addEventListener('touchstart', onTouchStart, false); + this.dom.addEventListener('change', onChange, false); + this.dom.addEventListener('focus', onFocus, false); + this.dom.addEventListener('blur', onBlur, false); - } + } - getValue() { + getValue() { - return this.value; + return this.value; - } + } - setValue(value) { + setValue(value) { - if (value !== undefined) { + if (value !== undefined) { - value = parseFloat(value); + value = parseFloat(value); - if (value < this.min) value = this.min; - if (value > this.max) value = this.max; + if (value < this.min) value = this.min; + if (value > this.max) value = this.max; - this.value = value; - this.dom.value = value.toFixed(this.precision); + this.value = value; + this.dom.value = value.toFixed(this.precision); - if (this.unit !== '') this.dom.value += ' ' + this.unit; + if (this.unit !== '') this.dom.value += ' ' + this.unit; - } + } - return this; + return this; - } + } - setPrecision(precision) { + setPrecision(precision) { - this.precision = precision; + this.precision = precision; - return this; + return this; - } + } - setStep(step) { + setStep(step) { - this.step = step; + this.step = step; - return this; + return this; - } + } - setNudge(nudge) { + setNudge(nudge) { - this.nudge = nudge; + this.nudge = nudge; - return this; + return this; - } + } - setRange(min, max) { + setRange(min, max) { - this.min = min; - this.max = max; + this.min = min; + this.max = max; - return this; + return this; - } + } - setUnit(unit) { + setUnit(unit) { - this.unit = unit; + this.unit = unit; - return this; + return this; - } + } } class UIInteger extends UIElement { - constructor(number) { + constructor(number) { - super(document.createElement('input')); + super(document.createElement('input')); - this.dom.style.cursor = 'ns-resize'; - this.dom.className = 'Number'; - this.dom.value = '0'; + this.dom.style.cursor = 'ns-resize'; + this.dom.className = 'Number'; + this.dom.value = '0'; - this.dom.setAttribute('autocomplete', 'off'); + this.dom.setAttribute('autocomplete', 'off'); - this.value = 0; + this.value = 0; - this.min = - Infinity; - this.max = Infinity; + this.min = - Infinity; + this.max = Infinity; - this.step = 1; - this.nudge = 1; + this.step = 1; + this.nudge = 1; - this.setValue(number); + this.setValue(number); - const scope = this; + const scope = this; - const changeEvent = document.createEvent('HTMLEvents'); - changeEvent.initEvent('change', true, true); + const changeEvent = document.createEvent('HTMLEvents'); + changeEvent.initEvent('change', true, true); - let distance = 0; - let onMouseDownValue = 0; + let distance = 0; + let onMouseDownValue = 0; - const pointer = { x: 0, y: 0 }; - const prevPointer = { x: 0, y: 0 }; + const pointer = { x: 0, y: 0 }; + const prevPointer = { x: 0, y: 0 }; - function onMouseDown(event) { + function onMouseDown(event) { - event.preventDefault(); + event.preventDefault(); - distance = 0; + distance = 0; - onMouseDownValue = scope.value; + onMouseDownValue = scope.value; - prevPointer.x = event.clientX; - prevPointer.y = event.clientY; + prevPointer.x = event.clientX; + prevPointer.y = event.clientY; - document.addEventListener('mousemove', onMouseMove, false); - document.addEventListener('mouseup', onMouseUp, false); + document.addEventListener('mousemove', onMouseMove, false); + document.addEventListener('mouseup', onMouseUp, false); - } + } - function onMouseMove(event) { + function onMouseMove(event) { - const currentValue = scope.value; + const currentValue = scope.value; - pointer.x = event.clientX; - pointer.y = event.clientY; + pointer.x = event.clientX; + pointer.y = event.clientY; - distance += (pointer.x - prevPointer.x) - (pointer.y - prevPointer.y); + distance += (pointer.x - prevPointer.x) - (pointer.y - prevPointer.y); - let value = onMouseDownValue + (distance / (event.shiftKey ? 5 : 50)) * scope.step; - value = Math.min(scope.max, Math.max(scope.min, value)) | 0; + let value = onMouseDownValue + (distance / (event.shiftKey ? 5 : 50)) * scope.step; + value = Math.min(scope.max, Math.max(scope.min, value)) | 0; - if (currentValue !== value) { + if (currentValue !== value) { - scope.setValue(value); - scope.dom.dispatchEvent(changeEvent); + scope.setValue(value); + scope.dom.dispatchEvent(changeEvent); - } + } - prevPointer.x = event.clientX; - prevPointer.y = event.clientY; + prevPointer.x = event.clientX; + prevPointer.y = event.clientY; - } + } - function onMouseUp() { + function onMouseUp() { - document.removeEventListener('mousemove', onMouseMove, false); - document.removeEventListener('mouseup', onMouseUp, false); + document.removeEventListener('mousemove', onMouseMove, false); + document.removeEventListener('mouseup', onMouseUp, false); - if (Math.abs(distance) < 2) { + if (Math.abs(distance) < 2) { - scope.dom.focus(); - scope.dom.select(); + scope.dom.focus(); + scope.dom.select(); - } + } - } + } - function onChange() { + function onChange() { - scope.setValue(scope.dom.value); + scope.setValue(scope.dom.value); - } + } - function onFocus() { + function onFocus() { - scope.dom.style.backgroundColor = ''; - scope.dom.style.cursor = ''; + scope.dom.style.backgroundColor = ''; + scope.dom.style.cursor = ''; - } + } - function onBlur() { + function onBlur() { - scope.dom.style.backgroundColor = 'transparent'; - scope.dom.style.cursor = 'ns-resize'; + scope.dom.style.backgroundColor = 'transparent'; + scope.dom.style.cursor = 'ns-resize'; - } + } - function onKeyDown(event) { + function onKeyDown(event) { - event.stopPropagation(); + event.stopPropagation(); - switch (event.keyCode) { + switch (event.keyCode) { - case 13: // enter - scope.dom.blur(); - break; + case 13: // enter + scope.dom.blur(); + break; - case 38: // up - event.preventDefault(); - scope.setValue(scope.getValue() + scope.nudge); - scope.dom.dispatchEvent(changeEvent); - break; + case 38: // up + event.preventDefault(); + scope.setValue(scope.getValue() + scope.nudge); + scope.dom.dispatchEvent(changeEvent); + break; - case 40: // down - event.preventDefault(); - scope.setValue(scope.getValue() - scope.nudge); - scope.dom.dispatchEvent(changeEvent); - break; + case 40: // down + event.preventDefault(); + scope.setValue(scope.getValue() - scope.nudge); + scope.dom.dispatchEvent(changeEvent); + break; - default: - break; + default: + break; - } + } - } + } - onBlur(); + onBlur(); - this.dom.addEventListener('keydown', onKeyDown, false); - this.dom.addEventListener('mousedown', onMouseDown, false); - this.dom.addEventListener('change', onChange, false); - this.dom.addEventListener('focus', onFocus, false); - this.dom.addEventListener('blur', onBlur, false); + this.dom.addEventListener('keydown', onKeyDown, false); + this.dom.addEventListener('mousedown', onMouseDown, false); + this.dom.addEventListener('change', onChange, false); + this.dom.addEventListener('focus', onFocus, false); + this.dom.addEventListener('blur', onBlur, false); - } + } - getValue() { + getValue() { - return this.value; + return this.value; - } + } - setValue(value) { + setValue(value) { - if (value !== undefined) { + if (value !== undefined) { - value = parseInt(value); + value = parseInt(value); - this.value = value; - this.dom.value = value; + this.value = value; + this.dom.value = value; - } + } - return this; + return this; - } + } - setStep(step) { + setStep(step) { - this.step = parseInt(step); + this.step = parseInt(step); - return this; + return this; - } + } - setNudge(nudge) { + setNudge(nudge) { - this.nudge = nudge; + this.nudge = nudge; - return this; + return this; - } + } - setRange(min, max) { + setRange(min, max) { - this.min = min; - this.max = max; + this.min = min; + this.max = max; - return this; + return this; - } + } } class UIBreak extends UIElement { - constructor() { + constructor() { - super(document.createElement('br')); + super(document.createElement('br')); - this.dom.className = 'Break'; + this.dom.className = 'Break'; - } + } } class UIHorizontalRule extends UIElement { - constructor() { + constructor() { - super(document.createElement('hr')); + super(document.createElement('hr')); - this.dom.className = 'HorizontalRule'; + this.dom.className = 'HorizontalRule'; - } + } } class UIButton extends UIElement { - constructor(value) { + constructor(value) { - super(document.createElement('button')); + super(document.createElement('button')); - this.dom.className = 'Button'; - this.dom.textContent = value; + this.dom.className = 'Button'; + this.dom.textContent = value; - } + } } class UIProgress extends UIElement { - constructor(value) { + constructor(value) { - super(document.createElement('progress')); + super(document.createElement('progress')); - this.dom.value = value; + this.dom.value = value; - } + } - setValue(value) { + setValue(value) { - this.dom.value = value; + this.dom.value = value; - } + } } class UITabbedPanel extends UIDiv { - constructor() { + constructor() { - super(); + super(); - this.dom.className = 'TabbedPanel'; + this.dom.className = 'TabbedPanel'; - this.tabs = []; - this.panels = []; + this.tabs = []; + this.panels = []; - this.tabsDiv = new UIDiv(); - this.tabsDiv.setClass('Tabs'); + this.tabsDiv = new UIDiv(); + this.tabsDiv.setClass('Tabs'); - this.panelsDiv = new UIDiv(); - this.panelsDiv.setClass('Panels'); + this.panelsDiv = new UIDiv(); + this.panelsDiv.setClass('Panels'); - this.add(this.tabsDiv); - this.add(this.panelsDiv); + this.add(this.tabsDiv); + this.add(this.panelsDiv); - this.selected = ''; + this.selected = ''; - } + } - select(id) { + select(id) { - let tab; - let panel; - const scope = this; + let tab; + let panel; + const scope = this; - // Deselect current selection - if (this.selected && this.selected.length) { + // Deselect current selection + if (this.selected && this.selected.length) { - tab = this.tabs.find(function (item) { + tab = this.tabs.find(function (item) { - return item.dom.id === scope.selected; + return item.dom.id === scope.selected; - }); - panel = this.panels.find(function (item) { + }); + panel = this.panels.find(function (item) { - return item.dom.id === scope.selected; + return item.dom.id === scope.selected; - }); + }); - if (tab) { + if (tab) { - tab.removeClass('selected'); + tab.removeClass('selected'); - } + } - if (panel) { + if (panel) { - panel.setDisplay('none'); + panel.setDisplay('none'); - } + } - } + } - tab = this.tabs.find(function (item) { + tab = this.tabs.find(function (item) { - return item.dom.id === id; + return item.dom.id === id; - }); - panel = this.panels.find(function (item) { + }); + panel = this.panels.find(function (item) { - return item.dom.id === id; + return item.dom.id === id; - }); + }); - if (tab) { + if (tab) { - tab.addClass('selected'); + tab.addClass('selected'); - } + } - if (panel) { + if (panel) { - panel.setDisplay(''); + panel.setDisplay(''); - } + } - this.selected = id; + this.selected = id; - return this; + return this; - } + } - addTab(id, label, items) { + addTab(id, label, items) { - const tab = new UITab(label, this); - tab.setId(id); - this.tabs.push(tab); - this.tabsDiv.add(tab); + const tab = new UITab(label, this); + tab.setId(id); + this.tabs.push(tab); + this.tabsDiv.add(tab); - const panel = new UIDiv(); - panel.setId(id); - panel.add(items); - panel.setDisplay('none'); - this.panels.push(panel); - this.panelsDiv.add(panel); + const panel = new UIDiv(); + panel.setId(id); + panel.add(items); + panel.setDisplay('none'); + this.panels.push(panel); + this.panelsDiv.add(panel); - this.select(id); + this.select(id); - } + } } class UITab extends UIText { - constructor(text, parent) { + constructor(text, parent) { - super(text); + super(text); - this.dom.className = 'Tab'; + this.dom.className = 'Tab'; - this.parent = parent; + this.parent = parent; - const scope = this; + const scope = this; - this.dom.addEventListener('click', function () { + this.dom.addEventListener('click', function () { - scope.parent.select(scope.dom.id); + scope.parent.select(scope.dom.id); - }); + }); - } + } } class UIListbox extends UIDiv { - constructor() { + constructor() { - super(); + super(); - this.dom.className = 'Listbox'; - this.dom.tabIndex = 0; + this.dom.className = 'Listbox'; + this.dom.tabIndex = 0; - this.items = []; - this.listitems = []; - this.selectedIndex = 0; - this.selectedValue = null; + this.items = []; + this.listitems = []; + this.selectedIndex = 0; + this.selectedValue = null; - } + } - setItems(items) { + setItems(items) { - if (Array.isArray(items)) { + if (Array.isArray(items)) { - this.items = items; + this.items = items; - } + } - this.render(); + this.render(); - } + } - render() { + render() { - while (this.listitems.length) { + while (this.listitems.length) { - const item = this.listitems[0]; + const item = this.listitems[0]; - item.dom.remove(); + item.dom.remove(); - this.listitems.splice(0, 1); + this.listitems.splice(0, 1); - } + } - for (let i = 0; i < this.items.length; i++) { + for (let i = 0; i < this.items.length; i++) { - const item = this.items[i]; + const item = this.items[i]; - const listitem = new UIListbox.ListboxItem(this); - listitem.setId(item.id || `Listbox-${i}`); - listitem.setTextContent(item.name || item.type); - this.add(listitem); + const listitem = new UIListbox.ListboxItem(this); + listitem.setId(item.id || `Listbox-${i}`); + listitem.setTextContent(item.name || item.type); + this.add(listitem); - } + } - } + } - add() { + add() { - const items = Array.from(arguments); + const items = Array.from(arguments); - this.listitems = this.listitems.concat(items); + this.listitems = this.listitems.concat(items); - UIElement.prototype.add.apply(this, items); + UIElement.prototype.add.apply(this, items); - } + } - selectIndex(index) { + selectIndex(index) { - if (index >= 0 && index < this.items.length) { + if (index >= 0 && index < this.items.length) { - this.setValue(this.listitems[index].getId()); + this.setValue(this.listitems[index].getId()); - } + } - this.selectedIndex = index; + this.selectedIndex = index; - } + } - getValue() { + getValue() { - return this.selectedValue; + return this.selectedValue; - } + } - setValue(value) { + setValue(value) { - for (let i = 0; i < this.listitems.length; i++) { + for (let i = 0; i < this.listitems.length; i++) { - const element = this.listitems[i]; + const element = this.listitems[i]; - if (element.getId() === value) { + if (element.getId() === value) { - element.addClass('active'); + element.addClass('active'); - } else { + } else { - element.removeClass('active'); + element.removeClass('active'); - } + } - } + } - this.selectedValue = value; + this.selectedValue = value; - const changeEvent = document.createEvent('HTMLEvents'); - changeEvent.initEvent('change', true, true); - this.dom.dispatchEvent(changeEvent); + const changeEvent = document.createEvent('HTMLEvents'); + changeEvent.initEvent('change', true, true); + this.dom.dispatchEvent(changeEvent); - } + } } class ListboxItem extends UIDiv { - constructor(parent) { + constructor(parent) { - super(); + super(); - this.dom.className = 'ListboxItem'; + this.dom.className = 'ListboxItem'; - this.parent = parent; + this.parent = parent; - const scope = this; + const scope = this; - function onClick() { + function onClick() { - if (scope.parent) { + if (scope.parent) { - scope.parent.setValue(scope.getId()); + scope.parent.setValue(scope.getId()); - } + } - } + } - this.dom.addEventListener('click', onClick, false); + this.dom.addEventListener('click', onClick, false); - } + } } diff --git a/src/ThreeEditor/js/sidebar/object/Object.Placement.ts b/src/ThreeEditor/js/sidebar/object/Object.Placement.ts index 2e28000de..f2a8e885a 100644 --- a/src/ThreeEditor/js/sidebar/object/Object.Placement.ts +++ b/src/ThreeEditor/js/sidebar/object/Object.Placement.ts @@ -2,7 +2,7 @@ import * as THREE from 'three'; import { Beam, isBeam } from '../../../Simulation/Physics/Beam'; import { isDetectGeometry } from '../../../Simulation/Detectors/DetectGeometry'; import { SimulationElement } from '../../../Simulation/Base/SimulationElement'; -import { SimulationPropertiesType } from '../../../../types/SimProperties'; +import { SimulationPropertiesType } from '../../../../types/SimulationProperties'; import { createRowParamNumberXYZ, hideUIElement, showUIElement } from '../../../../util/Ui/Uis'; import { isWorldZone } from '../../../Simulation/Zones/WorldZone/WorldZone'; import { diff --git a/src/WrapperApp/components/Simulation/SimulationCard.tsx b/src/WrapperApp/components/Simulation/SimulationCard.tsx index eaadec7e5..44859e9e0 100644 --- a/src/WrapperApp/components/Simulation/SimulationCard.tsx +++ b/src/WrapperApp/components/Simulation/SimulationCard.tsx @@ -62,7 +62,7 @@ export default function SimulationCard({ const { loadFromJson } = useLoader(); const rows = useMemo(() => { - const rows: any[] = []; + const rows: JSX.Element[] = []; if (currentJobStatusData[StatusState.RUNNING](simulation)) { row(0, 'Message', simulation.message, !!simulation.message); } diff --git a/src/__tests__/Converter.test.ts b/src/__tests__/Converter.test.ts index 0ed91d60b..74f44a1db 100644 --- a/src/__tests__/Converter.test.ts +++ b/src/__tests__/Converter.test.ts @@ -3,86 +3,151 @@ import chrome from 'selenium-webdriver/chrome'; import { readFileSync } from 'fs'; describe('NavDrawer component', () => { - let driver: WebDriver; - - beforeAll(async () => { - driver = await new Builder() - .forBrowser('chrome') - .setChromeOptions(new chrome.Options().headless().addArguments("--window-size=1920,1080")) - .build(); - }, 30000); - //test timeouts are set to 30000 ms, as default timeout of 5000 ms is not enough for the test to pass in github actions - - afterAll(async () => { - await driver.quit(); - }, 30000); - - //this test checks if converter works correctly - opens an example and generates config files - test('converter generates correct files', async () => { - await driver.get('http://localhost:3000'); - - //find the "Editor" button on the left menu and click it to open the editor - const editorButton = await driver.findElement(By.css("li.MuiListItem-root:nth-child(3)")); - await editorButton.click(); - - //find the "open" button (second from the left on the upper bar) and then click it - const openButton = await driver.findElement(By.css("div.css-12z0wuy:nth-child(2) > span:nth-child(1)")); - await openButton.click(); - - //wait for the "open project" window to appear - const openProjectWidget = await driver.wait(until.elementLocated(By.css(".MuiPaper-elevation24")), 10000); - - //find the "examples" button in the window and click it. (we find it by contained text as its id changes every time) - const examplesButton = await openProjectWidget.findElement(By.xpath("//button[contains(text(),'Examples')]")); - await examplesButton.click(); - - //find the first example option and click it - const firstExample = await openProjectWidget.findElement(By.css("li.MuiListItem-root:nth-child(1) > div:nth-child(1)")); - await firstExample.click(); - - //find the "load" button and click it - const loadButton = await openProjectWidget.findElement(By.css(".MuiButton-contained")); - await loadButton.click(); - - //accept the "current data will be lost" alert - await driver.switchTo().alert().accept(); - - //find the "Input Files" button on the left menu and click it to open the editor - const filesButton = await driver.findElement(By.css("li.MuiListItem-root:nth-child(4)")); - await filesButton.click(); - - //wait until the "generate from editor" button and click it (it takes some time for the button to change from "initializing") - //xpath is used as again the id changes every time - const generateButton = await driver.findElement(By.xpath("//button[contains(text(),'Generate from Editor')]")); - await driver.wait(until.elementIsEnabled(generateButton), 15000); - await generateButton.click(); - - //wait until the text has appeared in the first text field - await driver.wait(until.elementTextMatches(driver.findElement(By.css('.MuiCardContent-root > div:nth-child(2) > div:nth-child(2) > textarea:nth-child(1)')), /\S/)); - - //find all the text fields and check if they contain the correct text. characters other than text, numbers and dots are removed from the text before comparison - //also check if expected text loaded from file is not empty - const regex = /[^a-zA-Z0-9.]/g; - - const geoText = (await driver.findElement(By.css('.MuiCardContent-root > div:nth-child(2) > div:nth-child(2) > textarea:nth-child(1)')).getText()).replace(regex, ''); - const expectedGeoText = readFileSync('src/libs/converter/input_examples/expected_shieldhit_output/geo.dat', 'utf-8').replace(regex, ''); - expect (expectedGeoText).not.toBe(""); - expect (geoText).toContain(expectedGeoText); - - const matText = (await driver.findElement(By.css('.MuiCardContent-root > div:nth-child(3) > div:nth-child(2) > textarea:nth-child(1)')).getText()).replace(regex, ''); - const expectedMatText = readFileSync('src/libs/converter/input_examples/expected_shieldhit_output/mat.dat', 'utf-8').replace(regex, ''); - expect (expectedMatText).not.toBe(""); - expect (matText).toContain(expectedMatText); - - const beamText = (await driver.findElement(By.css('.MuiCardContent-root > div:nth-child(4) > div:nth-child(2) > textarea:nth-child(1)')).getText()).replace(regex, ''); - const expectedBeamText = readFileSync('src/libs/converter/input_examples/expected_shieldhit_output/beam.dat', 'utf-8').replace(regex, ''); - expect (expectedBeamText).not.toBe(""); - expect (beamText).toContain(expectedBeamText); - - const detectText = (await driver.findElement(By.css('.MuiCardContent-root > div:nth-child(5) > div:nth-child(2) > textarea:nth-child(1)')).getText()).replace(regex, ''); - const expectedDetectText = readFileSync('src/libs/converter/input_examples/expected_shieldhit_output/detect.dat', 'utf-8').replace(regex, ''); - expect (expectedDetectText).not.toBe(""); - expect (detectText).toContain(expectedDetectText); - - }, 50000); + let driver: WebDriver; + + beforeAll(async () => { + driver = await new Builder() + .forBrowser('chrome') + .setChromeOptions( + new chrome.Options().headless().addArguments('--window-size=1920,1080') + ) + .build(); + }, 30000); + //test timeouts are set to 30000 ms, as default timeout of 5000 ms is not enough for the test to pass in github actions + + afterAll(async () => { + await driver.quit(); + }, 30000); + + //this test checks if converter works correctly - opens an example and generates config files + test('converter generates correct files', async () => { + await driver.get('http://localhost:3000'); + + //find the "Editor" button on the left menu and click it to open the editor + const editorButton = await driver.findElement(By.css('li.MuiListItem-root:nth-child(3)')); + await editorButton.click(); + + //find the "open" button (second from the left on the upper bar) and then click it + const openButton = await driver.findElement( + By.css('div.css-12z0wuy:nth-child(2) > span:nth-child(1)') + ); + await openButton.click(); + + //wait for the "open project" window to appear + const openProjectWidget = await driver.wait( + until.elementLocated(By.css('.MuiPaper-elevation24')), + 10000 + ); + + //find the "examples" button in the window and click it. (we find it by contained text as its id changes every time) + const examplesButton = await openProjectWidget.findElement( + By.xpath("//button[contains(text(),'Examples')]") + ); + await examplesButton.click(); + + //find the first example option and click it + const firstExample = await openProjectWidget.findElement( + By.css('li.MuiListItem-root:nth-child(1) > div:nth-child(1)') + ); + await firstExample.click(); + + //find the "load" button and click it + const loadButton = await openProjectWidget.findElement(By.css('.MuiButton-contained')); + await loadButton.click(); + + //accept the "current data will be lost" alert + await driver.switchTo().alert().accept(); + + //find the "Input Files" button on the left menu and click it to open the editor + const filesButton = await driver.findElement(By.css('li.MuiListItem-root:nth-child(4)')); + await filesButton.click(); + + //wait until the "generate from editor" button and click it (it takes some time for the button to change from "initializing") + //xpath is used as again the id changes every time + const generateButton = await driver.findElement( + By.xpath("//button[contains(text(),'Generate from Editor')]") + ); + await driver.wait(until.elementIsEnabled(generateButton), 15000); + await generateButton.click(); + + //wait until the text has appeared in the first text field + await driver.wait( + until.elementTextMatches( + driver.findElement( + By.css( + '.MuiCardContent-root > div:nth-child(2) > div:nth-child(2) > textarea:nth-child(1)' + ) + ), + /\S/ + ) + ); + + //find all the text fields and check if they contain the correct text. characters other than text, numbers and dots are removed from the text before comparison + //also check if expected text loaded from file is not empty + const regex = /[^a-zA-Z0-9.]/g; + + const geoText = ( + await driver + .findElement( + By.css( + '.MuiCardContent-root > div:nth-child(2) > div:nth-child(2) > textarea:nth-child(1)' + ) + ) + .getText() + ).replace(regex, ''); + const expectedGeoText = readFileSync( + 'src/libs/converter/input_examples/expected_shieldhit_output/geo.dat', + 'utf-8' + ).replace(regex, ''); + expect(expectedGeoText).not.toBe(''); + expect(geoText).toContain(expectedGeoText); + + const matText = ( + await driver + .findElement( + By.css( + '.MuiCardContent-root > div:nth-child(3) > div:nth-child(2) > textarea:nth-child(1)' + ) + ) + .getText() + ).replace(regex, ''); + const expectedMatText = readFileSync( + 'src/libs/converter/input_examples/expected_shieldhit_output/mat.dat', + 'utf-8' + ).replace(regex, ''); + expect(expectedMatText).not.toBe(''); + expect(matText).toContain(expectedMatText); + + const beamText = ( + await driver + .findElement( + By.css( + '.MuiCardContent-root > div:nth-child(4) > div:nth-child(2) > textarea:nth-child(1)' + ) + ) + .getText() + ).replace(regex, ''); + const expectedBeamText = readFileSync( + 'src/libs/converter/input_examples/expected_shieldhit_output/beam.dat', + 'utf-8' + ).replace(regex, ''); + expect(expectedBeamText).not.toBe(''); + expect(beamText).toContain(expectedBeamText); + + const detectText = ( + await driver + .findElement( + By.css( + '.MuiCardContent-root > div:nth-child(5) > div:nth-child(2) > textarea:nth-child(1)' + ) + ) + .getText() + ).replace(regex, ''); + const expectedDetectText = readFileSync( + 'src/libs/converter/input_examples/expected_shieldhit_output/detect.dat', + 'utf-8' + ).replace(regex, ''); + expect(expectedDetectText).not.toBe(''); + expect(detectText).toContain(expectedDetectText); + }, 50000); }); diff --git a/src/services/JsRootService.tsx b/src/services/JsRootService.tsx index 4c372ca85..925be6ed6 100644 --- a/src/services/JsRootService.tsx +++ b/src/services/JsRootService.tsx @@ -10,23 +10,20 @@ const JsRootKey = 'JSROOT'; declare global { interface Window { - [JsRootKey]: {}; + [JsRootKey]: Record; } } -export interface JsRootProps { +export interface JsRootProps extends Partial { children: ReactNode; - JSROOT?: any; } -export interface IJsRoot { - JSROOT: any; -} +export type JsRootWindow = Pick; -const [useJSROOT, JsRootContextProvider] = createGenericContext(); +const [useJSROOT, JsRootContextProvider] = createGenericContext(); const JsRoot = (props: JsRootProps) => { - const [value, setValue] = useState(); + const [value, setValue] = useState(); const painterScript = useRef(); useEffect(() => { diff --git a/src/services/ShSimulatorService.tsx b/src/services/ShSimulatorService.tsx index 2d1bc9a32..c58eed4fb 100644 --- a/src/services/ShSimulatorService.tsx +++ b/src/services/ShSimulatorService.tsx @@ -32,7 +32,7 @@ export interface ShSimulationProps { children: ReactNode; } -export interface IShSimulation { +export interface RestSimulationContext { postJobDirect: (...args: RequestPostJob) => Promise; postJobBatch: (...args: RequestPostJob) => Promise; cancelJobDirect: (...args: RequestCancelJob) => Promise; @@ -88,7 +88,8 @@ const updateEstimators = (estimators: Estimator[]) => { } }; -const [useShSimulation, ShSimulationContextProvider] = createGenericContext(); +const [useShSimulation, ShSimulationContextProvider] = + createGenericContext(); const ShSimulation = ({ children }: ShSimulationProps) => { const { authKy } = useAuth(); diff --git a/src/services/StoreService.tsx b/src/services/StoreService.tsx index 94511fb95..fbf9f6de6 100644 --- a/src/services/StoreService.tsx +++ b/src/services/StoreService.tsx @@ -7,7 +7,7 @@ export interface StoreProps { children: ReactNode; } -export interface IStore { +export interface StoreContext { editorRef: React.MutableRefObject; resultsSimulationData?: JobStatusData; setResultsSimulationData: React.Dispatch< @@ -17,7 +17,7 @@ export interface IStore { setLocalResultsSimulationData: React.Dispatch>; } -const [useStore, StoreContextProvider] = createGenericContext(); +const [useStore, StoreContextProvider] = createGenericContext(); const Store = (props: StoreProps) => { const editorRef = useRef(); @@ -27,7 +27,7 @@ const Store = (props: StoreProps) => { [] ); - const value: IStore = { + const value: StoreContext = { editorRef, resultsSimulationData, setResultsSimulationData, diff --git a/src/types/Particle.ts b/src/types/Particle.ts index 84c8ccf02..f9982b861 100644 --- a/src/types/Particle.ts +++ b/src/types/Particle.ts @@ -1,3 +1,5 @@ +import { ParticleType } from '../ThreeEditor/components/Select/ParticleSelect'; + export type Particle = { id: number; name: string; @@ -79,4 +81,4 @@ export const PARTICLE_TYPES = [ id: 25, name: 'Heavy ions' } -] as const; +] as const satisfies readonly ParticleType[]; diff --git a/src/types/SimProperties.ts b/src/types/SimulationProperties.ts similarity index 100% rename from src/types/SimProperties.ts rename to src/types/SimulationProperties.ts diff --git a/src/util/Ui/Number.js b/src/util/Ui/Number.js index 35b27c119..797695f5c 100644 --- a/src/util/Ui/Number.js +++ b/src/util/Ui/Number.js @@ -1,6 +1,7 @@ import { UINumber, UIRow, UIText } from '../../ThreeEditor/js/libs/ui.js'; import { LABEL_MARGIN, LABEL_WIDTH, PRECISION_FRACTION, TRIPLE_LABEL_WIDTH } from './Uis.js'; +//TODO: extend UIElement type to include all events and properties /** * @typedef {import('../js/libs/ui').UIElement} UIElement */ diff --git a/src/util/hooks/signals.tsx b/src/util/hooks/signals.tsx index 41b1d2950..3966cc442 100644 --- a/src/util/hooks/signals.tsx +++ b/src/util/hooks/signals.tsx @@ -21,7 +21,7 @@ export const useSignal = ( /** * Type checked if it does not have `object` property */ -type ValidProxyState = T extends { object: any } ? never : T; +type ValidProxyState = T extends { object: Record } ? never : T; /** * Object wrapped in `Proxy`, that holds original object under `object` property. @@ -88,7 +88,7 @@ function useSmartWatchEditorState( proxyObjectRef.current = createProxy(); setState({ state: watchedObject ? proxyObjectRef.current : null }); - const callback = (object: any, property?: string) => { + const callback = (object: Record, property?: string) => { if (object === watchedObject) { if (debug) console.log(watchedPropertyArrRef.current, property); if (watchAnyChange) setState({ state: proxyObjectRef.current }); diff --git a/src/util/hooks/useKeyboardEditorControls.ts b/src/util/hooks/useKeyboardEditorControls.ts index 182d0bec7..47ed56d21 100644 --- a/src/util/hooks/useKeyboardEditorControls.ts +++ b/src/util/hooks/useKeyboardEditorControls.ts @@ -70,6 +70,7 @@ export const useKeyboardEditorControls = ( const IS_MAC = navigator.platform.toUpperCase().indexOf('MAC') >= 0; const onKeyDown = (event: KeyboardEvent) => { + //TODO: Fix types to remove any const eventFromSidebar = (event.target as any).closest('.ThreeEditorSidebar') !== null; if (eventFromSidebar) return;