MODULE W3dMenu;
IMPORT
KernelLog, Kernel, MathL, Modules, Files, Commands, Inputs, Strings,
WM := WMWindowManager, Messages := WMMessages, Rect := WMRectangles, Raster, WMGraphics,
Classes := TFClasses, Vectors := W3dVectors, Matrix := W3dMatrix,
AbstractWorld := W3dAbstractWorld, World := W3dWorld, ObjectGenerator := W3dObjectGenerator,
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);
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
lookat: Vectors.TVector3d;
radius, angle, height : LONGREAL;
mouseKeys, keyflags : SET;
oldX, oldY : LONGINT;
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;
manager := WM.GetDefaultManager();
h := 480; w := 640;
Init(w, h, FALSE);
radius := 800; angle := -MathL.pi / 2; height := 200;
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;
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;
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
END
END
END;
mouseKeys := (keys * {0, 1, 2});
END PointerUp;
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 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 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;
PROCEDURE Min(a, b: LONGINT):LONGINT;
BEGIN IF a < b THEN RETURN a ELSE RETURN b END
END Min;
PROCEDURE Max(a, b: LONGREAL):LONGREAL;
BEGIN IF a > b THEN RETURN a ELSE RETURN b END
END Max;
BEGIN
NEW(textures);
Modules.InstallTermHandler(Cleanup)
END W3dMenu.
W3dMenu.Open W3dFun.XML ~
W3dMenu.Open W3dMenu.XML ~
W3dMenu.Open W3dNetTool.XML ~
W3dMenu.Open W3dPersonal.XML ~
SystemTools.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 ~
~
SystemTools.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 ~