File: SVEditUserImplD.mesa
-- Last edited by Bier on July 6, 1983 4:51 pm
-- Contents: All of the procedures called by SVEditTool when menus and buttons are pressed (part 4)
DIRECTORY
 CoordSys,
 CSGGraphics,
 DisplayList3d,
 Fileout3d,
 GraphicsColor,
 IO,
 Labels,
 Matrix3d,
 Menus,
 MessageWindow,
 Rope,
 SVArtwork,
 SVArtworkUser,
 SVEditUser,
 SVEditUserB,
 SVMappings,
 SVTransforms,
 SVViewerTools,
 SVViewerUser,
 TFO3d,
 ViewerClasses,
 ViewerTools;
 
SVEditUserImplD: CEDAR PROGRAM
 IMPORTS CoordSys, CSGGraphics, DisplayList3d, Fileout3d, IO, Labels, Matrix3d, MessageWindow, Rope, SVArtwork, SVArtworkUser, SVEditUser, SVMappings, SVTransforms, SVViewerTools, SVViewerUser, TFO3d, ViewerTools
 EXPORTS SVEditUser, SVEditUserB =
 
BEGIN

Artwork: TYPE = SVArtwork.Artwork;
Assembly: TYPE = DisplayList3d.Assembly;
AssemblyList: TYPE = DisplayList3d.AssemblyList;
AssemblyGenerator: TYPE = DisplayList3d.AssemblyGenerator;
Camera: TYPE = CSGGraphics.Camera;
Color: TYPE = GraphicsColor.Color;
CoordSystem: TYPE = CoordSys.CoordSystem;
EditToolData: TYPE = SVEditUser.EditToolData;
LightSource: TYPE = DisplayList3d.LightSource;
Material: TYPE = SVArtwork.Material;
MasterObject: TYPE = DisplayList3d.MasterObject;
MasterObjectList: TYPE = DisplayList3d.MasterObjectList;
Matrix4by4: TYPE = Matrix3d.Matrix4by4;
MouseButton: TYPE = Menus.MouseButton;
NameAlreadyPresent: SIGNAL = DisplayList3d.NameAlreadyPresent;
OMap: TYPE = SVArtwork.OMap;
Point3d: TYPE = Matrix3d.Point3d;
Scene: TYPE = DisplayList3d.Scene;
SMap: TYPE = SVArtwork.SMap;
Tube: TYPE = SVMappings.Tube;
Box: TYPE = SVMappings.Box;
Viewer: TYPE = ViewerClasses.Viewer;
ViewerCell: TYPE = REF ViewerCellObj;
ViewerCellObj: TYPE = SVEditUser.ViewerCellObj;
ViewerToolData: TYPE = SVViewerUser.ViewerToolData;
ViewerPictureData: TYPE = SVViewerUser.ViewerPictureData;

-- GLOBAL VARIABLES

globalMatCount: NAT = SVEditUser.globalMatCount;
globalMatArray: PUBLIC ARRAY[1..globalMatCount] OF Rope.ROPE ←
 ["plastic", "chalk"];
globalBoxOMapIndex: PUBLIC NAT ← 1;
globalBoxOMapCount: NAT = 2;
globalBoxOMapArray: PUBLIC ARRAY[1..globalBoxOMapCount] OF Rope.ROPE ←
 ["Orthogonal", "Radial"];
  
ListScenes: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 g: DisplayList3d.SceneGenerator;
 scene: Scene;
 outHandle: IO.STREAM ← SVEditUser.GetOutHandle[];
 g ← DisplayList3d.GetSceneGenerator[];
 scene ← DisplayList3d.NextScene[g];
 outHandle.PutRope["Listing Current Scenes...\n"];
 UNTIL scene = NIL DO
  outHandle.PutF[" %g\n",[rope[scene.name]]];
  scene ← DisplayList3d.NextScene[g];
 ENDLOOP;
 }; -- end of ListScenes
 
