Updated copyright
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / gui / RenderingContext.java
index 3631547..0d16aa4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sixth 3D engine. Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * Sixth 3D engine. Copyright ©2012-2019, 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
@@ -9,7 +9,7 @@
 
 package eu.svjatoslav.sixth.e3d.gui;
 
-import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseClick;
+import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseEvent;
 import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseInteractionController;
 
 import java.awt.*;
@@ -20,37 +20,54 @@ 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;
-
     public final int xCenter;
     public final int yCenter;
-
     public final double zoom;
-
+    final BufferedImage bufferedImage;
     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.
      */
-    public boolean doRender = true; // TODO: make use of the variable
+    private MouseInteractionController currentMouseOverComponent;
 
-    public MouseClick mouseClick;
+    public void prepareForNewFrameRendering(){
+        mouseEvent = null;
+        objectUnderMouse = null;
+    }
+
+    /**
+     * Mouse click event that needs to be processed.
+     */
+    private  MouseEvent mouseEvent;
 
-    public MouseInteractionController clickedItem;
+    public void setMouseEvent(MouseEvent mouseEvent) {
+        this.mouseEvent = mouseEvent;
+    }
 
-    public RenderingContext(final int width, final int height,
-                            final RenderingContext oldContext) {
+    public MouseEvent getMouseEvent() {
+        return mouseEvent;
+    }
 
+    /**
+     * Item that user clicked on.
+     */
+    private MouseInteractionController objectUnderMouse;
+
+    /**
+     * 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 setObjectUnderMouse(MouseInteractionController objectUnderMouse) {
+        this.objectUnderMouse = objectUnderMouse;
+    }
+
+    public RenderingContext(final int width, final int height) {
         this.width = width;
         this.height = height;
 
@@ -63,20 +80,38 @@ public class RenderingContext {
 
         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);
+    }
 
-        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-                RenderingHints.VALUE_ANTIALIAS_ON);
-
-        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
-                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
-
-        if (oldContext != null) {
-            mouseClick = oldContext.mouseClick;
-            clickedItem = oldContext.clickedItem;
+    /**
+     * @return <code>true</code> if view repaint is needed.
+     */
+    public boolean handleDetectedComponentMouseEvents() {
+        if (objectUnderMouse != null) {
+            if (mouseEvent.button == 0) {
+                // mouse over
+                if (currentMouseOverComponent == null) {
+                    currentMouseOverComponent = objectUnderMouse;
+                    return currentMouseOverComponent.mouseEntered();
+                } else if (currentMouseOverComponent != objectUnderMouse) {
+                    boolean viewRepaintNeeded = currentMouseOverComponent.mouseExited();
+                    currentMouseOverComponent = objectUnderMouse;
+                    return viewRepaintNeeded | currentMouseOverComponent.mouseEntered();
+                }
+            } else {
+                // mouse click
+                return objectUnderMouse.mouseClicked();
+            }
+        } else if (currentMouseOverComponent != null) {
+            boolean viewRepaintNeeded = currentMouseOverComponent.mouseExited();
+            currentMouseOverComponent = null;
+            return viewRepaintNeeded;
         }
+        return false;
     }
 
 }