Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 64 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion mamar-wasm-bridge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ console_error_panic_hook = "0.1.6"
console_log = { version = "0.2", features = ["color"] }

pm64 = { path = "../pm64", features = ["midly"] }
ron = "0.10.1"

[dev-dependencies]
wasm-bindgen-test = "0.3.13"
9 changes: 6 additions & 3 deletions mamar-wasm-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ pub fn bgm_decode(data: &[u8]) -> JsValue {
Err(e) => to_js(&e.to_string()),
}
} else {
match ron::from_str::<Bgm>(&String::from_utf8_lossy(data)) {
let input_string = String::from_utf8_lossy(data);

match Bgm::from_ron_string(&input_string) {
Ok(bgm) => to_js(&bgm),
Err(e) => to_js(&e.to_string()),
}
Expand All @@ -68,8 +70,9 @@ pub fn bgm_encode(bgm: &JsValue) -> JsValue {
#[wasm_bindgen]
pub fn ron_encode(bgm: &JsValue) -> JsValue {
let bgm: Bgm = from_js(bgm);
match ron::ser::to_string_pretty(&bgm, ron::ser::PrettyConfig::new().indentor(" ").depth_limit(5)) {
Ok(ron) => ron.to_string().into(),

match bgm.to_ron_string() {
Ok(ron) => ron.into(),
Err(e) => e.to_string().into(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion mamar-web/src/app/doc/Ruler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export function useSegmentLengths(): number[] {
return segments.map(segment => {
if (bgm && segment.type === "Subseg") {
const master = bgm.trackLists[segment.trackList].tracks[0]
return master.commands.vec.reduce((totalDelay, event) => {
return master.commands.reduce((totalDelay, event) => {
if (event.type === "Delay") {
return totalDelay + event.value
} else {
Expand Down
10 changes: 8 additions & 2 deletions mamar-web/src/app/doc/SegmentMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,23 @@ import { TimeProvider } from "./timectx"
import TrackControls from "../emu/TrackControls"
import { useBgm, useDoc, useVariation } from "../store"
import useSelection, { SelectionProvider } from "../util/hooks/useSelection"
import { Track } from "pm64-typegen"

const TRACK_HEAD_WIDTH = 100 // Match with $trackHead-width

function hasParentTrack(track: Track): boolean {
const { polyphony } = track
return typeof polyphony === "object" && "ConditionalTakeover" in polyphony
}

function PianoRollThumbnail({ trackIndex, trackListIndex }: { trackIndex: number, trackListIndex: number }) {
const [doc, dispatch] = useDoc()
const [bgm] = useBgm()
const track = bgm?.trackLists[trackListIndex]?.tracks[trackIndex]
const isSelected = doc?.panelContent.type === "tracker" && doc?.panelContent.trackList === trackListIndex && doc?.panelContent.track === trackIndex
const nameId = useId()

if (!track || track.commands.vec.length === 0) {
if (!track || track.commands.length === 0) {
return <></>
} else {
const handlePress = (evt: any) => {
Expand All @@ -41,7 +47,7 @@ function PianoRollThumbnail({ trackIndex, trackListIndex }: { trackIndex: number
[styles.pianoRollThumbnail]: true,
[styles.drumRegion]: track.isDrumTrack,
[styles.disabledRegion]: track.isDisabled,
[styles.hasInterestingParentTrack]: track.parentTrackIdx !== 0,
[styles.hasInterestingParentTrack]: hasParentTrack(track),
[styles.selected]: isSelected,
})}
onClick={handlePress}
Expand Down
71 changes: 38 additions & 33 deletions mamar-web/src/app/doc/SubsegDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,13 @@ import styles from "./SubsegDetails.module.scss"
import Tracker from "./Tracker"

import { useBgm } from "../store"
import { Polyphony } from "pm64-typegen"

export interface Props {
trackListId: number
trackIndex: number
}

function polyphonicIdxToVoiceCount(polyphonicIdx: number): number {
// player->unk_22A
switch (polyphonicIdx) {
case 1: return 1
case 5: return 2
case 6: return 3
case 7: return 4
default: return 0
}
}

function voiceCountToPolyphonicIdx(voiceCount: number): number {
switch (voiceCount) {
case 1: return 1
case 2: return 5
case 3: return 6
case 4: return 7
default: return 0
}
}

export default function SubsegDetails({ trackListId, trackIndex }: Props) {
const hid = useId()
const [bgm, dispatch] = useBgm()
Expand Down Expand Up @@ -65,8 +45,8 @@ export default function SubsegDetails({ trackListId, trackIndex }: Props) {
<Switch isSelected={!track.isDisabled} onChange={v => dispatch({ type: "modify_track_settings", trackList: trackListId, track: trackIndex, isDisabled: !v })}>Enabled</Switch>
{trackIndex !== 0 ? <>
<Switch isSelected={track.isDrumTrack} onChange={isDrumTrack => dispatch({ type: "modify_track_settings", trackList: trackListId, track: trackIndex, isDrumTrack })}>Percussion</Switch>
<PolyphonyForm {...track} maxParentTrackIdx={trackIndex - 1} onChange={(polyphonicIdx, parentTrackIdx) => {
dispatch({ type: "modify_track_settings", trackList: trackListId, track: trackIndex, polyphonicIdx, parentTrackIdx })
<PolyphonyForm {...track} maxParentTrackIdx={trackIndex - 1} onChange={polyphony => {
dispatch({ type: "modify_track_settings", trackList: trackListId, track: trackIndex, polyphony })
}} />
</> : <></>}
</Form>
Expand All @@ -77,7 +57,7 @@ export default function SubsegDetails({ trackListId, trackIndex }: Props) {
</Grid>
}

function PolyphonyForm({ polyphonicIdx, parentTrackIdx, maxParentTrackIdx, onChange }: { polyphonicIdx: number, parentTrackIdx: number, maxParentTrackIdx: number, onChange: (polyphonicIdx: number, parentTrackIdx: number) => void }) {
function PolyphonyForm({ polyphony, maxParentTrackIdx, onChange }: { polyphony: Polyphony, maxParentTrackIdx: number, onChange: (polyphony: Polyphony) => void }) {
const polyphonyLabel = <Flex width="100%" alignItems="center">
<Text flexGrow={1}>Polyphony</Text>
<ContextualHelp variant="help" placement="right">
Expand Down Expand Up @@ -119,9 +99,18 @@ function PolyphonyForm({ polyphonicIdx, parentTrackIdx, maxParentTrackIdx, onCha
</ContextualHelp>
</Flex>

let state = "manual"
if (polyphonicIdx === 255) state = "auto"
if (parentTrackIdx !== 0) state = "parent"
let state: "auto" | "manual" | "parent" = "manual"
let parentTrackIdx = 0
let voiceCount = 1

if (polyphony === "Automatic") {
state = "auto"
} else if ("ConditionalTakeover" in polyphony) {
state = "parent"
parentTrackIdx = polyphony.ConditionalTakeover.parent
} else if ("Manual" in polyphony) {
voiceCount = polyphony.Manual.voices
}

// Store parent track between states, e.g. so that parent->manual->parent doesn't forget which track it was
const [recentNonZeroParentTrackIdx, setRecentNonZeroParentTrackIdx] = useState(1)
Expand All @@ -136,11 +125,19 @@ function PolyphonyForm({ polyphonicIdx, parentTrackIdx, maxParentTrackIdx, onCha
onChange={newState => {
if (state === newState) return
if (newState === "auto") {
onChange(255, 0)
onChange("Automatic")
} else if (newState === "manual") {
onChange(1, 0)
onChange({
Manual: {
voices: 1,
},
})
} else if (newState === "parent") {
onChange(polyphonicIdx, Math.min(recentNonZeroParentTrackIdx, maxParentTrackIdx))
onChange({
ConditionalTakeover: {
parent: Math.min(recentNonZeroParentTrackIdx, maxParentTrackIdx),
},
})
}
}}
>
Expand All @@ -150,11 +147,15 @@ function PolyphonyForm({ polyphonicIdx, parentTrackIdx, maxParentTrackIdx, onCha
</RadioGroup>
{state === "manual" ? <NumberField
label="Number of voices"
value={polyphonicIdxToVoiceCount(polyphonicIdx)}
value={voiceCount}
minValue={0}
maxValue={4}
step={1}
onChange={voiceCount => onChange(voiceCountToPolyphonicIdx(voiceCount), 0)}
onChange={voices => onChange({
Manual: {
voices,
},
})}
/> : <></>}
{state === "parent" ? <NumberField
label={takeoverLabel}
Expand All @@ -163,7 +164,11 @@ function PolyphonyForm({ polyphonicIdx, parentTrackIdx, maxParentTrackIdx, onCha
minValue={1}
maxValue={maxParentTrackIdx}
step={1}
onChange={parentTrackIdx => onChange(polyphonicIdx, parentTrackIdx)}
onChange={parentTrackIdx => onChange({
ConditionalTakeover: {
parent: parentTrackIdx,
},
})}
/> : <></>}
</View>
}
2 changes: 1 addition & 1 deletion mamar-web/src/app/doc/Tracker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ function CommandList({ width, height }: {
const [bgm] = useBgm()
const { trackListId, trackIndex } = useContext(trackListCtx)!
const track = bgm?.trackLists[trackListId]?.tracks[trackIndex]
const commands = track?.commands?.vec ?? []
const commands: pm64.Event[] = track?.commands ?? []

return <Droppable
droppableId="droppable"
Expand Down
Loading
Loading