phetsims / buoyancy

"Buoyancy" is an educational simulation in HTML5, by PhET Interactive Simulations.
GNU General Public License v3.0
2 stars 2 forks source link

Add “Depth Lines” control #117

Closed DianaTavares closed 1 month ago

DianaTavares commented 2 months ago

A new checkbox for Buoyancy and Buoynacy: Basics. The checkbox will be in the forces panel, below "Forces", like the next mockup:

For Buoynacy: Basics and Intro screen in Buoynacy image

For the rest of the screens that have vector scale: image

In Buoynacy, the screens Shapes and Applications DON'T INCLUDE THIS CONTROL.

Once the user selects this checkbox, 4 horizontal lines (white or black, depending on the color of the block) will appear in the blocks in the play area, dividing the block into 5 equal divisions.

image

zepumph commented 1 month ago

@samreid and I would like to start sometime around https://github.com/phetsims/density-buoyancy-common/blob/c7f6f0c3ce4ccfbf22c73be5f91cf403bed654e3/js/common/view/MassView.ts#L62-L68.

zepumph commented 1 month ago

Man. I got pretty thwarted today. I couldn't get anything to draw onto a cuboid. I was able to add a child to the mass tag label, but not to create another one. I'm going to get another pass on Monday.

```diff Subject: [PATCH] update doc, https://github.com/phetsims/chipper/issues/1435 --- Index: js/common/view/CuboidView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/CuboidView.ts b/js/common/view/CuboidView.ts --- a/js/common/view/CuboidView.ts (revision a01d10f2a7722132b7bc7178550cbc49d1e75e67) +++ b/js/common/view/CuboidView.ts (date 1712959138446) @@ -14,6 +14,10 @@ import Bounds3 from '../../../../dot/js/Bounds3.js'; import { TAG_OFFSET } from './MassTagView.js'; import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; +import { Circle, Path } from '../../../../scenery/js/imports.js'; +import Shape from '../../../../kite/js/Shape.js'; +import TextureQuad from '../../../../mobius/js/TextureQuad.js'; +import LabelTexture from './LabelTexture.js'; // constants const numElements = 18 * 3; @@ -57,6 +61,50 @@ cuboidGeometry.computeBoundingSphere(); }; this.cuboid.sizeProperty.lazyLink( this.updateListener ); + + // setTimeout( () => { + // + const position = Vector3.fromStateObject( this.position ); + const leftTop = modelToViewPoint( position.add( new Vector3( size.left, size.top, 0 ) ) ); + const left = leftTop.x; + const top = leftTop.y; + const rightBottom = modelToViewPoint( position.add( new Vector3( size.right, size.bottom, 0 ) ) ); + const right = rightBottom.x; + const bottom = rightBottom.y; +// debugger; + + // const hi = 100; + // const line = new Path( new Shape().moveTo( left, top ).lineTo( right, bottom ), { + // stroke: 'black', + // lineWidth: 3 + // } ); + const hi = 10; + const line = new Path( new Shape().moveTo( 0, 0 ).lineTo( size.left * hi, size.centerY * hi ).lineTo( size.right * hi, size.centerY * hi ), { + stroke: 'black', + lineWidth: 3, + scale: 10 + } ); + + const hi = new Circle( 100, { fill: 'red' } ); + const texture = new LabelTexture( hi ); + const tagWidth = texture._width; + const tagHeight = texture._height; + const quad = new TextureQuad( texture, 30, 30, { + depthTest: true + } ); + + const tagOffsetPropertyListener = ( offset: Vector3 ) => { + // Increase the z dimension just slightly to make sure it is always on top of the mass. + quad.position.set( offset.x, offset.y, offset.z + 0.0005 ); + }; + this.tagOffsetProperty.link( tagOffsetPropertyListener ); + quad.visible = true; + debugger; + + quad.renderOrder = 1; + this.add( quad ); + + // }, 1000 ); } /**
zepumph commented 1 month ago

maybe instead it will be best and easiest to handle it in a scenery layer like for force vectors, mass labels, and the scale force readout. See ScaleReadoutNode for example.

samreid commented 1 month ago
```diff Subject: [PATCH] update doc, https://github.com/phetsims/chipper/issues/1435 --- Index: js/common/view/MassView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/MassView.ts b/js/common/view/MassView.ts --- a/js/common/view/MassView.ts (revision a01d10f2a7722132b7bc7178550cbc49d1e75e67) +++ b/js/common/view/MassView.ts (date 1713204703656) @@ -62,7 +62,12 @@ if ( mass.tag !== MassTag.NONE ) { this.massTagView = new MassTagView( mass, this.tagOffsetProperty ); - this.add( this.massTagView ); + // this.add( this.massTagView ); + + this.add( new MassTagView( mass, this.tagOffsetProperty ) ); + + + } this.positionListener = () => { Index: js/common/view/DensityBuoyancyScreenView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/DensityBuoyancyScreenView.ts b/js/common/view/DensityBuoyancyScreenView.ts --- a/js/common/view/DensityBuoyancyScreenView.ts (revision a01d10f2a7722132b7bc7178550cbc49d1e75e67) +++ b/js/common/view/DensityBuoyancyScreenView.ts (date 1713204302438) @@ -26,7 +26,7 @@ import optionize from '../../../../phet-core/js/optionize.js'; import PhetFont from '../../../../scenery-phet/js/PhetFont.js'; import ResetAllButton from '../../../../scenery-phet/js/buttons/ResetAllButton.js'; -import { AlignBox, animatedPanZoomSingleton, Image, LinearGradient, Mouse, Node, Pointer, Rectangle, SceneryEvent, Text, TInputListener } from '../../../../scenery/js/imports.js'; +import { AlignBox, animatedPanZoomSingleton, Image, Line, LinearGradient, Mouse, Node, Pointer, Rectangle, SceneryEvent, Text, TInputListener, VBox } from '../../../../scenery/js/imports.js'; import Checkbox from '../../../../sun/js/Checkbox.js'; import EventType from '../../../../tandem/js/EventType.js'; import Tandem from '../../../../tandem/js/Tandem.js'; @@ -94,14 +94,19 @@ public readonly sceneNode: ThreeIsometricNode; + // TODO: move these to another file private readonly scaleReadoutLayer: Node; private readonly massLabelLayer: Node; + private readonly linesLayer: Node; private readonly forceDiagramLayer: Node; + // private readonly labelLayer:Node; + // private readonly massDecorationLayer: Node; private readonly massViews: MassView[]; private readonly scaleReadoutNodes: ScaleReadoutNode[]; private readonly forceDiagramNodes: ForceDiagramNode[]; private readonly massLabelNodes: MassLabelNode[]; + private readonly linesNodes: Node[] = []; private readonly startDragAction: PhetioAction<[ Mass, Vector2 ]>; private readonly updateDragAction: PhetioAction<[ Mass, Vector2 ]>; @@ -168,6 +173,9 @@ this.massLabelLayer = new Node(); this.addChild( this.massLabelLayer ); + this.linesLayer = new Node(); + this.addChild( this.linesLayer ); + this.forceDiagramLayer = new Node(); this.addChild( this.forceDiagramLayer ); @@ -659,6 +667,22 @@ this.scaleReadoutNodes.push( scaleReadoutNode ); } else { + + // const myMassTagView = new Node(); + + const lineGridNode = new VBox( { + spacing: 25, + children: [ + new Line( 0, 0, 100, 0, { lineWidth: 2, stroke: 'black' } ), + new Line( 0, 0, 100, 0, { lineWidth: 2, stroke: 'black' } ), + new Line( 0, 0, 100, 0, { lineWidth: 2, stroke: 'black' } ), + new Line( 0, 0, 100, 0, { lineWidth: 2, stroke: 'black' } ) + ] + } ); + lineGridNode.mass = mass; + this.linesLayer.addChild( lineGridNode ); + this.linesNodes.push( lineGridNode ); + const forceDiagramNode = new ForceDiagramNode( mass, model.showGravityForceProperty, @@ -891,6 +915,13 @@ massLabelNode.translation = modelPoint.plus( offsetPoint ); } ); + this.linesNodes.forEach( lineGridNode => { + const mass = lineGridNode.mass; + const modelPoint = this.modelToViewPoint( mass.matrix.translation.toVector3().plus( mass.massLabelOffsetProperty.value ) ); + const offsetPoint = scratchVector2.setXY( 0, lineGridNode.height ).componentMultiply( mass.massLabelOffsetOrientationProperty.value ); + lineGridNode.translation = modelPoint.plus( offsetPoint ); + } ); + this.debugView && this.debugView.step( dt ); }
zepumph commented 1 month ago

