DIRECTORY AtomButtons, AtomButtonsTypes, BasicTime, CodeTimer, Containers, CoordSys, DisplayListToTree, Feedback, FileNames, FS, GraphicsButton, Imager, IO, Menus, Random, Rope, SlackProcess, SV2d, SV3d, SVBasicTypes, SVCastRays, SVDrawMonitor, SVEditUser, SVEvent, SVFiles, SVGravity, SVInterfaceTypes, SVModelTypes, SVRayTypes, SVScene, SVSceneTypes, SVSelections, SVSessionLog, SVState, SVUserInput, SVUtility, SVViewersOnScene, SVViewerTool, SVWindow, TFO3d, ViewerClasses, ViewerOps, ViewerTools; SVEventImplA: CEDAR PROGRAM IMPORTS AtomButtons, BasicTime, SVCastRays, CodeTimer, CoordSys, DisplayListToTree, Feedback, FileNames, FS, GraphicsButton, IO, Random, Rope, SlackProcess, SVEditUser, SVEvent, SVFiles, SVGravity, SVScene, SVSelections, SVSessionLog, SVState, SVUserInput, SVUtility, SVViewersOnScene, SVWindow, TFO3d, ViewerOps, ViewerTools EXPORTS SVEvent = BEGIN Slice: TYPE = SVSceneTypes.Slice; BoundBox: TYPE = SVBasicTypes.BoundBox; Camera: TYPE = SVModelTypes.Camera; Color: TYPE = Imager.Color; CoordSysGenerator: TYPE = SVScene.CoordSysGenerator; CoordSystem: TYPE = SVModelTypes.CoordSystem; CSGTree: TYPE = SVRayTypes.CSGTree; DisplayContextProc: TYPE = SVInterfaceTypes.DCProc; DrawStyle: TYPE = SVModelTypes.DrawStyle; EditToolData: TYPE = SVInterfaceTypes.EditToolData; FeatureData: TYPE = SVInterfaceTypes.FeatureData; FeedbackData: TYPE = AtomButtonsTypes.FeedbackData; FileCamera: TYPE = SVSceneTypes.FileCamera; GravityType: TYPE = SVInterfaceTypes.GravityType; MasterObject: TYPE = SVSceneTypes.MasterObject; Matrix4by4: TYPE = SV3d.Matrix4by4; MouseButton: TYPE = Menus.MouseButton; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Primitive: TYPE = SVRayTypes.Primitive; Scene: TYPE = SVSceneTypes.Scene; TwoState: TYPE = AtomButtons.TwoState; Vector3d: TYPE = SV3d.Vector3d; Viewer: TYPE = ViewerClasses.Viewer; SVData: TYPE = SVInterfaceTypes.SVData; GravityChoiceChange: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { info: AtomButtons.EnumTypeRef _ svData.hitTest.gravityTypeMenu; name: Rope.ROPE; IF event.rest.first = $FlipForward THEN AtomButtons.TimeToFlipThru[LIST[$FlipForward, info]] ELSE AtomButtons.TimeToFlipThru[LIST[$FlipBackward, info]]; name _ info.flipLabel.name; SELECT TRUE FROM Rope.Equal[name, "StrictDistance", TRUE] => svData.hitTest.gravityType _ strictDistance; Rope.Equal[name, "PreferLines", TRUE] => svData.hitTest.gravityType _ linesPreferred; Rope.Equal[name, "PreferPoints", TRUE] => svData.hitTest.gravityType _ pointsPreferred; ENDCASE => ERROR; UpdateGravityChoice[svData]; }; UpdateGravityChoice: PROC [clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; SELECT AtomButtons.GetButtonState[svData.hitTest.gravButton] FROM on => SELECT svData.hitTest.gravityType FROM strictDistance => SVWindow.SetCursorLooks[strictDistance, svData]; linesPreferred => SVWindow.SetCursorLooks[linesPreferred, svData]; pointsPreferred => SVWindow.SetCursorLooks[pointsPreferred, svData]; ENDCASE => ERROR; -- SHOULD NOT USE off STATE off => SVWindow.SetCursorLooks[off, svData]; ENDCASE => ERROR; }; GravityExtentChange: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { ged: SVInterfaceTypes.GravityExtentData _ NARROW[GraphicsButton.GetValue[svData.hitTest.gravityExtentButton].buttonData]; extent: REAL _ ged.extent; success: BOOL _ TRUE; SELECT event.rest.first FROM $ValueUp => { IF extent < 18432.0 THEN extent _ extent*2.0 ELSE { Feedback.PutF[svData.feedback, oneLiner, "Can't extend gravity further than 256 inches."]; Feedback.Blink[svData.feedback]; success _ FALSE; }; }; $ValueDown => extent _ extent/2.0; ENDCASE => extent _ SVEditUser.GetDefaultGravityExtent[]; IF success THEN { SetGravityExtent[svData, extent/72.0]; }; }; SetGravityExtent: PUBLIC PROC [svData: SVData, inches: REAL] = { screenDots: REAL; graphicsState: AtomButtonsTypes.GraphicsState _ svData.hitTest.gravityExtentButton; ged: SVInterfaceTypes.GravityExtentData; screenDots _ inches*72.0; Feedback.PutF[svData.feedback, oneLiner, "Gravity extent is now %g inches.", [real[inches]] ]; ged _ NEW[SVInterfaceTypes.GravityExtentDataObj _ [extent: screenDots]]; GraphicsButton.SetButtonValueAndPaint[graphicsState, svData, ged]; svData.hitTest.tolerance _ screenDots; svData.hitTest.criticalR _ screenDots; svData.hitTest.innerR _ screenDots/2.0; }; ToggleGravity: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { stateInfo: TwoState _ svData.hitTest.gravButton; AtomButtons.SwitchState[stateInfo]; UpdateGravityChoice[svData]; }; ToggleMidpoints: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { stateInfo: TwoState _ svData.hitTest.midpointButton; AtomButtons.SwitchState[stateInfo]; SVWindow.RestoreScreenAndInvariants[paintAction: $None, svData: svData]; }; InitializeAlignments: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { }; Painter: PUBLIC PROC [proc: DisplayContextProc, svData: SVData _ NIL] = { }; -- end of Painter UpdateHeader: PUBLIC PROC [pictureFile: Rope.ROPE, svData: SVData] = { headerRope: Rope.ROPE; aisName: Rope.ROPE; viewName: Rope.ROPE _ svData.camera.viewName; IF pictureFile = NIL THEN pictureFile _ svData.scene.name; headerRope _ Rope.Cat[viewName, " View of Solid Scene: ", pictureFile]; aisName _ Rope.Concat[SVFiles.FilenameMinusExtension[pictureFile], ".ais"]; svData.outer.name _ headerRope; ViewerOps.PaintViewer[svData.outer, caption, FALSE, NIL]; }; NewVersion: PUBLIC PROC [viewer: Viewer] = { svData: SVData _ NARROW[viewer.data]; scene: Scene _ svData.scene; scene.dirty _ TRUE; svData.scene.tree.outOfDate _ TRUE; svData.outer.newVersion _ TRUE; UpdateHeader[scene.name, svData]; }; SceneOldVersion: PUBLIC PROC [svData: SVData] = { scene: Scene _ svData.scene; SVViewersOnScene.SceneOldVersion[svData, scene]; }; OldVersion: PUBLIC PROC [viewer: Viewer] = { svData: SVData _ NARROW[viewer.data]; scene: Scene _ svData.scene; scene.dirty _ FALSE; svData.scene.tree.outOfDate _ TRUE; -- OldVersion may result from loading a new scene, or creating an empty scene. In either case, the ray tracing tree is out of date. Set flag just in case. svData.outer.newVersion _ FALSE; UpdateHeader[scene.name, svData]; }; EraseAndDrawScene: PUBLIC PROC [svData: SVData] = { SVWindow.RestoreScreenAndInvariants[$PaintEntireScene, svData]; }; DrawSceneButton: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { SVWindow.RestoreScreenAndInvariants[$PaintEntireScene, svData]; }; Clear: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { editToolData: EditToolData _ svData.editToolData; oldScene: Scene _ svData.scene; newScene: Scene; oldScreenCS: CoordSystem; fileCamera: FileCamera; cameraName: Rope.ROPE; drawStyle: DrawStyle; oldScreenCS _ svData.camera.screenCS; newScene _ svData.scene _ SVScene.CreateScene["NoName.pic"]; SVSelections.KillSkitterAndSelections[editToolData]; UpdateHeader[newScene.name, svData]; SVEvent.Selected[event, svData]; IF newScene.cameraOrder = NIL THEN fileCamera _ newScene.cameras.first ELSE { success: BOOL; cameraName _ newScene.cameraOrder.first; [fileCamera, success] _ SVScene.FindFileCameraFromName[cameraName, newScene]; IF NOT success THEN { fileCamera _ newScene.cameras.first; Feedback.Append[svData.feedback, Rope.Cat["Camera ", cameraName, " not found"], oneLiner]; Feedback.Blink[svData.feedback]; }; }; drawStyle _ SVEvent.CurrentStyle[svData]; svData.camera _ SVScene.CreateCamera[newScene.coordSysRoot, CoordSys.CopyCoordSysFromAnyTree[oldScreenCS, "SCREEN", NIL, NIL], drawStyle]; SVScene.StuffCameraFromFileCamera[svData.camera, fileCamera, svData.camera.style, newScene]; SVViewersOnScene.NotifyOfEmpty[svData: svData, from: oldScene, to: svData.scene]; SceneOldVersion[svData]; SVWindow.RestoreScreenAndInvariants[$PaintEntireScene, svData]; }; Restore: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { editToolData: EditToolData _ svData.editToolData; success: BOOL; wdir: Rope.ROPE; scene: Scene _ svData.scene; wdir _ editToolData.originalWorkingDirectory; [scene, success] _ SVViewersOnScene.LoadScene[svData, scene.name, wdir]; IF success THEN { svData.scene _ scene; SVSelections.KillSkitterAndSelections[editToolData]; SceneOldVersion[svData]; UpdateHeader[scene.name, svData]; EraseAndDrawScene[svData]; SVEvent.Selected[event, svData]; }; }; -- end of Reset Save: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { success: BOOL; sceneName: Rope.ROPE; scene: Scene _ svData.scene; sceneName _ FileNames.StripVersionNumber[scene.name]; success _ SVViewersOnScene.SaveScene[svData, sceneName]; IF success THEN { SVEvent.Selected[event, svData]; SceneOldVersion[svData]; UpdateHeader[scene.name, svData]; }; }; -- end of Save Get: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { editToolData: EditToolData _ NARROW[svData.editToolData]; success: BOOL; picName: Rope.ROPE _ NARROW[event.rest.first]; fullName: Rope.ROPE; wdir: Rope.ROPE; scene: Scene; oldScreenCS: CoordSystem _ svData.camera.screenCS; startTime: BasicTime.GMT; endTime: BasicTime.GMT; totalTime: INT; timeRope: Rope.ROPE; drawStyle: DrawStyle; IF Rope.Length[picName] = 0 THEN RETURN; wdir _ editToolData.originalWorkingDirectory; success _ TRUE; [fullName,,] _ FS.ExpandName[picName, wdir ! FS.Error => IF error.group = user THEN { success _ FALSE; CONTINUE; } ]; IF NOT success THEN RETURN; startTime _ BasicTime.Now[]; [scene, success] _ SVViewersOnScene.LoadScene[svData, fullName, wdir]; IF success THEN { fileCamera: FileCamera; cameraName: Rope.ROPE; endTime _ BasicTime.Now[]; totalTime _ BasicTime.Period[startTime, endTime]; timeRope _ IO.PutFR[" Done in time (%r)", [integer[totalTime]]]; Feedback.Append[svData.feedback, timeRope, oneLiner]; IF scene.cameraOrder = NIL THEN fileCamera _ scene.cameras.first ELSE { cameraName _ scene.cameraOrder.first; [fileCamera, success] _ SVScene.FindFileCameraFromName[cameraName, scene]; IF NOT success THEN { fileCamera _ scene.cameras.first; Feedback.Append[svData.feedback, Rope.Cat["Camera ", cameraName, " not found"], oneLiner]; Feedback.Blink[svData.feedback]; }; }; svData.scene _ scene; SVSelections.KillSkitterAndSelections[editToolData]; drawStyle _ SVEvent.CurrentStyle[svData]; svData.camera _ SVScene.CreateCamera[scene.coordSysRoot, CoordSys.CopyCoordSysFromAnyTree[oldScreenCS, "SCREEN", NIL, NIL], drawStyle]; SVScene.StuffCameraFromFileCamera[svData.camera, fileCamera, svData.camera.style, scene]; SceneOldVersion[svData]; UpdateHeader[fullName, svData]; EraseAndDrawScene[svData]; SVEvent.Selected[event, svData]; }; }; -- end of Get Store: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { editToolData: EditToolData _ NARROW[svData.editToolData]; wdir: Rope.ROPE; success: BOOL; picName: Rope.ROPE _ NARROW[event.rest.first]; fullName: Rope.ROPE; scene: Scene _ svData.scene; IF Rope.Length[picName] = 0 THEN RETURN; wdir _ editToolData.originalWorkingDirectory; success _ TRUE; [fullName,,] _ FS.ExpandName[picName, wdir ! FS.Error => IF error.group = user THEN { success _ FALSE; CONTINUE; } ]; IF NOT success THEN RETURN; success _ SVViewersOnScene.StoreScene[svData, scene, fullName]; IF success THEN { UpdateHeader[fullName, svData]; SVEvent.Selected[event, svData]; SceneOldVersion[svData]; UpdateHeader[scene.name, svData]; }; }; -- end of Store Split: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { scene: Scene _ svData.scene; SVViewersOnScene.Split[svData, scene]; }; OpenScript: PUBLIC Menus.ClickProc = { svData: SVData _ NARROW[clientData]; name: Rope.ROPE _ ViewerTools.GetSelectionContents[]; SVSessionLog.OpenScript[name, svData]; IF svData.debug.logStream#NIL THEN [] _ SlackProcess.EnableSessionLogging[svData.slackHandle]; }; AppendToScript: PUBLIC Menus.ClickProc = { svData: SVData _ NARROW[clientData]; name: Rope.ROPE _ ViewerTools.GetSelectionContents[]; SVSessionLog.AppendScript[name, svData]; IF svData.debug.logStream#NIL THEN [] _ SlackProcess.EnableSessionLogging[svData.slackHandle]; }; CloseScript: PUBLIC Menus.ClickProc = { svData: SVData _ NARROW[clientData]; [] _ SlackProcess.DisableSessionLogging[svData.slackHandle]; SVSessionLog.CloseScript[svData]; }; PlaybackScript: PUBLIC Menus.ClickProc = { svData: SVData _ NARROW[clientData]; name: Rope.ROPE _ ViewerTools.GetSelectionContents[]; SVSessionLog.PlaybackFromFile[name, svData]; }; FastPlayScript: PUBLIC Menus.ClickProc = { svData: SVData _ NARROW[clientData]; name: Rope.ROPE _ ViewerTools.GetSelectionContents[]; SVUserInput.EventNotify[svData, LIST[$DisableRefresh]]; SVSessionLog.PlaybackFromFile[name, svData]; SVUserInput.EventNotify[svData, LIST[$EnableRefresh]]; SVUserInput.EventNotify[svData, LIST[$Refresh, $DoNotClearFeedback]]; }; RayCast: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { editToolData: EditToolData _ NARROW[svData.editToolData]; scene: Scene _ svData.scene; camera: Camera _ svData.camera; feedback: FeedbackData _ svData.feedback; tree: CSGTree; startTime: BasicTime.GMT; afterTreeTime: BasicTime.GMT; endTime: BasicTime.GMT; totalTime: INT; msgRope, wdir: Rope.ROPE; aisFileRope: Rope.ROPE; success: BOOL; maxRed, maxGreen, maxBlue, maxBlack: NAT; aisFileRope _ Rope.Concat[SVFiles.FilenameMinusExtension[scene.name], ".ais"]; wdir _ editToolData.originalWorkingDirectory; success _ TRUE; [aisFileRope,,] _ FS.ExpandName[aisFileRope, wdir ! FS.Error => IF error.group = user THEN { Feedback.Append[svData.feedback, Rope.Concat["RayCast: ", error.explanation], oneLiner]; success _ FALSE; CONTINUE; } ]; IF NOT success THEN RETURN; startTime _ BasicTime.Now[]; tree _ DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera]; afterTreeTime _ BasicTime.Now[]; totalTime _ BasicTime.Period[from: startTime, to: afterTreeTime]; Feedback.PutF[svData.feedback, oneLiner, "Building tree took (%r)",[integer[totalTime]]]; [success, maxRed, maxGreen, maxBlue, maxBlack] _ SVCastRays.DrawTree[tree, scene.lightSources, camera, aisFileRope, TRUE, SVEvent.RayCastProgress, svData, feedback]; IF NOT success THEN { Feedback.PutF[feedback, end, "...Raycast aborted."]; RETURN; }; endTime _ BasicTime.Now[]; totalTime _ BasicTime.Period[from: afterTreeTime, to: endTime]; Feedback.PutF[svData.feedback, begin, " Raycast took (%r).",[integer[totalTime]]]; msgRope _ IO.PutFR[" Max values were: red: (%g) green: (%g) blue: (%g) black: (%g)\n", [integer[maxRed]], [integer[maxGreen]], [integer[maxBlue]], [integer[maxBlack]]]; Feedback.AppendTypescript[svData.feedback, msgRope, end]; SVEvent.DrawBlackAndWhite[event, svData]; }; -- end of RayCast StopRays: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { camera: Camera _ svData.camera; camera.abort _ TRUE; }; ARay: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; outHandle: IO.STREAM _ Feedback.GetTypescriptStream[$Solidviews]; x, y: REAL; tree: CSGTree _ DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera]; color: Color; [x, y] _ SVUtility.ReadTwoReals[svData.textSection.xyz]; color _ SVCastRays.SingleRay[[x, y], tree, scene.lightSources, camera, svData.feedback, TRUE]; Feedback.PutFTypescript[svData.feedback, begin, "[%g,%g]: ",[real[x]], [real[y]]]; TFO3d.FileoutColor[outHandle, color]; Feedback.PutFTypescript[svData.feedback, end, "\n"]; }; -- end of ARay DrawCoordSystems: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { SVWindow.RestoreScreenAndInvariants[$DrawCoordSystems, svData]; }; DrawBoundBoxes: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { SVWindow.RestoreScreenAndInvariants[$DrawBoundBoxes, svData]; }; -- end of DrawBoundBoxes DrawBoundSpheres: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { SVWindow.RestoreScreenAndInvariants[$DrawBoundSpheres, svData]; }; -- end of DrawBoundSpheres DrawPt: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { camera: Camera _ svData.camera; SVWindow.RestoreScreenAndInvariants[$DrawPt, svData]; }; CrossHairs: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { SVWindow.RestoreScreenAndInvariants[$DrawCrossHairs, svData]; }; -- end of CrossHairs TestGravity: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { xRandomStream, yRandomStream: Random.RandomStream; testPoint: Point2d; pointCount: INT _ NARROW[event.rest.first, REF INT]^; x, y: INT; totalCount, hitCount, diffCount: NAT _ 0; surfacePtWORLD: Point3d; camera: Camera _ svData.camera; scene: Scene _ svData.scene; screenCS: CoordSystem _ camera.screenCS; feature: FeatureData; gravityType: GravityType _ SVState.GetGravityType[svData]; xRandomStream _ Random.Create[svData.actionArea.cw]; yRandomStream _ Random.Create[svData.actionArea.ch]; UNTIL totalCount >= pointCount DO x _ Random.NextInt[xRandomStream]; y _ Random.NextInt[yRandomStream]; testPoint _ [x, y]; testPoint _ CoordSys.ScreenToCamera[testPoint, screenCS]; svData.refresh.spotPoint _ testPoint; [surfacePtWORLD, ----, feature] _ SVGravity.RayMap[testPoint, svData.hitTest.criticalR, NIL, svData.hitTest.sceneBag, svData]; totalCount _ totalCount + 1; IF feature = NIL THEN { SVWindow.RestoreScreenAndInvariants[paintAction: $PaintSpot, svData: svData]; } ELSE { hitCount _ hitCount + 1; svData.refresh.hitPoint _ surfacePtWORLD; SVWindow.RestoreScreenAndInvariants[paintAction: $PaintHitLine, svData: svData]; }; ENDLOOP; Feedback.PutF[svData.feedback, oneLiner, "Tested %g total points. %g hits.", [integer[totalCount]], [integer[hitCount]]]; }; -- end TestGravity ResetStatistics: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { CodeTimer.ResetTable[CodeTimer.GetTable[$Solidviews]]; }; PrintStatistics: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { f: IO.STREAM _ Feedback.GetTypescriptStream[$Solidviews]; CodeTimer.PrintTable[f, CodeTimer.GetTable[$Solidviews]]; }; END. ΌFile: SVEventImplA.mesa Author: Eric Bier in October 1982 Copyright c 1984 by Xerox Corporation. All rights reserved. Last edited by Bier on May 7, 1987 3:26:22 pm PDT Contents: Code to respond to button presses made in an SVViewer Gravity Line Operations Alignment Lines MISCELLANEOUS Tell EditTool that scene is no longer dirty. EditTool will call back all affected viewers using OldVersion (see below). DRAW SOMETHING IN A SOLID VIEWER (Fetches a display context first) MENU PROCS Creates a new empty scene for the viewer to view. This must be done after NotifyOfEmpty since SVViewersOnScene expects to register to the newly created NoName scene before it resets the [New Version] headers. Reload this scene from its backing file. TIMING VARIABLES START TIMING END TIMING aisName _ Rope.Concat[SVFiles.FilenameMinusExtension[fullName], ".ais"]; Create a new viewer onto this scene. Update the ring of links joining all viewers onto this scene, Script Menu in SVEventImplA.OpenScript IF mouseButton = red OR mouseButton = blue THEN { [success, maxRed, maxGreen, maxBlue, maxBlack] _ SVCastRays.DrawTree[tree, scene.lightSources, camera, aisFileRope, mouseButton = blue, SVEvent.RayCastProgress, svData, feedback]; } ELSE { -- yellow bug cameraPoint: Point2d; [cameraPoint, ----] _ SVSelections.GetPositionSkitter[]; [success, maxRed, maxGreen, maxBlue, maxBlack] _ SVCastRays.DrawTreeWithStartLine[cameraPoint[2], tree, scene.lightSources, camera, aisFileRope, mouseButton = blue, SVEvent.RayCastProgress, svData, feedback]; }; Get x and y from appropriate slots. Interpret this as camera coordinates and draw a cross. viewer is Container get x and y from appropriate slots. Interpret this as camera coordinates and draw a cross. viewer is the crossHairs button Within the bounds of the viewer, randomly choose mouse positions. See if that mouse position is in range of any object. If so, draw a dot at that point. Repeat until 100 points have been drawn. Κ}˜Iheadšœ™Jšœ!™!Jšœ Οmœ1™Jšœ žœ˜Jšœžœ˜Jšœ˜Jšœ5˜5Jšœ8˜8šžœ žœ˜Jšœ ˜ Jšœ˜Jšœ!˜!Jšœ˜—Jšœ ˜J˜—šŸœžœžœ žœžœžœžœ˜=Jšœžœ˜9Jšœ žœ˜Jšœžœžœ˜.Jšœžœ˜Jšœ žœ˜Jšœ ˜ Jšœ2˜2Jšœ™Jšœ˜Jšœ˜Jšœ žœ˜Jšœžœ˜Jšœ˜J˜Jšžœžœžœ˜(Jš‘œ)˜-Jšœ žœ˜šœ‘œžœ˜*šœžœ žœžœ˜*Jšœ žœ˜Jšžœ˜ J˜—Jšœ˜—Jšžœžœ žœžœ˜Jšœ ™ Jš‘˜Jšœ‘œ˜Fšžœ žœ˜Jšœ˜Jšœžœ˜™ Jš‘˜Jšœ1˜1Jšœ@˜@Jšœ5˜5—J˜Jšžœžœžœ!˜@šžœ˜Jšœ%˜%JšœJ˜Jšžœžœ žœ˜Jšœ!˜!JšœZ˜ZJšœ ˜ J˜—J˜—Jšœ˜Jšœ4˜4Jšœ)˜)Jšœqžœžœ˜‡JšœY˜YJšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜—Jšœ ˜J˜—šŸœžœžœ žœžœžœžœ˜?Jšœžœ˜9Jšœ žœ˜Jšœ žœ˜Jšœžœžœ˜.Jšœžœ˜Jšœ˜J˜Jšžœž œ˜(Jšœ-˜-Jšœ žœ˜šœžœ˜*šœžœ žœžœ˜*Jšœ žœ˜Jšžœ˜ J˜—Jšœ˜—Jšžœžœ žœžœ˜Jšœ?˜?šžœ žœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ!˜!JšœH™HJ˜—Jšœ ˜J˜—šŸœžœžœ žœžœžœžœ˜?Jšœc™cJšœ˜Jšœ&˜&Jšœ˜—J˜™ Lšœ™—šŸ œžœ˜&Mšœžœ ˜$Mšœ žœ&˜5Mšœ&˜&Mšžœžœžœ<˜^L˜—šŸœžœ˜*Mšœžœ ˜$Mšœ žœ&˜5Mšœ(˜(Mšžœžœžœ<˜^L˜—šŸ œžœ˜'Mšœžœ ˜$Mšœ<˜šœ˜Jšœ˜Jšœ žœžœ-˜AJšœ[™[Jšœžœ˜ JšœP˜PJšœ ˜ Jšœ8˜8JšœVžœ˜^JšœR˜RJšœ%˜%Jšœ4˜4Jšœ ˜——J˜šŸœžœžœ žœžœžœžœ˜JJšœ?˜?Jšœ˜J˜—šŸœžœžœ žœžœžœžœ˜HJšœ™Jšœ=˜=Jšœ ˜J˜—šŸœžœžœ žœžœžœžœ˜JJšœ?˜?Jšœ ˜—J˜šŸœžœžœ žœžœžœžœ˜@Jšœ˜Jšœ[™[Jšœ5˜5Jšœ˜—šŸ œžœžœ žœžœžœžœ˜DJšœ™Jšœ=˜=Jšœ˜J˜—šŸ œžœžœ žœžœžœžœ˜EM™ΔMšœ2˜2Mšœ˜Mš œ žœžœžœžœ˜5Mšœžœ˜ Mšœ!žœ˜)Mšœ Οuœ ˜Mšœ˜Mšœ˜Mšœ(˜(Mšœ˜Mšœ:˜:M˜Mšœ4˜4Mšœ4˜4šžœž˜!Mšœ"˜"Mšœ"˜"M˜Mšœ9˜9Mš‘%˜%Mšœ œCžœ#˜~M˜šžœ žœžœ˜MšœM˜MM˜—šžœ˜M˜Mšœ#’œ˜)MšœP˜PM˜—Mšžœ˜—Mšœz˜zMšœ ˜M˜—šŸœžœžœ žœžœžœžœ˜IMšœ6˜6M˜—šŸœžœžœ žœžœžœžœ˜IMšœžœžœ-˜9Mšœ9˜9M˜—J˜Jšžœ˜J˜—…—ED`}