TAvatar


Croquet-Teapot

Comment:

TAvatar is the view the user presents of himself in a space. 

Hierarchy:

ProtoObject
Object
TObject
TFrame
TGroup
TAvatar

Summary:

instance variables:

content controlPitch doRender driving footFrame forwardOnY gotoCount gotoTransform height host laser lastDownFrame lastDownPosition newSpace nickname snapTrans speaker speedControl sticky transparency

methods:

instance class
CIM accessing construction driving events green-properties initialize render scripts testing transform voice chat no messages

Detail:

instance variables:

content
controlPitch
doRender
driving
footFrame
forwardOnY
gotoCount
gotoTransform
height
host
laser
lastDownFrame
lastDownPosition
newSpace
nickname
snapTrans
speaker
speedControl
sticky
transparency

instance methods:

CIM
chatMessage: aText from: aSender

	Transcript cr; show: 'TAvatar>>chatMessage:from: should be implemented'.
joinMeetingAt: transform in: aSpace

	self future: 0.0 perform:#goToPortal:transform: withArguments: {aSpace . transform}.
voiceChatFrom: ignored

	Transcript cr; show: 'TAvatar>>voiceChatfrom: should be implemented'.

accessing
content: aFrame

	content ifNotNil:[self removeChild: content].
	content _ aFrame.
	content ifNotNil:[self addChild: content].
host

	^host
host: aHost

	host := aHost
newSpace


	^ newSpace.
nickname

	^nickname
nickname: aString

	nickname := aString
scale: scale


	frameChildren ifNotNil:[
		frameChildren do:[ :fc | fc scale: scale.]].
setDoRender: bool


	doRender _ bool.
snapTrans


	^ snapTrans.
snapTrans: st


	snapTrans _ st.
speedControl: sc pointerTransform: ptr


	speedControl _ sc.
	self pointerTransform: ptr.
sticky: bool


	sticky _ bool.
transparency: tr


	transparency _ tr.
	super transparency: tr.

construction
makeWindowInFront

	"make a window in front of me"
	| win |
	win _ TWindow new.
	win translation: (self translation - (self lookAt *6) - (0@0.5@0)).
	win rotationAroundY: self yaw.
	self root addChild: win.
	^win.

driving
driveStep


	driving ifTrue: [
		self future: 50.0 deferRelative: 0.0 perform: #driveStep.
		self sticky: false.
		controlPitch
			ifTrue: [self pitch: (speedControl y * 25 min: 75 max: -75)]
			ifFalse: [ self forwardOnY: (speedControl y) negated.].
		self addYaw: (speedControl x * 5).
		].
startDriving: yControlsPitch

	driving ifFalse: [
		controlPitch _ yControlsPitch.
		driving _ true.
		self driveStep.].
stopDriving

	driving _ false.

events
handlesPointerDown: ptr

	^true
handlesPointerOver: ptr

	^true
pointerDown: pointer

pointerEnter: pointer

	self signal: #pointerEnter with: pointer with: self
pointerLeave: pointer
 
	self signal: #pointerLeave with: pointer with: self
pointerUp: pointer


green-properties
greenHost

	^host ifNil:['???']
greenNick

	^nickname ifNil:['???'].

initialize
defaultAvatar

	self loadAvatar: #('Content' 'Alice' 'Animals' 'AliceLiddell.mdl').
initialize

	super initialize.
	sticky _ false.
	doRender _ true.
	self defaultAvatar.
	height _ 4.6.
	lastDownPosition _ B3DVector3 new.
	footFrame _ TGroup new.
	footFrame singleParent: true.
	gotoCount _ 0.
	forwardOnY _ 0.
	driving _ false.
	controlPitch _ false.
	newSpace _ true.
	laser _ TLaser new.
	laser translation:(B3DVector3 x: 0.5 y:-0.3 z:-0.2).
	laser length: 0.5.
	self addChild: laser.
	transparency _ 1.0.
	^self
