TEditBox is used to manipulate and position a contained object in 3D space.
ProtoObjectObjectTObjectTFrameTGroupTEditBox
| box | contents | corners | edgeScale | edges | lastSpin | matCorner | matEdge | matHilite | matNorm | matOver | matSide | scaleContents | selectedFrame | selectedPoint | sides |
| box |
|---|
| contents |
|---|
| corners |
|---|
| edgeScale |
|---|
| edges |
|---|
| lastSpin |
|---|
| matCorner |
|---|
| matEdge |
|---|
| matHilite |
|---|
| matNorm |
|---|
| matOver |
|---|
| matSide |
|---|
| scaleContents |
|---|
| selectedFrame |
|---|
| selectedPoint |
|---|
| sides |
|---|
| accessing |
|---|
| contents: conts |
| parentFrame extent | contents _ conts. box _ contents boundingBox copy. parentFrame _ contents parent. self localTransform: conts localTransform. self translation: self translation + (self orientation localPointToGlobal:box center). contents localTransform: B3DMatrix4x4 identity. contents translation: (box center negated). extent _ box extent. box min: (extent/-2.0). box max: (extent/2.0). parentFrame replaceChild: contents with: self. self addChild: conts. scaleContents _ 1.0. self update. |
| scale: sc |
box scale: sc. " contents scale: sc." self update. |
| selectedPoint: sp |
selectedPoint _ sp. |
| actions |
|---|
| delete |
| | contents localTransform: (self localTransform composeWith: contents localTransform). self parent replaceChild: self with: contents. |
| dragBox: pointer |
| norm sp sf | sf _ selectedFrame translation. pointer shiftPressed ifTrue:[ sf x ~= 0 ifTrue:[ norm _ B3DVector3 x:0 y:1 z:0]. sf y ~= 0 ifTrue:[norm _ B3DVector3 x:0 y:0 z:1]. sf z ~= 0 ifTrue:[norm _ B3DVector3 x:0 y:1 z:0]. ] ifFalse:[norm _ sf normalized.]. sp _ selectedFrame localTransform localPointToGlobal: selectedPoint. (pointer frame: self pickPlane: sp normal: norm) ifTrue:[ self translation: self translation + (self orientation localPointToGlobal: (pointer selectedPoint-sp)).]. |
| resizeBox: pointer |
"This needs to be fixed - since the plane does not go through the center of the cube, there is a limit to how small this can get in any one motion. The advantage is this keeps us from getting too small." | len1 len2 norm sp sc| norm _ (pointer camera frameLookAt: self) negated. sp _ selectedFrame localTransform localPointToGlobal: selectedPoint. (pointer frame: self pickPlane: sp normal: norm) ifTrue:[ len1 _ sp length. len2 _ pointer selectedPoint length. len1 = 0.0 ifTrue:[^ false.]. sc _ len2/len1. self scale: sc. scaleContents _ scaleContents * sc. selectedPoint _ (selectedFrame localTransform orthoNormInverse localPointToGlobal: pointer selectedPoint). ^ true.]. ^ false. |
| rotateBoxX: pointer |
| len radius delta deltaLoc spto spfrom theta trans | " Rotate around the x-axis " len _ selectedFrame extent x/2.0. len _ len max: 100.0. radius _ selectedFrame location length. (pointer frame: self pickCylinderFrom: ( B3DVector3 x: len y: 0 z: 0) to:( B3DVector3 x: len negated y: 0 z: 0) radius: radius) ifFalse:["we are not on the cylinder anymore...." delta _ 2*radius. (pointer framePointer row2 dot: (pointer framePosition)) > 0 ifFalse:[ delta _ delta negated.]. deltaLoc _ pointer framePointer row2 * delta. (pointer frame: self pickCylinderFrom: (B3DVector3 x: len y: deltaLoc y z: deltaLoc z) to: (B3DVector3 x: len negated y: deltaLoc y z: deltaLoc z) radius: radius) ifFalse:[lastSpin _ nil. ^ false.]. spto _ pointer selectedPoint copy- deltaLoc. spto x: 0 y: spto y negated z: spto z negated. ] ifTrue: [spto _ pointer selectedPoint copy.]. spfrom _ selectedPoint copy. spfrom x: 0.0. spfrom normalize. spto x: 0.0. spto normalize. theta _ ((spfrom y * spto z) - (spto y * spfrom z))"/selectedRadiusSquared". theta < -1.0 ifTrue:[theta_ -1.0]. theta > 1.0 ifTrue:[theta _ 1.0]. theta _ theta arcSin radiansToDegrees/2.0. lastSpin _ B3DMatrix4x4 identity rotationAroundX: theta. trans _ self translation. self translationX: 0.0 y:0.0 z:0.0. self localTransform: (self localTransform composeWith: lastSpin). self translation: trans. self localTransform: localTransform clone. ^ true. |
| rotateBoxY: pointer |
| trans spfrom spto deltaLoc theta radius len delta | " Rotate around the y-axis " len _ selectedFrame extent y/2.0. len _ len max: 100.0. radius _ selectedFrame location length. (pointer frame: self pickCylinderFrom: (B3DVector3 x: 0.0 y: len z: 0.0) to: (B3DVector3 x: 0.0 y: len negated z: 0.0) radius: radius) ifFalse: [ "we are not on the cylinder anymore...." delta _ 2*radius. (pointer framePointer row1 dot: (pointer framePosition)) > 0 ifFalse:[ delta _ delta negated ]. deltaLoc _ pointer framePointer row1 * delta. (pointer frame: self pickCylinderFrom: (B3DVector3 x: deltaLoc x y: len z: deltaLoc z ) to: (B3DVector3 x: deltaLoc x y: len negated z: deltaLoc z) radius: radius) ifFalse:[lastSpin _ nil. ^ false.]. spto _ pointer selectedPoint copy- deltaLoc. spto x: spto x negated y: 0 z: spto z negated. ] ifTrue: [spto _ pointer selectedPoint copy.]. spfrom _ selectedPoint copy. spfrom y: 0.0. spfrom normalize. spto y: 0.0. spto normalize. theta _ ((spfrom z * spto x) - (spto z * spfrom x))"/selectedRadiusSquared". theta < -1.0 ifTrue:[theta_ -1.0]. theta > 1.0 ifTrue:[theta _ 1.0]. theta _ theta arcSin radiansToDegrees/2.0. lastSpin _ B3DMatrix4x4 identity rotationAroundY: theta. trans _ self translation. self translationX: 0.0 y:0.0 z:0.0. self localTransform: (self localTransform composeWith: lastSpin). self translation: trans. self localTransform: localTransform clone. ^ true. |
| rotateBoxZ: pointer |
| delta trans spfrom spto deltaLoc theta radius len | " Rotate around the z-axis " len _ selectedFrame extent z/2.0. len _ len max: 100.0. radius _ selectedFrame location length. (pointer frame: self pickCylinderFrom: (B3DVector3 x: 0.0 y: 0.0 z: len) to: (B3DVector3 x: 0.0 y: 0.0 z: len negated) radius: radius) ifFalse: [ "we are not on the cylinder anymore...." delta _ 2*radius. (pointer framePointer row2 dot: (pointer framePosition)) > 0 ifFalse:[ delta _ delta negated. ]. deltaLoc _ pointer framePointer row2 * delta. (pointer frame: self pickCylinderFrom: (B3DVector3 x: deltaLoc x y: deltaLoc y z: len) to: (B3DVector3 x: deltaLoc x y: deltaLoc y z: len negated) radius: radius) ifFalse:[lastSpin _ nil. ^ false.]. spto _ pointer selectedPoint copy- deltaLoc. spto x: spto x negated y: spto y negated z: 0. ] ifTrue: [spto _ pointer selectedPoint copy.]. spfrom _ selectedPoint copy. spfrom z: 0.0. spfrom normalize. spto z: 0.0. spto normalize. theta _ ((spfrom x * spto y) - (spto x * spfrom y))"/selectedRadiusSquared". theta < -1.0 ifTrue:[theta_ -1.0]. theta > 1.0 ifTrue:[theta _ 1.0]. theta _ theta arcSin radiansToDegrees/2.0. lastSpin _ B3DMatrix4x4 identity rotationAroundZ: theta. trans _ self translation. self translationX: 0.0 y:0.0 z:0.0. self localTransform: (self localTransform composeWith: lastSpin). self translation: trans. self localTransform: localTransform clone. ^ true. |
| selectChild |
| eb | contents frameChildren ifNotNil:[ contents frameChildren size > 0 ifTrue:[ eb_ TEditBox new. eb contents: (contents frameChildren at: 1). self delete. ]. ]. |
| selectLeftSibling |
| siblings previous eb | siblings _ self parent frameChildren. siblings size > 1 ifTrue:[ previous _ siblings previous: self. self delete. eb _ TEditBox new. eb contents: previous . ]. |
| selectParent |
| par eb | self parent ifNotNil: [ "we are the root" self parent ~= self root ifTrue:[ " don't select the root, as that would be really hard to edit" par _ self parent. self delete. eb _ TEditBox new. eb contents: par. ]. ]. |
| selectRightSibling |
| siblings next eb | siblings _ self parent frameChildren. siblings size > 1 ifTrue:[ next _ siblings next: self. self delete. eb _ TEditBox new. eb contents: next . ]. |
| events |
|---|
| handlesKeyboard: pointer |
^ true. |
| handlesPointerDown: pointer |
^ true. |
| handlesPointerOver: pointer |
^ true. |
| keyStroke: pointer |
| c spin | c _ pointer event2D keyCharacter. c = $x ifTrue:[ spin _ B3DMatrix4x4 identity rotationAroundX: -1.0]. c = $X ifTrue:[ spin _ B3DMatrix4x4 identity rotationAroundX: 1.0]. c = $y ifTrue:[ spin _ B3DMatrix4x4 identity rotationAroundY: -1.0]. c = $Y ifTrue:[ spin _ B3DMatrix4x4 identity rotationAroundY: 1.0]. c = $z ifTrue:[ spin _ B3DMatrix4x4 identity rotationAroundZ: -1.0]. c = $Z ifTrue:[ spin _ B3DMatrix4x4 identity rotationAroundZ: 1.0]. c = $d ifTrue:[self delete.]. pointer event2D keyValue= 28 ifTrue:[ self selectLeftSibling. ]. "left arrow" pointer event2D keyValue= 29 ifTrue:[ self selectRightSibling.]. "right arrow" pointer event2D keyValue= 30 ifTrue:[ self selectParent. ]. "up arrow" pointer event2D keyValue= 31 ifTrue:[ self selectChild. ]. "down arrow" spin ifNotNil:[self localTransform: (self localTransform composeWith: spin) ]. ^ true. |
| pointerDown: pointer |
selectedFrame _ pointer selectedFrame. selectedPoint _ pointer selectedPoint. ^ true. |
| pointerEnter: pointer |
selectedFrame _ pointer selectedFrame. " selectedFrame material: matOver." ^ true. |
| pointerMove: pointer |
self perform: selectedFrame objectName with: pointer. |
| pointerUp: pointer |
scaleContents ~= 1.0 ifTrue:[ contents scale: scaleContents. self selectedPoint: selectedPoint. scaleContents _ 1.0.]. ^ true. |
| initialize |
|---|
| initializeWithContents: conts |
| parentFrame extent txtr | super initialize. contents _ conts. box _ contents boundingBox copy. txtr _ TTexture new initializeWithFileName: 'box.png' mipmap: true shrinkFit: false. matNorm _ TMaterial new. matNorm ambientColor: #(0.5 0.7 0.7 0.5) asFloatArray. matNorm diffuseColor: #(0.5 0.7 0.7 0.5) asFloatArray. matNorm texture: txtr. matCorner _ TMaterial new. matCorner ambientColor: #(0.9 0.9 0.3 0.9) asFloatArray. matCorner diffuseColor: #(0.9 0.9 0.3 0.9) asFloatArray. matCorner texture: txtr. matEdge _ TMaterial new. matEdge ambientColor: #(1.0 0.4 0.4 0.9) asFloatArray. matEdge diffuseColor: #(1.0 0.4 0.4 0.9) asFloatArray. matEdge texture: txtr. matHilite _ TMaterial new. matHilite ambientColor: #(1.0 1.0 0.2 0.5) asFloatArray. matHilite diffuseColor: #(1.0 1.0 0.2 0.5) asFloatArray. matOver _ TMaterial new. matOver ambientColor: #(0.2 0.5 1.0 0.8) asFloatArray. matOver diffuseColor: #(0.2 0.5 1.0 0.8) asFloatArray. self makeCorners. self makeEdges. self makeSides. parentFrame _ contents parent. self localTransform: conts localTransform. self translation: self translation + (self orientation localPointToGlobal:box center). contents localTransform: B3DMatrix4x4 identity. contents translation: (box center negated). extent _ box extent. box min: (extent/-2.0). box max: (extent/2.0). parentFrame replaceChild: contents with: self. self addChild: conts. scaleContents _ 1.0. self update. ^self |
| makeCorners |
| c | corners _ OrderedCollection ofSize: 8. 1 to: 8 do:[:index | c _ TCube new. c material: matCorner. c solid: false. corners at: index put: c. self addChild: c. c objectOwner: self. c objectName: #corner. ]. |
| makeEdges |
| e | edges _ OrderedCollection ofSize: 12. 1 to: 12 do:[:index | e _ TCube new. e material: matEdge. e solid: false. e objectOwner: self. self addChild: e. edges at: index put: e. ]. |
| makeSides |
| s | sides _ OrderedCollection ofSize: 6. 1 to: 6 do:[:index | s _ TRectangle new. s material: matNorm. s solid: false. s objectOwner: self. s objectName: #side. self addChild: s. sides at: index put: s. ]. (sides at: 1)rotationAroundX:-90. (sides at: 2)rotationAroundX: 90. (sides at: 3)rotationAroundY:-90. (sides at: 4)rotationAroundY: 90. (sides at: 5)rotationAroundY:180. |
| testing |
|---|
| isComponent |
^ true. |
| transform |
|---|
| update |
| mn mx sz counter cc |
mn _ box min.
mx _ box max.
edgeScale _ (1@1@1)*((mx-mn)max/20.0).
cc _ edgeScale x/2.0.
sz_ (mx - mn max: (cc@cc@cc))/2.0.
mn _ box center - sz.
mx _ box center + sz.
counter _ 1.
{mn x. mx x} do:[:xx |
{mn y. mx y} do:[:yy |
{mn z. mx z} do:[:zz |
(corners at: counter) extent: edgeScale.
(corners at: counter) location: xx@yy@zz.
(corners at: counter) objectName: #resizeBox: .
counter _ counter + 1.
]]].
self updateEdge: (edges at: 1) from: (mn x @ mn y @ (mn z+cc)) to:(mn x @ mn y @ (mx z-cc))
message: #rotateBoxZ: .
self updateEdge: (edges at: 2) from: ((mn x+cc) @ mn y @ mx z) to:((mx x-cc) @ mn y @ mx z)
message: #rotateBoxX: .
self updateEdge: (edges at: 3) from: (mx x @ mn y @ (mx z-cc)) to:(mx x @ mn y @ (mn z+cc))
message: #rotateBoxZ: .
self updateEdge: (edges at: 4) from: ((mx x-cc) @ mn y @ mn z) to:((mn x+cc) @ mn y @ mn z)
message: #rotateBoxX: .
self updateEdge: (edges at: 5) from: (mn x @ mx y @ (mn z+cc)) to:(mn x @ mx y @ (mx z-cc))
message: #rotateBoxZ: .
self updateEdge: (edges at: 6) from: ((mn x+cc) @ mx y @ mx z) to:((mx x-cc) @ mx y @ mx z)
message: #rotateBoxX: .
self updateEdge: (edges at: 7) from: (mx x @ mx y @ (mx z-cc)) to:(mx x @ mx y @ (mn z+cc))
message: #rotateBoxZ: .
self updateEdge: (edges at: 8) from: ((mx x-cc) @ mx y @ mn z) to:((mn x+cc) @ mx y @ mn z)
message: #rotateBoxX: .
self updateEdge: (edges at: 9) from: (mn x @ (mn y+cc) @ mn z) to:(mn x @ (mx y-cc) @ mn z)
message: #rotateBoxY: .
self updateEdge: (edges at: 10) from: (mn x @ (mn y+cc) @ mx z) to:(mn x @ (mx y-cc) @ mx z)
message: #rotateBoxY: .
self updateEdge: (edges at: 11) from: (mx x @ (mn y+cc) @ mx z) to:(mx x @ (mx y-cc) @ mx z)
message: #rotateBoxY: .
self updateEdge: (edges at: 12) from: (mx x @ (mn y+cc) @ mn z) to:(mx x @ (mx y-cc) @ mn z)
message: #rotateBoxY: .
cc_ cc*2.
(sides at: 1) extent: (mx x-mn x-cc)@(mx z - mn z-cc).
(sides at: 1) translation: box center+(0@mx y@0).
(sides at: 2) extent: (mx x-mn x-cc)@(mx z - mn z-cc).
(sides at: 2) translation: box center+(0@mn y@0).
(sides at: 3) extent: (mx z-mn z-cc)@(mx y - mn y-cc).
(sides at: 3) translation: box center+(mn x@0@0).
(sides at: 4) extent: (mx z-mn z-cc)@(mx y - mn y-cc).
(sides at: 4) translation: box center+(mx x@0@0).
(sides at: 5) extent: (mx x-mn x-cc)@(mx y - mn y-cc).
(sides at: 5) translation: box center+(0@0@mn z).
(sides at: 6) extent: (mx x-mn x-cc)@(mx y - mn y-cc).
(sides at: 6) translation: box center+(0@0@mx z).
sides do:[:s | s objectName: #dragBox: ].
|
| updateEdge: edge from: from to: to message: msg |
| scale center | scale _ (from - to) abs max: edgeScale. center _ (from + to)/2.0. edge extent: scale. edge location: center. edge objectName: msg. |
| instance creation |
|---|
| castSpell: pointer |
| sf | sf _ pointer selectedFrame ifNil:[^ nil]. ^self new initializeWithContents: sf. |