UNPKG

lettuce

Version:

Lettuce JS, Mini Mobile Framework for Romantic with DSL.

605 lines (561 loc) 23.1 kB
(function() { var pe = game.ParticleEditor = game.ParticleEditor || {}; pe.PropertyWrapper = Object.extend({ init : function(propertyName) { this.object = null; this.propertyPath = propertyName.split("."); this.propertyName = this.propertyPath.pop(); }, _getNestedObject : function() { var object = this.object; for ( var i = 0, propertyPath = this.propertyPath, length = propertyPath.length; i < length; ++i) { object = object[propertyPath[i]]; } return object; }, getValue : function() { if (!this.object) { return; } var object = this._getNestedObject(); return object[this.propertyName]; }, setValue : function(value) { if (!this.object) { return false; } var object = this._getNestedObject(), propertyName = this.propertyName; if (object[propertyName] !== value) { object[propertyName] = value; me.event.publish("propertyChanged", [ this.object ]); return true; } return false; }, }); pe.WidgetBase = Object.extend({ init : function(propertyName) { this.property = new pe.PropertyWrapper(propertyName); this.rootNode = null; }, addInput : function(label, input) { if (!this.rootNode) { this.rootNode = document.createElement("div"); } var labelNode = document.createElement("label"); labelNode.appendChild(document.createTextNode(label.replace(/([A-Z])/g, ' $1').toLowerCase())) labelNode.appendChild(input) this.rootNode.appendChild(labelNode); }, setObject : function(object) { this.property.object = object; }, sync : function() { console.warn("sync is not implemented yet."); }, appendTo : function(container) { if (this.rootNode) { container.appendChild(this.rootNode); } } }); pe.NumberInputWidget = pe.WidgetBase.extend({ init : function(propertyName, settings) { this._super(pe.WidgetBase, 'init', [propertyName]); settings = settings || {}; var container = document.createElement("div"); container.classList.add("slider"); var slider = this.slider = document.createElement("input"); var input = this.input = document.createElement("input"); slider.setAttribute("type", "range"); input.setAttribute("type", "number"); if (typeof settings.step === "number") { slider.setAttribute("step", settings.step); input.setAttribute("step", (settings.step % 1 > 0) ? "any" : "1"); } else { slider.setAttribute("step", "any"); input.setAttribute("step", "any"); } var min = (typeof settings.min === "number") ? settings.min : -Infinity; var max = (typeof settings.max === "number") ? settings.max : Infinity; input.setAttribute("min", min); input.setAttribute("max", max); var sliderMin = (typeof settings.sliderMin === "number") ? settings.sliderMin : -Infinity; var sliderMax = (typeof settings.sliderMax === "number") ? settings.sliderMax : Infinity; slider.setAttribute("min", Math.max(min, sliderMin)); slider.setAttribute("max", Math.min(max, sliderMax)); slider.addEventListener("input", this.onSliderChange.bind(this)); slider.addEventListener("change", this.onSliderChange.bind(this)); input.addEventListener("change", this.onChange.bind(this)); container.appendChild(slider); container.appendChild(input); this.addInput(propertyName, container); }, onSliderChange : function() { if (this.slider.validity.valid) { this.property.setValue(parseFloat(this.slider.value)); } }, onChange : function() { if (this.input.validity.valid) { this.property.setValue(parseFloat(this.input.value)); } }, sync : function() { var value = this.property.getValue(); this.input.value = value; this.slider.value = value; } }); pe.TextInputWidget = pe.WidgetBase.extend({ init : function(propertyName) { this._super(pe.WidgetBase, 'init', [propertyName]); var input = this.input = document.createElement("input"); input.setAttribute("type", "text"); input.addEventListener("change", this.onChange.bind(this)); this.addInput(propertyName, input); }, onChange : function() { if (this.input.validity.valid) { this.property.setValue(this.input.value); } }, sync : function() { this.input.value = this.property.getValue() || ""; } }); pe.BooleanInputWidget = pe.WidgetBase.extend({ init : function(propertyName) { this._super(pe.WidgetBase, 'init', [propertyName]); var input = this.input = document.createElement("input"); input.setAttribute("type", "checkbox"); input.addEventListener("change", this.onChange.bind(this)); this.addInput(propertyName, input); }, onChange : function() { this.property.setValue(this.input.checked); }, sync : function() { this.input.checked = this.property.getValue(); } }); pe.ImageSelectionWidget = pe.WidgetBase.extend({ init : function(propertyName, resourceList) { this._super(pe.WidgetBase, 'init', [propertyName]); var select = this.select = document.createElement("select"); select.addEventListener("change", this.onChange.bind(this)); this.resourceList = resourceList = resourceList || game.resources || []; for ( var i = 0, length = resourceList.length, resource, option; i < length; ++i) { resource = resourceList[i]; if (resource.type === "image") { option = document.createElement("option"); option.setAttribute("value", resource.name); option.appendChild(document.createTextNode(resource.name)); select.appendChild(option); } } this.addInput(propertyName, select); }, onChange : function() { var image = me.loader.getImage(this.select.value); this.property.setValue(image); }, sync : function() { var image = this.property.getValue(); if (image) { var resourceList = this.resourceList; for ( var i = 0, length = resourceList.length, resource; i < length; ++i) { resource = resourceList[i]; if (image === me.loader.getImage(resource.name)) { this.select.selectedIndex = i; break; } } } else { this.select.selectedIndex = -1; } } }); pe.ShapeWidget = pe.WidgetBase.extend({ init : function() { this._super(pe.WidgetBase, 'init', [""]); this.shape = new pe.ShapeWidget.Helper("rgba(255, 86, 86, 0.3)"); this.dragHandler = new pe.DragHandler(new me.Color(255, 86, 86, 1)); this.dragHandler.onDrag = this.onDrag.bind(this); var input = this.input = document.createElement("input"); input.setAttribute("type", "checkbox"); input.addEventListener("change", this.onChange.bind(this)); this.addInput("shape widget", input); }, setObject : function(object) { this.object = object; }, onDrag : function(pos) { var object = this.object; if (object) { pos.sub(object.pos).clampSelf(0, Infinity); object.resize(pos.x, pos.y); me.event.publish("propertyChanged", [ object ]); } }, onChange : function() { if (this.input.checked) { me.game.world.addChild(this.shape); this.dragHandler.enable(); } else { me.game.world.removeChild(this.shape); this.dragHandler.disable(); } }, show : function() { if (!this.input.checked) { this.input.checked = true; this.onChange(); } }, hide : function() { if (this.input.checked) { this.input.checked = false; this.onChange(); } }, sync : function() { var object = this.object; if (object) { this.dragHandler.floating = this.shape.floating = object.floating; this.shape.setShape(object.pos, object.width, object.height); this.dragHandler.setPosition(object.pos.x + object.width, object.pos.y + object.height); } } }); pe.ShapeWidget.Helper = me.Renderable.extend({ init : function(color) { this._super(me.Renderable, 'init', [0, 0, 0, 0]); this.z = Infinity; this.color = color; }, setShape : function(v, w, h) { this.resize(w, h); this.pos.set(v.x, v.y); return this; }, draw : function(renderer) { renderer.setColor(this.color); renderer.fillRect(this.left, this.top, this.width, this.height); renderer.setLineWidth(1); renderer.strokeRect(this.left, this.top, this.width, this.height); } }); pe.DragHandler = me.Renderable.extend({ init : function(color) { this.originalSize = 40; this.createGradients(color, this.originalSize); this._super(me.Renderable, 'init', [0, 0, this.originalSize, this.originalSize]); this.z = Infinity; this.dragging = false; this.grabOffset = new me.Vector2d(0, 0); this._startDrag = this.startDrag.bind(this); this._stopDrag = this.stopDrag.bind(this); this._drag = this.drag.bind(this); this.onDrag = function() {}; me.input.registerPointerEvent("pointerup", me.game.viewport, this._stopDrag); me.input.registerPointerEvent("pointermove", me.game.viewport, this._drag); }, createGradients : function(color, size) { var context = me.video.renderer.getContext(); var bigGradient = this.bigGradient = context.createRadialGradient(0, 0, 0, 0, 0, size / 2); var smallGradient = this.smallGradient = context.createRadialGradient(0, 0, 0, 0, 0, size / 4); color.alpha = 0; bigGradient.addColorStop(0, color.toRGBA()); smallGradient.addColorStop(0, color.toRGBA()); color.alpha = 0.8; bigGradient.addColorStop(0.9, color.toRGBA()); smallGradient.addColorStop(0.9, color.toRGBA()); color.alpha = 0; bigGradient.addColorStop(1, color.toRGBA()); smallGradient.addColorStop(1, color.toRGBA()); this.color = bigGradient; }, enable : function(container) { me.input.registerPointerEvent("pointerdown", this, this._startDrag); (container || me.game.world).addChild(this); }, disable : function(container) { if (this.dragging) { this.stopDrag(); } me.input.releasePointerEvent("pointerdown", this, this._startDrag); (container || this.ancestor || me.game.world).removeChild(this); }, setPosition : function(x, y) { this.pos.set(x - (this.width / 2), y - (this.height / 2)); }, startDrag : function(event) { this.dragging = true; this.color = this.smallGradient; var size = this.originalSize / 2; this.resize(size, size); size /= 2; this.translate(size, size); var mousepos = me.input.mouse.pos; var x = mousepos.x - this.pos.x; var y = mousepos.y - this.pos.y; this.grabOffset.set(x, y); return false; }, stopDrag : function() { if (this.dragging) { this.dragging = false; this.color = this.bigGradient; var size = this.originalSize; this.resize(size, size); size /= -4; this.translate(size, size); return false; } }, drag : function(event) { if (this.dragging) { var pos = me.input.mouse.pos.clone().sub(this.grabOffset); pos.x += (this.width / 2); pos.y += (this.height / 2); this.onDrag(pos); return false; } }, draw : function(renderer) { renderer.save(); var context = renderer.getContext(); context.fillStyle = this.color; renderer.fillArc(this.pos.x, this.pos.y, this.width / 2, 0, Math.PI * 2); renderer.restore(); } }); pe.VectorWidget = pe.WidgetBase.extend({ init : function(name, color) { this._super(pe.WidgetBase, 'init', [""]); this.origin = new me.Vector2d(0, 0); this.vector = new me.Vector2d(0, 0); this.shape = new pe.VectorWidget.Helper(this, color); this.dragHandler = new pe.DragHandler(color); this.dragHandler.onDrag = this.onDrag.bind(this); var input = this.input = document.createElement("input"); input.setAttribute("type", "checkbox"); input.addEventListener("change", this.onChange.bind(this)); this.addInput(name + " widget", input); }, setObject : function(object) { this.object = object; }, setVector : function(x, y) { this.vector.set(x, y); this.dragHandler.setPosition(this.origin.x + x, this.origin.y + y); }, onDrag : function(pos) { var object = this.object; if (object) { pos.x -= object.pos.x + (object.width / 2); pos.y -= object.pos.y + (object.height / 2); var x = pos.x; var y = pos.y; if (x !== this.vector.x || y !== this.vector.y) { this.onVectorChanged(pos); this.setVector(x, y); me.event.publish("propertyChanged", [ object ]); } } }, onChange : function() { if (this.input.checked) { me.game.world.addChild(this.shape); this.dragHandler.enable(); } else { me.game.world.removeChild(this.shape); this.dragHandler.disable(); } }, show : function() { if (!this.input.checked) { this.input.checked = true; this.onChange(); } }, hide : function() { if (this.input.checked) { this.input.checked = false; this.onChange(); } }, sync : function() { var object = this.object; if (object) { this.dragHandler.floating = this.shape.floating = object.floating; this.origin.set(object.pos.x + (object.width / 2), object.pos.y + (object.height / 2)); this.onSync(object); this.shape.setShape(this.origin, this.vector.x, this.vector.y); } }, onVectorChanged : function(vector) { }, onSync : function(object) { } }); pe.VectorWidget.Helper = me.Renderable.extend({ init : function(widget, color) { this._super(me.Renderable, 'init', [0, 0, 0, 0]); this.widget = widget; this.z = Infinity; this.color = color.toRGBA(); }, setShape : function(v, w, h) { var x = w < 0 ? v.x + w : v.x; var y = h < 0 ? v.y + h : v.y; this.pos.set(x, y); this.resize(Math.abs(w), Math.abs(h)); return this; }, draw : function(renderer) { var origin = this.widget.origin; var vector = this.widget.vector; renderer.save(); renderer.setColor(this.color); renderer.setLineWidth(5); renderer.drawLine(origin.x, origin.y, vector.x, vector.y); renderer.restore(); } }); pe.VelocityWidget = pe.VectorWidget.extend({ init : function() { this._super(pe.VectorWidget, 'init', ["velocity", new me.Color(229, 216, 47, 0.3)]); this.scale = 30; }, onVectorChanged : function(vector) { var object = this.object; object.speed = vector.length() / this.scale; object.angle = Math.atan2(vector.x, vector.y) - Math.PI / 2; if (object.angle < -Math.PI) { object.angle += 2 * Math.PI; } }, onSync : function(object) { var length = object.speed * this.scale; var angle = object.angle; this.setVector(Math.cos(angle) * length, -Math.sin(angle) * length); } }); pe.ForceWidget = pe.VectorWidget.extend({ init : function() { this._super(pe.VectorWidget, 'init', ["force", new me.Color(79, 214, 72, 0.3)]); this.scale = 300; }, onVectorChanged : function(vector) { var object = this.object; object.wind = vector.x / this.scale; object.gravity = vector.y / this.scale; }, onSync : function(object) { this.setVector(object.wind * this.scale, object.gravity * this.scale); } }); pe.VelocityVariationWidget = pe.WidgetBase.extend({ init : function() { this._super(pe.WidgetBase, 'init', [""]); this.scale = 30; this.shape = new pe.VelocityVariationWidget.Helper(new me.Color(105, 190, 255, 0.3)); this.dragHandler = new pe.DragHandler(new me.Color(150, 150, 255, 1)); this.dragHandler.onDrag = this.onDrag.bind(this); var input = this.input = document.createElement("input"); input.setAttribute("type", "checkbox"); input.addEventListener("change", this.onChange.bind(this)); this.addInput("velocity variation widget", input); }, onDrag : function(pos) { var object = this.object; if (object) { pos.x -= object.pos.x + (object.width / 2); pos.y -= object.pos.y + (object.height / 2); var variation = object.angle - Math.atan2(-pos.y, pos.x); if (variation < -Math.PI / 2) { variation += 2 * Math.PI; } object.angleVariation = variation.clamp(0, Math.PI); variation = (pos.length() / this.scale) - object.speed; object.speedVariation = variation < 0 ? 0 : variation; me.event.publish("propertyChanged", [ object ]); } }, onChange : function() { if (this.input.checked) { me.game.world.addChild(this.shape); this.dragHandler.enable(); } else { me.game.world.removeChild(this.shape); this.dragHandler.disable(); } }, show : function() { if (!this.input.checked) { this.input.checked = true; this.onChange(); } }, hide : function() { if (this.input.checked) { this.input.checked = false; this.onChange(); } }, setObject : function(object) { this.object = object; }, sync : function() { var object = this.object; if (object) { this.shape.floating = object.floating; this.dragHandler.floating = object.floating; this.shape.set(object); var angle = object.angle - object.angleVariation; var radius = (object.speed + object.speedVariation) * this.scale; var x = object.pos.x + (object.width / 2) + Math.cos(angle) * radius; var y = object.pos.y + (object.height / 2) - Math.sin(angle) * radius; this.dragHandler.setPosition(x, y); } } }); pe.VelocityVariationWidget.Helper = me.Renderable.extend({ init : function(color) { this._super(me.Renderable, 'init', [0, 0, 0, 0]); this.color = color.toRGBA(); this.startAngle = 0; this.endAngle = 0; this.minRadius = 0; this.maxRadius = 0; this.scale = 30; this.z = Infinity; }, set : function(object) { this.pos.set(object.pos.x + (object.width / 2), object.pos.y + (object.height / 2)); this.startAngle = -(object.angle - object.angleVariation); this.endAngle = -(object.angle + object.angleVariation); this.minRadius = (object.speed - object.speedVariation) * this.scale; this.maxRadius = (object.speed + object.speedVariation) * this.scale; }, draw : function(renderer) { var x = this.pos.x, y = this.pos.y, context = renderer.getContext(); context.strokeStyle = this.color; context.fillStyle = this.color; context.beginPath(); context.arc(x, y, this.maxRadius, this.startAngle, this.endAngle, true); if (this.minRadius < 0) { context.arc(x, y, -this.minRadius, this.endAngle + Math.PI, this.startAngle + Math.PI); } else { context.arc(x, y, this.minRadius, this.endAngle, this.startAngle); } context.closePath(); context.fill(); context.stroke(); } }); })();