diff --git a/index.css b/index.css
index 15ce521..bfdb8be 100644
--- a/index.css
+++ b/index.css
@@ -73,34 +73,77 @@ body{
background-size: 200% 2000%;
background-position: 0% 0%;
}
-.sim_button{
+
+/* Sim UI */
+.sim_ui{
position: absolute;
width: 200px;
height: 100px;
border: none !important;
}
-.sim_button > div{
+.sim_ui > div{
position: absolute;
background: #dd4040;
color: #fff;
text-align: center;
border-radius: 10px;
}
-.sim_button > #reset_button{
+.sim_ui > #reset_button{
width: 150px;
left:25px;
top:0px;
font-size: 0.8em;
transition: top 0.3s ease-in-out;
}
-.sim_button > #start_button{
+.sim_ui > #start_button{
width: 200px;
padding: 0.5em 0;
}
-.sim_button[active] > #reset_button{
+.sim_ui[active] > #reset_button{
top:60px;
}
+/* Sandbox UI */
+.sandbox_ui{
+ width: 270px;
+}
+.sandbox_ui input[type="range"]{
+ width: 100%;
+}
+.choose_one{
+ overflow: hidden;
+}
+.choose_one > div{
+ float: left;
+ margin: 3px;
+ opacity: 0.25;
+}
+.choose_one > div[selected]{
+ opacity: 1;
+}
+.choose_color{
+ width: 40px;
+ height: 40px;
+ background: url(sprites/peeps.png);
+ background-size: auto 100%;
+ transform: scale(1.2);
+}
+.choose_tool{
+ font-size: 16px;
+ line-height: 16px;
+ border: 1px solid black;
+ padding: 3px;
+ border-radius: 5px;
+}
+#sandbox_shortcuts_label{
+ font-size: 18px;
+}
+#sandbox_shortcuts{
+ font-size: 14px;
+ line-height: 1.5em;
+ color: #999;
+}
+
/* MODAL */
#modal{
display: none;
diff --git a/index.html b/index.html
index 489dffb..dec18b4 100644
--- a/index.html
+++ b/index.html
@@ -278,6 +278,53 @@ WIN
↺ reset
+
+Contagion:
+
+
+simple
+
+
+complex
+
+
+The Contagion's Color:
+
+
+Select a tool...
+
+
+
+Draw Connections
+
+
+Add Peep
+
+
+Add "Infected" Peep
+
+
+Move Peep
+
+
+Delete Peep
+
+
+CLEAR IT ALL
+
+
+
+(...or, use keyboard shortcuts!)
+
+
+[1]: Add Peep
+
+[2]: Add Infected Peep
+
+[Space]: Move Peep
+
+[Backspace]: Delete Peep
+
@@ -312,6 +359,8 @@ WIN
+
+
diff --git a/js/chapters/2_Simple_Contagion.js b/js/chapters/2_Simple_Contagion.js
index ed49acb..0fb352b 100644
--- a/js/chapters/2_Simple_Contagion.js
+++ b/js/chapters/2_Simple_Contagion.js
@@ -44,7 +44,7 @@ SLIDES.push(
{
type:"box",
x:380, y:165,
- sim_button:"red"
+ sim_ui:"red"
},
// Outro text
@@ -104,7 +104,7 @@ SLIDES.push(
{
type:"box",
x:380, y:290,
- sim_button:"red"
+ sim_ui:"red"
},
// Intro text
diff --git a/js/chapters/3_Complex_Contagion.js b/js/chapters/3_Complex_Contagion.js
index bd5b521..0ca92df 100644
--- a/js/chapters/3_Complex_Contagion.js
+++ b/js/chapters/3_Complex_Contagion.js
@@ -35,7 +35,7 @@ SLIDES.push(
{
type:"box",
x:440, y:225,
- sim_button:"red"
+ sim_ui:"red"
},
// End text
@@ -96,7 +96,7 @@ SLIDES.push(
{
type:"box",
x:380, y:290,
- sim_button:"red"
+ sim_ui:"red"
},
// Intro text
@@ -172,7 +172,7 @@ SLIDES.push(
{
type:"box",
x:380, y:140,
- sim_button:"red"
+ sim_ui:"red"
},
// Outro text
diff --git a/js/chapters/5_Sandbox.js b/js/chapters/5_Sandbox.js
index 291b210..01c0b34 100644
--- a/js/chapters/5_Sandbox.js
+++ b/js/chapters/5_Sandbox.js
@@ -5,6 +5,7 @@ SLIDES.push(
clear:true,
add:[
+
// The fullscreen simulation
{
type:"sim",
@@ -15,7 +16,23 @@ SLIDES.push(
"peeps":[[443,213,1],[570,309,0],[686,194,0]],
"connections":[[0,1,0],[1,2,0]]
}
+ },
+
+ // The Sandbox UI
+ {
+ type:"box",
+ x:0, y:0,
+ sandbox:true
+ },
+
+ // Simulation UI
+ {
+ type:"box",
+ x:35, y:450,
+ sim_ui:"red"
}
+
+
]
}
diff --git a/js/lib/helpers.js b/js/lib/helpers.js
index a83e804..4ccad9e 100644
--- a/js/lib/helpers.js
+++ b/js/lib/helpers.js
@@ -44,7 +44,7 @@ function cloneObject(obj){
// Get words
function getWords(wordsID){
- return $("words#"+wordsID).innerHTML;
+ return $("words#"+wordsID).innerHTML.trim();
}
// Remove from array
diff --git a/js/sim/Simulations.js b/js/sim/Simulations.js
index 015afad..22a65fb 100644
--- a/js/sim/Simulations.js
+++ b/js/sim/Simulations.js
@@ -295,7 +295,14 @@ function Sim(config){
// Kill
self.kill = function(){
+
self.clear();
+
+ // key handlers, too
+ _keyHandlers.forEach(function(_handler){
+ unsubscribe(_handler);
+ });
+
};
///////////////////
@@ -361,8 +368,10 @@ function Sim(config){
};
self.reload = function(){
+ var contagionLevel = self.contagion; // hack for sandbox: keep contagion the same
self.STEP = 0;
self.init();
+ self.contagion = contagionLevel;
};
self.nextStep = function(){
@@ -387,7 +396,8 @@ function Sim(config){
var _draggingPeep = null;
var _draggingOffset = {x:0,y:0};
- subscribe("key/down/space",function(){
+ var _keyHandlers = [];
+ _keyHandlers.push(subscribe("key/down/space",function(){
if(!_draggingPeep){ // prevent double-activation
var hoveredPeep = self.getHoveredPeep(0);
if(hoveredPeep){
@@ -396,26 +406,26 @@ function Sim(config){
_draggingOffset.y = _draggingPeep.y-self.mouse.y;
}
}
- });
- subscribe("key/up/space",function(){
+ }));
+ _keyHandlers.push(subscribe("key/up/space",function(){
_draggingPeep = null;
- });
- subscribe("key/down/1",function(){
+ }));
+ _keyHandlers.push(subscribe("key/down/1",function(){
_addPeepAtMouse(false);
- });
- subscribe("key/down/2",function(){
+ }));
+ _keyHandlers.push(subscribe("key/down/2",function(){
_addPeepAtMouse(true);
- });
+ }));
var _addPeepAtMouse = function(infected){
var overlapPeep = self.getHoveredPeep(20);
if(!overlapPeep){
self.addPeep(self.mouse.x, self.mouse.y, infected);
}
};
- subscribe("key/down/delete",function(){
+ _keyHandlers.push(subscribe("key/down/delete",function(){
var toDeletePeep = self.getHoveredPeep(0);
if(toDeletePeep) self.removePeep(toDeletePeep);
- });
+ }));
self.getCurrentNetwork = function(){
var savedNetwork = {
diff --git a/js/slideshow/Boxes.js b/js/slideshow/Boxes.js
index 66a82a1..53879af 100644
--- a/js/slideshow/Boxes.js
+++ b/js/slideshow/Boxes.js
@@ -61,9 +61,14 @@ function Boxes(){
box.style.backgroundImage = "url("+config.img+")"
}
- // Sim Button
- if(config.sim_button){
- var simButton = SimButton(box, config.sim_button);
+ // Sim UI
+ if(config.sim_ui){
+ var simUI = new SimUI(box, config.sim_ui);
+ }
+
+ // Sandbox UI
+ if(config.sandbox){
+ var sandboxUI = new SandboxUI(box);
}
// Replace "next" buttons!
@@ -128,49 +133,4 @@ function Boxes(){
};
-}
-
-function SimButton(container, color){
-
- var self = this;
- self.container = container;
- self.container.classList.add("sim_button");
-
- // RESET
- var resetButton = document.createElement("div");
- resetButton.id = "reset_button";
- resetButton.innerHTML = getWords("sim_reset");
- self.container.appendChild(resetButton);
- resetButton.onclick = function(){
- if(Simulations.IS_RUNNING){
- publish("sim/reset");
- _updateButtonUI();
- }
- };
-
- // START / NEXT
- var startButton = document.createElement("div");
- startButton.id = "start_button";
- self.container.appendChild(startButton);
- startButton.onclick = function(){
- if(!Simulations.IS_RUNNING){
- publish("sim/start");
- _updateButtonUI();
- }else{
- publish("sim/next");
- }
- };
-
- // Update button UI
- var _updateButtonUI = function(){
- if(!Simulations.IS_RUNNING){
- startButton.innerHTML = getWords("sim_start");
- self.container.removeAttribute("active");
- }else{
- startButton.innerHTML = getWords("sim_next");
- self.container.setAttribute("active",true);
- }
- };
- _updateButtonUI();
-
-}
+}
\ No newline at end of file
diff --git a/js/slideshow/SandboxUI.js b/js/slideshow/SandboxUI.js
index 846fd16..c4e23ec 100644
--- a/js/slideshow/SandboxUI.js
+++ b/js/slideshow/SandboxUI.js
@@ -1,2 +1,155 @@
-function SandboxUI(){
-}
\ No newline at end of file
+function SandboxUI(container){
+
+ var self = this;
+ self.container = container;
+ self.container.classList.add("sandbox_ui");
+
+ //////////////////////
+ // Contagion Slider //
+ //////////////////////
+
+ var contagionLabel = document.createElement("div");
+ var contagionInput = document.createElement("input");
+ contagionInput.type = "range";
+ contagionInput.min = 0;
+ contagionInput.max = 1;
+ contagionInput.step = 0.05;
+ contagionInput.value = 0.25;
+ contagionInput.oninput = function(){
+ _updateContagion();
+ };
+ var _labelContagion0 = getWords("sandbox_contagion");
+ var _labelContagion1 = getWords("sandbox_contagion_simple");
+ var _labelContagion2 = getWords("sandbox_contagion_complex");
+ var _updateContagion = function(){
+
+ // update sim
+ var contagion = contagionInput.value;
+ slideshow.simulations.sims[0].contagion = contagion;
+
+ // update label
+ var label = _labelContagion0+" ";
+ label += Math.round(contagion*100)+"% ";
+ label += "("+((contagion==0) ? _labelContagion1 : _labelContagion2)+")";
+ contagionLabel.innerHTML = label;
+
+ };
+ container.appendChild(contagionLabel);
+ container.appendChild(contagionInput);
+ setTimeout(function(){
+ _updateContagion();
+ },1);
+
+ ///////////////////////////
+ // Choose Color of Peeps //
+ ///////////////////////////
+
+ var colorChooserLabel = document.createElement("div");
+ colorChooserLabel.innerHTML = getWords("sandbox_color_chooser");
+ colorChooserLabel.style.marginTop = "1em";
+ var colorChooser = new ChooseOne({
+ options:[
+ 1, // red
+ 2, // yellow
+ 3, // blue
+ 4, // green
+ 5, // pink
+ ],
+ makeButton:function(value){
+ var button = document.createElement("div");
+ button.className = "choose_color";
+ button.style.backgroundPosition = (-40*value)+"px 0px";
+ return button;
+ },
+ oninput:function(value){
+ // update sim
+ slideshow.simulations.sims[0].options.infectedFrame = value;
+ }
+ });
+ container.appendChild(colorChooserLabel);
+ container.appendChild(colorChooser.dom);
+
+ ////////////////////////////
+ // Choose Tool for Pencil //
+ ////////////////////////////
+
+ var toolChooserLabel = document.createElement("div");
+ toolChooserLabel.innerHTML = getWords("sandbox_tool_chooser");
+ toolChooserLabel.style.marginTop = "1em";
+ var toolChooser = new ChooseOne({
+ options:[
+ "pencil",
+ "add",
+ "add_infected",
+ "move",
+ "delete",
+ "clear"
+ ],
+ makeButton: function(value){
+ var button = document.createElement("div");
+ button.className = "choose_tool";
+ button.innerHTML = getWords("sandbox_tool_"+value);
+ return button;
+ },
+ oninput:function(value){
+ }
+ });
+ container.appendChild(toolChooserLabel);
+ container.appendChild(toolChooser.dom);
+
+ ////////////////////////
+ // Keyboard Shortcuts //
+ ////////////////////////
+
+ var shortcutsLabel = document.createElement("div");
+ shortcutsLabel.innerHTML = getWords("sandbox_shortcuts_label");
+ shortcutsLabel.id = "sandbox_shortcuts_label";
+ shortcutsLabel.style.marginTop = "1em";
+ var shortcuts = document.createElement("div");
+ shortcuts.innerHTML = getWords("sandbox_shortcuts");
+ shortcuts.id = "sandbox_shortcuts";
+ container.appendChild(shortcutsLabel);
+ container.appendChild(shortcuts);
+
+
+}
+
+function ChooseOne(config){
+
+ var self = this;
+
+ // Container
+ self.dom = document.createElement("div");
+ self.dom.className = "choose_one";
+
+ // Make Buttons
+ var buttons = [];
+ config.options.forEach(function(option){
+
+ var buttonConfig = option;//.button;
+ var value = option;//.value;
+
+ // New Button
+ var buttonDOM = config.makeButton(buttonConfig);
+ self.dom.appendChild(buttonDOM);
+ buttons.push(buttonDOM);
+
+ // On Input
+ buttonDOM.onclick = function(){
+ self.highlight(buttonDOM); // highlight
+ config.oninput(value); // input
+ };
+
+ });
+
+ // Highlight
+ self.highlight = function(toHighlight){
+ buttons.forEach(function(button){
+ button.removeAttribute("selected");
+ });
+ toHighlight.setAttribute("selected",true);
+ };
+ self.highlight(buttons[0]); // highlight 1st one always, whatever
+
+}
+
diff --git a/js/slideshow/Scratch.js b/js/slideshow/Scratch.js
index 555d91d..e7b7ae3 100644
--- a/js/slideshow/Scratch.js
+++ b/js/slideshow/Scratch.js
@@ -20,7 +20,6 @@ function Scratch(){
var handle = subscribe("update", function(){
var yOffset = Math.floor(frame)*(-100);
self.dom.style.backgroundPosition = xOffset+"% "+yOffset+"%";
- console.log(xOffset, yOffset);
if(frame>19){
unsubscribe(handle);
if(callback) callback();
diff --git a/js/slideshow/SimUI.js b/js/slideshow/SimUI.js
new file mode 100644
index 0000000..1d4f92c
--- /dev/null
+++ b/js/slideshow/SimUI.js
@@ -0,0 +1,44 @@
+function SimUI(container, color){
+
+ var self = this;
+ self.container = container;
+ self.container.classList.add("sim_ui");
+
+ // RESET
+ var resetButton = document.createElement("div");
+ resetButton.id = "reset_button";
+ resetButton.innerHTML = getWords("sim_reset");
+ self.container.appendChild(resetButton);
+ resetButton.onclick = function(){
+ if(Simulations.IS_RUNNING){
+ publish("sim/reset");
+ _updateButtonUI();
+ }
+ };
+
+ // START / NEXT
+ var startButton = document.createElement("div");
+ startButton.id = "start_button";
+ self.container.appendChild(startButton);
+ startButton.onclick = function(){
+ if(!Simulations.IS_RUNNING){
+ publish("sim/start");
+ _updateButtonUI();
+ }else{
+ publish("sim/next");
+ }
+ };
+
+ // Update button UI
+ var _updateButtonUI = function(){
+ if(!Simulations.IS_RUNNING){
+ startButton.innerHTML = getWords("sim_start");
+ self.container.removeAttribute("active");
+ }else{
+ startButton.innerHTML = getWords("sim_next");
+ self.container.setAttribute("active",true);
+ }
+ };
+ _updateButtonUI();
+
+}
diff --git a/js/slideshow/Slideshow.js b/js/slideshow/Slideshow.js
index b2edc01..d6ab500 100644
--- a/js/slideshow/Slideshow.js
+++ b/js/slideshow/Slideshow.js
@@ -25,8 +25,14 @@ function Slideshow(){
// GOTO and NEXT
var _delay = 300;
+ self.IS_TRANSITIONING = false;
self.goto = function(index){
+
+ // Wait for transition to finish!
+ if(self.IS_TRANSITIONING) return;
+ self.IS_TRANSITIONING = true;
+ // Which slide?
self.slideIndex = index;
var isFirstSlide = (self.currentSlide==null);
var slide = SLIDES[self.slideIndex];
@@ -105,6 +111,11 @@ function Slideshow(){
self.currentState = {};
if(slide.onstart) slide.onstart(self, self.currentState);
+ // Transition done... sorta!
+ _setTimeout(function(){
+ self.IS_TRANSITIONING = false;
+ },800);
+
}, _delayNewSlide);
// Tell everyone it's a new chapter