FartNebuleuse

Epic visualizer

Jun 23rd, 2021 (edited)
460
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 41.49 KB | None | 0 0
  1. --@name Epic visualizer
  2. --@author NekerSqu4w
  3. //version 2.22 Please don't delete this line to have semi-auto update :D
  4. --@include ./lang.txt
  5. --@include ./color.txt
  6.  
  7. //IMPORTANT Changelog 2.20
  8. //
  9. // Now loading YouTube playlist
  10. //
  11.  
  12. //Changelog 2.21
  13. //
  14. // 1. Small bug adjustment.
  15. // 2. Changed visual effect:
  16. // 2.1. Better particle effect
  17. // 2.2. Added a loading bar when starting
  18. // 2.3. Better match with background color
  19. //
  20. // 3. Added modifications to lang.txt --> https://pastebin.com/pTkL06UW
  21. //
  22.  
  23. //Changelog 2.22
  24. //
  25. // 1. Small bug adjustment.
  26. // 2. Changed visual effect:
  27. // 2.1. Smaller particle effect
  28. // 2.2. Better low frequency detecting
  29. // 2.3. Better pulsating effects
  30. //
  31. // 3. Addition of a new 'SynthWave' color palette to color.txt --> https://pastebin.com/n8fgDFww
  32.  
  33.  
  34. if SERVER then
  35. -- Auto link screen
  36. if chip():isWeldedTo() then
  37. chip():isWeldedTo():linkComponent(chip())
  38. end
  39. -------------------------------------------------------
  40. end
  41.  
  42. if CLIENT then
  43. -- Important information (Before run the code for the first time)
  44. //Download the lang file here --> 'https://pastebin.com/pTkL06UW'
  45. //Download the color palettes file here --> 'https://pastebin.com/n8fgDFww'
  46.  
  47. -- Settings
  48. local track = 50
  49. local playlist_id = "PLvL0CfXbtRGGvfWF9809g3q1aoieIFVp3" //Max track = 50 //Default = PLvL0CfXbtRGGvfWF9809g3q1aoieIFVp3
  50. local key = "YOUR_API_KEY" //Create your free api key here --> https://console.cloud.google.com/apis
  51. local max_hearing_distance = 1000
  52.  
  53. -- Visual settings
  54. local lang_use = "EN_lang"
  55. local principal_color = Color(150,255,100)
  56.  
  57. // Some cool color
  58. //
  59. // Apples: Color(150,255,100)
  60. // Orange: Color(255,150,70)
  61. // YouTube: Color(255,75,75)
  62. -------------------------------------------------------
  63.  
  64. -- Variable
  65. local ver = 2.22
  66. local lang = require("./lang.txt")(lang_use)
  67. local color = require("./color.txt")
  68. local volume = 0.5
  69. local loaded = 0
  70. local bassfft = 0
  71. local shake1, shake2 = 0, 0
  72. local fft, smooth_fft, visualizer = {}, {}, {}
  73. local startup = 1
  74. local black, black2 = 0, 0
  75. local startUpSize = 1300
  76. local posRight = 0
  77. local r,g,b,r2,g2,b2 = 0,0,0,{},{},{}
  78. local time, duration = 0, 10
  79. local start_time = 0
  80. local color_menu, show_visualizer, show_cursor = false, true, true
  81. local sizeToX, sizeToY = 0, 0
  82. local sizeX, sizeY = 0, 0
  83. local pi2 = math.pi*2
  84. local loading = ""
  85. local mat = {}
  86. local looping = true
  87. local use_color = 1
  88. local click_possible = false
  89. local last_real = Color(0,0,0)
  90. local title = ""
  91. local id = ""
  92. local thumbnail = ""
  93. local URL = ""
  94. local url = ""
  95. local playlist = {}
  96. local real = {}
  97. local j = 0
  98.  
  99. local fontName = "Akbar"
  100. local font = render.createFont(fontName, 250+50, 250+50, true, false, false, false, false, true)
  101. local font2 = render.createFont(fontName, 120+50, 120+50, true, false, false, false, false, true)
  102. local font3 = render.createFont(fontName, 180+50, 180+50, true, false, false, false, false, true)
  103.  
  104. local last_max = 0
  105. local bc = 1
  106. local si = {}
  107. local ra = {}
  108. local up = {}
  109. local turn = {}
  110.  
  111. for i=1, 15 do
  112. ra[i] = 512
  113. si[i] = 1
  114. up[i] = {}
  115. turn[i] = 0
  116. end
  117.  
  118. render.createRenderTarget("visualizer")
  119. render.createRenderTarget("background")
  120.  
  121. visualizer["1"] = { {x = 256, y = 256} }
  122. visualizer["2"] = { {x = 256, y = 256} }
  123. visualizer["3"] = { {x = 256, y = 256} }
  124. visualizer["4"] = { {x = 256, y = 256} }
  125. for h=1, 15 do
  126. for i = 2, 50 + 1 do visualizer["1"][i] = {} visualizer["2"][i] = {} visualizer["3"][i] = {} visualizer["4"][i] = {}
  127. up[h][i] = 0
  128. end
  129. end
  130.  
  131. -------------------------------------------------------
  132.  
  133. -- Custom function
  134. local cursor = {
  135. { x=0, y=0 },
  136. { x=3, y=2 },
  137. { x=1.1, y=2 },
  138. { x=2.1, y=3.9 },
  139. { x=1.9, y=4 },
  140. { x=0.9, y=2.1 },
  141. { x=0.1, y=4 },
  142. }
  143.  
  144. function getMouse(curX, curY, scale)
  145. local copyMouse = table.copy(cursor)
  146.  
  147. for i=1, #copyMouse do
  148. copyMouse[i].x = copyMouse[i].x*scale + curX
  149. copyMouse[i].y = copyMouse[i].y*scale + curY
  150. end
  151. return copyMouse
  152. end
  153.  
  154. function drawMouse(curX, curY)
  155. render.setRenderTargetTexture()
  156.  
  157. copyMouse = getMouse(curX, curY, 4)
  158. render.drawPoly(copyMouse)
  159. end
  160.  
  161. local function quotaCheck(n)
  162. return math.max(quotaAverage(), quotaUsed()) < quotaMax() * n
  163. end
  164.  
  165. local num = nil
  166. function changed(value)
  167. if not num == value then num = value val = true else val = false end
  168. return val
  169. end
  170.  
  171.  
  172. local max = 0
  173. function math.maxt(tbl,min,limit)
  174. for x=min, limit do
  175. for y=min, limit do
  176. if (tbl[x] or 0) > (tbl[y] or 0) then
  177. max = (tbl[x] or 0)
  178. elseif (tbl[x] or 0) < (tbl[y] or 0) then
  179. max = (tbl[y] or 0)
  180. end
  181. end
  182. end
  183.  
  184. return max
  185. end
  186.  
  187. local bassVal = 0
  188. function getBass(ft,limit)
  189. for h=1, limit do
  190. for w=1, limit do
  191. if (ft[h] or 0) < (ft[w] or 0) then
  192. bassVal = math.lerp(0.002,bassVal,(ft[w] or 0)*5)
  193. elseif (ft[h] or 0) > (ft[w] or 0) then
  194. bassVal = math.lerp(0.002,bassVal,(ft[h] or 0)*5)
  195. end
  196. end
  197. end
  198.  
  199. return bassVal
  200. end
  201.  
  202. function fftToRadius(i) return 54 + bassfft*20 - math.log10(i) - (smooth_fft[50-i] or 0)*100 end
  203.  
  204. function inrange(x, y, w, h)
  205. local cx, cy = render.cursorPos()
  206. if not cx or not cy then return false end
  207.  
  208. if cx > x and cx < x+w then
  209. if cy > y and cy < y+h then
  210. return true
  211. end
  212. end
  213. end
  214.  
  215. function information(cx,cy,txt,res,use_font)
  216. render.setFont(use_font)
  217. local w,h = render.getTextSize(txt)
  218.  
  219. render.setColor(Color(0,0,0,100))
  220. render.drawRect((cx/512)*res+50, (cy/512)*res-80, w, h)
  221.  
  222. render.setColor(Color(255,255,255))
  223. render.drawText((cx/512)*res+50, (cy/512)*res-85, txt,0)
  224.  
  225. return (w/res)*512,(h/res)*512
  226. end
  227.  
  228. function render.drawPolyOutline(table)
  229. local lx,ly = table[2].x, table[2].y
  230. for i=2, #table do
  231. x = table[i].x
  232. y = table[i].y
  233. render.drawLine(x,y,lx,ly)
  234. lx = x
  235. ly = y
  236. end
  237. end
  238. -------------------------------------------------------
  239.  
  240. -- Slider function
  241. local Slider = class("Slider")
  242. local objects = {}
  243.  
  244. function Slider:initialize(x, y, w, h, min, max, val, round, info, show_title, can_change)
  245. self.x = x
  246. self.y = y
  247. self.w = w
  248. self.h = h
  249. self.min = min or 0
  250. self.max = max or 100
  251. self.val = val or 0
  252. self.round = round or 0
  253. self.info = info or ""
  254. self.normal = self.val or 0
  255. self.title = show_title or false
  256. self.can_change = can_change or false
  257.  
  258. self.color1 = Color(100,100,100)
  259. self.color2 = Color(100,130,255)
  260. self.color3 = Color(230,230,230)
  261.  
  262. table.insert(objects, self)
  263. end
  264.  
  265. function Slider:think()
  266. if self.active then
  267.  
  268. local cx, cy = render.cursorPos()
  269. if not cx or not cy then return end
  270.  
  271. cx = math.clamp(cx, self.x, self.x + self.w)
  272. self.val = self.max / self.w * (cx - self.x)
  273.  
  274. end
  275.  
  276. if self.customThink then self:customThink() end
  277. end
  278.  
  279. function Slider:paint()
  280. local m = Matrix()
  281. m:setScale(Vector(0.08))
  282. render.pushMatrix(m)
  283.  
  284. local v = self.w / self.max * self.val
  285.  
  286. render.setColor(self.color1/1.3)
  287. render.drawRect((self.x/512)*6400, ((self.y+self.h/2.6)/512)*6400, (self.w/512)*6400, ( (self.h/4 )/512)*6400)
  288.  
  289. render.setColor(self.color2)
  290. render.drawRect((self.x/512)*6400, ((self.y+self.h/2.6)/512)*6400, (v/512)*6400, ( (self.h/4 )/512)*6400)
  291.  
  292. if self.active then
  293. render.setColor((self.color2/1.3):setA(255))
  294. else
  295. render.setColor(self.color2)
  296. end
  297.  
  298. render.drawRoundedBox( 1000, ((self.x+v - (self.h/3) )/512)*6400,((self.y+self.h/6)/512)*6400, ( (self.h/1.5)/512)*6400, ( (self.h/1.5)/512)*6400 )
  299.  
  300. if self.active and self.title then
  301. render.setFont(render.createFont("akbar", 200, 200, true, false, false, false, false, false))
  302. local width, height = render.getTextSize( math.round(self.val,self.round) .. " (" .. tostring(math.round((self.val/1)*100)) .. self.info .. ")" )
  303.  
  304. render.setColor(self.color3)
  305. render.setMaterial()
  306. render.drawRect(((self.x + v)/512)*6400 - (width+50)/2,((self.y-10)/512)*6400 - height/2,width+50,height)
  307.  
  308. render.setColor(Color(255,255,255))
  309. render.setFont(render.createFont("akbar", 200, 200, true, false, false, false, false, false))
  310. render.drawSimpleText(((self.x + v)/512)*6400, ((self.y-10)/512)*6400, math.round(self.val,self.round) .. " (" .. tostring(math.round((self.val/1)*100)) .. self.info .. ")", 1, 1)
  311. end
  312.  
  313. render.popMatrix()
  314. end
  315.  
  316. function markElement(active)
  317.  
  318. if not active then
  319. -- disable all elements
  320.  
  321. for k, v in pairs(objects) do
  322. v.active = false
  323. end
  324.  
  325. else
  326. -- find element under cursor
  327. for k, v in pairs(objects) do
  328. if inrange(v.x, v.y, v.w, v.h) then
  329. v.active = true
  330. break
  331. end
  332. end
  333.  
  334. end
  335.  
  336. end
  337. -------------------------------------------------------
  338.  
  339. -- Particle function
  340. local Particle = class("Particle")
  341. function Particle:initialize(pos, scale, direction, clr, life_time)
  342. self.x = pos.x or 0
  343. self.y = pos.y or 0
  344. self.scale = scale or 0
  345. self.first_scale = scale or 0
  346. self.x_vel = direction.x or 0
  347. self.y_vel = direction.y or 0
  348. self.color = clr or Color(255, 255, 255, 255)
  349. self.life = life_time or 5
  350. self.life_start = life_time or 5
  351. end
  352.  
  353. function Particle:think()
  354. self:draw()
  355.  
  356. self.x = self.x + self.x_vel
  357. self.y = self.y + self.y_vel
  358.  
  359. self.life = self.life - 0.01
  360. self.scale = (self.life/self.life_start) * self.first_scale
  361. end
  362.  
  363. function Particle:draw()
  364. render.setColor(self.color:setA(255))
  365. render.setMaterial(mat[3])
  366. render.drawTexturedRect(self.x - self.scale/2, self.y - self.scale/2, self.scale, self.scale)
  367. render.setMaterial(nil)
  368. render.setColor(Color(255,255,255):setA(255))
  369. end
  370.  
  371. local game = {}
  372. game.particles = {}
  373.  
  374. -------------------------------------------------------
  375.  
  376. -- Show the visualizer
  377. function load()
  378. bass.loadURL(URL,"noblock",function(snd)
  379. -- Setup slider
  380. timer.create("Setup",1,1,function()
  381. local volume_slider = Slider(400-150/2, 480-15/2, 150, 15, 0, 2, volume, 2, "%", true, false)
  382. volume_slider.customThink = function(self)
  383. self.color1 = Color(150, 150, 150):setA(75)
  384. self.color2 = principal_color
  385. self.color3 = Color(0,0,0,150)
  386.  
  387. volume = self.max * self.val
  388. end
  389.  
  390. local time_slider = Slider(256-480/2, 495-15/2, 480, 15, 0, length, snd:getTime(), 2, "%", false, true)
  391. time_slider.color1 = Color(150, 150, 150):setA(75)
  392. time_slider.color2 = principal_color
  393. time_slider.color3 = Color(0,0,0,150)
  394.  
  395. time_slider.customThink = function(self)
  396. self.color1 = Color(150, 150, 150):setA(75)
  397. self.color2 = principal_color
  398. self.color3 = Color(0,0,0,150)
  399.  
  400. snd:setTime(length / self.max * self.val)
  401. end
  402.  
  403. snd:play()
  404. end)
  405. -------------------------------------------------------
  406.  
  407. snd:pause()
  408. local Light = light.create(chip():getPos(),700,5,Color(0,0,0))
  409.  
  410. hook.add("render","visualizer",function()
  411. if snd:isValid() then
  412. if snd:getTime() >= length then
  413. snd:setTime(0)
  414. end
  415.  
  416. snd:setPos(render.getScreenEntity():getPos())
  417.  
  418. local dist = player():getPos():getDistance(chip():getPos())
  419. if dist > max_hearing_distance then snd:setVolume(0) else snd:setVolume(volume - (dist/max_hearing_distance)*volume) end
  420.  
  421. fft = snd:getFFT(4)
  422. if startup == 10 then
  423. bassfft = getBass(fft,20)
  424. end
  425. end
  426.  
  427. local cx, cy = render.cursorPos()
  428. click_possible = false
  429.  
  430. //shake1 = math.lerp(0.2,shake1,math.random(-bassfft*7,bassfft*7))
  431. //shake2 = math.lerp(0.2,shake2,math.random(-bassfft*7,bassfft*7))
  432.  
  433. local real = color[use_color].color[1] or Color(0,0,0)
  434. r = math.lerp(0.2,r, real.r)
  435. g = math.lerp(0.2,g, real.g)
  436. b = math.lerp(0.2,b, real.b)
  437.  
  438. Light:draw()
  439. Light:setPos( render.getScreenEntity():getPos() )
  440. Light:setColor(Color(r,g,b)*bassfft)
  441.  
  442. -- Background
  443. render.selectRenderTarget("background")
  444.  
  445. render.setMaterial(mat[1])
  446. render.setColor(Color(0, 0, 1):hsvToRGB())
  447.  
  448. render.setCullMode(1)
  449. render.drawTexturedRect( 256, 0, -750, 750)
  450.  
  451. render.setCullMode(0)
  452. render.drawTexturedRect( 256, 0, 750, 750)
  453.  
  454. if startup == 5 then
  455. if startup && startup then render.capturePixels() end
  456. j = 1
  457. for i=1, 10 do
  458. for h=1, 10 do
  459. x = 512-(i/10)*(512-(1/10)*512)
  460. y = (h/10)*(512-(1/10)*512)
  461.  
  462. real[j] = render.readPixel(x,y)
  463. j = j + 1
  464. end
  465. end
  466.  
  467. for i=1, 10 do
  468. color[1].color[i] = real[i]
  469. end
  470. end
  471.  
  472. render.setMaterial(nil)
  473. render.selectRenderTarget(nil)
  474.  
  475.  
  476. render.setColor(Color(0, 0, black+bassfft/4):hsvToRGB())
  477. render.setRenderTargetTexture("background")
  478. render.drawTexturedRect(0-bassfft/4*20,0-bassfft/4*20,1024+bassfft*20,1024+bassfft*20)
  479.  
  480. -------------------------------------------------------
  481.  
  482. if startup == 10 and show_visualizer == true then
  483. -- Setup and draw Particle
  484. if #game.particles <= 300 then
  485. local nP = Particle:new(Vector(256,256),math.random(10, 20),Vector(math.rand(-1,1),math.rand(-1,1)),color[use_color].color[math.random(1,#color[use_color].color)],3)
  486. table.insert(game.particles, nP)
  487. end
  488.  
  489. for k, v in pairs(game.particles) do
  490. if v.scale <= 0 then table.remove(game.particles, k) continue end
  491.  
  492. v:draw()
  493.  
  494. v.x = v.x + (v.x_vel*(0.5+bassfft*4))
  495. v.y = v.y + (v.y_vel*(0.5+bassfft*4))
  496.  
  497. v.life = v.life - 0.01
  498. v.scale = (v.life/v.life_start) * v.first_scale
  499.  
  500. //v:think()
  501. end
  502. -------------------------------------------------------
  503.  
  504. -- Setup visualizer
  505. for i=2, 50+1 do
  506. local theta = (((i - 1) - 1) * math.pi / (50 - 1))
  507. smooth_fft[i] = math.lerp((0.1*7.5),(smooth_fft[i] or 0), (fft[50+2-i+1] or 0) )
  508.  
  509. visualizer["1"][i].x = 256 + shake1 + math.cos(math.pi/2+theta + timer.curtime()/4) * (58 + ((smooth_fft[50+2-i + 1] or 0) * 140) + (bassfft * 20) + 50/4)
  510. visualizer["1"][i].y = 256 + shake2 + math.sin(math.pi/2+theta + timer.curtime()/4) * (58 + ((smooth_fft[50+2-i + 1] or 0) * 140) + (bassfft * 20) + 50/4)
  511.  
  512. visualizer["2"][i].x = 256 + shake1 + math.cos(math.pi/2-theta + timer.curtime()/4) * (58 + ((smooth_fft[50+2-i + 1] or 0) * 140) + (bassfft * 20) + 50/4)
  513. visualizer["2"][i].y = 256 + shake2 + math.sin(math.pi/2-theta + timer.curtime()/4) * (58 + ((smooth_fft[50+2-i + 1] or 0) * 140) + (bassfft * 20) + 50/4)
  514. end
  515.  
  516. -------------------------------------------------------
  517.  
  518. -- Draw visualizer
  519. render.selectRenderTarget("visualizer")
  520.  
  521. render.setMaterial(nil)
  522. render.clear(Color(0,0,0,0))
  523.  
  524. render.setColor(Color(255, 255, 255))
  525. render.setCullMode(0)
  526. render.drawPoly(visualizer["1"])
  527. render.setCullMode(1)
  528. render.drawPoly(visualizer["2"])
  529.  
  530. render.setCullMode(0)
  531.  
  532. render.selectRenderTarget(nil)
  533.  
  534. for v=1, #color[use_color].color do
  535. local real = color[use_color].color[math.round(#color[use_color].color+1-v)] or Color(0,0,0)
  536. r2[v] = math.lerp(0.1,r2[v] or 0, real.r)
  537. g2[v] = math.lerp(0.1,g2[v] or 0, real.g)
  538. b2[v] = math.lerp(0.1,b2[v] or 0, real.b)
  539. render.setColor(Color(r2[v],g2[v],b2[v]):setA(255))
  540.  
  541. render.setRenderTargetTexture("visualizer")
  542. render.drawTexturedRect(-200/4 + (v/#color[use_color].color)*200/4,-200/4 + (v/#color[use_color].color)*200/4,1024+200 - (v/#color[use_color].color)*200,1024+200 - (v/#color[use_color].color)*200)
  543. end
  544. end
  545.  
  546. -------------------------------------------------------
  547.  
  548. -- Starting animation
  549. if startup == 1 then if startUpSize >= -50 then startUpSize = startUpSize - 2 - (startUpSize/1300)*30 end end
  550. if startUpSize <= 100 and startup == 1 then if posRight <= 180 then posRight = posRight + 1 + (posRight/180)*2 black = (posRight/180)*0.2 else startup = 3 end end
  551. if startup == 3 then timer.create("aaaaa",2,1,function() startup = 5 end) startup = 4 end
  552. if startup == 5 then if posRight >= 0 then posRight = posRight - 5 black = 0.4-(posRight/180)*0.2 black2 = 1-(posRight/180)*1 end end
  553. if startup == 5 then if startUpSize <= 50 then startUpSize = startUpSize + 3 - (startUpSize/50)*2.9 else startup = 10 end end
  554.  
  555. if startup == 2 or startup == 3 or startup == 4 or startup == 5 or startUpSize <= 5 then
  556. render.setMaterial(mat[2])
  557.  
  558. render.setColor(Color(255, 255, 255):setA(math.clamp( 255-black2*600,0,255)))
  559. render.drawTexturedRect(256 - 70/4 * posRight*1.2, 256 - 70/4, 70, 70)
  560. render.drawTexturedRect(256 - 70/4 + posRight*1.2, 256 - 70/4, 70, 70)
  561.  
  562. render.setColor(Color(255, 255, 255):setA(math.clamp( 255-black2*1000,0,255)))
  563. render.drawTexturedRect(256 - 110/4 - posRight/1.1, 256 - 110/4, 110, 110)
  564. render.drawTexturedRect(256 - 110/4 + posRight/1.1, 256 - 110/4, 110, 110)
  565.  
  566. render.setColor(Color(255, 255, 255):setA(math.clamp( 255-black2*1400,0,255)))
  567. render.drawTexturedRect(256 - 140/4 - posRight/2, 256 - 140/4, 140, 140)
  568. render.drawTexturedRect(256 - 140/4 + posRight/2, 256 - 140/4, 140, 140)
  569.  
  570. render.setMaterial(nil)
  571. end
  572.  
  573. -------------------------------------------------------
  574.  
  575. -- Draw punch circle
  576. if startup == 10 and show_visualizer == true then
  577. if (math.maxt(fft,1,7) - last_max) > 0.1 then
  578. bc = bc + 1
  579.  
  580. if bc >= 15 then bc = 1 end
  581.  
  582. si[bc] = 1 + math.maxt(fft,3,7)*10
  583. ra[bc] = 50
  584. turn[bc] = timer.curtime()
  585.  
  586. for h=2, 51 do
  587. up[bc][h] = ((smooth_fft[50+2-h + 1] or 0) * 140) + (bassfft * 20) + 50/4
  588. end
  589. end
  590.  
  591. last_max = math.maxt(fft,1,7)
  592.  
  593. for i=1, 15 do
  594. if ra[i] < 512 then ra[i] = ra[i] + si[i] end
  595. render.setColor(Color(principal_color.r,principal_color.g,principal_color.b,100))
  596. //render.drawCircle(256,256,ra[i])
  597.  
  598. for h=2, 51 do
  599. local theta = (((h - 1) - 1) * math.pi / (50 - 1))
  600. visualizer["3"][h].x = 256 + shake1 + math.cos(math.pi/2+theta + turn[i]/4) * (ra[i] + up[i][h])
  601. visualizer["3"][h].y = 256 + shake2 + math.sin(math.pi/2+theta + turn[i]/4) * (ra[i] + up[i][h])
  602.  
  603. visualizer["4"][h].x = 256 + shake1 + math.cos(math.pi/2-theta + turn[i]/4) * (ra[i] + up[i][h])
  604. visualizer["4"][h].y = 256 + shake2 + math.sin(math.pi/2-theta + turn[i]/4) * (ra[i] + up[i][h])
  605. end
  606.  
  607. render.drawPolyOutline(visualizer["3"])
  608. render.drawPolyOutline(visualizer["4"])
  609. end
  610.  
  611. render.setCullMode(0)
  612. end
  613.  
  614. -------------------------------------------------------
  615.  
  616. if show_visualizer == true then
  617. -- Logo
  618. render.setMaterial(mat[2])
  619. render.setColor(Color(255, 255, 255))
  620. render.drawTexturedRect(512/2 - 220/4 - bassfft*80*0.25 + shake1 - startUpSize/4, 512/2 - 220/4 - bassfft*80*0.25 + shake2 - startUpSize/4, 220 + bassfft*80 + startUpSize, 220 + bassfft*80 + startUpSize)
  621.  
  622. -------------------------------------------------------
  623. end
  624.  
  625. -- Visualizer in logo
  626. if startup == 10 and show_visualizer == true then
  627. render.setMaterial(nil)
  628.  
  629. for i=1, 29 do
  630. local theta = (i-1)*2*(math.pi/2.5)/(30-1)
  631.  
  632. render.setColor(principal_color)
  633. render.drawTexturedRectRotated( 256 + shake1 + math.sin(-math.pi/2.5+theta) * fftToRadius(i), 256 + shake2 + math.cos(-math.pi/2.5+theta) * fftToRadius(i), 4, 2 + (smooth_fft[50-i] or 0)*200, -360/3.3+(360/2.5)/29+i*-(360/2.5)/29)
  634. end
  635.  
  636. -------------------------------------------------------
  637. end
  638.  
  639. -- Visualizer GUI
  640. if startup == 10 then
  641. local m = Matrix()
  642. m:setScale(Vector(0.08))
  643. render.pushMatrix(m)
  644.  
  645. -- Time bar
  646. render.setColor(Color(255))
  647. render.setFont(font3)
  648. render.drawSimpleText(800, 6000, string.toMinutesSeconds(snd:getTime()),1,1)
  649. render.setColor(Color(120,120,120))
  650. render.drawSimpleText(1400, 6000," / "..string.toMinutesSeconds(length),1,1)
  651.  
  652. render.setColor(principal_color)
  653. render.drawRoundedBox( 1000, 450-70/2, 6010-70/2, 70, 70)
  654.  
  655. render.setColor(Color(120,120,120))
  656. render.setFont(font)
  657. render.drawSimpleText(200, 200, "" .. track,1,1)
  658.  
  659. render.setColor(Color(255))
  660. render.setFont(font)
  661. render.drawSimpleText(400, 150, "" .. (playlist[track].snippet.title or "Deleted video"),0,1)
  662.  
  663. render.setColor(Color(180,180,180))
  664. render.setFont(font2)
  665. render.drawSimpleText(400, 320, "" .. url,0,1)
  666.  
  667. sizeX = math.lerp(0.4,sizeX,sizeToX)
  668.  
  669. render.setColor(Color(0, 0, 0, 255))
  670. render.setMaterial(mat[4])
  671. render.drawTexturedRect(0,0,6400,450)
  672.  
  673. render.setColor(Color(0, 0, 0, 255))
  674. render.setMaterial(mat[5])
  675. render.drawTexturedRect(0, 5800, 6400, 600)
  676.  
  677. render.setColor(Color(0, 0, 0, 255))
  678. render.setMaterial(mat[6])
  679. render.drawTexturedRect(0, 0, 0 + sizeX, 6400)
  680.  
  681. render.setColor(Color(0, 0, 0, 75))
  682. render.drawRect(sizeX/2, 500, 300, 300)
  683.  
  684. ------------------------------------------------
  685.  
  686. if inrange(((sizeX/2)/6400)*512, (500/6400)*512, (300/6400)*512, (300/6400)*512) then
  687. click_possible = true
  688. if color_menu == true then
  689. information(cx+4,cy+23,lang.color_on,6400,font3)
  690. else
  691. information(cx+4,cy+23,lang.color_off,6400,font3)
  692. end
  693. end
  694.  
  695. if color_menu == true then
  696. render.setColor(Color(255,255,255))
  697. render.setFont(font3)
  698. if show_visualizer == true then
  699. render.drawSimpleText(sizeX/2-100, 1600 + #color*180, lang.visualizer_on.."",0,1)
  700. else
  701. render.drawSimpleText(sizeX/2-100, 1600 + #color*180, lang.visualizer_off.."",0,1)
  702. end
  703.  
  704. if show_cursor == true then
  705. render.drawSimpleText(sizeX/2-100, 1300 + #color*180, lang.cursor_on.."",0,1)
  706. else
  707. render.drawSimpleText(sizeX/2-100, 1300 + #color*180, lang.cursor_off.."",0,1)
  708. end
  709.  
  710. sizeToX = 1500
  711.  
  712. render.setColor(Color(255, 255, 255))
  713. render.setMaterial(mat[7])
  714. render.drawTexturedRectRotated(sizeX/2+190, 500+150, 300, 300,-45)
  715.  
  716. for i=1, #color do
  717. if use_color == i then
  718. render.setColor(Color(255, 255, 255))
  719. render.setMaterial(mat[7])
  720. render.drawTexturedRectRotated(sizeX/2, 750 + i*180, 150, 150,-45)
  721. end
  722.  
  723. render.setColor( ( color[i].color[1] ):setA(255))
  724. render.drawRoundedBox(120, -1400+sizeX, 680 + i*180, 150, 150)
  725.  
  726. render.setMaterial(nil)
  727. render.drawPoly( {{ x = sizeX/2-150, y = 680 + i*180 }, { x = sizeX/2-200, y = 680 + i*180 + 150 }, { x = sizeX/2-450, y = 680 + i*180+150 }, { x = sizeX/2-400, y = 680 + i*180 }} )
  728.  
  729. if inrange(8, 54 + i*14.5, 40, 12) then
  730. click_possible = true
  731. information(cx+4,cy+23, "" .. color[i].name .. " palettes" ,6400,font3)
  732. end
  733. end
  734.  
  735. render.setMaterial(nil)
  736. if show_visualizer == true then render.setColor(principal_color) else render.setColor(Color(255,255,255):setA(75)) end
  737. render.drawPoly( {{ x = sizeX/2-150, y = 1500 + #color*180 }, { x = sizeX/2-200, y = 1500 + #color*180 + 200 }, { x = sizeX/2-650, y = 1500 + #color*180 + 200 }, { x = sizeX/2-600, y = 1500 + #color*180 }} )
  738.  
  739. if show_cursor == true then render.setColor(principal_color) else render.setColor(Color(255,255,255):setA(75)) end
  740. render.drawPoly( {{ x = sizeX/2-150, y = 1200 + #color*180 }, { x = sizeX/2-200, y = 1200 + #color*180 + 200 }, { x = sizeX/2-650, y = 1200 + #color*180 + 200 }, { x = sizeX/2-600, y = 1200 + #color*180 }} )
  741.  
  742. render.setColor(Color(255,255,255))
  743. render.setFont(font2)
  744. render.drawText(sizeX/2-600, 1800 + #color*180, "ver. "..ver,0,1)
  745. else
  746. sizeToX, sizeToY = 0, 0
  747.  
  748. render.setColor(Color(255, 255, 255))
  749. render.setMaterial(mat[7])
  750. render.drawTexturedRectRotated(sizeX/2+110, 500+150, 300, 300,135)
  751. end
  752.  
  753. render.popMatrix()
  754.  
  755. -------------------------------------------------------
  756.  
  757. -- Click logic
  758. --Pressed
  759. if changed(player():keyDown(IN_KEY.USE)) and player():keyDown(IN_KEY.USE) then
  760. markElement(true)
  761.  
  762. if inrange(((sizeX/2)/6400)*512, (500/6400)*512, (300/6400)*512, (300/6400)*512) then
  763. color_menu = !color_menu
  764. end
  765.  
  766. for i=1, #color do
  767. if inrange(8, 54 + i*14.5, 40, 12) and color_menu == true then
  768. use_color = i
  769. end
  770. end
  771.  
  772. if inrange(((sizeX/2-650)/6400)*512, ((1500 + #color*180)/6400)*512, ( (sizeX/2-250) /6400)*512, (200/6400)*512) then
  773. show_visualizer = !show_visualizer
  774. end
  775.  
  776. if inrange(((sizeX/2-650)/6400)*512, ((1200 + #color*180)/6400)*512, ( (sizeX/2-250) /6400)*512, (200/6400)*512) then
  777. show_cursor = !show_cursor
  778. end
  779. end
  780.  
  781. --Released
  782. if player():keyDown(IN_KEY.USE) == false then
  783. markElement(false)
  784. end
  785.  
  786. -------------------------------------------------------
  787.  
  788. if inrange(((sizeX/2)/6400)*512, (500/6400)*512, (300/6400)*512, (300/6400)*512) then
  789. click_possible = true
  790. end
  791.  
  792. if inrange(((sizeX/2-650)/6400)*512, ((1500 + #color*180)/6400)*512, ( (sizeX/2-250) /6400)*512, (200/6400)*512) then
  793. click_possible = true
  794. end
  795.  
  796. if inrange(((sizeX/2-650)/6400)*512, ((1200 + #color*180)/6400)*512, ( (sizeX/2-250) /6400)*512, (200/6400)*512) then
  797. click_possible = true
  798. end
  799.  
  800. -- Draw slider
  801. for k, v in pairs(objects) do
  802. v:paint()
  803.  
  804. if v.can_change then
  805. if v.active then
  806. v:think()
  807. else
  808. if k == 2 then
  809. v.val = snd:getTime()
  810. end
  811. end
  812. else
  813. v:think()
  814. end
  815.  
  816. if inrange(v.x,v.y,v.w,v.h) then
  817. click_possible = true
  818. end
  819. end
  820. -------------------------------------------------------
  821.  
  822. if cx and cy and show_cursor then
  823. if click_possible then
  824. render.setColor((principal_color/1.3):setA(255))
  825. else
  826. render.setColor(principal_color)
  827. end
  828.  
  829. drawMouse(cx, cy)
  830. end
  831. end
  832.  
  833. end)
  834. end)
  835. end
  836.  
  837. -- Load playlist data
  838. function load_youtube()
  839. loading = "playlistItems.json"
  840. loaded = loaded + 1
  841.  
  842. http.get("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId="..playlist_id.."&key="..key,function(data)
  843. loaded = loaded + 1
  844. if track > json.decode(data).pageInfo.totalResults then
  845. track = math.clamp(json.decode(data).pageInfo.totalResults,0,50)
  846. end
  847. for v, item in pairs(json.decode(data).items) do
  848. if v == track then
  849. url = "https://www.youtube.com/watch?v="..item.snippet.resourceId.videoId
  850. end
  851.  
  852. playlist[v] = item
  853. end
  854. loading = url
  855.  
  856. timer.create("a",1,1,function()
  857. loaded = loaded + 1
  858. http.get("https://michaelbelgium.me/ytconverter/convert.php?youtubelink=" .. url, function(data)
  859. loaded = loaded + 1
  860. if json.decode(data).error then
  861. loading = "An error occurred cannot load the song.\nERROR: " .. json.decode(data).message
  862. else
  863. URL = json.decode(data).file
  864. title = json.decode(data).title
  865. id = json.decode(data).youtube_id
  866. length = json.decode(data).duration
  867.  
  868. timer.create("b",1,1,function()
  869. loaded = loaded + 1
  870. loading = "googleapis.com/youtube/v3/videos?part=snippet&id="..id.."&key=#######"
  871.  
  872. http.get("https://www.googleapis.com/youtube/v3/videos?part=snippet&id="..id.."&key="..key, function(data)
  873. loaded = loaded + 1
  874. for v, item in pairs(json.decode(data).items) do
  875. if item.snippet.thumbnails.maxres then
  876. thumbnail = item.snippet.thumbnails.maxres.url
  877. else
  878. thumbnail = "https://i.imgur.com/trTUlBW.png?1"
  879. end
  880. end
  881.  
  882. timer.create("c",1,1,function()
  883. loaded = loaded + 1
  884. loading = "googleapis.com/youtube/v3/playlists?part=snippet&id="..playlist_id.."&key=#######"
  885.  
  886. http.get("https://www.googleapis.com/youtube/v3/playlists?part=snippet&id="..playlist_id.."&key="..key, function(data)
  887. loaded = loaded + 1
  888. for v, item in pairs(json.decode(data).items) do
  889. list = item.snippet
  890. end
  891.  
  892. timer.create("d",1,1,function()
  893. hook.remove("render", "loading")
  894. load_texture()
  895. end)
  896. end)
  897. end)
  898. end)
  899. end)
  900. end
  901. end)
  902. end)
  903. end)
  904.  
  905. local l = 0
  906.  
  907. hook.add("render","loading",function()
  908. local m = Matrix()
  909. m:setScale(Vector(0.08))
  910. render.pushMatrix(m)
  911.  
  912. render.setColor(Color(255))
  913. render.setFont(font2)
  914. render.setFilterMag(1)
  915.  
  916. if loading == "" then
  917. render.drawText(3200, 3400, lang.load_error.."",1,1)
  918. if http.canRequest() then
  919. load_youtube()
  920. end
  921. else
  922. render.drawText(3200, 3400, loading,1,1)
  923.  
  924. render.drawText(1200, 2800, "Loaded " .. loaded .. "/8",0,1)
  925. end
  926.  
  927. render.popMatrix()
  928.  
  929. render.setColor(Color(170,170,170))
  930. render.drawRect(256-320/2,256-10,320,20)
  931.  
  932. l = math.lerp(0.2,l,loaded)
  933.  
  934. render.setColor(principal_color)
  935. render.drawRect(256-320/2+1,256-10+1,(l/8) * 320-2,20-2)
  936. end)
  937. end
  938. -------------------------------------------------------
  939.  
  940. -- Load texture
  941. function load_texture()
  942. for i=1, 7 do mat[i] = material.create("UnlitGeneric") end
  943.  
  944. mat[1]:setTextureURL("$basetexture", thumbnail)
  945. mat[2]:setTextureURL("$basetexture", "https://i.imgur.com/bEtY4vd.png?1") // Use 512x512 resolution
  946. //mat[2]:setTextureURL("$basetexture", "https://i.imgur.com/tXeR0gy.png") // Discord logo lol
  947. mat[3]:setTexture("$basetexture", "particle/particle_glow_04")
  948. mat[4]:setTexture("$basetexture", "vgui/gradient-u")
  949. mat[5]:setTexture("$basetexture", "vgui/gradient-d")
  950. mat[6]:setTexture("$basetexture", "vgui/gradient-l")
  951. mat[7]:setTexture("$basetexture", "vgui/cursors/arrow")
  952.  
  953. hook.remove("render", "loading")
  954. load()
  955. end
  956. -------------------------------------------------------
  957.  
  958. -- Find update
  959. function findUpdate()
  960. if http.canRequest() then
  961. http.get("https://pastebin.com/raw/sEvNPKaZ",function(data)
  962. version = string.split(data:sub(string.find(data:sub(1,150),"//version"),150)," ")[2]
  963.  
  964. if version != tostring(ver) then
  965. print(Color(255,150,70), "[SF Visualizer ver. "..ver.."] " .. lang.new_update .. "" .. version)
  966. else
  967. print(Color(70,255,70), "[SF Visualizer ver. "..ver.."] " .. lang.no_update .. "")
  968. end
  969. end)
  970. end
  971. end
  972. -------------------------------------------------------
  973.  
  974. -- Permission setup
  975. local perms = {
  976. "render.screen",
  977. "bass.loadURL",
  978. "bass.play2D",
  979. "material.create",
  980. "material.urlcreate",
  981. "light.create",
  982. "http.get"
  983. }
  984.  
  985. if owner() == player() then
  986. findUpdate()
  987.  
  988. timer.create("load",1,1,function()
  989. if http.canRequest() then
  990. load_youtube()
  991. end
  992. end)
  993. else
  994. setupPermissionRequest(perms, lang.perm_description.."", true)
  995.  
  996. if hasPermission("render.screen") then
  997. hook.add("render", "perms", function()
  998. render.drawSimpleText(256, 256, lang.accept_perm.."", 1, 1)
  999. end)
  1000. end
  1001.  
  1002. hook.add("permissionrequest", "perms", function()
  1003. if permissionRequestSatisfied() then
  1004. hook.remove("permissionrequest", "perms")
  1005. hook.remove("render", "perms")
  1006.  
  1007. if http.canRequest() then
  1008. load_youtube()
  1009. end
  1010. end
  1011. end)
  1012. end
  1013. -------------------------------------------------------
  1014. end
Add Comment
Please, Sign In to add comment