loadAvatar: avatarPath

	| tframe  box scale dy |

	tframe _ CroquetData loadAliceFile: avatarPath.
	tframe ifNotNil:[
		box _ tframe boundingBox.
		scale _ 4.708164/box extentY.
		dy _ box centerY * scale negated.
		tframe scale: scale.
		box _ tframe boundingBox.
		tframe translationX: 0 y: 0.616526961326599+dy-2.3 z: 0.
		tframe singleParent: false.
		tframe solidTree: false.
		tframe objectOwner: nil.
	].
	self content: tframe.

render
renderFrame: ogl parent: parent root: root


	| ac rval |
	ac _ ogl camera.
	newSpace _ false.
	doRender ifTrue:[
"Render everyone else's avatars"
		ac avatar = self ifFalse:[  ^ super renderFrame: ogl parent: parent root: root].
"Only render ours if we are inside of a portal (such as a mirror) or the camera is behind the avatar"
		ac inPortal ifTrue:[ "just render if we are in a portal"
			transparency ~= 1.0 ifTrue:[self transparency: 1.0.].		
			^ super renderFrame: ogl parent: parent root: root. 
		] ifFalse:[ "otherwise, check to see if we are thirdPerson or not"
			ac thirdPerson cBool ifTrue:[
				ac thirdPerson ~= transparency ifTrue:[self transparency: ac thirdPerson.].
				rval _ super renderFrame: ogl parent: parent root: root.
				^ rval.
			].
		].
	].
	^ 0.
renderFrame: ogl space: space


	doRender ifTrue:[^ super renderFrame: ogl space: space].
	^ 0.

