local gc=love.graphics local gc_push,gc_pop=gc.push,gc.pop local gc_translate=gc.translate local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth local gc_line,gc_rectangle,gc_circle=gc.line,gc.rectangle,gc.circle local gc_draw,gc_print,gc_printf=gc.draw,gc.print,gc.printf local gc_stencil,gc_setStencilTest=gc.stencil,gc.setStencilTest local max,min=math.max,math.min local int=math.floor local ins=table.insert local setFont=setFont local searchText="" local searchTimer local results={} local selectedItem local path={} local pathStr="modes/" function _setPos(self,x,y,dx,dy) self.x0,self.y0=x,y self.x,self.y=x+dx,y+dy end local function _newItem(item) local text=gc.newText(getFont(20),item.name) local icon=MODEICON[item.icon or item.name] return{ type=item.folder and'folder'or'mode', name=item.name, author=item.author or'', text=text, text_scaleX=min(1,150/text:getWidth()), icon=icon, icon_scale=min(max(160/icon:getWidth(),130/icon:getHeight()),1), x0=0,y0=0, x=0,y=0, w=160,h=160, alpha=0, selTime=0, setPos=_setPos, } end local _backItem={folder=true,name='_back'} local function _freshPacks() --Change directory local t=MODETREE for i=1,#path do for j=1,#t do if t[j].name==path[i]then t=t[j] break end end end --Get items with searchText local r={} if path[1]then ins(r,_newItem(_backItem)) end for i=1,#t do local item=t[i] if #searchText==0 or item.name:find(searchText)then ins(r,_newItem(item)) end end --Add items in correct order TABLE.cut(results) for i=1,#r do if r[i].type=='folder'then ins(results,r[i]) end end for i=1,#r do if r[i].type~='folder'then ins(results,r[i]) end end --Set items' positions for i=0,#results-1 do results[i+1]:setPos(180*(i%4),200*int(i/4),26+16*i,i) end selectedItem=false end local function _scrollModes(y) if not results[1]then return end local r=results[#results] if r.y0+r.h+y<540 then y=540-r.y0-r.h end if results[1].y0>-y then y=-results[1].y0 end for i=1,#results do local item=results[i] item.y0=item.y0+y end end local scene={} function scene.sceneInit() BG.set() _freshPacks() searchTimer=0 end function scene.mouseMove(x,y,_,dy) x,y=x-40,y-150 if x<-40 or x>765 or y<-40 or y>570 then return end if love.mouse.isDown(1)then _scrollModes(1.26*dy) end end function scene.mouseClick(x,y,k) if k==1 then local sel=false x,y=x-40,y-150 if x<-40 or x>765 or y<-40 or y>570 then return end for i=1,#results do local item=results[i] if x>item.x and xitem.y and y765 or y<-40 or y>570 then return end _scrollModes(dy*1.26) end function scene.keyDown(key,isRep) if key=='up'or key=='down'or key=='left'or key=='right'then if not selectedItem then selectedItem=results[1] else local i=TABLE.find(results,selectedItem) if key=='up'then i=i-4 elseif key=='down'then i=i+4 elseif key=='left'then i=i-1 elseif key=='right'then i=i+1 end if i<1 then i=1 elseif i>#results then i=#results end selectedItem=results[i] if selectedItem.y0<0 then _scrollModes(-selectedItem.y) elseif selectedItem.y0+selectedItem.h>540 then _scrollModes(540-selectedItem.y0-selectedItem.h) end end elseif key=='f1'then SCN.go('mod') elseif key=='space'or key=='return'then if isRep then return end if selectedItem then if selectedItem.type=='mode'then loadGame(selectedItem.name) elseif selectedItem.type=='folder'then if selectedItem.name=='_back'then table.remove(path) SFX.play('uncheck') else ins(path,selectedItem.name) SFX.play('check') end pathStr="modes/" if path[1]then pathStr=pathStr..table.concat(path,'/').."/"end _freshPacks() end else selectedItem=results[1] end elseif key=='escape'then if isRep then return end if #searchText>0 then searchText="" _freshPacks() else SCN.back() end elseif key=='backspace'then if #searchText>0 then searchText=searchText:sub(1,-2) searchTimer=.26 end elseif #key==1 and #searchText<12 then searchText=searchText..key searchTimer=.26 end end function scene.update(dt) if searchTimer>0 then searchTimer=searchTimer-dt if searchTimer<=0 then _freshPacks() end end for i=1,#results do local item=results[i] item.x=item.x*.9+item.x0*.1 item.y=item.y*.9+item.y0*.1 if item.alpha<1 then item.alpha=min(item.alpha+dt*2.6,1) end if item==selectedItem then item.selTime=min(item.selTime+dt,.126) elseif item.selTime>0 then item.selTime=item.selTime-dt end end end local function _modePannelStencil() gc_rectangle('fill',0,0,810,610) end local _unknownModeText={'???','?','?????'} local _rankName={ CHAR.icon.rankB, CHAR.icon.rankA, CHAR.icon.rankS, CHAR.icon.rankU, CHAR.icon.rankX, } function scene.draw() --Gray background gc_setColor(COLOR.dX) gc_rectangle('fill',0,0,1280,110) gc_rectangle('fill',0,110,810,610) gc_setColor(COLOR.X) gc_rectangle('fill',810,110,475,610) --Seperating line gc_setLineWidth(2) gc_setColor(COLOR.Z) gc_line(0,110,1280,110) gc_line(810,110,810,720) --Path setFont(35) gc_print(pathStr,60,40) --SearchText gc_print(CHAR.key.right,800,40) if searchText==""then gc_setColor(COLOR.dH) gc_print(text.searchModeHelp,840,40) else gc_setColor(COLOR.Z) gc_print(searchText,840,40) end --Items gc_push('transform') gc_translate(0,110) gc_stencil(_modePannelStencil,'replace',1) gc_setStencilTest('equal',1) gc_translate(40,40) setFont(50) for i=1,#results do local item=results[i] local rank=RANKS[item.name] if rank==0 then rank=nil end if item.type=='folder'then --Folder's yellow back local r,g,b if item.name=='_back'then r,g,b=0,0,0 else r,g,b=1,.8,.5 end gc_setColor(r,g,b,item.alpha*.4) gc_rectangle('fill',item.x,item.y,item.w,item.h) gc_setColor(1,1,1,item.alpha) gc_circle('line',item.x+15,item.y+15,8) else --Rank background if rank then local r,g,b=RANK_BASE_COLORS[rank][1],RANK_BASE_COLORS[rank][2],RANK_BASE_COLORS[rank][3] gc_setColor(r,g,b,item.alpha*.3) gc_rectangle('fill',item.x,item.y,item.w,item.h) end end --Icon gc_setColor(1,1,1,item.alpha) mDraw(item.icon,item.x+item.w/2,item.y+(item.h-30)/2,0,item.icon_scale) --Frame gc_rectangle('line',item.x,item.y,item.w,item.h,6) gc_draw(item.text,item.x+6,item.y+item.h-28,0,item.text_scaleX,1) --Rank if rank then local rankStr=_rankName[RANKS[item.name]] gc_setColor(0,0,0,item.alpha) gc_print(rankStr,item.x+item.w-30+2,item.y-26+2) local r,g,b=RANK_COLORS[rank][1],RANK_COLORS[rank][2],RANK_COLORS[rank][3] gc_setColor(r,g,b,item.alpha) gc_print(rankStr,item.x+item.w-30,item.y-26) end --Selecting glow if item.selTime>0 then gc_setColor(1,1,1,item.selTime*2) gc_rectangle('fill',item.x+8,item.y+8,item.w-16,item.h-36,5) end end gc_setStencilTest() gc_pop() --Selected item info if selectedItem then if selectedItem.type=='folder'then gc_setColor(1,1,1,selectedItem.alpha) setFont(50)mStr(selectedItem.name,1043,110) setFont(30)mStr(selectedItem.author,1043,180) elseif selectedItem.type=='mode'then local M=MODES[selectedItem.name] --Slowmark if M.slowMark then gc_setColor(.6,.9,1,(1-3*TIME()%1*.8)*selectedItem.alpha) setFont(20) gc_print("CTRL",815,110) end --Mode title & info gc_setColor(1,1,1,selectedItem.alpha) local t=text.modes[M.name]or _unknownModeText setFont(40)mStr(t[1],1043,110) setFont(30)mStr(t[2],1043,153) setFont(25)mStr(t[3],1043,200) --High scores if M.score then mText(TEXTOBJ.highScore,1043,293) gc_setColor(COLOR.dX) gc_rectangle('fill',825,335,440,260,3) local L=M.records gc_setColor(1,1,1) setFont(20) if L[1]then for i=1,#L do local res=M.scoreDisp(L[i]) gc_print(res,830,310+25*i,0,min(35/#res,1),1) gc_printf(L[i].date or"-/-/-",1100,310+25*i,200,'right',0,.8,1) end else mText(TEXTOBJ.noScore,1043,433) end end end end end scene.widgetList={ WIDGET.newButton{name='mod',x=920,y=655,w=150,h=80,code=goScene'mod'}, WIDGET.newButton{name='back',x=1140,y=655,w=220,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene}, } return scene