diff --git a/assets/ArkPetsConfigDefault.json b/assets/ArkPetsConfigDefault.json
index 3f5c6230..e73b88d1 100644
--- a/assets/ArkPetsConfigDefault.json
+++ b/assets/ArkPetsConfigDefault.json
@@ -20,5 +20,6 @@
"physic_speed_limit_x":1000.0,
"physic_speed_limit_y":1000.0,
"physic_static_friction_acc":500.0,
- "window_style_toolwindow":true
+ "window_style_toolwindow":true,
+ "window_style_topmost":true
}
\ No newline at end of file
diff --git a/assets/UI/SettingsModule.fxml b/assets/UI/SettingsModule.fxml
index 96092e86..bcce1952 100644
--- a/assets/UI/SettingsModule.fxml
+++ b/assets/UI/SettingsModule.fxml
@@ -35,14 +35,14 @@
-
-
+
+
diff --git a/core/src/cn/harryh/arkpets/ArkConfig.java b/core/src/cn/harryh/arkpets/ArkConfig.java
index 285024cb..e2889add 100644
--- a/core/src/cn/harryh/arkpets/ArkConfig.java
+++ b/core/src/cn/harryh/arkpets/ArkConfig.java
@@ -84,6 +84,8 @@ public class ArkConfig implements Serializable {
public float physic_speed_limit_y;
/** @since ArkPets 3.2 */ @JSONField(defaultValue = "true")
public boolean window_style_toolwindow;
+ /** @since ArkPets 3.2 */ @JSONField(defaultValue = "true")
+ public boolean window_style_topmost;
private ArkConfig() {
}
diff --git a/core/src/cn/harryh/arkpets/ArkPets.java b/core/src/cn/harryh/arkpets/ArkPets.java
index a35a4d9c..30d68586 100644
--- a/core/src/cn/harryh/arkpets/ArkPets.java
+++ b/core/src/cn/harryh/arkpets/ArkPets.java
@@ -18,7 +18,6 @@
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
@@ -44,10 +43,8 @@ public class ArkPets extends ApplicationAdapter implements InputProcessor {
private final String APP_TITLE;
private final MouseStatus mouseStatus = new MouseStatus();
- private int APP_FPS = fpsDefault;
- private float WD_SCALE; // Window Scale
- private int WD_W; // Window Real Width
- private int WD_H; // Window Real Height
+ private int width; // Window Real Width
+ private int height; // Window Real Height
private int offsetY = 0;
private boolean isToolwindowStyle = false;
private boolean isAlwaysTransparent = false;
@@ -61,11 +58,10 @@ public void create() {
// When the APP was created
// 1.App setup
Logger.info("App", "Create with title \"" + APP_TITLE + "\"");
+ config = Objects.requireNonNull(ArkConfig.getConfig(), "ArkConfig returns a null instance, please check the config file.");
Gdx.input.setInputProcessor(this);
- config = Objects.requireNonNull(ArkConfig.getConfig());
- APP_FPS = config.display_fps;
- Gdx.graphics.setForegroundFPS(APP_FPS);
- getHWndLoopCtrl = new LoopCtrl(1f / APP_FPS * 4);
+ Gdx.graphics.setForegroundFPS(config.display_fps);
+
// 2.Character setup
Logger.info("App", "Using model asset \"" + config.character_asset + "\"");
cha = new ArkChar(config, skelBaseScale);
@@ -73,25 +69,39 @@ public void create() {
cha.adjustCanvas(behavior.defaultAnim().animClip().stage);
cha.setAnimation(behavior.defaultAnim());
Logger.info("Animation", "Available animation stages " + behavior.getStages());
- // 3.Window params setup
- windowPosition = new TransitionVector2(TernaryFunction.EASE_OUT_CUBIC, easingDuration);
- windowAlpha = new TransitionFloat(TernaryFunction.EASE_OUT_CUBIC, easingDuration);
- windowAlpha.reset(1f);
- WD_SCALE = config.display_scale;
- WD_W = (int)(WD_SCALE * cha.camera.getWidth());
- WD_H = (int)(WD_SCALE * cha.camera.getHeight());
- // 4.Plane setup
- plane = new Plane(new ArrayList<>());
+
+ // 3.Plane setup
+ width = (int)(config.display_scale * cha.camera.getWidth());
+ height = (int)(config.display_scale * cha.camera.getHeight());
+ plane = new Plane();
plane.setGravity(config.physic_gravity_acc);
plane.setResilience(0);
plane.setFrict(config.physic_air_friction_acc, config.physic_static_friction_acc);
- plane.setObjSize(WD_W, WD_H);
+ plane.setObjSize(width, height);
plane.setSpeedLimit(config.physic_speed_limit_x, config.physic_speed_limit_y);
- ArkConfig.Monitor primaryMonitor = ArkConfig.Monitor.getMonitors()[0];
- initWindow((int)(primaryMonitor.size[0] * config.initial_position_x - (WD_SCALE * cha.camera.getWidth()) / 2),
- (int)(primaryMonitor.size[1] * config.initial_position_y));
- // 5.Tray icon setup
+ ArkConfig.Monitor primaryMonitor = refreshMonitorInfo();
+ plane.changePosition(0,
+ primaryMonitor.size[0] * config.initial_position_x - width / 2f,
+ -(primaryMonitor.size[1] * config.initial_position_y + height)
+ );
+
+ // 4.Window position setup
+ getHWndLoopCtrl = new LoopCtrl(1f / config.display_fps * 4);
+ windowPosition = new TransitionVector2(TernaryFunction.EASE_OUT_CUBIC, easingDuration);
+ windowPosition.reset(plane.getX(), - (height + plane.getY()) + offsetY);
+ windowPosition.setToEnd();
+ setWindowPos();
+
+ // 5.Window style setup
+ windowAlpha = new TransitionFloat(TernaryFunction.EASE_OUT_CUBIC, easingDuration);
+ windowAlpha.reset(1f);
+ hWndMine = new HWndCtrl(null, APP_TITLE);
+ hWndMine.setWindowExStyle(HWndCtrl.WS_EX_LAYERED | (config.window_style_topmost ? HWndCtrl.WS_EX_TOPMOST : 0));
+ promiseToolwindowStyle(1000);
+
+ // 6.Tray icon setup
tray = new MemberTrayImpl(this, new SocketClient());
+
// Setup complete
Logger.info("App", "Render");
}
@@ -127,7 +137,7 @@ public void render() {
changeAnimation(newAnim); // Apply the new anim.
// 3.Window properties.
- windowPosition.reset(plane.getX(), - (WD_H + plane.getY()) + offsetY);
+ windowPosition.reset(plane.getX(), - (height + plane.getY()) + offsetY);
windowPosition.addProgress(Gdx.graphics.getDeltaTime());
setWindowPos();
if (!windowAlpha.isEnded()) {
@@ -156,9 +166,9 @@ public void changeStage() {
if (canChangeStage()) {
behavior.nextStage();
cha.adjustCanvas(behavior.getCurrentStage());
- WD_W = (int)(WD_SCALE * cha.camera.getWidth());
- WD_H = (int)(WD_SCALE * cha.camera.getHeight());
- plane.setObjSize(WD_W, WD_H);
+ width = (int)(config.display_scale * cha.camera.getWidth());
+ height = (int)(config.display_scale * cha.camera.getHeight());
+ plane.setObjSize(width, height);
Logger.info("Animation", "Changed to " + behavior.getCurrentStage());
changeAnimation(behavior.defaultAnim());
}
@@ -196,7 +206,7 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) {
tray.hideDialog();
} else if (button == Input.Buttons.RIGHT) {
// Right Click: Toggle the menu
- tray.toggleDialog((int)(plane.getX() + screenX), (int)(-plane.getY() - WD_H));
+ tray.toggleDialog((int)(plane.getX() + screenX), (int)(-plane.getY() - height));
}
}
}
@@ -213,7 +223,7 @@ public boolean touchDragged(int screenX, int screenY, int pointer) {
// Update window position
int x = (int)(windowPosition.now().x + screenX - mouseStatus.x);
int y = (int)(windowPosition.now().y + screenY - mouseStatus.y);
- plane.changePosition(Gdx.graphics.getDeltaTime(), x, -(WD_H + y));
+ plane.changePosition(Gdx.graphics.getDeltaTime(), x, -(height + y));
windowPosition.setToEnd();
tray.hideDialog();
return true;
@@ -293,38 +303,20 @@ public boolean scrolled(float a, float b) {
}
private boolean isMouseAtSolidPixel() {
- int pixel = cha.getPixel(mouseStatus.x, WD_H - mouseStatus.y - 1);
+ int pixel = cha.getPixel(mouseStatus.x, height - mouseStatus.y - 1);
return (pixel & 0x000000FF) > 0;
}
/* WINDOW OPERATIONS */
- private void initWindow(int x, int y) {
- // Initialize HWnd
- if (hWndMine == null || hWndMine.isEmpty())
- hWndMine = new HWndCtrl(null, APP_TITLE);
- hWndTopmost = refreshWindowIdx();
- // Set the initial style of the window
- hWndMine.setWindowExStyle(HWndCtrl.WS_EX_LAYERED | HWndCtrl.WS_EX_TOPMOST);
- hWndMine.setWindowTransparent(false);
- refreshMonitorInfo();
- promiseToolwindowStyle(1000);
- // Set the initial position of the window
- plane.changePosition(0, x, - (y + WD_H));
- windowPosition.reset(plane.getX(), - (WD_H + plane.getY()) + offsetY);
- windowPosition.setToEnd();
- setWindowPos();
- }
-
private void setWindowPos() {
if (hWndMine == null) return;
if (getHWndLoopCtrl.isExecutable(Gdx.graphics.getDeltaTime())) {
refreshMonitorInfo();
- HWndCtrl new_hwnd_topmost = refreshWindowIdx();
- if (new_hwnd_topmost != hWndTopmost)
- hWndTopmost = new_hwnd_topmost;
+ HWndCtrl new_hwnd_topmost = refreshWindowIndex();
+ hWndTopmost = new_hwnd_topmost != hWndTopmost ? new_hwnd_topmost : hWndTopmost;
hWndMine.setWindowTransparent(isAlwaysTransparent);
}
- hWndMine.setWindowPosition(hWndTopmost, (int)windowPosition.now().x, (int)windowPosition.now().y, WD_W, WD_H);
+ hWndMine.setWindowPosition(hWndTopmost, (int)windowPosition.now().x, (int)windowPosition.now().y, width, height);
}
private RelativeWindowPosition getRelativeWindowPositionAt(int x, int y) {
@@ -344,11 +336,11 @@ private RelativeWindowPosition getRelativeWindowPositionAt(int x, int y) {
return null;
}
- private HWndCtrl refreshWindowIdx() {
+ private HWndCtrl refreshWindowIndex() {
hWndList = HWndCtrl.getWindowList(true);
HWndCtrl minWindow = null;
HashMap line = new HashMap<>();
- int myPos = (int)(windowPosition.now().x + WD_W / 2);
+ int myPos = (int)(windowPosition.now().x + width / 2);
int minNum = 2048;
int myNum = coreTitleManager.getNumber(APP_TITLE);
final float quantityProduct = 1;
@@ -399,18 +391,18 @@ private HWndCtrl refreshWindowIdx() {
}
}
}
- return minWindow; // Return the last peer window.
+ return config.window_style_topmost ? minWindow : HWndCtrl.EMPTY; // Return the last peer window.
}
- private void refreshMonitorInfo() {
+ private ArkConfig.Monitor refreshMonitorInfo() {
ArkConfig.Monitor[] monitors = ArkConfig.Monitor.getMonitors();
if (monitors.length == 0) {
- Logger.error("App", "Failed to get monitors information");
- throw new RuntimeException("Launch ArkPets failed due to monitors config error.");
+ Logger.error("App", "Failed to get monitors information since no monitor has been found");
+ throw new RuntimeException("Failed to refresh monitors config.");
}
plane.world.clear();
boolean flag = true;
- for (ArkConfig.Monitor i : ArkConfig.Monitor.getMonitors()) {
+ for (ArkConfig.Monitor i : monitors) {
if (!flag) break;
flag = config.display_multi_monitors;
float left = i.virtual[0];
@@ -419,6 +411,7 @@ private void refreshMonitorInfo() {
float bottom = top - i.size[1] + config.display_margin_bottom;
plane.world.add(new Plane.RectArea(left, right, top, bottom));
}
+ return monitors[0];
}
private void promiseToolwindowStyle(int maxRetries) {
@@ -440,7 +433,7 @@ private void promiseToolwindowStyle(int maxRetries) {
/* WINDOW WALKING RELATED */
private void walkWindow(float len) {
- float expectedLen = len * WD_SCALE * (30f / APP_FPS);
+ float expectedLen = len * config.display_scale * (30f / config.display_fps);
int realLen = randomRound(expectedLen);
float newPlaneX = plane.getX() + realLen;
plane.changePosition(Gdx.graphics.getDeltaTime(), newPlaneX, plane.getY());
@@ -455,7 +448,7 @@ private int randomRound(float val) {
private boolean willReachBorder(float len) {
if (plane == null) return false;
- return (plane.getX() >= plane.borderRight() - WD_W && len > 0) || (plane.getX() <= plane.borderLeft() && len < 0);
+ return (plane.getX() >= plane.borderRight() - width && len > 0) || (plane.getX() <= plane.borderLeft() && len < 0);
}
diff --git a/core/src/cn/harryh/arkpets/utils/HWndCtrl.java b/core/src/cn/harryh/arkpets/utils/HWndCtrl.java
index 20b8579f..2211027e 100644
--- a/core/src/cn/harryh/arkpets/utils/HWndCtrl.java
+++ b/core/src/cn/harryh/arkpets/utils/HWndCtrl.java
@@ -301,7 +301,7 @@ public static class NumberedTitleManager {
public NumberedTitleManager(String coreName) {
zeroNameFormat = coreName;
numberedNameFormat = coreName + " (%d)";
- zeroNamePattern = Pattern.compile("^" + coreName + "(?! \\([0-9]+\\))");
+ zeroNamePattern = Pattern.compile("^" + coreName + "$");
numberedNamePattern = Pattern.compile("^" + coreName + " \\(([0-9]+)\\)");
}
diff --git a/core/src/cn/harryh/arkpets/utils/Plane.java b/core/src/cn/harryh/arkpets/utils/Plane.java
index f2841819..d9f04cf7 100644
--- a/core/src/cn/harryh/arkpets/utils/Plane.java
+++ b/core/src/cn/harryh/arkpets/utils/Plane.java
@@ -26,12 +26,11 @@ public class Plane {
private float droppedHeight = 0;
/** Initializes a plane with gravity field.
- * @param world The collection of all available areas.
*/
- public Plane(ArrayList world) {
+ public Plane() {
barriers = new ArrayList<>();
pointCharges = new ArrayList<>();
- this.world = world;
+ this.world = new ArrayList<>();
obj = new Vector2(0, 0);
position = new Vector2(0, 0);
speed = new Vector2(0, 0);
diff --git a/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java b/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java
index 183db85e..ea9da82a 100644
--- a/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java
+++ b/desktop/src/cn/harryh/arkpets/controllers/SettingsModule.java
@@ -38,6 +38,8 @@ public final class SettingsModule implements Controller {
@FXML
private JFXComboBox> configCanvasSize;
@FXML
+ private JFXCheckBox configWindowTopmost;
+ @FXML
private JFXComboBox configLoggingLevel;
@FXML
private Label exploreLogDir;
@@ -121,11 +123,17 @@ public Handbook getHandbook() {
return new ControlHandbook((Labeled)configCanvasSize.getParent().getChildrenUnmodifiable().get(0)) {
@Override
public String getContent() {
- return "桌宠窗口边界的相对大小。更宽的边界能够防止动画溢出;更窄的边界能够防止鼠标误触。";
+ return "设置桌宠窗口边界的相对大小。更宽的边界能够防止动画溢出;更窄的边界能够防止鼠标误触。";
}
};
}
};
+
+ configWindowTopmost.setSelected(app.config.window_style_topmost);
+ configWindowTopmost.setOnAction(e -> {
+ app.config.window_style_topmost = configWindowTopmost.isSelected();
+ app.config.save();
+ });
}
private void initConfigAdvanced() {
@@ -237,7 +245,7 @@ public Handbook getHandbook() {
return new ControlHandbook(configWindowToolwindow) {
@Override
public String getContent() {
- return "桌宠将以后台工具程序的样式启动。启用时,桌宠不会在任务栏中显示程序图标。禁用时,作为普通程序的桌宠可以被直播流软件捕获。";
+ return "启用时,桌宠将以后台工具程序的样式启动,不会在任务栏中显示程序图标。禁用时,作为普通程序启动的桌宠可以被直播流软件捕获。";
}
};
}