From d6198ff3116cfecb5e8f6d1987c31230047c6e56 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 1 Dec 2019 15:20:15 -0500 Subject: [PATCH] camera plugin: add option to rotate camera with right click The camera rotation only takes effect when there are no menu entries. This also adds an option to make the middle button then open the menu. Co-authored-by: Wynadorn --- .../main/java/net/runelite/api/VarPlayer.java | 7 +- .../client/plugins/camera/CameraConfig.java | 32 +++ .../client/plugins/camera/CameraPlugin.java | 195 +++++++++++++++++- 3 files changed, 228 insertions(+), 6 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java index c4d5cb4fdf..3c6c616599 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java +++ b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java @@ -171,7 +171,12 @@ public enum VarPlayer MUSIC_VOLUME(168), SOUND_EFFECT_VOLUME(169), - AREA_EFFECT_VOLUME(872); + AREA_EFFECT_VOLUME(872), + + /** + * 0 = 2 buttons, 1 = 1 button + */ + MOUSE_BUTTONS(170); private final int id; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraConfig.java index 59d1d33466..c7856d938b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraConfig.java @@ -115,4 +115,36 @@ public interface CameraConfig extends Config return 25; } + @ConfigItem( + keyName = "rightClickMovesCamera", + name = "Right click moves camera", + description = "Remaps right click to middle mouse click if there are no menu options", + position = 7 + ) + default boolean rightClickMovesCamera() + { + return false; + } + + @ConfigItem( + keyName = "ignoreExamine", + name = "Ignore Examine", + description = "Ignore the Examine menu entry", + position = 8 + ) + default boolean ignoreExamine() + { + return false; + } + + @ConfigItem( + keyName = "middleClickMenu", + name = "Middle-button opens menu", + description = "Middle-mouse button always opens the menu", + position = 9 + ) + default boolean middleClickMenu() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java index 5f42b19321..044798c07a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/camera/CameraPlugin.java @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 Abex * Copyright (c) 2018, Adam + * Copyright (c) 2019, Wynadorn * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,33 +27,48 @@ package net.runelite.client.plugins.camera; import com.google.common.primitives.Ints; -import com.google.inject.Inject; import com.google.inject.Provides; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import javax.inject.Inject; +import javax.swing.SwingUtilities; import net.runelite.api.Client; +import net.runelite.api.MenuAction; +import net.runelite.api.MenuEntry; import net.runelite.api.ScriptID; -import net.runelite.client.events.ConfigChanged; +import net.runelite.api.VarPlayer; +import net.runelite.api.events.ClientTick; import net.runelite.api.events.FocusChanged; import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.input.KeyListener; import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseListener; +import net.runelite.client.input.MouseManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @PluginDescriptor( name = "Camera", - description = "Expand zoom limit and/or enable vertical camera", - tags = {"zoom", "limit", "vertical"}, + description = "Expands zoom limit, provides vertical camera, and remaps mouse input keys", + tags = {"zoom", "limit", "vertical", "click", "mouse"}, enabledByDefault = false ) -public class CameraPlugin extends Plugin implements KeyListener +public class CameraPlugin extends Plugin implements KeyListener, MouseListener { private static final int DEFAULT_ZOOM_INCREMENT = 25; private boolean controlDown; + // flags used to store the mousedown states + private boolean rightClick; + private boolean middleClick; + /** + * Whether or not the current menu has any non-ignored menu entries + */ + private boolean menuHasEntries; @Inject private Client client; @@ -66,6 +82,9 @@ public class CameraPlugin extends Plugin implements KeyListener @Inject private KeyManager keyManager; + @Inject + private MouseManager mouseManager; + @Provides CameraConfig getConfig(ConfigManager configManager) { @@ -148,8 +167,12 @@ public class CameraPlugin extends Plugin implements KeyListener @Override protected void startUp() { + rightClick = false; + middleClick = false; + menuHasEntries = false; client.setCameraPitchRelaxerEnabled(config.relaxCameraPitch()); keyManager.registerKeyListener(this); + mouseManager.registerMouseListener(this); } @Override @@ -157,6 +180,7 @@ public class CameraPlugin extends Plugin implements KeyListener { client.setCameraPitchRelaxerEnabled(false); keyManager.unregisterKeyListener(this); + mouseManager.unregisterMouseListener(this); controlDown = false; } @@ -194,4 +218,165 @@ public class CameraPlugin extends Plugin implements KeyListener } } } + + /** + * Checks if the menu has any non-ignored entries + */ + private boolean hasMenuEntries(MenuEntry[] menuEntries) + { + for (MenuEntry menuEntry : menuEntries) + { + MenuAction action = MenuAction.of(menuEntry.getType()); + switch (action) + { + case CANCEL: + case WALK: + break; + case EXAMINE_OBJECT: + case EXAMINE_NPC: + case EXAMINE_ITEM_GROUND: + case EXAMINE_ITEM: + case EXAMINE_ITEM_BANK_EQ: + if (config.ignoreExamine()) + { + break; + } + default: + return true; + } + } + return false; + } + + /** + * Checks if the menu has any options, because menu entries are built each + * tick and the MouseListener runs on the awt thread + */ + @Subscribe + public void onClientTick(ClientTick event) + { + menuHasEntries = hasMenuEntries(client.getMenuEntries()); + } + + /** + * The event that is triggered when a mouse button is pressed + * In this method the right click is changed to a middle-click to enable rotating the camera + *

+ * This method also provides the config option to enable the middle-mouse button to always open the right click menu + */ + @Override + public MouseEvent mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isRightMouseButton(mouseEvent) && config.rightClickMovesCamera()) + { + boolean oneButton = client.getVar(VarPlayer.MOUSE_BUTTONS) == 1; + // Only move the camera if there is nothing at the menu, or if + // in one-button mode. In one-button mode, left and right click always do the same thing, + // so always treat it as the menu is empty + if (!menuHasEntries || oneButton) + { + // Set the rightClick flag to true so we can release the button in mouseReleased() later + rightClick = true; + // Change the mousePressed() MouseEvent to the middle mouse button + mouseEvent = new MouseEvent((java.awt.Component) mouseEvent.getSource(), + mouseEvent.getID(), + mouseEvent.getWhen(), + mouseEvent.getModifiersEx(), + mouseEvent.getX(), + mouseEvent.getY(), + mouseEvent.getClickCount(), + mouseEvent.isPopupTrigger(), + MouseEvent.BUTTON2); + } + } + else if (SwingUtilities.isMiddleMouseButton((mouseEvent)) && config.middleClickMenu()) + { + // Set the middleClick flag to true so we can release it later in mouseReleased() + middleClick = true; + // Chance the middle mouse button MouseEvent to a right-click + mouseEvent = new MouseEvent((java.awt.Component) mouseEvent.getSource(), + mouseEvent.getID(), + mouseEvent.getWhen(), + mouseEvent.getModifiersEx(), + mouseEvent.getX(), + mouseEvent.getY(), + mouseEvent.getClickCount(), + mouseEvent.isPopupTrigger(), + MouseEvent.BUTTON3); + } + return mouseEvent; + } + + /** + * Correct the MouseEvent to release the correct button + */ + @Override + public MouseEvent mouseReleased(MouseEvent mouseEvent) + { + if (rightClick) + { + rightClick = false; + // Change the MouseEvent to button 2 so the middle mouse button will be released + mouseEvent = new MouseEvent((java.awt.Component) mouseEvent.getSource(), + mouseEvent.getID(), + mouseEvent.getWhen(), + mouseEvent.getModifiersEx(), + mouseEvent.getX(), + mouseEvent.getY(), + mouseEvent.getClickCount(), + mouseEvent.isPopupTrigger(), + MouseEvent.BUTTON2); + + } + if (middleClick) + { + middleClick = false; + // Change the MouseEvent ot button 3 so the right mouse button will be released + mouseEvent = new MouseEvent((java.awt.Component) mouseEvent.getSource(), + mouseEvent.getID(), + mouseEvent.getWhen(), + mouseEvent.getModifiersEx(), + mouseEvent.getX(), + mouseEvent.getY(), + mouseEvent.getClickCount(), + mouseEvent.isPopupTrigger(), + MouseEvent.BUTTON3); + } + return mouseEvent; + } + + /* + * These methods are unused but required to be present in a MouseListener implementation + */ + // region Unused MouseListener methods + @Override + public MouseEvent mouseDragged(MouseEvent mouseEvent) + { + return mouseEvent; + } + + @Override + public MouseEvent mouseMoved(MouseEvent mouseEvent) + { + return mouseEvent; + } + + @Override + public MouseEvent mouseClicked(MouseEvent mouseEvent) + { + return mouseEvent; + } + + @Override + public MouseEvent mouseEntered(MouseEvent mouseEvent) + { + return mouseEvent; + } + + @Override + public MouseEvent mouseExited(MouseEvent mouseEvent) + { + return mouseEvent; + } + // endregion }