-- File: Fileout3dImpl.mesa
-- Last edited by Bier on December 19, 1982 5:55 pm
-- Author: Eric Bier on July 6, 1983 4:29 pm
-- Contents: Facilities for creating text files and writing out a human-readable version of a 3d object database

DIRECTORY
 CoordSys,
 DisplayList3d,
 Fileout3d,
IO,
 Matrix3d,
 Rope,
 Shading,
 SVArtwork,
 SweepGeometry,
 TFO3d;

Fileout3dImpl: PROGRAM
IMPORTS CoordSys, IO, DisplayList3d, TFO3d
EXPORTS Fileout3d =

BEGIN

Artwork: TYPE = SVArtwork.Artwork;

Matrix4by4: TYPE = Matrix3d.Matrix4by4;
Point3d: TYPE = Matrix3d.Point3d;
AssemblyList: TYPE = REF AssemblyListObj;
AssemblyListObj: TYPE = DisplayList3d.AssemblyListObj;
Assembly: TYPE = REF AssemblyObj;
AssemblyObj: TYPE = DisplayList3d.AssemblyObj;
MasterObject: TYPE = REF MasterObjectRec;
MasterObjectRec: TYPE = DisplayList3d.MasterObjectRec;
MasterObjectList: TYPE = DisplayList3d.MasterObjectList;
Scene: TYPE = REF SceneObj;
SceneObj: TYPE = DisplayList3d.SceneObj;
LightSource: TYPE = REF LightSourceObj;
LightSourceObj: TYPE = Shading.LightSourceObj;
LightSourceList: TYPE = LIST OF LightSource;

LinearMesh: TYPE = REF LinearMeshRecord;
LinearMeshRecord: TYPE = SweepGeometry.LinearMeshRecord;
RevoluteMesh: TYPE = REF RevoluteMeshRecord;
RevoluteMeshRecord: TYPE = SweepGeometry.RevoluteMeshRecord;

LinearMeshArray: TYPE = SweepGeometry.LinearMeshArray;
RevoluteMeshArray: TYPE = SweepGeometry.RevoluteMeshArray;

CoordSystem: TYPE = REF CoordSysObj;
CoordSysObj: TYPE = CoordSys.CoordSysObj;
CoordSysList: TYPE = CoordSys.CoordSysList;

FileoutScene: PUBLIC PROC [scene: Scene, f: IO.STREAM, fileName: Rope.ROPE] = {
 f.PutF["File: %g\n",[rope[fileName]]];
 f.PutF["3D file for scene: %g\n",[rope[fileName]]];
 f.PutF["Produced by %g\n\n", [rope[DisplayList3d.versionRope]]];
 f.PutF["Background color: "];
 TFO3d.FileoutColor[f, scene.backgroundColor];
 f.PutChar[IO.CR];
 f.PutChar[IO.CR];
 scene.coordSystems ← CoordSys.SortCoordSysListByBreadth[scene.coordSystems];
 FileoutCoordSystems[f,scene.coordSystems];
 FileoutLightSources[f,scene.lightSources];
 FileoutObjects[f,scene.masterObjects];
 FileoutAssembly[f, scene.assembly, scene.masterObjects];
 f.PutF["END"];
 f.Close[];
 scene.dirty ← FALSE;
 };

CountCoordSystems: PROC [csl: CoordSysList] RETURNS [count: NAT] = {
 count ← 0;
FOR list: CoordSysList ← csl, list.rest UNTIL list = NIL DO
  count ← count + 1;
ENDLOOP;
 };
  
FileoutCoordSystems: PROC [f: IO.STREAM, csl: CoordSysList] = {
 count: NAT ← CountCoordSystems[csl];
 thisCS: CoordSystem;
 f.PutF["CoordSystems [%g]:\n",[integer[count]]];
FOR thisCSL: CoordSysList ← csl, thisCSL.rest UNTIL thisCSL = NIL DO
  thisCS ← thisCSL.first;
  f.PutF["CoordSys: %g mat: ",[rope[thisCS.name]]];
  TFO3d.FileoutMatrix[f,thisCS.mat];
  f.PutF[" withRespectTo: "];
  IF thisCS.withRespectTo = NIL THEN f.PutF["NIL"]
  ELSE f.PutRope[thisCS.withRespectTo.name];
  f.PutChar[IO.CR];
ENDLOOP;
 f.PutChar[IO.CR];
 };
  
CountLightSources: PROC [lsl: LightSourceList] RETURNS [count: NAT] = {
 count ← 0;
FOR list: LightSourceList ← lsl, list.rest UNTIL list = NIL DO
  count ← count + 1;
ENDLOOP;
 };

FileoutLightSources: PUBLIC PROC [f: IO.STREAM, lsl: LightSourceList] = {
 count: NAT ← CountLightSources[lsl];
 thisLS: LightSource;
 f.PutF["LightSources [%g]:\n",[integer[count]]];
FOR thisLSL: LightSourceList ← lsl, thisLSL.rest UNTIL thisLSL = NIL DO
  thisLS ← thisLSL.first;
  FileoutLightSource[f, thisLS];
  f.PutChar[IO.CR];
ENDLOOP;
 f.PutChar[IO.CR];
 };

