Skip to Content

DM Note 문서

DM Note는 DJMAX RESPECT V를 비롯한 리듬게임에서 사용하기 위해 만들어진 키뷰어 프로그램입니다. 간편한 설정으로 스트리밍이나 플레이 영상 제작 시 키 입력을 시각적으로 보여줄 수 있습니다.

문서 구성

📖 기본 가이드

프로그램의 기본적인 사용법을 안내합니다.

🔌 플러그인 시스템

DM Note는 사용자가 작성한 JavaScript를 런타임에 주입할 수 있는 플러그인 시스템을 제공합니다. 이를 통해 앱 동작을 확장하고, 실시간 통계 패널 같은 고급 기능을 구현할 수 있습니다.

보안 경고: 플러그인은 앱 내부 API와 DOM에 완전한 접근 권한을 가집니다. 신뢰할 수 없는 스크립트는 절대 실행하지 마세요.

핵심 개념

두 가지 윈도우

DM Note는 두 개의 독립적인 윈도우에서 플러그인이 실행됩니다.

윈도우역할플러그인 용도
Main설정 UI, 키 맵핑 편집UI 확장, 설정 패널
Overlay실제 키 시각화, 노트 이펙트실시간 통계, 키 입력 처리
// 윈도우 타입 확인 if (dmn.window.type === "overlay") { // 오버레이에서만 실행되는 코드 } if (dmn.window.type === "main") { // 메인 윈도우에서만 실행되는 코드 }

플러그인 작성 방식

DM Note는 두 가지 플러그인 작성 방식을 제공합니다.

1. 선언형 API (권장)

defineElement를 사용하면 복잡한 DOM 조작 없이 선언적으로 UI를 정의할 수 있습니다.

// @id kps-panel dmn.plugin.defineElement({ name: "KPS 패널", settings: { textColor: { type: "color", default: "#FFFFFF", label: "텍스트 색상" }, }, template: (state, settings, { html }) => html` <div style="color: ${settings.textColor};">KPS: ${state.kps ?? 0}</div> `, onMount: ({ setState, onHook }) => { const timestamps = []; onHook("key", ({ state }) => { if (state === "DOWN") timestamps.push(Date.now()); }); const interval = setInterval(() => { const now = Date.now(); const recent = timestamps.filter((t) => t > now - 1000); timestamps.length = 0; timestamps.push(...recent); setState({ kps: timestamps.length }); }, 100); return () => clearInterval(interval); }, });

장점:

  • ✅ 자동 설정 UI 생성
  • ✅ 상태 동기화 (메인 ↔ 오버레이)
  • ✅ 컨텍스트 메뉴 자동 생성
  • ✅ 라이프사이클 자동 관리

2. 명령형 API (고급)

직접 DOM을 조작하고 세밀한 제어가 필요한 경우 사용합니다.

// @id custom-panel if (dmn.window.type !== "overlay") return; const panel = document.createElement("div"); panel.textContent = "Hello, Plugin!"; document.body.appendChild(panel); dmn.plugin.registerCleanup(() => { panel.remove(); });

플러그인 ID

각 플러그인은 고유 ID를 가지며, 파일 상단에 @id 주석으로 지정합니다.

// @id my-awesome-plugin // 또는 // @id: my-awesome-plugin

ID는 스토리지 네임스페이스로 사용되므로 신중하게 선택하세요.

전역 API (dmn)

모든 플러그인은 dmn 전역 객체를 통해 앱 기능에 접근합니다.

// 앱 데이터 조회 const bootstrap = await dmn.app.bootstrap(); // 설정 조회/변경 const settings = await dmn.settings.get(); await dmn.settings.update({ language: "en" }); // 키 이벤트 구독 const unsub = dmn.keys.onKeyState(({ key, state }) => { console.log(`${key} is ${state}`); }); // 플러그인 스토리지 await dmn.plugin.storage.set("data", { value: 123 }); const data = await dmn.plugin.storage.get("data");

다음 단계