/* * Copyright (c) 2014 tabletoptool.com team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * rptools.com team - initial implementation * tabletoptool.com team - further development */ package com.t3.client.tool.drawing; import java.awt.Cursor; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import com.t3.client.ScreenPoint; import com.t3.client.T3Util; import com.t3.client.TabletopTool; import com.t3.client.tool.DefaultTool; import com.t3.client.tool.LayerSelectionDialog; import com.t3.client.tool.LayerSelectionDialog.LayerSelectionListener; import com.t3.client.ui.zone.ZoneOverlay; import com.t3.client.ui.zone.ZoneRenderer; import com.t3.model.Zone; import com.t3.model.Zone.Layer; import com.t3.model.ZonePoint; import com.t3.model.drawing.Drawable; import com.t3.model.drawing.Pen; import com.t3.swing.ColorPicker; import com.t3.swing.SwingUtil; import com.t3.util.guidreference.ZoneReference; /** * Tool for drawing freehand lines. */ public abstract class AbstractDrawingTool extends DefaultTool implements ZoneOverlay { private static final long serialVersionUID = 9121558405484986225L; private boolean isEraser; private boolean isSnapToGridSelected; private boolean isEraseSelected; private static LayerSelectionDialog layerSelectionDialog; private static Zone.Layer selectedLayer = Zone.Layer.TOKEN; static { layerSelectionDialog = new LayerSelectionDialog(new Zone.Layer[] { Zone.Layer.TOKEN, Zone.Layer.GM, Zone.Layer.OBJECT, Zone.Layer.BACKGROUND }, new LayerSelectionListener() { @Override public void layerSelected(Layer layer) { selectedLayer = layer; } }); } protected Rectangle createRect(ZonePoint originPoint, ZonePoint newPoint) { int x = Math.min(originPoint.x, newPoint.x); int y = Math.min(originPoint.y, newPoint.y); int w = Math.max(originPoint.x, newPoint.x) - x; int h = Math.max(originPoint.y, newPoint.y) - y; return new Rectangle(x, y, w, h); } protected AffineTransform getPaintTransform(ZoneRenderer renderer) { AffineTransform transform = new AffineTransform(); transform.translate(renderer.getViewOffsetX(), renderer.getViewOffsetY()); transform.scale(renderer.getScale(), renderer.getScale()); return transform; } protected void paintTransformed(Graphics2D g, ZoneRenderer renderer, Drawable drawing, Pen pen) { AffineTransform transform = getPaintTransform(renderer); AffineTransform oldTransform = g.getTransform(); g.transform(transform); drawing.draw(g, pen); g.setTransform(oldTransform); } @Override protected void attachTo(ZoneRenderer renderer) { if (TabletopTool.getPlayer().isGM()) { TabletopTool.getFrame().showControlPanel(TabletopTool.getFrame().getColorPicker(), layerSelectionDialog); } else { TabletopTool.getFrame().showControlPanel(TabletopTool.getFrame().getColorPicker()); } renderer.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); TabletopTool.getFrame().getColorPicker().setSnapSelected(isSnapToGridSelected); TabletopTool.getFrame().getColorPicker().setEraseSelected(isEraseSelected); super.attachTo(renderer); } @Override protected void detachFrom(ZoneRenderer renderer) { TabletopTool.getFrame().hideControlPanel(); renderer.setCursor(Cursor.getDefaultCursor()); isSnapToGridSelected = TabletopTool.getFrame().getColorPicker().isSnapSelected(); isEraseSelected = TabletopTool.getFrame().getColorPicker().isEraseSelected(); super.detachFrom(renderer); } protected void setIsEraser(boolean eraser) { isEraser = eraser; } protected boolean isEraser() { return isEraser; } protected boolean isBackgroundFill(MouseEvent e) { boolean defaultValue = TabletopTool.getFrame().getColorPicker().isFillBackgroundSelected(); return defaultValue; } protected boolean isEraser(MouseEvent e) { boolean defaultValue = TabletopTool.getFrame().getColorPicker().isEraseSelected(); if (SwingUtil.isShiftDown(e)) { // Invert from the color panel defaultValue = !defaultValue; } return defaultValue; } protected boolean isSnapToGrid(MouseEvent e) { boolean defaultValue = TabletopTool.getFrame().getColorPicker().isSnapSelected(); if (SwingUtil.isControlDown(e)) { // Invert from the color panel defaultValue = !defaultValue; } return defaultValue; } protected Pen getPen() { Pen pen = new Pen(TabletopTool.getFrame().getPen()); pen.setEraser(isEraser); ColorPicker picker = TabletopTool.getFrame().getColorPicker(); if (picker.isFillForegroundSelected()) { pen.setForegroundMode(Pen.MODE_SOLID); } else { pen.setForegroundMode(Pen.MODE_TRANSPARENT); } if (picker.isFillBackgroundSelected()) { pen.setBackgroundMode(Pen.MODE_SOLID); } else { pen.setBackgroundMode(Pen.MODE_TRANSPARENT); } return pen; } protected ZonePoint getPoint(MouseEvent e) { ScreenPoint sp = new ScreenPoint(e.getX(), e.getY()); ZonePoint zp = sp.convertToZoneRnd(renderer); if (isSnapToGrid(e)) { zp = renderer.getZone().getNearestVertex(zp); sp = ScreenPoint.fromZonePoint(renderer, zp); } return zp; } @Override public abstract void paintOverlay(ZoneRenderer renderer, Graphics2D g); /** * Render a drawable on a zone. This method consolidates all of the calls to the server in one place so that it is * easier to keep them in sync. * * @param zone * the zone where the <code>drawable</code> is being drawn. * @param pen * The pen used to draw. * @param drawable * What is being drawn. */ protected void completeDrawable(ZoneReference zone, Pen pen, Drawable drawable) { if (!hasPaint(pen)) { return; } drawable.setLayer(selectedLayer); // Send new textures T3Util.uploadTexture(pen.getPaint()); T3Util.uploadTexture(pen.getBackgroundPaint()); // Tell the local/server to render the drawable. TabletopTool.serverCommand().draw(zone.getId(), pen, drawable); // Allow it to be undone Zone z = TabletopTool.getFrame().getCurrentZoneRenderer().getZone(); z.addDrawable(pen, drawable); } private boolean hasPaint(Pen pen) { return pen.getForegroundMode() != Pen.MODE_TRANSPARENT || pen.getBackgroundMode() != Pen.MODE_TRANSPARENT; } }