FileoutLightSource: PROC [f: IO.STREAM, lightSource: LightSource] = {
 f.PutF["LightSource: %g position: ",[rope[lightSource.name]]];
 TFO3d.FileoutPoint3d[f,lightSource.position];
 f.PutF[" color: "];
 TFO3d.FileoutColor[f, lightSource.color];
 };

CountAssemblies: PROC [asl: AssemblyList] RETURNS [count: NAT] = {
 count ← 0;
FOR list: LIST OF Assembly ← asl.list, list.rest UNTIL list = NIL DO
  count ← count + 1;
ENDLOOP;
 };

FileoutArtwork: PRIVATE PROC [f: IO.STREAM, artwork: Artwork] = {
 f.PutF["material: "];
 TFO3d.FileoutMaterial[f, artwork.material];
 f.PutF[" surface: "];
 TFO3d.FileoutSurface[f, artwork.surface];
 f.PutChar[IO.CR];
IF artwork.source # NIL THEN{
  f.PutF["SMap: "];
  TFO3d.FileoutSMap[f, artwork.sMap];
  f.PutF[" OMap: "];
  TFO3d.FileoutOMap[f, artwork.oMap];
  f.PutChar[IO.SP];
  f.PutF["source: %g ", [rope[artwork.source]]];
  IF artwork.isColorFile THEN f.PutF["colorFile"] ELSE f.PutF["bwFile"];
  f.PutF[" resolution: %g\n", [real[artwork.resolution]]];
  f.PutF["mat: "];
  TFO3d.FileoutMatrix3by3[f, artwork.artWRTPad.mat];
  };
 f.PutF[" color: "];
 TFO3d.FileoutColor[f, artwork.color];
 };

FileoutAssembly: PROC [f: IO.STREAM, assem: Assembly, mol: MasterObjectList] = {
 pointSetOp: Rope.ROPE;
  f.PutF["Assembly: %g, coordSys: %g, scalars: ",
    [rope[assem.name]],[rope[assem.coordSys.name]]];
  TFO3d.FileoutPoint3d[f, assem.scalars];
  f.PutChar[IO.CR];
  f.PutChar[IO.TAB];
  f.PutF["artwork: "];
  FileoutArtwork[f, assem.artwork];
  f.PutChar[IO.CR];
  -- file out subassembly or master object information
  f.PutChar[IO.TAB];
  WITH assem.object SELECT FROM
  alist: AssemblyList => {SELECT alist.pointSetOp FROM
         union => pointSetOp ← "union";
         intersection => pointSetOp ← "intersection";
         difference => pointSetOp ← "difference";
         ENDCASE => ERROR;
         f.PutF["subassemblies [point set op: %g]\n", [rope[pointSetOp]]];
         FileoutSubassemblyNames[f,alist];
         f.PutChar[IO.CR];
         FileoutAssemblies[f,alist,mol];};
  ENDCASE => {f.PutF["object: "];
       FileoutObjectName[f,assem.object]};
  f.PutChar[IO.CR];
 }; -- end of FileoutAssembly

FileoutAssemblies: PROC [f: IO.STREAM, as: AssemblyList, mol: MasterObjectList] = {
 count: NAT ← CountAssemblies[as];
 f.PutF["Subassemblies [%g]:\n",[integer[count]]];
FOR aso: LIST OF Assembly ← as.list, aso.rest UNTIL aso = NIL DO
  FileoutAssembly[f, aso.first, mol];
ENDLOOP; -- next assembly
 f.PutChar[IO.CR];
 }; -- end of FileoutAssemblies

FileoutObjectName: PROC [f: IO.STREAM, object: REF ANY] = {
 mo: MasterObject ← NARROW[object];
 f.PutRope[mo.name];
 };

FileoutSubassemblyNames: PROC [f: IO.STREAM, asl: AssemblyList] = {
 count: NAT ← CountAssemblies[asl];
 thisA: Assembly;
 f.PutF[" [%g]: (", [integer[count]]];
 IF count = 0 THEN {f.PutF[")\n"]; RETURN};
 thisA ← asl.list.first;
 f.PutRope[thisA.name];
FOR list: LIST OF Assembly ← asl.list.rest, list.rest UNTIL list = NIL DO
  thisA ← list.first;
  f.PutF[", %g",[rope[thisA.name]]];
ENDLOOP;
 f.PutF[")\n"];
 };

CountObjects: PROC [ol: MasterObjectList] RETURNS [count: NAT] = {
 count ← 0;
FOR list: MasterObjectList ← ol, list.rest UNTIL list = NIL DO
  count ← count + 1;
ENDLOOP;
 };

FileoutObjects: PROC [f: IO.STREAM, ol: MasterObjectList] = {
 mo: MasterObject;
 count: NAT ← CountObjects[ol];
 f.PutF["Objects [%g]:\n",[integer[count]]];
FOR mol: MasterObjectList ← ol, mol.rest UNTIL mol = NIL DO
  mo ← mol.first;
  f.PutF["Master Object: %g class: %g\n", [rope[mo.name]], [rope[mo.class.name]]];
  mo.class.fileout[f, mo];
ENDLOOP;
 f.PutChar[IO.CR];
 };
  
END.