ListAssemblies: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 name: Rope.ROPE;
 outHandle: IO.STREAM ← SVEditUser.GetOutHandle[];
 g: AssemblyGenerator;
 a: Assembly;
 outHandle.PutF["Listing top level assemblies in scene: %g\n",
  [rope[scene.name]]];
 g ← DisplayList3d.GetAssemblyGenerator[scene];
 a ← DisplayList3d.NextAssembly[g];
 UNTIL a = NIL DO
  name ← a.name;
  outHandle.PutF[" %g coordSys: %g wrt: %g",
   [rope[name]], [rope[a.coordSys.name]], [rope[a.coordSys.withRespectTo.name]]];
  IF ISTYPE[a.object, AssemblyList] THEN outHandle.PutF[" [cluster]\n"]
   ELSE outHandle.PutF[" [primitive]\n"];
  a ← DisplayList3d.NextAssembly[g];
 ENDLOOP;
 }; -- end of ListAssemblies
 
ListCoordSystems: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 g: CoordSys.Generator;
 outHandle: IO.STREAM ← SVEditUser.GetOutHandle[];
 cs: CoordSystem;
 g ← CoordSys.GetGenerator[currentScene.coordSystems];
 cs ← CoordSys.Next[g];
 outHandle.PutF["Listing Current CoordinateSystems in %g...\n",
  [rope[currentScene.name]]];
 UNTIL cs = NIL DO
  outHandle.PutF[" %g",[rope[cs.name]]];
  outHandle.PutChar[IO.SP];
  outHandle.PutRope["withRespectTo: "];
  IF cs.withRespectTo = NIL
   THEN IO.PutRope[outHandle,"NIL"]
   ELSE IO.PutRope[outHandle,cs.withRespectTo.name];
  IO.PutRope[outHandle, " mat:\n  "];
  TFO3d.FileoutMatrix[outHandle, cs.mat];   
  IO.PutChar[outHandle, IO.CR];
  IO.PutRope[outHandle, "  wrtCamera:\n  "];
  TFO3d.FileoutMatrix[outHandle, cs.wrtCamera];
  IO.PutChar[outHandle, IO.CR];
  IO.PutChar[outHandle, IO.CR];
  cs ← CoordSys.Next[g];
 ENDLOOP;
 }; -- end of ListCoordSystems
 
ListLights: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 outHandle: IO.STREAM ← SVEditUser.GetOutHandle[];
 outHandle.PutRope["Listing Current LightSources...\n"];
 Fileout3d.FileoutLightSources[outHandle, currentScene.lightSources];
 };

ListMasterObjects: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 outHandle: IO.STREAM ← SVEditUser.GetOutHandle[];
 list: MasterObjectList;
 outHandle.PutRope["Listing Current MasterObjects...\n"];
 FOR list ← DisplayList3d.MasterObjectsOfScene[currentScene], list.rest UNTIL list = NIL DO
  outHandle.PutF[" %g\n",
   [rope[list.first.name]] ];
 ENDLOOP;
 };
 
ListViewers: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 viewerToolData: ViewerToolData;
 viewerPictureData: ViewerPictureData;
 firstViewer: Viewer;
 count: NAT;
 outHandle: IO.STREAM ← SVEditUser.GetOutHandle[];
 FOR allList: LIST OF ViewerCell ← editToolData.allViewers, allList.rest UNTIL allList = NIL DO
  firstViewer ← allList.first.viewersOnScene;
  IF firstViewer = NIL THEN LOOP;
  viewerToolData ← NARROW[firstViewer.data];
  viewerPictureData ← NARROW[viewerToolData.viewerPicture.data];
  outHandle.PutF["\n%g: 1", [rope[viewerPictureData.scene.name]]];
  count ← 1;
  FOR viewerList: Viewer ← firstViewer.link, viewerList.link
  UNTIL viewerList = firstViewer OR viewerList = NIL DO
   count ← count + 1;
   outHandle.PutF[", %g", [integer[count]]];
  ENDLOOP;
 ENDLOOP;
 };

SetCamera: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 currentViewerToolData: ViewerToolData ← NARROW[editToolData.currentViewerToolData];
 currentViewerPictureData: ViewerPictureData ← NARROW[currentViewerToolData.viewerPicture.data];
 camera: Camera ← currentViewerPictureData.camera;
 focus: Point3d;
 origin: Point3d;
 focalLength: REAL;
  focus ← SVEditUser.GetPoint3d[editToolData.cameraSection.focus];
  currentViewerPictureData.focus ← focus;
  origin ← SVEditUser.GetPoint3d[editToolData.cameraSection.origin];
  focalLength ← SVViewerTools.GetReal[editToolData.cameraSection.focalLength, 1800];
 CSGGraphics.PlaceCamera[camera, focus, origin];
 CSGGraphics.SetFocalLengthCamera[camera, focalLength];
 SVViewerUser.DrawSceneInternal[currentViewerToolData.outer, currentViewerToolData, mouseButton, shift, control];
 }; -- end of SetCamera
 
