4 #define WINDOW_WIDTH 768
5 #define WINDOW_HEIGHT 480
7 #define SCALE ((float)virtualDesktop.clientSize.h / WINDOW_HEIGHT)
11 class Window3D : struct
13 Object cube, front, back, side;
15 Material frontMaterial { };
16 Material sideMaterial { };
17 Material backMaterial { };
19 Degrees position, wantedPosition;
23 static const char * iconFiles[] =
37 #define NUM_ICONS (sizeof(iconFiles)/sizeof(char *))
38 // #define DOCK_HEIGHT 500
39 #define DOCK_HEIGHT 400
40 #define FULL_SWITCH ((int)dock.iconBitmaps[0].width)
41 #define SMALL_SCALE 0.6f
42 #define SWITCH_SPEED 700
45 #define SLIDING_SPEED 0.5
46 #define SWITCHING_SPEED 0.5
47 #define ENTERING_SPEED 0.5
49 #define ORBIT_SPEED Degrees { 10 }
51 #define ORBIT_HEIGHT 1000
52 // #define ORBIT_HEIGHT 500
58 Bitmap iconBitmaps[NUM_ICONS];
60 float speed, position;
65 static Seconds lastTime;
69 static bool CreateBack(Mesh mesh, int width, int height, int depth, DisplaySystem displaySystem)
75 if(mesh.Allocate(MeshFeatures { vertices = true, texCoords1 = true }, 24, displaySystem))
77 Vector3Df vertices[24] =
79 { -(float)width/2,-(float)height/2,-(float)depth/2 },
80 { (float)width/2,-(float)height/2,-(float)depth/2 },
81 { (float)width/2, (float)height/2,-(float)depth/2 },
82 { -(float)width/2, (float)height/2,-(float)depth/2 },
83 { -(float)width/2,-(float)height/2, (float)depth/2 },
84 { (float)width/2,-(float)height/2, (float)depth/2 },
85 { (float)width/2, (float)height/2, (float)depth/2 },
86 { -(float)width/2, (float)height/2, (float)depth/2 },
88 { -(float)width/2,-(float)height/2,-(float)depth/2 },
89 { (float)width/2,-(float)height/2,-(float)depth/2 },
90 { (float)width/2, (float)height/2,-(float)depth/2 },
91 { -(float)width/2, (float)height/2,-(float)depth/2 },
92 { -(float)width/2,-(float)height/2, (float)depth/2 },
93 { (float)width/2,-(float)height/2, (float)depth/2 },
94 { (float)width/2, (float)height/2, (float)depth/2 },
95 { -(float)width/2, (float)height/2, (float)depth/2 },
97 { -(float)width/2,-(float)height/2,-(float)depth/2 },
98 { (float)width/2,-(float)height/2,-(float)depth/2 },
99 { (float)width/2, (float)height/2,-(float)depth/2 },
100 { -(float)width/2, (float)height/2,-(float)depth/2 },
101 { -(float)width/2,-(float)height/2, (float)depth/2 },
102 { (float)width/2,-(float)height/2, (float)depth/2 },
103 { (float)width/2, (float)height/2, (float)depth/2 },
104 { -(float)width/2, (float)height/2, (float)depth/2 }
106 Pointf texCoords[24] =
108 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
109 { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
110 { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
111 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
112 { 0, 1 }, { 1, 1 }, { 1, 1 }, { 0, 1 },
113 { 0, 0 }, { 1, 0 }, { 1, 0 }, { 0, 0 }
120 CopyBytes(mesh.vertices, vertices, sizeof(vertices));
121 CopyBytes(((Pointf *)mesh.texCoords), texCoords, sizeof(texCoords));
124 PrimitiveGroup group;
125 group = mesh.AddPrimitiveGroup(quads, 4);
128 CopyBytes(group.indices, indices, sizeof(indices));
129 mesh.UnlockPrimitiveGroup(group);
132 mesh.ComputeNormals();
134 mesh.Unlock(MeshFeatures{});
140 static bool CreateFront(Mesh mesh, int width, int height, int depth, DisplaySystem displaySystem)
145 if(mesh.Allocate(MeshFeatures { vertices = true, texCoords1 = true }, 24, displaySystem))
147 Vector3Df vertices[24] =
149 { -(float)width/2,-(float)height/2,-(float)depth/2 },
150 { (float)width/2,-(float)height/2,-(float)depth/2 },
151 { (float)width/2, (float)height/2,-(float)depth/2 },
152 { -(float)width/2, (float)height/2,-(float)depth/2 },
153 { -(float)width/2,-(float)height/2, (float)depth/2 },
154 { (float)width/2,-(float)height/2, (float)depth/2 },
155 { (float)width/2, (float)height/2, (float)depth/2 },
156 { -(float)width/2, (float)height/2, (float)depth/2 },
158 { -(float)width/2,-(float)height/2,-(float)depth/2 },
159 { (float)width/2,-(float)height/2,-(float)depth/2 },
160 { (float)width/2, (float)height/2,-(float)depth/2 },
161 { -(float)width/2, (float)height/2,-(float)depth/2 },
162 { -(float)width/2,-(float)height/2, (float)depth/2 },
163 { (float)width/2,-(float)height/2, (float)depth/2 },
164 { (float)width/2, (float)height/2, (float)depth/2 },
165 { -(float)width/2, (float)height/2, (float)depth/2 },
167 { -(float)width/2,-(float)height/2,-(float)depth/2 },
168 { (float)width/2,-(float)height/2,-(float)depth/2 },
169 { (float)width/2, (float)height/2,-(float)depth/2 },
170 { -(float)width/2, (float)height/2,-(float)depth/2 },
171 { -(float)width/2,-(float)height/2, (float)depth/2 },
172 { (float)width/2,-(float)height/2, (float)depth/2 },
173 { (float)width/2, (float)height/2, (float)depth/2 },
174 { -(float)width/2, (float)height/2, (float)depth/2 }
176 Pointf texCoords[24] =
178 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
179 { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
180 { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
181 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
182 { 0, 1 }, { 1, 1 }, { 1, 1 }, { 0, 1 },
183 { 0, 0 }, { 1, 0 }, { 1, 0 }, { 0, 0 }
190 CopyBytes(mesh.vertices, vertices, sizeof(vertices));
191 CopyBytes(((Pointf *)mesh.texCoords), texCoords, sizeof(texCoords));
194 PrimitiveGroup group;
195 group = mesh.AddPrimitiveGroup(quads, 4);
198 CopyBytes(group.indices, indices, sizeof(indices));
199 mesh.UnlockPrimitiveGroup(group);
202 mesh.ComputeNormals();
204 mesh.Unlock(MeshFeatures {});
210 static bool CreateSide(Mesh mesh, int width, int height, int depth, DisplaySystem displaySystem)
215 if(mesh.Allocate(MeshFeatures { vertices = true, texCoords1 = true }, 24, displaySystem))
217 Vector3Df vertices[24] =
219 { -(float)width/2,-(float)height/2,-(float)depth/2 },
220 { (float)width/2,-(float)height/2,-(float)depth/2 },
221 { (float)width/2, (float)height/2,-(float)depth/2 },
222 { -(float)width/2, (float)height/2,-(float)depth/2 },
223 { -(float)width/2,-(float)height/2, (float)depth/2 },
224 { (float)width/2,-(float)height/2, (float)depth/2 },
225 { (float)width/2, (float)height/2, (float)depth/2 },
226 { -(float)width/2, (float)height/2, (float)depth/2 },
228 { -(float)width/2,-(float)height/2,-(float)depth/2 },
229 { (float)width/2,-(float)height/2,-(float)depth/2 },
230 { (float)width/2, (float)height/2,-(float)depth/2 },
231 { -(float)width/2, (float)height/2,-(float)depth/2 },
232 { -(float)width/2,-(float)height/2, (float)depth/2 },
233 { (float)width/2,-(float)height/2, (float)depth/2 },
234 { (float)width/2, (float)height/2, (float)depth/2 },
235 { -(float)width/2, (float)height/2, (float)depth/2 },
237 { -(float)width/2,-(float)height/2,-(float)depth/2 },
238 { (float)width/2,-(float)height/2,-(float)depth/2 },
239 { (float)width/2, (float)height/2,-(float)depth/2 },
240 { -(float)width/2, (float)height/2,-(float)depth/2 },
241 { -(float)width/2,-(float)height/2, (float)depth/2 },
242 { (float)width/2,-(float)height/2, (float)depth/2 },
243 { (float)width/2, (float)height/2, (float)depth/2 },
244 { -(float)width/2, (float)height/2, (float)depth/2 }
246 Pointf texCoords[24] =
248 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
249 { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
250 { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
251 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
252 { 0, 1 }, { 1, 1 }, { 1, 1 }, { 0, 1 },
253 { 0, 0 }, { 1, 0 }, { 1, 0 }, { 0, 0 }
257 // up, down, right, left
264 CopyBytes(mesh.vertices, vertices, sizeof(vertices));
265 CopyBytes(((Pointf *)mesh.texCoords), texCoords, sizeof(texCoords));
268 PrimitiveGroup group;
269 group = mesh.AddPrimitiveGroup(quads, 16);
272 CopyBytes(group.indices, indices, sizeof(indices));
273 mesh.UnlockPrimitiveGroup(group);
276 mesh.ComputeNormals();
278 mesh.Unlock(MeshFeatures{});
284 class Desktop3D : Window
286 text = "Orbiting 3D Desktop";
288 anchor = { 0, 0, 0, 0 };
290 size = Size { WINDOW_WIDTH, WINDOW_HEIGHT };
296 lookAt, position = {0, ORBIT_HEIGHT, -2000}, target = lookAt, eulerOrientation = Euler { pitch = 15 },
297 zMin = 1, zMax = 10000, fovDirection = vertical, fov = 53
306 Window clippedWindow;
310 Degrees globalPosition;
313 Window poppingWindow;
314 float poppingPercent;
315 float poppingBiggest;
318 Quaternion fromAngle, toAngle;
319 Vector3D fromPosition, toPosition;
320 float sliding; // Camera sliding from the bottom position looking at the orbit to looking at 1 window
321 float switching; // Switching from looking at one application to the next within the orbit
332 Seconds time = GetTime();
333 Seconds diffTime = time - dock.lastTime;
334 dock.lastTime = time;
336 dock.position += (float)(dock.speed * diffTime);
338 if(dock.position >= FULL_SWITCH)
343 if(dock.currentIcon >= NUM_ICONS)
344 dock.currentIcon -= NUM_ICONS;
347 else if(dock.position <= -FULL_SWITCH)
352 if(dock.currentIcon < 0)
353 dock.currentIcon += NUM_ICONS;
367 Seconds time = GetTime();
368 Seconds diffTime = (time - lastTime);
372 //GetMouseState(&buttons, null, null);
375 eObject_RotateEuler(knot, P3D(diffTime / 10, diffTime / 10, diffTime / 10),
376 P3D(0,0,0), P3D(0,0,0));
378 Update(null); //Desktop3DSetDesktopDirty();
381 if(buttons & MOUSE_RIGHT)
383 eCamera_Move(camera, P3D(0,0,1000 * diffTime));
386 else if(buttons & MOUSE_MIDDLE)
388 eCamera_Move(camera, P3D(0,0,-1000 * diffTime));
396 if(sliding == 1 && switching == 1 && entering == 1)
398 globalPosition += (double)diffTime * ORBIT_SPEED;
400 for(child = firstChild; child; child = child.next)
402 if(child.display != display)
404 Window3D window3D = Desktop3DGetWindowHandle(child);
406 if(window3D.position < window3D.wantedPosition - 0.000001)
408 window3D.wantedPosition += (double)diffTime * ORBIT_SPEED;
409 window3D.position += (double)diffTime * (window3D.wantedPosition - window3D.position);
410 window3D.position = Min(window3D.position, window3D.wantedPosition);
411 biggest = Max(biggest, window3D.wantedPosition - window3D.position);
413 else if(window3D.position > window3D.wantedPosition + 0.000001)
415 window3D.wantedPosition += (double)diffTime * ORBIT_SPEED;
416 window3D.position -= (double)diffTime * (window3D.position - window3D.wantedPosition);
417 window3D.position = Max(window3D.position, window3D.wantedPosition);
418 biggest = Max(biggest, window3D.position - window3D.wantedPosition);
422 window3D.wantedPosition += (double)diffTime * ORBIT_SPEED;
423 window3D.position += (double)diffTime * ORBIT_SPEED;
430 #define FIRST_2WINDOWS_POPUP_SPEED 0.5
434 poppingPercent += (float)(diffTime * FIRST_2WINDOWS_POPUP_SPEED);
435 if(poppingPercent < 1)
436 poppingPercent += (float)((1.0 - poppingPercent) * diffTime * FIRST_2WINDOWS_POPUP_SPEED);
437 if(poppingPercent > 0.99999)
439 poppingWindow = null;
440 poppingPercent = 1.0f;
443 else if(biggest < 0.000001)
446 poppingWindow = null;
449 poppingPercent = (float)(1.0 - (Radians)(biggest / poppingBiggest));
450 poppingPercent = Min(poppingPercent, 1.0);
452 if(dockHidden && virtualDesktop.activeChild && entering == 1)
454 Window window = virtualDesktop.activeChild;
455 Window3D window3D = Desktop3DGetWindowHandle(window);
457 lookAt.transform.position = window3D.cube.transform.position;
458 lookAt.UpdateTransform();
460 toPosition = camera.cPosition;
461 toAngle = camera.cOrientation;
464 if(sliding < 1 || switching < 1 || entering < 1)
472 sliding += (float)(diffTime * SLIDING_SPEED);
473 sliding = Min(sliding, 1.0);
476 else if(switching < 1)
478 switching += (float)(diffTime * SWITCHING_SPEED);
479 switching = Min(switching, 1.0);
482 else if(entering < 1)
484 entering += (float)(diffTime * ENTERING_SPEED);
485 entering = Min(entering, 1.0);
489 angle.Slerp(fromAngle, toAngle, factor);
491 position.x = fromPosition.x + factor * (toPosition.x - fromPosition.x);
492 position.y = fromPosition.y + factor * (toPosition.y - fromPosition.y);
493 position.z = fromPosition.z + factor * (toPosition.z - fromPosition.z);
495 camera.AdjustAngle(angle);
496 camera.AdjustPosition(position);
507 SkyBox sky { size = { 10000, 10000, 10000 }, folder = ":skycube", extension = "jpg" };
513 fromPosition = toPosition = camera.cPosition;
514 fromAngle = toAngle = camera.cOrientation;
516 // Start with dock off
521 light.diffuse = white;
522 light.specular = white;
523 light.orientation = Euler { }; //Quaternion { 1,0,Pi,0 };
530 void OnResize(int width, int height)
532 camera.Setup(width, height, null);
535 bool OnLoadGraphics()
539 sky.Create(displaySystem);
542 eObject_Load(&knot, ":eknot.3ds", null, display);
543 knot->transform.scaling = P3D(10,10,10);
544 knot->transform.position = P3D(0,0, 2000);
547 // puzzle = eBitmap_Load(":puzzle.jpg", null, display);
549 // dock.background = Bitmap {};
550 // dock.background.Load(":background.jpg", null, displaySystem);
551 for(c = 0; c<NUM_ICONS; c++)
553 dock.iconBitmaps[c] = Bitmap {};
554 dock.iconBitmaps[c].Load(iconFiles[c], null, displaySystem);
556 lastTime = GetTime();
560 void OnUnloadGraphics()
564 //eObject_Free(cube, display);
566 for(c = 0; c<NUM_ICONS; c++)
567 dock.iconBitmaps[c].Free();
570 #define DOCK_SLIDING_DISTANCE 180
572 void Dock_OnRedraw(Surface surface)
574 int c, icon = dock.currentIcon;
575 float x = -120 - dock.position, starty = DOCK_HEIGHT;
582 starty += sliding * DOCK_SLIDING_DISTANCE;
583 alpha = 255 - (byte)(255*sliding);
587 starty += DOCK_SLIDING_DISTANCE - (sliding * DOCK_SLIDING_DISTANCE);
588 alpha = (byte)(255*sliding);
592 if(!dockHidden || sliding < 1)
595 if(icon < 0) icon += NUM_ICONS;
597 eSurface_Blit(surface, dock.background, 0,0,0,0,
598 dock.background->width, dock.background->height);
600 for(c = 0; c<NUM_ICONS; c++)
604 float scaling = SMALL_SCALE;
607 bitmap = dock.iconBitmaps[icon];
613 float a = dock.position / FULL_SWITCH;
614 if(icon == dock.currentIcon)
617 scaling = (float)(1 - (1-SMALL_SCALE) * a);
619 else if(icon == (dock.currentIcon + 1) % NUM_ICONS)
622 scaling = (float)(SMALL_SCALE + (1-SMALL_SCALE) * a);
625 else if(dock.speed < 0)
627 float a = -dock.position / FULL_SWITCH;
628 if(icon == dock.currentIcon)
631 scaling = 1 - (1-SMALL_SCALE) * a;
633 else if((icon + 1) % NUM_ICONS == dock.currentIcon)
636 scaling = SMALL_SCALE + (1-SMALL_SCALE) * a;
639 else if(icon == dock.currentIcon)
644 float percent = poppingPercent; // * poppingPercent * poppingPercent * poppingPercent;
645 y += (float) sin(percent * 2*Pi*3) * 4 + 0.5f;
649 w = (int)(bitmap.width * scaling);
650 h = (int)(bitmap.height * scaling);
655 surface.SetForeground(ColorAlpha{alpha, white});
656 surface.Stretch(bitmap, (int)(dx * SCALE), (int)(dy * SCALE), 0,0, (int)(w * SCALE), (int)(h * SCALE), bitmap.width, bitmap.height);
661 if(icon == NUM_ICONS) icon = 0;
666 #define ORBIT_RADIUS 800
668 void OnRedraw(Surface surface)
672 surface.Clear(depthBuffer);
674 //PrintLn("position: ", camera.cPosition);
675 display.SetLight(0, &light);
676 display.SetCamera(surface, camera);
678 sky.Render(camera, display);
680 for(child = firstChild; child; child = child.next)
684 Window3D window3D = Desktop3DGetWindowHandle(child);
685 Mesh mesh = window3D.front.mesh;
688 if(mesh.Lock(MeshFeatures { texCoords1 = true }))
690 ((Pointf *)mesh.texCoords)[3].x = 0;
691 ((Pointf *)mesh.texCoords)[3].y = 0;
692 ((Pointf *)mesh.texCoords)[2].x = (float)child.size.w / window3D.bitmap.width;
693 ((Pointf *)mesh.texCoords)[2].y = 0;
694 ((Pointf *)mesh.texCoords)[1].x = (float)child.size.w / window3D.bitmap.width;
695 ((Pointf *)mesh.texCoords)[1].y = (float)child.size.h / window3D.bitmap.height;
696 ((Pointf *)mesh.texCoords)[0].x = 0;
697 ((Pointf *)mesh.texCoords)[0].y = (float)child.size.h / window3D.bitmap.height;
698 mesh.Unlock(MeshFeatures {});
704 if(child == poppingWindow)
705 alpha = 0.5f * poppingPercent * poppingPercent * poppingPercent;
706 else if(child == virtualDesktop.activeChild)
711 alpha = 0.5f + entering / 2.0f;
713 alpha = 1.0f - entering / 2.0f;
719 window3D.frontMaterial.opacity = alpha;
720 window3D.sideMaterial.opacity = alpha;
721 window3D.backMaterial.opacity = alpha;
726 w = (int)(2*Pi*ORBIT_RADIUS / (numWindows+1));
727 h = w * WINDOW_HEIGHT / WINDOW_WIDTH;
735 if(child == poppingWindow)
737 Vector3D finalPosition;
738 Vector3D startPositionProjected = { (-120 + 284) * SCALE, DOCK_HEIGHT * SCALE, 1.0f };
739 Vector3D startPositionView, startPositionWorld;
741 camera.Unproject(startPositionProjected, startPositionView);
742 camera.Untransform(startPositionView, startPositionWorld);
744 finalPosition.x = (float)(cos(window3D.position) * ORBIT_RADIUS);
746 finalPosition.z = (float)(sin(window3D.position) * ORBIT_RADIUS);
748 window3D.cube.transform = Transform
752 startPositionWorld.x + (finalPosition.x - startPositionWorld.x) * poppingPercent,
753 startPositionWorld.y + (finalPosition.y - startPositionWorld.y) * poppingPercent,
754 startPositionWorld.z + (finalPosition.z - startPositionWorld.z) * poppingPercent
756 orientation = Euler { window3D.position - 90 + poppingPercent * 2 * 360, 10, 0 },
757 scaling = { w * poppingPercent, h * poppingPercent, 1 }
762 Vector3Df scaling = Vector3Df { 1,1,1 };
770 wb = (int)(2*Pi*ORBIT_RADIUS / (numWindows));
771 hb = (int)(wb * WINDOW_HEIGHT / WINDOW_WIDTH);
779 scaling.x = wb + (w - wb);// * poppingPercent;
780 scaling.y = hb + (h - hb);// * poppingPercent;
787 window3D.cube.transform = Transform
789 position = { (float)(cos(window3D.position) * ORBIT_RADIUS), 0, (float)(sin(window3D.position) * ORBIT_RADIUS) },
790 orientation = Euler { window3D.position - 90 + window3D.offset.yaw, 10 + window3D.offset.pitch, 0 },
791 scaling = { (float)scaling.x, (float)scaling.y, (float)scaling.z };
795 window3D.cube.UpdateTransform();
797 display.DrawObject(window3D.cube);
801 // display.DrawObject(knot);
803 display.SetCamera(null, null);
805 Dock_OnRedraw(surface);
808 Window GetCursorLocation(int x, int y, int * mx, int * my, bool * back)
810 Window window = null;
812 Vector3D viewSpace, worldSpace, local;
814 display.StartSelection(x, y, 1, 1);
815 display.IntersectPolygons();
816 display.SetCamera(null, camera);
820 window = clippedWindow;
821 window3D = Desktop3DGetWindowHandle(window);
822 display.pickingPlanes = true;
823 display.DrawObject(window3D.cube.Find("Front"));
830 display.CollectHits();
831 for(window = virtualDesktop.firstChild; window; window = window.next)
835 window3D = Desktop3DGetWindowHandle(window);
836 display.DrawObject(window3D.cube);
839 display.GetHits(list);
842 if(hit && hit.numTags)
844 window = (Window)hit.tags[0];
845 window3D = Desktop3DGetWindowHandle(window);
853 display.GetIntersect(viewSpace);
854 camera.Untransform(viewSpace, worldSpace);
855 local.DivideMatrix(worldSpace, window3D.cube.matrix);
857 *mx = (int)(local.x * window.size.w + window.size.w/2 + 0.5) + window.absPosition.x;
858 *my = (int)(local.y * window.size.h + window.size.h/2 + 0.5) + window.absPosition.y;
862 display.SetCamera(null, null);
863 display.StopSelection();
864 display.pickingPlanes = false;
869 int oldx = *mx, oldy = *my;
873 if(*mx < clipBox.left) *mx = clipBox.left;
874 if(*my < clipBox.top) *my = clipBox.top;
875 if(*mx > clipBox.right) *mx = clipBox.right;
876 if(*my > clipBox.bottom) *my = clipBox.bottom;
878 if(oldx != *mx || oldy != *my)
880 Vector3Df viewSpace, worldSpace;
882 local.x = ((float) *mx - window.absPosition.x - window.size.w/2.0 + 0.5) / (float)window.size.w;
883 local.y = ((float) *my - window.absPosition.y - window.size.h/2.0 + 0.5) / (float)window.size.h;
884 local.z = -THICKNESS/2;
886 worldSpace.MultMatrix(local, matrix);
887 camera.TransformPoint(viewSpace, worldSpace);
889 camera.Project(viewSpace, point);
893 SetMousePosition(x, y);
900 bool OnMouseMove(int x, int y, Modifiers mods)
904 int dx = (int)(x - lastMouse.x), dy = (int)(lastMouse.y - y);
907 camera.RotateYaw(-dx, 0,0);
908 camera.RotatePitch(dy, 0,0);
912 Window child = activeChild;
913 Window3D window3D = Desktop3DGetWindowHandle(child);
914 window3D.offset.yaw += dx;
915 window3D.offset.pitch += dy;
917 // window.dirty = true;
926 Window clickedWindow = GetCursorLocation(x,y, &mx, &my, &back);
929 if(Desktop3DMouseMessage(clickedWindow, 24, mx, my, &mods, false, true))
938 bool OnLeftButtonDown(int x, int y, Modifiers mods)
944 Window clickedWindow = GetCursorLocation(x,y, &mx, &my, &back);
947 if(back || Desktop3DTitleBarClicked(clickedWindow, mx, my))
949 clickedWindow.Activate();
950 movingCamera = false;
954 else if(Desktop3DMouseMessage(clickedWindow, 25, mx, my, &mods, false, true))
972 bool OnLeftButtonUp(int x, int y, Modifiers mods)
977 Window clickedWindow = GetCursorLocation(x, y, &mx, &my, &back);
980 Desktop3DMouseMessage(clickedWindow, 26, mx, my, &mods, false, true);
992 bool OnKeyHit(Key key, unichar character)
995 static const char * shotFileNames[] =
997 ":img1.jpg", ":img2.jpg", ":img3.jpg", ":img4.jpg", ":img5.jpg"
1006 Window ac = virtualDesktop.activeChild;
1008 if(fullScreen || sliding < 1 || switching < 1 || entering < 1) break;
1010 virtualDesktop.CycleChildren(true, false, false, true);
1011 if(ac == virtualDesktop.activeChild) break;
1013 window3D = Desktop3DGetWindowHandle(virtualDesktop.activeChild);
1015 fromAngle = camera.cOrientation;
1016 fromPosition = camera.cPosition;
1018 lookAt.transform.position = window3D.cube.transform.position;
1019 lookAt.UpdateTransform();
1020 camera.position = {};
1021 camera.eulerOrientation = Euler{};
1026 toPosition = camera.cPosition;
1027 toAngle = camera.cOrientation;
1029 camera.AdjustAngle(fromAngle);
1030 camera.AdjustPosition(fromPosition);
1034 if(!dockTimer.started && !poppingWindow)
1036 dock.lastTime = GetTime();
1038 dock.speed = -SWITCH_SPEED;
1046 Window ac = virtualDesktop.activeChild;
1048 if(fullScreen || sliding < 1 || switching < 1 || entering < 1) break;
1050 virtualDesktop.CycleChildren(false, false, false, true);
1051 if(ac == virtualDesktop.activeChild) break;
1053 window3D = Desktop3DGetWindowHandle(virtualDesktop.activeChild);
1055 fromAngle = camera.cOrientation;
1056 fromPosition = camera.cPosition;
1058 lookAt.transform.position = window3D.cube.transform.position;
1059 lookAt.UpdateTransform();
1064 toPosition = camera.cPosition;
1065 toAngle = camera.cOrientation;
1067 camera.AdjustAngle(fromAngle);
1068 camera.AdjustPosition(fromPosition);
1072 if(!dockTimer.started && !poppingWindow)
1074 dock.lastTime = GetTime();
1076 dock.speed = SWITCH_SPEED;
1082 if(poppingWindow) break;
1083 if(sliding == 1.0 && !dockHidden)
1085 Window window = virtualDesktop.activeChild;
1088 Window3D window3D = Desktop3DGetWindowHandle(window);
1091 fromAngle = camera.cOrientation;
1092 fromPosition = camera.cPosition;
1094 camera.type = lookAt;
1095 camera.position = { 0,0,0 };
1096 camera.eulerOrientation = Euler {};
1097 lookAt.transform.position = window3D.cube.transform.position;
1098 lookAt.transform.orientation = Euler {};
1099 lookAt.UpdateTransform();
1105 toPosition = camera.cPosition;
1106 toAngle = camera.cOrientation;
1108 camera.AdjustAngle(fromAngle);
1109 camera.AdjustPosition(fromPosition);
1112 if(!dockHidden) break; // Follow through to 'full screen' if dock is hiddens
1116 if(sliding < 1 || switching < 1 || entering < 1) break;
1121 /*if(dock.currentIcon == 1)
1125 this, multiLine = true, is3D = true, borderStyle = Fixed, hasClose = true, text = "Video",
1126 size = Size { WINDOW_WIDTH, WINDOW_HEIGHT }, fileName = ":430.flc"
1133 this, is3D = true, borderStyle = fixed, hasClose = true, text = "3D Window",
1134 size = Size { WINDOW_WIDTH, WINDOW_HEIGHT }, image = BitmapResource { fileName = shotFileNames[id] }, opacity = 1, inactive = false
1138 id %= sizeof(shotFileNames) / sizeof(char *);
1141 else if(!fullScreen)
1144 Window window = virtualDesktop.activeChild;
1145 Window3D window3D = Desktop3DGetWindowHandle(window);
1147 fromAngle = camera.cOrientation;
1148 fromPosition = camera.cPosition;
1150 distance = window3D.cube.transform.scaling.x * (float)camera.focal.w / virtualDesktop.clientSize.w;
1151 distance += THICKNESS/2;
1153 camera.type = attached;
1154 camera.position = {0,0,-distance};
1155 camera.eulerOrientation = Euler{};
1156 lookAt.transform.position = window3D.cube.transform.position;
1157 lookAt.transform.orientation = window3D.cube.transform.orientation;
1158 lookAt.UpdateTransform();
1163 toPosition = camera.cPosition;
1164 toAngle = camera.cOrientation;
1166 camera.AdjustAngle(fromAngle);
1167 camera.AdjustPosition(fromPosition);
1176 if(sliding == 1.0 && dockHidden)
1178 if(sliding < 1 || switching < 1 || entering < 1) break;
1180 fromAngle = camera.cOrientation;
1181 fromPosition = camera.cPosition;
1185 Window window = virtualDesktop.activeChild;
1186 Window3D window3D = Desktop3DGetWindowHandle(window);
1188 camera.type = lookAt;
1189 camera.position = {};
1190 camera.eulerOrientation = Euler {};
1191 lookAt.transform.position = window3D.cube.transform.position;
1196 camera.type = lookAt;
1197 camera.position = {0, ORBIT_HEIGHT, -2000};
1198 camera.eulerOrientation = Euler { pitch = 15 };
1199 lookAt.transform.position = {};
1205 lookAt.transform.orientation = Euler {};
1206 lookAt.UpdateTransform();
1209 toPosition = camera.cPosition;
1210 toAngle = camera.cOrientation;
1212 camera.AdjustAngle(fromAngle);
1213 camera.AdjustPosition(fromPosition);
1215 else if(key == escape)
1223 static Window3D Setup3DWindow(Window window, int w, int h)
1225 Window3D window3D {};
1228 window3D.bitmap = Bitmap {};
1229 window3D.bitmap.AllocateDD(virtualDesktop.displaySystem, w, h);
1230 // window3D.bitmap.AllocateDD(virtualDesktop.displaySystem, TEXTURE_SIZE, TEXTURE_SIZE);
1232 window3D.cube = Object {};
1233 window3D.cube.tag = window;
1235 window3D.frontMaterial.diffuse = white;
1236 window3D.frontMaterial.opacity = 0.5f;
1237 window3D.frontMaterial.baseMap = window3D.bitmap;
1238 window3D.frontMaterial.flags = MaterialFlags { translucent = true, doubleSided = true };
1240 window3D.backMaterial.diffuse = white;
1241 window3D.backMaterial.opacity = 0.5f;
1242 window3D.backMaterial.flags = MaterialFlags { translucent = true, doubleSided = true };
1244 window3D.sideMaterial.diffuse = white;
1245 window3D.sideMaterial.opacity = 0.5f;
1246 window3D.sideMaterial.flags = MaterialFlags { translucent = true, doubleSided = true };
1248 window3D.cube.AddName((window3D.back = Object {}), "Back");
1249 window3D.back.InitializeMesh(virtualDesktop.displaySystem);
1250 CreateBack(window3D.back.mesh, 1, 1, THICKNESS, virtualDesktop.displaySystem);
1251 window3D.back.mesh.ApplyMaterial(window3D.backMaterial);
1252 window3D.back.mesh.ApplyTranslucency(window3D.back);
1254 window3D.cube.AddName((window3D.front = Object {}), "Front");
1255 window3D.front.InitializeMesh(virtualDesktop.displaySystem);
1256 CreateFront(window3D.front.mesh, 1, 1, THICKNESS, virtualDesktop.displaySystem);
1257 window3D.front.mesh.ApplyMaterial(window3D.frontMaterial);
1258 window3D.front.mesh.ApplyTranslucency(window3D.front);
1260 window3D.cube.AddName((window3D.side = Object {}), "Side");
1261 window3D.side.InitializeMesh(virtualDesktop.displaySystem);
1262 CreateSide(window3D.side.mesh, 1, 1, THICKNESS, virtualDesktop.displaySystem);
1263 window3D.side.mesh.ApplyMaterial(window3D.sideMaterial);
1264 window3D.side.mesh.ApplyTranslucency(window3D.side);
1266 window3D.cube.SetMinMaxRadius(true);
1268 window3D.id = virtualDesktop.numWindows;
1269 virtualDesktop.poppingBiggest = 0;
1270 for(child = virtualDesktop.firstChild; child; child = child.next)
1272 if(child.is3D) //display != virtualDesktop.display)
1274 Window3D child3D = Desktop3DGetWindowHandle(child);
1278 child3D.wantedPosition = virtualDesktop.globalPosition +
1279 child3D.id * 2*Pi / (virtualDesktop.numWindows+1);
1281 window3D.position = window3D.wantedPosition;
1282 virtualDesktop.poppingBiggest = Max(virtualDesktop.poppingBiggest,
1283 child3D.position - child3D.wantedPosition);
1286 virtualDesktop.numWindows++;
1287 virtualDesktop.poppingWindow = window;
1288 virtualDesktop.poppingPercent = 0;
1293 static void Update3DWindow(Window window, Box box)
1295 Window3D window3D = Desktop3DGetWindowHandle(window);
1296 int w = box.right - box.left + 1;
1297 int h = box.bottom - box.top + 1;
1299 glBindTexture(GL_TEXTURE_2D, (int)(intptr)window3D.bitmap.driverData);
1300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1303 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
1305 window.size.h - h - box.top,
1306 box.left + virtualDesktop.clientStart.x,
1307 virtualDesktop.size.h - virtualDesktop.clientStart.y - h - box.top, w, h);
1310 class Orbit : GuiApplication
1318 Desktop3DInitialize(virtualDesktop, Setup3DWindow, Update3DWindow);
1323 Desktop3D virtualDesktop {};