Advertisement
cat568

Untitled

Jan 23rd, 2019
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 267.36 KB | None | 0 0
  1.  
  2. --Converted with ttyyuu12345's model to script plugin v4
  3. function sandbox(var,func)
  4. local env = getfenv(func)
  5. local newenv = setmetatable({},{
  6. __index = function(self,k)
  7. if k=="script" then
  8. return var
  9. else
  10. return env[k]
  11. end
  12. end,
  13. })
  14. setfenv(func,newenv)
  15. return func
  16. end
  17. cors = {}
  18. mas = Instance.new("Model",game:GetService("Lighting"))
  19. Tool0 = Instance.new("Tool")
  20. LocalScript1 = Instance.new("LocalScript")
  21. LocalScript2 = Instance.new("LocalScript")
  22. LocalScript3 = Instance.new("LocalScript")
  23. LocalScript4 = Instance.new("LocalScript")
  24. LocalScript5 = Instance.new("LocalScript")
  25. LocalScript6 = Instance.new("LocalScript")
  26. LocalScript7 = Instance.new("LocalScript")
  27. LocalScript8 = Instance.new("LocalScript")
  28. LocalScript9 = Instance.new("LocalScript")
  29. LocalScript10 = Instance.new("LocalScript")
  30. LocalScript11 = Instance.new("LocalScript")
  31. LocalScript12 = Instance.new("LocalScript")
  32. LocalScript13 = Instance.new("LocalScript")
  33. LocalScript14 = Instance.new("LocalScript")
  34. LocalScript15 = Instance.new("LocalScript")
  35. RemoteFunction16 = Instance.new("RemoteFunction")
  36. Script17 = Instance.new("Script")
  37. RemoteFunction18 = Instance.new("RemoteFunction")
  38. Script19 = Instance.new("Script")
  39. LocalScript20 = Instance.new("LocalScript")
  40. Part21 = Instance.new("Part")
  41. Decal22 = Instance.new("Decal")
  42. Decal23 = Instance.new("Decal")
  43. Decal24 = Instance.new("Decal")
  44. Decal25 = Instance.new("Decal")
  45. Decal26 = Instance.new("Decal")
  46. Decal27 = Instance.new("Decal")
  47. Camera28 = Instance.new("Camera")
  48. Frame29 = Instance.new("Frame")
  49. Frame30 = Instance.new("Frame")
  50. Frame31 = Instance.new("Frame")
  51. Frame32 = Instance.new("Frame")
  52. TextLabel33 = Instance.new("TextLabel")
  53. TextLabel34 = Instance.new("TextLabel")
  54. Frame35 = Instance.new("Frame")
  55. TextLabel36 = Instance.new("TextLabel")
  56. Frame37 = Instance.new("Frame")
  57. Frame38 = Instance.new("Frame")
  58. TextButton39 = Instance.new("TextButton")
  59. ImageLabel40 = Instance.new("ImageLabel")
  60. TextLabel41 = Instance.new("TextLabel")
  61. Frame42 = Instance.new("Frame")
  62. Frame43 = Instance.new("Frame")
  63. TextButton44 = Instance.new("TextButton")
  64. ImageLabel45 = Instance.new("ImageLabel")
  65. TextLabel46 = Instance.new("TextLabel")
  66. Frame47 = Instance.new("Frame")
  67. Frame48 = Instance.new("Frame")
  68. TextLabel49 = Instance.new("TextLabel")
  69. Frame50 = Instance.new("Frame")
  70. Frame51 = Instance.new("Frame")
  71. Frame52 = Instance.new("Frame")
  72. TextLabel53 = Instance.new("TextLabel")
  73. TextLabel54 = Instance.new("TextLabel")
  74. Frame55 = Instance.new("Frame")
  75. TextLabel56 = Instance.new("TextLabel")
  76. Frame57 = Instance.new("Frame")
  77. Frame58 = Instance.new("Frame")
  78. TextButton59 = Instance.new("TextButton")
  79. ImageLabel60 = Instance.new("ImageLabel")
  80. TextLabel61 = Instance.new("TextLabel")
  81. Frame62 = Instance.new("Frame")
  82. Frame63 = Instance.new("Frame")
  83. TextButton64 = Instance.new("TextButton")
  84. ImageLabel65 = Instance.new("ImageLabel")
  85. TextLabel66 = Instance.new("TextLabel")
  86. Frame67 = Instance.new("Frame")
  87. Frame68 = Instance.new("Frame")
  88. TextLabel69 = Instance.new("TextLabel")
  89. Frame70 = Instance.new("Frame")
  90. Frame71 = Instance.new("Frame")
  91. TextLabel72 = Instance.new("TextLabel")
  92. TextLabel73 = Instance.new("TextLabel")
  93. Frame74 = Instance.new("Frame")
  94. Frame75 = Instance.new("Frame")
  95. Frame76 = Instance.new("Frame")
  96. Frame77 = Instance.new("Frame")
  97. Frame78 = Instance.new("Frame")
  98. Frame79 = Instance.new("Frame")
  99. Frame80 = Instance.new("Frame")
  100. TextLabel81 = Instance.new("TextLabel")
  101. Frame82 = Instance.new("Frame")
  102. Frame83 = Instance.new("Frame")
  103. Frame84 = Instance.new("Frame")
  104. Frame85 = Instance.new("Frame")
  105. Frame86 = Instance.new("Frame")
  106. Frame87 = Instance.new("Frame")
  107. Frame88 = Instance.new("Frame")
  108. TextButton89 = Instance.new("TextButton")
  109. Frame90 = Instance.new("Frame")
  110. Frame91 = Instance.new("Frame")
  111. Frame92 = Instance.new("Frame")
  112. Frame93 = Instance.new("Frame")
  113. Frame94 = Instance.new("Frame")
  114. Frame95 = Instance.new("Frame")
  115. Frame96 = Instance.new("Frame")
  116. Frame97 = Instance.new("Frame")
  117. TextLabel98 = Instance.new("TextLabel")
  118. Frame99 = Instance.new("Frame")
  119. Frame100 = Instance.new("Frame")
  120. Frame101 = Instance.new("Frame")
  121. Frame102 = Instance.new("Frame")
  122. Frame103 = Instance.new("Frame")
  123. Frame104 = Instance.new("Frame")
  124. TextButton105 = Instance.new("TextButton")
  125. Frame106 = Instance.new("Frame")
  126. Frame107 = Instance.new("Frame")
  127. Frame108 = Instance.new("Frame")
  128. Frame109 = Instance.new("Frame")
  129. TextLabel110 = Instance.new("TextLabel")
  130. TextLabel111 = Instance.new("TextLabel")
  131. Frame112 = Instance.new("Frame")
  132. TextLabel113 = Instance.new("TextLabel")
  133. Frame114 = Instance.new("Frame")
  134. TextLabel115 = Instance.new("TextLabel")
  135. Frame116 = Instance.new("Frame")
  136. TextButton117 = Instance.new("TextButton")
  137. ImageLabel118 = Instance.new("ImageLabel")
  138. Frame119 = Instance.new("Frame")
  139. TextBox120 = Instance.new("TextBox")
  140. Frame121 = Instance.new("Frame")
  141. TextLabel122 = Instance.new("TextLabel")
  142. Frame123 = Instance.new("Frame")
  143. TextButton124 = Instance.new("TextButton")
  144. Frame125 = Instance.new("Frame")
  145. ImageLabel126 = Instance.new("ImageLabel")
  146. TextBox127 = Instance.new("TextBox")
  147. Frame128 = Instance.new("Frame")
  148. Frame129 = Instance.new("Frame")
  149. TextLabel130 = Instance.new("TextLabel")
  150. Frame131 = Instance.new("Frame")
  151. Frame132 = Instance.new("Frame")
  152. Frame133 = Instance.new("Frame")
  153. Frame134 = Instance.new("Frame")
  154. TextButton135 = Instance.new("TextButton")
  155. ImageLabel136 = Instance.new("ImageLabel")
  156. TextLabel137 = Instance.new("TextLabel")
  157. Frame138 = Instance.new("Frame")
  158. Frame139 = Instance.new("Frame")
  159. TextButton140 = Instance.new("TextButton")
  160. ImageLabel141 = Instance.new("ImageLabel")
  161. TextLabel142 = Instance.new("TextLabel")
  162. Frame143 = Instance.new("Frame")
  163. Frame144 = Instance.new("Frame")
  164. TextButton145 = Instance.new("TextButton")
  165. ImageLabel146 = Instance.new("ImageLabel")
  166. TextLabel147 = Instance.new("TextLabel")
  167. Frame148 = Instance.new("Frame")
  168. TextLabel149 = Instance.new("TextLabel")
  169. Frame150 = Instance.new("Frame")
  170. Frame151 = Instance.new("Frame")
  171. TextLabel152 = Instance.new("TextLabel")
  172. TextLabel153 = Instance.new("TextLabel")
  173. Frame154 = Instance.new("Frame")
  174. Frame155 = Instance.new("Frame")
  175. Frame156 = Instance.new("Frame")
  176. TextBox157 = Instance.new("TextBox")
  177. ImageLabel158 = Instance.new("ImageLabel")
  178. Frame159 = Instance.new("Frame")
  179. TextLabel160 = Instance.new("TextLabel")
  180. Frame161 = Instance.new("Frame")
  181. Frame162 = Instance.new("Frame")
  182. TextLabel163 = Instance.new("TextLabel")
  183. Frame164 = Instance.new("Frame")
  184. TextLabel165 = Instance.new("TextLabel")
  185. Frame166 = Instance.new("Frame")
  186. ImageLabel167 = Instance.new("ImageLabel")
  187. TextButton168 = Instance.new("TextButton")
  188. TextBox169 = Instance.new("TextBox")
  189. Frame170 = Instance.new("Frame")
  190. ImageLabel171 = Instance.new("ImageLabel")
  191. TextBox172 = Instance.new("TextBox")
  192. TextButton173 = Instance.new("TextButton")
  193. Frame174 = Instance.new("Frame")
  194. TextBox175 = Instance.new("TextBox")
  195. TextButton176 = Instance.new("TextButton")
  196. ImageLabel177 = Instance.new("ImageLabel")
  197. Frame178 = Instance.new("Frame")
  198. Frame179 = Instance.new("Frame")
  199. TextLabel180 = Instance.new("TextLabel")
  200. Frame181 = Instance.new("Frame")
  201. Frame182 = Instance.new("Frame")
  202. Frame183 = Instance.new("Frame")
  203. TextLabel184 = Instance.new("TextLabel")
  204. TextLabel185 = Instance.new("TextLabel")
  205. Frame186 = Instance.new("Frame")
  206. TextLabel187 = Instance.new("TextLabel")
  207. Frame188 = Instance.new("Frame")
  208. Frame189 = Instance.new("Frame")
  209. TextLabel190 = Instance.new("TextLabel")
  210. Frame191 = Instance.new("Frame")
  211. Frame192 = Instance.new("Frame")
  212. Frame193 = Instance.new("Frame")
  213. TextLabel194 = Instance.new("TextLabel")
  214. TextLabel195 = Instance.new("TextLabel")
  215. Frame196 = Instance.new("Frame")
  216. TextButton197 = Instance.new("TextButton")
  217. TextButton198 = Instance.new("TextButton")
  218. TextButton199 = Instance.new("TextButton")
  219. TextButton200 = Instance.new("TextButton")
  220. TextButton201 = Instance.new("TextButton")
  221. TextButton202 = Instance.new("TextButton")
  222. TextButton203 = Instance.new("TextButton")
  223. TextButton204 = Instance.new("TextButton")
  224. TextButton205 = Instance.new("TextButton")
  225. TextButton206 = Instance.new("TextButton")
  226. TextButton207 = Instance.new("TextButton")
  227. TextButton208 = Instance.new("TextButton")
  228. TextButton209 = Instance.new("TextButton")
  229. TextButton210 = Instance.new("TextButton")
  230. TextButton211 = Instance.new("TextButton")
  231. TextButton212 = Instance.new("TextButton")
  232. TextButton213 = Instance.new("TextButton")
  233. TextButton214 = Instance.new("TextButton")
  234. TextButton215 = Instance.new("TextButton")
  235. TextButton216 = Instance.new("TextButton")
  236. TextButton217 = Instance.new("TextButton")
  237. TextButton218 = Instance.new("TextButton")
  238. TextButton219 = Instance.new("TextButton")
  239. TextButton220 = Instance.new("TextButton")
  240. TextButton221 = Instance.new("TextButton")
  241. TextButton222 = Instance.new("TextButton")
  242. TextButton223 = Instance.new("TextButton")
  243. TextButton224 = Instance.new("TextButton")
  244. TextButton225 = Instance.new("TextButton")
  245. TextButton226 = Instance.new("TextButton")
  246. TextButton227 = Instance.new("TextButton")
  247. TextButton228 = Instance.new("TextButton")
  248. TextButton229 = Instance.new("TextButton")
  249. TextButton230 = Instance.new("TextButton")
  250. TextButton231 = Instance.new("TextButton")
  251. TextButton232 = Instance.new("TextButton")
  252. TextButton233 = Instance.new("TextButton")
  253. TextButton234 = Instance.new("TextButton")
  254. TextButton235 = Instance.new("TextButton")
  255. TextButton236 = Instance.new("TextButton")
  256. TextButton237 = Instance.new("TextButton")
  257. TextButton238 = Instance.new("TextButton")
  258. TextButton239 = Instance.new("TextButton")
  259. TextButton240 = Instance.new("TextButton")
  260. TextButton241 = Instance.new("TextButton")
  261. TextButton242 = Instance.new("TextButton")
  262. TextButton243 = Instance.new("TextButton")
  263. TextButton244 = Instance.new("TextButton")
  264. TextButton245 = Instance.new("TextButton")
  265. TextButton246 = Instance.new("TextButton")
  266. TextButton247 = Instance.new("TextButton")
  267. TextButton248 = Instance.new("TextButton")
  268. TextButton249 = Instance.new("TextButton")
  269. TextButton250 = Instance.new("TextButton")
  270. TextButton251 = Instance.new("TextButton")
  271. TextButton252 = Instance.new("TextButton")
  272. TextButton253 = Instance.new("TextButton")
  273. TextButton254 = Instance.new("TextButton")
  274. TextButton255 = Instance.new("TextButton")
  275. TextButton256 = Instance.new("TextButton")
  276. TextButton257 = Instance.new("TextButton")
  277. TextButton258 = Instance.new("TextButton")
  278. TextButton259 = Instance.new("TextButton")
  279. TextButton260 = Instance.new("TextButton")
  280. Frame261 = Instance.new("Frame")
  281. Frame262 = Instance.new("Frame")
  282. Frame263 = Instance.new("Frame")
  283. Frame264 = Instance.new("Frame")
  284. TextButton265 = Instance.new("TextButton")
  285. ImageLabel266 = Instance.new("ImageLabel")
  286. TextLabel267 = Instance.new("TextLabel")
  287. Frame268 = Instance.new("Frame")
  288. Frame269 = Instance.new("Frame")
  289. TextButton270 = Instance.new("TextButton")
  290. ImageLabel271 = Instance.new("ImageLabel")
  291. TextLabel272 = Instance.new("TextLabel")
  292. Frame273 = Instance.new("Frame")
  293. TextLabel274 = Instance.new("TextLabel")
  294. Frame275 = Instance.new("Frame")
  295. Frame276 = Instance.new("Frame")
  296. TextLabel277 = Instance.new("TextLabel")
  297. TextLabel278 = Instance.new("TextLabel")
  298. Frame279 = Instance.new("Frame")
  299. Frame280 = Instance.new("Frame")
  300. Frame281 = Instance.new("Frame")
  301. TextBox282 = Instance.new("TextBox")
  302. ImageLabel283 = Instance.new("ImageLabel")
  303. Frame284 = Instance.new("Frame")
  304. TextLabel285 = Instance.new("TextLabel")
  305. Frame286 = Instance.new("Frame")
  306. Frame287 = Instance.new("Frame")
  307. TextLabel288 = Instance.new("TextLabel")
  308. Frame289 = Instance.new("Frame")
  309. TextLabel290 = Instance.new("TextLabel")
  310. Frame291 = Instance.new("Frame")
  311. TextBox292 = Instance.new("TextBox")
  312. TextButton293 = Instance.new("TextButton")
  313. ImageLabel294 = Instance.new("ImageLabel")
  314. Frame295 = Instance.new("Frame")
  315. TextBox296 = Instance.new("TextBox")
  316. TextButton297 = Instance.new("TextButton")
  317. ImageLabel298 = Instance.new("ImageLabel")
  318. Frame299 = Instance.new("Frame")
  319. TextBox300 = Instance.new("TextBox")
  320. TextButton301 = Instance.new("TextButton")
  321. ImageLabel302 = Instance.new("ImageLabel")
  322. Frame303 = Instance.new("Frame")
  323. Frame304 = Instance.new("Frame")
  324. TextLabel305 = Instance.new("TextLabel")
  325. Frame306 = Instance.new("Frame")
  326. Frame307 = Instance.new("Frame")
  327. Frame308 = Instance.new("Frame")
  328. Frame309 = Instance.new("Frame")
  329. TextButton310 = Instance.new("TextButton")
  330. ImageLabel311 = Instance.new("ImageLabel")
  331. TextLabel312 = Instance.new("TextLabel")
  332. Frame313 = Instance.new("Frame")
  333. Frame314 = Instance.new("Frame")
  334. TextButton315 = Instance.new("TextButton")
  335. ImageLabel316 = Instance.new("ImageLabel")
  336. TextLabel317 = Instance.new("TextLabel")
  337. Frame318 = Instance.new("Frame")
  338. Frame319 = Instance.new("Frame")
  339. TextButton320 = Instance.new("TextButton")
  340. ImageLabel321 = Instance.new("ImageLabel")
  341. TextLabel322 = Instance.new("TextLabel")
  342. Frame323 = Instance.new("Frame")
  343. TextLabel324 = Instance.new("TextLabel")
  344. Frame325 = Instance.new("Frame")
  345. Frame326 = Instance.new("Frame")
  346. TextLabel327 = Instance.new("TextLabel")
  347. TextLabel328 = Instance.new("TextLabel")
  348. Frame329 = Instance.new("Frame")
  349. Frame330 = Instance.new("Frame")
  350. Frame331 = Instance.new("Frame")
  351. TextBox332 = Instance.new("TextBox")
  352. ImageLabel333 = Instance.new("ImageLabel")
  353. Frame334 = Instance.new("Frame")
  354. TextLabel335 = Instance.new("TextLabel")
  355. Frame336 = Instance.new("Frame")
  356. Frame337 = Instance.new("Frame")
  357. TextLabel338 = Instance.new("TextLabel")
  358. Frame339 = Instance.new("Frame")
  359. TextLabel340 = Instance.new("TextLabel")
  360. Frame341 = Instance.new("Frame")
  361. TextBox342 = Instance.new("TextBox")
  362. TextButton343 = Instance.new("TextButton")
  363. ImageLabel344 = Instance.new("ImageLabel")
  364. Frame345 = Instance.new("Frame")
  365. TextBox346 = Instance.new("TextBox")
  366. TextButton347 = Instance.new("TextButton")
  367. ImageLabel348 = Instance.new("ImageLabel")
  368. Frame349 = Instance.new("Frame")
  369. TextBox350 = Instance.new("TextBox")
  370. TextButton351 = Instance.new("TextButton")
  371. ImageLabel352 = Instance.new("ImageLabel")
  372. Frame353 = Instance.new("Frame")
  373. Frame354 = Instance.new("Frame")
  374. TextLabel355 = Instance.new("TextLabel")
  375. TextLabel356 = Instance.new("TextLabel")
  376. Frame357 = Instance.new("Frame")
  377. Frame358 = Instance.new("Frame")
  378. Frame359 = Instance.new("Frame")
  379. TextLabel360 = Instance.new("TextLabel")
  380. TextLabel361 = Instance.new("TextLabel")
  381. Frame362 = Instance.new("Frame")
  382. TextLabel363 = Instance.new("TextLabel")
  383. Frame364 = Instance.new("Frame")
  384. TextLabel365 = Instance.new("TextLabel")
  385. Frame366 = Instance.new("Frame")
  386. Frame367 = Instance.new("Frame")
  387. TextLabel368 = Instance.new("TextLabel")
  388. Frame369 = Instance.new("Frame")
  389. Frame370 = Instance.new("Frame")
  390. Frame371 = Instance.new("Frame")
  391. TextLabel372 = Instance.new("TextLabel")
  392. TextLabel373 = Instance.new("TextLabel")
  393. Frame374 = Instance.new("Frame")
  394. TextLabel375 = Instance.new("TextLabel")
  395. Frame376 = Instance.new("Frame")
  396. TextLabel377 = Instance.new("TextLabel")
  397. Frame378 = Instance.new("Frame")
  398. TextButton379 = Instance.new("TextButton")
  399. ImageLabel380 = Instance.new("ImageLabel")
  400. Frame381 = Instance.new("Frame")
  401. TextBox382 = Instance.new("TextBox")
  402. Frame383 = Instance.new("Frame")
  403. TextButton384 = Instance.new("TextButton")
  404. ImageLabel385 = Instance.new("ImageLabel")
  405. Frame386 = Instance.new("Frame")
  406. TextBox387 = Instance.new("TextBox")
  407. Frame388 = Instance.new("Frame")
  408. Frame389 = Instance.new("Frame")
  409. TextLabel390 = Instance.new("TextLabel")
  410. Frame391 = Instance.new("Frame")
  411. TextButton392 = Instance.new("TextButton")
  412. ImageLabel393 = Instance.new("ImageLabel")
  413. Frame394 = Instance.new("Frame")
  414. TextBox395 = Instance.new("TextBox")
  415. Frame396 = Instance.new("Frame")
  416. TextLabel397 = Instance.new("TextLabel")
  417. Frame398 = Instance.new("Frame")
  418. Frame399 = Instance.new("Frame")
  419. TextButton400 = Instance.new("TextButton")
  420. ImageLabel401 = Instance.new("ImageLabel")
  421. TextLabel402 = Instance.new("TextLabel")
  422. Frame403 = Instance.new("Frame")
  423. TextButton404 = Instance.new("TextButton")
  424. ImageLabel405 = Instance.new("ImageLabel")
  425. TextLabel406 = Instance.new("TextLabel")
  426. Frame407 = Instance.new("Frame")
  427. Frame408 = Instance.new("Frame")
  428. TextLabel409 = Instance.new("TextLabel")
  429. Frame410 = Instance.new("Frame")
  430. Frame411 = Instance.new("Frame")
  431. Frame412 = Instance.new("Frame")
  432. Frame413 = Instance.new("Frame")
  433. Frame414 = Instance.new("Frame")
  434. TextButton415 = Instance.new("TextButton")
  435. TextBox416 = Instance.new("TextBox")
  436. Frame417 = Instance.new("Frame")
  437. TextButton418 = Instance.new("TextButton")
  438. Frame419 = Instance.new("Frame")
  439. Frame420 = Instance.new("Frame")
  440. TextButton421 = Instance.new("TextButton")
  441. Frame422 = Instance.new("Frame")
  442. TextLabel423 = Instance.new("TextLabel")
  443. Frame424 = Instance.new("Frame")
  444. Frame425 = Instance.new("Frame")
  445. Frame426 = Instance.new("Frame")
  446. TextLabel427 = Instance.new("TextLabel")
  447. TextLabel428 = Instance.new("TextLabel")
  448. Frame429 = Instance.new("Frame")
  449. TextButton430 = Instance.new("TextButton")
  450. Frame431 = Instance.new("Frame")
  451. TextButton432 = Instance.new("TextButton")
  452. Frame433 = Instance.new("Frame")
  453. Frame434 = Instance.new("Frame")
  454. Frame435 = Instance.new("Frame")
  455. TextLabel436 = Instance.new("TextLabel")
  456. Frame437 = Instance.new("Frame")
  457. Frame438 = Instance.new("Frame")
  458. Frame439 = Instance.new("Frame")
  459. Frame440 = Instance.new("Frame")
  460. TextLabel441 = Instance.new("TextLabel")
  461. TextLabel442 = Instance.new("TextLabel")
  462. Frame443 = Instance.new("Frame")
  463. TextLabel444 = Instance.new("TextLabel")
  464. ImageButton445 = Instance.new("ImageButton")
  465. Frame446 = Instance.new("Frame")
  466. TextButton447 = Instance.new("TextButton")
  467. TextButton448 = Instance.new("TextButton")
  468. Frame449 = Instance.new("Frame")
  469. Frame450 = Instance.new("Frame")
  470. Frame451 = Instance.new("Frame")
  471. TextLabel452 = Instance.new("TextLabel")
  472. Frame453 = Instance.new("Frame")
  473. TextButton454 = Instance.new("TextButton")
  474. ImageLabel455 = Instance.new("ImageLabel")
  475. Frame456 = Instance.new("Frame")
  476. TextBox457 = Instance.new("TextBox")
  477. Frame458 = Instance.new("Frame")
  478. TextButton459 = Instance.new("TextButton")
  479. ImageLabel460 = Instance.new("ImageLabel")
  480. Frame461 = Instance.new("Frame")
  481. TextBox462 = Instance.new("TextBox")
  482. Frame463 = Instance.new("Frame")
  483. TextButton464 = Instance.new("TextButton")
  484. ImageLabel465 = Instance.new("ImageLabel")
  485. Frame466 = Instance.new("Frame")
  486. TextBox467 = Instance.new("TextBox")
  487. ImageButton468 = Instance.new("ImageButton")
  488. Frame469 = Instance.new("Frame")
  489. Frame470 = Instance.new("Frame")
  490. Frame471 = Instance.new("Frame")
  491. Frame472 = Instance.new("Frame")
  492. Frame473 = Instance.new("Frame")
  493. TextLabel474 = Instance.new("TextLabel")
  494. Frame475 = Instance.new("Frame")
  495. TextButton476 = Instance.new("TextButton")
  496. ImageLabel477 = Instance.new("ImageLabel")
  497. Frame478 = Instance.new("Frame")
  498. TextBox479 = Instance.new("TextBox")
  499. Frame480 = Instance.new("Frame")
  500. TextLabel481 = Instance.new("TextLabel")
  501. Frame482 = Instance.new("Frame")
  502. TextButton483 = Instance.new("TextButton")
  503. ImageLabel484 = Instance.new("ImageLabel")
  504. Frame485 = Instance.new("Frame")
  505. TextBox486 = Instance.new("TextBox")
  506. Frame487 = Instance.new("Frame")
  507. TextLabel488 = Instance.new("TextLabel")
  508. Frame489 = Instance.new("Frame")
  509. TextButton490 = Instance.new("TextButton")
  510. ImageLabel491 = Instance.new("ImageLabel")
  511. Frame492 = Instance.new("Frame")
  512. TextBox493 = Instance.new("TextBox")
  513. Frame494 = Instance.new("Frame")
  514. TextLabel495 = Instance.new("TextLabel")
  515. Frame496 = Instance.new("Frame")
  516. TextLabel497 = Instance.new("TextLabel")
  517. Frame498 = Instance.new("Frame")
  518. Frame499 = Instance.new("Frame")
  519. TextButton500 = Instance.new("TextButton")
  520. ImageLabel501 = Instance.new("ImageLabel")
  521. TextLabel502 = Instance.new("TextLabel")
  522. Frame503 = Instance.new("Frame")
  523. Frame504 = Instance.new("Frame")
  524. TextButton505 = Instance.new("TextButton")
  525. ImageLabel506 = Instance.new("ImageLabel")
  526. TextLabel507 = Instance.new("TextLabel")
  527. TextLabel508 = Instance.new("TextLabel")
  528. Frame509 = Instance.new("Frame")
  529. TextLabel510 = Instance.new("TextLabel")
  530. ImageButton511 = Instance.new("ImageButton")
  531. Frame512 = Instance.new("Frame")
  532. TextButton513 = Instance.new("TextButton")
  533. TextButton514 = Instance.new("TextButton")
  534. Frame515 = Instance.new("Frame")
  535. Frame516 = Instance.new("Frame")
  536. Frame517 = Instance.new("Frame")
  537. TextLabel518 = Instance.new("TextLabel")
  538. Frame519 = Instance.new("Frame")
  539. TextButton520 = Instance.new("TextButton")
  540. ImageLabel521 = Instance.new("ImageLabel")
  541. Frame522 = Instance.new("Frame")
  542. TextBox523 = Instance.new("TextBox")
  543. Frame524 = Instance.new("Frame")
  544. TextButton525 = Instance.new("TextButton")
  545. ImageLabel526 = Instance.new("ImageLabel")
  546. Frame527 = Instance.new("Frame")
  547. TextBox528 = Instance.new("TextBox")
  548. Frame529 = Instance.new("Frame")
  549. TextButton530 = Instance.new("TextButton")
  550. ImageLabel531 = Instance.new("ImageLabel")
  551. Frame532 = Instance.new("Frame")
  552. TextBox533 = Instance.new("TextBox")
  553. ImageButton534 = Instance.new("ImageButton")
  554. Frame535 = Instance.new("Frame")
  555. Frame536 = Instance.new("Frame")
  556. Frame537 = Instance.new("Frame")
  557. Frame538 = Instance.new("Frame")
  558. Frame539 = Instance.new("Frame")
  559. TextLabel540 = Instance.new("TextLabel")
  560. Frame541 = Instance.new("Frame")
  561. TextButton542 = Instance.new("TextButton")
  562. ImageLabel543 = Instance.new("ImageLabel")
  563. Frame544 = Instance.new("Frame")
  564. TextBox545 = Instance.new("TextBox")
  565. Frame546 = Instance.new("Frame")
  566. TextLabel547 = Instance.new("TextLabel")
  567. Frame548 = Instance.new("Frame")
  568. TextButton549 = Instance.new("TextButton")
  569. ImageLabel550 = Instance.new("ImageLabel")
  570. Frame551 = Instance.new("Frame")
  571. TextBox552 = Instance.new("TextBox")
  572. Frame553 = Instance.new("Frame")
  573. TextLabel554 = Instance.new("TextLabel")
  574. Frame555 = Instance.new("Frame")
  575. Frame556 = Instance.new("Frame")
  576. TextButton557 = Instance.new("TextButton")
  577. ImageLabel558 = Instance.new("ImageLabel")
  578. TextLabel559 = Instance.new("TextLabel")
  579. Frame560 = Instance.new("Frame")
  580. Frame561 = Instance.new("Frame")
  581. TextButton562 = Instance.new("TextButton")
  582. ImageLabel563 = Instance.new("ImageLabel")
  583. TextLabel564 = Instance.new("TextLabel")
  584. Frame565 = Instance.new("Frame")
  585. ImageButton566 = Instance.new("ImageButton")
  586. ImageLabel567 = Instance.new("ImageLabel")
  587. ImageButton568 = Instance.new("ImageButton")
  588. Frame569 = Instance.new("Frame")
  589. ImageLabel570 = Instance.new("ImageLabel")
  590. Frame571 = Instance.new("Frame")
  591. TextLabel572 = Instance.new("TextLabel")
  592. Frame573 = Instance.new("Frame")
  593. TextButton574 = Instance.new("TextButton")
  594. ImageLabel575 = Instance.new("ImageLabel")
  595. TextBox576 = Instance.new("TextBox")
  596. Frame577 = Instance.new("Frame")
  597. Frame578 = Instance.new("Frame")
  598. Frame579 = Instance.new("Frame")
  599. TextLabel580 = Instance.new("TextLabel")
  600. Frame581 = Instance.new("Frame")
  601. TextButton582 = Instance.new("TextButton")
  602. ImageLabel583 = Instance.new("ImageLabel")
  603. TextBox584 = Instance.new("TextBox")
  604. Frame585 = Instance.new("Frame")
  605. Frame586 = Instance.new("Frame")
  606. Frame587 = Instance.new("Frame")
  607. TextLabel588 = Instance.new("TextLabel")
  608. Frame589 = Instance.new("Frame")
  609. TextButton590 = Instance.new("TextButton")
  610. ImageLabel591 = Instance.new("ImageLabel")
  611. TextBox592 = Instance.new("TextBox")
  612. Frame593 = Instance.new("Frame")
  613. Frame594 = Instance.new("Frame")
  614. Frame595 = Instance.new("Frame")
  615. Frame596 = Instance.new("Frame")
  616. TextButton597 = Instance.new("TextButton")
  617. Frame598 = Instance.new("Frame")
  618. TextButton599 = Instance.new("TextButton")
  619. Frame600 = Instance.new("Frame")
  620. Frame601 = Instance.new("Frame")
  621. Frame602 = Instance.new("Frame")
  622. Frame603 = Instance.new("Frame")
  623. TextLabel604 = Instance.new("TextLabel")
  624. TextLabel605 = Instance.new("TextLabel")
  625. Frame606 = Instance.new("Frame")
  626. TextLabel607 = Instance.new("TextLabel")
  627. Frame608 = Instance.new("Frame")
  628. TextLabel609 = Instance.new("TextLabel")
  629. Frame610 = Instance.new("Frame")
  630. TextButton611 = Instance.new("TextButton")
  631. ImageLabel612 = Instance.new("ImageLabel")
  632. Frame613 = Instance.new("Frame")
  633. TextBox614 = Instance.new("TextBox")
  634. Frame615 = Instance.new("Frame")
  635. TextButton616 = Instance.new("TextButton")
  636. ImageLabel617 = Instance.new("ImageLabel")
  637. Frame618 = Instance.new("Frame")
  638. TextBox619 = Instance.new("TextBox")
  639. Frame620 = Instance.new("Frame")
  640. TextButton621 = Instance.new("TextButton")
  641. ImageLabel622 = Instance.new("ImageLabel")
  642. Frame623 = Instance.new("Frame")
  643. TextBox624 = Instance.new("TextBox")
  644. Frame625 = Instance.new("Frame")
  645. TextButton626 = Instance.new("TextButton")
  646. Frame627 = Instance.new("Frame")
  647. Frame628 = Instance.new("Frame")
  648. TextLabel629 = Instance.new("TextLabel")
  649. TextBox630 = Instance.new("TextBox")
  650. Frame631 = Instance.new("Frame")
  651. Frame632 = Instance.new("Frame")
  652. Frame633 = Instance.new("Frame")
  653. Frame634 = Instance.new("Frame")
  654. Frame635 = Instance.new("Frame")
  655. TextButton636 = Instance.new("TextButton")
  656. Frame637 = Instance.new("Frame")
  657. Frame638 = Instance.new("Frame")
  658. TextLabel639 = Instance.new("TextLabel")
  659. TextBox640 = Instance.new("TextBox")
  660. Frame641 = Instance.new("Frame")
  661. Frame642 = Instance.new("Frame")
  662. Frame643 = Instance.new("Frame")
  663. Frame644 = Instance.new("Frame")
  664. Frame645 = Instance.new("Frame")
  665. TextButton646 = Instance.new("TextButton")
  666. Frame647 = Instance.new("Frame")
  667. TextButton648 = Instance.new("TextButton")
  668. Frame649 = Instance.new("Frame")
  669. Frame650 = Instance.new("Frame")
  670. TextLabel651 = Instance.new("TextLabel")
  671. Frame652 = Instance.new("Frame")
  672. TextButton653 = Instance.new("TextButton")
  673. ImageLabel654 = Instance.new("ImageLabel")
  674. Frame655 = Instance.new("Frame")
  675. TextBox656 = Instance.new("TextBox")
  676. Frame657 = Instance.new("Frame")
  677. TextButton658 = Instance.new("TextButton")
  678. ImageLabel659 = Instance.new("ImageLabel")
  679. Frame660 = Instance.new("Frame")
  680. TextBox661 = Instance.new("TextBox")
  681. Frame662 = Instance.new("Frame")
  682. TextButton663 = Instance.new("TextButton")
  683. ImageLabel664 = Instance.new("ImageLabel")
  684. Frame665 = Instance.new("Frame")
  685. TextBox666 = Instance.new("TextBox")
  686. Frame667 = Instance.new("Frame")
  687. Frame668 = Instance.new("Frame")
  688. Frame669 = Instance.new("Frame")
  689. ImageButton670 = Instance.new("ImageButton")
  690. Frame671 = Instance.new("Frame")
  691. TextLabel672 = Instance.new("TextLabel")
  692. Frame673 = Instance.new("Frame")
  693. Frame674 = Instance.new("Frame")
  694. Frame675 = Instance.new("Frame")
  695. Frame676 = Instance.new("Frame")
  696. TextLabel677 = Instance.new("TextLabel")
  697. TextLabel678 = Instance.new("TextLabel")
  698. Frame679 = Instance.new("Frame")
  699. TextLabel680 = Instance.new("TextLabel")
  700. ImageButton681 = Instance.new("ImageButton")
  701. Frame682 = Instance.new("Frame")
  702. TextButton683 = Instance.new("TextButton")
  703. TextButton684 = Instance.new("TextButton")
  704. Frame685 = Instance.new("Frame")
  705. Frame686 = Instance.new("Frame")
  706. Frame687 = Instance.new("Frame")
  707. TextLabel688 = Instance.new("TextLabel")
  708. Frame689 = Instance.new("Frame")
  709. TextButton690 = Instance.new("TextButton")
  710. ImageLabel691 = Instance.new("ImageLabel")
  711. Frame692 = Instance.new("Frame")
  712. TextBox693 = Instance.new("TextBox")
  713. Frame694 = Instance.new("Frame")
  714. TextButton695 = Instance.new("TextButton")
  715. ImageLabel696 = Instance.new("ImageLabel")
  716. Frame697 = Instance.new("Frame")
  717. TextBox698 = Instance.new("TextBox")
  718. Frame699 = Instance.new("Frame")
  719. TextButton700 = Instance.new("TextButton")
  720. ImageLabel701 = Instance.new("ImageLabel")
  721. Frame702 = Instance.new("Frame")
  722. TextBox703 = Instance.new("TextBox")
  723. ImageButton704 = Instance.new("ImageButton")
  724. Frame705 = Instance.new("Frame")
  725. Frame706 = Instance.new("Frame")
  726. Frame707 = Instance.new("Frame")
  727. Frame708 = Instance.new("Frame")
  728. Frame709 = Instance.new("Frame")
  729. TextLabel710 = Instance.new("TextLabel")
  730. Frame711 = Instance.new("Frame")
  731. TextButton712 = Instance.new("TextButton")
  732. ImageLabel713 = Instance.new("ImageLabel")
  733. Frame714 = Instance.new("Frame")
  734. TextBox715 = Instance.new("TextBox")
  735. Frame716 = Instance.new("Frame")
  736. TextLabel717 = Instance.new("TextLabel")
  737. Frame718 = Instance.new("Frame")
  738. TextButton719 = Instance.new("TextButton")
  739. ImageLabel720 = Instance.new("ImageLabel")
  740. Frame721 = Instance.new("Frame")
  741. TextBox722 = Instance.new("TextBox")
  742. Frame723 = Instance.new("Frame")
  743. TextLabel724 = Instance.new("TextLabel")
  744. Frame725 = Instance.new("Frame")
  745. TextButton726 = Instance.new("TextButton")
  746. ImageLabel727 = Instance.new("ImageLabel")
  747. Frame728 = Instance.new("Frame")
  748. TextBox729 = Instance.new("TextBox")
  749. TextLabel730 = Instance.new("TextLabel")
  750. Frame731 = Instance.new("Frame")
  751. TextLabel732 = Instance.new("TextLabel")
  752. ImageButton733 = Instance.new("ImageButton")
  753. Frame734 = Instance.new("Frame")
  754. TextButton735 = Instance.new("TextButton")
  755. TextButton736 = Instance.new("TextButton")
  756. Frame737 = Instance.new("Frame")
  757. Frame738 = Instance.new("Frame")
  758. Frame739 = Instance.new("Frame")
  759. TextLabel740 = Instance.new("TextLabel")
  760. Frame741 = Instance.new("Frame")
  761. TextButton742 = Instance.new("TextButton")
  762. ImageLabel743 = Instance.new("ImageLabel")
  763. Frame744 = Instance.new("Frame")
  764. TextBox745 = Instance.new("TextBox")
  765. Frame746 = Instance.new("Frame")
  766. TextButton747 = Instance.new("TextButton")
  767. ImageLabel748 = Instance.new("ImageLabel")
  768. Frame749 = Instance.new("Frame")
  769. TextBox750 = Instance.new("TextBox")
  770. Frame751 = Instance.new("Frame")
  771. TextButton752 = Instance.new("TextButton")
  772. ImageLabel753 = Instance.new("ImageLabel")
  773. Frame754 = Instance.new("Frame")
  774. TextBox755 = Instance.new("TextBox")
  775. ImageButton756 = Instance.new("ImageButton")
  776. Frame757 = Instance.new("Frame")
  777. Frame758 = Instance.new("Frame")
  778. Frame759 = Instance.new("Frame")
  779. Frame760 = Instance.new("Frame")
  780. Frame761 = Instance.new("Frame")
  781. TextLabel762 = Instance.new("TextLabel")
  782. Frame763 = Instance.new("Frame")
  783. TextButton764 = Instance.new("TextButton")
  784. ImageLabel765 = Instance.new("ImageLabel")
  785. Frame766 = Instance.new("Frame")
  786. TextBox767 = Instance.new("TextBox")
  787. Frame768 = Instance.new("Frame")
  788. TextLabel769 = Instance.new("TextLabel")
  789. Frame770 = Instance.new("Frame")
  790. TextButton771 = Instance.new("TextButton")
  791. ImageLabel772 = Instance.new("ImageLabel")
  792. Frame773 = Instance.new("Frame")
  793. TextBox774 = Instance.new("TextBox")
  794. Frame775 = Instance.new("Frame")
  795. TextLabel776 = Instance.new("TextLabel")
  796. Frame777 = Instance.new("Frame")
  797. TextButton778 = Instance.new("TextButton")
  798. ImageLabel779 = Instance.new("ImageLabel")
  799. Frame780 = Instance.new("Frame")
  800. TextBox781 = Instance.new("TextBox")
  801. Frame782 = Instance.new("Frame")
  802. TextButton783 = Instance.new("TextButton")
  803. ImageLabel784 = Instance.new("ImageLabel")
  804. Frame785 = Instance.new("Frame")
  805. TextBox786 = Instance.new("TextBox")
  806. Frame787 = Instance.new("Frame")
  807. TextButton788 = Instance.new("TextButton")
  808. ImageLabel789 = Instance.new("ImageLabel")
  809. Frame790 = Instance.new("Frame")
  810. TextBox791 = Instance.new("TextBox")
  811. ImageButton792 = Instance.new("ImageButton")
  812. Frame793 = Instance.new("Frame")
  813. Frame794 = Instance.new("Frame")
  814. Frame795 = Instance.new("Frame")
  815. Frame796 = Instance.new("Frame")
  816. Frame797 = Instance.new("Frame")
  817. TextLabel798 = Instance.new("TextLabel")
  818. ImageButton799 = Instance.new("ImageButton")
  819. Frame800 = Instance.new("Frame")
  820. TextButton801 = Instance.new("TextButton")
  821. TextButton802 = Instance.new("TextButton")
  822. Frame803 = Instance.new("Frame")
  823. Frame804 = Instance.new("Frame")
  824. Frame805 = Instance.new("Frame")
  825. TextLabel806 = Instance.new("TextLabel")
  826. Frame807 = Instance.new("Frame")
  827. TextButton808 = Instance.new("TextButton")
  828. ImageLabel809 = Instance.new("ImageLabel")
  829. Frame810 = Instance.new("Frame")
  830. TextBox811 = Instance.new("TextBox")
  831. Frame812 = Instance.new("Frame")
  832. TextButton813 = Instance.new("TextButton")
  833. ImageLabel814 = Instance.new("ImageLabel")
  834. Frame815 = Instance.new("Frame")
  835. TextBox816 = Instance.new("TextBox")
  836. Frame817 = Instance.new("Frame")
  837. TextButton818 = Instance.new("TextButton")
  838. ImageLabel819 = Instance.new("ImageLabel")
  839. Frame820 = Instance.new("Frame")
  840. TextBox821 = Instance.new("TextBox")
  841. ImageButton822 = Instance.new("ImageButton")
  842. Frame823 = Instance.new("Frame")
  843. Frame824 = Instance.new("Frame")
  844. Frame825 = Instance.new("Frame")
  845. Frame826 = Instance.new("Frame")
  846. Frame827 = Instance.new("Frame")
  847. Frame828 = Instance.new("Frame")
  848. Frame829 = Instance.new("Frame")
  849. Frame830 = Instance.new("Frame")
  850. Frame831 = Instance.new("Frame")
  851. Frame832 = Instance.new("Frame")
  852. TextLabel833 = Instance.new("TextLabel")
  853. TextLabel834 = Instance.new("TextLabel")
  854. TextLabel835 = Instance.new("TextLabel")
  855. TextLabel836 = Instance.new("TextLabel")
  856. Frame837 = Instance.new("Frame")
  857. TextLabel838 = Instance.new("TextLabel")
  858. TextLabel839 = Instance.new("TextLabel")
  859. Frame840 = Instance.new("Frame")
  860. TextLabel841 = Instance.new("TextLabel")
  861. TextLabel842 = Instance.new("TextLabel")
  862. Frame843 = Instance.new("Frame")
  863. Frame844 = Instance.new("Frame")
  864. Frame845 = Instance.new("Frame")
  865. TextLabel846 = Instance.new("TextLabel")
  866. TextLabel847 = Instance.new("TextLabel")
  867. Frame848 = Instance.new("Frame")
  868. TextLabel849 = Instance.new("TextLabel")
  869. TextLabel850 = Instance.new("TextLabel")
  870. Frame851 = Instance.new("Frame")
  871. TextLabel852 = Instance.new("TextLabel")
  872. TextLabel853 = Instance.new("TextLabel")
  873. Frame854 = Instance.new("Frame")
  874. Frame855 = Instance.new("Frame")
  875. Frame856 = Instance.new("Frame")
  876. TextLabel857 = Instance.new("TextLabel")
  877. TextLabel858 = Instance.new("TextLabel")
  878. Frame859 = Instance.new("Frame")
  879. Frame860 = Instance.new("Frame")
  880. Frame861 = Instance.new("Frame")
  881. TextLabel862 = Instance.new("TextLabel")
  882. TextLabel863 = Instance.new("TextLabel")
  883. Frame864 = Instance.new("Frame")
  884. Frame865 = Instance.new("Frame")
  885. Frame866 = Instance.new("Frame")
  886. Frame867 = Instance.new("Frame")
  887. TextLabel868 = Instance.new("TextLabel")
  888. TextLabel869 = Instance.new("TextLabel")
  889. TextLabel870 = Instance.new("TextLabel")
  890. TextLabel871 = Instance.new("TextLabel")
  891. Frame872 = Instance.new("Frame")
  892. TextLabel873 = Instance.new("TextLabel")
  893. TextLabel874 = Instance.new("TextLabel")
  894. Frame875 = Instance.new("Frame")
  895. TextLabel876 = Instance.new("TextLabel")
  896. TextLabel877 = Instance.new("TextLabel")
  897. Frame878 = Instance.new("Frame")
  898. Frame879 = Instance.new("Frame")
  899. Frame880 = Instance.new("Frame")
  900. TextLabel881 = Instance.new("TextLabel")
  901. TextLabel882 = Instance.new("TextLabel")
  902. Frame883 = Instance.new("Frame")
  903. Frame884 = Instance.new("Frame")
  904. Frame885 = Instance.new("Frame")
  905. TextLabel886 = Instance.new("TextLabel")
  906. TextLabel887 = Instance.new("TextLabel")
  907. Frame888 = Instance.new("Frame")
  908. Frame889 = Instance.new("Frame")
  909. Frame890 = Instance.new("Frame")
  910. TextLabel891 = Instance.new("TextLabel")
  911. TextLabel892 = Instance.new("TextLabel")
  912. Frame893 = Instance.new("Frame")
  913. Frame894 = Instance.new("Frame")
  914. Frame895 = Instance.new("Frame")
  915. TextLabel896 = Instance.new("TextLabel")
  916. TextLabel897 = Instance.new("TextLabel")
  917. Frame898 = Instance.new("Frame")
  918. Frame899 = Instance.new("Frame")
  919. Frame900 = Instance.new("Frame")
  920. TextLabel901 = Instance.new("TextLabel")
  921. TextLabel902 = Instance.new("TextLabel")
  922. Frame903 = Instance.new("Frame")
  923. Frame904 = Instance.new("Frame")
  924. Frame905 = Instance.new("Frame")
  925. TextLabel906 = Instance.new("TextLabel")
  926. TextLabel907 = Instance.new("TextLabel")
  927. Frame908 = Instance.new("Frame")
  928. Frame909 = Instance.new("Frame")
  929. Frame910 = Instance.new("Frame")
  930. TextLabel911 = Instance.new("TextLabel")
  931. TextLabel912 = Instance.new("TextLabel")
  932. Frame913 = Instance.new("Frame")
  933. Frame914 = Instance.new("Frame")
  934. Frame915 = Instance.new("Frame")
  935. TextLabel916 = Instance.new("TextLabel")
  936. TextLabel917 = Instance.new("TextLabel")
  937. Frame918 = Instance.new("Frame")
  938. Frame919 = Instance.new("Frame")
  939. Frame920 = Instance.new("Frame")
  940. TextLabel921 = Instance.new("TextLabel")
  941. TextLabel922 = Instance.new("TextLabel")
  942. Frame923 = Instance.new("Frame")
  943. TextLabel924 = Instance.new("TextLabel")
  944. ImageButton925 = Instance.new("ImageButton")
  945. Frame926 = Instance.new("Frame")
  946. TextLabel927 = Instance.new("TextLabel")
  947. Frame928 = Instance.new("Frame")
  948. Frame929 = Instance.new("Frame")
  949. ImageButton930 = Instance.new("ImageButton")
  950. Frame931 = Instance.new("Frame")
  951. TextLabel932 = Instance.new("TextLabel")
  952. ImageButton933 = Instance.new("ImageButton")
  953. Frame934 = Instance.new("Frame")
  954. TextLabel935 = Instance.new("TextLabel")
  955. ImageButton936 = Instance.new("ImageButton")
  956. Frame937 = Instance.new("Frame")
  957. TextLabel938 = Instance.new("TextLabel")
  958. ImageButton939 = Instance.new("ImageButton")
  959. Frame940 = Instance.new("Frame")
  960. TextLabel941 = Instance.new("TextLabel")
  961. ImageButton942 = Instance.new("ImageButton")
  962. Frame943 = Instance.new("Frame")
  963. TextLabel944 = Instance.new("TextLabel")
  964. Frame945 = Instance.new("Frame")
  965. ImageButton946 = Instance.new("ImageButton")
  966. TextLabel947 = Instance.new("TextLabel")
  967. ImageButton948 = Instance.new("ImageButton")
  968. TextLabel949 = Instance.new("TextLabel")
  969. ImageButton950 = Instance.new("ImageButton")
  970. TextLabel951 = Instance.new("TextLabel")
  971. ImageButton952 = Instance.new("ImageButton")
  972. TextLabel953 = Instance.new("TextLabel")
  973. ImageButton954 = Instance.new("ImageButton")
  974. TextLabel955 = Instance.new("TextLabel")
  975. ImageButton956 = Instance.new("ImageButton")
  976. TextLabel957 = Instance.new("TextLabel")
  977. ImageButton958 = Instance.new("ImageButton")
  978. TextLabel959 = Instance.new("TextLabel")
  979. ImageButton960 = Instance.new("ImageButton")
  980. TextLabel961 = Instance.new("TextLabel")
  981. ImageButton962 = Instance.new("ImageButton")
  982. TextLabel963 = Instance.new("TextLabel")
  983. ImageButton964 = Instance.new("ImageButton")
  984. TextLabel965 = Instance.new("TextLabel")
  985. ImageButton966 = Instance.new("ImageButton")
  986. TextLabel967 = Instance.new("TextLabel")
  987. ImageButton968 = Instance.new("ImageButton")
  988. TextLabel969 = Instance.new("TextLabel")
  989. ImageButton970 = Instance.new("ImageButton")
  990. TextLabel971 = Instance.new("TextLabel")
  991. ImageButton972 = Instance.new("ImageButton")
  992. TextLabel973 = Instance.new("TextLabel")
  993. Frame974 = Instance.new("Frame")
  994. Frame975 = Instance.new("Frame")
  995. Frame976 = Instance.new("Frame")
  996. Frame977 = Instance.new("Frame")
  997. Frame978 = Instance.new("Frame")
  998. Frame979 = Instance.new("Frame")
  999. Frame980 = Instance.new("Frame")
  1000. Frame981 = Instance.new("Frame")
  1001. TextLabel982 = Instance.new("TextLabel")
  1002. Frame983 = Instance.new("Frame")
  1003. Frame984 = Instance.new("Frame")
  1004. Frame985 = Instance.new("Frame")
  1005. Frame986 = Instance.new("Frame")
  1006. Frame987 = Instance.new("Frame")
  1007. Frame988 = Instance.new("Frame")
  1008. TextLabel989 = Instance.new("TextLabel")
  1009. Frame990 = Instance.new("Frame")
  1010. TextLabel991 = Instance.new("TextLabel")
  1011. TextLabel992 = Instance.new("TextLabel")
  1012. Frame993 = Instance.new("Frame")
  1013. TextLabel994 = Instance.new("TextLabel")
  1014. TextLabel995 = Instance.new("TextLabel")
  1015. Tool996 = Instance.new("Tool")
  1016. Part997 = Instance.new("Part")
  1017. SpecialMesh998 = Instance.new("SpecialMesh")
  1018. Fire999 = Instance.new("Fire")
  1019. LocalScript1000 = Instance.new("LocalScript")
  1020. Script1001 = Instance.new("Script")
  1021. HopperBin1002 = Instance.new("HopperBin")
  1022. LocalScript1003 = Instance.new("LocalScript")
  1023. ScreenGui1004 = Instance.new("ScreenGui")
  1024. Frame1005 = Instance.new("Frame")
  1025. TextLabel1006 = Instance.new("TextLabel")
  1026. TextLabel1007 = Instance.new("TextLabel")
  1027. Frame1008 = Instance.new("Frame")
  1028. TextLabel1009 = Instance.new("TextLabel")
  1029. TextButton1010 = Instance.new("TextButton")
  1030. TextButton1011 = Instance.new("TextButton")
  1031. TextButton1012 = Instance.new("TextButton")
  1032. TextButton1013 = Instance.new("TextButton")
  1033. TextButton1014 = Instance.new("TextButton")
  1034. TextButton1015 = Instance.new("TextButton")
  1035. Frame1016 = Instance.new("Frame")
  1036. TextLabel1017 = Instance.new("TextLabel")
  1037. TextButton1018 = Instance.new("TextButton")
  1038. TextButton1019 = Instance.new("TextButton")
  1039. TextButton1020 = Instance.new("TextButton")
  1040. TextButton1021 = Instance.new("TextButton")
  1041. TextButton1022 = Instance.new("TextButton")
  1042. TextButton1023 = Instance.new("TextButton")
  1043. Frame1024 = Instance.new("Frame")
  1044. TextLabel1025 = Instance.new("TextLabel")
  1045. TextButton1026 = Instance.new("TextButton")
  1046. TextButton1027 = Instance.new("TextButton")
  1047. TextButton1028 = Instance.new("TextButton")
  1048. TextButton1029 = Instance.new("TextButton")
  1049. TextButton1030 = Instance.new("TextButton")
  1050. TextButton1031 = Instance.new("TextButton")
  1051. Frame1032 = Instance.new("Frame")
  1052. TextLabel1033 = Instance.new("TextLabel")
  1053. TextButton1034 = Instance.new("TextButton")
  1054. TextButton1035 = Instance.new("TextButton")
  1055. TextButton1036 = Instance.new("TextButton")
  1056. TextButton1037 = Instance.new("TextButton")
  1057. Frame1038 = Instance.new("Frame")
  1058. TextLabel1039 = Instance.new("TextLabel")
  1059. TextButton1040 = Instance.new("TextButton")
  1060. TextButton1041 = Instance.new("TextButton")
  1061. TextButton1042 = Instance.new("TextButton")
  1062. TextButton1043 = Instance.new("TextButton")
  1063. Frame1044 = Instance.new("Frame")
  1064. TextLabel1045 = Instance.new("TextLabel")
  1065. TextButton1046 = Instance.new("TextButton")
  1066. TextButton1047 = Instance.new("TextButton")
  1067. TextButton1048 = Instance.new("TextButton")
  1068. TextButton1049 = Instance.new("TextButton")
  1069. TextLabel1050 = Instance.new("TextLabel")
  1070. Frame1051 = Instance.new("Frame")
  1071. TextLabel1052 = Instance.new("TextLabel")
  1072. TextButton1053 = Instance.new("TextButton")
  1073. TextButton1054 = Instance.new("TextButton")
  1074. TextButton1055 = Instance.new("TextButton")
  1075. TextButton1056 = Instance.new("TextButton")
  1076. Script1057 = Instance.new("Script")
  1077. HopperBin1058 = Instance.new("HopperBin")
  1078. Handles1059 = Instance.new("Handles")
  1079. SelectionBox1060 = Instance.new("SelectionBox")
  1080. LocalScript1061 = Instance.new("LocalScript")
  1081. Script1062 = Instance.new("Script")
  1082. HopperBin1063 = Instance.new("HopperBin")
  1083. BoolValue1064 = Instance.new("BoolValue")
  1084. StringValue1065 = Instance.new("StringValue")
  1085. BoolValue1066 = Instance.new("BoolValue")
  1086. StringValue1067 = Instance.new("StringValue")
  1087. BoolValue1068 = Instance.new("BoolValue")
  1088. SelectionBox1069 = Instance.new("SelectionBox")
  1089. Script1070 = Instance.new("Script")
  1090. ScreenGui1071 = Instance.new("ScreenGui")
  1091. Frame1072 = Instance.new("Frame")
  1092. TextLabel1073 = Instance.new("TextLabel")
  1093. TextButton1074 = Instance.new("TextButton")
  1094. TextButton1075 = Instance.new("TextButton")
  1095. BoolValue1076 = Instance.new("BoolValue")
  1096. TextLabel1077 = Instance.new("TextLabel")
  1097. TextButton1078 = Instance.new("TextButton")
  1098. TextButton1079 = Instance.new("TextButton")
  1099. TextButton1080 = Instance.new("TextButton")
  1100. TextButton1081 = Instance.new("TextButton")
  1101. TextBox1082 = Instance.new("TextBox")
  1102. TextLabel1083 = Instance.new("TextLabel")
  1103. TextLabel1084 = Instance.new("TextLabel")
  1104. TextButton1085 = Instance.new("TextButton")
  1105. TextLabel1086 = Instance.new("TextLabel")
  1106. TextLabel1087 = Instance.new("TextLabel")
  1107. LocalScript1088 = Instance.new("LocalScript")
  1108. TextButton1089 = Instance.new("TextButton")
  1109. Frame1090 = Instance.new("Frame")
  1110. TextLabel1091 = Instance.new("TextLabel")
  1111. TextLabel1092 = Instance.new("TextLabel")
  1112. TextLabel1093 = Instance.new("TextLabel")
  1113. TextButton1094 = Instance.new("TextButton")
  1114. Script1095 = Instance.new("Script")
  1115. TextButton1096 = Instance.new("TextButton")
  1116. Script1097 = Instance.new("Script")
  1117. LocalScript1098 = Instance.new("LocalScript")
  1118. Frame1099 = Instance.new("Frame")
  1119. TextButton1100 = Instance.new("TextButton")
  1120. BoolValue1101 = Instance.new("BoolValue")
  1121. TextBox1102 = Instance.new("TextBox")
  1122. TextButton1103 = Instance.new("TextButton")
  1123. TextLabel1104 = Instance.new("TextLabel")
  1124. TextLabel1105 = Instance.new("TextLabel")
  1125. TextLabel1106 = Instance.new("TextLabel")
  1126. TextButton1107 = Instance.new("TextButton")
  1127. TextLabel1108 = Instance.new("TextLabel")
  1128. TextBox1109 = Instance.new("TextBox")
  1129. Frame1110 = Instance.new("Frame")
  1130. TextLabel1111 = Instance.new("TextLabel")
  1131. TextLabel1112 = Instance.new("TextLabel")
  1132. TextButton1113 = Instance.new("TextButton")
  1133. Script1114 = Instance.new("Script")
  1134. TextButton1115 = Instance.new("TextButton")
  1135. Script1116 = Instance.new("Script")
  1136. ObjectValue1117 = Instance.new("ObjectValue")
  1137. HopperBin1118 = Instance.new("HopperBin")
  1138. LocalScript1119 = Instance.new("LocalScript")
  1139. LocalScript1120 = Instance.new("LocalScript")
  1140. Model1121 = Instance.new("Model")
  1141. Model1122 = Instance.new("Model")
  1142. StringValue1123 = Instance.new("StringValue")
  1143. Color3Value1124 = Instance.new("Color3Value")
  1144. StringValue1125 = Instance.new("StringValue")
  1145. StringValue1126 = Instance.new("StringValue")
  1146. LocalScript1127 = Instance.new("LocalScript")
  1147. StringValue1128 = Instance.new("StringValue")
  1148. LocalScript1129 = Instance.new("LocalScript")
  1149. LocalScript1130 = Instance.new("LocalScript")
  1150. StringValue1131 = Instance.new("StringValue")
  1151. StringValue1132 = Instance.new("StringValue")
  1152. LocalScript1133 = Instance.new("LocalScript")
  1153. StringValue1134 = Instance.new("StringValue")
  1154. Color3Value1135 = Instance.new("Color3Value")
  1155. StringValue1136 = Instance.new("StringValue")
  1156. StringValue1137 = Instance.new("StringValue")
  1157. LocalScript1138 = Instance.new("LocalScript")
  1158. LocalScript1139 = Instance.new("LocalScript")
  1159. LocalScript1140 = Instance.new("LocalScript")
  1160. StringValue1141 = Instance.new("StringValue")
  1161. Color3Value1142 = Instance.new("Color3Value")
  1162. StringValue1143 = Instance.new("StringValue")
  1163. StringValue1144 = Instance.new("StringValue")
  1164. StringValue1145 = Instance.new("StringValue")
  1165. Color3Value1146 = Instance.new("Color3Value")
  1166. StringValue1147 = Instance.new("StringValue")
  1167. StringValue1148 = Instance.new("StringValue")
  1168. LocalScript1149 = Instance.new("LocalScript")
  1169. StringValue1150 = Instance.new("StringValue")
  1170. Color3Value1151 = Instance.new("Color3Value")
  1171. StringValue1152 = Instance.new("StringValue")
  1172. StringValue1153 = Instance.new("StringValue")
  1173. LocalScript1154 = Instance.new("LocalScript")
  1174. StringValue1155 = Instance.new("StringValue")
  1175. LocalScript1156 = Instance.new("LocalScript")
  1176. StringValue1157 = Instance.new("StringValue")
  1177. LocalScript1158 = Instance.new("LocalScript")
  1178. StringValue1159 = Instance.new("StringValue")
  1179. StringValue1160 = Instance.new("StringValue")
  1180. Color3Value1161 = Instance.new("Color3Value")
  1181. StringValue1162 = Instance.new("StringValue")
  1182. StringValue1163 = Instance.new("StringValue")
  1183. LocalScript1164 = Instance.new("LocalScript")
  1184. LocalScript1165 = Instance.new("LocalScript")
  1185. StringValue1166 = Instance.new("StringValue")
  1186. Color3Value1167 = Instance.new("Color3Value")
  1187. StringValue1168 = Instance.new("StringValue")
  1188. StringValue1169 = Instance.new("StringValue")
  1189. LocalScript1170 = Instance.new("LocalScript")
  1190. Model1171 = Instance.new("Model")
  1191. LocalScript1172 = Instance.new("LocalScript")
  1192. StringValue1173 = Instance.new("StringValue")
  1193. LocalScript1174 = Instance.new("LocalScript")
  1194. StringValue1175 = Instance.new("StringValue")
  1195. LocalScript1176 = Instance.new("LocalScript")
  1196. StringValue1177 = Instance.new("StringValue")
  1197. StringValue1178 = Instance.new("StringValue")
  1198. LocalScript1179 = Instance.new("LocalScript")
  1199. LocalScript1180 = Instance.new("LocalScript")
  1200. StringValue1181 = Instance.new("StringValue")
  1201. StringValue1182 = Instance.new("StringValue")
  1202. LocalScript1183 = Instance.new("LocalScript")
  1203. StringValue1184 = Instance.new("StringValue")
  1204. LocalScript1185 = Instance.new("LocalScript")
  1205. LocalScript1186 = Instance.new("LocalScript")
  1206. StringValue1187 = Instance.new("StringValue")
  1207. StringValue1188 = Instance.new("StringValue")
  1208. LocalScript1189 = Instance.new("LocalScript")
  1209. StringValue1190 = Instance.new("StringValue")
  1210. LocalScript1191 = Instance.new("LocalScript")
  1211. StringValue1192 = Instance.new("StringValue")
  1212. Color3Value1193 = Instance.new("Color3Value")
  1213. StringValue1194 = Instance.new("StringValue")
  1214. StringValue1195 = Instance.new("StringValue")
  1215. LocalScript1196 = Instance.new("LocalScript")
  1216. StringValue1197 = Instance.new("StringValue")
  1217. LocalScript1198 = Instance.new("LocalScript")
  1218. StringValue1199 = Instance.new("StringValue")
  1219. Color3Value1200 = Instance.new("Color3Value")
  1220. StringValue1201 = Instance.new("StringValue")
  1221. StringValue1202 = Instance.new("StringValue")
  1222. LocalScript1203 = Instance.new("LocalScript")
  1223. StringValue1204 = Instance.new("StringValue")
  1224. LocalScript1205 = Instance.new("LocalScript")
  1225. StringValue1206 = Instance.new("StringValue")
  1226. StringValue1207 = Instance.new("StringValue")
  1227. Color3Value1208 = Instance.new("Color3Value")
  1228. StringValue1209 = Instance.new("StringValue")
  1229. StringValue1210 = Instance.new("StringValue")
  1230. LocalScript1211 = Instance.new("LocalScript")
  1231. LocalScript1212 = Instance.new("LocalScript")
  1232. StringValue1213 = Instance.new("StringValue")
  1233. StringValue1214 = Instance.new("StringValue")
  1234. Color3Value1215 = Instance.new("Color3Value")
  1235. StringValue1216 = Instance.new("StringValue")
  1236. StringValue1217 = Instance.new("StringValue")
  1237. LocalScript1218 = Instance.new("LocalScript")
  1238. LocalScript1219 = Instance.new("LocalScript")
  1239. StringValue1220 = Instance.new("StringValue")
  1240. StringValue1221 = Instance.new("StringValue")
  1241. LocalScript1222 = Instance.new("LocalScript")
  1242. StringValue1223 = Instance.new("StringValue")
  1243. Color3Value1224 = Instance.new("Color3Value")
  1244. StringValue1225 = Instance.new("StringValue")
  1245. StringValue1226 = Instance.new("StringValue")
  1246. LocalScript1227 = Instance.new("LocalScript")
  1247. LocalScript1228 = Instance.new("LocalScript")
  1248. StringValue1229 = Instance.new("StringValue")
  1249. LocalScript1230 = Instance.new("LocalScript")
  1250. StringValue1231 = Instance.new("StringValue")
  1251. LocalScript1232 = Instance.new("LocalScript")
  1252. StringValue1233 = Instance.new("StringValue")
  1253. Color3Value1234 = Instance.new("Color3Value")
  1254. StringValue1235 = Instance.new("StringValue")
  1255. StringValue1236 = Instance.new("StringValue")
  1256. LocalScript1237 = Instance.new("LocalScript")
  1257. StringValue1238 = Instance.new("StringValue")
  1258. LocalScript1239 = Instance.new("LocalScript")
  1259. StringValue1240 = Instance.new("StringValue")
  1260. Color3Value1241 = Instance.new("Color3Value")
  1261. StringValue1242 = Instance.new("StringValue")
  1262. StringValue1243 = Instance.new("StringValue")
  1263. LocalScript1244 = Instance.new("LocalScript")
  1264. StringValue1245 = Instance.new("StringValue")
  1265. LocalScript1246 = Instance.new("LocalScript")
  1266. StringValue1247 = Instance.new("StringValue")
  1267. StringValue1248 = Instance.new("StringValue")
  1268. LocalScript1249 = Instance.new("LocalScript")
  1269. StringValue1250 = Instance.new("StringValue")
  1270. StringValue1251 = Instance.new("StringValue")
  1271. Color3Value1252 = Instance.new("Color3Value")
  1272. LocalScript1253 = Instance.new("LocalScript")
  1273. StringValue1254 = Instance.new("StringValue")
  1274. Color3Value1255 = Instance.new("Color3Value")
  1275. StringValue1256 = Instance.new("StringValue")
  1276. StringValue1257 = Instance.new("StringValue")
  1277. LocalScript1258 = Instance.new("LocalScript")
  1278. StringValue1259 = Instance.new("StringValue")
  1279. LocalScript1260 = Instance.new("LocalScript")
  1280. StringValue1261 = Instance.new("StringValue")
  1281. StringValue1262 = Instance.new("StringValue")
  1282. Color3Value1263 = Instance.new("Color3Value")
  1283. StringValue1264 = Instance.new("StringValue")
  1284. StringValue1265 = Instance.new("StringValue")
  1285. LocalScript1266 = Instance.new("LocalScript")
  1286. LocalScript1267 = Instance.new("LocalScript")
  1287. StringValue1268 = Instance.new("StringValue")
  1288. StringValue1269 = Instance.new("StringValue")
  1289. Color3Value1270 = Instance.new("Color3Value")
  1290. StringValue1271 = Instance.new("StringValue")
  1291. StringValue1272 = Instance.new("StringValue")
  1292. LocalScript1273 = Instance.new("LocalScript")
  1293. StringValue1274 = Instance.new("StringValue")
  1294. Color3Value1275 = Instance.new("Color3Value")
  1295. StringValue1276 = Instance.new("StringValue")
  1296. StringValue1277 = Instance.new("StringValue")
  1297. LocalScript1278 = Instance.new("LocalScript")
  1298. StringValue1279 = Instance.new("StringValue")
  1299. LocalScript1280 = Instance.new("LocalScript")
  1300. StringValue1281 = Instance.new("StringValue")
  1301. StringValue1282 = Instance.new("StringValue")
  1302. Color3Value1283 = Instance.new("Color3Value")
  1303. StringValue1284 = Instance.new("StringValue")
  1304. StringValue1285 = Instance.new("StringValue")
  1305. LocalScript1286 = Instance.new("LocalScript")
  1306. StringValue1287 = Instance.new("StringValue")
  1307. LocalScript1288 = Instance.new("LocalScript")
  1308. StringValue1289 = Instance.new("StringValue")
  1309. LocalScript1290 = Instance.new("LocalScript")
  1310. LocalScript1291 = Instance.new("LocalScript")
  1311. StringValue1292 = Instance.new("StringValue")
  1312. StringValue1293 = Instance.new("StringValue")
  1313. Color3Value1294 = Instance.new("Color3Value")
  1314. StringValue1295 = Instance.new("StringValue")
  1315. StringValue1296 = Instance.new("StringValue")
  1316. LocalScript1297 = Instance.new("LocalScript")
  1317. LocalScript1298 = Instance.new("LocalScript")
  1318. LocalScript1299 = Instance.new("LocalScript")
  1319. Model1300 = Instance.new("Model")
  1320. LocalScript1301 = Instance.new("LocalScript")
  1321. StringValue1302 = Instance.new("StringValue")
  1322. LocalScript1303 = Instance.new("LocalScript")
  1323. LocalScript1304 = Instance.new("LocalScript")
  1324. StringValue1305 = Instance.new("StringValue")
  1325. StringValue1306 = Instance.new("StringValue")
  1326. LocalScript1307 = Instance.new("LocalScript")
  1327. StringValue1308 = Instance.new("StringValue")
  1328. StringValue1309 = Instance.new("StringValue")
  1329. StringValue1310 = Instance.new("StringValue")
  1330. LocalScript1311 = Instance.new("LocalScript")
  1331. StringValue1312 = Instance.new("StringValue")
  1332. LocalScript1313 = Instance.new("LocalScript")
  1333. LocalScript1314 = Instance.new("LocalScript")
  1334. LocalScript1315 = Instance.new("LocalScript")
  1335. LocalScript1316 = Instance.new("LocalScript")
  1336. StringValue1317 = Instance.new("StringValue")
  1337. LocalScript1318 = Instance.new("LocalScript")
  1338. StringValue1319 = Instance.new("StringValue")
  1339. StringValue1320 = Instance.new("StringValue")
  1340. LocalScript1321 = Instance.new("LocalScript")
  1341. LocalScript1322 = Instance.new("LocalScript")
  1342. StringValue1323 = Instance.new("StringValue")
  1343. StringValue1324 = Instance.new("StringValue")
  1344. StringValue1325 = Instance.new("StringValue")
  1345. LocalScript1326 = Instance.new("LocalScript")
  1346. StringValue1327 = Instance.new("StringValue")
  1347. LocalScript1328 = Instance.new("LocalScript")
  1348. StringValue1329 = Instance.new("StringValue")
  1349. LocalScript1330 = Instance.new("LocalScript")
  1350. LocalScript1331 = Instance.new("LocalScript")
  1351. HopperBin1332 = Instance.new("HopperBin")
  1352. Script1333 = Instance.new("Script")
  1353. HopperBin1334 = Instance.new("HopperBin")
  1354. Script1335 = Instance.new("Script")
  1355. HopperBin1336 = Instance.new("HopperBin")
  1356. Script1337 = Instance.new("Script")
  1357. HopperBin1338 = Instance.new("HopperBin")
  1358. ScreenGui1339 = Instance.new("ScreenGui")
  1359. Frame1340 = Instance.new("Frame")
  1360. TextLabel1341 = Instance.new("TextLabel")
  1361. TextLabel1342 = Instance.new("TextLabel")
  1362. Frame1343 = Instance.new("Frame")
  1363. TextLabel1344 = Instance.new("TextLabel")
  1364. TextButton1345 = Instance.new("TextButton")
  1365. TextButton1346 = Instance.new("TextButton")
  1366. TextButton1347 = Instance.new("TextButton")
  1367. TextButton1348 = Instance.new("TextButton")
  1368. TextButton1349 = Instance.new("TextButton")
  1369. TextButton1350 = Instance.new("TextButton")
  1370. Frame1351 = Instance.new("Frame")
  1371. TextLabel1352 = Instance.new("TextLabel")
  1372. TextButton1353 = Instance.new("TextButton")
  1373. TextButton1354 = Instance.new("TextButton")
  1374. TextButton1355 = Instance.new("TextButton")
  1375. TextButton1356 = Instance.new("TextButton")
  1376. TextButton1357 = Instance.new("TextButton")
  1377. TextButton1358 = Instance.new("TextButton")
  1378. Frame1359 = Instance.new("Frame")
  1379. TextLabel1360 = Instance.new("TextLabel")
  1380. TextButton1361 = Instance.new("TextButton")
  1381. TextButton1362 = Instance.new("TextButton")
  1382. TextButton1363 = Instance.new("TextButton")
  1383. TextButton1364 = Instance.new("TextButton")
  1384. TextButton1365 = Instance.new("TextButton")
  1385. TextButton1366 = Instance.new("TextButton")
  1386. Frame1367 = Instance.new("Frame")
  1387. TextLabel1368 = Instance.new("TextLabel")
  1388. TextButton1369 = Instance.new("TextButton")
  1389. TextButton1370 = Instance.new("TextButton")
  1390. TextButton1371 = Instance.new("TextButton")
  1391. TextButton1372 = Instance.new("TextButton")
  1392. Frame1373 = Instance.new("Frame")
  1393. TextLabel1374 = Instance.new("TextLabel")
  1394. TextButton1375 = Instance.new("TextButton")
  1395. TextButton1376 = Instance.new("TextButton")
  1396. TextButton1377 = Instance.new("TextButton")
  1397. TextButton1378 = Instance.new("TextButton")
  1398. Frame1379 = Instance.new("Frame")
  1399. TextLabel1380 = Instance.new("TextLabel")
  1400. TextButton1381 = Instance.new("TextButton")
  1401. TextButton1382 = Instance.new("TextButton")
  1402. TextButton1383 = Instance.new("TextButton")
  1403. TextButton1384 = Instance.new("TextButton")
  1404. TextLabel1385 = Instance.new("TextLabel")
  1405. Frame1386 = Instance.new("Frame")
  1406. TextLabel1387 = Instance.new("TextLabel")
  1407. TextButton1388 = Instance.new("TextButton")
  1408. TextButton1389 = Instance.new("TextButton")
  1409. TextButton1390 = Instance.new("TextButton")
  1410. TextButton1391 = Instance.new("TextButton")
  1411. LocalScript1392 = Instance.new("LocalScript")
  1412. Script1393 = Instance.new("Script")
  1413. HopperBin1394 = Instance.new("HopperBin")
  1414. Script1395 = Instance.new("Script")
  1415. Script1396 = Instance.new("Script")
  1416. Tool0.Name = "Building Tools"
  1417. Tool0.Parent = mas
  1418. Tool0.ToolTip = "Building Tools by F3X"
  1419. LocalScript1.Name = "Building Tools by F3X"
  1420. LocalScript1.Parent = Tool0
  1421. table.insert(cors,sandbox(LocalScript1,function()
  1422. ------------------------------------------
  1423. -- Create references to important objects
  1424. ------------------------------------------
  1425. Services = {
  1426. ["Workspace"] = Game:GetService( "Workspace" );
  1427. ["Players"] = Game:GetService( "Players" );
  1428. ["Lighting"] = Game:GetService( "Lighting" );
  1429. ["Teams"] = Game:GetService( "Teams" );
  1430. ["Debris"] = Game:GetService( "Debris" );
  1431. ["MarketplaceService"] = Game:GetService( "MarketplaceService" );
  1432. ["JointsService"] = Game.JointsService;
  1433. ["BadgeService"] = Game:GetService( "BadgeService" );
  1434. ["RunService"] = Game:GetService( "RunService" );
  1435. ["ContentProvider"] = Game:GetService( "ContentProvider" );
  1436. ["TeleportService"] = Game:GetService( "TeleportService" );
  1437. ["SoundService"] = Game:GetService( "SoundService" );
  1438. ["InsertService"] = Game:GetService( "InsertService" );
  1439. ["CollectionService"] = Game:GetService( "CollectionService" );
  1440. ["UserInputService"] = Game:GetService( "UserInputService" );
  1441. ["GamePassService"] = Game:GetService( "GamePassService" );
  1442. ["StarterPack"] = Game:GetService( "StarterPack" );
  1443. ["StarterGui"] = Game:GetService( "StarterGui" );
  1444. ["TestService"] = Game:GetService( "TestService" );
  1445. ["ReplicatedStorage"] = Game:GetService( "ReplicatedStorage" );
  1446. ["Selection"] = Game:GetService( "Selection" );
  1447. ["CoreGui"] = Game:GetService( "CoreGui" );
  1448. };
  1449.  
  1450. Tool = script.Parent;
  1451. Player = Services.Players.LocalPlayer;
  1452. Mouse = nil;
  1453.  
  1454. -- Determine whether this is the plugin or tool
  1455. if plugin then
  1456. ToolType = 'plugin';
  1457. elseif Tool:IsA( 'Tool' ) then
  1458. ToolType = 'tool';
  1459. end;
  1460.  
  1461. -- Get tool type-specific resources
  1462. if ToolType == 'tool' then
  1463. GUIContainer = Player:WaitForChild( 'PlayerGui' );
  1464. in_server = not not Game:FindFirstChild( 'NetworkClient' );
  1465. elseif ToolType == 'plugin' then
  1466. GUIContainer = Services.CoreGui;
  1467. in_server = not not Game:FindFirstChild( 'NetworkServer' );
  1468. end;
  1469. if in_server then
  1470. Tool:WaitForChild( "GetAsync" );
  1471. Tool:WaitForChild( "PostAsync" );
  1472. GetAsync = function ( ... )
  1473. return Tool.GetAsync:InvokeServer( ... );
  1474. end;
  1475. PostAsync = function ( ... )
  1476. return Tool.PostAsync:InvokeServer( ... );
  1477. end;
  1478. end;
  1479.  
  1480. dark_slanted_rectangle = "http://www.roblox.com/asset/?id=127774197";
  1481. light_slanted_rectangle = "http://www.roblox.com/asset/?id=127772502";
  1482. action_completion_sound = "http://www.roblox.com/asset/?id=99666917";
  1483. expand_arrow = "http://www.roblox.com/asset/?id=134367382";
  1484. tool_decal = "http://www.roblox.com/asset/?id=129748355";
  1485. undo_active_decal = "http://www.roblox.com/asset/?id=141741408";
  1486. undo_inactive_decal = "http://www.roblox.com/asset/?id=142074557";
  1487. redo_active_decal = "http://www.roblox.com/asset/?id=141741327";
  1488. redo_inactive_decal = "http://www.roblox.com/asset/?id=142074553";
  1489. delete_active_decal = "http://www.roblox.com/asset/?id=141896298";
  1490. delete_inactive_decal = "http://www.roblox.com/asset/?id=142074644";
  1491. export_active_decal = "http://www.roblox.com/asset/?id=141741337";
  1492. export_inactive_decal = "http://www.roblox.com/asset/?id=142074569";
  1493. clone_active_decal = "http://www.roblox.com/asset/?id=142073926";
  1494. clone_inactive_decal = "http://www.roblox.com/asset/?id=142074563";
  1495. plugin_icon = "http://www.roblox.com/asset/?id=142287521";
  1496.  
  1497. ------------------------------------------
  1498. -- Load external dependencies
  1499. ------------------------------------------
  1500. RbxUtility = LoadLibrary( "RbxUtility" );
  1501. Services.ContentProvider:Preload( dark_slanted_rectangle );
  1502. Services.ContentProvider:Preload( light_slanted_rectangle );
  1503. Services.ContentProvider:Preload( action_completion_sound );
  1504. Services.ContentProvider:Preload( expand_arrow );
  1505. Services.ContentProvider:Preload( tool_decal );
  1506. Services.ContentProvider:Preload( undo_active_decal );
  1507. Services.ContentProvider:Preload( undo_inactive_decal );
  1508. Services.ContentProvider:Preload( redo_inactive_decal );
  1509. Services.ContentProvider:Preload( redo_active_decal );
  1510. Services.ContentProvider:Preload( delete_active_decal );
  1511. Services.ContentProvider:Preload( delete_inactive_decal );
  1512. Services.ContentProvider:Preload( export_active_decal );
  1513. Services.ContentProvider:Preload( export_inactive_decal );
  1514. Services.ContentProvider:Preload( clone_active_decal );
  1515. Services.ContentProvider:Preload( clone_inactive_decal );
  1516. Services.ContentProvider:Preload( plugin_icon );
  1517. Tool:WaitForChild( "Interfaces" );
  1518. repeat wait( 0 ) until _G.gloo;
  1519. Gloo = _G.gloo;
  1520.  
  1521. ------------------------------------------
  1522. -- Define functions that are depended-upon
  1523. ------------------------------------------
  1524. function _findTableOccurrences( haystack, needle )
  1525. -- Returns the positions of instances of `needle` in table `haystack`
  1526. local positions = {};
  1527.  
  1528. -- Add any indexes from `haystack` that have `needle`
  1529. for index, value in pairs( haystack ) do
  1530. if value == needle then
  1531. table.insert( positions, index );
  1532. end;
  1533. end;
  1534.  
  1535. return positions;
  1536. end;
  1537.  
  1538. function _getCollectionInfo( part_collection )
  1539. -- Returns the size and position of collection of parts `part_collection`
  1540.  
  1541. -- Get the corners
  1542. local corners = {};
  1543.  
  1544. -- Create shortcuts to certain things that are expensive to call constantly
  1545. -- (note: otherwise it actually becomes an issue if the selection grows
  1546. -- considerably large)
  1547. local table_insert = table.insert;
  1548. local newCFrame = CFrame.new;
  1549.  
  1550. for _, Part in pairs( part_collection ) do
  1551.  
  1552. local PartCFrame = Part.CFrame;
  1553. local partCFrameOffset = PartCFrame.toWorldSpace;
  1554. local PartSize = Part.Size / 2;
  1555. local size_x, size_y, size_z = PartSize.x, PartSize.y, PartSize.z;
  1556.  
  1557. table_insert( corners, partCFrameOffset( PartCFrame, newCFrame( size_x, size_y, size_z ) ) );
  1558. table_insert( corners, partCFrameOffset( PartCFrame, newCFrame( -size_x, size_y, size_z ) ) );
  1559. table_insert( corners, partCFrameOffset( PartCFrame, newCFrame( size_x, -size_y, size_z ) ) );
  1560. table_insert( corners, partCFrameOffset( PartCFrame, newCFrame( size_x, size_y, -size_z ) ) );
  1561. table_insert( corners, partCFrameOffset( PartCFrame, newCFrame( -size_x, size_y, -size_z ) ) );
  1562. table_insert( corners, partCFrameOffset( PartCFrame, newCFrame( -size_x, -size_y, size_z ) ) );
  1563. table_insert( corners, partCFrameOffset( PartCFrame, newCFrame( size_x, -size_y, -size_z ) ) );
  1564. table_insert( corners, partCFrameOffset( PartCFrame, newCFrame( -size_x, -size_y, -size_z ) ) );
  1565.  
  1566. end;
  1567.  
  1568. -- Get the extents
  1569. local x, y, z = {}, {}, {};
  1570.  
  1571. for _, Corner in pairs( corners ) do
  1572. table_insert( x, Corner.x );
  1573. table_insert( y, Corner.y );
  1574. table_insert( z, Corner.z );
  1575. end;
  1576.  
  1577. local x_min, y_min, z_min = math.min( unpack( x ) ),
  1578. math.min( unpack( y ) ),
  1579. math.min( unpack( z ) );
  1580.  
  1581. local x_max, y_max, z_max = math.max( unpack( x ) ),
  1582. math.max( unpack( y ) ),
  1583. math.max( unpack( z ) );
  1584.  
  1585. -- Get the size between the extents
  1586. local x_size, y_size, z_size = x_max - x_min,
  1587. y_max - y_min,
  1588. z_max - z_min;
  1589.  
  1590. local Size = Vector3.new( x_size, y_size, z_size );
  1591.  
  1592. -- Get the centroid of the collection of points
  1593. local Position = CFrame.new( x_min + ( x_max - x_min ) / 2,
  1594. y_min + ( y_max - y_min ) / 2,
  1595. z_min + ( z_max - z_min ) / 2 );
  1596.  
  1597. -- Return the size of the collection of parts
  1598. return Size, Position;
  1599. end;
  1600.  
  1601. function _round( number, places )
  1602. -- Returns `number` rounded to the number of decimal `places`
  1603. -- (from lua-users)
  1604.  
  1605. local mult = 10 ^ ( places or 0 );
  1606.  
  1607. return math.floor( number * mult + 0.5 ) / mult;
  1608.  
  1609. end
  1610.  
  1611. function _cloneTable( source )
  1612. -- Returns a deep copy of table `source`
  1613.  
  1614. -- Get a copy of `source`'s metatable, since the hacky method
  1615. -- we're using to copy the table doesn't include its metatable
  1616. local source_mt = getmetatable( source );
  1617.  
  1618. -- Return a copy of `source` including its metatable
  1619. return setmetatable( { unpack( source ) }, source_mt );
  1620. end;
  1621.  
  1622. function _getAllDescendants( Parent )
  1623. -- Recursively gets all the descendants of `Parent` and returns them
  1624.  
  1625. local descendants = {};
  1626.  
  1627. for _, Child in pairs( Parent:GetChildren() ) do
  1628.  
  1629. -- Add the direct descendants of `Parent`
  1630. table.insert( descendants, Child );
  1631.  
  1632. -- Add the descendants of each child
  1633. for _, Subchild in pairs( _getAllDescendants( Child ) ) do
  1634. table.insert( descendants, Subchild );
  1635. end;
  1636.  
  1637. end;
  1638.  
  1639. return descendants;
  1640.  
  1641. end;
  1642.  
  1643. function _pointToScreenSpace( Point )
  1644. -- Returns Vector3 `Point`'s position on the screen when rendered
  1645. -- (kudos to stravant for this)
  1646.  
  1647. local point = Services.Workspace.CurrentCamera.CoordinateFrame:pointToObjectSpace( Point );
  1648. local aspectRatio = Mouse.ViewSizeX / Mouse.ViewSizeY;
  1649. local hfactor = math.tan( math.rad( Services.Workspace.CurrentCamera.FieldOfView ) / 2 )
  1650. local wfactor = aspectRatio * hfactor;
  1651.  
  1652. local x = ( point.x / point.z ) / -wfactor;
  1653. local y = ( point.y / point.z ) / hfactor;
  1654.  
  1655. local screen_pos = Vector2.new( Mouse.ViewSizeX * ( 0.5 + 0.5 * x ), Mouse.ViewSizeY * ( 0.5 + 0.5 * y ) );
  1656. if ( screen_pos.x < 0 or screen_pos.x > Mouse.ViewSizeX ) or ( screen_pos.y < 0 or screen_pos.y > Mouse.ViewSizeY ) then
  1657. return nil;
  1658. end;
  1659. if Services.Workspace.CurrentCamera.CoordinateFrame:toObjectSpace( CFrame.new( Point ) ).z > 0 then
  1660. return nil;
  1661. end;
  1662.  
  1663. return screen_pos;
  1664.  
  1665. end;
  1666.  
  1667. function _cloneParts( parts )
  1668. -- Returns a table of cloned `parts`
  1669.  
  1670. local new_parts = {};
  1671.  
  1672. -- Copy the parts into `new_parts`
  1673. for part_index, Part in pairs( parts ) do
  1674. new_parts[part_index] = Part:Clone();
  1675. end;
  1676.  
  1677. return new_parts;
  1678. end;
  1679.  
  1680. function _replaceParts( old_parts, new_parts )
  1681. -- Removes `old_parts` and inserts `new_parts`
  1682.  
  1683. -- Remove old parts
  1684. for _, OldPart in pairs( old_parts ) do
  1685. OldPart.Parent = nil;
  1686. end;
  1687.  
  1688. -- Insert `new_parts
  1689. for _, NewPart in pairs( new_parts ) do
  1690. NewPart.Parent = Services.Workspace;
  1691. NewPart:MakeJoints();
  1692. end;
  1693.  
  1694. end;
  1695.  
  1696. function _splitString( str, delimiter )
  1697. -- Returns a table of string `str` split by pattern `delimiter`
  1698.  
  1699. local parts = {};
  1700. local pattern = ( "([^%s]+)" ):format( delimiter );
  1701.  
  1702. str:gsub( pattern, function ( part )
  1703. table.insert( parts, part );
  1704. end );
  1705.  
  1706. return parts;
  1707. end;
  1708.  
  1709. function _generateSerializationID()
  1710. -- Returns a random 5-character string
  1711. -- with characters A-Z, a-z, and 0-9
  1712. -- (there are 916,132,832 unique IDs)
  1713.  
  1714. local characters = {
  1715. "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
  1716. "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
  1717. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
  1718.  
  1719. local serialization_id = "";
  1720.  
  1721. -- Pick out 5 random characters
  1722. for _ = 1, 5 do
  1723. serialization_id = serialization_id .. ( characters[math.random( #characters )] );
  1724. end;
  1725.  
  1726. return serialization_id;
  1727. end;
  1728.  
  1729. function _splitNumberListString( str )
  1730. -- Returns the contents of _splitString( str, ", " ), except
  1731. -- each value in the table is turned into a number
  1732.  
  1733. -- Get the number strings
  1734. local numbers = _splitString( str, ", " );
  1735.  
  1736. -- Turn them into numbers
  1737. for number_index, number in pairs( numbers ) do
  1738. numbers[number_index] = tonumber( number );
  1739. end;
  1740.  
  1741. -- Return `numbers`
  1742. return numbers;
  1743. end;
  1744.  
  1745. function _getSerializationPartType( Part )
  1746. -- Returns a special number that determines the type of
  1747. -- part `Part` is
  1748.  
  1749. local Types = {
  1750. Normal = 1,
  1751. Truss = 2,
  1752. Wedge = 3,
  1753. Corner = 4,
  1754. Cylinder = 5,
  1755. Ball = 6,
  1756. Seat = 7,
  1757. VehicleSeat = 8,
  1758. Spawn = 9
  1759. };
  1760.  
  1761. -- Return the appropriate type number
  1762. if Part.ClassName == "Part" then
  1763. if Part.Shape == Enum.PartType.Block then
  1764. return Types.Normal;
  1765. elseif Part.Shape == Enum.PartType.Cylinder then
  1766. return Types.Cylinder;
  1767. elseif Part.Shape == Enum.PartType.Ball then
  1768. return Types.Ball;
  1769. end;
  1770.  
  1771. elseif Part.ClassName == "Seat" then
  1772. return Types.Seat;
  1773.  
  1774. elseif Part.ClassName == "VehicleSeat" then
  1775. return Types.VehicleSeat;
  1776.  
  1777. elseif Part.ClassName == "SpawnLocation" then
  1778. return Types.Spawn;
  1779.  
  1780. elseif Part.ClassName == "WedgePart" then
  1781. return Types.Wedge;
  1782.  
  1783. elseif Part.ClassName == "CornerWedgePart" then
  1784. return Types.Corner;
  1785.  
  1786. elseif Part.ClassName == "TrussPart" then
  1787. return Types.Truss;
  1788.  
  1789. end;
  1790.  
  1791. end;
  1792.  
  1793. function _serializeParts( parts )
  1794. -- Returns JSON-encoded data about parts in
  1795. -- table `parts` that can be used to recreate them
  1796.  
  1797. local data = {
  1798. version = 1,
  1799. parts = {}
  1800. };
  1801.  
  1802. local objects = {};
  1803.  
  1804. -- Store part data
  1805. for _, Part in pairs( parts ) do
  1806. local part_id = _generateSerializationID();
  1807. local PartData = {
  1808. _getSerializationPartType( Part ),
  1809. _splitNumberListString( tostring( Part.Size ) ),
  1810. _splitNumberListString( tostring( Part.CFrame ) ),
  1811. Part.BrickColor.Number,
  1812. Part.Material.Value,
  1813. Part.Anchored,
  1814. Part.CanCollide,
  1815. Part.Reflectance,
  1816. Part.Transparency,
  1817. Part.TopSurface.Value,
  1818. Part.BottomSurface.Value,
  1819. Part.LeftSurface.Value,
  1820. Part.RightSurface.Value,
  1821. Part.FrontSurface.Value,
  1822. Part.BackSurface.Value
  1823. };
  1824. data.parts[part_id] = PartData;
  1825. objects[part_id] = Part;
  1826. end;
  1827.  
  1828. -- Get any welds in the selection
  1829. local welds = {};
  1830. for object_id, Object in pairs( objects ) do
  1831. if Object:IsA( "BasePart" ) then
  1832. for _, Joint in pairs( _getAllDescendants( Services.Workspace ) ) do
  1833. if Joint:IsA( "Weld" ) and Joint.Name == "BTWeld" then
  1834. if Joint.Part0 == Object and #_findTableOccurrences( objects, Joint.Part1 ) > 0 then
  1835. table.insert( welds, Joint );
  1836. end;
  1837. end;
  1838. end;
  1839. end;
  1840. end;
  1841.  
  1842. -- Serialize any welds
  1843. if #welds > 0 then
  1844. data.welds = {};
  1845. for _, Weld in pairs( welds ) do
  1846. local weld_id = _generateSerializationID();
  1847. local WeldData = {
  1848. _findTableOccurrences( objects, Weld.Part0 )[1],
  1849. _findTableOccurrences( objects, Weld.Part1 )[1],
  1850. _splitNumberListString( tostring( Weld.C1 ) )
  1851. };
  1852. data.welds[weld_id] = WeldData;
  1853. objects[weld_id] = Weld;
  1854. end;
  1855. end;
  1856.  
  1857. -- Get any meshes in the selection
  1858. local meshes = {};
  1859. for _, Part in pairs( parts ) do
  1860. local Mesh = _getChildOfClass( Part, "SpecialMesh" );
  1861. if Mesh then
  1862. table.insert( meshes, Mesh );
  1863. end;
  1864. end;
  1865.  
  1866. -- Serialize any meshes
  1867. if #meshes > 0 then
  1868. data.meshes = {};
  1869. for _, Mesh in pairs( meshes ) do
  1870. local mesh_id = _generateSerializationID();
  1871. local MeshData = {
  1872. _findTableOccurrences( objects, Mesh.Parent )[1],
  1873. Mesh.MeshType.Value,
  1874. _splitNumberListString( tostring( Mesh.Scale ) ),
  1875. Mesh.MeshId,
  1876. Mesh.TextureId,
  1877. _splitNumberListString( tostring( Mesh.VertexColor ) )
  1878. };
  1879. data.meshes[mesh_id] = MeshData;
  1880. objects[mesh_id] = Mesh;
  1881. end;
  1882. end;
  1883.  
  1884. -- Get any textures in the selection
  1885. local textures = {};
  1886. for _, Part in pairs( parts ) do
  1887. local textures_found = _getChildrenOfClass( Part, "Texture" );
  1888. for _, Texture in pairs( textures_found ) do
  1889. table.insert( textures, Texture );
  1890. end;
  1891. local decals_found = _getChildrenOfClass( Part, "Decal" );
  1892. for _, Decal in pairs( decals_found ) do
  1893. table.insert( textures, Decal );
  1894. end;
  1895. end;
  1896.  
  1897. -- Serialize any textures
  1898. if #textures > 0 then
  1899. data.textures = {};
  1900. for _, Texture in pairs( textures ) do
  1901. local texture_type;
  1902. if Texture.ClassName == "Decal" then
  1903. texture_type = 1;
  1904. elseif Texture.ClassName == "Texture" then
  1905. texture_type = 2;
  1906. end;
  1907. local texture_id = _generateSerializationID();
  1908. local TextureData = {
  1909. _findTableOccurrences( objects, Texture.Parent )[1],
  1910. texture_type,
  1911. Texture.Face.Value,
  1912. Texture.Texture,
  1913. Texture.Transparency,
  1914. texture_type == 2 and Texture.StudsPerTileU or nil,
  1915. texture_type == 2 and Texture.StudsPerTileV or nil
  1916. };
  1917. data.textures[texture_id] = TextureData;
  1918. objects[texture_id] = Texture;
  1919. end;
  1920. end;
  1921.  
  1922. -- Get any lights in the selection
  1923. local lights = {};
  1924. for _, Part in pairs( parts ) do
  1925. local lights_found = _getChildrenOfClass( Part, "Light", true );
  1926. for _, Light in pairs( lights_found ) do
  1927. table.insert( lights, Light );
  1928. end;
  1929. end;
  1930.  
  1931. -- Serialize any lights
  1932. if #lights > 0 then
  1933. data.lights = {};
  1934. for _, Light in pairs( lights ) do
  1935. local light_type;
  1936. if Light:IsA( "PointLight" ) then
  1937. light_type = 1;
  1938. elseif Light:IsA( "SpotLight" ) then
  1939. light_type = 2;
  1940. end;
  1941. local light_id = _generateSerializationID();
  1942. local LightData = {
  1943. _findTableOccurrences( objects, Light.Parent )[1];
  1944. light_type,
  1945. _splitNumberListString( tostring( Light.Color ) ),
  1946. Light.Brightness,
  1947. Light.Range,
  1948. Light.Shadows,
  1949. light_type == 2 and Light.Angle or nil,
  1950. light_type == 2 and Light.Face.Value or nil
  1951. };
  1952. data.lights[light_id] = LightData;
  1953. objects[light_id] = Light;
  1954. end;
  1955. end;
  1956.  
  1957. -- Get any decorations in the selection
  1958. local decorations = {};
  1959. for _, Part in pairs( parts ) do
  1960. table.insert( decorations, _getChildOfClass( Part, 'Smoke' ) )
  1961. table.insert( decorations, _getChildOfClass( Part, 'Fire' ) );
  1962. table.insert( decorations, _getChildOfClass( Part, 'Sparkles' ) );
  1963. end;
  1964.  
  1965. -- Serialize any decorations
  1966. if #decorations > 0 then
  1967. data.decorations = {};
  1968. for _, Decoration in pairs( decorations ) do
  1969. local decoration_type;
  1970. if Decoration:IsA( 'Smoke' ) then
  1971. decoration_type = 1;
  1972. elseif Decoration:IsA( 'Fire' ) then
  1973. decoration_type = 2;
  1974. elseif Decoration:IsA( 'Sparkles' ) then
  1975. decoration_type = 3;
  1976. end;
  1977. local decoration_id = _generateSerializationID();
  1978. local DecorationData = {
  1979. _findTableOccurrences( objects, Decoration.Parent )[1],
  1980. decoration_type
  1981. };
  1982. if decoration_type == 1 then
  1983. DecorationData[3] = _splitNumberListString( tostring( Decoration.Color ) );
  1984. DecorationData[4] = Decoration.Opacity;
  1985. DecorationData[5] = Decoration.RiseVelocity;
  1986. DecorationData[6] = Decoration.Size;
  1987. elseif decoration_type == 2 then
  1988. DecorationData[3] = _splitNumberListString( tostring( Decoration.Color ) );
  1989. DecorationData[4] = _splitNumberListString( tostring( Decoration.SecondaryColor ) );
  1990. DecorationData[5] = Decoration.Heat;
  1991. DecorationData[6] = Decoration.Size;
  1992. elseif decoration_type == 3 then
  1993. DecorationData[3] = _splitNumberListString( tostring( Decoration.SparkleColor ) );
  1994. end;
  1995. data.decorations[decoration_id] = DecorationData;
  1996. objects[decoration_id] = Decoration;
  1997. end;
  1998. end;
  1999.  
  2000. return RbxUtility.EncodeJSON( data );
  2001.  
  2002. end;
  2003.  
  2004. function _getChildOfClass( Parent, class_name, inherit )
  2005. -- Returns the first child of `Parent` that is of class `class_name`
  2006. -- or nil if it couldn't find any
  2007.  
  2008. -- Look for a child of `Parent` of class `class_name` and return it
  2009. if not inherit then
  2010. for _, Child in pairs( Parent:GetChildren() ) do
  2011. if Child.ClassName == class_name then
  2012. return Child;
  2013. end;
  2014. end;
  2015. else
  2016. for _, Child in pairs( Parent:GetChildren() ) do
  2017. if Child:IsA( class_name ) then
  2018. return Child;
  2019. end;
  2020. end;
  2021. end;
  2022.  
  2023. return nil;
  2024.  
  2025. end;
  2026.  
  2027. function _getChildrenOfClass( Parent, class_name, inherit )
  2028. -- Returns a table containing the children of `Parent` that are
  2029. -- of class `class_name`
  2030. local matches = {};
  2031.  
  2032.  
  2033. if not inherit then
  2034. for _, Child in pairs( Parent:GetChildren() ) do
  2035. if Child.ClassName == class_name then
  2036. table.insert( matches, Child );
  2037. end;
  2038. end;
  2039. else
  2040. for _, Child in pairs( Parent:GetChildren() ) do
  2041. if Child:IsA( class_name ) then
  2042. table.insert( matches, Child );
  2043. end;
  2044. end;
  2045. end;
  2046.  
  2047. return matches;
  2048. end;
  2049.  
  2050. function _HSVToRGB( hue, saturation, value )
  2051. -- Returns the RGB equivalent of the given HSV-defined color
  2052. -- (adapted from some code found around the web)
  2053.  
  2054. -- If it's achromatic, just return the value
  2055. if saturation == 0 then
  2056. return value;
  2057. end;
  2058.  
  2059. -- Get the hue sector
  2060. local hue_sector = math.floor( hue / 60 );
  2061. local hue_sector_offset = ( hue / 60 ) - hue_sector;
  2062.  
  2063. local p = value * ( 1 - saturation );
  2064. local q = value * ( 1 - saturation * hue_sector_offset );
  2065. local t = value * ( 1 - saturation * ( 1 - hue_sector_offset ) );
  2066.  
  2067. if hue_sector == 0 then
  2068. return value, t, p;
  2069. elseif hue_sector == 1 then
  2070. return q, value, p;
  2071. elseif hue_sector == 2 then
  2072. return p, value, t;
  2073. elseif hue_sector == 3 then
  2074. return p, q, value;
  2075. elseif hue_sector == 4 then
  2076. return t, p, value;
  2077. elseif hue_sector == 5 then
  2078. return value, p, q;
  2079. end;
  2080. end;
  2081.  
  2082. function _RGBToHSV( red, green, blue )
  2083. -- Returns the HSV equivalent of the given RGB-defined color
  2084. -- (adapted from some code found around the web)
  2085.  
  2086. local hue, saturation, value;
  2087.  
  2088. local min_value = math.min( red, green, blue );
  2089. local max_value = math.max( red, green, blue );
  2090.  
  2091. value = max_value;
  2092.  
  2093. local value_delta = max_value - min_value;
  2094.  
  2095. -- If the color is not black
  2096. if max_value ~= 0 then
  2097. saturation = value_delta / max_value;
  2098.  
  2099. -- If the color is purely black
  2100. else
  2101. saturation = 0;
  2102. hue = -1;
  2103. return hue, saturation, value;
  2104. end;
  2105.  
  2106. if red == max_value then
  2107. hue = ( green - blue ) / value_delta;
  2108. elseif green == max_value then
  2109. hue = 2 + ( blue - red ) / value_delta;
  2110. else
  2111. hue = 4 + ( red - green ) / value_delta;
  2112. end;
  2113.  
  2114. hue = hue * 60;
  2115. if hue < 0 then
  2116. hue = hue + 360;
  2117. end;
  2118.  
  2119. return hue, saturation, value;
  2120. end;
  2121.  
  2122. ------------------------------------------
  2123. -- Create data containers
  2124. ------------------------------------------
  2125. ActiveKeys = {};
  2126.  
  2127. CurrentTool = nil;
  2128.  
  2129. function equipTool( NewTool )
  2130.  
  2131. -- If it's a different tool than the current one
  2132. if CurrentTool ~= NewTool then
  2133.  
  2134. -- Run (if existent) the old tool's `Unequipped` listener
  2135. if CurrentTool and CurrentTool.Listeners.Unequipped then
  2136. CurrentTool.Listeners.Unequipped();
  2137. end;
  2138.  
  2139. CurrentTool = NewTool;
  2140.  
  2141. -- Recolor the handle
  2142. if ToolType == 'tool' then
  2143. Tool.Handle.BrickColor = NewTool.Color;
  2144. end;
  2145.  
  2146. -- Highlight the right button on the dock
  2147. for _, Button in pairs( Dock.ToolButtons:GetChildren() ) do
  2148. Button.BackgroundTransparency = 1;
  2149. end;
  2150. local Button = Dock.ToolButtons:FindFirstChild( getToolName( NewTool ) .. "Button" );
  2151. if Button then
  2152. Button.BackgroundTransparency = 0;
  2153. end;
  2154.  
  2155. -- Run (if existent) the new tool's `Equipped` listener
  2156. if NewTool.Listeners.Equipped then
  2157. NewTool.Listeners.Equipped();
  2158. end;
  2159.  
  2160. end;
  2161. end;
  2162.  
  2163. function cloneSelection()
  2164. -- Clones the items in the selection
  2165.  
  2166. -- Make sure that there are items in the selection
  2167. if #Selection.Items > 0 then
  2168.  
  2169. local item_copies = {};
  2170.  
  2171. -- Make a copy of every item in the selection and add it to table `item_copies`
  2172. for _, Item in pairs( Selection.Items ) do
  2173. local ItemCopy = Item:Clone();
  2174. ItemCopy.Parent = Services.Workspace;
  2175. table.insert( item_copies, ItemCopy );
  2176. end;
  2177.  
  2178. -- Replace the selection with the copied items
  2179. Selection:clear();
  2180. for _, Item in pairs( item_copies ) do
  2181. Selection:add( Item );
  2182. end;
  2183.  
  2184. local HistoryRecord = {
  2185. copies = item_copies;
  2186. unapply = function ( self )
  2187. for _, Copy in pairs( self.copies ) do
  2188. if Copy then
  2189. Copy.Parent = nil;
  2190. end;
  2191. end;
  2192. end;
  2193. apply = function ( self )
  2194. Selection:clear();
  2195. for _, Copy in pairs( self.copies ) do
  2196. if Copy then
  2197. Copy.Parent = Services.Workspace;
  2198. Copy:MakeJoints();
  2199. Selection:add( Copy );
  2200. end;
  2201. end;
  2202. end;
  2203. };
  2204. History:add( HistoryRecord );
  2205.  
  2206. -- Play a confirmation sound
  2207. local Sound = RbxUtility.Create "Sound" {
  2208. Name = "BTActionCompletionSound";
  2209. Pitch = 1.5;
  2210. SoundId = action_completion_sound;
  2211. Volume = 1;
  2212. Parent = Player or Services.SoundService;
  2213. };
  2214. Sound:Play();
  2215. Sound:Destroy();
  2216.  
  2217. -- Highlight the outlines of the new parts
  2218. coroutine.wrap( function ()
  2219. for transparency = 1, 0.5, -0.1 do
  2220. for Item, SelectionBox in pairs( SelectionBoxes ) do
  2221. SelectionBox.Transparency = transparency;
  2222. end;
  2223. wait( 0.1 );
  2224. end;
  2225. end )();
  2226.  
  2227. end;
  2228.  
  2229. end;
  2230.  
  2231. function deleteSelection()
  2232. -- Deletes the items in the selection
  2233.  
  2234. if #Selection.Items == 0 then
  2235. return;
  2236. end;
  2237.  
  2238. local selection_items = _cloneTable( Selection.Items );
  2239.  
  2240. -- Create a history record
  2241. local HistoryRecord = {
  2242. targets = selection_items;
  2243. parents = {};
  2244. apply = function ( self )
  2245. for _, Target in pairs( self.targets ) do
  2246. if Target then
  2247. Target.Parent = nil;
  2248. end;
  2249. end;
  2250. end;
  2251. unapply = function ( self )
  2252. Selection:clear();
  2253. for _, Target in pairs( self.targets ) do
  2254. if Target then
  2255. Target.Parent = self.parents[Target];
  2256. Target:MakeJoints();
  2257. Selection:add( Target );
  2258. end;
  2259. end;
  2260. end;
  2261. };
  2262.  
  2263. for _, Item in pairs( selection_items ) do
  2264. HistoryRecord.parents[Item] = Item.Parent;
  2265. Item.Parent = nil;
  2266. end;
  2267.  
  2268. History:add( HistoryRecord );
  2269.  
  2270. end;
  2271.  
  2272. function prismSelect()
  2273. -- Selects all the parts within the area of the selected parts
  2274.  
  2275. -- Make sure parts to define the area are present
  2276. if #Selection.Items == 0 then
  2277. return;
  2278. end;
  2279.  
  2280. local parts = {};
  2281.  
  2282. -- Get all the parts in workspace
  2283. local workspace_parts = {};
  2284. local workspace_children = _getAllDescendants( Services.Workspace );
  2285. for _, Child in pairs( workspace_children ) do
  2286. if Child:IsA( 'BasePart' ) and not Selection:find( Child ) then
  2287. table.insert( workspace_parts, Child );
  2288. end;
  2289. end;
  2290.  
  2291. -- Go through each part and perform area tests on each one
  2292. local checks = {};
  2293. for _, Item in pairs( workspace_parts ) do
  2294. checks[Item] = 0;
  2295. for _, SelectionItem in pairs( Selection.Items ) do
  2296.  
  2297. -- Calculate the position of the item in question in relation to the area-defining parts
  2298. local offset = SelectionItem.CFrame:toObjectSpace( Item.CFrame );
  2299. local extents = SelectionItem.Size / 2;
  2300.  
  2301. -- Check the item off if it passed this test (if it's within the range of the extents)
  2302. if ( math.abs( offset.x ) <= extents.x ) and ( math.abs( offset.y ) <= extents.y ) and ( math.abs( offset.z ) <= extents.z ) then
  2303. checks[Item] = checks[Item] + 1;
  2304. end;
  2305.  
  2306. end;
  2307. end;
  2308.  
  2309. -- Delete the parts that were used to select the area
  2310. local selection_items = _cloneTable( Selection.Items );
  2311. local selection_item_parents = {};
  2312. for _, Item in pairs( selection_items ) do
  2313. selection_item_parents[Item] = Item.Parent;
  2314. Item.Parent = nil;
  2315. end;
  2316.  
  2317. -- Select the parts that passed any area checks
  2318. for _, Item in pairs( workspace_parts ) do
  2319. if checks[Item] > 0 then
  2320. Selection:add( Item );
  2321. end;
  2322. end;
  2323.  
  2324. -- Add a history record
  2325. History:add( {
  2326. selection_parts = selection_items;
  2327. selection_part_parents = selection_item_parents;
  2328. new_selection = _cloneTable( Selection.Items );
  2329. apply = function ( self )
  2330. Selection:clear();
  2331. for _, Item in pairs( self.selection_parts ) do
  2332. Item.Parent = nil;
  2333. end;
  2334. for _, Item in pairs( self.new_selection ) do
  2335. Selection:add( Item );
  2336. end;
  2337. end;
  2338. unapply = function ( self )
  2339. Selection:clear();
  2340. for _, Item in pairs( self.selection_parts ) do
  2341. Item.Parent = self.selection_part_parents[Item];
  2342. Selection:add( Item );
  2343. end;
  2344. end;
  2345. } );
  2346.  
  2347. end;
  2348.  
  2349. function toggleHelp()
  2350.  
  2351. -- Make sure the dock is ready
  2352. if not Dock then
  2353. return;
  2354. end;
  2355.  
  2356. -- Toggle the visibility of the help tooltip
  2357. Dock.HelpInfo.Visible = not Dock.HelpInfo.Visible;
  2358.  
  2359. end;
  2360.  
  2361. function getToolName( tool )
  2362. -- Returns the name of `tool` as registered in `Tools`
  2363.  
  2364. local name_search = _findTableOccurrences( Tools, tool );
  2365. if #name_search > 0 then
  2366. return name_search[1];
  2367. end;
  2368.  
  2369. end;
  2370.  
  2371. function isSelectable( Object )
  2372. -- Returns whether `Object` is selectable
  2373.  
  2374. if not Object or not Object.Parent or not Object:IsA( "BasePart" ) or Object.Locked or Selection:find( Object ) then
  2375. return false;
  2376. end;
  2377.  
  2378. -- If it passes all checks, return true
  2379. return true;
  2380. end;
  2381.  
  2382. -- Keep some state data
  2383. clicking = false;
  2384. selecting = false;
  2385. click_x, click_y = 0, 0;
  2386. override_selection = false;
  2387.  
  2388. SelectionBoxes = {};
  2389. SelectionExistenceListeners = {};
  2390. SelectionBoxColor = BrickColor.new( "Cyan" );
  2391. TargetBox = nil;
  2392.  
  2393. -- Keep a container for temporary connections
  2394. -- from the platform
  2395. Connections = {};
  2396.  
  2397. -- Set the grip for the handle
  2398. if ToolType == 'tool' then
  2399. Tool.Grip = CFrame.new( 0, 0, 0.4 );
  2400. end;
  2401.  
  2402. -- Make sure the UI container gets placed
  2403. UI = RbxUtility.Create "ScreenGui" {
  2404. Name = "Building Tools by F3X (UI)"
  2405. };
  2406. if ToolType == 'tool' then
  2407. UI.Parent = GUIContainer;
  2408. elseif ToolType == 'plugin' then
  2409. UI.Parent = Services.CoreGui;
  2410. end;
  2411.  
  2412. Dragger = nil;
  2413.  
  2414. function updateSelectionBoxColor()
  2415. -- Updates the color of the selectionboxes
  2416. for _, SelectionBox in pairs( SelectionBoxes ) do
  2417. SelectionBox.Color = SelectionBoxColor;
  2418. end;
  2419. end;
  2420.  
  2421. Selection = {
  2422.  
  2423. ["Items"] = {};
  2424.  
  2425. -- Provide events to listen to changes in the selection
  2426. ["Changed"] = RbxUtility.CreateSignal();
  2427. ["ItemAdded"] = RbxUtility.CreateSignal();
  2428. ["ItemRemoved"] = RbxUtility.CreateSignal();
  2429.  
  2430. -- Provide a method to get an item's index in the selection
  2431. ["find"] = function ( self, Needle )
  2432.  
  2433. -- Look through all the selected items and return the matching item's index
  2434. for item_index, Item in pairs( self.Items ) do
  2435. if Item == Needle then
  2436. return item_index;
  2437. end;
  2438. end;
  2439.  
  2440. -- Otherwise, return `nil`
  2441.  
  2442. end;
  2443.  
  2444. -- Provide a method to add items to the selection
  2445. ["add"] = function ( self, NewPart )
  2446.  
  2447. -- Make sure `NewPart` is selectable
  2448. if not isSelectable( NewPart ) then
  2449. return false;
  2450. end;
  2451.  
  2452. -- Make sure `NewPart` isn't already in the selection
  2453. if #_findTableOccurrences( self.Items, NewPart ) > 0 then
  2454. return false;
  2455. end;
  2456.  
  2457. -- Insert it into the selection
  2458. table.insert( self.Items, NewPart );
  2459.  
  2460. -- Add its SelectionBox
  2461. SelectionBoxes[NewPart] = Instance.new( "SelectionBox", UI );
  2462. SelectionBoxes[NewPart].Name = "BTSelectionBox";
  2463. SelectionBoxes[NewPart].Color = SelectionBoxColor;
  2464. SelectionBoxes[NewPart].Adornee = NewPart;
  2465. SelectionBoxes[NewPart].Transparency = 0.5;
  2466.  
  2467. -- Remove any target selection box focus
  2468. if NewPart == TargetBox.Adornee then
  2469. TargetBox.Adornee = nil;
  2470. end;
  2471.  
  2472. -- Make sure to remove the item from the selection when it's deleted
  2473. SelectionExistenceListeners[NewPart] = NewPart.AncestryChanged:connect( function ( Object, NewParent )
  2474. if NewParent == nil then
  2475. Selection:remove( NewPart );
  2476. end;
  2477. end );
  2478.  
  2479. -- Provide a reference to the last item added to the selection (i.e. NewPart)
  2480. self:focus( NewPart );
  2481.  
  2482. -- Fire events
  2483. self.ItemAdded:fire( NewPart );
  2484. self.Changed:fire();
  2485.  
  2486. end;
  2487.  
  2488. -- Provide a method to remove items from the selection
  2489. ["remove"] = function ( self, Item )
  2490.  
  2491. -- Make sure selection item `Item` exists
  2492. if not self:find( Item ) then
  2493. return false;
  2494. end;
  2495.  
  2496. -- Remove `Item`'s SelectionBox
  2497. local SelectionBox = SelectionBoxes[Item];
  2498. if SelectionBox then
  2499. SelectionBox:Destroy();
  2500. end;
  2501. SelectionBoxes[Item] = nil;
  2502.  
  2503. -- Delete the item from the selection
  2504. table.remove( self.Items, self:find( Item ) );
  2505.  
  2506. -- If it was logged as the last item, change it
  2507. if self.Last == Item then
  2508. self:focus( ( #self.Items > 0 ) and self.Items[#self.Items] or nil );
  2509. end;
  2510.  
  2511. -- Delete the existence listeners of the item
  2512. SelectionExistenceListeners[Item]:disconnect();
  2513. SelectionExistenceListeners[Item] = nil;
  2514.  
  2515. -- Fire events
  2516. self.ItemRemoved:fire( Item );
  2517. self.Changed:fire();
  2518.  
  2519. end;
  2520.  
  2521. -- Provide a method to clear the selection
  2522. ["clear"] = function ( self )
  2523.  
  2524. -- Go through all the items in the selection and call `self.remove` on them
  2525. for _, Item in pairs( _cloneTable( self.Items ) ) do
  2526. self:remove( Item );
  2527. end;
  2528.  
  2529. end;
  2530.  
  2531. -- Provide a method to change the focus of the selection
  2532. ["focus"] = function ( self, NewFocus )
  2533.  
  2534. -- Change the focus
  2535. self.Last = NewFocus;
  2536.  
  2537. -- Fire events
  2538. self.Changed:fire();
  2539.  
  2540. end;
  2541.  
  2542. };
  2543.  
  2544. -- Keep the Studio selection up-to-date (if applicable)
  2545. if ToolType == 'plugin' then
  2546. Selection.Changed:connect( function ()
  2547. Services.Selection:Set( Selection.Items );
  2548. end );
  2549. end;
  2550.  
  2551. Tools = {};
  2552.  
  2553. ------------------------------------------
  2554. -- Define other utilities needed by tools
  2555. ------------------------------------------
  2556.  
  2557. function createDropdown()
  2558.  
  2559. local Frame = RbxUtility.Create "Frame" {
  2560. Name = "Dropdown";
  2561. Size = UDim2.new( 0, 20, 0, 20 );
  2562. BackgroundTransparency = 1;
  2563. BorderSizePixel = 0;
  2564. ClipsDescendants = true;
  2565. };
  2566.  
  2567. RbxUtility.Create "ImageLabel" {
  2568. Parent = Frame;
  2569. Name = "Arrow";
  2570. BackgroundTransparency = 1;
  2571. BorderSizePixel = 0;
  2572. Image = expand_arrow;
  2573. Position = UDim2.new( 1, -21, 0, 3 );
  2574. Size = UDim2.new( 0, 20, 0, 20 );
  2575. ZIndex = 3;
  2576. };
  2577.  
  2578. local DropdownObject = {
  2579. -- Provide access to the actual frame
  2580. Frame = Frame;
  2581.  
  2582. -- Keep a list of all the options in the dropdown
  2583. _options = {};
  2584.  
  2585. -- Provide a function to add options to the dropdown
  2586. addOption = function ( self, option )
  2587.  
  2588. -- Add the option to the list
  2589. table.insert( self._options, option );
  2590.  
  2591. -- Create the GUI for the option
  2592. local Button = RbxUtility.Create "TextButton" {
  2593. Parent = self.Frame;
  2594. BackgroundColor3 = Color3.new( 0, 0, 0 );
  2595. BackgroundTransparency = 0.3;
  2596. BorderColor3 = Color3.new( 27 / 255, 42 / 255, 53 / 255 );
  2597. BorderSizePixel = 1;
  2598. Name = option;
  2599. Position = UDim2.new( math.ceil( #self._options / 9 ) - 1, 0, 0, 25 * ( ( #self._options % 9 == 0 ) and 9 or ( #self._options % 9 ) ) );
  2600. Size = UDim2.new( 1, 0, 0, 25 );
  2601. ZIndex = 3;
  2602. Text = "";
  2603. };
  2604. local Label = RbxUtility.Create "TextLabel" {
  2605. Parent = Button;
  2606. BackgroundTransparency = 1;
  2607. BorderSizePixel = 0;
  2608. Position = UDim2.new( 0, 6, 0, 0 );
  2609. Size = UDim2.new( 1, -30, 1, 0 );
  2610. ZIndex = 3;
  2611. Font = Enum.Font.ArialBold;
  2612. FontSize = Enum.FontSize.Size12;
  2613. Text = option;
  2614. TextColor3 = Color3.new( 1, 1, 1 );
  2615. TextXAlignment = Enum.TextXAlignment.Left;
  2616. TextYAlignment = Enum.TextYAlignment.Center;
  2617. };
  2618.  
  2619. -- Return the button object
  2620. return Button;
  2621.  
  2622. end;
  2623.  
  2624. selectOption = function ( self, option )
  2625. self.Frame.MainButton.CurrentOption.Text = option;
  2626. end;
  2627.  
  2628. open = false;
  2629.  
  2630. toggle = function ( self )
  2631.  
  2632. -- If it's open, close it
  2633. if self.open then
  2634. self.Frame.MainButton.BackgroundTransparency = 0.3;
  2635. self.Frame.ClipsDescendants = true;
  2636. self.open = false;
  2637.  
  2638. -- If it's not open, open it
  2639. else
  2640. self.Frame.MainButton.BackgroundTransparency = 0;
  2641. self.Frame.ClipsDescendants = false;
  2642. self.open = true;
  2643. end;
  2644.  
  2645. end;
  2646.  
  2647. };
  2648.  
  2649. -- Create the GUI for the option
  2650. local MainButton = RbxUtility.Create "TextButton" {
  2651. Parent = Frame;
  2652. Name = "MainButton";
  2653. BackgroundColor3 = Color3.new( 0, 0, 0 );
  2654. BackgroundTransparency = 0.3;
  2655. BorderColor3 = Color3.new( 27 / 255, 42 / 255, 53 / 255 );
  2656. BorderSizePixel = 1;
  2657. Position = UDim2.new( 0, 0, 0, 0 );
  2658. Size = UDim2.new( 1, 0, 0, 25 );
  2659. ZIndex = 2;
  2660. Text = "";
  2661.  
  2662. -- Toggle the dropdown when pressed
  2663. [RbxUtility.Create.E "MouseButton1Up"] = function ()
  2664. DropdownObject:toggle();
  2665. end;
  2666. };
  2667. RbxUtility.Create "TextLabel" {
  2668. Parent = MainButton;
  2669. Name = "CurrentOption";
  2670. BackgroundTransparency = 1;
  2671. BorderSizePixel = 0;
  2672. Position = UDim2.new( 0, 6, 0, 0 );
  2673. Size = UDim2.new( 1, -30, 1, 0 );
  2674. ZIndex = 3;
  2675. Font = Enum.Font.ArialBold;
  2676. FontSize = Enum.FontSize.Size12;
  2677. Text = "";
  2678. TextColor3 = Color3.new( 1, 1, 1 );
  2679. TextXAlignment = Enum.TextXAlignment.Left;
  2680. TextYAlignment = Enum.TextYAlignment.Center;
  2681. };
  2682.  
  2683. return DropdownObject;
  2684.  
  2685. end;
  2686.  
  2687. ------------------------------------------
  2688. -- Provide an interface to the 2D
  2689. -- selection system
  2690. ------------------------------------------
  2691.  
  2692. Select2D = {
  2693.  
  2694. -- Keep state data
  2695. ["enabled"] = false;
  2696.  
  2697. -- Keep objects
  2698. ["GUI"] = nil;
  2699.  
  2700. -- Keep temporary, disposable connections
  2701. ["Connections"] = {};
  2702.  
  2703. -- Provide an interface to the functions
  2704. ["start"] = function ( self )
  2705.  
  2706. if enabled then
  2707. return;
  2708. end;
  2709.  
  2710. self.enabled = true;
  2711.  
  2712. -- Create the GUI
  2713. self.GUI = RbxUtility.Create "ScreenGui" {
  2714. Name = "BTSelectionRectangle";
  2715. Parent = UI;
  2716. };
  2717.  
  2718. local Rectangle = RbxUtility.Create "Frame" {
  2719. Name = "Rectangle";
  2720. Active = false;
  2721. Parent = self.GUI;
  2722. BackgroundColor3 = Color3.new( 0, 0, 0 );
  2723. BackgroundTransparency = 0.5;
  2724. BorderSizePixel = 0;
  2725. Position = UDim2.new( 0, math.min( click_x, Mouse.X ), 0, math.min( click_y, Mouse.Y ) );
  2726. Size = UDim2.new( 0, math.max( click_x, Mouse.X ) - math.min( click_x, Mouse.X ), 0, math.max( click_y, Mouse.Y ) - math.min( click_y, Mouse.Y ) );
  2727. };
  2728.  
  2729. -- Listen for when to resize the selection
  2730. self.Connections.SelectionResize = Mouse.Move:connect( function ()
  2731. Rectangle.Position = UDim2.new( 0, math.min( click_x, Mouse.X ), 0, math.min( click_y, Mouse.Y ) );
  2732. Rectangle.Size = UDim2.new( 0, math.max( click_x, Mouse.X ) - math.min( click_x, Mouse.X ), 0, math.max( click_y, Mouse.Y ) - math.min( click_y, Mouse.Y ) );
  2733. end );
  2734.  
  2735. -- Listen for when the selection ends
  2736. self.Connections.SelectionEnd = Mouse.Button1Up:connect( function ()
  2737. self:select();
  2738. self:finish();
  2739. end );
  2740.  
  2741. end;
  2742.  
  2743. ["select"] = function ( self )
  2744.  
  2745. if not self.enabled then
  2746. return;
  2747. end;
  2748.  
  2749. for _, Object in pairs( _getAllDescendants( Services.Workspace ) ) do
  2750.  
  2751. -- Make sure we can select this part
  2752. if isSelectable( Object ) then
  2753.  
  2754. -- Check if the part is rendered within the range of the selection area
  2755. local PartPosition = _pointToScreenSpace( Object.Position );
  2756. if PartPosition then
  2757. local left_check = PartPosition.x >= self.GUI.Rectangle.AbsolutePosition.x;
  2758. local right_check = PartPosition.x <= ( self.GUI.Rectangle.AbsolutePosition.x + self.GUI.Rectangle.AbsoluteSize.x );
  2759. local top_check = PartPosition.y >= self.GUI.Rectangle.AbsolutePosition.y;
  2760. local bottom_check = PartPosition.y <= ( self.GUI.Rectangle.AbsolutePosition.y + self.GUI.Rectangle.AbsoluteSize.y );
  2761.  
  2762. -- If the part is within the selection area, select it
  2763. if left_check and right_check and top_check and bottom_check then
  2764. Selection:add( Object );
  2765. end;
  2766. end;
  2767.  
  2768. end;
  2769.  
  2770. end;
  2771.  
  2772. end;
  2773.  
  2774. ["finish"] = function ( self )
  2775.  
  2776. if not self.enabled then
  2777. return;
  2778. end;
  2779.  
  2780. -- Disconnect temporary connections
  2781. for connection_index, Connection in pairs( self.Connections ) do
  2782. Connection:disconnect();
  2783. self.Connections[connection_index] = nil;
  2784. end;
  2785.  
  2786. -- Remove temporary objects
  2787. self.GUI:Destroy();
  2788. self.GUI = nil;
  2789.  
  2790. self.enabled = false;
  2791.  
  2792. end;
  2793.  
  2794. };
  2795.  
  2796. ------------------------------------------
  2797. -- Provide an interface to the edge
  2798. -- selection system
  2799. ------------------------------------------
  2800. SelectEdge = {
  2801.  
  2802. -- Keep state data
  2803. ["enabled"] = false;
  2804. ["started"] = false;
  2805.  
  2806. -- Keep objects
  2807. ["Marker"] = nil;
  2808. ["MarkerOutline"] = RbxUtility.Create "SelectionBox" {
  2809. Color = BrickColor.new( "Institutional white" );
  2810. Parent = UI;
  2811. Name = "BTEdgeSelectionMarkerOutline";
  2812. };
  2813.  
  2814. -- Keep temporary, disposable connections
  2815. ["Connections"] = {};
  2816.  
  2817. -- Provide an interface to the functions
  2818. ["start"] = function ( self, edgeSelectionCallback )
  2819.  
  2820. if self.started then
  2821. return;
  2822. end;
  2823.  
  2824. -- Listen for when to engage in selection
  2825. self.Connections.KeyListener = Mouse.KeyDown:connect( function ( key )
  2826.  
  2827. local key = key:lower();
  2828. local key_code = key:byte();
  2829.  
  2830. if key == "t" and #Selection.Items > 0 then
  2831. self:enable( edgeSelectionCallback );
  2832. end;
  2833.  
  2834. end );
  2835.  
  2836. self.started = true;
  2837.  
  2838. end;
  2839.  
  2840. ["enable"] = function ( self, edgeSelectionCallback )
  2841.  
  2842. if self.enabled then
  2843. return;
  2844. end;
  2845.  
  2846. self.Connections.MoveListener = Mouse.Move:connect( function ()
  2847.  
  2848. -- Make sure the target can be selected
  2849. if not Selection:find( Mouse.Target ) then
  2850. return;
  2851. end;
  2852.  
  2853. -- Calculate the proximity to each edge
  2854. local Proximity = {};
  2855. local edges = {};
  2856.  
  2857. -- Create shortcuts to certain things that are expensive to call constantly
  2858. local table_insert = table.insert;
  2859. local newCFrame = CFrame.new;
  2860. local PartCFrame = Mouse.Target.CFrame;
  2861. local partCFrameOffset = PartCFrame.toWorldSpace;
  2862. local PartSize = Mouse.Target.Size / 2;
  2863. local size_x, size_y, size_z = PartSize.x, PartSize.y, PartSize.z;
  2864.  
  2865. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, size_y, size_z ) ) );
  2866. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, size_y, size_z ) ) );
  2867. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, -size_y, size_z ) ) );
  2868. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, size_y, -size_z ) ) );
  2869. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, size_y, -size_z ) ) );
  2870. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, -size_y, size_z ) ) );
  2871. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, -size_y, -size_z ) ) );
  2872. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, -size_y, -size_z ) ) );
  2873. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, size_y, 0 ) ) );
  2874. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, 0, size_z ) ) );
  2875. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( 0, size_y, size_z ) ) );
  2876. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, 0, 0 ) ) );
  2877. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( 0, size_y, 0 ) ) );
  2878. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( 0, 0, size_z ) ) );
  2879. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, size_y, 0 ) ) );
  2880. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, 0, size_z ) ) );
  2881. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( 0, -size_y, size_z ) ) );
  2882. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, 0, 0 ) ) );
  2883. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( 0, -size_y, 0 ) ) );
  2884. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( 0, 0, -size_z ) ) );
  2885. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, -size_y, 0 ) ) );
  2886. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( size_x, 0, -size_z ) ) );
  2887. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( 0, size_y, -size_z ) ) );
  2888. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, -size_y, 0 ) ) );
  2889. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( -size_x, 0, -size_z ) ) );
  2890. table_insert( edges, partCFrameOffset( PartCFrame, newCFrame( 0, -size_y, -size_z ) ) );
  2891.  
  2892. -- Calculate the proximity of every edge to the mouse
  2893. for edge_index, Edge in pairs( edges ) do
  2894. Proximity[edge_index] = ( Mouse.Hit.p - Edge.p ).magnitude;
  2895. end;
  2896.  
  2897. -- Get the closest edge to the mouse
  2898. local highest_proximity = 1;
  2899. for proximity_index, proximity in pairs( Proximity ) do
  2900. if proximity < Proximity[highest_proximity] then
  2901. highest_proximity = proximity_index;
  2902. end;
  2903. end;
  2904.  
  2905. -- Replace the current target edge (if any)
  2906. local ClosestEdge = edges[highest_proximity];
  2907.  
  2908. if self.Marker then
  2909. self.Marker:Destroy();
  2910. end;
  2911. self.Marker = RbxUtility.Create "Part" {
  2912. Name = "BTEdgeSelectionMarker";
  2913. Anchored = true;
  2914. Locked = true;
  2915. CanCollide = false;
  2916. Transparency = 1;
  2917. FormFactor = Enum.FormFactor.Custom;
  2918. Size = Vector3.new( 0.2, 0.2, 0.2 );
  2919. CFrame = ClosestEdge;
  2920. };
  2921.  
  2922. self.MarkerOutline.Adornee = self.Marker;
  2923.  
  2924. end );
  2925.  
  2926. self.Connections.ClickListener = Mouse.Button1Up:connect( function ()
  2927. override_selection = true;
  2928. self:select( edgeSelectionCallback );
  2929. end );
  2930.  
  2931. self.enabled = true;
  2932.  
  2933. end;
  2934.  
  2935. ["select"] = function ( self, callback )
  2936.  
  2937. if not self.enabled or not self.Marker then
  2938. return;
  2939. end;
  2940.  
  2941. self.MarkerOutline.Adornee = self.Marker;
  2942.  
  2943. callback( self.Marker );
  2944.  
  2945. -- Stop treating it like a marker
  2946. self.Marker = nil;
  2947.  
  2948. self:disable();
  2949.  
  2950. end;
  2951.  
  2952. ["disable"] = function ( self )
  2953.  
  2954. if not self.enabled then
  2955. return;
  2956. end;
  2957.  
  2958. -- Disconnect unnecessary temporary connections
  2959. if self.Connections.ClickListener then
  2960. self.Connections.ClickListener:disconnect();
  2961. self.Connections.ClickListener = nil;
  2962. end;
  2963. if self.Connections.MoveListener then
  2964. self.Connections.MoveListener:disconnect();
  2965. self.Connections.MoveListener = nil;
  2966. end;
  2967.  
  2968. -- Remove temporary objects
  2969. if self.Marker then
  2970. self.Marker:Destroy();
  2971. end;
  2972. self.Marker = nil;
  2973.  
  2974. self.MarkerOutline.Adornee = nil;
  2975. self.enabled = false;
  2976.  
  2977. end;
  2978.  
  2979. ["stop"] = function ( self )
  2980.  
  2981. if not self.started then
  2982. return;
  2983. end;
  2984.  
  2985. -- Disconnect & remove all temporary connections
  2986. for connection_index, Connection in pairs( self.Connections ) do
  2987. Connection:disconnect();
  2988. self.Connections[connection_index] = nil;
  2989. end;
  2990.  
  2991. -- Remove temporary objects
  2992. if self.Marker then
  2993. self.Marker:Destroy();
  2994. end;
  2995.  
  2996. self.started = false;
  2997.  
  2998. end;
  2999.  
  3000. };
  3001.  
  3002. ------------------------------------------
  3003. -- Provide an interface to the history
  3004. -- system
  3005. ------------------------------------------
  3006. History = {
  3007.  
  3008. -- Keep a container for the actual history data
  3009. ["Data"] = {};
  3010.  
  3011. -- Keep state data
  3012. ["index"] = 0;
  3013.  
  3014. -- Provide events for the platform to listen for changes
  3015. ["Changed"] = RbxUtility.CreateSignal();
  3016.  
  3017. -- Provide functions to control the system
  3018. ["undo"] = function ( self )
  3019.  
  3020. -- Make sure we're not getting out of boundary
  3021. if self.index - 1 < 0 then
  3022. return;
  3023. end;
  3024.  
  3025. -- Fetch the history record & unapply it
  3026. local CurrentRecord = self.Data[self.index];
  3027. CurrentRecord:unapply();
  3028.  
  3029. -- Go back in the history
  3030. self.index = self.index - 1;
  3031.  
  3032. -- Fire the relevant events
  3033. self.Changed:fire();
  3034.  
  3035. end;
  3036.  
  3037. ["redo"] = function ( self )
  3038.  
  3039. -- Make sure we're not getting out of boundary
  3040. if self.index + 1 > #self.Data then
  3041. return;
  3042. end;
  3043.  
  3044. -- Go forward in the history
  3045. self.index = self.index + 1;
  3046.  
  3047. -- Fetch the new history record & apply it
  3048. local NewRecord = self.Data[self.index];
  3049. NewRecord:apply();
  3050.  
  3051. -- Fire the relevant events
  3052. self.Changed:fire();
  3053.  
  3054. end;
  3055.  
  3056. ["add"] = function ( self, Record )
  3057.  
  3058. -- Place the record in its right spot
  3059. self.Data[self.index + 1] = Record;
  3060.  
  3061. -- Advance the history index
  3062. self.index = self.index + 1;
  3063.  
  3064. -- Clear out the following history
  3065. for index = self.index + 1, #self.Data do
  3066. self.Data[index] = nil;
  3067. end;
  3068.  
  3069. -- Fire the relevant events
  3070. self.Changed:fire();
  3071.  
  3072. end;
  3073.  
  3074. };
  3075.  
  3076.  
  3077. ------------------------------------------
  3078. -- Provide an interface color picker
  3079. -- system
  3080. ------------------------------------------
  3081. ColorPicker = {
  3082.  
  3083. -- Keep some state data
  3084. ["enabled"] = false;
  3085. ["callback"] = nil;
  3086. ["track_mouse"] = nil;
  3087. ["hue"] = 0;
  3088. ["saturation"] = 1;
  3089. ["value"] = 1;
  3090.  
  3091. -- Keep the current GUI here
  3092. ["GUI"] = nil;
  3093.  
  3094. -- Keep temporary, disposable connections here
  3095. ["Connections"] = {};
  3096.  
  3097. -- Provide an interface to the functions
  3098. ["start"] = function ( self, callback, start_color )
  3099.  
  3100. -- Replace any existing color pickers
  3101. if self.enabled then
  3102. self:cancel();
  3103. end;
  3104. self.enabled = true;
  3105.  
  3106. -- Create the GUI
  3107. self.GUI = Tool.Interfaces.BTHSVColorPicker:Clone();
  3108. self.GUI.Parent = UI;
  3109.  
  3110. -- Register the callback function for when we're done here
  3111. self.callback = callback;
  3112.  
  3113. -- Update the GUI
  3114. local start_color = start_color or Color3.new( 1, 0, 0 );
  3115. self:_changeColor( _RGBToHSV( start_color.r, start_color.g, start_color.b ) );
  3116.  
  3117. -- Add functionality to the GUI's interactive elements
  3118. table.insert( self.Connections, self.GUI.HueSaturation.MouseButton1Down:connect( function ( x, y )
  3119. self.track_mouse = 'hue-saturation';
  3120. self:_onMouseMove( x, y );
  3121. end ) );
  3122.  
  3123. table.insert( self.Connections, self.GUI.HueSaturation.MouseButton1Up:connect( function ()
  3124. self.track_mouse = nil;
  3125. end ) );
  3126.  
  3127. table.insert( self.Connections, self.GUI.MouseMoved:connect( function ( x, y )
  3128. self:_onMouseMove( x, y );
  3129. end ) );
  3130.  
  3131. table.insert( self.Connections, self.GUI.Value.MouseButton1Down:connect( function ( x, y )
  3132. self.track_mouse = 'value';
  3133. self:_onMouseMove( x, y );
  3134. end ) );
  3135.  
  3136. table.insert( self.Connections, self.GUI.Value.MouseButton1Up:connect( function ()
  3137. self.track_mouse = nil;
  3138. end ) );
  3139.  
  3140. table.insert( self.Connections, self.GUI.OkButton.MouseButton1Up:connect( function ()
  3141. self:finish();
  3142. end ) );
  3143.  
  3144. table.insert( self.Connections, self.GUI.CancelButton.MouseButton1Up:connect( function ()
  3145. self:cancel();
  3146. end ) );
  3147.  
  3148. table.insert( self.Connections, self.GUI.HueOption.Input.TextButton.MouseButton1Down:connect( function ()
  3149. self.GUI.HueOption.Input.TextBox:CaptureFocus();
  3150. end ) );
  3151. table.insert( self.Connections, self.GUI.HueOption.Input.TextBox.FocusLost:connect( function ( enter_pressed )
  3152. local potential_new = tonumber( self.GUI.HueOption.Input.TextBox.Text );
  3153. if potential_new then
  3154. if potential_new > 360 then
  3155. potential_new = 360;
  3156. elseif potential_new < 0 then
  3157. potential_new = 0;
  3158. end;
  3159. self:_changeColor( potential_new, self.saturation, self.value );
  3160. else
  3161. self:_updateGUI();
  3162. end;
  3163. end ) );
  3164.  
  3165. table.insert( self.Connections, self.GUI.SaturationOption.Input.TextButton.MouseButton1Down:connect( function ()
  3166. self.GUI.SaturationOption.Input.TextBox:CaptureFocus();
  3167. end ) );
  3168. table.insert( self.Connections, self.GUI.SaturationOption.Input.TextBox.FocusLost:connect( function ( enter_pressed )
  3169. local potential_new = tonumber( ( self.GUI.SaturationOption.Input.TextBox.Text:gsub( '%%', '' ) ) );
  3170. if potential_new then
  3171. if potential_new > 100 then
  3172. potential_new = 100;
  3173. elseif potential_new < 0 then
  3174. potential_new = 0;
  3175. end;
  3176. self:_changeColor( self.hue, potential_new / 100, self.value );
  3177. else
  3178. self:_updateGUI();
  3179. end;
  3180. end ) );
  3181.  
  3182. table.insert( self.Connections, self.GUI.ValueOption.Input.TextButton.MouseButton1Down:connect( function ()
  3183. self.GUI.ValueOption.Input.TextBox:CaptureFocus();
  3184. end ) );
  3185. table.insert( self.Connections, self.GUI.ValueOption.Input.TextBox.FocusLost:connect( function ( enter_pressed )
  3186. local potential_new = tonumber( ( self.GUI.ValueOption.Input.TextBox.Text:gsub( '%%', '' ) ) );
  3187. if potential_new then
  3188. if potential_new < 0 then
  3189. potential_new = 0;
  3190. elseif potential_new > 100 then
  3191. potential_new = 100;
  3192. end;
  3193. self:_changeColor( self.hue, self.saturation, potential_new / 100 );
  3194. else
  3195. self:_updateGUI();
  3196. end;
  3197. end ) );
  3198.  
  3199. end;
  3200.  
  3201. ["_onMouseMove"] = function ( self, x, y )
  3202. if not self.track_mouse then
  3203. return;
  3204. end;
  3205.  
  3206. if self.track_mouse == 'hue-saturation' then
  3207. -- Calculate the mouse position relative to the graph
  3208. local graph_x, graph_y = x - self.GUI.HueSaturation.AbsolutePosition.x, y - self.GUI.HueSaturation.AbsolutePosition.y;
  3209.  
  3210. -- Make sure we're not going out of bounds
  3211. if graph_x < 0 then
  3212. graph_x = 0;
  3213. elseif graph_x > self.GUI.HueSaturation.AbsoluteSize.x then
  3214. graph_x = self.GUI.HueSaturation.AbsoluteSize.x;
  3215. end;
  3216. if graph_y < 0 then
  3217. graph_y = 0;
  3218. elseif graph_y > self.GUI.HueSaturation.AbsoluteSize.y then
  3219. graph_y = self.GUI.HueSaturation.AbsoluteSize.y;
  3220. end;
  3221.  
  3222. -- Calculate the new color and change it
  3223. self:_changeColor( 359 * graph_x / 209, 1 - graph_y / 200, self.value );
  3224.  
  3225. elseif self.track_mouse == 'value' then
  3226. -- Calculate the mouse position relative to the value bar
  3227. local bar_y = y - self.GUI.Value.AbsolutePosition.y;
  3228.  
  3229. -- Make sure we're not going out of bounds
  3230. if bar_y < 0 then
  3231. bar_y = 0;
  3232. elseif bar_y > self.GUI.Value.AbsoluteSize.y then
  3233. bar_y = self.GUI.Value.AbsoluteSize.y;
  3234. end;
  3235.  
  3236. -- Calculate the new color and change it
  3237. self:_changeColor( self.hue, self.saturation, 1 - bar_y / 200 );
  3238. end;
  3239. end;
  3240.  
  3241. ["_changeColor"] = function ( self, hue, saturation, value )
  3242. if hue ~= hue then
  3243. hue = 359;
  3244. end;
  3245. self.hue = hue;
  3246. self.saturation = saturation == 0 and 0.01 or saturation;
  3247. self.value = value;
  3248. self:_updateGUI();
  3249. end;
  3250.  
  3251. ["_updateGUI"] = function ( self )
  3252.  
  3253. self.GUI.HueSaturation.Cursor.Position = UDim2.new( 0, 209 * self.hue / 360 - 8, 0, ( 1 - self.saturation ) * 200 - 8 );
  3254. self.GUI.Value.Cursor.Position = UDim2.new( 0, -2, 0, ( 1 - self.value ) * 200 - 8 );
  3255.  
  3256. local color = Color3.new( _HSVToRGB( self.hue, self.saturation, self.value ) );
  3257. self.GUI.ColorDisplay.BackgroundColor3 = color;
  3258. self.GUI.Value.ColorBG.BackgroundColor3 = Color3.new( _HSVToRGB( self.hue, self.saturation, 1 ) );
  3259.  
  3260. self.GUI.HueOption.Bar.BackgroundColor3 = color;
  3261. self.GUI.SaturationOption.Bar.BackgroundColor3 = color;
  3262. self.GUI.ValueOption.Bar.BackgroundColor3 = color;
  3263.  
  3264. self.GUI.HueOption.Input.TextBox.Text = math.floor( self.hue );
  3265. self.GUI.SaturationOption.Input.TextBox.Text = math.floor( self.saturation * 100 ) .. "%";
  3266. self.GUI.ValueOption.Input.TextBox.Text = math.floor( self.value * 100 ) .. "%";
  3267.  
  3268. end;
  3269.  
  3270. ["finish"] = function ( self )
  3271.  
  3272. if not self.enabled then
  3273. return;
  3274. end;
  3275.  
  3276. -- Remove the GUI
  3277. if self.GUI then
  3278. self.GUI:Destroy();
  3279. end;
  3280. self.GUI = nil;
  3281. self.track_mouse = nil;
  3282.  
  3283. -- Disconnect all temporary connections
  3284. for connection_index, connection in pairs( self.Connections ) do
  3285. connection:disconnect();
  3286. self.Connections[connection_index] = nil;
  3287. end;
  3288.  
  3289. -- Call the callback function that was provided to us
  3290. self.callback( self.hue, self.saturation, self.value );
  3291. self.callback = nil;
  3292.  
  3293. self.enabled = false;
  3294.  
  3295. end;
  3296.  
  3297. ["cancel"] = function ( self )
  3298.  
  3299. if not self.enabled then
  3300. return;
  3301. end;
  3302.  
  3303. -- Remove the GUI
  3304. if self.GUI then
  3305. self.GUI:Destroy();
  3306. end;
  3307. self.GUI = nil;
  3308. self.track_mouse = nil;
  3309.  
  3310. -- Disconnect all temporary connections
  3311. for connection_index, connection in pairs( self.Connections ) do
  3312. connection:disconnect();
  3313. self.Connections[connection_index] = nil;
  3314. end;
  3315.  
  3316. -- Call the callback function that was provided to us
  3317. self.callback();
  3318. self.callback = nil;
  3319.  
  3320. self.enabled = false;
  3321.  
  3322. end;
  3323.  
  3324. };
  3325.  
  3326. ------------------------------------------
  3327. -- Provide an interface to the
  3328. -- import/export system
  3329. ------------------------------------------
  3330. IE = {
  3331.  
  3332. ["export"] = function ()
  3333.  
  3334. if #Selection.Items == 0 then
  3335. return;
  3336. end;
  3337.  
  3338. local serialized_selection = _serializeParts( Selection.Items );
  3339.  
  3340. -- Dump to logs
  3341. -- Services.TestService:Warn( false, "[Building Tools by F3X] Exported Model: \n" .. serialized_selection );
  3342.  
  3343. -- Get ready to upload to the web for retrieval
  3344. local upload_data;
  3345. local cancelUpload;
  3346.  
  3347. -- Create the export dialog
  3348. local Dialog = Tool.Interfaces.BTExportDialog:Clone();
  3349. Dialog.Loading.Size = UDim2.new( 1, 0, 0, 0 );
  3350. Dialog.Parent = UI;
  3351. Dialog.Loading:TweenSize( UDim2.new( 1, 0, 0, 80 ), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25 );
  3352. Dialog.Loading.CloseButton.MouseButton1Up:connect( function ()
  3353. cancelUpload();
  3354. Dialog:Destroy();
  3355. end );
  3356.  
  3357. -- Run the upload/post-upload/failure code in a coroutine
  3358. -- so it can be cancelled
  3359. coroutine.resume( coroutine.create( function ()
  3360. cancelUpload = function ()
  3361. coroutine.yield();
  3362. end;
  3363. local upload_attempt = ypcall( function ()
  3364. upload_data = PostAsync( "http://www.f3xteam.com/bt/export", serialized_selection );
  3365. end );
  3366.  
  3367. -- Make sure we're in a server
  3368. if ToolType == 'plugin' and not in_server then
  3369. Dialog.Loading.TextLabel.Text = "Use Tools > Test > Start Server to export from Studio";
  3370. Dialog.Loading.TextLabel.TextWrapped = true;
  3371. Dialog.Loading.CloseButton.Position = UDim2.new( 0, 0, 0, 50 );
  3372. Dialog.Loading.CloseButton.Text = 'Got it';
  3373. return;
  3374. end;
  3375.  
  3376. -- Fail graciously
  3377. if not upload_attempt then
  3378. Dialog.Loading.TextLabel.Text = "Upload failed";
  3379. Dialog.Loading.CloseButton.Text = 'Ok :(';
  3380. return;
  3381. end;
  3382. if not ( upload_data and type( upload_data ) == 'string' and upload_data:len() > 0 ) then
  3383. Dialog.Loading.TextLabel.Text = "Upload failed";
  3384. Dialog.Loading.CloseButton.Text = 'Ok ;(';
  3385. return;
  3386. end;
  3387. if not pcall( function () upload_data = RbxUtility.DecodeJSON( upload_data ); end ) or not upload_data then
  3388. Dialog.Loading.TextLabel.Text = "Upload failed";
  3389. Dialog.Loading.CloseButton.Text = "Ok :'(";
  3390. return;
  3391. end;
  3392. if not upload_data.success then
  3393. Dialog.Loading.TextLabel.Text = "Upload failed";
  3394. Dialog.Loading.CloseButton.Text = "Ok :''(";
  3395. end;
  3396.  
  3397. print( "[Building Tools by F3X] Uploaded Export: " .. upload_data.id );
  3398.  
  3399. Dialog.Loading.Visible = false;
  3400. Dialog.Info.Size = UDim2.new( 1, 0, 0, 0 );
  3401. Dialog.Info.CreationID.Text = upload_data.id;
  3402. Dialog.Info.Visible = true;
  3403. Dialog.Info:TweenSize( UDim2.new( 1, 0, 0, 75 ), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25 );
  3404. Dialog.Tip.Size = UDim2.new( 1, 0, 0, 0 );
  3405. Dialog.Tip.Visible = true;
  3406. Dialog.Tip:TweenSize( UDim2.new( 1, 0, 0, 30 ), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25 );
  3407. Dialog.Close.Size = UDim2.new( 1, 0, 0, 0 );
  3408. Dialog.Close.Visible = true;
  3409. Dialog.Close:TweenSize( UDim2.new( 1, 0, 0, 20 ), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25 );
  3410. Dialog.Close.Button.MouseButton1Up:connect( function ()
  3411. Dialog:Destroy();
  3412. end );
  3413.  
  3414. -- Play a confirmation sound
  3415. local Sound = RbxUtility.Create "Sound" {
  3416. Name = "BTActionCompletionSound";
  3417. Pitch = 1.5;
  3418. SoundId = action_completion_sound;
  3419. Volume = 1;
  3420. Parent = Player or Services.SoundService;
  3421. };
  3422. Sound:Play();
  3423. Sound:Destroy();
  3424. end ) );
  3425.  
  3426. end;
  3427.  
  3428. };
  3429.  
  3430. ------------------------------------------
  3431. -- Prepare the dock UI
  3432. ------------------------------------------
  3433.  
  3434. Tooltips = {};
  3435.  
  3436. Dock = Tool.Interfaces:WaitForChild( "BTDockGUI" ):Clone();
  3437. Dock.Parent = UI;
  3438. Dock.Visible = false;
  3439.  
  3440. -- Add functionality to each tool button
  3441. for _, ToolButton in pairs( Dock.ToolButtons:GetChildren() ) do
  3442.  
  3443. -- Get the tool name and the tool
  3444. local tool_name = ToolButton.Name:match( "(.+)Button" );
  3445.  
  3446. if tool_name then
  3447.  
  3448. -- Create the click connection
  3449. ToolButton.MouseButton1Up:connect( function ()
  3450. local Tool = Tools[tool_name];
  3451. if Tool then
  3452. equipTool( Tool );
  3453. end;
  3454. end );
  3455.  
  3456. ToolButton.MouseEnter:connect( function ()
  3457. local Tooltip = Tooltips[tool_name];
  3458. if Tooltip then
  3459. Tooltip:focus( 'button' );
  3460. end;
  3461. end );
  3462.  
  3463. ToolButton.MouseLeave:connect( function ()
  3464. local Tooltip = Tooltips[tool_name];
  3465. if Tooltip then
  3466. Tooltip:unfocus( 'button' );
  3467. end;
  3468. end );
  3469.  
  3470. end;
  3471.  
  3472. end;
  3473.  
  3474. -- Prepare the tooltips
  3475. for _, Tooltip in pairs( Dock.Tooltips:GetChildren() ) do
  3476.  
  3477. local tool_name = Tooltip.Name:match( "(.+)Info" );
  3478.  
  3479. Tooltips[tool_name] = {
  3480.  
  3481. GUI = Tooltip;
  3482.  
  3483. button_focus = false;
  3484. tooltip_focus = false;
  3485.  
  3486. focus = function ( self, source )
  3487. if Dock.HelpInfo.Visible then
  3488. return;
  3489. end;
  3490. if source == 'button' then
  3491. self.button_focus = true;
  3492. elseif source == 'tooltip' then
  3493. self.tooltip_focus = true;
  3494. end;
  3495. for _, Tooltip in pairs( Dock.Tooltips:GetChildren() ) do
  3496. Tooltip.Visible = false;
  3497. end;
  3498. self.GUI.Visible = true;
  3499. end;
  3500.  
  3501. unfocus = function ( self, source )
  3502. if source == 'button' then
  3503. self.button_focus = false;
  3504. elseif source == 'tooltip' then
  3505. self.tooltip_focus = false;
  3506. end;
  3507. if not self.button_focus and not self.tooltip_focus then
  3508. self.GUI.Visible = false;
  3509. end;
  3510. end;
  3511.  
  3512. };
  3513.  
  3514. -- Make it disappear after it's out of mouse focus
  3515. Tooltip.MouseEnter:connect( function ()
  3516. Tooltips[tool_name]:focus( 'tooltip' );
  3517. end );
  3518. Tooltip.MouseLeave:connect( function ()
  3519. Tooltips[tool_name]:unfocus( 'tooltip' );
  3520. end );
  3521.  
  3522. -- Create the scrolling container
  3523. local ScrollingContainer = Gloo.ScrollingContainer( true, false, 15 );
  3524. ScrollingContainer.GUI.Parent = Tooltip;
  3525.  
  3526. -- Put the tooltip content in the container
  3527. for _, Child in pairs( Tooltip.Content:GetChildren() ) do
  3528. Child.Parent = ScrollingContainer.Container;
  3529. end;
  3530. ScrollingContainer.GUI.Size = Dock.Tooltips.Size;
  3531. ScrollingContainer.Container.Size = Tooltip.Content.Size;
  3532. ScrollingContainer.Boundary.Size = Dock.Tooltips.Size;
  3533. ScrollingContainer.Boundary.BackgroundTransparency = 1;
  3534. Tooltip.Content:Destroy();
  3535.  
  3536. end;
  3537.  
  3538.  
  3539. -- Create the scrolling container for the help tooltip
  3540. local ScrollingContainer = Gloo.ScrollingContainer( true, false, 15 );
  3541. ScrollingContainer.GUI.Parent = Dock.HelpInfo;
  3542.  
  3543. -- Put the help tooltip content in the container
  3544. for _, Child in pairs( Dock.HelpInfo.Content:GetChildren() ) do
  3545. Child.Parent = ScrollingContainer.Container;
  3546. end;
  3547. ScrollingContainer.GUI.Size = Dock.HelpInfo.Size;
  3548. ScrollingContainer.Container.Size = Dock.HelpInfo.Content.Size;
  3549. ScrollingContainer.Boundary.Size = Dock.HelpInfo.Size;
  3550. ScrollingContainer.Boundary.BackgroundTransparency = 1;
  3551. Dock.HelpInfo.Content:Destroy();
  3552.  
  3553. -- Add functionality to the other GUI buttons
  3554. Dock.SelectionButtons.UndoButton.MouseButton1Up:connect( function ()
  3555. History:undo();
  3556. end );
  3557. Dock.SelectionButtons.RedoButton.MouseButton1Up:connect( function ()
  3558. History:redo();
  3559. end );
  3560. Dock.SelectionButtons.DeleteButton.MouseButton1Up:connect( function ()
  3561. deleteSelection();
  3562. end );
  3563. Dock.SelectionButtons.CloneButton.MouseButton1Up:connect( function ()
  3564. cloneSelection();
  3565. end );
  3566. Dock.SelectionButtons.ExportButton.MouseButton1Up:connect( function ()
  3567. IE:export();
  3568. end );
  3569. Dock.InfoButtons.HelpButton.MouseButton1Up:connect( function ()
  3570. toggleHelp();
  3571. end );
  3572.  
  3573. -- Shade the buttons according to whether they'll function or not
  3574. Selection.Changed:connect( function ()
  3575.  
  3576. -- If there are items, they should be active
  3577. if #Selection.Items > 0 then
  3578. Dock.SelectionButtons.DeleteButton.Image = delete_active_decal;
  3579. Dock.SelectionButtons.CloneButton.Image = clone_active_decal;
  3580. Dock.SelectionButtons.ExportButton.Image = export_active_decal;
  3581.  
  3582. -- If there aren't items, they shouldn't be active
  3583. else
  3584. Dock.SelectionButtons.DeleteButton.Image = delete_inactive_decal;
  3585. Dock.SelectionButtons.CloneButton.Image = clone_inactive_decal;
  3586. Dock.SelectionButtons.ExportButton.Image = export_inactive_decal;
  3587. end;
  3588.  
  3589. end );
  3590.  
  3591. -- Make the selection/info buttons display tooltips upon hovering over them
  3592. for _, SelectionButton in pairs( Dock.SelectionButtons:GetChildren() ) do
  3593. SelectionButton.MouseEnter:connect( function ()
  3594. if SelectionButton:FindFirstChild( 'Tooltip' ) then
  3595. SelectionButton.Tooltip.Visible = true;
  3596. end;
  3597. end );
  3598. SelectionButton.MouseLeave:connect( function ()
  3599. if SelectionButton:FindFirstChild( 'Tooltip' ) then
  3600. SelectionButton.Tooltip.Visible = false;
  3601. end;
  3602. end );
  3603. end;
  3604. Dock.InfoButtons.HelpButton.MouseEnter:connect( function ()
  3605. Dock.InfoButtons.HelpButton.Tooltip.Visible = true;
  3606. end );
  3607. Dock.InfoButtons.HelpButton.MouseLeave:connect( function ()
  3608. Dock.InfoButtons.HelpButton.Tooltip.Visible = false;
  3609. end );
  3610.  
  3611. History.Changed:connect( function ()
  3612.  
  3613. -- If there are any records
  3614. if #History.Data > 0 then
  3615.  
  3616. -- If we're at the beginning
  3617. if History.index == 0 then
  3618. Dock.SelectionButtons.UndoButton.Image = undo_inactive_decal;
  3619. Dock.SelectionButtons.RedoButton.Image = redo_active_decal;
  3620.  
  3621. -- If we're at the end
  3622. elseif History.index == #History.Data then
  3623. Dock.SelectionButtons.UndoButton.Image = undo_active_decal;
  3624. Dock.SelectionButtons.RedoButton.Image = redo_inactive_decal;
  3625.  
  3626. -- If we're neither at the beginning or the end
  3627. else
  3628. Dock.SelectionButtons.UndoButton.Image = undo_active_decal;
  3629. Dock.SelectionButtons.RedoButton.Image = redo_active_decal;
  3630. end;
  3631.  
  3632. -- If there are no records
  3633. else
  3634. Dock.SelectionButtons.UndoButton.Image = undo_inactive_decal;
  3635. Dock.SelectionButtons.RedoButton.Image = redo_inactive_decal;
  3636. end;
  3637.  
  3638. end );
  3639.  
  3640. ------------------------------------------
  3641. -- Attach tool event listeners
  3642. ------------------------------------------
  3643.  
  3644. function equipBT( CurrentMouse )
  3645.  
  3646. Mouse = CurrentMouse;
  3647.  
  3648. -- Enable the move tool if there's no tool currently enabled
  3649. if not CurrentTool then
  3650. equipTool( Tools.Move );
  3651. end;
  3652.  
  3653. if not TargetBox then
  3654. TargetBox = Instance.new( "SelectionBox", UI );
  3655. TargetBox.Name = "BTTargetBox";
  3656. TargetBox.Color = BrickColor.new( "Institutional white" );
  3657. TargetBox.Transparency = 0.5;
  3658. end;
  3659.  
  3660. -- Enable any temporarily-disabled selection boxes
  3661. for _, SelectionBox in pairs( SelectionBoxes ) do
  3662. SelectionBox.Parent = UI;
  3663. end;
  3664.  
  3665. -- Update the internal selection if this is a plugin
  3666. if ToolType == 'plugin' then
  3667. for _, Item in pairs( Services.Selection:Get() ) do
  3668. Selection:add( Item );
  3669. end;
  3670. end;
  3671.  
  3672. -- Call the `Equipped` listener of the current tool
  3673. if CurrentTool and CurrentTool.Listeners.Equipped then
  3674. CurrentTool.Listeners.Equipped();
  3675. end;
  3676.  
  3677. -- Show the dock
  3678. Dock.Visible = true;
  3679.  
  3680. table.insert( Connections, Mouse.KeyDown:connect( function ( key )
  3681.  
  3682. local key = key:lower();
  3683. local key_code = key:byte();
  3684.  
  3685. -- Provide the abiltiy to delete via the shift + X key combination
  3686. if ActiveKeys[47] or ActiveKeys[48] and key == "x" then
  3687. deleteSelection();
  3688. return;
  3689. end;
  3690.  
  3691. -- Provide the ability to clone via the shift + C key combination
  3692. if ActiveKeys[47] or ActiveKeys[48] and key == "c" then
  3693. cloneSelection();
  3694. return;
  3695. end;
  3696.  
  3697. -- Undo if shift+z is pressed
  3698. if key == "z" and ( ActiveKeys[47] or ActiveKeys[48] ) then
  3699. History:undo();
  3700. return;
  3701.  
  3702. -- Redo if shift+y is pressed
  3703. elseif key == "y" and ( ActiveKeys[47] or ActiveKeys[48] ) then
  3704. History:redo();
  3705. return;
  3706. end;
  3707.  
  3708. -- Serialize and dump selection to logs if shift+p is pressed
  3709. if key == "p" and ( ActiveKeys[47] or ActiveKeys[48] ) then
  3710. IE:export();
  3711. return;
  3712. end;
  3713.  
  3714. -- Perform a prism selection if shift + k is pressed
  3715. if key == "k" and ( ActiveKeys[47] or ActiveKeys[48] ) then
  3716. prismSelect();
  3717. return;
  3718. end;
  3719.  
  3720. -- Clear the selection if shift + r is pressed
  3721. if key == "r" and ( ActiveKeys[47] or ActiveKeys[48] ) then
  3722. Selection:clear();
  3723. return;
  3724. end;
  3725.  
  3726. if key == "z" then
  3727. equipTool( Tools.Move );
  3728.  
  3729. elseif key == "x" then
  3730. equipTool( Tools.Resize );
  3731.  
  3732. elseif key == "c" then
  3733. equipTool( Tools.Rotate );
  3734.  
  3735. elseif key == "v" then
  3736. equipTool( Tools.Paint );
  3737.  
  3738. elseif key == "b" then
  3739. equipTool( Tools.Surface );
  3740.  
  3741. elseif key == "n" then
  3742. equipTool( Tools.Material );
  3743.  
  3744. elseif key == "m" then
  3745. equipTool( Tools.Anchor );
  3746.  
  3747. elseif key == "k" then
  3748. equipTool( Tools.Collision );
  3749.  
  3750. elseif key == "j" then
  3751. equipTool( Tools.NewPart );
  3752.  
  3753. elseif key == "h" then
  3754. equipTool( Tools.Mesh );
  3755.  
  3756. elseif key == "g" then
  3757. equipTool( Tools.Texture );
  3758.  
  3759. elseif key == "f" then
  3760. equipTool( Tools.Weld );
  3761.  
  3762. elseif key == "u" then
  3763. equipTool( Tools.Lighting );
  3764.  
  3765. elseif key == "p" then
  3766. equipTool( Tools.Decorate );
  3767.  
  3768. end;
  3769.  
  3770. ActiveKeys[key_code] = key_code;
  3771. ActiveKeys[key] = key;
  3772.  
  3773. -- If it's now in multiselection mode, update `selecting`
  3774. -- (these are the left/right ctrl & shift keys)
  3775. if ActiveKeys[47] or ActiveKeys[48] or ActiveKeys[49] or ActiveKeys[50] then
  3776. selecting = ActiveKeys[47] or ActiveKeys[48] or ActiveKeys[49] or ActiveKeys[50];
  3777. end;
  3778.  
  3779. end ) );
  3780.  
  3781. table.insert( Connections, Mouse.KeyUp:connect( function ( key )
  3782.  
  3783. local key = key:lower();
  3784. local key_code = key:byte();
  3785.  
  3786. ActiveKeys[key_code] = nil;
  3787. ActiveKeys[key] = nil;
  3788.  
  3789. -- If it's no longer in multiselection mode, update `selecting` & related values
  3790. if selecting and not ActiveKeys[selecting] then
  3791. selecting = false;
  3792. if Select2D.enabled then
  3793. Select2D:select();
  3794. Select2D:finish();
  3795. end;
  3796. end;
  3797.  
  3798. -- Fire tool listeners
  3799. if CurrentTool and CurrentTool.Listeners.KeyUp then
  3800. CurrentTool.Listeners.KeyUp( key );
  3801. end;
  3802.  
  3803. end ) );
  3804.  
  3805. table.insert( Connections, Mouse.Button1Down:connect( function ()
  3806.  
  3807. clicking = true;
  3808. click_x, click_y = Mouse.X, Mouse.Y;
  3809.  
  3810. -- If multiselection is, just add to the selection
  3811. if selecting then
  3812. return;
  3813. end;
  3814.  
  3815. -- Fire tool listeners
  3816. if CurrentTool and CurrentTool.Listeners.Button1Down then
  3817. CurrentTool.Listeners.Button1Down();
  3818. end;
  3819.  
  3820. end ) );
  3821.  
  3822. table.insert( Connections, Mouse.Move:connect( function ()
  3823.  
  3824. -- If the mouse has moved since it was clicked, start 2D selection mode
  3825. if not override_selection and not Select2D.enabled and clicking and selecting and ( click_x ~= Mouse.X or click_y ~= Mouse.Y ) then
  3826. Select2D:start();
  3827. end;
  3828.  
  3829. -- If the target has changed, update the selectionbox appropriately
  3830. if not override_selection and isSelectable( Mouse.Target ) and TargetBox.Adornee ~= Mouse.Target then
  3831. TargetBox.Adornee = Mouse.Target;
  3832. end;
  3833.  
  3834. -- When aiming at something invalid, don't highlight any targets
  3835. if not override_selection and not isSelectable( Mouse.Target ) then
  3836. TargetBox.Adornee = nil;
  3837. end;
  3838.  
  3839. -- Fire tool listeners
  3840. if CurrentTool and CurrentTool.Listeners.Move then
  3841. CurrentTool.Listeners.Move();
  3842. end;
  3843.  
  3844. if override_selection then
  3845. override_selection = false;
  3846. end;
  3847.  
  3848. end ) );
  3849.  
  3850. table.insert( Connections, Mouse.Button1Up:connect( function ()
  3851.  
  3852. clicking = false;
  3853.  
  3854. -- Make sure the person didn't accidentally miss a handle or something
  3855. if not Select2D.enabled and ( Mouse.X ~= click_x or Mouse.Y ~= click_y ) then
  3856. override_selection = true;
  3857. end;
  3858.  
  3859. -- If the target when clicking was invalid then clear the selection (unless we're multi-selecting)
  3860. if not override_selection and not selecting and not isSelectable( Mouse.Target ) then
  3861. Selection:clear();
  3862. end;
  3863.  
  3864. -- If multi-selecting, add to/remove from the selection
  3865. if not override_selection and selecting then
  3866.  
  3867. -- If the item isn't already selected, add it to the selection
  3868. if not Selection:find( Mouse.Target ) then
  3869. if isSelectable( Mouse.Target ) then
  3870. Selection:add( Mouse.Target );
  3871. end;
  3872.  
  3873. -- If the item _is_ already selected, remove it from the selection
  3874. else
  3875. if ( Mouse.X == click_x and Mouse.Y == click_y ) and Selection:find( Mouse.Target ) then
  3876. Selection:remove( Mouse.Target );
  3877. end;
  3878. end;
  3879.  
  3880. -- If not multi-selecting, replace the selection
  3881. else
  3882. if not override_selection and isSelectable( Mouse.Target ) then
  3883. Selection:clear();
  3884. Selection:add( Mouse.Target );
  3885. end;
  3886. end;
  3887.  
  3888. -- Fire tool listeners
  3889. if CurrentTool and CurrentTool.Listeners.Button1Up then
  3890. CurrentTool.Listeners.Button1Up();
  3891. end;
  3892.  
  3893. if override_selection then
  3894. override_selection = false;
  3895. end;
  3896.  
  3897. end ) );
  3898.  
  3899. table.insert( Connections, Mouse.Button2Down:connect( function ()
  3900. -- Fire tool listeners
  3901. if CurrentTool and CurrentTool.Listeners.Button2Down then
  3902. CurrentTool.Listeners.Button2Down();
  3903. end;
  3904. end ) );
  3905.  
  3906. table.insert( Connections, Mouse.Button2Up:connect( function ()
  3907. -- Fire tool listeners
  3908. if CurrentTool and CurrentTool.Listeners.Button2Up then
  3909. CurrentTool.Listeners.Button2Up();
  3910. end;
  3911. end ) );
  3912.  
  3913. end;
  3914.  
  3915. function unequipBT()
  3916.  
  3917. Mouse = nil;
  3918.  
  3919. -- Remove the mouse target SelectionBox from `Player`
  3920. if TargetBox then
  3921. TargetBox:Destroy();
  3922. TargetBox = nil;
  3923. end;
  3924.  
  3925. -- Disable all the selection boxes temporarily
  3926. for _, SelectionBox in pairs( SelectionBoxes ) do
  3927. SelectionBox.Parent = nil;
  3928. end;
  3929.  
  3930. -- Hide the dock
  3931. Dock.Visible = false;
  3932.  
  3933. -- Disconnect temporary platform-related connections
  3934. for connection_index, Connection in pairs( Connections ) do
  3935. Connection:disconnect();
  3936. Connections[connection_index] = nil;
  3937. end;
  3938.  
  3939. -- Call the `Unequipped` listener of the current tool
  3940. if CurrentTool and CurrentTool.Listeners.Unequipped then
  3941. CurrentTool.Listeners.Unequipped();
  3942. end;
  3943.  
  3944. end;
  3945.  
  3946.  
  3947. ------------------------------------------
  3948. -- Provide the platform's environment for
  3949. -- other tool scripts to extend upon
  3950. ------------------------------------------
  3951.  
  3952. local tool_list = {
  3953. "Anchor",
  3954. "Collision",
  3955. "Material",
  3956. "Mesh",
  3957. "Move",
  3958. "NewPart",
  3959. "Paint",
  3960. "Resize",
  3961. "Rotate",
  3962. "Surface",
  3963. "Texture",
  3964. "Weld",
  3965. "Lighting",
  3966. "Decorate"
  3967. };
  3968.  
  3969. -- Make sure all the tool scripts are in the tool & deactivate them
  3970. for _, tool_name in pairs( tool_list ) do
  3971. local script_name = "BT" .. tool_name .. "Tool";
  3972. repeat wait() until script:FindFirstChild( script_name );
  3973. script[script_name].Disabled = true;
  3974. end;
  3975.  
  3976. -- Load the platform
  3977. if not _G.BTCoreEnv then
  3978. _G.BTCoreEnv = {};
  3979. end;
  3980. _G.BTCoreEnv[Tool] = getfenv( 0 );
  3981. CoreReady = true;
  3982.  
  3983. -- Reload the tool scripts
  3984. for _, tool_name in pairs( tool_list ) do
  3985. local script_name = "BT" .. tool_name .. "Tool";
  3986. script[script_name].Disabled = false;
  3987. end;
  3988.  
  3989. -- Wait for all the tools to load
  3990. for _, tool_name in pairs( tool_list ) do
  3991. if not Tools[tool_name] then
  3992. repeat wait() until Tools[tool_name];
  3993. end;
  3994. repeat wait() until Tools[tool_name].Loaded;
  3995. end;
  3996.  
  3997. -- Activate the plugin and tool connections
  3998. if ToolType == 'plugin' then
  3999. local ToolbarButton = plugin:CreateToolbar( 'Building Tools by F3X' ):CreateButton( '', 'Building Tools by F3X', plugin_icon );
  4000. local plugin_active = false;
  4001. ToolbarButton.Click:connect( function ()
  4002. if plugin_active then
  4003. plugin_active = false;
  4004. unequipBT();
  4005. else
  4006. plugin_active = true;
  4007. plugin:Activate( true );
  4008. equipBT( plugin:GetMouse() );
  4009. end;
  4010. end );
  4011. plugin.Deactivation:connect( unequipBT );
  4012.  
  4013. elseif ToolType == 'tool' then
  4014. Tool.Equipped:connect( equipBT );
  4015. Tool.Unequipped:connect( unequipBT );
  4016. end;
  4017. end))
  4018. LocalScript2.Name = "BTMoveTool"
  4019. LocalScript2.Parent = LocalScript1
  4020. table.insert(cors,sandbox(LocalScript2,function()
  4021. -- Load the main tool's core environment when it's ready
  4022. repeat wait() until (
  4023. _G.BTCoreEnv and
  4024. _G.BTCoreEnv[script.Parent.Parent] and
  4025. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  4026. );
  4027. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  4028.  
  4029. ------------------------------------------
  4030. -- Move tool
  4031. ------------------------------------------
  4032.  
  4033. -- Create the main container for this tool
  4034. Tools.Move = {};
  4035.  
  4036. -- Define the color of the tool
  4037. Tools.Move.Color = BrickColor.new( "Deep orange" );
  4038.  
  4039. -- Keep a container for temporary connections
  4040. Tools.Move.Connections = {};
  4041.  
  4042. -- Keep options in a container too
  4043. Tools.Move.Options = {
  4044. ["increment"] = 1;
  4045. ["axes"] = "global";
  4046. };
  4047.  
  4048. -- Keep internal state data in its own container
  4049. Tools.Move.State = {
  4050. ["distance_moved"] = 0;
  4051. ["moving"] = false;
  4052. ["PreMove"] = {};
  4053. };
  4054.  
  4055. -- Add listeners
  4056. Tools.Move.Listeners = {};
  4057.  
  4058. Tools.Move.Listeners.Equipped = function ()
  4059.  
  4060. local self = Tools.Move;
  4061.  
  4062. -- Make sure the tool is actually being equipped (because this is the default tool)
  4063. if not Mouse then
  4064. return;
  4065. end;
  4066.  
  4067. -- Change the color of selection boxes temporarily
  4068. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  4069. SelectionBoxColor = self.Color;
  4070. updateSelectionBoxColor();
  4071.  
  4072. -- Reveal the GUI
  4073. self:showGUI();
  4074.  
  4075. -- Create the boundingbox if it doesn't already exist
  4076. if not self.BoundingBox then
  4077. self.BoundingBox = RbxUtility.Create "Part" {
  4078. Name = "BTBoundingBox";
  4079. CanCollide = false;
  4080. Transparency = 1;
  4081. Anchored = true;
  4082. };
  4083. end;
  4084. Mouse.TargetFilter = self.BoundingBox;
  4085.  
  4086. -- Refresh the axis type option
  4087. self:changeAxes( self.Options.axes );
  4088.  
  4089. -- Listen for any keystrokes that might affect any dragging operation
  4090. self.Connections.DraggerKeyListener = Mouse.KeyDown:connect( function ( key )
  4091.  
  4092. local key = key:lower();
  4093.  
  4094. -- Make sure a dragger exists
  4095. if not self.Dragger then
  4096. return;
  4097. end;
  4098.  
  4099. -- Rotate along the Z axis if `r` is pressed
  4100. if key == "r" then
  4101. self.Dragger:AxisRotate( Enum.Axis.Z );
  4102.  
  4103. -- Rotate along the X axis if `t` is pressed
  4104. elseif key == "t" then
  4105. self.Dragger:AxisRotate( Enum.Axis.X );
  4106.  
  4107. -- Rotate along the Y axis if `y` is pressed
  4108. elseif key == "y" then
  4109. self.Dragger:AxisRotate( Enum.Axis.Y );
  4110. end;
  4111.  
  4112. -- Simulate a mouse move so that it applies the changes
  4113. self.Dragger:MouseMove( Mouse.UnitRay );
  4114.  
  4115. end );
  4116.  
  4117. -- Oh, and update the boundingbox and the GUI regularly
  4118. coroutine.wrap( function ()
  4119. updater_on = true;
  4120.  
  4121. -- Provide a function to stop the loop
  4122. self.Updater = function ()
  4123. updater_on = false;
  4124. end;
  4125.  
  4126. while wait( 0.1 ) and updater_on do
  4127.  
  4128. -- Make sure the tool's equipped
  4129. if CurrentTool == self then
  4130.  
  4131. -- Update the GUI if it's visible
  4132. if self.GUI and self.GUI.Visible then
  4133. self:updateGUI();
  4134. end;
  4135.  
  4136. -- Update the boundingbox if it's visible
  4137. if self.Options.axes == "global" then
  4138. self:updateBoundingBox();
  4139. end;
  4140.  
  4141. end;
  4142.  
  4143. end;
  4144.  
  4145. end )();
  4146.  
  4147. end;
  4148.  
  4149. Tools.Move.Listeners.Unequipped = function ()
  4150.  
  4151. local self = Tools.Move;
  4152.  
  4153. -- Stop the update loop
  4154. if self.Updater then
  4155. self.Updater();
  4156. self.Updater = nil;
  4157. end;
  4158.  
  4159. -- Hide the GUI
  4160. self:hideGUI();
  4161.  
  4162. -- Hide the handles
  4163. self:hideHandles();
  4164.  
  4165. -- Clear out any temporary connections
  4166. for connection_index, Connection in pairs( self.Connections ) do
  4167. Connection:disconnect();
  4168. self.Connections[connection_index] = nil;
  4169. end;
  4170.  
  4171. -- Restore the original color of the selection boxes
  4172. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  4173. updateSelectionBoxColor();
  4174.  
  4175. end;
  4176.  
  4177. Tools.Move.updateGUI = function ( self )
  4178.  
  4179. if self.GUI then
  4180. local GUI = self.GUI;
  4181.  
  4182. if #Selection.Items > 0 then
  4183.  
  4184. -- Look for identical numbers in each axis
  4185. local position_x, position_y, position_z = nil, nil, nil;
  4186. for item_index, Item in pairs( Selection.Items ) do
  4187.  
  4188. -- Set the first values for the first item
  4189. if item_index == 1 then
  4190. position_x, position_y, position_z = _round( Item.Position.x, 2 ), _round( Item.Position.y, 2 ), _round( Item.Position.z, 2 );
  4191.  
  4192. -- Otherwise, compare them and set them to `nil` if they're not identical
  4193. else
  4194. if position_x ~= _round( Item.Position.x, 2 ) then
  4195. position_x = nil;
  4196. end;
  4197. if position_y ~= _round( Item.Position.y, 2 ) then
  4198. position_y = nil;
  4199. end;
  4200. if position_z ~= _round( Item.Position.z, 2 ) then
  4201. position_z = nil;
  4202. end;
  4203. end;
  4204.  
  4205. end;
  4206.  
  4207. -- If each position along each axis is the same, display that number; otherwise, display "*"
  4208. if not self.State.pos_x_focused then
  4209. GUI.Info.Center.X.TextBox.Text = position_x and tostring( position_x ) or "*";
  4210. end;
  4211. if not self.State.pos_y_focused then
  4212. GUI.Info.Center.Y.TextBox.Text = position_y and tostring( position_y ) or "*";
  4213. end;
  4214. if not self.State.pos_z_focused then
  4215. GUI.Info.Center.Z.TextBox.Text = position_z and tostring( position_z ) or "*";
  4216. end;
  4217.  
  4218. GUI.Info.Visible = true;
  4219. else
  4220. GUI.Info.Visible = false;
  4221. end;
  4222.  
  4223. if self.State.distance_moved then
  4224. GUI.Changes.Text.Text = "moved " .. tostring( self.State.distance_moved ) .. " studs";
  4225. GUI.Changes.Position = GUI.Info.Visible and UDim2.new( 0, 5, 0, 165 ) or UDim2.new( 0, 5, 0, 100 );
  4226. GUI.Changes.Visible = true;
  4227. else
  4228. GUI.Changes.Text.Text = "";
  4229. GUI.Changes.Visible = false;
  4230. end;
  4231. end;
  4232.  
  4233. end;
  4234.  
  4235. Tools.Move.changePosition = function ( self, component, new_value )
  4236.  
  4237. self:startHistoryRecord();
  4238.  
  4239. -- Change the position of each item selected
  4240. for _, Item in pairs( Selection.Items ) do
  4241. Item.CFrame = CFrame.new(
  4242. component == 'x' and new_value or Item.Position.x,
  4243. component == 'y' and new_value or Item.Position.y,
  4244. component == 'z' and new_value or Item.Position.z
  4245. ) * CFrame.Angles( Item.CFrame:toEulerAnglesXYZ() );
  4246. end;
  4247.  
  4248. self:finishHistoryRecord();
  4249.  
  4250. end;
  4251.  
  4252. Tools.Move.startHistoryRecord = function ( self )
  4253.  
  4254. if self.State.HistoryRecord then
  4255. self.State.HistoryRecord = nil;
  4256. end;
  4257.  
  4258. -- Create a history record
  4259. self.State.HistoryRecord = {
  4260. targets = _cloneTable( Selection.Items );
  4261. initial_positions = {};
  4262. terminal_positions = {};
  4263. unapply = function ( self )
  4264. Selection:clear();
  4265. for _, Target in pairs( self.targets ) do
  4266. if Target then
  4267. Target.CFrame = self.initial_positions[Target];
  4268. Target:MakeJoints();
  4269. Selection:add( Target );
  4270. end;
  4271. end;
  4272. end;
  4273. apply = function ( self )
  4274. Selection:clear();
  4275. for _, Target in pairs( self.targets ) do
  4276. if Target then
  4277. Target.CFrame = self.terminal_positions[Target];
  4278. Target:MakeJoints();
  4279. Selection:add( Target );
  4280. end;
  4281. end;
  4282. end;
  4283. };
  4284. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  4285. if Item then
  4286. self.State.HistoryRecord.initial_positions[Item] = Item.CFrame;
  4287. end;
  4288. end;
  4289.  
  4290. end;
  4291.  
  4292. Tools.Move.finishHistoryRecord = function ( self )
  4293.  
  4294. if not self.State.HistoryRecord then
  4295. return;
  4296. end;
  4297.  
  4298. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  4299. if Item then
  4300. self.State.HistoryRecord.terminal_positions[Item] = Item.CFrame;
  4301. end;
  4302. end;
  4303. History:add( self.State.HistoryRecord );
  4304. self.State.HistoryRecord = nil;
  4305.  
  4306. end;
  4307.  
  4308. Tools.Move.Listeners.Button1Down = function ()
  4309.  
  4310. local self = Tools.Move;
  4311.  
  4312. local Target = self.ManualTarget or Mouse.Target;
  4313. self.ManualTarget = nil;
  4314.  
  4315. -- If an unselected part is being moved, switch to it
  4316. if not Selection:find( Target ) and isSelectable( Target ) then
  4317. Selection:clear();
  4318. Selection:add( Target );
  4319. end;
  4320.  
  4321. -- If the unselected target can't be selected at all, ignore the rest of the procedure
  4322. if not Selection:find( Target ) then
  4323. return;
  4324. end;
  4325.  
  4326. for _, Item in pairs( Selection.Items ) do
  4327. Item.RotVelocity = Vector3.new( 0, 0, 0 );
  4328. Item.Velocity = Vector3.new( 0, 0, 0 );
  4329. end;
  4330.  
  4331. self:startHistoryRecord();
  4332.  
  4333. self.State.dragging = true;
  4334. override_selection = true;
  4335.  
  4336. self.Dragger = Instance.new( "Dragger" );
  4337. self.Dragger:MouseDown( Target, Target.CFrame:toObjectSpace( CFrame.new( Mouse.Hit.p ) ).p, Selection.Items );
  4338. self.Connections.DraggerConnection = Mouse.Button1Up:connect( function ()
  4339.  
  4340. override_selection = true;
  4341.  
  4342. -- Disable the dragger
  4343. if self.Connections.DraggerConnection then
  4344. self.Connections.DraggerConnection:disconnect();
  4345. self.Connections.DraggerConnection = nil;
  4346. end;
  4347. if not self.Dragger then
  4348. return;
  4349. end;
  4350. self.Dragger:MouseUp();
  4351. self.State.dragging = false;
  4352. self.Dragger:Destroy();
  4353. self.Dragger = nil;
  4354.  
  4355. self:finishHistoryRecord();
  4356.  
  4357. end );
  4358.  
  4359. end;
  4360.  
  4361. Tools.Move.Listeners.Move = function ()
  4362.  
  4363. local self = Tools.Move;
  4364.  
  4365. if not self.Dragger then
  4366. return;
  4367. end;
  4368.  
  4369. override_selection = true;
  4370.  
  4371. self.Dragger:MouseMove( Mouse.UnitRay );
  4372.  
  4373. end;
  4374.  
  4375. Tools.Move.showGUI = function ( self )
  4376.  
  4377. -- Initialize the GUI if it's not ready yet
  4378. if not self.GUI then
  4379.  
  4380. local Container = Tool.Interfaces:WaitForChild( "BTMoveToolGUI" ):Clone();
  4381. Container.Parent = UI;
  4382.  
  4383. -- Change the axis type option when the button is clicked
  4384. Container.AxesOption.Global.Button.MouseButton1Down:connect( function ()
  4385. self:changeAxes( "global" );
  4386. Container.AxesOption.Global.SelectedIndicator.BackgroundTransparency = 0;
  4387. Container.AxesOption.Global.Background.Image = dark_slanted_rectangle;
  4388. Container.AxesOption.Local.SelectedIndicator.BackgroundTransparency = 1;
  4389. Container.AxesOption.Local.Background.Image = light_slanted_rectangle;
  4390. Container.AxesOption.Last.SelectedIndicator.BackgroundTransparency = 1;
  4391. Container.AxesOption.Last.Background.Image = light_slanted_rectangle;
  4392. end );
  4393.  
  4394. Container.AxesOption.Local.Button.MouseButton1Down:connect( function ()
  4395. self:changeAxes( "local" );
  4396. Container.AxesOption.Global.SelectedIndicator.BackgroundTransparency = 1;
  4397. Container.AxesOption.Global.Background.Image = light_slanted_rectangle;
  4398. Container.AxesOption.Local.SelectedIndicator.BackgroundTransparency = 0;
  4399. Container.AxesOption.Local.Background.Image = dark_slanted_rectangle;
  4400. Container.AxesOption.Last.SelectedIndicator.BackgroundTransparency = 1;
  4401. Container.AxesOption.Last.Background.Image = light_slanted_rectangle;
  4402. end );
  4403.  
  4404. Container.AxesOption.Last.Button.MouseButton1Down:connect( function ()
  4405. self:changeAxes( "last" );
  4406. Container.AxesOption.Global.SelectedIndicator.BackgroundTransparency = 1;
  4407. Container.AxesOption.Global.Background.Image = light_slanted_rectangle;
  4408. Container.AxesOption.Local.SelectedIndicator.BackgroundTransparency = 1;
  4409. Container.AxesOption.Local.Background.Image = light_slanted_rectangle;
  4410. Container.AxesOption.Last.SelectedIndicator.BackgroundTransparency = 0;
  4411. Container.AxesOption.Last.Background.Image = dark_slanted_rectangle;
  4412. end );
  4413.  
  4414. -- Change the increment option when the value of the textbox is updated
  4415. Container.IncrementOption.Increment.TextBox.FocusLost:connect( function ( enter_pressed )
  4416. self.Options.increment = tonumber( Container.IncrementOption.Increment.TextBox.Text ) or self.Options.increment;
  4417. Container.IncrementOption.Increment.TextBox.Text = tostring( self.Options.increment );
  4418. end );
  4419.  
  4420. -- Add functionality to the position inputs
  4421. Container.Info.Center.X.TextButton.MouseButton1Down:connect( function ()
  4422. self.State.pos_x_focused = true;
  4423. Container.Info.Center.X.TextBox:CaptureFocus();
  4424. end );
  4425. Container.Info.Center.X.TextBox.FocusLost:connect( function ( enter_pressed )
  4426. local potential_new = tonumber( Container.Info.Center.X.TextBox.Text );
  4427. if potential_new then
  4428. self:changePosition( 'x', potential_new );
  4429. end;
  4430. self.State.pos_x_focused = false;
  4431. end );
  4432. Container.Info.Center.Y.TextButton.MouseButton1Down:connect( function ()
  4433. self.State.pos_y_focused = true;
  4434. Container.Info.Center.Y.TextBox:CaptureFocus();
  4435. end );
  4436. Container.Info.Center.Y.TextBox.FocusLost:connect( function ( enter_pressed )
  4437. local potential_new = tonumber( Container.Info.Center.Y.TextBox.Text );
  4438. if potential_new then
  4439. self:changePosition( 'y', potential_new );
  4440. end;
  4441. self.State.pos_y_focused = false;
  4442. end );
  4443. Container.Info.Center.Z.TextButton.MouseButton1Down:connect( function ()
  4444. self.State.pos_z_focused = true;
  4445. Container.Info.Center.Z.TextBox:CaptureFocus();
  4446. end );
  4447. Container.Info.Center.Z.TextBox.FocusLost:connect( function ( enter_pressed )
  4448. local potential_new = tonumber( Container.Info.Center.Z.TextBox.Text );
  4449. if potential_new then
  4450. self:changePosition( 'z', potential_new );
  4451. end;
  4452. self.State.pos_z_focused = false;
  4453. end );
  4454.  
  4455. self.GUI = Container;
  4456. end;
  4457.  
  4458. -- Reveal the GUI
  4459. self.GUI.Visible = true;
  4460.  
  4461. end;
  4462.  
  4463. Tools.Move.hideGUI = function ( self )
  4464.  
  4465. -- Hide the GUI if it exists
  4466. if self.GUI then
  4467. self.GUI.Visible = false;
  4468. end;
  4469.  
  4470. end;
  4471.  
  4472. Tools.Move.showHandles = function ( self, Part )
  4473.  
  4474. -- Create the handles if they don't exist yet
  4475. if not self.Handles then
  4476.  
  4477. -- Create the object
  4478. self.Handles = RbxUtility.Create "Handles" {
  4479. Name = "BTMovementHandles";
  4480. Color = self.Color;
  4481. Parent = GUIContainer;
  4482. };
  4483.  
  4484. -- Add functionality to the handles
  4485.  
  4486. self.Handles.MouseButton1Down:connect( function ()
  4487.  
  4488. -- Prevent the platform from thinking we're selecting
  4489. override_selection = true;
  4490. self.State.moving = true;
  4491.  
  4492. -- Clear the change stats
  4493. self.State.distance_moved = 0;
  4494.  
  4495. self:startHistoryRecord();
  4496.  
  4497. -- Do a few things to the selection before manipulating it
  4498. for _, Item in pairs( Selection.Items ) do
  4499.  
  4500. -- Keep a copy of the state of each item
  4501. self.State.PreMove[Item] = Item:Clone();
  4502.  
  4503. -- Anchor each item
  4504. Item.Anchored = true;
  4505.  
  4506. end;
  4507.  
  4508. -- Return stuff to normal once the mouse button is released
  4509. self.Connections.HandleReleaseListener = Mouse.Button1Up:connect( function ()
  4510.  
  4511. -- Prevent the platform from thinking we're selecting
  4512. override_selection = true;
  4513. self.State.moving = false;
  4514.  
  4515. -- Stop this connection from firing again
  4516. if self.Connections.HandleReleaseListener then
  4517. self.Connections.HandleReleaseListener:disconnect();
  4518. self.Connections.HandleReleaseListener = nil;
  4519. end;
  4520.  
  4521. self:finishHistoryRecord();
  4522.  
  4523. -- Restore properties that may have been changed temporarily
  4524. -- from the pre-movement state copies
  4525. for Item, PreviousItemState in pairs( self.State.PreMove ) do
  4526. Item.Anchored = PreviousItemState.Anchored;
  4527. self.State.PreMove[Item] = nil;
  4528. Item:MakeJoints();
  4529. Item.Velocity = Vector3.new( 0, 0, 0 );
  4530. Item.RotVelocity = Vector3.new( 0, 0, 0 );
  4531. end;
  4532.  
  4533. end );
  4534.  
  4535. end );
  4536.  
  4537. self.Handles.MouseDrag:connect( function ( face, drag_distance )
  4538.  
  4539. -- Calculate which multiple of the increment to use based on the current drag distance's
  4540. -- proximity to their nearest upper and lower multiples
  4541.  
  4542. local difference = drag_distance % self.Options.increment;
  4543.  
  4544. local lower_degree = drag_distance - difference;
  4545. local upper_degree = drag_distance - difference + self.Options.increment;
  4546.  
  4547. local lower_degree_proximity = math.abs( drag_distance - lower_degree );
  4548. local upper_degree_proximity = math.abs( drag_distance - upper_degree );
  4549.  
  4550. if lower_degree_proximity <= upper_degree_proximity then
  4551. drag_distance = lower_degree;
  4552. else
  4553. drag_distance = upper_degree;
  4554. end;
  4555.  
  4556. local increase = drag_distance;
  4557.  
  4558. self.State.distance_moved = drag_distance;
  4559.  
  4560. -- Increment the position of each selected item in the direction of `face`
  4561. for _, Item in pairs( Selection.Items ) do
  4562.  
  4563. -- Remove any joints connected with `Item` so that it can freely move
  4564. Item:BreakJoints();
  4565.  
  4566. -- Update the position of `Item` depending on the type of axes that is currently set
  4567. if face == Enum.NormalId.Top then
  4568. if self.Options.axes == "global" then
  4569. Item.CFrame = CFrame.new( self.State.PreMove[Item].CFrame.p ):toWorldSpace( CFrame.new( 0, increase, 0 ) ) * CFrame.Angles( self.State.PreMove[Item].CFrame:toEulerAnglesXYZ() );
  4570. elseif self.Options.axes == "local" then
  4571. Item.CFrame = self.State.PreMove[Item].CFrame:toWorldSpace( CFrame.new( 0, increase, 0 ) );
  4572. elseif self.Options.axes == "last" then
  4573. Item.CFrame = self.State.PreMove[Selection.Last].CFrame:toWorldSpace( CFrame.new( 0, increase, 0 ) ):toWorldSpace( self.State.PreMove[Item].CFrame:toObjectSpace( self.State.PreMove[Selection.Last].CFrame ):inverse() );
  4574. end;
  4575.  
  4576. elseif face == Enum.NormalId.Bottom then
  4577. if self.Options.axes == "global" then
  4578. Item.CFrame = CFrame.new( self.State.PreMove[Item].CFrame.p ):toWorldSpace( CFrame.new( 0, -increase, 0 ) ) * CFrame.Angles( self.State.PreMove[Item].CFrame:toEulerAnglesXYZ() );
  4579. elseif self.Options.axes == "local" then
  4580. Item.CFrame = self.State.PreMove[Item].CFrame:toWorldSpace( CFrame.new( 0, -increase, 0 ) );
  4581. elseif self.Options.axes == "last" then
  4582. Item.CFrame = self.State.PreMove[Selection.Last].CFrame:toWorldSpace( CFrame.new( 0, -increase, 0 ) ):toWorldSpace( self.State.PreMove[Item].CFrame:toObjectSpace( self.State.PreMove[Selection.Last].CFrame ):inverse() );
  4583. end;
  4584.  
  4585. elseif face == Enum.NormalId.Front then
  4586. if self.Options.axes == "global" then
  4587. Item.CFrame = CFrame.new( self.State.PreMove[Item].CFrame.p ):toWorldSpace( CFrame.new( 0, 0, -increase ) ) * CFrame.Angles( self.State.PreMove[Item].CFrame:toEulerAnglesXYZ() );
  4588. elseif self.Options.axes == "local" then
  4589. Item.CFrame = self.State.PreMove[Item].CFrame:toWorldSpace( CFrame.new( 0, 0, -increase ) );
  4590. elseif self.Options.axes == "last" then
  4591. Item.CFrame = self.State.PreMove[Selection.Last].CFrame:toWorldSpace( CFrame.new( 0, 0, -increase ) ):toWorldSpace( self.State.PreMove[Item].CFrame:toObjectSpace( self.State.PreMove[Selection.Last].CFrame ):inverse() );
  4592. end;
  4593.  
  4594. elseif face == Enum.NormalId.Back then
  4595. if self.Options.axes == "global" then
  4596. Item.CFrame = CFrame.new( self.State.PreMove[Item].CFrame.p ):toWorldSpace( CFrame.new( 0, 0, increase ) ) * CFrame.Angles( self.State.PreMove[Item].CFrame:toEulerAnglesXYZ() );
  4597. elseif self.Options.axes == "local" then
  4598. Item.CFrame = self.State.PreMove[Item].CFrame:toWorldSpace( CFrame.new( 0, 0, increase ) );
  4599. elseif self.Options.axes == "last" then
  4600. Item.CFrame = self.State.PreMove[Selection.Last].CFrame:toWorldSpace( CFrame.new( 0, 0, increase ) ):toWorldSpace( self.State.PreMove[Item].CFrame:toObjectSpace( self.State.PreMove[Selection.Last].CFrame ):inverse() );
  4601. end;
  4602.  
  4603. elseif face == Enum.NormalId.Right then
  4604. if self.Options.axes == "global" then
  4605. Item.CFrame = CFrame.new( self.State.PreMove[Item].CFrame.p ):toWorldSpace( CFrame.new( increase, 0, 0 ) ) * CFrame.Angles( self.State.PreMove[Item].CFrame:toEulerAnglesXYZ() );
  4606. elseif self.Options.axes == "local" then
  4607. Item.CFrame = self.State.PreMove[Item].CFrame:toWorldSpace( CFrame.new( increase, 0, 0 ) );
  4608. elseif self.Options.axes == "last" then
  4609. Item.CFrame = self.State.PreMove[Selection.Last].CFrame:toWorldSpace( CFrame.new( increase, 0, 0 ) ):toWorldSpace( self.State.PreMove[Item].CFrame:toObjectSpace( self.State.PreMove[Selection.Last].CFrame ):inverse() );
  4610. end;
  4611.  
  4612. elseif face == Enum.NormalId.Left then
  4613. if self.Options.axes == "global" then
  4614. Item.CFrame = CFrame.new( self.State.PreMove[Item].CFrame.p ):toWorldSpace( CFrame.new( -increase, 0, 0 ) ) * CFrame.Angles( self.State.PreMove[Item].CFrame:toEulerAnglesXYZ() );
  4615. elseif self.Options.axes == "local" then
  4616. Item.CFrame = self.State.PreMove[Item].CFrame:toWorldSpace( CFrame.new( -increase, 0, 0 ) );
  4617. elseif self.Options.axes == "last" then
  4618. Item.CFrame = self.State.PreMove[Selection.Last].CFrame:toWorldSpace( CFrame.new( -increase, 0, 0 ) ):toWorldSpace( self.State.PreMove[Item].CFrame:toObjectSpace( self.State.PreMove[Selection.Last].CFrame ):inverse() );
  4619. end;
  4620.  
  4621. end;
  4622.  
  4623. end;
  4624.  
  4625. end );
  4626.  
  4627. end;
  4628.  
  4629. -- Stop listening for the existence of the previous adornee (if any)
  4630. if self.Connections.AdorneeExistenceListener then
  4631. self.Connections.AdorneeExistenceListener:disconnect();
  4632. self.Connections.AdorneeExistenceListener = nil;
  4633. end;
  4634.  
  4635. -- Attach the handles to `Part`
  4636. self.Handles.Adornee = Part;
  4637.  
  4638. -- Make sure to hide the handles if `Part` suddenly stops existing
  4639. self.Connections.AdorneeExistenceListener = Part.AncestryChanged:connect( function ( Object, NewParent )
  4640.  
  4641. -- Make sure this change in parent applies directly to `Part`
  4642. if Object ~= Part then
  4643. return;
  4644. end;
  4645.  
  4646. -- Show the handles according to the existence of the part
  4647. if NewParent == nil then
  4648. self:hideHandles();
  4649. else
  4650. self:showHandles( Part );
  4651. end;
  4652.  
  4653. end );
  4654.  
  4655. end;
  4656.  
  4657. Tools.Move.hideHandles = function ( self )
  4658.  
  4659. -- Hide the handles if they exist
  4660. if self.Handles then
  4661. self.Handles.Adornee = nil;
  4662. end;
  4663.  
  4664. end;
  4665.  
  4666. Tools.Move.updateBoundingBox = function ( self )
  4667.  
  4668. if #Selection.Items > 0 and not self.State.dragging then
  4669. local SelectionSize, SelectionPosition = _getCollectionInfo( Selection.Items );
  4670. self.BoundingBox.Size = SelectionSize;
  4671. self.BoundingBox.CFrame = SelectionPosition;
  4672. self:showHandles( self.BoundingBox );
  4673.  
  4674. else
  4675. self:hideHandles();
  4676. end;
  4677.  
  4678. end;
  4679.  
  4680. Tools.Move.changeAxes = function ( self, new_axes )
  4681.  
  4682. -- Have a quick reference to the GUI (if any)
  4683. local AxesOptionGUI = self.GUI and self.GUI.AxesOption or nil;
  4684.  
  4685. -- Disconnect any handle-related listeners that are specific to a certain axes option
  4686.  
  4687. if self.Connections.HandleFocusChangeListener then
  4688. self.Connections.HandleFocusChangeListener:disconnect();
  4689. self.Connections.HandleFocusChangeListener = nil;
  4690. end;
  4691.  
  4692. if self.Connections.HandleSelectionChangeListener then
  4693. self.Connections.HandleSelectionChangeListener:disconnect();
  4694. self.Connections.HandleSelectionChangeListener = nil;
  4695. end;
  4696.  
  4697. if new_axes == "global" then
  4698.  
  4699. -- Update the options
  4700. self.Options.axes = "global";
  4701.  
  4702. -- Clear out any previous adornee
  4703. self:hideHandles();
  4704.  
  4705. -- Focus the handles on the boundary box
  4706. self:showHandles( self.BoundingBox );
  4707.  
  4708. -- Update the GUI's option panel
  4709. if self.GUI then
  4710. AxesOptionGUI.Global.SelectedIndicator.BackgroundTransparency = 0;
  4711. AxesOptionGUI.Global.Background.Image = dark_slanted_rectangle;
  4712. AxesOptionGUI.Local.SelectedIndicator.BackgroundTransparency = 1;
  4713. AxesOptionGUI.Local.Background.Image = light_slanted_rectangle;
  4714. AxesOptionGUI.Last.SelectedIndicator.BackgroundTransparency = 1;
  4715. AxesOptionGUI.Last.Background.Image = light_slanted_rectangle;
  4716. end;
  4717.  
  4718. end;
  4719.  
  4720. if new_axes == "local" then
  4721.  
  4722. -- Update the options
  4723. self.Options.axes = "local";
  4724.  
  4725. -- Always have the handles on the most recent addition to the selection
  4726. self.Connections.HandleSelectionChangeListener = Selection.Changed:connect( function ()
  4727.  
  4728. -- Clear out any previous adornee
  4729. self:hideHandles();
  4730.  
  4731. -- If there /is/ a last item in the selection, attach the handles to it
  4732. if Selection.Last then
  4733. self:showHandles( Selection.Last );
  4734. end;
  4735.  
  4736. end );
  4737.  
  4738. -- Switch the adornee of the handles if the second mouse button is pressed
  4739. self.Connections.HandleFocusChangeListener = Mouse.Button2Up:connect( function ()
  4740.  
  4741. -- Make sure the platform doesn't think we're selecting
  4742. override_selection = true;
  4743.  
  4744. -- If the target is in the selection, make it the new adornee
  4745. if Selection:find( Mouse.Target ) then
  4746. Selection:focus( Mouse.Target );
  4747. self:showHandles( Mouse.Target );
  4748. end;
  4749.  
  4750. end );
  4751.  
  4752. -- Finally, attach the handles to the last item added to the selection (if any)
  4753. if Selection.Last then
  4754. self:showHandles( Selection.Last );
  4755. end;
  4756.  
  4757. -- Update the GUI's option panel
  4758. if self.GUI then
  4759. AxesOptionGUI.Global.SelectedIndicator.BackgroundTransparency = 1;
  4760. AxesOptionGUI.Global.Background.Image = light_slanted_rectangle;
  4761. AxesOptionGUI.Local.SelectedIndicator.BackgroundTransparency = 0;
  4762. AxesOptionGUI.Local.Background.Image = dark_slanted_rectangle;
  4763. AxesOptionGUI.Last.SelectedIndicator.BackgroundTransparency = 1;
  4764. AxesOptionGUI.Last.Background.Image = light_slanted_rectangle;
  4765. end;
  4766.  
  4767. end;
  4768.  
  4769. if new_axes == "last" then
  4770.  
  4771. -- Update the options
  4772. self.Options.axes = "last";
  4773.  
  4774. -- Always have the handles on the most recent addition to the selection
  4775. self.Connections.HandleSelectionChangeListener = Selection.Changed:connect( function ()
  4776.  
  4777. -- Clear out any previous adornee
  4778. self:hideHandles();
  4779.  
  4780. -- If there /is/ a last item in the selection, attach the handles to it
  4781. if Selection.Last then
  4782. self:showHandles( Selection.Last );
  4783. end;
  4784.  
  4785. end );
  4786.  
  4787. -- Switch the adornee of the handles if the second mouse button is pressed
  4788. self.Connections.HandleFocusChangeListener = Mouse.Button2Up:connect( function ()
  4789.  
  4790. -- Make sure the platform doesn't think we're selecting
  4791. override_selection = true;
  4792.  
  4793. -- If the target is in the selection, make it the new adornee
  4794. if Selection:find( Mouse.Target ) then
  4795. Selection:focus( Mouse.Target );
  4796. self:showHandles( Mouse.Target );
  4797. end;
  4798.  
  4799. end );
  4800.  
  4801. -- Finally, attach the handles to the last item added to the selection (if any)
  4802. if Selection.Last then
  4803. self:showHandles( Selection.Last );
  4804. end;
  4805.  
  4806. -- Update the GUI's option panel
  4807. if self.GUI then
  4808. AxesOptionGUI.Global.SelectedIndicator.BackgroundTransparency = 1;
  4809. AxesOptionGUI.Global.Background.Image = light_slanted_rectangle;
  4810. AxesOptionGUI.Local.SelectedIndicator.BackgroundTransparency = 1;
  4811. AxesOptionGUI.Local.Background.Image = light_slanted_rectangle;
  4812. AxesOptionGUI.Last.SelectedIndicator.BackgroundTransparency = 0;
  4813. AxesOptionGUI.Last.Background.Image = dark_slanted_rectangle;
  4814. end;
  4815.  
  4816. end;
  4817.  
  4818. end;
  4819.  
  4820. Tools.Move.Loaded = true;
  4821. end))
  4822. LocalScript2.Disabled = true
  4823. LocalScript3.Name = "BTResizeTool"
  4824. LocalScript3.Parent = LocalScript1
  4825. table.insert(cors,sandbox(LocalScript3,function()
  4826. -- Load the main tool's core environment when it's ready
  4827. repeat wait() until (
  4828. _G.BTCoreEnv and
  4829. _G.BTCoreEnv[script.Parent.Parent] and
  4830. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  4831. );
  4832. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  4833.  
  4834. ------------------------------------------
  4835. -- Resize tool
  4836. ------------------------------------------
  4837.  
  4838. -- Create the tool
  4839. Tools.Resize = {};
  4840.  
  4841. -- Create structures that will be used within the tool
  4842. Tools.Resize.Connections = {};
  4843.  
  4844. Tools.Resize.Options = {
  4845. ["increment"] = 1;
  4846. ["directions"] = "normal";
  4847. };
  4848.  
  4849. Tools.Resize.State = {
  4850. ["PreResize"] = {};
  4851. ["previous_distance"] = 0;
  4852. ["resizing"] = false;
  4853. ["length_resized"] = 0;
  4854. };
  4855.  
  4856. Tools.Resize.Listeners = {};
  4857.  
  4858. -- Define the color of the tool
  4859. Tools.Resize.Color = BrickColor.new( "Cyan" );
  4860.  
  4861. Tools.Resize.Listeners.Equipped = function ()
  4862.  
  4863. local self = Tools.Resize;
  4864.  
  4865. -- Change the color of selection boxes temporarily
  4866. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  4867. SelectionBoxColor = self.Color;
  4868. updateSelectionBoxColor();
  4869.  
  4870. -- Reveal the GUI
  4871. self:showGUI();
  4872.  
  4873. -- Always have the handles on the most recent addition to the selection
  4874. table.insert( self.Connections, Selection.Changed:connect( function ()
  4875.  
  4876. -- Clear out any previous adornee
  4877. self:hideHandles();
  4878.  
  4879. -- If there /is/ a last item in the selection, attach the handles to it
  4880. if Selection.Last then
  4881. self:showHandles( Selection.Last );
  4882. end;
  4883.  
  4884. end ) );
  4885.  
  4886. -- Switch the adornee of the handles if the second mouse button is pressed
  4887. table.insert( self.Connections, Mouse.Button2Up:connect( function ()
  4888.  
  4889. -- Make sure the platform doesn't think we're selecting
  4890. override_selection = true;
  4891.  
  4892. -- If the target is in the selection, make it the new adornee
  4893. if Selection:find( Mouse.Target ) then
  4894. Selection:focus( Mouse.Target );
  4895. end;
  4896.  
  4897. end ) );
  4898.  
  4899. -- Finally, attach the handles to the last item added to the selection (if any)
  4900. if Selection.Last then
  4901. self:showHandles( Selection.Last );
  4902. end;
  4903.  
  4904. -- Update the GUI regularly
  4905. coroutine.wrap( function ()
  4906. updater_on = true;
  4907.  
  4908. -- Provide a function to stop the loop
  4909. self.Updater = function ()
  4910. updater_on = false;
  4911. end;
  4912.  
  4913. while wait( 0.1 ) and updater_on do
  4914.  
  4915. -- Make sure the tool's equipped
  4916. if CurrentTool == self then
  4917.  
  4918. -- Update the GUI if it's visible
  4919. if self.GUI and self.GUI.Visible then
  4920. self:updateGUI();
  4921. end;
  4922.  
  4923. end;
  4924.  
  4925. end;
  4926.  
  4927. end )();
  4928.  
  4929. end;
  4930.  
  4931. Tools.Resize.Listeners.Unequipped = function ()
  4932.  
  4933. local self = Tools.Resize;
  4934.  
  4935. -- Stop the update loop
  4936. if self.Updater then
  4937. self.Updater();
  4938. self.Updater = nil;
  4939. end;
  4940.  
  4941. -- Hide the GUI
  4942. self:hideGUI();
  4943.  
  4944. -- Hide the handles
  4945. self:hideHandles();
  4946.  
  4947. -- Clear out any temporary connections
  4948. for connection_index, Connection in pairs( self.Connections ) do
  4949. Connection:disconnect();
  4950. self.Connections[connection_index] = nil;
  4951. end;
  4952.  
  4953. -- Restore the original color of the selection boxes
  4954. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  4955. updateSelectionBoxColor();
  4956.  
  4957. end;
  4958.  
  4959. Tools.Resize.showGUI = function ( self )
  4960.  
  4961. -- Initialize the GUI if it's not ready yet
  4962. if not self.GUI then
  4963.  
  4964. local Container = Tool.Interfaces:WaitForChild( "BTResizeToolGUI" ):Clone();
  4965. Container.Parent = UI;
  4966.  
  4967. -- Change the axis type option when the button is clicked
  4968. Container.DirectionsOption.Normal.Button.MouseButton1Down:connect( function ()
  4969. self.Options.directions = "normal";
  4970. Container.DirectionsOption.Normal.SelectedIndicator.BackgroundTransparency = 0;
  4971. Container.DirectionsOption.Normal.Background.Image = dark_slanted_rectangle;
  4972. Container.DirectionsOption.Both.SelectedIndicator.BackgroundTransparency = 1;
  4973. Container.DirectionsOption.Both.Background.Image = light_slanted_rectangle;
  4974. end );
  4975.  
  4976. Container.DirectionsOption.Both.Button.MouseButton1Down:connect( function ()
  4977. self.Options.directions = "both";
  4978. Container.DirectionsOption.Normal.SelectedIndicator.BackgroundTransparency = 1;
  4979. Container.DirectionsOption.Normal.Background.Image = light_slanted_rectangle;
  4980. Container.DirectionsOption.Both.SelectedIndicator.BackgroundTransparency = 0;
  4981. Container.DirectionsOption.Both.Background.Image = dark_slanted_rectangle;
  4982. end );
  4983.  
  4984. -- Change the increment option when the value of the textbox is updated
  4985. Container.IncrementOption.Increment.TextBox.FocusLost:connect( function ( enter_pressed )
  4986. self.Options.increment = tonumber( Container.IncrementOption.Increment.TextBox.Text ) or self.Options.increment;
  4987. Container.IncrementOption.Increment.TextBox.Text = tostring( self.Options.increment );
  4988. end );
  4989.  
  4990. -- Add functionality to the size inputs
  4991. Container.Info.SizeInfo.X.TextButton.MouseButton1Down:connect( function ()
  4992. self.State.size_x_focused = true;
  4993. Container.Info.SizeInfo.X.TextBox:CaptureFocus();
  4994. end );
  4995. Container.Info.SizeInfo.X.TextBox.FocusLost:connect( function ( enter_pressed )
  4996. local potential_new = tonumber( Container.Info.SizeInfo.X.TextBox.Text );
  4997. if potential_new then
  4998. self:changeSize( 'x', potential_new );
  4999. end;
  5000. self.State.size_x_focused = false;
  5001. end );
  5002. Container.Info.SizeInfo.Y.TextButton.MouseButton1Down:connect( function ()
  5003. self.State.size_y_focused = true;
  5004. Container.Info.SizeInfo.Y.TextBox:CaptureFocus();
  5005. end );
  5006. Container.Info.SizeInfo.Y.TextBox.FocusLost:connect( function ( enter_pressed )
  5007. local potential_new = tonumber( Container.Info.SizeInfo.Y.TextBox.Text );
  5008. if potential_new then
  5009. self:changeSize( 'y', potential_new );
  5010. end;
  5011. self.State.size_y_focused = false;
  5012. end );
  5013. Container.Info.SizeInfo.Z.TextButton.MouseButton1Down:connect( function ()
  5014. self.State.size_z_focused = true;
  5015. Container.Info.SizeInfo.Z.TextBox:CaptureFocus();
  5016. end );
  5017. Container.Info.SizeInfo.Z.TextBox.FocusLost:connect( function ( enter_pressed )
  5018. local potential_new = tonumber( Container.Info.SizeInfo.Z.TextBox.Text );
  5019. if potential_new then
  5020. self:changeSize( 'z', potential_new );
  5021. end;
  5022. self.State.size_z_focused = false;
  5023. end );
  5024.  
  5025. self.GUI = Container;
  5026. end;
  5027.  
  5028. -- Reveal the GUI
  5029. self.GUI.Visible = true;
  5030.  
  5031. end;
  5032.  
  5033. Tools.Resize.startHistoryRecord = function ( self )
  5034.  
  5035. if self.State.HistoryRecord then
  5036. self.State.HistoryRecord = nil;
  5037. end;
  5038.  
  5039. -- Create a history record
  5040. self.State.HistoryRecord = {
  5041. targets = _cloneTable( Selection.Items );
  5042. initial_positions = {};
  5043. terminal_positions = {};
  5044. initial_sizes = {};
  5045. terminal_sizes = {};
  5046. unapply = function ( self )
  5047. Selection:clear();
  5048. for _, Target in pairs( self.targets ) do
  5049. if Target then
  5050. Target.Size = self.initial_sizes[Target];
  5051. Target.CFrame = self.initial_positions[Target];
  5052. Target:MakeJoints();
  5053. Selection:add( Target );
  5054. end;
  5055. end;
  5056. end;
  5057. apply = function ( self )
  5058. Selection:clear();
  5059. for _, Target in pairs( self.targets ) do
  5060. if Target then
  5061. Target.Size = self.terminal_sizes[Target];
  5062. Target.CFrame = self.terminal_positions[Target];
  5063. Target:MakeJoints();
  5064. Selection:add( Target );
  5065. end;
  5066. end;
  5067. end;
  5068. };
  5069. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  5070. if Item then
  5071. self.State.HistoryRecord.initial_sizes[Item] = Item.Size;
  5072. self.State.HistoryRecord.initial_positions[Item] = Item.CFrame;
  5073. end;
  5074. end;
  5075.  
  5076. end;
  5077.  
  5078. Tools.Resize.finishHistoryRecord = function ( self )
  5079.  
  5080. if not self.State.HistoryRecord then
  5081. return;
  5082. end;
  5083.  
  5084. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  5085. if Item then
  5086. self.State.HistoryRecord.terminal_sizes[Item] = Item.Size;
  5087. self.State.HistoryRecord.terminal_positions[Item] = Item.CFrame;
  5088. end;
  5089. end;
  5090. History:add( self.State.HistoryRecord );
  5091. self.State.HistoryRecord = nil;
  5092.  
  5093. end;
  5094.  
  5095. Tools.Resize.changeSize = function ( self, component, new_value )
  5096.  
  5097. self:startHistoryRecord();
  5098.  
  5099. -- Change the size of each item selected
  5100. for _, Item in pairs( Selection.Items ) do
  5101. local OldCFrame = Item.CFrame;
  5102. -- Make the item be able to be freely resized
  5103. if ( pcall( function () local test = Item.FormFactor; end ) ) then
  5104. Item.FormFactor = Enum.FormFactor.Custom;
  5105. end;
  5106. Item.Size = Vector3.new(
  5107. component == 'x' and new_value or Item.Size.x,
  5108. component == 'y' and new_value or Item.Size.y,
  5109. component == 'z' and new_value or Item.Size.z
  5110. );
  5111. Item.CFrame = OldCFrame;
  5112. end;
  5113.  
  5114. self:finishHistoryRecord();
  5115.  
  5116. end;
  5117.  
  5118. Tools.Resize.updateGUI = function ( self )
  5119.  
  5120. -- Make sure the GUI exists
  5121. if not self.GUI then
  5122. return;
  5123. end;
  5124.  
  5125. local GUI = self.GUI;
  5126.  
  5127. if #Selection.Items > 0 then
  5128.  
  5129. -- Look for identical numbers in each axis
  5130. local size_x, size_y, size_z = nil, nil, nil;
  5131. for item_index, Item in pairs( Selection.Items ) do
  5132.  
  5133. -- Set the first values for the first item
  5134. if item_index == 1 then
  5135. size_x, size_y, size_z = _round( Item.Size.x, 2 ), _round( Item.Size.y, 2 ), _round( Item.Size.z, 2 );
  5136.  
  5137. -- Otherwise, compare them and set them to `nil` if they're not identical
  5138. else
  5139. if size_x ~= _round( Item.Size.x, 2 ) then
  5140. size_x = nil;
  5141. end;
  5142. if size_y ~= _round( Item.Size.y, 2 ) then
  5143. size_y = nil;
  5144. end;
  5145. if size_z ~= _round( Item.Size.z, 2 ) then
  5146. size_z = nil;
  5147. end;
  5148. end;
  5149.  
  5150. end;
  5151.  
  5152. -- Update the size info on the GUI
  5153. if not self.State.size_x_focused then
  5154. GUI.Info.SizeInfo.X.TextBox.Text = size_x and tostring( size_x ) or "*";
  5155. end;
  5156. if not self.State.size_y_focused then
  5157. GUI.Info.SizeInfo.Y.TextBox.Text = size_y and tostring( size_y ) or "*";
  5158. end;
  5159. if not self.State.size_z_focused then
  5160. GUI.Info.SizeInfo.Z.TextBox.Text = size_z and tostring( size_z ) or "*";
  5161. end;
  5162.  
  5163. GUI.Info.Visible = true;
  5164. else
  5165. GUI.Info.Visible = false;
  5166. end;
  5167.  
  5168. if self.State.length_resized then
  5169. GUI.Changes.Text.Text = "resized " .. tostring( self.State.length_resized ) .. " studs";
  5170. GUI.Changes.Position = GUI.Info.Visible and UDim2.new( 0, 5, 0, 165 ) or UDim2.new( 0, 5, 0, 100 );
  5171. GUI.Changes.Visible = true;
  5172. else
  5173. GUI.Changes.Text.Text = "";
  5174. GUI.Changes.Visible = false;
  5175. end;
  5176.  
  5177. end;
  5178.  
  5179. Tools.Resize.hideGUI = function ( self )
  5180.  
  5181. -- Hide the GUI if it exists
  5182. if self.GUI then
  5183. self.GUI.Visible = false;
  5184. end;
  5185.  
  5186. end;
  5187.  
  5188. Tools.Resize.showHandles = function ( self, Part )
  5189.  
  5190. -- Create the handles if they don't exist yet
  5191. if not self.Handles then
  5192.  
  5193. -- Create the object
  5194. self.Handles = RbxUtility.Create "Handles" {
  5195. Name = "BTResizeHandles";
  5196. Style = Enum.HandlesStyle.Resize;
  5197. Color = self.Color;
  5198. Parent = GUIContainer;
  5199. };
  5200.  
  5201. -- Add functionality to the handles
  5202. self.Handles.MouseButton1Down:connect( function ()
  5203.  
  5204. -- Prevent the platform from thinking we're selecting
  5205. override_selection = true;
  5206. self.State.resizing = true;
  5207.  
  5208. -- Clear the change stats
  5209. self.State.length_resized = 0;
  5210.  
  5211. self:startHistoryRecord();
  5212.  
  5213. -- Do a few things to the selection before manipulating it
  5214. for _, Item in pairs( Selection.Items ) do
  5215.  
  5216. -- Keep a copy of the state of each item
  5217. self.State.PreResize[Item] = Item:Clone();
  5218.  
  5219. -- Make the item be able to be freely resized
  5220. if ( pcall( function () local test = Item.FormFactor; end ) ) then
  5221. Item.FormFactor = Enum.FormFactor.Custom;
  5222. end;
  5223.  
  5224. -- Anchor each item
  5225. Item.Anchored = true;
  5226.  
  5227. end;
  5228.  
  5229. -- Return stuff to normal once the mouse button is released
  5230. self.Connections.HandleReleaseListener = Mouse.Button1Up:connect( function ()
  5231.  
  5232. -- Prevent the platform from thinking we're selecting
  5233. override_selection = true;
  5234. self.State.resizing = false;
  5235.  
  5236. -- Stop this connection from firing again
  5237. if self.Connections.HandleReleaseListener then
  5238. self.Connections.HandleReleaseListener:disconnect();
  5239. self.Connections.HandleReleaseListener = nil;
  5240. end;
  5241.  
  5242. self:finishHistoryRecord();
  5243.  
  5244. -- Restore properties that may have been changed temporarily
  5245. -- from the pre-resize state copies
  5246. for Item, PreviousItemState in pairs( self.State.PreResize ) do
  5247. Item.Anchored = PreviousItemState.Anchored;
  5248. self.State.PreResize[Item] = nil;
  5249. Item:MakeJoints();
  5250. end;
  5251.  
  5252. end );
  5253.  
  5254. end );
  5255.  
  5256. self.Handles.MouseDrag:connect( function ( face, drag_distance )
  5257.  
  5258. -- Calculate which multiple of the increment to use based on the current drag distance's
  5259. -- proximity to their nearest upper and lower multiples
  5260.  
  5261. local difference = drag_distance % self.Options.increment;
  5262.  
  5263. local lower_degree = drag_distance - difference;
  5264. local upper_degree = drag_distance - difference + self.Options.increment;
  5265.  
  5266. local lower_degree_proximity = math.abs( drag_distance - lower_degree );
  5267. local upper_degree_proximity = math.abs( drag_distance - upper_degree );
  5268.  
  5269. if lower_degree_proximity <= upper_degree_proximity then
  5270. drag_distance = lower_degree;
  5271. else
  5272. drag_distance = upper_degree;
  5273. end;
  5274.  
  5275. local increase = drag_distance;
  5276.  
  5277. -- Log the distance that the handle was dragged
  5278. self.State.previous_distance = drag_distance;
  5279.  
  5280. -- Note the length by which the selection will be enlarged
  5281. if self.Options.directions == "both" then
  5282. increase = drag_distance * 2;
  5283. end;
  5284. self.State.length_resized = increase;
  5285.  
  5286. -- Go through the selection and make changes to it
  5287. for _, Item in pairs( Selection.Items ) do
  5288.  
  5289. -- Keep a copy of `Item` in case we need to revert anything
  5290. local PreviousItemState = Item:Clone();
  5291.  
  5292. -- Break any of `Item`'s joints so it can move freely
  5293. Item:BreakJoints();
  5294.  
  5295. -- Position and resize `Item` according to the options and the handle that was used
  5296.  
  5297. if face == Enum.NormalId.Top then
  5298.  
  5299. -- Calculate the appropriate increment to the size based on the shape of `Item`
  5300. local SizeIncrease;
  5301. if ( pcall( function () local test = Item.Shape; end ) ) and ( Item.Shape == Enum.PartType.Ball or Item.Shape == Enum.PartType.Cylinder ) then
  5302. SizeIncrease = Vector3.new( increase, increase, increase );
  5303. elseif not ( pcall( function () local test = Item.Shape; end ) ) or ( Item.Shape and Item.Shape == Enum.PartType.Block ) then
  5304. SizeIncrease = Vector3.new( 0, increase, 0 );
  5305. end;
  5306.  
  5307. Item.Size = self.State.PreResize[Item].Size + SizeIncrease;
  5308. if Item.Size == self.State.PreResize[Item].Size + SizeIncrease then
  5309. Item.CFrame = ( self.Options.directions == "normal" and self.State.PreResize[Item].CFrame:toWorldSpace( CFrame.new( 0, increase / 2, 0 ) ) )
  5310. or ( self.Options.directions == "both" and self.State.PreResize[Item].CFrame );
  5311. -- If the resizing was not possible, revert `Item`'s state
  5312. else
  5313. Item.Size = PreviousItemState.Size;
  5314. Item.CFrame = PreviousItemState.CFrame;
  5315. end;
  5316.  
  5317. elseif face == Enum.NormalId.Bottom then
  5318.  
  5319. -- Calculate the appropriate increment to the size based on the shape of `Item`
  5320. local SizeIncrease;
  5321. if ( pcall( function () local test = Item.Shape; end ) ) and ( Item.Shape == Enum.PartType.Ball or Item.Shape == Enum.PartType.Cylinder ) then
  5322. SizeIncrease = Vector3.new( increase, increase, increase );
  5323. elseif not ( pcall( function () local test = Item.Shape; end ) ) or ( Item.Shape and Item.Shape == Enum.PartType.Block ) then
  5324. SizeIncrease = Vector3.new( 0, increase, 0 );
  5325. end;
  5326.  
  5327. Item.Size = self.State.PreResize[Item].Size + SizeIncrease;
  5328. if Item.Size == self.State.PreResize[Item].Size + SizeIncrease then
  5329. Item.CFrame = ( self.Options.directions == "normal" and self.State.PreResize[Item].CFrame:toWorldSpace( CFrame.new( 0, -increase / 2, 0 ) ) )
  5330. or ( self.Options.directions == "both" and self.State.PreResize[Item].CFrame );
  5331. -- If the resizing was not possible, revert `Item`'s state
  5332. else
  5333. Item.Size = PreviousItemState.Size;
  5334. Item.CFrame = PreviousItemState.CFrame;
  5335. end;
  5336.  
  5337. elseif face == Enum.NormalId.Front then
  5338.  
  5339. -- Calculate the appropriate increment to the size based on the shape of `Item`
  5340. local SizeIncrease;
  5341. if ( pcall( function () local test = Item.Shape; end ) ) and ( Item.Shape == Enum.PartType.Ball or Item.Shape == Enum.PartType.Cylinder ) then
  5342. SizeIncrease = Vector3.new( increase, increase, increase );
  5343. elseif not ( pcall( function () local test = Item.Shape; end ) ) or ( Item.Shape and Item.Shape == Enum.PartType.Block ) then
  5344. SizeIncrease = Vector3.new( 0, 0, increase );
  5345. end;
  5346.  
  5347. Item.Size = self.State.PreResize[Item].Size + SizeIncrease;
  5348. if Item.Size == self.State.PreResize[Item].Size + SizeIncrease then
  5349. Item.CFrame = ( self.Options.directions == "normal" and self.State.PreResize[Item].CFrame:toWorldSpace( CFrame.new( 0, 0, -increase / 2 ) ) )
  5350. or ( self.Options.directions == "both" and self.State.PreResize[Item].CFrame );
  5351. -- If the resizing was not possible, revert `Item`'s state
  5352. else
  5353. Item.Size = PreviousItemState.Size;
  5354. Item.CFrame = PreviousItemState.CFrame;
  5355. end;
  5356.  
  5357. elseif face == Enum.NormalId.Back then
  5358.  
  5359. -- Calculate the appropriate increment to the size based on the shape of `Item`
  5360. local SizeIncrease;
  5361. if ( pcall( function () local test = Item.Shape; end ) ) and ( Item.Shape == Enum.PartType.Ball or Item.Shape == Enum.PartType.Cylinder ) then
  5362. SizeIncrease = Vector3.new( increase, increase, increase );
  5363. elseif not ( pcall( function () local test = Item.Shape; end ) ) or ( Item.Shape and Item.Shape == Enum.PartType.Block ) then
  5364. SizeIncrease = Vector3.new( 0, 0, increase );
  5365. end;
  5366.  
  5367. Item.Size = self.State.PreResize[Item].Size + SizeIncrease;
  5368. if Item.Size == self.State.PreResize[Item].Size + SizeIncrease then
  5369. Item.CFrame = ( self.Options.directions == "normal" and self.State.PreResize[Item].CFrame:toWorldSpace( CFrame.new( 0, 0, increase / 2 ) ) )
  5370. or ( self.Options.directions == "both" and self.State.PreResize[Item].CFrame );
  5371. -- If the resizing was not possible, revert `Item`'s state
  5372. else
  5373. Item.Size = PreviousItemState.Size;
  5374. Item.CFrame = PreviousItemState.CFrame;
  5375. end;
  5376.  
  5377. elseif face == Enum.NormalId.Left then
  5378.  
  5379. -- Calculate the appropriate increment to the size based on the shape of `Item`
  5380. local SizeIncrease;
  5381. if ( pcall( function () local test = Item.Shape; end ) ) and ( Item.Shape == Enum.PartType.Ball or Item.Shape == Enum.PartType.Cylinder ) then
  5382. SizeIncrease = Vector3.new( increase, increase, increase );
  5383. elseif not ( pcall( function () local test = Item.Shape; end ) ) or ( Item.Shape and Item.Shape == Enum.PartType.Block ) then
  5384. SizeIncrease = Vector3.new( increase, 0, 0 );
  5385. end;
  5386.  
  5387. Item.Size = self.State.PreResize[Item].Size + SizeIncrease;
  5388. if Item.Size == self.State.PreResize[Item].Size + SizeIncrease then
  5389. Item.CFrame = ( self.Options.directions == "normal" and self.State.PreResize[Item].CFrame:toWorldSpace( CFrame.new( -increase / 2, 0, 0 ) ) )
  5390. or ( self.Options.directions == "both" and self.State.PreResize[Item].CFrame );
  5391. -- If the resizing was not possible, revert `Item`'s state
  5392. else
  5393. Item.Size = PreviousItemState.Size;
  5394. Item.CFrame = PreviousItemState.CFrame;
  5395. end;
  5396.  
  5397. elseif face == Enum.NormalId.Right then
  5398.  
  5399. -- Calculate the appropriate increment to the size based on the shape of `Item`
  5400. local SizeIncrease;
  5401. if ( pcall( function () local test = Item.Shape; end ) ) and ( Item.Shape == Enum.PartType.Ball or Item.Shape == Enum.PartType.Cylinder ) then
  5402. SizeIncrease = Vector3.new( increase, increase, increase );
  5403. elseif not ( pcall( function () local test = Item.Shape; end ) ) or ( Item.Shape and Item.Shape == Enum.PartType.Block ) then
  5404. SizeIncrease = Vector3.new( increase, 0, 0 );
  5405. end;
  5406.  
  5407. Item.Size = self.State.PreResize[Item].Size + SizeIncrease;
  5408. if Item.Size == self.State.PreResize[Item].Size + SizeIncrease then
  5409. Item.CFrame = ( self.Options.directions == "normal" and self.State.PreResize[Item].CFrame:toWorldSpace( CFrame.new( increase / 2, 0, 0 ) ) )
  5410. or ( self.Options.directions == "both" and self.State.PreResize[Item].CFrame );
  5411. -- If the resizing was not possible, revert `Item`'s state
  5412. else
  5413. Item.Size = PreviousItemState.Size;
  5414. Item.CFrame = PreviousItemState.CFrame;
  5415. end;
  5416. end;
  5417.  
  5418. -- Make joints with surrounding parts again once the resizing is done
  5419. Item:MakeJoints();
  5420.  
  5421. end;
  5422.  
  5423. end );
  5424.  
  5425. end;
  5426.  
  5427. -- Stop listening for the existence of the previous adornee (if any)
  5428. if self.Connections.AdorneeExistenceListener then
  5429. self.Connections.AdorneeExistenceListener:disconnect();
  5430. self.Connections.AdorneeExistenceListener = nil;
  5431. end;
  5432.  
  5433. -- Attach the handles to `Part`
  5434. self.Handles.Adornee = Part;
  5435.  
  5436. -- Make sure to hide the handles if `Part` suddenly stops existing
  5437. self.Connections.AdorneeExistenceListener = Part.AncestryChanged:connect( function ( Object, NewParent )
  5438.  
  5439. -- Make sure this change in parent applies directly to `Part`
  5440. if Object ~= Part then
  5441. return;
  5442. end;
  5443.  
  5444. -- Show the handles according to the existence of the part
  5445. if NewParent == nil then
  5446. self:hideHandles();
  5447. else
  5448. self:showHandles( Part );
  5449. end;
  5450.  
  5451. end );
  5452.  
  5453. end;
  5454.  
  5455. Tools.Resize.hideHandles = function ( self )
  5456.  
  5457. -- Hide the handles if they exist
  5458. if self.Handles then
  5459. self.Handles.Adornee = nil;
  5460. end;
  5461.  
  5462. end;
  5463.  
  5464. Tools.Resize.Loaded = true;
  5465. end))
  5466. LocalScript3.Disabled = true
  5467. LocalScript4.Name = "BTRotateTool"
  5468. LocalScript4.Parent = LocalScript1
  5469. table.insert(cors,sandbox(LocalScript4,function()
  5470. -- Load the main tool's core environment when it's ready
  5471. repeat wait() until (
  5472. _G.BTCoreEnv and
  5473. _G.BTCoreEnv[script.Parent.Parent] and
  5474. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  5475. );
  5476. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  5477.  
  5478. ------------------------------------------
  5479. -- Rotate tool
  5480. ------------------------------------------
  5481.  
  5482. -- Create the tool
  5483. Tools.Rotate = {};
  5484.  
  5485. -- Create structures to hold data that the tool needs
  5486. Tools.Rotate.Connections = {};
  5487.  
  5488. Tools.Rotate.Options = {
  5489. ["increment"] = 15;
  5490. ["pivot"] = "center"
  5491. };
  5492.  
  5493. Tools.Rotate.State = {
  5494. ["PreRotation"] = {};
  5495. ["rotating"] = false;
  5496. ["previous_distance"] = 0;
  5497. ["degrees_rotated"] = 0;
  5498. ["rotation_size"] = 0;
  5499. };
  5500.  
  5501. Tools.Rotate.Listeners = {};
  5502.  
  5503. -- Define the color of the tool
  5504. Tools.Rotate.Color = BrickColor.new( "Bright green" );
  5505.  
  5506. -- Start adding functionality to the tool
  5507. Tools.Rotate.Listeners.Equipped = function ()
  5508.  
  5509. local self = Tools.Rotate;
  5510.  
  5511. -- Change the color of selection boxes temporarily
  5512. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  5513. SelectionBoxColor = self.Color;
  5514. updateSelectionBoxColor();
  5515.  
  5516. -- Reveal the GUI
  5517. self:showGUI();
  5518.  
  5519. -- Create the boundingbox if it doesn't already exist
  5520. if not self.BoundingBox then
  5521. self.BoundingBox = RbxUtility.Create "Part" {
  5522. Name = "BTBoundingBox";
  5523. CanCollide = false;
  5524. Transparency = 1;
  5525. Anchored = true;
  5526. };
  5527. end;
  5528. Mouse.TargetFilter = self.BoundingBox;
  5529.  
  5530. -- Update the pivot option
  5531. self:changePivot( self.Options.pivot );
  5532.  
  5533. -- Oh, and update the boundingbox and the GUI regularly
  5534. coroutine.wrap( function ()
  5535. updater_on = true;
  5536.  
  5537. -- Provide a function to stop the loop
  5538. self.Updater = function ()
  5539. updater_on = false;
  5540. end;
  5541.  
  5542. while wait( 0.1 ) and updater_on do
  5543.  
  5544. -- Make sure the tool's equipped
  5545. if CurrentTool == self then
  5546.  
  5547. -- Update the GUI if it's visible
  5548. if self.GUI and self.GUI.Visible then
  5549. self:updateGUI();
  5550. end;
  5551.  
  5552. -- Update the boundingbox if it's visible
  5553. if self.Options.pivot == "center" then
  5554. self:updateBoundingBox();
  5555. end;
  5556.  
  5557. end;
  5558.  
  5559. end;
  5560.  
  5561. end )();
  5562.  
  5563. -- Also enable the ability to select an edge as a pivot
  5564. SelectEdge:start( function ( EdgeMarker )
  5565. self:changePivot( "last" );
  5566. self.Options.PivotPoint = EdgeMarker.CFrame;
  5567. self.Connections.EdgeSelectionRemover = Selection.Changed:connect( function ()
  5568. self.Options.PivotPoint = nil;
  5569. if self.Connections.EdgeSelectionRemover then
  5570. self.Connections.EdgeSelectionRemover:disconnect();
  5571. self.Connections.EdgeSelectionRemover = nil;
  5572. end;
  5573. end );
  5574. self:showHandles( EdgeMarker );
  5575. end );
  5576.  
  5577. end;
  5578.  
  5579. Tools.Rotate.Listeners.Unequipped = function ()
  5580.  
  5581. local self = Tools.Rotate;
  5582.  
  5583. -- Stop the update loop
  5584. if self.Updater then
  5585. self.Updater();
  5586. self.Updater = nil;
  5587. end;
  5588.  
  5589. -- Disable the ability to select edges
  5590. SelectEdge:stop();
  5591. if self.Options.PivotPoint then
  5592. self.Options.PivotPoint = nil;
  5593. end;
  5594.  
  5595. -- Hide the GUI
  5596. self:hideGUI();
  5597.  
  5598. -- Hide the handles
  5599. self:hideHandles();
  5600.  
  5601. -- Clear out any temporary connections
  5602. for connection_index, Connection in pairs( self.Connections ) do
  5603. Connection:disconnect();
  5604. self.Connections[connection_index] = nil;
  5605. end;
  5606.  
  5607. -- Restore the original color of the selection boxes
  5608. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  5609. updateSelectionBoxColor();
  5610.  
  5611. end;
  5612.  
  5613. Tools.Rotate.Listeners.Button1Down = function ()
  5614.  
  5615. local self = Tools.Rotate;
  5616.  
  5617. if not self.State.rotating and self.Options.PivotPoint then
  5618. self.Options.PivotPoint = nil;
  5619. end;
  5620.  
  5621. end;
  5622.  
  5623. Tools.Rotate.showGUI = function ( self )
  5624.  
  5625. -- Initialize the GUI if it's not ready yet
  5626. if not self.GUI then
  5627.  
  5628. local Container = Tool.Interfaces:WaitForChild( "BTRotateToolGUI" ):Clone();
  5629. Container.Parent = UI;
  5630.  
  5631. -- Change the pivot type option when the button is clicked
  5632. Container.PivotOption.Center.Button.MouseButton1Down:connect( function ()
  5633. self:changePivot( "center" );
  5634. end );
  5635.  
  5636. Container.PivotOption.Local.Button.MouseButton1Down:connect( function ()
  5637. self:changePivot( "local" );
  5638. end );
  5639.  
  5640. Container.PivotOption.Last.Button.MouseButton1Down:connect( function ()
  5641. self:changePivot( "last" );
  5642. end );
  5643.  
  5644. -- Change the increment option when the value of the textbox is updated
  5645. Container.IncrementOption.Increment.TextBox.FocusLost:connect( function ( enter_pressed )
  5646. self.Options.increment = tonumber( Container.IncrementOption.Increment.TextBox.Text ) or self.Options.increment;
  5647. Container.IncrementOption.Increment.TextBox.Text = tostring( self.Options.increment );
  5648. end );
  5649.  
  5650. -- Add functionality to the rotation inputs
  5651. Container.Info.RotationInfo.X.TextButton.MouseButton1Down:connect( function ()
  5652. self.State.rot_x_focused = true;
  5653. Container.Info.RotationInfo.X.TextBox:CaptureFocus();
  5654. end );
  5655. Container.Info.RotationInfo.X.TextBox.FocusLost:connect( function ( enter_pressed )
  5656. local potential_new = tonumber( Container.Info.RotationInfo.X.TextBox.Text );
  5657. if potential_new then
  5658. self:changeRotation( 'x', math.rad( potential_new ) );
  5659. end;
  5660. self.State.rot_x_focused = false;
  5661. end );
  5662. Container.Info.RotationInfo.Y.TextButton.MouseButton1Down:connect( function ()
  5663. self.State.rot_y_focused = true;
  5664. Container.Info.RotationInfo.Y.TextBox:CaptureFocus();
  5665. end );
  5666. Container.Info.RotationInfo.Y.TextBox.FocusLost:connect( function ( enter_pressed )
  5667. local potential_new = tonumber( Container.Info.RotationInfo.Y.TextBox.Text );
  5668. if potential_new then
  5669. self:changeRotation( 'y', math.rad( potential_new ) );
  5670. end;
  5671. self.State.rot_y_focused = false;
  5672. end );
  5673. Container.Info.RotationInfo.Z.TextButton.MouseButton1Down:connect( function ()
  5674. self.State.rot_z_focused = true;
  5675. Container.Info.RotationInfo.Z.TextBox:CaptureFocus();
  5676. end );
  5677. Container.Info.RotationInfo.Z.TextBox.FocusLost:connect( function ( enter_pressed )
  5678. local potential_new = tonumber( Container.Info.RotationInfo.Z.TextBox.Text );
  5679. if potential_new then
  5680. self:changeRotation( 'z', math.rad( potential_new ) );
  5681. end;
  5682. self.State.rot_z_focused = false;
  5683. end );
  5684.  
  5685. self.GUI = Container;
  5686. end;
  5687.  
  5688. -- Reveal the GUI
  5689. self.GUI.Visible = true;
  5690.  
  5691. end;
  5692.  
  5693. Tools.Rotate.startHistoryRecord = function ( self )
  5694.  
  5695. if self.State.HistoryRecord then
  5696. self.State.HistoryRecord = nil;
  5697. end;
  5698.  
  5699. -- Create a history record
  5700. self.State.HistoryRecord = {
  5701. targets = _cloneTable( Selection.Items );
  5702. initial_cframes = {};
  5703. terminal_cframes = {};
  5704. unapply = function ( self )
  5705. Selection:clear();
  5706. for _, Target in pairs( self.targets ) do
  5707. if Target then
  5708. Target.CFrame = self.initial_cframes[Target];
  5709. Target:MakeJoints();
  5710. Selection:add( Target );
  5711. end;
  5712. end;
  5713. end;
  5714. apply = function ( self )
  5715. Selection:clear();
  5716. for _, Target in pairs( self.targets ) do
  5717. if Target then
  5718. Target.CFrame = self.terminal_cframes[Target];
  5719. Target:MakeJoints();
  5720. Selection:add( Target );
  5721. end;
  5722. end;
  5723. end;
  5724. };
  5725. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  5726. if Item then
  5727. self.State.HistoryRecord.initial_cframes[Item] = Item.CFrame;
  5728. end;
  5729. end;
  5730.  
  5731. end;
  5732.  
  5733. Tools.Rotate.finishHistoryRecord = function ( self )
  5734.  
  5735. if not self.State.HistoryRecord then
  5736. return;
  5737. end;
  5738.  
  5739. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  5740. if Item then
  5741. self.State.HistoryRecord.terminal_cframes[Item] = Item.CFrame;
  5742. end;
  5743. end;
  5744. History:add( self.State.HistoryRecord );
  5745. self.State.HistoryRecord = nil;
  5746.  
  5747. end;
  5748.  
  5749. Tools.Rotate.changeRotation = function ( self, component, new_value )
  5750.  
  5751. self:startHistoryRecord();
  5752.  
  5753. -- Change the rotation of each item selected
  5754. for _, Item in pairs( Selection.Items ) do
  5755. local old_x_rot, old_y_rot, old_z_rot = Item.CFrame:toEulerAnglesXYZ();
  5756. Item.CFrame = CFrame.new( Item.Position ) * CFrame.Angles(
  5757. component == 'x' and new_value or old_x_rot,
  5758. component == 'y' and new_value or old_y_rot,
  5759. component == 'z' and new_value or old_z_rot
  5760. );
  5761. end;
  5762.  
  5763. self:finishHistoryRecord();
  5764.  
  5765. end;
  5766.  
  5767. Tools.Rotate.updateGUI = function ( self )
  5768.  
  5769. -- Make sure the GUI exists
  5770. if not self.GUI then
  5771. return;
  5772. end;
  5773.  
  5774. local GUI = self.GUI;
  5775.  
  5776. if #Selection.Items > 0 then
  5777.  
  5778. -- Look for identical numbers in each axis
  5779. local rot_x, rot_y, rot_z = nil, nil, nil;
  5780. for item_index, Item in pairs( Selection.Items ) do
  5781.  
  5782. local item_rot_x, item_rot_y, item_rot_z = Item.CFrame:toEulerAnglesXYZ();
  5783.  
  5784. -- Set the first values for the first item
  5785. if item_index == 1 then
  5786. rot_x, rot_y, rot_z = _round( math.deg( item_rot_x ), 2 ), _round( math.deg( item_rot_y ), 2 ), _round( math.deg( item_rot_z ), 2 );
  5787.  
  5788. -- Otherwise, compare them and set them to `nil` if they're not identical
  5789. else
  5790. if rot_x ~= _round( math.deg( item_rot_x ), 2 ) then
  5791. rot_x = nil;
  5792. end;
  5793. if rot_y ~= _round( math.deg( item_rot_y ), 2 ) then
  5794. rot_y = nil;
  5795. end;
  5796. if rot_z ~= _round( math.deg( item_rot_z ), 2 ) then
  5797. rot_z = nil;
  5798. end;
  5799. end;
  5800.  
  5801. end;
  5802.  
  5803. -- Update the size info on the GUI
  5804. if not self.State.rot_x_focused then
  5805. GUI.Info.RotationInfo.X.TextBox.Text = rot_x and tostring( rot_x ) or "*";
  5806. end;
  5807. if not self.State.rot_y_focused then
  5808. GUI.Info.RotationInfo.Y.TextBox.Text = rot_y and tostring( rot_y ) or "*";
  5809. end;
  5810. if not self.State.rot_z_focused then
  5811. GUI.Info.RotationInfo.Z.TextBox.Text = rot_z and tostring( rot_z ) or "*";
  5812. end;
  5813.  
  5814. GUI.Info.Visible = true;
  5815. else
  5816. GUI.Info.Visible = false;
  5817. end;
  5818.  
  5819. if self.State.degrees_rotated then
  5820. GUI.Changes.Text.Text = "rotated " .. tostring( self.State.degrees_rotated ) .. " degrees";
  5821. GUI.Changes.Position = GUI.Info.Visible and UDim2.new( 0, 5, 0, 165 ) or UDim2.new( 0, 5, 0, 100 );
  5822. GUI.Changes.Visible = true;
  5823. else
  5824. GUI.Changes.Text.Text = "";
  5825. GUI.Changes.Visible = false;
  5826. end;
  5827.  
  5828. end;
  5829.  
  5830. Tools.Rotate.hideGUI = function ( self )
  5831.  
  5832. -- Hide the GUI if it exists
  5833. if self.GUI then
  5834. self.GUI.Visible = false;
  5835. end;
  5836.  
  5837. end;
  5838.  
  5839. Tools.Rotate.updateBoundingBox = function ( self )
  5840.  
  5841. if #Selection.Items > 0 then
  5842. local SelectionSize, SelectionPosition = _getCollectionInfo( Selection.Items );
  5843. self.BoundingBox.Size = SelectionSize;
  5844. self.BoundingBox.CFrame = SelectionPosition;
  5845. self:showHandles( self.BoundingBox );
  5846.  
  5847. else
  5848. self:hideHandles();
  5849. end;
  5850.  
  5851. end;
  5852.  
  5853. Tools.Rotate.changePivot = function ( self, new_pivot )
  5854.  
  5855. -- Have a quick reference to the GUI (if any)
  5856. local PivotOptionGUI = self.GUI and self.GUI.PivotOption or nil;
  5857.  
  5858. -- Disconnect any handle-related listeners that are specific to a certain pivot option
  5859. if self.Connections.HandleFocusChangeListener then
  5860. self.Connections.HandleFocusChangeListener:disconnect();
  5861. self.Connections.HandleFocusChangeListener = nil;
  5862. end;
  5863.  
  5864. if self.Connections.HandleSelectionChangeListener then
  5865. self.Connections.HandleSelectionChangeListener:disconnect();
  5866. self.Connections.HandleSelectionChangeListener = nil;
  5867. end;
  5868.  
  5869. -- Remove any temporary edge selection
  5870. if self.Options.PivotPoint then
  5871. self.Options.PivotPoint = nil;
  5872. end;
  5873.  
  5874. if new_pivot == "center" then
  5875.  
  5876. -- Update the options
  5877. self.Options.pivot = "center";
  5878.  
  5879. -- Focus the handles on the boundingbox
  5880. self:showHandles( self.BoundingBox );
  5881.  
  5882. -- Update the GUI's option panel
  5883. if self.GUI then
  5884. PivotOptionGUI.Center.SelectedIndicator.BackgroundTransparency = 0;
  5885. PivotOptionGUI.Center.Background.Image = dark_slanted_rectangle;
  5886. PivotOptionGUI.Local.SelectedIndicator.BackgroundTransparency = 1;
  5887. PivotOptionGUI.Local.Background.Image = light_slanted_rectangle;
  5888. PivotOptionGUI.Last.SelectedIndicator.BackgroundTransparency = 1;
  5889. PivotOptionGUI.Last.Background.Image = light_slanted_rectangle;
  5890. end;
  5891.  
  5892. end;
  5893.  
  5894. if new_pivot == "local" then
  5895.  
  5896. -- Update the options
  5897. self.Options.pivot = "local";
  5898.  
  5899. -- Always have the handles on the most recent addition to the selection
  5900. self.Connections.HandleSelectionChangeListener = Selection.Changed:connect( function ()
  5901.  
  5902. -- Clear out any previous adornee
  5903. self:hideHandles();
  5904.  
  5905. -- If there /is/ a last item in the selection, attach the handles to it
  5906. if Selection.Last then
  5907. self:showHandles( Selection.Last );
  5908. end;
  5909.  
  5910. end );
  5911.  
  5912. -- Switch the adornee of the handles if the second mouse button is pressed
  5913. self.Connections.HandleFocusChangeListener = Mouse.Button2Up:connect( function ()
  5914.  
  5915. -- Make sure the platform doesn't think we're selecting
  5916. override_selection = true;
  5917.  
  5918. -- If the target is in the selection, make it the new adornee
  5919. if Selection:find( Mouse.Target ) then
  5920. Selection:focus( Mouse.Target );
  5921. self:showHandles( Mouse.Target );
  5922. end;
  5923.  
  5924. end );
  5925.  
  5926. -- Finally, attach the handles to the last item added to the selection (if any)
  5927. if Selection.Last then
  5928. self:showHandles( Selection.Last );
  5929. end;
  5930.  
  5931. -- Update the GUI's option panel
  5932. if self.GUI then
  5933. PivotOptionGUI.Center.SelectedIndicator.BackgroundTransparency = 1;
  5934. PivotOptionGUI.Center.Background.Image = light_slanted_rectangle;
  5935. PivotOptionGUI.Local.SelectedIndicator.BackgroundTransparency = 0;
  5936. PivotOptionGUI.Local.Background.Image = dark_slanted_rectangle;
  5937. PivotOptionGUI.Last.SelectedIndicator.BackgroundTransparency = 1;
  5938. PivotOptionGUI.Last.Background.Image = light_slanted_rectangle;
  5939. end;
  5940.  
  5941. end;
  5942.  
  5943. if new_pivot == "last" then
  5944.  
  5945. -- Update the options
  5946. self.Options.pivot = "last";
  5947.  
  5948. -- Always have the handles on the most recent addition to the selection
  5949. self.Connections.HandleSelectionChangeListener = Selection.Changed:connect( function ()
  5950.  
  5951. -- Clear out any previous adornee
  5952. if not self.Options.PivotPoint then
  5953. self:hideHandles();
  5954. end;
  5955.  
  5956. -- If there /is/ a last item in the selection, attach the handles to it
  5957. if Selection.Last and not self.Options.PivotPoint then
  5958. self:showHandles( Selection.Last );
  5959. end;
  5960.  
  5961. end );
  5962.  
  5963. -- Switch the adornee of the handles if the second mouse button is pressed
  5964. self.Connections.HandleFocusChangeListener = Mouse.Button2Up:connect( function ()
  5965.  
  5966. -- Make sure the platform doesn't think we're selecting
  5967. override_selection = true;
  5968.  
  5969. -- If the target is in the selection, make it the new adornee
  5970. if Selection:find( Mouse.Target ) then
  5971. Selection:focus( Mouse.Target );
  5972. self:showHandles( Mouse.Target );
  5973. end;
  5974.  
  5975. end );
  5976.  
  5977. -- Finally, attach the handles to the last item added to the selection (if any)
  5978. if Selection.Last then
  5979. self:showHandles( Selection.Last );
  5980. end;
  5981.  
  5982. -- Update the GUI's option panel
  5983. if self.GUI then
  5984. PivotOptionGUI.Center.SelectedIndicator.BackgroundTransparency = 1;
  5985. PivotOptionGUI.Center.Background.Image = light_slanted_rectangle;
  5986. PivotOptionGUI.Local.SelectedIndicator.BackgroundTransparency = 1;
  5987. PivotOptionGUI.Local.Background.Image = light_slanted_rectangle;
  5988. PivotOptionGUI.Last.SelectedIndicator.BackgroundTransparency = 0;
  5989. PivotOptionGUI.Last.Background.Image = dark_slanted_rectangle;
  5990. end;
  5991.  
  5992. end;
  5993.  
  5994. end;
  5995.  
  5996.  
  5997. Tools.Rotate.showHandles = function ( self, Part )
  5998.  
  5999. -- Create the handles if they don't exist yet
  6000. if not self.Handles then
  6001.  
  6002. -- Create the object
  6003. self.Handles = RbxUtility.Create "ArcHandles" {
  6004. Name = "BTRotationHandles";
  6005. Color = self.Color;
  6006. Parent = GUIContainer;
  6007. };
  6008.  
  6009. -- Add functionality to the handles
  6010.  
  6011. self.Handles.MouseButton1Down:connect( function ()
  6012.  
  6013. -- Prevent the platform from thinking we're selecting
  6014. override_selection = true;
  6015. self.State.rotating = true;
  6016.  
  6017. -- Clear the change stats
  6018. self.State.degrees_rotated = 0;
  6019. self.State.rotation_size = 0;
  6020.  
  6021. self:startHistoryRecord();
  6022.  
  6023. -- Do a few things to the selection before manipulating it
  6024. for _, Item in pairs( Selection.Items ) do
  6025.  
  6026. -- Keep a copy of the state of each item
  6027. self.State.PreRotation[Item] = Item:Clone();
  6028.  
  6029. -- Anchor each item
  6030. Item.Anchored = true;
  6031.  
  6032. end;
  6033.  
  6034. -- Also keep the position of the original selection
  6035. local PreRotationSize, PreRotationPosition = _getCollectionInfo( self.State.PreRotation );
  6036. self.State.PreRotationPosition = PreRotationPosition;
  6037.  
  6038. -- Return stuff to normal once the mouse button is released
  6039. self.Connections.HandleReleaseListener = Mouse.Button1Up:connect( function ()
  6040.  
  6041. -- Prevent the platform from thinking we're selecting
  6042. override_selection = true;
  6043. self.State.rotating = false;
  6044.  
  6045. -- Stop this connection from firing again
  6046. if self.Connections.HandleReleaseListener then
  6047. self.Connections.HandleReleaseListener:disconnect();
  6048. self.Connections.HandleReleaseListener = nil;
  6049. end;
  6050.  
  6051. self:finishHistoryRecord();
  6052.  
  6053. -- Restore properties that may have been changed temporarily
  6054. -- from the pre-rotation state copies
  6055. for Item, PreviousItemState in pairs( self.State.PreRotation ) do
  6056. Item.Anchored = PreviousItemState.Anchored;
  6057. self.State.PreRotation[Item] = nil;
  6058. Item:MakeJoints();
  6059. end;
  6060.  
  6061. end );
  6062.  
  6063. end );
  6064.  
  6065. self.Handles.MouseDrag:connect( function ( axis, drag_distance )
  6066.  
  6067. -- Round down and convert the drag distance to degrees to make it easier to work with
  6068. local drag_distance = math.floor( math.deg( drag_distance ) );
  6069.  
  6070. -- Calculate which multiple of the increment to use based on the current angle's
  6071. -- proximity to their nearest upper and lower multiples
  6072.  
  6073. local difference = drag_distance % self.Options.increment;
  6074.  
  6075. local lower_degree = drag_distance - difference;
  6076. local upper_degree = drag_distance - difference + self.Options.increment;
  6077.  
  6078. local lower_degree_proximity = math.abs( drag_distance - lower_degree );
  6079. local upper_degree_proximity = math.abs( drag_distance - upper_degree );
  6080.  
  6081. if lower_degree_proximity <= upper_degree_proximity then
  6082. drag_distance = lower_degree;
  6083. else
  6084. drag_distance = upper_degree;
  6085. end;
  6086.  
  6087. local increase = self.Options.increment * math.floor( drag_distance / self.Options.increment );
  6088.  
  6089. self.State.degrees_rotated = drag_distance;
  6090.  
  6091. -- Go through the selection and make changes to it
  6092. for _, Item in pairs( Selection.Items ) do
  6093.  
  6094. -- Keep a copy of `Item` in case we need to revert anything
  6095. local PreviousItemState = Item:Clone();
  6096.  
  6097. -- Break any of `Item`'s joints so it can move freely
  6098. Item:BreakJoints();
  6099.  
  6100. -- Rotate `Item` according to the options and the handle that was used
  6101. if axis == Enum.Axis.Y then
  6102. if self.Options.pivot == "center" then
  6103. Item.CFrame = self.State.PreRotationPosition:toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( 0, math.rad( increase ), 0 ) ):toWorldSpace( self.State.PreRotation[Item].CFrame:toObjectSpace( self.State.PreRotationPosition ):inverse() );
  6104. elseif self.Options.pivot == "local" then
  6105. Item.CFrame = self.State.PreRotation[Item].CFrame:toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( 0, math.rad( increase ), 0 ) );
  6106. elseif self.Options.pivot == "last" then
  6107. Item.CFrame = ( self.Options.PivotPoint or self.State.PreRotation[Selection.Last].CFrame ):toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( 0, math.rad( increase ), 0 ) ):toWorldSpace( self.State.PreRotation[Item].CFrame:toObjectSpace( self.Options.PivotPoint or self.State.PreRotation[Selection.Last].CFrame ):inverse() );
  6108. end;
  6109. elseif axis == Enum.Axis.X then
  6110. if self.Options.pivot == "center" then
  6111. Item.CFrame = self.State.PreRotationPosition:toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( math.rad( increase ), 0, 0 ) ):toWorldSpace( self.State.PreRotation[Item].CFrame:toObjectSpace( self.State.PreRotationPosition ):inverse() );
  6112. elseif self.Options.pivot == "local" then
  6113. Item.CFrame = self.State.PreRotation[Item].CFrame:toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( math.rad( increase ), 0, 0 ) );
  6114. elseif self.Options.pivot == "last" then
  6115. Item.CFrame = ( self.Options.PivotPoint or self.State.PreRotation[Selection.Last].CFrame ):toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( math.rad( increase ), 0, 0 ) ):toWorldSpace( self.State.PreRotation[Item].CFrame:toObjectSpace( self.Options.PivotPoint or self.State.PreRotation[Selection.Last].CFrame ):inverse() );
  6116. end;
  6117. elseif axis == Enum.Axis.Z then
  6118. if self.Options.pivot == "center" then
  6119. Item.CFrame = self.State.PreRotationPosition:toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( 0, 0, math.rad( increase ) ) ):toWorldSpace( self.State.PreRotation[Item].CFrame:toObjectSpace( self.State.PreRotationPosition ):inverse() );
  6120. elseif self.Options.pivot == "local" then
  6121. Item.CFrame = self.State.PreRotation[Item].CFrame:toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( 0, 0, math.rad( increase ) ) );
  6122. elseif self.Options.pivot == "last" then
  6123. Item.CFrame = ( self.Options.PivotPoint or self.State.PreRotation[Selection.Last].CFrame ):toWorldSpace( CFrame.new( 0, 0, 0 ) * CFrame.Angles( 0, 0, math.rad( increase ) ) ):toWorldSpace( self.State.PreRotation[Item].CFrame:toObjectSpace( self.Options.PivotPoint or self.State.PreRotation[Selection.Last].CFrame ):inverse() );
  6124. end;
  6125. end;
  6126.  
  6127. -- Make joints with surrounding parts again once the resizing is done
  6128. Item:MakeJoints();
  6129.  
  6130. end;
  6131.  
  6132. end );
  6133.  
  6134. end;
  6135.  
  6136. -- Stop listening for the existence of the previous adornee (if any)
  6137. if self.Connections.AdorneeExistenceListener then
  6138. self.Connections.AdorneeExistenceListener:disconnect();
  6139. self.Connections.AdorneeExistenceListener = nil;
  6140. end;
  6141.  
  6142. -- Attach the handles to `Part`
  6143. self.Handles.Adornee = Part;
  6144.  
  6145. -- Make sure to hide the handles if `Part` suddenly stops existing
  6146. self.Connections.AdorneeExistenceListener = Part.AncestryChanged:connect( function ( Object, NewParent )
  6147.  
  6148. -- Make sure this change in parent applies directly to `Part`
  6149. if Object ~= Part then
  6150. return;
  6151. end;
  6152.  
  6153. -- Show the handles according to the existence of the part
  6154. if NewParent == nil then
  6155. self:hideHandles();
  6156. else
  6157. self:showHandles( Part );
  6158. end;
  6159.  
  6160. end );
  6161.  
  6162. end;
  6163.  
  6164. Tools.Rotate.hideHandles = function ( self )
  6165.  
  6166. -- Hide the handles if they exist
  6167. if self.Handles then
  6168. self.Handles.Adornee = nil;
  6169. end;
  6170.  
  6171. end;
  6172.  
  6173. Tools.Rotate.Loaded = true;
  6174. end))
  6175. LocalScript4.Disabled = true
  6176. LocalScript5.Name = "BTPaintTool"
  6177. LocalScript5.Parent = LocalScript1
  6178. table.insert(cors,sandbox(LocalScript5,function()
  6179. -- Load the main tool's core environment when it's ready
  6180. repeat wait() until (
  6181. _G.BTCoreEnv and
  6182. _G.BTCoreEnv[script.Parent.Parent] and
  6183. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  6184. );
  6185. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  6186.  
  6187. ------------------------------------------
  6188. -- Paint tool
  6189. ------------------------------------------
  6190.  
  6191. -- Create the main container for this tool
  6192. Tools.Paint = {};
  6193.  
  6194. -- Define the color of the tool
  6195. Tools.Paint.Color = BrickColor.new( "Really red" );
  6196.  
  6197. -- Define options
  6198. Tools.Paint.Options = {
  6199. ["Color"] = nil
  6200. };
  6201.  
  6202. Tools.Paint.State = {};
  6203.  
  6204. -- Add listeners
  6205. Tools.Paint.Listeners = {};
  6206.  
  6207. Tools.Paint.Listeners.Equipped = function ()
  6208.  
  6209. local self = Tools.Paint;
  6210.  
  6211. -- Change the color of selection boxes temporarily
  6212. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  6213. SelectionBoxColor = self.Color;
  6214. updateSelectionBoxColor();
  6215.  
  6216. -- Show the GUI
  6217. self:showGUI();
  6218.  
  6219. -- Update the selected color
  6220. self:changeColor( self.Options.Color );
  6221.  
  6222. end;
  6223.  
  6224. Tools.Paint.Listeners.Unequipped = function ()
  6225.  
  6226. local self = Tools.Paint;
  6227.  
  6228. -- Clear out the preferred color option
  6229. self:changeColor( nil );
  6230.  
  6231. -- Hide the GUI
  6232. self:hideGUI();
  6233.  
  6234. -- Restore the original color of the selection boxes
  6235. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  6236. updateSelectionBoxColor();
  6237.  
  6238. end;
  6239.  
  6240. Tools.Paint.startHistoryRecord = function ( self )
  6241.  
  6242. if self.State.HistoryRecord then
  6243. self.State.HistoryRecord = nil;
  6244. end;
  6245.  
  6246. -- Create a history record
  6247. self.State.HistoryRecord = {
  6248. targets = _cloneTable( Selection.Items );
  6249. initial_colors = {};
  6250. terminal_colors = {};
  6251. unapply = function ( self )
  6252. Selection:clear();
  6253. for _, Target in pairs( self.targets ) do
  6254. if Target then
  6255. Target.BrickColor = self.initial_colors[Target];
  6256. Selection:add( Target );
  6257. end;
  6258. end;
  6259. end;
  6260. apply = function ( self )
  6261. Selection:clear();
  6262. for _, Target in pairs( self.targets ) do
  6263. if Target then
  6264. Target.BrickColor = self.terminal_colors[Target];
  6265. Selection:add( Target );
  6266. end;
  6267. end;
  6268. end;
  6269. };
  6270. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  6271. if Item then
  6272. self.State.HistoryRecord.initial_colors[Item] = Item.BrickColor;
  6273. end;
  6274. end;
  6275.  
  6276. end;
  6277.  
  6278. Tools.Paint.finishHistoryRecord = function ( self )
  6279.  
  6280. if not self.State.HistoryRecord then
  6281. return;
  6282. end;
  6283.  
  6284. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  6285. if Item then
  6286. self.State.HistoryRecord.terminal_colors[Item] = Item.BrickColor;
  6287. end;
  6288. end;
  6289. History:add( self.State.HistoryRecord );
  6290. self.State.HistoryRecord = nil;
  6291.  
  6292. end;
  6293.  
  6294. Tools.Paint.Listeners.Button1Up = function ()
  6295.  
  6296. local self = Tools.Paint;
  6297.  
  6298. -- Make sure that they clicked on one of the items in their selection
  6299. -- (and they weren't multi-selecting)
  6300. if Selection:find( Mouse.Target ) and not selecting and not selecting then
  6301.  
  6302. override_selection = true;
  6303.  
  6304. self:startHistoryRecord();
  6305.  
  6306. -- Paint all of the selected items `Tools.Paint.Options.Color`
  6307. if self.Options.Color then
  6308. for _, Item in pairs( Selection.Items ) do
  6309. Item.BrickColor = self.Options.Color;
  6310. end;
  6311. end;
  6312.  
  6313. self:finishHistoryRecord();
  6314.  
  6315. end;
  6316.  
  6317. end;
  6318.  
  6319. Tools.Paint.changeColor = function ( self, Color )
  6320.  
  6321. -- Alright so if `Color` is given, set that as the preferred color
  6322. if Color then
  6323.  
  6324. -- First of all, change the color option itself
  6325. self.Options.Color = Color;
  6326.  
  6327. self:startHistoryRecord();
  6328.  
  6329. -- Then, we want to update the color of any items in the selection
  6330. for _, Item in pairs( Selection.Items ) do
  6331. Item.BrickColor = Color;
  6332. end;
  6333.  
  6334. self:finishHistoryRecord();
  6335.  
  6336. -- After that, we want to mark our new color in the palette
  6337. if self.GUI then
  6338.  
  6339. -- First clear out any other marks
  6340. for _, ColorSquare in pairs( self.GUI.Palette:GetChildren() ) do
  6341. ColorSquare.Text = "";
  6342. end;
  6343.  
  6344. -- Then mark the right square
  6345. self.GUI.Palette[Color.Name].Text = "X";
  6346.  
  6347. end;
  6348.  
  6349. -- Otherwise, let's assume no color at all
  6350. else
  6351.  
  6352. -- Set the preferred color to none
  6353. self.Options.Color = nil;
  6354.  
  6355. -- Clear out any color option marks on any of the squares
  6356. if self.GUI then
  6357. for _, ColorSquare in pairs( self.GUI.Palette:GetChildren() ) do
  6358. ColorSquare.Text = "";
  6359. end;
  6360. end;
  6361.  
  6362. end;
  6363.  
  6364. end;
  6365.  
  6366. Tools.Paint.showGUI = function ( self )
  6367.  
  6368. -- Initialize the GUI if it's not ready yet
  6369. if not self.GUI then
  6370.  
  6371. local Container = Tool.Interfaces:WaitForChild( "BTPaintToolGUI" ):Clone();
  6372. Container.Parent = UI;
  6373.  
  6374. for _, ColorButton in pairs( Container.Palette:GetChildren() ) do
  6375. ColorButton.MouseButton1Click:connect( function ()
  6376. self:changeColor( BrickColor.new( ColorButton.Name ) );
  6377. end );
  6378. end;
  6379.  
  6380. self.GUI = Container;
  6381. end;
  6382.  
  6383. -- Reveal the GUI
  6384. self.GUI.Visible = true;
  6385.  
  6386. end;
  6387.  
  6388. Tools.Paint.hideGUI = function ( self )
  6389.  
  6390. -- Hide the GUI if it exists
  6391. if self.GUI then
  6392. self.GUI.Visible = false;
  6393. end;
  6394.  
  6395. end;
  6396.  
  6397. Tools.Paint.Loaded = true;
  6398. end))
  6399. LocalScript5.Disabled = true
  6400. LocalScript6.Name = "BTSurfaceTool"
  6401. LocalScript6.Parent = LocalScript1
  6402. table.insert(cors,sandbox(LocalScript6,function()
  6403. -- Load the main tool's core environment when it's ready
  6404. repeat wait() until (
  6405. _G.BTCoreEnv and
  6406. _G.BTCoreEnv[script.Parent.Parent] and
  6407. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  6408. );
  6409. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  6410.  
  6411. ------------------------------------------
  6412. -- Surface tool
  6413. ------------------------------------------
  6414.  
  6415. -- Create the tool
  6416. Tools.Surface = {};
  6417.  
  6418. -- Define the tool's color
  6419. Tools.Surface.Color = BrickColor.new( "Bright violet" );
  6420.  
  6421. -- Keep a container for temporary connections
  6422. Tools.Surface.Connections = {};
  6423.  
  6424. -- Keep a container for state data
  6425. Tools.Surface.State = {
  6426. ["type"] = nil;
  6427. };
  6428.  
  6429. -- Maintain a container for options
  6430. Tools.Surface.Options = {
  6431. ["side"] = Enum.NormalId.Front;
  6432. };
  6433.  
  6434. -- Keep a container for platform event connections
  6435. Tools.Surface.Listeners = {};
  6436.  
  6437. -- Start adding functionality to the tool
  6438. Tools.Surface.Listeners.Equipped = function ()
  6439.  
  6440. local self = Tools.Surface;
  6441.  
  6442. -- Change the color of selection boxes temporarily
  6443. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  6444. SelectionBoxColor = self.Color;
  6445. updateSelectionBoxColor();
  6446.  
  6447. -- Reveal the GUI
  6448. self:showGUI();
  6449.  
  6450. -- Restore the side option
  6451. self:changeSurface( self.Options.side );
  6452.  
  6453. -- Update the GUI regularly
  6454. coroutine.wrap( function ()
  6455. updater_on = true;
  6456.  
  6457. -- Provide a function to stop the loop
  6458. self.Updater = function ()
  6459. updater_on = false;
  6460. end;
  6461.  
  6462. while wait( 0.1 ) and updater_on do
  6463.  
  6464. -- Make sure the tool's equipped
  6465. if CurrentTool == self then
  6466.  
  6467. -- Update the surface type of every item in the selection
  6468. local surface_type = nil;
  6469. for item_index, Item in pairs( Selection.Items ) do
  6470.  
  6471. -- Set the first values for the first item
  6472. if item_index == 1 then
  6473. surface_type = Item[self.Options.side.Name .. "Surface"];
  6474.  
  6475. -- Otherwise, compare them and set them to `nil` if they're not identical
  6476. else
  6477. if surface_type ~= Item[self.Options.side.Name .. "Surface"] then
  6478. surface_type = nil;
  6479. end;
  6480. end;
  6481.  
  6482. end;
  6483.  
  6484. self.State.type = surface_type;
  6485.  
  6486. -- Update the GUI if it's visible
  6487. if self.GUI and self.GUI.Visible then
  6488. self:updateGUI();
  6489. end;
  6490.  
  6491. end;
  6492.  
  6493. end;
  6494.  
  6495. end )();
  6496.  
  6497. end;
  6498.  
  6499. Tools.Surface.Listeners.Unequipped = function ()
  6500.  
  6501. local self = Tools.Surface;
  6502.  
  6503. -- Stop the GUI updating loop
  6504. self.Updater();
  6505. self.Updater = nil;
  6506.  
  6507. -- Hide the GUI
  6508. self:hideGUI();
  6509.  
  6510. -- Disconnect temporary connections
  6511. for connection_index, Connection in pairs( self.Connections ) do
  6512. Connection:disconnect();
  6513. self.Connections[connection_index] = nil;
  6514. end;
  6515.  
  6516. -- Restore the original color of selection boxes
  6517. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  6518. updateSelectionBoxColor();
  6519.  
  6520. end;
  6521.  
  6522. Tools.Surface.Listeners.Button2Down = function ()
  6523.  
  6524. local self = Tools.Surface;
  6525.  
  6526. -- Capture the camera rotation (for later use
  6527. -- in determining whether a surface was being
  6528. -- selected or the camera was being rotated
  6529. -- with the right mouse button)
  6530. local cr_x, cr_y, cr_z = Services.Workspace.CurrentCamera.CoordinateFrame:toEulerAnglesXYZ();
  6531. self.State.PreB2DownCameraRotation = Vector3.new( cr_x, cr_y, cr_z );
  6532.  
  6533. end;
  6534.  
  6535. Tools.Surface.Listeners.Button2Up = function ()
  6536.  
  6537. local self = Tools.Surface;
  6538.  
  6539. local cr_x, cr_y, cr_z = Services.Workspace.CurrentCamera.CoordinateFrame:toEulerAnglesXYZ();
  6540. local CameraRotation = Vector3.new( cr_x, cr_y, cr_z );
  6541.  
  6542. -- If a surface is selected
  6543. if Selection:find( Mouse.Target ) and self.State.PreB2DownCameraRotation == CameraRotation then
  6544. self:changeSurface( Mouse.TargetSurface );
  6545. end;
  6546.  
  6547. end;
  6548.  
  6549. Tools.Surface.startHistoryRecord = function ( self )
  6550.  
  6551. if self.State.HistoryRecord then
  6552. self.State.HistoryRecord = nil;
  6553. end;
  6554.  
  6555. -- Create a history record
  6556. self.State.HistoryRecord = {
  6557. targets = _cloneTable( Selection.Items );
  6558. target_surface = self.Options.side;
  6559. initial_surfaces = {};
  6560. terminal_surfaces = {};
  6561. unapply = function ( self )
  6562. Selection:clear();
  6563. for _, Target in pairs( self.targets ) do
  6564. if Target then
  6565. Target[self.target_surface.Name .. "Surface"] = self.initial_surfaces[Target];
  6566. Target:MakeJoints();
  6567. Selection:add( Target );
  6568. end;
  6569. end;
  6570. end;
  6571. apply = function ( self )
  6572. Selection:clear();
  6573. for _, Target in pairs( self.targets ) do
  6574. if Target then
  6575. Target[self.target_surface.Name .. "Surface"] = self.terminal_surfaces[Target];
  6576. Target:MakeJoints();
  6577. Selection:add( Target );
  6578. end;
  6579. end;
  6580. end;
  6581. };
  6582. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  6583. if Item then
  6584. self.State.HistoryRecord.initial_surfaces[Item] = Item[self.Options.side.Name .. "Surface"];
  6585. end;
  6586. end;
  6587.  
  6588. end;
  6589.  
  6590. Tools.Surface.finishHistoryRecord = function ( self )
  6591.  
  6592. if not self.State.HistoryRecord then
  6593. return;
  6594. end;
  6595.  
  6596. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  6597. if Item then
  6598. self.State.HistoryRecord.terminal_surfaces[Item] = Item[self.Options.side.Name .. "Surface"];
  6599. end;
  6600. end;
  6601. History:add( self.State.HistoryRecord );
  6602. self.State.HistoryRecord = nil;
  6603.  
  6604. end;
  6605.  
  6606. Tools.Surface.SpecialTypeNames = {
  6607. SmoothNoOutlines = "NO OUTLINE",
  6608. Inlet = "INLETS"
  6609. };
  6610.  
  6611. Tools.Surface.changeType = function ( self, surface_type )
  6612.  
  6613. self:startHistoryRecord();
  6614.  
  6615. -- Apply `surface_type` to all items in the selection
  6616. for _, Item in pairs( Selection.Items ) do
  6617. Item[self.Options.side.Name .. "Surface"] = surface_type;
  6618. Item:MakeJoints();
  6619. end;
  6620.  
  6621. self:finishHistoryRecord();
  6622.  
  6623. self.TypeDropdown:selectOption( self.SpecialTypeNames[surface_type.Name] or surface_type.Name:upper() );
  6624. if self.TypeDropdown.open then
  6625. self.TypeDropdown:toggle();
  6626. end;
  6627. end;
  6628.  
  6629. Tools.Surface.changeSurface = function ( self, surface )
  6630. self.Options.side = surface;
  6631. self.SideDropdown:selectOption( surface.Name:upper() );
  6632. if self.SideDropdown.open then
  6633. self.SideDropdown:toggle();
  6634. end;
  6635. end;
  6636.  
  6637. Tools.Surface.updateGUI = function ( self )
  6638.  
  6639. -- Make sure the GUI exists
  6640. if not self.GUI then
  6641. return;
  6642. end;
  6643.  
  6644. if #Selection.Items > 0 then
  6645. self.TypeDropdown:selectOption( self.State.type and ( self.SpecialTypeNames[self.State.type.Name] or self.State.type.Name:upper() ) or "*" );
  6646. else
  6647. self.TypeDropdown:selectOption( "" );
  6648. end;
  6649.  
  6650. end;
  6651.  
  6652. Tools.Surface.showGUI = function ( self )
  6653.  
  6654. -- Initialize the GUI if it's not ready yet
  6655. if not self.GUI then
  6656.  
  6657. local Container = Tool.Interfaces:WaitForChild( "BTSurfaceToolGUI" ):Clone();
  6658. Container.Parent = UI;
  6659.  
  6660. local SideDropdown = createDropdown();
  6661. self.SideDropdown = SideDropdown;
  6662. SideDropdown.Frame.Parent = Container.SideOption;
  6663. SideDropdown.Frame.Position = UDim2.new( 0, 30, 0, 0 );
  6664. SideDropdown.Frame.Size = UDim2.new( 0, 72, 0, 25 );
  6665.  
  6666. SideDropdown:addOption( "TOP" ).MouseButton1Up:connect( function ()
  6667. self:changeSurface( Enum.NormalId.Top );
  6668. end );
  6669. SideDropdown:addOption( "BOTTOM" ).MouseButton1Up:connect( function ()
  6670. self:changeSurface( Enum.NormalId.Bottom );
  6671. end );
  6672. SideDropdown:addOption( "FRONT" ).MouseButton1Up:connect( function ()
  6673. self:changeSurface( Enum.NormalId.Front );
  6674. end );
  6675. SideDropdown:addOption( "BACK" ).MouseButton1Up:connect( function ()
  6676. self:changeSurface( Enum.NormalId.Back );
  6677. end );
  6678. SideDropdown:addOption( "LEFT" ).MouseButton1Up:connect( function ()
  6679. self:changeSurface( Enum.NormalId.Left );
  6680. end );
  6681. SideDropdown:addOption( "RIGHT" ).MouseButton1Up:connect( function ()
  6682. self:changeSurface( Enum.NormalId.Right );
  6683. end );
  6684.  
  6685. local TypeDropdown = createDropdown();
  6686. self.TypeDropdown = TypeDropdown;
  6687. TypeDropdown.Frame.Parent = Container.TypeOption;
  6688. TypeDropdown.Frame.Position = UDim2.new( 0, 30, 0, 0 );
  6689. TypeDropdown.Frame.Size = UDim2.new( 0, 87, 0, 25 );
  6690.  
  6691. TypeDropdown:addOption( "STUDS" ).MouseButton1Up:connect( function ()
  6692. self:changeType( Enum.SurfaceType.Studs );
  6693. end );
  6694. TypeDropdown:addOption( "INLETS" ).MouseButton1Up:connect( function ()
  6695. self:changeType( Enum.SurfaceType.Inlet );
  6696. end );
  6697. TypeDropdown:addOption( "SMOOTH" ).MouseButton1Up:connect( function ()
  6698. self:changeType( Enum.SurfaceType.Smooth );
  6699. end );
  6700. TypeDropdown:addOption( "WELD" ).MouseButton1Up:connect( function ()
  6701. self:changeType( Enum.SurfaceType.Weld );
  6702. end );
  6703. TypeDropdown:addOption( "GLUE" ).MouseButton1Up:connect( function ()
  6704. self:changeType( Enum.SurfaceType.Glue );
  6705. end );
  6706. TypeDropdown:addOption( "UNIVERSAL" ).MouseButton1Up:connect( function ()
  6707. self:changeType( Enum.SurfaceType.Universal );
  6708. end );
  6709. TypeDropdown:addOption( "HINGE" ).MouseButton1Up:connect( function ()
  6710. self:changeType( Enum.SurfaceType.Hinge );
  6711. end );
  6712. TypeDropdown:addOption( "MOTOR" ).MouseButton1Up:connect( function ()
  6713. self:changeType( Enum.SurfaceType.Motor );
  6714. end );
  6715. TypeDropdown:addOption( "NO OUTLINE" ).MouseButton1Up:connect( function ()
  6716. self:changeType( Enum.SurfaceType.SmoothNoOutlines );
  6717. end );
  6718.  
  6719. self.GUI = Container;
  6720.  
  6721. end;
  6722.  
  6723. -- Reveal the GUI
  6724. self.GUI.Visible = true;
  6725.  
  6726. end;
  6727.  
  6728. Tools.Surface.hideGUI = function ( self )
  6729.  
  6730. -- Hide the GUI if it exists already
  6731. if self.GUI then
  6732. self.GUI.Visible = false;
  6733. end;
  6734.  
  6735. end;
  6736.  
  6737. Tools.Surface.Loaded = true;
  6738. end))
  6739. LocalScript6.Disabled = true
  6740. LocalScript7.Name = "BTMaterialTool"
  6741. LocalScript7.Parent = LocalScript1
  6742. table.insert(cors,sandbox(LocalScript7,function()
  6743. -- Load the main tool's core environment when it's ready
  6744. repeat wait() until (
  6745. _G.BTCoreEnv and
  6746. _G.BTCoreEnv[script.Parent.Parent] and
  6747. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  6748. );
  6749. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  6750.  
  6751. ------------------------------------------
  6752. -- Material tool
  6753. ------------------------------------------
  6754.  
  6755. -- Create the tool
  6756. Tools.Material = {};
  6757. Tools.Material.Color = BrickColor.new( "Bright violet" );
  6758. Tools.Material.Connections = {};
  6759. Tools.Material.State = {
  6760. ["material"] = nil;
  6761. ["reflectance_focused"] = false;
  6762. ["transparency_focused"] = false;
  6763. };
  6764. Tools.Material.Listeners = {};
  6765. Tools.Material.SpecialMaterialNames = {
  6766. CorrodedMetal = "CORRODED METAL",
  6767. DiamondPlate = "DIAMOND PLATE",
  6768. SmoothPlastic = "SMOOTH PLASTIC"
  6769. };
  6770.  
  6771. -- Start adding functionality to the tool
  6772. Tools.Material.Listeners.Equipped = function ()
  6773.  
  6774. local self = Tools.Material;
  6775.  
  6776. -- Change the color of selection boxes temporarily
  6777. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  6778. SelectionBoxColor = self.Color;
  6779. updateSelectionBoxColor();
  6780.  
  6781. -- Reveal the GUI
  6782. self:showGUI();
  6783.  
  6784. -- Update the GUI regularly
  6785. coroutine.wrap( function ()
  6786. updater_on = true;
  6787.  
  6788. -- Provide a function to stop the loop
  6789. self.Updater = function ()
  6790. updater_on = false;
  6791. end;
  6792.  
  6793. while wait( 0.1 ) and updater_on do
  6794.  
  6795. -- Make sure the tool's equipped
  6796. if CurrentTool == self then
  6797.  
  6798. -- Update the material type of every item in the selection
  6799. local material_type, transparency, reflectance = nil, nil, nil;
  6800. for item_index, Item in pairs( Selection.Items ) do
  6801.  
  6802. -- Set the first values for the first item
  6803. if item_index == 1 then
  6804. material_type = Item.Material;
  6805. transparency = Item.Transparency;
  6806. reflectance = Item.Reflectance;
  6807.  
  6808. -- Otherwise, compare them and set them to `nil` if they're not identical
  6809. else
  6810. if material_type ~= Item.Material then
  6811. material_type = nil;
  6812. end;
  6813. if reflectance ~= Item.Reflectance then
  6814. reflectance = nil;
  6815. end;
  6816. if transparency ~= Item.Transparency then
  6817. transparency = nil;
  6818. end;
  6819. end;
  6820.  
  6821. end;
  6822.  
  6823. self.State.material = material_type;
  6824. self.State.transparency = transparency;
  6825. self.State.reflectance = reflectance;
  6826.  
  6827. -- Update the GUI if it's visible
  6828. if self.GUI and self.GUI.Visible then
  6829. self:updateGUI();
  6830. end;
  6831.  
  6832. end;
  6833.  
  6834. end;
  6835.  
  6836. end )();
  6837.  
  6838. end;
  6839.  
  6840. Tools.Material.Listeners.Unequipped = function ()
  6841.  
  6842. local self = Tools.Material;
  6843.  
  6844. -- Stop the GUI updating loop
  6845. self.Updater();
  6846. self.Updater = nil;
  6847.  
  6848. -- Hide the GUI
  6849. self:hideGUI();
  6850.  
  6851. -- Disconnect temporary connections
  6852. for connection_index, Connection in pairs( self.Connections ) do
  6853. Connection:disconnect();
  6854. self.Connections[connection_index] = nil;
  6855. end;
  6856.  
  6857. -- Restore the original color of selection boxes
  6858. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  6859. updateSelectionBoxColor();
  6860.  
  6861. end;
  6862.  
  6863. Tools.Material.startHistoryRecord = function ( self )
  6864.  
  6865. if self.State.HistoryRecord then
  6866. self.State.HistoryRecord = nil;
  6867. end;
  6868.  
  6869. -- Create a history record
  6870. self.State.HistoryRecord = {
  6871. targets = _cloneTable( Selection.Items );
  6872. initial_material = {};
  6873. terminal_material = {};
  6874. initial_transparency = {};
  6875. terminal_transparency = {};
  6876. initial_reflectance = {};
  6877. terminal_reflectance = {};
  6878. unapply = function ( self )
  6879. Selection:clear();
  6880. for _, Target in pairs( self.targets ) do
  6881. if Target then
  6882. Target.Material = self.initial_material[Target];
  6883. Target.Transparency = self.initial_transparency[Target];
  6884. Target.Reflectance = self.initial_reflectance[Target];
  6885. Selection:add( Target );
  6886. end;
  6887. end;
  6888. end;
  6889. apply = function ( self )
  6890. Selection:clear();
  6891. for _, Target in pairs( self.targets ) do
  6892. if Target then
  6893. Target.Material = self.terminal_material[Target];
  6894. Target.Transparency = self.terminal_transparency[Target];
  6895. Target.Reflectance = self.terminal_reflectance[Target];
  6896. Selection:add( Target );
  6897. end;
  6898. end;
  6899. end;
  6900. };
  6901. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  6902. if Item then
  6903. self.State.HistoryRecord.initial_material[Item] = Item.Material;
  6904. self.State.HistoryRecord.initial_transparency[Item] = Item.Transparency;
  6905. self.State.HistoryRecord.initial_reflectance[Item] = Item.Reflectance;
  6906. end;
  6907. end;
  6908.  
  6909. end;
  6910.  
  6911. Tools.Material.finishHistoryRecord = function ( self )
  6912.  
  6913. if not self.State.HistoryRecord then
  6914. return;
  6915. end;
  6916.  
  6917. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  6918. if Item then
  6919. self.State.HistoryRecord.terminal_material[Item] = Item.Material;
  6920. self.State.HistoryRecord.terminal_transparency[Item] = Item.Transparency;
  6921. self.State.HistoryRecord.terminal_reflectance[Item] = Item.Reflectance;
  6922. end;
  6923. end;
  6924. History:add( self.State.HistoryRecord );
  6925. self.State.HistoryRecord = nil;
  6926.  
  6927. end;
  6928.  
  6929. Tools.Material.changeMaterial = function ( self, material_type )
  6930.  
  6931. self:startHistoryRecord();
  6932.  
  6933. -- Apply `material_type` to all items in the selection
  6934. for _, Item in pairs( Selection.Items ) do
  6935. Item.Material = material_type;
  6936. end;
  6937.  
  6938. self:finishHistoryRecord();
  6939.  
  6940. if self.MaterialDropdown.open then
  6941. self.MaterialDropdown:toggle();
  6942. end;
  6943. end;
  6944.  
  6945. Tools.Material.changeTransparency = function ( self, transparency )
  6946.  
  6947. self:startHistoryRecord();
  6948.  
  6949. -- Apply `transparency` to all items in the selection
  6950. for _, Item in pairs( Selection.Items ) do
  6951. Item.Transparency = transparency;
  6952. end;
  6953.  
  6954. self:finishHistoryRecord();
  6955.  
  6956. end;
  6957.  
  6958. Tools.Material.changeReflectance = function ( self, reflectance )
  6959.  
  6960. self:startHistoryRecord();
  6961.  
  6962. -- Apply `reflectance` to all items in the selection
  6963. for _, Item in pairs( Selection.Items ) do
  6964. Item.Reflectance = reflectance;
  6965. end;
  6966.  
  6967. self:finishHistoryRecord();
  6968.  
  6969. end;
  6970.  
  6971. Tools.Material.updateGUI = function ( self )
  6972.  
  6973. -- Make sure the GUI exists
  6974. if not self.GUI then
  6975. return;
  6976. end;
  6977.  
  6978. if #Selection.Items > 0 then
  6979. self.GUI.Size = UDim2.new( 0, 200, 0, 145 );
  6980. self.GUI.MaterialOption.Visible = true;
  6981. self.GUI.ReflectanceOption.Visible = true;
  6982. self.GUI.TransparencyOption.Visible = true;
  6983. self.GUI.SelectNote.Visible = false;
  6984. self.MaterialDropdown:selectOption( self.State.material and ( self.SpecialMaterialNames[self.State.material.Name] or self.State.material.Name:upper() ) or "*" );
  6985.  
  6986. -- Update the text inputs without interrupting the user
  6987. if not self.State.transparency_focused then
  6988. self.GUI.TransparencyOption.TransparencyInput.TextBox.Text = self.State.transparency and tostring( _round( self.State.transparency, 2 ) ) or "*";
  6989. end;
  6990. if not self.State.reflectance_focused then
  6991. self.GUI.ReflectanceOption.ReflectanceInput.TextBox.Text = self.State.reflectance and tostring( _round( self.State.reflectance, 2 ) ) or "*";
  6992. end;
  6993.  
  6994. else
  6995. self.GUI.Size = UDim2.new( 0, 200, 0, 62 );
  6996. self.GUI.MaterialOption.Visible = false;
  6997. self.GUI.ReflectanceOption.Visible = false;
  6998. self.GUI.TransparencyOption.Visible = false;
  6999. self.GUI.SelectNote.Visible = true;
  7000. self.MaterialDropdown:selectOption( "" );
  7001. self.GUI.TransparencyOption.TransparencyInput.TextBox.Text = "";
  7002. self.GUI.ReflectanceOption.ReflectanceInput.TextBox.Text = "";
  7003. end;
  7004.  
  7005. end;
  7006.  
  7007.  
  7008. Tools.Material.showGUI = function ( self )
  7009.  
  7010. -- Initialize the GUI if it's not ready yet
  7011. if not self.GUI then
  7012.  
  7013. local Container = Tool.Interfaces:WaitForChild( "BTMaterialToolGUI" ):Clone();
  7014. Container.Parent = UI;
  7015.  
  7016. local MaterialDropdown = createDropdown();
  7017. self.MaterialDropdown = MaterialDropdown;
  7018. MaterialDropdown.Frame.Parent = Container.MaterialOption;
  7019. MaterialDropdown.Frame.Position = UDim2.new( 0, 50, 0, 0 );
  7020. MaterialDropdown.Frame.Size = UDim2.new( 0, 130, 0, 25 );
  7021.  
  7022. MaterialDropdown:addOption( "SMOOTH PLASTIC" ).MouseButton1Up:connect( function ()
  7023. self:changeMaterial( Enum.Material.SmoothPlastic );
  7024. end );
  7025. MaterialDropdown:addOption( "PLASTIC" ).MouseButton1Up:connect( function ()
  7026. self:changeMaterial( Enum.Material.Plastic );
  7027. end );
  7028. MaterialDropdown:addOption( "CONCRETE" ).MouseButton1Up:connect( function ()
  7029. self:changeMaterial( Enum.Material.Concrete );
  7030. end );
  7031. MaterialDropdown:addOption( "DIAMOND PLATE" ).MouseButton1Up:connect( function ()
  7032. self:changeMaterial( Enum.Material.DiamondPlate );
  7033. end );
  7034. MaterialDropdown:addOption( "CORRODED METAL" ).MouseButton1Up:connect( function ()
  7035. self:changeMaterial( Enum.Material.CorrodedMetal );
  7036. end );
  7037. MaterialDropdown:addOption( "BRICK" ).MouseButton1Up:connect( function ()
  7038. self:changeMaterial( Enum.Material.Brick );
  7039. end );
  7040. MaterialDropdown:addOption( "FABRIC" ).MouseButton1Up:connect( function ()
  7041. self:changeMaterial( Enum.Material.Fabric );
  7042. end );
  7043. MaterialDropdown:addOption( "FOIL" ).MouseButton1Up:connect( function ()
  7044. self:changeMaterial( Enum.Material.Foil );
  7045. end );
  7046. MaterialDropdown:addOption( "GRANITE" ).MouseButton1Up:connect( function ()
  7047. self:changeMaterial( Enum.Material.Granite );
  7048. end );
  7049. MaterialDropdown:addOption( "GRASS" ).MouseButton1Up:connect( function ()
  7050. self:changeMaterial( Enum.Material.Grass );
  7051. end );
  7052. MaterialDropdown:addOption( "ICE" ).MouseButton1Up:connect( function ()
  7053. self:changeMaterial( Enum.Material.Ice );
  7054. end );
  7055. MaterialDropdown:addOption( "MARBLE" ).MouseButton1Up:connect( function ()
  7056. self:changeMaterial( Enum.Material.Marble );
  7057. end );
  7058. MaterialDropdown:addOption( "PEBBLE" ).MouseButton1Up:connect( function ()
  7059. self:changeMaterial( Enum.Material.Pebble );
  7060. end );
  7061. MaterialDropdown:addOption( "SAND" ).MouseButton1Up:connect( function ()
  7062. self:changeMaterial( Enum.Material.Sand );
  7063. end );
  7064. MaterialDropdown:addOption( "SLATE" ).MouseButton1Up:connect( function ()
  7065. self:changeMaterial( Enum.Material.Slate );
  7066. end );
  7067. MaterialDropdown:addOption( "WOOD" ).MouseButton1Up:connect( function ()
  7068. self:changeMaterial( Enum.Material.Wood );
  7069. end );
  7070.  
  7071. -- Capture focus of the input when clicked
  7072. -- (so we can detect when it is focused-on)
  7073. Container.TransparencyOption.TransparencyInput.TextButton.MouseButton1Down:connect( function ()
  7074. self.State.transparency_focused = true;
  7075. Container.TransparencyOption.TransparencyInput.TextBox:CaptureFocus();
  7076. end );
  7077.  
  7078. -- Change the transparency when the value of the textbox is updated
  7079. Container.TransparencyOption.TransparencyInput.TextBox.FocusLost:connect( function ( enter_pressed )
  7080. local potential_new = tonumber( Container.TransparencyOption.TransparencyInput.TextBox.Text );
  7081. if potential_new then
  7082. if potential_new > 1 then
  7083. potential_new = 1;
  7084. elseif potential_new < 0 then
  7085. potential_new = 0;
  7086. end;
  7087. self:changeTransparency( potential_new );
  7088. end;
  7089. self.State.transparency_focused = false;
  7090. end );
  7091.  
  7092. -- Capture focus of the input when clicked
  7093. -- (so we can detect when it is focused-on)
  7094. Container.ReflectanceOption.ReflectanceInput.TextButton.MouseButton1Down:connect( function ()
  7095. self.State.reflectance_focused = true;
  7096. Container.ReflectanceOption.ReflectanceInput.TextBox:CaptureFocus();
  7097. end );
  7098.  
  7099. -- Change the reflectance when the value of the textbox is updated
  7100. Container.ReflectanceOption.ReflectanceInput.TextBox.FocusLost:connect( function ( enter_pressed )
  7101. local potential_new = tonumber( Container.ReflectanceOption.ReflectanceInput.TextBox.Text );
  7102. if potential_new then
  7103. if potential_new > 1 then
  7104. potential_new = 1;
  7105. elseif potential_new < 0 then
  7106. potential_new = 0;
  7107. end;
  7108. self:changeReflectance( potential_new );
  7109. end;
  7110. self.State.reflectance_focused = false;
  7111. end );
  7112.  
  7113. self.GUI = Container;
  7114.  
  7115. end;
  7116.  
  7117. -- Reveal the GUI
  7118. self.GUI.Visible = true;
  7119.  
  7120. end;
  7121.  
  7122. Tools.Material.hideGUI = function ( self )
  7123.  
  7124. -- Hide the GUI if it exists already
  7125. if self.GUI then
  7126. self.GUI.Visible = false;
  7127. end;
  7128.  
  7129. end;
  7130.  
  7131. Tools.Material.Loaded = true;
  7132. end))
  7133. LocalScript7.Disabled = true
  7134. LocalScript8.Name = "BTAnchorTool"
  7135. LocalScript8.Parent = LocalScript1
  7136. table.insert(cors,sandbox(LocalScript8,function()
  7137. -- Load the main tool's core environment when it's ready
  7138. repeat wait() until (
  7139. _G.BTCoreEnv and
  7140. _G.BTCoreEnv[script.Parent.Parent] and
  7141. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  7142. );
  7143. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  7144.  
  7145. ------------------------------------------
  7146. -- Anchor tool
  7147. ------------------------------------------
  7148.  
  7149. -- Create the tool
  7150. Tools.Anchor = {};
  7151.  
  7152. -- Create structures to hold data that the tool needs
  7153. Tools.Anchor.Connections = {};
  7154.  
  7155. Tools.Anchor.State = {
  7156. ["anchored"] = nil;
  7157. };
  7158.  
  7159. Tools.Anchor.Listeners = {};
  7160.  
  7161. -- Define the color of the tool
  7162. Tools.Anchor.Color = BrickColor.new( "Really black" );
  7163.  
  7164. -- Start adding functionality to the tool
  7165. Tools.Anchor.Listeners.Equipped = function ()
  7166.  
  7167. local self = Tools.Anchor;
  7168.  
  7169. -- Change the color of selection boxes temporarily
  7170. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  7171. SelectionBoxColor = self.Color;
  7172. updateSelectionBoxColor();
  7173.  
  7174. -- Reveal the GUI
  7175. self:showGUI();
  7176.  
  7177. -- Update the GUI regularly
  7178. coroutine.wrap( function ()
  7179. updater_on = true;
  7180.  
  7181. -- Provide a function to stop the loop
  7182. self.Updater = function ()
  7183. updater_on = false;
  7184. end;
  7185.  
  7186. while wait( 0.1 ) and updater_on do
  7187.  
  7188. -- Make sure the tool's equipped
  7189. if CurrentTool == self then
  7190.  
  7191. -- Update the anchor status of every item in the selection
  7192. local anchor_status = nil;
  7193. for item_index, Item in pairs( Selection.Items ) do
  7194.  
  7195. -- Set the first values for the first item
  7196. if item_index == 1 then
  7197. anchor_status = Item.Anchored;
  7198.  
  7199. -- Otherwise, compare them and set them to `nil` if they're not identical
  7200. else
  7201. if anchor_status ~= Item.Anchored then
  7202. anchor_status = nil;
  7203. end;
  7204. end;
  7205.  
  7206. end;
  7207.  
  7208. self.State.anchored = anchor_status;
  7209.  
  7210. -- Update the GUI if it's visible
  7211. if self.GUI and self.GUI.Visible then
  7212. self:updateGUI();
  7213. end;
  7214.  
  7215. end;
  7216.  
  7217. end;
  7218.  
  7219. end )();
  7220.  
  7221. -- Listen for the Enter button to be pressed to toggle the anchor
  7222. self.Connections.EnterButtonListener = Mouse.KeyDown:connect( function ( key )
  7223.  
  7224. local key = key:lower();
  7225. local key_code = key:byte();
  7226.  
  7227. -- If the Enter button is pressed
  7228. if key_code == 13 then
  7229.  
  7230. if self.State.anchored == true then
  7231. self:unanchor();
  7232.  
  7233. elseif self.State.anchored == false then
  7234. self:anchor();
  7235.  
  7236. elseif self.State.anchored == nil then
  7237. self:anchor();
  7238.  
  7239. end;
  7240.  
  7241. end;
  7242.  
  7243. end );
  7244.  
  7245. end;
  7246.  
  7247.  
  7248. Tools.Anchor.startHistoryRecord = function ( self )
  7249.  
  7250. if self.State.HistoryRecord then
  7251. self.State.HistoryRecord = nil;
  7252. end;
  7253.  
  7254. -- Create a history record
  7255. self.State.HistoryRecord = {
  7256. targets = _cloneTable( Selection.Items );
  7257. initial_positions = {};
  7258. terminal_positions = {};
  7259. initial_anchors = {};
  7260. terminal_anchors = {};
  7261. unapply = function ( self )
  7262. Selection:clear();
  7263. for _, Target in pairs( self.targets ) do
  7264. if Target then
  7265. Target.RotVelocity = Vector3.new( 0, 0, 0 );
  7266. Target.Velocity = Vector3.new( 0, 0, 0 );
  7267. Target.CFrame = self.initial_positions[Target];
  7268. Target.Anchored = self.initial_anchors[Target];
  7269. Target:MakeJoints();
  7270. Selection:add( Target );
  7271. end;
  7272. end;
  7273. end;
  7274. apply = function ( self )
  7275. Selection:clear();
  7276. for _, Target in pairs( self.targets ) do
  7277. if Target then
  7278. Target.RotVelocity = Vector3.new( 0, 0, 0 );
  7279. Target.Velocity = Vector3.new( 0, 0, 0 );
  7280. Target.CFrame = self.terminal_positions[Target];
  7281. Target.Anchored = self.terminal_anchors[Target];
  7282. Target:MakeJoints();
  7283. Selection:add( Target );
  7284. end;
  7285. end;
  7286. end;
  7287. };
  7288. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  7289. if Item then
  7290. self.State.HistoryRecord.initial_anchors[Item] = Item.Anchored;
  7291. self.State.HistoryRecord.initial_positions[Item] = Item.CFrame;
  7292. end;
  7293. end;
  7294.  
  7295. end;
  7296.  
  7297. Tools.Anchor.finishHistoryRecord = function ( self )
  7298.  
  7299. if not self.State.HistoryRecord then
  7300. return;
  7301. end;
  7302.  
  7303. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  7304. if Item then
  7305. self.State.HistoryRecord.terminal_anchors[Item] = Item.Anchored;
  7306. self.State.HistoryRecord.terminal_positions[Item] = Item.CFrame;
  7307. end;
  7308. end;
  7309. History:add( self.State.HistoryRecord );
  7310. self.State.HistoryRecord = nil;
  7311.  
  7312. end;
  7313.  
  7314. Tools.Anchor.anchor = function ( self )
  7315.  
  7316. self:startHistoryRecord();
  7317.  
  7318. -- Anchor all the items in the selection
  7319. for _, Item in pairs( Selection.Items ) do
  7320. Item.Anchored = true;
  7321. Item:MakeJoints();
  7322. end;
  7323.  
  7324. self:finishHistoryRecord();
  7325.  
  7326. end;
  7327.  
  7328. Tools.Anchor.unanchor = function ( self )
  7329.  
  7330. self:startHistoryRecord();
  7331.  
  7332. -- Unanchor all the items in the selection
  7333. for _, Item in pairs( Selection.Items ) do
  7334. Item.Anchored = false;
  7335. Item.Velocity = Vector3.new( 0, 0, 0 );
  7336. Item.RotVelocity = Vector3.new( 0, 0, 0 );
  7337. Item:MakeJoints();
  7338. end;
  7339.  
  7340. self:finishHistoryRecord();
  7341.  
  7342. end;
  7343.  
  7344. Tools.Anchor.showGUI = function ( self )
  7345.  
  7346. -- Initialize the GUI if it's not ready yet
  7347. if not self.GUI then
  7348.  
  7349. local Container = Tool.Interfaces:WaitForChild( "BTAnchorToolGUI" ):Clone();
  7350. Container.Parent = UI;
  7351.  
  7352. -- Change the anchor status when the button is clicked
  7353. Container.Status.Anchored.Button.MouseButton1Down:connect( function ()
  7354. self:anchor();
  7355. end );
  7356.  
  7357. Container.Status.Unanchored.Button.MouseButton1Down:connect( function ()
  7358. self:unanchor();
  7359. end );
  7360.  
  7361. self.GUI = Container;
  7362. end;
  7363.  
  7364. -- Reveal the GUI
  7365. self.GUI.Visible = true;
  7366.  
  7367. end;
  7368.  
  7369. Tools.Anchor.updateGUI = function ( self )
  7370.  
  7371. -- Make sure the GUI exists
  7372. if not self.GUI then
  7373. return;
  7374. end;
  7375.  
  7376. local GUI = self.GUI;
  7377.  
  7378. if self.State.anchored == nil then
  7379. GUI.Status.Anchored.Background.Image = light_slanted_rectangle;
  7380. GUI.Status.Anchored.SelectedIndicator.BackgroundTransparency = 1;
  7381. GUI.Status.Unanchored.Background.Image = light_slanted_rectangle;
  7382. GUI.Status.Unanchored.SelectedIndicator.BackgroundTransparency = 1;
  7383.  
  7384. elseif self.State.anchored == true then
  7385. GUI.Status.Anchored.Background.Image = dark_slanted_rectangle;
  7386. GUI.Status.Anchored.SelectedIndicator.BackgroundTransparency = 0;
  7387. GUI.Status.Unanchored.Background.Image = light_slanted_rectangle;
  7388. GUI.Status.Unanchored.SelectedIndicator.BackgroundTransparency = 1;
  7389.  
  7390. elseif self.State.anchored == false then
  7391. GUI.Status.Anchored.Background.Image = light_slanted_rectangle;
  7392. GUI.Status.Anchored.SelectedIndicator.BackgroundTransparency = 1;
  7393. GUI.Status.Unanchored.Background.Image = dark_slanted_rectangle;
  7394. GUI.Status.Unanchored.SelectedIndicator.BackgroundTransparency = 0;
  7395.  
  7396. end;
  7397.  
  7398. end;
  7399.  
  7400. Tools.Anchor.hideGUI = function ( self )
  7401.  
  7402. -- Hide the GUI if it exists
  7403. if self.GUI then
  7404. self.GUI.Visible = false;
  7405. end;
  7406.  
  7407. end;
  7408.  
  7409. Tools.Anchor.Listeners.Unequipped = function ()
  7410.  
  7411. local self = Tools.Anchor;
  7412.  
  7413. -- Stop the update loop
  7414. if self.Updater then
  7415. self.Updater();
  7416. self.Updater = nil;
  7417. end;
  7418.  
  7419. -- Hide the GUI
  7420. self:hideGUI();
  7421.  
  7422. -- Clear out any temporary connections
  7423. for connection_index, Connection in pairs( self.Connections ) do
  7424. Connection:disconnect();
  7425. self.Connections[connection_index] = nil;
  7426. end;
  7427.  
  7428. -- Restore the original color of the selection boxes
  7429. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  7430. updateSelectionBoxColor();
  7431.  
  7432. end;
  7433.  
  7434. Tools.Anchor.Loaded = true;
  7435. end))
  7436. LocalScript8.Disabled = true
  7437. LocalScript9.Name = "BTCollisionTool"
  7438. LocalScript9.Parent = LocalScript1
  7439. table.insert(cors,sandbox(LocalScript9,function()
  7440. -- Load the main tool's core environment when it's ready
  7441. repeat wait() until (
  7442. _G.BTCoreEnv and
  7443. _G.BTCoreEnv[script.Parent.Parent] and
  7444. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  7445. );
  7446. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  7447.  
  7448. ------------------------------------------
  7449. -- Collision tool
  7450. ------------------------------------------
  7451.  
  7452. -- Create the tool
  7453. Tools.Collision = {};
  7454.  
  7455. -- Create structures to hold data that the tool needs
  7456. Tools.Collision.Connections = {};
  7457.  
  7458. Tools.Collision.State = {
  7459. ["colliding"] = nil;
  7460. };
  7461.  
  7462. Tools.Collision.Listeners = {};
  7463.  
  7464. -- Define the color of the tool
  7465. Tools.Collision.Color = BrickColor.new( "Really black" );
  7466.  
  7467. -- Start adding functionality to the tool
  7468. Tools.Collision.Listeners.Equipped = function ()
  7469.  
  7470. local self = Tools.Collision;
  7471.  
  7472. -- Change the color of selection boxes temporarily
  7473. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  7474. SelectionBoxColor = self.Color;
  7475. updateSelectionBoxColor();
  7476.  
  7477. -- Reveal the GUI
  7478. self:showGUI();
  7479.  
  7480. -- Update the GUI regularly
  7481. coroutine.wrap( function ()
  7482. updater_on = true;
  7483.  
  7484. -- Provide a function to stop the loop
  7485. self.Updater = function ()
  7486. updater_on = false;
  7487. end;
  7488.  
  7489. while wait( 0.1 ) and updater_on do
  7490.  
  7491. -- Make sure the tool's equipped
  7492. if CurrentTool == self then
  7493.  
  7494. -- Update the collision status of every item in the selection
  7495. local colliding = nil;
  7496. for item_index, Item in pairs( Selection.Items ) do
  7497.  
  7498. -- Set the first values for the first item
  7499. if item_index == 1 then
  7500. colliding = Item.CanCollide;
  7501.  
  7502. -- Otherwise, compare them and set them to `nil` if they're not identical
  7503. else
  7504. if colliding ~= Item.CanCollide then
  7505. colliding = nil;
  7506. end;
  7507. end;
  7508.  
  7509. end;
  7510.  
  7511. self.State.colliding = colliding;
  7512.  
  7513. -- Update the GUI if it's visible
  7514. if self.GUI and self.GUI.Visible then
  7515. self:updateGUI();
  7516. end;
  7517.  
  7518. end;
  7519.  
  7520. end;
  7521.  
  7522. end )();
  7523.  
  7524. -- Listen for the Enter button to be pressed to toggle collision
  7525. self.Connections.EnterButtonListener = Mouse.KeyDown:connect( function ( key )
  7526.  
  7527. local key = key:lower();
  7528. local key_code = key:byte();
  7529.  
  7530. -- If the Enter button is pressed
  7531. if key_code == 13 then
  7532.  
  7533. if self.State.colliding == true then
  7534. self:disable();
  7535.  
  7536. elseif self.State.colliding == false then
  7537. self:enable();
  7538.  
  7539. elseif self.State.colliding == nil then
  7540. self:enable();
  7541.  
  7542. end;
  7543.  
  7544. end;
  7545.  
  7546. end );
  7547.  
  7548. end;
  7549.  
  7550. Tools.Collision.startHistoryRecord = function ( self )
  7551.  
  7552. if self.State.HistoryRecord then
  7553. self.State.HistoryRecord = nil;
  7554. end;
  7555.  
  7556. -- Create a history record
  7557. self.State.HistoryRecord = {
  7558. targets = _cloneTable( Selection.Items );
  7559. initial_collide = {};
  7560. terminal_collide = {};
  7561. initial_cframe = {};
  7562. terminal_cframe = {};
  7563. unapply = function ( self )
  7564. Selection:clear();
  7565. for _, Target in pairs( self.targets ) do
  7566. if Target then
  7567. Target.CanCollide = self.initial_collide[Target];
  7568. Target.CFrame = self.initial_cframe[Target];
  7569. Target:MakeJoints();
  7570. Selection:add( Target );
  7571. end;
  7572. end;
  7573. end;
  7574. apply = function ( self )
  7575. Selection:clear();
  7576. for _, Target in pairs( self.targets ) do
  7577. if Target then
  7578. Target.CanCollide = self.terminal_collide[Target];
  7579. Target.CFrame = self.terminal_cframe[Target];
  7580. Target:MakeJoints();
  7581. Selection:add( Target );
  7582. end;
  7583. end;
  7584. end;
  7585. };
  7586. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  7587. if Item then
  7588. self.State.HistoryRecord.initial_collide[Item] = Item.CanCollide;
  7589. self.State.HistoryRecord.initial_cframe[Item] = Item.CFrame;
  7590. end;
  7591. end;
  7592.  
  7593. end;
  7594.  
  7595. Tools.Collision.finishHistoryRecord = function ( self )
  7596.  
  7597. if not self.State.HistoryRecord then
  7598. return;
  7599. end;
  7600.  
  7601. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  7602. if Item then
  7603. self.State.HistoryRecord.terminal_collide[Item] = Item.CanCollide;
  7604. self.State.HistoryRecord.terminal_cframe[Item] = Item.CFrame;
  7605. end;
  7606. end;
  7607. History:add( self.State.HistoryRecord );
  7608. self.State.HistoryRecord = nil;
  7609.  
  7610. end;
  7611.  
  7612. Tools.Collision.enable = function ( self )
  7613.  
  7614. self:startHistoryRecord();
  7615.  
  7616. -- Enable collision for all the items in the selection
  7617. for _, Item in pairs( Selection.Items ) do
  7618. Item.CanCollide = true;
  7619. Item:MakeJoints();
  7620. end;
  7621.  
  7622. self:finishHistoryRecord();
  7623.  
  7624. end;
  7625.  
  7626. Tools.Collision.disable = function ( self )
  7627.  
  7628. self:startHistoryRecord();
  7629.  
  7630. -- Disable collision for all the items in the selection
  7631. for _, Item in pairs( Selection.Items ) do
  7632. Item.CanCollide = false;
  7633. Item:MakeJoints();
  7634. end;
  7635.  
  7636. self:finishHistoryRecord();
  7637.  
  7638. end;
  7639.  
  7640. Tools.Collision.showGUI = function ( self )
  7641.  
  7642. -- Initialize the GUI if it's not ready yet
  7643. if not self.GUI then
  7644.  
  7645. local Container = Tool.Interfaces:WaitForChild( "BTCollisionToolGUI" ):Clone();
  7646. Container.Parent = UI;
  7647.  
  7648. Container.Status.On.Button.MouseButton1Down:connect( function ()
  7649. self:enable();
  7650. end );
  7651.  
  7652. Container.Status.Off.Button.MouseButton1Down:connect( function ()
  7653. self:disable();
  7654. end );
  7655.  
  7656. self.GUI = Container;
  7657. end;
  7658.  
  7659. -- Reveal the GUI
  7660. self.GUI.Visible = true;
  7661.  
  7662. end;
  7663.  
  7664. Tools.Collision.updateGUI = function ( self )
  7665.  
  7666. -- Make sure the GUI exists
  7667. if not self.GUI then
  7668. return;
  7669. end;
  7670.  
  7671. local GUI = self.GUI;
  7672.  
  7673. if self.State.colliding == nil then
  7674. GUI.Status.On.Background.Image = light_slanted_rectangle;
  7675. GUI.Status.On.SelectedIndicator.BackgroundTransparency = 1;
  7676. GUI.Status.Off.Background.Image = light_slanted_rectangle;
  7677. GUI.Status.Off.SelectedIndicator.BackgroundTransparency = 1;
  7678.  
  7679. elseif self.State.colliding == true then
  7680. GUI.Status.On.Background.Image = dark_slanted_rectangle;
  7681. GUI.Status.On.SelectedIndicator.BackgroundTransparency = 0;
  7682. GUI.Status.Off.Background.Image = light_slanted_rectangle;
  7683. GUI.Status.Off.SelectedIndicator.BackgroundTransparency = 1;
  7684.  
  7685. elseif self.State.colliding == false then
  7686. GUI.Status.On.Background.Image = light_slanted_rectangle;
  7687. GUI.Status.On.SelectedIndicator.BackgroundTransparency = 1;
  7688. GUI.Status.Off.Background.Image = dark_slanted_rectangle;
  7689. GUI.Status.Off.SelectedIndicator.BackgroundTransparency = 0;
  7690.  
  7691. end;
  7692.  
  7693. end;
  7694.  
  7695. Tools.Collision.hideGUI = function ( self )
  7696.  
  7697. -- Hide the GUI if it exists
  7698. if self.GUI then
  7699. self.GUI.Visible = false;
  7700. end;
  7701.  
  7702. end;
  7703.  
  7704. Tools.Collision.Listeners.Unequipped = function ()
  7705.  
  7706. local self = Tools.Collision;
  7707.  
  7708. -- Stop the update loop
  7709. if self.Updater then
  7710. self.Updater();
  7711. self.Updater = nil;
  7712. end;
  7713.  
  7714. -- Hide the GUI
  7715. self:hideGUI();
  7716.  
  7717. -- Clear out any temporary connections
  7718. for connection_index, Connection in pairs( self.Connections ) do
  7719. Connection:disconnect();
  7720. self.Connections[connection_index] = nil;
  7721. end;
  7722.  
  7723. -- Restore the original color of the selection boxes
  7724. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  7725. updateSelectionBoxColor();
  7726.  
  7727. end;
  7728.  
  7729. Tools.Collision.Loaded = true;
  7730. end))
  7731. LocalScript9.Disabled = true
  7732. LocalScript10.Name = "BTNewPartTool"
  7733. LocalScript10.Parent = LocalScript1
  7734. table.insert(cors,sandbox(LocalScript10,function()
  7735. -- Load the main tool's core environment when it's ready
  7736. repeat wait() until (
  7737. _G.BTCoreEnv and
  7738. _G.BTCoreEnv[script.Parent.Parent] and
  7739. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  7740. );
  7741. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  7742.  
  7743. ------------------------------------------
  7744. -- New part tool
  7745. ------------------------------------------
  7746.  
  7747. -- Create the tool
  7748. Tools.NewPart = {};
  7749.  
  7750. -- Define the tool's color
  7751. Tools.NewPart.Color = BrickColor.new( "Really black" );
  7752.  
  7753. -- Keep a container for temporary connections
  7754. Tools.NewPart.Connections = {};
  7755.  
  7756. -- Keep a container for state data
  7757. Tools.NewPart.State = {
  7758. ["Part"] = nil;
  7759. };
  7760.  
  7761. -- Maintain a container for options
  7762. Tools.NewPart.Options = {
  7763. ["type"] = "normal"
  7764. };
  7765.  
  7766. -- Keep a container for platform event connections
  7767. Tools.NewPart.Listeners = {};
  7768.  
  7769. -- Start adding functionality to the tool
  7770. Tools.NewPart.Listeners.Equipped = function ()
  7771.  
  7772. local self = Tools.NewPart;
  7773.  
  7774. -- Change the color of selection boxes temporarily
  7775. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  7776. SelectionBoxColor = self.Color;
  7777. updateSelectionBoxColor();
  7778.  
  7779. -- Reveal the GUI
  7780. self:showGUI();
  7781.  
  7782. -- Restore the type option
  7783. self:changeType( self.Options.type );
  7784.  
  7785. end;
  7786.  
  7787. Tools.NewPart.Listeners.Unequipped = function ()
  7788.  
  7789. local self = Tools.NewPart;
  7790.  
  7791. -- Hide the GUI
  7792. self:hideGUI();
  7793.  
  7794. -- Disconnect temporary connections
  7795. for connection_index, Connection in pairs( self.Connections ) do
  7796. Connection:disconnect();
  7797. self.Connections[connection_index] = nil;
  7798. end;
  7799.  
  7800. -- Restore the original color of selection boxes
  7801. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  7802. updateSelectionBoxColor();
  7803.  
  7804. end;
  7805.  
  7806. Tools.NewPart.Listeners.Button1Down = function ()
  7807.  
  7808. local self = Tools.NewPart;
  7809.  
  7810. local NewPart;
  7811.  
  7812. -- Create the new part of type `self.Options.type`
  7813. if self.Options.type == "normal" then
  7814. NewPart = Instance.new( "Part", Services.Workspace );
  7815. NewPart.FormFactor = "Custom";
  7816. NewPart.Size = Vector3.new( 4, 1, 2 );
  7817. elseif self.Options.type == "truss" then
  7818. NewPart = Instance.new( "TrussPart", Services.Workspace );
  7819. elseif self.Options.type == "wedge" then
  7820. NewPart = Instance.new( "WedgePart", Services.Workspace );
  7821. elseif self.Options.type == "corner" then
  7822. NewPart = Instance.new( "CornerWedgePart", Services.Workspace );
  7823. elseif self.Options.type == "cylinder" then
  7824. NewPart = Instance.new( "Part", Services.Workspace );
  7825. NewPart.Shape = "Cylinder";
  7826. elseif self.Options.type == "ball" then
  7827. NewPart = Instance.new( "Part", Services.Workspace );
  7828. NewPart.Shape = "Ball";
  7829. elseif self.Options.type == "seat" then
  7830. NewPart = Instance.new( "Seat", Services.Workspace );
  7831. elseif self.Options.type == "vehicle seat" then
  7832. NewPart = Instance.new( "VehicleSeat", Services.Workspace );
  7833. elseif self.Options.type == "spawn" then
  7834. NewPart = Instance.new( "SpawnLocation", Services.Workspace );
  7835. end;
  7836. NewPart.Anchored = true;
  7837.  
  7838. -- Select the new part
  7839. Selection:clear();
  7840. Selection:add( NewPart );
  7841.  
  7842. local HistoryRecord = {
  7843. target = NewPart;
  7844. apply = function ( self )
  7845. Selection:clear();
  7846. if self.target then
  7847. self.target.Parent = Services.Workspace;
  7848. Selection:add( self.target );
  7849. end;
  7850. end;
  7851. unapply = function ( self )
  7852. if self.target then
  7853. self.target.Parent = nil;
  7854. end;
  7855. end;
  7856. };
  7857. History:add( HistoryRecord );
  7858.  
  7859. -- Switch to the move tool and simulate clicking so
  7860. -- that the user could easily position their new part
  7861. equipTool( Tools.Move );
  7862. Tools.Move.ManualTarget = NewPart;
  7863. NewPart.CFrame = CFrame.new( Mouse.Hit.p );
  7864. Tools.Move.Listeners.Button1Down();
  7865. Tools.Move.Listeners.Move();
  7866.  
  7867. end;
  7868.  
  7869. Tools.NewPart.changeType = function ( self, new_type )
  7870. self.Options.type = new_type;
  7871. self.TypeDropdown:selectOption( new_type:upper() );
  7872. if self.TypeDropdown.open then
  7873. self.TypeDropdown:toggle();
  7874. end;
  7875. end;
  7876.  
  7877. Tools.NewPart.showGUI = function ( self )
  7878.  
  7879. -- Initialize the GUI if it's not ready yet
  7880. if not self.GUI then
  7881.  
  7882. local Container = Tool.Interfaces:WaitForChild( "BTNewPartToolGUI" ):Clone();
  7883. Container.Parent = UI;
  7884.  
  7885. local TypeDropdown = createDropdown();
  7886. self.TypeDropdown = TypeDropdown;
  7887. TypeDropdown.Frame.Parent = Container.TypeOption;
  7888. TypeDropdown.Frame.Position = UDim2.new( 0, 70, 0, 0 );
  7889. TypeDropdown.Frame.Size = UDim2.new( 0, 140, 0, 25 );
  7890.  
  7891. TypeDropdown:addOption( "NORMAL" ).MouseButton1Up:connect( function ()
  7892. self:changeType( "normal" );
  7893. end );
  7894. TypeDropdown:addOption( "TRUSS" ).MouseButton1Up:connect( function ()
  7895. self:changeType( "truss" );
  7896. end );
  7897. TypeDropdown:addOption( "WEDGE" ).MouseButton1Up:connect( function ()
  7898. self:changeType( "wedge" );
  7899. end );
  7900. TypeDropdown:addOption( "CORNER" ).MouseButton1Up:connect( function ()
  7901. self:changeType( "corner" );
  7902. end );
  7903. TypeDropdown:addOption( "CYLINDER" ).MouseButton1Up:connect( function ()
  7904. self:changeType( "cylinder" );
  7905. end );
  7906. TypeDropdown:addOption( "BALL" ).MouseButton1Up:connect( function ()
  7907. self:changeType( "ball" );
  7908. end );
  7909. TypeDropdown:addOption( "SEAT" ).MouseButton1Up:connect( function ()
  7910. self:changeType( "seat" );
  7911. end );
  7912. TypeDropdown:addOption( "VEHICLE SEAT" ).MouseButton1Up:connect( function ()
  7913. self:changeType( "vehicle seat" );
  7914. end );
  7915. TypeDropdown:addOption( "SPAWN" ).MouseButton1Up:connect( function ()
  7916. self:changeType( "spawn" );
  7917. end );
  7918.  
  7919. self.GUI = Container;
  7920. end;
  7921.  
  7922. -- Reveal the GUI
  7923. self.GUI.Visible = true;
  7924.  
  7925. end;
  7926.  
  7927. Tools.NewPart.hideGUI = function ( self )
  7928.  
  7929. -- Hide the GUI if it exists already
  7930. if self.GUI then
  7931. self.GUI.Visible = false;
  7932. end;
  7933.  
  7934. end;
  7935.  
  7936. Tools.NewPart.Loaded = true;
  7937. end))
  7938. LocalScript10.Disabled = true
  7939. LocalScript11.Name = "BTMeshTool"
  7940. LocalScript11.Parent = LocalScript1
  7941. table.insert(cors,sandbox(LocalScript11,function()
  7942. -- Load the main tool's core environment when it's ready
  7943. repeat wait() until (
  7944. _G.BTCoreEnv and
  7945. _G.BTCoreEnv[script.Parent.Parent] and
  7946. _G.BTCoreEnv[script.Parent.Parent].CoreReady
  7947. );
  7948. setfenv( 1, _G.BTCoreEnv[script.Parent.Parent] );
  7949.  
  7950. ------------------------------------------
  7951. -- Mesh tool
  7952. ------------------------------------------
  7953.  
  7954. -- Create the tool
  7955. Tools.Mesh = {};
  7956.  
  7957. -- Define the tool's color
  7958. Tools.Mesh.Color = BrickColor.new( "Bright violet" );
  7959.  
  7960. -- Keep a container for state data
  7961. Tools.Mesh.State = {};
  7962.  
  7963. -- Keep a container for temporary connections
  7964. Tools.Mesh.Connections = {};
  7965.  
  7966. -- Keep a container for platform event connections
  7967. Tools.Mesh.Listeners = {};
  7968.  
  7969. -- Start adding functionality to the tool
  7970. Tools.Mesh.Listeners.Equipped = function ()
  7971.  
  7972. local self = Tools.Mesh;
  7973.  
  7974. -- Change the color of selection boxes temporarily
  7975. self.State.PreviousSelectionBoxColor = SelectionBoxColor;
  7976. SelectionBoxColor = self.Color;
  7977. updateSelectionBoxColor();
  7978.  
  7979. -- Reveal the GUI
  7980. self:showGUI();
  7981.  
  7982. -- Update the GUI regularly
  7983. coroutine.wrap( function ()
  7984. updater_on = true;
  7985.  
  7986. -- Provide a function to stop the loop
  7987. self.stopGUIUpdater = function ( self )
  7988. updater_on = false;
  7989. end;
  7990.  
  7991. while wait( 0.1 ) and updater_on do
  7992.  
  7993. -- Make sure the tool's equipped
  7994. if CurrentTool == self then
  7995.  
  7996. -- Update the GUI if it's visible
  7997. if self.GUI and self.GUI.Visible then
  7998. self:updateGUI();
  7999. end;
  8000.  
  8001. end;
  8002.  
  8003. end;
  8004.  
  8005. end )();
  8006.  
  8007. end;
  8008.  
  8009. Tools.Mesh.Listeners.Unequipped = function ()
  8010.  
  8011. local self = Tools.Mesh;
  8012.  
  8013. -- Stop the GUI updater
  8014. self:stopGUIUpdater();
  8015.  
  8016. -- Hide the GUI
  8017. self:hideGUI();
  8018.  
  8019. -- Disconnect temporary connections
  8020. for connection_index, Connection in pairs( self.Connections ) do
  8021. Connection:disconnect();
  8022. self.Connections[connection_index] = nil;
  8023. end;
  8024.  
  8025. -- Restore the original color of selection boxes
  8026. SelectionBoxColor = self.State.PreviousSelectionBoxColor;
  8027. updateSelectionBoxColor();
  8028.  
  8029. end;
  8030.  
  8031. Tools.Mesh.TypeDropdownLabels = {
  8032. [Enum.MeshType.Brick] = "BLOCK";
  8033. [Enum.MeshType.Cylinder] = "CYLINDER";
  8034. [Enum.MeshType.FileMesh] = "FILE";
  8035. [Enum.MeshType.Head] = "HEAD";
  8036. [Enum.MeshType.Sphere] = "SPHERE";
  8037. [Enum.MeshType.Torso] = "TRAPEZOID";
  8038. [Enum.MeshType.Wedge] = "WEDGE";
  8039. };
  8040.  
  8041. Tools.Mesh.changeType = function ( self, new_type )
  8042.  
  8043. -- Apply type `new_type` to all the meshes in items from the selection
  8044. local meshes = {};
  8045. for _, Item in pairs( Selection.Items ) do
  8046. local Mesh = _getChildOfClass( Item, "SpecialMesh" );
  8047. if Mesh then
  8048. table.insert( meshes, Mesh );
  8049. end;
  8050. end;
  8051.  
  8052. self:startHistoryRecord( meshes );
  8053. for _, Mesh in pairs( meshes ) do
  8054. Mesh.MeshType = new_type;
  8055. end;
  8056. self:finishHistoryRecord();
  8057.  
  8058. if self.TypeDropdown.open then
  8059. self.TypeDropdown:toggle();
  8060. end;
  8061.  
  8062. self:finishHistoryRecord();
  8063.  
  8064. end;
  8065.  
  8066. Tools.Mesh.updateGUI = function ( self )
  8067.  
  8068. -- Make sure the GUI exists
  8069. if not self.GUI then
  8070. return;
  8071. end;
  8072.  
  8073. local GUI = self.GUI;
  8074.  
  8075. if #Selection.Items > 0 then
  8076.  
  8077. local meshes = {};
  8078. for _, Item in pairs( Selection.Items ) do
  8079. local Mesh = _getChildOfClass( Item, "SpecialMesh" );
  8080. if Mesh then
  8081. table.insert( meshes, Mesh );
  8082. end;
  8083. end;
  8084.  
  8085. local show_add, show_remove, show_mesh_id;
  8086. local mesh_type, mesh_scale_x, mesh_scale_y, mesh_scale_z, mesh_id, mesh_texture, mesh_tint_r, mesh_tint_g, mesh_tint_b;
  8087.  
  8088. -- If every item has a mesh
  8089. if #meshes == #Selection.Items then
  8090. show_add = false;
  8091. show_remove = true;
  8092.  
  8093. -- If no item has a mesh
  8094. elseif #meshes == 0 then
  8095. show_add = true;
  8096. show_remove = false;
  8097.  
  8098. -- If some items have a mesh
  8099. else
  8100. show_add = true;
  8101. show_remove = true;
  8102. end;
  8103.  
  8104. -- If there are meshes
  8105. if #meshes > 0 then
  8106. show_type = true;
  8107. for mesh_index, Mesh in pairs( meshes ) do
  8108.  
  8109. -- Set the start values for later comparison
  8110. if mesh_index == 1 then
  8111. mesh_type = Mesh.MeshType;
  8112. mesh_scale_x, mesh_scale_y, mesh_scale_z = Mesh.Scale.x, Mesh.Scale.y, Mesh.Scale.z;
  8113. mesh_id = Mesh.MeshId:lower();
  8114. mesh_texture = Mesh.TextureId:lower();
  8115. mesh_tint_r, mesh_tint_g, mesh_tint_b = Mesh.VertexColor.x, Mesh.VertexColor.y, Mesh.VertexColor.z;
  8116.  
  8117. -- Set the values to `nil` if they vary across the selection
  8118. else
  8119. if mesh_type ~= Mesh.MeshType then
  8120. mesh_type = nil;
  8121. end;
  8122. if mesh_scale_x ~= Mesh.Scale.x then
  8123. mesh_scale_x = nil;
  8124. end;
  8125. if mesh_scale_y ~= Mesh.Scale.y then
  8126. mesh_scale_y = nil;
  8127. end;
  8128. if mesh_scale_z ~= Mesh.Scale.z then
  8129. mesh_scale_z = nil;
  8130. end;
  8131. if mesh_id ~= Mesh.MeshId:lower() then
  8132. mesh_id = nil;
  8133. end;
  8134. if mesh_texture ~= Mesh.TextureId:lower() then
  8135. mesh_texture = nil;
  8136. end;
  8137. if mesh_tint_r ~= Mesh.VertexColor.x then
  8138. mesh_tint_r = nil;
  8139. end;
  8140. if mesh_tint_g ~= Mesh.VertexColor.y then
  8141. mesh_tint_g = nil;
  8142. end;
  8143. if mesh_tint_b ~= Mesh.VertexColor.z then
  8144. mesh_tint_b = nil;
  8145. end;
  8146. end;
  8147.  
  8148. -- If there's a FileMesh around here, note that
  8149. if Mesh.MeshType == Enum.MeshType.FileMesh then
  8150. show_mesh_id = true;
  8151. end;
  8152.  
  8153. end;
  8154.  
  8155. self.State.mesh_tint = ( mesh_tint_r and mesh_tint_g and mesh_tint_b ) and Color3.new( mesh_tint_r, mesh_tint_g, mesh_tint_b ) or nil;
  8156.  
  8157. if show_mesh_id and show_add and show_remove then
  8158. self.GUI.AddButton.Visible = true;
  8159. self.GUI.RemoveButton.Visible = true;
  8160. self.GUI.MeshIDOption.Visible = true;
  8161. self.GUI.TextureIDOption.Visible = true;
  8162. self.GUI.ScaleOption.Visible = true;
  8163. self.GUI.TintOption.Visible = true;
  8164. self.GUI.TypeOption.Visible = true;
  8165. self.GUI.TypeOption.Position = UDim2.new( 0, 14, 0, 65 );
  8166. self.GUI.ScaleOption.Position = UDim2.new( 0, 0, 0, 100 );
  8167. self.GUI.MeshIDOption.Position = UDim2.new( 0, 14, 0, 135 );
  8168. self.GUI.TextureIDOption.Position = UDim2.new( 0, 14, 0, 165 );
  8169. self.GUI.TintOption.Position = UDim2.new( 0, 0, 0, 200 );
  8170. self.GUI.Size = UDim2.new( 0, 200, 0, 265 );
  8171. elseif show_mesh_id and not show_add and show_remove then
  8172. self.GUI.AddButton.Visible = false;
  8173. self.GUI.RemoveButton.Visible = true;
  8174. self.GUI.MeshIDOption.Visible = true;
  8175. self.GUI.TextureIDOption.Visible = true;
  8176. self.GUI.ScaleOption.Visible = true;
  8177. self.GUI.TintOption.Visible = true;
  8178. self.GUI.TypeOption.Visible = true;
  8179. self.GUI.TypeOption.Position = UDim2.new( 0, 14, 0, 30 );
  8180. self.GUI.ScaleOption.Position = UDim2.new( 0, 0, 0, 65 );
  8181. self.GUI.MeshIDOption.Position = UDim2.new( 0, 14, 0, 100 );
  8182. self.GUI.TextureIDOption.Position = UDim2.new( 0, 14, 0, 130 );
  8183. self.GUI.TintOption.Position = UDim2.new( 0, 0, 0, 165 );
  8184. self.GUI.Size = UDim2.new( 0, 200, 0, 230 );
  8185.  
  8186. elseif not show_mesh_id and show_add and show_remove then
  8187. self.GUI.AddButton.Visible = true;
  8188. self.GUI.RemoveButton.Visible = true;
  8189. self.GUI.MeshIDOption.Visible = false;
  8190. self.GUI.TextureIDOption.Visible = false;
  8191. self.GUI.ScaleOption.Visible = true;
  8192. self.GUI.TintOption.Visible = false;
  8193. self.GUI.TypeOption.Visible = true;
  8194. self.GUI.TypeOption.Position = UDim2.new( 0, 14, 0, 65 );
  8195. self.GUI.ScaleOption.Position = UDim2.new( 0, 0, 0, 100 );
  8196. self.GUI.Size = UDim2.new( 0, 200, 0, 165 );
  8197. elseif not show_mesh_id and not show_add and show_remove then
  8198. self.GUI.AddButton.Visible = false;
  8199. self.GUI.RemoveButton.Visible = true;
  8200. self.GUI.MeshIDOption.Visible = false;
  8201. self.GUI.TextureIDOption.Visible = false;
  8202. self.GUI.ScaleOption.Visible = true;
  8203. self.GUI.TintOption.Visible = false;
  8204. self.GUI.TypeOption.Visible = true;
  8205. self.GUI.TypeOption.Position = UDim2.new( 0, 14, 0, 30 );
  8206. self.GUI.ScaleOption.Position = UDim2.new( 0, 0, 0, 65 );
  8207. self.GUI.Size = UDim2.new( 0, 200, 0, 130 );
  8208. end;
  8209.  
  8210. -- Update the values shown on the GUI
  8211. if not self.State.mesh_id_focused then
  8212. self.GUI.MeshIDOption.TextBox.Text = mesh_id and ( mesh_id:match( "%?id=([0-9]+)" ) or "" ) or "*";
  8213. end;
  8214. if not self.State.texture_id_focused then
  8215. self.GUI.TextureIDOption.TextBox.Text = mesh_texture and ( mesh_texture:match( "%?id=([0-9]+)" ) or "" ) or "*";
  8216. end;
  8217. self.TypeDropdown:selectOption( mesh_type and self.TypeDropdownLabels[mesh_type] or "*" );
  8218. if not self.State.scale_x_focused then
  8219. self.GUI.ScaleOption.XInput.TextBox.Text = mesh_scale_x and _round( mesh_scale_x, 2 ) or "*";
  8220. end;
  8221. if not self.State.scale_y_focused then
  8222. self.GUI.ScaleOption.YInput.TextBox.Text = mesh_scale_y and _round( mesh_scale_y, 2 ) or "*";
  8223. end;
  8224. if not self.State.scale_z_focused then
  8225. self.GUI.ScaleOption.ZInput.TextBox.Text = mesh_scale_z and _round( mesh_scale_z, 2 ) or "*";
  8226. end;
  8227. if not self.State.tint_r_focused then
  8228. self.GUI.TintOption.RInput.TextBox.Text = mesh_tint_r and _round( mesh_tint_r * 255, 0 ) or "*";
  8229. end;
  8230. if not self.State.tint_g_focused then
  8231. self.GUI.TintOption.GInput.TextBox.Text = mesh_tint_g and _round( mesh_tint_g * 255, 0 ) or "*";
  8232. end;
  8233. if not self.State.tint_b_focused then
  8234. self.GUI.TintOption.BInput.TextBox.Text = mesh_tint_b and _round( mesh_tint_b * 255, 0 ) or "*";
  8235. end;
  8236.  
  8237. -- If there are no meshes
  8238. else
  8239. self.GUI.AddButton.Visible = true;
  8240. self.GUI.RemoveButton.Visible = false;
  8241. self.GUI.MeshIDOption.Visible = false;
  8242. self.GUI.TextureIDOption.Visible = false;
  8243. self.GUI.ScaleOption.Visible = false;
  8244. self.GUI.TintOption.Visible = false;
  8245. self.GUI.TypeOption.Visible = false;
  8246. self.GUI.Size = UDim2.new( 0, 200, 0, 62 );
  8247. end;
  8248. self.GUI.SelectNote.Visible = false;
  8249.  
  8250. -- Show a note that says to select something
  8251. else
  8252. self.GUI.AddButton.Visible = false;
  8253. self.GUI.RemoveButton.Visible = false;
  8254. self.GUI.MeshIDOption.Visible = false;
  8255. self.GUI.TextureIDOption.Visible = false;
  8256. self.GUI.ScaleOption.Visible = false;
  8257. self.GUI.TintOption.Visible = false;
  8258. self.GUI.TypeOption.Visible = false;
  8259. self.GUI.SelectNote.Visible = true;
  8260. self.GUI.Size = UDim2.new( 0, 200, 0, 55 );
  8261. end;
  8262.  
  8263. end;
  8264.  
  8265. Tools.Mesh.showGUI = function ( self )
  8266.  
  8267. -- Initialize the GUI if it's not ready yet
  8268. if not self.GUI then
  8269. local Container = Tool.Interfaces:WaitForChild( "BTMeshToolGUI" ):Clone();
  8270. Container.Parent = UI;
  8271.  
  8272. -- Add functionality to the add/remove buttons
  8273. Container.AddButton.Button.MouseButton1Up:connect( function ()
  8274. self:addMesh();
  8275. end );
  8276. Container.RemoveButton.Button.MouseButton1Up:connect( function ()
  8277. self:removeMesh();
  8278. end );
  8279.  
  8280. -- Add the type dropdown
  8281. local TypeDropdown = createDropdown();
  8282. self.TypeDropdown = TypeDropdown;
  8283. TypeDropdown.Frame.Parent = Container.TypeOption;
  8284. TypeDropdown.Frame.Position = UDim2.new( 0, 40, 0, 0 );
  8285. TypeDropdown.Frame.Size = UDim2.new( 1, -40, 0, 25 );
  8286. TypeDropdown:addOption( "BLOCK" ).MouseButton1Up:connect( function ()
  8287. self:changeType( Enum.MeshType.Brick );
  8288. end );
  8289. TypeDropdown:addOption( "CYLINDER" ).MouseButton1Up:connect( function ()
  8290. self:changeType( Enum.MeshType.Cylinder );
  8291. end );
  8292. TypeDropdown:addOption( "FILE" ).MouseButton1Up:connect( function ()
  8293. self:changeType( Enum.MeshType.FileMesh );
  8294. end );
  8295. TypeDropdown:addOption( "HEAD" ).MouseButton1Up:connect( function ()
  8296. self:changeType( Enum.MeshType.Head );
  8297. end );
  8298. TypeDropdown:addOption( "SPHERE" ).MouseButton1Up:connect( function ()
  8299. self:changeType( Enum.MeshType.Sphere );
  8300. end );
  8301. TypeDropdown:addOption( "TRAPEZOID" ).MouseButton1Up:connect( function ()
  8302. self:changeType( Enum.MeshType.Torso );
  8303. end );
  8304. TypeDropdown:addOption( "WEDGE" ).MouseButton1Up:connect( function ()
  8305. self:changeType( Enum.MeshType.Wedge );
  8306. end );
  8307.  
  8308. -- Add functionality to the scale inputs
  8309. Container.ScaleOption.XInput.TextButton.MouseButton1Down:connect( function ()
  8310. self.State.scale_x_focused = true;
  8311. Container.ScaleOption.XInput.TextBox:CaptureFocus();
  8312. end );
  8313. Container.ScaleOption.XInput.TextBox.FocusLost:connect( function ( enter_pressed )
  8314. local potential_new = tonumber( Container.ScaleOption.XInput.TextBox.Text );
  8315. if potential_new then
  8316. self:changeScale( 'x', potential_new );
  8317. end;
  8318. self.State.scale_x_focused = false;
  8319. end );
  8320.  
  8321. Container.ScaleOption.YInput.TextButton.MouseButton1Down:connect( function ()
  8322. self.State.scale_y_focused = true;
  8323. Container.ScaleOption.YInput.TextBox:CaptureFocus();
  8324. end );
  8325. Container.ScaleOption.YInput.TextBox.FocusLost:connect( function ( enter_pressed )
  8326. local potential_new = tonumber( Container.ScaleOption.YInput.TextBox.Text );
  8327. if potential_new then
  8328. self:changeScale( 'y', potential_new );
  8329. end;
  8330. self.State.scale_y_focused = false;
  8331. end );
  8332.  
  8333. Container.ScaleOption.ZInput.TextButton.MouseButton1Down:connect( function ()
  8334. self.State.scale_z_focused = true;
  8335. Container.ScaleOption.ZInput.TextBox:CaptureFocus();
  8336. end );
  8337. Container.ScaleOption.ZInput.TextBox.FocusLost:connect( function ( enter_pressed )
  8338. local potential_new = tonumber( Container.ScaleOption.ZInput.TextBox.Text );
  8339. if potential_new then
  8340. self:changeScale( 'z', potential_new );
  8341. end;
  8342. self.State.scale_z_focused = false;
  8343. end );
  8344.  
  8345. -- Add functionality to the mesh/texture ID inputs
  8346. Container.MeshIDOption.TextButton.MouseButton1Down:connect( function ()
  8347. self.State.mesh_id_focused = true;
  8348. Container.MeshIDOption.TextBox:CaptureFocus();
  8349. end );
  8350. Container.MeshIDOption.TextBox.FocusLost:connect( function ( enter_pressed )
  8351. local input = Container.MeshIDOption.TextBox.Text;
  8352. local potential_new = tonumber( input ) or input:lower():match( "%?id=([0-9]+)" );
  8353. if potential_new then
  8354. self:changeMesh( potential_new );
  8355. end;
  8356. self.State.mesh_id_focused = false;
  8357. end );
  8358.  
  8359. Container.TextureIDOption.TextButton.MouseButton1Down:connect( function ()
  8360. self.State.texture_id_focused = true;
  8361. Container.TextureIDOption.TextBox:CaptureFocus();
  8362. end );
  8363. Container.TextureIDOption.TextBox.FocusLost:connect( function ( enter_pressed )
  8364. local input = Container.TextureIDOption.TextBox.Text;
  8365. local potential_new = tonumber( input ) or input:lower():match( "%?id=([0-9]+)" );
  8366. if potential_new then
  8367. self:changeTexture( potential_new );
  8368. end;
  8369. self.State.texture_id_focused = false;
  8370. end );
  8371.  
  8372. -- Add functionality to the tint inputs
  8373. Container.TintOption.RInput.TextButton.MouseButton1Down:connect( function ()
  8374. self.State.tint_r_focused = true;
  8375. Container.TintOption.RInput.TextBox:CaptureFocus();
  8376. end );
  8377. Container.TintOption.RInput.TextBox.FocusLost:connect( function ( enter_pressed )
  8378. local potential_new = tonumber( Container.TintOption.RInput.TextBox.Text );
  8379. if potential_new then
  8380. if potential_new > 255 then
  8381. potential_new = 255;
  8382. elseif potential_new < 0 then
  8383. potential_new = 0;
  8384. end;
  8385. self:changeTint( 'r', potential_new / 255 );
  8386. end;
  8387. self.State.tint_r_focused = false;
  8388. end );
  8389.  
  8390. Container.TintOption.GInput.TextButton.MouseButton1Down:connect( function ()
  8391. self.State.tint_g_focused = true;
  8392. Container.TintOption.GInput.TextBox:CaptureFocus();
  8393. end );
  8394. Container.TintOption.GInput.TextBox.FocusLost:connect( function ( enter_pressed )
  8395. local potential_new = tonumber( Container.TintOption.GInput.TextBox.Text );
  8396. if potential_new then
  8397. if potential_new > 255 then
  8398. potential_new = 255;
  8399. elseif potential_new < 0 then
  8400. potential_new = 0;
  8401. end;
  8402. self:changeTint( 'g', potential_new / 255 );
  8403. end;
  8404. self.State.tint_g_focused = false;
  8405. end );
  8406.  
  8407. Container.TintOption.BInput.TextButton.MouseButton1Down:connect( function ()
  8408. self.State.tint_b_focused = true;
  8409. Container.TintOption.BInput.TextBox:CaptureFocus();
  8410. end );
  8411. Container.TintOption.BInput.TextBox.FocusLost:connect( function ( enter_pressed )
  8412. local potential_new = tonumber( Container.TintOption.BInput.TextBox.Text );
  8413. if potential_new then
  8414. if potential_new > 255 then
  8415. potential_new = 255;
  8416. elseif potential_new < 0 then
  8417. potential_new = 0;
  8418. end;
  8419. self:changeTint( 'b', potential_new / 255 );
  8420. end;
  8421. self.State.tint_b_focused = false;
  8422. end );
  8423.  
  8424. Container.TintOption.HSVPicker.MouseButton1Up:connect( function ()
  8425. ColorPicker:start( function ( ... )
  8426. local args = { ... };
  8427. -- If a color was picked, change the spotlights' color
  8428. -- to the selected color
  8429. if #args == 3 then
  8430. local meshes = {};
  8431. for _, Item in pairs( Selection.Items ) do
  8432. local Mesh = _getChildOfClass( Item, "SpecialMesh" );
  8433. if Mesh then
  8434. table.insert( meshes, Mesh );
  8435. end;
  8436. end;
  8437. self:startHistoryRecord( meshes );
  8438. for _, Mesh in pairs( meshes ) do
  8439. Mesh.VertexColor = Vector3.new( _HSVToRGB( ... ) );
  8440. end;
  8441. self:finishHistoryRecord();
  8442. end;
  8443. end, self.State.mesh_tint );
  8444. end );
  8445.  
  8446. self.GUI = Container;
  8447. end;
  8448.  
  8449. -- Reveal the GUI
  8450. self.GUI.Visible = true;
  8451.  
  8452. end;
  8453.  
  8454. Tools.Mesh.addMesh = function ( self )
  8455.  
  8456. local HistoryRecord = {
  8457. apply = function ( self )
  8458. Selection:clear();
  8459. for _, Mesh in pairs( self.meshes ) do
  8460. Mesh.Parent = self.mesh_parents[Mesh];
  8461. Selection:add( Mesh.Parent );
  8462. end;
  8463. end;
  8464. unapply = function ( self )
  8465. Selection:clear();
  8466. for _, Mesh in pairs( self.meshes ) do
  8467. Selection:add( Mesh.Parent );
  8468. Mesh.Parent = nil;
  8469. end;
  8470. end;
  8471. };
  8472.  
  8473. -- Add meshes to all the items from the selection that
  8474. -- don't already have one
  8475. local meshes = {};
  8476. local mesh_parents = {};
  8477. for _, Item in pairs( Selection.Items ) do
  8478. local Mesh = _getChildOfClass( Item, "SpecialMesh" );
  8479. if not Mesh then
  8480. local Mesh = RbxUtility.Create "SpecialMesh" {
  8481. Parent = Item;
  8482. MeshType = Enum.MeshType.Brick;
  8483. };
  8484. table.insert( meshes, Mesh );
  8485. mesh_parents[Mesh] = Item;
  8486. end;
  8487. end;
  8488.  
  8489. HistoryRecord.meshes = meshes;
  8490. HistoryRecord.mesh_parents = mesh_parents;
  8491. History:add( HistoryRecord );
  8492.  
  8493. end;
  8494.  
  8495. Tools.Mesh.removeMesh = function ( self )
  8496.  
  8497. local HistoryRecord = {
  8498. apply = function ( self )
  8499. Selection:clear();
  8500. for _, Mesh in pairs( self.meshes ) do
  8501. Selection:add( Mesh.Parent );
  8502. Mesh.Parent = nil;
  8503. end;
  8504. end;
  8505. unapply = function ( self )
  8506. Selection:clear();
  8507. for _, Mesh in pairs( self.meshes ) do
  8508. Mesh.Parent = self.mesh_parents[Mesh];
  8509. Selection:add( Mesh.Parent );
  8510. end;
  8511. end;
  8512. };
  8513.  
  8514. local meshes = {};
  8515. local mesh_parents = {};
  8516. -- Remove meshes from all the selected items
  8517. for _, Item in pairs( Selection.Items ) do
  8518. local meshes_found = _getChildrenOfClass( Item, "SpecialMesh" );
  8519. for _, Mesh in pairs( meshes_found ) do
  8520. table.insert( meshes, Mesh );
  8521. mesh_parents[Mesh] = Mesh.Parent;
  8522. Mesh.Parent = nil;
  8523. end;
  8524. end;
  8525.  
  8526. HistoryRecord.meshes = meshes;
  8527. HistoryRecord.mesh_parents = mesh_parents;
  8528. History:add( HistoryRecord );
  8529.  
  8530. end;
  8531.  
  8532. Tools.Mesh.startHistoryRecord = function ( self, meshes )
  8533.  
  8534. if self.State.HistoryRecord then
  8535. self.State.HistoryRecord = nil;
  8536. end;
  8537.  
  8538. -- Create a history record
  8539. self.State.HistoryRecord = {
  8540. targets = _cloneTable( meshes );
  8541. initial_type = {};
  8542. terminal_type = {};
  8543. initial_mesh = {};
  8544. terminal_mesh = {};
  8545. initial_texture = {};
  8546. terminal_texture = {};
  8547. initial_scale = {};
  8548. terminal_scale = {};
  8549. initial_tint = {};
  8550. terminal_tint = {};
  8551. unapply = function ( self )
  8552. Selection:clear();
  8553. for _, Target in pairs( self.targets ) do
  8554. if Target then
  8555. Selection:add( Target.Parent );
  8556. Target.MeshType = self.initial_type[Target];
  8557. Target.MeshId = self.initial_mesh[Target];
  8558. Target.TextureId = self.initial_texture[Target];
  8559. Target.Scale = self.initial_scale[Target];
  8560. Target.VertexColor = self.initial_tint[Target];
  8561. end;
  8562. end;
  8563. end;
  8564. apply = function ( self )
  8565. Selection:clear();
  8566. for _, Target in pairs( self.targets ) do
  8567. if Target then
  8568. Selection:add( Target.Parent );
  8569. Target.MeshType = self.terminal_type[Target];
  8570. Target.MeshId = self.terminal_mesh[Target];
  8571. Target.TextureId = self.terminal_texture[Target];
  8572. Target.Scale = self.terminal_scale[Target];
  8573. Target.VertexColor = self.terminal_tint[Target];
  8574. end;
  8575. end;
  8576. end;
  8577. };
  8578. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  8579. if Item then
  8580. self.State.HistoryRecord.initial_type[Item] = Item.MeshType;
  8581. self.State.HistoryRecord.initial_mesh[Item] = Item.MeshId;
  8582. self.State.HistoryRecord.initial_texture[Item] = Item.TextureId;
  8583. self.State.HistoryRecord.initial_scale[Item] = Item.Scale;
  8584. self.State.HistoryRecord.initial_tint[Item] = Item.VertexColor;
  8585. end;
  8586. end;
  8587.  
  8588. end;
  8589.  
  8590. Tools.Mesh.finishHistoryRecord = function ( self )
  8591.  
  8592. if not self.State.HistoryRecord then
  8593. return;
  8594. end;
  8595.  
  8596. for _, Item in pairs( self.State.HistoryRecord.targets ) do
  8597. if Item then
  8598. self.State.HistoryRecord.terminal_type[Item] = Item.MeshType;
  8599. self.State.HistoryRecord.terminal_mesh[Item] = Item.MeshId;
  8600. self.State.HistoryRecord.terminal_texture[Item] = Item.TextureId;
  8601. self.State.HistoryRecord.terminal_scale[Item] = Item.Scale;
  8602. self.State.HistoryRecord.terminal_tint[Item] = Item.VertexColor;
  8603. end;
  8604. end;
  8605. History:add( self.State.HistoryRecord );
  8606. self.State.HistoryRecord = nil;
  8607.  
  8608. end;
  8609.  
  8610. Tools.Mesh.changeMesh = function ( self, mesh_id )
  8611.  
  8612. local meshes = {};
  8613.  
  8614. for _, Item in pairs( Selection.Items ) do
  8615. local Mesh = _getChildOfClass( Item, "SpecialMesh" );
  8616. if Mesh then
  8617. table.insert( meshes, Mesh );
  8618. end;
  8619. end;
  8620. self:startHistoryRecord( meshes );
  8621. for _, Mesh in pairs( meshes ) do
  8622. Mesh.MeshId = "http://www.roblox.com/asset/?id=" .. mesh_id;
  8623. end;
  8624. self:finishHistoryRecord();
  8625.  
  8626. end;
  8627.  
  8628. Tools.Mesh.changeTexture = function ( self, texture_id )
  8629.  
  8630. local meshes = {};
  8631.  
  8632. for _, Item in pairs( Selection.Items ) do
  8633. local Mesh = _getChildOfClass( Item, "SpecialMesh" );
  8634. if Mesh then
  8635. table.insert( meshes, Mesh );
  8636. end;
  8637. end;
  8638. self:startHistoryRecord( meshes );
  8639. for _, Mesh in pairs( meshes ) do
  8640. Mesh.TextureId = "http://www.roblox.com/asset/?id=" .. texture_id;
  8641. end;
  8642. self:finishHistoryRecord();
  8643.  
  8644. end;
  8645.  
  8646. Tools.Mesh.changeScale = function ( self, component, new_value )
  8647.  
  8648. local meshes = {};
  8649.  
  8650. for _, Item in pairs( Selection.Items ) do
  8651. local Mesh = _getChildOfClass( Item, "SpecialMesh" );
  8652. if Mesh then
  8653. table.insert( meshes, Mesh );
  8654. end;
  8655. end;
  8656.  
  8657. self:startHistoryRecord( meshes );
  8658. for _, Mesh in pairs( meshes ) do
  8659. Mesh.Scale = Vector3.new(
  8660. component == 'x' and new_value or Mesh.Scale.x,
  8661. component == 'y' and new_value or Mesh.Scale.y,
  8662. component == 'z' and new_value or Mesh.Scale.z
  8663. );
  8664. end;
  8665. self:finishHistoryRecord();
  8666.  
  8667. end;
  8668.  
  8669. Tools.Mesh.changeTint = function ( self, component, new_value )
  8670.  
  8671. local meshes = {};
  8672.  
  8673. for _, Item in pairs( Selection.Items ) do
  8674. local Mesh = _getChildOfClass( Item, "SpecialMesh" );
  8675. if Mesh then
  8676. table.insert( meshes, Mesh );
  8677. end;
  8678. end;
  8679.  
  8680. self:startHistoryRecord( meshes );
  8681. for _, Mesh in pairs( meshes ) do
  8682. Mesh.VertexColor = Vector3.new(
  8683. component == 'r' and new_value or Mesh.VertexColor.x,
  8684. component == 'g' and new_value or Mesh.VertexColor.y,
  8685. component == 'b' and new_value or Mesh.VertexColor.z
  8686. );
  8687. end;
  8688. self:finishHistoryRecord();
  8689.  
  8690. end;
  8691.  
  8692. Tools.Mesh.hideGUI = function ( self )
  8693.  
  8694. -- Hide the GUI if it exists already
  8695. if self.GUI then
  8696. self.GUI.Visible = false;
  8697. end;
  8698.  
  8699. end;
  8700.  
  8701. Tools.Mesh.Loaded = true;
  8702. end))
  8703. LocalScript11.Disabled = true
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement