diff --git a/src/SceneBinding.ts b/src/SceneBinding.ts index 3b56042a..a0f7738f 100644 --- a/src/SceneBinding.ts +++ b/src/SceneBinding.ts @@ -12,6 +12,7 @@ import { CylinderBuilder as BabylonCylinderBuilder } from '@babylonjs/core/Meshe import { PlaneBuilder as BabylonPlaneBuilder } from '@babylonjs/core/Meshes/Builders/planeBuilder'; import { Vector3 as BabylonVector3, Vector4 as BabylonVector4 } from '@babylonjs/core/Maths/math.vector'; import { Texture as BabylonTexture } from '@babylonjs/core/Materials/Textures/texture'; +import { DynamicTexture as BabylonDynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture'; import { Material as BabylonMaterial } from '@babylonjs/core/Materials/material'; import { StandardMaterial as BabylonStandardMaterial } from '@babylonjs/core/Materials/standardMaterial'; import { GizmoManager as BabylonGizmoManager } from '@babylonjs/core/Gizmos/gizmoManager'; @@ -54,6 +55,7 @@ import WorkerInstance from "./WorkerInstance"; import LocalizedString from './util/LocalizedString'; import ScriptManager from './ScriptManager'; import { RENDER_SCALE } from './renderConstants'; +import { number } from 'prop-types'; export type FrameLike = BabylonTransformNode | BabylonAbstractMesh; @@ -116,6 +118,8 @@ class SceneBinding { private materialIdIter_ = 0; + private seed_ = 0; + constructor(bScene: BabylonScene, ammo: unknown) { this.bScene_ = bScene; this.scene_ = Scene.EMPTY; @@ -163,26 +167,92 @@ class SceneBinding { } }; + private random = (max: number, min: number) => { + let x = Math.sin(this.seed_++) * 10000; + x = x - Math.floor(x); + x = ((x - .5) * (max - min)) + ((max + min) / 2); + return x; + }; + private buildGeometry_ = async (name: string, geometry: Geometry, faceUvs?: RawVector2[]): Promise => { let ret: FrameLike; switch (geometry.type) { case 'box': { - ret = BabylonBoxBuilder.CreateBox(name, { + const rect = BabylonBoxBuilder.CreateBox(name, { + updatable:true, width: Distance.toCentimetersValue(geometry.size.x), height: Distance.toCentimetersValue(geometry.size.y), depth: Distance.toCentimetersValue(geometry.size.z), faceUV: this.buildGeometryFaceUvs_(faceUvs, 12), }, this.bScene_); + const verts = rect.getVerticesData("position"); + if (name.includes('Solar')) { + // 20-23 are the bottom 4 verts + // 16-19 are the top 4 verts + + for (let i = 18; i < 20; i++) { + verts[i * 3 + 1] = verts[i * 3 + 1] + 10; + verts[i * 3] = verts[i * 3] - 10; + } + for (let i = 16; i < 18; i++) { + verts[i * 3] = verts[i * 3] - 5; + } + for (let i = 0; i < 16; i++) { + verts[i * 3] = verts[i * 3] - 10; + } + for (let i = 20; i < 24; i++) { + verts[i * 3] = verts[i * 3] - 10; + } + } + // console.log(name, verts); + // verts[7] = verts[7] * 2; + rect.updateVerticesData("position", verts); + ret = rect; break; } case 'sphere': { const bFaceUvs = this.buildGeometryFaceUvs_(faceUvs, 2)?.[0]; - ret = BabylonSphereBuilder.CreateSphere(name, { - // Why?? Why is a sphere defined by its diameter? - diameter: Distance.toCentimetersValue(geometry.radius) * 2, + const segments = 4; + const rock = BabylonSphereBuilder.CreateSphere(name, { + segments: segments, + updatable:true, frontUVs: bFaceUvs, sideOrientation: bFaceUvs ? BabylonMesh.DOUBLESIDE : undefined, + diameterX:Distance.toCentimetersValue(geometry.radius) * 2, + diameterY:Distance.toCentimetersValue(geometry.radius) * 2 * geometry.squash, + diameterZ:Distance.toCentimetersValue(geometry.radius) * 2 * geometry.stretch, }, this.bScene_); + + const positions = rock.getVerticesData("position"); + if (name.includes('Hab')) { + for (let i = 51; i < positions.length; i++) { + positions[3 * i + 1] = 0; + } + } + if (name.includes('Rock')) { + // when segments = 1, rings are 7 points; s=2, rings=9; s=3, r=11; s=4, r=13 + // for a sphere, the vertices ring down in circles, starting with 7 on the top, and then 7 for each layer + // 0-6 controls height of top; 7-13 controls hight of top middle; 14-20...; 21-27 + // const skip = [13,14,20];+6 // for segments = 1 + // const skip = [17,18,26,27,34];+8 // for segments = 2 + // const skip = [21,22,32,33,43,44]+10; // for segments = 3 + const skip = [25,26,38,39,51,52,64,65]; // for segments = 4 + // for (let i = 8; i < 20; i++) { + // for (let i = 10; i < 35; i++) { + // for (let i = 12; i < 54; i++) { + for (let i = 14; i < 65; i++) { + if (skip.includes(i)) { + continue; + } else { + positions[3 * i] = positions[3 * i] + this.random(geometry.noise, -1 * geometry.noise); + positions[1 + 3 * i] = positions[1 + 3 * i] + this.random(geometry.noise, -1 * geometry.noise); + positions[2 + 3 * i] = positions[2 + 3 * i] + this.random(geometry.noise, -1 * geometry.noise); + } + } + } + rock.updateVerticesData("position", positions); + + ret = rock; break; } case 'cylinder': { @@ -218,13 +288,17 @@ class SceneBinding { const res = await BabylonSceneLoader.ImportMeshAsync(geometry.include ?? '', baseName, fileName, this.bScene_); if (res.meshes.length === 1) return res.meshes[0]; + // const nonColliders: BabylonMesh[] = []; + ret = new BabylonTransformNode(geometry.uri, this.bScene_); - for (const mesh of res.meshes) { + for (const mesh of res.meshes as BabylonMesh[]) { // GLTF importer adds a __root__ mesh (always the first one) that we can ignore if (mesh.name === '__root__') continue; + // nonColliders.push(mesh); mesh.setParent(ret); } + // const mesh = BabylonMesh.MergeMeshes(nonColliders, true, true, undefined, false, true); break; } default: { @@ -235,10 +309,13 @@ class SceneBinding { if (ret instanceof BabylonAbstractMesh) { ret.visibility = 1; } else { - const children = ret.getChildren(c => c instanceof BabylonAbstractMesh) as BabylonAbstractMesh[]; - for (const child of children) { - child.visibility = 1; - } + const children = ret.getChildren(c => c instanceof BabylonAbstractMesh) as BabylonMesh[]; + const mesh = BabylonMesh.MergeMeshes(children, true, true, undefined, false, true); + mesh.visibility = 1; + ret = mesh; + // for (const child of children) { + // child.visibility = 1; + // } } return ret; @@ -264,6 +341,7 @@ class SceneBinding { }; private createMaterial_ = (id: string, material: Material) => { + // console.log('Creating material', id, material); let bMaterial: BabylonMaterial; switch (material.type) { @@ -282,9 +360,27 @@ class SceneBinding { if (!color.uri) { basic.diffuseColor = new BabylonColor3(0.5, 0, 0.5); } else { - basic.diffuseTexture = new BabylonTexture(color.uri, this.bScene_); + if (id === '1.1.2-4 Sky') { + console.log('night_sky', color.uri); + basic.reflectionTexture = new BabylonTexture(color.uri, this.bScene_); + basic.reflectionTexture.coordinatesMode = BabylonTexture.FIXED_EQUIRECTANGULAR_MODE; + basic.backFaceCulling = false; + basic.disableLighting = true; + } else if (id === 'Container') { + const myDynamicTexture = new BabylonDynamicTexture("dynamic texture", 1000, this.bScene_, true); + // myDynamicTexture.drawText(material.text, 130, 600, "18px Arial", "white", "gray", true); + myDynamicTexture.drawText(color.uri, 130, 600, "18px Arial", "white", "gray", true); + basic.diffuseTexture = myDynamicTexture; + } else { + basic.bumpTexture = new BabylonTexture(color.uri, this.bScene_); + basic.emissiveTexture = new BabylonTexture(color.uri, this.bScene_); + basic.diffuseTexture = new BabylonTexture(color.uri, this.bScene_); + basic.diffuseTexture.coordinatesMode = BabylonTexture.FIXED_EQUIRECTANGULAR_MODE; + basic.backFaceCulling = false; + } } + break; } } @@ -297,7 +393,6 @@ class SceneBinding { case 'pbr': { const pbr = new BabylonPBRMaterial(id, this.bScene_); const { albedo, ambient, emissive, metalness, reflection } = material; - if (albedo) { switch (albedo.type) { case 'color3': { @@ -387,9 +482,15 @@ class SceneBinding { break; } case 'texture': { + console.log('Updating texture', color.next.uri); if (!color.next.uri) { bMaterial.diffuseColor = new BabylonColor3(0.5, 0, 0.5); bMaterial.diffuseTexture = null; + } else if (color.next.uri[0] !== '/') { + const myDynamicTexture = new BabylonDynamicTexture("dynamic texture", 1000, this.bScene_, true); + // myDynamicTexture.drawText(material.text, 130, 600, "18px Arial", "white", "gray", true); + myDynamicTexture.drawText(color.next.uri, 130, 600, "18px Arial", "white", "gray", true); + bMaterial.diffuseTexture = myDynamicTexture; } else { bMaterial.diffuseColor = Color.toBabylon(Color.WHITE); bMaterial.diffuseTexture = new BabylonTexture(color.next.uri, this.bScene_); @@ -506,8 +607,10 @@ class SceneBinding { }; private updateMaterial_ = (bMaterial: BabylonMaterial, material: Patch) => { + console.log('updateMaterial_', bMaterial, material); switch (material.type) { case Patch.Type.OuterChange: { + console.log('OuterChange'); const { next } = material; const id = bMaterial ? `${bMaterial.id}` : `Scene Material ${this.materialIdIter_++}`; if (bMaterial) bMaterial.dispose(); @@ -518,6 +621,7 @@ class SceneBinding { return null; } case Patch.Type.InnerChange: { + console.log('InnerChange'); const { inner, next } = material; switch (next.type) { case 'basic': { @@ -542,7 +646,7 @@ class SceneBinding { console.error(`node ${LocalizedString.lookup(node.name, LocalizedString.EN_US)} has invalid geometry ID: ${node.geometryId}`); return null; } - + // console.log(node); const ret = await this.buildGeometry_(node.name[LocalizedString.EN_US], geometry, node.faceUvs); if (!node.visible) { @@ -677,7 +781,31 @@ class SceneBinding { let nodeToCreate: Node = node; // Resolve template nodes into non-template nodes by looking up the template by ID - if (node.type === 'from-template') { + if (node.type === 'from-jbc-template') { + const nodeTemplate = preBuiltTemplates[node.templateId]; + if (!nodeTemplate) { + console.warn('template node has invalid template ID:', node.templateId); + return null; + } + + nodeToCreate = { + ...node, + ...nodeTemplate, + }; + } + if (node.type === 'from-rock-template') { + const nodeTemplate = preBuiltTemplates[node.templateId]; + if (!nodeTemplate) { + console.warn('template node has invalid template ID:', node.templateId); + return null; + } + + nodeToCreate = { + ...node, + ...nodeTemplate, + }; + } + if (node.type === 'from-space-template') { const nodeTemplate = preBuiltTemplates[node.templateId]; if (!nodeTemplate) { console.warn('template node has invalid template ID:', node.templateId); @@ -785,6 +913,8 @@ class SceneBinding { }; private updateObject_ = async (id: string, node: Patch.InnerChange, nextScene: Scene): Promise => { + console.log('update object:', id, node); + const bNode = this.findBNode_(id) as FrameLike; // If the object's geometry ID changes, recreate the object entirely @@ -838,6 +968,55 @@ class SceneBinding { return Promise.resolve(bNode); }; + private updateSpaceObject_ = async (id: string, node: Patch.InnerChange, nextScene: Scene): Promise => { + console.log('update object:', id, node); + + const bNode = this.findBNode_(id) as FrameLike; + + // If the object's geometry ID changes, recreate the object entirely + if (node.inner.geometryId.type === Patch.Type.OuterChange) { + this.destroyNode_(id); + return (await this.createNode_(id, node.next, nextScene)) as FrameLike; + } + + if (node.inner.name.type === Patch.Type.OuterChange) { + bNode.name = node.inner.name.next[LocalizedString.EN_US]; + } + + if (node.inner.parentId.type === Patch.Type.OuterChange) { + const parent = this.findBNode_(node.inner.parentId.next, true); + bNode.setParent(parent); + } + + let bMaterial = this.findMaterial_(bNode); + bMaterial = this.updateMaterial_(bMaterial, node.inner.material); + SceneBinding.apply_(bNode, m => { + m.material = bMaterial; + }); + + // TODO: Handle changes to faceUvs when we fully support it + + if (node.inner.origin.type === Patch.Type.OuterChange) { + this.updateNodePosition_(node.next, bNode); + } + + if (node.inner.visible.type === Patch.Type.OuterChange) { + const nextVisible = node.inner.visible.next; + SceneBinding.apply_(bNode, m => { + m.isVisible = nextVisible; + + // Create/remove physics impostor for object becoming visible/invisible + if (!nextVisible) { + this.removePhysicsImpostor(m); + } else { + this.restorePhysicsImpostor(m, node.next, id, nextScene); + } + }); + } + + return Promise.resolve(bNode); + }; + private updateDirectionalLight_ = (id: string, node: Patch.InnerChange): BabylonDirectionalLight => { const bNode = this.findBNode_(id) as BabylonDirectionalLight; @@ -884,7 +1063,205 @@ class SceneBinding { return robotBinding; }; - private updateFromTemplate_ = (id: string, node: Patch.InnerChange, nextScene: Scene): Promise => { + private updateRockFromTemplate_ = (id: string, node: Patch.InnerChange, nextScene: Scene): Promise => { + // If the template ID changes, recreate the node entirely + if (node.inner.templateId.type === Patch.Type.OuterChange) { + this.destroyNode_(id); + return this.createNode_(id, node.next, nextScene); + } + + const bNode = this.findBNode_(id); + + const nodeTemplate = preBuiltTemplates[node.next.templateId]; + if (!nodeTemplate) { + console.warn('template node has invalid template ID:', node.next.templateId); + return Promise.resolve(bNode); + } + + const prevBaseProps = Node.Base.upcast(node.prev); + const nextBaseProps = Node.Base.upcast(node.next); + + // Create a Patch for the underlying node type and call its update function + switch (nodeTemplate.type) { + case 'empty': { + const emptyChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'empty'>('empty'), + }, + }; + return Promise.resolve(this.updateEmpty_(id, emptyChange)); + } + case 'object': { + const objectChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'object'>('object'), + geometryId: Patch.none(nodeTemplate.geometryId), + physics: Patch.none(nodeTemplate.physics), + material: Patch.none(nodeTemplate.material), + faceUvs: Patch.none(nodeTemplate.faceUvs), + }, + }; + return this.updateObject_(id, objectChange, nextScene); + } + case 'directional-light': { + const directionalLightChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'directional-light'>('directional-light'), + radius: Patch.none(nodeTemplate.radius), + range: Patch.none(nodeTemplate.range), + direction: Patch.none(nodeTemplate.direction), + intensity: Patch.none(nodeTemplate.intensity), + }, + }; + return Promise.resolve(this.updateDirectionalLight_(id, directionalLightChange)); + } + case 'spot-light': { + const spotLightChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'spot-light'>('spot-light'), + direction: Patch.none(nodeTemplate.direction), + angle: Patch.none(nodeTemplate.angle), + exponent: Patch.none(nodeTemplate.exponent), + intensity: Patch.none(nodeTemplate.intensity), + }, + }; + return Promise.resolve(this.updateSpotLight_(id, spotLightChange)); + } + case 'point-light': { + const pointLightChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'point-light'>('point-light'), + intensity: Patch.none(nodeTemplate.intensity), + radius: Patch.none(nodeTemplate.radius), + range: Patch.none(nodeTemplate.range), + }, + }; + return Promise.resolve(this.updatePointLight_(id, pointLightChange)); + } + default: return Promise.resolve(bNode); + } + }; + private updateSpaceFromTemplate_ = (id: string, node: Patch.InnerChange, nextScene: Scene): Promise => { + // If the template ID changes, recreate the node entirely + console.log('IN updateSpaceFromTemplate_'); + if (node.inner.templateId.type === Patch.Type.OuterChange) { + this.destroyNode_(id); + return this.createNode_(id, node.next, nextScene); + } + + const bNode = this.findBNode_(id); + + const nodeTemplate = preBuiltTemplates[node.next.templateId]; + if (!nodeTemplate) { + console.warn('template node has invalid template ID:', node.next.templateId); + return Promise.resolve(bNode); + } + + const prevBaseProps = Node.Base.upcast(node.prev); + const nextBaseProps = Node.Base.upcast(node.next); + + // Create a Patch for the underlying node type and call its update function + switch (nodeTemplate.type) { + case 'empty': { + const emptyChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'empty'>('empty'), + }, + }; + return Promise.resolve(this.updateEmpty_(id, emptyChange)); + } + case 'object': { + const objectChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'object'>('object'), + geometryId: Patch.none(nodeTemplate.geometryId), + physics: Patch.none(nodeTemplate.physics), + material: Patch.none(node.next.material), + faceUvs: Patch.none(nodeTemplate.faceUvs), + }, + }; + return this.updateSpaceObject_(id, node, nextScene); + // return this.updateObject_(id, objectChange, nextScene); + } + case 'directional-light': { + const directionalLightChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'directional-light'>('directional-light'), + radius: Patch.none(nodeTemplate.radius), + range: Patch.none(nodeTemplate.range), + direction: Patch.none(nodeTemplate.direction), + intensity: Patch.none(nodeTemplate.intensity), + }, + }; + return Promise.resolve(this.updateDirectionalLight_(id, directionalLightChange)); + } + case 'spot-light': { + const spotLightChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'spot-light'>('spot-light'), + direction: Patch.none(nodeTemplate.direction), + angle: Patch.none(nodeTemplate.angle), + exponent: Patch.none(nodeTemplate.exponent), + intensity: Patch.none(nodeTemplate.intensity), + }, + }; + return Promise.resolve(this.updateSpotLight_(id, spotLightChange)); + } + case 'point-light': { + const pointLightChange: Patch.InnerChange = { + type: Patch.Type.InnerChange, + prev: { ...nodeTemplate, ...prevBaseProps }, + next: { ...nodeTemplate, ...nextBaseProps }, + inner: { + ...node.inner, + type: Patch.none<'point-light'>('point-light'), + intensity: Patch.none(nodeTemplate.intensity), + radius: Patch.none(nodeTemplate.radius), + range: Patch.none(nodeTemplate.range), + }, + }; + return Promise.resolve(this.updatePointLight_(id, pointLightChange)); + } + default: return Promise.resolve(bNode); + } + }; + private updateJBCFromTemplate_ = (id: string, node: Patch.InnerChange, nextScene: Scene): Promise => { // If the template ID changes, recreate the node entirely if (node.inner.templateId.type === Patch.Type.OuterChange) { this.destroyNode_(id); @@ -984,9 +1361,11 @@ class SceneBinding { }; private updateNode_ = async (id: string, node: Patch, geometryPatches: Dict>, nextScene: Scene): Promise => { + switch (node.type) { // The node hasn't changed type, but some fields have been changed case Patch.Type.InnerChange: { + console.log('updateNode_ InnerChange', id, node); // If scriptIds changed, rebind the scripts if (node.inner.scriptIds.type === Patch.Type.OuterChange) { for (const scriptId of node.inner.scriptIds.prev || []) this.scriptManager_.unbind(scriptId, id); @@ -1012,7 +1391,12 @@ class SceneBinding { await this.updateRobot_(id, node as Patch.InnerChange); return null; } - case 'from-template': return this.updateFromTemplate_(id, node as Patch.InnerChange, nextScene); + case 'from-jbc-template': return this.updateJBCFromTemplate_(id, node as Patch.InnerChange, nextScene); + case 'from-rock-template': return this.updateRockFromTemplate_(id, node as Patch.InnerChange, nextScene); + case 'from-space-template': { + console.log('updateNode_ from-space-template', id, node); + return this.updateSpaceFromTemplate_(id, node as Patch.InnerChange, nextScene); + } default: { console.error('invalid node type for inner change:', (node.next as Node).type); return this.findBNode_(id); @@ -1074,6 +1458,7 @@ class SceneBinding { ret.attachControl(this.bScene_.getEngine().getRenderingCanvas(), true); ret.position = Vector3.toBabylon(camera.position, 'centimeters'); ret.panningSensibility = 100; + // ret.checkCollisions = true; return ret; }; @@ -1123,7 +1508,7 @@ class SceneBinding { otherImpostors: BabylonPhysicsImpostor[]; }[]> = {}; - private restorePhysicsImpostor = (mesh: BabylonAbstractMesh, objectNode: Node.Obj, nodeId: string, scene: Scene): void => { + private restorePhysicsImpostor = (mesh: BabylonAbstractMesh, objectNode: Node.Obj | Node.FromSpaceTemplate, nodeId: string, scene: Scene): void => { // Physics impostors should only be added to physics-enabled, visible, non-selected objects if ( !objectNode.physics || @@ -1275,10 +1660,17 @@ class SceneBinding { let prevNodeObj: Node.Obj; const prevNode = scene.nodes[prev]; if (prevNode.type === 'object') prevNodeObj = prevNode; - else if (prevNode.type === 'from-template') { + else if (prevNode.type === 'from-jbc-template') { + const nodeTemplate = preBuiltTemplates[prevNode.templateId]; + if (nodeTemplate?.type === 'object') prevNodeObj = { ...nodeTemplate, ...Node.Base.upcast(prevNode) }; + } else if (prevNode.type === 'from-rock-template') { + const nodeTemplate = preBuiltTemplates[prevNode.templateId]; + if (nodeTemplate?.type === 'object') prevNodeObj = { ...nodeTemplate, ...Node.Base.upcast(prevNode) }; + } else if (prevNode.type === 'from-space-template') { const nodeTemplate = preBuiltTemplates[prevNode.templateId]; if (nodeTemplate?.type === 'object') prevNodeObj = { ...nodeTemplate, ...Node.Base.upcast(prevNode) }; } + const prevBNode = this.bScene_.getNodeByID(prev); if (prevNodeObj && (prevBNode instanceof BabylonAbstractMesh || prevBNode instanceof BabylonTransformNode)) { prevBNode.metadata = { ...(prevBNode.metadata as SceneMeshMetadata), selected: false }; diff --git a/src/components/World/AddNodeDialog.tsx b/src/components/World/AddNodeDialog.tsx index 47b8933a..648e594b 100644 --- a/src/components/World/AddNodeDialog.tsx +++ b/src/components/World/AddNodeDialog.tsx @@ -78,7 +78,7 @@ class AddNodeDialog extends React.PureComponent { this.state = { id: uuid.v4(), node: { - type: 'from-template', + type: 'from-jbc-template', templateId: 'can', name: tr('Unnamed Object'), startingOrigin: origin, diff --git a/src/components/World/NodeSettings.tsx b/src/components/World/NodeSettings.tsx index ff8e36fe..25d3b8c7 100644 --- a/src/components/World/NodeSettings.tsx +++ b/src/components/World/NodeSettings.tsx @@ -147,21 +147,57 @@ class NodeSettings extends React.PureComponent { let transmutedNode = Node.transmute(node, selectedType); - const TEMPLATE_OPTIONS: ComboBox.Option[] = [ + const JBC_TEMPLATE_OPTIONS: ComboBox.Option[] = [ ComboBox.option(LocalizedString.lookup(tr('Can'), locale), 'can'), ComboBox.option(LocalizedString.lookup(tr('Paper Ream'), locale), 'ream'), ]; + const ROCK_TEMPLATE_OPTIONS: ComboBox.Option[] = [ + ComboBox.option(LocalizedString.lookup(tr('Basalt Rock'), locale), 'basalt'), + ComboBox.option(LocalizedString.lookup(tr('Anorthosite Rock'), locale), 'anorthosite'), + ComboBox.option(LocalizedString.lookup(tr('Breccia Rock'), locale), 'breccia'), + ComboBox.option(LocalizedString.lookup(tr('Meteorite Rock'), locale), 'meteorite'), + ]; + const SPACE_TEMPLATE_OPTIONS: ComboBox.Option[] = [ + ComboBox.option(LocalizedString.lookup(tr('Communication Tower'), locale), 'tower'), + ComboBox.option(LocalizedString.lookup(tr('Hab'), locale), 'hab'), + ComboBox.option(LocalizedString.lookup(tr('Science Pad'), locale), 'sciencepad'), + ComboBox.option(LocalizedString.lookup(tr('Life Science Pack'), locale), 'lifescience'), + ComboBox.option(LocalizedString.lookup(tr('Radiation Science Pack'), locale), 'radscience'), + ComboBox.option(LocalizedString.lookup(tr('Communication Tower 2'), locale), 'comstower'), + ComboBox.option(LocalizedString.lookup(tr('Hab 2'), locale), 'habitat'), + ComboBox.option(LocalizedString.lookup(tr('Walkway'), locale), 'walkway'), + ComboBox.option(LocalizedString.lookup(tr('Solar Panel'), locale), 'solarpanel'), + ComboBox.option(LocalizedString.lookup(tr('BotGuy Astronaut'), locale), 'botguy'), + ]; + + // If the new type is from a template, set the template ID to a default value // If the new type is from a template, set the template ID to a default value - if (transmutedNode.type === 'from-template') { - const defaultTemplateId = TEMPLATE_OPTIONS[0].data as string; + if (transmutedNode.type === 'from-jbc-template') { + const defaultTemplateId = JBC_TEMPLATE_OPTIONS[0].data as string; + + transmutedNode = { + ...transmutedNode, + templateId: defaultTemplateId, + }; + } + // If the new type is from a template, set the template ID to a default value + if (transmutedNode.type === 'from-rock-template') { + const defaultTemplateId = ROCK_TEMPLATE_OPTIONS[0].data as string; + + transmutedNode = { + ...transmutedNode, + templateId: defaultTemplateId, + }; + } + if (transmutedNode.type === 'from-space-template') { + const defaultTemplateId = SPACE_TEMPLATE_OPTIONS[0].data as string; transmutedNode = { ...transmutedNode, templateId: defaultTemplateId, }; } - // If the new type is an object, add a new geometry and reset the physics type if (transmutedNode.type === 'object') { const defaultGeometryType: Geometry.Type = 'box'; @@ -436,9 +472,10 @@ class NodeSettings extends React.PureComponent { private onMaterialBasicFieldTextureUriChange_ = (field: keyof Omit) => (event: React.SyntheticEvent) => { const { node, onNodeChange } = this.props; - if (node.type !== 'object') throw new Error('Node is not an object'); + if (node.type !== 'object' && node.type !== 'from-space-template') throw new Error('Node is not an object'); const material = node.material as Material.Basic; + console.log("prev", material); const nextMaterial = { ...material }; const member = material[field]; @@ -448,6 +485,7 @@ class NodeSettings extends React.PureComponent { ...member, uri: event.currentTarget.value }; + console.log("update", nextMaterial); onNodeChange({ ...node, @@ -461,7 +499,7 @@ class NodeSettings extends React.PureComponent { private onMaterialPbrAmbientTextureUriChange_ = this.onMaterialPbrFieldTextureUriChange_('ambient'); private onMaterialPbrMetalnessTextureUriChange_ = this.onMaterialPbrFieldTextureUriChange_('metalness'); - private onMaterialBasicColorTextureUriChange_ = this.onMaterialBasicFieldTextureUriChange_('color'); + private onMaterialBasicColorTextureUriChange2_ = this.onMaterialBasicFieldTextureUriChange_('color'); private static materialType = (material: Material) => { if (!material) return 'unset'; @@ -518,11 +556,26 @@ class NodeSettings extends React.PureComponent { } }; - private onTemplateSelect_ = (index: number, option: ComboBox.Option) => { + private onJBCTemplateSelect_ = (index: number, option: ComboBox.Option) => { + const { props } = this; + const { node } = props; + + if (node.type !== 'from-jbc-template') return; + + const templateId = option.data as string; + + this.props.onNodeChange({ + ...node, + templateId + }); + }; + + private onRockTemplateSelect_ = (index: number, option: ComboBox.Option) => { + console.log("onRockTemplateSelect_"); const { props } = this; const { node } = props; - if (node.type !== 'from-template') return; + if (node.type !== 'from-rock-template') return; const templateId = option.data as string; @@ -532,6 +585,20 @@ class NodeSettings extends React.PureComponent { }); }; + private onSpaceTemplateSelect_ = (index: number, option: ComboBox.Option) => { + console.log("onSpaceTemplateSelect_"); + const { props } = this; + const { node } = props; + + if (node.type !== 'from-space-template') return; + + const templateId = option.data as string; + + this.props.onNodeChange({ + ...node, + templateId + }); + }; private onCollapsedChange_ = (key: string) => (collapsed: boolean) => { this.setState({ collapsed: { @@ -895,13 +962,55 @@ class NodeSettings extends React.PureComponent { return dict; }, {}); - - const TEMPLATE_OPTIONS: ComboBox.Option[] = [ + + const JBC_TEMPLATE_OPTIONS: ComboBox.Option[] = [ ComboBox.option(LocalizedString.lookup(tr('Can'), locale), 'can'), ComboBox.option(LocalizedString.lookup(tr('Paper Ream'), locale), 'ream'), ]; + const ROCK_TEMPLATE_OPTIONS: ComboBox.Option[] = [ + ComboBox.option(LocalizedString.lookup(tr('Basalt Rock'), locale), 'basalt'), + ComboBox.option(LocalizedString.lookup(tr('Anorthosite Rock'), locale), 'anorthosite'), + ComboBox.option(LocalizedString.lookup(tr('Breccia Rock'), locale), 'breccia'), + ComboBox.option(LocalizedString.lookup(tr('Meteorite Rock'), locale), 'meteorite'), + ]; + const SPACE_TEMPLATE_OPTIONS: ComboBox.Option[] = [ + ComboBox.option(LocalizedString.lookup(tr('Communication Tower'), locale), 'tower'), + ComboBox.option(LocalizedString.lookup(tr('Hab'), locale), 'hab'), + ComboBox.option(LocalizedString.lookup(tr('Life Science Pack'), locale), 'lifescience'), + ComboBox.option(LocalizedString.lookup(tr('Radiation Science Pack'), locale), 'radscience'), + ComboBox.option(LocalizedString.lookup(tr('Radiation Science Pack'), locale), 'noradscience'), + ComboBox.option(LocalizedString.lookup(tr('Communication Tower 2'), locale), 'commstower'), + ComboBox.option(LocalizedString.lookup(tr('Science Pad'), locale), 'sciencepad'), + ComboBox.option(LocalizedString.lookup(tr('Living Habitat'), locale), 'habitat'), + ComboBox.option(LocalizedString.lookup(tr('Research Habitat'), locale), 'research_habitat'), + ComboBox.option(LocalizedString.lookup(tr('Controls Habitat'), locale), 'control_habitat'), + ComboBox.option(LocalizedString.lookup(tr('Walkway'), locale), 'walkway'), + ComboBox.option(LocalizedString.lookup(tr('Solar Panel'), locale), 'solarpanel'), + ComboBox.option(LocalizedString.lookup(tr('BotGuy Astronaut'), locale), 'botguy'), + ComboBox.option(LocalizedString.lookup(tr('Moon Rock Container'), locale), 'container'), + ]; + + const RADIATION_TEMPLATE_OPTIONS: ComboBox.Option[] = [ + ComboBox.option(LocalizedString.lookup(tr('Radiation Science Pack - Low'), locale), 'noradscience'), + ComboBox.option(LocalizedString.lookup(tr('Radiation Science Pack - High'), locale), 'radscience'), + ]; - const TEMPLATE_REVERSE_OPTIONS: Dict = TEMPLATE_OPTIONS.reduce((dict, option, i) => { + const JBC_TEMPLATE_REVERSE_OPTIONS: Dict = JBC_TEMPLATE_OPTIONS.reduce((dict, option, i) => { + dict[option.data as string] = i; + return dict; + }, {}); + + const ROCK_TEMPLATE_REVERSE_OPTIONS: Dict = ROCK_TEMPLATE_OPTIONS.reduce((dict, option, i) => { + dict[option.data as string] = i; + return dict; + }, {}); + + const SPACE_TEMPLATE_REVERSE_OPTIONS: Dict = SPACE_TEMPLATE_OPTIONS.reduce((dict, option, i) => { + dict[option.data as string] = i; + return dict; + }, {}); + + const RADIATION_TEMPLATE_REVERSE_OPTIONS: Dict = RADIATION_TEMPLATE_OPTIONS.reduce((dict, option, i) => { dict[option.data as string] = i; return dict; }, {}); @@ -921,13 +1030,23 @@ class NodeSettings extends React.PureComponent { ]; const NODE_TYPE_OPTIONS: ComboBox.Option[] = [ - ComboBox.option(LocalizedString.lookup(tr('Empty'), locale), 'empty'), - ComboBox.option(LocalizedString.lookup(tr('Standard Object'), locale), 'from-template'), + ComboBox.option(LocalizedString.lookup(tr('Space Base'), locale), 'from-space-template'), + ComboBox.option(LocalizedString.lookup(tr('JBC Pieces'), locale), 'from-jbc-template'), + ComboBox.option(LocalizedString.lookup(tr('Moon Rock'), locale), 'from-rock-template'), ComboBox.option(LocalizedString.lookup(tr('Custom Object'), locale), 'object'), // ComboBox.option('Directional Light', 'directional-light'), ComboBox.option(LocalizedString.lookup(tr('Point Light'), locale), 'point-light'), + ComboBox.option(LocalizedString.lookup(tr('Empty'), locale), 'empty'), + ComboBox.option(LocalizedString.lookup(tr('All'), locale), 'all'), // ComboBox.option('Spot Light', 'spot-light'), ]; + + const ROCK_DESCRIPTIONS: Dict = { + 'basalt': LocalizedString.lookup(tr('Basalt is an aphanitic (fine-grained) extrusive igneous rock formed from the rapid cooling of low-viscosity lava rich in magnesium and iron (mafic lava) exposed at or very near the surface of a rocky planet or moon.'), locale), + 'anorthosite': LocalizedString.lookup(tr('Anorthosite is a phaneritic, intrusive igneous rock characterized by its composition: mostly plagioclase feldspar (90–100%), with a minimal mafic component (0–10%).'), locale), + 'breccia': LocalizedString.lookup(tr('Breccia is a rock composed of large angular broken fragments of minerals or rocks cemented together by a fine-grained matrix.'), locale), + 'meteorite': LocalizedString.lookup(tr('Meteorite is a solid piece of debris from an object, such as a comet, asteroid, or meteoroid, that originates in outer space and survives its passage through the atmosphere to reach the surface of a planet or moon.'), locale), + }; const NODE_TYPE_OPTIONS_REV = (() => { const map: Record = {}; @@ -1026,17 +1145,59 @@ class NodeSettings extends React.PureComponent { /> )} - - {node.type === 'from-template' && ( + {node.type === 'from-jbc-template' && ( )} + {node.type === 'from-rock-template' && ( + + + + )} + {node.type === 'from-space-template' && ( + + + + )} + +
+ {node.type === 'from-rock-template' && ( + <> + <>{ROCK_DESCRIPTIONS[node.templateId]} + + )} + {/* {node.material && node.material.type === 'basic' && node.material.color && node.material.color.type === 'texture' && ( */} + {node.type === 'from-space-template' && (node.templateId === 'radscience' || node.templateId === 'noradscience') && ( + + + + )} + {node.type === 'from-space-template' && node.material && node.material.type === 'basic' && node.material.color.type === 'texture' && node.templateId === 'container' && ( + + + + )}
{(node.type === 'object' && geometry && geometry.type === 'box') ? (
{ />
) : undefined} - + {(node.type === 'object' && geometry.type === 'file') ? (
@@ -1177,7 +1338,7 @@ class NodeSettings extends React.PureComponent { )} {node.material && node.material.type === 'basic' && node.material.color && node.material.color.type === 'texture' && ( - + )} diff --git a/src/index.html.ejs b/src/index.html.ejs index 5725de75..f662c494 100644 --- a/src/index.html.ejs +++ b/src/index.html.ejs @@ -3,9 +3,9 @@ - - - + + + KISS IDE Simulator diff --git a/src/login/LoginPage.tsx b/src/login/LoginPage.tsx index f29160b8..08687582 100644 --- a/src/login/LoginPage.tsx +++ b/src/login/LoginPage.tsx @@ -46,7 +46,7 @@ const Container = styled('div', (props: ThemeProps) => ({ justifyContent: 'center', width: '100%', height: '100vh', - backgroundImage: 'url(../../static/Triangular_Background_Compressed.png)', + backgroundImage: 'url(../../static/backgrounds/Triangular_Background_Compressed.png)', backgroundSize: 'cover', })); diff --git a/src/login/login.html.ejs b/src/login/login.html.ejs index 9e90556b..aaffd56f 100644 --- a/src/login/login.html.ejs +++ b/src/login/login.html.ejs @@ -3,9 +3,9 @@ - - - + + + KISS IDE Simulator diff --git a/src/node-templates/index.ts b/src/node-templates/index.ts index 0b98211b..e35c7548 100644 --- a/src/node-templates/index.ts +++ b/src/node-templates/index.ts @@ -20,7 +20,64 @@ const canTemplate: Node.TemplatedNode = { type: 'basic', color: { type: 'texture', - uri: '/static/Can Texture.png' + uri: '/static/textures/Can_Texture.png' + }, + }, + faceUvs: [Vector2.ZERO, Vector2.ZERO, Vector2.create(1, 0), Vector2.create(0, 1), Vector2.ZERO, Vector2.ZERO], +}; + +const lifescienceTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'can', + physics: { + type: 'cylinder', + mass: Mass.grams(5), + friction: 0.7, + restitution: 0.3, + }, + material: { + type: 'basic', + color: { + type: 'texture', + uri: '/static/textures/sciencepack/life_science_pack.png' + }, + }, + faceUvs: [Vector2.ZERO, Vector2.ZERO, Vector2.create(1, 0), Vector2.create(0, 1), Vector2.ZERO, Vector2.ZERO], +}; + +const radscienceTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'can', + physics: { + type: 'cylinder', + mass: Mass.grams(5), + friction: 0.7, + restitution: 0.3, + }, + material: { + type: 'basic', + color: { + type: 'texture', + uri: '/static/textures/sciencepack/rad_science_pack.png' + }, + }, + faceUvs: [Vector2.ZERO, Vector2.ZERO, Vector2.create(1, 0), Vector2.create(0, 1), Vector2.ZERO, Vector2.ZERO], +}; + +const noradscienceTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'can', + physics: { + type: 'cylinder', + mass: Mass.grams(5), + friction: 0.7, + restitution: 0.3, + }, + material: { + type: 'basic', + color: { + type: 'texture', + uri: '/static/textures/sciencepack/no_rad_science_pack.png' }, }, faceUvs: [Vector2.ZERO, Vector2.ZERO, Vector2.create(1, 0), Vector2.create(0, 1), Vector2.ZERO, Vector2.ZERO], @@ -31,7 +88,7 @@ const reamTemplate: Node.TemplatedNode = { geometryId: 'ream', physics: { type: 'box', - restitution: 0, + restitution: .9, friction: 1, mass: Mass.pounds(5), }, @@ -39,7 +96,96 @@ const reamTemplate: Node.TemplatedNode = { type: 'basic', color: { type: 'color3', - color: Color.Rgb.create(250, 249, 246), + color: Color.Rgb.create(250, 250, 250), + }, + }, +}; + +const sciencePadTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'sciencepad', + physics: { + type: 'box', + restitution: 1, + friction: 1, + }, + material: { + type: 'basic', + color: { + type: "texture", + uri: "/static/textures/science_pad2.png" + }, + }, +}; + +const basaltTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'basalt', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.5), + }, + material: { + type: 'basic', + color: { + type: 'texture', + uri: '/static/textures/rocks/basalt_texture_m.png' + }, + }, +}; + +const anorthositeTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'anorthosite', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.5), + }, + material: { + type: 'basic', + color: { + type: 'texture', + uri: '/static/textures/rocks/anorthosite_texture_m.png' + }, + }, +}; + +const brecciaTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'breccia', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.5), + }, + material: { + type: 'basic', + color: { + type: 'texture', + uri: '/static/textures/rocks/breccia_texture_m.png' + }, + }, +}; + +const meteoriteTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'meteorite', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.5), + }, + material: { + type: 'basic', + color: { + type: 'texture', + uri: '/static/textures/rocks/meteorite_texture_m.png' }, }, }; @@ -64,19 +210,139 @@ const jbcMatBTemplate: Node.TemplatedNode = { }, }; +const containerTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'container', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + // mass: Mass.pounds(20), + }, +}; +const botguyTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'botguy', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.3), + }, +}; +const solarpanelTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'solarpanel', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.3), + }, +}; + +const walkwayTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'walkway', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.3), + }, +}; +const commstowerTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'commstower', + physics: { + type: 'box', + restitution: .3, + friction: 1, + mass: Mass.pounds(.3), + }, +}; + +const habitatTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'habitat', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.3), + }, +}; + +const habitatResearchTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'research_habitat', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.3), + }, +}; + +const habitatControlTemplate: Node.TemplatedNode = { + type: 'object', + geometryId: 'control_habitat', + physics: { + type: 'mesh', + restitution: .3, + friction: 1, + mass: Mass.pounds(.3), + }, +}; + export const preBuiltTemplates = Object.freeze>>({ 'can': canTemplate, + 'sciencepad': sciencePadTemplate, + 'lifescience': lifescienceTemplate, + 'radscience': radscienceTemplate, + 'noradscience': noradscienceTemplate, 'ream': reamTemplate, + 'basalt': basaltTemplate, + 'anorthosite': anorthositeTemplate, + 'breccia': brecciaTemplate, + 'meteorite': meteoriteTemplate, 'jbc_mat_a': jbcMatATemplate, 'jbc_mat_b': jbcMatBTemplate, + 'container': containerTemplate, + 'botguy': botguyTemplate, + 'solarpanel': solarpanelTemplate, + 'walkway': walkwayTemplate, + 'commstower': commstowerTemplate, + 'habitat': habitatTemplate, + 'research_habitat': habitatResearchTemplate, + 'control_habitat': habitatControlTemplate, }); + export const preBuiltGeometries = Object.freeze>({ 'can': { type: 'cylinder', height: Distance.centimeters(11.15), radius: Distance.centimeters(3), }, + 'lifescience': { + type: 'cylinder', + height: Distance.centimeters(7), + radius: Distance.centimeters(3), + }, + 'radscience': { + type: 'cylinder', + height: Distance.centimeters(7), + radius: Distance.centimeters(3), + }, + 'sciencepad': { + type: 'box', + size: { + x: Distance.feet(1), + y: Distance.centimeters(4), + z: Distance.feet(1), + } + }, 'ream': { type: 'box', size: { @@ -85,12 +351,72 @@ export const preBuiltGeometries = Object.freeze>({ z: Distance.centimeters(21.59), }, }, + 'basalt': { + type: 'sphere', + radius: Distance.centimeters(5), + squash: 1, + stretch: 1, + noise: .5, + }, + 'anorthosite': { + type: 'sphere', + radius: Distance.centimeters(5), + squash: .8, + stretch: 1, + noise: 1, + }, + 'breccia': { + type: 'sphere', + radius: Distance.centimeters(5), + squash: 1, + stretch: 1, + noise: 1, + }, + 'meteorite': { + type: 'sphere', + radius: Distance.centimeters(5), + squash: 1, + stretch: 1, + noise: 1, + }, 'jbc_mat_a': { type: 'file', - uri: '/static/jbcMatA.glb' + uri: '/static/object_binaries/jbcMatA.glb' }, 'jbc_mat_b': { type: 'file', - uri: '/static/jbcMatB.glb' + uri: '/static/object_binaries/jbcMatB.glb' + }, + 'container': { + type: 'file', + uri: '/static/object_binaries/container_with_lid.glb' + }, + 'botguy': { + type: 'file', + uri: '/static/object_binaries/botguy.glb' + }, + 'solarpanel': { + type: 'file', + uri: '/static/object_binaries/solar_panel2.glb' + }, + 'walkway': { + type: 'file', + uri: '/static/object_binaries/new_walkway.glb' + }, + 'commstower': { + type: 'file', + uri: '/static/object_binaries/comm_tower_lowered.glb' + }, + 'habitat': { + type: 'file', + uri: '/static/object_binaries/hab_living.glb' + }, + 'research_habitat': { + type: 'file', + uri: '/static/object_binaries/hab_research.glb' + }, + 'control_habitat': { + type: 'file', + uri: '/static/object_binaries/hab_comms.glb' }, }); \ No newline at end of file diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx index c70c4bd6..aff3e1d2 100644 --- a/src/pages/Dashboard.tsx +++ b/src/pages/Dashboard.tsx @@ -78,14 +78,14 @@ class Dashboard extends React.PureComponent { title={LocalizedString.lookup(tr('Tutorials'), locale)} description={LocalizedString.lookup(tr('Learn how to get started with the simulator'), locale)} backgroundColor={'#6c6ca1'} - backgroundImage={'url(../../static/Laptop_Icon_Sunscreen.png)'} + backgroundImage={'url(../../static/icons/Laptop_Icon_Sunscreen.png)'} onClick={onTutorialsClick} /> @@ -93,7 +93,7 @@ class Dashboard extends React.PureComponent { theme={theme} title={LocalizedString.lookup(tr('About'), locale)} description={LocalizedString.lookup(tr('KIPR is a 501(c) 3 organization started to make the long-term educational benefits of robotics accessible to students.'), locale)} - backgroundImage={'linear-gradient(#3b3c3c, transparent), url(../../static/Botguy-Picture-Small.png)'} + backgroundImage={'linear-gradient(#3b3c3c, transparent), url(../../static/icons/Botguy-Picture-Small.png)'} backgroundColor={'#3b3c3c'} backgroundSize={'80%'} hoverBackgroundSize={'95%'} diff --git a/src/pages/tutorialList.ts b/src/pages/tutorialList.ts index d5acd7c2..baafd348 100644 --- a/src/pages/tutorialList.ts +++ b/src/pages/tutorialList.ts @@ -7,25 +7,25 @@ export const tutorialList: Tutorial [] = [ title: tr('Quick Start'), description: tr('Learn how to get started with the simulator'), backgroundColor: '#6c6ca1', - backgroundImage: 'url(../../static/Laptop_Icon_Sunscreen.png)', + backgroundImage: 'url(../../static/icons/Laptop_Icon_Sunscreen.png)', src: 'https://www.youtube.com/embed/7Szf-iQjNCw', }, { title: tr('Navigating in 3D'), description: tr('Learn the controls for navigating in 3D in the simulator'), - backgroundImage: 'linear-gradient(#3b3c3c, transparent), url(../../static/Simulator_Full_View.png)', + backgroundImage: 'linear-gradient(#3b3c3c, transparent), url(../../static/example_images/Simulator_Full_View.png)', src: 'https://www.youtube.com/embed/RBpWIpBlYK8', }, { title: tr('Robot Section'), description: tr('How to use the robot section'), - backgroundImage: 'url(../../static/Simulator-Robot-Closeup.png)', + backgroundImage: 'url(../../static/example_images/Simulator-Robot-Closeup.png)', src: 'https://www.youtube.com/embed/SmYR1esidcc', }, { title: tr('World Section'), description: tr('Learn how to create and manipulate items and scene in the simulator'), - backgroundImage: 'linear-gradient(#3b3c3c, transparent), url(../../static/Can_Ream.png)', + backgroundImage: 'linear-gradient(#3b3c3c, transparent), url(../../static/textures/Can_Ream.png)', src: 'https://www.youtube.com/embed/K7GsS8s3Rfg', }, ]; diff --git a/src/robots/demobot.ts b/src/robots/demobot.ts index 5cc88c61..312966e9 100644 --- a/src/robots/demobot.ts +++ b/src/robots/demobot.ts @@ -137,10 +137,10 @@ export const DEMOBOT: Robot = { }), }, geometry: { - chassis_link: Geometry.remoteMesh({ uri: '/static/chassis.glb' }), - wheel_link: Geometry.remoteMesh({ uri: '/static/wheel.glb' }), - arm_link: Geometry.remoteMesh({ uri: '/static/arm.glb' }), - claw_link: Geometry.remoteMesh({ uri: '/static/claw.glb' }), + chassis_link: Geometry.remoteMesh({ uri: '/static/object_binaries/chassis.glb' }), + wheel_link: Geometry.remoteMesh({ uri: '/static/object_binaries/wheel.glb' }), + arm_link: Geometry.remoteMesh({ uri: '/static/object_binaries/arm.glb' }), + claw_link: Geometry.remoteMesh({ uri: '/static/object_binaries/claw.glb' }), }, origin: { orientation: Rotation.eulerDegrees(0, -90, 0), diff --git a/src/scenes/index.ts b/src/scenes/index.ts index 3c7e4121..fabb64dd 100644 --- a/src/scenes/index.ts +++ b/src/scenes/index.ts @@ -34,4 +34,5 @@ export * from './jbc20'; export * from './jbc21'; export * from './jbc22'; export * from './scriptPlayground'; -export * from './lightSensorTest'; \ No newline at end of file +export * from './lightSensorTest'; +export * from './moonSandbox'; \ No newline at end of file diff --git a/src/scenes/jbc15b.ts b/src/scenes/jbc15b.ts index f73f5384..e296e41b 100644 --- a/src/scenes/jbc15b.ts +++ b/src/scenes/jbc15b.ts @@ -55,7 +55,7 @@ export const JBC_15B: Scene = { origin: ROBOT_ORIGIN, }, 'ream1': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'ream', name: tr('Paper Ream 1'), startingOrigin: REAM1_ORIGIN, @@ -63,7 +63,7 @@ export const JBC_15B: Scene = { visible: true, }, 'ream2': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'ream', name: tr('Paper Ream 2'), startingOrigin: REAM2_ORIGIN, diff --git a/src/scenes/jbc19.ts b/src/scenes/jbc19.ts index 76c0e769..e1933a5d 100644 --- a/src/scenes/jbc19.ts +++ b/src/scenes/jbc19.ts @@ -31,7 +31,7 @@ export const JBC_19: Scene = { 'can2': createCanNode(2, { x: Distance.centimeters(-10), y: Distance.centimeters(6), z: Distance.centimeters(91.6) }), 'can3': createCanNode(3, { x: Distance.centimeters(-17), y: Distance.centimeters(6), z: Distance.centimeters(84.6) }), 'ream': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'ream', name: tr('Paper Ream'), startingOrigin: REAM_ORIGIN, diff --git a/src/scenes/jbc20.ts b/src/scenes/jbc20.ts index c07aa3e8..23ce1266 100644 --- a/src/scenes/jbc20.ts +++ b/src/scenes/jbc20.ts @@ -43,7 +43,7 @@ export const JBC_20: Scene = { 'can10': createCanNode(10), 'can12': createCanNode(12), 'ream': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'ream', name: tr('Paper Ream'), startingOrigin: REAM_ORIGIN, diff --git a/src/scenes/jbcBase.ts b/src/scenes/jbcBase.ts index 3e328639..5d3c53c2 100644 --- a/src/scenes/jbcBase.ts +++ b/src/scenes/jbcBase.ts @@ -78,7 +78,7 @@ export function createBaseSceneSurfaceA(): Scene { nodes: { 'robot': ROBOT, 'jbc_mat_a': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'jbc_mat_a', name: tr('JBC Surface A'), startingOrigin: JBC_MAT_ORIGIN, @@ -147,7 +147,7 @@ export function createBaseSceneSurfaceB(): Scene { nodes: { 'robot': ROBOT, 'jbc_mat_b': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'jbc_mat_b', name: tr('JBC Surface B'), startingOrigin: JBC_MAT_ORIGIN, @@ -211,7 +211,7 @@ export function createCanNode(canNumber: number, canPosition?: Vector3, editable }; return { - type: 'from-template', + type: 'from-jbc-template', templateId: 'can', name: Dict.map(tr('Can %s'), (str: string) => sprintf(str, canNumber)), startingOrigin: origin, diff --git a/src/scenes/jbcSandboxA.ts b/src/scenes/jbcSandboxA.ts index fdfaf939..73363ab6 100644 --- a/src/scenes/jbcSandboxA.ts +++ b/src/scenes/jbcSandboxA.ts @@ -57,7 +57,7 @@ export const JBC_Sandbox_A: Scene = { 'can11': createCanNode(11, undefined, true, false), 'can12': createCanNode(12, undefined, true, false), 'ream1': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'ream', name: tr('Paper Ream 1'), startingOrigin: REAM1_ORIGIN, @@ -66,7 +66,7 @@ export const JBC_Sandbox_A: Scene = { visible: false, }, 'ream2': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'ream', name: tr('Paper Ream 2'), startingOrigin: REAM2_ORIGIN, diff --git a/src/scenes/moonBase.ts b/src/scenes/moonBase.ts new file mode 100644 index 00000000..bed08a2b --- /dev/null +++ b/src/scenes/moonBase.ts @@ -0,0 +1,167 @@ +import { ReferenceFrame, Rotation, Vector3 } from "../unit-math"; +import { Angle, Distance, Mass } from "../util"; +import Node from "../state/State/Scene/Node"; +import Camera from "../state/State/Scene/Camera"; +import Scene from "../state/State/Scene"; +import AbstractRobot from '../AbstractRobot'; +import LocalizedString from '../util/LocalizedString'; +import Author from '../db/Author'; +import { Color } from "../state/State/Scene/Color"; +import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial'; + +import tr from '@i18n'; +import { sprintf } from 'sprintf-js'; +import Dict from '../Dict'; + + +const ROBOT_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(0, 20, 0), + orientation: Rotation.eulerDegrees(0, 0, 0), +}; + +const GROUND_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(0, -0.5, 50), + orientation: Rotation.eulerDegrees(0, 0, 0) +}; + +const START_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(0, 0, 0), + orientation: Rotation.eulerDegrees(0, 90, 0) +}; + +const SKY_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(0, -17.2, 50), + orientation: Rotation.eulerDegrees(90, 0, 0) +}; + +const LIGHT_ORIGIN: ReferenceFrame = { + position: Vector3.meters(0, 40.91, .5), +}; + +const ROBOT: Node.Robot = { + type: 'robot', + name: tr('Robot'), + robotId: 'demobot', + state: AbstractRobot.Stateless.NIL, + visible: true, + startingOrigin: ROBOT_ORIGIN, + origin: ROBOT_ORIGIN +}; + +export function createBaseSceneSurface(): Scene { + return { + name: tr('Base Scene - Moon Surface'), + description: tr('A base scene. Intended to be augmented to create full Moon scenes'), + author: Author.organization('kipr'), + geometry: { + 'moon ground': { + type: 'cylinder', + radius: Distance.feet(25), + height: Distance.centimeters(1), + }, + 'sky': { + type: 'box', + size: { + x: Distance.meters(15), + y: Distance.meters(15), + z: Distance.meters(15), + } + }, + 'start': { + type: 'box', + size: { + x: Distance.feet(2), + y: Distance.centimeters(.1), + z: Distance.feet(2), + } + }, + + }, + nodes: { + 'robot': ROBOT, + 'Moon ground': { + type: 'object', + geometryId: 'moon ground', + name: tr('1.1.1 Ground'), + startingOrigin: GROUND_ORIGIN, + origin: GROUND_ORIGIN, + visible: true, + physics: { + type: 'box', + restitution: 1, + friction: 1, + }, + material: { + type: 'basic', + color: { + type: "texture", + uri: "/static/textures/Moon-2d-Surface.png" + }, + }, + }, + 'start': { + type: 'object', + geometryId: 'start', + name: tr('1.1.6-8 Start Area'), + startingOrigin: START_ORIGIN, + origin: START_ORIGIN, + visible: true, + editable: true, + physics: { + type: 'box', + restitution: 1, + friction: 1, + }, + material: { + type: 'basic', + color: { + type: "texture", + uri: "/static/textures/start_texture_light.png" + }, + }, + }, + 'light0': { + type: 'point-light', + intensity: .25, + name: tr('Light'), + startingOrigin: LIGHT_ORIGIN, + origin: LIGHT_ORIGIN, + visible: true + }, + 'night_sky': { + type: 'object', + name: tr('1.1.2-4 Sky'), + geometryId: 'sky', + visible: true, + startingOrigin: SKY_ORIGIN, + origin: SKY_ORIGIN, + material: { + type: 'basic', + color: { + type: "texture", + uri: "/static/textures/earthrise.png" + }, + }, + } + }, + camera: Camera.arcRotate({ + radius: Distance.meters(5), + target: { + x: Distance.meters(0), + y: Distance.meters(0), + z: Distance.meters(0.05), + }, + position: { + x: Distance.meters(-1), + y: Distance.meters(0.51), + z: Distance.meters(-1.5), + } + }), + gravity: { + x: Distance.meters(0), + y: Distance.meters(-9.8 * .17), + z: Distance.meters(0), + } + }; +} + diff --git a/src/scenes/moonSandbox.ts b/src/scenes/moonSandbox.ts new file mode 100644 index 00000000..8532d9f4 --- /dev/null +++ b/src/scenes/moonSandbox.ts @@ -0,0 +1,334 @@ +// In scenes we build upon the base, and add objects to the scene. +// The objects are set up in the node-templates index.ts file. +// Here we add the objects and their properties to the scene. + +import Scene from "../state/State/Scene"; +import Script from '../state/State/Scene/Script'; +import { ReferenceFrame, Rotation, Vector3 } from "../unit-math"; +import { Distance } from "../util"; +import { Color } from '../state/State/Scene/Color'; +import LocalizedString from '../util/LocalizedString'; + +import { createBaseSceneSurface } from './moonBase'; + +import tr from '@i18n'; + +const rockEvaluation = ` +const setNodeVisible = (nodeId, visible) => scene.setNode(nodeId, { + ...scene.nodes[nodeId], + visible: visible +}); + +// When the pad detects life a green light glows. + +scene.addOnIntersectionListener('meteorite', (type, otherNodeId) => { + console.log('meteorite may have life!', type, otherNodeId); + const visible = type === 'start'; + setNodeVisible('life indicator', visible); + if (visible) alert('You found a meteorite rock! It may have life! Bring this to the container for further study.'); +}, 'sciencepad'); + +scene.addOnIntersectionListener('basalt', (type, otherNodeId) => { + console.log('basalt may have life!', type, otherNodeId); + const visible = type === 'start'; + setNodeVisible('nolife indicator', visible); + if (visible) alert('You found a basalt rock! There does not appear to be life here. Try another rock.'); +}, 'sciencepad'); + +scene.addOnIntersectionListener('anorthosite', (type, otherNodeId) => { + console.log('anorthosite may have life!', type, otherNodeId); + const visible = type === 'start'; + setNodeVisible('nolife indicator', visible); + if (visible) alert('You found a anorthosite rock! There does not appear to be life here. Try another rock.'); +}, 'sciencepad'); + +scene.addOnIntersectionListener('breccia', (type, otherNodeId) => { + console.log('breccia may have life!', type, otherNodeId); + const visible = type === 'start'; + setNodeVisible('nolife indicator', visible); + if (visible) alert('You found a breccia rock! There does not appear to be life here. Try another rock.'); +}, 'sciencepad'); +`; + + +const baseScene = createBaseSceneSurface(); + +const SCIENCEPAD_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(0, 2, 100), + orientation: Rotation.eulerDegrees(0, 90, 0) +}; + +const CONTAINER_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(-60, 0, 100), + scale: { x: 15, y: 15, z: 15 }, + orientation: Rotation.eulerDegrees(0, 180, 0) +}; + +const BOTGUY_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(-50, 0, 30), + scale: { x: 25, y: 25, z: 25 } +}; + +const SOLARPANEL_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(20, 0, 135), + scale: { x: 4, y: 4, z: 4 }, + orientation: Rotation.eulerDegrees(0, 180, 0) +}; + +const WALKWAY_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(50, 9, 65), + scale: { x: 12, y: 12, z: 12 } +}; + +const COMMSTOWER_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(80, 4, 0), + scale: { x: 7, y: 7, z: 7 } +}; + +const HABITAT_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(50, 3.5, 95), + scale: { x: 12, y: 12, z: 12 }, + orientation: Rotation.eulerDegrees(0, 180, 0) +}; + +const RESEARCH_HABITAT_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(50, 3.5, 35), + scale: { x: 12, y: 12, z: 12 }, + orientation: Rotation.eulerDegrees(0, 180, 0) +}; + +const CONTROL_HABITAT_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(50, 3.5, 5), + scale: { x: 12, y: 12, z: 12 }, + orientation: Rotation.eulerDegrees(0, 180, 0) +}; + +const LIFESCIENCE_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(-50, 6, 50.3), +}; + +const RADSCIENCE_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(-50, 6, 40.3), +}; + +const BASALT_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(-30, 1, 61.3), +}; +const ANORTHOSITE_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(-15, 1, 61.3), +}; +const BRECCIA_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(0, 1, 61.3), +}; +const METEORITE_ORIGIN: ReferenceFrame = { + position: Vector3.centimeters(15, 1, 61.3), +}; +export const Moon_Sandbox: Scene = { + ...baseScene, + name: tr('Moon Sandbox'), + description: tr('Lunar sandbox. Currently supports 4 types of rocks. Demo Ready.'), + scripts: { + 'rockEvaluation': Script.ecmaScript('Rock Evaluation Test', rockEvaluation), + }, + geometry: { + ...baseScene.geometry, + 'indicator': { + type: 'cylinder', + radius: Distance.centimeters(3), + height: Distance.centimeters(0.1), + }, + }, + nodes: { + ...baseScene.nodes, + 'robot': { + ...baseScene.nodes['robot'], + editable: true, + }, + 'basalt': { + type: 'from-rock-template', + templateId: 'basalt', + name: tr('Basalt Rock'), + startingOrigin: BASALT_ORIGIN, + origin: BASALT_ORIGIN, + editable: true, + visible: true, + }, + 'anorthosite': { + type: 'from-rock-template', + templateId: 'anorthosite', + name: tr('Anorthosite Rock'), + startingOrigin: ANORTHOSITE_ORIGIN, + origin: ANORTHOSITE_ORIGIN, + editable: true, + visible: true, + }, + 'breccia': { + type: 'from-rock-template', + templateId: 'breccia', + name: tr('Breccia Rock'), + startingOrigin: BRECCIA_ORIGIN, + origin: BRECCIA_ORIGIN, + editable: true, + visible: true, + }, + 'meteorite': { + type: 'from-rock-template', + templateId: 'meteorite', + name: tr('Meteorite Rock'), + startingOrigin: METEORITE_ORIGIN, + origin: METEORITE_ORIGIN, + editable: true, + visible: true, + }, + 'lifescience': { + type: 'from-space-template', + templateId: 'lifescience', + name: tr('Life Science Pack'), + startingOrigin: LIFESCIENCE_ORIGIN, + origin: LIFESCIENCE_ORIGIN, + editable: true, + visible: true, + }, + 'radscience': { + type: 'from-space-template', + templateId: 'radscience', + name: tr('Radiation Science Pack - High'), + startingOrigin: RADSCIENCE_ORIGIN, + origin: RADSCIENCE_ORIGIN, + editable: true, + visible: true, + }, + // 'noradscience': { + // type: 'from-space-template', + // templateId: 'noradscience', + // name: tr('Radiation Science Pack - Low'), + // startingOrigin: RADSCIENCE_ORIGIN, + // origin: RADSCIENCE_ORIGIN, + // editable: true, + // visible: false, + // }, + 'sciencepad': { + type: 'from-space-template', + templateId: 'sciencepad', + name: tr('Science Pad'), + startingOrigin: SCIENCEPAD_ORIGIN, + origin: SCIENCEPAD_ORIGIN, + editable: true, + visible: true, + }, + 'container': { + type: 'from-space-template', + templateId: 'container', + name: tr('Container'), + startingOrigin: CONTAINER_ORIGIN, + origin: CONTAINER_ORIGIN, + editable: true, + visible: true, + material: { + type: 'basic', + color: { + type: "texture", + uri: "Rocks with Possible Life" // default text to display + }, + }, + }, + 'botguy': { + type: 'from-space-template', + templateId: 'botguy', + name: tr('Space Bot Guy'), + startingOrigin: BOTGUY_ORIGIN, + origin: BOTGUY_ORIGIN, + visible: true, + editable: true, + }, + 'solarpanel': { + type: 'from-space-template', + templateId: 'solarpanel', + name: tr('Solar Panel'), + startingOrigin: SOLARPANEL_ORIGIN, + origin: SOLARPANEL_ORIGIN, + visible: true, + editable: true, + }, + 'walkway': { + type: 'from-space-template', + templateId: 'walkway', + name: tr('Walkway'), + startingOrigin: WALKWAY_ORIGIN, + origin: WALKWAY_ORIGIN, + visible: false, + editable: true, + }, + 'commstower': { + type: 'from-space-template', + templateId: 'commstower', + name: tr('Comms Tower'), + startingOrigin: COMMSTOWER_ORIGIN, + origin: COMMSTOWER_ORIGIN, + visible: false, + editable: true, + }, + 'habitat': { + type: 'from-space-template', + templateId: 'habitat', + name: tr('Human Living Habitat'), + startingOrigin: HABITAT_ORIGIN, + origin: HABITAT_ORIGIN, + visible: false, + editable: true, + }, + 'research_habitat': { + type: 'from-space-template', + templateId: 'research_habitat', + name: tr('Human Research Habitat'), + startingOrigin: RESEARCH_HABITAT_ORIGIN, + origin: RESEARCH_HABITAT_ORIGIN, + visible: false, + editable: true, + }, + 'control_habitat': { + type: 'from-space-template', + templateId: 'control_habitat', + name: tr('Human Control/Comms Station Habitat'), + startingOrigin: CONTROL_HABITAT_ORIGIN, + origin: CONTROL_HABITAT_ORIGIN, + visible: false, + editable: true, + }, + 'life indicator': { + type: 'object', + geometryId: 'indicator', + name: tr('Life Indicator Light'), + visible: false, + editable: true, + origin: { + position: Vector3.centimeters(-10, 4, 110) + }, + material: { + type: 'pbr', + emissive: { + type: 'color3', + color: Color.rgb(0, 255, 0), + }, + }, + }, + 'nolife indicator': { + type: 'object', + geometryId: 'indicator', + name: tr('No Life Indicator Light'), + visible: false, + editable: true, + origin: { + position: Vector3.centimeters(10, 4, 110) + }, + material: { + type: 'pbr', + emissive: { + type: 'color3', + color: Color.rgb(255, 0, 0), + }, + }, + }, + } + +}; \ No newline at end of file diff --git a/src/scenes/scriptPlayground.ts b/src/scenes/scriptPlayground.ts index e1decdbe..7d8f7353 100644 --- a/src/scenes/scriptPlayground.ts +++ b/src/scenes/scriptPlayground.ts @@ -118,7 +118,7 @@ export const scriptPlayground: Scene = { 'can11': createCanNode(11, undefined, true, false), 'can12': createCanNode(12, undefined, true, false), 'ream1': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'ream', name: tr('Paper Ream 1'), origin: { @@ -136,7 +136,7 @@ export const scriptPlayground: Scene = { visible: false, }, 'ream2': { - type: 'from-template', + type: 'from-jbc-template', templateId: 'ream', name: tr('Paper Ream 2'), origin: { diff --git a/src/state/State/Scene/Geometry.ts b/src/state/State/Scene/Geometry.ts index b26aea68..0f72c992 100644 --- a/src/state/State/Scene/Geometry.ts +++ b/src/state/State/Scene/Geometry.ts @@ -33,6 +33,9 @@ namespace Geometry { export interface Sphere { type: 'sphere'; radius: Distance; + squash?: number; + stretch?: number; + noise?: number; } export namespace Sphere { diff --git a/src/state/State/Scene/Node.ts b/src/state/State/Scene/Node.ts index acdbc807..80c1eff9 100644 --- a/src/state/State/Scene/Node.ts +++ b/src/state/State/Scene/Node.ts @@ -247,25 +247,25 @@ namespace Node { }; } - export interface FromTemplate extends Base { - type: 'from-template'; + export interface FromJBCTemplate extends Base { + type: 'from-jbc-template'; parentId?: string; templateId: string; } - export namespace FromTemplate { - export const NIL: FromTemplate = { - type: 'from-template', + export namespace FromJBCTemplate { + export const NIL: FromJBCTemplate = { + type: 'from-jbc-template', ...Base.NIL, templateId: '', }; - export const from = (t: T): FromTemplate => ({ + export const from = (t: T): FromJBCTemplate => ({ ...NIL, ...Base.upcast(t) }); - export const diff = (prev: FromTemplate, next: FromTemplate): Patch => { + export const diff = (prev: FromJBCTemplate, next: FromJBCTemplate): Patch => { if (!deepNeq(prev, next)) return Patch.none(prev); return Patch.innerChange(prev, next, { @@ -277,6 +277,73 @@ namespace Node { }; } + export interface FromRockTemplate extends Base { + type: 'from-rock-template'; + parentId?: string; + material?: Material; + templateId: string; + } + + export namespace FromRockTemplate { + export const NIL: FromRockTemplate = { + type: 'from-rock-template', + ...Base.NIL, + templateId: '', + }; + + export const from = (t: T): FromRockTemplate => ({ + ...NIL, + ...Base.upcast(t) + }); + + export const diff = (prev: FromRockTemplate, next: FromRockTemplate): Patch => { + if (!deepNeq(prev, next)) return Patch.none(prev); + + return Patch.innerChange(prev, next, { + type: Patch.none(prev.type), + parentId: Patch.diff(prev.parentId, next.parentId), + templateId: Patch.diff(prev.templateId, next.templateId), + ...Base.partialDiff(prev, next), + }); + }; + } + + export interface FromSpaceTemplate extends Base { + type: 'from-space-template'; + templateId: string; + parentId?: string; + physics?: Physics; + material?: Material; + geometryId?: string; + } + + export namespace FromSpaceTemplate { + export const NIL: FromSpaceTemplate = { + type: 'from-space-template', + ...Base.NIL, + templateId: '', + }; + + export const from = (t: T): FromSpaceTemplate => ({ + ...NIL, + ...Base.upcast(t) + }); + + export const diff = (prev: FromSpaceTemplate, next: FromSpaceTemplate): Patch => { + if (!deepNeq(prev, next)) return Patch.none(prev); + + return Patch.innerChange(prev, next, { + type: Patch.none(prev.type), + parentId: Patch.diff(prev.parentId, next.parentId), + templateId: Patch.diff(prev.templateId, next.templateId), + physics: Patch.diff(prev.physics, next.physics), + material: Material.diff(prev.material, next.material), + geometryId: Patch.diff(prev.geometryId, next.geometryId), + ...Base.partialDiff(prev, next), + }); + }; + } + export interface Robot extends Base { type: 'robot'; robotId: string; @@ -317,12 +384,14 @@ namespace Node { case 'point-light': return PointLight.diff(prev, next as PointLight); case 'spot-light': return SpotLight.diff(prev, next as SpotLight); case 'directional-light': return DirectionalLight.diff(prev, next as DirectionalLight); - case 'from-template': return FromTemplate.diff(prev, next as FromTemplate); + case 'from-jbc-template': return FromJBCTemplate.diff(prev, next as FromJBCTemplate); + case 'from-rock-template': return FromRockTemplate.diff(prev, next as FromRockTemplate); + case 'from-space-template': return FromSpaceTemplate.diff(prev, next as FromSpaceTemplate); case 'robot': return Robot.diff(prev, next as Robot); } }; - export type Type = 'empty' | 'object' | 'point-light' | 'spot-light' | 'directional-light' | 'from-template' | 'robot'; + export type Type = 'empty' | 'object' | 'point-light' | 'spot-light' | 'directional-light' | 'from-jbc-template' | 'from-space-template' | 'from-rock-template' | 'robot' | 'all'; export const transmute = (node: Node, type: Type): Node => { switch (type) { @@ -331,7 +400,9 @@ namespace Node { case 'point-light': return PointLight.from(node); case 'spot-light': return SpotLight.from(node); case 'directional-light': return DirectionalLight.from(node); - case 'from-template': return FromTemplate.from(node); + case 'from-jbc-template': return FromJBCTemplate.from(node); + case 'from-rock-template': return FromRockTemplate.from(node); + case 'from-space-template': return FromSpaceTemplate.from(node); case 'robot': return Robot.from(node); } }; @@ -345,7 +416,9 @@ type Node = ( Node.PointLight | Node.SpotLight | Node.DirectionalLight | - Node.FromTemplate | + Node.FromJBCTemplate | + Node.FromRockTemplate | + Node.FromSpaceTemplate | Node.Robot ); diff --git a/src/state/reducer/scenes.ts b/src/state/reducer/scenes.ts index 228c9433..14724209 100644 --- a/src/state/reducer/scenes.ts +++ b/src/state/reducer/scenes.ts @@ -283,7 +283,9 @@ export type ScenesAction = ( ScenesAction.SetScript ); + const DEFAULT_SCENES: Scenes = { + moonSandbox: Async.loaded({ value: JBC_SCENES.Moon_Sandbox }), jbcSandboxA: Async.loaded({ value: JBC_SCENES.JBC_Sandbox_A }), jbcSandboxB: Async.loaded({ value: JBC_SCENES.JBC_Sandbox_B }), jbc1: Async.loaded({ value: JBC_SCENES.JBC_1 }), diff --git a/static/arm.blend b/static/arm.blend deleted file mode 100644 index 9953591b..00000000 --- a/static/arm.blend +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:680bcd7b444589d2bd61207c2dac4b08d3b65b132a40ea40f151e8ac0741e1a4 -size 14387852 diff --git a/static/arm.blend1 b/static/arm.blend1 deleted file mode 100644 index c780c312..00000000 Binary files a/static/arm.blend1 and /dev/null differ diff --git a/static/Triangular_Background_Compressed.png b/static/backgrounds/Triangular_Background_Compressed.png similarity index 100% rename from static/Triangular_Background_Compressed.png rename to static/backgrounds/Triangular_Background_Compressed.png diff --git a/static/gray-hex-background.png b/static/backgrounds/gray-hex-background.png similarity index 100% rename from static/gray-hex-background.png rename to static/backgrounds/gray-hex-background.png diff --git a/static/red-geometric.png b/static/backgrounds/red-geometric.png similarity index 100% rename from static/red-geometric.png rename to static/backgrounds/red-geometric.png diff --git a/static/cayley_interior_1k.hdr b/static/cayley_interior_1k.hdr deleted file mode 100644 index 58059201..00000000 Binary files a/static/cayley_interior_1k.hdr and /dev/null differ diff --git a/static/chassis.blend b/static/chassis.blend deleted file mode 100644 index fcc78e30..00000000 --- a/static/chassis.blend +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e1783b7b501ae07cc19956a95d2b4115feb7a2c28a4bf1fa86b8740104727bd3 -size 42695836 diff --git a/static/chassis.blend1 b/static/chassis.blend1 deleted file mode 100644 index db8884d5..00000000 Binary files a/static/chassis.blend1 and /dev/null differ diff --git a/static/claw.blend b/static/claw.blend deleted file mode 100644 index e53a4c12..00000000 --- a/static/claw.blend +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:75f228951cc3926a1cfa8f2cdfcc4fc280e001a407ab55938d981d1fe04a3784 -size 9057012 diff --git a/static/Can_Ream.png b/static/example_images/Can_Ream.png similarity index 100% rename from static/Can_Ream.png rename to static/example_images/Can_Ream.png diff --git a/static/Simulator-Robot-Closeup.png b/static/example_images/Simulator-Robot-Closeup.png similarity index 100% rename from static/Simulator-Robot-Closeup.png rename to static/example_images/Simulator-Robot-Closeup.png diff --git a/static/Simulator_Full_View.png b/static/example_images/Simulator_Full_View.png similarity index 100% rename from static/Simulator_Full_View.png rename to static/example_images/Simulator_Full_View.png diff --git a/static/Botguy-Picture-Small.png b/static/icons/Botguy-Picture-Small.png similarity index 100% rename from static/Botguy-Picture-Small.png rename to static/icons/Botguy-Picture-Small.png diff --git a/static/KIPR-Logo-bk.jpg b/static/icons/KIPR-Logo-bk.jpg similarity index 100% rename from static/KIPR-Logo-bk.jpg rename to static/icons/KIPR-Logo-bk.jpg diff --git a/static/Laptop_Icon_Sunscreen.png b/static/icons/Laptop_Icon_Sunscreen.png similarity index 100% rename from static/Laptop_Icon_Sunscreen.png rename to static/icons/Laptop_Icon_Sunscreen.png diff --git a/static/apple-touch-icon.png b/static/icons/apple-touch-icon.png similarity index 100% rename from static/apple-touch-icon.png rename to static/icons/apple-touch-icon.png diff --git a/static/favicon-16x16.png b/static/icons/favicon-16x16.png similarity index 100% rename from static/favicon-16x16.png rename to static/icons/favicon-16x16.png diff --git a/static/favicon-32x32.png b/static/icons/favicon-32x32.png similarity index 100% rename from static/favicon-32x32.png rename to static/icons/favicon-32x32.png diff --git a/static/google_signin_dark_normal.png b/static/icons/google_signin_dark_normal.png similarity index 100% rename from static/google_signin_dark_normal.png rename to static/icons/google_signin_dark_normal.png diff --git a/static/arena.glb b/static/object_binaries/arena.glb similarity index 100% rename from static/arena.glb rename to static/object_binaries/arena.glb diff --git a/static/arm.glb b/static/object_binaries/arm.glb similarity index 100% rename from static/arm.glb rename to static/object_binaries/arm.glb diff --git a/static/object_binaries/botguy.glb b/static/object_binaries/botguy.glb new file mode 100644 index 00000000..a07689dd --- /dev/null +++ b/static/object_binaries/botguy.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74af0b5a0216e0f4f288713d58f2e7ba148c7e04792fa4917317427ebbb3e5d9 +size 89364 diff --git a/static/chassis.glb b/static/object_binaries/chassis.glb similarity index 100% rename from static/chassis.glb rename to static/object_binaries/chassis.glb diff --git a/static/claw.glb b/static/object_binaries/claw.glb similarity index 100% rename from static/claw.glb rename to static/object_binaries/claw.glb diff --git a/static/object_binaries/comm_tower.glb b/static/object_binaries/comm_tower.glb new file mode 100644 index 00000000..bbf9ba9d --- /dev/null +++ b/static/object_binaries/comm_tower.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64e2b0b52f3a23db62fcbb40655e7a34ff46df64a2c1a3fad2667ff7be6a4f12 +size 70376 diff --git a/static/object_binaries/comm_tower_lowered.glb b/static/object_binaries/comm_tower_lowered.glb new file mode 100644 index 00000000..fc6630fa --- /dev/null +++ b/static/object_binaries/comm_tower_lowered.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a14482f361041f6573a90d53a23c492a5ed41a3f75cd4c47089a84f9136be219 +size 70416 diff --git a/static/object_binaries/container_with_lid.glb b/static/object_binaries/container_with_lid.glb new file mode 100644 index 00000000..bc754665 --- /dev/null +++ b/static/object_binaries/container_with_lid.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a977e2f268040eb1653c5f80d7ee8f14027c4298acfa39b6fee3a7af07f5d3f +size 4536 diff --git a/static/demobot_v6.glb b/static/object_binaries/demobot_v6.glb similarity index 100% rename from static/demobot_v6.glb rename to static/object_binaries/demobot_v6.glb diff --git a/static/object_binaries/hab_comms.glb b/static/object_binaries/hab_comms.glb new file mode 100644 index 00000000..dcf364fa --- /dev/null +++ b/static/object_binaries/hab_comms.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:857d37333f0fc9992d6cbc4c9a642f820f2d3f7e0dc462de926e73f67d63e700 +size 154088 diff --git a/static/object_binaries/hab_living.glb b/static/object_binaries/hab_living.glb new file mode 100644 index 00000000..430276f6 --- /dev/null +++ b/static/object_binaries/hab_living.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fcd6213e109b5a307885be3f5de27ad40740bb7164400fb42374bce5dcf7526a +size 142992 diff --git a/static/object_binaries/hab_research.glb b/static/object_binaries/hab_research.glb new file mode 100644 index 00000000..1fd3a6d0 --- /dev/null +++ b/static/object_binaries/hab_research.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3e6ed605b7357e0024332f2eb8d80ee1981639fbd0c7043023f81663eb473be +size 278948 diff --git a/static/object_binaries/habitat3.glb b/static/object_binaries/habitat3.glb new file mode 100644 index 00000000..430276f6 --- /dev/null +++ b/static/object_binaries/habitat3.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fcd6213e109b5a307885be3f5de27ad40740bb7164400fb42374bce5dcf7526a +size 142992 diff --git a/static/object_binaries/habitat_research.glb b/static/object_binaries/habitat_research.glb new file mode 100644 index 00000000..1fd3a6d0 --- /dev/null +++ b/static/object_binaries/habitat_research.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3e6ed605b7357e0024332f2eb8d80ee1981639fbd0c7043023f81663eb473be +size 278948 diff --git a/static/jbcMatA.glb b/static/object_binaries/jbcMatA.glb similarity index 100% rename from static/jbcMatA.glb rename to static/object_binaries/jbcMatA.glb diff --git a/static/jbcMatB.glb b/static/object_binaries/jbcMatB.glb similarity index 100% rename from static/jbcMatB.glb rename to static/object_binaries/jbcMatB.glb diff --git a/static/object_binaries/new_walkway.glb b/static/object_binaries/new_walkway.glb new file mode 100644 index 00000000..e6931c9d --- /dev/null +++ b/static/object_binaries/new_walkway.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:123567d5deaa341f310d0465665e5330bb94a1a803ea586ece585e0f1d8d8721 +size 91484 diff --git a/static/object_binaries/solar_panel2.glb b/static/object_binaries/solar_panel2.glb new file mode 100644 index 00000000..6eaf44f7 --- /dev/null +++ b/static/object_binaries/solar_panel2.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aad47fe7de4ce9caee4948c8c98a7d3d1665636aa1e278da1dae883c780636ff +size 161488 diff --git a/static/suzanne.glb b/static/object_binaries/suzanne.glb similarity index 100% rename from static/suzanne.glb rename to static/object_binaries/suzanne.glb diff --git a/static/table.glb b/static/object_binaries/table.glb similarity index 100% rename from static/table.glb rename to static/object_binaries/table.glb diff --git a/static/wheel.glb b/static/object_binaries/wheel.glb similarity index 100% rename from static/wheel.glb rename to static/object_binaries/wheel.glb diff --git a/static/Can Texture.png b/static/textures/Can_Texture.png similarity index 100% rename from static/Can Texture.png rename to static/textures/Can_Texture.png diff --git a/static/textures/Moon-2d-Surface.png b/static/textures/Moon-2d-Surface.png new file mode 100644 index 00000000..4cd8ab74 Binary files /dev/null and b/static/textures/Moon-2d-Surface.png differ diff --git a/static/textures/NightSkybox.png b/static/textures/NightSkybox.png new file mode 100644 index 00000000..05bc2712 Binary files /dev/null and b/static/textures/NightSkybox.png differ diff --git a/static/textures/earthrise.png b/static/textures/earthrise.png new file mode 100644 index 00000000..36075030 Binary files /dev/null and b/static/textures/earthrise.png differ diff --git a/static/textures/hab5.png b/static/textures/hab5.png new file mode 100644 index 00000000..efc2b9bd Binary files /dev/null and b/static/textures/hab5.png differ diff --git a/static/Surface-A.png b/static/textures/jbcmat/Surface-A.png similarity index 100% rename from static/Surface-A.png rename to static/textures/jbcmat/Surface-A.png diff --git a/static/Surface-B.png b/static/textures/jbcmat/Surface-B.png similarity index 100% rename from static/Surface-B.png rename to static/textures/jbcmat/Surface-B.png diff --git a/static/textures/rocks/anorthosite_texture.png b/static/textures/rocks/anorthosite_texture.png new file mode 100644 index 00000000..b40ab4fa Binary files /dev/null and b/static/textures/rocks/anorthosite_texture.png differ diff --git a/static/textures/rocks/anorthosite_texture_m.png b/static/textures/rocks/anorthosite_texture_m.png new file mode 100644 index 00000000..6c90509d Binary files /dev/null and b/static/textures/rocks/anorthosite_texture_m.png differ diff --git a/static/textures/rocks/anorthosite_texture_w.png b/static/textures/rocks/anorthosite_texture_w.png new file mode 100644 index 00000000..d1da449f Binary files /dev/null and b/static/textures/rocks/anorthosite_texture_w.png differ diff --git a/static/textures/rocks/anorthosite_texture_wn.png b/static/textures/rocks/anorthosite_texture_wn.png new file mode 100644 index 00000000..67df2012 Binary files /dev/null and b/static/textures/rocks/anorthosite_texture_wn.png differ diff --git a/static/textures/rocks/basalt_texture.png b/static/textures/rocks/basalt_texture.png new file mode 100644 index 00000000..687422b5 Binary files /dev/null and b/static/textures/rocks/basalt_texture.png differ diff --git a/static/textures/rocks/basalt_texture2.png b/static/textures/rocks/basalt_texture2.png new file mode 100644 index 00000000..128a460b Binary files /dev/null and b/static/textures/rocks/basalt_texture2.png differ diff --git a/static/textures/rocks/basalt_texture_m.png b/static/textures/rocks/basalt_texture_m.png new file mode 100644 index 00000000..a38b445c Binary files /dev/null and b/static/textures/rocks/basalt_texture_m.png differ diff --git a/static/textures/rocks/basalt_texture_w.png b/static/textures/rocks/basalt_texture_w.png new file mode 100644 index 00000000..b1ee123d Binary files /dev/null and b/static/textures/rocks/basalt_texture_w.png differ diff --git a/static/textures/rocks/basalt_texture_wn.png b/static/textures/rocks/basalt_texture_wn.png new file mode 100644 index 00000000..6d710760 Binary files /dev/null and b/static/textures/rocks/basalt_texture_wn.png differ diff --git a/static/textures/rocks/breccia_texture.png b/static/textures/rocks/breccia_texture.png new file mode 100644 index 00000000..8391a961 Binary files /dev/null and b/static/textures/rocks/breccia_texture.png differ diff --git a/static/textures/rocks/breccia_texture_m.png b/static/textures/rocks/breccia_texture_m.png new file mode 100644 index 00000000..74c77e18 Binary files /dev/null and b/static/textures/rocks/breccia_texture_m.png differ diff --git a/static/textures/rocks/breccia_texture_w.png b/static/textures/rocks/breccia_texture_w.png new file mode 100644 index 00000000..3a6c86b4 Binary files /dev/null and b/static/textures/rocks/breccia_texture_w.png differ diff --git a/static/textures/rocks/breccia_texture_wn.png b/static/textures/rocks/breccia_texture_wn.png new file mode 100644 index 00000000..0e326ff2 Binary files /dev/null and b/static/textures/rocks/breccia_texture_wn.png differ diff --git a/static/textures/rocks/meteorite_texture.png b/static/textures/rocks/meteorite_texture.png new file mode 100644 index 00000000..33b5be37 Binary files /dev/null and b/static/textures/rocks/meteorite_texture.png differ diff --git a/static/textures/rocks/meteorite_texture_m.png b/static/textures/rocks/meteorite_texture_m.png new file mode 100644 index 00000000..62e12a31 Binary files /dev/null and b/static/textures/rocks/meteorite_texture_m.png differ diff --git a/static/textures/rocks/meteorite_texture_w.png b/static/textures/rocks/meteorite_texture_w.png new file mode 100644 index 00000000..63f2484c Binary files /dev/null and b/static/textures/rocks/meteorite_texture_w.png differ diff --git a/static/textures/rocks/meteorite_texture_wn.png b/static/textures/rocks/meteorite_texture_wn.png new file mode 100644 index 00000000..3749c923 Binary files /dev/null and b/static/textures/rocks/meteorite_texture_wn.png differ diff --git a/static/textures/science_pad.png b/static/textures/science_pad.png new file mode 100644 index 00000000..cd69b8c9 Binary files /dev/null and b/static/textures/science_pad.png differ diff --git a/static/textures/science_pad2.png b/static/textures/science_pad2.png new file mode 100644 index 00000000..2d66de00 Binary files /dev/null and b/static/textures/science_pad2.png differ diff --git a/static/textures/sciencepack/life_science_pack.png b/static/textures/sciencepack/life_science_pack.png new file mode 100644 index 00000000..5ec767fb Binary files /dev/null and b/static/textures/sciencepack/life_science_pack.png differ diff --git a/static/textures/sciencepack/no_rad_science_pack.png b/static/textures/sciencepack/no_rad_science_pack.png new file mode 100644 index 00000000..8d42f344 Binary files /dev/null and b/static/textures/sciencepack/no_rad_science_pack.png differ diff --git a/static/textures/sciencepack/rad_science_pack.png b/static/textures/sciencepack/rad_science_pack.png new file mode 100644 index 00000000..df89f8f7 Binary files /dev/null and b/static/textures/sciencepack/rad_science_pack.png differ diff --git a/static/textures/solar.png b/static/textures/solar.png new file mode 100644 index 00000000..ac598eb1 Binary files /dev/null and b/static/textures/solar.png differ diff --git a/static/textures/start_texture_dark.png b/static/textures/start_texture_dark.png new file mode 100644 index 00000000..dd8ed5f7 Binary files /dev/null and b/static/textures/start_texture_dark.png differ diff --git a/static/textures/start_texture_light.png b/static/textures/start_texture_light.png new file mode 100644 index 00000000..e3a69fa9 Binary files /dev/null and b/static/textures/start_texture_light.png differ diff --git a/static/textures/tower/tall_tower_texture.png b/static/textures/tower/tall_tower_texture.png new file mode 100644 index 00000000..9b69aa54 Binary files /dev/null and b/static/textures/tower/tall_tower_texture.png differ diff --git a/static/textures/tower/tower_texture.png b/static/textures/tower/tower_texture.png new file mode 100644 index 00000000..acf542c5 Binary files /dev/null and b/static/textures/tower/tower_texture.png differ diff --git a/test/util/Patch.spec.ts b/test/util/Patch.spec.ts index 826d9402..3123eba1 100644 --- a/test/util/Patch.spec.ts +++ b/test/util/Patch.spec.ts @@ -43,7 +43,7 @@ const SCENE_B: Scene = { name: { [LocalizedString.EN_US]: 'Node 0' }, }, '1': { - type: 'from-template', + type: 'from-jbc-template', name: { [LocalizedString.EN_US]: 'Node 1' }, templateId: 'template', }, diff --git a/yarn.lock b/yarn.lock index 2dc3720d..b56689f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2621,15 +2621,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001219: - version "1.0.30001243" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001243.tgz#d9250155c91e872186671c523f3ae50cfc94a3aa" - integrity sha512-vNxw9mkTBtkmLFnJRv/2rhs1yufpDfCkBZexG3Y0xdOH2Z/eE/85E4Dl5j1YUN34nZVsSp6vVRFQRrez9wJMRA== - -caniuse-lite@^1.0.30001449: - version "1.0.30001458" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz#871e35866b4654a7d25eccca86864f411825540c" - integrity sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w== +caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001449: + version "1.0.30001505" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001505.tgz" + integrity sha512-jaAOR5zVtxHfL0NjZyflVTtXm3D3J9P15zSJ7HmQF8dSKGA6tqzQq+0ZI3xkjyQj46I4/M0K2GbMpcAFOcbr3A== caw@^2.0.0, caw@^2.0.1: version "2.0.1"