com.ardor3d.input.MouseState.java Source code

Java tutorial

Introduction

Here is the source code for com.ardor3d.input.MouseState.java

Source

/**
 * Copyright (c) 2008-2012 Ardor Labs, Inc.
 *
 * This file is part of Ardor3D.
 *
 * Ardor3D is free software: you can redistribute it and/or modify it 
 * under the terms of its license which may be found in the accompanying
 * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
 */

package com.ardor3d.input;

import java.util.EnumMap;
import java.util.EnumSet;

import com.ardor3d.annotation.Immutable;
import com.google.common.collect.EnumMultiset;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import com.google.common.collect.ImmutableMultiset.Builder;

/**
 * Describes the mouse state at some point in time.
 */
@Immutable
public class MouseState {
    public static final MouseState NOTHING = new MouseState(0, 0, 0, 0, 0, null, null);
    public static long CLICK_TIME_MS = 500;

    private final int _x;
    private final int _y;
    private final int _dx;
    private final int _dy;
    private final int _dwheel;
    private final ImmutableMap<MouseButton, ButtonState> _buttonStates;
    private final ImmutableMultiset<MouseButton> _clickCounts;

    /**
     * Constructs a new MouseState instance.
     * 
     * @param x
     *            the mouse's x position
     * @param y
     *            the mouse's y position
     * @param dx
     *            the delta in the mouse's x position since the last update
     * @param dy
     *            the delta in the mouse's y position since the last update
     * @param dwheel
     *            the delta in the mouse's wheel movement since the last update
     * @param buttonStates
     *            the states of the various given buttons.
     * @param clicks
     *            the number of times each button has been clicked
     */
    public MouseState(final int x, final int y, final int dx, final int dy, final int dwheel,
            final EnumMap<MouseButton, ButtonState> buttonStates, final Multiset<MouseButton> clicks) {
        _x = x;
        _y = y;
        _dx = dx;
        _dy = dy;
        _dwheel = dwheel;
        if (buttonStates != null) {
            final com.google.common.collect.ImmutableMap.Builder<MouseButton, ButtonState> builder = ImmutableMap
                    .builder();
            _buttonStates = builder.putAll(buttonStates).build();
        } else {
            _buttonStates = ImmutableMap.of();
        }
        if (clicks != null) {
            final Builder<MouseButton> builder = ImmutableMultiset.builder();
            _clickCounts = builder.addAll(clicks).build();
        } else {
            _clickCounts = ImmutableMultiset.of();
        }
    }

    public int getX() {
        return _x;
    }

    public int getY() {
        return _y;
    }

    public int getDx() {
        return _dx;
    }

    public int getDy() {
        return _dy;
    }

    public int getDwheel() {
        return _dwheel;
    }

    /**
     * 
     * @param state
     *            the button state to look for
     * @return true if at least one mouse button is in the given button state.
     */
    public boolean hasButtonState(final ButtonState state) {
        return _buttonStates.containsValue(state);
    }

    /**
     * 
     * @param state
     *            the button to look for
     * @return true if the given mouse button is currently mapped to a state.
     */
    public boolean hasButtonState(final MouseButton button) {
        return _buttonStates.containsKey(button);
    }

    /**
     * Returns all the buttons' states. It could be easier for most classes to use the
     * {@link #getButtonState(MouseButton)} methods, and that also results in less object creation.
     * 
     * @return a defensive copy of the states of all the buttons at this point in time.
     */
    public EnumMap<MouseButton, ButtonState> getButtonStates() {
        return getButtonStates(null);
    }

    /**
     * Returns all the buttons' states. It could be easier for most classes to use the
     * {@link #getButtonState(MouseButton)} methods, and that also results in less object creation.
     * 
     * @param store
     *            a map to store the states in... any values in store are cleared first. If store is null, a new map is
     *            created.
     * @return a defensive copy of the states of all the buttons at this point in time.
     */
    public EnumMap<MouseButton, ButtonState> getButtonStates(final EnumMap<MouseButton, ButtonState> store) {
        EnumMap<MouseButton, ButtonState> rVal = store;
        if (store == null) {
            rVal = Maps.newEnumMap(MouseButton.class);
        }
        rVal.clear();
        rVal.putAll(_buttonStates);
        return rVal;
    }

