Fixed git clone URL
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / gui / RenderingContext.java
1 /*
2  * Sixth 3D engine. Author: Svjatoslav Agejenko.
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.sixth.e3d.gui;
6
7 import eu.svjatoslav.sixth.e3d.geometry.Point2D;
8 import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseEvent;
9 import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseInteractionController;
10
11 import java.awt.*;
12 import java.awt.image.BufferedImage;
13 import java.awt.image.DataBufferByte;
14 import java.awt.image.WritableRaster;
15
16 /**
17  * Rendering context that contains all the information that is needed to render the scene.
18  */
19
20 public class RenderingContext {
21
22     public static final int bufferedImageType = BufferedImage.TYPE_4BYTE_ABGR;
23
24     public final Graphics2D graphics;
25
26     /**
27      * Pixels of the rendering area.
28      * Each pixel is represented by 4 bytes: alpha, blue, green, red.
29      */
30     public final byte[] pixels;
31
32     /**
33      * Width of the rendering area in pixels.
34      */
35     public final int width;
36
37     /**
38      * Height of the rendering area in pixels.
39      */
40     public final int height;
41
42     /**
43      * Center of the screen in screen space (pixels).
44      * This is the point where (0,0) coordinate of the world space is rendered.
45      */
46     public final Point2D centerCoordinate;
47
48     /**
49      * Zoom factor. The bigger the value, the more zoomed in the view is.
50      */
51     public final double zoom;
52     final BufferedImage bufferedImage;
53     /**
54      * Number of frame that is currently being rendered.
55      * Every frame has its own number.
56      */
57     public int frameNumber = 0;
58
59     /**
60      * UI component that mouse is currently hovering over.
61      */
62     private MouseInteractionController objectPreviouslyUnderMouseCursor;
63     /**
64      * Mouse click event that needs to be processed.
65      * This event is processed only once per frame.
66      * If there are multiple objects under mouse cursor, the top-most object will receive the event.
67      * If there are no objects under mouse cursor, the event will be ignored.
68      * If there is no event, this field will be null.
69      * This field is set to null after the event is processed.
70      */
71     private MouseEvent mouseEvent;
72     /**
73      * UI component that mouse is currently hovering over.
74      */
75     private MouseInteractionController currentObjectUnderMouseCursor;
76
77     public RenderingContext(final int width, final int height) {
78         this.width = width;
79         this.height = height;
80         this.centerCoordinate = new Point2D(width / 2d, height / 2d);
81         this.zoom = width / 3d;
82
83         bufferedImage = new BufferedImage(width, height, bufferedImageType);
84
85         final WritableRaster raster = bufferedImage.getRaster();
86         final DataBufferByte dbi = (DataBufferByte) raster.getDataBuffer();
87         pixels = dbi.getData();
88
89         graphics = (Graphics2D) bufferedImage.getGraphics();
90         graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
91         graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
92     }
93
94     public void prepareForNewFrameRendering() {
95         mouseEvent = null;
96         currentObjectUnderMouseCursor = null;
97     }
98
99     public MouseEvent getMouseEvent() {
100         return mouseEvent;
101     }
102
103     public void setMouseEvent(MouseEvent mouseEvent) {
104         this.mouseEvent = mouseEvent;
105     }
106
107     /**
108      * Called when given object was detected under mouse cursor, while processing {@link #mouseEvent}.
109      * Because objects are rendered back to front. The last method caller will set the top-most object, if
110      * there are multiple objects under mouse cursor.
111      */
112     public void setCurrentObjectUnderMouseCursor(MouseInteractionController currentObjectUnderMouseCursor) {
113         this.currentObjectUnderMouseCursor = currentObjectUnderMouseCursor;
114     }
115
116     /**
117      * @return <code>true</code> if view update is needed as a consequence of this mouse event.
118      */
119     public boolean handlePossibleComponentMouseEvent() {
120         if (mouseEvent == null) return false;
121
122         boolean viewRepaintNeeded = false;
123
124         if (objectPreviouslyUnderMouseCursor != currentObjectUnderMouseCursor) {
125             // Mouse cursor has just entered or left component.
126             viewRepaintNeeded = objectPreviouslyUnderMouseCursor != null && objectPreviouslyUnderMouseCursor.mouseExited();
127             viewRepaintNeeded |= currentObjectUnderMouseCursor != null && currentObjectUnderMouseCursor.mouseEntered();
128             objectPreviouslyUnderMouseCursor = currentObjectUnderMouseCursor;
129         }
130
131         if (mouseEvent.button != 0 && currentObjectUnderMouseCursor != null) {
132             // Mouse button was clicked on some component.
133             viewRepaintNeeded |= currentObjectUnderMouseCursor.mouseClicked(mouseEvent.button);
134         }
135
136         return viewRepaintNeeded;
137     }
138
139 }