SetFocus: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 currentViewerToolData: ViewerToolData ← NARROW[editToolData.currentViewerToolData];
 currentViewerPictureData: ViewerPictureData ← NARROW[currentViewerToolData.viewerPicture.data];
 camera: Camera ← currentViewerPictureData.camera;
 focus: Point3d;
  focus ← SVEditUser.GetPoint3d[editToolData.cameraSection.focus];
  currentViewerPictureData.focus ← focus;
 CSGGraphics.PlaceCamera[camera, focus, Matrix3d.OriginOfMatrix[camera.coordSys.mat]];
 SVViewerUser.DrawSceneInternal[currentViewerToolData.outer, currentViewerToolData, mouseButton, shift, control];
 }; -- end of SetFocus
 
SetResolution: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 currentViewerToolData: ViewerToolData ← NARROW[editToolData.currentViewerToolData];
 currentViewerPictureData: ViewerPictureData ← NARROW[currentViewerToolData.viewerPicture.data];
 camera: Camera ← currentViewerPictureData.camera;
 camera.resolution ← SVViewerTools.GetReal[editToolData.cameraSection.resolution, 72.0];
 }; -- end of SetResolution
  
SetOrigin: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 currentViewerToolData: ViewerToolData ← NARROW[editToolData.currentViewerToolData];
 currentViewerPictureData: ViewerPictureData ← NARROW[currentViewerToolData.viewerPicture.data];
 camera: Camera ← currentViewerPictureData.camera;
 origin: Point3d;
  origin ← SVEditUser.GetPoint3d[editToolData.cameraSection.origin];
 CSGGraphics.PlaceCamera[camera, currentViewerPictureData.focus, origin];
 SVViewerUser.DrawSceneInternal[currentViewerToolData.outer, currentViewerToolData, mouseButton, shift, control];
 }; -- end of SetOrigin
 
SetFocalLength: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 currentViewerToolData: ViewerToolData ← NARROW[editToolData.currentViewerToolData];
 currentViewerPictureData: ViewerPictureData ← NARROW[currentViewerToolData.viewerPicture.data];
 camera: Camera ← currentViewerPictureData.camera;
 focalLength: REAL ← SVViewerTools.GetReal[editToolData.cameraSection.focalLength, 1800];
 CSGGraphics.SetFocalLengthCamera[camera, focalLength];
 SVViewerUser.DrawSceneInternal[currentViewerToolData.outer, currentViewerToolData, mouseButton, shift, control];
 }; -- end of SetFocalLength
 
SetShadows: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 currentScene: Scene ← editToolData.sceneSection.currentScene;
 currentScene.shadows ← editToolData.cameraSection.shadowValue;
 }; -- end of SetFocalLength

NormalizeRot: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 -- find the mat between 'Assembly' and 'WithRespectTo', remove its rotational components leaving translation and scaling as they were.
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 found: BOOL ← TRUE;
 assemblyCS, wrtCS: CoordSystem;
 oldMat, newMat: Matrix4by4;
 [assemblyCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [wrtCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.wrt, scene];
 IF NOT found THEN RETURN;
 oldMat ← CoordSys.FindAinTermsOfB[a: assemblyCS, b: wrtCS];
 newMat ← Matrix3d.NormalizeNoRotation[oldMat];
 CoordSys.TPlaceAwrtB[a: assemblyCS, b: wrtCS, aWRTb: newMat];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 };

Normalize: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 -- find the mat between 'Assembly' and 'WithRespectTo', remove its rotational and translational components leaving scaling as it was.
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 found: BOOL ← TRUE;
 -- sx, sy, sz: REAL;
 assemblyCS, wrtCS: CoordSystem;
 -- oldMat: Matrix4by4;
 newMat: Matrix4by4;
 [assemblyCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [wrtCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.wrt, scene];
 IF NOT found THEN RETURN;
 -- oldMat ← CoordSys.FindAinTermsOfB[a: assemblyCS, b: wrtCS];
 -- [sx, sy, sz] ← Matrix3d.ScaleFromMatrix[oldMat];
 -- newMat ← Matrix3d.MakeScaleMat[sx, sy, sz];
 newMat ← Matrix3d.Identity[];
 CoordSys.TPlaceAwrtB[a: assemblyCS, b: wrtCS, aWRTb: newMat];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 };
 