scripts
jumpScript

	| script1 script2 |
	"First start the script which will drop little farts along the way"
	self startScript: #dropFart.
	"Now move up the full distance. This method will block until completion"
	self move: #up distance: 10 duration: 4.
	"Now move down but make us a little pirouette.
	This still looks a bit ugly - we would need something like #doTogether: here"
	script1 _ self startScript: #move:distance:duration: withArguments:{#down. 10. 4.}.
	script2 _ self startScript: #turn:turns:duration: withArguments:{#left. 4. 4}.
	self waitUntilAllOf:{script1. #done. script2. #done}.
	self stopScript: #dropFart.
showIDScript

	"This script is triggered on pointer enter"
	| myText |
	myText := TPrimitiveText new.
	myText text: 'Name:	' asText allBold, nickname printString,'
Host:	' asText allBold, host printString.
	myText textAlign: #bottomCenter.
	myText translationX: 0 y: 1 z: 0.
	self addChild: myText.
	"wait until mouse leaves"
	self waitUntil: #pointerLeave.
	self removeChild: myText.

testing
isComponent

	^true

transform
addToNewSpace: aSpace


	aSpace addChild: self.
	self frameChanged.
	newSpace _ true.
	self signal: #spaceEnter with: aSpace.
	aSpace signal: #objectEnter with: self.
doGoto


	| qFrom qTo fromLoc toLoc trans |
" Is used to move the camera to a specific pose (location and orientation) in the TSpace, via an interpolated rotation/translation. "
	gotoCount = 1 ifTrue:[
		self localTransform: gotoTransform.
		gotoCount _ 0.
		self yawTransform.
		"yaw _ (gotoTransform rotation y)."
		^ self.].

	qFrom _ localTransform asQuaternion.
	qTo _ gotoTransform asQuaternion.
	fromLoc _ localTransform translation.
	toLoc _ gotoTransform translation.
	fromLoc ~= toLoc ifTrue:[
		fromLoc _ fromLoc  + ((toLoc - fromLoc)/gotoCount).].
	qFrom _ qFrom slerpTo: qTo at: (1.0/gotoCount).
	trans _ qFrom asMatrix4x4.
	trans translation: fromLoc.
	self localTransform: trans.
	gotoCount _ gotoCount - 1. 
downFloor: floor distance: dist position: pos


		| trans ht transFloor downPosition |
	gotoCount ~= 0 ifTrue:[ ^ self doGoto].
	sticky ifTrue:[^ self].
	floor ifNotNil:[
	floor isSolid ifTrue:[
		trans _ self translation.
" ---- Calculate distance to the current floor."
		dist = height ifFalse:[
			ht _ trans y + height - dist.
			trans y > ht ifTrue:[ trans y - ht > 0.5 ifTrue:[ ht _ trans y - 0.5.].].
			trans y: ht].
" ---- Calculate the floor frame position in the floor's local frame. "
		transFloor _ footFrame globalPosition-lastDownPosition.
		lastDownFrame ~= floor ifTrue:[
			floor addChild: footFrame.
			].
		downPosition _ pos.
		downPosition y: (downPosition y-height).
		footFrame translation: downPosition.
		lastDownPosition _ footFrame globalPosition.
		lastDownFrame _ floor.
		trans x: trans x+transFloor x y: trans y z: trans z+ transFloor z.
		self translation = trans ifFalse: [
			self translation: trans.
			self localTransform:  self localTransform clone. ]	"why clone?"	
		].
	].
enter: aTSpace


	| tfm |
	tfm := aTSpace dropInFrame ifNil: [self localTransform].
	self goToPortal: aTSpace transform: tfm.
forwardOnY


	^ forwardOnY.
forwardOnY: foy


	| trans |
	trans _ B3DMatrix4x4 identity. 
	trans translationX: 0.0 y:0.0 z: foy.
	localTransform _ localTransform composeWith: trans.
	self pitch > 0.001 ifTrue:[self pitch: self pitch * 0.8].
	self frameChanged.
goToPortal: aPortal transform: aTransform

	| oldRoot aSpace |
	oldRoot := self root.
	aSpace := aPortal root.

	self signal: #spaceLeave with: oldRoot.
	oldRoot signal: #objectLeave with: self.
	self parent removeChild: self.  "move out of space"
	self localTransform: aTransform. "setup transform"
	self yawTransform.

	"self future: 0.0 perform: #addToNewSpace: withArguments: { aSpace }."
	self addToNewSpace: aSpace.
	"addChild: in the new space will force the necessary joins of the viewingParticipants"
goto: transform count: count


" This is used to force the camera to move to a position/orientation. The final location is gotoTransform, and the number of interpolations is in gotoCount."
	sticky _ true.
	snapTrans _ self localTransform.
	gotoTransform _ transform.
	gotoCount _ count.
pointerTransform: ptr


	| p0 p1 at up side m |
	ptr selectedFrame ifNotNil:[
		p0 _ laser globalPosition.
		p1 _ ptr selectedFrame globalTransform localPointToGlobal: ptr selectedPoint.
		p0 _ self globalOrientation orthoNormInverse localPointToGlobal: (p0-p1).
		at _ p0 normalized.
		up _ 0@1@0.
		side _ (at cross: up) normalized negated.
		up _ (side cross: at) normalized negated.
		m _ B3DMatrix4x4 identity.
		m a11: side x.
		m a21: side y.
		m a31: side z.
		m a12: up x.
		m a22: up y.
		m a32: up z.
		m a13: at x.
		m a23: at y.
		m a33: at z.
		laser orientation: m.
		ptr isDown ifTrue:[laser length: p0 length] ifFalse:[laser length:0.5].
	] ifNil:[
		laser length: 0.5.
		laser orientation:ptr orientation.
		].
		

		

snapBack


	self goto: snapTrans count: 6.
	snapTrans _ nil.

voice chat
initPhone


	| tframe  |
	tframe _ TWidget createNewWithUrl:'http://www.reed.com/TeaLand/widgets/speaker.tea'
		fileName:{FileDirectory default pathName. 'Content'. 'Widgets'. 'speaker.ASE'} scale:1.0.
	speaker _ TSpeaker new initializeWithFrame: tframe.
	speaker translationX: 0 y: 1.5 z: 0.
	speaker rotationAroundY: 180.
	self addChild: speaker.
playSoundBuffer: soundBuffer at: deltaMSecs stereo: stereoFlag samplingRate: samplingRate codec: codec worldsExcept: aCWorld

	"don't play sound in the world where it was sourced"
	Croquet world = aCWorld ifTrue: [^self].
	"Queue in the given sound buffer at deltaMSecs from the start of the sound."
	speaker signalVolume: (self streamingSound addSoundBuffer: soundBuffer at: deltaMSecs stereo: stereoFlag samplingRate: samplingRate codec: codec).
	

class methods:

^top


- made by Dandelion -