test 5
This commit is contained in:
@@ -4153,12 +4153,10 @@ function startCustomTooltips() {
|
||||
}
|
||||
|
||||
function vmixCountdownSyncCommands(input, selectedName, millisecondsProvider, action = "start") {
|
||||
// BUILD106: Runtime is the ONLY source of truth for game/penalty time.
|
||||
// Important vMix detail: SetCountdown changes the countdown Duration; it does not
|
||||
// reliably replace the current position of a countdown that was previously started
|
||||
// or suspended. Therefore every operator state change performs a hard reseed:
|
||||
// freeze title rendering -> reset native countdown -> set Runtime value -> unfreeze.
|
||||
// Start/Resume then starts from that freshly seeded Runtime value.
|
||||
// BUILD107: Runtime remains the source of truth, but normal operator control no
|
||||
// longer uses StopCountdown because vMix defines it as Stop + Reset.
|
||||
// ChangeCountdown updates the CURRENT countdown position; SetCountdown only changes
|
||||
// Duration. PauseCountdown is used only for an actual Runtime pause transition.
|
||||
const target = { Input: String(input || "").trim(), SelectedName: String(selectedName || "").trim() };
|
||||
const renderTarget = { Input: target.Input };
|
||||
const currentValue = () => {
|
||||
@@ -4167,24 +4165,32 @@ function startCustomTooltips() {
|
||||
};
|
||||
if (!target.Input || !target.SelectedName) return [];
|
||||
|
||||
const reseedStopped = [
|
||||
{ Function: "PauseRender", ...renderTarget },
|
||||
{ Function: "StopCountdown", ...target },
|
||||
{ Function: "SetCountdown", ...target, Value: currentValue },
|
||||
{ Function: "ResumeRender", ...renderTarget },
|
||||
];
|
||||
|
||||
if (action === "stop" || action === "pause" || action === "set") {
|
||||
// Do not trust the native vMix current position on Pause. Freeze at the exact
|
||||
// Runtime value and leave the native countdown stopped. The next Resume will
|
||||
// hard-reseed again before StartCountdown.
|
||||
return reseedStopped;
|
||||
if (action === "pause" || action === "stop") {
|
||||
// Space pause: toggle the native countdown into Pause, then pin its current value
|
||||
// to the exact Runtime time. No StopCountdown reset is allowed in this path.
|
||||
return [
|
||||
{ Function: "PauseRender", ...renderTarget },
|
||||
{ Function: "PauseCountdown", ...target },
|
||||
{ Function: "ChangeCountdown", ...target, Value: currentValue },
|
||||
{ Function: "ResumeRender", ...renderTarget },
|
||||
];
|
||||
}
|
||||
|
||||
if (action === "set") {
|
||||
// Scoreboard/F1 pre-sync while Runtime is not running: update only the current
|
||||
// vMix position. Do not toggle PauseCountdown because it is a Pause/Resume toggle.
|
||||
return [
|
||||
{ Function: "PauseRender", ...renderTarget },
|
||||
{ Function: "ChangeCountdown", ...target, Value: currentValue },
|
||||
{ Function: "ResumeRender", ...renderTarget },
|
||||
];
|
||||
}
|
||||
|
||||
// Start/Resume: set the native CURRENT position from Runtime and then run it.
|
||||
// This avoids both StopCountdown reset and SetCountdown duration-only semantics.
|
||||
return [
|
||||
{ Function: "PauseRender", ...renderTarget },
|
||||
{ Function: "StopCountdown", ...target },
|
||||
{ Function: "SetCountdown", ...target, Value: currentValue },
|
||||
{ Function: "ChangeCountdown", ...target, Value: currentValue },
|
||||
{ Function: "ResumeRender", ...renderTarget },
|
||||
{ Function: "StartCountdown", ...target },
|
||||
];
|
||||
@@ -13915,7 +13921,7 @@ function renderHockeyPenaltyDashboard(node, component, runtime) {
|
||||
<div class="shortcut-finish-action-list">${timerFinishActionRows(step)}</div>
|
||||
|
||||
<div class="shortcut-vmix-inventory-note"><span>${escapeHtml(shortcutInventoryLabel())}</span><small>Для каждого countdown теперь обязательно выбирается конкретный Text / SelectedName. Это исключает отправку времени в первый текстовый элемент по умолчанию.</small></div>
|
||||
<p class="shortcut-step-note">Режим <b>Countdown vMix</b>: веб-таймер является единственным источником времени. Перед Start/Resume vMix выполняет <code>StopCountdown → SetCountdown(время Runtime) → StartCountdown</code>; при Pause/Stop vMix выполняет <code>StopCountdown → SetCountdown(время Runtime)</code> и остаётся остановленным на точном веб-времени. Команды идут в Agent без ACK отдельными кадрами строго по порядку. Каждую секунду значение в vMix не передаётся. <b>Text mirror</b> оставлен только для совместимости со старыми титрами. Для верхнего счёта используется одна penalty-плашка: при реальном большинстве она показывает ближайшее изменение численного состава; при чистом равном обоюдном удалении сама по себе не появляется.</p>
|
||||
<p class="shortcut-step-note">Режим <b>Countdown vMix</b>: веб-таймер является источником времени. Перед Start/Resume vMix выполняет <code>ChangeCountdown(время Runtime) → StartCountdown</code>; при Pause/Stop выполняет <code>PauseCountdown → ChangeCountdown(время Runtime)</code>. <code>StopCountdown</code> в обычном управлении не используется, потому что он сбрасывает countdown. Команды идут в Agent без ACK отдельными кадрами строго по порядку. Каждую секунду значение в vMix не передаётся. <b>Text mirror</b> оставлен только для совместимости со старыми титрами. Для верхнего счёта используется одна penalty-плашка: при реальном большинстве она показывает ближайшее изменение численного состава; при чистом равном обоюдном удалении сама по себе не появляется.</p>
|
||||
</div>`;
|
||||
} else if (step.type === "delay") {
|
||||
body.innerHTML = `<div class="shortcut-step-grid"><label>Задержка, мс<input type="number" min="0" max="10000" step="10" data-step-field="milliseconds" value="${Number(step.milliseconds) || 0}"></label></div>`;
|
||||
|
||||
Reference in New Issue
Block a user