Updated readability of the code.
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / gui / RenderingContext.java
index a16c2d5..c5c42f6 100644 (file)
@@ -1,15 +1,11 @@
 /*
- * Sixth - System for data storage, computation, exploration and interaction.
- * Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
- * 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 3 of the GNU Lesser General Public License
- * or later as published by the Free Software Foundation.
+ * Sixth 3D engine. Author: Svjatoslav Agejenko. 
+ * This project is released under Creative Commons Zero (CC0) license.
  */
-
 package eu.svjatoslav.sixth.e3d.gui;
 
-import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseClick;
+import eu.svjatoslav.sixth.e3d.geometry.Point2D;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseEvent;
 import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseInteractionController;
 
 import java.awt.*;
@@ -20,63 +16,107 @@ import java.awt.image.WritableRaster;
 public class RenderingContext {
 
     public static final int bufferedImageType = BufferedImage.TYPE_4BYTE_ABGR;
-
-    public final BufferedImage bufferedImage;
-
     public final Graphics2D graphics;
-
-    public final byte[] bytes;
-
+    public final byte[] pixels;
     public final int width;
     public final int height;
+    /**
+     * Center of the screen in screen space (pixels).
+     * This is the point where (0,0) coordinate of the world space is rendered.
+     */
+    public final Point2D centerCoordinate;
 
-    public final int xCenter;
-    public final int yCenter;
-
+    /**
+     * Zoom factor. The bigger the value, the more zoomed in the view is.
+     */
     public final double zoom;
-
+    final BufferedImage bufferedImage;
+    /**
+     * Number of frame that is currently being rendered.
+     * Every frame has its own number.
+     */
     public int frameNumber = 0;
 
     /**
-     * Used to signal that actual rendering should be performed. It is useful to
-     * skip rendering when we only want to detect mouse clicks intersections
-     * without actually updating rendered frame.
+     * UI component that mouse is currently hovering over.
+     */
+    private MouseInteractionController objectPreviouslyUnderMouseCursor;
+
+    public void prepareForNewFrameRendering(){
+        mouseEvent = null;
+        currentObjectUnderMouseCursor = null;
+    }
+
+    /**
+     * Mouse click event that needs to be processed.
+     * This event is processed only once per frame.
+     * If there are multiple objects under mouse cursor, the top-most object will receive the event.
+     * If there are no objects under mouse cursor, the event will be ignored.
+     * If there is no event, this field will be null.
+     * This field is set to null after the event is processed.
      */
-    public boolean doRender = true; // TODO: make use of the variable
+    private MouseEvent mouseEvent;
 
-    public MouseClick mouseClick;
+    public void setMouseEvent(MouseEvent mouseEvent) {
+        this.mouseEvent = mouseEvent;
+    }
 
-    public MouseInteractionController clickedItem;
+    public MouseEvent getMouseEvent() {
+        return mouseEvent;
+    }
 
-    public RenderingContext(final int width, final int height,
-                            final RenderingContext oldContext) {
+    /**
+     * UI component that mouse is currently hovering over.
+     */
+    private MouseInteractionController currentObjectUnderMouseCursor;
+
+    /**
+     * Called when given object was detected under mouse cursor, while processing {@link #mouseEvent}.
+     * Because objects are rendered back to front. The last method caller will set the top-most object, if
+     * there are multiple objects under mouse cursor.
+     */
+    public void setCurrentObjectUnderMouseCursor(MouseInteractionController currentObjectUnderMouseCursor) {
+        this.currentObjectUnderMouseCursor = currentObjectUnderMouseCursor;
+    }
 
+    public RenderingContext(final int width, final int height) {
         this.width = width;
         this.height = height;
-
-        this.xCenter = width / 2;
-        this.yCenter = height / 2;
-
+        this.centerCoordinate = new Point2D(width / 2d, height / 2d);
         this.zoom = width / 3d;
 
         bufferedImage = new BufferedImage(width, height, bufferedImageType);
 
         final WritableRaster raster = bufferedImage.getRaster();
         final DataBufferByte dbi = (DataBufferByte) raster.getDataBuffer();
-        bytes = dbi.getData();
+        pixels = dbi.getData();
 
         graphics = (Graphics2D) bufferedImage.getGraphics();
+        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+    }
+
+    /**
+     * @return <code>true</code> if view update is needed as a consequence of this mouse event.
+     */
+    public boolean handlePossibleComponentMouseEvent() {
+        if (mouseEvent == null) return false;
 
-        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-                RenderingHints.VALUE_ANTIALIAS_ON);
+        boolean viewRepaintNeeded = false;
 
-        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
-                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+        if (objectPreviouslyUnderMouseCursor != currentObjectUnderMouseCursor) {
+            // Mouse cursor has just entered or left component.
+            viewRepaintNeeded = objectPreviouslyUnderMouseCursor != null && objectPreviouslyUnderMouseCursor.mouseExited();
+            viewRepaintNeeded |= currentObjectUnderMouseCursor != null && currentObjectUnderMouseCursor.mouseEntered();
+            objectPreviouslyUnderMouseCursor = currentObjectUnderMouseCursor;
+        }
 
-        if (oldContext != null) {
-            mouseClick = oldContext.mouseClick;
-            clickedItem = oldContext.clickedItem;
+        if (mouseEvent.button != 0 && currentObjectUnderMouseCursor != null) {
+            // Mouse button was clicked on some component.
+            viewRepaintNeeded |= currentObjectUnderMouseCursor.mouseClicked(mouseEvent.button);
         }
+
+        return viewRepaintNeeded;
     }
 
 }