Align: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 -- find the mat between 'Assembly' and 'WithRespectTo', rotate it as little as possible so that the axes of Assembly are parallel to some ordering of the axes of WithRespectTo.
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 found: BOOL ← TRUE;
 wrtCS: CoordSystem;
 assembly: Assembly;
 [assembly, found] ← SVEditUser.GetAssembly[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [wrtCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.wrt, scene];
 IF NOT found THEN RETURN;
 SVTransforms.Align[assembly, wrtCS];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 }; -- end of Align
 
Abut: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 -- simply translate Assembly to the origin of WithRespectTo.
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 found: BOOL ← TRUE;
 wrtCS: CoordSystem;
 assembly: Assembly;
 [assembly, found] ← SVEditUser.GetAssembly[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [wrtCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.wrt, scene];
 IF NOT found THEN RETURN;
 SVTransforms.Abut[assembly, wrtCS];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 }; -- end of Abut
 
AbutX: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 -- change the x translation between Assembly and WithRespectTo to be zero.
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 found: BOOL ← TRUE;
 wrtCS: CoordSystem;
 assembly: Assembly;
 [assembly, found] ← SVEditUser.GetAssembly[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [wrtCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.wrt, scene];
 IF NOT found THEN RETURN;
 SVTransforms.AbutX[assembly, wrtCS];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 }; -- end of AbutX
 
AbutY: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 -- change the y translation between Assembly and WithRespectTo to be zero.
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 found: BOOL ← TRUE;
 wrtCS: CoordSystem;
 assembly: Assembly;
 [assembly, found] ← SVEditUser.GetAssembly[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [wrtCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.wrt, scene];
 IF NOT found THEN RETURN;
 SVTransforms.AbutY[assembly, wrtCS];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 }; -- end of AbutY
 
AbutZ: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
 -- change the z translation between Assembly and WithRespectTo to be zero.
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 found: BOOL ← TRUE;
 wrtCS: CoordSystem;
 assembly: Assembly;
 [assembly, found] ← SVEditUser.GetAssembly[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [wrtCS, found] ← SVEditUser.GetCoordSys[editToolData.sceneSection.wrt, scene];
 IF NOT found THEN RETURN;
 SVTransforms.AbutZ[assembly, wrtCS];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 }; -- end of AbutZ
 

MaterialCycle: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 editToolData.artworkSection.materialValue ← IF editToolData.artworkSection.materialValue = globalMatCount THEN 1 ELSE editToolData.artworkSection.materialValue + 1;
 Labels.Set[editToolData.artworkSection.material, globalMatArray[editToolData.artworkSection.materialValue]];
 };
 
BoxOCycle: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 globalBoxOMapIndex ← IF globalBoxOMapIndex = globalBoxOMapCount THEN 1 ELSE globalBoxOMapIndex + 1;
 Labels.Set[editToolData.artworkSection.oMapLabel, globalBoxOMapArray[globalBoxOMapIndex]];
 };
  
ShadowsPrompt: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = {
 editToolData: EditToolData ← NARROW[clientData];
 IF editToolData.cameraSection.shadowValue THEN {
  Labels.Set[editToolData.cameraSection.shadowLabel, "FALSE"];
  editToolData.cameraSection.shadowValue ← FALSE;
  }
 ELSE {
  Labels.Set[editToolData.cameraSection.shadowLabel, "TRUE"];
  editToolData.cameraSection.shadowValue ← TRUE;
  };
 };

