mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
- Making throttle-based targeting overlay optimization optional for users running older hardware at slower CPU clock speeds.
This commit is contained in:
@@ -103,6 +103,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
|||||||
lstControls.add(Pair.of(view.getCbEnableSounds(), FPref.UI_ENABLE_SOUNDS));
|
lstControls.add(Pair.of(view.getCbEnableSounds(), FPref.UI_ENABLE_SOUNDS));
|
||||||
lstControls.add(Pair.of(view.getCbAltSoundSystem(), FPref.UI_ALT_SOUND_SYSTEM));
|
lstControls.add(Pair.of(view.getCbAltSoundSystem(), FPref.UI_ALT_SOUND_SYSTEM));
|
||||||
lstControls.add(Pair.of(view.getCbUiForTouchScreen(), FPref.UI_FOR_TOUCHSCREN));
|
lstControls.add(Pair.of(view.getCbUiForTouchScreen(), FPref.UI_FOR_TOUCHSCREN));
|
||||||
|
lstControls.add(Pair.of(view.getCbTimedTargOverlay(), FPref.UI_TIMED_TARGETING_OVERLAY_UPDATES));
|
||||||
lstControls.add(Pair.of(view.getCbCompactMainMenu(), FPref.UI_COMPACT_MAIN_MENU));
|
lstControls.add(Pair.of(view.getCbCompactMainMenu(), FPref.UI_COMPACT_MAIN_MENU));
|
||||||
lstControls.add(Pair.of(view.getCbPromptFreeBlocks(), FPref.MATCHPREF_PROMPT_FREE_BLOCKS));
|
lstControls.add(Pair.of(view.getCbPromptFreeBlocks(), FPref.MATCHPREF_PROMPT_FREE_BLOCKS));
|
||||||
lstControls.add(Pair.of(view.getCbPauseWhileMinimized(), FPref.UI_PAUSE_WHILE_MINIMIZED));
|
lstControls.add(Pair.of(view.getCbPauseWhileMinimized(), FPref.UI_PAUSE_WHILE_MINIMIZED));
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
private final JCheckBox cbEnableMusic = new OptionsCheckBox("Enable Music");
|
private final JCheckBox cbEnableMusic = new OptionsCheckBox("Enable Music");
|
||||||
private final JCheckBox cbAltSoundSystem = new OptionsCheckBox("Use Alternate Sound System");
|
private final JCheckBox cbAltSoundSystem = new OptionsCheckBox("Use Alternate Sound System");
|
||||||
private final JCheckBox cbUiForTouchScreen = new OptionsCheckBox("Enhance UI for Touchscreens");
|
private final JCheckBox cbUiForTouchScreen = new OptionsCheckBox("Enhance UI for Touchscreens");
|
||||||
|
private final JCheckBox cbTimedTargOverlay = new OptionsCheckBox("Enable Targeting Overlay Optimization");
|
||||||
private final JCheckBox cbCompactMainMenu = new OptionsCheckBox("Use Compact Main Sidebar Menu");
|
private final JCheckBox cbCompactMainMenu = new OptionsCheckBox("Use Compact Main Sidebar Menu");
|
||||||
private final JCheckBox cbDetailedPaymentDesc = new OptionsCheckBox("Spell Description in Payment Prompt");
|
private final JCheckBox cbDetailedPaymentDesc = new OptionsCheckBox("Spell Description in Payment Prompt");
|
||||||
private final JCheckBox cbPromptFreeBlocks = new OptionsCheckBox("Free Block Handling");
|
private final JCheckBox cbPromptFreeBlocks = new OptionsCheckBox("Free Block Handling");
|
||||||
@@ -252,6 +253,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
pnlPrefs.add(cbStackCreatures, regularConstraints);
|
pnlPrefs.add(cbStackCreatures, regularConstraints);
|
||||||
pnlPrefs.add(new NoteLabel("Stacks identical creatures on the battlefield like lands, artifacts, and enchantments."), regularConstraints);
|
pnlPrefs.add(new NoteLabel("Stacks identical creatures on the battlefield like lands, artifacts, and enchantments."), regularConstraints);
|
||||||
|
|
||||||
|
pnlPrefs.add(cbTimedTargOverlay, "w 80%!, gap 10% 0 0 10px, span 2 1");
|
||||||
|
pnlPrefs.add(new NoteLabel("Enables throttling-based optimization of targeting overlay to reduce CPU use (only disable if you experience choppiness on older hardware, requires starting a new match)"), regularConstraints);
|
||||||
|
|
||||||
pnlPrefs.add(cbpDisplayCurrentCardColors, "w 80%!, gap 10% 0 0 10px, span 2 1");
|
pnlPrefs.add(cbpDisplayCurrentCardColors, "w 80%!, gap 10% 0 0 10px, span 2 1");
|
||||||
pnlPrefs.add(new NoteLabel("Displays the breakdown of the current color of cards in the card detail information panel."), regularConstraints);
|
pnlPrefs.add(new NoteLabel("Displays the breakdown of the current color of cards in the card detail information panel."), regularConstraints);
|
||||||
|
|
||||||
@@ -582,6 +586,11 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
return cbAltSoundSystem;
|
return cbAltSoundSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return {@link javax.swing.JCheckBox} */
|
||||||
|
public JCheckBox getCbTimedTargOverlay() {
|
||||||
|
return cbTimedTargOverlay;
|
||||||
|
}
|
||||||
|
|
||||||
public final JCheckBox getCbUiForTouchScreen() {
|
public final JCheckBox getCbUiForTouchScreen() {
|
||||||
return cbUiForTouchScreen;
|
return cbUiForTouchScreen;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ import forge.game.card.CardView;
|
|||||||
import forge.game.combat.CombatView;
|
import forge.game.combat.CombatView;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.StackItemView;
|
import forge.game.spellability.StackItemView;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgePreferences;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.match.controllers.CDock.ArcState;
|
import forge.screens.match.controllers.CDock.ArcState;
|
||||||
import forge.screens.match.views.VField;
|
import forge.screens.match.views.VField;
|
||||||
import forge.screens.match.views.VStack.StackInstanceTextArea;
|
import forge.screens.match.views.VStack.StackInstanceTextArea;
|
||||||
@@ -101,8 +104,102 @@ public class TargetingOverlay {
|
|||||||
return this.pnl;
|
return this.pnl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Though this is called on every repaint, we take means to avoid it fully
|
// The original version of assembleArcs, without code to throttle it.
|
||||||
// running every time (to reduce CPU usage).
|
// Re-added as the new version was causing issues for at least one user.
|
||||||
|
private void assembleArcs(final CombatView combat) {
|
||||||
|
//List<VField> fields = VMatchUI.SINGLETON_INSTANCE.getFieldViews();
|
||||||
|
arcsFoe.clear();
|
||||||
|
arcsFriend.clear();
|
||||||
|
cardPanels.clear();
|
||||||
|
cardsVisualized.clear();
|
||||||
|
|
||||||
|
final StackInstanceTextArea activeStackItem = matchUI.getCStack().getView().getHoveredItem();
|
||||||
|
|
||||||
|
switch (matchUI.getCDock().getArcState()) {
|
||||||
|
case OFF:
|
||||||
|
return;
|
||||||
|
case MOUSEOVER:
|
||||||
|
// Draw only hovered card
|
||||||
|
activePanel = null;
|
||||||
|
for (final VField f : matchUI.getFieldViews()) {
|
||||||
|
cardPanels.addAll(f.getTabletop().getCardPanels());
|
||||||
|
final List<CardPanel> cPanels = f.getTabletop().getCardPanels();
|
||||||
|
for (final CardPanel c : cPanels) {
|
||||||
|
if (c.isSelected()) {
|
||||||
|
activePanel = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (activePanel == null && activeStackItem == null) { return; }
|
||||||
|
break;
|
||||||
|
case ON:
|
||||||
|
// Draw all
|
||||||
|
for (final VField f : matchUI.getFieldViews()) {
|
||||||
|
cardPanels.addAll(f.getTabletop().getCardPanels());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//final Point docOffsets = FView.SINGLETON_INSTANCE.getLpnDocument().getLocationOnScreen();
|
||||||
|
// Locations of arc endpoint, per card, with ID as primary key.
|
||||||
|
final Map<Integer, Point> endpoints = new HashMap<Integer, Point>();
|
||||||
|
|
||||||
|
Point cardLocOnScreen;
|
||||||
|
Point locOnScreen = this.getPanel().getLocationOnScreen();
|
||||||
|
|
||||||
|
for (CardPanel c : cardPanels) {
|
||||||
|
if (c.isShowing()) {
|
||||||
|
cardLocOnScreen = c.getCardLocationOnScreen();
|
||||||
|
endpoints.put(c.getCard().getId(), new Point(
|
||||||
|
(int) (cardLocOnScreen.getX() - locOnScreen.getX() + (float)c.getWidth() * CardPanel.TARGET_ORIGIN_FACTOR_X),
|
||||||
|
(int) (cardLocOnScreen.getY() - locOnScreen.getY() + (float)c.getHeight() * CardPanel.TARGET_ORIGIN_FACTOR_Y)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchUI.getCDock().getArcState() == ArcState.MOUSEOVER) {
|
||||||
|
// Only work with the active panel
|
||||||
|
if (activePanel != null) {
|
||||||
|
addArcsForCard(activePanel.getCard(), endpoints, combat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Work with all card panels currently visible
|
||||||
|
for (final CardPanel c : cardPanels) {
|
||||||
|
if (!c.isShowing()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
addArcsForCard(c.getCard(), endpoints, combat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw arrow connecting active item on stack
|
||||||
|
if (activeStackItem != null) {
|
||||||
|
Point itemLocOnScreen = activeStackItem.getLocationOnScreen();
|
||||||
|
if (itemLocOnScreen != null) {
|
||||||
|
itemLocOnScreen.x += StackInstanceTextArea.CARD_WIDTH * CardPanel.TARGET_ORIGIN_FACTOR_X + StackInstanceTextArea.PADDING - locOnScreen.getX();
|
||||||
|
itemLocOnScreen.y += StackInstanceTextArea.CARD_HEIGHT * CardPanel.TARGET_ORIGIN_FACTOR_Y + StackInstanceTextArea.PADDING - locOnScreen.getY();
|
||||||
|
|
||||||
|
StackItemView instance = activeStackItem.getItem();
|
||||||
|
PlayerView activator = instance.getActivatingPlayer();
|
||||||
|
while (instance != null) {
|
||||||
|
for (CardView c : instance.getTargetCards()) {
|
||||||
|
addArc(endpoints.get(c.getId()), itemLocOnScreen, activator.isOpponentOf(c.getController()));
|
||||||
|
}
|
||||||
|
for (PlayerView p : instance.getTargetPlayers()) {
|
||||||
|
Point point = getPlayerTargetingArrowPoint(p, locOnScreen);
|
||||||
|
if(point != null) {
|
||||||
|
addArc(point, itemLocOnScreen, activator.isOpponentOf(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instance = instance.getSubInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A throttled version of assembleArcs. Though it is still called on every
|
||||||
|
// repaint, we take means to avoid it fully running every time (to reduce CPU usage).
|
||||||
private boolean assembleArcs(final CombatView combat, boolean forceAssemble) {
|
private boolean assembleArcs(final CombatView combat, boolean forceAssemble) {
|
||||||
if (!forceAssemble) {
|
if (!forceAssemble) {
|
||||||
/* -- Minimum update frequency timer, currently disabled --
|
/* -- Minimum update frequency timer, currently disabled --
|
||||||
@@ -203,6 +300,7 @@ public class TargetingOverlay {
|
|||||||
return endpoints;
|
return endpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This section is a refactored portion of the new-style assembleArcs.
|
||||||
private void assembleStackArrows() {
|
private void assembleStackArrows() {
|
||||||
final StackInstanceTextArea activeStackItem = matchUI.getCStack().getView().getHoveredItem();
|
final StackInstanceTextArea activeStackItem = matchUI.getCStack().getView().getHoveredItem();
|
||||||
|
|
||||||
@@ -356,7 +454,9 @@ public class TargetingOverlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class OverlayPanel extends SkinnedPanel {
|
private class OverlayPanel extends SkinnedPanel {
|
||||||
// Arrow drawing code by the MAGE team, used with permission.
|
private final boolean useThrottling = FModel.getPreferences().getPrefBoolean(FPref.UI_TIMED_TARGETING_OVERLAY_UPDATES);
|
||||||
|
|
||||||
|
// Arrow drawing code by the XMage team, used with permission.
|
||||||
private Area getArrow(float length, float bendPercent) {
|
private Area getArrow(float length, float bendPercent) {
|
||||||
float p1x = 0, p1y = 0;
|
float p1x = 0, p1y = 0;
|
||||||
float p2x = length, p2y = 0;
|
float p2x = length, p2y = 0;
|
||||||
@@ -453,13 +553,18 @@ public class TargetingOverlay {
|
|||||||
boolean assembled = false;
|
boolean assembled = false;
|
||||||
final GameView gameView = matchUI.getGameView();
|
final GameView gameView = matchUI.getGameView();
|
||||||
if (gameView != null) {
|
if (gameView != null) {
|
||||||
assembled = assembleArcs(gameView.getCombat(), false);
|
if (useThrottling) {
|
||||||
assembleStackArrows();
|
assembled = assembleArcs(gameView.getCombat(), false);
|
||||||
|
assembleStackArrows();
|
||||||
|
} else {
|
||||||
|
assembleArcs(gameView.getCombat());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arcsFoe.isEmpty() && arcsFriend.isEmpty()) {
|
if (arcsFoe.isEmpty() && arcsFriend.isEmpty()) {
|
||||||
if (assembled) {
|
if (assembled) {
|
||||||
// We still need to repaint to get rid of visual artifacts
|
// We still need to repaint to get rid of visual artifacts
|
||||||
|
// The original (non-throttled) code did not do this repaint.
|
||||||
FView.SINGLETON_INSTANCE.getFrame().repaint();
|
FView.SINGLETON_INSTANCE.getFrame().repaint();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -481,7 +586,7 @@ public class TargetingOverlay {
|
|||||||
drawArcs(g2d, colorOther, arcsFriend);
|
drawArcs(g2d, colorOther, arcsFriend);
|
||||||
drawArcs(g2d, colorCombat, arcsFoe);
|
drawArcs(g2d, colorCombat, arcsFoe);
|
||||||
|
|
||||||
if (assembled) {
|
if (assembled || !useThrottling) {
|
||||||
FView.SINGLETON_INSTANCE.getFrame().repaint(); // repaint the match UI
|
FView.SINGLETON_INSTANCE.getFrame().repaint(); // repaint the match UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ This release features most Commander 2016 cards scripted and ready to play. The
|
|||||||
- User interface updates and changes -
|
- User interface updates and changes -
|
||||||
Some notable modifications were made to the Forge UI for desktop computers. First of all, many pop-up prompts have been replaced with prompt window queries - for example, Scry 1 now shows the request to put the card on the top or bottom of the library in the prompt window instead of a pop-up dialog window, and allows to view the card in question by moving the mouse over the prompt window, which is more convenient. Second of all, in both desktop and mobile Forge, there is now an option in Forge Preferences called "Preselect Last Order of Abilities" that preselects the last known order of simultaneous abilities, thus making it possible to just use "Space" once to confirm the previous order instead of having to press Space for each ability or clicking the ">>" button to add the previous order once more. This option is currently disabled by default to avoid being confusing to users who are used to doing it the way it used to be before. Also, there is now an option to view detailed spell ability descriptions in the prompt window during mana payment and targeting, which is enabled by default but can be enabled/disabled in Forge preferences ("Spell Description in Payment Prompt" under the "Gameplay" preference group).
|
Some notable modifications were made to the Forge UI for desktop computers. First of all, many pop-up prompts have been replaced with prompt window queries - for example, Scry 1 now shows the request to put the card on the top or bottom of the library in the prompt window instead of a pop-up dialog window, and allows to view the card in question by moving the mouse over the prompt window, which is more convenient. Second of all, in both desktop and mobile Forge, there is now an option in Forge Preferences called "Preselect Last Order of Abilities" that preselects the last known order of simultaneous abilities, thus making it possible to just use "Space" once to confirm the previous order instead of having to press Space for each ability or clicking the ">>" button to add the previous order once more. This option is currently disabled by default to avoid being confusing to users who are used to doing it the way it used to be before. Also, there is now an option to view detailed spell ability descriptions in the prompt window during mana payment and targeting, which is enabled by default but can be enabled/disabled in Forge preferences ("Spell Description in Payment Prompt" under the "Gameplay" preference group).
|
||||||
|
|
||||||
|
- Targeting Overlay Optional Optimization -
|
||||||
|
Throttling-based targeting overlay optimization aimed at eliminating continuous CPU use has been made optional (but enabled by default). Most users running modern hardware will want this option enabled because it will significantly reduce CPU use when playing Forge, especially when playing with the targeting overlay always on. However, some users running older hardware at slower CPU clock speed may experience choppiness (for example, when dragging card panels in hand), in which case we advise you to try disabling the option "Enabled Targeting Overlay Optimization" in Forge preferences under "Graphic Options".
|
||||||
|
|
||||||
- AI updates -
|
- AI updates -
|
||||||
Artificial intelligence received several improvements and fixes. The AI should now be able to use mana ritual cards (Dark Ritual and similar cards), sacrifice-and-upgrade cards (Birthing Pod, Eldritch Evolution, Natural Order). AI for some other card groups has been improved. The AI should no longer animate manlands with other manlands that were animated during the same turn, it should not instantly sac Bomat Courier, no longer kill itself by activating Smallpox and Pox at 1 life. The AI should now be able to use Spellskite correctly (at least when redirecting a single targeted ability). Some other improvements and modifications were made as well, hopefully making the AI more fun to play against.
|
Artificial intelligence received several improvements and fixes. The AI should now be able to use mana ritual cards (Dark Ritual and similar cards), sacrifice-and-upgrade cards (Birthing Pod, Eldritch Evolution, Natural Order). AI for some other card groups has been improved. The AI should no longer animate manlands with other manlands that were animated during the same turn, it should not instantly sac Bomat Courier, no longer kill itself by activating Smallpox and Pox at 1 life. The AI should now be able to use Spellskite correctly (at least when redirecting a single targeted ability). Some other improvements and modifications were made as well, hopefully making the AI more fun to play against.
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
|||||||
UI_SKIN ("Default"),
|
UI_SKIN ("Default"),
|
||||||
UI_PREFERRED_AVATARS_ONLY ("false"),
|
UI_PREFERRED_AVATARS_ONLY ("false"),
|
||||||
UI_TARGETING_OVERLAY ("0"),
|
UI_TARGETING_OVERLAY ("0"),
|
||||||
|
UI_TIMED_TARGETING_OVERLAY_UPDATES ("true"),
|
||||||
UI_ENABLE_SOUNDS ("true"),
|
UI_ENABLE_SOUNDS ("true"),
|
||||||
UI_ENABLE_MUSIC ("true"),
|
UI_ENABLE_MUSIC ("true"),
|
||||||
UI_ALT_SOUND_SYSTEM ("false"),
|
UI_ALT_SOUND_SYSTEM ("false"),
|
||||||
|
|||||||
Reference in New Issue
Block a user