plugin v1.0.1
Deploy / Deploy (push) Successful in 1m15s Details

This commit is contained in:
JotaChina 2025-11-23 14:36:24 -03:00
parent f80643b28b
commit 9d279d6bda
2 changed files with 400 additions and 415 deletions

View File

@ -1,7 +1,4 @@
/* =============================================== */ /* MMPCreator - Folha de Estilos Principal */
/* MMPCreator - Folha de Estilos Principal */
/* =============================================== */
:root { :root {
--bg-body: #2d3035; --bg-body: #2d3035;
--bg-toolbar: #3b3f45; --bg-toolbar: #3b3f45;

View File

@ -70,425 +70,418 @@
</style> </style>
</head> </head>
<body> <body>
<aside class="sample-browser">
<div class="studio-wrapper"> <div class="browser-header">Navegador de Samples</div>
<div class="browser-content" id="browser-content"></div>
<aside class="sample-browser"> </aside>
<div class="browser-header">Navegador de Samples</div>
<div class="browser-content" id="browser-content"></div>
</aside>
<button id="sidebar-toggle"><i class="fa-solid fa-caret-left"></i></button> <button id="sidebar-toggle"><i class="fa-solid fa-caret-left"></i></button>
<div class="app-container">
<div class="app-container"> <header class="global-toolbar">
<header class="global-toolbar"> <div class="control-group">
<div class="control-group"> <i
<i class="fa-solid fa-file"
class="fa-solid fa-file" id="new-project-btn"
id="new-project-btn" title="Novo Projeto"
title="Novo Projeto" ></i>
></i> <i
<i class="fa-solid fa-folder-open"
class="fa-solid fa-folder-open" id="open-mmp-btn"
id="open-mmp-btn" title="Abrir Projeto do Servidor"
title="Abrir Projeto do Servidor" ></i>
></i> <i
<i class="fa-solid fa-save"
class="fa-solid fa-save" id="save-mmp-btn"
id="save-mmp-btn" title="Salvar Projeto (.mmp)"
title="Salvar Projeto (.mmp)" ></i>
></i> <i
<i class="fa-solid fa-upload"
class="fa-solid fa-upload" id="upload-sample-btn"
id="upload-sample-btn" title="Carregar Sample do Computador"
title="Carregar Sample do Computador" ></i>
></i> </div>
</div> <div class="divider"></div>
<div class="divider"></div> <div class="control-group">
<div class="control-group"> <i
<i class="fa-solid fa-backward-step"
class="fa-solid fa-backward-step" id="rewind-btn"
id="rewind-btn" title="Voltar ao Início"
title="Voltar ao Início" ></i>
></i> <i class="fa-solid fa-play" title="Play/Pause Global (Futuro)"></i>
<i class="fa-solid fa-play" title="Play/Pause Global (Futuro)"></i> <i class="fa-solid fa-stop" title="Stop Global (Futuro)"></i>
<i class="fa-solid fa-stop" title="Stop Global (Futuro)"></i> <button id="record-btn" class="transport-btn" title="Gravar">
<button id="record-btn" class="transport-btn" title="Gravar"> <i class="fa-solid fa-circle-dot"></i>
<i class="fa-solid fa-circle-dot"></i> </button>
</button> </div>
</div> <div class="divider"></div>
<div class="divider"></div> <div class="info-display-group">
<div class="info-display-group"> <div class="info-display">
<div class="info-display"> <div class="interactive-input-container">
<div class="interactive-input-container"> <button class="adjust-btn" data-target="bpm" data-step="-1">
<button class="adjust-btn" data-target="bpm" data-step="-1"> -
- </button>
</button> <input
<input type="text"
type="text" class="value-input"
class="value-input" id="bpm-input"
id="bpm-input" value="140"
value="140" data-min="20"
data-min="20" data-max="400"
data-max="400" />
/> <button class="adjust-btn" data-target="bpm" data-step="1">
<button class="adjust-btn" data-target="bpm" data-step="1"> +
+ </button>
</button>
</div>
<div class="label">ANDAMENTO/BPM</div>
</div> </div>
<div class="info-display"> <div class="label">ANDAMENTO/BPM</div>
<div class="interactive-input-container"> </div>
<button class="adjust-btn" data-target="bars" data-step="-1"> <div class="info-display">
<div class="interactive-input-container">
<button class="adjust-btn" data-target="bars" data-step="-1">
-
</button>
<input
type="text"
class="value-input"
id="bars-input"
value="1"
data-min="1"
data-max="64"
/>
<button class="adjust-btn" data-target="bars" data-step="1">
+
</button>
</div>
<div class="label">COMPASSOS</div>
</div>
<div class="info-display">
<div class="interactive-input-container">
<div class="compasso-group">
<button
class="adjust-btn"
data-target="compasso-a"
data-step="-1"
>
- -
</button> </button>
<input <input
type="text" type="text"
class="value-input" class="value-input compasso-input"
id="bars-input" id="compasso-a-input"
value="1" value="4"
data-min="1" data-min="1"
data-max="64" data-max="16"
/> />
<button class="adjust-btn" data-target="bars" data-step="1"> <button
class="adjust-btn"
data-target="compasso-a"
data-step="1"
>
+ +
</button> </button>
</div> </div>
<div class="label">COMPASSOS</div> <span class="compasso-separator">/</span>
</div> <div class="compasso-group">
<div class="info-display"> <button
<div class="interactive-input-container"> class="adjust-btn"
<div class="compasso-group"> data-target="compasso-b"
<button data-step="-1"
class="adjust-btn" >
data-target="compasso-a" -
data-step="-1" </button>
> <input
- type="text"
</button> class="value-input compasso-input"
<input id="compasso-b-input"
type="text" value="4"
class="value-input compasso-input" data-min="1"
id="compasso-a-input" data-max="16"
value="4" />
data-min="1" <button
data-max="16" class="adjust-btn"
/> data-target="compasso-b"
<button data-step="1"
class="adjust-btn" >
data-target="compasso-a" +
data-step="1" </button>
>
+
</button>
</div>
<span class="compasso-separator">/</span>
<div class="compasso-group">
<button
class="adjust-btn"
data-target="compasso-b"
data-step="-1"
>
-
</button>
<input
type="text"
class="value-input compasso-input"
id="compasso-b-input"
value="4"
data-min="1"
data-max="16"
/>
<button
class="adjust-btn"
data-target="compasso-b"
data-step="1"
>
+
</button>
</div>
</div> </div>
<div class="label">COMPASSO</div>
</div>
<div class="info-display">
<div
id="timer-display"
class="interactive-input-container"
style="font-size: 0.7rem; color: var(--text-dark)"
>
00:00:00
</div>
<div class="label">MIN:SEC:MSEC</div>
</div> </div>
<div class="label">COMPASSO</div>
</div> </div>
<div class="control-group"> <div class="info-display">
<button id="metronome-btn" title="Metrônomo On/Off">Metrônomo</button> <div
<button id="timer-display"
id="create-room-btn" class="interactive-input-container"
class="transport-btn" style="font-size: 0.7rem; color: var(--text-dark)"
title="Criar ou entrar em uma sala compartilhada"
> >
<i class="fa-solid fa-users"></i> 00:00:00
<span style="margin-left: 8px">Criar Sala</span>
</button>
</div>
<div class="spacer"></div>
<div class="control-group master-controls">
<div class="knob-container">
<div class="knob" id="master-volume-knob">
<div class="knob-indicator"></div>
</div>
<span>VOL MASTER</span>
</div> </div>
<div class="knob-container"> <div class="label">MIN:SEC:MSEC</div>
<div class="knob" id="master-pan-knob"> </div>
<div class="knob-indicator"></div> </div>
</div> <div class="control-group">
<span>PAN MASTER</span> <button id="metronome-btn" title="Metrônomo On/Off">Metrônomo</button>
<button
id="create-room-btn"
class="transport-btn"
title="Criar ou entrar em uma sala compartilhada"
>
<i class="fa-solid fa-users"></i>
<span style="margin-left: 8px">Criar Sala</span>
</button>
</div>
<div class="spacer"></div>
<div class="control-group master-controls">
<div class="knob-container">
<div class="knob" id="master-volume-knob">
<div class="knob-indicator"></div>
</div>
<span>VOL MASTER</span>
</div>
<div class="knob-container">
<div class="knob" id="master-pan-knob">
<div class="knob-indicator"></div>
</div>
<span>PAN MASTER</span>
</div>
</div>
</header>
<main class="main-content">
<div class="beat-editor">
<div class="editor-header">
Mostrar/esconder Editor de Bases
<div class="window-controls">
<i class="fa-solid fa-minus"></i
><i class="fa-regular fa-square"></i
><i class="fa-solid fa-xmark"></i>
</div> </div>
</div> </div>
</header> <div class="editor-toolbar">
<div class="playback-controls">
<i class="fa-solid fa-play" id="play-btn" title="Play/Pause"></i>
<i class="fa-solid fa-stop" id="stop-btn" title="Stop"></i>
</div>
<div class="pattern-manager">
<h2 id="beat-bassline-title"></h2>
<select
id="global-pattern-selector"
class="pattern-selector"
disabled
>
<option>Selecione uma faixa</option>
</select>
<button id="add-pattern-btn" class="pattern-btn">+</button>
<button id="remove-pattern-btn" class="pattern-btn">-</button>
<main class="main-content"> <button
<div class="beat-editor"> id="send-pattern-to-playlist-btn"
<div class="editor-header"> class="pattern-btn"
Mostrar/esconder Editor de Bases title="Enviar Pattern para a Playlist"
<div class="window-controls"> style="width: auto; padding: 0 8px; font-size: 0.9rem"
<i class="fa-solid fa-minus"></i >
><i class="fa-regular fa-square"></i <i class="fa-solid fa-arrow-right-to-bracket"></i> Enviar
><i class="fa-solid fa-xmark"></i> </button>
</div>
<div class="tool-icons">
<i class="fa-solid fa-table-cells"></i
><i class="fa-solid fa-bars-staggered"></i>
<i class="fa-solid fa-music" id="open-piano-roll-btn" title="Abrir Piano Roll"></i>
<i
class="fa-solid fa-wave-square"
id="bounce-pattern-btn"
title="Renderizar Pattern para Pista de Áudio"
></i>
<i
class="fa-solid fa-plus"
id="add-bar-btn"
title="Adicionar 1 Compasso"
></i>
</div>
<div id="timeline-context-menu">
<div id="copy-clip">Copiar</div>
<div id="cut-clip">Recortar</div>
<div id="paste-clip">Colar</div>
<div class="menu-divider"></div>
<div id="delete-clip" style="color: var(--accent-red)">
Excluir Clipe
</div> </div>
</div> </div>
<div class="editor-toolbar">
<div class="playback-controls">
<i class="fa-solid fa-play" id="play-btn" title="Play/Pause"></i>
<i class="fa-solid fa-stop" id="stop-btn" title="Stop"></i>
</div>
<div class="pattern-manager">
<h2 id="beat-bassline-title"></h2>
<select
id="global-pattern-selector"
class="pattern-selector"
disabled
>
<option>Selecione uma faixa</option>
</select>
<button id="add-pattern-btn" class="pattern-btn">+</button>
<button id="remove-pattern-btn" class="pattern-btn">-</button>
<button <div id="ruler-context-menu">
id="send-pattern-to-playlist-btn" <div id="ruler-set-loop-start">Definir Início do Loop</div>
class="pattern-btn" <div id="ruler-set-loop-end">Definir Fim do Loop</div>
title="Enviar Pattern para a Playlist"
style="width: auto; padding: 0 8px; font-size: 0.9rem"
>
<i class="fa-solid fa-arrow-right-to-bracket"></i> Enviar
</button>
</div>
<div class="tool-icons">
<i class="fa-solid fa-table-cells"></i
><i class="fa-solid fa-bars-staggered"></i>
<i class="fa-solid fa-music" id="open-piano-roll-btn" title="Abrir Piano Roll"></i>
<i
class="fa-solid fa-wave-square"
id="bounce-pattern-btn"
title="Renderizar Pattern para Pista de Áudio"
></i>
<i
class="fa-solid fa-plus"
id="add-bar-btn"
title="Adicionar 1 Compasso"
></i>
</div>
<div id="timeline-context-menu">
<div id="copy-clip">Copiar</div>
<div id="cut-clip">Recortar</div>
<div id="paste-clip">Colar</div>
<div class="menu-divider"></div>
<div id="delete-clip" style="color: var(--accent-red)">
Excluir Clipe
</div>
</div>
<div id="ruler-context-menu">
<div id="ruler-set-loop-start">Definir Início do Loop</div>
<div id="ruler-set-loop-end">Definir Fim do Loop</div>
</div>
<div class="zoom-controls">
<i class="fa-solid fa-minus" id="remove-instrument-btn"></i
><i class="fa-solid fa-plus" id="add-instrument-btn"></i>
</div>
</div> </div>
<div id="track-container"></div> <div class="zoom-controls">
</div> <i class="fa-solid fa-minus" id="remove-instrument-btn"></i
><i class="fa-solid fa-plus" id="add-instrument-btn"></i>
<div class="piano-roll-editor" id="piano-roll-editor" style="display: none;">
<div class="editor-header">
<span>Piano Roll - <span id="piano-roll-instrument-name">Instrumento 1</span></span>
<div class="window-controls">
<i class="fa-solid fa-xmark" id="close-piano-roll-btn"></i>
</div>
</div>
<div class="piano-roll-toolbar">
<div class="playback-controls">
<i class="fa-solid fa-pencil active" title="Draw Tool"></i>
<i class="fa-solid fa-eraser" title="Erase Tool"></i>
</div>
<div class="snap-controls">
<label>Snap:</label>
<select>
<option>1/4</option>
<option>1/8</option>
<option selected>1/16</option>
</select>
</div>
</div>
<div class="piano-roll-workspace">
<div class="piano-keys-container" id="piano-keys-container">
<canvas id="piano-keys-canvas"></canvas>
</div>
<div class="piano-grid-container" id="piano-grid-container">
<canvas id="piano-grid-canvas"></canvas>
</div>
</div> </div>
</div> </div>
<div id="track-container"></div>
</div>
<div class="piano-roll-editor" id="piano-roll-editor" style="display: none;">
<div class="editor-header">
<span>Piano Roll - <span id="piano-roll-instrument-name">Instrumento 1</span></span>
<div class="window-controls">
<i class="fa-solid fa-xmark" id="close-piano-roll-btn"></i>
</div>
</div>
<div class="piano-roll-toolbar">
<div class="playback-controls">
<i class="fa-solid fa-pencil active" title="Draw Tool"></i>
<i class="fa-solid fa-eraser" title="Erase Tool"></i>
</div>
<div class="snap-controls">
<label>Snap:</label>
<select>
<option>1/4</option>
<option>1/8</option>
<option selected>1/16</option>
</select>
</div>
</div>
<div class="audio-editor"> <div class="piano-roll-workspace">
<div class="editor-header"> <div class="piano-keys-container" id="piano-keys-container">
<span>Editor de Amostras de Áudio</span> <canvas id="piano-keys-canvas"></canvas>
</div>
<div class="piano-grid-container" id="piano-grid-container">
<canvas id="piano-grid-canvas"></canvas>
</div>
</div>
</div>
<div class="audio-editor">
<div class="editor-header">
<span>Editor de Amostras de Áudio</span>
<div class="playback-controls"> <div class="playback-controls">
<i <i
class="fa-solid fa-search-minus" class="fa-solid fa-search-minus"
id="zoom-out-btn" id="zoom-out-btn"
title="Zoom Out" title="Zoom Out"
></i> ></i>
<i <i
class="fa-solid fa-search-plus" class="fa-solid fa-search-plus"
id="zoom-in-btn" id="zoom-in-btn"
title="Zoom In" title="Zoom In"
></i> ></i>
<i <i
class="fa-solid fa-scissors" class="fa-solid fa-scissors"
id="slice-tool-btn" id="slice-tool-btn"
title="Ferramenta de Corte" title="Ferramenta de Corte"
></i> ></i>
<i <i
class="fa-solid fa-arrows-left-right-to-line" class="fa-solid fa-arrows-left-right-to-line"
id="resize-tool-trim" id="resize-tool-trim"
title="Modo de Redimensionamento (Aparar/Trimming)" title="Modo de Redimensionamento (Aparar/Trimming)"
></i> ></i>
<i <i
class="fa-solid fa-arrows-left-right" class="fa-solid fa-arrows-left-right"
id="resize-tool-stretch" id="resize-tool-stretch"
title="Modo de Redimensionamento (Esticar/Time Stretch)" title="Modo de Redimensionamento (Esticar/Time Stretch)"
></i> ></i>
<i <i
class="fa-solid fa-play" class="fa-solid fa-play"
id="audio-editor-play-btn" id="audio-editor-play-btn"
title="Play/Pause" title="Play/Pause"
></i> ></i>
<i <i
class="fa-solid fa-stop" class="fa-solid fa-stop"
id="audio-editor-stop-btn" id="audio-editor-stop-btn"
title="Stop" title="Stop"
></i> ></i>
<i <i
class="fa-solid fa-repeat" class="fa-solid fa-repeat"
id="audio-editor-loop-btn" id="audio-editor-loop-btn"
title="Ativar/Desativar Loop" title="Ativar/Desativar Loop"
></i> ></i>
<button <button
id="sync-mode-btn" id="sync-mode-btn"
class="control-btn active" class="control-btn active"
title="Modo de Sincronia de Playback (Global/Local)" title="Modo de Sincronia de Playback (Global/Local)"
> >
Global Global
</button> </button>
<i <i
class="fa-solid fa-plus" class="fa-solid fa-plus"
id="add-audio-track-btn" id="add-audio-track-btn"
title="Adicionar Pista de Áudio" title="Adicionar Pista de Áudio"
></i> ></i>
</div>
</div> </div>
<div id="audio-track-container"> </div>
<div class="audio-track-lane"> <div id="audio-track-container">
<div class="track-info"> <div class="audio-track-lane">
<div class="track-info-header"> <div class="track-info">
<i class="fa-solid fa-gear"></i> <div class="track-info-header">
<span class="track-name">Pista de Áudio 1</span> <i class="fa-solid fa-gear"></i>
<div class="track-mute"></div> <span class="track-name">Pista de Áudio 1</span>
</div> <div class="track-mute"></div>
<div class="track-controls">
<div class="knob-container">
<div class="knob" data-control="volume">
<div class="knob-indicator"></div>
</div>
<span>VOL</span>
</div>
<div class="knob-container">
<div class="knob" data-control="pan">
<div class="knob-indicator"></div>
</div>
<span>PAN</span>
</div>
</div>
</div> </div>
<div class="track-controls">
<div class="timeline-container"> <div class="knob-container">
<div class="spectrogram-view-grid" style="width: 4000px"> <div class="knob" data-control="volume">
<div <div class="knob-indicator"></div>
class="timeline-clip" </div>
style="left: 100px; width: 400px" <span>VOL</span>
></div> </div>
<div class="playhead"></div> <div class="knob-container">
<div class="knob" data-control="pan">
<div class="knob-indicator"></div>
</div>
<span>PAN</span>
</div> </div>
</div> </div>
</div> </div>
<div class="audio-track-lane"> <div class="timeline-container">
<div class="track-info"> <div class="spectrogram-view-grid" style="width: 4000px">
<div class="track-info-header"> <div
<i class="fa-solid fa-gear"></i> class="timeline-clip"
<span class="track-name">Pista de Áudio 2</span> style="left: 100px; width: 400px"
<div class="track-mute"></div> ></div>
</div>
<div class="track-controls">
<div class="knob-container">
<div class="knob" data-control="volume">
<div class="knob-indicator"></div>
</div>
<span>VOL</span>
</div>
<div class="knob-container">
<div class="knob" data-control="pan">
<div class="knob-indicator"></div>
</div>
<span>PAN</span>
</div>
</div>
</div>
<div class="timeline-container">
<div id="loop-region" class="loop-region">
<div class="spectrogram-view-grid" style="width: 4000px">
<div class="timeline-clip" style="left: 50px; width: 600px">
<div class="clip-name">jungle01.ogg</div>
</div>
</div>
</div>
<div class="playhead"></div> <div class="playhead"></div>
</div> </div>
</div> </div>
</div> </div>
<div class="audio-track-lane">
<div class="track-info">
<div class="track-info-header">
<i class="fa-solid fa-gear"></i>
<span class="track-name">Pista de Áudio 2</span>
<div class="track-mute"></div>
</div>
<div class="track-controls">
<div class="knob-container">
<div class="knob" data-control="volume">
<div class="knob-indicator"></div>
</div>
<span>VOL</span>
</div>
<div class="knob-container">
<div class="knob" data-control="pan">
<div class="knob-indicator"></div>
</div>
<span>PAN</span>
</div>
</div>
</div>
<div class="timeline-container">
<div id="loop-region" class="loop-region">
<div class="spectrogram-view-grid" style="width: 4000px">
<div class="timeline-clip" style="left: 50px; width: 600px">
<div class="clip-name">jungle01.ogg</div>
</div>
</div>
</div>
<div class="playhead"></div>
</div>
</div>
</div> </div>
</main> </div>
</div> </main>
</div> </div>
<input <input
type="file" type="file"
@ -536,19 +529,14 @@
// Variáveis de Controle // Variáveis de Controle
let currentTrackId = null; let currentTrackId = null;
// --- Configurações --- const CONSTANTS = {
const CONSTANTS = { NOTE_HEIGHT: 20,
NOTE_HEIGHT: 20, KEY_WIDTH: 60,
KEY_WIDTH: 60, BEAT_WIDTH: 40,
BEAT_WIDTH: 40, // Largura visual de 1 batida (Quarter Note) TOTAL_KEYS: 84, // 7 oitavas
TOTAL_KEYS: 84, START_NOTE: 24, // C1
START_NOTE: 24, TICKS_PER_PIXEL: 0 // Calculado dinamicamente
};
// --- CORREÇÃO DE ESCALA ---
// O LMMS usa 192 ticks por batida (Quarter Note).
// Se nossa batida tem 40px de largura, a relação é:
TICKS_PER_PIXEL: 192 / 40 // = 4.8
};
const pianoRollEditor = document.getElementById('piano-roll-editor'); const pianoRollEditor = document.getElementById('piano-roll-editor');
const keysCanvas = document.getElementById('piano-keys-canvas'); const keysCanvas = document.getElementById('piano-keys-canvas');
@ -584,26 +572,26 @@
// --- DESENHO E LÓGICA --- // --- DESENHO E LÓGICA ---
function resizeCanvas() { function resizeCanvas() {
const totalHeight = CONSTANTS.TOTAL_KEYS * CONSTANTS.NOTE_HEIGHT; const totalHeight = CONSTANTS.TOTAL_KEYS * CONSTANTS.NOTE_HEIGHT;
// 64 compassos * 192 ticks / (ticks por beat) * largura... simplificando:
// Calcula a largura total baseada nos compassos definidos no input // Vamos fixar uma largura grande por enquanto
const barsCount = parseInt(document.getElementById('bars-input')?.value || 1); const totalWidth = 3000;
// 1 Compasso = 4 Batidas. Largura = Batidas * Largura da Batida
const totalWidth = (barsCount * 4) * CONSTANTS.BEAT_WIDTH;
keysCanvas.width = CONSTANTS.KEY_WIDTH; keysCanvas.width = CONSTANTS.KEY_WIDTH;
keysCanvas.height = totalHeight; keysCanvas.height = totalHeight;
gridCanvas.width = totalWidth;
gridCanvas.width = totalWidth; // Ajusta largura ao tamanho real da música gridCanvas.height = totalHeight;
gridCanvas.height = totalHeight;
// REMOVA ESTA LINHA ANTIGA: // Importante: Sincronizar a conversão de Pixel <-> Tick
// CONSTANTS.TICKS_PER_PIXEL = 48 / CONSTANTS.BEAT_WIDTH; // 1 Beat = 48 ticks (em 16th) ou 192 ticks por bar?
// No seu file.js: ticksPerStep = 12 (1/16).
// Então BEAT_WIDTH (40px) = 4 steps = 48 ticks.
CONSTANTS.TICKS_PER_PIXEL = 48 / CONSTANTS.BEAT_WIDTH;
drawKeys(); drawKeys();
drawGrid(); drawGrid();
drawNotes(); drawNotes();
} }
function drawKeys() { function drawKeys() {
keysCtx.clearRect(0, 0, keysCanvas.width, keysCanvas.height); keysCtx.clearRect(0, 0, keysCanvas.width, keysCanvas.height);
@ -755,4 +743,4 @@
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script> <script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
<script src="assets/js/creations/socket.js" type="module"></script> <script src="assets/js/creations/socket.js" type="module"></script>
</body> </body>
</html> </html>