Skip to content

Instantly share code, notes, and snippets.

@Longor1996
Created May 25, 2014 18:17
Show Gist options
  • Save Longor1996/6a3f70c0cb125c4c8274 to your computer and use it in GitHub Desktop.
Save Longor1996/6a3f70c0cb125c4c8274 to your computer and use it in GitHub Desktop.
Testomatiko: Testing a special CanvasRenderer for Paint.JAVA.
/*
WARNING: This code is:
- NOT commented.
- NOT fully tested.
- NOT safe for instant usage.
- A bit messy.
Also note that there is no exception/error/problem-checking at all.
Use at your own caution.
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.TexturePaint;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Float;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.text.NumberFormat;
import javax.swing.JComponent;
/**
* Handles:
* - Handling of the Camera
* - Drawing of any given Image.
**/
@SuppressWarnings("serial")
public class PaintCanvas extends JComponent implements MouseListener, MouseMotionListener, MouseWheelListener, KeyListener
{
// MISC
final Mainframe mainframe;
final float maxDegreeOfRotation = 45F / 4F;
BufferedImage image;
// DEBUG
NumberFormat numberFormat;
// Camera
float cam_zoom;
float cam_rotation;
float cam_positionX;
float cam_positionY;
// Controls
boolean isSpacebarDown;
int mouseLastDragPosX;
int mouseLastDragPosY;
// Paint
BufferedImage backgroundImage;
TexturePaint backgroundPaint;
Rectangle2D backgroundRectangle;
public PaintCanvas(Mainframe mainframe)
{
this.mainframe = mainframe;
this.setMinimumSize(new Dimension(8,8));
this.setDoubleBuffered(true);
this.setFocusable(true);
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.addMouseWheelListener(this);
this.addKeyListener(this);
this.numberFormat = NumberFormat.getInstance();
{
this.numberFormat.setMaximumFractionDigits(4);
this.numberFormat.setMinimumFractionDigits(4);
this.numberFormat.setGroupingUsed(true);
this.numberFormat.setMinimumIntegerDigits(8);
this.numberFormat.setMaximumIntegerDigits(8);
}
{
this.backgroundImage = new BufferedImage(2,2, BufferedImage.TYPE_BYTE_GRAY);
this.backgroundImage.setRGB(0, 0, 0x111111);
this.backgroundImage.setRGB(1, 1, 0x111111);
this.backgroundImage.setRGB(0, 1, 0x555555);
this.backgroundImage.setRGB(1, 0, 0x555555);
}
this.cam_zoom = 1;
this.cam_rotation = 0;
this.cam_positionX = 0;
this.cam_positionY = 0;;
this.updateBackground();
this.isSpacebarDown = false;
this.mouseLastDragPosX = 0;
this.mouseLastDragPosY = 0;
try
{
// XXX: Replace the example image file here with any image file to test this JComponent.
BufferedImage testimage = javax.imageio.ImageIO.read(new java.io.File("vray-PhyCam-Test.png"));
this.setImage(testimage);
}
catch (java.io.IOException e)
{
e.printStackTrace();
}
}
public void setImage(BufferedImage image)
{
this.image = image;
this.cam_zoom = 1;
this.cam_rotation = 0;
this.cam_positionX = image.getWidth() / 2;
this.cam_positionY = image.getHeight() / 2;
this.updateBackground();
this.repaint();
}
public void setImageContent(int[] rawARGB)
{
int width = this.image.getWidth();
int height = this.image.getHeight();
int surface = width * height;
if(surface != rawARGB.length)
{
throw new RuntimeException("Given ARGB-array is not equal in surface area compared to current image. Unable to replace contents!");
}
this.image.setRGB(0, 0, width, height, rawARGB, 0, width);
// full update
this.updateBackground();
this.repaint();
}
@Override
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
// clear background
g2d.setColor(Color.BLACK);
g2d.setPaint(this.backgroundPaint);
g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
// rendering hints for image drawing
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform Tx = new AffineTransform();
Tx.translate(this.getWidth()/2, this.getHeight()/2);
Tx.scale(this.cam_zoom, this.cam_zoom);
Tx.rotate(this.cam_rotation);
Tx.translate(-this.cam_positionX, -this.cam_positionY);
g2d.transform(Tx);
g2d.drawImage(this.image, 0, 0, null);
// System.out.println("repainted canvas");
}
@Override
public void mouseClicked(MouseEvent e)
{
if((e.getClickCount() == 2) && (e.getButton() == MouseEvent.BUTTON2))
{
this.cam_zoom = 1;
this.cam_rotation = 0;
this.repaint();
}
}
@Override
public void mousePressed(MouseEvent e)
{
this.mouseLastDragPosX = e.getX();
this.mouseLastDragPosY = e.getY();
if(e.getButton() == MouseEvent.BUTTON1)
{
Point2D p = this.transformCanvasPointToImagePoint(e.getPoint());
int Cx = (int) p.getX();
int Cy = (int) p.getY();
for(int y = Cy-2; y < (Cy+2); y++)
{
for(int x = Cx-2; x < (Cx+2); x++)
{
this.image.setRGB(x,y, 0xFFFFFFFF);
}
}
this.repaint();
}
}
public final Point2D.Float transformCanvasPointToImagePoint(Point2D in)
{
AffineTransform Tx = new AffineTransform();
Tx.translate(this.getWidth()/2, this.getHeight()/2);
Tx.rotate(this.cam_rotation);
Tx.scale(this.cam_zoom, this.cam_zoom);
Tx.translate(-this.cam_positionX, -this.cam_positionY);
try
{
Tx.invert();
}
catch (NoninvertibleTransformException e1)
{
e1.printStackTrace();
}
return (Float) Tx.transform(in, null);
}
@Override
public void mouseReleased(MouseEvent e)
{
}
@Override
public void mouseEntered(MouseEvent e)
{
}
@Override
public void mouseExited(MouseEvent e)
{
}
@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
int ctrlMod = MouseWheelEvent.CTRL_MASK | MouseWheelEvent.CTRL_DOWN_MASK;
int modifier = e.getModifiers();
boolean ctrlDown = (modifier & ctrlMod) != 0;
if(ctrlDown)
{
int sign = e.getWheelRotation();
if(sign > 0)
{
this.cam_zoom_increase();
return;
}
if(sign < 0)
{
this.cam_zoom_decrease();
return;
}
}
}
@Override
public void mouseDragged(MouseEvent e)
{
int ctrlMod = MouseWheelEvent.CTRL_MASK | MouseWheelEvent.CTRL_DOWN_MASK;
int middleMouseMod = MouseEvent.BUTTON2_DOWN_MASK | MouseEvent.BUTTON2_MASK;
int modifier = e.getModifiers();
boolean ctrlDown = (modifier & ctrlMod) != 0;
boolean middleMouseDown = (modifier & middleMouseMod) != 0;
boolean returned = true;
if(ctrlDown && returned)
{
float mouseX = e.getX();
float mouseY = e.getY();
// screen center
mouseX -= this.getWidth()/2;
mouseY -= this.getHeight()/2;
float mouseLength = (float) Math.sqrt((mouseX*mouseX) + (mouseY*mouseY));
mouseX /= mouseLength;
mouseY /= mouseLength;
float rotation = (float) Math.atan2(mouseY, mouseX);
if(e.isShiftDown())
{
rotation = (float) Math.toDegrees(rotation);
rotation /= this.maxDegreeOfRotation;
rotation = Math.round(rotation);
rotation *= this.maxDegreeOfRotation;
rotation = (float) Math.toRadians(rotation);
}
this.cam_rotation = rotation;
this.repaint();
returned = false;
}
if(middleMouseDown && returned)
{
float dragX = e.getX() - this.mouseLastDragPosX;
float dragY = e.getY() - this.mouseLastDragPosY;
float ROT = -this.cam_rotation;
float new_dragX = (float) ((dragX * Math.cos(ROT)) - (dragY * Math.sin(ROT)));
float new_dragY = (float) ((dragX * Math.sin(ROT)) + (dragY * Math.cos(ROT)));
dragX = new_dragX;
dragY = new_dragY;
this.cam_positionX -= dragX / this.cam_zoom;
this.cam_positionY -= dragY / this.cam_zoom;
if(this.cam_positionX < 0) {
this.cam_positionX = 0;
}
if(this.cam_positionY < 0) {
this.cam_positionY = 0;
}
if(this.cam_positionX > this.image.getWidth()) {
this.cam_positionX = this.image.getWidth();
}
if(this.cam_positionY > this.image.getHeight()) {
this.cam_positionY = this.image.getHeight();
}
this.updateBackground();
this.repaint();
returned = false;
}
this.mouseLastDragPosX = e.getX();
this.mouseLastDragPosY = e.getY();
}
@Override
public void mouseMoved(MouseEvent e)
{
}
private void cam_zoom_decrease()
{
float scale = this.cam_zoom;
if(scale > 1)
{
scale = (int) scale - 1;
}
else if(scale > (1 / 10f))
{
scale = scale - (1 / 10f);
}
this.setScale(scale);
}
private void cam_zoom_increase()
{
float scale = this.cam_zoom;
if(scale < 1)
{
scale = scale + (1 / 10f);
}
else if(scale < 64)
{
scale = (int) scale + 1;
}
this.setScale(scale);
}
private void setScale(float scale)
{
this.cam_zoom = scale;
this.updateBackground();
this.repaint();
}
private void updateBackground()
{
this.backgroundRectangle = new Rectangle2D.Float(-this.cam_positionX, -this.cam_positionY, 32f * this.cam_zoom, 32f * this.cam_zoom);
this.backgroundPaint = new TexturePaint(this.backgroundImage, this.backgroundRectangle);
}
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
int key = e.getKeyCode();
if(key == KeyEvent.VK_SPACE)
{
this.isSpacebarDown = true;
}
}
@Override
public void keyReleased(KeyEvent e)
{
int key = e.getKeyCode();
if(key == KeyEvent.VK_SPACE)
{
this.isSpacebarDown = false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment