diff --git a/.classpath b/.classpath
index fc2b6d2..49d75d3 100644
--- a/.classpath
+++ b/.classpath
@@ -12,5 +12,8 @@
+
+
+
diff --git a/.gitignore b/.gitignore
index 8f5d6dc..e11ffda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ Thumbs.db
/[Bb]uild/
/[Dd]ist/
/[Dd]oc/
+out/
# Ignore files created by posix people
*~
# Ignore vim swapfiles
diff --git a/assets/2001tray.png b/assets/2001tray.png
index d611a12..e10f3ec 100644
Binary files a/assets/2001tray.png and b/assets/2001tray.png differ
diff --git a/assets/gear.png b/assets/gear.png
new file mode 100644
index 0000000..c174dc1
Binary files /dev/null and b/assets/gear.png differ
diff --git a/assets/gear_gold.png b/assets/gear_gold.png
new file mode 100644
index 0000000..a7c2c94
Binary files /dev/null and b/assets/gear_gold.png differ
diff --git a/assets/icon-large.png b/assets/icon-large.png
index d997faa..5df58a0 100644
Binary files a/assets/icon-large.png and b/assets/icon-large.png differ
diff --git a/assets/icon.png b/assets/icon.png
new file mode 100644
index 0000000..e94e6fb
Binary files /dev/null and b/assets/icon.png differ
diff --git a/assets/icon_warn.png b/assets/icon_warn.png
new file mode 100644
index 0000000..1f03b50
Binary files /dev/null and b/assets/icon_warn.png differ
diff --git a/build.xml b/build.xml
index b7f358a..d65f456 100644
--- a/build.xml
+++ b/build.xml
@@ -103,6 +103,7 @@
+
diff --git a/lib/flatlaf-3.1.1.jar b/lib/flatlaf-3.1.1.jar
new file mode 100644
index 0000000..2b13cdd
Binary files /dev/null and b/lib/flatlaf-3.1.1.jar differ
diff --git a/lib/jna-5.13.0.jar b/lib/jna-5.13.0.jar
new file mode 100644
index 0000000..3d49c81
Binary files /dev/null and b/lib/jna-5.13.0.jar differ
diff --git a/lib/jna-platform-5.13.0.jar b/lib/jna-platform-5.13.0.jar
new file mode 100644
index 0000000..816a567
Binary files /dev/null and b/lib/jna-platform-5.13.0.jar differ
diff --git a/src/Client/ConfigWindow.java b/src/Client/ConfigWindow.java
index a536785..ec2d0b6 100644
--- a/src/Client/ConfigWindow.java
+++ b/src/Client/ConfigWindow.java
@@ -18,17 +18,24 @@
*/
package Client;
+import static Client.Util.isDarkThemeFlatLAF;
+import static Client.Util.isUsingFlatLAFTheme;
+import static Client.Util.osScaleDiv;
+import static Client.Util.osScaleMul;
+
import Client.KeybindSet.KeyModifier;
import Game.Camera;
import Game.Client;
import Game.Game;
import Game.KeyboardHandler;
+import Game.Renderer;
+import com.formdev.flatlaf.ui.FlatRoundBorder;
+import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
-import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
@@ -38,14 +45,23 @@
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.SystemTray;
+import java.awt.Toolkit;
+import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@@ -59,6 +75,7 @@
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
+import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
@@ -74,13 +91,11 @@
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-import javax.swing.UIManager.LookAndFeelInfo;
-import javax.swing.UnsupportedLookAndFeelException;
-import javax.swing.border.EmptyBorder;
+import javax.swing.ToolTipManager;
+import javax.swing.border.LineBorder;
+import javax.swing.border.MatteBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
-import javax.swing.plaf.nimbus.NimbusLookAndFeel;
/**
* GUI designed for the RSCPlus client that manages configuration options and keybind values from
@@ -123,6 +138,15 @@ public class ConfigWindow {
ButtonFocusListener focusListener = new ButtonFocusListener();
JTabbedPane tabbedPane;
+ // Tooltip-related components
+ private final AWTEventListener eventQueueListener;
+ private final String toolTipInitText =
+ "Click here to display additional information about settings";
+ private boolean isListeningForEventQueue = false;
+ private JPanel toolTipPanel;
+ private JLabel toolTipTextLabel;
+ private String toolTipTextString;
+
/*
* JComponent variables which hold configuration data
*/
@@ -131,6 +155,15 @@ public class ConfigWindow {
private JCheckBox generalPanelClientSizeCheckbox;
private JSpinner generalPanelClientSizeXSpinner;
private JSpinner generalPanelClientSizeYSpinner;
+ private SpinnerNumberModel spinnerWinXModel;
+ private SpinnerNumberModel spinnerWinYModel;
+ private JCheckBox generalPanelScaleWindowCheckbox;
+ private JRadioButton generalPanelIntegerScalingFocusButton;
+ private JSpinner generalPanelIntegerScalingSpinner;
+ private JRadioButton generalPanelBilinearScalingFocusButton;
+ private JSpinner generalPanelBilinearScalingSpinner;
+ private JRadioButton generalPanelBicubicScalingFocusButton;
+ private JSpinner generalPanelBicubicScalingSpinner;
private JCheckBox generalPanelCheckUpdates;
private JCheckBox generalPanelWelcomeEnabled;
// private JCheckBox generalPanelChatHistoryCheckbox;
@@ -159,12 +192,16 @@ public class ConfigWindow {
private JCheckBox generalPanelColoredTextCheckbox;
private JSlider generalPanelFoVSlider;
private JCheckBox generalPanelCustomCursorCheckbox;
+ private JCheckBox generalPanelShiftScrollCameraRotationCheckbox;
+ private JSlider generalPanelTrackpadRotationSlider;
private JSlider generalPanelViewDistanceSlider;
private JCheckBox generalPanelLimitFPSCheckbox;
private JSpinner generalPanelLimitFPSSpinner;
private JCheckBox generalPanelAutoScreenshotCheckbox;
private JCheckBox generalPanelPatchGenderCheckbox;
private JCheckBox generalPanelPatchHbar512LastPixelCheckbox;
+ private JCheckBox generalPanelUseDarkModeCheckbox;
+ private JCheckBox generalPanelUseNimbusThemeCheckbox;
private JCheckBox generalPanelDebugModeCheckbox;
private JCheckBox generalPanelExceptionHandlerCheckbox;
private JLabel generalPanelNamePatchModeDesc;
@@ -206,7 +243,6 @@ public class ConfigWindow {
private JCheckBox notificationPanelPMNotifsCheckbox;
private JCheckBox notificationPanelTradeNotifsCheckbox;
private JCheckBox notificationPanelUnderAttackNotifsCheckbox;
- private JCheckBox notificationPanelLogoutNotifsCheckbox;
private JCheckBox notificationPanelLowHPNotifsCheckbox;
private JSpinner notificationPanelLowHPNotifsSpinner;
private JCheckBox notificationPanelHighlightedItemTimerCheckbox;
@@ -250,26 +286,8 @@ public class ConfigWindow {
private JPanel worldListPanel = new JPanel();
public ConfigWindow() {
- try {
- // Set System L&F as a fall-back option.
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
- if ("Nimbus".equals(info.getName())) {
- UIManager.setLookAndFeel(info.getClassName());
- NimbusLookAndFeel laf = (NimbusLookAndFeel) UIManager.getLookAndFeel();
- laf.getDefaults().put("defaultFont", new Font(Font.SANS_SERIF, Font.PLAIN, 11));
- break;
- }
- }
- } catch (UnsupportedLookAndFeelException e) {
- Logger.Error("Unable to set L&F: Unsupported look and feel");
- } catch (ClassNotFoundException e) {
- Logger.Error("Unable to set L&F: Class not found");
- } catch (InstantiationException e) {
- Logger.Error("Unable to set L&F: Class object cannot be instantiated");
- } catch (IllegalAccessException e) {
- Logger.Error("Unable to set L&F: Illegal access exception");
- }
+ Util.setUITheme();
+ eventQueueListener = createConfigWindowEventQueueListener();
initialize();
}
@@ -279,9 +297,23 @@ public void showConfigWindow() {
}
public void hideConfigWindow() {
+ resetToolTipListener();
+
frame.setVisible(false);
}
+ public void toggleConfigWindow() {
+ if (this.isShown()) {
+ this.hideConfigWindow();
+ } else {
+ this.showConfigWindow();
+ }
+ }
+
+ public boolean isShown() {
+ return frame.isVisible();
+ }
+
/** Initialize the contents of the frame. */
private void initialize() {
Logger.Info("Creating configuration window");
@@ -307,18 +339,47 @@ public void run() {
private void runInit() {
frame = new JFrame();
frame.setTitle("Settings");
- frame.setBounds(100, 100, 800, 650);
+ frame.setBounds(osScaleDiv(100), osScaleDiv(100), osScaleMul(800), osScaleMul(650));
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout(0, 0));
- URL iconURL = Launcher.getResource("/assets/RSCX.logo.png");
+ URL iconURL = Launcher.getResource("/assets/icon.png");
if (iconURL != null) {
ImageIcon icon = new ImageIcon(iconURL);
frame.setIconImage(icon.getImage());
}
+ frame.addWindowListener(
+ new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ resetToolTipListener();
+ super.windowClosed(e);
+ }
+ });
// Container declarations
/** The tabbed pane holding the five configuration tabs */
tabbedPane = new JTabbedPane();
+ if (isUsingFlatLAFTheme()) {
+ tabbedPane.putClientProperty("JTabbedPane.tabType", "card");
+ }
+ tabbedPane.addMouseListener(
+ new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ super.mouseClicked(e);
+ if (isListeningForEventQueue) {
+ toolTipTextString = "Waiting for mouse hover...";
+ } else {
+ toolTipTextString = toolTipInitText;
+ }
+ toolTipTextLabel.setText(toolTipTextString);
+ }
+ });
+
+ /* The JPanel containing the tooltip text components */
+ toolTipPanel = new JPanel();
+ resetToolTipBarPanelColors();
+
/**
* The JPanel containing the OK, Cancel, Apply, and Restore Defaults buttons at the bottom of
* the window
@@ -334,22 +395,68 @@ private void runInit() {
JScrollPane worldListScrollPane = new JScrollPane();
JScrollPane authorsScrollPane = new JScrollPane();
+ if (isUsingFlatLAFTheme()) {
+ Color navigationPanelBackgroundColor = null;
+
+ if (isDarkThemeFlatLAF()) {
+ navigationPanelBackgroundColor = new Color(60, 63, 65);
+ } else if (Util.isLightThemeFlatLAF()) {
+ navigationPanelBackgroundColor = new Color(225, 225, 225);
+ }
+
+ navigationPanel.setBackground(navigationPanelBackgroundColor);
+
+ Color scrollPaneBorderColor = null;
+
+ if (isDarkThemeFlatLAF()) {
+ scrollPaneBorderColor = new Color(82, 86, 87);
+ } else if (Util.isLightThemeFlatLAF()) {
+ scrollPaneBorderColor = new Color(194, 194, 194);
+ }
+
+ MatteBorder scrollPaneBorder =
+ BorderFactory.createMatteBorder(
+ 0, osScaleMul(1), osScaleMul(1), osScaleMul(1), scrollPaneBorderColor);
+
+ presetsScrollPane.setBorder(scrollPaneBorder);
+ generalScrollPane.setBorder(scrollPaneBorder);
+ overlayScrollPane.setBorder(scrollPaneBorder);
+ notificationScrollPane.setBorder(scrollPaneBorder);
+ streamingScrollPane.setBorder(scrollPaneBorder);
+ keybindScrollPane.setBorder(scrollPaneBorder);
+ worldListScrollPane.setBorder(scrollPaneBorder);
+ authorsScrollPane.setBorder(scrollPaneBorder);
+ }
+
JPanel presetsPanel = new JPanel();
+ presetsPanel.setName("presets");
JPanel generalPanel = new JPanel();
+ generalPanel.setName("general");
JPanel overlayPanel = new JPanel();
+ overlayPanel.setName("overlays");
JPanel notificationPanel = new JPanel();
+ notificationPanel.setName("notifications");
JPanel streamingPanel = new JPanel();
+ streamingPanel.setName("streaming_privacy");
JPanel keybindPanel = new JPanel();
+ keybindPanel.setName("keybinds");
worldListPanel = new JPanel();
+ worldListPanel.setName("world_list");
JPanel authorsPanel = new JPanel();
+ authorsPanel.setName("authors");
frame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
- frame.getContentPane().add(navigationPanel, BorderLayout.PAGE_END);
+
+ JPanel pageEndPanel = new JPanel();
+ pageEndPanel.setLayout(new BoxLayout(pageEndPanel, BoxLayout.Y_AXIS));
+ pageEndPanel.add(toolTipPanel);
+ pageEndPanel.add(navigationPanel);
+ frame.getContentPane().add(pageEndPanel, BorderLayout.PAGE_END);
tabbedPane.addTab("Presets", null, presetsScrollPane, null);
tabbedPane.addTab("General", null, generalScrollPane, null);
tabbedPane.addTab("Overlays", null, overlayScrollPane, null);
- // tabbedPane.addTab("Notifications", null, notificationScrollPane, null);
+ tabbedPane.addTab("Notifications", null, notificationScrollPane, null);
tabbedPane.addTab("Streaming & Privacy", null, streamingScrollPane, null);
tabbedPane.addTab("Keybinds", null, keybindScrollPane, null);
tabbedPane.addTab("World List", null, worldListScrollPane, null);
@@ -365,24 +472,80 @@ private void runInit() {
authorsScrollPane.setViewportView(authorsPanel);
// Adding padding for aesthetics
- navigationPanel.setBorder(BorderFactory.createEmptyBorder(7, 10, 10, 10));
- presetsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
- generalPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
- overlayPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
- notificationPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
- streamingPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
- keybindPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
- worldListPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
- authorsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
-
- setScrollSpeed(presetsScrollPane, 20, 15);
- setScrollSpeed(generalScrollPane, 20, 15);
- setScrollSpeed(overlayScrollPane, 20, 15);
- setScrollSpeed(notificationScrollPane, 20, 15);
- setScrollSpeed(streamingScrollPane, 20, 15);
- setScrollSpeed(keybindScrollPane, 20, 15);
- setScrollSpeed(worldListScrollPane, 20, 15);
- setScrollSpeed(authorsScrollPane, 20, 15);
+ int border10 = osScaleMul(10);
+ if (Util.isUsingFlatLAFTheme()) {
+ Color borderColor = isDarkThemeFlatLAF() ? new Color(82, 86, 87) : new Color(194, 194, 194);
+ toolTipPanel.setBorder(
+ BorderFactory.createMatteBorder(
+ 0, osScaleMul(1), osScaleMul(1), osScaleMul(1), borderColor));
+ } else {
+ toolTipPanel.setBorder(
+ BorderFactory.createCompoundBorder(
+ BorderFactory.createEmptyBorder(0, osScaleMul(2), 0, osScaleMul(2)),
+ BorderFactory.createLineBorder(new Color(146, 151, 161))));
+ }
+ navigationPanel.setBorder(
+ BorderFactory.createEmptyBorder(osScaleMul(7), border10, border10, border10));
+ presetsPanel.setBorder(BorderFactory.createEmptyBorder(border10, border10, border10, border10));
+ generalPanel.setBorder(BorderFactory.createEmptyBorder(border10, border10, border10, border10));
+ overlayPanel.setBorder(BorderFactory.createEmptyBorder(border10, border10, border10, border10));
+ notificationPanel.setBorder(
+ BorderFactory.createEmptyBorder(border10, border10, border10, border10));
+ streamingPanel.setBorder(
+ BorderFactory.createEmptyBorder(border10, border10, border10, border10));
+ keybindPanel.setBorder(BorderFactory.createEmptyBorder(border10, border10, border10, border10));
+ worldListPanel.setBorder(
+ BorderFactory.createEmptyBorder(border10, border10, border10, border10));
+ authorsPanel.setBorder(BorderFactory.createEmptyBorder(border10, border10, border10, border10));
+
+ int verticalSpeed = osScaleMul(20);
+ int horizontalSpeed = osScaleMul(15);
+
+ setScrollSpeed(presetsScrollPane, verticalSpeed, horizontalSpeed);
+ setScrollSpeed(generalScrollPane, verticalSpeed, horizontalSpeed);
+ setScrollSpeed(overlayScrollPane, verticalSpeed, horizontalSpeed);
+ setScrollSpeed(notificationScrollPane, verticalSpeed, horizontalSpeed);
+ setScrollSpeed(streamingScrollPane, verticalSpeed, horizontalSpeed);
+ setScrollSpeed(keybindScrollPane, verticalSpeed, horizontalSpeed);
+ setScrollSpeed(worldListScrollPane, verticalSpeed, horizontalSpeed);
+ setScrollSpeed(authorsScrollPane, verticalSpeed, horizontalSpeed);
+
+ /*
+ Tooltip panel
+ */
+ toolTipPanel.setLayout(new BoxLayout(toolTipPanel, BoxLayout.X_AXIS));
+ toolTipTextLabel = new JLabel(toolTipInitText);
+ toolTipTextLabel.setBorder(
+ BorderFactory.createEmptyBorder(osScaleMul(2), border10, osScaleMul(2), border10));
+ toolTipTextLabel.setText(toolTipInitText);
+ toolTipTextLabel.setMinimumSize(osScaleMul(new Dimension(100, 28)));
+ toolTipTextLabel.setMaximumSize(new Dimension(Short.MAX_VALUE, osScaleMul(28)));
+ toolTipTextLabel.setAlignmentY(0.75f);
+ toolTipPanel.add(toolTipTextLabel);
+
+ toolTipPanel.addMouseListener(
+ new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ if (isListeningForEventQueue) {
+ resetToolTipBarPanelColors();
+ toolTipTextLabel.setText(toolTipInitText);
+ removeConfigWindowEventQueueListener();
+ } else {
+ // Uses theme tooltip colors
+ if (Util.isDarkThemeFlatLAF()) {
+ toolTipPanel.setBackground(new Color(21, 23, 24));
+ } else if (Util.isLightThemeFlatLAF()) {
+ toolTipPanel.setBackground(new Color(250, 250, 250));
+ } else {
+ toolTipPanel.setBackground(new Color(242, 242, 189));
+ }
+ toolTipTextString = "Waiting for mouse hover...";
+ toolTipTextLabel.setText(toolTipTextString);
+ addConfigWindowEventQueueListener();
+ }
+ }
+ });
/*
* Navigation buttons
@@ -390,86 +553,116 @@ private void runInit() {
navigationPanel.setLayout(new BoxLayout(navigationPanel, BoxLayout.X_AXIS));
- addButton("OK", navigationPanel, Component.LEFT_ALIGNMENT)
- .addActionListener(
- new ActionListener() {
+ JButton okButton = addButton("OK", navigationPanel, Component.LEFT_ALIGNMENT);
+ if (isDarkThemeFlatLAF()) {
+ okButton.setBackground(new Color(42, 46, 48));
+ }
+ okButton.addActionListener(
+ new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- Launcher.getConfigWindow().saveSettings();
- Launcher.getConfigWindow().hideConfigWindow();
- }
- });
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Launcher.getConfigWindow().applySettings();
+ Launcher.getConfigWindow().hideConfigWindow();
+ }
+ });
- addButton("Cancel", navigationPanel, Component.LEFT_ALIGNMENT)
- .addActionListener(
- new ActionListener() {
+ if (isUsingFlatLAFTheme()) {
+ navigationPanel.add(Box.createRigidArea(osScaleMul(new Dimension(4, 0))));
+ }
- @Override
- public void actionPerformed(ActionEvent e) {
- Launcher.getConfigWindow().applySettings();
- Launcher.getConfigWindow().hideConfigWindow();
- }
- });
+ JButton cancelButton = addButton("Cancel", navigationPanel, Component.LEFT_ALIGNMENT);
- addButton("Apply", navigationPanel, Component.LEFT_ALIGNMENT)
- .addActionListener(
- new ActionListener() {
+ if (isDarkThemeFlatLAF()) {
+ cancelButton.setBackground(new Color(42, 46, 48));
+ }
- @Override
- public void actionPerformed(ActionEvent e) {
- Launcher.getConfigWindow().applySettings();
- }
- });
+ cancelButton.addActionListener(
+ new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Launcher.getConfigWindow().hideConfigWindow();
+ }
+ });
+
+ if (isUsingFlatLAFTheme()) {
+ navigationPanel.add(Box.createRigidArea(osScaleMul(new Dimension(4, 0))));
+ }
+
+ JButton applyButton = addButton("Apply", navigationPanel, Component.LEFT_ALIGNMENT);
+
+ if (isDarkThemeFlatLAF()) {
+ applyButton.setBackground(new Color(42, 46, 48));
+ }
+
+ applyButton.addActionListener(
+ new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Launcher.getConfigWindow().applySettings();
+ }
+ });
navigationPanel.add(Box.createHorizontalGlue());
- addButton("Restore Defaults", navigationPanel, Component.RIGHT_ALIGNMENT)
- .addActionListener(
- new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- int choice =
- JOptionPane.showConfirmDialog(
- Launcher.getConfigWindow().frame,
- "Are you sure you want to restore all settings to their defaults?",
- "Confirm",
- JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE);
- if (choice == JOptionPane.CLOSED_OPTION || choice == JOptionPane.NO_OPTION) {
- return;
- }
+ JButton restoreDefaultsButton =
+ addButton("Restore Defaults", navigationPanel, Component.RIGHT_ALIGNMENT);
- Settings.initSettings(); // make sure "default" is really default
- Settings.save("default");
- synchronizeGuiValues();
-
- // Restore defaults
- /* TODO: reimplement per-tab defaults?
- switch (tabbedPane.getSelectedIndex()) {
- case 0:
- Settings.restoreDefaultGeneral();
- Game.getInstance().resizeFrameWithContents();
- break;
- case 1:
- Settings.restoreDefaultOverlays();
- break;
- case 2:
- Settings.restoreDefaultNotifications();
- break;
- case 3:
- Settings.restoreDefaultPrivacy();
- break;
- case 4:
- Settings.restoreDefaultKeybinds();
- break;
- //TODO more pages
- default:
- Logger.Error("Restore defaults attempted to operate on a non-existent tab!");
- }
- */
- }
- });
+ if (isDarkThemeFlatLAF()) {
+ restoreDefaultsButton.setBackground(new Color(42, 46, 48));
+ }
+
+ restoreDefaultsButton.addActionListener(
+ new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JPanel confirmDefaultPanel =
+ Util.createOptionMessagePanel(
+ "Are you sure you want to restore all settings to their defaults?");
+ int choice =
+ JOptionPane.showConfirmDialog(
+ Launcher.getConfigWindow().frame,
+ confirmDefaultPanel,
+ "Confirm",
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.QUESTION_MESSAGE);
+ if (choice == JOptionPane.CLOSED_OPTION || choice == JOptionPane.NO_OPTION) {
+ return;
+ }
+
+ Settings.initSettings(); // make sure "default" is really default
+ Settings.save("default");
+ synchronizeGuiValues();
+
+ // Restore defaults
+ /* TODO: reimplement per-tab defaults?
+ switch (tabbedPane.getSelectedIndex()) {
+ case 0:
+ Settings.restoreDefaultGeneral();
+ Game.getInstance().resizeFrameWithContents();
+ break;
+ case 1:
+ Settings.restoreDefaultOverlays();
+ break;
+ case 2:
+ Settings.restoreDefaultNotifications();
+ break;
+ case 3:
+ Settings.restoreDefaultPrivacy();
+ break;
+ case 4:
+ Settings.restoreDefaultKeybinds();
+ break;
+ //TODO more pages
+ default:
+ Logger.Error("Restore defaults attempted to operate on a non-existent tab!");
+ }
+ */
+ }
+ });
/*
* General tab
@@ -486,193 +679,388 @@ public void actionPerformed(ActionEvent e) {
generalPanel.add(generalPanelClientSizePanel);
generalPanelClientSizePanel.setLayout(
new BoxLayout(generalPanelClientSizePanel, BoxLayout.X_AXIS));
- generalPanelClientSizePanel.setPreferredSize(new Dimension(0, 37));
generalPanelClientSizePanel.setAlignmentX(Component.LEFT_ALIGNMENT);
// TODO: Perhaps change to "Save client size on close"?
generalPanelClientSizeCheckbox =
- addCheckbox("Default client size:", generalPanelClientSizePanel);
- generalPanelClientSizeCheckbox.setToolTipText("Start the client with the supplied window size");
+ addCheckbox("Client window dimensions:", generalPanelClientSizePanel);
+ generalPanelClientSizeCheckbox.setToolTipText("Set the client size to the supplied dimensions");
generalPanelClientSizeXSpinner = new JSpinner();
generalPanelClientSizePanel.add(generalPanelClientSizeXSpinner);
- generalPanelClientSizeXSpinner.setMaximumSize(new Dimension(58, 22));
- generalPanelClientSizeXSpinner.setMinimumSize(new Dimension(58, 22));
- generalPanelClientSizeXSpinner.setAlignmentY((float) 0.75);
- generalPanelClientSizeXSpinner.setToolTipText("Default client width (512 minimum)");
+ generalPanelClientSizeXSpinner.setMaximumSize(osScaleMul(new Dimension(70, 23)));
+ generalPanelClientSizeXSpinner.setMinimumSize(osScaleMul(new Dimension(70, 23)));
+ generalPanelClientSizeXSpinner.setAlignmentY(0.7f);
+ generalPanelClientSizeXSpinner.setToolTipText("Default client width (512 minimum at 1x scale)");
generalPanelClientSizeXSpinner.putClientProperty("JComponent.sizeVariant", "mini");
JLabel generalPanelClientSizeByLabel = new JLabel("x");
generalPanelClientSizePanel.add(generalPanelClientSizeByLabel);
- generalPanelClientSizeByLabel.setAlignmentY((float) 0.9);
- generalPanelClientSizeByLabel.setBorder(new EmptyBorder(0, 2, 0, 2));
+ generalPanelClientSizeByLabel.setAlignmentY(0.8f);
+
+ int spinnerByMargin = isUsingFlatLAFTheme() ? 4 : 2;
+
+ generalPanelClientSizeByLabel.setBorder(
+ BorderFactory.createEmptyBorder(
+ 0, osScaleMul(spinnerByMargin), 0, osScaleMul(spinnerByMargin)));
generalPanelClientSizeYSpinner = new JSpinner();
generalPanelClientSizePanel.add(generalPanelClientSizeYSpinner);
- generalPanelClientSizeYSpinner.setMaximumSize(new Dimension(58, 22));
- generalPanelClientSizeYSpinner.setMinimumSize(new Dimension(58, 22));
- generalPanelClientSizeYSpinner.setAlignmentY((float) 0.75);
- generalPanelClientSizeYSpinner.setToolTipText("Default client height (357 minimum)");
+ generalPanelClientSizeYSpinner.setMaximumSize(osScaleMul(new Dimension(70, 23)));
+ generalPanelClientSizeYSpinner.setMinimumSize(osScaleMul(new Dimension(70, 23)));
+ generalPanelClientSizeYSpinner.setAlignmentY(0.7f);
+ generalPanelClientSizeYSpinner.setToolTipText(
+ "Default client height (357 minimum at 1x scale)");
generalPanelClientSizeYSpinner.putClientProperty("JComponent.sizeVariant", "mini");
// Sanitize JSpinner values
- SpinnerNumberModel spinnerWinXModel = new SpinnerNumberModel();
+ spinnerWinXModel = new SpinnerNumberModel();
spinnerWinXModel.setMinimum(512);
spinnerWinXModel.setValue(512);
spinnerWinXModel.setStepSize(10);
generalPanelClientSizeXSpinner.setModel(spinnerWinXModel);
- SpinnerNumberModel spinnerWinYModel = new SpinnerNumberModel();
+ spinnerWinYModel = new SpinnerNumberModel();
spinnerWinYModel.setMinimum(357);
spinnerWinYModel.setValue(357);
spinnerWinYModel.setStepSize(10);
generalPanelClientSizeYSpinner.setModel(spinnerWinYModel);
- generalPanelCheckUpdates =
- addCheckbox("Check for rsctimes updates from GitHub at launch", generalPanel);
- generalPanelCheckUpdates.setToolTipText(
- "When enabled, rsctimes will check for client updates before launching the game and install them when prompted");
-
- generalPanelWelcomeEnabled =
- addCheckbox("Remind you how to open the Settings every time you log in", generalPanel);
- generalPanelWelcomeEnabled.setToolTipText(
- "When enabled, rsctimes will insert a message telling the current keybinding to open the settings menu and remind you about the tray icon");
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelClientSizePanel.add(Box.createRigidArea(osScaleMul(new Dimension(6, 0))));
+ }
- generalPanelCustomCursorCheckbox = addCheckbox("Use custom mouse cursor", generalPanel);
- generalPanelCustomCursorCheckbox.setToolTipText(
- "Switch to using a custom mouse cursor instead of the system default");
+ JButton generalPanelClientSizeMaxButton =
+ addButton("Max", generalPanelClientSizePanel, Component.RIGHT_ALIGNMENT);
+ generalPanelClientSizeMaxButton.setAlignmentY(0.7f);
+ generalPanelClientSizeMaxButton.addActionListener(
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Dimension maximumWindowSize =
+ ScaledWindow.getInstance().getMaximumEffectiveWindowSize();
- generalPanelAutoScreenshotCheckbox =
- addCheckbox("Take a screenshot when you level up or complete a quest", generalPanel);
- generalPanelAutoScreenshotCheckbox.setToolTipText(
- "Takes a screenshot for you for level ups and quest completion");
+ int windowWidth = maximumWindowSize.width;
+ int windowHeight = maximumWindowSize.height;
- JLabel generalPanelFoVLabel = new JLabel("Field of view (Default 9)");
- generalPanelFoVLabel.setToolTipText("Sets the field of view (not recommended past 10)");
- generalPanel.add(generalPanelFoVLabel);
- generalPanelFoVLabel.setAlignmentY((float) 0.9);
+ // This only changes the values in the boxes
+ spinnerWinXModel.setValue(windowWidth);
+ spinnerWinYModel.setValue(windowHeight);
+ }
+ });
- generalPanelFoVSlider = new JSlider();
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelClientSizePanel.add(Box.createRigidArea(osScaleMul(new Dimension(6, 0))));
+ }
- generalPanel.add(generalPanelFoVSlider);
- generalPanelFoVSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
- generalPanelFoVSlider.setMaximumSize(new Dimension(200, 55));
- generalPanelFoVSlider.setBorder(new EmptyBorder(0, 0, 5, 0));
- generalPanelFoVSlider.setMinimum(7);
- generalPanelFoVSlider.setMaximum(16);
- generalPanelFoVSlider.setMajorTickSpacing(1);
- generalPanelFoVSlider.setPaintTicks(true);
- generalPanelFoVSlider.setPaintLabels(true);
+ JButton generalPanelClientSizeResetButton =
+ addButton("Reset", generalPanelClientSizePanel, Component.RIGHT_ALIGNMENT);
+ generalPanelClientSizeResetButton.setAlignmentY(0.7f);
+ generalPanelClientSizeResetButton.addActionListener(
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // This only changes the values in the boxes
+ Dimension scaledMinimumWindowSize =
+ ScaledWindow.getInstance().getMinimumViewportSizeForScalar();
+ spinnerWinXModel.setValue(scaledMinimumWindowSize.width);
+ spinnerWinYModel.setValue(scaledMinimumWindowSize.height);
+ }
+ });
- JLabel generalPanelViewDistanceLabel = new JLabel("View distance");
- generalPanelViewDistanceLabel.setToolTipText(
- "Sets the max render distance of structures and landscape");
- generalPanel.add(generalPanelViewDistanceLabel);
- generalPanelViewDistanceLabel.setAlignmentY((float) 0.9);
+ JLabel generalPanelClientSizeScaleWarning =
+ new JLabel("(Will be reset if window scale changes)");
+ generalPanelClientSizeScaleWarning.setAlignmentY(0.8f);
+ generalPanelClientSizeScaleWarning.setBorder(
+ BorderFactory.createEmptyBorder(0, osScaleMul(6), 0, 0));
+ generalPanelClientSizePanel.add(generalPanelClientSizeScaleWarning);
+
+ // Scaling options
+ JPanel generalPanelScalePanel = new JPanel();
+ generalPanel.add(generalPanelScalePanel);
+ generalPanelScalePanel.setLayout(new BoxLayout(generalPanelScalePanel, BoxLayout.Y_AXIS));
+ generalPanelScalePanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ generalPanelScaleWindowCheckbox = addCheckbox("Scale window:", generalPanelScalePanel);
+ generalPanelScaleWindowCheckbox.setToolTipText("Enable to scale the game client");
+ generalPanelScaleWindowCheckbox.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, osScaleMul(5), 0));
+
+ ButtonGroup generalPanelScaleWindowTypeButtonGroup = new ButtonGroup();
+ String scaleLargerThanResolutionToolTip =
+ "This scale value will produce a window bigger than your screen resolution";
+
+ // Integer scaling
+ JPanel generalPanelIntegerScalingPanel = new JPanel();
+ generalPanelScalePanel.add(generalPanelIntegerScalingPanel);
+ generalPanelIntegerScalingPanel.setLayout(
+ new BoxLayout(generalPanelIntegerScalingPanel, BoxLayout.X_AXIS));
+ generalPanelIntegerScalingPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ generalPanelIntegerScalingFocusButton =
+ addRadioButton("Integer scaling", generalPanelIntegerScalingPanel, osScaleMul(20));
+ generalPanelIntegerScalingFocusButton.setToolTipText(
+ "Uses the nearest neighbor algorithm for pixel-perfect client scaling");
+ generalPanelScaleWindowTypeButtonGroup.add(generalPanelIntegerScalingFocusButton);
+
+ generalPanelIntegerScalingSpinner = new JSpinner();
+ generalPanelIntegerScalingPanel.add(generalPanelIntegerScalingSpinner);
+ String integerScalingSpinnerToolTip =
+ "Integer scaling value " + (int) Renderer.minScalar + "-" + (int) Renderer.maxIntegerScalar;
+ generalPanelIntegerScalingSpinner.setMaximumSize(osScaleMul(new Dimension(55, 26)));
+ generalPanelIntegerScalingSpinner.setMinimumSize(osScaleMul(new Dimension(55, 26)));
+ generalPanelIntegerScalingSpinner.setAlignmentY(0.625f);
+ generalPanelIntegerScalingSpinner.setToolTipText(integerScalingSpinnerToolTip);
+ generalPanelIntegerScalingSpinner.putClientProperty("JComponent.sizeVariant", "mini");
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelIntegerScalingSpinner.setBorder(new FlatRoundBorder());
+ } else {
+ generalPanelIntegerScalingSpinner.setBorder(
+ BorderFactory.createEmptyBorder(
+ osScaleMul(2), osScaleMul(2), osScaleMul(2), osScaleMul(2)));
+ }
+ generalPanelIntegerScalingSpinner.addChangeListener(
+ new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ Dimension maximumWindowSize = ScaledWindow.getInstance().getMaximumWindowSize();
+ int scalar = (int) generalPanelIntegerScalingSpinner.getValue();
+
+ if (((512 * scalar) + ScaledWindow.getInstance().getWindowWidthInsets()
+ > maximumWindowSize.getWidth())
+ || ((357 * scalar) + ScaledWindow.getInstance().getWindowHeightInsets()
+ > maximumWindowSize.getHeight())) {
+ generalPanelIntegerScalingSpinner.setBorder(
+ new LineBorder(Color.orange, osScaleMul(2)));
+ generalPanelIntegerScalingSpinner.setToolTipText(scaleLargerThanResolutionToolTip);
+ } else {
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelIntegerScalingSpinner.setBorder(new FlatRoundBorder());
+ } else {
+ generalPanelIntegerScalingSpinner.setBorder(
+ BorderFactory.createEmptyBorder(
+ osScaleMul(2), osScaleMul(2), osScaleMul(2), osScaleMul(2)));
+ }
+ generalPanelIntegerScalingSpinner.setToolTipText(integerScalingSpinnerToolTip);
+ }
+ }
+ });
- generalPanelViewDistanceSlider = new JSlider();
+ SpinnerNumberModel spinnerLimitIntegerScaling =
+ new SpinnerNumberModel(2, (int) Renderer.minScalar, (int) Renderer.maxIntegerScalar, 1);
+ generalPanelIntegerScalingSpinner.setModel(spinnerLimitIntegerScaling);
+
+ // Bilinear scaling
+ JPanel generalPanelBilinearScalingPanel = new JPanel();
+ generalPanelScalePanel.add(generalPanelBilinearScalingPanel);
+ generalPanelBilinearScalingPanel.setLayout(
+ new BoxLayout(generalPanelBilinearScalingPanel, BoxLayout.X_AXIS));
+ generalPanelBilinearScalingPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ generalPanelBilinearScalingFocusButton =
+ addRadioButton("Bilinear interpolation", generalPanelBilinearScalingPanel, osScaleMul(20));
+ generalPanelBilinearScalingFocusButton.setToolTipText(
+ "Uses the bilinear interpolation algorithm for client scaling");
+ generalPanelScaleWindowTypeButtonGroup.add(generalPanelBilinearScalingFocusButton);
+
+ generalPanelBilinearScalingSpinner = new JSpinner();
+ generalPanelBilinearScalingPanel.add(generalPanelBilinearScalingSpinner);
+ String bilinearScalingSpinnerToolTip =
+ "Bilinear scaling value " + Renderer.minScalar + "-" + Renderer.maxInterpolationScalar;
+ generalPanelBilinearScalingSpinner.setMaximumSize(osScaleMul(new Dimension(55, 26)));
+ generalPanelBilinearScalingSpinner.setMinimumSize(osScaleMul(new Dimension(55, 26)));
+ generalPanelBilinearScalingSpinner.setAlignmentY(0.625f);
+ generalPanelBilinearScalingSpinner.setToolTipText(bilinearScalingSpinnerToolTip);
+ generalPanelBilinearScalingSpinner.putClientProperty("JComponent.sizeVariant", "mini");
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelBilinearScalingSpinner.setBorder(new FlatRoundBorder());
+ } else {
+ generalPanelBilinearScalingSpinner.setBorder(
+ BorderFactory.createEmptyBorder(
+ osScaleMul(2), osScaleMul(2), osScaleMul(2), osScaleMul(2)));
+ }
+ generalPanelBilinearScalingSpinner.addChangeListener(
+ new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ Dimension maximumWindowSize = ScaledWindow.getInstance().getMaximumWindowSize();
+ float scalar = (float) generalPanelBilinearScalingSpinner.getValue();
+
+ if (((512 * scalar) + ScaledWindow.getInstance().getWindowWidthInsets()
+ > maximumWindowSize.getWidth())
+ || ((357 * scalar) + ScaledWindow.getInstance().getWindowHeightInsets()
+ > maximumWindowSize.getHeight())) {
+ generalPanelBilinearScalingSpinner.setBorder(
+ new LineBorder(Color.orange, osScaleMul(2)));
+ generalPanelBilinearScalingSpinner.setToolTipText(scaleLargerThanResolutionToolTip);
+ } else {
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelBilinearScalingSpinner.setBorder(new FlatRoundBorder());
+ } else {
+ generalPanelBilinearScalingSpinner.setBorder(
+ BorderFactory.createEmptyBorder(
+ osScaleMul(2), osScaleMul(2), osScaleMul(2), osScaleMul(2)));
+ }
+ generalPanelBilinearScalingSpinner.setToolTipText(bilinearScalingSpinnerToolTip);
+ }
+ }
+ });
- generalPanel.add(generalPanelViewDistanceSlider);
- generalPanelViewDistanceSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
- generalPanelViewDistanceSlider.setMaximumSize(new Dimension(200, 55));
- generalPanelViewDistanceSlider.setBorder(new EmptyBorder(0, 0, 5, 0));
- generalPanelViewDistanceSlider.setMinorTickSpacing(500);
- generalPanelViewDistanceSlider.setMajorTickSpacing(1000);
- generalPanelViewDistanceSlider.setMinimum(2300);
- generalPanelViewDistanceSlider.setMaximum(20000);
- generalPanelViewDistanceSlider.setPaintTicks(true);
+ SpinnerNumberModel spinnerLimitBilinearScaling =
+ new SpinnerNumberModel(
+ new Float(1.5f),
+ new Float(Renderer.minScalar),
+ new Float(Renderer.maxInterpolationScalar),
+ new Float(0.1f));
+ generalPanelBilinearScalingSpinner.setModel(spinnerLimitBilinearScaling);
+
+ JLabel bilinearInterpolationScalingWarning =
+ new JLabel("(May affect performance at high scaling values)");
+ bilinearInterpolationScalingWarning.setAlignmentY(0.75f);
+ int bilinearInterpolationScalingMargin = isUsingFlatLAFTheme() ? 6 : 2;
+ bilinearInterpolationScalingWarning.setBorder(
+ BorderFactory.createEmptyBorder(0, osScaleMul(bilinearInterpolationScalingMargin), 0, 0));
+ generalPanelBilinearScalingPanel.add(bilinearInterpolationScalingWarning);
+
+ // Bicubic scaling
+ JPanel generalPanelBicubicScalingPanel = new JPanel();
+ generalPanelScalePanel.add(generalPanelBicubicScalingPanel);
+ generalPanelBicubicScalingPanel.setLayout(
+ new BoxLayout(generalPanelBicubicScalingPanel, BoxLayout.X_AXIS));
+ generalPanelBicubicScalingPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ generalPanelBicubicScalingFocusButton =
+ addRadioButton("Bicubic interpolation", generalPanelBicubicScalingPanel, osScaleMul(20));
+ generalPanelBicubicScalingFocusButton.setToolTipText(
+ "Uses the bicubic interpolation algorithm for client scaling");
+ generalPanelScaleWindowTypeButtonGroup.add(generalPanelBicubicScalingFocusButton);
+
+ generalPanelBicubicScalingSpinner = new JSpinner();
+ generalPanelBicubicScalingPanel.add(generalPanelBicubicScalingSpinner);
+ String bicubicScalingSpinnerToolTip =
+ "Bicubic scaling value " + Renderer.minScalar + "-" + Renderer.maxInterpolationScalar;
+ generalPanelBicubicScalingSpinner.setMaximumSize(osScaleMul(new Dimension(55, 26)));
+ generalPanelBicubicScalingSpinner.setMinimumSize(osScaleMul(new Dimension(55, 26)));
+ generalPanelBicubicScalingSpinner.setAlignmentY(0.625f);
+ generalPanelBicubicScalingSpinner.setToolTipText(bicubicScalingSpinnerToolTip);
+ generalPanelBicubicScalingSpinner.putClientProperty("JComponent.sizeVariant", "mini");
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelBicubicScalingSpinner.setBorder(new FlatRoundBorder());
+ } else {
+ generalPanelBicubicScalingSpinner.setBorder(
+ BorderFactory.createEmptyBorder(
+ osScaleMul(2), osScaleMul(2), osScaleMul(2), osScaleMul(2)));
+ }
+ generalPanelBicubicScalingSpinner.addChangeListener(
+ new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ Dimension maximumWindowSize = ScaledWindow.getInstance().getMaximumWindowSize();
+ float scalar = (float) generalPanelBicubicScalingSpinner.getValue();
+
+ if (((512 * scalar) + ScaledWindow.getInstance().getWindowWidthInsets()
+ > maximumWindowSize.getWidth())
+ || ((357 * scalar) + ScaledWindow.getInstance().getWindowHeightInsets()
+ > maximumWindowSize.getHeight())) {
+ generalPanelBicubicScalingSpinner.setBorder(new LineBorder(Color.orange, 2));
+ generalPanelBicubicScalingSpinner.setToolTipText(scaleLargerThanResolutionToolTip);
+ } else {
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelBicubicScalingSpinner.setBorder(new FlatRoundBorder());
+ } else {
+ generalPanelBicubicScalingSpinner.setBorder(
+ BorderFactory.createEmptyBorder(
+ osScaleMul(2), osScaleMul(2), osScaleMul(2), osScaleMul(2)));
+ }
+ generalPanelBicubicScalingSpinner.setToolTipText(bicubicScalingSpinnerToolTip);
+ }
+ }
+ });
- Hashtable generalPanelViewDistanceLabelTable =
- new Hashtable();
- generalPanelViewDistanceLabelTable.put(new Integer(2300), new JLabel("2,300"));
- generalPanelViewDistanceLabelTable.put(new Integer(10000), new JLabel("10,000"));
- generalPanelViewDistanceLabelTable.put(new Integer(20000), new JLabel("20,000"));
- generalPanelViewDistanceSlider.setLabelTable(generalPanelViewDistanceLabelTable);
- generalPanelViewDistanceSlider.setPaintLabels(true);
+ SpinnerNumberModel spinnerLimitBicubicScaling =
+ new SpinnerNumberModel(
+ new Float(1.5f),
+ new Float(Renderer.minScalar),
+ new Float(Renderer.maxInterpolationScalar),
+ new Float(0.1f));
+ generalPanelBicubicScalingSpinner.setModel(spinnerLimitBicubicScaling);
+
+ JLabel bicubicInterpolationScalingWarning =
+ new JLabel("(May affect performance at high scaling values)");
+ bicubicInterpolationScalingWarning.setAlignmentY(0.75f);
+ int bicubicInterpolationScalingMargin = isUsingFlatLAFTheme() ? 6 : 2;
+ bicubicInterpolationScalingWarning.setBorder(
+ BorderFactory.createEmptyBorder(0, osScaleMul(bicubicInterpolationScalingMargin), 0, 0));
+ generalPanelBicubicScalingPanel.add(bicubicInterpolationScalingWarning);
+
+ if (isUsingFlatLAFTheme()) {
+ generalPanelScalePanel.add(Box.createRigidArea(osScaleMul(new Dimension(0, 5))));
+ }
+ // End scaling options
- //////
- JPanel generalPanelLimitFPSPanel = new JPanel();
- generalPanel.add(generalPanelLimitFPSPanel);
- generalPanelLimitFPSPanel.setLayout(new BoxLayout(generalPanelLimitFPSPanel, BoxLayout.X_AXIS));
- generalPanelLimitFPSPanel.setPreferredSize(new Dimension(0, 37));
- generalPanelLimitFPSPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+ generalPanelCheckUpdates =
+ addCheckbox("Check for RSCTimes updates from GitHub at launch", generalPanel);
+ generalPanelCheckUpdates.setToolTipText(
+ "When enabled, RSCTimes will check for client updates before launching the game and install them when prompted");
- generalPanelLimitFPSCheckbox =
- addCheckbox("FPS limit (doubled while F1 interlaced):", generalPanelLimitFPSPanel);
- generalPanelLimitFPSCheckbox.setToolTipText(
- "Limit FPS for a more 2001 feeling (or to save battery)");
+ generalPanelWelcomeEnabled =
+ addCheckbox(
+ "Remind you how to open the Settings every time you log in (!!! Disable this if you know how to open the settings)",
+ generalPanel);
+ generalPanelWelcomeEnabled.setToolTipText(
+ "When enabled, RSCTimes will insert a message telling the current keybinding to open the settings menu and remind you about the tray icon");
- generalPanelLimitFPSSpinner = new JSpinner();
- generalPanelLimitFPSPanel.add(generalPanelLimitFPSSpinner);
- generalPanelLimitFPSSpinner.setMaximumSize(new Dimension(45, 22));
- generalPanelLimitFPSSpinner.setMinimumSize(new Dimension(45, 22));
- generalPanelLimitFPSSpinner.setAlignmentY((float) 0.75);
- generalPanelLimitFPSSpinner.setToolTipText("Target FPS");
- generalPanelLimitFPSSpinner.putClientProperty("JComponent.sizeVariant", "mini");
- generalPanelLimitFPSSpinner.setEnabled(false);
+ generalPanelCustomCursorCheckbox = addCheckbox("Use custom mouse cursor", generalPanel);
+ generalPanelCustomCursorCheckbox.setToolTipText(
+ "Switch to using a custom mouse cursor instead of the system default");
- // Sanitize JSpinner value
- SpinnerNumberModel spinnerLimitFpsModel = new SpinnerNumberModel();
- spinnerLimitFpsModel.setMinimum(1);
- spinnerLimitFpsModel.setMaximum(50);
- spinnerLimitFpsModel.setValue(10);
- spinnerLimitFpsModel.setStepSize(1);
- generalPanelLimitFPSSpinner.setModel(spinnerLimitFpsModel);
- //////
+ generalPanelShiftScrollCameraRotationCheckbox =
+ addCheckbox("Enable camera rotation with compatible trackpads", generalPanel);
+ generalPanelShiftScrollCameraRotationCheckbox.setToolTipText(
+ "Trackpads that send SHIFT-SCROLL WHEEL when swiping left or right with two fingers will be able to rotate the camera");
+
+ JPanel generalPanelTrackPadRotationPanel = new JPanel();
+ generalPanel.add(generalPanelTrackPadRotationPanel);
+ generalPanelTrackPadRotationPanel.setLayout(
+ new BoxLayout(generalPanelTrackPadRotationPanel, BoxLayout.Y_AXIS));
+ generalPanelTrackPadRotationPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ JLabel generalPanelTrackpadRotationLabel = new JLabel("Camera rotation trackpad sensitivity");
+ generalPanelTrackpadRotationLabel.setToolTipText(
+ "Sets the camera rotation trackpad sensitivity (Default: 8)");
+ generalPanelTrackPadRotationPanel.add(generalPanelTrackpadRotationLabel);
+ generalPanelTrackpadRotationLabel.setAlignmentY(1.0f);
+
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelTrackPadRotationPanel.add(Box.createRigidArea(osScaleMul(new Dimension(0, 10))));
+ }
- JPanel generalPanelLogVerbosityPanel = new JPanel();
- generalPanelLogVerbosityPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- generalPanelLogVerbosityPanel.setMaximumSize(new Dimension(350, 128));
- generalPanelLogVerbosityPanel.setLayout(
- new BoxLayout(generalPanelLogVerbosityPanel, BoxLayout.Y_AXIS));
- generalPanel.add(generalPanelLogVerbosityPanel);
+ generalPanelTrackpadRotationSlider = new JSlider();
- JLabel generalPanelLogVerbosityTitle = new JLabel("Log verbosity maximum");
- generalPanelLogVerbosityTitle.setToolTipText(
- "What max level of log text will be shown in the rsctimes log/console");
- generalPanelLogVerbosityPanel.add(generalPanelLogVerbosityTitle);
- generalPanelLogVerbosityTitle.setAlignmentY((float) 0.9);
+ generalPanelTrackPadRotationPanel.add(generalPanelTrackpadRotationSlider);
+ generalPanelTrackpadRotationSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
+ generalPanelTrackpadRotationSlider.setMaximumSize(osScaleMul(new Dimension(200, 55)));
+ generalPanelTrackpadRotationSlider.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, osScaleMul(10), 0));
+ generalPanelTrackpadRotationSlider.setMajorTickSpacing(2);
+ generalPanelTrackpadRotationSlider.setMinorTickSpacing(1);
+ generalPanelTrackpadRotationSlider.setMinimum(0);
+ generalPanelTrackpadRotationSlider.setMaximum(16);
+ generalPanelTrackpadRotationSlider.setPaintTicks(true);
- Hashtable generalPanelLogVerbosityLabelTable =
+ Hashtable generalPanelTrackpadRotationLabelTable =
new Hashtable();
- generalPanelLogVerbosityLabelTable.put(new Integer(0), new JLabel("Error"));
- generalPanelLogVerbosityLabelTable.put(new Integer(1), new JLabel("Warning"));
- generalPanelLogVerbosityLabelTable.put(new Integer(2), new JLabel("Game"));
- generalPanelLogVerbosityLabelTable.put(new Integer(3), new JLabel("Info"));
- generalPanelLogVerbosityLabelTable.put(new Integer(4), new JLabel("Debug"));
- generalPanelLogVerbosityLabelTable.put(new Integer(5), new JLabel("Opcode"));
+ generalPanelTrackpadRotationLabelTable.put(new Integer(0), new JLabel("0"));
+ generalPanelTrackpadRotationLabelTable.put(new Integer(4), new JLabel("4"));
+ generalPanelTrackpadRotationLabelTable.put(new Integer(8), new JLabel("8"));
+ generalPanelTrackpadRotationLabelTable.put(new Integer(12), new JLabel("12"));
+ generalPanelTrackpadRotationLabelTable.put(new Integer(16), new JLabel("16"));
+ generalPanelTrackpadRotationSlider.setLabelTable(generalPanelTrackpadRotationLabelTable);
+ generalPanelTrackpadRotationSlider.setPaintLabels(true);
- generalPanelLogVerbositySlider = new JSlider();
- generalPanelLogVerbositySlider.setMajorTickSpacing(1);
- generalPanelLogVerbositySlider.setLabelTable(generalPanelLogVerbosityLabelTable);
- generalPanelLogVerbositySlider.setPaintLabels(true);
- generalPanelLogVerbositySlider.setPaintTicks(true);
- generalPanelLogVerbositySlider.setSnapToTicks(true);
- generalPanelLogVerbositySlider.setMinimum(0);
- generalPanelLogVerbositySlider.setMaximum(5);
- generalPanelLogVerbositySlider.setPreferredSize(new Dimension(200, 55));
- generalPanelLogVerbositySlider.setAlignmentX(Component.LEFT_ALIGNMENT);
- generalPanelLogVerbositySlider.setBorder(new EmptyBorder(0, 0, 5, 0));
- generalPanelLogVerbositySlider.setOrientation(SwingConstants.HORIZONTAL);
- generalPanelLogVerbosityPanel.add(generalPanelLogVerbositySlider);
-
- generalPanelLogTimestampsCheckbox = addCheckbox("Show timestamps in log", generalPanel);
- generalPanelLogTimestampsCheckbox.setToolTipText(
- "Displays the time text was output to the log");
-
- generalPanelLogLevelCheckbox = addCheckbox("Show log level in log", generalPanel);
- generalPanelLogLevelCheckbox.setToolTipText("Displays the log level of output in the log");
-
- generalPanelLogForceTimestampsCheckbox = addCheckbox("Force timestamps in log", generalPanel);
- generalPanelLogForceTimestampsCheckbox.setToolTipText(
- "Forces display of the time text was output to the log");
-
- generalPanelLogForceLevelCheckbox = addCheckbox("Force log level in log", generalPanel);
- generalPanelLogForceLevelCheckbox.setToolTipText(
- "Forces display of the log level of output in the log");
-
- generalPanelColoredTextCheckbox = addCheckbox("Colored console text", generalPanel);
- generalPanelColoredTextCheckbox.setToolTipText(
- "When running the client from a console, chat messages in the console will reflect the colors they are in game");
+ generalPanelAutoScreenshotCheckbox =
+ addCheckbox("Take a screenshot when you level up or complete a quest", generalPanel);
+ generalPanelAutoScreenshotCheckbox.setToolTipText(
+ "Takes a screenshot for you for level ups and quest completion");
generalPanelDebugModeCheckbox = addCheckbox("Enable debug mode", generalPanel);
generalPanelDebugModeCheckbox.setToolTipText(
@@ -703,7 +1091,6 @@ public void actionPerformed(ActionEvent e) {
addCheckbox("Combat style menu shown outside of combat", generalPanel);
generalPanelCombatXPMenuCheckbox.setToolTipText(
"Always show the combat style menu when out of combat");
- generalPanelCombatXPMenuCheckbox.setBorder(new EmptyBorder(7, 0, 10, 0));
generalPanelCombatXPMenuCheckbox.setEnabled(false);
generalPanelCombatXPMenuHiddenCheckbox =
@@ -729,11 +1116,6 @@ public void actionPerformed(ActionEvent e) {
generalPanelRoofHidingCheckbox = addCheckbox("Roof hiding", generalPanel);
generalPanelRoofHidingCheckbox.setToolTipText("Always hide rooftops");
- generalPanelDisableUndergroundLightingCheckbox =
- addCheckbox("Disable underground lighting flicker", generalPanel);
- generalPanelDisableUndergroundLightingCheckbox.setToolTipText(
- "Underground will no longer flicker, basically");
-
generalPanelCameraZoomableCheckbox = addCheckbox("Camera zoom enhancement", generalPanel);
generalPanelCameraZoomableCheckbox.setToolTipText(
"Zoom the camera in and out with the mouse wheel, and no longer zooms in inside buildings");
@@ -751,11 +1133,113 @@ public void actionPerformed(ActionEvent e) {
generalPanelCameraMovableRelativeCheckbox.setToolTipText(
"Camera movement will follow the player position");
+ addSettingsHeader(generalPanel, "Graphical effect changes");
+
+ JPanel generalPanelViewDistancePanel = new JPanel();
+ generalPanel.add(generalPanelViewDistancePanel);
+ generalPanelViewDistancePanel.setLayout(
+ new BoxLayout(generalPanelViewDistancePanel, BoxLayout.Y_AXIS));
+ generalPanelViewDistancePanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ JLabel generalPanelViewDistanceLabel = new JLabel("View distance");
+ generalPanelViewDistanceLabel.setToolTipText(
+ "Sets the max render distance of structures and landscape");
+ generalPanelViewDistancePanel.add(generalPanelViewDistanceLabel);
+ generalPanelViewDistanceLabel.setAlignmentY(1.0f);
+
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelViewDistancePanel.add(Box.createRigidArea(osScaleMul(new Dimension(0, 5))));
+ }
+
+ generalPanelViewDistanceSlider = new JSlider();
+
+ generalPanelViewDistancePanel.add(generalPanelViewDistanceSlider);
+ generalPanelViewDistanceSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
+ generalPanelViewDistanceSlider.setMaximumSize(osScaleMul(new Dimension(350, 55)));
+ generalPanelViewDistanceSlider.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, osScaleMul(10), 0));
+ generalPanelViewDistanceSlider.setMinorTickSpacing(500);
+ generalPanelViewDistanceSlider.setMajorTickSpacing(1000);
+ generalPanelViewDistanceSlider.setMinimum(2300);
+ generalPanelViewDistanceSlider.setMaximum(20000);
+ generalPanelViewDistanceSlider.setPaintTicks(true);
+
+ Hashtable generalPanelViewDistanceLabelTable =
+ new Hashtable();
+ generalPanelViewDistanceLabelTable.put(new Integer(2300), new JLabel("2,300"));
+ generalPanelViewDistanceLabelTable.put(new Integer(10000), new JLabel("10,000"));
+ generalPanelViewDistanceLabelTable.put(new Integer(20000), new JLabel("20,000"));
+ generalPanelViewDistanceSlider.setLabelTable(generalPanelViewDistanceLabelTable);
+ generalPanelViewDistanceSlider.setPaintLabels(true);
+ //////
+
+ // FOV slider
+ JPanel generalPanelFoVPanel = new JPanel();
+ generalPanel.add(generalPanelFoVPanel);
+ generalPanelFoVPanel.setLayout(new BoxLayout(generalPanelFoVPanel, BoxLayout.Y_AXIS));
+ generalPanelFoVPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ JLabel generalPanelFoVLabel = new JLabel("Field of view (Default 9)");
+ generalPanelFoVLabel.setToolTipText("Sets the field of view (not recommended past 10)");
+ generalPanelFoVPanel.add(generalPanelFoVLabel);
+ generalPanelFoVLabel.setAlignmentY(1.0f);
+
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelFoVPanel.add(Box.createRigidArea(osScaleMul(new Dimension(0, 5))));
+ }
+
+ generalPanelFoVSlider = new JSlider();
+
+ generalPanelFoVPanel.add(generalPanelFoVSlider);
+ generalPanelFoVSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
+ generalPanelFoVSlider.setMaximumSize(osScaleMul(new Dimension(300, 55)));
+ generalPanelFoVSlider.setBorder(BorderFactory.createEmptyBorder(0, 0, osScaleMul(10), 0));
+ generalPanelFoVSlider.setMinimum(7);
+ generalPanelFoVSlider.setMaximum(16);
+ generalPanelFoVSlider.setMajorTickSpacing(1);
+ generalPanelFoVSlider.setPaintTicks(true);
+ generalPanelFoVSlider.setPaintLabels(true);
+ //////
+
+ generalPanelDisableUndergroundLightingCheckbox =
+ addCheckbox("Disable underground lighting flicker", generalPanel);
+ generalPanelDisableUndergroundLightingCheckbox.setToolTipText(
+ "Underground will no longer flicker, basically");
+
+ // FPS limit
+ JPanel generalPanelLimitFPSPanel = new JPanel();
+ generalPanel.add(generalPanelLimitFPSPanel);
+ generalPanelLimitFPSPanel.setLayout(new BoxLayout(generalPanelLimitFPSPanel, BoxLayout.X_AXIS));
+ generalPanelLimitFPSPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ generalPanelLimitFPSCheckbox =
+ addCheckbox("FPS limit (doubled while F1 interlaced):", generalPanelLimitFPSPanel);
+ generalPanelLimitFPSCheckbox.setToolTipText(
+ "Limit FPS for a more 2001 feeling (or to save battery)");
+
+ generalPanelLimitFPSSpinner = new JSpinner();
+ generalPanelLimitFPSPanel.add(generalPanelLimitFPSSpinner);
+ generalPanelLimitFPSSpinner.setMaximumSize(osScaleMul(new Dimension(50, 22)));
+ generalPanelLimitFPSSpinner.setMinimumSize(osScaleMul(new Dimension(50, 22)));
+ generalPanelLimitFPSSpinner.setAlignmentY(0.75f);
+ generalPanelLimitFPSSpinner.setToolTipText("Target FPS");
+ generalPanelLimitFPSSpinner.putClientProperty("JComponent.sizeVariant", "mini");
+ generalPanelLimitFPSSpinner.setEnabled(false);
+
+ // Sanitize JSpinner value
+ SpinnerNumberModel spinnerLimitFpsModel = new SpinnerNumberModel();
+ spinnerLimitFpsModel.setMinimum(1);
+ spinnerLimitFpsModel.setMaximum(50);
+ spinnerLimitFpsModel.setValue(10);
+ spinnerLimitFpsModel.setStepSize(1);
+ generalPanelLimitFPSSpinner.setModel(spinnerLimitFpsModel);
+ //////
+
addSettingsHeader(generalPanel, "Menu/Item patching");
JPanel generalPanelNamePatchModePanel = new JPanel();
generalPanelNamePatchModePanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- generalPanelNamePatchModePanel.setMaximumSize(new Dimension(300, 60));
+ generalPanelNamePatchModePanel.setMaximumSize(osScaleMul(new Dimension(300, 85)));
generalPanelNamePatchModePanel.setLayout(
new BoxLayout(generalPanelNamePatchModePanel, BoxLayout.X_AXIS));
generalPanel.add(generalPanelNamePatchModePanel);
@@ -767,17 +1251,19 @@ public void actionPerformed(ActionEvent e) {
generalPanelNamePatchModeSlider.setSnapToTicks(true);
generalPanelNamePatchModeSlider.setMinimum(0);
generalPanelNamePatchModeSlider.setMaximum(3);
- generalPanelNamePatchModeSlider.setPreferredSize(new Dimension(33, 0));
+ generalPanelNamePatchModeSlider.setPreferredSize(osScaleMul(new Dimension(40, 0)));
generalPanelNamePatchModeSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
- generalPanelNamePatchModeSlider.setBorder(new EmptyBorder(7, 0, 10, 0));
+ generalPanelNamePatchModeSlider.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, osScaleMul(10), 0));
generalPanelNamePatchModeSlider.setOrientation(SwingConstants.VERTICAL);
generalPanelNamePatchModePanel.add(generalPanelNamePatchModeSlider);
generalPanelNamePatchModeSlider.setEnabled(false);
JPanel generalPanelNamePatchModeTextPanel = new JPanel();
- generalPanelNamePatchModeTextPanel.setPreferredSize(new Dimension(255, 80));
+ generalPanelNamePatchModeTextPanel.setPreferredSize(osScaleMul(new Dimension(255, 80)));
generalPanelNamePatchModeTextPanel.setLayout(new BorderLayout());
- generalPanelNamePatchModeTextPanel.setBorder(new EmptyBorder(7, 10, 0, 0));
+ generalPanelNamePatchModeTextPanel.setBorder(
+ BorderFactory.createEmptyBorder(0, osScaleMul(10), 0, 0));
generalPanelNamePatchModePanel.add(generalPanelNamePatchModeTextPanel);
JLabel generalPanelNamePatchModeTitle =
@@ -832,6 +1318,91 @@ public void stateChanged(ChangeEvent e) {
"Even in the very last versions of the client, the horizontal blue bar at the bottom was still misaligned so that 1 pixel shines through at the end");
generalPanelPatchHbar512LastPixelCheckbox.setEnabled(false);
+ // Logger settings
+
+ addSettingsHeader(generalPanel, "Logging settings");
+
+ JPanel generalPanelLogVerbosityPanel = new JPanel();
+ generalPanelLogVerbosityPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+ generalPanelLogVerbosityPanel.setMaximumSize(osScaleMul(new Dimension(350, 128)));
+ generalPanelLogVerbosityPanel.setLayout(
+ new BoxLayout(generalPanelLogVerbosityPanel, BoxLayout.Y_AXIS));
+ generalPanel.add(generalPanelLogVerbosityPanel);
+
+ JLabel generalPanelLogVerbosityTitle = new JLabel("Log verbosity maximum");
+ generalPanelLogVerbosityTitle.setToolTipText(
+ "What max level of log text will be shown in the RSCTimes log/console");
+ generalPanelLogVerbosityPanel.add(generalPanelLogVerbosityTitle);
+ generalPanelLogVerbosityTitle.setAlignmentY(1.0f);
+
+ Hashtable generalPanelLogVerbosityLabelTable =
+ new Hashtable();
+ generalPanelLogVerbosityLabelTable.put(new Integer(0), new JLabel("Error"));
+ generalPanelLogVerbosityLabelTable.put(new Integer(1), new JLabel("Warning"));
+ generalPanelLogVerbosityLabelTable.put(new Integer(2), new JLabel("Game"));
+ generalPanelLogVerbosityLabelTable.put(new Integer(3), new JLabel("Info"));
+ generalPanelLogVerbosityLabelTable.put(new Integer(4), new JLabel("Debug"));
+ generalPanelLogVerbosityLabelTable.put(new Integer(5), new JLabel("Opcode"));
+
+ if (Util.isUsingFlatLAFTheme()) {
+ generalPanelLogVerbosityPanel.add(Box.createRigidArea(osScaleMul(new Dimension(0, 5))));
+ }
+
+ generalPanelLogVerbositySlider = new JSlider();
+ generalPanelLogVerbositySlider.setMajorTickSpacing(1);
+ generalPanelLogVerbositySlider.setLabelTable(generalPanelLogVerbosityLabelTable);
+ generalPanelLogVerbositySlider.setPaintLabels(true);
+ generalPanelLogVerbositySlider.setPaintTicks(true);
+ generalPanelLogVerbositySlider.setSnapToTicks(true);
+ generalPanelLogVerbositySlider.setMinimum(0);
+ generalPanelLogVerbositySlider.setMaximum(5);
+ generalPanelLogVerbositySlider.setPreferredSize(osScaleMul(new Dimension(200, 55)));
+ generalPanelLogVerbositySlider.setAlignmentX(Component.LEFT_ALIGNMENT);
+ generalPanelLogVerbositySlider.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, osScaleMul(5), 0));
+ generalPanelLogVerbositySlider.setOrientation(SwingConstants.HORIZONTAL);
+ generalPanelLogVerbosityPanel.add(generalPanelLogVerbositySlider);
+
+ generalPanelLogTimestampsCheckbox = addCheckbox("Show timestamps in log", generalPanel);
+ generalPanelLogTimestampsCheckbox.setToolTipText(
+ "Displays the time text was output to the log");
+
+ generalPanelLogLevelCheckbox = addCheckbox("Show log level in log", generalPanel);
+ generalPanelLogLevelCheckbox.setToolTipText("Displays the log level of output in the log");
+
+ generalPanelLogForceTimestampsCheckbox = addCheckbox("Force timestamps in log", generalPanel);
+ generalPanelLogForceTimestampsCheckbox.setToolTipText(
+ "Forces display of the time text was output to the log");
+
+ generalPanelLogForceLevelCheckbox = addCheckbox("Force log level in log", generalPanel);
+ generalPanelLogForceLevelCheckbox.setToolTipText(
+ "Forces display of the log level of output in the log");
+
+ generalPanelColoredTextCheckbox = addCheckbox("Coloured console text", generalPanel);
+ generalPanelColoredTextCheckbox.setToolTipText(
+ "When running the client from a console, chat messages in the console will reflect the colours they are in game");
+
+ // UI Settings
+ addSettingsHeader(generalPanel, "UI settings");
+
+ generalPanelUseDarkModeCheckbox =
+ addCheckbox(
+ "Use dark mode for the interface (Requires restart & modern UI theme)", generalPanel);
+ generalPanelUseDarkModeCheckbox.setToolTipText(
+ "Uses the darker UI theme, unless the legacy theme is enabled");
+
+ generalPanelUseNimbusThemeCheckbox =
+ addCheckbox("Use legacy RSCx UI theme (Requires restart)", generalPanel);
+ generalPanelUseNimbusThemeCheckbox.setToolTipText("Uses the legacy RSCx Nimbus look-and-feel");
+
+ if (Util.isModernWindowsOS() && Launcher.OSScalingFactor != 1.0) {
+ generalPanelUseNimbusThemeCheckbox.setEnabled(false);
+ generalPanelUseNimbusThemeCheckbox.setText(
+ "Use legacy RSCx UI theme You must disable OS level scaling in Windows to enable this option (Requires restart)");
+ }
+
+ addPanelBottomGlue(generalPanel);
+
/*
* Overlays tab
*/
@@ -843,7 +1414,6 @@ public void stateChanged(ChangeEvent e) {
addSettingsHeader(overlayPanel, "Interface Overlays");
overlayPanelStatusDisplayCheckbox = addCheckbox("Show HP display", overlayPanel);
overlayPanelStatusDisplayCheckbox.setToolTipText("Toggle hits display");
- overlayPanelStatusDisplayCheckbox.setBorder(new EmptyBorder(0, 0, 10, 0));
overlayPanelBuffsCheckbox =
addCheckbox("Show combat (de)buffs and cooldowns display", overlayPanel);
@@ -875,11 +1445,10 @@ public void stateChanged(ChangeEvent e) {
overlayPanel.add(overlayPanelRscTimesButtonsPanel);
overlayPanelRscTimesButtonsPanel.setLayout(
new BoxLayout(overlayPanelRscTimesButtonsPanel, BoxLayout.X_AXIS));
- overlayPanelRscTimesButtonsPanel.setPreferredSize(new Dimension(0, 37));
overlayPanelRscTimesButtonsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- overlayPanelRscTimesButtonsPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
+ overlayPanelRscTimesButtonsPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
JLabel rsctimesButtonsSpacingLabel = new JLabel("");
- rsctimesButtonsSpacingLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 20));
+ rsctimesButtonsSpacingLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, osScaleMul(20)));
overlayPanelRscTimesButtonsPanel.add(rsctimesButtonsSpacingLabel);
overlayPanelRscTimesButtonsCheckbox =
addCheckbox(
@@ -913,14 +1482,14 @@ public void stateChanged(ChangeEvent e) {
addSettingsHeader(overlayPanel, "XP Bar");
overlayPanelXPBarCheckbox = addCheckbox("Show a Goal bar", overlayPanel);
overlayPanelXPBarCheckbox.setToolTipText("Show a Goal bar to the left of the wrench");
- overlayPanelXPBarCheckbox.setBorder(new EmptyBorder(7, 0, 10, 0));
ButtonGroup XPAlignButtonGroup = new ButtonGroup();
- overlayPanelXPRightAlignFocusButton = addRadioButton("Display on the right", overlayPanel, 20);
+ overlayPanelXPRightAlignFocusButton =
+ addRadioButton("Display on the right", overlayPanel, osScaleMul(20));
overlayPanelXPRightAlignFocusButton.setToolTipText(
"The Goal bar will be shown just left of the Settings menu.");
overlayPanelXPCenterAlignFocusButton =
- addRadioButton("Display in the center", overlayPanel, 20);
+ addRadioButton("Display in the center", overlayPanel, osScaleMul(20));
overlayPanelXPCenterAlignFocusButton.setToolTipText(
"The Goal bar will be shown at the top-middle of the screen.");
XPAlignButtonGroup.add(overlayPanelXPRightAlignFocusButton);
@@ -943,7 +1512,7 @@ public void stateChanged(ChangeEvent e) {
overlayPanelLagIndicatorCheckbox = addCheckbox("Lag indicator", overlayPanel);
overlayPanelLagIndicatorCheckbox.setToolTipText(
- "When there's a problem with your connection, rsctimes will tell you in the bottom right");
+ "When there's a problem with your connection, RSCTimes will tell you in the bottom right");
overlayPanelFoodHealingCheckbox =
addCheckbox("Show food healing overlay (Not implemented yet)", overlayPanel);
@@ -966,7 +1535,6 @@ public void stateChanged(ChangeEvent e) {
addCheckbox("Show hitboxes around NPCs, players, and items", overlayPanel);
overlayPanelHitboxCheckbox.setToolTipText(
"Shows the clickable areas on NPCs, players, and items");
- overlayPanelHitboxCheckbox.setBorder(new EmptyBorder(0, 0, 10, 0));
overlayPanelPlayerNamesCheckbox =
addCheckbox("Show player names over their heads", overlayPanel);
@@ -995,41 +1563,45 @@ public void stateChanged(ChangeEvent e) {
addCheckbox("Display the names of items on the ground", overlayPanel);
overlayPanelItemNamesCheckbox.setToolTipText("Shows the names of dropped items");
+ int itemsTextHeight = isUsingFlatLAFTheme() ? 32 : 37;
+
// Blocked Items
JPanel blockedItemsPanel = new JPanel();
overlayPanel.add(blockedItemsPanel);
blockedItemsPanel.setLayout(new BoxLayout(blockedItemsPanel, BoxLayout.X_AXIS));
- blockedItemsPanel.setPreferredSize(new Dimension(0, 37));
+ blockedItemsPanel.setPreferredSize(osScaleMul(new Dimension(0, itemsTextHeight)));
blockedItemsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- blockedItemsPanel.setBorder(new EmptyBorder(0, 0, 9, 0));
+ blockedItemsPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, osScaleMul(9), 0));
JLabel blockedItemsPanelNameLabel = new JLabel("Blocked items: ");
blockedItemsPanel.add(blockedItemsPanelNameLabel);
- blockedItemsPanelNameLabel.setAlignmentY((float) 0.9);
+ blockedItemsPanelNameLabel.setAlignmentY(0.9f);
blockedItemsTextField = new JTextField();
blockedItemsPanel.add(blockedItemsTextField);
- blockedItemsTextField.setMinimumSize(new Dimension(100, 28));
- blockedItemsTextField.setMaximumSize(new Dimension(Short.MAX_VALUE, 28));
- blockedItemsTextField.setAlignmentY((float) 0.75);
+ blockedItemsTextField.setMinimumSize(osScaleMul(new Dimension(100, 28)));
+ blockedItemsTextField.setMaximumSize(new Dimension(Short.MAX_VALUE, osScaleMul(28)));
+ blockedItemsTextField.setAlignmentY(0.75f);
// Highlighted Items
JPanel highlightedItemsPanel = new JPanel();
overlayPanel.add(highlightedItemsPanel);
highlightedItemsPanel.setLayout(new BoxLayout(highlightedItemsPanel, BoxLayout.X_AXIS));
- highlightedItemsPanel.setPreferredSize(new Dimension(0, 37));
+ highlightedItemsPanel.setPreferredSize(osScaleMul(new Dimension(0, itemsTextHeight)));
highlightedItemsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
- highlightedItemsPanel.setBorder(new EmptyBorder(0, 0, 9, 0));
+ highlightedItemsPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, osScaleMul(9), 0));
JLabel highlightedItemsPanelNameLabel = new JLabel("Highlighted items: ");
highlightedItemsPanel.add(highlightedItemsPanelNameLabel);
- highlightedItemsPanelNameLabel.setAlignmentY((float) 0.9);
+ highlightedItemsPanelNameLabel.setAlignmentY(0.9f);
highlightedItemsTextField = new JTextField();
highlightedItemsPanel.add(highlightedItemsTextField);
- highlightedItemsTextField.setMinimumSize(new Dimension(100, 28));
- highlightedItemsTextField.setMaximumSize(new Dimension(Short.MAX_VALUE, 28));
- highlightedItemsTextField.setAlignmentY((float) 0.75);
+ highlightedItemsTextField.setMinimumSize(osScaleMul(new Dimension(100, 28)));
+ highlightedItemsTextField.setMaximumSize(new Dimension(Short.MAX_VALUE, osScaleMul(28)));
+ highlightedItemsTextField.setAlignmentY(0.75f);
+
+ addPanelBottomGlue(overlayPanel);
/*
* Notifications tab
@@ -1041,29 +1613,31 @@ public void stateChanged(ChangeEvent e) {
notificationPanelTrayPopupCheckbox =
addCheckbox("Enable notification tray popups", notificationPanel);
- notificationPanelTrayPopupCheckbox.setBorder(BorderFactory.createEmptyBorder(0, 0, 7, 0));
+ notificationPanelTrayPopupCheckbox.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, osScaleMul(7), 0));
notificationPanelTrayPopupCheckbox.setToolTipText(
"Shows a system notification when a notification is triggered");
ButtonGroup trayPopupButtonGroup = new ButtonGroup();
notificationPanelTrayPopupClientFocusButton =
- addRadioButton("Only when client is not focused", notificationPanel, 20);
+ addRadioButton("Only when client is not focused", notificationPanel, osScaleMul(20));
notificationPanelTrayPopupAnyFocusButton =
- addRadioButton("Regardless of client focus", notificationPanel, 20);
+ addRadioButton("Regardless of client focus", notificationPanel, osScaleMul(20));
trayPopupButtonGroup.add(notificationPanelTrayPopupClientFocusButton);
trayPopupButtonGroup.add(notificationPanelTrayPopupAnyFocusButton);
notificationPanelNotifSoundsCheckbox =
addCheckbox("Enable notification sounds", notificationPanel);
- notificationPanelNotifSoundsCheckbox.setBorder(BorderFactory.createEmptyBorder(0, 0, 7, 0));
+ notificationPanelNotifSoundsCheckbox.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, osScaleMul(7), 0));
notificationPanelNotifSoundsCheckbox.setToolTipText(
"Plays a sound when a notification is triggered");
ButtonGroup notifSoundButtonGroup = new ButtonGroup();
notificationPanelNotifSoundClientFocusButton =
- addRadioButton("Only when client is not focused", notificationPanel, 20);
+ addRadioButton("Only when client is not focused", notificationPanel, osScaleMul(20));
notificationPanelNotifSoundAnyFocusButton =
- addRadioButton("Regardless of client focus", notificationPanel, 20);
+ addRadioButton("Regardless of client focus", notificationPanel, osScaleMul(20));
notifSoundButtonGroup.add(notificationPanelNotifSoundClientFocusButton);
notifSoundButtonGroup.add(notificationPanelNotifSoundAnyFocusButton);
@@ -1081,7 +1655,8 @@ public void stateChanged(ChangeEvent e) {
addSettingsHeader(notificationPanel, "Notifications");
notificationPanelPMNotifsCheckbox = addCheckbox("Enable PM notifications", notificationPanel);
- notificationPanelPMNotifsCheckbox.setBorder(BorderFactory.createEmptyBorder(0, 0, 7, 0));
+ notificationPanelPMNotifsCheckbox.setBorder(
+ BorderFactory.createEmptyBorder(0, 0, osScaleMul(7), 0));
notificationPanelPMNotifsCheckbox.setToolTipText(
"Shows a system notification when a PM is received");
@@ -1095,16 +1670,11 @@ public void stateChanged(ChangeEvent e) {
notificationPanelUnderAttackNotifsCheckbox.setToolTipText(
"Shows a system notification when a player attacks you");
- notificationPanelLogoutNotifsCheckbox =
- addCheckbox("Enable logout notification", notificationPanel);
- notificationPanelLogoutNotifsCheckbox.setToolTipText(
- "Shows a system notification when about to idle out");
-
JPanel notificationPanelLowHPNotifsPanel = new JPanel();
notificationPanel.add(notificationPanelLowHPNotifsPanel);
notificationPanelLowHPNotifsPanel.setLayout(
new BoxLayout(notificationPanelLowHPNotifsPanel, BoxLayout.X_AXIS));
- notificationPanelLowHPNotifsPanel.setPreferredSize(new Dimension(0, 37));
+ notificationPanelLowHPNotifsPanel.setPreferredSize(osScaleMul(new Dimension(0, 28)));
notificationPanelLowHPNotifsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
notificationPanelLowHPNotifsCheckbox =
@@ -1113,16 +1683,17 @@ public void stateChanged(ChangeEvent e) {
"Shows a system notification when your HP drops below the specified value");
notificationPanelLowHPNotifsSpinner = new JSpinner();
- notificationPanelLowHPNotifsSpinner.setMaximumSize(new Dimension(45, 22));
- notificationPanelLowHPNotifsSpinner.setMinimumSize(new Dimension(45, 22));
- notificationPanelLowHPNotifsSpinner.setAlignmentY((float) 0.75);
+ notificationPanelLowHPNotifsSpinner.setMaximumSize(osScaleMul(new Dimension(55, 22)));
+ notificationPanelLowHPNotifsSpinner.setMinimumSize(osScaleMul(new Dimension(55, 22)));
+ notificationPanelLowHPNotifsSpinner.setAlignmentY(0.75f);
notificationPanelLowHPNotifsPanel.add(notificationPanelLowHPNotifsSpinner);
notificationPanelLowHPNotifsSpinner.putClientProperty("JComponent.sizeVariant", "mini");
JLabel notificationPanelLowHPNotifsEndLabel = new JLabel("% HP");
notificationPanelLowHPNotifsPanel.add(notificationPanelLowHPNotifsEndLabel);
- notificationPanelLowHPNotifsEndLabel.setAlignmentY((float) 0.9);
- notificationPanelLowHPNotifsEndLabel.setBorder(new EmptyBorder(0, 2, 0, 0));
+ notificationPanelLowHPNotifsEndLabel.setAlignmentY(0.8f);
+ notificationPanelLowHPNotifsEndLabel.setBorder(
+ BorderFactory.createEmptyBorder(0, osScaleMul(2), 0, 0));
// Sanitize JSpinner values
SpinnerNumberModel spinnerHPNumModel = new SpinnerNumberModel();
@@ -1136,15 +1707,17 @@ public void stateChanged(ChangeEvent e) {
notificationPanel.add(warnHighlightedOnGroundPanel);
warnHighlightedOnGroundPanel.setLayout(
new BoxLayout(warnHighlightedOnGroundPanel, BoxLayout.X_AXIS));
- warnHighlightedOnGroundPanel.setPreferredSize(new Dimension(0, 37));
+ warnHighlightedOnGroundPanel.setPreferredSize(osScaleMul(new Dimension(0, 28)));
warnHighlightedOnGroundPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+ // TODO: implement feature, remove "setEnabled(false)" below
notificationPanelHighlightedItemTimerCheckbox =
addCheckbox(
"Warn if one of your highlighted items has been on the ground for more than",
warnHighlightedOnGroundPanel);
notificationPanelHighlightedItemTimerCheckbox.setToolTipText(
"Highlighted items can be configured in the Overlays tab");
+ notificationPanelHighlightedItemTimerCheckbox.setEnabled(false);
JLabel highlightedItemsSuggestionJLabel =
new JLabel(
@@ -1152,20 +1725,26 @@ public void stateChanged(ChangeEvent e) {
+ "Note: Loot from kills despawns after about 2 minutes."
+ "