TEditBox


Croquet-Teapot

Comment:

TEditBox is used to manipulate and position a contained object in 3D space.

Hierarchy:

ProtoObject
Object
TObject
TFrame
TGroup
TEditBox

Summary:

instance variables:

box contents corners edgeScale edges lastSpin matCorner matEdge matHilite matNorm matOver matSide scaleContents selectedFrame selectedPoint sides

methods:

instance class
accessing actions events initialize testing transform instance creation

Detail:

instance variables:

box
contents
corners
edgeScale
edges
lastSpin
matCorner
matEdge
matHilite
matNorm
matOver
matSide
scaleContents
selectedFrame
selectedPoint
sides

instance methods:

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.

class methods:

instance creation
castSpell: pointer


	| sf |
	sf _ pointer  selectedFrame ifNil:[^ nil].
	^self new initializeWithContents: sf.



^top


- made by Dandelion -