Skip to content

Commit db71713

Browse files
feat(blocks): add text2speech translate and video sensing extension blocks
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
1 parent 2952495 commit db71713

7 files changed

Lines changed: 175 additions & 0 deletions

File tree

packages/hikkaku/src/blocks/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ export * from './pen'
99
export * from './procedures'
1010
export * from './sensing'
1111
export * from './sound'
12+
export * from './text2speech'
13+
export * from './translate'
14+
export * from './videosensing'
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { describe, expect, test } from 'vite-plus/test'
2+
import { block, createBlocks } from '../core/composer'
3+
import { setLanguage, setVoice, speakAndWait } from './text2speech'
4+
5+
describe('blocks/text2speech', () => {
6+
test('creates text to speech extension blocks', () => {
7+
const blocks = createBlocks(() => {
8+
block('event_whenflagclicked', { topLevel: true })
9+
setVoice('TENOR')
10+
setLanguage('ja')
11+
speakAndWait('hello')
12+
})
13+
14+
const opcodes = Object.values(blocks).map((b) => b.opcode)
15+
expect(opcodes).toContain('text2speech_setVoice')
16+
expect(opcodes).toContain('text2speech_setLanguage')
17+
expect(opcodes).toContain('text2speech_speakAndWait')
18+
})
19+
})
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { InputType } from 'sb3-types/enum'
2+
import { fromPrimitiveSource } from '../core/block-helper'
3+
import { block } from '../core/composer'
4+
import type { HikkakuString, PrimitiveSource } from '../core/types'
5+
6+
export type TextToSpeechVoice =
7+
| 'ALTO'
8+
| 'TENOR'
9+
| 'SQUEAK'
10+
| 'GIANT'
11+
| 'KITTEN'
12+
| 'GOOGLE'
13+
14+
export const speakAndWait = (words: PrimitiveSource<HikkakuString>) => {
15+
return block('text2speech_speakAndWait', {
16+
inputs: {
17+
WORDS: fromPrimitiveSource(InputType.String, words, 'hello'),
18+
},
19+
})
20+
}
21+
22+
export const setVoice = (voice: PrimitiveSource<HikkakuString>) => {
23+
return block('text2speech_setVoice', {
24+
inputs: {
25+
VOICE: fromPrimitiveSource(InputType.String, voice, 'ALTO'),
26+
},
27+
})
28+
}
29+
30+
export const setLanguage = (language: PrimitiveSource<HikkakuString>) => {
31+
return block('text2speech_setLanguage', {
32+
inputs: {
33+
LANGUAGE: fromPrimitiveSource(InputType.String, language, 'en'),
34+
},
35+
})
36+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, expect, test } from 'vite-plus/test'
2+
import { block, createBlocks } from '../core/composer'
3+
import { say } from './looks'
4+
import { getViewerLanguage, translate } from './translate'
5+
6+
describe('blocks/translate', () => {
7+
test('creates translate extension blocks', () => {
8+
const blocks = createBlocks(() => {
9+
block('event_whenflagclicked', { topLevel: true })
10+
say(translate('hello', 'ja'))
11+
say(getViewerLanguage())
12+
})
13+
14+
const opcodes = Object.values(blocks).map((b) => b.opcode)
15+
expect(opcodes).toContain('translate_getTranslate')
16+
expect(opcodes).toContain('translate_getViewerLanguage')
17+
})
18+
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { InputType } from 'sb3-types/enum'
2+
import { fromPrimitiveSource } from '../core/block-helper'
3+
import { valueBlock } from '../core/composer'
4+
import type { HikkakuString, PrimitiveSource } from '../core/types'
5+
6+
export const translate = (
7+
words: PrimitiveSource<HikkakuString>,
8+
language: PrimitiveSource<HikkakuString>,
9+
) => {
10+
return valueBlock<HikkakuString>('translate_getTranslate', {
11+
inputs: {
12+
WORDS: fromPrimitiveSource(InputType.String, words, 'hello'),
13+
LANGUAGE: fromPrimitiveSource(InputType.String, language, 'ja'),
14+
},
15+
})
16+
}
17+
18+
export const getViewerLanguage = () => {
19+
return valueBlock<HikkakuString>('translate_getViewerLanguage', {})
20+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { describe, expect, test } from 'vite-plus/test'
2+
import { block, createBlocks } from '../core/composer'
3+
import { say } from './looks'
4+
import {
5+
setVideoTransparency,
6+
videoOn,
7+
videoToggle,
8+
whenMotionGreaterThan,
9+
} from './videosensing'
10+
11+
describe('blocks/videosensing', () => {
12+
test('creates video sensing extension blocks', () => {
13+
const blocks = createBlocks(() => {
14+
block('event_whenflagclicked', { topLevel: true })
15+
whenMotionGreaterThan(10)
16+
say(videoOn('motion', 'this sprite'))
17+
videoToggle('on')
18+
setVideoTransparency(50)
19+
})
20+
21+
const opcodes = Object.values(blocks).map((b) => b.opcode)
22+
expect(opcodes).toContain('videoSensing_whenMotionGreaterThan')
23+
expect(opcodes).toContain('videoSensing_videoOn')
24+
expect(opcodes).toContain('videoSensing_videoToggle')
25+
expect(opcodes).toContain('videoSensing_setVideoTransparency')
26+
})
27+
})
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { InputType } from 'sb3-types/enum'
2+
import { fromPrimitiveSource } from '../core/block-helper'
3+
import { block, valueBlock } from '../core/composer'
4+
import type {
5+
HikkakuNumber,
6+
HikkakuString,
7+
PrimitiveSource,
8+
} from '../core/types'
9+
10+
export type VideoSensingAttribute = 'motion' | 'direction'
11+
export type VideoSensingSubject = 'this sprite' | 'stage'
12+
export type VideoState = 'on' | 'off' | 'on-flipped'
13+
14+
export const whenMotionGreaterThan = (
15+
reference: PrimitiveSource<HikkakuNumber>,
16+
) => {
17+
return block('videoSensing_whenMotionGreaterThan', {
18+
inputs: {
19+
REFERENCE: fromPrimitiveSource(InputType.Number, reference, 10),
20+
},
21+
})
22+
}
23+
24+
export const videoOn = (
25+
attribute: PrimitiveSource<HikkakuString>,
26+
subject: PrimitiveSource<HikkakuString>,
27+
) => {
28+
return valueBlock<HikkakuNumber>('videoSensing_videoOn', {
29+
inputs: {
30+
ATTRIBUTE: fromPrimitiveSource(InputType.String, attribute, 'motion'),
31+
SUBJECT: fromPrimitiveSource(InputType.String, subject, 'this sprite'),
32+
},
33+
})
34+
}
35+
36+
export const videoToggle = (state: PrimitiveSource<HikkakuString>) => {
37+
return block('videoSensing_videoToggle', {
38+
inputs: {
39+
VIDEO_STATE: fromPrimitiveSource(InputType.String, state, 'on'),
40+
},
41+
})
42+
}
43+
44+
export const setVideoTransparency = (
45+
transparency: PrimitiveSource<HikkakuNumber>,
46+
) => {
47+
return block('videoSensing_setVideoTransparency', {
48+
inputs: {
49+
TRANSPARENCY: fromPrimitiveSource(InputType.Number, transparency, 50),
50+
},
51+
})
52+
}

0 commit comments

Comments
 (0)