Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (c) 2005 by Scott Giese, Rodney Kinney, Brent Easton
- * Modified for the Warmahordes module by Malnorma Cxio.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License (LGPL) as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, copies are available
- * at http://www.opensource.org.
- */
- package cxio.malnorma;
- import java.awt.AlphaComposite;
- import java.awt.Color;
- import java.awt.Component;
- import java.awt.Composite;
- import java.awt.Frame;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.Point;
- import java.awt.Rectangle;
- import java.awt.Shape;
- import java.awt.Window;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.geom.AffineTransform;
- import java.awt.geom.Area;
- import java.awt.geom.Arc2D;
- import java.awt.geom.Ellipse2D;
- import java.beans.PropertyChangeEvent;
- import java.beans.PropertyChangeListener;
- import java.util.*;
- import javax.swing.Box;
- import javax.swing.BoxLayout;
- import javax.swing.JButton;
- import javax.swing.JLabel;
- import javax.swing.JPanel;
- import javax.swing.JSeparator;
- import javax.swing.JTextField;
- import javax.swing.KeyStroke;
- import javax.swing.SwingUtilities;
- import VASSAL.build.module.Map;
- import VASSAL.build.module.documentation.HelpFile;
- import VASSAL.build.module.map.MapShader;
- import VASSAL.build.module.map.boardPicker.Board;
- import VASSAL.build.module.map.boardPicker.board.GeometricGrid;
- import VASSAL.build.module.map.boardPicker.board.MapGrid;
- import VASSAL.command.ChangeTracker;
- import VASSAL.command.Command;
- import VASSAL.configure.BooleanConfigurer;
- import VASSAL.configure.ChooseComponentDialog;
- import VASSAL.configure.ColorConfigurer;
- import VASSAL.configure.IntConfigurer;
- import VASSAL.configure.NamedHotKeyConfigurer;
- import VASSAL.configure.StringConfigurer;
- import VASSAL.counters.Decorator;
- import VASSAL.counters.FreeRotator;
- import VASSAL.counters.GamePiece;
- import VASSAL.counters.KeyCommand;
- import VASSAL.counters.PieceEditor;
- import VASSAL.i18n.PieceI18nData;
- import VASSAL.i18n.Resources;
- import VASSAL.i18n.TranslatablePiece;
- import VASSAL.tools.NamedKeyStroke;
- import VASSAL.tools.SequenceEncoder;
- /**
- * @author Scott Giese sgiese@sprintmail.com
- *
- * Displays a transparency surrounding the GamePiece which represents the Area of Effect of the GamePiece
- */
- public class AreaOfEffect extends Decorator implements TranslatablePiece, MapShader.ShadedPiece {
- public static final String ID = "cxio.malnorma.AreaOfEffectMal;";
- protected static final Color defaultTransparencyColor = Color.GRAY;
- protected static final float defaultTransparencyLevel = 0.3F;
- protected static final int defaultRadius = 1;
- protected Color transparencyColor;
- protected List<Color> colorOptions = new ArrayList<Color>();
- protected float transparencyLevel;
- protected int radius;
- protected boolean alwaysActive;
- protected boolean active;
- protected String activateCommand;
- protected NamedKeyStroke activateKey;
- protected KeyCommand[] commands;
- protected String mapShaderName;
- protected MapShader shader;
- protected KeyCommand keyCommand;
- protected boolean fixedRadius = true;
- protected String radiusMarker = "";
- protected String description = "";
- protected String halfCircleMarker = "";
- public AreaOfEffect() {
- this(ID + ColorConfigurer.colorToString(defaultTransparencyColor), null);
- }
- public AreaOfEffect(String type, GamePiece inner) {
- mySetType(type);
- setInner(inner);
- colorOptions.add(null);
- colorOptions.add(new Color(255, 28, 45));
- colorOptions.add(new Color(28, 255, 102));
- colorOptions.add(new Color(20, 180, 255));
- colorOptions.add(new Color(255, 255, 100));
- }
- public String getDescription() {
- String d = "Area Of Effect [Mal]";
- if (description.length() > 0) {
- d += " - " + description;
- }
- return d;
- }
- public String myGetType() {
- final SequenceEncoder se = new SequenceEncoder(';');
- se.append(transparencyColor);
- se.append((int) (transparencyLevel * 100));
- se.append(radius);
- se.append(alwaysActive);
- se.append(activateCommand);
- se.append(activateKey);
- se.append(mapShaderName == null ? "" : mapShaderName);
- se.append(fixedRadius);
- se.append(radiusMarker);
- se.append(description);
- se.append(halfCircleMarker);
- return ID + se.getValue();
- }
- public void mySetType(String type) {
- final SequenceEncoder.Decoder st = new SequenceEncoder.Decoder(type, ';');
- st.nextToken(); // Discard ID
- transparencyColor = st.nextColor(defaultTransparencyColor);
- transparencyLevel = st.nextInt((int) (defaultTransparencyLevel * 100)) / 100.0F;
- radius = st.nextInt(defaultRadius);
- alwaysActive = st.nextBoolean(true);
- activateCommand = st.nextToken("Show Area");
- activateKey = st.nextNamedKeyStroke(null);
- keyCommand = new KeyCommand(activateCommand, activateKey, Decorator.getOutermost(this), this);
- mapShaderName = st.nextToken("");
- if (mapShaderName.length() == 0) {
- mapShaderName = null;
- }
- fixedRadius = st.nextBoolean(true);
- radiusMarker = st.nextToken("");
- description = st.nextToken("");
- halfCircleMarker = st.nextToken("");
- shader = null;
- commands = null;
- }
- // State does not change during the game
- public String myGetState() {
- return alwaysActive ? "" : String.valueOf(active);
- }
- // State does not change during the game
- public void mySetState(String newState) {
- if (!alwaysActive) {
- active = "true".equals(newState);
- }
- }
- public Rectangle boundingBox() {
- // TODO: Need the context of the parent Component, because the transparency is only drawn
- // on a Map.View object. Because this context is not known, the bounding box returned by
- // this method does not encompass the bounds of the transparency. The result of this is
- // that portions of the transparency will not be drawn after scrolling the Map window.
- return piece.boundingBox();
- }
- public Shape getShape() {
- return piece.getShape();
- }
- public String getName() {
- return piece.getName();
- }
- public void draw(Graphics g, int x, int y, Component obs, double zoom) {
- if ((alwaysActive || active) && mapShaderName == null && getRadius() > 0) {
- // The transparency is only drawn on a Map.View component. Only the
- // GamePiece is drawn within other windows (Counter Palette, etc.).
- if (obs instanceof Map.View && getMap() != null) {
- final Graphics2D g2d = (Graphics2D) g;
- final Color oldColor = g2d.getColor();
- int auraLevel = getAuraLayer();
- g2d.setColor(transparencyColor);
- if (auraLevel > 0 && auraLevel <= colorOptions.size()) {
- g2d.setColor(colorOptions.get(auraLevel));
- }
- final Composite oldComposite = g2d.getComposite();
- g2d.setComposite(AlphaComposite.getInstance(
- AlphaComposite.SRC_OVER, transparencyLevel));
- Area a = getArea();
- if (zoom != 1.0) {
- a = new Area(AffineTransform.getScaleInstance(zoom,zoom)
- .createTransformedShape(a));
- }
- g2d.fill(a);
- g2d.setColor(oldColor);
- g2d.setComposite(oldComposite);
- }
- }
- // Draw the GamePiece
- piece.draw(g, x, y, obs, zoom);
- }
- protected Area getArea() {
- Area a;
- final Map map = getMap();
- // Always draw the area centered on the piece's current position
- // (For instance, don't draw it at an offset if it's in an expanded stack)
- final Point mapPosition = getPosition();
- final int myRadius = getRadius();
- final Board board = map.findBoard(mapPosition);
- final MapGrid grid = board == null ? null : board.getGrid();
- if (grid instanceof GeometricGrid) {
- final GeometricGrid gGrid = (GeometricGrid) grid;
- final Rectangle boardBounds = board.bounds();
- final Point boardPosition = new Point(
- mapPosition.x-boardBounds.x, mapPosition.y-boardBounds.y);
- a = gGrid.getGridShape(boardPosition, myRadius); // In board co-ords
- final AffineTransform t = AffineTransform.getTranslateInstance(
- boardBounds.x, boardBounds.y); // Translate back to map co-ords
- final double mag = board.getMagnification();
- if (mag != 1.0) {
- t.translate(boardPosition.x, boardPosition.y);
- t.scale(mag, mag);
- t.translate(-boardPosition.x, -boardPosition.y);
- }
- a = a.createTransformedArea(t);
- }
- else {
- FreeRotator myRotation = (FreeRotator) Decorator.getDecorator(this, FreeRotator.class);
- double ringWidth = 10;
- double start = 0;
- if (myRotation != null) {
- start = myRotation.getCumulativeAngle();
- while (start < 0) start += 360;
- }
- double innerDiff = Math.toDegrees(Math.asin(ringWidth / myRadius));
- a = getHalfCircle() ?
- new Area(new Arc2D.Double(mapPosition.x - myRadius,
- mapPosition.y - myRadius,
- myRadius * 2,
- myRadius * 2, start, 180, Arc2D.CHORD)) :
- new Area(new Ellipse2D.Double(mapPosition.x - myRadius,
- mapPosition.y - myRadius,
- myRadius * 2,
- myRadius * 2));
- a.subtract(getHalfCircle() ?
- new Area(new Arc2D.Double(mapPosition.x - myRadius + ringWidth,
- mapPosition.y - myRadius + ringWidth,
- (myRadius - ringWidth) * 2,
- (myRadius - ringWidth) * 2,
- start + innerDiff, 180 - innerDiff * 2, Arc2D.CHORD))
- : new Area(new Ellipse2D.Double(mapPosition.x - myRadius + ringWidth,
- mapPosition.y - myRadius + ringWidth,
- (myRadius - ringWidth) * 2,
- (myRadius - ringWidth) * 2)));
- }
- return a;
- }
- protected int getRadius() {
- if (fixedRadius) {
- return radius;
- }
- else {
- final String r =
- (String) Decorator.getOutermost(this).getProperty(radiusMarker);
- try {
- return Integer.parseInt(r);
- }
- catch (NumberFormatException e) {
- reportDataError(this, Resources.getString("Error.non_number_error"), "radius["+radiusMarker+"]="+r, e);
- return 0;
- }
- }
- }
- protected int getAuraLayer() {
- final String r =
- (String) Decorator.getOutermost(this).getProperty("Aura Color");
- try {
- return Integer.parseInt(r);
- }
- catch (NumberFormatException e) {
- return 0;
- }
- }
- protected boolean getHalfCircle() {
- final String marker = (String) Decorator.getOutermost(this).getProperty(halfCircleMarker);
- int halfcircle = 0;
- try {
- halfcircle = Integer.parseInt(marker);
- } catch (NumberFormatException e) {
- // Just eat it - treat an error as 0
- }
- return halfcircle > 0;
- }
- // No hot-keys
- protected KeyCommand[] myGetKeyCommands() {
- if (commands == null) {
- if (alwaysActive || activateCommand.length() == 0) {
- commands = new KeyCommand[0];
- }
- else {
- commands = new KeyCommand[]{keyCommand};
- }
- }
- return commands;
- }
- // No hot-keys
- public Command myKeyEvent(KeyStroke stroke) {
- Command c = null;
- myGetKeyCommands();
- if (!alwaysActive
- && keyCommand.matches(stroke)) {
- final ChangeTracker t = new ChangeTracker(this);
- active = !active;
- c = t.getChangeCommand();
- }
- return c;
- }
- public HelpFile getHelpFile() {
- return HelpFile.getReferenceManualPage("AreaOfEffect.htm");
- }
- public PieceEditor getEditor() {
- return new TraitEditor(this);
- }
- public Area getArea(MapShader shader) {
- Area a = null;
- final MapShader.ShadedPiece shaded = (MapShader.ShadedPiece) Decorator.getDecorator(piece,MapShader.ShadedPiece.class);
- if (shaded != null) {
- a = shaded.getArea(shader);
- }
- if (alwaysActive || active) {
- if (shader.getConfigureName().equals(mapShaderName)) {
- Area myArea = getArea();
- if (a == null) {
- a = myArea;
- }
- else {
- a.add(myArea);
- }
- }
- }
- return a;
- }
- protected static class TraitEditor implements PieceEditor {
- protected JPanel panel;
- protected ColorConfigurer transparencyColorValue;
- protected IntConfigurer transparencyValue;
- protected IntConfigurer radiusValue;
- protected BooleanConfigurer alwaysActive;
- protected StringConfigurer activateCommand;
- protected NamedHotKeyConfigurer activateKey;
- protected BooleanConfigurer useMapShader;
- protected BooleanConfigurer fixedRadius;
- protected StringConfigurer radiusMarker;
- protected StringConfigurer descConfig;
- protected Box selectShader;
- protected String mapShaderId;
- protected StringConfigurer halfCircleMarker;
- protected TraitEditor(AreaOfEffect trait) {
- panel = new JPanel();
- panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
- panel.add(new JLabel("Contributed by Scott Giese (sgiese@sprintmail.com)", JLabel.CENTER));
- panel.add(new JSeparator());
- panel.add(new JLabel(" "));
- descConfig = new StringConfigurer(null, "Description: ", trait.description);
- panel.add(descConfig.getControls());
- useMapShader = new BooleanConfigurer(null, "Use Map Shading?", trait.mapShaderName != null);
- mapShaderId = trait.mapShaderName;
- panel.add(useMapShader.getControls());
- selectShader = Box.createHorizontalBox();
- panel.add(selectShader);
- final JLabel l = new JLabel("Map Shading: ");
- selectShader.add(l);
- final JTextField tf = new JTextField(12);
- tf.setEditable(false);
- selectShader.add(tf);
- tf.setText(trait.mapShaderName);
- final JButton b = new JButton("Select");
- selectShader.add(b);
- b.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- ChooseComponentDialog d = new ChooseComponentDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, panel), MapShader.class);
- d.setVisible(true);
- if (d.getTarget() != null) {
- mapShaderId = d.getTarget().getConfigureName();
- tf.setText(mapShaderId);
- }
- else {
- mapShaderId = null;
- tf.setText("");
- }
- }
- });
- transparencyColorValue = new ColorConfigurer(null, "Fill Color: ", trait.transparencyColor);
- panel.add(transparencyColorValue.getControls());
- transparencyValue = new IntConfigurer(null, "Opacity (%): ", (int) (trait.transparencyLevel * 100));
- panel.add(transparencyValue.getControls());
- fixedRadius = new BooleanConfigurer(null, "Fixed Radius?",
- Boolean.valueOf(trait.fixedRadius));
- fixedRadius.addPropertyChangeListener(new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent evt) {
- updateRangeVisibility();
- }
- });
- panel.add(fixedRadius.getControls());
- radiusValue = new IntConfigurer(null, "Radius: ", trait.radius);
- panel.add(radiusValue.getControls());
- radiusMarker = new StringConfigurer(null, "Radius Marker: ", trait.radiusMarker);
- panel.add(radiusMarker.getControls());
- alwaysActive = new BooleanConfigurer(null, "Always visible?", trait.alwaysActive ? Boolean.TRUE : Boolean.FALSE);
- activateCommand = new StringConfigurer(null, "Toggle visible command: ", trait.activateCommand);
- activateKey = new NamedHotKeyConfigurer(null, "Toggle visible keyboard shortcut: ", trait.activateKey);
- halfCircleMarker = new StringConfigurer(null, "Semicircle Marker: ", trait.halfCircleMarker);
- panel.add(halfCircleMarker.getControls());
- updateRangeVisibility();
- alwaysActive.addPropertyChangeListener(new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent evt) {
- updateCommandVisibility();
- }
- });
- updateCommandVisibility();
- useMapShader.addPropertyChangeListener(new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent evt) {
- updateFillVisibility();
- }
- });
- updateFillVisibility();
- panel.add(alwaysActive.getControls());
- panel.add(activateCommand.getControls());
- panel.add(activateKey.getControls());
- }
- protected void updateFillVisibility() {
- final boolean useShader = Boolean.TRUE.equals(useMapShader.getValue());
- transparencyColorValue.getControls().setVisible(!useShader);
- transparencyValue.getControls().setVisible(!useShader);
- selectShader.setVisible(useShader);
- repack();
- }
- protected void updateRangeVisibility() {
- final boolean fixedRange = fixedRadius.booleanValue().booleanValue();
- radiusValue.getControls().setVisible(fixedRange);
- radiusMarker.getControls().setVisible(!fixedRange);
- repack();
- }
- protected void updateCommandVisibility() {
- final boolean alwaysActiveSelected = Boolean.TRUE.equals(alwaysActive.getValue());
- activateCommand.getControls().setVisible(!alwaysActiveSelected);
- activateKey.getControls().setVisible(!alwaysActiveSelected);
- repack();
- }
- protected void repack() {
- final Window w = SwingUtilities.getWindowAncestor(alwaysActive.getControls());
- if (w != null) {
- w.pack();
- }
- }
- public Component getControls() {
- return panel;
- }
- public String getState() {
- return "false";
- }
- public String getType() {
- final boolean alwaysActiveSelected = Boolean.TRUE.equals(alwaysActive.getValue());
- final SequenceEncoder se = new SequenceEncoder(';');
- se.append(transparencyColorValue.getValueString());
- se.append(transparencyValue.getValueString());
- se.append(radiusValue.getValueString());
- se.append(alwaysActiveSelected);
- se.append(activateCommand.getValueString());
- se.append(activateKey.getValueString());
- if (Boolean.TRUE.equals(useMapShader.getValue()) && mapShaderId != null) {
- se.append(mapShaderId);
- }
- else {
- se.append("");
- }
- se.append(fixedRadius.getValueString());
- se.append(radiusMarker.getValueString());
- se.append(descConfig.getValueString());
- se.append(halfCircleMarker.getValueString());
- return AreaOfEffect.ID + se.getValue();
- }
- }
- public PieceI18nData getI18nData() {
- return getI18nData(activateCommand, getCommandDescription(description, "Toggle Visible command"));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement