grep -p -po -c -i "(slice|sliceD)':\b(Slice|SliceDescriptor)\b='>" GG*.mesa!H
grep -p -po -c -i "ISTYPE'[\w',\b(OutlineDescriptor|SliceDescriptor)" GG*.mesa!H
grep -p -po -c -i "\w':\b(Slice|SliceDescriptor)\b='>" GG*.mesa!H
71 total locations found by grep. 12 need work.
[]<>candy>Bier.pa>Gargoyle>GGAlignImpl.mesa!19 (12170) UpdateBagsForNewSlices
[]<>candy>Bier.pa>Gargoyle>GGAlignImpl.mesa!19 (23194) IncrementalFilters
[]<>candy>Bier.pa>Gargoyle>GGAlignImpl.mesa!19 (30626)
[]<>candy>bier.pa>Gargoyle>GGBoundBoxImpl.mesa!5 (6406) BoundBoxOfSelected
[]<>candy>bier.pa>Gargoyle>GGBoundBoxImpl.mesa!5 (7196) BoundBoxOfMoving
[]<>candy>bier.pa>Gargoyle>GGCaretImpl.mesa!5 (2730) SittingOnEnd
SittingOnEndNEWW ready when assumptions OK
[]<>candy>Bier.pa>Gargoyle>GGEventImplA.mesa!16 (51870) Close
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (2761) Top
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (3559) Bottom
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (6226) LineWidth
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (7821) LineEnds
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (9300) TrajJoints
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (10608) DashesFromSelection
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (11794) DashesOff
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (13387) PrintStrokeValues
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!10 (20966) MakeHot
[]<>candy>bier.pa>Gargoyle>GGEventImplB.mesa!9 (23118) MakeAllHot
[]<>candy>bier.pa>Gargoyle>GGEventImplC.mesa!10 (20058) DescribeCurve
[]<>candy>bier.pa>Gargoyle>GGEventImplC.mesa!10 (20839) AddControlPoint
[]<>candy>bier.pa>Gargoyle>GGEventImplC.mesa!10 (25150) AddJoint
[]<>candy>bier.pa>Gargoyle>GGEventImplC.mesa!10 (30555) DoTheTransforms
[]<>candy>bier.pa>Gargoyle>GGEventImplC.mesa!10 (32136) AreaSelectNewAndDelete
GGEventImplC.AreaSelectNewAndDeleteNEWW should already compile
[]<>candy>bier.pa>Gargoyle>GGEventImplC.mesa!10 (34345) AreaSelectAux
[]<>candy>bier.pa>Gargoyle>GGEventImplC.mesa!10 (34971) AreaSelectAux
GGEventImplC.AreaSelectAuxNEWW should already compile.
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (18248) AreaColorToColorTool
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (18996) LineColorToColorTool
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (23162) SelectMatchingAreaColor
GGEventImplD.SelectMatchingAreaColorNEWW should already compile.
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (23162) SelectMatchingLineColor
GGEventImplD.SelectMatchingLineColorNEWW should already compile..
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (28017) PrintAreaColor
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (29326) PrintLineColor
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (31336) AreaColorAux
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (32022) LineColorAux
[]<>candy>Bier.pa>Gargoyle>GGEventImplD.mesa!12 (40422) DescribeCaretObject
[]<>candy>Bier.pa>Gargoyle>GGFileOutImpl.mesa!7 (3638) FileoutEntity
goes away.
[]<>candy>Bier.pa>Gargoyle>GGFileOutImpl.mesa!7 () FileoutSlice
FileoutSliceNEWW OK when assumptions are OK.
[]<>candy>bier.pa>Gargoyle>GGMouseEventImplA.mesa!34 (4249) SortNewEntities
[]<>candy>bier.pa>Gargoyle>GGMouseEventImplA.mesa!34 (4418) SortNewEntities
[]<>candy>bier.pa>Gargoyle>GGMouseEventImplA.mesa!34 (17887) SitOnFeature
[]<>candy>bier.pa>Gargoyle>GGMouseEventImplA.mesa!34 (21148) UpdateSceneForCopy
[]<>candy>bier.pa>Gargoyle>GGMouseEventImplA.mesa!34 (22751) TransformObjectsAfterMove
[]<>candy>bier.pa>Gargoyle>GGMouseEventImplA.mesa!34 (30917) SafelyGetCaretTraj
GGMouseEventImplA.SafelyGetCaretTrajNEWW OK when assumptions are OK..
[]<>candy>bier.pa>Gargoyle>GGMouseEventImplB.mesa!26 (8206) SelectAndDescribeTrajPart
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (7504) RefreshOverlay
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (10210) DrawAttractorFeedback
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (18040) BackmostSelectedSlice
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (19722) DrawObjects
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (20954) DrawObjectsFiltered
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (23569) PaintTightBoxes
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (31026) SnapshotBackground
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (31963) MoveToOverlay
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (32747) MoveToBackground
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (33169) MoveOverlayToBackground
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (33752) OnOverlay
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (33793) OnOverlay
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (34206) OrderOverlayList
[]<>candy>bier.pa>Gargoyle>GGRefreshImpl.mesa!17 (34997) OrderOverlayList
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (4104) EntityPriority
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (4444) UpdatePriorities
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (11417) UpOne
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (12615) DownOne
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (13558)
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (15694) ListBoxesInScene
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (16181) ListTightBoxesInScene
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (17528) ListTrajsInScene
ListTrajsInSceneNEWW OK after assumptions.
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (17961) ListOutlinesInScene
ListOutlinesInSceneNEWW OK after assumptions.
[]<>candy>Bier.pa>Gargoyle>GGSceneImpl.mesa!8 (18303) ListSlicesInScene
ListSlicesInSceneNEWW OK after assumptions.
[]<>candy>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (3429) SelectAll
[]<>candy>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (6711) DeselectAll
[]<>candy>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (7340) DeselectEntity
[]<>candy>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (7404) DeselectEntity
[]<>candy>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (13777) IsSelectedInFull
IsSelectedInFullNEWW OK after assumptions (needs isComplete class proc)
[]<>candy>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (14629) IsSelectedInPart
[]<>candy>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (21042) SelectedOutlineSequences
SelectedOutlineSequencesNEWW needs GGSelect.OutlineSequenceObj redefined.
QFind -c "$Outline" GG*.mesa!H
14 matches with QFind. 9 more cases to worry about. 21 found so far.
[]<>mouse>bier.pa>Gargoyle>GGCaretImpl.mesa!6 (2788) SittingOnEnd
[]<>mouse>Bier.pa>Gargoyle>GGEventImplA.mesa!15 (51908) Close
NEWW will work when assumptions are OK.
[]<>mouse>bier.pa>Gargoyle>GGEventImplC.mesa!10 (20889) AddControlPoint
NEWW will work when attractor is a SliceDescriptor
[]<>mouse>bier.pa>Gargoyle>GGEventImplC.mesa!10 (25200) AddJoint
NEWW will work when attractor is a SliceDescriptor
[]<>mouse>Bier.pa>Gargoyle>GGFileInImpl.mesa!6 (5839) FileinEntity
Unify with GGFileInImpl.FileInSlice. Careful of version management.
[]<>mouse>bier.pa>Gargoyle>GGMouseEventImplB.mesa!26 (7263) EndSelectAux
EndSelectAuxNEWW should work using SitTheCaretNEWW
[]<>mouse>bier.pa>Gargoyle>GGMouseEventImplB.mesa!26 (9649) SitTheCaret
SitTheCaretNEWW should be checked for correctness
[]<>mouse>Bier.pa>Gargoyle>GGOutlineImplA.mesa!21 (4213) MakeOutlineClass
Update as needed
[]<>mouse>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (8082) DeselectEntireSlice
NEWW version should work after assumptions
[]<>mouse>bier.pa>Gargoyle>GGSelectImpl.mesa!7 (13817) IsSelectedInFull
[]<>mouse>Bier.pa>Gargoyle>GGSliceImplA.mesa!12 (76656) UpdateDescriptorBoundBoxes
This proc should go away when GGSlice.UpdateDescriptorBoundBoxes handles all types
[]<>mouse>Bier.pa>Gargoyle>GGSliceImplA.mesa!12 (77438) SegmentsInDescriptor
NEWW version should compile now; will work when assumptions are OK
[]<>mouse>Bier.pa>Gargoyle>GGSliceImplA.mesa!12 (77858) WalkSegments
NEWW version should compile now; will work when assumptions are OK
ASSUMPTIONS:
caret.chair becomes SliceDescriptor - GGInterfaceTypes
caret.attractor becomes SliceDescriptor - GGInterfaceTypes
GGSelect.SelectedStuff returns SliceDescriptorGenerator - is this different from GGSelect.SelectedSlices ??
GGScene.TopLevelEntitiesInScene returns SliceGenerator - is this different from TopLevelSlicesInScene ??
GGSelect.IsSelectedInFull takes Slice - GGSelectImpl
Implement WalkSegments for Outline class - GGOutlineImplA.
class fileout procs do everything except class name - GGFileOutImpl
Check GGMouseEventImplB.EndSelectAuxNEW and SitTheCaretNEW for correctness.
Check GGSelectImpl and collapse slice/outline specific procs as needed.
Get rid of all the List.Mubles for LIST OF SliceDescriptor; use GGUtility instead.
implement IsEmpty, IsComplete for all slices. GGSliceImpl*
RENAME class proc emptyParts to IsEmpty - GGModelTypes.
create new class proc IsComplete - GGModelTypes.
write GGOutline.TrajectoriesOfOutline to return LIST OF Traj - GGOutlineImplB.
scene.entities RETURNS LIST OF Slice - GGSceneType.
GGOutline.SaveSelectionsInOutline, GGOutline.RemakeSelectionsFromOutline take slices. GGOutlineImplB.
GGCaret.GetAttractor RETURNS SliceDescriptor. GGCaretImpl.
ggData.drag.outlineToExtend goes away. GGInterfaceTypes
GGOutline.UpdateDescriptorBoundBoxes replaced by new version of in GGSliceImplA.UpdateDescriptorBoundBoxes. GGOutlineImplB.
Implement segmentsInDescriptor, nextSegment, walkSegments for outline types GGOutlineImplA.
GGSelect.OutlineSequenceObj should contain slices. GGSelect.
everything in GGOutline that used to take outlines take slices. GGOutline.
Global Type Substitutions
OutlineDescriptor SliceDescriptor
OutlineDescriptorObj SliceDescriptorObj
Outline Slice
OutlineObj SliceObj
OutlineClass SliceClass
OutlineClassObj SliceClassObj
EntityGenerator SliceGenerator
EntityGeneratorObj SliceGeneratorObj
OutlineGenerator SliceGenerator
OutlineGeneratorObj SliceGeneratorObj
OutlineDescriptorGenerator SliceDescriptorGenerator
OutlineDescriptorGeneratorObj SliceDescriptorGeneratorObj
OutlinePointGenerator PointGenerator
OutlinePointGeneratorObj PointGeneratorObj
OutlinePointPairGenerator PointPairGenerator
OutlinePointPairGeneratorObj PointPairGeneratorObj
Obsolete Code
GGAlignImpl.mesa
AddAllHotOutlines: PROC [scene: Scene, triggerBag: TriggerBag] = {
feature: FeatureData;
outDGen: GGModelTypes.SliceDescriptorGenerator;
outDGen ← GGSelect.SelectedOutlines[scene, hot];
FOR outlineD: SliceDescriptor ← GGSelect.NextSliceDescriptor[outDGen], GGSelect.NextSliceDescriptor[outDGen] UNTIL outlineD = NIL DO
feature ← GGGravity.FeatureFromOutline[outlineD.slice, outlineD.parts];
AddFeature[feature, triggerBag];
ENDLOOP;
};
RemoveMovingOutline: PUBLIC PROC [outlineD: SliceDescriptor, scene: Scene] RETURNS [stationary: SliceDescriptor] = {
selSliceD: SliceDescriptor ← GGSelect.FindSelectedSlice[outlineD.slice, scene, normal];
background, overlay, rubber, drag, move: SliceDescriptor;
IF selSliceD = NIL THEN RETURN[outlineD]; -- clearly nothing is moving
[background, overlay, rubber, drag] ← outlineD.slice.class.movingParts[selSliceD.slice, selSliceD.parts];
move ← outlineD.slice.class.unionParts[rubber, drag];
stationary ← outlineD.slice.class.differenceParts[outlineD, move];
};
AddHotOutline: PUBLIC PROC [outlineD: SliceDescriptor, triggerBag: TriggerBag] RETURNS [feature: FeatureData] = {
oldD, unionD: SliceDescriptor;
oldD ← FindOldOutlineD[outlineD.slice, triggerBag.outlines];
IF oldD = NIL THEN {
feature ← GGGravity.FeatureFromOutline[outlineD.slice, outlineD.parts];
triggerBag.outlines ← AppendFeature[feature, triggerBag.outlines];
}
ELSE {
unionD ← outlineD.slice.class.unionParts[oldD, outlineD];
triggerBag.outlines ← DeleteOutlineD[oldD, triggerBag.outlines];
feature ← GGGravity.FeatureFromOutline[outlineD.slice, unionD.parts];
triggerBag.outlines ← AppendFeature[feature, triggerBag.outlines];
};
};
IncrementalFilterOutline: PUBLIC PROC [outlineD: SliceDescriptor, filters: Filters, hideAlignments: BOOL, alignBag: AlignBag] RETURNS [alignObjects: LIST OF FeatureData] = {
pointGen: GGModelTypes.PointGenerator;
pointPairGen: GGModelTypes.PointPairGenerator;
pointGen ← outlineD.slice.class.pointsInDescriptor[outlineD];
FOR next: GGModelTypes.PointAndDone ← outlineD.slice.class.nextPoint[pointGen], outlineD.slice.class.nextPoint[pointGen] UNTIL next.done DO
alignObjects ← NARROW[GList.Nconc[PointFireRule[next.point, filters, alignBag], alignObjects]];
ENDLOOP;
pointPairGen ← outlineD.slice.class.pointPairsInDescriptor[outlineD];
FOR next: GGModelTypes.PointPairAndDone ← outlineD.slice.class.nextPointPair[pointPairGen], outlineD.slice.class.nextPointPair[pointPairGen] UNTIL next.done DO
alignObjects ← NARROW[GList.Nconc[SegmentFireRule[9999, next.lo, next.hi, filters, alignBag], alignObjects]];
ENDLOOP;
};
IncrementalMidpointsOutline: PUBLIC PROC [outlineD: SliceDescriptor, midpoints: BOOL, alignBag: AlignBag] = {
THIS CODE IS NO LONGER USED EXCEPT FOR PERFORMANCE BENCHMARKS; GGState.PrecomputeMidpoints[] is FALSE by default.
Add to the object bag the midpoints of all segments in outlineD.
outPointPairGen: GGModelTypes.PointPairGenerator;
pairCount: NAT ← 0;
IF NOT midpoints THEN RETURN;
IF NOT GGState.PrecomputeMidpoints[] THEN RETURN;
outPointPairGen ← outlineD.slice.class.pointPairsInDescriptor[outlineD];
FOR next: GGModelTypes.PointPairAndDone ← outlineD.slice.class.nextPointPair[outPointPairGen], outlineD.slice.class.nextPointPair[outPointPairGen] UNTIL next.done DO
[] ← GGGravity.SegmentAddMidpoint[pairCount, next.lo, next.hi, alignBag];
pairCount ← pairCount + 1;
ENDLOOP;
};
RemoveHotOutline: PUBLIC PROC [outlineD: SliceDescriptor, triggerBag: TriggerBag] = {
oldOut, diff: SliceDescriptor;
feature: FeatureData;
oldOut ← FindOldOutlineD[outlineD.slice, triggerBag.outlines];
IF oldOut#NIL THEN {
diff ← outlineD.slice.class.differenceParts[oldOut, outlineD];
triggerBag.outlines ← DeleteOutlineD[oldOut, triggerBag.outlines];
IF NOT outlineD.slice.class.isEmptyParts[diff] THEN {
feature ← GGGravity.FeatureFromOutline[outlineD.slice, diff.parts];
triggerBag.outlines ← AppendFeature[feature, triggerBag.outlines];
};
};
};
RemoveEntireHotOutline: PUBLIC PROC [outline: Slice, triggerBag: TriggerBag] RETURNS [oldD: SliceDescriptor] = {
oldD ← FindOldOutlineD[outline, triggerBag.outlines];
IF oldD#NIL THEN {
triggerBag.outlines ← DeleteOutlineD[oldD, triggerBag.outlines];
};
};
RemoveMentionOutline: PUBLIC PROC [outline: Slice, alignBag: AlignBag] = {
Removes all alignment objects and midpoints that were triggered (only) by this outline. Removes mention of this outline from those alignment objects that are trigger by other triggers as well.
line: AlignmentLine;
FOR list: LIST OF FeatureData ← alignBag.slopeLines, list.rest UNTIL list = NIL DO
line ← NARROW[list.first.shape];
ENDLOOP;
};
RemoveMentionSlice: PUBLIC PROC [slice: Slice, alignBag: AlignBag] = {
Removes all alignment objects and midpoints that were triggered (only) by this slice. Removes mention of this slice from those alignment objects that are trigger by other triggers as well.
};
AddAllTrajectories: PROC [scene: Scene, triggerBag: TriggerBag] = {
outlineGen: GGModelTypes.SliceGenerator;
feature: FeatureData;
outlineGen ← GGScene.OutlinesInScene[scene];
FOR outline: Slice ← GGScene.NextOutline[outlineGen], GGScene.NextOutline[outlineGen] UNTIL outline = NIL DO
feature ← GGGravity.FeatureFromOutline[outline];
AddFeature[feature, triggerBag];
ENDLOOP;
};
TAddTriggersFilter: PUBLIC PROC [triggerBag: TriggerBag, filterSeqProc: FilterSequenceProc, filterSliceProc: FilterSliceProc, ggData: GGData] = {
When this procedure is called, all sequences in the scene are passed to filterSeqProc to see if they should be added (in all or in part). filterSeqProc should return those parts which should be added. AddSequenceTrigger adds these parts to triggerBag. A similar things happens for slices using the filterSliceProc and calls to AddSliceTrigger
add: BOOL;
seq: Sequence;
sliceGen: SliceGenerator;
trajGen: TrajGenerator ← GGScene.TrajsInScene[ggData.scene];
FOR traj: Traj ← GGScene.NextTraj[trajGen], GGScene.NextTraj[trajGen] UNTIL traj = NIL DO
seq ← GGSequence.CreateComplete[traj];
filterSeqProc[seq]; -- keeps those parts of seq which should remain
AddSequenceTrigger[seq, triggerBag];
ENDLOOP;
sliceGen ← GGScene.SlicesInScene[ggData.scene];
FOR slice: Slice ← GGScene.NextSlice[sliceGen], GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO
add ← filterSliceProc[slice];
IF add THEN AddSliceTrigger[slice, triggerBag];
ENDLOOP;
};
FindOldOutlineD: PROC [outline: Slice, list: LIST OF FeatureData] RETURNS [oldSliceD: SliceDescriptor] = {
FOR l: LIST OF FeatureData ← list, l.rest UNTIL l = NIL DO
IF NARROW[l.first.shape, SliceDescriptor].slice = outline THEN RETURN [NARROW[l.first.shape]];
ENDLOOP;
RETURN [NIL];
};
FindOutlineDAndNeighbors: PROC [entity: Slice, entityList: LIST OF FeatureData] RETURNS [beforeEnt, ent, afterEnt: LIST OF FeatureData] = {
lastE: LIST OF FeatureData ← NIL;
eList: LIST OF FeatureData ← entityList;
IF eList = NIL THEN ERROR EntityNotFound;
UNTIL eList = NIL DO
IF NARROW[eList.first.shape, SliceDescriptor].slice = entity THEN {
beforeEnt ← lastE; ent ← eList; afterEnt ← eList.rest; RETURN};
lastE ← eList;
eList ← eList.rest;
ENDLOOP;
SIGNAL EntityNotFound;
};
FindSliceDAndNeighbors: PROC [entity: Slice, entityList: LIST OF FeatureData] RETURNS [beforeEnt, ent, afterEnt: LIST OF FeatureData] = {
lastE: LIST OF FeatureData ← NIL;
eList: LIST OF FeatureData ← entityList;
IF eList = NIL THEN ERROR EntityNotFound;
UNTIL eList = NIL DO
IF NARROW[eList.first.shape, SliceDescriptor].slice = entity THEN {
beforeEnt ← lastE; ent ← eList; afterEnt ← eList.rest; RETURN};
lastE ← eList;
eList ← eList.rest;
ENDLOOP;
SIGNAL EntityNotFound;
};
DeleteOutline: PROC [outline: Slice, featureList: LIST OF FeatureData] RETURNS [smallerList: LIST OF FeatureData, notFound: BOOLFALSE] = {
before, at, after: LIST OF FeatureData;
IF featureList = NIL THEN RETURN[NIL, TRUE];
[before, at, after] ← FindOutlineAndNeighbors[outline, featureList ! EntityNotFound => {notFound ← TRUE; CONTINUE}];
IF notFound THEN RETURN[featureList, TRUE];
IF before = NIL THEN smallerList ← after
ELSE {
before.rest ← after;
smallerList ← featureList;
};
};
DeleteOutlineD: PROC [outlineD: SliceDescriptor, featureList: LIST OF FeatureData] RETURNS [smallerList: LIST OF FeatureData] = {
before, at, after: LIST OF FeatureData;
notFound: BOOLFALSE;
IF featureList = NIL THEN RETURN[NIL];
[before, at, after] ← FindOutlineAndNeighbors[outlineD.slice, featureList ! EntityNotFound => {notFound ← TRUE; CONTINUE}];
IF notFound THEN RETURN[featureList];
IF before = NIL THEN smallerList ← after
ELSE {
before.rest ← after;
smallerList ← featureList;
};
};
ReplaceObsoleteOutlineTrigger: PUBLIC PROC [ggData: GGData, oldOutline: Slice, newOutline: Slice] = {
triggerBag: TriggerBag ← ggData.hitTest.triggerBag;
alignBag: AlignBag ← ggData.hitTest.alignBag;
sceneBag: TriggerBag ← ggData.hitTest.sceneBag;
feature: FeatureData;
hotD: SliceDescriptor;
notFound: BOOL;
First, get rid of all references to the obsolete outline.
notFound ← FALSE;
UNTIL notFound DO
[sceneBag.outlines, notFound] ← DeleteOutline[oldOutline, sceneBag.outlines];
ENDLOOP;
notFound ← FALSE;
UNTIL notFound DO
[triggerBag.outlines, notFound] ← DeleteOutline[oldOutline, triggerBag.outlines];
ENDLOOP;
Next, add back any appropriate references to the new outline. Assume that the next operation will be a CaretPos.
If this traj is hot, add its hot parts to the triggerBag.
hotD ← GGSelect.FindSelectedOutline[newOutline, ggData.scene, hot];
IF hotD # NIL THEN {
feature ← GGGravity.FeatureFromOutline[hotD.slice, hotD.parts];
AddFeature[feature, triggerBag];
};
Add the whole object to the scene bag.
feature ← GGGravity.FeatureFromOutline[newOutline];
AddFeature[feature, sceneBag];
};
ComputeAllBoundingBoxes: PROC [sceneBag: TriggerBag] = {
featureData: FeatureData;
outlineD: SliceDescriptor;
FOR list: LIST OF FeatureData ← sceneBag.outlines, list.rest UNTIL list = NIL DO
featureData ← list.first;
outlineD ← NARROW[featureData.shape];
GGSlice.UpdateDescriptorBoundBoxes[outlineD];
ENDLOOP;
};
GGBoundBoxImpl.mesa
BoxEdge: PRIVATE PROC [bBox: BoundBox, index: NAT] RETURNS [edge: Edge] = {
IF bBox.null OR bBox.infinite THEN ERROR;
SELECT index FROM
0 => edge ← Lines2d.CreateEdge[[bBox.loX, bBox.loY], [bBox.loX, bBox.hiY]];
1 => edge ← Lines2d.CreateEdge[[bBox.loX, bBox.hiY], [bBox.hiX, bBox.hiY]];
2 => edge ← Lines2d.CreateEdge[[bBox.hiX, bBox.hiY], [bBox.hiX, bBox.loY]];
3 => edge ← Lines2d.CreateEdge[[bBox.hiX, bBox.loY], [bBox.loX, bBox.loY]];
ENDCASE => ERROR;
};
GGBuiltinShapesImpl.mesa
Polygon: PUBLIC PROC [sideCount: NAT, origin: Point, sideLength: REAL, defaults: DefaultData] RETURNS [outline: Slice] = {
The bottom-most edge of the returned polygon will be horizontal. The polygon will be inscribed inside a circle centered at "origin". Each side of the polygon will have length "sideLength".
};
GGCaretImpl.mesa
For use by GGRefreshImpl.
TellOnOverlay: PUBLIC PROC [caret: Caret, onOverlay: BOOL] = {
caret.onOverlay ← onOverlay;
};
IsOnOverlay: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = {
RETURN[caret.onOverlay];
};
SittingOnEndOLDD: PUBLIC PROC [caret: Caret] RETURNS [BOOL] = {
success: BOOL;
partType: TrajPartType;
jointNum: NAT;
traj: Traj;
IF caret.chair = NIL THEN RETURN[FALSE];
WITH caret.chair SELECT FROM
outlineD: SliceDescriptor => {
[success, partType, traj, ----, jointNum] ← GGOutline.UnpackSimpleDescriptorOld[outlineD];
IF NOT success OR partType # joint THEN RETURN[FALSE];
RETURN[GGTraj.IsEndJoint[traj, jointNum]];
};
sliceD: SliceDescriptor => {
IF sliceD.slice.class.type # $Slice THEN RETURN[FALSE];
[success, partType, traj, ----, jointNum] ← GGOutline.UnpackSimpleDescriptor[sliceD];
IF NOT success OR partType # joint THEN RETURN[FALSE];
RETURN[GGTraj.IsEndJoint[traj, jointNum]];
};
ENDCASE => ERROR;
};
Touching.
MakeJointTouchJoint: PROC [traj1, traj2: Traj, joint1, joint2: Joint, point: Point, ggData: GGData] = {
touchGroup, group1, group2: TouchGroup;
IF joint1.touchItem # NIL AND joint2.touchItem = NIL THEN {
joint1 already belongs to a group. Add joint2 to this group.
touchGroup ← GGTouch.TouchGroupOfItem[joint1.touchItem];
joint2.touchItem ← GGTouch.AddJoint[traj2, joint2, touchGroup];
}
ELSE IF joint1.touchItem = NIL AND joint2.touchItem # NIL THEN {
touchGroup ← GGTouch.TouchGroupOfItem[joint2.touchItem];
joint1.touchItem ← GGTouch.AddJoint[traj1, joint1, touchGroup];
}
ELSE IF joint1.touchItem # NIL AND joint2.touchItem # NIL THEN {
Merge the two groups.
group1 ← GGTouch.TouchGroupOfItem[joint1.touchItem];
group2 ← GGTouch.TouchGroupOfItem[joint2.touchItem];
GGTouch.MergeGroups[group1, group2, ggData];
}
ELSE {
touchGroup ← GGTouch.CreateTouchGroup[ggData, point];
joint1.touchItem ← GGTouch.AddJoint[traj1, joint1, touchGroup];
joint2.touchItem ← GGTouch.AddJoint[traj2, joint2, touchGroup];
};
};
RatherClose: PROC [p1, p2: Point] RETURNS [BOOL] = {
epsilon: REAL = 1.0e-5;
RETURN[ABS[p1.x - p2.x] < epsilon OR ABS[p1.y - p2.y] < epsilon];
};
FindItemAtPoint: PROC [point: Point, touchItemList: LIST OF TouchItem] RETURNS [TouchItem] = {
FOR list: LIST OF TouchItem ← touchItemList, list.rest UNTIL list = NIL DO
IF RatherClose[list.first.segPoint, point] THEN RETURN[list.first]
ENDLOOP;
RETURN[NIL];
};
MakeJointTouchSegment: PROC [traj1, traj2: Traj, joint: Joint, seg: Segment, point: Point, ggData: GGData] = {
samePointItem: TouchItem;
touchGroup, group1, group2: TouchGroup;
samePointItem ← FindItemAtPoint[point, seg.touchItemList];
IF joint.touchItem # NIL AND samePointItem = NIL THEN {
touchGroup ← GGTouch.TouchGroupOfItem[joint.touchItem];
seg.touchItemList ← CONS[GGTouch.AddSegment[traj2, seg, point, touchGroup], seg.touchItemList];
}
ELSE IF joint.touchItem = NIL AND samePointItem # NIL THEN {
touchGroup ← GGTouch.TouchGroupOfItem[samePointItem];
joint.touchItem ← GGTouch.AddJoint[traj1, joint, touchGroup];
}
ELSE IF joint.touchItem # NIL AND samePointItem # NIL THEN {
group1 ← GGTouch.TouchGroupOfItem[joint.touchItem];
group2 ← GGTouch.TouchGroupOfItem[samePointItem];
GGTouch.MergeGroups[group1, group2, ggData];
}
ELSE {
touchGroup ← GGTouch.CreateTouchGroup[ggData, point];
joint.touchItem ← GGTouch.AddJoint[traj1, joint, touchGroup];
seg.touchItemList ←
CONS[GGTouch.AddSegment[traj2, seg, point, touchGroup], seg.touchItemList];
};
};
MakeSegmentTouchSegment: PROC [chair, attractor: Traj, chairSeg, attractorSeg: Segment, point: Point, ggData: GGData] = {
Not yet implemented.
};
MakeChairTouchAttractor: PUBLIC PROC [caret: Caret, ggData: GGData] = {
};
MakeChairTouchTrajJoint: PUBLIC PROC [caret: Caret, ggData: GGData, traj: Traj, jointNum: NAT] = {
};
GGCircleCacheImpl.mesa
GGCirclesImpl.mesa
GGContainerImpl.mesa
GGCubic2Impl.mesa
GGDescribeImpl.mesa
DescribeItem: PROC [f: IO.STREAM, item: TouchItem] = {
SELECT item.touchingPartType FROM
joint => f.PutF["Item: joint on %g", [rope[DescribeTraj[NARROW[item.traj]]]]];
segment => f.PutF["Item: segment on %g", [rope[DescribeTraj[NARROW[item.traj]]]]];
ENDCASE => ERROR;
};
DescribeTouchGroup: PUBLIC PROC [group: TouchGroup] RETURNS [text: Rope.ROPE] = {
f: IO.STREAM;
touchGen: TouchItemGenerator;
f ← IO.ROS[];
f.PutF["TouchGroup: (%1.2f, %1.2f)\n", [real[group.point.x]], [real[group.point.y]]];
touchGen ← GGTouch.AllTouchItems[group];
FOR item: TouchItem ← GGTouch.NextTouchItem[touchGen], GGTouch.NextTouchItem[touchGen] UNTIL item = NIL DO
f.PutChar[IO.TAB];
DescribeItem[f, item];
f.PutChar[IO.CR];
ENDLOOP;
text ← IO.RopeFromROS[f];
};
GGEditToolImpl.mesa
GGEventImplA.mesa
ShowFontValues: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
Outputs string in the form <FontPrefix> <FontFamily> <FontFace> transformation preferredSize
ggData: GGData ← NARROW[clientData];
sliceDescGen: SliceDescriptorGenerator ← GGSelect.SelectedSlices[ggData.scene, normal];
sliceDesc: SliceDescriptor ← GGSelect.NextSliceDescriptor[sliceDescGen];
IF sliceDesc=NIL OR sliceDesc.slice.class.type#$Text OR GGSelect.NextSliceDescriptor[sliceDescGen]#NIL THEN {
Feedback.AppendHerald[ggData.feedback, "Select a single text slice for font printing", oneLiner];
Feedback.Blink[ggData.feedback];
}
ELSE Feedback.PutF[ggData.feedback, oneLiner, "Font Values: %g", [rope[GGSlice.GetFontDataRope[sliceDesc.slice]]] ];
};
ShowFontValuesLiteral: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
Outputs string in the form <FontFullName> <transformation> <storedSize> <designSize>
ggData: GGData ← NARROW[clientData];
sliceDescGen: SliceDescriptorGenerator ← GGSelect.SelectedSlices[ggData.scene, normal];
sliceDesc: SliceDescriptor ← GGSelect.NextSliceDescriptor[sliceDescGen];
IF sliceDesc=NIL OR sliceDesc.slice.class.type#$Text OR GGSelect.NextSliceDescriptor[sliceDescGen]#NIL THEN {
Feedback.AppendHerald[ggData.feedback, "Select a single text slice for font printing", oneLiner];
Feedback.Blink[ggData.feedback];
}
ELSE Feedback.PutF[ggData.feedback, oneLiner, "Font Values: %g", [rope[GGSlice.GetFontLiteralDataRope[sliceDesc.slice]]] ];
};
OldDeleteAllSelected: PROC [ggData: GGData] RETURNS [bBox: BoundBox] = {
sliceDescGen: SliceDescriptorGenerator;
outSeqGen: GGSelect.OutlineSequenceGenerator;
oldOutline: Slice;
fenceSeq: Sequence;
thisBox: BoundBox;
bBox ← GGBoundBox.BoundBoxOfSelected[ggData.scene, normal];
Implemented enough for non-gargoyle slices only.
sliceDescGen ← GGSelect.SelectedSlices[ggData.scene, normal];
FOR sliceD: SliceDescriptor ← GGSelect.NextSliceDescriptor[sliceDescGen], GGSelect.NextSliceDescriptor[sliceDescGen] UNTIL sliceD = NIL DO
GGSelect.DeselectEntityAllClasses[sliceD.slice, ggData.scene];
GGSlice.DeleteSlice[ggData.scene, sliceD.slice];
ENDLOOP;
Now delete selected sequences.
outSeqGen ← GGSelect.SelectedOutlineSequences[ggData.scene, normal];
WHILE outSeqGen.list # NIL DO
FOR outSeq: GGSelect.OutlineSequence ← GGSelect.NextOutlineSequences[outSeqGen], GGSelect.NextOutlineSequences[outSeqGen] UNTIL outSeq = NIL DO
fenceSeq ← outSeq.fenceSeq;
FOR holeSeq: Sequence ← GGSequence.NextSequence[outSeq.holeSeqs], GGSequence.NextSequence[outSeq.holeSeqs] UNTIL holeSeq = NIL DO
[oldOutline,----] ← GGInterface.DeleteSequence[holeSeq, ggData.scene];
thisBox ← GGTraj.GetBoundBox[holeSeq.traj];
GGBoundBox.EnlargeByBox[bBox: bBox, by: thisBox];
GOTO SelectionsHaveChanged;
ENDLOOP;
IF fenceSeq # NIL THEN {
[oldOutline,----] ← GGInterface.DeleteSequence[fenceSeq, ggData.scene];
IF fenceSeq.traj.role = open THEN {
GGSequence.UpdateBoundBox[fenceSeq];
GGBoundBox.EnlargeByBox[bBox: bBox, by: fenceSeq.boundBox];
}
ELSE {
thisBox ← GGTraj.GetBoundBox[fenceSeq.traj];
GGBoundBox.EnlargeByBox[bBox: bBox, by: thisBox];
};
GOTO SelectionsHaveChanged;
};
REPEAT
SelectionsHaveChanged => {
outSeqGen ← GGSelect.SelectedOutlineSequences[ggData.scene, normal];
};
ENDLOOP;
ENDLOOP;
};
DeleteAllSelected: PROC [ggData: GGData] RETURNS [bBox: BoundBox] = {
DeleteRun: GGSelect.RunProc = {
traj ← NIL;
};
sliceDescGen: SliceDescriptorGenerator;
thisBox: BoundBox;
bBox ← GGBoundBox.BoundBoxOfSelected[ggData.scene, normal];
Implemented enough for non-gargoyle slices only.
sliceDescGen ← GGSelect.SelectedSlices[ggData.scene, normal];
FOR sliceD: SliceDescriptor ← GGSelect.NextSliceDescriptor[sliceDescGen], GGSelect.NextSliceDescriptor[sliceDescGen] UNTIL sliceD = NIL DO
GGSelect.DeselectEntityAllClasses[sliceD.slice, ggData.scene];
GGSlice.DeleteSlice[ggData.scene, sliceD.slice];
ENDLOOP;
GGCaret.NoAttractor[ggData.caret];
Overly conservative. Just in case the caret was attracted to something that was just deleted.
thisBox ← GGSelect.ForEachOutlineRun[ggData.scene, ggData.caret, normal, DeleteRun, FALSE];
GGBoundBox.EnlargeByBox[bBox: bBox, by: thisBox];
};
CloseOLDD: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
ggData: GGData ← NARROW[clientData];
chair: REF ANY;
traj: Traj;
outline: Slice;
firstPoint, lastPoint: Point;
seg: Segment;
success: BOOL;
chair ← GGCaret.GetChair[ggData.caret];
BEGIN
IF chair = NIL THEN GOTO NoCaretTraj;
WITH chair SELECT FROM
outlineD: SliceDescriptor => {
[success, ----, traj] ← GGOutline.UnpackSimpleDescriptorOld[outlineD];
IF NOT success THEN ERROR;
};
sliceD: SliceDescriptor => {
IF sliceD.slice.class.type # $Slice THEN GOTO NoCaretTraj;
[success, ----, traj] ← GGOutline.UnpackSimpleDescriptor[sliceD];
IF NOT success THEN GOTO NoCaretTraj;
};
ENDCASE => ERROR;
IF traj.role = fence OR traj.role = hole THEN GOTO AlreadyClosed;
Feedback.AppendHerald[ggData.feedback, "The caret trajectory will be closed.", oneLiner];
outline ← GGOutline.OutlineOfTraj[traj];
firstPoint ← GGTraj.FetchJointPos[traj, 0];
lastPoint ← GGTraj.LastJointPos[traj];
IF firstPoint # lastPoint THEN {
lastSeg: Segment ← GGTraj.FetchSegment[traj, GGTraj.HiSegment[traj]];
seg ← GGSegment.MakeLine[lastPoint, firstPoint, NIL];
GGSegment.CopyLooks[lastSeg, seg];
GGTraj.CloseWithSegment[traj, seg, lo];
[] ← GGSelect.ReselectTraj[traj, hi, ggData.scene, TRUE];
}
ELSE {
GGOutline.SaveSelectionsInOutline[outline, ggData.scene];
GGSelect.DeselectEntityAllClasses[outline, ggData.scene];
GGTraj.CloseByDistorting[traj, hi];
GGOutline.RemakeSelectionsFromOutline[outline, ggData.scene];
};
GGSelect.SelectTraj[traj, ggData.scene, normal];
GGCaret.SitOn[ggData.caret, NIL];
GGCaret.NoAttractor[caret: ggData.caret];
outline.class.setFillColor[outline, ggData.defaults.fillColor];
ggData.refresh.startBoundBox^ ← traj.boundBox^;
GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectChangedBoundBoxProvided, ggData: ggData, remake: triggerBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: FALSE];
N.B. It's a shame we have to remake the triggerBag here. This is because the closed trajectory might have been hot. Its hot sequence is obsolete.
EXITS
NoCaretTraj => {
Feedback.AppendHerald[ggData.feedback, "There is no caret trajectory to close.", oneLiner];
Feedback.Blink[ggData.feedback];
};
AlreadyClosed => {
Feedback.AppendHerald[ggData.feedback, "That trajectory is already closed.", oneLiner];
Feedback.Blink[ggData.feedback];
};
END;
}; -- end Close
ShowPoints: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
ggData: GGData ← NARROW[clientData];
seqGen: SequenceGenerator ← GGSelect.SelectedSequences[ggData.scene, normal];
FOR seq: Sequence ← GGSequence.NextSequence[seqGen], GGSequence.NextSequence[seqGen] UNTIL seq = NIL DO
seq.traj.visibleJoints ← TRUE;
ENDLOOP;
};
HidePoints: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
ggData: GGData ← NARROW[clientData];
seqGen: SequenceGenerator ← GGSelect.SelectedSequences[ggData.scene, normal];
FOR seq: Sequence ← GGSequence.NextSequence[seqGen], GGSequence.NextSequence[seqGen] UNTIL seq = NIL DO
seq.traj.visibleJoints ← FALSE;
ENDLOOP;
};
GGEventImplB.mesa
GetRadius: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
ggData: GGData ← NARROW[clientData];
oldFoundButton: AtomButtons.ScalarButtonClient;
seqGen: SequenceGenerator;
segGen: SegmentGenerator;
seq, next: Sequence;
radius: REAL;
seqGen ← GGSelect.SelectedSequences[ggData.scene, normal];
seq ← GGSequence.NextSequence[seqGen];
next ← GGSequence.NextSequence[seqGen];
IF seq = NIL OR next # NIL THEN {
Feedback.Append[ggData.feedback, "Select a single segment for GetRadius.", oneLiner];
Feedback.Blink[ggData.feedback];
RETURN;
};
segGen ← GGSequence.SegmentsInSequence[seq];
FOR seg: Segment ← GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
radius ← Vectors2d.Distance[seg.lo, seg.hi]/ggData.hitTest.scaleUnit;
oldFoundButton ← AtomButtons.AddValueSorted[ggData, ggData.hitTest.radiusHeader, [NIL, radius, LIST[$ToggleRadius, NEW[REAL ← radius]], on], incr];
ENDLOOP;
GGWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsSelected, ggData: ggData, remake: objectBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
GGEventImplC.mesa
AddControlPointOLDD: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
Adds a new control point to a segment
ggData: GGData ← NARROW[clientData];
attractor: REF ANY;
seg, newSeg: Segment;
segNum: INT;
traj, newRun, newTraj: Traj;
refreshBox: BoundBox;
success: BOOL;
partType: TrajPartType;
caretPos: Point ← GGCaret.GetPoint[ggData.caret];
attractor ← GGCaret.GetAttractor[ggData.caret];
BEGIN
IF attractor = NIL THEN GOTO NotOnSpline;
WITH attractor SELECT FROM
oD: SliceDescriptor => {
[success, partType, traj, ----, ----, ----, ----, seg, segNum] ← GGOutline.UnpackSimpleDescriptorOld[oD];
IF NOT success OR partType # segment THEN GOTO NotOnSpline;
};
sD: SliceDescriptor => {
IF sD.slice.class.type # $Slice THEN GOTO NotOnSpline;
[success, partType, traj, ----, ----, ----, ----, seg, segNum] ← GGOutline.UnpackSimpleDescriptor[sD];
IF NOT success OR partType # segment THEN GOTO NotOnSpline;
};
ENDCASE => ERROR;
IF seg.class.type # $CubicSpline THEN GOTO NotOnSpline;
Must save select data now so that segment copy (in CSControlPointAdd) will reflect selection data.
GGSelect.DeselectAll[ggData.scene, normal];
GGTraj.SaveSelection[traj, normal, ggData.scene]; -- to clear field bits
GGTraj.SaveSelection[traj, hot, ggData.scene]; -- to save hot field bits
newSeg ← GGSegment.CSControlPointAdd[seg, caretPos];
newRun ← GGTraj.CreateTraj[newSeg.lo];
GGTraj.SetTrajStrokeJoint[newRun, traj.strokeJoint];
IF NOT GGTraj.AddSegment[newRun, hi, newSeg, lo] THEN ERROR;
IF (segNum ← GGTraj.IndexOfSegment[seg, traj]) = -1 THEN ERROR; -- inconsistent
[refreshBox, newTraj] ← GGSelect.SubstituteForSegment[traj, segNum, newRun, ggData.scene];
GGCaret.NoAttractor[ggData.caret];
GGCaret.SitOn[ggData.caret, NIL];
ggData.refresh.startBoundBox^ ← refreshBox^;
GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectChangedBoundBoxProvided, ggData: ggData, remake: triggerBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE];
EXITS
NotOnSpline => {
Feedback.Append[ggData.feedback, "Caret must lie on a cubic spline to add a control point", oneLiner];
Feedback.Blink[ggData.feedback];
};
END;
};
AddJointOLDD: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
ggData: GGData ← NARROW[clientData];
attractor: REF ANY;
seg, newSeg1, newSeg2: Segment;
segNum: INT;
traj, newRun, newTraj: Traj;
refreshBox, oldBox: BoundBox;
newJoint: Joint;
success: BOOL;
partType: TrajPartType;
caretPos: Point ← GGCaret.GetPoint[ggData.caret];
attractor ← GGCaret.GetAttractor[ggData.caret];
BEGIN
IF attractor = NIL THEN GOTO NotASegment;
WITH attractor SELECT FROM
oD: SliceDescriptor => {
[success, partType, traj, ----, ----, ----, ----, seg, segNum] ← GGOutline.UnpackSimpleDescriptorOld[oD];
IF NOT success OR partType # segment THEN GOTO NotASegment;
};
sD: SliceDescriptor => {
IF sD.slice.class.type # $Slice THEN GOTO NotASegment;
[success, partType, traj, ----, ----, ----, ----, seg, segNum] ← GGOutline.UnpackSimpleDescriptor[sD];
IF NOT success OR partType # segment THEN GOTO NotASegment;
};
ENDCASE => ERROR;
IF seg.class.type=$Conic THEN GOTO ConicsAreNotDone;
Save select data now so that segment copy (in CSControlPointAdd) will reflect selection data.
GGSelect.DeselectAll[ggData.scene, normal];
GGTraj.SaveSelection[traj, normal, ggData.scene];
GGTraj.SaveSelection[traj, hot, ggData.scene];
[Artwork node; type 'ArtworkInterpress on' to command tool]
[newSeg1, newSeg2] ← seg.class.addJoint[seg, caretPos];
newRun ← GGTraj.CreateTraj[newSeg1.lo];
IF NOT GGTraj.AddSegment[newRun, hi, newSeg1, lo] THEN ERROR;
IF NOT GGTraj.AddSegment[newRun, hi, newSeg2, lo] THEN ERROR;
newJoint ← GGTraj.FetchJoint[newRun, 1];
newJoint.TselectedInFull.normal ← TRUE;
IF (segNum ← GGTraj.IndexOfSegment[seg, traj]) = -1 THEN ERROR; -- inconsistent
oldBox ← seg.class.boundBox[seg];
[refreshBox, newTraj] ← GGSelect.SubstituteForSegment[traj, segNum, newRun, ggData.scene];
GGTraj.SetTrajStrokeJoint[newTraj, traj.strokeJoint];
GGBoundBox.EnlargeByBox[refreshBox, oldBox];
GGCaret.NoAttractor[ggData.caret];
GGCaret.SitOn[ggData.caret, NIL];
ggData.refresh.startBoundBox^ ← refreshBox^;
GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectChangedBoundBoxProvided, ggData: ggData, remake: triggerBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE];
EXITS
NotASegment => {
Feedback.Append[ggData.feedback, "Caret must lie on a segment to add a joint", oneLiner];
Feedback.Blink[ggData.feedback];
};
ConicsAreNotDone => {
Feedback.Append[ggData.feedback, "Can't add joints to Conics", oneLiner];
Feedback.Blink[ggData.feedback];
};
END;
};
AreaSelectNewAndDeleteOLDD: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
ggData: GGData ← NARROW[clientData];
Select all objects within area(s) bounded by original selection(s) and delete original selection
IF GGSelect.NoSelections[ggData.scene, normal] THEN RETURN
ELSE { -- there were some original selections
oldSelectedGen: SliceGenerator ← GGSelect.SelectedSlices[ggData.scene, normal]; -- save original selection
startBox: BoundBox ← GGBoundBox.BoundBoxOfSelected[ggData.scene, normal];
AreaSelectAux[ggData: ggData, new: TRUE, paint: FALSE];
FOR formerSelected: REF ANY ← GGScene.NextEntity[oldSelectedGen], GGScene.NextEntity[oldSelectedGen] UNTIL formerSelected=NIL DO
WITH formerSelected SELECT FROM
outlineD: SliceDescriptor => {
N.B.: DeleteOutline deletes too much
GGSelect.DeselectEntityAllClasses[outlineD.slice, ggData.scene];
GGScene.DeleteOutline[ggData.scene, outlineD.slice];
};
sliceD: SliceDescriptor => {
GGSelect.DeselectEntityAllClasses[sliceD.slice, ggData.scene];
GGSlice.DeleteSlice[ggData.scene, sliceD.slice];
};
ENDCASE => ERROR;
ENDLOOP;
GGCaret.NoAttractor[ggData.caret];
GGCaret.SitOn[ggData.caret, NIL];
ggData.refresh.startBoundBox^ ← startBox^;
GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectChangedBoundBoxProvided, ggData: ggData, remake: triggerBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
};
AreaSelectAuxOLDD: PROC [ggData: GGData, new: BOOLTRUE, paint: BOOLTRUE] = {
Within: PROC [test, bound: GGBoundBox.BoundBox] RETURNS [BOOL] = {
RETURN [ test.hiX <= bound.hiX AND test.loX >= bound.loX AND test.hiY <= bound.hiY AND test.loY >= bound.loY ];
};
selectedGen: SliceGenerator;
sceneGen: SliceGenerator;
IF GGSelect.NoSelections[ggData.scene, normal] THEN RETURN;
selectedGen ← GGSelect.SelectedSlices[ggData.scene, normal];
IF new THEN GGSelect.DeselectAll[ggData.scene, normal]; -- get rid of old selection
outer loop on each individual selected object
FOR nextSelected: REF ANY ← GGScene.NextEntity[selectedGen], GGScene.NextEntity[selectedGen] UNTIL nextSelected=NIL DO
sBox: BoundBox;
currentEntity: REF ANY;
WITH nextSelected SELECT FROM
outlineD: SliceDescriptor => {
sBox ← outlineD.slice.class.getBoundBox[outlineD.slice, outlineD.parts];
currentEntity ← outlineD.slice;
};
sliceD: SliceDescriptor => {
sBox ← sliceD.slice.class.getBoundBox[sliceD.slice, sliceD.parts];
currentEntity ← sliceD.slice;
};
ENDCASE => ERROR;
inner loop on each individual scene object
sceneGen ← GGScene.TopLevelEntitiesInScene[ggData.scene];
FOR nextEntity: REF ANY ← GGScene.NextEntity[sceneGen], GGScene.NextEntity[sceneGen] UNTIL nextEntity=NIL DO
IF nextEntity=currentEntity THEN LOOP;
IF NOT GGSelect.IsSelectedInFull[nextEntity, ggData.scene, normal] THEN -- don't reprocess
WITH nextEntity SELECT FROM
outline: Slice => {
IF Within[outline.class.getBoundBox[outline, NIL], sBox] THEN {
GGSelect.SelectEntireSlice[outline, ggData.scene, normal];
};
};
slice: Slice => {
IF Within[slice.class.getBoundBox[slice, NIL], sBox] THEN {
GGSelect.SelectSlice[slice.class.newParts[slice, NIL, topLevel], ggData.scene, normal ];
};
};
ENDCASE => ERROR;
ENDLOOP;
ENDLOOP;
IF paint THEN GGWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
}; -- end AreaSelectAux
GGEventImplD.mesa
SelectMatchingAreaColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
ggData: GGData ← NARROW[clientData];
rgb: ImagerColor.RGB;
name: Rope.ROPEIF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first];
entityGen: SliceGenerator ← GGScene.TopLevelEntitiesInScene[ggData.scene];
noneFlag: BOOL ← Rope.Equal[name, "none", FALSE];
IF NOT noneFlag THEN rgb ← SELECT event.first FROM
$SelectMatchingAreaCNS =>
ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[name !
NamedColors.UndefinedName => GOTO UndefinedName;
NamedColors.BadGrammar => GOTO BadGrammar;
]],
$SelectMatchingAreaRGB =>
RGBFromRope[name ! RGBFromRopeError => GOTO SyntaxError]
ENDCASE => ERROR;
GGSelect.DeselectAll[ggData.scene, normal];
FOR entity: REF ANY ← GGScene.NextEntity[entityGen], GGScene.NextEntity[entityGen] UNTIL entity = NIL DO
WITH entity SELECT FROM
outline: Slice => {
fillColor: Imager.Color ← outline.class.getFillColor[outline];
IF RGBEqualsColor[rgb, fillColor, noneFlag] THEN GGSelect.SelectEntireOutline[outline, ggData.scene, normal];
};
slice: Slice => {
fillColor: Imager.Color ← slice.class.getFillColor[slice];
IF RGBEqualsColor[rgb, fillColor, noneFlag] THEN GGSelect.SelectSlice[slice.class.newParts[slice, NIL, topLevel], ggData.scene, normal];
};
ENDCASE => ERROR;
ENDLOOP;
Feedback.PutFHerald[ggData.feedback, oneLiner, "Areas with fill color %g selected", [rope[name]] ];
GGWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
EXITS
SyntaxError => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "RGB Syntax is R: [0.0..1.0] G: [0.0..1.0] B: [0.0..1.0]", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];};
UndefinedName => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Undefined Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];};
BadGrammar => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Bad Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];};
};
TestMultiGravity: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = {
ggData: GGData ← NARROW[clientData];
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.
xRandomStream, yRandomStream: Random.RandomStream;
testPoint: Point;
x, y: INT;
totalCount: NAT ← 0;
features: GGMultiGravity.NearFeatures;
points: GGMultiGravity.NearPoints;
distances: GGMultiGravity.NearDistances;
currentObjects: AlignBag;
sceneObjects: TriggerBag;
count: NAT;
xRandomStream ← Random.Create[ggData.actionArea.cw];
yRandomStream ← Random.Create[ggData.actionArea.ch];
GGAlign.SetBagsForAction[ggData, $CaretPos];
GGWindow.RestoreScreenAndInvariants[paintAction: $PaintAlign, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
ggData.hitTest.hitCount ← 0;
ggData.aborted[gravitytest] ← FALSE; -- in case there was one left over from prior abort
UNTIL totalCount > 1000 DO
IF ggData.aborted[gravitytest] THEN {
ggData.aborted[gravitytest] ← FALSE;
EXIT;
};
x ← Random.NextInt[xRandomStream];
y ← Random.NextInt[yRandomStream];
testPoint ← [x, y];
testPoint ← GGWindow.ViewerToWorld[viewerPoint: testPoint, ggData: ggData];
ggData.refresh.spotPoint ← testPoint;
currentObjects ← ggData.hitTest.alignBag;
sceneObjects ← ggData.hitTest.sceneBag;
[features, points, distances, count] ← GGMultiGravity.MultiMap[20, testPoint, ggData.hitTest.tolerance, currentObjects, sceneObjects, ggData, TRUE];
IF count > 0 THEN {
FOR i: NAT IN [0..count-1] DO
ggData.refresh.hitPoint ← points[i];
IF distances[i] > ggData.hitTest.tolerance THEN GOTO Done;
GGWindow.RestoreScreenAndInvariants[paintAction: $PaintHitLine, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
ggData.hitTest.hitCount ← ggData.hitTest.hitCount + 1;
REPEAT
Done => {
IF i = 0 THEN
GGWindow.RestoreScreenAndInvariants[paintAction: $PaintSpot, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
};
ENDLOOP;
}
ELSE {
GGWindow.RestoreScreenAndInvariants[paintAction: $PaintSpot, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
};
totalCount ← totalCount + 1;
ENDLOOP;
Feedback.PutF[ggData.feedback, oneLiner, "Tested %g total points. %g were hits", [integer[totalCount]], [integer[ggData.hitTest.hitCount]]];
};
GGFileInImpl.mesa
GGFileOutImpl.mesa
FileoutSceneAndOptionsOLDD: PUBLIC PROC [f: IO.STREAM, ggData: GGData, fileName: Rope.ROPE] = {
entityGen: SliceGenerator ← GGScene.TopLevelEntitiesInScene[ggData.scene];
entityCount: NAT ← GGScene.EntityCount[entityGen];
fileName ← FileNames.GetShortName[fileName];
f.PutF["Gargoyle file for scene: %g\n", [rope[fileName]]];
f.PutF["Produced by version %g\n\n", [rope[versionRope]]];
FileoutAlignments[f, ggData];
f.PutF["Entities: [%g]:\n\n", [integer[entityCount]]];
FOR entity: REF ANY ← GGScene.NextEntity[entityGen], GGScene.NextEntity[entityGen] UNTIL entity = NIL DO
FileoutEntity[f, entity];
ENDLOOP;
};
FileoutSceneOnlyOLDD: PUBLIC PROC [f: IO.STREAM, scene: Scene, fileName: Rope.ROPE] = {
entityGen: SliceGenerator ← GGScene.TopLevelEntitiesInScene[scene];
entityCount: NAT ← GGScene.EntityCount[entityGen];
fileName ← FileNames.GetShortName[fileName];
f.PutF["Gargoyle file for scene: %g\n", [rope[fileName]]];
f.PutF["Produced by version %g\n\n", [rope[versionRope]]];
FileoutAlignments[f, ggData];
f.PutChar[IO.CR];
f.PutChar[IO.CR];
f.PutF["Entities: [%g]:\n\n", [integer[entityCount]]];
FOR entity: REF ANY ← GGScene.NextEntity[entityGen], GGScene.NextEntity[entityGen] UNTIL entity = NIL DO
FileoutEntity[f, entity];
ENDLOOP;
};
FileoutEntityOLDD: PROC [f: IO.STREAM, entity: REF ANY] = {
WITH entity SELECT FROM
slice: Slice => FileoutSlice[f, slice];
outline: Slice => outline.class.fileout[outline, f];
ENDCASE => ERROR;
};
FileoutSliceOLDD: PUBLIC PROC [f: IO.STREAM, slice: Slice] = {
className: Rope.ROPE ← Atom.GetPName[slice.class.type];
f.PutF["Slice (class: %g) [%g]:\n", [rope[className]], [integer[0]]];
f.PutF["Data: "];
slice.class.fileout[slice, f];
f.PutChar[IO.CR];
f.PutChar[IO.CR];
};
GGFontImpl.mesa
GGFromImagerImpl.mesa
GGGravityImpl.mesa
AddLineIntersections: PROC [featureData: FeatureData, objectBag: AlignBag] = {
iPoint: Point;
parallel: BOOL;
points: ARRAY[1..2] OF Point;
hitCount: NAT;
line: Line;
WITH featureData.shape SELECT FROM
l: Line => line ← l;
aL: AlignmentLine => line ← aL.line;
ENDCASE => ERROR Problem[msg: "Broken Invariant"];
FOR lineList: LIST OF FeatureData ← objectBag.slopeLines, lineList.rest UNTIL lineList = NIL DO
[iPoint, parallel] ← Lines2d.LineMeetsLine[NARROW[lineList.first.shape, AlignmentLine].line, line];
IF NOT parallel THEN {
AddIntersectionPointFeature[iPoint, featureData, lineList.first, objectBag];
};
ENDLOOP;
FOR lineList: LIST OF FeatureData ← objectBag.angleLines, lineList.rest UNTIL lineList = NIL DO
[iPoint, parallel] ← Lines2d.LineMeetsLine[NARROW[lineList.first.shape, AlignmentLine].line, line];
IF NOT parallel THEN {
AddIntersectionPointFeature[iPoint, featureData, lineList.first, objectBag];
};
ENDLOOP;
FOR dlineList: LIST OF FeatureData ← objectBag.distanceLines, dlineList.rest UNTIL dlineList = NIL DO
[iPoint, parallel] ← Lines2d.LineMeetsLine[NARROW[dlineList.first.shape], line];
IF NOT parallel THEN {
AddIntersectionPointFeature[iPoint, featureData, dlineList.first, objectBag];
};
ENDLOOP;
FOR circleList: LIST OF FeatureData ← objectBag.radiiCircles, circleList.rest UNTIL circleList = NIL DO
[points, hitCount] ← GGCircles.LineMeetsCircle[line, NARROW[circleList.first.shape, AlignmentCircle].circle];
FOR i: NAT IN [1..hitCount] DO
AddIntersectionPointFeature[points[i], featureData, circleList.first, objectBag];
ENDLOOP;
ENDLOOP;
};
AddCircleIntersections: PROC [featureData: FeatureData, objectBag: AlignBag] = {
points: ARRAY[1..2] OF Point;
hitCount: NAT;
circle: Circle ← NARROW[featureData.shape, AlignmentCircle].circle;
FOR lineList: LIST OF FeatureData ← objectBag.slopeLines, lineList.rest UNTIL lineList = NIL DO
[points, hitCount] ← GGCircles.LineMeetsCircle[NARROW[lineList.first.shape, AlignmentLine].line, circle];
FOR i: NAT IN [1..hitCount] DO
AddIntersectionPointFeature[points[i], lineList.first, featureData, objectBag];
ENDLOOP;
ENDLOOP;
FOR lineList: LIST OF FeatureData ← objectBag.angleLines, lineList.rest UNTIL lineList = NIL DO
[points, hitCount] ← GGCircles.LineMeetsCircle[NARROW[lineList.first.shape, AlignmentLine].line, circle];
FOR i: NAT IN [1..hitCount] DO
AddIntersectionPointFeature[points[i], lineList.first, featureData, objectBag];
ENDLOOP;
ENDLOOP;
FOR dlineList: LIST OF FeatureData ← objectBag.distanceLines, dlineList.rest UNTIL dlineList = NIL DO
[points, hitCount] ← GGCircles.LineMeetsCircle[NARROW[dlineList.first.shape], circle];
FOR i: NAT IN [1..hitCount] DO
AddIntersectionPointFeature[points[i], dlineList.first, featureData, objectBag];
ENDLOOP;
ENDLOOP;
FOR circleList: LIST OF FeatureData ← objectBag.radiiCircles, circleList.rest UNTIL circleList = NIL DO
[points, hitCount] ← GGCircles.CircleMeetsCircle[NARROW[circleList.first.shape, AlignmentCircle].circle, circle];
FOR i: NAT IN [1..hitCount] DO
AddIntersectionPointFeature[points[i], circleList.first, featureData, objectBag];
ENDLOOP;
ENDLOOP;
};
AddIntersectionPointFeature: PRIVATE PROC [point: Point, feature1, feature2: FeatureData, objectBag: AlignBag] = {
featureData: FeatureData;
alignmentPoint: AlignmentPoint;
featureData ← NEW[FeatureDataObj];
alignmentPoint ← NEW[AlignmentPointObj ← [point: point, curve1: feature1, curve2: feature2]];
featureData.type ← intersectionPoint;
featureData.shape ← alignmentPoint;
AddFeature[featureData, objectBag];
};
Map: PUBLIC PROC [testPoint: Point, criticalR: REAL, currentObjects: AlignBag, activeObjects: TriggerBag, ggData: GGData, intersections: BOOL] RETURNS [resultPoint: Point, feature: FeatureData] = {
ENABLE UNWIND => ggData.gravityPool ← NewGravityPool[]; -- in case an ABORT happened while pool was in use
[resultPoint, feature] ← GGMultiGravity.Map[testPoint, criticalR, currentObjects, activeObjects, ggData, intersections];
};
ExtractResultFromCurve: PROC [curve: GoodCurve, feature: FeatureData] = {
SELECT feature.type FROM
outline => feature.hitPart ← curve.hitData;
slice => feature.hitPart ← curve.hitData;
slopeLine, angleLine, radiiCircle, distanceLine => {};
ENDCASE => SIGNAL Problem[msg: "Unimplemented type."];
};
ExtractResultFromPoint: PROC [goodPoint: GoodPoint, feature: FeatureData] = {
SELECT goodPoint.type FROM
joint, controlPoint => feature.hitPart ← goodPoint.hitData;
slice => feature.hitPart ← goodPoint.hitData;
intersectionPoint => feature.hitPart ← NIL;
midpoint => {
midPoint features contain a reasonable segNum in their hitPart
};
ENDCASE => SIGNAL Problem [msg: "Unimplemented result type."];
};
GGInterfaceImpl.mesa
GGMeasureImpl.mesa
GGMenusImpl.mesa
OverlapMenu: Menus.ClickProc = {
ggData: GGData ← NARROW[clientData];
menu: LIST OF PopUpMenuEntry;
menu ← LIST [
["Top", ],
["Bottom", LIST [$Bottom]],
["UpOne", LIST [$UpOne]],
["DownOne", LIST [$DownOne]]
];
QueuePopUpMenuAction["Overlap", menu, ggData, mouseButton#blue];
};
GGMouseEventImplA.mesa
UpdateSceneForCopy: PROC [scene: Scene, feedback: FeedbackData] RETURNS [newSlices: LIST OF Slice, success: BOOLTRUE] = {
sliceDGen: SliceDescriptorGenerator;
outSeqGen: GGSelect.OutlineSequenceGenerator;
newOutline, outline: Slice;
newTraj: Traj;
newSlice: Slice;
Copy selected slices.
sliceDGen ← GGSelect.SelectedSlices[scene, normal];
FOR sliceD: SliceDescriptor ← GGSelect.NextSliceDescriptor[sliceDGen], GGSelect.NextSliceDescriptor[sliceDGen] UNTIL sliceD = NIL DO
newSlice ← GGSlice.CopySlice[sliceD.slice]; -- make the new one
GGSelect.DeselectSlice[sliceD.slice, sliceD.parts, scene, normal];
newSlices ← CONS[newSlice, newSlices];
newSlice.priority ← GGScene.SlicePriority[scene, sliceD.slice];
ENDLOOP;
BEGIN
outSeqGen ← GGSelect.SelectedOutlineSequences[scene, normal];
FOR outSeq: GGSelect.OutlineSequence ← GGSelect.NextOutlineSequences[outSeqGen], GGSelect.NextOutlineSequences[outSeqGen] UNTIL outSeq = NIL DO
outline ← outSeq.outline;
IF outSeq.fenceSeq # NIL THEN {
IF NOT GGSequence.ContainsSomeSegment[outSeq.fenceSeq] THEN GOTO NoSegmentsSelected;
If the whole outline is selected, copy it as a whole.
IF GGSelect.IsSelectedInFull[outline, scene, normal] THEN {
newOutline ← outline.class.copy[outline];
GGSelect.DeselectEntireSlice[outline, scene, normal]; -- deselect the old one
newSlices ← CONS[newOutline, newSlices];
newOutline.priority ← outline.priority;
LOOP;
}
Otherwise, each piece becomes a new slice.
ELSE {
newTraj ← GGTraj.CopyTrajFromRun[outSeq.fenceSeq];
newOutline ← GGOutline.CreateOutline[newTraj, outline.class.getFillColor[outline]];
GGSelect.DeselectSequence[outSeq.fenceSeq, scene, normal];
newSlices ← CONS[newOutline, newSlices];
newOutline.priority ← outline.priority;
};
};
FOR holeSeq: Sequence ← GGSequence.NextSequence[outSeq.holeSeqs], GGSequence.NextSequence[outSeq.holeSeqs] UNTIL holeSeq = NIL DO
IF NOT GGSequence.ContainsSomeSegment[holeSeq] THEN GOTO NoSegmentsSelected;
newTraj ← GGTraj.CopyTrajFromRun[holeSeq];
newOutline ← GGOutline.CreateOutline[newTraj, outline.class.getFillColor[outline]];
GGSelect.DeselectSequence[holeSeq, scene, normal];
newSlices ← CONS[newOutline, newSlices];
newOutline.priority ← outline.priority;
ENDLOOP;
ENDLOOP;
Sort the new slices
newSlices ← SortNewEntities[scene, newSlices];
Add all the new slices to the scene.
FOR sliceList: LIST OF Slice ← newSlices, sliceList.rest UNTIL sliceList = NIL DO
allParts: SliceDescriptor;
GGScene.AddSlice[scene, sliceList.first, -1];
allParts ← sliceList.first.class.newParts[sliceList.first, NIL, slice];
GGSelect.SelectSlice[allParts, scene, normal];
ENDLOOP;
EXITS
NoSegmentsSelected => {
Feedback.AppendHerald[feedback, ". . . Cannot Copy Joints or CPs", begin];
Feedback.Blink[feedback];
GGSelect.DeselectAll[scene, normal];
We are about to self-abort. We deselect all so that we don't delete any of the original geometry (see AbortCopyAndDrag above).
RETURN[NIL, FALSE];
};
END;
};
SafelyGetCaretTrajOLDD: PROC [caret: Caret] RETURNS [outlineD: SliceDescriptor, partType: TrajPartType, traj: Traj, jointNum: NAT] = {
chair: REF ANY;
success: BOOL;
chair ← GGCaret.GetChair[caret];
IF ISTYPE[chair, SliceDescriptor] THEN ERROR Problem[msg: "Slices are Outlines now. Update this code."];
outlineD ← NARROW[chair];
[success, partType, traj, ----, jointNum] ← GGOutline.UnpackSimpleDescriptorOld[outlineD];
IF NOT success OR partType # joint THEN ERROR Problem[msg: "Attempt to extend a trajectory without the caret on its end"];
};
GGMouseEventImplB.mesa
EndSelectAuxOLDD: PROC [ggData: GGData, resultPoint: Point, feature: FeatureData, hitData: REF ANY, mode: SelectMode, opName: Rope.ROPE] = {
Prepare for a subsequent Add operation and for Extend.
IF feature = NIL THEN {
GGCaret.SitOn[ggData.caret, NIL];
Feedback.PutFHerald[ggData.feedback, oneLiner, "No near %g found.", [rope[opName]]];
}
ELSE {
Make Selection and Prepare for Extend.
SELECT mode FROM
joint => ggData.drag.extendMode ← joint;
segment => ggData.drag.extendMode ← segmentRange;
traj => ggData.drag.extendMode ← traj;
topLevel => ggData.drag.extendMode ← topLevel;
ENDCASE => ERROR;
SELECT feature.type FROM
outline => {
outlineD: SliceDescriptor ← NARROW[SelectSlicePart[feature, hitData, ggData, mode]];
SitTheCaret[ggData.caret, outlineD, hitData, mode];
IF mode = topLevel THEN Feedback.AppendHerald[ggData.feedback, "Top level outline selected.", oneLiner]
ELSE Feedback.AppendHerald[ggData.feedback, Rope.Concat[outlineD.slice.class.describe[outlineD], " selected"], oneLiner];
ggData.drag.outlineToExtend ← outlineD;
ggData.drag.sliceToExtend ← NIL;
};
slice => {
sliceD: SliceDescriptor ← NARROW[SelectSlicePart[feature, hitData, ggData, mode]];
IF sliceD.slice.class.type = $Slice THEN {
ERROR Problem[msg: "Outlines must be Slices now."];
}
ELSE {
IF mode = traj OR mode = topLevel THEN GGCaret.SitOn[ggData.caret, NIL]
ELSE GGCaret.SitOn[ggData.caret, sliceD];
};
Feedback.AppendHerald[ggData.feedback, Rope.Concat[sliceD.slice.class.describe[sliceD], " selected"], oneLiner];
ggData.drag.outlineToExtend ← NIL;
ggData.drag.sliceToExtend ← sliceD;
};
ENDCASE => ERROR Problem[msg: "Unexpected feature type"];
};
GGWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
}; -- end EndSelectAux
SitTheCaretOLDD: PROC [caret: Caret, outlineD: SliceDescriptor, hitData: REF ANY, mode: SelectMode] = {
SELECT mode FROM
joint => GGCaret.SitOn[caret, outlineD];
segment, traj, topLevel => {
jointParts: SliceParts;
jointSeq: Sequence;
jointD: SliceDescriptor;
jointNum: NAT;
traj: Traj;
IF outlineD.slice.class.type = $Slice THEN {
[jointNum, traj] ← GGOutline.NearestJointToHitData[hitData];
jointSeq ← GGSequence.CreateFromJoint[traj, jointNum];
jointParts ← GGOutline.PartsFromSequence[outlineD.slice, jointSeq];
jointD ← GGOutline.DescriptorFromParts[outlineD.slice, jointParts];
GGCaret.SitOn[caret, jointD];
}
ELSE GGCaret.SitOn[caret, NIL];
};
ENDCASE => ERROR;
};
GGMultiGravityImpl.mesa
GGOutlineImplA.mesa
OutlineDescribeProc: TYPE = GGModelTypes.OutlineDescribeProc;
OutlineFileoutProc: TYPE = GGModelTypes.OutlineFileoutProc;
OutlineFileinProc: TYPE = GGModelTypes.OutlineFileinProc;
OutlineUnionPartsProc: TYPE = GGModelTypes.OutlineUnionPartsProc;
OutlineDifferencePartsProc: TYPE = GGModelTypes.OutlineDifferencePartsProc;
OutlineAugmentPartsProc: TYPE = GGModelTypes.OutlineAugmentPartsProc;
OutlinePointsInDescriptorProc: TYPE = GGModelTypes.OutlinePointsInDescriptorProc;
OutlinePointPairsInDescriptorProc: TYPE = GGModelTypes.OutlinePointPairsInDescriptorProc;
OutlineNextPointProc: TYPE = GGModelTypes.OutlineNextPointProc;
OutlineNextPointPairProc: TYPE = GGModelTypes.OutlineNextPointPairProc;
OutlineClosestPointProc: TYPE = GGModelTypes.OutlineClosestPointProc;
OutlineClosestPointAndTangentProc: TYPE = GGModelTypes.OutlineClosestPointAndTangentProc;
OutlineClosestSegmentProc: TYPE = GGModelTypes.OutlineClosestSegmentProc;
OutlineSetArrowsProc: TYPE = GGModelTypes.OutlineSetArrowsProc;
OutlineGetArrowsProc: TYPE = GGModelTypes.OutlineGetArrowsProc;
FetchSliceClass: PUBLIC PROC [name: ATOM] RETURNS [class: SliceClass] = {
class ← globalOutlineClass;
};
FetchOutlineClass: PROC [] RETURNS [class: SliceClass] = {
class ← globalOutlineClass;
};
globalOutlineClass: SliceClass;
Init: PROC [] = {
globalOutlineClass ← MakeOutlineClass[];
};
Init[];
GGOutlineImplB.mesa
OutlineDescribeProc: TYPE = GGModelTypes.OutlineDescribeProc;
OutlineFileoutProc: TYPE = GGModelTypes.OutlineFileoutProc;
OutlineFileinProc: TYPE = GGModelTypes.OutlineFileinProc;
OutlineUnionPartsProc: TYPE = GGModelTypes.OutlineUnionPartsProc;
OutlineDifferencePartsProc: TYPE = GGModelTypes.OutlineDifferencePartsProc;
OutlineAugmentPartsProc: TYPE = GGModelTypes.OutlineAugmentPartsProc;
OutlinePointsInDescriptorProc: TYPE = GGModelTypes.OutlinePointsInDescriptorProc;
OutlinePointPairsInDescriptorProc: TYPE = GGModelTypes.OutlinePointPairsInDescriptorProc;
OutlineNextPointProc: TYPE = GGModelTypes.OutlineNextPointProc;
OutlineNextPointPairProc: TYPE = GGModelTypes.OutlineNextPointPairProc;
OutlineClosestPointProc: TYPE = GGModelTypes.OutlineClosestPointProc;
OutlineClosestPointAndTangentProc: TYPE = GGModelTypes.OutlineClosestPointAndTangentProc;
OutlineClosestSegmentProc: TYPE = GGModelTypes.OutlineClosestSegmentProc;
OutlineSetArrowsProc: TYPE = GGModelTypes.OutlineSetArrowsProc;
OutlineGetArrowsProc: TYPE = GGModelTypes.OutlineGetArrowsProc;
UnpackSimpleDescriptorOld: PUBLIC PROC [outlineD: SliceDescriptor] RETURNS [success: BOOL, partType: TrajPartType, traj: Traj, joint: Joint ← NIL, jointNum: NAT ← 999, cp: Point, cpNum: NAT ← 999, seg: Segment ← NIL, segNum: NAT ← 999] = {
parts: OutlineParts;
theSeq: Sequence;
IF outlineD = NIL THEN RETURN[FALSE, joint, NIL, NIL, 999, [0,0]];
parts ← NARROW[outlineD.parts];
traj ← NIL;
FOR list: LIST OF Sequence ← parts.seqs, list.rest UNTIL list = NIL DO
IF list.first # NIL THEN {
IF traj # NIL THEN RETURN[FALSE, joint, NIL, NIL, 999, [0,0]]
ELSE {
theSeq ← list.first;
traj ← theSeq.traj;
[success, partType, traj, joint, jointNum, cp, cpNum, seg, segNum] ← GGSequence.UnpackSimpleSequence[theSeq];
};
};
ENDLOOP;
};
DescriptorFromParts: PUBLIC PROC [outline: Slice, sliceParts: SliceParts] RETURNS [sliceD: SliceDescriptor] = {
sliceD ← NEW[SliceDescriptorObj ← [outline, sliceParts]];
};
AddHole: PUBLIC PROC [outline: Slice, hole: Traj] RETURNS [holier: Slice] = {
Holes can be removed using DeleteSequence.
Should check for duplicates. -- Bier, February 20
holier ← outline.class.copy[outline];
holier.children ← AppendTrajList[holier.children, LIST[hole]];
hole.parent ← holier;
hole.role ← hole;
UpdateBoundBox[holier];
};
UpdateDescriptorBoundBoxes: PUBLIC PROC [outlineD: SliceDescriptor] = {
Update the bound boxes of all contained sequences.
parts: OutlineParts ← NARROW[outlineD.parts];
FOR list: LIST OF Sequence ← parts.seqs, list.rest UNTIL list = NIL DO
IF list.first # NIL THEN GGSequence.UpdateBoundBox[list.first];
ENDLOOP;
};
GGParseInImpl.mesa
GGParseOutImpl.mesa
GGRefreshImpl.mesa
AllSelectedOutlines: PROC [scene: Scene] RETURNS [selectedList: LIST OF Slice ← NIL] = {
Puts all the selected (hot & normal) outlines in a list, and returns them
ptr: LIST OF Slice;
outDGen: GGModelTypes.SliceDescriptorGenerator;
outDGen ← GGSelect.SelectedOutlines[scene, hot];
[selectedList, ptr] ← GGUtility.StartOutlineList[];
FOR outD: SliceDescriptor ← GGSelect.NextOutlineDescriptor[outDGen], GGSelect.NextOutlineDescriptor[outDGen] UNTIL outD = NIL DO
[selectedList, ptr] ← GGUtility.AddOutline[outD.slice, selectedList, ptr];
ENDLOOP;
outDGen ← GGSelect.SelectedOutlines[scene, normal];
FOR outD: SliceDescriptor ← GGSelect.NextOutlineDescriptor[outDGen], GGSelect.NextOutlineDescriptor[outDGen] UNTIL outD = NIL DO
IF NOT GGSelect.IsSelectedInPart[outD.slice, scene, hot] THEN [selectedList, ptr] ← GGUtility.AddOutline[outD.slice, selectedList, ptr];
ENDLOOP;
};
DrawCpsOfSelectedOutlines: PROC [dc: Imager.Context, scene: Scene, camera: CameraData, dragInProgress, caretIsMoving: BOOL] = {
normalD, hotD: SliceDescriptor;
normalParts, hotParts: SliceParts;
outline: Slice;
IF caretIsMoving OR dragInProgress THEN RETURN;
FOR oList: LIST OF Slice ← AllSelectedOutlines[scene], oList.rest UNTIL oList=NIL DO
outline ← oList.first;
normalD ← GGSelect.FindSelectedOutline[outline, scene, normal];
hotD ← GGSelect.FindSelectedOutline[outline, scene, hot];
normalParts ← IF normalD # NIL THEN normalD.parts ELSE NIL;
hotParts ← IF hotD # NIL THEN hotD.parts ELSE NIL;
outline.class.drawSelectionFeedback[outline, normalParts, hotParts, dc, camera, dragInProgress, caretIsMoving, FALSE, caretIsMoving];
ENDLOOP;
};
WhoCaresIfChairIsAttractor: PROC [ggData: GGData] RETURNS [attOn: GGInterfaceTypes.CaretOn, attractor: REF ANY, attJointNum: NAT, attSeg: Segment] = {
For now, I'm going to allow highlighting of moving objects. You only live once. Eric. Note: this procedure fixes a bug with ChairIsNotAttractor. Namely, highlighting does not occur with ChairIsNotAttractor when the caret is positioned on a selected segment.
[attractor: attractor, on: attOn, jointNum: attJointNum, seg: attSeg] ← GGCaret.GetAttractor[ggData.caret];
WITH attractor SELECT FROM
oSliceD: SliceDescriptor => {};
aSliceD: SliceDescriptor => {};
ENDCASE => attOn ← nothing;
};
ChairIsNotAttractor: PROC [ggData: GGData] RETURNS [attOn: GGInterfaceTypes.CaretOn, attractor: REF ANY, attJointNum: NAT, attSeg: Segment] = {
This code figures out if the chair and the attractor are "identical" in a bunch of weird cases. It returns on=nothing if they are "identical" and returns the attractor data if not "identical".
This is the wrong question to ask. The right thing to do is to take those objects that the caret is attracted to, and subtract away any parts that are moving. -- Bier, December 16, 1986.
chair: REF ANY;
chairOn: GGInterfaceTypes.CaretOn;
attSegNum, chairJointNum, chairSegNum: NAT;
chairSeg: Segment;
[attractor: attractor, on: attOn, jointNum: attJointNum, seg: attSeg, segNum: attSegNum] ← GGCaret.GetAttractor[ggData.caret];
[chair: chair, on: chairOn, jointNum: chairJointNum, segNum: chairSegNum, seg: chairSeg] ← GGCaret.GetChair[ggData.caret];
WITH attractor SELECT FROM
aTraj: Traj => {
attSeg1, attSeg2, chairSeg1, chairSeg2: NAT;
IF chair#attractor THEN RETURN; -- return attractor information
attractor and chair are the same traj
IF attOn=joint THEN {
IF GGTraj.IsEndJoint[aTraj, attJointNum] THEN attSeg2 ← attSeg1 ← IF attJointNum=0 THEN 0 ELSE attJointNum-1 -- open traj, end joint
ELSE { -- closed traj or not end joint
attSeg1 ← attJointNum;
attSeg2 ← GGTraj.PreviousSegmentNum[aTraj, attJointNum];
};
}
ELSE IF attOn=seg OR attOn=cp THEN attSeg2 ← attSeg1 ← attSegNum;
IF chairOn=joint THEN {
IF GGTraj.IsEndJoint[aTraj, chairJointNum] THEN chairSeg2 ← chairSeg1 ← IF chairJointNum=0 THEN 0 ELSE chairJointNum-1 -- open traj, end joint
ELSE { -- closed traj or not end joint
chairSeg1 ← chairJointNum;
chairSeg2 ← GGTraj.PreviousSegmentNum[aTraj, chairJointNum];
};
}
ELSE IF chairOn=seg OR chairOn=cp THEN chairSeg2 ← chairSeg1 ← chairSegNum;
IF attSeg1=chairSeg1 OR attSeg2=chairSeg1 OR attSeg1=chairSeg2 OR attSeg2=chairSeg2 THEN attOn ← nothing;
};
aSliceD: SliceDescriptor => { -- if slices are the same (don't user parts) then chair=attractor
WITH chair SELECT FROM
chairSliceD: SliceDescriptor => IF aSliceD.slice=chairSliceD.slice THEN attOn ← nothing;
ENDCASE;
};
ENDCASE => attOn ← nothing;
};
GetOutlineParts: PROC [sliceD: SliceDescriptor, atom: ATOM] RETURNS [parts: SliceDescriptor] = {
parts ← SELECT atom FROM
$DrawBackgroundBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].background,
$DrawOverlayBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].overlay,
$DrawRubberBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].rubber,
$DrawDragBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].drag,
ENDCASE => ERROR;
};
GGSceneImpl.mesa
TopLevelEntitiesInScene: PUBLIC PROC [scene: SceneRef] RETURNS [sliceGen: SliceGenerator] = {
Generates all of the outlines and slices in the scene.
sliceGen ← NEW[SliceGeneratorObj ← [
list: scene.entities
]];
};
NearestTrajectoryInScene: PUBLIC PROC [scene: SceneRef, worldPt: Point, ggData: GGData] RETURNS [traj: Traj] = {
feature: GGModelTypes.FeatureData;
resultPoint: Point;
sceneObjects: GGInterfaceTypes.TriggerBag;
sceneObjects ← NARROW[ggData.hitTest.sceneBag];
[resultPoint, feature] ← GGMultiGravity.StrictDistance[worldPt, ggData.hitTest.criticalR, GGAlign.emptyAlignBag, sceneObjects, ggData];
RETURN[IF feature=NIL OR feature.type=slice THEN NIL ELSE NARROW[feature.shape, Sequence].traj];
};
AddEntity: PUBLIC PROC [scene: SceneRef, entity: REF ANY, priority: INT] = {
Adds the entity to the scene. If priority = 0, it becomes the rearmost entity. IF priority = -1, it becomes the frontmost entity. If the priority given is too high, we proceed as if priority = -1.
IF priority = -1 THEN AppendEntity[scene, entity]
ELSE IF priority = 0 THEN {
scene.ptrValid ← FALSE;
scene.entities ← CONS[entity, scene.entities];
}
ELSE SIGNAL Problem["Not yet implemented."];
scene.prioritiesValid ← FALSE;
};
DeleteEntity: PUBLIC PROC [scene: SceneRef, entity: REF ANY] = {
Removes the named entity from the scene. If the entity is not on the list, no action is taken.
scene.ptrValid ← FALSE;
scene.entities ← List.DRemove[entity, scene.entities];
scene.prioritiesValid ← FALSE;
};
NextEntity: PUBLIC PROC [g: SliceGenerator] RETURNS [next: REF ANY] = {
IF g.list = NIL THEN RETURN[NIL]
ELSE {
next ← g.list.first;
g.list ← g.list.rest;
};
};
EntityCount: PUBLIC PROC [g: SliceGenerator] RETURNS [count: NAT] = {
IF g.countValid THEN RETURN[g.count];
count ← 0;
FOR list: LIST OF REF ANY ← g.list, list.rest UNTIL list = NIL DO
count ← count + 1;
ENDLOOP;
};
ListTrajsInSceneOLDD: PROC [scene: SceneRef] RETURNS [allTrajs: LIST OF Traj] = {
allTrajs ← NIL;
FOR entities: LIST OF REF ANY ← scene.entities, entities.rest UNTIL entities = NIL DO
WITH entities.first SELECT FROM
slice: Slice => {
};
outline: Slice => {
FOR trajs: LIST OF Traj ← outline.children, trajs.rest UNTIL trajs = NIL DO
allTrajs ← CONS[trajs.first, allTrajs];
ENDLOOP;
};
ENDCASE => ERROR;
ENDLOOP;
};
ListOutlinesInSceneOLDD: PROC [scene: SceneRef] RETURNS [allOutlines: LIST OF Slice] = {
allOutlines ← NIL;
FOR entities: LIST OF REF ANY ← scene.entities, entities.rest UNTIL entities = NIL DO
WITH entities.first SELECT FROM
slice: Slice => {
};
outline: Slice => {
allOutlines ← CONS[outline, allOutlines];
};
ENDCASE => ERROR;
ENDLOOP;
};
ListSlicesInSceneOLDD: PROC [scene: SceneRef] RETURNS [allSlices: LIST OF Slice] = {
allSlices ← NIL;
FOR entities: LIST OF REF ANY ← scene.entities, entities.rest UNTIL entities = NIL DO
WITH entities.first SELECT FROM
slice: Slice => {
Doesn't work on Gargoyle slices.
allSlices ← CONS[slice, allSlices];
};
outline: Slice => {};
ENDCASE => ERROR;
ENDLOOP;
};
GGSegmentImplA.mesa
CurveMaskStroke: PROC [seg: Segment, dc: Imager.Context] = {
GGSegmentTypes.MaskStrokeProc
Draw yourself into dc as a stroke. Assume that strokeWidth and color are already set.
path: CubicPaths.Path ← GetPath[seg];
pathProc: ImagerPath.PathProc = {CubicPaths.EnumeratePath[path, moveTo, curveTo]};
Imager.SetStrokeEnd[dc, seg.strokeEnd];
Imager.MaskStroke[dc, pathProc];
};
GGSegmentImplB.mesa
GGSelectImpl.mesa
SetComponentSelectedFields: PROC [entity: REF ANY, selected: BOOL, selectClass: SelectionClass] = {
WITH entity SELECT FROM
sliceD: SliceDescriptor => {
SetSliceField[sliceD.slice, selected, selectClass];
};
outlineD: SliceDescriptor => {
outlineD.slice.class.setSelectedFields[outlineD, selected, selectClass];
};
traj: Traj => { -- this case needed for ReselectTraj
joint: Joint;
jointGen: JointGenerator;
segGen: SegmentGenerator;
jointGen ← GGSequence.JointsInTraj[traj];
Joint Fields.
FOR jointNum: INT ← GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL jointNum = -1 DO
joint ← NARROW[Rosary.Fetch[traj.joints, jointNum]];
SetJointField[joint, selected, selectClass];
ENDLOOP;
Segment Fields.
segGen ← GGSequence.SegmentsInTraj[traj];
FOR seg: Segment ← GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO
SetSegmentField[seg, selected, selectClass];
ENDLOOP;
};
ENDCASE => ERROR;
};
ChangeDonkeyTailOutline: PROC [sliceD: SliceDescriptor, selectClass: SelectionClass] = {
SELECT selectClass FROM
normal => sliceD.slice.normalSelectedParts ← sliceD;
hot => sliceD.slice.hotSelectedParts ← sliceD;
active => sliceD.slice.activeSelectedParts ← sliceD;
ENDCASE;
};
NoDonkeyTailOutline: PROC [slice: Slice, selectClass: SelectionClass] = {
SELECT selectClass FROM
normal => slice.normalSelectedParts ← NIL;
hot => slice.hotSelectedParts ← NIL;
active => slice.activeSelectedParts ← NIL;
ENDCASE;
};
SelectOutline: PUBLIC PROC [sliceD: SliceDescriptor, scene: SceneRef, selectClass: SelectionClass] = {
oldD, union: SliceDescriptor;
slice: Slice ← sliceD.slice;
IF slice.class.emptyParts[sliceD] THEN RETURN;
oldD ← FindSelectedOutline[slice, scene, selectClass];
IF oldD # NIL THEN {
union ← slice.class.unionParts[oldD, sliceD];
DeselectOutline[slice, oldD.parts, scene, selectClass]; -- throw away old selection
}
ELSE union ← sliceD;
IF selectClass = normal THEN union ← slice.class.augmentParts[union, selectClass];
AppendSelection[scene, union, selectClass];
ChangeDonkeyTailOutline[union, selectClass];
}; -- end SelectOutline
SelectEntireOutline: PUBLIC PROC [outline: Slice, scene: SceneRef, selectClass: SelectionClass] = {
allParts: SliceDescriptor ← outline.class.newParts[outline, NIL, slice];
SelectOutline[allParts, scene, selectClass];
SelectEntireSlice[outline, scene, selectClass];
};
DeselectEntireSliceOLDD: PUBLIC PROC [slice: Slice, scene: SceneRef, selectClass: SelectionClass] = {
If this is a non-gargoyle slice, then make sure it is on the list, and take it off.
selSliceD: SliceDescriptor ← FindSelectedSlice[slice, scene, selectClass];
IF selSliceD#NIL THEN {
IF selSliceD.slice.class.type = $Slice THEN ERROR NotYetImplemented;
DeleteSelection[scene, selSliceD, selectClass];
NoDonkeyTail[selSliceD.slice, selectClass];
SetComponentSelectedFields[selSliceD, FALSE, selectClass];
};
};
DeselectOutline: PUBLIC PROC [outline: Slice, parts: SliceParts, scene: SceneRef, selectClass: SelectionClass] = {
Deselect each of the component trajectories;
oldD, newD, tempD: SliceDescriptor;
oldD ← FindSelectedOutline[outline, scene, selectClass];
IF oldD # NIL THEN {
tempD ← GGOutline.DescriptorFromParts[outline, parts];
newD ← outline.class.differenceParts[oldD, tempD];
DeleteSelection[scene, oldD, selectClass];
NoDonkeyTailOutline[outline, selectClass];
IF NOT outline.class.emptyParts[newD] THEN {
IF selectClass = normal THEN newD ← outline.class.augmentParts[newD, selectClass];
AppendSelection[scene, newD, selectClass];
ChangeDonkeyTailOutline[newD, selectClass];
};
};
};
DeselectEntireOutline: PUBLIC PROC [outline: Slice, scene: SceneRef, selectClass: SelectionClass] = {
Remove this outline from the selected list, and reset all selected fields.
outlineD: SliceDescriptor ← FindSelectedOutline[outline, scene, selectClass];
IF outlineD # NIL THEN {
DeleteSelection[scene, outlineD, selectClass];
NoDonkeyTailOutline[outlineD.slice, selectClass];
};
};
ListSelectedSequences: PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [selectedList: LIST OF Sequence] = {
This can be sped up by keeping separate lists for the different types of selected object.
seq: Sequence;
selectedList ← NIL;
FOR entityList: LIST OF REF ANY ← ListSelected[scene, selectClass], entityList.rest UNTIL entityList = NIL DO
IF ISTYPE[entityList.first, Sequence] THEN {
seq ← NARROW[entityList.first];
selectedList ← CONS[seq, selectedList];
};
ENDLOOP;
};
IsSelectedInFullOLDD: PUBLIC PROC [entity: REF ANY, scene: SceneRef, selectClass: SelectionClass] RETURNS [BOOL] = {
WITH entity SELECT FROM
slice: Slice => {
IF slice.class.type = $Slice THEN ERROR NotYetImplemented;
SELECT selectClass FROM
normal => RETURN[slice.selectedInFull.normal];
hot => RETURN[slice.selectedInFull.hot];
active => RETURN[slice.selectedInFull.active];
ENDCASE => ERROR;
};
outline: Slice => {
trajGen: TrajGenerator;
trajGen ← GGOutline.TrajsInOutline[outline];
FOR traj: Traj ← GGScene.NextTraj[trajGen], GGScene.NextTraj[trajGen] UNTIL traj = NIL DO
IF NOT IsSelectedInFull[traj, scene, selectClass] THEN RETURN[FALSE];
ENDLOOP;
RETURN[TRUE];
};
traj: Traj => {
seq: Sequence;
seq ← FindSelectedSequence[traj, scene, selectClass];
IF seq = NIL THEN RETURN[FALSE];
RETURN[GGSequence.IsComplete[seq]];
};
ENDCASE => ERROR;
};
FindSelectedOutline: PUBLIC PROC [outline: Slice, scene: SceneRef, selectClass: SelectionClass] RETURNS [outlineD: SliceDescriptor] = {
SELECT selectClass FROM
normal => outlineD ← IF outline.normalSelectedParts = NIL THEN NIL ELSE outline.normalSelectedParts;
hot => outlineD ← IF outline.hotSelectedParts = NIL THEN NIL ELSE outline.hotSelectedParts;
active => outlineD ← IF outline.activeSelectedParts = NIL THEN NIL ELSE outline.activeSelectedParts;
ENDCASE => ERROR;
};
SelectedStuff: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [sliceDescGen: SliceDescriptorGenerator] = {
ptr: LIST OF SliceDescriptor ← NIL;
sliceDescGen ← NEW[SliceDescriptorGeneratorObj];
FOR sliceDList: LIST OF SliceDescriptor ← ListSelected[scene, selectClass], sliceDList.rest UNTIL sliceDList = NIL DO
[sliceDescGen.list, ptr] ← AddSliceDescriptor[sliceDList.first, sliceDescGen.list, ptr];
ENDLOOP;
};
SelectedSlices: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [sliceDescGen: SliceDescriptorGenerator] = {
sliceD: SliceDescriptor ← NIL;
ptr: LIST OF SliceDescriptor ← NIL;
sliceDescGen ← NEW[SliceDescriptorGeneratorObj];
FOR entityList: LIST OF REF ANY ← ListSelected[scene, selectClass], entityList.rest UNTIL entityList = NIL DO
IF ISTYPE[entityList.first, SliceDescriptor] THEN {
sliceD ← NARROW[entityList.first];
[sliceDescGen.list, ptr] ← AddSliceDescriptor[sliceD, sliceDescGen.list, ptr];
};
ENDLOOP;
};
NextOutlineDescriptor: PUBLIC PROC [g: SliceDescriptorGenerator] RETURNS [next: SliceDescriptor] = {
IF g.list = NIL THEN RETURN[NIL]
ELSE {
next ← g.list.first;
g.list ← g.list.rest;
};
};
AddOutlineDescriptor: PROC [entity: SliceDescriptor, entityList, ptr: LIST OF SliceDescriptor] RETURNS [newList, newPtr: LIST OF SliceDescriptor] = {
IF ptr = NIL THEN {
IF NOT entityList = NIL THEN ERROR;
newPtr ← newList ← CONS[entity, NIL];
RETURN;
}
ELSE {
newList ← entityList;
ptr.rest ← CONS[entity, NIL];
newPtr ← ptr.rest;
};
};
SelectedOutlineSequencesOLDD: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [outSeqGen: OutlineSequenceGenerator] = {
Returns a generator for all selected sequences, grouped by outline.
holeSeqs, ptr: LIST OF Sequence;
outSeqPtr: LIST OF OutlineSequence;
outlineSeq: OutlineSequence;
fenceSeq, seq: Sequence;
entityGen: GGModelTypes.SliceGenerator;
seqList: LIST OF Sequence;
newSeqGen: SequenceGenerator;
outSeqGen ← NEW[OutlineSequenceGeneratorObj];
[outSeqGen.list, outSeqPtr] ← StartOutlineSequenceList[];
entityGen ← SelectedStuff[scene, selectClass];
FOR entity: REF ANY ← GGScene.NextEntity[entityGen], GGScene.NextEntity[entityGen] UNTIL entity = NIL DO
WITH entity SELECT FROM
sliceD: SliceDescriptor => NULL;
outlineD: SliceDescriptor => {
fenceSeq ← NIL;
[holeSeqs, ptr] ← GGUtility.StartSequenceList[];
seqList ← GGOutline.SequencesOfOutline[outlineD];
seq ← seqList.first;
IF seq.traj.role = fence OR seq.traj.role = open THEN {
fenceSeq ← seq;
seqList ← seqList.rest;
};
FOR list: LIST OF Sequence ← seqList, list.rest UNTIL list = NIL DO
[holeSeqs, ptr] ← GGUtility.AddSequence[list.first, holeSeqs, ptr];
ENDLOOP;
newSeqGen ← IF holeSeqs=NIL THEN nilSeqGen ELSE NEW[SequenceGeneratorObj ← [list: holeSeqs]];
outlineSeq ← NEW[OutlineSequenceObj ← [outline: outlineD.slice, fenceSeq: fenceSeq, holeSeqs: newSeqGen]];
[outSeqGen.list, outSeqPtr] ← AddOutlineSequence[outlineSeq, outSeqGen.list, outSeqPtr];
};
ENDCASE => ERROR;
ENDLOOP;
};
DoForEachSelectedOutline: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass, outlineProc: OutlineProc] = {
outDGen: SliceDescriptorGenerator ← SelectedOutlines[scene, selectClass];
FOR outlineD: SliceDescriptor ← NextOutlineDescriptor[outDGen], NextOutlineDescriptor[outDGen] UNTIL outlineD = NIL DO
outlineProc[outlineD];
ENDLOOP;
};
SetSliceField: PROC [slice: Slice, selected: BOOL, selectClass: SelectionClass] = {
SELECT selectClass FROM
normal => slice.selectedInFull.normal ← selected;
hot => slice.selectedInFull.hot ← selected;
active => slice.selectedInFull.active ← selected;
ENDCASE;
};
GGSequenceImpl.mesa
GGSessionLogImpl.mesa
GGShapesImpl.mesa
GGSliceImplA.mesa
UpdateDescriptorBoundBoxesOLDD: PUBLIC PROC [sliceD: SliceDescriptor] = {
IF sliceD.slice.class.type = $Outline THEN SIGNAL Problem[msg: "Time to have this proc call GGOutline.UpdateDescriptorBoundBoxes"];
};
SegmentsInDescriptorOLDD: PUBLIC PROC [sliceD: SliceDescriptor] RETURNS [segGen: SegmentGenerator] = {
IF sliceD.slice.class.type=$Outline THEN SIGNAL Problem[msg: "GGSlice.SegmentsInSlice called with Slice slice. ILLEGAL"]
ELSE segGen ← sliceD.slice.class.segmentsInDescriptor[sliceD];
};
WalkSegmentsOLDD: PUBLIC PROC [slice: Slice, walkProc: WalkProc] RETURNS [sliceD: SliceDescriptor] = {
Calls the slice class walkSegments proc.
The walkProc is called with each segment in the slice. If walkProc returns TRUE, the part of the slice that corresponds to the segment will be in the SliceDescriptor returned by WalkSegments.
IF slice.class.type=$Outline THEN SIGNAL Problem[msg: "GGSlice.WalkSegments called with Slice slice. ILLEGAL"]
ELSE sliceD ← slice.class.walkSegments[slice, walkProc];
};
GGSliceImplB.mesa
GGSliceImplC.mesa
GGStateImpl.mesa
GGTrajImpl.mesa
GGTransformImpl.mesa
GGUserInputImpl.mesa
GGUserProfileImpl.mesa
GGUtilityImpl.mesa
GGViewerOpsImpl.mesa
GGWindowImpl.mesa
PlaceOrigin: PROC [viewer: Viewer] = {
viewer is the ActionArea. The created bitmap contexts have their transformations concatted with the analogous BiScrollers transformation so that operations on the new bitmaps will match the viewer when they are finally displayed.
clientToViewer: Imager.Transformation;
ggData: GGData ← NARROW[BiScrollers.ClientDataOfViewer[viewer]];
[clientToViewer, ----] ← BiScrollers.GetStyle[].GetTransforms[BiScrollers.QuaBiScroller[viewer]];
BufferedRefresh.FitSandwichToScreen[ggData.refresh.sandwich, viewer.cw, viewer.ch];
};