123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- MODULE W3dMenu; (** AUTHOR "TF"; PURPOSE "3d Menu (case study)"; *)
- IMPORT
- (* Low level *)
- KernelLog, Kernel, MathL, Modules, Files, Commands, Inputs, Strings,
- (* Window Manager *)
- WM := WMWindowManager, Messages := WMMessages, Rect := WMRectangles, Raster, WMGraphics,
- (* 3d framework *)
- Classes := TFClasses, Vectors := W3dVectors, Matrix := W3dMatrix,
- AbstractWorld := W3dAbstractWorld, World := W3dWorld, ObjectGenerator := W3dObjectGenerator,
- (* XML framework *)
- XML, Scanner := XMLScanner, XMLParser, Objects := XMLObjects;
- CONST BoxDistance = 200;
- SphereSel = 1;
- BlurpSel = 2;
- TYPE
- ReloadMsg = OBJECT
- VAR
- name:ARRAY 100 OF CHAR
- END ReloadMsg;
- Symbol = OBJECT
- VAR
- pos : Vectors.TVector3d;
- command : ARRAY 128 OF CHAR;
- obj : AbstractWorld.Object;
- world : AbstractWorld.World;
- tex : AbstractWorld.Texture;
- index : LONGINT;
- PROCEDURE &Init*(world : AbstractWorld.World; pos : Vectors.TVector3d; command : ARRAY OF CHAR);
- BEGIN
- COPY(command, SELF.command); SELF.pos := pos; SELF.world := world
- END Init;
- END Symbol;
- UpdateProc = PROCEDURE {DELEGATE};
- Blurp = OBJECT
- VAR
- timer : Kernel.Timer;
- alive : BOOLEAN;
- obj, o2 : AbstractWorld.Object;
- update : UpdateProc;
- i, direct : LONGINT;
- dead, run, anirun : BOOLEAN;
- pos : Vectors.TVector3d;
- tex : AbstractWorld.Texture;
- world : AbstractWorld.World;
- PROCEDURE &Init*(world: AbstractWorld.World; update: UpdateProc);
- BEGIN
- SELF.update := update; SELF.world := world;
- SELF.obj := world.CreateObject(); SELF.o2 := world.CreateObject(); direct := 1; tex := NIL;
- world.AddObject(obj);
- (* a bit a trick *)
- world.SetAnimated(obj, TRUE); world.SetAnimated(o2, TRUE);
- END Init;
- PROCEDURE Update;
- VAR temp : AbstractWorld.Object;
- BEGIN
- o2.Clear;
- IF run THEN
- ObjectGenerator.TexBox(Matrix.Translation4x4(pos.x, pos.y + i * 2, pos.z), 105 + i*4, 105 + i*4, 105 + i*4, o2, 0FF0000H, tex);
- i := i + direct;
- IF i > 8 THEN BEGIN {EXCLUSIVE} anirun := FALSE END END
- END;
- temp := obj; world.ReplaceObject(obj, o2); obj := o2; o2 := temp;
- update
- END Update;
- PROCEDURE Set(pos : Vectors.TVector3d; tex : AbstractWorld.Texture);
- BEGIN {EXCLUSIVE}
- run := TRUE; anirun := TRUE; i := 0; timer.Wakeup; SELF.pos := pos; SELF.tex := tex; direct := 1
- END Set;
- PROCEDURE Stop;
- BEGIN {EXCLUSIVE}
- IF run THEN run := FALSE; Update END
- END Stop;
- PROCEDURE Kill;
- BEGIN {EXCLUSIVE}
- alive := FALSE; timer.Wakeup
- END Kill;
- PROCEDURE AwaitDead;
- BEGIN {EXCLUSIVE}
- AWAIT(dead)
- END AwaitDead;
- BEGIN {ACTIVE}
- dead := FALSE; alive := TRUE; NEW(timer);
- WHILE alive DO
- timer.Sleep(10);
- BEGIN {EXCLUSIVE} AWAIT(anirun & run OR ~alive) END;
- IF alive THEN Update END
- END;
- BEGIN {EXCLUSIVE} dead := TRUE END
- END Blurp;
- Window = OBJECT ( WM.BufferWindow )
- VAR
- (* Navigation *)
- lookat: Vectors.TVector3d;
- radius, angle, height : LONGREAL;
- mouseKeys, keyflags : SET;
- oldX, oldY : LONGINT;
- (* 3d World *)
- world : World.World;
- mx, my, mz : LONGREAL;
- infoList : Classes.List;
- index : LONGINT;
- aniObj, aniObj2 : AbstractWorld.Object;
- selectionMethod : SET;
- blurp : Blurp;
- selectedSymbol : Symbol;
- PROCEDURE SetSelection(pos : Vectors.TVector3d; l : LONGREAL; visible : BOOLEAN);
- VAR temp : AbstractWorld.Object;
- BEGIN
- aniObj2.Clear;
- IF visible THEN
- IF SphereSel IN selectionMethod THEN
- ObjectGenerator.Sphere(Matrix.Translation4x4(pos.x, pos.y + 80, pos.z), 30, 15, aniObj2, 0FFFF00H)
- END;
- END;
- temp := aniObj; world.ReplaceObject(aniObj, aniObj2); aniObj := aniObj2; aniObj2 := temp;
- RenderAnimation
- END SetSelection;
- PROCEDURE AddSelectionObjects;
- BEGIN
- NEW(blurp, world, RenderAnimation);
- aniObj := world.CreateObject(); world.SetAnimated(aniObj, TRUE);
- aniObj2 := world.CreateObject(); world.SetAnimated(aniObj2, TRUE);
- world.AddObject(aniObj)
- END AddSelectionObjects;
- PROCEDURE ParseLine(line : XML.Element; pos: Vectors.TVector3d);
- VAR cont : Objects.Enumerator; p : ANY; el : XML.Element; s, t : Strings.String;
- x: Symbol;
- BEGIN
- cont := line.GetContents(); cont.Reset();
- WHILE cont.HasMoreElements() DO
- p := cont.GetNext();
- el := p(XML.Element);
- s := el.GetName();
- IF s^ = "ImgBox" THEN
- s := el.GetAttributeValue("cmd"); IF s = NIL THEN NEW(x, world, pos, "hello") ELSE NEW(x, world, pos, s^) END;
- x.index := index; INC(index); infoList.Add(x);
- x.pos := pos; mx := MAX(pos.x, mx);
- pos.x := pos.x + BoxDistance;
- s := el.GetAttributeValue("img");
- IF s = NIL THEN NEW(s, 16) END;
- x.obj := world.CreateObject(); x.obj.SetIndex(x.index); world.AddObject(x.obj);
- x.tex := TextureByName(s^, x.obj);
- ObjectGenerator.TexBox(Matrix.Translation4x4(x.pos.x, x.pos.y, x.pos.z), 100, 100, 100, x.obj, 0FFAA00H,
- x.tex)
- ELSIF s^="SymbolBox" THEN
- s := el.GetAttributeValue("cmd"); IF s = NIL THEN NEW(x, world, pos, "hello") ELSE NEW(x, world, pos, s^) END;
- x.index := index; INC(index); winstance.infoList.Add(x);
- x.pos := pos; mx := MAX(pos.x, mx);
- pos.x := pos.x + BoxDistance;
- s := el.GetAttributeValue("img"); IF s = NIL THEN NEW(s, 16) END;
- t := el.GetAttributeValue("title"); IF t = NIL THEN NEW(t, 16) END;
- x.obj := world.CreateObject(); x.obj.SetIndex(x.index); world.AddObject(x.obj);
- x.tex := GenTexture(s^, t^, x.obj);
- ObjectGenerator.TexBox(Matrix.Translation4x4(x.pos.x, x.pos.y, x.pos.z), 100, 100, 100, x.obj, 0FFAA00H,
- x.tex)
- END
- END
- END ParseLine;
- PROCEDURE ParseLayer(layer : XML.Element; pos : Vectors.TVector3d);
- VAR cont : Objects.Enumerator; p : ANY; el : XML.Element;s : Strings.String;
- BEGIN
- cont := layer.GetContents(); cont.Reset();
- WHILE cont.HasMoreElements() DO
- p := cont.GetNext();
- el := p(XML.Element);
- s := el.GetName(); IF s^ = "Line" THEN
- ParseLine(el, pos); mz := MAX(pos.z, mz);
- pos.z := pos.z + BoxDistance
- END
- END
- END ParseLayer;
- PROCEDURE Load(filename: ARRAY OF CHAR);
- VAR f : Files.File;
- scanner : Scanner.Scanner;
- parser : XMLParser.Parser;
- reader : Files.Reader;
- doc : XML.Document;
- p : ANY;
- root: XML.Element;
- el : XML.Content;
- s : Strings.String;
- cont : Objects.Enumerator;
- pos : Vectors.TVector3d;
- obj : AbstractWorld.Object;
- BEGIN
- world.Clear; infoList.Clear; mx := 0; my := 0; mz := 0;
- IF blurp # NIL THEN blurp.Kill; blurp.AwaitDead END;
- index := 1;
- KernelLog.String(filename); KernelLog.Ln;
- f := Files.Old(filename);
- IF f # NIL THEN
- NEW(reader, f, 0);
- NEW(scanner, reader); NEW(parser, scanner); doc := parser.Parse();
- root := doc.GetRoot();
- cont := root.GetContents(); cont.Reset();
- WHILE cont.HasMoreElements() DO
- p := cont.GetNext();
- IF p IS XML.Element THEN
- el := p(XML.Element);
- s := el(XML.Element).GetName(); IF s^ = "Layer" THEN
- ParseLayer(el(XML.Element), pos); my := MAX(pos.z, my);
- pos.y := pos.y + BoxDistance
- END
- END
- END
- END;
- lookat := Vectors.Vector3d(mx / 2, my / 2, mz / 2);
- obj := world.CreateObject(); obj.SetIndex(index); world.AddObject(obj);
- ObjectGenerator.Box(Matrix.Translation4x4(mx/2, my/2 - 50 - 5, mz/2), mx +100, 10, mz + 100, obj, 0FFFFCCH);
- AddSelectionObjects;
- Render
- END Load;
- PROCEDURE &New*(fileName: ARRAY OF CHAR);
- VAR w, h : LONGINT;
- BEGIN
- IF winstance = NIL THEN winstance := SELF END; (* fld, adapt to new semantics of NEW *)
- manager := WM.GetDefaultManager();
- h := 480; w := 640;
- Init(w, h, FALSE);
- (* Init navigation parameters *)
- radius := 800; angle := -MathL.pi / 2; height := 200;
- (* Setup the 3d World *)
- NEW(world, w, h, 000000088H); world.quality := 1;
- NEW(infoList); Load(fileName);
- selectionMethod := { BlurpSel };
- WM.DefaultAddWindow(SELF);
- SetTitle(Strings.NewString("Menu 3d"));
- Render
- END New;
- PROCEDURE Close*;
- BEGIN
- IF blurp # NIL THEN blurp.Kill; blurp.AwaitDead END;
- Close^;
- winstance := NIL
- END Close;
- (* BEGIN Navigation and Rendering *)
- PROCEDURE RenderAnimation;
- BEGIN
- world.Render(img, TRUE);
- Invalidate(Rect.MakeRect(0,0,img.width, img.height))
- END RenderAnimation;
- PROCEDURE Render;
- VAR pos, dir, up : Vectors.TVector3d;
- BEGIN {EXCLUSIVE}
- pos := Vectors.VAdd3(lookat, Vectors.Vector3d(MathL.cos(angle) * radius, 0, MathL.sin(angle) * radius)); pos.y := height;
- (* lookat := Vectors.Vector3d(lookat.x, lookat.y, lookat.z); *)
- dir := Vectors.VNormed3(Vectors.VSub3(lookat, pos));
- up := Vectors.VNeg3(Vectors.VNormed3(Vectors.Cross(Vectors.Cross(Vectors.Vector3d(0, 1, 0), dir), dir)));
- world.SetCamera(pos, dir, up); world.Render(img, FALSE);
- Invalidate(Rect.MakeRect(0, 0, img.width, img.height))
- END Render;
- PROCEDURE PointerDown*(x, y : LONGINT; keys :SET);
- BEGIN
- mouseKeys := (keys * {0, 1, 2});
- oldX := x; oldY := y
- END PointerDown;
- PROCEDURE PointerMove*(x, y: LONGINT; keys: SET);
- VAR idx : LONGINT;
- info : Symbol; dummy : ANY;
- BEGIN
- IF mouseKeys = {} THEN
- idx := world.GetOwnerIndex(x, y) - 1;
- IF (idx >= 0) THEN
- infoList.Lock;
- info := NIL;
- IF idx < infoList.GetCount() THEN dummy := infoList.GetItem(idx); info := dummy(Symbol) END;
- infoList.Unlock;
- IF selectedSymbol # info THEN
- IF info # NIL THEN
- SetSelection(info.pos, 0, TRUE);
- IF BlurpSel IN selectionMethod THEN blurp.Set(info.pos, info.tex)
- ELSE blurp.Stop;
- END
- ELSE blurp.Stop; SetSelection(Vectors.Vector3d(0,0,0), 0, FALSE)
- END
- END;
- selectedSymbol := info
- ELSE
- IF selectedSymbol # NIL THEN
- selectedSymbol := NIL; blurp.Stop;
- SetSelection(Vectors.Vector3d(0,0,0), 0, FALSE)
- END
- END;
- RETURN
- END;
- IF mouseKeys * {0} # {} THEN
- IF mouseKeys * {2} # {} THEN
- radius := radius - (y - oldY) * 10; IF radius < 10 THEN radius := 10 END;
- ELSE
- height := height + (y - oldY)
- END;
- angle := angle - (x - oldX) / img.width * 3.141;
- Render
- END;
- oldX := x; oldY := y
- END PointerMove;
- PROCEDURE PointerUp*(x, y: LONGINT; keys: SET);
- BEGIN
- IF mouseKeys = {0} THEN
- IF selectedSymbol # NIL THEN
- IF keyflags * Inputs.Shift # {} THEN
- lookat := selectedSymbol.pos; Render
- (* ELSE
- Commands.Call(selectedSymbol.command, {}, res, msg);
- IF res # 0 THEN
- KernelLog.Enter; KernelLog.String(msg); KernelLog.Exit
- END *)
- END
- END
- END;
- mouseKeys := (keys * {0, 1, 2});
- END PointerUp;
- (* PROCEDURE KeyPressed(ch : CHAR; flags : SET; keysym : LONGINT);
- BEGIN
- keyflags := flags;
- IF ch = "s" THEN
- IF SphereSel IN selectionMethod THEN selectionMethod := selectionMethod - {SphereSel}
- ELSE selectionMethod := selectionMethod + {SphereSel}
- END
- ELSIF ch = "b" THEN
- IF BlurpSel IN selectionMethod THEN selectionMethod := selectionMethod - {BlurpSel}
- ELSE selectionMethod := selectionMethod + {BlurpSel}
- END
- END
- END KeyPressed;
- *)
- PROCEDURE Handle*(VAR m : Messages.Message);
- BEGIN
- IF m.msgType = Messages.MsgExt THEN
- IF m.ext IS ReloadMsg THEN Load(m.ext(ReloadMsg).name) END
- ELSE
- Handle^(m)
- END
- END Handle;
- (* END Navigation and Rendering *)
- END Window;
- TextureInfo = OBJECT
- VAR
- img : Raster.Image;
- name : ARRAY 128 OF CHAR
- END TextureInfo;
- VAR
- winstance : Window;
- textures: Classes.List;
- PROCEDURE GenTexture(icon, title: ARRAY OF CHAR; obj : AbstractWorld.Object): AbstractWorld.Texture;
- VAR res : BOOLEAN;
- mode: Raster.Mode;
- pix : Raster.Pixel;
- tex : AbstractWorld.Texture;
- img : Raster.Image;
- timg: Raster.Image;
- tw, th, dx, dy : LONGINT;
- BEGIN
- timg := WMGraphics.LoadImage(icon, TRUE);
- Raster.InitMode(mode, Raster.srcCopy);
- NEW(img); Raster.Create(img, 64, 64, Raster.BGR565);
- Raster.SetRGB(pix, 0C0H, 0C0H, 0C0H); Raster.Fill(img, 1, 1, 62, 62, pix, mode);
- Raster.SetRGB(pix, 0H, 0H, 0H);
- Raster.Fill(img, 0, 11, 63, 12, pix, mode);
- Raster.Fill(img, 7, 12, 56, 62, pix, mode);
- Raster.SetRGB(pix, 0FFH, 0FFH, 0FFH);
- Raster.Fill(img, 9, 14, 54, 60, pix, mode);
- timg := WMGraphics.LoadImage(icon, TRUE); tex := NIL;
- IF res THEN
- tw := MIN(timg.width, 46); th := MIN(timg.height, 46);
- dx := (46 - tw) DIV 2 + 9;
- dy := (46 - th) DIV 2 + 14;
- Raster.Copy(timg, img, 0, 0, tw, th, dx, dy, mode)
- END;
- tex := obj.AddTexture(img);
- RETURN tex
- END GenTexture;
- PROCEDURE TextureByName(name: ARRAY OF CHAR; obj : AbstractWorld.Object): AbstractWorld.Texture;
- VAR i : LONGINT;
- dummy : ANY;
- ti : TextureInfo; mode: Raster.Mode;
- timg: Raster.Image;
- BEGIN
- textures.Lock;
- FOR i := 0 TO textures.GetCount()-1 DO
- dummy := textures.GetItem(i); ti := dummy(TextureInfo);
- IF ti.name = name THEN
- IF ti.img = NIL THEN
- textures.Unlock;
- RETURN NIL
- ELSE textures.Unlock;
- RETURN obj.AddTexture(ti.img)
- END
- END
- END;
- textures.Unlock;
- NEW(ti); COPY(name, ti.name);
- timg := WMGraphics.LoadImage(name, TRUE);
- IF timg # NIL THEN
- NEW(ti.img); Raster.Create(ti.img, timg.width, timg.height, Raster.BGR565);
- Raster.InitMode(mode, Raster.srcCopy);
- Raster.Copy(timg, ti.img, 0, 0, timg.width, timg.height, 0, 0, mode)
- END;
- IF ti.img # NIL THEN RETURN obj.AddTexture(ti.img) ELSE RETURN NIL END
- END TextureByName;
- (* PROCEDURE MatchI(VAR buf: ARRAY OF CHAR; with: ARRAY OF CHAR): BOOLEAN;
- VAR i: LONGINT;
- BEGIN
- i := 0; WHILE (with[i] # 0X) & (CAP(buf[i]) = CAP(with[i])) DO INC(i) END;
- RETURN with[i] = 0X
- END MatchI;
- *)
- PROCEDURE Open*(context : Commands.Context);
- VAR name : ARRAY 100 OF CHAR;
- BEGIN
- IF context.arg.GetString(name) THEN
- IF winstance = NIL THEN NEW(winstance, name) END;
- END;
- END Open;
- PROCEDURE Cleanup;
- BEGIN
- IF winstance # NIL THEN winstance.Close END
- END Cleanup;
- BEGIN
- NEW(textures);
- Modules.InstallTermHandler(Cleanup)
- END W3dMenu.
- W3dMenu.Open W3dFun.XML ~
- W3dMenu.Open W3dMenu.XML ~
- W3dMenu.Open W3dNetTool.XML ~
- W3dMenu.Open W3dPersonal.XML ~
- System.Free W3dMenu ~
- Compiler.Compile \s W3dVectors.Mod W3dMatrix.Mod W3dGeometry.Mod W3dAbstractWorld.Mod W3dObjectGenerator.Mod
- W3dRasterizer.Mod W3dWorld.Mod W3dExplorer.Mod W3dClusterWatch.Mod W3dMenu.Mod~
- oberon.bmp objecttracker.bmp networktracker.bmp launcher.bmp tetris.bmp iconvnc.bmp iconhome.bmp iconreload.bmp
- iconbones.bmp iconbunny.bmp iconfrog.bmp iconfire.bmp iconfun.bmp iconmemory.bmp iconnettools.bmp iconkeycode.bmp
- iconxml.bmp
- PC.Compile \s TFVectors.Mod TFMatrix.Mod TFGeometry.Mod TFAbstractWorld.Mod TFObjectGenerator.Mod
- Float.TFRasterizer3d.Mod TFWorld3d.Mod TFExplorer.Mod Menu3d.Mod ~
- ~
- System.Free W3dMenu W3dWorld W3dRasterizer W3dObjectGenerator W3dAbstractWorld W3dGeometry W3dMatrix W3dVectors~
- EditTools.OpenAscii W3dFun.XML ~
- EditTools.OpenAscii W3dMenu.XML ~
- EditTools.OpenAscii W3dNetTools.XML ~
- EditTools.OpenAscii W3dPersonal.XML ~
|