SetTubeArtwork: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 tubeHeight: REAL ← SVViewerTools.GetReal[editToolData.artworkSection.tubeHeight, 100];
 tubeRadius: REAL ← SVViewerTools.GetReal[editToolData.artworkSection.tubeRadius, 50];
 picName: Rope.ROPE ← ViewerTools.GetContents[editToolData.artworkSection.picName];
 materialName: Rope.ROPE ← globalMatArray[editToolData.artworkSection.materialValue];
 resolution: REAL ← SVViewerTools.GetReal[editToolData.artworkSection.resolution, 72.0];
 material: Material;
 background: Color;
 tube: Tube;
 artwork: Artwork;
 assembly: Assembly;
 found: BOOL;
 [assembly, found] ← SVEditUser.GetAssembly[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [background, found] ← SVViewerTools.GetColor[editToolData.artworkSection.rgb];
 IF NOT found THEN RETURN;
 [material, found] ← SVArtwork.RopeToMaterial[materialName];
 IF NOT found THEN {
  MessageWindow.Append[Rope.Concat[materialName, "not known as a material"], TRUE];
  MessageWindow.Blink[];
  RETURN};
 tube ← SVMappings.CreateTube[tubeRadius, tubeHeight];
 IF SVViewerTools.GetBool[editToolData.artworkSection.isColor] THEN
  artwork ← SVArtwork.CreateFileArtwork[material: material, surface: tube, oMap: tubeO, sMap: tubeS, filename: picName, isColor: TRUE, background: background, resolution: resolution]
 ELSE artwork ← SVArtwork.CreateFileArtwork[material: material, surface: tube, oMap: tubeO, sMap: tubeS, filename: picName, isColor: FALSE, background: background, resolution: resolution];
 DisplayList3d.SetArtworkAssembly[assembly, artwork, scene];
 SVArtworkUser.SetArtwork[editToolData.artworkTool, artwork, scene.name, assembly.name];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 };
 
GetBoxOMap: PRIVATE PROC [viewer: Viewer] RETURNS [oMap: OMap] = TRUSTED {
 mapRope: Rope.ROPE ← ViewerTools.GetContents[viewer];
 SELECT TRUE FROM
 Rope.Equal[mapRope, "Orthogonal", TRUE] => RETURN[orthogonal];
 Rope.Equal[mapRope, "Radial", TRUE] => RETURN[radial];
 ENDCASE => ERROR UnknownOMap;
 };
UnknownOMap: ERROR = CODE;

SetBoxArtwork: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 x, y, z: REAL;
 picName: Rope.ROPE ← ViewerTools.GetContents[editToolData.artworkSection.picName];
 materialName: Rope.ROPE ← globalMatArray[editToolData.artworkSection.materialValue];
 resolution: REAL ← SVViewerTools.GetReal[editToolData.artworkSection.resolution, 72.0];
 material: Material;
 background: Color;
 box: Box;
 oMap: OMap ← GetBoxOMap[editToolData.artworkSection.oMapLabel];
 artwork: Artwork;
 assembly: Assembly;
 found: BOOL;
 [assembly, found] ← SVEditUser.GetAssembly[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 [background, found] ← SVViewerTools.GetColor[editToolData.artworkSection.rgb];
 IF NOT found THEN RETURN;
 [material, found] ← SVArtwork.RopeToMaterial[materialName];
 IF NOT found THEN {
  MessageWindow.Append[Rope.Concat[materialName, "not known as a material"], TRUE];
  MessageWindow.Blink[];
  RETURN};
 [x, y, z] ← SVViewerTools.GetThreeReals[editToolData.artworkSection.boxXYZ];
 box ← SVMappings.CreateBox[x,y,z];
 found ← TRUE;
 IF SVViewerTools.GetBool[editToolData.artworkSection.isColor] THEN
  artwork ← SVArtwork.CreateFileArtwork[material: material, surface: box, oMap: oMap, sMap: unfoldedBox, filename: picName, isColor: TRUE, background: background, resolution: resolution
  !SVArtwork.FileNotFound => {found ← FALSE; CONTINUE}]
 ELSE artwork ← SVArtwork.CreateFileArtwork[material: material, surface: box, oMap: oMap, sMap: unfoldedBox, filename: picName, isColor: FALSE, background: background, resolution: resolution
  !SVArtwork.FileNotFound => {found ← FALSE; CONTINUE}];
 IF NOT found THEN RETURN;
 DisplayList3d.SetArtworkAssembly[assembly, artwork, scene];
 SVArtworkUser.SetArtwork[editToolData.artworkTool, artwork, scene.name, assembly.name];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 };
 
