mirror of
https://github.com/dualshock-tools/dualshock-tools.github.io.git
synced 2026-03-01 11:19:54 +03:00
Add stick dials to the range calibration modal
This commit is contained in:
10
css/main.css
10
css/main.css
@@ -114,6 +114,16 @@ dl.row dd {
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
|
||||
/* Pulsing animation for text */
|
||||
@keyframes pulse-text {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
.pulsing-text {
|
||||
animation: pulse-text 0.75s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Set text color to red for internationalized elements */
|
||||
/* .ds-i18n {
|
||||
color: red;
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="setCenterCalibrationMethod('quick', event)">
|
||||
<i class="fas fa-check me-2" id="check-quick" style="visibility: hidden;"></i><span class="ds-i18n">Use quick calibration</span>
|
||||
<i class="fas fa-check me-2" id="check-quick" style="display: none;"></i><span class="ds-i18n">Use quick calibration</span>
|
||||
</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="setCenterCalibrationMethod('four-step', event)">
|
||||
<i class="fas fa-check me-2" id="check-four-step"></i><span class="ds-i18n">Use four-step calibration</span>
|
||||
@@ -200,7 +200,7 @@
|
||||
<i class="fas fa-check me-2" id="check-range-normal"></i><span class="ds-i18n">Use normal mode</span>
|
||||
</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="setRangeCalibrationMethod('expert', event)">
|
||||
<i class="fas fa-check me-2" id="check-range-expert" style="visibility: hidden;"></i><span class="ds-i18n">Use expert mode</span>
|
||||
<i class="fas fa-check me-2" id="check-range-expert" style="display: none;"></i><span class="ds-i18n">Use expert mode</span>
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
21
js/core.js
21
js/core.js
@@ -5,10 +5,10 @@ import { initControllerManager } from './controller-manager.js';
|
||||
import ControllerFactory from './controllers/controller-factory.js';
|
||||
import { lang_init, l } from './translations.js';
|
||||
import { loadAllTemplates } from './template-loader.js';
|
||||
import { draw_stick_position, CIRCULARITY_DATA_SIZE } from './stick-renderer.js';
|
||||
import { draw_stick_dial, CIRCULARITY_DATA_SIZE } from './stick-renderer.js';
|
||||
import { ds5_finetune, isFinetuneVisible, finetune_handle_controller_input } from './modals/finetune-modal.js';
|
||||
import { calibrate_stick_centers, auto_calibrate_stick_centers } from './modals/calib-center-modal.js';
|
||||
import { calibrate_range } from './modals/calib-range-modal.js';
|
||||
import { calibrate_range, rangeCalibHandleControllerInput } from './modals/calib-range-modal.js';
|
||||
import {
|
||||
show_quick_test_modal,
|
||||
isQuickTestVisible,
|
||||
@@ -526,14 +526,14 @@ function refresh_stick_pos() {
|
||||
const enable_circ_test = circ_checked();
|
||||
|
||||
// Draw left stick
|
||||
draw_stick_position(ctx, hb, yb, sz, plx, ply, {
|
||||
draw_stick_dial(ctx, hb, yb, sz, plx, ply, {
|
||||
circularity_data: enable_circ_test ? ll_data : null,
|
||||
enable_zoom_center,
|
||||
});
|
||||
|
||||
if(!hasSingleStick) {
|
||||
// Draw right stick
|
||||
draw_stick_position(ctx, w-hb, yb, sz, prx, pry, {
|
||||
draw_stick_dial(ctx, w-hb, yb, sz, prx, pry, {
|
||||
circularity_data: enable_circ_test ? rr_data : null,
|
||||
enable_zoom_center,
|
||||
});
|
||||
@@ -763,10 +763,23 @@ function detectFailedRangeCalibration(changes) {
|
||||
}
|
||||
}
|
||||
|
||||
function isRangeCalibrationVisible() {
|
||||
const modal = document.getElementById('rangeModal');
|
||||
if (!modal) return false;
|
||||
return modal.classList.contains('show');
|
||||
}
|
||||
|
||||
// Callback function to handle UI updates after controller input processing
|
||||
function handleControllerInput({ changes, inputConfig, touchPoints, batteryStatus }) {
|
||||
const { buttonMap } = inputConfig;
|
||||
|
||||
// Update range calibration modal stick visualization if visible
|
||||
if (isRangeCalibrationVisible() && changes.sticks) {
|
||||
collectCircularityData(changes.sticks, ll_data, rr_data);
|
||||
rangeCalibHandleControllerInput(changes);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Quick Test Modal input (can be open from any tab)
|
||||
if (isQuickTestVisible()) {
|
||||
quicktest_handle_controller_input(changes, batteryStatus);
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
|
||||
import { sleep } from '../utils.js';
|
||||
import { l } from '../translations.js';
|
||||
import { CIRCULARITY_DATA_SIZE } from '../stick-renderer.js';
|
||||
import { CIRCULARITY_DATA_SIZE, draw_stick_dial } from '../stick-renderer.js';
|
||||
|
||||
const SECONDS_UNTIL_UNLOCK = 15;
|
||||
const EXPERT_MODE_STORAGE_KEY = 'rangeCalibExpertMode';
|
||||
|
||||
/**
|
||||
* Calibrate Stick Range Modal Class
|
||||
@@ -41,6 +40,16 @@ export class CalibRangeModal {
|
||||
this.doneCallback = doneCallback;
|
||||
|
||||
this.hasSingleStick = (this.controller.currentController.getNumberOfSticks() == 1);
|
||||
|
||||
// Stick rendering
|
||||
this.leftCanvasCtx = null;
|
||||
this.rightCanvasCtx = null;
|
||||
this.stickRenderInterval = null;
|
||||
this.currentStickPositions = {
|
||||
left: { x: 0, y: 0 },
|
||||
right: { x: 0, y: 0 }
|
||||
};
|
||||
|
||||
this._initEventListeners();
|
||||
}
|
||||
|
||||
@@ -78,6 +87,8 @@ export class CalibRangeModal {
|
||||
this.ll_data.fill(0);
|
||||
this.rr_data.fill(0);
|
||||
|
||||
this._initializeCanvases();
|
||||
|
||||
this._updateUIVisibility();
|
||||
if (!this.expertMode) {
|
||||
this.updateProgress(); // reset progress bar
|
||||
@@ -92,6 +103,7 @@ export class CalibRangeModal {
|
||||
}
|
||||
|
||||
async onClose() {
|
||||
this.stopStickRendering();
|
||||
this.stopProgressMonitoring();
|
||||
this.stopCountdown();
|
||||
|
||||
@@ -292,6 +304,89 @@ export class CalibRangeModal {
|
||||
$('#range-progress-text-container').show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize canvas elements for stick rendering
|
||||
*/
|
||||
_initializeCanvases() {
|
||||
const leftCanvas = document.getElementById('range-left-stick-canvas');
|
||||
const rightCanvas = document.getElementById('range-right-stick-canvas');
|
||||
|
||||
this.leftCanvasCtx = leftCanvas.getContext('2d');
|
||||
this.rightCanvasCtx = rightCanvas.getContext('2d');
|
||||
|
||||
// Clear initial canvases
|
||||
this._clearCanvas(this.leftCanvasCtx, leftCanvas);
|
||||
this._clearCanvas(this.rightCanvasCtx, rightCanvas);
|
||||
|
||||
// Start rendering loop
|
||||
this.startStickRendering();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a canvas with white background
|
||||
*/
|
||||
_clearCanvas(ctx, canvas) {
|
||||
if (!ctx) return;
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update current stick positions for rendering
|
||||
*/
|
||||
handleControllerInput({sticks}) {
|
||||
if (sticks?.left) {
|
||||
this.currentStickPositions.left = { ...sticks.left };
|
||||
}
|
||||
if (sticks?.right) {
|
||||
this.currentStickPositions.right = { ...sticks.right };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start stick rendering loop
|
||||
*/
|
||||
startStickRendering() {
|
||||
if (this.stickRenderInterval) return;
|
||||
|
||||
this.stickRenderInterval = setInterval(() => {
|
||||
this._renderSticks();
|
||||
}, 16); // ~60 FPS
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop stick rendering loop
|
||||
*/
|
||||
stopStickRendering() {
|
||||
if (this.stickRenderInterval) {
|
||||
clearInterval(this.stickRenderInterval);
|
||||
this.stickRenderInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render both stick dials
|
||||
*/
|
||||
_renderSticks() {
|
||||
if (!this.leftCanvasCtx || !this.rightCanvasCtx) return;
|
||||
|
||||
const leftCanvas = this.leftCanvasCtx.canvas;
|
||||
const rightCanvas = this.rightCanvasCtx.canvas;
|
||||
|
||||
// Clear canvases
|
||||
this._clearCanvas(this.leftCanvasCtx, leftCanvas);
|
||||
this._clearCanvas(this.rightCanvasCtx, rightCanvas);
|
||||
|
||||
// Draw stick dials in normal mode (no circularity data, no zoom)
|
||||
const size = 60;
|
||||
const centerX = leftCanvas.width / 2;
|
||||
const centerY = leftCanvas.height / 2;
|
||||
const {left, right} = this.currentStickPositions;
|
||||
|
||||
draw_stick_dial(this.leftCanvasCtx, centerX, centerY, size, left.x, left.y);
|
||||
draw_stick_dial(this.rightCanvasCtx, centerX, centerY, size, right.x, right.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Global reference to the current range calibration instance
|
||||
@@ -321,5 +416,11 @@ async function calibrate_range_on_close() {
|
||||
}
|
||||
}
|
||||
|
||||
export function rangeCalibHandleControllerInput(changes) {
|
||||
if (currentCalibRangeInstance) {
|
||||
currentCalibRangeInstance.handleControllerInput(changes);
|
||||
}
|
||||
}
|
||||
|
||||
// Expose functions to window for HTML onclick handlers
|
||||
window.calibrate_range_on_close = calibrate_range_on_close;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import { draw_stick_position } from '../stick-renderer.js';
|
||||
import { draw_stick_dial } from '../stick-renderer.js';
|
||||
import { dec2hex32, float_to_str, la } from '../utils.js';
|
||||
import { auto_calibrate_stick_centers } from './calib-center-modal.js';
|
||||
import { calibrate_range } from './calib-range-modal.js';
|
||||
@@ -698,13 +698,13 @@ export class Finetune {
|
||||
if (this._mode === 'circularity') {
|
||||
// Draw stick position with circle
|
||||
const circularityData = lOrR === 'left' ? this.ll_data : this.rr_data;
|
||||
draw_stick_position(ctx, hb, yb, sz, plx, ply, {
|
||||
draw_stick_dial(ctx, hb, yb, sz, plx, ply, {
|
||||
circularity_data: circularityData,
|
||||
highlight
|
||||
});
|
||||
} else {
|
||||
// Draw stick position with crosshair
|
||||
draw_stick_position(ctx, hb, yb, sz, plx, ply, {
|
||||
draw_stick_dial(ctx, hb, yb, sz, plx, ply, {
|
||||
enable_zoom_center: true,
|
||||
highlight
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ export const CIRCULARITY_DATA_SIZE = 48; // Number of angular positions to sampl
|
||||
* @param {boolean} opts.enable_zoom_center - Whether to apply center zoom transformation
|
||||
* @param {boolean} opts.highlight - Whether to highlight the stick position
|
||||
*/
|
||||
export function draw_stick_position(ctx, center_x, center_y, sz, stick_x, stick_y, opts = {}) {
|
||||
export function draw_stick_dial(ctx, center_x, center_y, sz, stick_x, stick_y, opts = {}) {
|
||||
const { circularity_data = null, enable_zoom_center = false, highlight } = opts;
|
||||
|
||||
// Draw base circle
|
||||
|
||||
@@ -6,9 +6,19 @@
|
||||
<h1 class="modal-title fs-5 ds-i18n" id="staticBackdropLabel">Range calibration</h1>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="ds-i18n"><b>The controller is now sampling data!</b></p>
|
||||
<p class="ds-i18n"><b class="pulsing-text">The controller is now sampling data!</b></p>
|
||||
<p class="ds-i18n">Rotate the sticks slowly at least 2 times in one direction and 2 times in the other direction to cover the whole range.</p>
|
||||
<div class="progress mt-3" id="range-progress-container" role="progressbar" aria-label="Range calibration progress" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
|
||||
<div style="display: flex; justify-content: center; gap: 0px;">
|
||||
<div style="text-align: center; margin-right: 0px;">
|
||||
<canvas id="range-left-stick-canvas" width="150" height="150"></canvas>
|
||||
</div>
|
||||
<div style="text-align: center; margin-left: 0px;">
|
||||
<canvas id="range-right-stick-canvas" width="150" height="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="progress mt-2" id="range-progress-container" role="progressbar" aria-label="Range calibration progress" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
|
||||
<div id="range-progress-bar" class="progress-bar" style="width:0%"></div>
|
||||
</div>
|
||||
<div class="mt-2" id="range-progress-text-container">
|
||||
|
||||
Reference in New Issue
Block a user