diff --git a/Zframework/background.lua b/Zframework/background.lua deleted file mode 100644 index 22f81786..00000000 --- a/Zframework/background.lua +++ /dev/null @@ -1,56 +0,0 @@ -local gc_clear=love.graphics.clear -local BGs={ - none={draw=function()gc_clear(.08,.08,.084)end} -} -local BGlist={'none'} -local BG={ - default='none', - locked=false, - cur='none', - init=false, - resize=false, - update=NULL, - draw=BGs.none.draw, - event=false, - discard=NULL, -} - -function BG.lock()BG.locked=true end -function BG.unlock()BG.locked=false end -function BG.add(name,bg) - BGs[name]=bg - BGlist[#BGlist+1]=name -end -function BG.getList() - return BGlist -end -function BG.remList(name) - table.remove(BGlist,TABLE.find(BGlist,name)) -end -function BG.send(...) - if BG.event then - BG.event(...) - end -end -function BG.setDefault(bg) - BG.default=bg -end -function BG.set(name) - name=name or BG.default - if not BGs[name]or BG.locked then return end - if name~=BG.cur then - BG.discard() - BG.cur=name - local bg=BGs[name] - - BG.init= bg.init or NULL - BG.resize= bg.resize or NULL - BG.update= bg.update or NULL - BG.draw= bg.draw or NULL - BG.event= bg.event or NULL - BG.discard=bg.discard or NULL - BG.init() - end - return true -end -return BG diff --git a/Zframework/bgm.lua b/Zframework/bgm.lua deleted file mode 100644 index 924f1a46..00000000 --- a/Zframework/bgm.lua +++ /dev/null @@ -1,182 +0,0 @@ -local lastLoaded={} -local maxLoadedCount=3 -local nameList={} -local SourceObjList={} -local volume=1 - -local BGM={ - default=false, - onChange=NULL, - --nowPlay=[str:playing ID] - --playing=[src:playing SRC] - --lastPlayed=[str:lastPlayed ID] -} - -local function _tryReleaseSources() - local n=#lastLoaded - while #lastLoaded>maxLoadedCount do - local name=lastLoaded[n] - if SourceObjList[name].source:isPlaying()then - n=n-1 - if n<=0 then return end - else - SourceObjList[name].source=SourceObjList[name].source:release()and nil - table.remove(lastLoaded,n) - return - end - end -end -local function _addFile(name,path) - if not SourceObjList[name]then - table.insert(nameList,name) - SourceObjList[name]={path=path,source=false} - end -end - -function BGM.getList()return nameList end -function BGM.getCount()return #nameList end -function BGM.load(name,path) - if type(name)=='table'then - for k,v in next,name do - _addFile(k,v) - end - else - _addFile(name,path) - end - table.sort(nameList) - LOG(BGM.getCount().." BGM files added") -end - -function BGM.setDefault(bgm) - BGM.default=bgm -end -function BGM.setMaxSources(count) - maxLoadedCount=count - _tryReleaseSources() -end -function BGM.setChange(func) - BGM.onChange=func -end -function BGM.setVol(v) - assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume') - volume=v - if BGM.playing then - if volume>0 then - BGM.playing:setVolume(volume) - BGM.playing:play() - elseif BGM.nowPlay then - BGM.playing:pause() - end - end -end - -local function task_fadeOut(src) - while true do - coroutine.yield() - local v=src:getVolume()-volume/40 - src:setVolume(v>0 and v or 0) - if v<=0 then - src:stop() - return true - end - end -end -local function task_fadeIn(src) - while true do - coroutine.yield() - local v=volume - v=math.min(v,src:getVolume()+v/40) - src:setVolume(v) - if v>=volume then - return true - end - end -end -local function check_curFadeOut(task,code,src) - return task.code==code and task.args[1]==src -end -local function _tryLoad(name) - if SourceObjList[name]then - if SourceObjList[name].source then - return true - elseif love.filesystem.getInfo(SourceObjList[name].path)then - SourceObjList[name].source=love.audio.newSource(SourceObjList[name].path,'stream') - SourceObjList[name].source:setVolume(0) - table.insert(lastLoaded,1,name) - _tryReleaseSources() - return true - else - LOG("No BGM: "..SourceObjList[name],5) - end - elseif name then - LOG("No BGM: "..name,5) - end -end -function BGM.play(name,args) - name=name or BGM.default - args=args or"" - if not _tryLoad(name)or args:sArg('-preLoad')then return end - if volume==0 then - BGM.nowPlay=name - BGM.playing=SourceObjList[name].source - return true - end - if name and SourceObjList[name].source then - if BGM.nowPlay~=name then - if BGM.nowPlay then - if not args:sArg('-sdout')then - TASK.new(task_fadeOut,BGM.playing) - else - BGM.playing:pause() - end - end - TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[name].source) - TASK.removeTask_code(task_fadeIn) - - BGM.nowPlay=name - BGM.playing=SourceObjList[name].source - if not args:sArg('-sdin')then - BGM.playing:setVolume(0) - TASK.new(task_fadeIn,BGM.playing) - else - BGM.playing:setVolume(volume) - BGM.playing:play() - end - SourceObjList[name].source:setLooping(not args:sArg('-noloop')) - BGM.lastPlayed=BGM.nowPlay - BGM.playing:play() - BGM.onChange(name) - end - return true - end -end -function BGM.seek(t) - if BGM.playing then - BGM.playing:seek(t) - end -end -function BGM.isPlaying() - return BGM.playing and BGM.playing:isPlaying() -end -function BGM.continue() - if BGM.lastPlayed then - BGM.nowPlay,BGM.playing=BGM.lastPlayed,SourceObjList[BGM.lastPlayed].source - TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[BGM.nowPlay].source) - TASK.removeTask_code(task_fadeIn) - TASK.new(task_fadeIn,BGM.playing) - BGM.playing:play() - end -end -function BGM.stop(args) - args=args or"" - TASK.removeTask_code(task_fadeIn) - if not args:sArg('-s')then - if BGM.nowPlay then - TASK.new(task_fadeOut,BGM.playing) - end - elseif BGM.playing then - BGM.playing:pause() - end - BGM.nowPlay,BGM.playing=nil -end -return BGM diff --git a/Zframework/color.lua b/Zframework/color.lua deleted file mode 100644 index 3b1ded1c..00000000 --- a/Zframework/color.lua +++ /dev/null @@ -1,148 +0,0 @@ -local abs=math.abs -local function hsv(h,s,v,a)--Color type, Color amount, Light - if s<=0 then return v,v,v,a end - h=h*6 - local c=v*s - local x=abs((h-1)%2-1)*c - if h<1 then return v,x+v-c,v-c,a - elseif h<2 then return x+v-c,v,v-c,a - elseif h<3 then return v-c,v,x+v-c,a - elseif h<4 then return v-c,x+v-c,v,a - elseif h<5 then return x+v-c,v-c,v,a - else return v,v-c,x+v-c,a - end -end - -local COLOR={ - hsv=hsv, - - red= {hsv(0.00, 0.89, 0.91)}, - fire= {hsv(0.04, 0.93, 0.94)}, - orange= {hsv(0.09, 0.99, 0.96)}, - yellow= {hsv(0.15, 0.82, 0.90)}, - lime= {hsv(0.20, 0.89, 0.88)}, - jade= {hsv(0.25, 1.00, 0.82)}, - green= {hsv(0.33, 1.00, 0.81)}, - aqua= {hsv(0.47, 1.00, 0.76)}, - cyan= {hsv(0.53, 1.00, 0.88)}, - navy= {hsv(0.56, 1.00, 1.00)}, - sea= {hsv(0.61, 1.00, 1.00)}, - blue= {hsv(0.64, 1.00, 0.95)}, - violet= {hsv(0.74, 1.00, 0.91)}, - purple= {hsv(0.80, 1.00, 0.81)}, - magenta= {hsv(0.86, 1.00, 0.78)}, - wine= {hsv(0.92, 0.98, 0.91)}, - - lRed= {hsv(0.00, 0.38, 0.93)}, - lFire= {hsv(0.04, 0.45, 0.91)}, - lOrange= {hsv(0.10, 0.53, 0.92)}, - lYellow= {hsv(0.14, 0.61, 0.95)}, - lLime= {hsv(0.20, 0.66, 0.92)}, - lJade= {hsv(0.26, 0.56, 0.90)}, - lGreen= {hsv(0.34, 0.49, 0.89)}, - lAqua= {hsv(0.47, 0.59, 0.86)}, - lCyan= {hsv(0.51, 0.77, 0.88)}, - lNavy= {hsv(0.54, 0.80, 0.95)}, - lSea= {hsv(0.57, 0.72, 0.97)}, - lBlue= {hsv(0.64, 0.44, 0.96)}, - lViolet= {hsv(0.72, 0.47, 0.95)}, - lPurple= {hsv(0.80, 0.62, 0.89)}, - lMagenta= {hsv(0.86, 0.61, 0.89)}, - lWine= {hsv(0.93, 0.57, 0.92)}, - - dRed= {hsv(0.00, 0.80, 0.48)}, - dFire= {hsv(0.04, 0.80, 0.34)}, - dOrange= {hsv(0.07, 0.80, 0.39)}, - dYellow= {hsv(0.12, 0.80, 0.37)}, - dLime= {hsv(0.20, 0.80, 0.26)}, - dJade= {hsv(0.29, 0.80, 0.27)}, - dGreen= {hsv(0.33, 0.80, 0.26)}, - dAqua= {hsv(0.46, 0.80, 0.24)}, - dCyan= {hsv(0.50, 0.80, 0.30)}, - dNavy= {hsv(0.58, 0.80, 0.42)}, - dSea= {hsv(0.64, 0.80, 0.40)}, - dBlue= {hsv(0.67, 0.80, 0.34)}, - dViolet= {hsv(0.71, 0.80, 0.35)}, - dPurple= {hsv(0.76, 0.80, 0.32)}, - dMagenta= {hsv(0.87, 0.80, 0.28)}, - dWine= {hsv(0.92, 0.80, 0.28)}, - - black= {hsv(0.04, 0.04, 0.14)}, - dGray= {hsv(0.02, 0.05, 0.44)}, - gray= {hsv(0.02, 0.05, 0.65)}, - lGray= {hsv(0.02, 0.06, 0.86)}, - white= {hsv(0.01, 0.02, 0.99)}, - - xGray= {hsv(0.00, 0.00, 0.35,.8)}, - lxGray= {hsv(0.00, 0.00, 0.62,.8)}, - dxGray= {hsv(0.00, 0.00, 0.16,.8)}, -} -for k,v in next,{ - R='red', F='fire', O='orange', Y='yellow', L='lime', J='jade', G='green', A='aqua', C='cyan', N='navy', S='sea', B='blue', V='violet', P='purple', M='magenta', W='wine', - lR='lRed',lF='lFire',lO='lOrange',lY='lYellow',lL='lLime',lJ='lJade',lG='lGreen',lA='lAqua',lC='lCyan',lN='lNavy',lS='lSea',lB='lBlue',lV='lViolet',lP='lPurple',lM='lMagenta',lW='lWine', - dR='dRed',dF='dFire',dO='dOrange',dY='dYellow',dL='dLime',dJ='dJade',dG='dGreen',dA='dAqua',dC='dCyan',dN='dNavy',dS='dSea',dB='dBlue',dV='dViolet',dP='dPurple',dM='dMagenta',dW='dWine', - D='black',dH='dGray',H='gray',lH='lGray',Z='white', - X='xGray',lX='lxGray',dX='dxGray', - --Remain letter: EIKQTUX -}do - COLOR[k]=COLOR[v] -end -setmetatable(COLOR,{__index=function(_,k) - error("No color: "..tostring(k)) -end}) - - -do--Random generators - local rnd=math.random - local list_norm={'red','fire','orange','yellow','lime','jade','green','aqua','cyan','navy','sea','blue','violet','purple','magenta','wine'} - local len_list_norm=#list_norm - function COLOR.random_norm() - return COLOR[list_norm[rnd(len_list_norm)]] - end - - local list_bright={'lRed','lFire','lOrange','lYellow','lLime','lJade','lGreen','lAqua','lCyan','lNavy','lSea','lBlue','lViolet','lPurple','lMagenta','lWine'} - local len_list_bright=#list_bright - function COLOR.random_bright() - return COLOR[list_bright[rnd(len_list_bright)]] - end - - local list_dark={'dRed','dFire','dOrange','dYellow','dLime','dJade','dGreen','dAqua','dCyan','dNavy','dSea','dBlue','dViolet','dPurple','dMagenta','dWine'} - local len_list_dark=#list_dark - function COLOR.random_dark() - return COLOR[list_dark[rnd(len_list_dark)]] - end -end - -do--Rainbow generators - local sin=math.sin - function COLOR.rainbow(phase,a) - return - sin(phase)*.4+.6, - sin(phase+2.0944)*.4+.6, - sin(phase-2.0944)*.4+.6, - a - end - function COLOR.rainbow_light(phase,a) - return - sin(phase)*.2+.7, - sin(phase+2.0944)*.2+.7, - sin(phase-2.0944)*.2+.7, - a - end - function COLOR.rainbow_dark(phase,a) - return - sin(phase)*.2+.4, - sin(phase+2.0944)*.2+.4, - sin(phase-2.0944)*.2+.4, - a - end - function COLOR.rainbow_gray(phase,a) - return - sin(phase)*.16+.5, - sin(phase+2.0944)*.16+.5, - sin(phase-2.0944)*.16+.5, - a - end -end - -return COLOR diff --git a/Zframework/file.lua b/Zframework/file.lua deleted file mode 100644 index 83b847c5..00000000 --- a/Zframework/file.lua +++ /dev/null @@ -1,105 +0,0 @@ -local fs=love.filesystem -local FILE={} -function FILE.load(name,args) - if not args then args=''end - if fs.getInfo(name)then - local F=fs.newFile(name) - assert(F:open'r','open error') - local s=F:read()F:close() - local mode= - STRING.sArg(args,'-luaon')and'luaon'or - STRING.sArg(args,'-lua')and'lua'or - STRING.sArg(args,'-json')and'json'or - STRING.sArg(args,'-string')and'string'or - s:sub(1,6)=='return{'and'luaon'or - (s:sub(1,1)=='['and s:sub(-1)==']'or s:sub(1,1)=='{'and s:sub(-1)=='}')and'json'or - 'string' - if mode=='luaon'then - local func,err_mes=loadstring(s) - if func then - setfenv(func,{}) - local res=func() - return assert(res,'decode error') - else - error('decode error: '..err_mes) - end - elseif mode=='lua'then - local func,err_mes=loadstring(s) - if func then - local res=func() - return assert(res,'run error') - else - error('compile error: '..err_mes) - end - elseif mode=='json'then - local res=JSON.decode(s) - if res then - return res - end - error('decode error') - elseif mode=='string'then - return s - else - error('unknown mode') - end - else - error('no file') - end -end -function FILE.save(data,name,args) - if not args then args=''end - if STRING.sArg(args,'-d')and fs.getInfo(name)then - error('duplicate') - end - - if type(data)=='table'then - if STRING.sArg(args,'-luaon')then - data=TABLE.dump(data) - if not data then - error('encode error') - end - else - data=JSON.encode(data) - if not data then - error('encode error') - end - end - else - data=tostring(data) - end - - local F=fs.newFile(name) - assert(F:open('w'),'open error') - F:write(data)F:flush()F:close() -end -function FILE.clear(path) - if fs.getRealDirectory(path)==SAVEDIR and fs.getInfo(path).type=='directory'then - for _,name in next,fs.getDirectoryItems(path)do - name=path..'/'..name - if fs.getRealDirectory(name)==SAVEDIR then - local t=fs.getInfo(name).type - if t=='file'then - fs.remove(name) - end - end - end - end -end -function FILE.clear_s(path) - if path==''or(fs.getRealDirectory(path)==SAVEDIR and fs.getInfo(path).type=='directory')then - for _,name in next,fs.getDirectoryItems(path)do - name=path..'/'..name - if fs.getRealDirectory(name)==SAVEDIR then - local t=fs.getInfo(name).type - if t=='file'then - fs.remove(name) - elseif t=='directory'then - FILE.clear_s(name) - fs.remove(name) - end - end - end - fs.remove(path) - end -end -return FILE diff --git a/Zframework/font.lua b/Zframework/font.lua deleted file mode 100644 index 78238bd6..00000000 --- a/Zframework/font.lua +++ /dev/null @@ -1,60 +0,0 @@ -local gc=love.graphics -local set=gc.setFont -local fontFiles,fontCache={},{} -local defaultFont,defaultFallBack -local curFont=false--Current using font object - -local FONT={} -function FONT.setDefault(name)defaultFont=name end -function FONT.setFallback(name)defaultFallBack=name end -function FONT.rawget(s) - if not fontCache[s]then - fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2) - end - return fontCache[s] -end -function FONT.rawset(s) - set(fontCache[s]or FONT.rawget(s)) -end -function FONT.load(fonts) - for name,path in next,fonts do - assert(love.filesystem.getInfo(path),STRING.repD("Font file $1($2) not exist!",name,path)) - fontFiles[name]=love.filesystem.newFile(path) - fontCache[name]={} - end - FONT.reset() -end -function FONT.get(size,name) - if not name then name=defaultFont end - local f=fontCache[name][size] - if not f then - f=gc.setNewFont(fontFiles[name],size,'light',gc.getDPIScale()*SCR.k*2) - if defaultFallBack and name~=defaultFallBack then - f:setFallbacks(FONT.get(size,defaultFallBack)) - end - fontCache[name][size]=f - end - return f -end -function FONT.set(size,name) - if not name then name=defaultFont end - - local f=fontCache[name][size] - if f~=curFont then - curFont=f or FONT.get(size,name) - set(curFont) - end -end -function FONT.reset() - for name,cache in next,fontCache do - if type(cache)=='table'then - for size in next,cache do - cache[size]=FONT.get(size,name) - end - else - fontCache[name]=FONT.rawget(name) - end - end -end - -return FONT diff --git a/Zframework/gcExtend.lua b/Zframework/gcExtend.lua deleted file mode 100644 index 57cea2b0..00000000 --- a/Zframework/gcExtend.lua +++ /dev/null @@ -1,164 +0,0 @@ -local gc=love.graphics -local setColor,printf,draw=gc.setColor,gc.printf,gc.draw -local GC={} -function GC.mStr(obj,x,y)printf(obj,x-626,y,1252,'center')end--Printf a string with 'center' -function GC.simpX(obj,x,y)draw(obj,x-obj:getWidth()*.5,y)end--Simply draw an obj with x=obj:getWidth()/2 -function GC.simpY(obj,x,y)draw(obj,x,y-obj:getHeight()*.5)end--Simply draw an obj with y=obj:getWidth()/2 -function GC.X(obj,x,y,a,k)draw(obj,x,y,a,k,nil,obj:getWidth()*.5,0)end--Draw an obj with x=obj:getWidth()/2 -function GC.Y(obj,x,y,a,k)draw(obj,x,y,a,k,nil,0,obj:getHeight()*.5)end--Draw an obj with y=obj:getWidth()/2 -function GC.draw(obj,x,y,a,k)draw(obj,x,y,a,k,nil,obj:getWidth()*.5,obj:getHeight()*.5)end--Draw an obj with both middle X & Y -function GC.outDraw(obj,div,x,y,a,k) - local w,h=obj:getWidth()*.5,obj:getHeight()*.5 - draw(obj,x-div,y-div,a,k,nil,w,h) - draw(obj,x-div,y+div,a,k,nil,w,h) - draw(obj,x+div,y-div,a,k,nil,w,h) - draw(obj,x+div,y+div,a,k,nil,w,h) -end -function GC.shadedPrint(str,x,y,mode,d,clr1,clr2) - local w=1280 - if mode=='center'then - x=x-w*.5 - elseif mode=='right'then - x=x-w - end - if not d then d=1 end - setColor(clr1 or COLOR.D) - printf(str,x-d,y-d,w,mode) - printf(str,x-d,y+d,w,mode) - printf(str,x+d,y-d,w,mode) - printf(str,x+d,y+d,w,mode) - setColor(clr2 or COLOR.Z) - printf(str,x,y,w,mode) -end -function GC.regularPolygon(mode,x,y,R,segments,r,phase) - local X,Y={},{} - local ang=phase or 0 - local angStep=6.283185307179586/segments - for i=1,segments do - X[i]=x+R*math.cos(ang) - Y[i]=y+R*math.sin(ang) - ang=ang+angStep - end - X[segments+1]=x+R*math.cos(ang) - Y[segments+1]=y+R*math.sin(ang) - local halfAng=6.283185307179586/segments/2 - local erasedLen=r*math.tan(halfAng) - if mode=='line'then - erasedLen=erasedLen+1--Fix 1px cover - for i=1,segments do - --Line - local x1,y1,x2,y2=X[i],Y[i],X[i+1],Y[i+1] - local dir=math.atan2(y2-y1,x2-x1) - gc.line(x1+erasedLen*math.cos(dir),y1+erasedLen*math.sin(dir),x2-erasedLen*math.cos(dir),y2-erasedLen*math.sin(dir)) - - --Arc - ang=ang+angStep - local R2=R-r/math.cos(halfAng) - local arcCX,arcCY=x+R2*math.cos(ang),y+R2*math.sin(ang) - gc.arc('line','open',arcCX,arcCY,r,ang-halfAng,ang+halfAng) - end - elseif mode=='fill'then - local L={} - for i=1,segments do - --Line - local x1,y1,x2,y2=X[i],Y[i],X[i+1],Y[i+1] - local dir=math.atan2(y2-y1,x2-x1) - table.insert(L,x1+erasedLen*math.cos(dir)) - table.insert(L,y1+erasedLen*math.sin(dir)) - table.insert(L,x2-erasedLen*math.cos(dir)) - table.insert(L,y2-erasedLen*math.sin(dir)) - - --Arc - ang=ang+angStep - local R2=R-r/math.cos(halfAng) - local arcCX,arcCY=x+R2*math.cos(ang),y+R2*math.sin(ang) - gc.arc('fill','open',arcCX,arcCY,r,ang-halfAng,ang+halfAng) - end - gc.polygon('fill',L) - else - error("Draw mode should be 'line' or 'fill'") - end -end -do--function GC.DO(L) - local cmds={ - origin="origin", - move="translate", - scale="scale", - rotate="rotate", - shear="shear", - clear="clear", - - setCL="setColor", - setCM="setColorMask", - setLW="setLineWidth", - setLS="setLineStyle", - setLJ="setLineJoin", - - print="print", - rawFT=function(...)FONT.rawset(...)end, - setFT=function(...)FONT.set(...)end, - mText=GC.mStr, - mDraw=GC.draw, - mDrawX=GC.X, - mDrawY=GC.Y, - mOutDraw=GC.outDraw, - - draw="draw", - line="line", - fRect=function(...)gc.rectangle('fill',...)end, - dRect=function(...)gc.rectangle('line',...)end, - fCirc=function(...)gc.circle('fill',...)end, - dCirc=function(...)gc.circle('line',...)end, - fElps=function(...)gc.ellipse('fill',...)end, - dElps=function(...)gc.ellipse('line',...)end, - fPoly=function(...)gc.polygon('fill',...)end, - dPoly=function(...)gc.polygon('line',...)end, - - dPie=function(...)gc.arc('line',...)end, - dArc=function(...)gc.arc('line','open',...)end, - dBow=function(...)gc.arc('line','closed',...)end, - fPie=function(...)gc.arc('fill',...)end, - fArc=function(...)gc.arc('fill','open',...)end, - fBow=function(...)gc.arc('fill','closed',...)end, - - fRPol=function(...)GC.regularPolygon('fill',...)end, - dRPol=function(...)GC.regularPolygon('line',...)end, - } - local sizeLimit=gc.getSystemLimits().texturesize - function GC.DO(L) - gc.push() - ::REPEAT_tryAgain:: - local success,canvas=pcall(gc.newCanvas,math.min(L[1],sizeLimit),math.min(L[2],sizeLimit)) - if not success then - sizeLimit=math.floor(sizeLimit*.8) - goto REPEAT_tryAgain - end - gc.setCanvas(canvas) - gc.origin() - gc.clear(1,1,1,0) - gc.setColor(1,1,1) - gc.setLineWidth(1) - for i=3,#L do - local cmd=L[i][1] - if type(cmd)=='boolean'and cmd then - table.remove(L[i],1) - cmd=L[i][1] - end - if type(cmd)=='string'then - local func=cmds[cmd] - if type(func)=='string'then - func=gc[func] - end - if func then - func(unpack(L[i],2)) - else - error("No gc command: "..cmd) - end - end - end - gc.setCanvas() - gc.pop() - return canvas - end -end -return GC diff --git a/Zframework/image.lua b/Zframework/image.lua deleted file mode 100644 index 7f541230..00000000 --- a/Zframework/image.lua +++ /dev/null @@ -1,25 +0,0 @@ -local IMG={} -function IMG.init(list) - IMG.init=nil - - setmetatable(IMG,{__index=function(self,name) - if type(list[name])=='table'then - self[name]={} - for i=1,#list[name]do - self[name][i]=love.graphics.newImage(list[name][i]) - end - elseif type(list[name])=='string'then - self[name]=love.graphics.newImage(list[name]) - else - LOG("No IMG: "..name) - self[name]=PAPER - end - return self[name] - end}) - - function IMG.loadAll() - for k in next,list do local _=IMG[k]end - IMG.loadAll=nil - end -end -return IMG diff --git a/Zframework/init.lua b/Zframework/init.lua deleted file mode 100644 index 400a6263..00000000 --- a/Zframework/init.lua +++ /dev/null @@ -1,885 +0,0 @@ -NONE={}function NULL()end PAPER=love.graphics.newCanvas(1,1) -EDITING="" -LOADED=false - ---Pure lua modules (basic) -MATH= require'Zframework.mathExtend' -COLOR= require'Zframework.color' -TABLE= require'Zframework.tableExtend' -STRING= require'Zframework.stringExtend' -PROFILE= require'Zframework.profile' -JSON= require'Zframework.json' -TEST= require'Zframework.test' - -do--Add pcall & MES for JSON lib - local encode,decode=JSON.encode,JSON.decode - JSON.encode=function(val) - local a,b=pcall(encode,val) - if a then - return b - elseif MES then - MES.traceback() - end - end - JSON.decode=function(str) - local a,b=pcall(decode,str) - if a then - return b - elseif MES then - MES.traceback() - end - end -end - ---Pure lua modules (complex) -LOG= require'Zframework.log' -REQUIRE= require'Zframework.require' -TASK= require'Zframework.task' -WS= require'Zframework.websocket' -LANG= require'Zframework.languages' - ---Love-based modules (basic) -FILE= require'Zframework.file' -WHEELMOV= require'Zframework.wheelScroll' -SCR= require'Zframework.screen' -SCN= require'Zframework.scene' -LIGHT= require'Zframework.light' - ---Love-based modules (complex) -GC= require'Zframework.gcExtend' -FONT= require'Zframework.font' -TEXT= require'Zframework.text' -SYSFX= require'Zframework.sysFX' -MES= require'Zframework.message' -BG= require'Zframework.background' -WIDGET= require'Zframework.widget' -VIB= require'Zframework.vibrate' -SFX= require'Zframework.sfx' -IMG= require'Zframework.image' -BGM= require'Zframework.bgm' -VOC= require'Zframework.voice' - -local ms,kb=love.mouse,love.keyboard -local KBisDown=kb.isDown - -local gc=love.graphics -local gc_push,gc_pop,gc_clear,gc_discard=gc.push,gc.pop,gc.clear,gc.discard -local gc_replaceTransform,gc_present=gc.replaceTransform,gc.present -local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth -local gc_draw,gc_line,gc_circle,gc_print=gc.draw,gc.line,gc.circle,gc.print - -local WIDGET,SCR,SCN=WIDGET,SCR,SCN -local xOy=SCR.xOy -local ITP=xOy.inverseTransformPoint - -local max,min=math.max,math.min - -local devMode -local mx,my,mouseShow,cursorSpd=640,360,false,0 -local jsState={}--map, joystickID->axisStates: {axisName->axisVal} -local errData={}--list, each error create {mes={errMes strings},scene=sceneNameStr} - -local function drawCursor(_,x,y) - gc_setColor(1,1,1) - gc_setLineWidth(2) - gc_circle(ms.isDown(1)and'fill'or'line',x,y,6) -end -local showPowerInfo=true -local showClickFX=true -local discardCanvas=false -local frameMul=100 -local sleepInterval=1/60 -local onQuit=NULL - -local batteryImg=GC.DO{31,20, - {'fRect',1,0,26,2}, - {'fRect',1,18,26,2}, - {'fRect',0,1,2,18}, - {'fRect',26,1,2,18}, - {'fRect',29,3,2,14}, -} -local infoCanvas=gc.newCanvas(108,27) -local function updatePowerInfo() - local state,pow=love.system.getPowerInfo() - gc.setCanvas(infoCanvas) - gc_push('transform') - gc.origin() - gc_clear(0,0,0,.25) - if state~='unknown'then - gc_setLineWidth(4) - if state=='nobattery'then - gc_setColor(1,1,1) - gc_setLineWidth(2) - gc_line(74,5,100,22) - elseif pow then - if state=='charging'then gc_setColor(0,1,0) - elseif pow>50 then gc_setColor(1,1,1) - elseif pow>26 then gc_setColor(1,1,0) - elseif pow==26 then gc_setColor(.5,0,1) - else gc_setColor(1,0,0) - end - gc.rectangle('fill',76,6,pow*.22,14) - if pow<100 then - FONT.set(15) - gc.setColor(COLOR.D) - gc_print(pow,77,1) - gc_print(pow,77,3) - gc_print(pow,79,1) - gc_print(pow,79,3) - gc_setColor(COLOR.Z) - gc_print(pow,78,2) - end - end - gc_draw(batteryImg,73,3) - end - FONT.set(25) - gc_print(os.date("%H:%M"),3,-5) - gc_pop() - gc.setCanvas() -end -------------------------------------------------------------- -local lastX,lastY=0,0--Last click pos -local function _updateMousePos(x,y,dx,dy) - if SCN.swapping then return end - dx,dy=dx/SCR.k,dy/SCR.k - if SCN.mouseMove then SCN.mouseMove(x,y,dx,dy)end - if ms.isDown(1)then - WIDGET.drag(x,y,dx,dy) - else - WIDGET.cursorMove(x,y) - end -end -local function _triggerMouseDown(x,y,k) - if devMode==1 then - print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format( - x,y, - x-lastX,y-lastY, - math.floor(x/10)*10,math.floor(y/10)*10, - math.floor((x-lastX)/10)*10,math.floor((y-lastY)/10)*10 - )) - end - if SCN.swapping then return end - if SCN.mouseDown then SCN.mouseDown(x,y,k)end - WIDGET.press(x,y,k) - lastX,lastY=x,y - if showClickFX then SYSFX.newTap(3,x,y)end -end -local function mouse_update(dt) - if not KBisDown('lctrl','rctrl')and KBisDown('up','down','left','right')then - local dx,dy=0,0 - if KBisDown('up')then dy=dy-cursorSpd end - if KBisDown('down')then dy=dy+cursorSpd end - if KBisDown('left')then dx=dx-cursorSpd end - if KBisDown('right')then dx=dx+cursorSpd end - mx=max(min(mx+dx,1280),0) - my=max(min(my+dy,720),0) - if my==0 or my==720 then - WIDGET.sel=false - WIDGET.drag(0,0,0,-dy) - end - _updateMousePos(mx,my,dx,dy) - cursorSpd=min(cursorSpd+dt*26,12.6) - else - cursorSpd=6 - end -end -local function gp_update(js,dt) - local sx,sy=js._jsObj:getGamepadAxis('leftx'),js._jsObj:getGamepadAxis('lefty') - if math.abs(sx)>.1 or math.abs(sy)>.1 then - local dx,dy=0,0 - if sy<-.1 then dy=dy+2*sy*cursorSpd end - if sy>.1 then dy=dy+2*sy*cursorSpd end - if sx<-.1 then dx=dx+2*sx*cursorSpd end - if sx>.1 then dx=dx+2*sx*cursorSpd end - mx=max(min(mx+dx,1280),0) - my=max(min(my+dy,720),0) - if my==0 or my==720 then - WIDGET.sel=false - WIDGET.drag(0,0,0,-dy) - end - _updateMousePos(mx,my,dx,dy) - cursorSpd=min(cursorSpd+dt*26,12.6) - else - cursorSpd=6 - end -end -function love.mousepressed(x,y,k,touch) - if touch then return end - mouseShow=true - mx,my=ITP(xOy,x,y) - _triggerMouseDown(mx,my,k) -end -function love.mousemoved(x,y,dx,dy,touch) - if touch then return end - mouseShow=true - mx,my=ITP(xOy,x,y) - _updateMousePos(mx,my,dx,dy) -end -function love.mousereleased(x,y,k,touch) - if touch or SCN.swapping then return end - mx,my=ITP(xOy,x,y) - if SCN.mouseUp then SCN.mouseUp(mx,my,k)end - if WIDGET.sel then - WIDGET.release(mx,my) - else - if lastX and SCN.mouseClick and(mx-lastX)^2+(my-lastY)^2<62 then - SCN.mouseClick(mx,my,k) - end - end -end -function love.wheelmoved(x,y) - if SCN.swapping then return end - if SCN.wheelMoved then - SCN.wheelMoved(x,y) - else - WIDGET.unFocus() - WIDGET.drag(0,0,0,100*y) - end -end - -function love.touchpressed(id,x,y) - mouseShow=false - if SCN.swapping then return end - if not SCN.mainTouchID then - SCN.mainTouchID=id - WIDGET.unFocus(true) - love.touchmoved(id,x,y,0,0) - end - x,y=ITP(xOy,x,y) - lastX,lastY=x,y - WIDGET.cursorMove(x,y) - if SCN.touchDown then SCN.touchDown(x,y,id)end - if kb.hasTextInput()then kb.setTextInput(false)end -end -function love.touchmoved(id,x,y,dx,dy) - if SCN.swapping then return end - x,y=ITP(xOy,x,y) - if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k,id)end - WIDGET.drag(x,y,dx/SCR.k,dy/SCR.k) -end -function love.touchreleased(id,x,y) - if SCN.swapping then return end - x,y=ITP(xOy,x,y) - if id==SCN.mainTouchID then - WIDGET.press(x,y,1) - WIDGET.release(x,y) - WIDGET.cursorMove(x,y) - WIDGET.unFocus() - SCN.mainTouchID=false - end - if SCN.touchUp then SCN.touchUp(x,y,id)end - if(x-lastX)^2+(y-lastY)^2<62 then - if SCN.touchClick then SCN.touchClick(x,y)end - if showClickFX then SYSFX.newTap(3,x,y)end - end -end - -local fnKey={NULL,NULL,NULL,NULL,NULL,NULL,NULL} -local function noDevkeyPressed(key) - if key=='f1'then fnKey[1]() - elseif key=='f2'then fnKey[2]() - elseif key=='f3'then fnKey[3]() - elseif key=='f4'then fnKey[4]() - elseif key=='f5'then fnKey[5]() - elseif key=='f6'then fnKey[6]() - elseif key=='f7'then fnKey[7]() - elseif key=='f8'then devMode=nil MES.new('info',"DEBUG OFF",.2) - elseif key=='f9'then devMode=1 MES.new('info',"DEBUG 1") - elseif key=='f10'then devMode=2 MES.new('info',"DEBUG 2") - elseif key=='f11'then devMode=3 MES.new('info',"DEBUG 3") - elseif key=='f12'then devMode=4 MES.new('info',"DEBUG 4") - elseif devMode==2 then - local W=WIDGET.sel - if W then - if key=='left'then W.x=W.x-10 - elseif key=='right'then W.x=W.x+10 - elseif key=='up'then W.y=W.y-10 - elseif key=='down'then W.y=W.y+10 - elseif key==','then W.w=W.w-10 - elseif key=='.'then W.w=W.w+10 - elseif key=='/'then W.h=W.h-10 - elseif key=='\''then W.h=W.h+10 - elseif key=='['then W.font=W.font-5 - elseif key==']'then W.font=W.font+5 - else return true - end - else - return true - end - else - return true - end -end -function love.keypressed(key,_,isRep) - mouseShow=false - if devMode and not noDevkeyPressed(key)then - return - elseif key=='f8'then - devMode=1 - MES.new('info',"DEBUG ON",.2) - elseif key=='f11'then - SETTING.fullscreen=not SETTING.fullscreen - applySettings() - saveSettings() - elseif not SCN.swapping then - if EDITING==""and(not SCN.keyDown or SCN.keyDown(key,isRep))then - local W=WIDGET.sel - if key=='escape'and not isRep then - SCN.back() - elseif key=='up'or key=='down'or key=='left'or key=='right'then - mouseShow=true - if KBisDown('lctrl','rctrl')then - if W and W.arrowKey then W:arrowKey(key)end - end - elseif key=='space'or key=='return'then - mouseShow=true - if not isRep then - if showClickFX then SYSFX.newTap(3,mx,my)end - _triggerMouseDown(mx,my,1) - end - else - if W and W.keypress then - W:keypress(key) - end - end - end - end -end -function love.keyreleased(i) - if SCN.swapping then return end - if SCN.keyUp then SCN.keyUp(i)end -end - -function love.textedited(texts) - EDITING=texts -end -function love.textinput(texts) - WIDGET.textinput(texts) -end - ---analog sticks: -1, 0, 1 for neg, neutral, pos ---triggers: 0 for released, 1 for pressed -local jsAxisEventName={ - leftx={'leftstick_left','leftstick_right'}, - lefty={'leftstick_up','leftstick_down'}, - rightx={'rightstick_left','rightstick_right'}, - righty={'rightstick_up','rightstick_down'}, - triggerleft='triggerleft', - triggerright='triggerright' -} -local gamePadKeys={'a','b','x','y','back','guide','start','leftstick','rightstick','leftshoulder','rightshoulder','dpup','dpdown','dpleft','dpright'} -local dPadToKey={ - dpup='up', - dpdown='down', - dpleft='left', - dpright='right', - start='return', - back='escape', -} -function love.joystickadded(JS) - table.insert(jsState,{ - _id=JS:getID(), - _jsObj=JS, - leftx=0,lefty=0, - rightx=0,righty=0, - triggerleft=0,triggerright=0 - }) - MES.new('info',"Joystick added") -end -function love.joystickremoved(JS) - for i=1,#jsState do - if jsState[i]._jsObj==JS then - for j=1,#gamePadKeys do - if JS:isGamepadDown(gamePadKeys[j])then - love.gamepadreleased(JS,gamePadKeys[j]) - end - end - love.gamepadaxis(JS,'leftx',0) - love.gamepadaxis(JS,'lefty',0) - love.gamepadaxis(JS,'rightx',0) - love.gamepadaxis(JS,'righty',0) - love.gamepadaxis(JS,'triggerleft',-1) - love.gamepadaxis(JS,'triggerright',-1) - MES.new('info',"Joystick removed") - table.remove(jsState,i) - break - end - end -end -function love.gamepadaxis(JS,axis,val) - if jsState[1]and JS==jsState[1]._jsObj then - local js=jsState[1] - if axis=='leftx'or axis=='lefty'or axis=='rightx'or axis=='righty'then - local newVal=--range: [0,1] - val>.4 and 1 or - val<-.4 and -1 or - 0 - if newVal~=js[axis]then - if js[axis]==-1 then - love.gamepadreleased(JS,jsAxisEventName[axis][1]) - elseif js[axis]~=0 then - love.gamepadreleased(JS,jsAxisEventName[axis][2]) - end - if newVal==-1 then - love.gamepadpressed(JS,jsAxisEventName[axis][1]) - elseif newVal==1 then - love.gamepadpressed(JS,jsAxisEventName[axis][2]) - end - js[axis]=newVal - end - elseif axis=='triggerleft'or axis=='triggerright'then - local newVal=val>.3 and 1 or 0--range: [0,1] - if newVal~=js[axis]then - if newVal==1 then - love.gamepadpressed(JS,jsAxisEventName[axis]) - else - love.gamepadreleased(JS,jsAxisEventName[axis]) - end - js[axis]=newVal - end - end - end -end -function love.gamepadpressed(_,key) - mouseShow=false - if not SCN.swapping then - local cursorCtrl - if SCN.gamepadDown then - cursorCtrl=SCN.gamepadDown(key) - elseif SCN.keyDown then - cursorCtrl=SCN.keyDown(dPadToKey[key]or key) - else - cursorCtrl=true - end - if cursorCtrl then - key=dPadToKey[key]or key - mouseShow=true - local W=WIDGET.sel - if key=='back'then - SCN.back() - elseif key=='up'or key=='down'or key=='left'or key=='right'then - mouseShow=true - if W and W.arrowKey then W:arrowKey(key)end - elseif key=='return'then - mouseShow=true - if showClickFX then SYSFX.newTap(3,mx,my)end - _triggerMouseDown(mx,my,1) - else - if W and W.keypress then - W:keypress(key) - end - end - end - end -end -function love.gamepadreleased(_,i) - if SCN.swapping then return end - if SCN.gamepadUp then SCN.gamepadUp(i)end -end - -function love.filedropped(file) - if SCN.fileDropped then SCN.fileDropped(file)end -end -function love.directorydropped(dir) - if SCN.directoryDropped then SCN.directoryDropped(dir)end -end -local autoGCcount=0 -function love.lowmemory() - collectgarbage() - if autoGCcount<3 then - autoGCcount=autoGCcount+1 - MES.new('check',"[auto GC] low MEM 设备内存过低") - end -end - -local onResize=NULL -function love.resize(w,h) - if SCR.w==w and SCR.h==h then return end - SCR.resize(w,h) - if BG.resize then BG.resize(w,h)end - if SCN.resize then SCN.resize(w,h)end - WIDGET.resize(w,h) - FONT.reset() - onResize(w,h) -end - -local onFocus=NULL -function love.focus(f)onFocus(f)end - -local yield=coroutine.yield -local function secondLoopThread() - local mainLoop=love.run() - repeat yield()until mainLoop() -end -function love.errorhandler(msg) - if type(msg)~='string'then - msg="Unknown error" - elseif msg:find("Invalid UTF-8")and text then - msg=text.tryAnotherBuild - end - - --Generate error message - local err={"Error:"..msg} - local c=2 - for l in debug.traceback("",2):gmatch("(.-)\n")do - if c>2 then - if not l:find("boot")then - err[c]=l:gsub("^\t*","") - c=c+1 - end - else - err[2]="Traceback" - c=3 - end - end - print(table.concat(err,"\n",1,c-2)) - - --Reset something - love.audio.stop() - gc.reset() - - if LOADED and #errData<3 then - BG.set('none') - local scn=SCN and SCN.cur or"NULL" - table.insert(errData,{mes=err,scene=scn}) - - --Write messages to log file - love.filesystem.append('conf/error.log', - os.date("%Y/%m/%d %A %H:%M:%S\n").. - #errData.." crash(es) "..love.system.getOS().."-"..VERSION.string.." scene: "..scn.."\n".. - table.concat(err,"\n",1,c-2).."\n\n" - ) - - --Get screencapture - gc.captureScreenshot(function(_)errData[#errData].shot=gc.newImage(_)end) - gc.present() - - --Create a new mainLoop thread to keep game alive - local status,resume=coroutine.status,coroutine.resume - local loopThread=coroutine.create(secondLoopThread) - local res,threadErr - repeat - res,threadErr=resume(loopThread) - until status(loopThread)=='dead' - if not res then - love.errorhandler(threadErr) - return - end - else - ms.setVisible(true) - - local errorMsg - errorMsg=LOADED and - "Too many errors or fatal error occured.\nPlease restart the game."or - "An error has occurred during loading.\nError info has been created, and you can send it to the author." - while true do - love.event.pump() - for E,a,b in love.event.poll()do - if E=='quit'or a=='escape'then - return true - elseif E=='resize'then - SCR.resize(a,b) - end - end - gc_clear(.3,.5,.9) - gc_push('transform') - gc_replaceTransform(SCR.xOy) - FONT.set(100)gc_print(":(",100,0,0,1.2) - FONT.set(40)gc.printf(errorMsg,100,160,SCR.w0-100) - FONT.set(20) - gc_print(love.system.getOS().."-"..VERSION.string.." scene:"..(SCN and SCN.cur or"NULL"),100,660) - gc.printf(err[1],100,360,1260-100) - gc_print("TRACEBACK",100,450) - for i=4,#err-2 do - gc_print(err[i],100,400+20*i) - end - gc_pop() - gc_present() - love.timer.sleep(.26) - end - end -end -love.threaderror=nil - -love.draw,love.update=nil--remove default draw/update - -local devColor={ - COLOR.Z, - COLOR.lM, - COLOR.lG, - COLOR.lB, -} -local WS=WS -local WSnames={'app','user','play','stream','chat','manage'} -local wsImg={}do - local L={78,18, - {'clear',1,1,1,0}, - {'setCL',1,1,1,.3}, - {'fRect',60,0,18,18}, - } - for i=0,59 do - table.insert(L,{'setCL',1,1,1,i*.005}) - table.insert(L,{'fRect',i,0,1,18}) - end - wsImg.bottom=GC.DO(L) - wsImg.dead=GC.DO{20,20, - {'rawFT',20}, - {'setCL',1,.3,.3}, - {'mText',"X",11,-1}, - } - wsImg.connecting=GC.DO{20,20, - {'rawFT',20}, - {'setLW',3}, - {'mText',"C",11,-1}, - } - wsImg.running=GC.DO{20,20, - {'rawFT',20}, - {'setCL',.5,1,0}, - {'mText',"R",11,-1}, - } -end - -local debugInfos={ - {"Cache",gcinfo}, -} -function love.run() - local love=love - - local BG=BG - local TEXT_update,TEXT_draw=TEXT.update,TEXT.draw - local MES_update,MES_draw=MES.update,MES.draw - local WS_update=WS.update - local TASK_update=TASK.update - local SYSFX_update,SYSFX_draw=SYSFX.update,SYSFX.draw - local WIDGET_update,WIDGET_draw=WIDGET.update,WIDGET.draw - local STEP,WAIT=love.timer.step,love.timer.sleep - local FPS,MINI=love.timer.getFPS,love.window.isMinimized - local PUMP,POLL=love.event.pump,love.event.poll - - local timer,VERSION=love.timer.getTime,VERSION - - local frameTimeList={} - local lastFrame=timer() - local lastFreshPow=lastFrame - local FCT=0--Framedraw counter, from 0~99 - - love.resize(gc.getWidth(),gc.getHeight()) - - --Scene Launch - while #SCN.stack>0 do SCN.pop()end - SCN.push('quit','slowFade') - SCN.init(#errData==0 and'load'or'error') - - return function() - local _ - - local time=timer() - local dt=time-lastFrame - lastFrame=time - - --EVENT - PUMP() - for N,a,b,c,d,e in POLL()do - if love[N]then - love[N](a,b,c,d,e) - elseif N=='quit'then - onQuit() - return a or true - end - end - - --UPDATE - STEP() - if mouseShow then mouse_update(dt)end - if next(jsState)then gp_update(jsState[1],dt)end - VOC.update() - BG.update(dt) - TEXT_update(dt) - MES_update(dt) - WS_update(dt) - TASK_update(dt) - SYSFX_update(dt) - if SCN.update then SCN.update(dt)end - if SCN.swapping then SCN.swapUpdate(dt)end - WIDGET_update(dt) - - --DRAW - if not MINI()then - FCT=FCT+frameMul - if FCT>=100 then - FCT=FCT-100 - - gc_replaceTransform(SCR.origin) - gc_setColor(1,1,1) - BG.draw() - gc_replaceTransform(SCR.xOy) - if SCN.draw then SCN.draw()end - WIDGET_draw() - SYSFX_draw() - TEXT_draw() - - --Draw cursor - if mouseShow then drawCursor(time,mx,my)end - gc_replaceTransform(SCR.xOy_ul) - MES_draw() - gc_replaceTransform(SCR.origin) - --Draw power info. - if showPowerInfo then - gc_setColor(1,1,1) - gc_draw(infoCanvas,SCR.safeX,0,0,SCR.k) - end - - --Draw scene swapping animation - if SCN.swapping then - gc_setColor(1,1,1) - _=SCN.stat - _.draw(_.time) - end - gc_replaceTransform(SCR.xOy_d) - --Draw Version string - gc_setColor(.9,.9,.9,.42) - FONT.set(20) - mStr(VERSION.string,0,-30) - gc_replaceTransform(SCR.xOy_dl) - local safeX=SCR.safeX/SCR.k - - --Draw FPS - FONT.set(15) - gc_setColor(1,1,1) - gc_print(FPS(),safeX+5,-20) - - --Debug info. - if devMode then - --Debug infos at left-down - gc_setColor(devColor[devMode]) - - --Text infos - for i=1,#debugInfos do - gc_print(debugInfos[i][1],safeX+5,-20-20*i) - gc_print(debugInfos[i][2](),safeX+62.6,-20-20*i) - end - - --Update & draw frame time - table.insert(frameTimeList,1,dt)table.remove(frameTimeList,126) - gc_setColor(1,1,1,.3) - for i=1,#frameTimeList do - gc.rectangle('fill',150+2*i,-20,2,-frameTimeList[i]*4000) - end - - --Cursor pos disp - gc_replaceTransform(SCR.origin) - local x,y=SCR.xOy:transformPoint(mx,my) - gc_setLineWidth(1) - gc_line(x,0,x,SCR.h) - gc_line(0,y,SCR.w,y) - local t=math.floor(mx+.5)..","..math.floor(my+.5) - gc.setColor(COLOR.D) - gc_print(t,x+1,y) - gc_print(t,x+1,y-1) - gc_print(t,x+2,y-1) - gc_setColor(COLOR.Z) - gc_print(t,x+2,y) - - gc_replaceTransform(SCR.xOy_dr) - --Websocket status - for i=1,6 do - local status=WS.status(WSnames[i]) - gc_setColor(1,1,1) - gc.draw(wsImg.bottom,-79,20*i-139) - if status=='dead'then - gc_draw(wsImg.dead,-20,20*i-140) - elseif status=='connecting'then - gc_setColor(1,1,1,.5+.3*math.sin(time*6.26)) - gc_draw(wsImg.connecting,-20,20*i-140) - elseif status=='running'then - gc_draw(wsImg.running,-20,20*i-140) - end - local t1,t2,t3=WS.getTimers(WSnames[i]) - gc_setColor(.9,.9,.9,t1)gc.rectangle('fill',-60,20*i-122,-16,-16) - gc_setColor(.3,1,.3,t2)gc.rectangle('fill',-42,20*i-122,-16,-16) - gc_setColor(1,.2,.2,t3)gc.rectangle('fill',-24,20*i-122,-16,-16) - end - end - gc_present() - - --SPEED UPUPUP! - if discardCanvas then gc_discard()end - end - end - - --Fresh power info. - if time-lastFreshPow>2.6 then - if showPowerInfo then - updatePowerInfo() - lastFreshPow=time - end - if gc.getWidth()~=SCR.w or gc.getHeight()~=SCR.h then - love.resize(gc.getWidth(),gc.getHeight()) - end - end - - --Slow devmode - if devMode then - if devMode==3 then - WAIT(.1) - elseif devMode==4 then - WAIT(.5) - end - end - - _=timer()-lastFrame - if _= math.huge then - error("unexpected number value '" .. tostring(val) .. "'") - end - return string.format("%.14g", val) -end - -local type_func_map = { - ['nil'] = encode_nil, - ['table'] = encode_table, - ['string'] = encode_string, - ['number'] = encode_number, - ['boolean'] = tostring -} - -_encode = function(val, stack) - local t = type(val) - local f = type_func_map[t] - if f then return f(val, stack) end - error("unexpected type '" .. t .. "'") -end - -json.encode=_encode - -------------------------------------------------------------------------------- --- Decode -------------------------------------------------------------------------------- - -local parse - -local function create_set(...) - local res = {} - for i = 1, select("#", ...) do res[select(i, ...)] = true end - return res -end - -local space_chars = create_set(" ", "\t", "\r", "\n") -local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") -local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") -local literals = create_set("true", "false", "null") - -local literal_map = {["true"] = true, ["false"] = false, ["null"] = nil} - -local function next_char(str, idx, set, negate) - for i = idx, #str do if set[str:sub(i, i)] ~= negate then return i end end - return #str + 1 -end - -local function decode_error(str, idx, msg) - local line_count = 1 - local col_count = 1 - for i = 1, idx - 1 do - col_count = col_count + 1 - if str:sub(i, i) == "\n" then - line_count = line_count + 1 - col_count = 1 - end - end - error(string.format("%s at line %d col %d", msg, line_count, col_count)) -end - -local function codepoint_to_utf8(n) - -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa - local f = bit.rshift - if n <= 0x7f then - return char(n) - elseif n <= 0x7ff then - return char(f(n, 6) + 192, n % 64 + 128) - elseif n <= 0xffff then - return char(f(n, 12) + 224, f(n % 4096, 6) + 128, n % 64 + 128) - elseif n <= 0x10ffff then - return char(f(n, 18) + 240, f(n % 262144, 12) + 128, f(n % 4096, 6) + 128, n % 64 + 128) - end - error(string.format("invalid unicode codepoint '%x'", n)) -end - -local function parse_unicode_escape(s) - local n1 = tonumber(s:sub(1, 4), 16) - local n2 = tonumber(s:sub(7, 10), 16) - -- Surrogate pair? - if n2 then - return - codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) - else - return codepoint_to_utf8(n1) - end -end - -local function parse_string(str, i) - local res = "" - local j = i + 1 - local k = j - - while j <= #str do - local x = str:byte(j) - - if x < 32 then - decode_error(str, j, "control character in string") - - elseif x == 92 then -- `\`: Escape - res = res .. str:sub(k, j - 1) - j = j + 1 - local c = str:sub(j, j) - if c == "u" then - local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) or - str:match("^%x%x%x%x", j + 1) or - decode_error(str, j - 1, - "invalid unicode escape in string") - res = res .. parse_unicode_escape(hex) - j = j + #hex - else - if not escape_chars[c] then - decode_error(str, j - 1, - "invalid escape char '" .. c .. "' in string") - end - res = res .. escape_char_map_inv[c] - end - k = j + 1 - - elseif x == 34 then -- `"`: End of string - res = res .. str:sub(k, j - 1) - return res, j + 1 - end - - j = j + 1 - end - - decode_error(str, i, "expected closing quote for string") -end - -local function parse_number(str, i) - local x = next_char(str, i, delim_chars) - local s = str:sub(i, x - 1) - local n = tonumber(s) - if not n then decode_error(str, i, "invalid number '" .. s .. "'") end - return n, x -end - -local function parse_literal(str, i) - local x = next_char(str, i, delim_chars) - local word = str:sub(i, x - 1) - if not literals[word] then - decode_error(str, i, "invalid literal '" .. word .. "'") - end - return literal_map[word], x -end - -local function parse_array(str, i) - local res = {} - local n = 1 - i = i + 1 - while 1 do - local x - i = next_char(str, i, space_chars, true) - -- Empty / end of array? - if str:sub(i, i) == "]" then - i = i + 1 - break - end - -- Read token - x, i = parse(str, i) - res[n] = x - n = n + 1 - -- Next token - i = next_char(str, i, space_chars, true) - local chr = str:sub(i, i) - i = i + 1 - if chr == "]" then break end - if chr ~= "," then decode_error(str, i, "expected ']' or ','") end - end - return res, i -end - -local function parse_object(str, i) - local res = {} - i = i + 1 - while 1 do - local key, val - i = next_char(str, i, space_chars, true) - -- Empty / end of object? - if str:sub(i, i) == "}" then - i = i + 1 - break - end - -- Read key - if str:sub(i, i) ~= '"' then - decode_error(str, i, "expected string for key") - end - key, i = parse(str, i) - -- Read ':' delimiter - i = next_char(str, i, space_chars, true) - if str:sub(i, i) ~= ":" then - decode_error(str, i, "expected ':' after key") - end - i = next_char(str, i + 1, space_chars, true) - -- Read value - val, i = parse(str, i) - -- Set - res[key] = val - -- Next token - i = next_char(str, i, space_chars, true) - local chr = str:sub(i, i) - i = i + 1 - if chr == "}" then break end - if chr ~= "," then decode_error(str, i, "expected '}' or ','") end - end - return res, i -end - -local char_func_map = { - ['"'] = parse_string, - ["0"] = parse_number, - ["1"] = parse_number, - ["2"] = parse_number, - ["3"] = parse_number, - ["4"] = parse_number, - ["5"] = parse_number, - ["6"] = parse_number, - ["7"] = parse_number, - ["8"] = parse_number, - ["9"] = parse_number, - ["-"] = parse_number, - ["t"] = parse_literal, - ["f"] = parse_literal, - ["n"] = parse_literal, - ["["] = parse_array, - ["{"] = parse_object -} - -function parse(str, idx) - local chr = str:sub(idx, idx) - local f = char_func_map[chr] - if f then return f(str, idx) end - decode_error(str, idx, "unexpected character '" .. chr .. "'") -end - -function json.decode(str) - if type(str) ~= 'string' then - error("expected argument of type string, got " .. type(str)) - end - local res, idx = parse(str, next_char(str, 1, space_chars, true)) - idx = next_char(str, idx, space_chars, true) - if idx <= #str then decode_error(str, idx, "trailing garbage") end - return res -end -return json diff --git a/Zframework/languages.lua b/Zframework/languages.lua deleted file mode 100644 index ad40ce35..00000000 --- a/Zframework/languages.lua +++ /dev/null @@ -1,57 +0,0 @@ -local LANG={} ---ONLY FIRST CALL MAKE SENSE ---Create LANG.get() and LANG.addScene() -function LANG.init(defaultLang,langList,publicText,pretreatFunc) - local function _langFallback(T0,T) - for k,v in next,T0 do - if type(v)=='table'and not v.refuseCopy then--refuseCopy: just copy pointer, not contents - if not T[k]then T[k]={}end - if type(T[k])=='table'then - _langFallback(v,T[k]) - end - elseif not T[k]then - T[k]=v - end - end - end - - --Set public text - if publicText then - for _,L in next,langList do - for key,list in next,publicText do L[key]=list end - end - end - - --Fallback to default language - for name,L in next,langList do - if name~=defaultLang then - _langFallback(langList[L.fallback or defaultLang],L) - end - end - - --Custom pretreatment for each language - if pretreatFunc then - for _,L in next,langList do - pretreatFunc(L) - end - end - - function LANG.get(l) - if not langList[l]then - LOG("Wrong language: "..tostring(l)) - l=defaultLang - end - return langList[l] - end - - function LANG.addScene(name) - for _,L in next,langList do - if L.WidgetText and not L.WidgetText[name]then - L.WidgetText[name]={} - end - end - end - - function LANG.init()end -end -return LANG diff --git a/Zframework/light/init.lua b/Zframework/light/init.lua deleted file mode 100644 index 71213969..00000000 --- a/Zframework/light/init.lua +++ /dev/null @@ -1,86 +0,0 @@ ---LIGHT MODULE (Optimized by MrZ, Original on github/LÖVE community/simple-love-lights) ---Heavily based on mattdesl's libGDX implementation: ---https://github.com/mattdesl/lwjgl-basics/wiki/2D-Pixel-Perfect-Shadows -local gc=love.graphics -local clear,gc_translate=gc.clear,gc.translate -local gc_setCanvas,gc_setShader=gc.setCanvas,gc.setShader -local gc_setColor,gc_draw=gc.setColor,gc.draw - -local shadowMapShader=gc.newShader('Zframework/light/shadowMap.glsl')--Shader for caculating the 1D shadow map. -local lightRenderShader=gc.newShader('Zframework/light/lightRender.glsl')--Shader for rendering blurred lights and shadows. -local Lights={}--Lightsource objects -local function move(L,x,y) - L.x,L.y=x,y -end -local function setPow(L,pow) - L.size=pow -end -local function drawLight(L) - local s=L.size - - --Initialization - gc_setCanvas(L.blackCanvas)clear() - gc_setCanvas(L.shadowCanvas)clear() - gc_setCanvas(L.renderCanvas)clear() - lightRenderShader:send('xresolution',s) - shadowMapShader:send('yresolution',s) - - --Get up-left of light - local X=L.x-s*.5 - local Y=L.y-s*.5 - - --Render solid - gc_translate(-X,-Y) - L.blackCanvas:renderTo(L.blackFn) - gc_translate(X,Y) - - --Render shade canvas by solid - gc_setShader(shadowMapShader) - gc_setCanvas(L.shadowCanvas) - gc_draw(L.blackCanvas) - - --Render light canvas by shade - gc_setShader(lightRenderShader) - gc_setCanvas(L.renderCanvas) - gc_draw(L.shadowCanvas,0,0,0,1,s) - - --Ready to final render - gc_setShader()gc_setCanvas()gc.setBlendMode('add') - - --Render to screen - gc_draw(L.renderCanvas,X,Y+s,0,1,-1) - - --Reset - gc.setBlendMode('alpha') -end - -local LIGHT={} -function LIGHT.draw() - gc_setColor(1,1,1) - for i=1,#Lights do - drawLight(Lights[i]) - end -end -function LIGHT.clear() - for i=1,#Lights do - Lights[i].blackCanvas:release() - Lights[i].shadowCanvas:release() - Lights[i].renderCanvas:release() - Lights[i]=nil - end -end -function LIGHT.add(x,y,radius,solidFunc) - local id=#Lights+1 - Lights[id]={ - id=id, - x=x,y=y,size=radius, - blackCanvas=gc.newCanvas(radius,radius),--Solid canvas - shadowCanvas=gc.newCanvas(radius,1),--1D vis-depth canvas - renderCanvas=gc.newCanvas(radius,radius),--Light canvas - blackFn=solidFunc,--Solid draw function - - move=move, - setPow=setPow, - } -end -return LIGHT diff --git a/Zframework/light/lightRender.glsl b/Zframework/light/lightRender.glsl deleted file mode 100644 index 7d3efe70..00000000 --- a/Zframework/light/lightRender.glsl +++ /dev/null @@ -1,29 +0,0 @@ -#define PI 3.14159 -extern float xresolution; -// Sample from 1D vis-depth map -float samp(vec2 coord,float r,Image u_texture){ - return step(r,Texel(u_texture,coord).r); -} -vec4 effect(vec4 color,Image tex,vec2 tex_coords,vec2 screen_coords){ - // Cartesian to polar, y of 1D sample is always 0 - vec2 norm=tex_coords.st*2.-1.; - vec2 tc=vec2((atan(norm.y,norm.x)+PI)/(2.*PI),0.); - float r=length(norm); - - // Enlarge blur parameter by distance, light scattering simulation - float blur=(1./xresolution)*smoothstep(0.3,1.,r); - - // Simple Gaussian blur - float sum=// Brightness(0~1) - samp(vec2(tc.x-3.*blur,tc.y),r,tex)*0.1 - +samp(vec2(tc.x-2.*blur,tc.y),r,tex)*0.13 - +samp(vec2(tc.x-1.*blur,tc.y),r,tex)*0.17 - - +samp(tc,r,tex)*0.2// The center tex coord, which gives us hard shadows. - +samp(vec2(tc.x+1.*blur,tc.y),r,tex)*0.17 - +samp(vec2(tc.x+2.*blur,tc.y),r,tex)*0.13 - +samp(vec2(tc.x+3.*blur,tc.y),r,tex)*0.1; - - // Multiply the distance to get a soft fading - return vec4(vec3(1.),sum*smoothstep(1.,0.,r)); -} diff --git a/Zframework/light/shadowMap.glsl b/Zframework/light/shadowMap.glsl deleted file mode 100644 index 54809c79..00000000 --- a/Zframework/light/shadowMap.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#define PI 3.14 -extern float yresolution; -vec4 effect(vec4 color,Image tex,vec2 tex_coords,vec2 screen_coords){ - // Iterate through the occluder map's y-axis. - for(float y=0.;y0.1 - )return vec4(vec3(y/yresolution),1.);// Collision check, alpha>0.1 means transparent - } - return vec4(1.);// Return max distance 1 -} diff --git a/Zframework/log.lua b/Zframework/log.lua deleted file mode 100644 index f1cec3cd..00000000 --- a/Zframework/log.lua +++ /dev/null @@ -1,20 +0,0 @@ -local ins=table.insert - -local logs={os.date("Techmino logs %Y/%m/%d %A")} - -local function log(message) - ins(logs,os.date("[%H:%M:%S] ")..message) -end - -local LOG=setmetatable({logs=logs},{ - __call=function(_,message) - print(message) - log(message) - end -}) - -function LOG.read() - return table.concat(logs,"\n") -end - -return LOG diff --git a/Zframework/mathExtend.lua b/Zframework/mathExtend.lua deleted file mode 100644 index 85249212..00000000 --- a/Zframework/mathExtend.lua +++ /dev/null @@ -1,50 +0,0 @@ -local MATH={}for k,v in next,math do MATH[k]=v end - -local int,ceil=math.floor,math.ceil -local rnd=math.random - -MATH.tau=2*math.pi - -function MATH.sign(a) - return a>0 and 1 or a<0 and -1 or 0 -end - -function MATH.roll(chance) - return rnd()<(chance or .5) -end - -function MATH.coin(a,b) - if rnd()<.5 then - return a - else - return b - end -end - -function MATH.interval(v,low,high) - if v<=low then - return low - elseif v>=high then - return high - else - return v - end -end - -function MATH.lerp(s,e,t) - return s+(e-s)*t -end - -do--function MATH.listLerp(list,t) - local interval,lerp=MATH.interval,MATH.lerp - function MATH.listLerp(list,t) - local t2=(#list-1)*interval(t,0,1)+1 - return lerp(list[int(t2)],list[ceil(t2)],t2%1) - end -end - -function MATH.expApproach(a,b,k) - return b+(a-b)*2.718281828459045^-k -end - -return MATH diff --git a/Zframework/message.lua b/Zframework/message.lua deleted file mode 100644 index c2bbafa0..00000000 --- a/Zframework/message.lua +++ /dev/null @@ -1,148 +0,0 @@ -local gc=love.graphics -local gc_push,gc_pop=gc.push,gc.pop -local gc_translate,gc_setColor,gc_draw=gc.translate,gc.setColor,gc.draw - -local ins,rem=table.insert,table.remove -local max=math.max - -local mesList={} -local mesIcon={ - check=GC.DO{40,40, - {'setLW',10}, - {'setCL',0,0,0}, - {'line',4,19,15,30,36,9}, - {'setLW',6}, - {'setCL',.7,1,.6}, - {'line',5,20,15,30,35,10}, - }, - info=GC.DO{40,40, - {'setCL',.2,.25,.85}, - {'fCirc',20,20,15}, - {'setCL',1,1,1}, - {'setLW',2}, - {'dCirc',20,20,15}, - {'fRect',18,11,4,4}, - {'fRect',18,17,4,12}, - }, - broadcast=GC.DO{40,40, - {'setCL',1,1,1}, - {'fRect',2,4,36,26,3}, - {'fPoly',2,27,2,37,14,25}, - {'setCL',.5,.5,.5}, - {'fRect',6,11,4,4,1},{'fRect',14,11,19,4,1}, - {'fRect',6,19,4,4,1},{'fRect',14,19,19,4,1}, - }, - warn=GC.DO{40,40, - {'setCL',.95,.83,.4}, - {'fPoly',20.5,1,0,38,40,38}, - {'setCL',0,0,0}, - {'dPoly',20.5,1,0,38,40,38}, - {'fRect',17,10,7,18,2}, - {'fRect',17,29,7,7,2}, - {'setCL',1,1,1}, - {'fRect',18,11,5,16,2}, - {'fRect',18,30,5,5,2}, - }, - error=GC.DO{40,40, - {'setCL',.95,.3,.3}, - {'fCirc',20,20,19}, - {'setCL',0,0,0}, - {'dCirc',20,20,19}, - {'setLW',6}, - {'line',10.2,10.2,29.8,29.8}, - {'line',10.2,29.8,29.8,10.2}, - {'setLW',4}, - {'setCL',1,1,1}, - {'line',11,11,29,29}, - {'line',11,29,29,11}, - }, - music=GC.DO{40,40, - {'setLW',2}, - {'dRect',1,3,38,34,3}, - {'setLW',4}, - {'line',21,26,21,10,28,10}, - {'fElps',17,26,6,5}, - }, -} - -local MES={} -local backColors={ - check={.3,.6,.3,.7}, - broadcast={.3,.3,.6,.8}, - warn={.4,.4,.2,.9}, - error={.4,.2,.2,.9}, - music={.2,.4,.4,.9}, -} -function MES.new(icon,str,time) - local backColor={.5,.5,.5,.7} - if type(icon)=='string'then - backColor=backColors[icon]or backColor - icon=mesIcon[icon] - end - local t=gc.newText(FONT.get(30),str) - local w=math.max(t:getWidth()+(icon and 45 or 5),200)+15 - local h=math.max(t:getHeight(),46)+2 - local L={w,h, - {'clear',backColor}, - {'setCL',.7,.7,.7}, - {'setLW',2}, - {'dRect',1,1,w-2,h-2}, - {'setCL',1,1,1}, - } - if icon then - ins(L,{'draw',icon,4,4,nil,40/icon:getWidth(),40/icon:getHeight()}) - end - ins(L,{'mDrawY',t,icon and 50 or 10,h/2}) - - ins(mesList,{ - startTime=.5, - endTime=.5, - time=time or 3, - canvas=GC.DO(L), - width=w,height=h, - scale=h>400 and 1/math.min(h/400,2.6)or 1 - }) -end - -function MES.update(dt) - for i=#mesList,1,-1 do - local m=mesList[i] - if m.startTime>0 then - m.startTime=max(m.startTime-dt,0) - elseif m.time>0 then - m.time=max(m.time-dt,0) - elseif m.endTime>0 then - m.endTime=m.endTime-dt - else - rem(mesList,i) - end - end -end - -function MES.draw() - gc_push('transform') - if #mesList>0 then - gc_translate(SCR.safeX,30) - for i=1,#mesList do - local m=mesList[i] - gc_setColor(1,1,1,2*(m.endTime-m.startTime)) - gc_draw(m.canvas,40-80*(m.endTime+m.startTime),0,nil,m.scale) - gc_translate(0,m.height*m.scale+2) - end - end - gc_pop() -end - -function MES.traceback() - local mes= - debug.traceback('',1) - :gsub(': in function',', in') - :gsub(':',' ') - :gsub('\t','') - MES.new('error',mes:sub( - mes:find("\n",2)+1, - mes:find("\n%[C%], in 'xpcall'") - ),5) -end - -return MES diff --git a/Zframework/profile.lua b/Zframework/profile.lua deleted file mode 100644 index 65266f60..00000000 --- a/Zframework/profile.lua +++ /dev/null @@ -1,157 +0,0 @@ -local clock=os.clock - -local profile={} - -local _labeled={} -- function labels -local _defined={} -- function definitions -local _tcalled={} -- time of last call -local _telapsed={}-- total execution time -local _ncalls={} -- number of calls -local _internal={}-- list of internal profiler functions - -local getInfo=debug.getinfo -function profile.hooker(event,line,info) - info=info or getInfo(2,'fnS') - local f=info.func - if _internal[f]then return end-- ignore the profiler itself - if info.name then _labeled[f]=info.name end-- get the function name if available - -- find the line definition - if not _defined[f]then - _defined[f]=info.short_src..":"..info.linedefined - _ncalls[f]=0 - _telapsed[f]=0 - end - if _tcalled[f]then - local dt=clock()-_tcalled[f] - _telapsed[f]=_telapsed[f]+dt - _tcalled[f]=nil - end - if event=='tail call'then - local prev=getInfo(3,'fnS') - profile.hooker('return',line,prev) - profile.hooker('call',line,info) - elseif event=='call'then - _tcalled[f]=clock() - else - _ncalls[f]=_ncalls[f]+1 - end -end - ---- Starts collecting data. -function profile.start() - if jit then - jit.off() - jit.flush() - end - debug.sethook(profile.hooker,'cr') -end - ---- Stops collecting data. -function profile.stop() - debug.sethook() - for f in next,_tcalled do - local dt=clock()-_tcalled[f] - _telapsed[f]=_telapsed[f]+dt - _tcalled[f]=nil - end - -- merge closures - local lookup={} - for f,d in next,_defined do - local id=(_labeled[f]or"?")..d - local f2=lookup[id] - if f2 then - _ncalls[f2]=_ncalls[f2]+(_ncalls[f]or 0) - _telapsed[f2]=_telapsed[f2]+(_telapsed[f]or 0) - _defined[f],_labeled[f]=nil,nil - _ncalls[f],_telapsed[f]=nil,nil - else - lookup[id]=f - end - end - collectgarbage() -end - ---- Resets all collected data. -function profile.reset() - for f in next,_ncalls do - _ncalls[f]=0 - _telapsed[f]=0 - _tcalled[f]=nil - end - collectgarbage() -end - -local function _comp(a,b) - local dt=_telapsed[b]-_telapsed[a] - return dt==0 and _ncalls[b]<_ncalls[a]or dt<0 -end - ---- Iterates all functions that have been called since the profile was started. -function profile.query(limit) - local t={} - for f,n in next,_ncalls do - if n>0 then - t[#t+1]=f - end - end - table.sort(t,_comp) - - if limit then while #t>limit do table.remove(t)end end - - for i,f in ipairs(t)do - local dt=0 - if _tcalled[f]then - dt=clock()-_tcalled[f] - end - t[i]={i,_labeled[f]or"?",math.floor((_telapsed[f]+dt)*1e6)/1e6,_ncalls[f],_defined[f]} - end - return t -end - -local cols={3,20,8,6,32} -function profile.report(n) - local out={} - local report=profile.query(n) - for i,row in ipairs(report)do - for j=1,5 do - local s=tostring(row[j]) - local l1,l2=#s,cols[j] - if l1l2 then - s=s:sub(l1-l2+1,l1) - end - row[j]=s - end - out[i]=table.concat(row," | ") - end - - local row=" +-----+----------------------+----------+--------+----------------------------------+ \n" - local col=" | # | Function | Time | Calls | Code | \n" - local sz=row..col..row - if #out>0 then - sz=sz.." | "..table.concat(out," | \n | ").." | \n" - end - return "\n"..sz..row -end - -local switch=false -function profile.switch() - switch=not switch - if not switch then - profile.stop() - love.system.setClipboardText(profile.report()) - profile.reset() - return false - else - profile.start() - return true - end -end - --- store all internal profiler functions -for _,v in next,profile do - _internal[v]=type(v)=='function' -end - -return profile diff --git a/Zframework/require.lua b/Zframework/require.lua deleted file mode 100644 index d1b1afae..00000000 --- a/Zframework/require.lua +++ /dev/null @@ -1,33 +0,0 @@ -package.cpath=package.cpath..';'..SAVEDIR..'/lib/lib?.so;'..'?.dylib' -local loaded={} -return function(libName) - local require=require - if love.system.getOS()=='OS X'then - require=package.loadlib(libName..'.dylib','luaopen_'..libName) - libname=nil - elseif love.system.getOS()=='Android'then - if not loaded[libName]then - local platform=(function() - local p=io.popen('uname -m') - local arch=p:read('*a'):lower() - p:close() - if arch:find('v8')or arch:find('64')then - return'arm64-v8a' - else - return'armeabi-v7a' - end - end)() - love.filesystem.write( - 'lib/libCCloader.so', - love.filesystem.read('data','libAndroid/'..platform..'/libCCloader.so') - ) - loaded[libName]=true - end - end - local success,res=pcall(require,libName) - if success and res then - return res - else - MES.new('error',"Cannot load "..libName..": "..res) - end -end diff --git a/Zframework/scene.lua b/Zframework/scene.lua deleted file mode 100644 index e990c71b..00000000 --- a/Zframework/scene.lua +++ /dev/null @@ -1,210 +0,0 @@ -local gc=love.graphics -local abs=math.abs - -local scenes={} - -local SCN={ - mainTouchID=nil, --First touching ID(userdata) - cur='NULL', --Current scene name - swapping=false, --If Swapping - stat={ - tar=false, --Swapping target - style=false, --Swapping style - changeTime=false,--Loading point - time=false, --Full swap time - draw=false, --Swap draw func - }, - stack={},--Scene stack - prev=false, - args={},--Arguments from previous scene - - scenes=scenes, - - --Events - update=false, - draw=false, - mouseClick=false, - touchClick=false, - mouseDown=false, - mouseMove=false, - mouseUp=false, - wheelMoved=false, - touchDown=false, - touchUp=false, - touchMove=false, - keyDown=false, - keyUp=false, - gamepadDown=false, - gamepadUp=false, - fileDropped=false, - directoryDropped=false, - resize=false, - socketRead=false, -}--Scene datas, returned - -function SCN.add(name,scene) - scenes[name]=scene - if scene.widgetList then - setmetatable(scene.widgetList,WIDGET.indexMeta) - end -end - -function SCN.swapUpdate(dt) - local S=SCN.stat - S.time=S.time-dt - if S.time=S.changeTime then - --Scene swapped this frame - SCN.prev=SCN.cur - SCN.init(S.tar) - SCN.mainTouchID=nil - end - if S.time<0 then - SCN.swapping=false - end -end -function SCN.init(s) - love.keyboard.setTextInput(false) - - local S=scenes[s] - SCN.cur=s - - WIDGET.setScrollHeight(S.widgetScrollHeight) - WIDGET.setWidgetList(S.widgetList) - SCN.sceneInit=S.sceneInit - SCN.sceneBack=S.sceneBack - SCN.mouseDown=S.mouseDown - SCN.mouseMove=S.mouseMove - SCN.mouseUp=S.mouseUp - SCN.mouseClick=S.mouseClick - SCN.wheelMoved=S.wheelMoved - SCN.touchDown=S.touchDown - SCN.touchUp=S.touchUp - SCN.touchMove=S.touchMove - SCN.touchClick=S.touchClick - SCN.keyDown=S.keyDown - SCN.keyUp=S.keyUp - SCN.gamepadDown=S.gamepadDown - SCN.gamepadUp=S.gamepadUp - SCN.fileDropped=S.fileDropped - SCN.directoryDropped=S.directoryDropped - SCN.resize=S.resize - SCN.socketRead=S.socketRead - SCN.update=S.update - SCN.draw=S.draw - if S.sceneInit then - S.sceneInit() - end -end -function SCN.push(tar,style) - if not SCN.swapping then - local m=#SCN.stack - SCN.stack[m+1]=tar or SCN.cur - SCN.stack[m+2]=style or'fade' - end -end -function SCN.pop() - local s=SCN.stack - s[#s],s[#s-1]=nil -end - -local swap={ - none={ - duration=0,changeTime=0, - draw=function()end - }, - flash={ - duration=.16,changeTime=.08, - draw=function()gc.clear(1,1,1)end - }, - fade={ - duration=.5,changeTime=.25, - draw=function(t) - t=t>.25 and 2-t*4 or t*4 - gc.setColor(0,0,0,t) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - end - }, - fade_togame={ - duration=2,changeTime=.5, - draw=function(t) - t=t>.5 and(2-t)/1.5 or t*.5 - gc.setColor(0,0,0,t) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - end - }, - slowFade={ - duration=3,changeTime=1.5, - draw=function(t) - t=t>1.5 and (3-t)/1.5 or t/1.5 - gc.setColor(0,0,0,t) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - end - }, - swipeL={ - duration=.5,changeTime=.25, - draw=function(t) - t=t*2 - gc.setColor(.1,.1,.1,1-abs(t-.5)) - t=t*t*(3-2*t)*2-1 - gc.rectangle('fill',t*SCR.w,0,SCR.w,SCR.h) - end - }, - swipeR={ - duration=.5,changeTime=.25, - draw=function(t) - t=t*2 - gc.setColor(.1,.1,.1,1-abs(t-.5)) - t=t*t*(2*t-3)*2+1 - gc.rectangle('fill',t*SCR.w,0,SCR.w,SCR.h) - end - }, - swipeD={ - duration=.5,changeTime=.25, - draw=function(t) - t=t*2 - gc.setColor(.1,.1,.1,1-abs(t-.5)) - t=t*t*(2*t-3)*2+1 - gc.rectangle('fill',0,t*SCR.h,SCR.w,SCR.h) - end - }, -}--Scene swapping animations -function SCN.swapTo(tar,style,...)--Parallel scene swapping, cannot back - if scenes[tar]then - if not SCN.swapping and tar~=SCN.cur then - style=style or'fade' - SCN.swapping=true - SCN.args={...} - local S=SCN.stat - S.tar,S.style=tar,style - S.time=swap[style].duration - S.changeTime=swap[style].changeTime - S.draw=swap[style].draw - end - else - MES.new('warn',"No Scene: "..tar) - end -end -function SCN.go(tar,style,...)--Normal scene swapping, can back - if scenes[tar]then - SCN.push() - SCN.swapTo(tar,style,...) - else - MES.new('warn',"No Scene: "..tar) - end -end -function SCN.back(...) - if SCN.swapping then return end - - --Leave scene - if SCN.sceneBack then - SCN.sceneBack() - end - - --Poll&Back to previous Scene - local m=#SCN.stack - if m>0 then - SCN.swapTo(SCN.stack[m-1],SCN.stack[m],...) - SCN.stack[m],SCN.stack[m-1]=nil - end -end -return SCN diff --git a/Zframework/screen.lua b/Zframework/screen.lua deleted file mode 100644 index cf86cbd4..00000000 --- a/Zframework/screen.lua +++ /dev/null @@ -1,73 +0,0 @@ -local SCR={ - w0=1280,h0=720, --Default Screen Size - x=0,y=0, --Up-left Coord on screen - cx=0,cy=0, --Center Coord on screen (Center X/Y) - ex=0,ey=0, --Down-right Coord on screen (End X/Y) - w=0,h=0, --Fullscreen w/h for graphic functions - W=0,H=0, --Fullscreen w/h for shader - safeX=0,safeY=0,--Safe area - safeW=0,safeH=0,--Safe area - rad=0, --Radius - k=1, --Scale size - dpi=1, --DPI from gc.getDPIScale() - - --Screen transformation objects - origin=love.math.newTransform(), - xOy=love.math.newTransform(), - xOy_m=love.math.newTransform(), - xOy_ul=love.math.newTransform(), - xOy_u=love.math.newTransform(), - xOy_ur=love.math.newTransform(), - xOy_l=love.math.newTransform(), - xOy_r=love.math.newTransform(), - xOy_dl=love.math.newTransform(), - xOy_d=love.math.newTransform(), - xOy_dr=love.math.newTransform(), -} -function SCR.setSize(w,h) - SCR.w0,SCR.h0=w,h -end -function SCR.resize(w,h) - SCR.w,SCR.h,SCR.dpi=w,h,love.graphics.getDPIScale() - SCR.W,SCR.H=SCR.w*SCR.dpi,SCR.h*SCR.dpi - SCR.r=h/w - SCR.rad=(w^2+h^2)^.5 - - SCR.x,SCR.y=0,0 - if SCR.r>=SCR.h0/SCR.w0 then - SCR.k=w/SCR.w0 - SCR.y=(h-SCR.h0*SCR.k)/2 - else - SCR.k=h/SCR.h0 - SCR.x=(w-SCR.w0*SCR.k)/2 - end - SCR.cx,SCR.cy=SCR.w/2,SCR.h/2 - SCR.ex,SCR.ey=SCR.w-SCR.x,SCR.h-SCR.y - SCR.safeX,SCR.safeY,SCR.safeW,SCR.safeH=love.window.getSafeArea() - - SCR.origin:setTransformation(0,0) - SCR.xOy:setTransformation(SCR.x,SCR.y,0,SCR.k) - SCR.xOy_m:setTransformation(w/2,h/2,0,SCR.k) - SCR.xOy_ul:setTransformation(0,0,0,SCR.k) - SCR.xOy_u:setTransformation(w/2,0,0,SCR.k) - SCR.xOy_ur:setTransformation(w,0,0,SCR.k) - SCR.xOy_l:setTransformation(0,h/2,0,SCR.k) - SCR.xOy_r:setTransformation(w,h/2,0,SCR.k) - SCR.xOy_dl:setTransformation(0,h,0,SCR.k) - SCR.xOy_d:setTransformation(w/2,h,0,SCR.k) - SCR.xOy_dr:setTransformation(w,h,0,SCR.k) -end -function SCR.info() - return{ - ("w0,h0 : %d, %d"):format(SCR.w0,SCR.h0), - ("x,y : %d, %d"):format(SCR.x,SCR.y), - ("cx,cy : %d, %d"):format(SCR.cx,SCR.cy), - ("ex,ey : %d, %d"):format(SCR.ex,SCR.ey), - ("w,h : %d, %d"):format(SCR.w,SCR.h), - ("W,H : %d, %d"):format(SCR.W,SCR.H), - ("safeX,safeY : %d, %d"):format(SCR.safeX,SCR.safeY), - ("safeW,safeH : %d, %d"):format(SCR.safeW,SCR.safeH), - ("k,dpi,rad : %.2f, %d, %.2f"):format(SCR.k,SCR.dpi,SCR.rad), - } -end -return SCR diff --git a/Zframework/sfx.lua b/Zframework/sfx.lua deleted file mode 100644 index 8f5c5c20..00000000 --- a/Zframework/sfx.lua +++ /dev/null @@ -1,170 +0,0 @@ -local type,rem=type,table.remove -local int,rnd=math.floor,math.random -local interval=MATH.interval - -local sfxList={} -local packSetting={} -local Sources={} -local volume=1 -local stereo=1 - -local noteVal={ - C=1,c=1, - D=3,d=3, - E=5,e=5, - F=6,f=6, - G=8,g=8, - A=10,a=10, - B=12,b=12, -} -local noteName={'C','C#','D','D#','E','F','F#','G','G#','A','A#','B'} -local function _getTuneHeight(tune) - local octave=tonumber(tune:sub(-1,-1)) - if octave then - local tuneHeight=noteVal[tune:sub(1,1)] - if tuneHeight then - tuneHeight=tuneHeight+(octave-1)*12 - local s=tune:sub(2,2) - if s=='s'or s=='#'then - tuneHeight=tuneHeight+1 - elseif s=='f'or s=='b'then - tuneHeight=tuneHeight-1 - end - return tuneHeight - end - end -end - -local SFX={} - -function SFX.init(list) - assert(type(list)=='table',"Initialize SFX lib with a list of filenames!") - for i=1,#list do table.insert(sfxList,list[i])end -end -function SFX.load(path) - local c=0 - local missing=0 - for i=1,#sfxList do - local fullPath=path..sfxList[i]..'.ogg' - if love.filesystem.getInfo(fullPath)then - if Sources[sfxList[i]]then - for j=1,#Sources[sfxList[i]]do - Sources[sfxList[i]][j]:release() - end - end - Sources[sfxList[i]]={love.audio.newSource(fullPath,'static')} - c=c+1 - else - LOG("No SFX: "..sfxList[i]..'.ogg',.1) - missing=missing+1 - end - end - LOG(c.."/"..#sfxList.." SFX files loaded") - LOG(missing.." SFX files missing") - if missing>0 then - MES.new('info',missing.." SFX files missing") - end - collectgarbage() -end -function SFX.loadSample(pack) - assert(type(pack)=='table',"Usage: SFX.loadsample([table])") - assert(pack.name,"No field: name") - assert(pack.path,"No field: path") - local num=1 - while love.filesystem.getInfo(pack.path..'/'..num..'.ogg')do - Sources[pack.name..num]={love.audio.newSource(pack.path..'/'..num..'.ogg','static')} - num=num+1 - end - local base=(_getTuneHeight(pack.base)or 37)-1 - local top=base+num-1 - packSetting[pack.name]={base=base,top=top} - LOG((num-1).." "..pack.name.." samples loaded") -end - -function SFX.getCount() - return #sfxList -end -function SFX.setVol(v) - assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume') - volume=v -end -function SFX.setStereo(v) - assert(type(v)=='number'and v>=0 and v<=1,'Wrong stereo') - stereo=v -end - -function SFX.getNoteName(note) - if note<1 then - return'---' - else - note=note-1 - local octave=int(note/12)+1 - return noteName[note%12+1]..octave - end -end -function SFX.playSample(pack,...)--vol-1, sampSet1, vol-2, sampSet2 - if ... then - local arg={...} - local vol - for i=1,#arg do - local a=arg[i] - if type(a)=='number'and a<=1 then - vol=a - else - local base=packSetting[pack].base - local top=packSetting[pack].top - local tune=type(a)=='string'and _getTuneHeight(a)or a--Absolute tune in number - local playTune=tune+rnd(-2,2) - if playTune<=base then--Too low notes - playTune=base+1 - elseif playTune>top then--Too high notes - playTune=top - end - SFX.play(pack..playTune-base,vol,nil,tune-playTune) - end - end - end -end -local function _play(name,vol,pos,pitch) - if volume==0 or vol==0 then return end - local S=Sources[name]--Source list - if not S then return end - local n=1 - while S[n]:isPlaying()do - n=n+1 - if not S[n]then - S[n]=S[1]:clone() - S[n]:seek(0) - break - end - end - S=S[n]--AU_SRC - if S:getChannelCount()==1 then - if pos then - pos=interval(pos,-1,1)*stereo - S:setPosition(pos,1-pos^2,0) - else - S:setPosition(0,0,0) - end - end - S:setVolume(vol^1.626) - S:setPitch(pitch and 1.0594630943592953^pitch or 1) - S:play() -end -SFX.fplay=_play--Play sounds without apply module's volume setting -function SFX.play(name,vol,pos,pitch) - _play(name,(vol or 1)*volume,pos,pitch) -end -function SFX.reset() - for _,L in next,Sources do - if type(L)=='table'then - for i=#L,1,-1 do - if not L[i]:isPlaying()then - rem(L,i) - end - end - end - end -end - -return SFX diff --git a/Zframework/stringExtend.lua b/Zframework/stringExtend.lua deleted file mode 100644 index e31fff4a..00000000 --- a/Zframework/stringExtend.lua +++ /dev/null @@ -1,272 +0,0 @@ -local data=love.data -local STRING={} -local assert,tostring,tonumber=assert,tostring,tonumber -local int,format=math.floor,string.format -local find,sub,gsub=string.find,string.sub,string.gsub -local rep,upper=string.rep,string.upper -local char,byte=string.char,string.byte - ---"Replace dollars", replace all $n with ... -function STRING.repD(str,...) - local l={...} - for i=#l,1,-1 do - str=gsub(str,'$'..i,l[i]) - end - return str -end - ---"Scan arg", scan if str has the arg (format of str is like "-json -q", arg is like "-q") -function STRING.sArg(str,switch) - if find(str.." ",switch.." ")then - return true - end -end - -do--function STRING.shiftChar(c) - local shiftMap={ - ['1']='!',['2']='@',['3']='#',['4']='$',['5']='%', - ['6']='^',['7']='&',['8']='*',['9']='(',['0']=')', - ['`']='~',['-']='_',['=']='+', - ['[']='{',[']']='}',['\\']='|', - [';']=':',['\'']='"', - [',']='<',['.']='>',['/']='?', - } - function STRING.shiftChar(c) - return shiftMap[c]or upper(c) - end -end - -function STRING.trim(s) - if not s:find("%S")then return""end - s=s:sub((s:find("%S"))):reverse() - return s:sub((s:find("%S"))):reverse() -end - -function STRING.split(s,sep,regex) - local L={} - local p1,p2=1--start,target - if regex then - while p1<=#s do - p2=find(s,sep,p1)or #s+1 - L[#L+1]=sub(s,p1,p2-1) - p1=p2+#sep - end - else - while p1<=#s do - p2=find(s,sep,p1,true)or #s+1 - L[#L+1]=sub(s,p1,p2-1) - p1=p2+#sep - end - end - return L -end - -function STRING.simpEmailCheck(e) - e=STRING.split(e,"@") - if #e~=2 then return false end - if e[1]:sub(-1)=="."or e[2]:sub(-1)=="."then return false end - local e1,e2=STRING.split(e[1],"."),STRING.split(e[2],".") - if #e1*#e2==0 then return false end - for _,v in next,e1 do if #v==0 then return false end end - for _,v in next,e2 do if #v==0 then return false end end - return true -end - -function STRING.time_simp(t) - return format("%02d:%02d",int(t/60),int(t%60)) -end - -function STRING.time(t) - if t<60 then - return format("%.3f″",t) - elseif t<3600 then - return format("%d′%05.2f″",int(t/60),int(t%60*100)/100) - else - return format("%d:%.2d′%05.2f″",int(t/3600),int(t/60%60),int(t%60*100)/100) - end -end - -function STRING.UTF8(n)--Simple utf8 coding - assert(type(n)=='number',"Wrong type ("..type(n)..")") - assert(n>=0 and n<2^31,"Out of range ("..n..")") - if n<2^7 then return char(n) - elseif n<2^11 then return char(192+int(n/2^06),128+n%2^6) - elseif n<2^16 then return char(224+int(n/2^12),128+int(n/2^06)%2^6,128+n%2^6) - elseif n<2^21 then return char(240+int(n/2^18),128+int(n/2^12)%2^6,128+int(n/2^06)%2^6,128+n%2^6) - elseif n<2^26 then return char(248+int(n/2^24),128+int(n/2^18)%2^6,128+int(n/2^12)%2^6,128+int(n/2^06)%2^6,128+n%2^6) - elseif n<2^31 then return char(252+int(n/2^30),128+int(n/2^24)%2^6,128+int(n/2^18)%2^6,128+int(n/2^12)%2^6,128+int(n/2^06)%2^6,128+n%2^6) - end -end - -do--function STRING.bigInt(t) - local lg=math.log10 - local units={"","K","M","B","T","Qa","Qt","Sx","Sp","Oc","No"} - local preUnits={"","U","D","T","Qa","Qt","Sx","Sp","O","N"} - local secUnits={"Dc","Vg","Tg","Qd","Qi","Se","St","Og","Nn","Ce"}--Ce is next-level unit, but DcCe is not used so used here - for _,preU in next,preUnits do for _,secU in next,secUnits do table.insert(units,preU..secU)end end - function STRING.bigInt(t) - if t<1000 then - return tostring(t) - elseif t~=1e999 then - local e=int(lg(t)/3) - return(t/10^(e*3))..units[e+1] - else - return"INF" - end - end -end - -do--function STRING.toBin, STRING.toOct, STRING.toHex(n,len) - function STRING.toBin(n,len) - local s="" - while n>0 do - s=(n%2)..s - n=int(n/2) - end - if len then - return rep("0",len-#s)..s - else - return s - end - end - function STRING.toOct(n,len) - local s="" - while n>0 do - s=(n%8)..s - n=int(n/8) - end - if len then - return rep("0",len-#s)..s - else - return s - end - end - local b16={[0]='0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'} - function STRING.toHex(n,len) - local s="" - while n>0 do - s=b16[n%16]..s - n=int(n/16) - end - if len then - return rep("0",len-#s)..s - else - return s - end - end -end - -function STRING.hexColor(str)--[LOW PERFORMENCE] - assert(type(str)=='string') - if str:sub(1,1)=="#"then str=str:sub(2)end - assert(#str<=8) - local r=(tonumber(str:sub(1,2),16)or 0)/255 - local g=(tonumber(str:sub(3,4),16)or 0)/255 - local b=(tonumber(str:sub(5,6),16)or 0)/255 - local a=(tonumber(str:sub(7,8),16)or 255)/255 - return r,g,b,a -end - -do--function STRING.urlEncode(s) - local rshift=bit.rshift - local b16={[0]='0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'} - function STRING.urlEncode(s) - local out="" - for i=1,#s do - if s:sub(i,i):match("[a-zA-Z0-9]")then - out=out..s:sub(i,i) - else - local b=s:byte(i) - out=out.."%"..b16[rshift(b,4)]..b16[b%16] - end - end - return out - end -end - -function STRING.vcsEncrypt(text,key) - local keyLen=#key - local result="" - local buffer="" - for i=0,#text-1 do - buffer=buffer..char((byte(text,i+1)-32+byte(key,i%keyLen+1))%95+32) - if #buffer==26 then - result=result..buffer - buffer="" - end - end - return result..buffer -end -function STRING.vcsDecrypt(text,key) - local keyLen=#key - local result="" - local buffer="" - for i=0,#text-1 do - buffer=buffer..char((byte(text,i+1)-32-byte(key,i%keyLen+1))%95+32) - if #buffer==26 then - result=result..buffer - buffer="" - end - end - return result..buffer -end -function STRING.digezt(text)--Not powerful hash, just protect the original text - local out={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} - local seed=26 - for i=1,#text do - local c=byte(text,i) - seed=(seed+c)%26 - c=c+seed - local pos=c*i%16 - local step=(c+i)%4+1 - local times=2+(c%6) - for _=1,times do - out[pos+1]=(out[pos+1]+c)%256 - pos=(pos+step)%16 - end - end - local result="" - for i=1,16 do result=result..char(out[i])end - return result -end - -function STRING.readLine(str) - local p=str:find("\n") - if p then - return str:sub(1,p-1),str:sub(p+1) - else - return str,"" - end -end -function STRING.readChars(str,n) - return sub(str,1,n),sub(str,n+1) -end - -function STRING.packBin(s) - return data.encode('string','base64',data.compress('string','zlib',s)) -end -function STRING.unpackBin(str) - local res - res,str=pcall(data.decode,'string','base64',str) - if not res then return end - res,str=pcall(data.decompress,'string','zlib',str) - if res then return str end -end -function STRING.packText(s) - return data.encode('string','base64',data.compress('string','gzip',s)) -end -function STRING.unpackText(str) - local res - res,str=pcall(data.decode,'string','base64',str) - if not res then return end - res,str=pcall(data.decompress,'string','gzip',str) - if res then return str end -end -function STRING.packTable(t) - return STRING.packText(JSON.encode(t)) -end -function STRING.unpackTable(t) - return JSON.decode(STRING.unpackText(t)) -end - -return STRING diff --git a/Zframework/sysFX.lua b/Zframework/sysFX.lua deleted file mode 100644 index 07ddef2c..00000000 --- a/Zframework/sysFX.lua +++ /dev/null @@ -1,205 +0,0 @@ -local gc=love.graphics -local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth -local gc_draw,gc_line=gc.draw,gc.line -local gc_rectangle,gc_circle=gc.rectangle,gc.circle - -local max,min=math.max,math.min -local rnd=math.random -local ins,rem=table.insert,table.remove - -local fx={} - -local function _normUpdate(S,dt) - S.t=S.t+dt*S.rate - return S.t>1 -end - -local FXupdate={} -function FXupdate.badge(S,dt) - S.t=S.t+dt - if S.t<.2 then - S.x,S.y=S.x1-14,S.y1-14 - elseif S.t<.8 then - local t=((S.t-.2)*1.6667) - t=(3-2*t)*t*t - S.x,S.y=S.x1*(1-t)+S.x2*t-14,S.y1*(1-t)+S.y2*t-14 - else - S.x,S.y=S.x2-14,S.y2-14 - end - return S.t>=1 -end -FXupdate.attack=_normUpdate -FXupdate.tap=_normUpdate -FXupdate.ripple=_normUpdate -FXupdate.rectRipple=_normUpdate -FXupdate.shade=_normUpdate -function FXupdate.cell(S,dt) - if S.vx then - S.x=S.x+S.vx*S.rate - S.y=S.y+S.vy*S.rate - if S.ax then - S.vx=S.vx+S.ax*S.rate - S.vy=S.vy+S.ay*S.rate - end - end - S.t=S.t+dt*S.rate - return S.t>1 -end -FXupdate.line=_normUpdate - -local FXdraw={} -function FXdraw.badge(S) - gc_setColor(1,1,1,S.t<.2 and S.t*.6 or S.t<.8 and 1 or(1-S.t)*.6) - gc_draw(IMG.badgeIcon,S.x,S.y) -end -function FXdraw.attack(S) - gc_setColor(S.r*2,S.g*2,S.b*2,S.a*min(4-S.t*4,1)) - - gc_setLineWidth(S.wid) - local t1,t2=max(5*S.t-4,0),min(S.t*4,1) - gc_line( - S.x1*(1-t1)+S.x2*t1, - S.y1*(1-t1)+S.y2*t1, - S.x1*(1-t2)+S.x2*t2, - S.y1*(1-t2)+S.y2*t2 - ) - - gc_setLineWidth(S.wid*.6) - t1,t2=max(4*S.t-3,0),min(S.t*5,1) - gc_line( - S.x1*(1-t1)+S.x2*t1, - S.y1*(1-t1)+S.y2*t1, - S.x1*(1-t2)+S.x2*t2, - S.y1*(1-t2)+S.y2*t2 - ) -end -function FXdraw.tap(S) - local t=S.t - gc_setColor(1,1,1,(1-t)*.4) - gc_circle('fill',S.x,S.y,30*(1-t)^.5) -end -function FXdraw.ripple(S) - local t=S.t - gc_setLineWidth(2) - gc_setColor(1,1,1,1-t) - gc_circle('line',S.x,S.y,t*(2-t)*S.r) -end -function FXdraw.rectRipple(S) - gc_setLineWidth(6) - gc_setColor(1,1,1,1-S.t) - local r=(10*S.t)^1.2 - gc_rectangle('line',S.x-r,S.y-r,S.w+2*r,S.h+2*r) -end -function FXdraw.shade(S) - gc_setColor(S.r,S.g,S.b,1-S.t) - gc_rectangle('fill',S.x,S.y,S.w,S.h,2) -end -function FXdraw.cell(S) - gc_setColor(1,1,1,1-S.t) - gc_draw(S.image,S.x,S.y,nil,S.size,nil,S.cx,S.cy) -end -function FXdraw.line(S) - gc_setColor(1,1,1,S.a*(1-S.t)) - gc_line(S.x1,S.y1,S.x2,S.y2) -end - -local SYSFX={} -function SYSFX.update(dt) - for i=#fx,1,-1 do - if fx[i]:update(dt)then - rem(fx,i) - end - end -end -function SYSFX.draw() - for i=1,#fx do - fx[i]:draw() - end -end - -function SYSFX.newBadge(x1,y1,x2,y2) - ins(fx,{ - update=FXupdate.badge, - draw=FXdraw.badge, - t=0, - x=x1,y=y1, - x1=x1,y1=y1, - x2=x2,y2=y2, - }) -end -function SYSFX.newAttack(rate,x1,y1,x2,y2,wid,r,g,b,a) - ins(fx,{ - update=FXupdate.attack, - draw=FXdraw.attack, - t=0, - rate=rate, - x1=x1,y1=y1,--Start pos - x2=x2,y2=y2,--End pos - wid=wid,--Line width - r=r,g=g,b=b,a=a, - }) -end -function SYSFX.newTap(rate,x,y) - local T= - { - update=FXupdate.tap, - draw=FXdraw.tap, - t=0, - rate=rate, - x=x,y=y, - } - ins(fx,T) -end -function SYSFX.newRipple(rate,x,y,r) - ins(fx,{ - update=FXupdate.ripple, - draw=FXdraw.ripple, - t=0, - rate=rate, - x=x,y=y,r=r, - }) -end -function SYSFX.newRectRipple(rate,x,y,w,h) - ins(fx,{ - update=FXupdate.rectRipple, - draw=FXdraw.rectRipple, - t=0, - rate=rate, - x=x,y=y,w=w,h=h, - }) -end -function SYSFX.newShade(rate,x,y,w,h,r,g,b) - ins(fx,{ - update=FXupdate.shade, - draw=FXdraw.shade, - t=0, - rate=rate, - x=x,y=y,w=w,h=h, - r=r or 1,g=g or 1,b=b or 1, - }) -end -function SYSFX.newCell(rate,image,size,x,y,vx,vy,ax,ay) - ins(fx,{ - update=FXupdate.cell, - draw=FXdraw.cell, - t=0, - rate=rate*(.9+rnd()*.2), - image=image,size=size, - cx=image:getWidth()*.5,cy=image:getHeight()*.5, - x=x,y=y, - vx=vx,vy=vy, - ax=ax,ay=ay, - }) -end -function SYSFX.newLine(rate,x1,y1,x2,y2,r,g,b,a) - ins(fx,{ - update=FXupdate.line, - draw=FXdraw.line, - t=0, - rate=rate, - x1=x1 or 0,y1=y1 or 0, - x2=x2 or x1 or 1280,y2=y2 or y1 or 720, - r=r or 1,g=g or 1,b=b or 1,a=a or 1, - }) -end -return SYSFX diff --git a/Zframework/tableExtend.lua b/Zframework/tableExtend.lua deleted file mode 100644 index d8ec7a4d..00000000 --- a/Zframework/tableExtend.lua +++ /dev/null @@ -1,271 +0,0 @@ -local rnd=math.random -local find=string.find -local rem=table.remove -local next,type=next,type -local TABLE={} - ---Get a new filled table -function TABLE.new(val,count) - local L={} - for i=1,count do - L[i]=val - end - return L -end - ---Get a copy of [1~#] elements -function TABLE.shift(org,depth) - if not depth then depth=1e99 end - local L={} - for i=1,#org do - if type(org[i])=='table'and depth>0 then - L[i]=TABLE.shift(org[i],depth-1) - else - L[i]=org[i] - end - end - return L -end - ---Get a full copy of a table, depth = how many layers will be recreate, default to inf -function TABLE.copy(org,depth) - if not depth then depth=1e99 end - local L={} - for k,v in next,org do - if type(v)=='table'and depth>0 then - L[k]=TABLE.copy(v,depth-1) - else - L[k]=v - end - end - return L -end - ---For all things in new, push to old -function TABLE.cover(new,old) - for k,v in next,new do - old[k]=v - end -end - ---For all things in new, push to old -function TABLE.coverR(new,old) - for k,v in next,new do - if type(v)=='table'and type(old[k])=='table'then - TABLE.coverR(v,old[k]) - else - old[k]=v - end - end -end - ---For all things in new if same type in old, push to old -function TABLE.update(new,old) - for k,v in next,new do - if type(v)==type(old[k])then - if type(v)=='table'then - TABLE.update(v,old[k]) - else - old[k]=v - end - end - end -end - ---For all things in new if no val in old, push to old -function TABLE.complete(new,old) - for k,v in next,new do - if type(v)=='table'then - if old[k]==nil then old[k]={}end - TABLE.complete(v,old[k]) - elseif old[k]==nil then - old[k]=v - end - end -end - --------------------------- - ---Pop & return random [1~#] of table -function TABLE.popRandom(t) - local l=#t - if l>0 then - local r=rnd(l) - r,t[r]=t[r],t[l] - t[l]=nil - return r - end -end - ---Remove [1~#] of table -function TABLE.cut(G) - for i=1,#G do - G[i]=nil - end -end - ---Clear table -function TABLE.clear(G) - for k in next,G do - G[k]=nil - end -end - --------------------------- - ---Remove duplicated value of [1~#] -function TABLE.trimDuplicate(org) - local cache={} - for i=1,#org,-1 do - if cache[org[i]]then - rem(org,i) - else - cache[org[i]]=true - end - end -end - ---Discard duplicated value -function TABLE.remDuplicate(org) - local cache={} - for k,v in next,org do - if cache[v]then - org[k]=nil - else - cache[v]=true - end - end -end - --------------------------- - ---Reverse [1~#] -function TABLE.reverse(org) - local l=#org - for i=1,math.floor(l/2)do - org[i],org[l+1-i]=org[l+1-i],org[i] - end -end - --------------------------- - ---Find value in [1~#] -function TABLE.find(t,val) - for i=1,#t do if t[i]==val then return i end end -end - ---Return next value of [1~#] (by value) -function TABLE.next(t,val) - for i=1,#t do if t[i]==val then return t[i%#t+1]end end -end - --------------------------- - ---Find value in whole table -function TABLE.search(t,val) - for k,v in next,t do if v==val then return k end end -end - ---Re-index string value of a table -function TABLE.reIndex(org) - for k,v in next,org do - if type(v)=='string'then - org[k]=org[v] - end - end -end - --------------------------- - ---Dump a simple lua table -do--function TABLE.dump(L,t) - local tabs={ - [0]="", - "\t", - "\t\t", - "\t\t\t", - "\t\t\t\t", - "\t\t\t\t\t", - } - local function dump(L,t) - local s - if t then - s="{\n" - else - s="return{\n" - t=1 - if type(L)~='table'then - return - end - end - local count=1 - for k,v in next,L do - local T=type(k) - if T=='number'then - if k==count then - k="" - count=count+1 - else - k="["..k.."]=" - end - elseif T=='string'then - if find(k,"[^0-9a-zA-Z_]")then - k="[\""..k.."\"]=" - else - k=k.."=" - end - elseif T=='boolean'then k="["..k.."]=" - else error("Error key type!") - end - T=type(v) - if T=='number'then v=tostring(v) - elseif T=='string'then v="\""..v.."\"" - elseif T=='table'then v=dump(v,t+1) - elseif T=='boolean'then v=tostring(v) - else error("Error data type!") - end - s=s..tabs[t]..k..v..",\n" - end - return s..tabs[t-1].."}" - end - TABLE.dump=dump -end - ---Dump a simple lua table (no whitespaces) -do--function TABLE.dumpDeflate(L,t) - local function dump(L) - local s="return{" - if type(L)~='table'then return end - local count=1 - for k,v in next,L do - local T=type(k) - if T=='number'then - if k==count then - k="" - count=count+1 - else - k="["..k.."]=" - end - elseif T=='string'then - if find(k,"[^0-9a-zA-Z_]")then - k="[\""..k.."\"]=" - else - k=k.."=" - end - elseif T=='boolean'then k="["..k.."]=" - else error("Error key type!") - end - T=type(v) - if T=='number'then v=tostring(v) - elseif T=='string'then v="\""..v.."\"" - elseif T=='table'then v=dump(v) - elseif T=='boolean'then v=tostring(v) - else error("Error data type!") - end - end - return s.."}" - end - TABLE.dumpDeflate=dump -end - -return TABLE diff --git a/Zframework/task.lua b/Zframework/task.lua deleted file mode 100644 index 6de25226..00000000 --- a/Zframework/task.lua +++ /dev/null @@ -1,56 +0,0 @@ -local rem=table.remove -local assert,resume,status=assert,coroutine.resume,coroutine.status -local tasks={} - -local TASK={} -function TASK.getCount() - return #tasks -end -local trigFrame=0 -function TASK.update(dt) - trigFrame=trigFrame+dt*60 - while trigFrame>=1 do - for i=#tasks,1,-1 do - local T=tasks[i] - if status(T.thread)=='dead'then - rem(tasks,i) - else - assert(resume(T.thread)) - end - end - trigFrame=trigFrame-1 - end -end -function TASK.new(code,...) - local thread=coroutine.create(code) - assert(resume(thread,...)) - if status(thread)~='dead'then - tasks[#tasks+1]={ - thread=thread, - code=code, - args={...}, - } - end -end -function TASK.removeTask_code(code) - for i=#tasks,1,-1 do - if tasks[i].code==code then - rem(tasks,i) - end - end -end -function TASK.removeTask_iterate(func,...) - for i=#tasks,1,-1 do - if func(tasks[i],...)then - rem(tasks,i) - end - end -end -function TASK.clear() - local i=#tasks - while i>0 do - tasks[i]=nil - i=i-1 - end -end -return TASK diff --git a/Zframework/test.lua b/Zframework/test.lua deleted file mode 100644 index 46be780c..00000000 --- a/Zframework/test.lua +++ /dev/null @@ -1,12 +0,0 @@ -local TEST={} - ---Wait for the scene swapping animation to finish -function TEST.yieldUntilNextScene() - while SCN.swapping do YIELD()end -end - -function TEST.yieldN(frames) - for _=1,frames do YIELD()end -end - -return TEST diff --git a/Zframework/text.lua b/Zframework/text.lua deleted file mode 100644 index ddc464e5..00000000 --- a/Zframework/text.lua +++ /dev/null @@ -1,153 +0,0 @@ -local gc=love.graphics -local getColor,setColor=gc.getColor,gc.setColor - -local int,rnd=math.floor,math.random -local ins,rem=table.insert,table.remove -local draw=gc.draw - -local texts={} - -local textFX={} -function textFX.appear(t) - draw( - t.text,t.x,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.sudden(t) - setColor(1,1,1,1-t.c) - draw( - t.text,t.x,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.fly(t) - draw( - t.text,t.x+(t.c-.5)^3*300,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.stretch(t) - draw( - t.text,t.x,t.y, - nil, - t.c<.3 and(.3-t.c)*1.6+1 or 1,1, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.drive(t) - draw( - t.text,t.x,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5, - t.c<.3 and(.3-t.c)*2 or 0,0 - ) -end -function textFX.spin(t) - draw( - t.text,t.x,t.y, - t.c<.3 and(.3-t.c)^2*4 or t.c<.8 and 0 or(t.c-.8)^2*-4, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.flicker(t) - local _,_,_,T=getColor() - setColor(1,1,1,T*(rnd()+.5)) - draw( - t.text,t.x,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.zoomout(t) - draw( - t.text,t.x,t.y, - nil, - t.c^.5*.1+1,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.beat(t) - local k=t.c<.3 and 1.3-t.c^2/.3 or 1 - draw( - t.text,t.x,t.y, - nil, - k,k, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.score(t) - local _,_,_,T=getColor() - setColor(1,1,1,T*.5) - draw( - t.text,t.x,t.y-0-t.c^.2*50, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end - -local TEXT={} -function TEXT.clear() - texts={} -end -function TEXT.show(text,x,y,font,style,spd,stop) - ins(texts,{ - c=0, --Timer - text=gc.newText(FONT.get(int(font/5)*5 or 40),text), --String - x=x or 0, --X - y=y or 0, --Y - spd=(spd or 1), --Timing speed(1=last 1 sec) - stop=stop, --Stop time(sustained text) - draw=assert(textFX[style or'appear'],"no text type:"..style),--Draw method - }) -end -function TEXT.getText(text,x,y,font,style,spd,stop)--Another version of TEXT.show(), but only return text object, need manual management - return{ - c=0, - text=gc.newText(FONT.get(int(font/5)*5 or 40),text), - x=x or 0, - y=y or 0, - spd=(spd or 1), - stop=stop, - draw=textFX[style or'appear']or error("unavailable type:"..style), - } -end -function TEXT.update(dt,list) - if not list then - list=texts - end - for i=#list,1,-1 do - local t=list[i] - t.c=t.c+t.spd*dt - if t.stop then - if t.c>t.stop then - t.c=t.stop - end - end - if t.c>1 then - rem(list,i) - end - end -end -function TEXT.draw(list) - if not list then - list=texts - end - for i=1,#list do - local t=list[i] - local p=t.c - setColor(1,1,1,p<.2 and p*5 or p<.8 and 1 or 5-p*5) - t:draw() - end -end -return TEXT diff --git a/Zframework/vibrate.lua b/Zframework/vibrate.lua deleted file mode 100644 index 9443b01b..00000000 --- a/Zframework/vibrate.lua +++ /dev/null @@ -1,12 +0,0 @@ -local level={0,0,.01,.016,.023,.03,.04,.05,.06,.07,.08,.09,.12,.15} -local vib=love.system.vibrate -return love.system.getOS()=='iOS'and - function(t) - t=level[t] - if t then vib(t<=.03 and 1 or t<=.09 and 2 or 3)end - end -or - function(t) - t=level[t] - if t then vib(t)end - end \ No newline at end of file diff --git a/Zframework/voice.lua b/Zframework/voice.lua deleted file mode 100644 index 4963bc3d..00000000 --- a/Zframework/voice.lua +++ /dev/null @@ -1,132 +0,0 @@ -local rnd=math.random -local volume=1 -local diversion=0 -local VOC={ - getCount=function()return 0 end, - getQueueCount=function()return 0 end, - load=function()error("Cannot load before init!")end, - getFreeChannel=NULL, - play=NULL, - update=NULL, -} -function VOC.setDiversion(n) - assert(type(n)=='number'and n>0 and n<12,'Wrong div') - diversion=n -end -function VOC.setVol(v) - assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume') - volume=v -end -function VOC.init(list) - VOC.init=nil - local rem=table.remove - local voiceQueue={free=0} - local bank={}--{vocName1={SRC1s},vocName2={SRC2s},...} - local Source={} - - local count=#list function VOC.getCount()return count end - local function _loadVoiceFile(path,N,vocName) - local fullPath=path..vocName..'.ogg' - if love.filesystem.getInfo(fullPath)then - bank[vocName]={love.audio.newSource(fullPath,'stream')} - table.insert(Source[N],vocName) - return true - end - end - --Load voice with string - local function _getVoice(str) - local L=bank[str] - local n=1 - while L[n]:isPlaying()do - n=n+1 - if not L[n]then - L[n]=L[1]:clone() - L[n]:seek(0) - break - end - end - return L[n] - end - function VOC.load(path) - for i=1,count do - Source[list[i]]={} - - local n=0 - repeat n=n+1 until not _loadVoiceFile(path,list[i],list[i]..'_'..n) - - if n==1 then - if not _loadVoiceFile(path,list[i],list[i])then - LOG("No VOC: "..list[i],.1) - end - end - if not Source[list[i]][1]then - Source[list[i]]=nil - end - end - - function VOC.getQueueCount() - return #voiceQueue - end - function VOC.getFreeChannel() - local l=#voiceQueue - for i=1,l do - if #voiceQueue[i]==0 then return i end - end - voiceQueue[l+1]={s=0} - return l+1 - end - - function VOC.play(s,chn) - if volume>0 then - local _=Source[s] - if not _ then return end - if chn then - local L=voiceQueue[chn] - L[#L+1]=_[rnd(#_)] - L.s=1 - --Add to queue[chn] - else - voiceQueue[VOC.getFreeChannel()]={s=1,_[rnd(#_)]} - --Create new channel & play - end - end - end - function VOC.update() - for i=#voiceQueue,1,-1 do - local Q=voiceQueue[i] - if Q.s==0 then--Free channel, auto delete when >3 - if i>3 then - rem(voiceQueue,i) - end - elseif Q.s==1 then--Waiting load source - Q[1]=_getVoice(Q[1]) - Q[1]:setVolume(volume) - Q[1]:setPitch(1.0594630943592953^(diversion*(rnd()*2-1))) - Q[1]:play() - Q.s=Q[2]and 2 or 4 - elseif Q.s==2 then--Playing 1,ready 2 - if Q[1]:getDuration()-Q[1]:tell()<.08 then - Q[2]=_getVoice(Q[2]) - Q[2]:setVolume(volume) - Q[1]:setPitch(1.0594630943592953^(diversion*(rnd()*2-1))) - Q[2]:play() - Q.s=3 - end - elseif Q.s==3 then--Playing 12 same time - if not Q[1]:isPlaying()then - for j=1,#Q do - Q[j]=Q[j+1] - end - Q.s=Q[2]and 2 or 4 - end - elseif Q.s==4 then--Playing last - if not Q[1].isPlaying(Q[1])then - Q[1]=nil - Q.s=0 - end - end - end - end - end -end -return VOC diff --git a/Zframework/websocket.lua b/Zframework/websocket.lua deleted file mode 100644 index fca1e70c..00000000 --- a/Zframework/websocket.lua +++ /dev/null @@ -1,191 +0,0 @@ -local host= - -- '127.0.0.1' - -- '192.168.114.102' - 'game.techmino.org' -local port='10026' -local path='/tech/socket/v1' - --- lua + LÖVE threading websocket client --- Original pure lua ver. by flaribbit and Particle_G --- Threading version by MrZ - -local type=type -local timer=love.timer.getTime -local CHN=love.thread.newChannel() -local CHN_getCount,CHN_push,CHN_pop=CHN.getCount,CHN.push,CHN.pop -local TRD=love.thread.newThread("\n") -local TRD_isRunning=TRD.isRunning - -local WS={} -local wsList=setmetatable({},{ - __index=function(l,k) - local ws={ - real=false, - status='dead', - lastPongTime=timer(), - sendTimer=0, - alertTimer=0, - pongTimer=0, - } - l[k]=ws - return ws - end -}) - -function WS.switchHost(_1,_2,_3) - for k in next,wsList do - WS.close(k) - end - host=_1 - port=_2 or port - path=_3 or path -end - -function WS.connect(name,subPath,body,timeout) - if wsList[name]and wsList[name].thread then - wsList[name].thread:release() - end - local ws={ - real=true, - thread=love.thread.newThread('Zframework/websocket_thread.lua'), - triggerCHN=love.thread.newChannel(), - sendCHN=love.thread.newChannel(), - readCHN=love.thread.newChannel(), - lastPingTime=0, - lastPongTime=timer(), - pingInterval=6, - status='connecting',--'connecting', 'running', 'dead' - sendTimer=0, - alertTimer=0, - pongTimer=0, - } - wsList[name]=ws - ws.thread:start(ws.triggerCHN,ws.sendCHN,ws.readCHN) - CHN_push(ws.sendCHN,host) - CHN_push(ws.sendCHN,port) - CHN_push(ws.sendCHN,path..subPath) - CHN_push(ws.sendCHN,body or"") - CHN_push(ws.sendCHN,timeout or 2.6) -end - -function WS.status(name) - local ws=wsList[name] - return ws.status or'dead' -end - -function WS.getTimers(name) - local ws=wsList[name] - return ws.pongTimer,ws.sendTimer,ws.alertTimer -end - -function WS.setPingInterval(name,time) - local ws=wsList[name] - ws.pingInterval=math.max(time or 2.6,2.6) -end - -function WS.alert(name) - local ws=wsList[name] - ws.alertTimer=2.6 -end - -local OPcode={ - continue=0, - text=1, - binary=2, - close=8, - ping=9, - pong=10, -} -local OPname={ - [0]='continue', - [1]='text', - [2]='binary', - [8]='close', - [9]='ping', - [10]='pong', -} -function WS.send(name,message,op) - if type(message)=='string'then - local ws=wsList[name] - if ws.real and ws.status=='running'then - CHN_push(ws.sendCHN,op and OPcode[op]or 2)--2=binary - CHN_push(ws.sendCHN,message) - ws.lastPingTime=timer() - ws.sendTimer=1 - end - else - MES.new('error',"Attempt to send non-string value!") - MES.traceback() - end -end - -function WS.read(name) - local ws=wsList[name] - if ws.real and ws.status~='connecting'and CHN_getCount(ws.readCHN)>=2 then - local op,message=CHN_pop(ws.readCHN),CHN_pop(ws.readCHN) - if op==8 then--8=close - ws.status='dead' - elseif op==9 then--9=ping - WS.send(name,message or"",'pong') - end - ws.lastPongTime=timer() - ws.pongTimer=1 - return message,OPname[op]or op - end -end - -function WS.close(name) - local ws=wsList[name] - if ws.real then - CHN_push(ws.sendCHN,8)--close - CHN_push(ws.sendCHN,"") - ws.status='dead' - end -end - -function WS.update(dt) - local time=timer() - for name,ws in next,wsList do - if ws.real and ws.status~='dead'then - if TRD_isRunning(ws.thread)then - if CHN_getCount(ws.triggerCHN)==0 then - CHN_push(ws.triggerCHN,0) - end - if ws.status=='connecting'then - local mes=CHN_pop(ws.readCHN) - if mes then - if mes=='success'then - ws.status='running' - ws.lastPingTime=time - ws.lastPongTime=time - ws.pongTimer=1 - else - ws.status='dead' - MES.new('warn',text.wsFailed..": "..(mes=="timeout"and text.netTimeout or mes)) - end - end - elseif ws.status=='running'then - if time-ws.lastPingTime>ws.pingInterval then - WS.send(name,"",'pong') - end - if time-ws.lastPongTime>6+2*ws.pingInterval then - WS.close(name) - end - end - if ws.sendTimer>0 then ws.sendTimer=ws.sendTimer-dt end - if ws.pongTimer>0 then ws.pongTimer=ws.pongTimer-dt end - if ws.alertTimer>0 then ws.alertTimer=ws.alertTimer-dt end - else - ws.status='dead' - local err=ws.thread:getError() - if err then - err=err:sub((err:find(":",(err:find(":")or 0)+1)or 0)+1,(err:find("\n")or 0)-1) - MES.new('warn',text.wsClose..err) - WS.alert(name) - end - end - end - end -end - -return WS diff --git a/Zframework/websocket_thread.lua b/Zframework/websocket_thread.lua deleted file mode 100644 index db4dc548..00000000 --- a/Zframework/websocket_thread.lua +++ /dev/null @@ -1,191 +0,0 @@ -local triggerCHN,sendCHN,readCHN=... - -local CHN_demand,CHN_getCount=triggerCHN.demand,triggerCHN.getCount -local CHN_push,CHN_pop=triggerCHN.push,triggerCHN.pop - -local SOCK=require'socket'.tcp() -local JSON=require'Zframework.json' - -do--Connect - local host=CHN_demand(sendCHN) - local port=CHN_demand(sendCHN) - local path=CHN_demand(sendCHN) - local body=CHN_demand(sendCHN) - local timeout=CHN_demand(sendCHN) - - SOCK:settimeout(timeout) - local res,err=SOCK:connect(host,port) - assert(res,err) - - --WebSocket handshake - if not body then body=''end - SOCK:send( - 'GET '..path..' HTTP/1.1\r\n'.. - 'Host: '..host..':'..port..'\r\n'.. - 'Connection: Upgrade\r\n'.. - 'Upgrade: websocket\r\n'.. - 'Content-Type: application/json\r\n'.. - 'Content-Length: '..#body..'\r\n'.. - 'Sec-WebSocket-Version: 13\r\n'.. - 'Sec-WebSocket-Key: osT3F7mvlojIvf3/8uIsJQ==\r\n\r\n'..--secKey - body - ) - - --First line of HTTP - res,err=SOCK:receive('*l') - assert(res,err) - local code,ctLen - code=res:find(' ') - code=res:sub(code+1,code+3) - - --Get body length from headers and remove headers - repeat - res,err=SOCK:receive('*l') - assert(res,err) - if not ctLen and res:find('length')then - ctLen=tonumber(res:match('%d+')) - end - until res=='' - - --Result - if ctLen then - if code=='101'then - CHN_push(readCHN,'success') - else - res,err=SOCK:receive(ctLen) - res=JSON.decode(assert(res,err)) - error((code or"XXX")..":"..(res and res.reason or"Server Error")) - end - end - SOCK:settimeout(0) -end - -local YIELD=coroutine.yield -local byte,char=string.byte,string.char -local band,bor,bxor=bit.band,bit.bor,bit.bxor -local shl,shr=bit.lshift,bit.rshift - -local mask_key={1,14,5,14} -local mask_str=char(unpack(mask_key)) -local function _send(op,message) - --Message type - SOCK:send(char(bor(op,0x80))) - - if message then - --Length - local length=#message - if length>65535 then - SOCK:send(char(bor(127,0x80),0,0,0,0,band(shr(length,24),0xff),band(shr(length,16),0xff),band(shr(length,8),0xff),band(length,0xff))) - elseif length>125 then - SOCK:send(char(bor(126,0x80),band(shr(length,8),0xff),band(length,0xff))) - else - SOCK:send(char(bor(length,0x80))) - end - local msgbyte={byte(message,1,length)} - for i=1,length do - msgbyte[i]=bxor(msgbyte[i],mask_key[(i-1)%4+1]) - end - return SOCK:send(mask_str..char(unpack(msgbyte))) - else - SOCK:send('\128'..mask_str) - return 0 - end -end -local sendThread=coroutine.wrap(function() - while true do - while CHN_getCount(sendCHN)>=2 do - _send(CHN_pop(sendCHN),CHN_pop(sendCHN)) - end - YIELD() - end -end) - -local function _receive(sock,len) - local buffer="" - while true do - local r,e,p=sock:receive(len) - if r then - buffer=buffer..r - len=len-#r - elseif p then - buffer=buffer..p - len=len-#p - elseif e then - return nil,e - end - if len==0 then - return buffer - end - YIELD() - end -end -local readThread=coroutine.wrap(function() - local res,err - local op,fin - local lBuffer=""--Long multi-pack buffer - while true do - --Byte 0-1 - res,err=_receive(SOCK,2) - assert(res,err) - - op=band(byte(res,1),0x0f) - fin=band(byte(res,1),0x80)==0x80 - - --Calculating data length - local length=band(byte(res,2),0x7f) - if length==126 then - res,err=_receive(SOCK,2) - assert(res,err) - length=shl(byte(res,1),8)+byte(res,2) - elseif length==127 then - local lenData - lenData,err=_receive(SOCK,8) - assert(res,err) - local _,_,_,_,_5,_6,_7,_8=byte(lenData,1,8) - length=shl(_5,24)+shl(_6,16)+shl(_7,8)+_8 - end - res,err=_receive(SOCK,length) - assert(res,err) - - --React - if op==8 then--8=close - CHN_push(readCHN,8)--close - if type(res)=='string'then - CHN_push(readCHN,res:sub(3))--[Warning] 2 bytes close code at start so :sub(3) - else - CHN_push(readCHN,"WS closed") - end - return - elseif op==0 then--0=continue - lBuffer=lBuffer..res - if fin then - CHN_push(readCHN,lBuffer) - lBuffer="" - end - else - CHN_push(readCHN,op) - if fin then - CHN_push(readCHN,res) - lBuffer="" - else - lBuffer=res - end - end - YIELD() - end -end) - -local success,err - -while true do--Running - CHN_demand(triggerCHN) - success,err=pcall(sendThread) - if not success or err then break end - success,err=pcall(readThread) - if not success or err then break end -end - -SOCK:close() -CHN_push(readCHN,8)--close -CHN_push(readCHN,err or"Disconnected") -error() diff --git a/Zframework/wheelScroll.lua b/Zframework/wheelScroll.lua deleted file mode 100644 index 5e6024e8..00000000 --- a/Zframework/wheelScroll.lua +++ /dev/null @@ -1,19 +0,0 @@ -local love=love -local max,min=math.max,math.min -local trigDist=0 -return function(y,key1,key2) - if y>0 then - trigDist=max(trigDist,0)+y^1.2 - elseif y<0 then - if trigDist>0 then trigDist=0 end - trigDist=min(trigDist,0)-(-y)^1.2 - end - while trigDist>=1 do - love.keypressed(key1 or'up') - trigDist=trigDist-1 - end - while trigDist<=-1 do - love.keypressed(key2 or'down') - trigDist=trigDist+1 - end -end diff --git a/Zframework/widget.lua b/Zframework/widget.lua deleted file mode 100644 index a22b5d25..00000000 --- a/Zframework/widget.lua +++ /dev/null @@ -1,1499 +0,0 @@ -local gc=love.graphics -local gc_origin=gc.origin -local gc_translate,gc_replaceTransform=gc.translate,gc.replaceTransform -local gc_stencil,gc_setStencilTest=gc.stencil,gc.setStencilTest -local gc_push,gc_pop=gc.push,gc.pop -local gc_setCanvas,gc_setBlendMode=gc.setCanvas,gc.setBlendMode -local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth -local gc_draw,gc_line=gc.draw,gc.line -local gc_rectangle=gc.rectangle -local gc_print,gc_printf=gc.print,gc.printf - -local kb=love.keyboard -local timer=love.timer.getTime - -local next=next -local int,ceil=math.floor,math.ceil -local max,min=math.max,math.min -local sub,ins,rem=string.sub,table.insert,table.remove -local xOy=SCR.xOy -local FONT=FONT -local mStr=GC.mStr -local approach=MATH.expApproach - -local downArrowIcon=GC.DO{40,25,{'fPoly',0,0,20,25,40,0}} -local upArrowIcon=GC.DO{40,25,{'fPoly',0,25,20,0,40,25}} -local clearIcon=GC.DO{40,40, - {'fRect',16,5,8,3}, - {'fRect',8,8,24,3}, - {'fRect',11,14,18,21}, -} -local sureIcon=GC.DO{40,40, - {'rawFT',35}, - {'mText',"?",20,0}, -} -local smallerThen=GC.DO{20,20, - {'setLW',5}, - {'line',18,2,1,10,18,18}, -} -local largerThen=GC.DO{20,20, - {'setLW',5}, - {'line',2,2,19,10,2,18}, -} - -local STW,STH--stencil-wid/hei -local function _rectangleStencil() - gc.rectangle('fill',1,1,STW-2,STH-2) -end - -local onChange=NULL - -local WIDGET={} - -function WIDGET.setOnChange(func)onChange=assert(type(func)=='function'and func,"WIDGET.setOnChange(func): func must be a function")end - -local widgetMetatable={ - __tostring=function(self) - return self:getInfo() - end, -} - -local text={ - type='text', - mustHaveText=true, - alpha=0, -} - -function text:reset()end -function text:update(dt) - if self.hideF and self.hideF()then - if self.alpha>0 then - self.alpha=max(self.alpha-dt*7.5,0) - end - elseif self.alpha<1 then - self.alpha=min(self.alpha+dt*7.5,1) - end -end -function text:draw() - if self.alpha>0 then - local c=self.color - gc_setColor(c[1],c[2],c[3],self.alpha) - local w=self.obj:getWidth() - local k=min(self.lim/self.obj:getWidth(),1) - if self.align=='M'then - gc_draw(self.obj,self.x,self.y,nil,k,1,w*.5,0) - elseif self.align=='L'then - gc_draw(self.obj,self.x,self.y,nil,k,1) - elseif self.align=='R'then - gc_draw(self.obj,self.x,self.y,nil,k,1,w,0) - end - end -end -function WIDGET.newText(D)--name,x,y[,lim][,fText][,color][,font=30][,fType][,align='M'][,hideF][,hide] - local _={ - name= D.name or"_", - x= D.x, - y= D.y, - lim= D.lim or 1e99, - - fText=D.fText, - color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, - font= D.font or 30, - fType=D.fType, - align=D.align or'M', - hideF=D.hideF, - } - for k,v in next,text do _[k]=v end - if not _.hideF then _.alpha=1 end - setmetatable(_,widgetMetatable) - return _ -end - -local image={ - type='image', -} -function image:reset() - if type(self.img)=='string'then - self.img=IMG[self.img] - end -end -function image:draw() - gc_setColor(1,1,1,self.alpha) - gc_draw(self.img,self.x,self.y,self.ang,self.k) -end -function WIDGET.newImage(D)--name[,img(name)],x,y[,ang][,k][,hideF][,hide] - local _={ - name= D.name or"_", - img= D.img or D.name or"_", - alpha=D.alpha, - x= D.x, - y= D.y, - ang= D.ang, - k= D.k, - hideF=D.hideF, - hide= D.hide, - } - for k,v in next,image do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local button={ - type='button', - mustHaveText=true, - ATV=0,--Activating time(0~8) -} -function button:reset() - self.ATV=0 -end -function button:setObject(obj) - if type(obj)=='string'or type(obj)=='number'then - self.obj=gc.newText(FONT.get(self.font,self.fType),obj) - elseif obj then - self.obj=obj - end -end -function button:isAbove(x,y) - local ATV=self.ATV - return - x>self.x-ATV and - y>self.y and - x0 then self.ATV=max(ATV-dt*30,0)end - end -end -function button:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local ATV=self.ATV - local c=self.color - local r,g,b=c[1],c[2],c[3] - - --Button - gc_setColor(.15+r*.7,.15+g*.7,.15+b*.7,.9) - gc_rectangle('fill',x-ATV,y,w+2*ATV,h,4) - gc_setLineWidth(2) - gc_setColor(.3+r*.7,.3+g*.7,.3+b*.7) - gc_rectangle('line',x-ATV,y,w+2*ATV,h,5) - if ATV>0 then - gc_setColor(.97,.97,.97,ATV*.125) - gc_rectangle('line',x-ATV,y,w+2*ATV,h,3) - end - - --Drawable - local obj=self.obj - local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5 - local y0=y+h*.5 - gc_setColor(1,1,1,.2+ATV*.05) - if self.align=='M'then - local x0=x+w*.5 - local kx=obj:type()=='Text'and min(w/ox/2,1)or 1 - gc_draw(obj,x0-1,y0-1,nil,kx,1,ox,oy) - gc_draw(obj,x0-1,y0+1,nil,kx,1,ox,oy) - gc_draw(obj,x0+1,y0-1,nil,kx,1,ox,oy) - gc_draw(obj,x0+1,y0+1,nil,kx,1,ox,oy) - gc_setColor(r*.55,g*.55,b*.55) - gc_draw(obj,x0,y0,nil,kx,1,ox,oy) - elseif self.align=='L'then - local edge=self.edge - gc_draw(obj,x+edge-1,y0-1-oy) - gc_draw(obj,x+edge-1,y0+1-oy) - gc_draw(obj,x+edge+1,y0-1-oy) - gc_draw(obj,x+edge+1,y0+1-oy) - gc_setColor(r*.55,g*.55,b*.55) - gc_draw(obj,x+edge,y0-oy) - elseif self.align=='R'then - local x0=x+w-self.edge-ox*2 - gc_draw(obj,x0-1,y0-1-oy) - gc_draw(obj,x0-1,y0+1-oy) - gc_draw(obj,x0+1,y0-1-oy) - gc_draw(obj,x0+1,y0+1-oy) - gc_setColor(r*.55,g*.55,b*.55) - gc_draw(obj,x0,y0-oy) - end -end -function button:getInfo() - return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font,self.fType) -end -function button:press(_,_,k) - self.code(k) - local ATV=self.ATV - SYSFX.newRectRipple( - 6, - self.x-ATV, - self.y-WIDGET.scrollPos, - self.w+2*ATV, - self.h - ) - if self.sound then - SFX.play(self.sound) - end -end -function WIDGET.newButton(D)--name,x,y,w[,h][,fText][,color][,font=30][,fType][,sound][,align='M'][,edge=0][,code][,hideF][,hide] - if not D.h then D.h=D.w end - local _={ - name= D.name or"_", - - x= D.x-D.w*.5, - y= D.y-D.h*.5, - w= D.w, - h= D.h, - - resCtr={ - D.x,D.y, - D.x-D.w*.35,D.y-D.h*.35, - D.x-D.w*.35,D.y+D.h*.35, - D.x+D.w*.35,D.y-D.h*.35, - D.x+D.w*.35,D.y+D.h*.35, - }, - - fText=D.fText, - color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, - font= D.font or 30, - fType=D.fType, - align=D.align or'M', - edge= D.edge or 0, - code= D.code or NULL, - hideF=D.hideF, - hide= D.hide, - } - if D.sound==false then - _.sound=false - elseif type(D.sound)=='string'then - _.sound=D.sound - else - _.sound='button' - end - - for k,v in next,button do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local key={ - type='key', - mustHaveText=true, - ATV=0,--Activating time(0~4) -} -function key:reset() - self.ATV=0 -end -function key:setObject(obj) - if type(obj)=='string'or type(obj)=='number'then - self.obj=gc.newText(FONT.get(self.font,self.fType),obj) - elseif obj then - self.obj=obj - end -end -function key:isAbove(x,y) - return - x>self.x and - y>self.y and - x0 then self.ATV=max(ATV-dt*30,0)end - end -end -function key:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local ATV=self.ATV - local c=self.color - local align=self.align - local r,g,b=c[1],c[2],c[3] - - --Fill - if self.fShade then - gc_setColor(r,g,b,ATV*.25) - if align=='M'then - gc_draw(self.fShade,x+w*.5-self.fShade:getWidth()*.5,y+h*.5-self.fShade:getHeight()*.5) - elseif align=='L'then - gc_draw(self.fShade,x+self.edge,y+h*.5-self.fShade:getHeight()*.5) - elseif align=='R'then - gc_draw(self.fShade,x+w-self.edge-self.fShade:getWidth(),y+h*.5-self.fShade:getHeight()*.5) - end - else - --Background - gc_setColor(0,0,0,.3) - gc_rectangle('fill',x,y,w,h,4) - - --Frame - gc_setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7) - gc_setLineWidth(2) - gc_rectangle('line',x,y,w,h,3) - - --Shade - gc_setColor(1,1,1,ATV*.05) - gc_rectangle('fill',x,y,w,h,3) - end - - --Drawable - local obj=self.obj - local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5 - gc_setColor(r,g,b) - if align=='M'then - local kx=obj:type()=='Text'and min(w/ox/2,1)or 1 - gc_draw(obj,x+w*.5,y+h*.5,nil,kx,1,ox,oy) - elseif align=='L'then - gc_draw(obj,x+self.edge,y-oy+h*.5) - elseif align=='R'then - gc_draw(obj,x+w-self.edge-ox*2,y-oy+h*.5) - end -end -function key:getInfo() - return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font,self.fType) -end -function key:press(_,_,k) - self.code(k) - if self.sound then - SFX.play(self.sound) - end -end -function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,color][,font=30][,fType][,sound][,align='M'][,edge=0][,code][,hideF][,hide] - if not D.h then D.h=D.w end - local _={ - name= D.name or"_", - - x= D.x-D.w*.5, - y= D.y-D.h*.5, - w= D.w, - h= D.h, - - resCtr={ - D.x,D.y, - D.x-D.w*.35,D.y-D.h*.35, - D.x-D.w*.35,D.y+D.h*.35, - D.x+D.w*.35,D.y-D.h*.35, - D.x+D.w*.35,D.y+D.h*.35, - }, - - fText= D.fText, - fShade= D.fShade, - color= D.color and(COLOR[D.color]or D.color)or COLOR.Z, - font= D.font or 30, - fType= D.fType, - align= D.align or'M', - edge= D.edge or 0, - code= D.code or NULL, - hideF= D.hideF, - hide= D.hide, - } - if D.sound==false then - _.sound=false - elseif type(D.sound)=='string'then - _.sound=D.sound - else - _.sound='key' - end - for k,v in next,key do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local switch={ - type='switch', - mustHaveText=true, - ATV=0,--Activating time(0~8) - CHK=0,--Check alpha(0~6) -} -function switch:reset() - self.ATV=0 - self.CHK=0 -end -function switch:isAbove(x,y) - return x>self.x and xself.y-25 and y0 then self.ATV=max(ATV-dt*30,0)end - end - local chk=self.CHK - if self:disp()then - if chk<6 then self.CHK=min(chk+dt*60,6)end - else - if chk>0 then self.CHK=max(chk-dt*60,0)end - end -end -function switch:draw() - local x,y=self.x,self.y - local ATV=self.ATV - - --Background - gc_setColor(0,0,0,.3) - gc_rectangle('fill',x,y-25,50,50,4) - - --Frame - gc_setLineWidth(2) - gc_setColor(1,1,1,.6+ATV*.1) - gc_rectangle('line',x,y-25,50,50,3) - - --Checked - if ATV>0 then - gc_setColor(1,1,1,ATV*.06) - gc_rectangle('fill',x,y-25,50,50,3) - end - if self.CHK>0 then - gc_setColor(.9,1,.9,self.CHK/6) - gc_setLineWidth(5) - gc_line(x+5,y,x+18,y+13,x+45,y-14) - end - - --Drawable - local obj=self.obj - gc_setColor(self.color) - gc_draw(obj,x-12-ATV,y,nil,min(self.lim/obj:getWidth(),1),1,obj:getWidth(),obj:getHeight()*.5) -end -function switch:getInfo() - return("x=%d,y=%d,font=%d"):format(self.x,self.y,self.font,self.fType) -end -function switch:press() - self.code() - if self.sound then - SFX.play(self.disp()and'check'or'uncheck') - end -end -function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,fType][,sound=true][,disp][,code][,hideF][,hide] - local _={ - name= D.name or"_", - - x= D.x, - y= D.y, - lim= D.lim or 1e99, - - resCtr={ - D.x+25,D.y, - }, - - fText=D.fText, - color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, - font= D.font or 30, - fType=D.fType, - sound=D.sound~=false, - disp= D.disp, - code= D.code or NULL, - hideF=D.hideF, - hide= D.hide, - } - for k,v in next,switch do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local slider={ - type='slider', - ATV=0,--Activating time(0~8) - TAT=0,--Text activating time(0~180) - pos=0,--Position shown - lastTime=0,--Last value changing time -} -local sliderShowFunc={ - int=function(S) - return S.disp() - end, - float=function(S) - return int(S.disp()*100)*.01 - end, - percent=function(S) - return int(S.disp()*100).."%" - end, -} -function slider:reset() - self.ATV=0 - self.TAT=180 - self.pos=0 -end -function slider:isAbove(x,y) - return x>self.x-10 and xself.y-25 and y0 then - self.TAT=max(self.TAT-dt*60,0) - end - if WIDGET.sel==self then - if ATV<6 then self.ATV=min(ATV+dt*60,6)end - self.TAT=180 - else - if ATV>0 then self.ATV=max(ATV-dt*30,0)end - end - if not self.hide then - self.pos=approach(self.pos,self.disp(),dt*26) - end -end -function slider:draw() - local x,y=self.x,self.y - local ATV=self.ATV - local x2=x+self.w - - gc_setColor(1,1,1,.5+ATV*.06) - - --Units - if not self.smooth then - gc_setLineWidth(2) - for p=self.rangeL,self.rangeR,self.unit do - local X=x+(x2-x)*(p-self.rangeL)/(self.rangeR-self.rangeL) - gc_line(X,y+7,X,y-7) - end - end - - --Axis - gc_setLineWidth(4) - gc_line(x,y,x2,y) - - --Block - local cx=x+(x2-x)*(self.pos-self.rangeL)/(self.rangeR-self.rangeL) - local bx,by,bw,bh=cx-10-ATV*.5,y-16-ATV,20+ATV,32+2*ATV - gc_setColor(.8,.8,.8) - gc_rectangle('fill',bx,by,bw,bh,3) - - --Glow - if ATV>0 then - gc_setLineWidth(2) - gc_setColor(.97,.97,.97,ATV*.16) - gc_rectangle('line',bx+1,by+1,bw-2,bh-2,3) - end - - --Float text - if self.TAT>0 and self.show then - FONT.set(25) - gc_setColor(.97,.97,.97,self.TAT/180) - mStr(self:show(),cx,by-30) - end - - --Drawable - local obj=self.obj - if obj then - gc_setColor(self.color) - gc_draw(obj,x-12-ATV,y,nil,min(self.lim/obj:getWidth(),1),1,obj:getWidth(),obj:getHeight()*.5) - end -end -function slider:getInfo() - return("x=%d,y=%d,w=%d"):format(self.x,self.y,self.w) -end -function slider:press(x) - self:drag(x) -end -function slider:drag(x) - if not x then return end - x=x-self.x - local newPos=MATH.interval(x/self.w,0,1) - local newVal - if not self.unit then - newVal=(1-newPos)*self.rangeL+newPos*self.rangeR - else - newVal=newPos*(self.rangeR-self.rangeL) - newVal=self.rangeL+newVal-newVal%self.unit - end - if newVal~=self.disp()then - self.code(newVal) - end - if self.change and timer()-self.lastTime>.5 then - self.lastTime=timer() - self.change() - end -end -function slider:release(x) - self:drag(x) - self.lastTime=0 -end -function slider:scroll(n) - local p=self.disp() - local u=self.unit or .01 - local P=MATH.interval(p+u*n,self.rangeL,self.rangeR) - if p==P or not P then return end - self.code(P) - if self.change and timer()-self.lastTime>.18 then - self.lastTime=timer() - self.change() - end -end -function slider:arrowKey(k) - self:scroll((k=='left'or k=='up')and -1 or 1) -end -function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,axis][,smooth][,font=30][,fType][,change],disp[,show][,code],hide - if not D.axis then - D.axis={0,1,false} - D.smooth=true - elseif not D.axis[3]then - D.smooth=true - end - local _={ - name= D.name or"_", - - x= D.x, - y= D.y, - w= D.w, - lim= D.lim or 1e99, - - resCtr={ - D.x,D.y, - D.x+D.w*.25,D.y, - D.x+D.w*.5,D.y, - D.x+D.w*.75,D.y, - D.x+D.w,D.y, - }, - - fText= D.fText, - color= D.color and(COLOR[D.color]or D.color)or COLOR.Z, - rangeL=D.axis[1], - rangeR=D.axis[2], - unit= D.axis[3], - smooth=D.smooth, - font= D.font or 30, - fType= D.fType, - change=D.change, - disp= D.disp, - code= D.code or NULL, - hideF= D.hideF, - hide= D.hide, - show= false, - } - if D.show then - if type(D.show)=='function'then - _.show=D.show - else - _.show=sliderShowFunc[D.show] - end - elseif D.show~=false then--Use default if nil - if _.unit and _.unit%1==0 then - _.show=sliderShowFunc.int - else - _.show=sliderShowFunc.percent - end - end - for k,v in next,slider do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local selector={ - type='selector', - mustHaveText=true, - ATV=8,--Activating time(0~4) - select=false,--Selected item ID - selText=false,--Selected item name -} -function selector:reset() - self.ATV=0 - local V,L=self.disp(),self.list - for i=1,#L do - if L[i]==V then - self.select=i - self.selText=self.list[i] - return - end - end - self.select=0 - self.selText="" - MES.new('error',"Selector "..self.name.." dead, disp= "..tostring(V)) -end -function selector:isAbove(x,y) - return - x>self.x and - xself.y and - y0 then self.ATV=max(ATV-dt*30,0)end - end -end -function selector:draw() - local x,y=self.x,self.y - local w=self.w - local ATV=self.ATV - - --Background - gc_setColor(0,0,0,.3) - gc_rectangle('fill',x,y,w,60,4) - - --Frame - gc_setColor(1,1,1,.6+ATV*.1) - gc_setLineWidth(2) - gc_rectangle('line',x,y,w,60,3) - - --Arrow - gc_setColor(1,1,1,.2+ATV*.1) - local t=(timer()%.5)^.5 - if self.select>1 then - gc_draw(smallerThen,x+6,y+33) - if ATV>0 then - gc_setColor(1,1,1,ATV*.4*(.5-t)) - gc_draw(smallerThen,x+6-t*40,y+33) - gc_setColor(1,1,1,.2+ATV*.1) - end - end - if self.select<#self.list then - gc_draw(largerThen,x+w-26,y+33) - if ATV>0 then - gc_setColor(1,1,1,ATV*.4*(.5-t)) - gc_draw(largerThen,x+w-26+t*40,y+33) - end - end - - --Drawable - gc_setColor(self.color) - gc_draw(self.obj,x+w*.5,y-4,nil,min((w-20)/self.obj:getWidth(),1),1,self.obj:getWidth()*.5,0) - gc_setColor(1,1,1) - FONT.set(30) - mStr(self.selText,x+w*.5,y+22) -end -function selector:getInfo() - return("x=%d,y=%d,w=%d"):format(self.x+self.w*.5,self.y+30,self.w) -end -function selector:press(x) - if x then - local s=self.select - if x1 then - s=s-1 - SYSFX.newShade(3,self.x,self.y-WIDGET.scrollPos,self.w*.5,60) - end - else - if s<#self.list then - s=s+1 - SYSFX.newShade(3,self.x+self.w*.5,self.y-WIDGET.scrollPos,self.w*.5,60) - end - end - if self.select~=s then - self.code(self.list[s]) - self.select=s - self.selText=self.list[s] - if self.sound then - SFX.play('selector') - end - end - end -end -function selector:scroll(n) - local s=self.select - if n==-1 then - if s==1 then return end - s=s-1 - SYSFX.newShade(3,self.x,self.y-WIDGET.scrollPos,self.w*.5,60) - else - if s==#self.list then return end - s=s+1 - SYSFX.newShade(3,self.x+self.w*.5,self.y-WIDGET.scrollPos,self.w*.5,60) - end - self.code(self.list[s]) - self.select=s - self.selText=self.list[s] - if self.sound then - SFX.play('selector') - end -end -function selector:arrowKey(k) - self:scroll((k=='left'or k=='up')and -1 or 1) -end - -function WIDGET.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,disp[,code],hide - local _={ - name= D.name or"_", - - x= D.x-D.w*.5, - y= D.y-30, - w= D.w, - - resCtr={ - D.x,D.y, - D.x+D.w*.25,D.y, - D.x+D.w*.5,D.y, - D.x+D.w*.75,D.y, - D.x+D.w,D.y, - }, - - fText=D.fText, - color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, - sound=D.sound~=false, - font= 30, - list= D.list, - disp= D.disp, - code= D.code or NULL, - hideF=D.hideF, - hide= D.hide, - } - for k,v in next,selector do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local inputBox={ - type='inputBox', - keepFocus=true, - ATV=0,--Activating time(0~4) - value="",--Text contained -} -function inputBox:reset() - self.ATV=0 -end -function inputBox:hasText() - return #self.value>0 -end -function inputBox:getText() - return self.value -end -function inputBox:setText(str) - if type(str)=='string'then - self.value=str - end -end -function inputBox:addText(str) - if type(str)=='string'then - self.value=self.value..str - else - MES.new('error',"inputBox "..self.name.." dead, addText("..type(str)..")") - end -end -function inputBox:clear() - self.value="" -end -function inputBox:isAbove(x,y) - return - x>self.x and - y>self.y and - x0 then self.ATV=max(ATV-dt*15,0)end - end -end -function inputBox:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local ATV=self.ATV - - --Background - gc_setColor(0,0,0,.4) - gc_rectangle('fill',x,y,w,h,4) - - --Highlight - gc_setColor(1,1,1,ATV*.08*(math.sin(TIME()*4.2)*.2+.8)) - gc_rectangle('fill',x,y,w,h,4) - - --Frame - gc_setColor(1,1,1) - gc_setLineWidth(3) - gc_rectangle('line',x,y,w,h,3) - - --Drawable - local f=self.font - FONT.set(f,self.fType) - if self.obj then - gc_draw(self.obj,x-12-self.obj:getWidth(),y+h*.5-self.obj:getHeight()*.5) - end - if self.secret then - y=y+h*.5-f*.2 - for i=1,#self.value do - gc_rectangle("fill",x+f*.6*i,y,f*.4,f*.4) - end - else - gc_printf(self.value,x+10,y,self.w) - FONT.set(f-10) - if WIDGET.sel==self then - gc_print(EDITING,x+10,y+12-f*1.4) - end - end -end -function inputBox:getInfo() - return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h) -end -function inputBox:press() - if MOBILE then - local _,y1=xOy:transformPoint(0,self.y+self.h) - kb.setTextInput(true,0,y1,1,1) - end -end -function inputBox:keypress(k) - local t=self.value - if #t>0 and EDITING==""then - if k=='backspace'then - local p=#t - while t:byte(p)>=128 and t:byte(p)<192 do - p=p-1 - end - t=sub(t,1,p-1) - SFX.play('lock') - elseif k=='delete'then - t="" - SFX.play('hold') - end - self.value=t - end -end -function WIDGET.newInputBox(D)--name,x,y,w[,h][,font=30][,fType][,secret][,regex][,limit],hide - local _={ - name= D.name or"_", - - x= D.x, - y= D.y, - w= D.w, - h= D.h, - - resCtr={ - D.x+D.w*.2,D.y, - D.x+D.w*.5,D.y, - D.x+D.w*.8,D.y, - }, - - font= D.font or int(D.h/7-1)*5, - fType= D.fType, - secret=D.secret==true, - regex= D.regex, - limit= D.limit, - hideF= D.hideF, - hide= D.hide, - } - for k,v in next,inputBox do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local textBox={ - type='textBox', - scrollPos=0,--Scroll-down-distance - sure=0,--Sure-timer for clear history -} -function textBox:reset() - --haha nothing here, techmino is so fun! -end -function textBox:setTexts(t) - self.texts=t - self.scrollPos=0 -end -function textBox:clear() - self.texts={} - self.scrollPos=0 - SFX.play('fall') -end -function textBox:isAbove(x,y) - return - x>self.x and - y>self.y and - x0 then - self.sure=max(self.sure-dt,0) - end -end -function textBox:push(t) - ins(self.texts,t) - if self.scrollPos==(#self.texts-1-self.capacity)*self.lineH then--minus 1 for the new message - self.scrollPos=min(self.scrollPos+self.lineH,(#self.texts-self.capacity)*self.lineH) - end -end -function textBox:press(x,y) - if not(x and y)then return end - self:drag(0,0,0,0) - if not self.fix and x>self.x+self.w-40 and y0 then - self:clear() - self.sure=0 - else - self.sure=1 - end - end -end -function textBox:drag(_,_,_,dy) - self.scrollPos=max(0,min(self.scrollPos-dy,(#self.texts-self.capacity)*self.lineH)) -end -function textBox:scroll(dir) - if type(dir)=='string'then - if dir=="up"then - dir=-1 - elseif dir=="down"then - dir=1 - else - return - end - end - self:drag(nil,nil,nil,-dir*self.lineH) -end -function textBox:arrowKey(k) - if k=='up'then - self:scroll(-1) - elseif k=='down'then - self:scroll(-1) - end -end -function textBox:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local texts=self.texts - local scrollPos=self.scrollPos - local cap=self.capacity - local lineH=self.lineH - - --Background - gc_setColor(0,0,0,.3) - gc_rectangle('fill',x,y,w,h,4) - - --Frame - gc_setLineWidth(2) - gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z) - gc_rectangle('line',x,y,w,h,3) - - --Texts - FONT.set(self.font,self.fType) - gc_push('transform') - gc_translate(x,y) - - --Slider - gc_setColor(1,1,1) - if #texts>cap then - local len=h*h/(#texts*lineH) - gc_rectangle('fill',-15,(h-len)*scrollPos/((#texts-cap)*lineH),12,len,3) - end - - --Clear button - if not self.fix then - gc_rectangle('line',w-40,0,40,40,3) - gc_draw(self.sure==0 and clearIcon or sureIcon,w-40,0) - end - - gc_setStencilTest('equal',1) - STW,STH=w,h - gc_stencil(_rectangleStencil) - gc_translate(0,-(scrollPos%lineH)) - local pos=int(scrollPos/lineH) - for i=pos+1,min(pos+cap+1,#texts)do - gc_printf(texts[i],10,4,w-16) - gc_translate(0,lineH) - end - gc_setStencilTest() - gc_pop() -end -function textBox:getInfo() - return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h) -end -function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,fType][,lineH][,fix],hide - local _={ - name= D.name or"_", - - resCtr={ - D.x+D.w*.5,D.y+D.h*.5, - D.x+D.w*.5,D.y, - D.x-D.w*.5,D.y, - D.x,D.y+D.h*.5, - D.x,D.y-D.h*.5, - D.x,D.y, - D.x+D.w,D.y, - D.x,D.y+D.h, - D.x+D.w,D.y+D.h, - }, - - x= D.x, - y= D.y, - w= D.w, - h= D.h, - - font= D.font or 30, - fType=D.fType, - fix= D.fix, - texts={}, - hideF=D.hideF, - hide= D.hide, - } - _.lineH=D.lineH or _.font*7/5 - _.capacity=ceil((D.h-10)/_.lineH) - - for k,v in next,textBox do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local listBox={ - type='listBox', - keepFocus=true, - scrollPos=0,--Scroll-down-distance - selected=0,--Hidden wheel move value -} -function listBox:reset() - --haha nothing here too, techmino is really fun! -end -function listBox:clear() - self.list={} - self.scrollPos=0 -end -function listBox:setList(t) - self.list=t - self.selected=1 - self.scrollPos=0 -end -function listBox:getList() - return self.list -end -function listBox:getLen() - return #self.list -end -function listBox:getSel() - return self.list[self.selected] -end -function listBox:isAbove(x,y) - return - x>self.x and - y>self.y and - x0 then - rem(self.list) - listBox:drag(0,0,0,0) - end -end -function listBox:remove() - if self.selected then - rem(self.list,self.selected) - if not self.list[self.selected]then - self:arrowKey('up') - end - self:drag(0,0,0,0) - end -end -function listBox:press(x,y) - if not(x and y)then return end - x,y=x-self.x,y-self.y - if not(x and y and x>0 and y>0 and x<=self.w and y<=self.h)then return end - self:drag(0,0,0,0) - y=int((y+self.scrollPos)/self.lineH)+1 - if self.list[y]then - if self.selected~=y then - self.selected=y - SFX.play('selector',.8,0,12) - end - end -end -function listBox:drag(_,_,_,dy) - self.scrollPos=max(0,min(self.scrollPos-dy,(#self.list-self.capacity)*self.lineH)) -end -function listBox:scroll(n) - self:drag(nil,nil,nil,-n*self.lineH) -end -function listBox:arrowKey(dir) - if dir=="up"then - self.selected=max(self.selected-1,1) - if self.selectedint(self.scrollPos/self.lineH)+self.capacity-1 then - self:drag(nil,nil,nil,-self.lineH) - end - end -end -function listBox:select(i) - self.selected=i - if self.selectedint(self.scrollPos/self.lineH)+self.capacity-1 then - self:drag(nil,nil,nil,-1e99) - end -end -function listBox:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local list=self.list - local scrollPos=self.scrollPos - local cap=self.capacity - local lineH=self.lineH - - gc_push('transform') - gc_translate(x,y) - - --Background - gc_setColor(0,0,0,.4) - gc_rectangle('fill',0,0,w,h,4) - - --Frame - gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z) - gc_setLineWidth(2) - gc_rectangle('line',0,0,w,h,3) - - --Slider - if #list>cap then - gc_setColor(1,1,1) - local len=h*h/(#list*lineH) - gc_rectangle('fill',-15,(h-len)*scrollPos/((#list-cap)*lineH),12,len,3) - end - - --List - gc_setStencilTest('equal',1) - STW,STH=w,h - gc_stencil(_rectangleStencil) - local pos=int(scrollPos/lineH) - gc_translate(0,-(scrollPos%lineH)) - for i=pos+1,min(pos+cap+1,#list)do - self.drawF(list[i],i,i==self.selected) - gc_translate(0,lineH) - end - gc_setStencilTest() - gc_pop() -end -function listBox:getInfo() - return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h) -end -function WIDGET.newListBox(D)--name,x,y,w,h,lineH,drawF[,hideF][,hide] - local _={ - name= D.name or"_", - - resCtr={ - D.x+D.w*.5,D.y+D.h*.5, - D.x+D.w*.5,D.y, - D.x-D.w*.5,D.y, - D.x,D.y+D.h*.5, - D.x,D.y-D.h*.5, - D.x,D.y, - D.x+D.w,D.y, - D.x,D.y+D.h, - D.x+D.w,D.y+D.h, - }, - - x= D.x, - y= D.y, - w= D.w, - h= D.h, - - list= {}, - lineH= D.lineH, - capacity=ceil(D.h/D.lineH), - drawF= D.drawF, - hideF= D.hideF, - hide= D.hide, - } - - for k,v in next,listBox do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -WIDGET.active={}--Table contains all active widgets -WIDGET.scrollHeight=0--Max drag height, not actual container height! -WIDGET.scrollPos=0--Current scroll position -WIDGET.sel=false--Selected widget -WIDGET.indexMeta={ - __index=function(L,k) - for i=1,#L do - if L[i].name==k then - return L[i] - end - end - end -} -function WIDGET.setWidgetList(list) - WIDGET.unFocus(true) - WIDGET.active=list or NONE - WIDGET.cursorMove(SCR.xOy:inverseTransformPoint(love.mouse.getPosition())) - - --Reset all widgets - if list then - for i=1,#list do - list[i]:reset() - end - onChange() - end -end -function WIDGET.setScrollHeight(height) - WIDGET.scrollHeight=height and height or 0 - WIDGET.scrollPos=0 -end -function WIDGET.setLang(widgetText) - for S,L in next,SCN.scenes do - if L.widgetList then - for _,W in next,L.widgetList do - local t=W.fText or widgetText[S][W.name] - if not t and W.mustHaveText then - t=W.name or"##" - W.color=COLOR.dV - end - if type(t)=='string'and W.font then - t=gc.newText(FONT.get(W.font),t) - end - W.obj=t - end - end - end -end -function WIDGET.getSelected() - return WIDGET.sel -end -function WIDGET.isFocus(W) - if W then - return W and WIDGET.sel==W - else - return WIDGET.sel~=false - end -end -function WIDGET.focus(W) - if WIDGET.sel==W then return end - if WIDGET.sel and WIDGET.sel.type=='inputBox'then - kb.setTextInput(false) - EDITING="" - end - WIDGET.sel=W - if W and W.type=='inputBox'then - local _,y1=xOy:transformPoint(0,W.y+W.h) - kb.setTextInput(true,0,y1,1,1) - end -end -function WIDGET.unFocus(force) - local W=WIDGET.sel - if W and(force or not W.keepFocus)then - if W.type=='inputBox'then - kb.setTextInput(false) - EDITING="" - end - WIDGET.sel=false - end -end - -function WIDGET.cursorMove(x,y) - for _,W in next,WIDGET.active do - if not W.hide and W.resCtr and W:isAbove(x,y+WIDGET.scrollPos)then - WIDGET.focus(W) - return - end - end - if WIDGET.sel and not WIDGET.sel.keepFocus then - WIDGET.unFocus() - end -end -function WIDGET.press(x,y,k) - local W=WIDGET.sel - if W then - W:press(x,y and y+WIDGET.scrollPos,k) - if W.hide then WIDGET.unFocus()end - end -end -function WIDGET.drag(x,y,dx,dy) - if WIDGET.sel then - local W=WIDGET.sel - if W.drag then - W:drag(x,y+WIDGET.scrollPos,dx,dy) - elseif not W:isAbove(x,y+WIDGET.scrollPos)then - WIDGET.unFocus(true) - end - else - WIDGET.scrollPos=max(min(WIDGET.scrollPos-dy,WIDGET.scrollHeight),0) - end -end -function WIDGET.release(x,y) - local W=WIDGET.sel - if W and W.release then - W:release(x,y+WIDGET.scrollPos) - end -end -function WIDGET.textinput(texts) - local W=WIDGET.sel - if W and W.type=='inputBox'then - if(not W.regex or texts:match(W.regex))and(not W.limit or #(WIDGET.sel.value..texts)<=W.limit)then - WIDGET.sel.value=WIDGET.sel.value..texts - SFX.play('touch') - else - SFX.play('drop_cancel') - end - end -end - -function WIDGET.update(dt) - for _,W in next,WIDGET.active do - if W.hideF then - W.hide=W.hideF() - if W.hide and W==WIDGET.sel then - WIDGET.unFocus(true) - end - end - if W.update then W:update(dt)end - end -end -local widgetCanvas -local widgetCover do - local L={1,360,{'fRect',0,30,1,300}} - for i=0,30 do - ins(L,{'setCL',1,1,1,i/30}) - ins(L,{'fRect',0,i,1,2}) - ins(L,{'fRect',0,360-i,1,2}) - end - widgetCover=GC.DO(L) -end -local scr_w,scr_h -function WIDGET.resize(w,h) - scr_w,scr_h=w,h - widgetCanvas=gc.newCanvas(w,h) -end -function WIDGET.draw() - gc_setCanvas({stencil=true},widgetCanvas) - gc_translate(0,-WIDGET.scrollPos) - for _,W in next,WIDGET.active do - if not W.hide then W:draw()end - end - gc_origin() - gc_setColor(1,1,1) - if WIDGET.scrollHeight>0 then - if WIDGET.scrollPos>0 then - gc_draw(upArrowIcon,scr_w*.5,10,0,SCR.k,nil,upArrowIcon:getWidth()*.5,0) - end - if WIDGET.scrollPos