@samreid and I, after discussion. Want to proceed with the "scenery layers" strategy instead of the texture-related rendering into three. MassTagView may also be a good candidate for converting over to this layer's based strategy (could be simpler and faster).

zepumph commented 1 month ago

First pass

```diff Subject: [PATCH] add TODO --- Index: js/common/view/CuboidView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/CuboidView.ts b/js/common/view/CuboidView.ts --- a/js/common/view/CuboidView.ts (revision 85fa629d82585e507a06dcf10033b1cfe7d43b06) +++ b/js/common/view/CuboidView.ts (date 1713208662182) @@ -14,17 +14,23 @@ import Bounds3 from '../../../../dot/js/Bounds3.js'; import { TAG_OFFSET } from './MassTagView.js'; import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; +import { MassDecorationLayer } from './DensityBuoyancyScreenView.js'; +import Vector2 from '../../../../dot/js/Vector2.js'; +import { Line, VBox,Node } from '../../../../scenery/js/imports.js'; // constants const numElements = 18 * 3; +const scratchVector2 = new Vector2( 0, 0 ); export default class CuboidView extends MassView { public readonly cuboid: Cuboid; private readonly cuboidGeometry: THREE.BufferGeometry; private readonly updateListener: ( size: Bounds3 ) => void; + private readonly lineGridNode: Node; - public constructor( cuboid: Cuboid, modelToViewPoint: ModelPoint3ToViewPoint2, dragBoundsProperty: TReadOnlyProperty ) { + public constructor( cuboid: Cuboid, modelToViewPoint: ModelPoint3ToViewPoint2, + dragBoundsProperty: TReadOnlyProperty ) { const size = cuboid.sizeProperty.value; const positionArray = new Float32Array( numElements * 3 ); @@ -57,6 +63,33 @@ cuboidGeometry.computeBoundingSphere(); }; this.cuboid.sizeProperty.lazyLink( this.updateListener ); + + + // ////// + this.lineGridNode = new VBox( { + spacing: 25, + children: [ + new Line( 0, 0, 100, 0, { lineWidth: 2, stroke: 'black' } ), + new Line( 0, 0, 100, 0, { lineWidth: 2, stroke: 'black' } ), + new Line( 0, 0, 100, 0, { lineWidth: 2, stroke: 'black' } ), + new Line( 0, 0, 100, 0, { lineWidth: 2, stroke: 'black' } ) + ] + } ); + this.mass.transformedEmitter.addListener( () => { + const modelPoint = modelToViewPoint( cuboid.matrix.translation.toVector3().plus( cuboid.massLabelOffsetProperty.value ) ); + const offsetPoint = scratchVector2.setXY( 0, this.lineGridNode.height ).componentMultiply( cuboid.massLabelOffsetOrientationProperty.value ); + this.lineGridNode.translation = modelPoint.plus( offsetPoint ); + + } ); + } + + public override decorate( layer: MassDecorationLayer ): void { + + layer.addChild( this.lineGridNode ); + this.disposeEmitter.addListener( () => { + layer.removeChild( this.lineGridNode ); + } ); + } /** Index: js/common/view/MassView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/MassView.ts b/js/common/view/MassView.ts --- a/js/common/view/MassView.ts (revision 85fa629d82585e507a06dcf10033b1cfe7d43b06) +++ b/js/common/view/MassView.ts (date 1713208662191) @@ -25,13 +25,23 @@ import MassTag from '../model/MassTag.js'; import grabSoundPlayer from '../../../../tambo/js/shared-sound-players/grabSoundPlayer.js'; import releaseSoundPlayer from '../../../../tambo/js/shared-sound-players/releaseSoundPlayer.js'; +import { MassDecorationLayer } from './DensityBuoyancyScreenView.js'; +import Disposable from '../../../../axon/js/Disposable.js'; +import { TReadOnlyEmitter } from '../../../../axon/js/TEmitter.js'; export type ModelPoint3ToViewPoint2 = ( point: Vector3 ) => Vector2; const INVERT_Y_TRANSFORM = ModelViewTransform2.createSinglePointScaleInvertedYMapping( Vector2.ZERO, Vector2.ZERO, 1 ); +// TODO: It would be clearer if the class that extends "Mesh" was named as such, and composed in the class export default abstract class MassView extends THREE.Mesh { + + // TODO: once we change the supertype to compose, please extend Disposable + private disposable = new Disposable(); + public readonly disposeEmitter: TReadOnlyEmitter; + + public readonly mass: Mass; public materialView: MaterialView; private readonly materialListener: ( material: Material ) => void; @@ -42,11 +52,13 @@ public readonly focusablePath: Path | null; - protected constructor( mass: Mass, initialGeometry: THREE.BufferGeometry, modelToViewPoint: ModelPoint3ToViewPoint2, + protected constructor( mass: Mass, initialGeometry: THREE.BufferGeometry, + protected readonly modelToViewPoint: ModelPoint3ToViewPoint2, dragBoundsProperty: TReadOnlyProperty ) { const materialView = DensityMaterials.getMaterialView( mass.materialProperty.value ); super( initialGeometry, materialView.material ); + this.disposeEmitter = this.disposable.disposeEmitter; this.mass = mass; this.materialView = materialView; @@ -155,6 +167,10 @@ return this.massTagView ? this.massTagView.tagHeight : null; } + public decorate( decorationLayer: MassDecorationLayer ): void { + // TODO: at some point will have force vectors? No. It will be in the subtype called "ExperimentalMassView extends MassView. + } + /** * Releases references. */ @@ -168,6 +184,7 @@ this.massTagView && this.massTagView.dispose(); + this.disposable.dispose(); // @ts-expect-error super.dispose && super.dispose(); } Index: js/common/view/DensityBuoyancyScreenView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/DensityBuoyancyScreenView.ts b/js/common/view/DensityBuoyancyScreenView.ts --- a/js/common/view/DensityBuoyancyScreenView.ts (revision 85fa629d82585e507a06dcf10033b1cfe7d43b06) +++ b/js/common/view/DensityBuoyancyScreenView.ts (date 1713207649404) @@ -80,6 +80,10 @@ export type DensityBuoyancyScreenViewOptions = SelfOptions & ScreenViewOptions; +export class MassDecorationLayer extends Node { + public readonly depthLinesLayer = new Node(); +} + export default class DensityBuoyancyScreenView extends ScreenView { protected readonly model: Model; @@ -94,6 +98,7 @@ public readonly sceneNode: ThreeIsometricNode; + private readonly massDecorationLayer: MassDecorationLayer = new MassDecorationLayer(); private readonly scaleReadoutLayer: Node; private readonly massLabelLayer: Node; private readonly forceDiagramLayer: Node; @@ -162,6 +167,8 @@ } ); this.addChild( this.sceneNode ); + this.addChild( this.massDecorationLayer ); + this.scaleReadoutLayer = new Node(); this.addChild( this.scaleReadoutLayer ); @@ -648,6 +655,7 @@ this.sceneNode.stage.threeScene.add( massView ); this.massViews.push( massView ); massView.focusablePath && this.sceneNode.backgroundEventTarget.addChild( massView.focusablePath ); + massView.decorate( this.massDecorationLayer ); if ( massView instanceof ScaleView ) {
samreid commented 1 month ago
```diff Subject: [PATCH] add TODO --- Index: js/common/view/MassView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/MassView.ts b/js/common/view/MassView.ts --- a/js/common/view/MassView.ts (revision a01d10f2a7722132b7bc7178550cbc49d1e75e67) +++ b/js/common/view/MassView.ts (date 1713209096762) @@ -25,13 +25,21 @@ import MassTag from '../model/MassTag.js'; import grabSoundPlayer from '../../../../tambo/js/shared-sound-players/grabSoundPlayer.js'; import releaseSoundPlayer from '../../../../tambo/js/shared-sound-players/releaseSoundPlayer.js'; +import { MassDecorationLayer } from './DensityBuoyancyScreenView.js'; +import Disposable from '../../../../axon/js/Disposable.js'; +import { TReadOnlyEmitter } from '../../../../axon/js/TEmitter.js'; export type ModelPoint3ToViewPoint2 = ( point: Vector3 ) => Vector2; const INVERT_Y_TRANSFORM = ModelViewTransform2.createSinglePointScaleInvertedYMapping( Vector2.ZERO, Vector2.ZERO, 1 ); +// TODO: It would be clearer if the class that extends "Mesh" was named as such, and composed in the class export default abstract class MassView extends THREE.Mesh { + // TODO: once we change the supertype to compose, please extend Disposable + private disposable = new Disposable(); + public readonly disposeEmitter: TReadOnlyEmitter; + public readonly mass: Mass; public materialView: MaterialView; private readonly materialListener: ( material: Material ) => void; @@ -42,11 +50,13 @@ public readonly focusablePath: Path | null; - protected constructor( mass: Mass, initialGeometry: THREE.BufferGeometry, modelToViewPoint: ModelPoint3ToViewPoint2, + protected constructor( mass: Mass, initialGeometry: THREE.BufferGeometry, + protected readonly modelToViewPoint: ModelPoint3ToViewPoint2, dragBoundsProperty: TReadOnlyProperty ) { const materialView = DensityMaterials.getMaterialView( mass.materialProperty.value ); super( initialGeometry, materialView.material ); + this.disposeEmitter = this.disposable.disposeEmitter; this.mass = mass; this.materialView = materialView; @@ -155,6 +165,10 @@ return this.massTagView ? this.massTagView.tagHeight : null; } + public decorate( decorationLayer: MassDecorationLayer ): void { + // TODO: at some point will have force vectors? No. It will be in the subtype called "ExperimentalMassView extends MassView. + } + /** * Releases references. */ @@ -168,6 +182,7 @@ this.massTagView && this.massTagView.dispose(); + this.disposable.dispose(); // @ts-expect-error super.dispose && super.dispose(); } Index: js/common/view/DensityBuoyancyScreenView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/DensityBuoyancyScreenView.ts b/js/common/view/DensityBuoyancyScreenView.ts --- a/js/common/view/DensityBuoyancyScreenView.ts (revision a01d10f2a7722132b7bc7178550cbc49d1e75e67) +++ b/js/common/view/DensityBuoyancyScreenView.ts (date 1713209352605) @@ -80,6 +80,15 @@ export type DensityBuoyancyScreenViewOptions = SelfOptions & ScreenViewOptions; +export class MassDecorationLayer extends Node { + public readonly depthLinesLayer = new Node(); + + public constructor() { + super(); + this.addChild( this.depthLinesLayer ); + } +} + export default class DensityBuoyancyScreenView extends ScreenView { protected readonly model: Model; @@ -94,6 +103,7 @@ public readonly sceneNode: ThreeIsometricNode; + private readonly massDecorationLayer = new MassDecorationLayer(); private readonly scaleReadoutLayer: Node; private readonly massLabelLayer: Node; private readonly forceDiagramLayer: Node; @@ -162,6 +172,8 @@ } ); this.addChild( this.sceneNode ); + this.addChild( this.massDecorationLayer ); + this.scaleReadoutLayer = new Node(); this.addChild( this.scaleReadoutLayer ); @@ -617,7 +629,7 @@ const dragBoundsProperty = model.invisibleBarrierBoundsProperty; const onMassAdded = ( mass: Mass ) => { - let massView = null; + let massView!: MassView; if ( mass instanceof Cuboid ) { massView = new CuboidView( mass, boundModelToViewPoint, dragBoundsProperty ); @@ -643,37 +655,37 @@ else if ( mass instanceof Boat ) { massView = new BoatView( mass, boundModelToViewPoint, dragBoundsProperty, model.pool.liquidYInterpolatedProperty ); } + assert && assert( !!massView, `massView is falsy, mass: ${mass.constructor.name}` ); - if ( massView ) { - this.sceneNode.stage.threeScene.add( massView ); - this.massViews.push( massView ); - massView.focusablePath && this.sceneNode.backgroundEventTarget.addChild( massView.focusablePath ); + this.sceneNode.stage.threeScene.add( massView ); + this.massViews.push( massView ); + massView.focusablePath && this.sceneNode.backgroundEventTarget.addChild( massView.focusablePath ); + massView.decorate( this.massDecorationLayer ); - if ( massView instanceof ScaleView ) { + if ( massView instanceof ScaleView ) { - // eslint-disable-next-line no-simple-type-checking-assertions - assert && assert( mass instanceof Scale ); + // eslint-disable-next-line no-simple-type-checking-assertions + assert && assert( mass instanceof Scale ); - const scaleReadoutNode = new ScaleReadoutNode( mass as Scale, model.gravityProperty ); - this.scaleReadoutLayer.addChild( scaleReadoutNode ); - this.scaleReadoutNodes.push( scaleReadoutNode ); - } - else { - const forceDiagramNode = new ForceDiagramNode( - mass, - model.showGravityForceProperty, - model.showBuoyancyForceProperty, - model.showContactForceProperty, - model.showForceValuesProperty, - model.forceScaleProperty - ); - this.forceDiagramLayer.addChild( forceDiagramNode ); - this.forceDiagramNodes.push( forceDiagramNode ); + const scaleReadoutNode = new ScaleReadoutNode( mass as Scale, model.gravityProperty ); + this.scaleReadoutLayer.addChild( scaleReadoutNode ); + this.scaleReadoutNodes.push( scaleReadoutNode ); + } + else { + const forceDiagramNode = new ForceDiagramNode( + mass, + model.showGravityForceProperty, + model.showBuoyancyForceProperty, + model.showContactForceProperty, + model.showForceValuesProperty, + model.forceScaleProperty + ); + this.forceDiagramLayer.addChild( forceDiagramNode ); + this.forceDiagramNodes.push( forceDiagramNode ); - const massLabelNode = new MassLabelNode( mass, model.showMassesProperty ); - this.massLabelLayer.addChild( massLabelNode ); - this.massLabelNodes.push( massLabelNode ); - } + const massLabelNode = new MassLabelNode( mass, model.showMassesProperty ); + this.massLabelLayer.addChild( massLabelNode ); + this.massLabelNodes.push( massLabelNode ); } }; model.masses.addItemAddedListener( onMassAdded ); Index: js/common/view/CuboidView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/CuboidView.ts b/js/common/view/CuboidView.ts --- a/js/common/view/CuboidView.ts (revision a01d10f2a7722132b7bc7178550cbc49d1e75e67) +++ b/js/common/view/CuboidView.ts (date 1713210939184) @@ -14,17 +14,24 @@ import Bounds3 from '../../../../dot/js/Bounds3.js'; import { TAG_OFFSET } from './MassTagView.js'; import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; +import { MassDecorationLayer } from './DensityBuoyancyScreenView.js'; +import Vector2 from '../../../../dot/js/Vector2.js'; +import { Node, Path } from '../../../../scenery/js/imports.js'; +import { Shape } from '../../../../kite/js/imports.js'; // constants const numElements = 18 * 3; +const scratchVector2 = new Vector2( 0, 0 ); export default class CuboidView extends MassView { public readonly cuboid: Cuboid; private readonly cuboidGeometry: THREE.BufferGeometry; private readonly updateListener: ( size: Bounds3 ) => void; + private readonly lineGridNode: Path; - public constructor( cuboid: Cuboid, modelToViewPoint: ModelPoint3ToViewPoint2, dragBoundsProperty: TReadOnlyProperty ) { + public constructor( cuboid: Cuboid, modelToViewPoint: ModelPoint3ToViewPoint2, + dragBoundsProperty: TReadOnlyProperty ) { const size = cuboid.sizeProperty.value; const positionArray = new Float32Array( numElements * 3 ); @@ -57,6 +64,51 @@ cuboidGeometry.computeBoundingSphere(); }; this.cuboid.sizeProperty.lazyLink( this.updateListener ); + + const shape = new Shape(); + shape.moveTo( 0, 0 ); + shape.lineTo( 100, 100 ); + + this.lineGridNode = new Path( shape, { + lineWidth: 2, + stroke: 'black' + } ); + const updatePosition = () => { + const viewPoint = modelToViewPoint( cuboid.matrix.translation.toVector3() ); + console.log( viewPoint ); + // const offsetPoint = scratchVector2.setXY( 0, this.lineGridNode.height ); + this.lineGridNode.translation = viewPoint; + + // const center = modelToViewPoint( cuboid.matrix.translation.toVector3() ); + + + }; + this.mass.transformedEmitter.addListener( updatePosition ); + + cuboid.sizeProperty.link( size => { + setTimeout( () => { + const shape = new Shape(); + + const topLeftView = modelToViewPoint( new Vector3( size.minX, size.maxY, size.maxZ ) ); + const topRightView = modelToViewPoint( new Vector3( size.maxX, size.maxY, size.maxZ ) ); + + const width = topRightView.x - topLeftView.x; + + shape.moveTo( -width / 2, 0 ); + shape.lineTo( width / 2, 0 ); + this.lineGridNode.shape = shape; + + }, 2000 ); + } ); + + this.disposeEmitter.addListener( () => { + this.mass.transformedEmitter.removeListener( updatePosition ); + } ); + } + + public override decorate( massDecorationLayer: MassDecorationLayer ): void { + massDecorationLayer.depthLinesLayer.addChild( this.lineGridNode ); + this.disposeEmitter.addListener( () => massDecorationLayer.depthLinesLayer.removeChild( this.lineGridNode ) ); } /**
zepumph commented 1 month ago

Design questions:

  1. Do you like 5 segments, or 4? image
  2. What color should the depth lines be for a custom material? It can go from quite light to very dark. I'm unsure if it should change or not.
  3. Please let me know what exact colors you want. I made entries for the color editor called depthLinesLightProperty and depthLinesDarkProperty.
DianaTavares commented 1 month ago

Do you like 5 segments, or 4?

5 segments, 4 lines

What color should the depth lines be for a custom material? It can go from quite light to very dark. I'm unsure if it should change or not.

Good question! Can the lines change color in the inverse gradient color used in the block? In that way, it is always going to be visible.

Please let me know what exact colors you want. I made entries for the color editor called depthLinesLightProperty and depthLinesDarkProperty.

I was thinking just in white and black, but I can use this property to play around. I can do that the Thursday.

zepumph commented 1 month ago

Alright. I believe that all is done on my side. The only open questions are for Diana to review the specific colors for light/dark, and so see how I'm updating the custom color to either light or dark depending. Let me know if you want to discuss.

DianaTavares commented 1 month ago

It is amazing! thanks!!