DIRECTORY CodeTimer, Feedback, Imager, ImagerBackdoor, ImagerPath, IO, Matrix3d, Rope, SV2d, SV3d, SVAlign, SVAssembly, SVBasicTypes, SVCaret, SVDescribe, SVGraphics, SVGravity, SVInterfaceTypes, SVModelTypes, SVMouseEvent, SVRefresh, SVScene, SVSceneTypes, SVSelect, SVState, SVWindow, TIPUser, ViewerClasses; SVMouseEventImplB: CEDAR PROGRAM IMPORTS CodeTimer, SVGraphics, Feedback, Imager, ImagerBackdoor, Matrix3d, Rope, SVAlign, SVAssembly, SVCaret, SVDescribe, SVGravity, SVRefresh, SVScene, SVSelect, SVState, SVWindow EXPORTS SVMouseEvent = BEGIN ArtworkToolData: TYPE = SVInterfaceTypes.ArtworkToolData; BoundBox: TYPE = SVBasicTypes.BoundBox; Camera: TYPE = SVModelTypes.Camera; Classification: TYPE = SVSceneTypes.Classification; CoordSystem: TYPE = SVModelTypes.CoordSystem; EditToolData: TYPE = SVInterfaceTypes.EditToolData; ExtendMode: TYPE = SVSceneTypes.ExtendMode; FeatureData: TYPE = SVInterfaceTypes.FeatureData; FileCamera: TYPE = SVSceneTypes.FileCamera; FrameBox: TYPE = SVModelTypes.FrameBox; MasterObject: TYPE = SVSceneTypes.MasterObject; Matrix4by4: TYPE = SV3d.Matrix4by4; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Primitive: TYPE = SVSceneTypes.Primitive; Ray: TYPE = SVSceneTypes.Ray; Scene: TYPE = SVSceneTypes.Scene; Selection: TYPE = SVInterfaceTypes.Selection; SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator; SelectMode: TYPE = SVSceneTypes.SelectMode; Skitter: TYPE = SVSceneTypes.Skitter; SkitterMode: TYPE = SVSceneTypes.SkitterMode; Slice: TYPE = SVSceneTypes.Slice; SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor; ToolData: TYPE = SVSceneTypes.ToolData; TrigLine: TYPE = SV2d.TrigLine; Vector3d: TYPE = SV3d.Vector3d; SVData: TYPE = SVInterfaceTypes.SVData; MouseProc: TYPE = SVMouseEvent.MouseProc; StartProc: TYPE = SVMouseEvent.StartProc; Problem: SIGNAL [msg: Rope.ROPE] = Feedback.Problem; FrameUpLeft: PUBLIC StartProc = { camera: Camera _ svData.camera; camera.frame.fullScreen _ FALSE; camera.frame.downLeft[1] _ cameraPoint[1]; camera.frame.upRight[2] _ cameraPoint[2]; camera.frame.downLeft[2] _ cameraPoint[2] - 50.0; -- Just to give the frame an initial size. camera.frame.upRight[1] _ cameraPoint[1] + 50.0; SVWindow.RestoreScreenAndInvariants[$DuringMotion, svData]; }; FrameDownRightMove: PUBLIC MouseProc = { camera: Camera _ svData.camera; DoDrawFrame: PROC [dc: Imager.Context] = { Imager.SetColor[dc, ImagerBackdoor.invert]; SVGraphics.DrawFrame [dc, camera]; }; camera.frame.downLeft[2] _ cameraPoint[2]; camera.frame.upRight[1] _ cameraPoint[1]; SVWindow.RestoreScreenAndInvariants[$DuringMotion, svData]; }; FrameDownRightEnd: PUBLIC MouseProc = { camera: Camera _ svData.camera; fileCamera: FileCamera; success: BOOL; FrameDownRightMove[event, svData, cameraPoint]; [fileCamera, success] _ SVScene.FindFileCameraFromName[camera.viewName, svData.scene]; IF success THEN { fileCamera.frame.downLeft _ camera.frame.downLeft; fileCamera.frame.upRight _ camera.frame.upRight; fileCamera.frame.fullScreen _ FALSE; }; }; DeleteFrame: PUBLIC MouseProc = { camera: Camera _ svData.camera; frame: FrameBox _ camera.frame; DoDrawFrame: PROC [dc: Imager.Context] = { Imager.SetColor[dc, ImagerBackdoor.invert]; SVGraphics.DrawFrame [dc, camera]; }; SVWindow.RestoreScreenAndInvariants[$FrameChanged, svData]; frame.fullScreen _ TRUE; }; SaveSavedState: PROC [svData: SVData] = { SVScene.SaveSelections[svData.scene]; }; StartSelectJoint: PUBLIC StartProc = { svData.drag.selectState _ joint; StartSelectAux[svData, cameraPoint]; DuringSelect[NIL, svData, cameraPoint]; }; StartSelectSegment: PUBLIC StartProc = { svData.drag.selectState _ segment; StartSelectAux[svData, cameraPoint]; DuringSelect[NIL, svData, cameraPoint]; }; StartSelectTraj: PUBLIC StartProc = { svData.drag.selectState _ traj; StartSelectAux[svData, cameraPoint]; DuringSelect[NIL, svData, cameraPoint]; }; StartSelectTopLevel: PUBLIC StartProc = { svData.drag.selectState _ topLevel; StartSelectAux[svData, cameraPoint]; DuringSelect[NIL, svData, cameraPoint]; }; StartSelectAux: PROC [svData: SVData, cameraPoint: Point2d] = { IF NOT SVRefresh.EmptyOverlay[svData] THEN ERROR; SaveSavedState[svData]; }; DuringSelect: PUBLIC MouseProc = { opRope: Rope.ROPE = "Selecting "; worldPt: Point3d; normalVec: Vector3d; feature: FeatureData; hitData: REF ANY; scene: Scene _ svData.scene; selectMode: SelectMode _ SVState.GetSelectMode[svData]; SELECT selectMode FROM joint => [worldPt, normalVec, feature, hitData] _ SVGravity.PointsPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE]; segment => [worldPt, normalVec, feature, hitData] _ SVGravity.LinesPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE]; traj, topLevel => [worldPt, normalVec, feature, hitData] _ SVGravity.FacesPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData]; ENDCASE => ERROR; SetCaretAttractorEndpoint[svData, cameraPoint, worldPt, normalVec, feature, hitData]; SVSelect.DeselectAll[scene, normal]; IF feature#NIL THEN SelectAndDescribeSlicePart[feature, hitData, worldPt, svData, selectMode, opRope] ELSE DescribeOperationOnNothing[svData, opRope]; SVWindow.RestoreScreenAndInvariants[paintAction: $DuringSelect, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; -- end DuringSelect SelectAndDescribeSlicePart: PUBLIC PROC [feature: FeatureData, hitData: REF ANY, hitPoint: Point3d, svData: SVData, mode: SelectMode, opRope: Rope.ROPE] = { selectedD: REF ANY _ SelectSlicePart[feature, hitData, hitPoint, svData, mode]; description: Rope.ROPE _ WITH selectedD SELECT FROM sliceD: SliceDescriptor => SVAssembly.Describe[sliceD], ENDCASE => SVDescribe.DescribeFeature[feature, hitData, svData]; Feedback.PutFHerald[svData.feedback, oneLiner, "%g %g", [rope[opRope]], [rope[description]] ]; }; SelectSlicePart: PUBLIC PROC [feature: FeatureData, hitData: REF ANY, hitPoint: Point3d, svData: SVData, mode: SelectMode] RETURNS [selectedD: REF ANY] = { SELECT feature.type FROM slice => { slice: Slice _ NARROW[feature.shape, SliceDescriptor].slice; selectedSliceD: SliceDescriptor; selectedSliceD _ SVAssembly.NewParts[slice, hitData, hitPoint, mode]; SVSelect.SelectSlice[selectedSliceD, svData.scene, normal]; selectedD _ selectedSliceD; }; slopeLine, angleLine, distanceLine, intersectionPoint, radiiCircle, midpoint => ERROR; ENDCASE => ERROR Problem[msg: "unimplemented result type"]; }; DescribeOperationOnNothing: PUBLIC PROC [svData: SVData, opRope: Rope.ROPE] = { Feedback.PutFHerald[svData.feedback, oneLiner, "%g %g", [rope[opRope]], [rope["nothing"]] ]; }; SetCaretAttractorEndpoint: PUBLIC PROC [svData: SVData, cameraPoint: Point2d, worldPt: Point3d, normal: Vector3d, feature: FeatureData, hitData: REF ANY] = { sliceD: SliceDescriptor; skitter: Skitter _ svData.editToolData.skitter; sliceD _ IF feature = NIL THEN NIL ELSE NARROW[feature.shape]; IF feature=NIL THEN SVCaret.SetAttractor[skitter, cameraPoint, worldPt, normal, sliceD] ELSE { shape: REF ANY _ feature.shape; SELECT feature.type FROM slice => { jointPos: Point3d; jointNormal: Vector3d; sliceD: SliceDescriptor _ NARROW[shape]; jointD: SliceDescriptor; [jointD, jointPos, jointNormal] _ SVAssembly.ClosestJointToHitData[sliceD, worldPt, normal, hitData]; SVCaret.SetAttractor[skitter, cameraPoint, jointPos, jointNormal, sliceD]; }; ENDCASE => SVCaret.SetAttractor[skitter, cameraPoint, worldPt, normal, sliceD]; }; }; EndSelect: PUBLIC MouseProc = { pointWorld: Point3d; normalWorld: Vector3d; feature: FeatureData; hitData: REF ANY; scene: Scene _ svData.scene; featureCycler: SVGravity.FeatureCycler; selectMode: SelectMode _ SVState.GetSelectMode[svData]; SELECT selectMode FROM joint => featureCycler _ SVGravity.PointsPreferredCycler[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE, 1]; segment => featureCycler _ SVGravity.LinesPreferredCycler[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE, 1]; traj, topLevel => { featureCycler _ SVGravity.FacesPreferredCycler[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData]; }; ENDCASE => ERROR; [pointWorld, normalWorld, feature, hitData] _ SVGravity.FirstFeature[featureCycler]; SVState.SetSelectionCycler[svData, featureCycler]; SelectFromFeature[svData, cameraPoint, pointWorld, normalWorld, feature, hitData]; }; -- end EndSelect SelectFromFeature: PUBLIC PROC [svData: SVData, cameraPt: Point2d, pointWorld: Point3d, normalWorld: Vector3d, feature: FeatureData, hitData: REF ANY] = { selectMode: SelectMode _ SVState.GetSelectMode[svData]; scene: Scene _ svData.scene; SetCaretAttractorEndpoint[svData, cameraPt, pointWorld, normalWorld, feature, hitData]; SVWindow.NewCaretPos[svData]; SVSelect.DeselectAll[scene, normal]; SELECT selectMode FROM joint => EndSelectAux[svData, cameraPt, feature, hitData, pointWorld, joint, "joint"]; segment => EndSelectAux[svData, cameraPt, feature, hitData, pointWorld, segment, "segment"]; traj => EndSelectAux[svData, cameraPt, feature, hitData, pointWorld, traj, "trajectory"]; topLevel => EndSelectAux[svData, cameraPt, feature, hitData, pointWorld, topLevel, "object"]; ENDCASE => ERROR; }; EndSelectAux: PROC [svData: SVData, cameraPoint: Point2d, feature: FeatureData, hitData: REF ANY, hitPoint: Point3d, mode: SelectMode, opName: Rope.ROPE] = { IF feature = NIL THEN { Feedback.PutFHerald[svData.feedback, oneLiner, "No near %g found.", [rope[opName]]]; } ELSE { SELECT mode FROM joint => SVState.SetExtendMode[svData, joint]; segment => SVState.SetExtendMode[svData, segmentRange]; traj => SVState.SetExtendMode[svData, traj]; topLevel => SVState.SetExtendMode[svData, topLevel]; ENDCASE => ERROR; SELECT feature.type FROM slice => { sliceD: SliceDescriptor _ NARROW[SelectSlicePart[feature, hitData, hitPoint, svData, mode]]; featureCycler: SVGravity.FeatureCycler _ SVState.GetSelectionCycler[svData]; cycleCount: NAT _ featureCycler.count; IF cycleCount > 1 THEN Feedback.PutFHerald[svData.feedback, oneLiner, Rope.Concat[SVAssembly.Describe[sliceD], " selected (%g more)"], [integer[cycleCount-1]]] ELSE Feedback.AppendHerald[svData.feedback, Rope.Concat[SVAssembly.Describe[sliceD], " selected"], oneLiner]; SVState.SetSliceToExtend[svData, sliceD]; }; ENDCASE => ERROR Problem[msg: "Unexpected feature type"]; }; SVWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; -- end EndSelectAux StartExtendSelectJoint: PUBLIC StartProc = { svData.drag.extendMode _ joint; RETURN[StartExtendSelection[event, svData, cameraPoint]]; }; StartExtendSelectSegment: PUBLIC StartProc = { svData.drag.extendMode _ segment; RETURN[StartExtendSelection[event, svData, cameraPoint]]; }; StartExtendSelectTraj: PUBLIC StartProc = { svData.drag.extendMode _ traj; RETURN[StartExtendSelection[event, svData, cameraPoint]]; }; StartExtendSelectTopLevel: PUBLIC StartProc = { svData.drag.extendMode _ topLevel; RETURN[StartExtendSelection[event, svData, cameraPoint]]; }; StartExtendSelection: PUBLIC StartProc = { IF NOT SVRefresh.EmptyOverlay[svData] THEN ERROR; SaveSavedState[svData]; -- must do this before any possible aborts occur svData.drag.currentPoint _ cameraPoint; svData.drag.transform _ Matrix3d.Identity[]; DuringExtendSelection[NIL, svData, cameraPoint]; }; DuringExtendSelection: PUBLIC MouseProc= { opRope: Rope.ROPE = "Extending to "; surfacePtWorld: Point3d; normalWorld: Vector3d; feature: FeatureData; hitData: REF ANY; scene: Scene _ svData.scene; extendMode: ExtendMode _ SVState.GetExtendMode[svData]; CodeTimer.StartInt[$DuringExtendSelection, $Solidviews]; SELECT extendMode FROM joint => { [surfacePtWorld, normalWorld, feature, hitData] _ SVGravity.PointsPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE]; }; segment, segmentRange => { [surfacePtWorld, normalWorld, feature, hitData] _ SVGravity.LinesPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE]; }; traj, slice, topLevel => { [surfacePtWorld, normalWorld, feature, hitData] _ SVGravity.FacesPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData]; }; ENDCASE => ERROR; SetCaretAttractorEndpoint[svData, cameraPoint, surfacePtWorld, normalWorld, feature, hitData]; SVSelect.DeselectAll[scene, normal]; SVScene.RestoreSelections[scene]; IF feature#NIL THEN { SELECT extendMode FROM joint, segment, segmentRange, traj, topLevel => DuringExtendSelectionFeedback[feature, hitData, surfacePtWorld, svData]; slice, none => NULL; ENDCASE => ERROR; } ELSE DescribeOperationOnNothing[svData, opRope]; SVWindow.RestoreScreenAndInvariants[paintAction: $DuringSelect, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; CodeTimer.StopInt[$DuringExtendSelection, $Solidviews]; }; -- end DuringExtendSelection DuringExtendSelectionFeedback: PROC [feature: FeatureData, hitData: REF ANY, hitPoint: Point3d, svData: SVData] = { opRope: Rope.ROPE _ "Extending to "; SELECT svData.drag.extendMode FROM joint, segment, traj, topLevel => [] _ SelectAndDescribeSlicePart[feature, hitData, hitPoint, svData, SVState.GetExtendMode[svData], opRope]; segmentRange => { GOTO RegularSelectMechanism; EXITS RegularSelectMechanism => [] _ SelectAndDescribeSlicePart[feature, hitData, hitPoint, svData, segment, opRope]; }; ENDCASE => ERROR; -- should have been weeded about before calling this Proc }; EndExtendSelection: PUBLIC MouseProc = { SVWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; -- end EndExtendSelection InitStats: PROC [] = { interval: CodeTimer.Interval; interval _ CodeTimer.CreateInterval[$DuringExtendSelection]; CodeTimer.AddInt[interval, $Solidviews]; }; InitStats[]; END. €File: SVMouseEventImplB.mesa Last edited by Bier on July 10, 1987 12:17:54 pm PDT Copyright c 1984 by Xerox Corporation. All rights reserved. Contents: Procedures for responding to button clicks made in a solidviewer. Bloomenthal, June 16, 1987 7:29:53 pm PDT Controlpoint is in camera coordinates. Controlpoint is in camera coordinates. Draw the new frame. Once last update with the final position. Tell the appropriate file camera about the new frame. Erase the old frame. SVWindow.SaveCaretPos[gargoyleData]; SVCaret.Copy[from: svData.caret, to: svData.drag.savedCaret]; Selection Procs While a joint, segment, traj, or top level object is being selected, gravity is forced to be StrictDistance. The object bag should consist only of trajectories and slices. The caret is moved to the segment endpoint of the nearest segment or traj as appropriate or tracks the cursor if none are nearby. Feedback is in the form of highlighted joints. Find out which point is being selected and highlight it. Prepare for a subsequent Add operation and for Extend. GGCaret.SitOn[svData.caret, NIL]; Make Selection and Prepare for Extend. IF mode = traj OR mode = topLevel THEN GGCaret.SitOn[svData.caret, NIL] ELSE GGCaret.SitOn[svData.caret, sliceD]; Extend selection procs. Put Caret on a joint (if any). Reselect all. depending on extend mode, check if feature is in that mode, then select the new feature. ส ˜Iheadšœ™Jšœ4™4Jšœ ฯmœ1™<šœK™KIcode™)—J˜šฯk ˜ Jšœ9žœ๑˜ฌ—J˜šœž ˜ Jšžœฎ˜ตJšžœ˜—J˜šž˜Jšœžœ$˜9Jšœ žœ˜'Jšœžœ˜#Jšœžœ˜3Jšœ žœ˜-Jšœžœ!˜3Jšœ žœ˜+Jšœ žœ ˜1Jšœ žœ˜+Jšœ žœ˜'Jšœžœ˜/Jšœ žœ˜#Jšœ žœ˜Jšœ žœ˜Jšœ žœ˜)Jšœžœ˜Jšœžœ˜!Jšœ žœ˜-Jšœžœ'˜?Jšœ žœ˜+Jšœ žœ˜%Jšœ žœ˜-Jšœžœ˜!Jšœžœ ˜5Jšœ žœ˜'Jšœ žœ˜Jšœ žœ˜Jšœžœ˜'J˜Lšœ žœ˜)Lšœ žœ˜)Lšฯnœžœ žœ˜4J˜—J˜šŸ œžœ˜!Jšœ&™&Jšœ˜Jšœžœ˜ Jšœ*˜*Jšœ)˜)Jšœ2ฯc*˜\Jšœ0˜0Jšœ;˜;Jšœ˜J˜—šŸœžœ˜(Jšœ&™&Jšœ˜šŸ œžœ˜*J˜+Jšœ"˜"Jšœ˜—Jšœ*˜*šœ)˜)J™—Jšœ;˜;Jšœ˜J˜—šŸœžœ˜'Jšœ˜Jšœ˜Jšœ žœ˜šœ/˜/J™)J™5—JšœV˜Všžœ žœ˜Jšœ2˜2Jšœ0˜0Jšœžœ˜$J˜—Jšœ˜J˜—šŸ œžœ ˜!Jšœ˜Jšœ˜šŸ œžœ˜*Jšœ+˜+Jšœ"˜"Jšœ˜J™—Jšœ;˜;Jšœžœ˜Jšœ˜J˜—J˜šŸœžœ˜)Lšœ%˜%Lšœ$™$Lšœ=™=L˜L˜—L˜L™šŸœžœ˜&Lšœ ˜ Lšœ$˜$Lšœ žœ˜'L˜L˜—šŸœžœ˜(Lšœ"˜"Lšœ$˜$Lšœ žœ˜'L˜L˜—šŸœžœ˜%Lšœ˜Lšœ$˜$Lšœ žœ˜'L˜L˜—šŸœžœ˜)Lšœ#˜#Lšœ$˜$Lšœ žœ˜'L˜L˜—šŸœžœ+˜?Lšžœžœ žœžœ˜1Lšœ˜L˜L˜—šŸ œžœ˜"L™฿Lšœ žœ˜!Lšœ˜L˜Lšœ˜Lšœ žœžœ˜L˜Lšœ7˜7L˜šžœ ž˜Lšœฃžœ˜ฉLšœคžœ˜ชLšœซ˜ซLšžœžœ˜—LšŸœ<˜ULšœ ฯb œ˜$Lšžœ žœžœSžœ,˜–Lšœižœ žœžœ˜˜Lšœ˜L˜—š Ÿœžœžœ!žœžœDžœ˜œLšœ žœžœ=˜Ošœžœžœ žœž˜3L˜7Lšžœ9˜@—Lšœ^˜^L˜L˜—šŸœžœžœ!žœžœ7žœ žœžœ˜›L™8šžœž˜šœ ˜ Lšœžœ'˜Lšžœ žœžœD˜Wšžœ˜Lšœžœžœ˜šžœž˜šœ ˜ Lšœ˜Lšœ˜Lšœžœ˜(Lšœ˜Lšœe˜eLšœJ˜JL˜—LšžœH˜O—L˜—L˜L˜—šŸ œžœ˜Lšœฯuœ ˜Lšœขœ ˜Lšœ˜Lšœ žœžœ˜Lšœ˜L˜'Lšœ7˜7L˜šžœ ž˜Lšœžœ˜™Lšœ‘žœ˜ššœ˜Lšœ†˜†L˜—Lšžœžœ˜—Lšœขœขœ<˜TLšœ2˜2Lšœ,ขœขœ˜RLšœ ˜L˜—šŸœžœžœ*ขœขœ+žœžœ˜šLšœ7˜7Lšœ˜Lšœ1ขœขœ˜WLšœ˜Lšœ$˜$šžœ ž˜Lšœ?ขœ˜VLšœAขœ˜\Lšœ>ขœ˜YLšœBขœ˜]Lšžœžœ˜—L˜L˜—š Ÿ œžœGžœžœ4žœ˜Lšก6™6šžœ žœžœ˜Lšœžœ™!LšœT˜TL˜—šžœ˜Lšก&™&šžœž˜Lšœ.˜.Lšกœ"ก œ˜7Lšœ,˜,Lšœ4˜4Lšžœžœ˜—šžœž˜˜ Lšœžœ<˜\LšœL˜LLšœ žœ˜&Lšžœ žœžœžœ™GLšžœ%™)Lšžœžœ‰˜ŸLšžœi˜mLšœ)˜)L˜—Lšžœžœ)˜9—L˜—Lšœmžœ žœžœ˜œLšœ ˜L˜—L™L™šŸ ะbnŸœžœ˜,Lšœ˜Lšžœ3˜9L˜L˜—šŸ ฃŸœžœ˜.Lšœ!˜!Lšžœ3˜9L˜L˜—šŸ ฃŸœžœ˜+Lšœ˜Lšžœ3˜9L˜L˜—šŸ ฃŸœžœ˜/Lšœ"˜"Lšžœ3˜9L˜L˜—šŸœžœ˜*Lšžœžœ žœžœ˜1Lšœ 0˜HLšœ'˜'Lšœ,˜,Lšœžœ˜0L˜L˜—šŸœžœ ˜*Lšœ žœ˜$Lšœ ขœ ˜Lšœขœ ˜Lšœ˜Lšœ žœžœ˜Lšœ˜Lšœ7˜7L˜Lšœ8˜8šžœ ž˜šœ ˜ Lšœ ขœขœ‡žœ˜ฉL˜—˜Lšœ ขœขœ†žœ˜จL˜—šœ˜Lšœ ขœขœ†˜ขL˜—Lšžœžœ˜—Lšก™Lšœ8ขœขœ˜^Lšก ™ Lšœ$˜$Lšœ!˜!šžœ žœžœ˜šžœ ž˜Lšœjขœ ˜yLšœžœ˜Lšžœžœ˜—L˜—Lšžœ,˜0Lšœižœ žœžœ˜˜Lšœ7˜7Lšœ˜L˜—šŸœžœ!žœžœ(˜sL™XLšœ žœ˜$šžœž˜"Lšœ˜šœ˜Lšžœ˜šž˜LšœŸœ6˜o—L˜—Lšžœžœ 9˜K—L˜L˜—šŸฃœžœ˜(Lšœmžœ žœžœ˜œLšœ ˜L˜—šŸ œžœ˜Jšœ˜Jšœ<˜