package br.com.etyllica.awt.core; import java.awt.Component; import java.awt.Cursor; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.Transparency; import java.awt.dnd.DropTarget; import java.awt.event.ComponentEvent; import java.awt.image.MemoryImageSource; import java.awt.image.VolatileImage; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import br.com.etyllica.awt.AWTGraphics; import br.com.etyllica.awt.FullScreenWindow; import br.com.etyllica.awt.core.input.AWTKeyboard; import br.com.etyllica.core.GameCore; import br.com.etyllica.core.InnerCore; import br.com.etyllica.core.collision.CollisionDetector; import br.com.etyllica.core.context.Application; import br.com.etyllica.core.context.Session; import br.com.etyllica.core.engine.EtyllicaFrame; import br.com.etyllica.core.event.GUIEvent; import br.com.etyllica.core.graphics.Monitor; import br.com.etyllica.core.loop.FrameSkippingLoop; import br.com.etyllica.core.loop.GameLoop; import br.com.etyllica.effects.GenericFullScreenEffect; import br.com.etyllica.gui.Window; import br.com.etyllica.loader.Loader; import br.com.etyllica.util.io.IOHelper; /** * AWTCore is an InnerCore based on AWT * @author yuripourre * */ public class AWTCore extends InnerCore implements Runnable, GameCore, java.awt.event.ComponentListener { private int width; private int height; private Set<Loader> loaders; private GraphicsConfiguration configuration; private java.awt.Component component; private Window window; private VolatileImage volatileImage; private String path = ""; private AWTGraphics graphic; private FullScreenWindow fullScreen = null; private EtyllicaFrame engine; private boolean running = true; private GameLoop gameLoop; private boolean locked = false; private DropTarget dropTarget; public AWTCore(Component component, int width, int height) { super(width, height); this.component = component; this.configuration = component.getGraphicsConfiguration(); this.width = width; this.height = height; initGraphics(width, height); //Core methods initMonitors(width, height); moveToCenter(); window = new Window(component.getX(), component.getY(), width, height); window.setSessionMap(new Session()); window.setComponent(component); gameLoop = new FrameSkippingLoop(this); dropTarget = new DropTarget(component, new AWTDragAndDrop(this)); } public void initMonitors(int width, int height) { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice[] devices = ge.getScreenDevices(); if(devices.length > 0) { for (int i = 0; i < devices.length; i++) { Rectangle gcBounds = devices[i].getDefaultConfiguration().getBounds(); int x = gcBounds.x; int y = gcBounds.y; int w = gcBounds.width; int h = gcBounds.height; monitors.add(new Monitor(x, y, w, h, devices[i])); } } else { monitors.add(new Monitor(0, 0, width, height, devices[0])); } } public void moveToCenter() { Monitor firstMonitor = monitors.get(0); int x = firstMonitor.getW()/2-component.getWidth()/2; int y = firstMonitor.getH()/2-component.getHeight()/2; component.setLocation(x, y); } public void setSession(Session session) { window.setSessionMap(session); } private void initGraphics(int width, int height) { locked = true; this.graphic = new AWTGraphics(width, height); defineSize(width, height); locked = false; } public String getPath() { return path; } public void setPath(String path) { //For Windows String s = IOHelper.fixPath(path); this.path = s; } public void initDefault() { for(Loader loader:loaders) { loader.setUrl(path); loader.initLoader(); } } public void enableFullScreen() { Monitor selectedMonitor = monitors.get(0); Point p = this.component.getLocation(); for(Monitor monitor: monitors) { if(CollisionDetector.colideRectPoint(monitor, p.x, p.y)) { selectedMonitor = monitor; } } if (!isFullScreenEnable()) { fullScreen = FullScreenHelper.enableFullScreen(this, selectedMonitor); setFullScreenEnable(true); } addEffect(new GenericFullScreenEffect(0, 0, this.width, height)); } public void disableFullScreen() { FullScreenHelper.disableFullScreen(this); setFullScreenEnable(false); } public void startCore(Application application) { this.window.setApplication(application); replaceWindow(window); component.setFocusTraversalKeysEnabled(false); component.setFocusable(true); component.requestFocus(); hideDefaultCursor(component); component.addMouseMotionListener( getMouse() ); component.addMouseWheelListener( getMouse() ); component.addMouseListener( getMouse() ); component.addKeyListener( (AWTKeyboard)getKeyboard() ); } //Component Methods private VolatileImage createBackBuffer(int width, int height) { return createBackBuffer(width, height, Transparency.OPAQUE); } private VolatileImage createBackBuffer(int width, int height, int transparency) { return configuration.createCompatibleVolatileImage(width, height, transparency); } public void defineSize(int width, int height) { component.setSize(width, height); volatileImage = createBackBuffer(width, height); if(volatileImage != null) { //graphic.setBufferedImage(volatileImage.getSnapshot()); graphic.setVolatileImage(volatileImage); } } public void validateVolatileImage() { int valCode = volatileImage.validate(configuration); // This means the device doesn't match up to this hardware accelerated image. if(valCode == VolatileImage.IMAGE_INCOMPATIBLE) { volatileImage = createBackBuffer(width,height); // recreate the hardware accelerated image. graphic.setVolatileImage(volatileImage); } } public static void hideDefaultCursor(Component component) { int[] pixels = new int[16 * 16]; Cursor transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor( Toolkit.getDefaultToolkit().createImage( new MemoryImageSource(16, 16, pixels, 0, 16)) , new Point(0, 0), "invisibleCursor"); component.setCursor( transparentCursor ); } public void paint( Graphics g ) { if(locked) return; //GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); //GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration(); validateVolatileImage(); draw(graphic); //volatileImg.getGraphics().drawImage(desktop.getApplication().getBimg(), desktop.getApplication().getX(), desktop.getApplication().getY(), this); //volatileImg.getGraphics().drawImage(grafico.getBimg(), desktop.getApplication().getX(), desktop.getApplication().getY(), this); if(graphic.getVimg() == null) return; if (!isFullScreenEnable()) { g.drawImage(graphic.getVimg(), (int)window.getContext().getX(), (int)window.getContext().getY(), component); } else { fullScreen.draw(graphic.getVimg()); } g.dispose(); } public int getW() { return width; } public void setW(int w) { this.width = w; } public int getH() { return height; } public void setH(int h) { this.height = h; } public void setLoaders(Set<Loader> loaders) { this.loaders = loaders; } public void update(double delta) throws Exception { long now = System.currentTimeMillis(); update(now); updateEngine(delta); } public void render() { engine.draw(); } @Override public void hideCursor() { super.hideCursor(); } public void setEngine(EtyllicaFrame engine) { this.engine = engine; } public void startEngine() { component.setVisible(true); ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(this); } @Override public void run() { try { gameLoop.loop(); } catch (Exception e) { e.printStackTrace(); } } private void updateEngine(double delta) { GUIEvent event = getSuperEvent(); engine.updateSuperEvent(event); } @Override public boolean isRunning() { return running; } @Override public void setFps(int fps) { //System.out.println("frames: " + fps); super.setFps(fps); } @Override public void componentHidden(ComponentEvent event) { // TODO Auto-generated method stub } @Override public void componentMoved(ComponentEvent event) { // TODO Auto-generated method stub } @Override public void componentResized(ComponentEvent event) { Component component = event.getComponent(); Rectangle bounds = component.getBounds(); int width = bounds.width; int height = bounds.height; initGraphics(width, height); //System.out.println("Resized: "+bounds.x+", "+bounds.y+", "+bounds.width+", "+bounds.height); resizeApplication(width, height); } @Override public void componentShown(ComponentEvent event) { // TODO Auto-generated method stub } public Component getComponent() { return component; } public FullScreenWindow getFullScreenWindow() { return fullScreen; } }