001/**
002 * Copyright (c) 2008-2014 Ardor Labs, Inc.
003 *
004 * This file is part of Ardor3D.
005 *
006 * Ardor3D is free software: you can redistribute it and/or modify it
007 * under the terms of its license which may be found in the accompanying
008 * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
009 */
010
011package com.ardor3d.example.canvas;
012
013import java.io.IOException;
014import java.net.URISyntaxException;
015import java.util.HashMap;
016import java.util.Map;
017import java.util.logging.Logger;
018
019import org.eclipse.swt.SWT;
020import org.eclipse.swt.custom.SashForm;
021import org.eclipse.swt.events.ControlEvent;
022import org.eclipse.swt.events.ControlListener;
023import org.eclipse.swt.graphics.Rectangle;
024import org.eclipse.swt.layout.FillLayout;
025import org.eclipse.swt.widgets.Composite;
026import org.eclipse.swt.widgets.Display;
027import org.eclipse.swt.widgets.Event;
028import org.eclipse.swt.widgets.Listener;
029import org.eclipse.swt.widgets.Menu;
030import org.eclipse.swt.widgets.MenuItem;
031import org.eclipse.swt.widgets.Shell;
032import org.eclipse.swt.widgets.TabFolder;
033import org.eclipse.swt.widgets.TabItem;
034
035import com.ardor3d.example.Purpose;
036import com.ardor3d.framework.Canvas;
037import com.ardor3d.framework.CanvasRenderer;
038import com.ardor3d.framework.DisplaySettings;
039import com.ardor3d.framework.FrameHandler;
040import com.ardor3d.framework.jogl.JoglCanvasRenderer;
041import com.ardor3d.framework.jogl.swt.JoglNewtSwtCanvas;
042import com.ardor3d.image.util.ImageLoaderUtil;
043import com.ardor3d.image.util.jogl.JoglImageLoader;
044import com.ardor3d.input.ControllerWrapper;
045import com.ardor3d.input.GrabbedState;
046import com.ardor3d.input.Key;
047import com.ardor3d.input.MouseCursor;
048import com.ardor3d.input.PhysicalLayer;
049import com.ardor3d.input.jogl.JoglNewtFocusWrapper;
050import com.ardor3d.input.jogl.JoglNewtKeyboardWrapper;
051import com.ardor3d.input.jogl.JoglNewtMouseManager;
052import com.ardor3d.input.jogl.JoglNewtMouseWrapper;
053import com.ardor3d.input.logical.DummyControllerWrapper;
054import com.ardor3d.input.logical.InputTrigger;
055import com.ardor3d.input.logical.KeyPressedCondition;
056import com.ardor3d.input.logical.LogicalLayer;
057import com.ardor3d.input.logical.TriggerAction;
058import com.ardor3d.input.logical.TwoInputStates;
059import com.ardor3d.renderer.Camera;
060import com.ardor3d.util.Timer;
061import com.ardor3d.util.resource.ResourceLocatorTool;
062import com.ardor3d.util.resource.SimpleResourceLocator;
063import com.ardor3d.util.resource.URLResourceSource;
064
065/**
066 * This examples demonstrates how to render OpenGL (via JOGL) in a NEWT SWT canvas. FIXME update the thumbnail and the
067 * description
068 */
069@Purpose(htmlDescriptionKey = "com.ardor3d.example.canvas.JoglSwtExample", //
070thumbnailPath = "com/ardor3d/example/media/thumbnails/canvas_JoglSwtExample.jpg", //
071maxHeapMemory = 64)
072public class JoglNewtSwtExample {
073    static MouseCursor _cursor1;
074    static MouseCursor _cursor2;
075
076    static Map<Canvas, Boolean> _showCursor1 = new HashMap<>();
077
078    private static final Logger logger = Logger.getLogger(JoglNewtSwtExample.class.toString());
079    private static int i = 0;
080
081    public static void main(final String[] args) {
082        System.setProperty("ardor3d.useMultipleContexts", "true");
083
084        final Timer timer = new Timer();
085        final FrameHandler frameWork = new FrameHandler(timer);
086        final LogicalLayer logicalLayer = new LogicalLayer();
087
088        final MyExit exit = new MyExit();
089        final ExampleScene scene = new ExampleScene();
090        final RotatingCubeGame game = new RotatingCubeGame(scene, exit, logicalLayer, Key.T);
091
092        frameWork.addUpdater(game);
093
094        // INIT SWT STUFF
095        final Display display = new Display();
096        final Shell shell = new Shell(display);
097        shell.setLayout(new FillLayout());
098
099        // This is our tab folder, it will be accepting our 3d canvases
100        final TabFolder tabFolder = new TabFolder(shell, SWT.BORDER);
101
102        // Add a menu item that will create and add a new canvas.
103        final Menu bar = new Menu(shell, SWT.BAR);
104        shell.setMenuBar(bar);
105
106        final MenuItem fileItem = new MenuItem(bar, SWT.CASCADE);
107        fileItem.setText("&Tasks");
108
109        final Menu submenu = new Menu(shell, SWT.DROP_DOWN);
110        fileItem.setMenu(submenu);
111        final MenuItem item = new MenuItem(submenu, SWT.PUSH);
112        item.addListener(SWT.Selection, new Listener() {
113            @Override
114            public void handleEvent(final Event e) {
115                Display.getDefault().asyncExec(new Runnable() {
116                    @Override
117                    public void run() {
118                        addNewCanvas(tabFolder, scene, frameWork, logicalLayer);
119                    }
120                });
121            }
122        });
123        item.setText("Add &3d Canvas");
124        item.setAccelerator(SWT.MOD1 + '3');
125
126        JoglImageLoader.registerLoader();
127
128        try {
129            final SimpleResourceLocator srl = new SimpleResourceLocator(ResourceLocatorTool.getClassPathResource(
130                    JoglNewtSwtExample.class, "com/ardor3d/example/media/"));
131            ResourceLocatorTool.addResourceLocator(ResourceLocatorTool.TYPE_TEXTURE, srl);
132        } catch (final URISyntaxException ex) {
133            ex.printStackTrace();
134        }
135
136        addNewCanvas(tabFolder, scene, frameWork, logicalLayer);
137
138        shell.open();
139
140        game.init();
141
142        while (!shell.isDisposed() && !exit.isExit()) {
143            display.readAndDispatch();
144            frameWork.updateFrame();
145            Thread.yield();
146        }
147
148        display.dispose();
149        System.exit(0);
150    }
151
152    private static void addNewCanvas(final TabFolder tabFolder, final ExampleScene scene, final FrameHandler frameWork,
153            final LogicalLayer logicalLayer) {
154        i++;
155        logger.info("Adding canvas");
156
157        // Add a new tab to hold our canvas
158        final TabItem item = new TabItem(tabFolder, SWT.NONE);
159        item.setText("Canvas #" + i);
160        tabFolder.setSelection(item);
161        final Composite canvasParent = new Composite(tabFolder, SWT.NONE);
162        canvasParent.setLayout(new FillLayout());
163        item.setControl(canvasParent);
164
165        final SashForm splitter = new SashForm(canvasParent, SWT.HORIZONTAL);
166
167        final SashForm splitterLeft = new SashForm(splitter, SWT.VERTICAL);
168        final Composite topLeft = new Composite(splitterLeft, SWT.NONE);
169        topLeft.setLayout(new FillLayout());
170        final Composite bottomLeft = new Composite(splitterLeft, SWT.NONE);
171        bottomLeft.setLayout(new FillLayout());
172
173        final SashForm splitterRight = new SashForm(splitter, SWT.VERTICAL);
174        final Composite topRight = new Composite(splitterRight, SWT.NONE);
175        topRight.setLayout(new FillLayout());
176        final Composite bottomRight = new Composite(splitterRight, SWT.NONE);
177        bottomRight.setLayout(new FillLayout());
178
179        canvasParent.layout();
180
181        final DisplaySettings settings = new DisplaySettings(400, 300, 24, 0, 0, 16, 0, 0, false, false);
182
183        final JoglCanvasRenderer canvasRenderer1 = new JoglCanvasRenderer(scene);
184        final JoglNewtSwtCanvas canvas1 = new JoglNewtSwtCanvas(settings, canvasRenderer1, topLeft, SWT.NONE);
185        frameWork.addCanvas(canvas1);
186        canvas1.addControlListener(newResizeHandler(canvas1, canvasRenderer1));
187
188        final JoglCanvasRenderer canvasRenderer2 = new JoglCanvasRenderer(scene);
189        final JoglNewtSwtCanvas canvas2 = new JoglNewtSwtCanvas(settings, canvasRenderer2, bottomLeft, SWT.NONE);
190        frameWork.addCanvas(canvas2);
191        canvas2.addControlListener(newResizeHandler(canvas2, canvasRenderer2));
192
193        final JoglCanvasRenderer canvasRenderer3 = new JoglCanvasRenderer(scene);
194        final JoglNewtSwtCanvas canvas3 = new JoglNewtSwtCanvas(settings, canvasRenderer3, topRight, SWT.NONE);
195        frameWork.addCanvas(canvas3);
196        canvas3.addControlListener(newResizeHandler(canvas3, canvasRenderer3));
197
198        final JoglCanvasRenderer canvasRenderer4 = new JoglCanvasRenderer(scene);
199        final JoglNewtSwtCanvas canvas4 = new JoglNewtSwtCanvas(settings, canvasRenderer4, bottomRight, SWT.NONE);
200        frameWork.addCanvas(canvas4);
201        canvas4.addControlListener(newResizeHandler(canvas4, canvasRenderer4));
202
203        canvas1.setFocus();
204
205        final JoglNewtKeyboardWrapper keyboardWrapper = new JoglNewtKeyboardWrapper(canvas1);
206        final JoglNewtFocusWrapper focusWrapper = new JoglNewtFocusWrapper(canvas1);
207        final JoglNewtMouseManager mouseManager = new JoglNewtMouseManager(canvas1);
208        final JoglNewtMouseWrapper mouseWrapper = new JoglNewtMouseWrapper(canvas1, mouseManager);
209        canvas1.setMouseManager(mouseManager);
210        final ControllerWrapper controllerWrapper = new DummyControllerWrapper();
211
212        final PhysicalLayer pl = new PhysicalLayer(keyboardWrapper, mouseWrapper, controllerWrapper, focusWrapper);
213
214        logicalLayer.registerInput(canvas1, pl);
215
216        logicalLayer.registerTrigger(new InputTrigger(new KeyPressedCondition(Key.H), new TriggerAction() {
217            @Override
218            public void perform(final Canvas source, final TwoInputStates inputStates, final double tpf) {
219                if (source != canvas1) {
220                    return;
221                }
222
223                if (_showCursor1.get(canvas1)) {
224                    mouseManager.setCursor(_cursor1);
225                } else {
226                    mouseManager.setCursor(_cursor2);
227                }
228
229                _showCursor1.put(canvas1, !_showCursor1.get(canvas1));
230            }
231        }));
232        logicalLayer.registerTrigger(new InputTrigger(new KeyPressedCondition(Key.J), new TriggerAction() {
233            @Override
234            public void perform(final Canvas source, final TwoInputStates inputStates, final double tpf) {
235                if (source != canvas1) {
236                    return;
237                }
238
239                mouseManager.setCursor(MouseCursor.SYSTEM_DEFAULT);
240            }
241        }));
242        logicalLayer.registerTrigger(new InputTrigger(new KeyPressedCondition(Key.G), new TriggerAction() {
243            @Override
244            public void perform(final Canvas source, final TwoInputStates inputStates, final double tpf) {
245                if (source != canvas1) {
246                    return;
247                }
248
249                mouseManager.setGrabbed(mouseManager.getGrabbed() == GrabbedState.NOT_GRABBED ? GrabbedState.GRABBED
250                        : GrabbedState.NOT_GRABBED);
251            }
252        }));
253
254        try {
255            _cursor1 = createMouseCursor("com/ardor3d/example/media/input/wait_cursor.png");
256            _cursor2 = createMouseCursor("com/ardor3d/example/media/input/movedata.gif");
257        } catch (final IOException ioe) {
258            ioe.printStackTrace();
259        }
260
261        _showCursor1.put(canvas1, true);
262    }
263
264    private static MouseCursor createMouseCursor(final String resourceName) throws IOException {
265        final com.ardor3d.image.Image image = ImageLoaderUtil
266                .loadImage(
267                        new URLResourceSource(ResourceLocatorTool.getClassPathResource(JoglNewtSwtExample.class,
268                                resourceName)), false);
269
270        return new MouseCursor("cursor1", image, 0, image.getHeight() - 1);
271    }
272
273    static ControlListener newResizeHandler(final JoglNewtSwtCanvas swtCanvas, final CanvasRenderer canvasRenderer) {
274        final ControlListener retVal = new ControlListener() {
275            @Override
276            public void controlMoved(final ControlEvent e) {}
277
278            @Override
279            public void controlResized(final ControlEvent event) {
280                final Rectangle size = swtCanvas.getClientArea();
281                if ((size.width == 0) && (size.height == 0)) {
282                    return;
283                }
284                final float aspect = (float) size.width / (float) size.height;
285                final Camera camera = canvasRenderer.getCamera();
286                if (camera != null) {
287                    final double fovY = camera.getFovY();
288                    final double near = camera.getFrustumNear();
289                    final double far = camera.getFrustumFar();
290                    camera.setFrustumPerspective(fovY, aspect, near, far);
291                    camera.resize(size.width, size.height);
292                }
293            }
294        };
295        return retVal;
296    }
297
298    private static class MyExit implements Exit {
299        private volatile boolean exit = false;
300
301        @Override
302        public void exit() {
303            exit = true;
304        }
305
306        public boolean isExit() {
307            return exit;
308        }
309    }
310}