dreemgl
Version:
DreemGL is an open-source multi-screen prototyping framework for mediated environments, with a visual editor and shader styling for webGL and DALi runtimes written in JavaScript. As a toolkit for gpu-accelerated multiscreen development, DreemGL includes
334 lines (303 loc) • 9.72 kB
JavaScript
/* DreemGL is a collaboration between Teeming Society & Samsung Electronics, sponsored by Samsung and others.
Copyright 2015-2016 Teeming Society. Licensed under the Apache License, Version 2.0 (the "License"); You may not use this file except in compliance with the License.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.*/
define.class('$ui/label', function (require, $ui$, view, label) {
var ROW_HEIGHT = 28
this.text = ''
this.bgcolor = NaN
this.height = ROW_HEIGHT
this.cursor = 'move'
var ubuntufont = require('$resources/fonts/ubuntu_medium_256_baked.glf')
this.attributes = {
zoom: wire('this.parent.zoom'),
scroll: wire('this.parent.scroll'),
data: Config({type: Array, value: wire('this.parent.data')}),
rows: Config({type: Number, value: 1})
}
this.onrows = function () {
this.height = this.rows * ROW_HEIGHT
}
// Temporarily disable new event creation on drag
// this.pointermove = function(event) {
// var eventghost = this.find('eventghost')
// var timeline = this.parent
// eventghost.title = ''
// eventghost.start = timeline.getRangeStart() + timeline.getRange() * (event.min[0] / this.layout.width)
// eventghost.end = timeline.getRangeStart() + timeline.getRange() * (event.max[0] / this.layout.width)
// timeline.lockscroll = true
// this.redraw()
// }
//
// this.pointerend = function(event) {
// var eventghost = this.find('eventghost')
// var timeline = this.parent
// if (abs(event.delta.x) > 2) {
// var eventdata = {
// title: 'New Event',
// date: eventghost.start,
// enddate: eventghost.end,
// metadata: {
// location: {
// name: 'New Location',
// lattitude: 0,
// longitute: 0
// }
// }
// }
// timeline.makeEvent(eventdata)
// }
// eventghost.start = 0
// eventghost.end = 0
// timeline.lockscroll = false
// }
define.class(this, 'event', view, function(){
this.bgcolor = '#999999'
this.position = 'absolute'
this.flexdirection = 'row'
this.justifycontent = "center"
this.borderradius = 6
this.cursor = 'ew-resize'
var RESIZE_HANDLE_WIDTH = 10
this.attributes = {
title: '',
id: null,
color: vec4(1,1,1,1),
duration: 1,
offset: 0,
start: 0,
end: 0,
row: 0
}
var editmode = ''
this.pointerhover = this.pointerstart = function (event) {
this.cursor = 'ew-resize'
editmode = 'move'
var localstart = this.globalToLocal(event.position)
var localstartx = localstart[0] - (this.offset - this.scroll[0]) * event.view.layout.width
var pxduration = this.duration * event.view.layout.width
if (localstartx < min(RESIZE_HANDLE_WIDTH, pxduration / 2)) {
this.cursor = 'w-resize'
editmode = 'setstart'
} else if (pxduration - localstartx < min(RESIZE_HANDLE_WIDTH, pxduration / 2)) {
this.cursor = 'e-resize'
editmode = 'setend'
}
}
this.pointermove = function(event) {
var eventghost = this.parent.find('eventghost')
var timeline = this.parent.parent
var offset = event.delta[0] / timeline.layout.width
if (editmode == 'setstart') {
eventghost.start = this.start + timeline.getRange() * offset
eventghost.end = this.end
} else if (editmode == 'move') {
eventghost.start = this.start + timeline.getRange() * offset
eventghost.end = this.end + timeline.getRange() * offset
} else if (editmode == 'setend') {
eventghost.start = this.start
eventghost.end = this.end + timeline.getRange() * offset
}
if (eventghost.start > eventghost.end) {
var start = eventghost.start
eventghost.start = eventghost.end
eventghost.end = start
}
timeline.lockscroll = true
this.redraw()
}
this.pointerend = function(event) {
if (abs(event.delta[0]) < 2) return
var eventghost = this.parent.find('eventghost')
var timeline = this.parent.parent
timeline.updateEvent(this.id, {
date: eventghost.start,
enddate: eventghost.end,
})
eventghost.start = 0
eventghost.end = 0
timeline.lockscroll = false
}
this.pointertap = function(event) {
if (event.clicker === 2) {
var timeline = this.parent.parent
timeline.deleteEvent(this.id)
}
}
this.layout = function(){
this._layout.width = this.parent._layout.width
this._layout.height = this.parent._layout.height / this.parent.rows
if (this.row === -1) {
this._layout.top = 0
this._layout.height = this.parent._layout.height
} else {
this._layout.top = this._layout.height * this.row
}
}
this.atDraw = function () {
this.scroll = this.parent.scroll
this.duration = new Date(this.end).getTime() - new Date(this.start).getTime()
this.duration = this.duration / this.parent.parent.TIME_SCALE / this.parent.zoom
this.offset = new Date(this.start).getTime() - this.parent.parent.getStart()
this.offset = this.offset / this.parent.parent.TIME_SCALE / this.parent.zoom
this.find('eventlabel').xoffset = (this.offset - this.scroll[0]) * this.layout.width
this.find('eventlabel').xwidth = this.duration * this.layout.width
}
this.roundedrect = {
position: function(){
pos = mesh.pos.xy
pos.x = pos.x * view.duration + (view.offset - view.scroll.x) * view.layout.width
var ca = cos(mesh.angle + PI)
var sa = sin(mesh.angle + PI)
var rad = (mesh.radmult.x * view.borderradius.x + mesh.radmult.y * view.borderradius.y + mesh.radmult.z * view.borderradius.z + mesh.radmult.w * view.borderradius.w)
pos.x += ca * rad
pos.y += sa * rad
uv = vec2(pos.x / view.layout.width, pos.y / view.layout.height)
sized = vec2(pos.x, pos.y)
return vec4(sized.x, sized.y, 0, 1) * view.totalmatrix * view.viewmatrix
},
color: function(){
var col = view.bgcolorfn(vec2(pos.x / view.layout.width, pos.y/view.layout.height))
if (uv.y > 0.85) {
return vec4(view.color.rgb, col.a * view.opacity)
} else {
return vec4(col.rgb, col.a * view.opacity)
}
}
}
this.hardrect = {
position: function(){
var pos = vec2(mesh.x * view.duration + view.offset - view.scroll.x, mesh.y)
return vec4(pos.x * view.layout.width, pos.y * view.layout.height, 0, 1) * view.totalmatrix * view.viewmatrix
}
}
define.class(this, 'eventlabel', label, function(){
this.xoffset = 0
this.xwidth = 0
this.fgcolor = "black"
this.alignself = "center"
this.padding = vec4(6)
this.atDraw = function () {
this.fontsize = 13
this.opacity = this.xwidth < this.layout.width * 0.6 ? 0 : 1
}
this.textstyle = function(style, tag) {
var pos = style.pos
style.pos = vec3((pos.x + this.xoffset), pos.y, 0)
return style
}
})
this.render = function () {
return [
this.eventlabel({
name: 'eventlabel',
text: this.title,
font: ubuntufont
})
]
}
})
this.renderEvents = function (data) {
var rows = [[],[],[],[],[],[]]
this.rows = 1
for (var i = 0; i < data.length; i++) {
var color = data[i].color || null
var event = this.event({
title: data[i].title,
id: data[i].id,
bgcolor: vec4(0.75, 0.75, 0.75, 1),
color: color || vec4(1, 1, 1, 1),
start: new Date(data[i].date).getTime(),
end: new Date(data[i].enddate).getTime()
})
for (var r = 0; r < rows.length; r++) {
var canfit = true
for (var k = 0; k < rows[r].length; k++) {
if (!(
(rows[r][k].start > event.end && rows[r][k].end > event.end) ||
(rows[r][k].start < event.start && rows[r][k].end < event.start)
)) {
canfit = false
}
}
if (canfit) {
event.row = r
this.rows = max(this.rows, r + 1)
rows[r].push(event)
break
}
}
}
return rows
}
this.render = function () {
return [
this.renderEvents(this.data),
this.event({
name: "eventghost",
id: -1,
size: 3,
opacity: 0.5,
fontsize: 6,
start: 0,
end: 0,
bgcolor: vec4(0.2, 0.7, 1, 0.5),
row: -1
})
]
}
// define.class(this, 'eventrects', this.Shader, function(){
//
// var vertstruct = define.struct({
// pos: vec2,
// uv: vec2,
// id: float
// })
// this.mesh = vertstruct.array()
//
// this.update = function(){
// var startTime = this.view.parent.getStart()
// var view = this.view
// var data = view.data
// var mesh = this.mesh = vertstruct.array();
// for (var i = 0; i < data.length; i++) {
//
// var date = new Date(data[i].date)
// var enddate = new Date(data[i].enddate)
//
// var timeOffset = date.getTime() - startTime
// var dayOffset = timeOffset / 1000 / 60 / 60 / 24
// var dayWidth = (enddate.getTime() - date.getTime()) / 1000 / 60 / 60 / 24
//
// var w = dayWidth
// var h = 1
// var x = dayOffset
// var y = 0
//
// mesh.pushQuad(
// x , y , 0, 0, i,
// x+w, y , 1, 0, i,
// x , y+h, 0, 1, i,
// x+w, y+h, 1, 1, i
// )
// }
// }
//
// this.position = function(){
// var pos = mesh.pos
// pos.x = pos.x - view.zoom * view.scroll.x
// pos = pos * vec2(view.layout.width / view.zoom, view.layout.height)
// return vec4(pos, 0, 1) * view.totalmatrix * view.viewmatrix
// }
// this.color = function(){
// PickGuid = mesh.id
// if (view.hoverid == mesh.id){
// return vec4(0.5, 0.75, 1, 1)
// }
// return vec4(0.75, 0.75, 0.75, 1)
// }
// })
//
// this.eventrects = true
})