    /**
     * Returns the current state for the supplied button, or UP if no state for that button is registered.
     * 
     * @param button
     *            the mouse button to check
     * @return the button's state, or {@link ButtonState#UP} if no button state registered.
     */
    public ButtonState getButtonState(final MouseButton button) {
        if (_buttonStates.containsKey(button)) {
            return _buttonStates.get(button);
        }

        return ButtonState.UP;
    }

    public EnumSet<MouseButton> getButtonsReleasedSince(final MouseState previous) {
        final EnumSet<MouseButton> result = EnumSet.noneOf(MouseButton.class);
        for (final MouseButton button : MouseButton.values()) {
            if (previous.getButtonState(button) == ButtonState.DOWN) {
                if (getButtonState(button) != ButtonState.DOWN) {
                    result.add(button);
                }
            }
        }

        return result;
    }

    public EnumSet<MouseButton> getButtonsPressedSince(final MouseState previous) {
        final EnumSet<MouseButton> result = EnumSet.noneOf(MouseButton.class);
        for (final MouseButton button : MouseButton.values()) {
            if (getButtonState(button) == ButtonState.DOWN) {
                if (previous.getButtonState(button) != ButtonState.DOWN) {
                    result.add(button);
                }
            }
        }

        return result;
    }

    /**
     * Returns all the buttons' states. It could be easier for most classes to use the
     * {@link #getClickCount(MouseButton)} method, and that also results in less object creation.
     * 
     * @return a defensive copy of the click counts of all the buttons at this point in time.
     */
    public Multiset<MouseButton> getClickCounts() {
        if (_clickCounts.isEmpty()) {
            return EnumMultiset.create(MouseButton.class);
        } else {
            return EnumMultiset.create(_clickCounts);
        }
    }

    public Multiset<MouseButton> getClickCounts(final EnumMultiset<MouseButton> store) {
        final EnumMultiset<MouseButton> rVal = store;
        if (store == null) {
            if (_clickCounts.isEmpty()) {
                return EnumMultiset.create(MouseButton.class);
            } else {
                return EnumMultiset.create(_clickCounts);
            }
        }
        rVal.clear();
        rVal.addAll(_clickCounts);
        return rVal;
    }

    /**
     * Returns the click count of a mouse button as of this frame. Click counts are non-zero only for frames when the
     * mouse button is released. A double-click sequence, for instance, could show up like this:
     * <nl>
     * <li>Frame 1, mouse button pressed - click count == 0</li>
     * <li>Frame 2, mouse button down - click count == 0</li>
     * <li>Frame 3, mouse button released - click count == 1</li>
     * <li>Frame 4, mouse button up - click count == 0</li>
     * <li>Frame 5, mouse button pressed - click count == 0</li>
     * <li>Frame 6, mouse button down - click count == 0</li>
     * <li>Frame 7, mouse button released - click count == 2</li>
     * </nl>
     * 
     * Whether or not a mouse press/release sequence counts as a click (or double-click) depends on the time passed
     * between them. See {@link #CLICK_TIME_MS}.
     * 
     * 
     * @param button
     *            the button to check for clicks
     * @return the click count in this frame
     */
    public int getClickCount(final MouseButton button) {
        return _clickCounts.count(button);
    }

    /**
     * Returns a new EnumSet of all buttons that were clicked this frame.
     * 
     * @return every mouse button whose click count this frame is > 0
     */
    public EnumSet<MouseButton> getButtonsClicked() {
        final EnumSet<MouseButton> result = EnumSet.noneOf(MouseButton.class);
        for (final MouseButton button : MouseButton.values()) {
            if (getClickCount(button) != 0) {
                result.add(button);
            }
        }

        return result;
    }

    @Override
    public String toString() {
        return "MouseState{" + "x=" + _x + ", y=" + _y + ", dx=" + _dx + ", dy=" + _dy + ", dwheel=" + _dwheel
                + ", buttonStates=" + _buttonStates.toString() + ", clickCounts=" + _clickCounts.toString() + '}';
    }
}