@@ -459,7 +459,7 @@ class SoundEditor extends React.Component {
459
459
460
460
handleModifyMenu ( ) {
461
461
const playURI = `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OSIgaGVpZ2h0PSI1MiIgdmlld0JveD0iLTUgMCA0OSA0OCI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTM1LjUwOCAxOS4zNzRjNC4yNTkgMi41NTYgNC4yNTIgNi43MDIgMCA5LjI1NEwxMi43MTIgNDIuMzA1Yy00LjI1OCAyLjU1NS03LjcxLjU5Ny03LjcxLTQuMzhWMTAuMDc3YzAtNC45NzMgMy40NTgtNi45MyA3LjcxLTQuMzh6Ii8+PC9zdmc+` ;
462
- const stopURI = `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MiIgaGVpZ2h0PSI1MiIgdmlld0JveD0iMCAwIDUyIDUyIj48cmVjdCBmaWxsPSIjRkZGIiB3aWR0aD0iNDQiIGhlaWdodD0iNDQiIHJ4PSI0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDQpIi8+PC9zdmc+ ` ;
462
+ const stopURI = `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MiIgaGVpZ2h0PSI1MiIgdmlld0JveD0iMCAwIDUyIDUyIj48cmVjdCBmaWxsPSIjRkZGIiB3aWR0aD0iMzUiIGhlaWdodD0iMzUiIHJ4PSI0IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg4LjUgOC41KSIvPjwvc3ZnPg== ` ;
463
463
464
464
const genSliderDiv = ( title , params , scalar ) => {
465
465
const div = document . createElement ( "div" ) ;
@@ -587,75 +587,83 @@ class SoundEditor extends React.Component {
587
587
vNumber . oninput = vNumber . onchange ;
588
588
}
589
589
handleFormatMenu ( ) {
590
+ const genTitle = ( text ) => {
591
+ const label = document . createElement ( "div" ) ;
592
+ label . style = "font-weight: 500;font-size: 14px;margin-bottom: 5px;" ;
593
+ const inner = document . createElement ( "span" ) ;
594
+ inner . textContent = text ;
595
+ label . appendChild ( inner ) ;
596
+ return label ;
597
+ } ;
598
+ const genCheckableLabel = ( text , id , isChecked ) => {
599
+ const div = document . createElement ( "div" ) ;
600
+ div . classList . add ( "check-outer" ) ;
601
+ div . id = id ;
602
+ div . style = "margin-top: 3px;" ;
603
+ const check = document . createElement ( "input" ) ;
604
+ check . style = "margin-right: 8px;" ;
605
+ check . type = "radio" ;
606
+ check . checked = isChecked ?? false ;
607
+ const label = document . createElement ( "span" ) ;
608
+ label . textContent = text ;
609
+ div . append ( check , label ) ;
610
+ return div ;
611
+ } ;
612
+
590
613
const sampleRates = [
591
614
3000 , 4000 , 8000 , 11025 , 16000 , 22050 , 32000 , 44100 ,
592
615
48000 , 88200 , 96000 , 176400 , 192000 , 352800 , 384000 ,
593
616
] ;
594
617
let selectedSampleRate = this . props . sampleRate ;
595
618
let selectedForceRate = false ;
596
- const menu = this . displayPopup ( "Format Sound" , 580 , 300 , "Apply" , "Cancel" , ( ) => {
619
+ const menu = this . displayPopup ( "Format Sound" , 350 , 275 , "Apply" , "Cancel" , ( ) => {
597
620
// accepted
598
- const edits = {
599
- sampleRate : selectedSampleRate ,
600
- } ;
601
- if ( selectedForceRate ) {
602
- edits . sampleRateEnforced = selectedSampleRate ;
603
- }
621
+ const edits = { sampleRate : selectedSampleRate } ;
622
+ if ( selectedForceRate ) edits . sampleRateEnforced = selectedSampleRate ;
604
623
this . handleEffect ( edits ) ;
605
624
} ) ;
606
625
607
- menu . textarea . style = "padding:8px;" ;
626
+ menu . textarea . style = "padding: 10px 20px;" ;
627
+ const rateTitle = genTitle ( "New Sample Rate:" ) ;
608
628
609
- const labelSampleRate = document . createElement ( "p" ) ;
610
- labelSampleRate . innerHTML = "Sample Rate" ;
611
- labelSampleRate . style = "font-size:14px;" ;
612
- menu . textarea . append ( labelSampleRate ) ;
613
- const inputSampleRate = document . createElement ( "select" ) ;
614
- inputSampleRate . style = "width:50%;"
615
- menu . textarea . append ( inputSampleRate ) ;
629
+ const rateSelector = document . createElement ( "select" ) ;
630
+ rateSelector . style = "border-radius: 5px;text-align: center;margin-left: 10px;width: 50%;" ;
616
631
for ( const rate of sampleRates ) {
617
632
const option = document . createElement ( "option" ) ;
618
633
option . value = rate ;
619
- option . innerHTML = ` ${ rate } ` ;
620
- inputSampleRate . append ( option ) ;
634
+ option . textContent = rate ;
635
+ rateSelector . append ( option ) ;
621
636
}
622
- inputSampleRate . selectedIndex = sampleRates . indexOf ( this . props . sampleRate ) ;
623
- const labelSampleRateWarning = document . createElement ( "p" ) ;
624
- labelSampleRateWarning . innerHTML = "Choosing a higher sample rate than the current rate will not make the existing audio higher quality." ;
625
- labelSampleRateWarning . style = "font-size:13px;opacity:0.5;" ;
626
- menu . textarea . append ( labelSampleRateWarning ) ;
627
- inputSampleRate . onchange = ( ) => {
628
- selectedSampleRate = inputSampleRate . value ;
637
+ rateSelector . selectedIndex = sampleRates . indexOf ( this . props . sampleRate ) ;
638
+ rateSelector . onchange = ( ) => {
639
+ selectedSampleRate = rateSelector . value ;
629
640
} ;
641
+ rateTitle . appendChild ( rateSelector ) ;
642
+
643
+ const warningDiv = document . createElement ( "div" ) ;
644
+ warningDiv . style . marginBottom = "15px" ;
645
+ const warning = document . createElement ( "i" ) ;
646
+ warning . textContent = "Choosing a higher sample rate than the current rate will not make the existing audio higher quality" ;
647
+ warning . style = "font-size:13px;opacity:0.5;" ;
648
+ warningDiv . appendChild ( warning ) ;
649
+
650
+ const applicatorDiv = document . createElement ( "div" ) ;
651
+ applicatorDiv . append (
652
+ genCheckableLabel ( "this selection" , "0" , true ) ,
653
+ genCheckableLabel ( "whole sound" , "1" , false )
654
+ ) ;
655
+ applicatorDiv . addEventListener ( "click" , ( e ) => {
656
+ const div = e . target . closest ( `div[class="check-outer"]` ) ;
657
+ if ( ! div ) return ;
630
658
631
- const labelResampleAudio = document . createElement ( "label" ) ;
632
- labelResampleAudio . innerHTML = "Enforce New Sample Rate" ;
633
- menu . textarea . append ( labelResampleAudio ) ;
634
- const inputResampleAudio = document . createElement ( "input" ) ;
635
- inputResampleAudio . type = "checkbox" ;
636
- inputResampleAudio . style = "margin-right:8px;" ;
637
- labelResampleAudio . prepend ( inputResampleAudio ) ;
638
- const labelResampleAudioWarning = document . createElement ( "p" ) ;
639
- labelResampleAudioWarning . innerHTML = "This changes the properties of the entire sound, "
640
- + "making lower sample rates use less file size. "
641
- + "However, audio added to this sound will only be able to use the new sample rate." ;
642
- labelResampleAudioWarning . style = "font-size:13px;opacity:0.5;" ;
643
- menu . textarea . append ( labelResampleAudioWarning ) ;
644
-
645
- const warning = document . createElement ( "p" ) ;
646
- warning . innerHTML = "Applying these changes will cause the entire sound to change, not just the selected area." ;
647
- warning . style = "font-size:14px;" ;
648
- warning . style . display = "none" ;
649
- menu . textarea . append ( warning ) ;
650
-
651
- inputResampleAudio . onchange = ( ) => {
652
- selectedForceRate = inputResampleAudio . checked ;
653
- if ( selectedForceRate ) {
654
- warning . style . display = "" ;
655
- } else {
656
- warning . style . display = "none" ;
659
+ for ( const checkable of Array . from ( div . parentNode . children ) ) {
660
+ checkable . firstChild . checked = false ;
657
661
}
658
- } ;
662
+ div . firstChild . checked = true ;
663
+ if ( div . id === 0 ) selectedForceRate = div . id === 0 ;
664
+ e . stopPropagation ( ) ;
665
+ } ) ;
666
+ menu . textarea . append ( rateTitle , warningDiv , genTitle ( "Apply to:" ) , applicatorDiv ) ;
659
667
}
660
668
661
669
// TODO: use actual scratch-gui menus instead of this
0 commit comments