W3dMenu.Mod 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. MODULE W3dMenu; (** AUTHOR "TF"; PURPOSE "3d Menu (case study)"; *)
  2. IMPORT
  3. (* Low level *)
  4. KernelLog, Kernel, MathL, Modules, Files, Commands, Inputs, Strings,
  5. (* Window Manager *)
  6. WM := WMWindowManager, Messages := WMMessages, Rect := WMRectangles, Raster, WMGraphics,
  7. (* 3d framework *)
  8. Classes := TFClasses, Vectors := W3dVectors, Matrix := W3dMatrix,
  9. AbstractWorld := W3dAbstractWorld, World := W3dWorld, ObjectGenerator := W3dObjectGenerator,
  10. (* XML framework *)
  11. XML, Scanner := XMLScanner, XMLParser, Objects := XMLObjects;
  12. CONST BoxDistance = 200;
  13. SphereSel = 1;
  14. BlurpSel = 2;
  15. TYPE
  16. ReloadMsg = OBJECT
  17. VAR
  18. name:ARRAY 100 OF CHAR
  19. END ReloadMsg;
  20. Symbol = OBJECT
  21. VAR
  22. pos : Vectors.TVector3d;
  23. command : ARRAY 128 OF CHAR;
  24. obj : AbstractWorld.Object;
  25. world : AbstractWorld.World;
  26. tex : AbstractWorld.Texture;
  27. index : LONGINT;
  28. PROCEDURE &Init*(world : AbstractWorld.World; pos : Vectors.TVector3d; command : ARRAY OF CHAR);
  29. BEGIN
  30. COPY(command, SELF.command); SELF.pos := pos; SELF.world := world
  31. END Init;
  32. END Symbol;
  33. UpdateProc = PROCEDURE {DELEGATE};
  34. Blurp = OBJECT
  35. VAR
  36. timer : Kernel.Timer;
  37. alive : BOOLEAN;
  38. obj, o2 : AbstractWorld.Object;
  39. update : UpdateProc;
  40. i, direct : LONGINT;
  41. dead, run, anirun : BOOLEAN;
  42. pos : Vectors.TVector3d;
  43. tex : AbstractWorld.Texture;
  44. world : AbstractWorld.World;
  45. PROCEDURE &Init*(world: AbstractWorld.World; update: UpdateProc);
  46. BEGIN
  47. SELF.update := update; SELF.world := world;
  48. SELF.obj := world.CreateObject(); SELF.o2 := world.CreateObject(); direct := 1; tex := NIL;
  49. world.AddObject(obj);
  50. (* a bit a trick *)
  51. world.SetAnimated(obj, TRUE); world.SetAnimated(o2, TRUE);
  52. END Init;
  53. PROCEDURE Update;
  54. VAR temp : AbstractWorld.Object;
  55. BEGIN
  56. o2.Clear;
  57. IF run THEN
  58. ObjectGenerator.TexBox(Matrix.Translation4x4(pos.x, pos.y + i * 2, pos.z), 105 + i*4, 105 + i*4, 105 + i*4, o2, 0FF0000H, tex);
  59. i := i + direct;
  60. IF i > 8 THEN BEGIN {EXCLUSIVE} anirun := FALSE END END
  61. END;
  62. temp := obj; world.ReplaceObject(obj, o2); obj := o2; o2 := temp;
  63. update
  64. END Update;
  65. PROCEDURE Set(pos : Vectors.TVector3d; tex : AbstractWorld.Texture);
  66. BEGIN {EXCLUSIVE}
  67. run := TRUE; anirun := TRUE; i := 0; timer.Wakeup; SELF.pos := pos; SELF.tex := tex; direct := 1
  68. END Set;
  69. PROCEDURE Stop;
  70. BEGIN {EXCLUSIVE}
  71. IF run THEN run := FALSE; Update END
  72. END Stop;
  73. PROCEDURE Kill;
  74. BEGIN {EXCLUSIVE}
  75. alive := FALSE; timer.Wakeup
  76. END Kill;
  77. PROCEDURE AwaitDead;
  78. BEGIN {EXCLUSIVE}
  79. AWAIT(dead)
  80. END AwaitDead;
  81. BEGIN {ACTIVE}
  82. dead := FALSE; alive := TRUE; NEW(timer);
  83. WHILE alive DO
  84. timer.Sleep(10);
  85. BEGIN {EXCLUSIVE} AWAIT(anirun & run OR ~alive) END;
  86. IF alive THEN Update END
  87. END;
  88. BEGIN {EXCLUSIVE} dead := TRUE END
  89. END Blurp;
  90. Window = OBJECT ( WM.BufferWindow )
  91. VAR
  92. (* Navigation *)
  93. lookat: Vectors.TVector3d;
  94. radius, angle, height : LONGREAL;
  95. mouseKeys, keyflags : SET;
  96. oldX, oldY : LONGINT;
  97. (* 3d World *)
  98. world : World.World;
  99. mx, my, mz : LONGREAL;
  100. infoList : Classes.List;
  101. index : LONGINT;
  102. aniObj, aniObj2 : AbstractWorld.Object;
  103. selectionMethod : SET;
  104. blurp : Blurp;
  105. selectedSymbol : Symbol;
  106. PROCEDURE SetSelection(pos : Vectors.TVector3d; l : LONGREAL; visible : BOOLEAN);
  107. VAR temp : AbstractWorld.Object;
  108. BEGIN
  109. aniObj2.Clear;
  110. IF visible THEN
  111. IF SphereSel IN selectionMethod THEN
  112. ObjectGenerator.Sphere(Matrix.Translation4x4(pos.x, pos.y + 80, pos.z), 30, 15, aniObj2, 0FFFF00H)
  113. END;
  114. END;
  115. temp := aniObj; world.ReplaceObject(aniObj, aniObj2); aniObj := aniObj2; aniObj2 := temp;
  116. RenderAnimation
  117. END SetSelection;
  118. PROCEDURE AddSelectionObjects;
  119. BEGIN
  120. NEW(blurp, world, RenderAnimation);
  121. aniObj := world.CreateObject(); world.SetAnimated(aniObj, TRUE);
  122. aniObj2 := world.CreateObject(); world.SetAnimated(aniObj2, TRUE);
  123. world.AddObject(aniObj)
  124. END AddSelectionObjects;
  125. PROCEDURE ParseLine(line : XML.Element; pos: Vectors.TVector3d);
  126. VAR cont : Objects.Enumerator; p : ANY; el : XML.Element; s, t : Strings.String;
  127. x: Symbol;
  128. BEGIN
  129. cont := line.GetContents(); cont.Reset();
  130. WHILE cont.HasMoreElements() DO
  131. p := cont.GetNext();
  132. el := p(XML.Element);
  133. s := el.GetName();
  134. IF s^ = "ImgBox" THEN
  135. s := el.GetAttributeValue("cmd"); IF s = NIL THEN NEW(x, world, pos, "hello") ELSE NEW(x, world, pos, s^) END;
  136. x.index := index; INC(index); infoList.Add(x);
  137. x.pos := pos; mx := MAX(pos.x, mx);
  138. pos.x := pos.x + BoxDistance;
  139. s := el.GetAttributeValue("img");
  140. IF s = NIL THEN NEW(s, 16) END;
  141. x.obj := world.CreateObject(); x.obj.SetIndex(x.index); world.AddObject(x.obj);
  142. x.tex := TextureByName(s^, x.obj);
  143. ObjectGenerator.TexBox(Matrix.Translation4x4(x.pos.x, x.pos.y, x.pos.z), 100, 100, 100, x.obj, 0FFAA00H,
  144. x.tex)
  145. ELSIF s^="SymbolBox" THEN
  146. s := el.GetAttributeValue("cmd"); IF s = NIL THEN NEW(x, world, pos, "hello") ELSE NEW(x, world, pos, s^) END;
  147. x.index := index; INC(index); winstance.infoList.Add(x);
  148. x.pos := pos; mx := MAX(pos.x, mx);
  149. pos.x := pos.x + BoxDistance;
  150. s := el.GetAttributeValue("img"); IF s = NIL THEN NEW(s, 16) END;
  151. t := el.GetAttributeValue("title"); IF t = NIL THEN NEW(t, 16) END;
  152. x.obj := world.CreateObject(); x.obj.SetIndex(x.index); world.AddObject(x.obj);
  153. x.tex := GenTexture(s^, t^, x.obj);
  154. ObjectGenerator.TexBox(Matrix.Translation4x4(x.pos.x, x.pos.y, x.pos.z), 100, 100, 100, x.obj, 0FFAA00H,
  155. x.tex)
  156. END
  157. END
  158. END ParseLine;
  159. PROCEDURE ParseLayer(layer : XML.Element; pos : Vectors.TVector3d);
  160. VAR cont : Objects.Enumerator; p : ANY; el : XML.Element;s : Strings.String;
  161. BEGIN
  162. cont := layer.GetContents(); cont.Reset();
  163. WHILE cont.HasMoreElements() DO
  164. p := cont.GetNext();
  165. el := p(XML.Element);
  166. s := el.GetName(); IF s^ = "Line" THEN
  167. ParseLine(el, pos); mz := MAX(pos.z, mz);
  168. pos.z := pos.z + BoxDistance
  169. END
  170. END
  171. END ParseLayer;
  172. PROCEDURE Load(filename: ARRAY OF CHAR);
  173. VAR f : Files.File;
  174. scanner : Scanner.Scanner;
  175. parser : XMLParser.Parser;
  176. reader : Files.Reader;
  177. doc : XML.Document;
  178. p : ANY;
  179. root: XML.Element;
  180. el : XML.Content;
  181. s : Strings.String;
  182. cont : Objects.Enumerator;
  183. pos : Vectors.TVector3d;
  184. obj : AbstractWorld.Object;
  185. BEGIN
  186. world.Clear; infoList.Clear; mx := 0; my := 0; mz := 0;
  187. IF blurp # NIL THEN blurp.Kill; blurp.AwaitDead END;
  188. index := 1;
  189. KernelLog.String(filename); KernelLog.Ln;
  190. f := Files.Old(filename);
  191. IF f # NIL THEN
  192. NEW(reader, f, 0);
  193. NEW(scanner, reader); NEW(parser, scanner); doc := parser.Parse();
  194. root := doc.GetRoot();
  195. cont := root.GetContents(); cont.Reset();
  196. WHILE cont.HasMoreElements() DO
  197. p := cont.GetNext();
  198. IF p IS XML.Element THEN
  199. el := p(XML.Element);
  200. s := el(XML.Element).GetName(); IF s^ = "Layer" THEN
  201. ParseLayer(el(XML.Element), pos); my := MAX(pos.z, my);
  202. pos.y := pos.y + BoxDistance
  203. END
  204. END
  205. END
  206. END;
  207. lookat := Vectors.Vector3d(mx / 2, my / 2, mz / 2);
  208. obj := world.CreateObject(); obj.SetIndex(index); world.AddObject(obj);
  209. ObjectGenerator.Box(Matrix.Translation4x4(mx/2, my/2 - 50 - 5, mz/2), mx +100, 10, mz + 100, obj, 0FFFFCCH);
  210. AddSelectionObjects;
  211. Render
  212. END Load;
  213. PROCEDURE &New*(fileName: ARRAY OF CHAR);
  214. VAR w, h : LONGINT;
  215. BEGIN
  216. IF winstance = NIL THEN winstance := SELF END; (* fld, adapt to new semantics of NEW *)
  217. manager := WM.GetDefaultManager();
  218. h := 480; w := 640;
  219. Init(w, h, FALSE);
  220. (* Init navigation parameters *)
  221. radius := 800; angle := -MathL.pi / 2; height := 200;
  222. (* Setup the 3d World *)
  223. NEW(world, w, h, 000000088H); world.quality := 1;
  224. NEW(infoList); Load(fileName);
  225. selectionMethod := { BlurpSel };
  226. WM.DefaultAddWindow(SELF);
  227. SetTitle(Strings.NewString("Menu 3d"));
  228. Render
  229. END New;
  230. PROCEDURE Close*;
  231. BEGIN
  232. IF blurp # NIL THEN blurp.Kill; blurp.AwaitDead END;
  233. Close^;
  234. winstance := NIL
  235. END Close;
  236. (* BEGIN Navigation and Rendering *)
  237. PROCEDURE RenderAnimation;
  238. BEGIN
  239. world.Render(img, TRUE);
  240. Invalidate(Rect.MakeRect(0,0,img.width, img.height))
  241. END RenderAnimation;
  242. PROCEDURE Render;
  243. VAR pos, dir, up : Vectors.TVector3d;
  244. BEGIN {EXCLUSIVE}
  245. pos := Vectors.VAdd3(lookat, Vectors.Vector3d(MathL.cos(angle) * radius, 0, MathL.sin(angle) * radius)); pos.y := height;
  246. (* lookat := Vectors.Vector3d(lookat.x, lookat.y, lookat.z); *)
  247. dir := Vectors.VNormed3(Vectors.VSub3(lookat, pos));
  248. up := Vectors.VNeg3(Vectors.VNormed3(Vectors.Cross(Vectors.Cross(Vectors.Vector3d(0, 1, 0), dir), dir)));
  249. world.SetCamera(pos, dir, up); world.Render(img, FALSE);
  250. Invalidate(Rect.MakeRect(0, 0, img.width, img.height))
  251. END Render;
  252. PROCEDURE PointerDown*(x, y : LONGINT; keys :SET);
  253. BEGIN
  254. mouseKeys := (keys * {0, 1, 2});
  255. oldX := x; oldY := y
  256. END PointerDown;
  257. PROCEDURE PointerMove*(x, y: LONGINT; keys: SET);
  258. VAR idx : LONGINT;
  259. info : Symbol; dummy : ANY;
  260. BEGIN
  261. IF mouseKeys = {} THEN
  262. idx := world.GetOwnerIndex(x, y) - 1;
  263. IF (idx >= 0) THEN
  264. infoList.Lock;
  265. info := NIL;
  266. IF idx < infoList.GetCount() THEN dummy := infoList.GetItem(idx); info := dummy(Symbol) END;
  267. infoList.Unlock;
  268. IF selectedSymbol # info THEN
  269. IF info # NIL THEN
  270. SetSelection(info.pos, 0, TRUE);
  271. IF BlurpSel IN selectionMethod THEN blurp.Set(info.pos, info.tex)
  272. ELSE blurp.Stop;
  273. END
  274. ELSE blurp.Stop; SetSelection(Vectors.Vector3d(0,0,0), 0, FALSE)
  275. END
  276. END;
  277. selectedSymbol := info
  278. ELSE
  279. IF selectedSymbol # NIL THEN
  280. selectedSymbol := NIL; blurp.Stop;
  281. SetSelection(Vectors.Vector3d(0,0,0), 0, FALSE)
  282. END
  283. END;
  284. RETURN
  285. END;
  286. IF mouseKeys * {0} # {} THEN
  287. IF mouseKeys * {2} # {} THEN
  288. radius := radius - (y - oldY) * 10; IF radius < 10 THEN radius := 10 END;
  289. ELSE
  290. height := height + (y - oldY)
  291. END;
  292. angle := angle - (x - oldX) / img.width * 3.141;
  293. Render
  294. END;
  295. oldX := x; oldY := y
  296. END PointerMove;
  297. PROCEDURE PointerUp*(x, y: LONGINT; keys: SET);
  298. BEGIN
  299. IF mouseKeys = {0} THEN
  300. IF selectedSymbol # NIL THEN
  301. IF keyflags * Inputs.Shift # {} THEN
  302. lookat := selectedSymbol.pos; Render
  303. (* ELSE
  304. Commands.Call(selectedSymbol.command, {}, res, msg);
  305. IF res # 0 THEN
  306. KernelLog.Enter; KernelLog.String(msg); KernelLog.Exit
  307. END *)
  308. END
  309. END
  310. END;
  311. mouseKeys := (keys * {0, 1, 2});
  312. END PointerUp;
  313. (* PROCEDURE KeyPressed(ch : CHAR; flags : SET; keysym : LONGINT);
  314. BEGIN
  315. keyflags := flags;
  316. IF ch = "s" THEN
  317. IF SphereSel IN selectionMethod THEN selectionMethod := selectionMethod - {SphereSel}
  318. ELSE selectionMethod := selectionMethod + {SphereSel}
  319. END
  320. ELSIF ch = "b" THEN
  321. IF BlurpSel IN selectionMethod THEN selectionMethod := selectionMethod - {BlurpSel}
  322. ELSE selectionMethod := selectionMethod + {BlurpSel}
  323. END
  324. END
  325. END KeyPressed;
  326. *)
  327. PROCEDURE Handle*(VAR m : Messages.Message);
  328. BEGIN
  329. IF m.msgType = Messages.MsgExt THEN
  330. IF m.ext IS ReloadMsg THEN Load(m.ext(ReloadMsg).name) END
  331. ELSE
  332. Handle^(m)
  333. END
  334. END Handle;
  335. (* END Navigation and Rendering *)
  336. END Window;
  337. TextureInfo = OBJECT
  338. VAR
  339. img : Raster.Image;
  340. name : ARRAY 128 OF CHAR
  341. END TextureInfo;
  342. VAR
  343. winstance : Window;
  344. textures: Classes.List;
  345. PROCEDURE GenTexture(icon, title: ARRAY OF CHAR; obj : AbstractWorld.Object): AbstractWorld.Texture;
  346. VAR res : BOOLEAN;
  347. mode: Raster.Mode;
  348. pix : Raster.Pixel;
  349. tex : AbstractWorld.Texture;
  350. img : Raster.Image;
  351. timg: Raster.Image;
  352. tw, th, dx, dy : LONGINT;
  353. BEGIN
  354. timg := WMGraphics.LoadImage(icon, TRUE);
  355. Raster.InitMode(mode, Raster.srcCopy);
  356. NEW(img); Raster.Create(img, 64, 64, Raster.BGR565);
  357. Raster.SetRGB(pix, 0C0H, 0C0H, 0C0H); Raster.Fill(img, 1, 1, 62, 62, pix, mode);
  358. Raster.SetRGB(pix, 0H, 0H, 0H);
  359. Raster.Fill(img, 0, 11, 63, 12, pix, mode);
  360. Raster.Fill(img, 7, 12, 56, 62, pix, mode);
  361. Raster.SetRGB(pix, 0FFH, 0FFH, 0FFH);
  362. Raster.Fill(img, 9, 14, 54, 60, pix, mode);
  363. timg := WMGraphics.LoadImage(icon, TRUE); tex := NIL;
  364. IF res THEN
  365. tw := MIN(timg.width, 46); th := MIN(timg.height, 46);
  366. dx := (46 - tw) DIV 2 + 9;
  367. dy := (46 - th) DIV 2 + 14;
  368. Raster.Copy(timg, img, 0, 0, tw, th, dx, dy, mode)
  369. END;
  370. tex := obj.AddTexture(img);
  371. RETURN tex
  372. END GenTexture;
  373. PROCEDURE TextureByName(name: ARRAY OF CHAR; obj : AbstractWorld.Object): AbstractWorld.Texture;
  374. VAR i : LONGINT;
  375. dummy : ANY;
  376. ti : TextureInfo; mode: Raster.Mode;
  377. timg: Raster.Image;
  378. BEGIN
  379. textures.Lock;
  380. FOR i := 0 TO textures.GetCount()-1 DO
  381. dummy := textures.GetItem(i); ti := dummy(TextureInfo);
  382. IF ti.name = name THEN
  383. IF ti.img = NIL THEN
  384. textures.Unlock;
  385. RETURN NIL
  386. ELSE textures.Unlock;
  387. RETURN obj.AddTexture(ti.img)
  388. END
  389. END
  390. END;
  391. textures.Unlock;
  392. NEW(ti); COPY(name, ti.name);
  393. timg := WMGraphics.LoadImage(name, TRUE);
  394. IF timg # NIL THEN
  395. NEW(ti.img); Raster.Create(ti.img, timg.width, timg.height, Raster.BGR565);
  396. Raster.InitMode(mode, Raster.srcCopy);
  397. Raster.Copy(timg, ti.img, 0, 0, timg.width, timg.height, 0, 0, mode)
  398. END;
  399. IF ti.img # NIL THEN RETURN obj.AddTexture(ti.img) ELSE RETURN NIL END
  400. END TextureByName;
  401. (* PROCEDURE MatchI(VAR buf: ARRAY OF CHAR; with: ARRAY OF CHAR): BOOLEAN;
  402. VAR i: LONGINT;
  403. BEGIN
  404. i := 0; WHILE (with[i] # 0X) & (CAP(buf[i]) = CAP(with[i])) DO INC(i) END;
  405. RETURN with[i] = 0X
  406. END MatchI;
  407. *)
  408. PROCEDURE Open*(context : Commands.Context);
  409. VAR name : ARRAY 100 OF CHAR;
  410. BEGIN
  411. IF context.arg.GetString(name) THEN
  412. IF winstance = NIL THEN NEW(winstance, name) END;
  413. END;
  414. END Open;
  415. PROCEDURE Cleanup;
  416. BEGIN
  417. IF winstance # NIL THEN winstance.Close END
  418. END Cleanup;
  419. BEGIN
  420. NEW(textures);
  421. Modules.InstallTermHandler(Cleanup)
  422. END W3dMenu.
  423. W3dMenu.Open W3dFun.XML ~
  424. W3dMenu.Open W3dMenu.XML ~
  425. W3dMenu.Open W3dNetTool.XML ~
  426. W3dMenu.Open W3dPersonal.XML ~
  427. System.Free W3dMenu ~
  428. Compiler.Compile \s W3dVectors.Mod W3dMatrix.Mod W3dGeometry.Mod W3dAbstractWorld.Mod W3dObjectGenerator.Mod
  429. W3dRasterizer.Mod W3dWorld.Mod W3dExplorer.Mod W3dClusterWatch.Mod W3dMenu.Mod~
  430. oberon.bmp objecttracker.bmp networktracker.bmp launcher.bmp tetris.bmp iconvnc.bmp iconhome.bmp iconreload.bmp
  431. iconbones.bmp iconbunny.bmp iconfrog.bmp iconfire.bmp iconfun.bmp iconmemory.bmp iconnettools.bmp iconkeycode.bmp
  432. iconxml.bmp
  433. PC.Compile \s TFVectors.Mod TFMatrix.Mod TFGeometry.Mod TFAbstractWorld.Mod TFObjectGenerator.Mod
  434. Float.TFRasterizer3d.Mod TFWorld3d.Mod TFExplorer.Mod Menu3d.Mod ~
  435. ~
  436. System.Free W3dMenu W3dWorld W3dRasterizer W3dObjectGenerator W3dAbstractWorld W3dGeometry W3dMatrix W3dVectors~
  437. EditTools.OpenAscii W3dFun.XML ~
  438. EditTools.OpenAscii W3dMenu.XML ~
  439. EditTools.OpenAscii W3dNetTools.XML ~
  440. EditTools.OpenAscii W3dPersonal.XML ~