| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- local view = lib.object.create()
- function view:init()
- self.x = 0
- self.y = 0
- self.width = 960
- self.height = 720
- self.xmin = -math.huge
- self.ymin = -math.huge
- self.xmax = math.huge--self.width
- self.ymax = math.huge--self.height
- self.frame = {
- x = 0,
- y = 0,
- width = g.getWidth(),
- height = g.getHeight()
- }
- self.viewId = 0
- self.draws = {}
- self.guis = {}
- self.effects = {}
- self.toRemove = {}
- self.target = nil
- self.prevx = 0
- self.prevy = 0
- self.prevscale = 1
- self.shake = 0
- end
- function view:bind()
- self:resize()
- self.draw = lib.rx.Subject.create()
- self.hud = lib.rx.Subject.create()
- self.draw.onNext = f.self(self.doDraw, self)
- self.hud.onNext = f.self(self.doHud, self)
- return {
- love.resize
- :subscribe(function()
- self:resize()
- end),
- love.update
- :subscribe(function()
- self:update()
- end),
- love.draw
- :subscribe(function()
- self.draw:onNext()
- self.hud:onNext()
- end)
- }
- end
- function view:update()
- self.prevx = self.x
- self.prevy = self.y
- self.prevscale = self.scale
- self:contain()
- self.shake = math.max(self.shake - lib.tick.rate, 0)
- end
- function view:doDraw()
- local w, h = g.getDimensions()
- local subject = self.draw
- local source, target = self.sourceCanvas, self.targetCanvas
- self:worldPush()
- g.setCanvas(source)
- for i = #subject.observers, 1, -1 do
- if subject.observers[i] then
- subject.observers[i].depth = subject.observers[i]:onNext() or 0
- if subject.observers[i] then
- subject.observers[i].depthNudge = subject.observers[i].depthNudge or love.math.random() * .01
- end
- end
- end
- table.sort(subject.observers, function(a, b)
- return (a.depth or 0) + (a.depthNudge or 0) < (b.depth or 0) + (b.depthNudge or 0)
- end)
- g.setCanvas()
- g.pop()
- g.setCanvas()
- g.white()
- g.draw(source)
- --[[local fr = self.frame
- local fx, fy, fw, fh = fr.x, fr.y, fr.width, fr.height
- g.setColor(0, 0, 0)
- g.rectangle('fill', 0, 0, w, fy)
- g.rectangle('fill', 0, 0, fx, h)
- g.rectangle('fill', 0, fy + fh, w, h - (fy + fh))
- g.rectangle('fill', fx + fw, 0, w - (fx + fw), h)]]
- end
- function view:doHud()
- local w, h = g.getDimensions()
- local subject = self.hud
- local source, target = self.sourceCanvas, self.targetCanvas
- table.sort(subject.observers, function(a, b)
- return (a.depth or 0) < (b.depth or 0)
- end)
- for i = #subject.observers, 1, -1 do
- if subject.observers[i] then
- subject.observers[i].depth = subject.observers[i]:onNext() or 0
- end
- end
- end
- function view:resize()
- local w, h = g.getDimensions()
- local ratio = w / h
- self.frame.x, self.frame.y, self.frame.width, self.frame.height = 0, 0, self.width, self.height
- if true or (self.width / self.height) > (w / h) then
- self.scale = w / self.width
- local margin = math.max(util.round(((h - w * (self.height / self.width)) / 2)), 0)
- self.frame.y = margin
- self.frame.height = h - 2 * margin
- self.frame.width = w
- else
- self.scale = h / self.height
- local margin = math.max(util.round(((w - h * (self.width / self.height)) / 2)), 0)
- self.frame.x = margin
- self.frame.width = w - 2 * margin
- self.frame.height = h
- end
- self.sourceCanvas = g.newCanvas(w, h)
- self.targetCanvas = g.newCanvas(w, h)
- end
- function view:register(x, action)
- x.viewId = self.viewId
- action = action or 'draw'
- if action == 'draw' then
- table.insert(self.draws, x)
- x.depth = x.depth or 0
- elseif action == 'gui' then
- table.insert(self.guis, x)
- elseif action == 'effect' then
- table.insert(self.effects, x)
- end
- self.viewId = self.viewId + 1
- end
- function view:unregister(x)
- table.insert(self.toRemove, x)
- end
- function view:convertZ(z)
- return (.8 * z) ^ (1 + (.0008 * z))
- end
- function view:three(x, y, z)
- local sx, sy = util.lerp(self.prevx, self.x, lib.tick.accum / lib.tick.rate), util.lerp(self.prevy, self.y, lib.tick.accum / lib.tick.rate)
- z = self:convertZ(z)
- return x - (z * ((sx + self.width / 2 - x) / 500)), y - (z * ((sy + self.height / 2 - y) / 500))
- end
- function view:threeDepth(x, y, z)
- return util.clamp(util.distance(x, y, self.x + self.width / 2, self.y + self.height / 2) * self.scale - 1000 - z, -4096, -16)
- end
- function view:contain()
- --self.x = util.clamp(self.x, self.xmin, self.xmax - self.width)
- --self.y = util.clamp(self.y, self.ymin, self.ymax - self.height)
- end
- function view:worldPoint(x, y)
- x = util.round(((x - self.frame.x) / self.scale) + self.x)
- if y then y = util.round(((y - self.frame.y) / self.scale) + self.y) end
- return x, y
- end
- function view:screenPoint(x, y)
- local vx, vy = util.lerp(self.prevx, self.x, lib.tick.accum / lib.tick.rate), util.lerp(self.prevy, self.y, lib.tick.accum / lib.tick.rate)
- x = (x - vx) * self.scale
- if y then y = (y - vy) * self.scale end
- return x, y
- end
- function view:worldMouseX()
- return util.round(((love.mouse.getX() - self.frame.x) / self.scale) + self.x)
- end
- function view:worldMouseY()
- return util.round(((love.mouse.getY() - self.frame.y) / self.scale) + self.y)
- end
- function view:frameMouseX()
- return love.mouse.getX() - self.frame.x
- end
- function view:frameMouseY()
- return love.mouse.getY() - self.frame.y
- end
- function view:screenshake(amount)
- self.shake = math.max(self.shake, amount)
- end
- function view:worldPush()
- local x, y, s = unpack(util.interpolateTable({self.prevx, self.prevy, self.prevscale}, {self.x, self.y, self.scale}, lib.tick.accum / lib.tick.rate))
- if self.shake > .01 then
- local shakex = -1 + love.math.random() * 2
- local shakey = -1 + love.math.random() * 2
- x = x + (shakex * 5)
- y = y + (shakey * 5)
- end
- g.push()
- g.translate(self.frame.x, self.frame.y)
- g.scale(s)
- g.translate(-x, -y)
- end
- function view:guiPush()
- g.push()
- g.translate(self.self.frame.x, self.self.frame.y)
- end
- return view
|