GetArtwork: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 -- get the artwork of the currently named assembly. Stuff this information into the artwork section and display the artwork.
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 assembly: Assembly;
 artwork: Artwork;
 materialName: Rope.ROPE;
 found: BOOL;
 [assembly, found] ← SVEditUser.GetAssembly[editToolData.sceneSection.assemblyName, scene];
 IF NOT found THEN RETURN;
 artwork ← assembly.artwork;
 ViewerTools.SetContents[editToolData.artworkSection.picName, artwork.source];
 SVViewerTools.SetColor[editToolData.artworkSection.rgb, artwork.color];
 materialName ← SVArtwork.MaterialToRope[artwork.material];
 ViewerTools.SetContents[editToolData.artworkSection.material, materialName];
 IF artwork.source = NIL THEN {} -- a pure color artwork. Update color and material only.
 ELSE { -- a file artwork. Display isColorFile, resolution, simple surface parameters and mapping types
  SVViewerTools.SetBool[editToolData.artworkSection.isColor, artwork.isColorFile];
  SVViewerTools.SetReal[editToolData.artworkSection.resolution, artwork.resolution];
  WITH artwork.surface SELECT FROM
   tube: SVMappings.Tube => {
    SVViewerTools.SetReal[editToolData.artworkSection.tubeHeight, tube.H];
    SVViewerTools.SetReal[editToolData.artworkSection.tubeRadius, tube.R];
    };
   box: SVMappings.Box => {
    SVViewerTools.SetThreeReals[editToolData.artworkSection.boxXYZ, box.x, 2*box.halfY, box.z];
    };
  ENDCASE => ERROR;
  };
 SVArtworkUser.SetArtwork[editToolData.artworkTool, artwork, scene.name, assembly.name]; 
 }; -- end of GetArtwork
 
RotateArtwork: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
  editToolData: EditToolData ← NARROW[clientData];
  degrees: REAL ← SVViewerTools.GetReal[editToolData.artworkTransformSection.degrees, 45];
  SVArtworkUser.RotateArtwork[editToolData.artworkTool, degrees];
  SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
  };
  
NormalizeArtwork: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = TRUSTED {
  editToolData: EditToolData ← NARROW[clientData];
  SVArtworkUser.NormalizeArtwork[editToolData.artworkTool];
  SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
  };
 
AddLight: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 lightsource: LightSource;
 name: Rope.ROPE;
 position: Point3d;
 success, alreadyPresent: BOOL;
 color: Color;
 name ← ViewerTools.GetContents[editToolData.lightSection.name];
 [position[1], position[2], position[3]] ←
  SVViewerTools.GetThreeReals[editToolData.lightSection.position];
 [color, success] ← SVViewerTools.GetColor[editToolData.lightSection.color];
 IF NOT success THEN RETURN;
 IF mouseButton = red OR mouseButton = yellow THEN {
  lightsource ← DisplayList3d.CreateLightSource[name, position, color];
  alreadyPresent ← FALSE;
  DisplayList3d.AddLightSourceToScene[lightsource, scene
   !DisplayList3d.NameAlreadyPresent => {alreadyPresent ← TRUE; CONTINUE}];
  IF alreadyPresent THEN {
   MessageWindow.Append[Rope.Cat["Lightsource named ", name, " is already present"], TRUE];
   MessageWindow.Blink[];
   RETURN}
  }
 ELSE {
  [lightsource, success] ← DisplayList3d.FindLightFromName[name, scene];
  IF NOT success THEN {
   MessageWindow.Append[Rope.Cat["Lightsource named ", name, " is not present"], TRUE];
   MessageWindow.Blink[];
   RETURN};
  lightsource.position ← position;
  lightsource.color ← color;
  };
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 };
 
DeleteLight: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 name: Rope.ROPE;
 name ← ViewerTools.GetContents[editToolData.lightSection.name];
 DisplayList3d.DeleteLightSourceNamed[name, scene];
 SVViewerUser.SceneNewVersion[editToolData.currentViewerToolData];
 SVEditUser.DrawSceneInternal[parent, clientData, mouseButton, shift, control];
 };
 
EditLight: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton,
  shift, control: BOOL] = TRUSTED {
 editToolData: EditToolData ← NARROW[clientData];
 scene: Scene ← editToolData.sceneSection.currentScene;
 success: BOOL;
 lightName: Rope.ROPE;
 light: LightSource;
 lightName ← ViewerTools.GetContents[editToolData.lightSection.name];
 [light, success] ← DisplayList3d.FindLightFromName[lightName, scene];
 IF NOT success THEN {
  MessageWindow.Append[Rope.Cat["Lightsource: ", lightName, "not found."]];
  MessageWindow.Blink[];
  RETURN;
  };
 -- stuff position and color into the appropriate spaces.
 SVViewerTools.SetThreeReals[editToolData.lightSection.position, light.position[1], light.position[2], light.position[3]];
 SVViewerTools.SetColor[editToolData.lightSection.color, light.color];
 }; -- end of EditLight
 
END.