feat: dialogue pages

This commit is contained in:
cha0s 2024-09-07 12:07:05 -05:00
parent de8ff49270
commit 336ec04f66
4 changed files with 52 additions and 18 deletions

View File

@ -18,36 +18,63 @@ export default function Dialogue({
const ref = useRef(); const ref = useRef();
const [dimensions, setDimensions] = useState({h: 0, w: 0}); const [dimensions, setDimensions] = useState({h: 0, w: 0});
const [caret, setCaret] = useState(0); const [caret, setCaret] = useState(0);
const [page, setPage] = useState(0);
const radians = useRadians(); const radians = useRadians();
const [pageLetters, setPageLetters] = useState([]);
useEffect(() => { useEffect(() => {
setCaret(0);
setPageLetters(dialogue.letters.filter((letter) => letter.page === page));
}, [dialogue, page]);
useEffect(() => {
if (0 === pageLetters.length) {
return;
}
return dialogue.addSkipListener(() => { return dialogue.addSkipListener(() => {
if (caret >= dialogue.letters.length - 1) { // at end
dialogue.onClose(); if (caret >= pageLetters.length - 1) {
if (page < dialogue.pages - 1) {
setPage((page) => page + 1);
}
else {
dialogue.onClose();
}
} }
// skip to end
else { else {
setCaret(dialogue.letters.length - 1); setCaret(pageLetters.length - 1);
} }
}); });
}, [caret, dialogue]); }, [caret, dialogue, page, pageLetters]);
useEffect(() => { useEffect(() => {
const {params} = dialogue.letters[caret]; if (0 === pageLetters.length) {
return;
}
const {params} = pageLetters[caret];
let handle; let handle;
if (caret >= dialogue.letters.length - 1) { // start lingering timeout
if (caret >= pageLetters.length - 1) {
const {linger} = dialogue; const {linger} = dialogue;
if (!linger) { if (!linger) {
return; return;
} }
handle = setTimeout(() => { handle = setTimeout(() => {
dialogue.onClose(); if (page < dialogue.pages - 1) {
setPage((page) => page + 1);
}
else {
dialogue.onClose();
}
}, linger * 1000); }, linger * 1000);
} }
else { else {
// jump to next caret spot
let jump = caret; let jump = caret;
while (0 === dialogue.letters[jump].params.rate.frequency && jump < dialogue.letters.length - 1) { while (0 === pageLetters[jump].params.rate.frequency && jump < pageLetters.length - 1) {
jump += 1; jump += 1;
} }
setCaret(jump); setCaret(jump);
if (jump < dialogue.letters.length - 1) { if (jump < pageLetters.length - 1) {
// wait for next jump
handle = setTimeout(() => { handle = setTimeout(() => {
setCaret(caret + 1); setCaret(caret + 1);
}, params.rate.frequency * 1000) }, params.rate.frequency * 1000)
@ -56,7 +83,7 @@ export default function Dialogue({
return () => { return () => {
clearTimeout(handle); clearTimeout(handle);
} }
}, [caret, dialogue]); }, [caret, dialogue, page, pageLetters]);
const updateDimensions = useCallback(() => { const updateDimensions = useCallback(() => {
if (ref.current) { if (ref.current) {
const {height, width} = ref.current.getBoundingClientRect(); const {height, width} = ref.current.getBoundingClientRect();
@ -65,8 +92,8 @@ export default function Dialogue({
}, [domScale]); }, [domScale]);
useAnimationFrame(updateDimensions); useAnimationFrame(updateDimensions);
const localRender = useMemo( const localRender = useMemo(
() => render(dialogue.letters, styles.letter), () => render(pageLetters, styles.letter),
[dialogue.letters], [pageLetters],
); );
let position = 'function' === typeof dialogue.position let position = 'function' === typeof dialogue.position
? dialogue.position() ? dialogue.position()

View File

@ -45,6 +45,7 @@ export default function Entities({
dialogues[key].position = () => updating[id].Position; dialogues[key].position = () => updating[id].Position;
} }
dialogues[key].letters = parseLetters(dialogues[key].body); dialogues[key].letters = parseLetters(dialogues[key].body);
dialogues[key].pages = 1 + dialogues[key].letters.at(-1).page;
setChatMessages((chatMessages) => ({ setChatMessages((chatMessages) => ({
[[id, key].join('-')]: dialogues[key].letters, [[id, key].join('-')]: dialogues[key].letters,
...chatMessages, ...chatMessages,

View File

@ -289,11 +289,7 @@ export default async function createHomestead(id) {
interacting: 1, interacting: 1,
interactScript: ` interactScript: `
const lines = [ const lines = [
'mrowwr', 'Mind your own business, buddy.\\n\\ner, I mean, <shake>MEEHHHHHH</shake>',
'p<shake>rrr</shake>o<wave>wwwww</wave>',
'mew<rate frequency={0.5}> </rate>mew!',
'me<wave>wwwww</wave>',
'\\\\*pu<shake>rrrrr</shake>\\\\*',
]; ];
const line = lines[Math.floor(Math.random() * lines.length)]; const line = lines[Math.floor(Math.random() * lines.length)];
subject.Interlocutor.dialogue({ subject.Interlocutor.dialogue({

View File

@ -27,6 +27,7 @@ function computeParams(ancestors) {
export function parseLetters(source) { export function parseLetters(source) {
let letters = []; let letters = [];
let page = 0;
try { try {
const tree = parser.parse(source); const tree = parser.parse(source);
tree.dialogue = { tree.dialogue = {
@ -43,6 +44,10 @@ export function parseLetters(source) {
} }
break; break;
} }
case 'paragraph': {
page += 1;
break;
}
case 'text': { case 'text': {
const params = computeParams(ancestors); const params = computeParams(ancestors);
const split = node.value.split(''); const split = node.value.split('');
@ -51,7 +56,12 @@ export function parseLetters(source) {
for (const name in params) { for (const name in params) {
indices[name] = i + params[name].length; indices[name] = i + params[name].length;
} }
letters.push({character: split[i], indices, params}); letters.push({
character: split[i],
indices,
page: page - 1,
params,
});
} }
for (const name in params) { for (const name in params) {
params[name].length += split.length; params[name].length += split.length;