Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

I made a volume slider for SugarCube 2 if anyone else needs one.

edited April 2017 in Workshop
Here's the code:

Note: If you're using SugarCube 2.15.0 or later, it's recommended that you use <<include>> instead of <<display>> (just run a find and replace "<<display" for "<<include"). I used <<display>> in this code so that it'd have compatibility across all versions.

CSS your slider using this handy site: range.css. Note that you might have to adjust some things, especially stuff related to focusing, to cooperate with SugarCube's default styles.

In your story's JavaScript (Twine 2: Story JavaScript; Twine 1: script-tagged passage):
//I tried setup, but it just wouldn't work for me (I'm sure it's an operator error).  I broke down and made the function global.
window.volumeSlider = function () {
//display the volControl passage whenever the slider is adjusted:
  $('input[name=volume]').on('change', function(){
    State.variables.vol = $('input[name=volume]').val();
    new Wikifier(null, Story.get('volControl').text);
  });
}

In your story:
::StoryInit
<<set $vol to 10>>
<<set $volStr to "10">> /% the string value helps us out a bit later on %/
/% or whatever you want your default audio level to be (between 0(off) and 10 (loudest)) %/
<<set $audioswitch to 1>> /% for the mute button (more on that later), leave this line out if you don't want/need the mute button %/

::volume [nobr]
<span id="volMaker"></span>/% this is just here for the postdisplay's append %/

/% I have this passage (and others) tagged 'nobr' so I don't have to worry about whitespace. %/

/% the following script builds the volume slider 
   it will 'remember' where it was set to               %/
<<script>>
postdisplay['volume-control'] = function (taskName) {
  delete postdisplay[taskName]; //don't need the task in other passages
  $('#volMaker').append('<input type="range" name="volume" min="0" max="10" step="1" value="' + State.variables.vol + '" oninput="volumeSlider();" />');
};
<</script>>

::volControl [nobr]
/% <<switch>> didn't work right for me here, just kept getting the default;
   floating point values, i guess?                                                  %/
<<if $vol lte 1>>
    <<masteraudio volume 0>>
<<elseif $vol lte 2>>
    <<masteraudio volume 0.20>>
<<elseif $vol lte 3>>
    <<masteraudio volume 0.30>>
<<elseif $vol lte 4>>
    <<masteraudio volume 0.40>>
<<elseif $vol lte 5>>
    <<masteraudio volume 0.50>>
<<elseif $vol lte 6>>
    <<masteraudio volume 0.60>>
<<elseif $vol lte 7>>
    <<masteraudio volume 0.70>>
<<elseif $vol lte 8>>
    <<masteraudio volume 0.80>>
<<elseif $vol lte 9>>
    <<masteraudio volume 0.90>>
<<else>>
    <<masteraudio volume 1.00>>
<</if>>

/% prevent movement when going from double to single digits 
   by adding a leading '0' to single-digits                   %/
<<if $vol lt 10>>
  <<set $volStr to "0" + $vol>>
<<else>>
  <<set $volStr to $vol>>
<</if>>

/% replace the displayed audio level %/
<<replace "#vol">>\
  <<print $volStr>>\
<</replace>>

::muter [nobr]
/% $audioswitch just keeps track of the 'position' of the mute switch:
   1 = currently unmuted
   0 = currently muted                                                 %/
   
<<button "Mute">>
  <<if $audioswitch>>
    <<masteraudio mute>>
    <<set $audioswitch to 0>>
  <<else>>
    <<masteraudio unmute>>
    <<set $audioswitch to 1>>
  <</if>>
<</button>>
/% you can omit this passage/code if you don't want the mute button %/

Optional: You can put the whole thing together as a widget if you want, for ease of use.
::volumeWidget [widget]
<<widget "volumeControls">>Volume: <span id="vol"><<print $volStr>></span> <<display "vol_settings">> <<display "muter">><</widget>>

USE:
/% with widget: %/
<<volumeControls>>

or 

/% without widget: %/
Volume: <span id="vol"><<print $volStr>></span> <<display "vol_settings">> <<display "muter">>

Obviously, if you've decided to leave the mute button out, you'll want to leave out the last display macro.

Below is the CSS I'm using for reference, but note that in my story, the background is white, so YMMV if you don't change the colors. You can use your browser's default styles, they don't look too bad from what I've seen:
input[type=range] {
  -webkit-appearance: none;
  width: 200px;
  margin: 0 10px;
  vertical-align: text-bottom;
  border: 0;
}
input[type=range]:focus {
  outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
  width: 100%;
  height: 5px;
  cursor: pointer;
  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
  background: #000000;
  border-radius: 0px;
  border: 0px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
  box-shadow: 0px 0px 0px rgba(0, 0, 62, 0.67), 0px 0px 0px rgba(0, 0, 88, 0.67);
  border: 1.9px solid #000000;
  height: 15px;
  width: 15px;
  border-radius: 15px;
  background: #ffffff;
  cursor: pointer;
  -webkit-appearance: none;
  margin-top: -5px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
  background: #0a0a0a;
}
input[type=range]::-moz-range-track {
  width: 100%;
  height: 5px;
  cursor: pointer;
  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
  background: #000000;
  border-radius: 0px;
  border: 0px solid #010101;
}
input[type=range]::-moz-range-thumb {
  box-shadow: 0px 0px 0px rgba(0, 0, 62, 0.67), 0px 0px 0px rgba(0, 0, 88, 0.67);
  border: 1.9px solid #000000;
  height: 15px;
  width: 15px;
  border-radius: 15px;
  background: #ffffff;
  cursor: pointer;
}
input[type=range]::-ms-track {
  width: 100%;
  height: 5px;
  cursor: pointer;
  background: transparent;
  border-color: transparent;
  color: transparent;
}
input[type=range]::-ms-fill-lower {
  background: #000000;
  border: 0px solid #010101;
  border-radius: 0px;
  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
  background: #000000;
  border: 0px solid #010101;
  border-radius: 0px;
  box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-thumb {
  box-shadow: 0px 0px 0px rgba(0, 0, 62, 0.67), 0px 0px 0px rgba(0, 0, 88, 0.67);
  border: 1.9px solid #000000;
  height: 15px;
  width: 15px;
  border-radius: 15px;
  background: #ffffff;
  cursor: pointer;
  height: 5px;
}
input[type=range]:focus::-ms-fill-lower {
  background: #000000;
}
input[type=range]:focus::-ms-fill-upper {
  background: #0a0a0a;
}

I'm sure it's not perfect/there are better ways. I welcome suggestions and let me know if there are any errors.

Comments

  • Chapel wrote: »
    ::volumeWidget [widget]
    <<widget "volumeControls">>Volume: <span id="vol"><<print $volStr>></span> <<display "vol_settings">> <<display "muter">><</widget>>
    

    USE:
    /% with widget: %/
    <<volumeControls>>
    
    or 
    
    /% without widget: %/
    Volume: <span id="vol"><<print $volStr>></span> <<display "vol_settings">> <<display "muter">>
    
    I made a mistake. <<display "vol_settings">> should be <<display "volume">> in both cases in the above code. Sorry about that.
Sign In or Register to comment.