Advertisement
Guest User

spritewindow

a guest
Jan 8th, 2019
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 120.70 KB | None | 0 0
  1. module MessageConfig
  2. FontName = "Power Green"
  3. # in Graphics/Windowskins/ (specify empty string to use the default windowskin)
  4. TextSkinName = "speech hgss 1"
  5. ChoiceSkinName = "choice 1"
  6. WindowOpacity = 255
  7. TextSpeed = nil # can be positive to wait frames or negative to
  8. # show multiple characters in a single frame
  9. LIGHTTEXTBASE = Color.new(248,248,248)
  10. LIGHTTEXTSHADOW = Color.new(72,80,88)
  11. DARKTEXTBASE = Color.new(88,88,80)
  12. BUBBLETEXTBASE = Color.new(22,22,22)
  13. BUBBLETEXTSHADOW= Color.new(166,160,151)
  14. DARKTEXTSHADOW = Color.new(168,184,184)
  15. # 0 = Pause cursor is displayed at end of text
  16. # 1 = Pause cursor is displayed at bottom right
  17. # 2 = Pause cursor is displayed at lower middle side
  18. CURSORMODE = 1
  19. FontSubstitutes = {
  20. "Power Red and Blue"=>"Pokemon RS",
  21. "Power Red and Green"=>"Pokemon FireLeaf",
  22. "Power Green"=>"Pokemon Emerald",
  23. "Power Green Narrow"=>"Pokemon Emerald Narrow",
  24. "Power Green Small"=>"Pokemon Emerald Small",
  25. "Power Clear"=>"Pokemon DP",
  26. "Arial"=>"PF Tempesta Seven"
  27. }
  28. @@systemFrame = nil
  29. @@defaultTextSkin = nil
  30. @@systemFont = nil
  31. @@textSpeed = nil
  32.  
  33. def self.pbTryFonts(*args)
  34. for a in args
  35. if a && a.is_a?(String)
  36. return a if Font.exist?(a)
  37. a=MessageConfig::FontSubstitutes[a] || a
  38. return a if Font.exist?(a)
  39. elsif a && a.is_a?(Array)
  40. for aa in a
  41. ret=MessageConfig.pbTryFonts(aa)
  42. return ret if ret!=""
  43. end
  44. end
  45. end
  46. return ""
  47. end
  48.  
  49. def self.pbDefaultTextSpeed
  50. return TextSpeed ? TextSpeed : (Graphics.width > 400) ? -2 : 1
  51. end
  52.  
  53. def self.pbDefaultSystemFrame
  54. return "" if !MessageConfig::ChoiceSkinName
  55. return pbResolveBitmap("Graphics/Windowskins/"+MessageConfig::ChoiceSkinName)||""
  56. end
  57.  
  58. def self.pbDefaultSpeechFrame
  59. return "" if !MessageConfig::TextSkinName
  60. return pbResolveBitmap("Graphics/Windowskins/"+MessageConfig::TextSkinName)||""
  61. end
  62.  
  63. def self.pbDefaultSystemFontName
  64. return MessageConfig.pbTryFonts(MessageConfig::FontName,"Arial Narrow","Arial","PF Tempesta Seven")
  65. end
  66.  
  67. def self.pbDefaultWindowskin
  68. skin=load_data("Data/System.rxdata").windowskin_name rescue nil
  69. if skin && skin!=""
  70. skin=pbResolveBitmap("Graphics/Windowskins/"+skin) || ""
  71. end
  72. if !skin || skin==""
  73. skin=pbResolveBitmap("Graphics/System/Window")
  74. end
  75. if !skin || skin==""
  76. skin=pbResolveBitmap("Graphics/Windowskins/001-Blue01")
  77. end
  78. return skin || ""
  79. end
  80.  
  81. def self.pbGetSpeechFrame
  82. if !@@defaultTextSkin
  83. skin=MessageConfig.pbDefaultSpeechFrame()
  84. if !skin || skin==""
  85. skin=MessageConfig.pbDefaultWindowskin()
  86. end
  87. @@defaultTextSkin=skin || ""
  88. end
  89. return @@defaultTextSkin
  90. end
  91.  
  92. def self.pbGetTextSpeed
  93. if !@@textSpeed
  94. @@textSpeed=pbDefaultTextSpeed()
  95. end
  96. return @@textSpeed
  97. end
  98.  
  99. def self.pbGetSystemFontName
  100. if !@@systemFont
  101. @@systemFont=pbDefaultSystemFontName()
  102. end
  103. return @@systemFont
  104. end
  105.  
  106. def self.pbGetSystemFrame
  107. if !@@systemFrame
  108. skin=MessageConfig.pbDefaultSystemFrame()
  109. if !skin || skin==""
  110. skin=MessageConfig.pbDefaultWindowskin()
  111. end
  112. @@systemFrame=skin || ""
  113. end
  114. return @@systemFrame
  115. end
  116.  
  117. def self.pbSetSystemFrame(value)
  118. @@systemFrame=pbResolveBitmap(value) || ""
  119. end
  120.  
  121. def self.pbSetSpeechFrame(value)
  122. @@defaultTextSkin=pbResolveBitmap(value) || ""
  123. end
  124.  
  125. def self.pbSetSystemFontName(value)
  126. @@systemFont=MessageConfig.pbTryFonts(value,"Arial Narrow","Arial")
  127. end
  128. #Custom Party Font
  129. def self.pbSetPartyFontName(value)
  130. @@systemFont=MessageConfig.pbTryFonts(value,"PF Tempesta Seven")
  131. end
  132.  
  133. def self.pbSetTextSpeed(value)
  134. @@textSpeed=value
  135. end
  136. end
  137.  
  138.  
  139. #############################
  140. #############################
  141.  
  142.  
  143. # Works around a problem with FileTest.directory if directory contains accent marks
  144. def safeIsDirectory?(f)
  145. ret=false
  146. Dir.chdir(f) { ret=true } rescue nil
  147. return ret
  148. end
  149.  
  150. # Works around a problem with FileTest.exist if path contains accent marks
  151. def safeExists?(f)
  152. ret=false
  153. if f[/\A[\x20-\x7E]*\z/]
  154. return FileTest.exist?(f)
  155. end
  156. begin
  157. File.open(f,"rb") { ret=true }
  158. rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES
  159. ret=false
  160. end
  161. return ret
  162. end
  163.  
  164. # Similar to "Dir.glob", but designed to work around a problem with accessing
  165. # files if a path contains accent marks.
  166. # "dir" is the directory path, "wildcard" is the filename pattern to match.
  167. def safeGlob(dir,wildcard)
  168. ret=[]
  169. afterChdir=false
  170. begin
  171. Dir.chdir(dir){
  172. afterChdir=true
  173. Dir.glob(wildcard){|f|
  174. ret.push(dir+"/"+f)
  175. }
  176. }
  177. rescue Errno::ENOENT
  178. raise if afterChdir
  179. end
  180. if block_given?
  181. ret.each{|f|
  182. yield(f)
  183. }
  184. end
  185. return (block_given?) ? nil : ret
  186. end
  187.  
  188.  
  189. #############################
  190. #############################
  191.  
  192.  
  193. module GifLibrary
  194. @@loadlib=Win32API.new("Kernel32.dll","LoadLibrary",'p','')
  195. if safeExists?("gif.dll")
  196. PngDll=@@loadlib.call("gif.dll")
  197. GifToPngFiles=Win32API.new("gif.dll","GifToPngFiles",'pp','l')
  198. GifToPngFilesInMemory=Win32API.new("gif.dll","GifToPngFilesInMemory",'plp','l')
  199. CopyDataString=Win32API.new("gif.dll","CopyDataString",'lpl','l')
  200. FreeDataString=Win32API.new("gif.dll","FreeDataString",'l','')
  201. else
  202. PngDll=nil
  203. end
  204.  
  205. def self.getDataFromResult(result)
  206. datasize=CopyDataString.call(result,"",0)
  207. ret=nil
  208. if datasize!=0
  209. data="0"*datasize
  210. CopyDataString.call(result,data,datasize)
  211. ret=data.unpack("V*")
  212. end
  213. FreeDataString.call(result)
  214. return ret
  215. end
  216. end
  217.  
  218.  
  219. #############################
  220. #############################
  221.  
  222.  
  223. class AnimatedBitmap
  224. def initialize(file,hue=0)
  225. raise "filename is nil" if file==nil
  226. if file[/^\[(\d+)\]/] # Starts with 1 or more digits in brackets
  227. @bitmap=PngAnimatedBitmap.new(file,hue)
  228. else
  229. @bitmap=GifBitmap.new(file,hue)
  230. end
  231. end
  232.  
  233. def [](index); @bitmap[index]; end
  234. def width; @bitmap.bitmap.width; end
  235. def height; @bitmap.bitmap.height; end
  236. def length; @bitmap.length; end
  237. def each; @bitmap.each {|item| yield item }; end
  238. def bitmap; @bitmap.bitmap; end
  239. def currentIndex; @bitmap.currentIndex; end
  240. def frameDelay; @bitmap.frameDelay; end
  241. def totalFrames; @bitmap.totalFrames; end
  242. def disposed?; @bitmap.disposed?; end
  243. def update; @bitmap.update; end
  244. def dispose; @bitmap.dispose; end
  245. def deanimate; @bitmap.deanimate; end
  246. def copy; @bitmap.copy; end
  247. end
  248.  
  249.  
  250.  
  251. def pbGetTileBitmap(filename, tile_id, hue)
  252. return BitmapCache.tileEx(filename, tile_id, hue){|f|
  253. AnimatedBitmap.new("Graphics/Tilesets/"+filename).deanimate;
  254. }
  255. end
  256.  
  257. def pbGetAnimation(name,hue=0)
  258. return AnimatedBitmap.new("Graphics/Animations/"+name,hue).deanimate
  259. end
  260.  
  261. def pbGetTileset(name,hue=0)
  262. return AnimatedBitmap.new("Graphics/Tilesets/"+name,hue).deanimate
  263. end
  264.  
  265. def pbGetAutotile(name,hue=0)
  266. return AnimatedBitmap.new("Graphics/Autotiles/"+name,hue).deanimate
  267. end
  268.  
  269. #########################
  270. #
  271. # Message support
  272. #
  273. #########################
  274. if !defined?(_INTL)
  275. def _INTL(*args);
  276. string=args[0].clone
  277. for i in 1...args.length
  278. string.gsub!(/\{#{i}\}/,"#{args[i]}")
  279. end
  280. return string
  281. end
  282. end
  283.  
  284. if !defined?(_ISPRINTF)
  285. def _ISPRINTF(*args);
  286. string=args[0].clone
  287. for i in 1...args.length
  288. string.gsub!(/\{#{i}\:([^\}]+?)\}/){|m|
  289. next sprintf("%"+$1,args[i])
  290. }
  291. end
  292. return string
  293. end
  294. end
  295.  
  296. if !defined?(_MAPINTL)
  297. def _MAPINTL(*args);
  298. string=args[1].clone
  299. for i in 2...args.length
  300. string.gsub!(/\{#{i}\}/,"#{args[i+1]}")
  301. end
  302. return string
  303. end
  304. end
  305.  
  306.  
  307.  
  308. module Graphics
  309. if !self.respond_to?("width")
  310. def self.width; return 640; end
  311. end
  312. if !self.respond_to?("height")
  313. def self.height; return 480; end
  314. end
  315. end
  316.  
  317.  
  318. #############################
  319. #############################
  320.  
  321.  
  322. module MiniRegistry
  323. HKEY_CLASSES_ROOT = 0x80000000
  324. HKEY_CURRENT_USER = 0x80000001
  325. HKEY_LOCAL_MACHINE = 0x80000002
  326. HKEY_USERS = 0x80000003
  327. FormatMessageA=Win32API.new("kernel32","FormatMessageA","LPLLPLP","L")
  328. RegOpenKeyExA=Win32API.new("advapi32","RegOpenKeyExA","LPLLP","L")
  329. RegCloseKey=Win32API.new("advapi32","RegCloseKey","L","L")
  330. RegQueryValueExA=Win32API.new("advapi32","RegQueryValueExA","LPLPPP","L")
  331.  
  332. def self.open(hkey,subkey,bit64=false)
  333. key=0.chr*4
  334. flag=bit64 ? 0x20119 : 0x20019
  335. rg=RegOpenKeyExA.call(hkey, subkey, 0, flag, key)
  336. if rg!=0
  337. return nil
  338. end
  339. key=key.unpack("V")[0]
  340. if block_given?
  341. begin
  342. yield(key)
  343. ensure
  344. check(RegCloseKey.call(key))
  345. end
  346. else
  347. return key
  348. end
  349. end
  350.  
  351. def self.close(hkey); check(RegCloseKey.call(hkey)) if hkey; end
  352.  
  353. def self.get(hkey,subkey,name,defaultValue=nil,bit64=false)
  354. self.open(hkey,subkey,bit64){|key|
  355. return self.read(key,name) rescue defaultValue
  356. }
  357. return defaultValue
  358. end
  359.  
  360. def self.read(hkey,name)
  361. hkey=0 if !hkey
  362. type=0.chr*4; size=0.chr*4
  363. check(RegQueryValueExA.call(hkey,name,0,type,0,size))
  364. data=" "*size.unpack("V")[0]
  365. check(RegQueryValueExA.call(hkey,name,0,type,data,size))
  366. type=type.unpack("V")[0]
  367. data=data[0,size.unpack("V")[0]]
  368. case type
  369. when 1; return data.chop # REG_SZ
  370. when 2; return data.gsub(/%([^%]+)%/) { ENV[$1] || $& } # REG_EXPAND_SZ
  371. when 3; return data # REG_BINARY
  372. when 4; return data.unpack("V")[0] # REG_DWORD
  373. when 5; return data.unpack("V")[0] # REG_DWORD_BIG_ENDIAN
  374. when 11; qw=data.unpack("VV"); return (data[1]<<32|data[0]) # REG_QWORD
  375. else; raise "Type #{type} not supported."
  376. end
  377. end
  378.  
  379. private
  380.  
  381. def self.check(code)
  382. if code!=0
  383. msg="\0"*1024
  384. len = FormatMessageA.call(0x1200, 0, code, 0, msg, 1024, 0)
  385. raise msg[0, len].tr("\r", '').chomp
  386. end
  387. end
  388. end
  389.  
  390.  
  391.  
  392. def getUnicodeStringFromAnsi(addr)
  393. return "" if addr==0
  394. rtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  395. ret=""
  396. data="x"
  397. index=(addr.is_a?(String)) ? 0 : addr
  398. loop do
  399. if addr.is_a?(String)
  400. data=addr[index,1]
  401. else
  402. rtlMoveMemory_pi.call(data, index, 1)
  403. end
  404. index+=1
  405. codepoint=data.unpack("C")[0]
  406. break if codepoint==0 || !codepoint
  407. break if codepoint==0
  408. if codepoint<=0x7F
  409. ret+=codepoint.chr
  410. else
  411. ret+=(0xC0|((codepoint>>6)&0x1F)).chr
  412. ret+=(0x80|(codepoint &0x3F)).chr
  413. end
  414. end
  415. return ret
  416. end
  417.  
  418. def getUnicodeString(addr)
  419. return "" if addr==0
  420. rtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  421. ret=""
  422. data="xx"
  423. index=(addr.is_a?(String)) ? 0 : addr
  424. loop do
  425. if addr.is_a?(String)
  426. data=addr[index,2]
  427. else
  428. rtlMoveMemory_pi.call(data, index, 2)
  429. end
  430. codepoint=data.unpack("v")[0]
  431. break if codepoint==0
  432. index+=2
  433. if codepoint<=0x7F
  434. ret+=codepoint.chr
  435. elsif codepoint<=0x7FF
  436. ret+=(0xC0|((codepoint>>6)&0x1F)).chr
  437. ret+=(0x80|(codepoint &0x3F)).chr
  438. elsif codepoint<=0xFFFF
  439. ret+=(0xE0|((codepoint>>12)&0x0F)).chr
  440. ret+=(0x80|((codepoint>>6)&0x3F)).chr
  441. ret+=(0x80|(codepoint &0x3F)).chr
  442. elsif codepoint<=0x10FFFF
  443. ret+=(0xF0|((codepoint>>18)&0x07)).chr
  444. ret+=(0x80|((codepoint>>12)&0x3F)).chr
  445. ret+=(0x80|((codepoint>>6)&0x3F)).chr
  446. ret+=(0x80|(codepoint &0x3F)).chr
  447. end
  448. end
  449. return ret
  450. end
  451.  
  452. def getKnownFolder(guid)
  453. packedGuid=guid.pack("VvvC*")
  454. shGetKnownFolderPath=Win32API.new("shell32.dll","SHGetKnownFolderPath","pllp","i") rescue nil
  455. coTaskMemFree=Win32API.new("ole32.dll","CoTaskMemFree","i","") rescue nil
  456. if shGetKnownFolderPath && coTaskMemFree
  457. path="\0"*4
  458. ret=shGetKnownFolderPath.call(packedGuid,0,0,path)
  459. path=path.unpack("V")[0]
  460. ret=getUnicodeString(path)
  461. coTaskMemFree.call(path)
  462. return ret
  463. end
  464. return ""
  465. end
  466.  
  467.  
  468.  
  469. module RTP
  470. @rtpPaths=nil
  471.  
  472. def self.exists?(filename,extensions=[])
  473. return false if !filename || filename==""
  474. eachPathFor(filename) {|path|
  475. return true if safeExists?(path)
  476. for ext in extensions
  477. return true if safeExists?(path+ext)
  478. end
  479. }
  480. return false
  481. end
  482.  
  483. def self.getImagePath(filename)
  484. return self.getPath(filename,["",".png",".jpg",".gif",".bmp",".jpeg"])
  485. end
  486.  
  487. def self.getAudioPath(filename)
  488. return self.getPath(filename,["",".mp3",".wav",".wma",".mid",".ogg",".midi"])
  489. end
  490.  
  491. def self.getPath(filename,extensions=[])
  492. return filename if !filename || filename==""
  493. eachPathFor(filename) {|path|
  494. return path if safeExists?(path)
  495. for ext in extensions
  496. file=path+ext
  497. return file if safeExists?(file)
  498. end
  499. }
  500. return filename
  501. end
  502.  
  503. # Gets the absolute RGSS paths for the given file name
  504. def self.eachPathFor(filename)
  505. return if !filename
  506. if filename[/^[A-Za-z]\:[\/\\]/] || filename[/^[\/\\]/]
  507. # filename is already absolute
  508. yield filename
  509. else
  510. # relative path
  511. RTP.eachPath {|path|
  512. if path=="./"
  513. yield filename
  514. else
  515. yield path+filename
  516. end
  517. }
  518. end
  519. end
  520.  
  521. # Gets all RGSS search paths
  522. def self.eachPath
  523. # XXX: Use "." instead of Dir.pwd because of problems retrieving files if
  524. # the current directory contains an accent mark
  525. yield ".".gsub(/[\/\\]/,"/").gsub(/[\/\\]$/,"")+"/"
  526. if !@rtpPaths
  527. tmp=Sprite.new
  528. isRgss2=tmp.respond_to?("wave_amp")
  529. tmp.dispose
  530. @rtpPaths=[]
  531. if isRgss2
  532. rtp=getGameIniValue("Game","RTP")
  533. if rtp!=""
  534. rtp=MiniRegistry.get(MiniRegistry::HKEY_LOCAL_MACHINE,
  535. "SOFTWARE\\Enterbrain\\RGSS2\\RTP",rtp,nil)
  536. if rtp && safeIsDirectory?(rtp)
  537. @rtpPaths.push(rtp.sub(/[\/\\]$/,"")+"/")
  538. end
  539. end
  540. else
  541. %w( RTP1 RTP2 RTP3 ).each{|v|
  542. rtp=getGameIniValue("Game",v)
  543. if rtp!=""
  544. rtp=MiniRegistry.get(MiniRegistry::HKEY_LOCAL_MACHINE,
  545. "SOFTWARE\\Enterbrain\\RGSS\\RTP",rtp,nil)
  546. if rtp && safeIsDirectory?(rtp)
  547. @rtpPaths.push(rtp.sub(/[\/\\]$/,"")+"/")
  548. end
  549. end
  550. }
  551. end
  552. end
  553. @rtpPaths.each{|x| yield x }
  554. end
  555.  
  556. private
  557.  
  558. def self.getGameIniValue(section,key)
  559. val = "\0"*256
  560. gps = Win32API.new('kernel32', 'GetPrivateProfileString',%w(p p p p l p), 'l')
  561. gps.call(section, key, "", val, 256, ".\\Game.ini")
  562. val.delete!("\0")
  563. return val
  564. end
  565.  
  566. @@folder=nil
  567.  
  568. def self.isDirWritable(dir)
  569. return false if !dir || dir==""
  570. loop do
  571. name=dir.gsub(/[\/\\]$/,"")+"/writetest"
  572. for i in 0...12
  573. name+=sprintf("%02X",rand(256))
  574. end
  575. name+=".tmp"
  576. if !safeExists?(name)
  577. retval=false
  578. begin
  579. File.open(name,"wb"){retval=true}
  580. rescue Errno::EINVAL, Errno::EACCES, Errno::ENOENT
  581. ensure
  582. File.delete(name) rescue nil
  583. end
  584. return retval
  585. end
  586. end
  587. end
  588.  
  589. def self.ensureGameDir(dir)
  590. title=RTP.getGameIniValue("Game","Title")
  591. title="RGSS Game" if title==""
  592. title=title.gsub(/[^\w ]/,"_")
  593. newdir=dir.gsub(/[\/\\]$/,"")+"/"
  594. # Convert to UTF-8 because of ANSI function
  595. newdir+=getUnicodeStringFromAnsi(title)
  596. Dir.mkdir(newdir) rescue nil
  597. ret=safeIsDirectory?(newdir) ? newdir : dir
  598. return ret
  599. end
  600.  
  601. def self.getSaveFileName(fileName)
  602. return getSaveFolder().gsub(/[\/\\]$/,"")+"/"+fileName
  603. end
  604.  
  605. def self.getSaveFolder
  606. if !@@folder
  607. # XXX: Use "." instead of Dir.pwd because of problems retrieving files if
  608. # the current directory contains an accent mark
  609. pwd="."
  610. # Get the known folder path for saved games
  611. savedGames=getKnownFolder([0x4c5c32ff,0xbb9d,0x43b0,
  612. 0xb5,0xb4,0x2d,0x72,0xe5,0x4e,0xaa,0xa4])
  613. if savedGames && savedGames!="" && isDirWritable(savedGames)
  614. pwd=ensureGameDir(savedGames)
  615. end
  616. if isDirWritable(pwd)
  617. @@folder=pwd
  618. else
  619. appdata=ENV["LOCALAPPDATA"]
  620. if isDirWritable(appdata)
  621. appdata=ensureGameDir(appdata)
  622. else
  623. appdata=ENV["APPDATA"]
  624. if isDirWritable(appdata)
  625. appdata=ensureGameDir(appdata)
  626. elsif isDirWritable(pwd)
  627. appdata=pwd
  628. else
  629. appdata="."
  630. end
  631. end
  632. @@folder=appdata
  633. end
  634. end
  635. return @@folder
  636. end
  637. end
  638.  
  639.  
  640.  
  641. module FileTest
  642. Image_ext = ['.bmp', '.png', '.jpg', '.jpeg', '.gif']
  643. Audio_ext = ['.mp3', '.mid', '.midi', '.ogg', '.wav', '.wma']
  644.  
  645. def self.audio_exist?(filename)
  646. return RTP.exists?(filename,Audio_ext)
  647. end
  648.  
  649. def self.image_exist?(filename)
  650. return RTP.exists?(filename,Image_ext)
  651. end
  652. end
  653.  
  654.  
  655. ###########
  656.  
  657.  
  658. class PngAnimatedBitmap # :nodoc:
  659. # Creates an animated bitmap from a PNG file.
  660. def initialize(file,hue=0)
  661. @frames=[]
  662. @currentFrame=0
  663. @framecount=0
  664. panorama=BitmapCache.load_bitmap(file,hue)
  665. if file[/^\[(\d+)\]/] # Starts with 1 or more digits in brackets
  666. # File has a frame count
  667. numFrames=$1.to_i
  668. if numFrames<=0
  669. raise "Invalid frame count in #{file}"
  670. end
  671. if panorama.width % numFrames != 0
  672. raise "Bitmap's width (#{panorama.width}) is not divisible by frame count: #{file}"
  673. end
  674. subWidth=panorama.width/numFrames
  675. for i in 0...numFrames
  676. subBitmap=BitmapWrapper.new(subWidth,panorama.height)
  677. subBitmap.blt(0,0,panorama,Rect.new(subWidth*i,0,subWidth,panorama.height))
  678. @frames.push(subBitmap)
  679. end
  680. panorama.dispose
  681. else
  682. @frames=[panorama]
  683. end
  684. end
  685.  
  686. def [](index)
  687. return @frames[index]
  688. end
  689.  
  690. def width; self.bitmap.width; end
  691.  
  692. def height; self.bitmap.height; end
  693.  
  694. def deanimate
  695. for i in 1...@frames.length
  696. @frames[i].dispose
  697. end
  698. @frames=[@frames[0]]
  699. @currentFrame=0
  700. return @frames[0]
  701. end
  702.  
  703. def bitmap
  704. @frames[@currentFrame]
  705. end
  706.  
  707. def currentIndex
  708. @currentFrame
  709. end
  710.  
  711. def frameDelay(index)
  712. return 10
  713. end
  714.  
  715. def length
  716. @frames.length
  717. end
  718.  
  719. def each
  720. @frames.each {|item| yield item}
  721. end
  722.  
  723. def totalFrames
  724. 10*@frames.length
  725. end
  726.  
  727. def disposed?
  728. @disposed
  729. end
  730.  
  731. def update
  732. return if disposed?
  733. if @frames.length>1
  734. @framecount+=1
  735. if @framecount>=10
  736. @framecount=0
  737. @currentFrame+=1
  738. @currentFrame%=@frames.length
  739. end
  740. end
  741. end
  742.  
  743. def dispose
  744. if !@disposed
  745. for i in @frames
  746. i.dispose
  747. end
  748. end
  749. @disposed=true
  750. end
  751.  
  752. attr_accessor :frames # internal
  753.  
  754. def copy
  755. x=self.clone
  756. x.frames=x.frames.clone
  757. for i in 0...x.frames.length
  758. x.frames[i]=x.frames[i].copy
  759. end
  760. return x
  761. end
  762. end
  763.  
  764.  
  765.  
  766. #internal class
  767. class GifBitmap
  768. # Creates a bitmap from a GIF file with the specified
  769. # optional viewport. Can also load non-animated bitmaps.
  770. def initialize(file,hue=0)
  771. @gifbitmaps=[]
  772. @gifdelays=[]
  773. @totalframes=0
  774. @framecount=0
  775. @currentIndex=0
  776. @disposed=false
  777. bitmap=nil
  778. filestring=nil
  779. filestrName=nil
  780. file="" if !file
  781. file=canonicalize(file)
  782. begin
  783. bitmap=BitmapCache.load_bitmap(file,hue)
  784. rescue
  785. bitmap=nil
  786. end
  787. if !bitmap || (bitmap.width==32 && bitmap.height==32)
  788. if !file || file.length<1 || file[file.length-1]!=0x2F
  789. if (filestring=pbGetFileChar(file))
  790. filestrName=file
  791. elsif (filestring=pbGetFileChar(file+".gif"))
  792. filestrName=file+".gif"
  793. elsif (filestring=pbGetFileChar(file+".png"))
  794. filestrName=file+".png"
  795. elsif (filestring=pbGetFileChar(file+".jpg"))
  796. filestrName=file+".jpg"
  797. elsif (filestring=pbGetFileChar(file+".bmp"))
  798. filestrName=file+".bmp"
  799. end
  800. end
  801. end
  802. if bitmap && filestring && filestring[0]==0x47 &&
  803. bitmap.width==32 && bitmap.height==32
  804. #File.open("debug.txt","ab"){|f| f.puts("rejecting bitmap") }
  805. bitmap.dispose
  806. bitmap=nil
  807. end
  808. if bitmap
  809. #File.open("debug.txt","ab"){|f| f.puts("reusing bitmap") }
  810. # Have a regular non-animated bitmap
  811. @totalframes=1
  812. @framecount=0
  813. @gifbitmaps=[bitmap]
  814. @gifdelays=[1]
  815. else
  816. tmpBase=File.basename(file)+"_tmp_"
  817. filestring=pbGetFileString(filestrName) if filestring
  818. Dir.chdir(ENV["TEMP"]){ # navigate to temp folder since game might be on a CD-ROM
  819. if filestring && filestring[0]==0x47 && GifLibrary::PngDll
  820. result=GifLibrary::GifToPngFilesInMemory.call(filestring,
  821. filestring.length,tmpBase)
  822. else
  823. result=0
  824. end
  825. if result>0
  826. @gifdelays=GifLibrary.getDataFromResult(result)
  827. @totalframes=@gifdelays.pop
  828. for i in 0...@gifdelays.length
  829. @gifdelays[i]=[@gifdelays[i],1].max
  830. bmfile=sprintf("%s%d.png",tmpBase,i)
  831. if safeExists?(bmfile)
  832. gifbitmap=BitmapWrapper.new(bmfile)
  833. @gifbitmaps.push(gifbitmap)
  834. bmfile.hue_change(hue) if hue!=0
  835. if hue==0 && @gifdelays.length==1
  836. BitmapCache.setKey(file,gifbitmap)
  837. end
  838. File.delete(bmfile)
  839. else
  840. @gifbitmaps.push(BitmapWrapper.new(32,32))
  841. end
  842. end
  843. end
  844. }
  845. if @gifbitmaps.length==0
  846. @gifbitmaps=[BitmapWrapper.new(32,32)]
  847. @gifdelays=[1]
  848. end
  849. if @gifbitmaps.length==1
  850. BitmapCache.setKey(file,@gifbitmaps[0])
  851. end
  852. end
  853. end
  854.  
  855. def [](index)
  856. return @gifbitmaps[index]
  857. end
  858.  
  859. def width; self.bitmap.width; end
  860.  
  861. def height; self.bitmap.height; end
  862.  
  863. def deanimate
  864. for i in 1...@gifbitmaps.length
  865. @gifbitmaps[i].dispose
  866. end
  867. @gifbitmaps=[@gifbitmaps[0]]
  868. @currentIndex=0
  869. return @gifbitmaps[0]
  870. end
  871.  
  872. def bitmap
  873. @gifbitmaps[@currentIndex]
  874. end
  875.  
  876. def currentIndex
  877. @currentIndex
  878. end
  879.  
  880. def frameDelay(index)
  881. return @gifdelay[index]/2 # Due to frame count being incremented by 2
  882. end
  883.  
  884. def length
  885. @gifbitmaps.length
  886. end
  887.  
  888. def each
  889. @gifbitmaps.each {|item| yield item }
  890. end
  891.  
  892. def totalFrames
  893. @totalframes/2 # Due to frame count being incremented by 2
  894. end
  895.  
  896. def disposed?
  897. @disposed
  898. end
  899.  
  900. def width
  901. @gifbitmaps.length==0 ? 0 : @gifbitmaps[0].width
  902. end
  903.  
  904. def height
  905. @gifbitmaps.length==0 ? 0 : @gifbitmaps[0].height
  906. end
  907.  
  908. # This function must be called in order to animate the GIF image.
  909. def update
  910. return if disposed?
  911. if @gifbitmaps.length>0
  912. @framecount+=2
  913. @framecount=@totalframes<=0 ? 0 : @framecount%@totalframes
  914. frametoshow=0
  915. for i in 0...@gifdelays.length
  916. frametoshow=i if @gifdelays[i]<=@framecount
  917. end
  918. @currentIndex=frametoshow
  919. end
  920. end
  921.  
  922. def dispose
  923. if !@disposed
  924. for i in @gifbitmaps
  925. i.dispose
  926. end
  927. end
  928. @disposed=true
  929. end
  930.  
  931. attr_accessor :gifbitmaps # internal
  932. attr_accessor :gifdelays # internal
  933.  
  934. def copy
  935. x=self.clone
  936. x.gifbitmaps=x.gifbitmaps.clone
  937. x.gifdelays=x.gifdelays.clone
  938. for i in 0...x.gifbitmaps.length
  939. x.gifbitmaps[i]=x.gifbitmaps[i].copy
  940. end
  941. return x
  942. end
  943. end
  944.  
  945.  
  946. #########################
  947.  
  948.  
  949. def pbDrawShadow(bitmap,x,y,width,height,string)
  950. return if !bitmap || !string
  951. pbDrawShadowText(bitmap,x,y,width,height,string,nil,bitmap.font.color)
  952. end
  953.  
  954. def pbDrawShadowText(bitmap,x,y,width,height,string,baseColor,shadowColor=nil,align=0)
  955. return if !bitmap || !string
  956. width=(width<0) ? bitmap.text_size(string).width+4 : width
  957. height=(height<0) ? bitmap.text_size(string).height+4 : height
  958. if shadowColor
  959. bitmap.font.color=shadowColor
  960. bitmap.draw_text(x+2,y,width,height,string,align)
  961. bitmap.draw_text(x,y+2,width,height,string,align)
  962. bitmap.draw_text(x+2,y+2,width,height,string,align)
  963. end
  964. if baseColor
  965. bitmap.font.color=baseColor
  966. bitmap.draw_text(x,y,width,height,string,align)
  967. end
  968. end
  969.  
  970. def pbDrawOutlineText(bitmap,x,y,width,height,string,baseColor,shadowColor=nil,align=0)
  971. return if !bitmap || !string
  972. width=(width<0) ? bitmap.text_size(string).width+4 : width
  973. height=(height<0) ? bitmap.text_size(string).height+4 : height
  974. if shadowColor
  975. bitmap.font.color=shadowColor
  976. bitmap.draw_text(x-2,y-2,width,height,string,align)
  977. bitmap.draw_text(x,y-2,width,height,string,align)
  978. bitmap.draw_text(x+2,y-2,width,height,string,align)
  979. bitmap.draw_text(x-2,y,width,height,string,align)
  980. bitmap.draw_text(x+2,y,width,height,string,align)
  981. bitmap.draw_text(x-2,y+2,width,height,string,align)
  982. bitmap.draw_text(x,y+2,width,height,string,align)
  983. bitmap.draw_text(x+2,y+2,width,height,string,align)
  984. end
  985. if baseColor
  986. bitmap.font.color=baseColor
  987. bitmap.draw_text(x,y,width,height,string,align)
  988. end
  989. end
  990.  
  991. def pbCopyBitmap(dstbm,srcbm,x,y,opacity=255)
  992. rc=Rect.new(0,0,srcbm.width,srcbm.height)
  993. dstbm.blt(x,y,srcbm,rc,opacity)
  994. end
  995.  
  996. def using(window)
  997. begin
  998. yield if block_given?
  999. ensure
  1000. window.dispose
  1001. end
  1002. end
  1003.  
  1004. def pbBottomRight(window)
  1005. window.x=Graphics.width-window.width
  1006. window.y=Graphics.height-window.height
  1007. end
  1008.  
  1009. def pbBottomLeft(window)
  1010. window.x=0
  1011. window.y=Graphics.height-window.height
  1012. end
  1013.  
  1014. def pbBottomLeftLines(window,lines,width=nil)
  1015. window.x=0
  1016. window.width=width ? width : Graphics.width
  1017. window.height=(window.borderY rescue 32)+lines*32
  1018. window.y=Graphics.height-window.height
  1019. end
  1020.  
  1021. def pbDisposed?(x)
  1022. return true if !x
  1023. if x.is_a?(Viewport)
  1024. begin
  1025. x.rect=x.rect
  1026. rescue
  1027. return true
  1028. end
  1029. return false
  1030. else
  1031. return x.disposed?
  1032. end
  1033. end
  1034.  
  1035. def isDarkBackground(background,rect=nil)
  1036. if !background || background.disposed?
  1037. return true
  1038. end
  1039. rect=background.rect if !rect
  1040. if rect.width<=0 || rect.height<=0
  1041. return true
  1042. end
  1043. xSeg=(rect.width/16)
  1044. xLoop=(xSeg==0) ? 1 : 16
  1045. xStart=(xSeg==0) ? rect.x+(rect.width/2) : rect.x+xSeg/2
  1046. ySeg=(rect.height/16)
  1047. yLoop=(ySeg==0) ? 1 : 16
  1048. yStart=(ySeg==0) ? rect.y+(rect.height/2) : rect.y+ySeg/2
  1049. count=0
  1050. y=yStart
  1051. r=0; g=0; b=0
  1052. yLoop.times {
  1053. x=xStart
  1054. xLoop.times {
  1055. clr=background.get_pixel(x,y)
  1056. if clr.alpha!=0
  1057. r+=clr.red; g+=clr.green; b+=clr.blue
  1058. count+=1
  1059. end
  1060. x+=xSeg
  1061. }
  1062. y+=ySeg
  1063. }
  1064. return true if count==0
  1065. r/=count
  1066. g/=count
  1067. b/=count
  1068. return (r*0.299+g*0.587+b*0.114)<128
  1069. end
  1070.  
  1071. def isDarkWindowskin(windowskin)
  1072. if !windowskin || windowskin.disposed?
  1073. return true
  1074. end
  1075. if windowskin.width==192 && windowskin.height==128
  1076. return isDarkBackground(windowskin,Rect.new(0,0,128,128))
  1077. elsif windowskin.width==128 && windowskin.height==128
  1078. return isDarkBackground(windowskin,Rect.new(0,0,64,64))
  1079. else
  1080. clr=windowskin.get_pixel(windowskin.width/2, windowskin.height/2)
  1081. return (clr.red*0.299+clr.green*0.587+clr.blue*0.114)<128
  1082. end
  1083. end
  1084.  
  1085. def getDefaultTextColors(windowskin)
  1086. if !windowskin || windowskin.disposed? ||
  1087. windowskin.width!=128 || windowskin.height!=128
  1088. if isDarkWindowskin(windowskin)
  1089. return [MessageConfig::LIGHTTEXTBASE,MessageConfig::LIGHTTEXTSHADOW] # White
  1090. else
  1091. return [MessageConfig::DARKTEXTBASE,MessageConfig::DARKTEXTSHADOW] # Dark gray
  1092. end
  1093. else # VX windowskin
  1094. color=windowskin.get_pixel(64, 96)
  1095. shadow=nil
  1096. isdark=(color.red+color.green+color.blue)/3 < 128
  1097. if isdark
  1098. shadow=Color.new(color.red+64,color.green+64,color.blue+64)
  1099. else
  1100. shadow=Color.new(color.red-64,color.green-64,color.blue-64)
  1101. end
  1102. return [color,shadow]
  1103. end
  1104. end
  1105.  
  1106. def pbDoEnsureBitmap(bitmap,dwidth,dheight)
  1107. if !bitmap || bitmap.disposed? || bitmap.width<dwidth || bitmap.height<dheight
  1108. oldfont=(bitmap && !bitmap.disposed?) ? bitmap.font : nil
  1109. bitmap.dispose if bitmap
  1110. bitmap=Bitmap.new([1,dwidth].max,[1,dheight].max)
  1111. if !oldfont
  1112. pbSetSystemFont(bitmap)
  1113. else
  1114. bitmap.font=oldfont
  1115. end
  1116. if bitmap.font && bitmap.font.respond_to?("shadow")
  1117. bitmap.font.shadow=false
  1118. end
  1119. end
  1120. return bitmap
  1121. end
  1122.  
  1123. def pbUpdateSpriteHash(windows)
  1124. for i in windows
  1125. window=i[1]
  1126. if window
  1127. if window.is_a?(Sprite) || window.is_a?(Window)
  1128. window.update if !pbDisposed?(window)
  1129. elsif window.is_a?(Plane)
  1130. begin
  1131. window.update if !window.disposed?
  1132. rescue NoMethodError
  1133. end
  1134. elsif window.respond_to?("update")
  1135. begin
  1136. window.update
  1137. rescue RGSSError
  1138. end
  1139. end
  1140. end
  1141. end
  1142. end
  1143.  
  1144. # Disposes all objects in the specified hash.
  1145. def pbDisposeSpriteHash(sprites)
  1146. if sprites
  1147. for i in sprites.keys
  1148. pbDisposeSprite(sprites,i)
  1149. end
  1150. sprites.clear
  1151. end
  1152. end
  1153.  
  1154. # Disposes the specified graphics object within the specified hash. Basically like:
  1155. # sprites[id].dispose
  1156. def pbDisposeSprite(sprites,id)
  1157. sprite=sprites[id]
  1158. if sprite && !pbDisposed?(sprite)
  1159. sprite.dispose
  1160. end
  1161. sprites[id]=nil
  1162. end
  1163.  
  1164. # Draws text on a bitmap. _textpos_ is an array
  1165. # of text commands. Each text command is an array
  1166. # that contains the following:
  1167. # 0 - Text to draw
  1168. # 1 - X coordinate
  1169. # 2 - Y coordinate
  1170. # 3 - If true or 1, the text is right aligned. If 2, the text is centered.
  1171. # Otherwise, the text is left aligned.
  1172. # 4 - Base color
  1173. # 5 - Shadow color
  1174. def pbDrawTextPositions(bitmap,textpos)
  1175. for i in textpos
  1176. textsize=bitmap.text_size(i[0])
  1177. x=i[1]
  1178. y=i[2]
  1179. if i[3]==true || i[3]==1 # right align
  1180. x-=textsize.width
  1181. elsif i[3]==2 # centered
  1182. x-=(textsize.width/2)
  1183. end
  1184. if i[6]==true || i[6]==1 # outline text
  1185. pbDrawOutlineText(bitmap,x,y,textsize.width,textsize.height,i[0],i[4],i[5])
  1186. else
  1187. pbDrawShadowText(bitmap,x,y,textsize.width,textsize.height,i[0],i[4],i[5])
  1188. end
  1189. end
  1190. end
  1191.  
  1192. #Summary font
  1193. def pbDrawSummaryText(bitmap,textpos)
  1194. for i in textpos
  1195. textsize=bitmap.text_size(i[0])
  1196. bitmap.font.name = "PF Tempesta Seven"
  1197. bitmap.font.size = 24
  1198. x=i[1]
  1199. y=i[2]
  1200. if i[3]==true || i[3]==1 # right align
  1201. x-=textsize.width
  1202. elsif i[3]==2 # centered
  1203. x-=(textsize.width/2)
  1204. end
  1205. if i[6]==true || i[6]==1 # outline text
  1206. pbDrawOutlineText(bitmap,x,y,textsize.width,textsize.height,i[0],i[4],i[5])
  1207. else
  1208. pbDrawShadowText(bitmap,x,y,textsize.width,textsize.height,i[0],i[4],i[5])
  1209. end
  1210. end
  1211. end
  1212.  
  1213. #Party font
  1214. def pbDrawPartyText(bitmap,textpos)
  1215. for i in textpos
  1216. textsize=bitmap.text_size(i[0])
  1217. bitmap.font.name = "PF Tempesta Seven"
  1218. bitmap.font.size = 24
  1219. x=i[1]
  1220. y=i[2]
  1221. if i[3]==true || i[3]==1 # right align
  1222. x-=textsize.width
  1223. elsif i[3]==2 # centered
  1224. x-=(textsize.width/2)
  1225. end
  1226. if i[6]==true || i[6]==1 # outline text
  1227. pbDrawOutlineText(bitmap,x,y,textsize.width,textsize.height,i[0],i[4],i[5])
  1228. else
  1229. pbDrawShadowText(bitmap,x,y,textsize.width,textsize.height,i[0],i[4],i[5])
  1230. end
  1231. end
  1232. end
  1233.  
  1234. def pbDrawImagePositions(bitmap,textpos)
  1235. for i in textpos
  1236. srcbitmap=AnimatedBitmap.new(pbBitmapName(i[0]))
  1237. x=i[1]
  1238. y=i[2]
  1239. srcx=i[3]
  1240. srcy=i[4]
  1241. width=i[5]>=0 ? i[5] : srcbitmap.width
  1242. height=i[6]>=0 ? i[6] : srcbitmap.height
  1243. srcrect=Rect.new(srcx,srcy,width,height)
  1244. bitmap.blt(x,y,srcbitmap.bitmap,srcrect)
  1245. srcbitmap.dispose
  1246. end
  1247. end
  1248.  
  1249.  
  1250.  
  1251. class Game_Temp
  1252. attr_accessor :fadestate
  1253.  
  1254. def fadestate
  1255. return @fadestate ? @fadestate : 0
  1256. end
  1257. end
  1258.  
  1259.  
  1260.  
  1261. def pbPushFade
  1262. if $game_temp
  1263. $game_temp.fadestate=[$game_temp.fadestate+1,0].max
  1264. end
  1265. end
  1266.  
  1267. def pbPopFade
  1268. if $game_temp
  1269. $game_temp.fadestate=[$game_temp.fadestate-1,0].max
  1270. end
  1271. end
  1272.  
  1273. def pbIsFaded?
  1274. if $game_temp
  1275. return $game_temp.fadestate>0
  1276. else
  1277. return false
  1278. end
  1279. end
  1280.  
  1281. # pbFadeOutIn(z) { block }
  1282. # Fades out the screen before a block is run and fades it back in after the
  1283. # block exits. z indicates the z-coordinate of the viewport used for this effect
  1284. def pbFadeOutIn(z,nofadeout=false)
  1285. col=Color.new(0,0,0,0)
  1286. viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
  1287. viewport.z=z
  1288. for j in 0..17
  1289. col.set(0,0,0,j*15)
  1290. viewport.color=col
  1291. Graphics.update
  1292. Input.update
  1293. end
  1294. pbPushFade
  1295. begin
  1296. yield if block_given?
  1297. ensure
  1298. pbPopFade
  1299. if !nofadeout
  1300. for j in 0..17
  1301. col.set(0,0,0,(17-j)*15)
  1302. viewport.color=col
  1303. Graphics.update
  1304. Input.update
  1305. end
  1306. end
  1307. viewport.dispose
  1308. end
  1309. end
  1310.  
  1311. def pbFadeOutAndHide(sprites)
  1312. visiblesprites={}
  1313. pbDeactivateWindows(sprites){
  1314. for j in 0..17
  1315. pbSetSpritesToColor(sprites,Color.new(0,0,0,j*15))
  1316. block_given? ? yield : pbUpdateSpriteHash(sprites)
  1317. end
  1318. }
  1319. for i in sprites
  1320. next if !i[1]
  1321. next if pbDisposed?(i[1])
  1322. visiblesprites[i[0]]=true if i[1].visible
  1323. i[1].visible=false
  1324. end
  1325. return visiblesprites
  1326. end
  1327.  
  1328. def pbFadeInAndShow(sprites,visiblesprites=nil)
  1329. if visiblesprites
  1330. for i in visiblesprites
  1331. if i[1] && sprites[i[0]] && !pbDisposed?(sprites[i[0]])
  1332. sprites[i[0]].visible=true
  1333. end
  1334. end
  1335. end
  1336. pbDeactivateWindows(sprites){
  1337. for j in 0..17
  1338. pbSetSpritesToColor(sprites,Color.new(0,0,0,((17-j)*15)))
  1339. block_given? ? yield : pbUpdateSpriteHash(sprites)
  1340. end
  1341. }
  1342. end
  1343.  
  1344. # Restores which windows are active for the given sprite hash.
  1345. # _activeStatuses_ is the result of a previous call to pbActivateWindows
  1346. def pbRestoreActivations(sprites,activeStatuses)
  1347. return if !sprites || !activeStatuses
  1348. for k in activeStatuses.keys
  1349. if sprites[k] && sprites[k].is_a?(Window) && !pbDisposed?(sprites[k])
  1350. sprites[k].active=activeStatuses[k] ? true : false
  1351. end
  1352. end
  1353. end
  1354.  
  1355. # Deactivates all windows. If a code block is given, deactivates all windows,
  1356. # runs the code in the block, and reactivates them.
  1357. def pbDeactivateWindows(sprites)
  1358. if block_given?
  1359. pbActivateWindow(sprites,nil) { yield }
  1360. else
  1361. pbActivateWindow(sprites,nil)
  1362. end
  1363. end
  1364.  
  1365. # Activates a specific window of a sprite hash. _key_ is the key of the window
  1366. # in the sprite hash. If a code block is given, deactivates all windows except
  1367. # the specified window, runs the code in the block, and reactivates them.
  1368. def pbActivateWindow(sprites,key)
  1369. return if !sprites
  1370. activeStatuses={}
  1371. for i in sprites
  1372. if i[1] && i[1].is_a?(Window) && !pbDisposed?(i[1])
  1373. activeStatuses[i[0]]=i[1].active
  1374. i[1].active=(i[0]==key)
  1375. end
  1376. end
  1377. if block_given?
  1378. begin
  1379. yield
  1380. ensure
  1381. pbRestoreActivations(sprites,activeStatuses)
  1382. end
  1383. return {}
  1384. else
  1385. return activeStatuses
  1386. end
  1387. end
  1388.  
  1389. def pbAlphaBlend(dstColor,srcColor)
  1390. r=(255*(srcColor.red-dstColor.red)/255)+dstColor.red
  1391. g=(255*(srcColor.green-dstColor.green)/255)+dstColor.green
  1392. b=(255*(srcColor.blue-dstColor.blue)/255)+dstColor.blue
  1393. a=(255*(srcColor.alpha-dstColor.alpha)/255)+dstColor.alpha
  1394. return Color.new(r,g,b,a)
  1395. end
  1396.  
  1397. def pbSrcOver(dstColor,srcColor)
  1398. er=srcColor.red*srcColor.alpha/255
  1399. eg=srcColor.green*srcColor.alpha/255
  1400. eb=srcColor.blue*srcColor.alpha/255
  1401. iea=255-srcColor.alpha
  1402. cr=dstColor.red*dstColor.alpha/255
  1403. cg=dstColor.green*dstColor.alpha/255
  1404. cb=dstColor.blue*dstColor.alpha/255
  1405. ica=255-dstColor.alpha
  1406. a=255-(iea*ica)/255
  1407. r=(iea*cr)/255+er
  1408. g=(iea*cg)/255+eg
  1409. b=(iea*cb)/255+eb
  1410. r=(a==0) ? 0 : r*255/a
  1411. g=(a==0) ? 0 : g*255/a
  1412. b=(a==0) ? 0 : b*255/a
  1413. return Color.new(r,g,b,a)
  1414. end
  1415.  
  1416. def pbSetSpritesToColor(sprites,color)
  1417. return if !sprites || !color
  1418. colors={}
  1419. for i in sprites
  1420. next if !i[1] || pbDisposed?(i[1])
  1421. colors[i[0]]=i[1].color.clone
  1422. i[1].color=pbSrcOver(i[1].color,color)
  1423. end
  1424. Graphics.update
  1425. Input.update
  1426. for i in colors
  1427. next if !sprites[i[0]]
  1428. sprites[i[0]].color=i[1]
  1429. end
  1430. end
  1431.  
  1432. def pbTryString(x)
  1433. ret=pbGetFileChar(x)
  1434. return (ret!=nil && ret!="") ? x : nil
  1435. end
  1436.  
  1437. # Finds the real path for an image file. This includes paths in encrypted
  1438. # archives. Returns _x_ if the path can't be found.
  1439. def pbBitmapName(x)
  1440. ret=pbResolveBitmap(x)
  1441. return ret ? ret : x
  1442. end
  1443.  
  1444. # Finds the real path for an image file. This includes paths in encrypted
  1445. # archives. Returns nil if the path can't be found.
  1446. def pbResolveBitmap(x)
  1447. return nil if !x
  1448. noext=x.gsub(/\.(bmp|png|gif|jpg|jpeg)$/,"")
  1449. filename=nil
  1450. # RTP.eachPathFor(x) {|path|
  1451. # filename=pbTryString(path) if !filename
  1452. # filename=pbTryString(path+".gif") if !filename
  1453. # }
  1454. RTP.eachPathFor(noext) {|path|
  1455. filename=pbTryString(path+".png") if !filename
  1456. filename=pbTryString(path+".gif") if !filename
  1457. # filename=pbTryString(path+".jpg") if !filename
  1458. # filename=pbTryString(path+".jpeg") if !filename
  1459. # filename=pbTryString(path+".bmp") if !filename
  1460. }
  1461. return filename
  1462. end
  1463.  
  1464. # Adds a background to the sprite hash.
  1465. # _planename_ is the hash key of the background.
  1466. # _background_ is a filename within the Graphics/Pictures/ folder and can be
  1467. # an animated image.
  1468. # _viewport_ is a viewport to place the background in.
  1469. def addBackgroundPlane(sprites,planename,background,viewport=nil)
  1470. sprites[planename]=AnimatedPlane.new(viewport)
  1471. bitmapName=pbResolveBitmap("Graphics/Pictures/#{background}")
  1472. if bitmapName==nil
  1473. # Plane should exist in any case
  1474. sprites[planename].bitmap=nil
  1475. sprites[planename].visible=false
  1476. else
  1477. sprites[planename].setBitmap(bitmapName)
  1478. for spr in sprites.values
  1479. if spr.is_a?(Window)
  1480. spr.windowskin=nil
  1481. end
  1482. end
  1483. end
  1484. end
  1485.  
  1486. # Adds a background to the sprite hash.
  1487. # _planename_ is the hash key of the background.
  1488. # _background_ is a filename within the Graphics/Pictures/ folder and can be
  1489. # an animated image.
  1490. # _color_ is the color to use if the background can't be found.
  1491. # _viewport_ is a viewport to place the background in.
  1492. def addBackgroundOrColoredPlane(sprites,planename,background,color,viewport=nil)
  1493. bitmapName=pbResolveBitmap("Graphics/Pictures/#{background}")
  1494. if bitmapName==nil
  1495. # Plane should exist in any case
  1496. sprites[planename]=ColoredPlane.new(color,@viewport)
  1497. else
  1498. sprites[planename]=AnimatedPlane.new(viewport)
  1499. sprites[planename].setBitmap(bitmapName)
  1500. for spr in sprites.values
  1501. if spr.is_a?(Window)
  1502. spr.windowskin=nil
  1503. end
  1504. end
  1505. end
  1506. end
  1507.  
  1508. # Sets a bitmap's font to the system font.
  1509. def pbSetSystemFont(bitmap)
  1510. fontname=MessageConfig.pbGetSystemFontName()
  1511. bitmap.font.name=fontname
  1512. if fontname=="Pokemon FireLeaf" || fontname=="Power Red and Green"
  1513. bitmap.font.size=29
  1514. elsif fontname=="Pokemon Emerald Small" || fontname=="Power Green Small"
  1515. bitmap.font.size=25
  1516. else
  1517. bitmap.font.size=31
  1518. end
  1519. end
  1520.  
  1521. #Custom Party Font
  1522. # Sets a bitmap's font to the party font.
  1523. def pbSetPartyFont(bitmap)
  1524. fontname=MessageConfig.pbGetSystemFontName()
  1525. bitmap.font.name=fontname
  1526. if fontname=="PF Tempesta Seven" || fontname=="Arial"
  1527. bitmap.font.size=16
  1528. end
  1529. end
  1530.  
  1531. # Gets the name of the system small font.
  1532. def pbSmallFontName()
  1533. return MessageConfig.pbTryFonts("Power Green Small","Pokemon Emerald Small",
  1534. "Arial Narrow","Arial")
  1535. end
  1536.  
  1537. # Gets the name of the system narrow font.
  1538. def pbNarrowFontName()
  1539. return MessageConfig.pbTryFonts("Power Green Narrow","Pokemon Emerald Narrow",
  1540. "Arial Narrow","Arial")
  1541. end
  1542.  
  1543. # Sets a bitmap's font to the system small font.
  1544. def pbSetSmallFont(bitmap)
  1545. bitmap.font.name=pbSmallFontName()
  1546. bitmap.font.size=25
  1547. end
  1548.  
  1549. # Sets a bitmap's font to the system narrow font.
  1550. def pbSetNarrowFont(bitmap)
  1551. bitmap.font.name=pbNarrowFontName()
  1552. bitmap.font.size=31
  1553. end
  1554.  
  1555.  
  1556.  
  1557. ################################################################################
  1558. # SpriteWrapper is a class based on Sprite which wraps Sprite's properties.
  1559. ################################################################################
  1560. class SpriteWrapper < Sprite
  1561. def initialize(viewport=nil)
  1562. @sprite=Sprite.new(viewport)
  1563. end
  1564.  
  1565. def dispose; @sprite.dispose; end
  1566. def disposed?; return @sprite.disposed?; end
  1567. def viewport; return @sprite.viewport; end
  1568. def flash(color,duration); return @sprite.flash(color,duration); end
  1569. def update; return @sprite.update; end
  1570. def x; @sprite.x; end
  1571. def x=(value); @sprite.x=value; end
  1572. def y; @sprite.y; end
  1573. def y=(value); @sprite.y=value; end
  1574. def bitmap; @sprite.bitmap; end
  1575. def bitmap=(value); @sprite.bitmap=value; end
  1576. def src_rect; @sprite.src_rect; end
  1577. def src_rect=(value); @sprite.src_rect=value; end
  1578. def visible; @sprite.visible; end
  1579. def visible=(value); @sprite.visible=value; end
  1580. def z; @sprite.z; end
  1581. def z=(value); @sprite.z=value; end
  1582. def ox; @sprite.ox; end
  1583. def ox=(value); @sprite.ox=value; end
  1584. def oy; @sprite.oy; end
  1585. def oy=(value); @sprite.oy=value; end
  1586. def zoom_x; @sprite.zoom_x; end
  1587. def zoom_x=(value); @sprite.zoom_x=value; end
  1588. def zoom_y; @sprite.zoom_y; end
  1589. def zoom_y=(value); @sprite.zoom_y=value; end
  1590. def angle; @sprite.angle; end
  1591. def angle=(value); @sprite.angle=value; end
  1592. def mirror; @sprite.mirror; end
  1593. def mirror=(value); @sprite.mirror=value; end
  1594. def bush_depth; @sprite.bush_depth; end
  1595. def bush_depth=(value); @sprite.bush_depth=value; end
  1596. def opacity; @sprite.opacity; end
  1597. def opacity=(value); @sprite.opacity=value; end
  1598. def blend_type; @sprite.blend_type; end
  1599. def blend_type=(value); @sprite.blend_type=value; end
  1600. def color; @sprite.color; end
  1601. def color=(value); @sprite.color=value; end
  1602. def tone; @sprite.tone; end
  1603. def tone=(value); @sprite.tone=value; end
  1604.  
  1605. def viewport=(value)
  1606. return if self.viewport==value
  1607. bitmap=@sprite.bitmap
  1608. src_rect=@sprite.src_rect
  1609. visible=@sprite.visible
  1610. x=@sprite.x
  1611. y=@sprite.y
  1612. z=@sprite.z
  1613. ox=@sprite.ox
  1614. oy=@sprite.oy
  1615. zoom_x=@sprite.zoom_x
  1616. zoom_y=@sprite.zoom_y
  1617. angle=@sprite.angle
  1618. mirror=@sprite.mirror
  1619. bush_depth=@sprite.bush_depth
  1620. opacity=@sprite.opacity
  1621. blend_type=@sprite.blend_type
  1622. color=@sprite.color
  1623. tone=@sprite.tone
  1624. @sprite.dispose
  1625. @sprite=Sprite.new(value)
  1626. @sprite.bitmap=bitmap
  1627. @sprite.src_rect=src_rect
  1628. @sprite.visible=visible
  1629. @sprite.x=x
  1630. @sprite.y=y
  1631. @sprite.z=z
  1632. @sprite.ox=ox
  1633. @sprite.oy=oy
  1634. @sprite.zoom_x=zoom_x
  1635. @sprite.zoom_y=zoom_y
  1636. @sprite.angle=angle
  1637. @sprite.mirror=mirror
  1638. @sprite.bush_depth=bush_depth
  1639. @sprite.opacity=opacity
  1640. @sprite.blend_type=blend_type
  1641. @sprite.color=color
  1642. @sprite.tone=tone
  1643. end
  1644. end
  1645.  
  1646.  
  1647. #########################################################################
  1648.  
  1649.  
  1650. class StringInput
  1651. include Enumerable
  1652.  
  1653. class << self
  1654. def new( str )
  1655. if block_given?
  1656. begin
  1657. f = super
  1658. yield f
  1659. ensure
  1660. f.close if f
  1661. end
  1662. else
  1663. super
  1664. end
  1665. end
  1666. alias open new
  1667. end
  1668.  
  1669. def initialize( str )
  1670. @string = str
  1671. @pos = 0
  1672. @closed = false
  1673. @lineno = 0
  1674. end
  1675.  
  1676. attr_reader :lineno,:string
  1677.  
  1678. def inspect
  1679. return "#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@string[0,30].inspect}>"
  1680. end
  1681.  
  1682. def close
  1683. raise IOError, 'closed stream' if @closed
  1684. @pos=nil; @closed=true
  1685. end
  1686.  
  1687. def closed?; @closed; end
  1688.  
  1689. def pos
  1690. raise IOError, 'closed stream' if @closed
  1691. [@pos, @string.size].min
  1692. end
  1693.  
  1694. alias tell pos
  1695.  
  1696. def rewind; seek(0); end
  1697.  
  1698. def pos=(value); seek(value); end
  1699.  
  1700. def seek( offset, whence=IO::SEEK_SET )
  1701. raise IOError, 'closed stream' if @closed
  1702. case whence
  1703. when IO::SEEK_SET
  1704. @pos=offset
  1705. when IO::SEEK_CUR
  1706. @pos+=offset
  1707. when IO::SEEK_END
  1708. @pos=@string.size - offset
  1709. else
  1710. raise ArgumentError, "unknown seek flag: #{whence}"
  1711. end
  1712. @pos = 0 if @pos < 0
  1713. @pos = [@pos, @string.size + 1].min
  1714. offset
  1715. end
  1716.  
  1717. def eof?
  1718. raise IOError, 'closed stream' if @closed
  1719. @pos > @string.size
  1720. end
  1721.  
  1722. def each( &block )
  1723. raise IOError, 'closed stream' if @closed
  1724. begin
  1725. @string.each(&block)
  1726. ensure
  1727. @pos = 0
  1728. end
  1729. end
  1730.  
  1731. def gets
  1732. raise IOError, 'closed stream' if @closed
  1733. if idx = @string.index(?\n, @pos)
  1734. idx += 1 # "\n".size
  1735. line = @string[ @pos ... idx ]
  1736. @pos = idx
  1737. @pos += 1 if @pos == @string.size
  1738. else
  1739. line = @string[ @pos .. -1 ]
  1740. @pos = @string.size + 1
  1741. end
  1742. @lineno += 1
  1743. line
  1744. end
  1745.  
  1746. def getc
  1747. raise IOError, 'closed stream' if @closed
  1748. ch = @string[@pos]
  1749. @pos += 1
  1750. @pos += 1 if @pos == @string.size
  1751. ch
  1752. end
  1753.  
  1754. def read( len = nil )
  1755. raise IOError, 'closed stream' if @closed
  1756. if !len
  1757. return nil if eof?
  1758. rest = @string[@pos ... @string.size]
  1759. @pos = @string.size + 1
  1760. return rest
  1761. end
  1762. str = @string[@pos, len]
  1763. @pos += len
  1764. @pos += 1 if @pos == @string.size
  1765. str
  1766. end
  1767.  
  1768. def read_all; read(); end
  1769.  
  1770. alias sysread read
  1771. end
  1772.  
  1773.  
  1774.  
  1775. module ::Marshal
  1776. class << self
  1777. if !@oldloadAliased
  1778. alias oldload load
  1779. @oldloadAliased=true
  1780. end
  1781.  
  1782. def neverload
  1783. return @@neverload
  1784. end
  1785.  
  1786. @@neverload=false
  1787.  
  1788. def neverload=(value)
  1789. @@neverload=value
  1790. end
  1791.  
  1792. def load(port,*arg)
  1793. if @@neverload
  1794. if port.is_a?(IO)
  1795. return port.read
  1796. else
  1797. return port
  1798. end
  1799. end
  1800. oldpos=port.pos if port.is_a?(IO)
  1801. begin
  1802. oldload(port,*arg)
  1803. rescue
  1804. p [$!.class,$!.message,$!.backtrace]
  1805. if port.is_a?(IO)
  1806. port.pos=oldpos
  1807. return port.read
  1808. else
  1809. return port
  1810. end
  1811. end
  1812. end
  1813. end
  1814. end
  1815.  
  1816.  
  1817.  
  1818. # Used to determine whether a data file exists (rather than a graphics or
  1819. # audio file). Doesn't check RTP, but does check encrypted archives.
  1820. def pbRgssExists?(filename)
  1821. filename=canonicalize(filename)
  1822. if (safeExists?("./Game.rgssad") || safeExists?("./Game.rgss2a"))
  1823. return pbGetFileChar(filename)!=nil
  1824. else
  1825. return safeExists?(filename)
  1826. end
  1827. end
  1828.  
  1829. # Opens an IO, even if the file is in an encrypted archive.
  1830. # Doesn't check RTP for the file.
  1831. def pbRgssOpen(file,mode=nil)
  1832. #File.open("debug.txt","ab"){|fw| fw.write([file,mode,Time.now.to_f].inspect+"\r\n") }
  1833. if !safeExists?("./Game.rgssad") && !safeExists?("./Game.rgss2a")
  1834. if block_given?
  1835. File.open(file,mode){|f| yield f }
  1836. return nil
  1837. else
  1838. return File.open(file,mode)
  1839. end
  1840. end
  1841. file=canonicalize(file)
  1842. Marshal.neverload=true
  1843. begin
  1844. str=load_data(file)
  1845. ensure
  1846. Marshal.neverload=false
  1847. end
  1848. if block_given?
  1849. StringInput.open(str){|f| yield f }
  1850. return nil
  1851. else
  1852. return StringInput.open(str)
  1853. end
  1854. end
  1855.  
  1856. # Gets at least the first byte of a file. Doesn't check RTP, but does check
  1857. # encrypted archives.
  1858. def pbGetFileChar(file)
  1859. file=canonicalize(file)
  1860. if !(safeExists?("./Game.rgssad") || safeExists?("./Game.rgss2a"))
  1861. return nil if !safeExists?(file)
  1862. begin
  1863. File.open(file,"rb"){|f|
  1864. return f.read(1) # read one byte
  1865. }
  1866. rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES
  1867. return nil
  1868. end
  1869. end
  1870. Marshal.neverload=true
  1871. str=nil
  1872. begin
  1873. str=load_data(file)
  1874. rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES, RGSSError
  1875. str=nil
  1876. ensure
  1877. Marshal.neverload=false
  1878. end
  1879. return str
  1880. end
  1881.  
  1882. # Gets the contents of a file. Doesn't check RTP, but does check
  1883. # encrypted archives.
  1884. def pbGetFileString(file)
  1885. file=canonicalize(file)
  1886. if !(safeExists?("./Game.rgssad") || safeExists?("./Game.rgss2a"))
  1887. return nil if !safeExists?(file)
  1888. begin
  1889. File.open(file,"rb"){|f|
  1890. return f.read # read all data
  1891. }
  1892. rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES
  1893. return nil
  1894. end
  1895. end
  1896. Marshal.neverload=true
  1897. str=nil
  1898. begin
  1899. str=load_data(file)
  1900. rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES, RGSSError
  1901. str=nil
  1902. ensure
  1903. Marshal.neverload=false
  1904. end
  1905. return str
  1906. end
  1907.  
  1908.  
  1909.  
  1910. #===============================================================================
  1911. # SpriteWindow is a class based on Window which emulates Window's functionality.
  1912. # This class is necessary in order to change the viewport of windows (with
  1913. # viewport=) and to make windows fade in and out (with tone=).
  1914. #===============================================================================
  1915. class SpriteWindowCursorRect < Rect
  1916. def initialize(window)
  1917. @window=window
  1918. @x=0
  1919. @y=0
  1920. @width=0
  1921. @height=0
  1922. end
  1923.  
  1924. attr_reader :x,:y,:width,:height
  1925.  
  1926. def empty
  1927. needupdate=@x!=0 || @y!=0 || @width!=0 || @height!=0
  1928. if needupdate
  1929. @x=0
  1930. @y=0
  1931. @width=0
  1932. @height=0
  1933. @window.width=@window.width
  1934. end
  1935. end
  1936.  
  1937. def isEmpty?
  1938. return @x==0 && @y==0 && @width==0 && @height==0
  1939. end
  1940.  
  1941. def set(x,y,width,height)
  1942. needupdate=@x!=x || @y!=y || @width!=width || @height!=height
  1943. if needupdate
  1944. @x=x
  1945. @y=y
  1946. @width=width
  1947. @height=height
  1948. @window.width=@window.width
  1949. end
  1950. end
  1951.  
  1952. def height=(value)
  1953. @height=value; @window.width=@window.width
  1954. end
  1955.  
  1956. def width=(value)
  1957. @width=value; @window.width=@window.width
  1958. end
  1959.  
  1960. def x=(value)
  1961. @x=value; @window.width=@window.width
  1962. end
  1963.  
  1964. def y=(value)
  1965. @y=value; @window.width=@window.width
  1966. end
  1967. end
  1968.  
  1969.  
  1970.  
  1971. class SpriteWindow < Window
  1972. attr_reader :tone
  1973. attr_reader :color
  1974. attr_reader :viewport
  1975. attr_reader :contents
  1976. attr_reader :ox
  1977. attr_reader :oy
  1978. attr_reader :x
  1979. attr_reader :y
  1980. attr_reader :z
  1981. attr_reader :zoom_x
  1982. attr_reader :zoom_y
  1983. attr_reader :offset_x
  1984. attr_reader :offset_y
  1985. attr_reader :width
  1986. attr_reader :active
  1987. attr_reader :pause
  1988. attr_reader :height
  1989. attr_reader :opacity
  1990. attr_reader :back_opacity
  1991. attr_reader :contents_opacity
  1992. attr_reader :visible
  1993. attr_reader :cursor_rect
  1994. attr_reader :contents_blend_type
  1995. attr_reader :blend_type
  1996. attr_reader :openness
  1997.  
  1998. def windowskin
  1999. @_windowskin
  2000. end
  2001.  
  2002. # Flags used to preserve compatibility
  2003. # with RGSS/RGSS2's version of Window
  2004. module CompatBits
  2005. CorrectZ = 1
  2006. ExpandBack = 2
  2007. ShowScrollArrows = 4
  2008. StretchSides = 8
  2009. ShowPause = 16
  2010. ShowCursor = 32
  2011. end
  2012.  
  2013. attr_reader :compat
  2014.  
  2015. def compat=(value)
  2016. @compat=value
  2017. privRefresh(true)
  2018. end
  2019.  
  2020. def initialize(viewport=nil)
  2021. @sprites={}
  2022. @spritekeys=[
  2023. "back",
  2024. "corner0","side0","scroll0",
  2025. "corner1","side1","scroll1",
  2026. "corner2","side2","scroll2",
  2027. "corner3","side3","scroll3",
  2028. "cursor","contents","pause"
  2029. ]
  2030. @viewport=viewport
  2031. @sidebitmaps=[nil,nil,nil,nil]
  2032. @cursorbitmap=nil
  2033. @bgbitmap=nil
  2034. for i in @spritekeys
  2035. @sprites[i]=Sprite.new(@viewport)
  2036. end
  2037. @disposed=false
  2038. @tone=Tone.new(0,0,0)
  2039. @color=Color.new(0,0,0,0)
  2040. @blankcontents=Bitmap.new(1,1) # RGSS2 requires this
  2041. @contents=@blankcontents
  2042. @_windowskin=nil
  2043. @rpgvx=false
  2044. @compat=CompatBits::ExpandBack|CompatBits::StretchSides
  2045. @x=0
  2046. @y=0
  2047. @width=0
  2048. @height=0
  2049. @offset_x=0
  2050. @offset_y=0
  2051. @zoom_x=1.0
  2052. @zoom_y=1.0
  2053. @ox=0
  2054. @oy=0
  2055. @z=0
  2056. @stretch=true
  2057. @visible=true
  2058. @active=true
  2059. @openness=255
  2060. @opacity=255
  2061. @back_opacity=255
  2062. @blend_type=0
  2063. @contents_blend_type=0
  2064. @contents_opacity=255
  2065. @cursor_rect=SpriteWindowCursorRect.new(self)
  2066. @cursorblink=0
  2067. @cursoropacity=255
  2068. @pause=false
  2069. @pauseframe=0
  2070. @flash=0
  2071. @pauseopacity=0
  2072. @skinformat=0
  2073. @skinrect=Rect.new(0,0,0,0)
  2074. @trim=[16,16,16,16]
  2075. privRefresh(true)
  2076. end
  2077.  
  2078. def dispose
  2079. if !self.disposed?
  2080. for i in @sprites
  2081. i[1].dispose if i[1]
  2082. @sprites[i[0]]=nil
  2083. end
  2084. for i in 0...@sidebitmaps.length
  2085. @sidebitmaps[i].dispose if @sidebitmaps[i]
  2086. @sidebitmaps[i]=nil
  2087. end
  2088. @blankcontents.dispose
  2089. @cursorbitmap.dispose if @cursorbitmap
  2090. @backbitmap.dispose if @backbitmap
  2091. @sprites.clear
  2092. @sidebitmaps.clear
  2093. @_windowskin=nil
  2094. @disposed=true
  2095. end
  2096. end
  2097.  
  2098. def stretch=(value)
  2099. @stretch=value
  2100. privRefresh(true)
  2101. end
  2102.  
  2103. def visible=(value)
  2104. @visible=value
  2105. privRefresh
  2106. end
  2107.  
  2108. def viewport=(value)
  2109. @viewport=value
  2110. for i in @spritekeys
  2111. @sprites[i].dispose if @sprites[i]
  2112. end
  2113. for i in @spritekeys
  2114. if @sprites[i].is_a?(Sprite)
  2115. @sprites[i]=Sprite.new(@viewport)
  2116. else
  2117. @sprites[i]=nil
  2118. end
  2119. end
  2120. privRefresh(true)
  2121. end
  2122.  
  2123. def z=(value)
  2124. @z=value
  2125. privRefresh
  2126. end
  2127.  
  2128. def disposed?
  2129. return @disposed
  2130. end
  2131.  
  2132. def contents=(value)
  2133. if @contents!=value
  2134. @contents=value
  2135. privRefresh if @visible
  2136. end
  2137. end
  2138.  
  2139. def ox=(value)
  2140. if @ox!=value
  2141. @ox=value
  2142. privRefresh if @visible
  2143. end
  2144. end
  2145.  
  2146. def oy=(value)
  2147. if @oy!=value
  2148. @oy=value
  2149. privRefresh if @visible
  2150. end
  2151. end
  2152.  
  2153. def active=(value)
  2154. @active=value
  2155. privRefresh(true)
  2156. end
  2157.  
  2158. def cursor_rect=(value)
  2159. if !value
  2160. @cursor_rect.empty
  2161. else
  2162. @cursor_rect.set(value.x,value.y,value.width,value.height)
  2163. end
  2164. end
  2165.  
  2166. def openness=(value)
  2167. @openness=value
  2168. @openness=0 if @openness<0
  2169. @openness=255 if @openness>255
  2170. privRefresh
  2171. end
  2172.  
  2173. def width=(value)
  2174. @width=value
  2175. privRefresh(true)
  2176. end
  2177.  
  2178. def height=(value)
  2179. @height=value
  2180. privRefresh(true)
  2181. end
  2182.  
  2183. def pause=(value)
  2184. @pause=value
  2185. @pauseopacity=0 if !value
  2186. privRefresh if @visible
  2187. end
  2188.  
  2189. def x=(value)
  2190. @x=value
  2191. privRefresh if @visible
  2192. end
  2193.  
  2194. def y=(value)
  2195. @y=value
  2196. privRefresh if @visible
  2197. end
  2198.  
  2199. def zoom_x=(value)
  2200. @zoom_x=value
  2201. privRefresh if @visible
  2202. end
  2203.  
  2204. def zoom_y=(value)
  2205. @zoom_y=value
  2206. privRefresh if @visible
  2207. end
  2208.  
  2209. def offset_x=(value)
  2210. @x=value
  2211. privRefresh if @visible
  2212. end
  2213.  
  2214. def offset_y=(value)
  2215. @y=value
  2216. privRefresh if @visible
  2217. end
  2218.  
  2219. def opacity=(value)
  2220. @opacity=value
  2221. @opacity=0 if @opacity<0
  2222. @opacity=255 if @opacity>255
  2223. privRefresh if @visible
  2224. end
  2225.  
  2226. def back_opacity=(value)
  2227. @back_opacity=value
  2228. @back_opacity=0 if @back_opacity<0
  2229. @back_opacity=255 if @back_opacity>255
  2230. privRefresh if @visible
  2231. end
  2232.  
  2233. def contents_opacity=(value)
  2234. @contents_opacity=value
  2235. @contents_opacity=0 if @contents_opacity<0
  2236. @contents_opacity=255 if @contents_opacity>255
  2237. privRefresh if @visible
  2238. end
  2239.  
  2240. def tone=(value)
  2241. @tone=value
  2242. privRefresh if @visible
  2243. end
  2244.  
  2245. def color=(value)
  2246. @color=value
  2247. privRefresh if @visible
  2248. end
  2249.  
  2250. def blend_type=(value)
  2251. @blend_type=value
  2252. privRefresh if @visible
  2253. end
  2254.  
  2255. def flash(color,duration)
  2256. return if disposed?
  2257. @flash=duration+1
  2258. for i in @sprites
  2259. i[1].flash(color,duration)
  2260. end
  2261. end
  2262.  
  2263. def update
  2264. return if disposed?
  2265. mustchange=false
  2266. if @active
  2267. if @cursorblink==0
  2268. @cursoropacity-=8
  2269. @cursorblink=1 if @cursoropacity<=128
  2270. else
  2271. @cursoropacity+=8
  2272. @cursorblink=0 if @cursoropacity>=255
  2273. end
  2274. privRefreshCursor
  2275. else
  2276. @cursoropacity=128
  2277. privRefreshCursor
  2278. end
  2279. if @pause
  2280. oldpauseframe=@pauseframe
  2281. oldpauseopacity=@pauseopacity
  2282. @pauseframe=(Graphics.frame_count / 8) % 4
  2283. @pauseopacity=[@pauseopacity+64,255].min
  2284. mustchange=@pauseframe!=oldpauseframe || @pauseopacity!=oldpauseopacity
  2285. end
  2286. privRefresh if mustchange
  2287. if @flash>0
  2288. for i in @sprites.values
  2289. i.update
  2290. end
  2291. @flash-=1
  2292. end
  2293. end
  2294.  
  2295. #############
  2296. attr_reader :skinformat
  2297. attr_reader :skinrect
  2298.  
  2299. def loadSkinFile(file)
  2300. if (self.windowskin.width==80 || self.windowskin.width==96) &&
  2301. self.windowskin.height==48
  2302. # Body = X, Y, width, height of body rectangle within windowskin
  2303. @skinrect.set(32,16,16,16)
  2304. # Trim = X, Y, width, height of trim rectangle within windowskin
  2305. @trim=[32,16,16,16]
  2306. elsif self.windowskin.width==80 && self.windowskin.height==80
  2307. @skinrect.set(32,32,16,16)
  2308. @trim=[32,16,16,48]
  2309. end
  2310. end
  2311.  
  2312. def windowskin=(value)
  2313. oldSkinWidth=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.width : -1
  2314. oldSkinHeight=(@_windowskin && !@_windowskin.disposed?) ? @_windowskin.height : -1
  2315. @_windowskin=value
  2316. if @skinformat==1
  2317. @rpgvx=false
  2318. if @_windowskin && !@_windowskin.disposed?
  2319. if @_windowskin.width!=oldSkinWidth || @_windowskin.height!=oldSkinHeight
  2320. # Update skinrect and trim if windowskin's dimensions have changed
  2321. @skinrect.set((@_windowskin.width-16)/2,(@_windowskin.height-16)/2,16,16)
  2322. @trim=[@skinrect.x,@skinrect.y,@skinrect.x,@skinrect.y]
  2323. end
  2324. else
  2325. @skinrect.set(16,16,16,16)
  2326. @trim=[16,16,16,16]
  2327. end
  2328. else
  2329. if value && value.is_a?(Bitmap) && !value.disposed? && value.width==128
  2330. @rpgvx=true
  2331. else
  2332. @rpgvx=false
  2333. end
  2334. @trim=[16,16,16,16]
  2335. end
  2336. privRefresh(true)
  2337. end
  2338.  
  2339. def skinrect=(value)
  2340. @skinrect=value
  2341. privRefresh
  2342. end
  2343.  
  2344. def skinformat=(value)
  2345. if @skinformat!=value
  2346. @skinformat=value
  2347. privRefresh(true)
  2348. end
  2349. end
  2350.  
  2351. def borderX
  2352. return 32 if !@trim || skinformat==0
  2353. if @_windowskin && !@_windowskin.disposed?
  2354. return @trim[0]+(@_windowskin.width-@trim[2]-@trim[0])
  2355. end
  2356. return 32
  2357. end
  2358.  
  2359. def borderY
  2360. return 32 if !@trim || skinformat==0
  2361. if @_windowskin && !@_windowskin.disposed?
  2362. return @trim[1]+(@_windowskin.height-@trim[3]-@trim[1])
  2363. end
  2364. return 32
  2365. end
  2366.  
  2367. def leftEdge; self.startX; end
  2368. def topEdge; self.startY; end
  2369. def rightEdge; self.borderX-self.leftEdge; end
  2370. def bottomEdge; self.borderY-self.topEdge; end
  2371.  
  2372. def startX
  2373. return !@trim || skinformat==0 ? 16 : @trim[0]
  2374. end
  2375.  
  2376. def startY
  2377. return !@trim || skinformat==0 ? 16 : @trim[1]
  2378. end
  2379.  
  2380. def endX
  2381. return !@trim || skinformat==0 ? 16 : @trim[2]
  2382. end
  2383.  
  2384. def endY
  2385. return !@trim || skinformat==0 ? 16 : @trim[3]
  2386. end
  2387.  
  2388. def startX=(value)
  2389. @trim[0]=value
  2390. privRefresh
  2391. end
  2392.  
  2393. def startY=(value)
  2394. @trim[1]=value
  2395. privRefresh
  2396. end
  2397.  
  2398. def endX=(value)
  2399. @trim[2]=value
  2400. privRefresh
  2401. end
  2402.  
  2403. def endY=(value)
  2404. @trim[3]=value
  2405. privRefresh
  2406. end
  2407.  
  2408. #############
  2409. private
  2410.  
  2411. def ensureBitmap(bitmap,dwidth,dheight)
  2412. if !bitmap||bitmap.disposed?||bitmap.width<dwidth||bitmap.height<dheight
  2413. bitmap.dispose if bitmap
  2414. bitmap=Bitmap.new([1,dwidth].max,[1,dheight].max)
  2415. end
  2416. return bitmap
  2417. end
  2418.  
  2419. def tileBitmap(dstbitmap,dstrect,srcbitmap,srcrect)
  2420. return if !srcbitmap || srcbitmap.disposed?
  2421. left=dstrect.x
  2422. top=dstrect.y
  2423. y=0;loop do break unless y<dstrect.height
  2424. x=0;loop do break unless x<dstrect.width
  2425. dstbitmap.blt(x+left,y+top,srcbitmap,srcrect)
  2426. x+=srcrect.width
  2427. end
  2428. y+=srcrect.height
  2429. end
  2430. end
  2431.  
  2432. def privRefreshCursor
  2433. contopac=self.contents_opacity
  2434. cursoropac=@cursoropacity*contopac/255
  2435. @sprites["cursor"].opacity=cursoropac
  2436. end
  2437.  
  2438. def privRefresh(changeBitmap=false)
  2439. return if !self || self.disposed?
  2440. backopac=self.back_opacity*self.opacity/255
  2441. contopac=self.contents_opacity
  2442. cursoropac=@cursoropacity*contopac/255
  2443. haveskin=@_windowskin && !@_windowskin.disposed?
  2444. for i in 0...4
  2445. @sprites["corner#{i}"].bitmap=@_windowskin
  2446. @sprites["scroll#{i}"].bitmap=@_windowskin
  2447. end
  2448. @sprites["pause"].bitmap=@_windowskin
  2449. @sprites["contents"].bitmap=@contents
  2450. if haveskin
  2451. for i in 0...4
  2452. @sprites["corner#{i}"].opacity=@opacity
  2453. @sprites["corner#{i}"].tone=@tone
  2454. @sprites["corner#{i}"].color=@color
  2455. @sprites["corner#{i}"].visible=@visible
  2456. @sprites["corner#{i}"].blend_type=@blend_type
  2457. @sprites["side#{i}"].opacity=@opacity
  2458. @sprites["side#{i}"].tone=@tone
  2459. @sprites["side#{i}"].color=@color
  2460. @sprites["side#{i}"].blend_type=@blend_type
  2461. @sprites["side#{i}"].visible=@visible
  2462. @sprites["scroll#{i}"].opacity=@opacity
  2463. @sprites["scroll#{i}"].tone=@tone
  2464. @sprites["scroll#{i}"].color=@color
  2465. @sprites["scroll#{i}"].visible=@visible
  2466. @sprites["scroll#{i}"].blend_type=@blend_type
  2467. end
  2468. for i in ["back","cursor","pause","contents"]
  2469. @sprites[i].color=@color
  2470. @sprites[i].tone=@tone
  2471. @sprites[i].blend_type=@blend_type
  2472. end
  2473. @sprites["contents"].blend_type=@contents_blend_type
  2474. @sprites["back"].opacity=backopac
  2475. @sprites["contents"].opacity=contopac
  2476. @sprites["cursor"].opacity=cursoropac
  2477. @sprites["pause"].opacity=@pauseopacity
  2478. supported=(@skinformat==0)
  2479. hascontents=(@contents && !@contents.disposed?)
  2480. @sprites["back"].visible=@visible
  2481. @sprites["contents"].visible=@visible && @openness==255
  2482. @sprites["pause"].visible=supported && @visible && @pause &&
  2483. (@combat & CompatBits::ShowPause)
  2484. @sprites["cursor"].visible=supported && @visible && @openness==255 &&
  2485. (@combat & CompatBits::ShowCursor)
  2486. @sprites["scroll0"].visible = false
  2487. @sprites["scroll1"].visible = false
  2488. @sprites["scroll2"].visible = false
  2489. @sprites["scroll3"].visible = false
  2490. else
  2491. for i in 0...4
  2492. @sprites["corner#{i}"].visible=false
  2493. @sprites["side#{i}"].visible=false
  2494. @sprites["scroll#{i}"].visible=false
  2495. end
  2496. @sprites["contents"].visible=@visible && @openness==255
  2497. @sprites["contents"].color=@color
  2498. @sprites["contents"].tone=@tone
  2499. @sprites["contents"].blend_type=@contents_blend_type
  2500. @sprites["contents"].opacity=contopac
  2501. @sprites["back"].visible=false
  2502. @sprites["pause"].visible=false
  2503. @sprites["cursor"].visible=false
  2504. end
  2505. for i in @spritekeys
  2506. @sprites[i].z=@z
  2507. end
  2508. if (@compat & CompatBits::CorrectZ)>0 && @skinformat==0 && !@rpgvx
  2509. # Compatibility Mode: Cursor, pause, and contents have higher Z
  2510. @sprites["cursor"].z=@z+1
  2511. @sprites["contents"].z=@z+2
  2512. @sprites["pause"].z=@z+2
  2513. end
  2514. if @skinformat==0
  2515. startX=16
  2516. startY=16
  2517. endX=16
  2518. endY=16
  2519. trimStartX=16
  2520. trimStartY=16
  2521. trimWidth=32
  2522. trimHeight=32
  2523. if @rpgvx
  2524. trimX=64
  2525. trimY=0
  2526. backRect=Rect.new(0,0,64,64)
  2527. blindsRect=Rect.new(0,64,64,64)
  2528. else
  2529. trimX=128
  2530. trimY=0
  2531. backRect=Rect.new(0,0,128,128)
  2532. blindsRect=nil
  2533. end
  2534. if @_windowskin && !@_windowskin.disposed?
  2535. @sprites["corner0"].src_rect.set(trimX,trimY+0,16,16);
  2536. @sprites["corner1"].src_rect.set(trimX+48,trimY+0,16,16);
  2537. @sprites["corner2"].src_rect.set(trimX,trimY+48,16,16);
  2538. @sprites["corner3"].src_rect.set(trimX+48,trimY+48,16,16);
  2539. @sprites["scroll0"].src_rect.set(trimX+24, trimY+16, 16, 8) # up
  2540. @sprites["scroll3"].src_rect.set(trimX+24, trimY+40, 16, 8) # down
  2541. @sprites["scroll1"].src_rect.set(trimX+16, trimY+24, 8, 16) # left
  2542. @sprites["scroll2"].src_rect.set(trimX+40, trimY+24, 8, 16) # right
  2543. cursorX=trimX
  2544. cursorY=trimY+64
  2545. sideRects=[
  2546. Rect.new(trimX+16,trimY+0,32,16),
  2547. Rect.new(trimX,trimY+16,16,32),
  2548. Rect.new(trimX+48,trimY+16,16,32),
  2549. Rect.new(trimX+16,trimY+48,32,16)
  2550. ]
  2551. pauseRects=[
  2552. trimX+32,trimY+64,
  2553. trimX+48,trimY+64,
  2554. trimX+32,trimY+80,
  2555. trimX+48,trimY+80,
  2556. ]
  2557. pauseWidth=16
  2558. pauseHeight=16
  2559. @sprites["pause"].src_rect.set(
  2560. pauseRects[@pauseframe*2],
  2561. pauseRects[@pauseframe*2+1],
  2562. pauseWidth,pauseHeight
  2563. )
  2564. end
  2565. else
  2566. trimStartX=@trim[0]
  2567. trimStartY=@trim[1]
  2568. trimWidth=@trim[0]+(@skinrect.width-@trim[2]+@trim[0])
  2569. trimHeight=@trim[1]+(@skinrect.height-@trim[3]+@trim[1])
  2570. if @_windowskin && !@_windowskin.disposed?
  2571. # width of left end of window
  2572. startX=@skinrect.x
  2573. # width of top end of window
  2574. startY=@skinrect.y
  2575. backWidth=@skinrect.width
  2576. backHeight=@skinrect.height
  2577. cx=@skinrect.x+@skinrect.width # right side of BODY rect
  2578. cy=@skinrect.y+@skinrect.height # bottom side of BODY rect
  2579. # width of right end of window
  2580. endX=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.x : @_windowskin.width-cx
  2581. # height of bottom end of window
  2582. endY=(!@_windowskin || @_windowskin.disposed?) ? @skinrect.y : @_windowskin.height-cy
  2583. @sprites["corner0"].src_rect.set(0,0,startX,startY);
  2584. @sprites["corner1"].src_rect.set(cx,0,endX,startY);
  2585. @sprites["corner2"].src_rect.set(0,cy,startX,endY);
  2586. @sprites["corner3"].src_rect.set(cx,cy,endX,endY);
  2587. backRect=Rect.new(@skinrect.x,@skinrect.y,
  2588. @skinrect.width,@skinrect.height);
  2589. blindsRect=nil
  2590. sideRects=[
  2591. Rect.new(startX,0,@skinrect.width,startY), # side0 (top)
  2592. Rect.new(0,startY,startX,@skinrect.height), # side1 (left)
  2593. Rect.new(cx,startY,endX,@skinrect.height), # side2 (right)
  2594. Rect.new(startX,cy,@skinrect.width,endY) # side3 (bottom)
  2595. ]
  2596. end
  2597. end
  2598. if @width>trimWidth && @height>trimHeight
  2599. @sprites["contents"].src_rect.set(@ox,@oy,@width-trimWidth,@height-trimHeight)
  2600. else
  2601. @sprites["contents"].src_rect.set(0,0,0,0)
  2602. end
  2603. @sprites["contents"].x=@x+trimStartX
  2604. @sprites["contents"].y=@y+trimStartY
  2605. if (@compat & CompatBits::ShowScrollArrows)>0 && @skinformat==0
  2606. # Compatibility mode: Make scroll arrows visible
  2607. if @skinformat==0 && @_windowskin && !@_windowskin.disposed? &&
  2608. @contents && !@contents.disposed?
  2609. @sprites["scroll0"].visible = @visible && hascontents && @oy > 0
  2610. @sprites["scroll1"].visible = @visible && hascontents && @ox > 0
  2611. @sprites["scroll2"].visible = @visible && (@contents.width - @ox) > @width-trimWidth
  2612. @sprites["scroll3"].visible = @visible && (@contents.height - @oy) > @height-trimHeight
  2613. end
  2614. end
  2615. if @_windowskin && !@_windowskin.disposed?
  2616. backTrimX=startX+endX
  2617. backTrimY=startX+endX
  2618. borderX=startX+endX
  2619. borderY=startY+endY
  2620. @sprites["corner0"].x=@x
  2621. @sprites["corner0"].y=@y
  2622. @sprites["corner1"].x=@x+@width-endX
  2623. @sprites["corner1"].y=@y
  2624. @sprites["corner2"].x=@x
  2625. @sprites["corner2"].y=@y+@height-endY
  2626. @sprites["corner3"].x=@x+@width-endX
  2627. @sprites["corner3"].y=@y+@height-endY
  2628. @sprites["side0"].x=@x+startX
  2629. @sprites["side0"].y=@y
  2630. @sprites["side1"].x=@x
  2631. @sprites["side1"].y=@y+startY
  2632. @sprites["side2"].x=@x+@width-endX
  2633. @sprites["side2"].y=@y+startY
  2634. @sprites["side3"].x=@x+startX
  2635. @sprites["side3"].y=@y+@height-endY
  2636. @sprites["scroll0"].x = @x+@width / 2 - 8
  2637. @sprites["scroll0"].y = @y+8
  2638. @sprites["scroll1"].x = @x+8
  2639. @sprites["scroll1"].y = @y+@height / 2 - 8
  2640. @sprites["scroll2"].x = @x+@width - 16
  2641. @sprites["scroll2"].y = @y+@height / 2 - 8
  2642. @sprites["scroll3"].x = @x+@width / 2 - 8
  2643. @sprites["scroll3"].y = @y+@height - 16
  2644. @sprites["cursor"].x=@x+startX+@cursor_rect.x
  2645. @sprites["cursor"].y=@y+startY+@cursor_rect.y
  2646. if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0
  2647. # Compatibility mode: Expand background
  2648. @sprites["back"].x=@x+2
  2649. @sprites["back"].y=@y+2
  2650. else
  2651. @sprites["back"].x=@x+startX
  2652. @sprites["back"].y=@y+startY
  2653. end
  2654. end
  2655. if changeBitmap && @_windowskin && !@_windowskin.disposed?
  2656. if @skinformat==0
  2657. @sprites["cursor"].x=@x+startX+@cursor_rect.x
  2658. @sprites["cursor"].y=@y+startY+@cursor_rect.y
  2659. width=@cursor_rect.width
  2660. height=@cursor_rect.height
  2661. if width > 0 && height > 0
  2662. cursorrects=[
  2663. # sides
  2664. Rect.new(cursorX+2, cursorY+0, 28, 2),
  2665. Rect.new(cursorX+0, cursorY+2, 2, 28),
  2666. Rect.new(cursorX+30, cursorY+2, 2, 28),
  2667. Rect.new(cursorX+2, cursorY+30, 28, 2),
  2668. # corners
  2669. Rect.new(cursorX+0, cursorY+0, 2, 2),
  2670. Rect.new(cursorX+30, cursorY+0, 2, 2),
  2671. Rect.new(cursorX+0, cursorY+30, 2, 2),
  2672. Rect.new(cursorX+30, cursorY+30, 2, 2),
  2673. # back
  2674. Rect.new(cursorX+2, cursorY+2, 28, 28)
  2675. ]
  2676. margin=2
  2677. fullmargin=4
  2678. @cursorbitmap = ensureBitmap(@cursorbitmap, width, height)
  2679. @cursorbitmap.clear
  2680. @sprites["cursor"].bitmap=@cursorbitmap
  2681. @sprites["cursor"].src_rect.set(0,0,width,height)
  2682. rect = Rect.new(margin,margin,width - fullmargin, height - fullmargin)
  2683. @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[8])
  2684. @cursorbitmap.blt(0, 0, @_windowskin, cursorrects[4])# top left
  2685. @cursorbitmap.blt(width-margin, 0, @_windowskin, cursorrects[5]) # top right
  2686. @cursorbitmap.blt(0, height-margin, @_windowskin, cursorrects[6]) # bottom right
  2687. @cursorbitmap.blt(width-margin, height-margin, @_windowskin, cursorrects[7]) # bottom left
  2688. rect = Rect.new(margin, 0,width - fullmargin, margin)
  2689. @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[0])
  2690. rect = Rect.new(0, margin,margin, height - fullmargin)
  2691. @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[1])
  2692. rect = Rect.new(width - margin, margin, margin, height - fullmargin)
  2693. @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[2])
  2694. rect = Rect.new(margin, height-margin, width - fullmargin, margin)
  2695. @cursorbitmap.stretch_blt(rect, @_windowskin, cursorrects[3])
  2696. else
  2697. @sprites["cursor"].visible=false
  2698. @sprites["cursor"].src_rect.set(0,0,0,0)
  2699. end
  2700. end
  2701. for i in 0..3
  2702. case i
  2703. when 0
  2704. dwidth=@width-startX-endX
  2705. dheight=startY
  2706. when 1
  2707. dwidth=startX
  2708. dheight=@height-startY-endY
  2709. when 2
  2710. dwidth=endX
  2711. dheight=@height-startY-endY
  2712. when 3
  2713. dwidth=@width-startX-endX
  2714. dheight=endY
  2715. end
  2716. @sidebitmaps[i]=ensureBitmap(@sidebitmaps[i],dwidth,dheight)
  2717. @sprites["side#{i}"].bitmap=@sidebitmaps[i]
  2718. @sprites["side#{i}"].src_rect.set(0,0,dwidth,dheight)
  2719. @sidebitmaps[i].clear
  2720. if sideRects[i].width>0 && sideRects[i].height>0
  2721. if (@compat & CompatBits::StretchSides)>0 && @skinformat==0
  2722. # Compatibility mode: Stretch sides
  2723. @sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect,
  2724. @_windowskin,sideRects[i])
  2725. else
  2726. tileBitmap(@sidebitmaps[i],@sprites["side#{i}"].src_rect,
  2727. @_windowskin,sideRects[i])
  2728. end
  2729. end
  2730. end
  2731. if (@compat & CompatBits::ExpandBack)>0 && @skinformat==0
  2732. # Compatibility mode: Expand background
  2733. backwidth=@width-4
  2734. backheight=@height-4
  2735. else
  2736. backwidth=@width-borderX
  2737. backheight=@height-borderY
  2738. end
  2739. if backwidth>0 && backheight>0
  2740. @backbitmap=ensureBitmap(@backbitmap,backwidth,backheight)
  2741. @sprites["back"].bitmap=@backbitmap
  2742. @sprites["back"].src_rect.set(0,0,backwidth,backheight)
  2743. @backbitmap.clear
  2744. if @stretch
  2745. @backbitmap.stretch_blt(@sprites["back"].src_rect,@_windowskin,backRect)
  2746. else
  2747. tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,backRect)
  2748. end
  2749. if blindsRect
  2750. tileBitmap(@backbitmap,@sprites["back"].src_rect,@_windowskin,blindsRect)
  2751. end
  2752. else
  2753. @sprites["back"].visible=false
  2754. @sprites["back"].src_rect.set(0,0,0,0)
  2755. end
  2756. end
  2757. if @openness!=255
  2758. opn=@openness/255.0
  2759. for k in @spritekeys
  2760. sprite=@sprites[k]
  2761. ratio=(@height<=0) ? 0 : (sprite.y-@y)*1.0/@height
  2762. sprite.zoom_y=opn
  2763. sprite.zoom_x=1.0
  2764. sprite.oy=0
  2765. sprite.y=(@y+(@height/2.0)+(@height*ratio*opn)-(@height/2*opn)).floor
  2766. oldbitmap=sprite.bitmap
  2767. oldsrcrect=sprite.src_rect.clone
  2768. end
  2769. else
  2770. for k in @spritekeys
  2771. sprite=@sprites[k]
  2772. sprite.zoom_x=1.0
  2773. sprite.zoom_y=1.0
  2774. end
  2775. end
  2776. i=0
  2777. # Ensure Z order
  2778. for k in @spritekeys
  2779. sprite=@sprites[k]
  2780. y=sprite.y
  2781. sprite.y=i
  2782. sprite.oy=(sprite.zoom_y<=0) ? 0 : (i-y)/sprite.zoom_y
  2783. sprite.zoom_x*=@zoom_x
  2784. sprite.zoom_y*=@zoom_y
  2785. sprite.x*=@zoom_x
  2786. sprite.y*=@zoom_y
  2787. sprite.x+=(@offset_x/sprite.zoom_x)
  2788. sprite.y+=(@offset_y/sprite.zoom_y)
  2789. end
  2790. end
  2791. end
  2792.  
  2793.  
  2794.  
  2795. class SpriteWindow_Base < SpriteWindow
  2796. TEXTPADDING=4 # In pixels
  2797.  
  2798. def initialize(x, y, width, height)
  2799. super()
  2800. self.x = x
  2801. self.y = y
  2802. self.width = width
  2803. self.height = height
  2804. self.z = 100
  2805. @curframe=MessageConfig.pbGetSystemFrame()
  2806. @curfont=MessageConfig.pbGetSystemFontName()
  2807. @sysframe=AnimatedBitmap.new(@curframe)
  2808. @customskin=nil
  2809. __setWindowskin(@sysframe.bitmap)
  2810. __resolveSystemFrame()
  2811. pbSetSystemFont(self.contents) if self.contents
  2812. end
  2813.  
  2814. def __setWindowskin(skin)
  2815. if skin && (skin.width==192 && skin.height==128) || # RPGXP Windowskin
  2816. (skin.width==128 && skin.height==128) # RPGVX Windowskin
  2817. self.skinformat=0
  2818. else
  2819. self.skinformat=1
  2820. end
  2821. self.windowskin=skin
  2822. end
  2823.  
  2824. def __resolveSystemFrame
  2825. if self.skinformat==1
  2826. if !@resolvedFrame
  2827. @resolvedFrame=MessageConfig.pbGetSystemFrame()
  2828. @resolvedFrame.sub!(/\.[^\.\/\\]+$/,"")
  2829. end
  2830. self.loadSkinFile("#{@resolvedFrame}.txt") if @resolvedFrame!=""
  2831. end
  2832. end
  2833.  
  2834. def setSkin(skin) # Filename of windowskin to apply. Supports XP, VX, and animated skins.
  2835. @customskin.dispose if @customskin
  2836. @customskin=nil
  2837. resolvedName=pbResolveBitmap(skin)
  2838. return if !resolvedName || resolvedName==""
  2839. @customskin=AnimatedBitmap.new(resolvedName)
  2840. __setWindowskin(@customskin.bitmap)
  2841. if self.skinformat==1
  2842. skinbase=resolvedName.sub(/\.[^\.\/\\]+$/,"")
  2843. self.loadSkinFile("#{skinbase}.txt")
  2844. end
  2845. end
  2846.  
  2847. def setSystemFrame
  2848. @customskin.dispose if @customskin
  2849. @customskin=nil
  2850. __setWindowskin(@sysframe.bitmap)
  2851. __resolveSystemFrame()
  2852. end
  2853.  
  2854. def update
  2855. super
  2856. if self.windowskin
  2857. if @customskin
  2858. if @customskin.totalFrames>1
  2859. @customskin.update
  2860. __setWindowskin(@customskin.bitmap)
  2861. end
  2862. elsif @sysframe
  2863. if @sysframe.totalFrames>1
  2864. @sysframe.update
  2865. __setWindowskin(@sysframe.bitmap)
  2866. end
  2867. end
  2868. end
  2869. if @curframe!=MessageConfig.pbGetSystemFrame()
  2870. @curframe=MessageConfig.pbGetSystemFrame()
  2871. if @sysframe && !@customskin
  2872. @sysframe.dispose if @sysframe
  2873. @sysframe=AnimatedBitmap.new(@curframe)
  2874. @resolvedFrame=nil
  2875. __setWindowskin(@sysframe.bitmap)
  2876. __resolveSystemFrame()
  2877. end
  2878. begin
  2879. refresh
  2880. rescue NoMethodError
  2881. end
  2882. end
  2883. if @curfont!=MessageConfig.pbGetSystemFontName()
  2884. @curfont=MessageConfig.pbGetSystemFontName()
  2885. if self.contents && !self.contents.disposed?
  2886. pbSetSystemFont(self.contents)
  2887. end
  2888. begin
  2889. refresh
  2890. rescue NoMethodError
  2891. end
  2892. end
  2893. end
  2894.  
  2895. def dispose
  2896. self.contents.dispose if self.contents
  2897. @sysframe.dispose
  2898. @customskin.dispose if @customskin
  2899. super
  2900. end
  2901. end
  2902.  
  2903.  
  2904.  
  2905. class SpriteWindow_Selectable < SpriteWindow_Base
  2906. attr_reader :index
  2907.  
  2908. def initialize(x, y, width, height)
  2909. super(x, y, width, height)
  2910. @item_max = 1
  2911. @column_max = 1
  2912. @virtualOy=0
  2913. @index = -1
  2914. @row_height = 32
  2915. @column_spacing = 32
  2916. @ignore_input = false
  2917. end
  2918.  
  2919. def itemCount
  2920. return @item_max || 0
  2921. end
  2922.  
  2923. def index=(index)
  2924. if @index!=index
  2925. @index = index
  2926. priv_update_cursor_rect(true)
  2927. end
  2928. end
  2929.  
  2930. def rowHeight
  2931. return @row_height || 32
  2932. end
  2933.  
  2934. def rowHeight=(value)
  2935. if @row_height!=value
  2936. oldTopRow=self.top_row
  2937. @row_height=[1,value].max
  2938. self.top_row=oldTopRow
  2939. update_cursor_rect
  2940. end
  2941. end
  2942.  
  2943. def columns
  2944. return @column_max || 1
  2945. end
  2946.  
  2947. def columns=(value)
  2948. if @column_max!=value
  2949. @column_max=[1,value].max
  2950. update_cursor_rect
  2951. end
  2952. end
  2953.  
  2954. def columnSpacing
  2955. return @column_spacing || 32
  2956. end
  2957.  
  2958. def columnSpacing=(value)
  2959. if @column_spacing!=value
  2960. @column_spacing=[0,value].max
  2961. update_cursor_rect
  2962. end
  2963. end
  2964.  
  2965. def ignore_input=(value)
  2966. @ignore_input=value
  2967. end
  2968.  
  2969. def count
  2970. return @item_max
  2971. end
  2972.  
  2973. def row_max
  2974. return ((@item_max + @column_max - 1) / @column_max).to_i
  2975. end
  2976.  
  2977. def top_row
  2978. return (@virtualOy / (@row_height || 32)).to_i
  2979. end
  2980.  
  2981. def top_item
  2982. return top_row * @column_max
  2983. end
  2984.  
  2985. def update_cursor_rect
  2986. priv_update_cursor_rect
  2987. end
  2988.  
  2989. def top_row=(row)
  2990. if row>row_max-1
  2991. row=row_max-1
  2992. end
  2993. if row<0 # NOTE: The two comparison checks must be reversed since row_max can be 0
  2994. row=0
  2995. end
  2996. @virtualOy=row*@row_height
  2997. end
  2998.  
  2999. def page_row_max
  3000. return priv_page_row_max.to_i
  3001. end
  3002.  
  3003. def page_item_max
  3004. return priv_page_item_max.to_i
  3005. end
  3006.  
  3007. def itemRect(item)
  3008. if item<0 || item>=@item_max || item<self.top_item ||
  3009. item>self.top_item+self.page_item_max
  3010. return Rect.new(0,0,0,0)
  3011. else
  3012. cursor_width = (self.width-self.borderX-(@column_max-1)*@column_spacing) / @column_max
  3013. x = item % @column_max * (cursor_width + @column_spacing)
  3014. y = item / @column_max * @row_height - @virtualOy
  3015. return Rect.new(x, y, cursor_width, @row_height)
  3016. end
  3017. end
  3018.  
  3019. def update
  3020. super
  3021. if self.active and @item_max > 0 and @index >= 0 and !@ignore_input
  3022. if Input.repeat?(Input::DOWN)
  3023. if (Input.trigger?(Input::DOWN) && (@item_max%@column_max)==0) or
  3024. @index < @item_max - @column_max
  3025. oldindex=@index
  3026. @index = (@index + @column_max) % @item_max
  3027. if @index!=oldindex
  3028. pbPlayCursorSE()
  3029. update_cursor_rect
  3030. end
  3031. end
  3032. end
  3033. if Input.repeat?(Input::UP)
  3034. if (Input.trigger?(Input::UP) && (@item_max%@column_max)==0) or
  3035. @index >= @column_max
  3036. oldindex=@index
  3037. @index = (@index - @column_max + @item_max) % @item_max
  3038. if @index!=oldindex
  3039. pbPlayCursorSE()
  3040. update_cursor_rect
  3041. end
  3042. end
  3043. end
  3044. if Input.repeat?(Input::RIGHT)
  3045. if @column_max >= 2 and @index < @item_max - 1
  3046. oldindex=@index
  3047. @index += 1
  3048. if @index!=oldindex
  3049. pbPlayCursorSE()
  3050. update_cursor_rect
  3051. end
  3052. end
  3053. end
  3054. if Input.repeat?(Input::LEFT)
  3055. if @column_max >= 2 and @index > 0
  3056. oldindex=@index
  3057. @index -= 1
  3058. if @index!=oldindex
  3059. pbPlayCursorSE()
  3060. update_cursor_rect
  3061. end
  3062. end
  3063. end
  3064. if Input.repeat?(Input::R)
  3065. if self.index < @item_max-1
  3066. oldindex=@index
  3067. @index = [self.index+self.page_item_max, @item_max-1].min
  3068. if @index!=oldindex
  3069. pbPlayCursorSE()
  3070. self.top_row += self.page_row_max
  3071. update_cursor_rect
  3072. end
  3073. end
  3074. end
  3075. if Input.repeat?(Input::L)
  3076. if self.index > 0
  3077. oldindex=@index
  3078. @index = [self.index-self.page_item_max, 0].max
  3079. if @index!=oldindex
  3080. pbPlayCursorSE()
  3081. self.top_row -= self.page_row_max
  3082. update_cursor_rect
  3083. end
  3084. end
  3085. end
  3086. end
  3087. end
  3088.  
  3089. def refresh; ;end
  3090.  
  3091. private
  3092.  
  3093. def priv_page_row_max
  3094. return (self.height - self.borderY) / @row_height
  3095. end
  3096.  
  3097. def priv_page_item_max
  3098. return (self.height - self.borderY) / @row_height * @column_max
  3099. end
  3100.  
  3101. def priv_update_cursor_rect(force=false)
  3102. if @index < 0
  3103. self.cursor_rect.empty
  3104. self.refresh
  3105. return
  3106. end
  3107. row = @index / @column_max
  3108. if row < self.top_row
  3109. self.top_row = row
  3110. dorefresh=true
  3111. end
  3112. if row > self.top_row + (self.page_row_max - 1)
  3113. self.top_row = row - (self.page_row_max - 1)
  3114. dorefresh=true
  3115. end
  3116. self.top_row = [self.top_row, self.row_max - self.page_row_max].min
  3117. cursor_width = (self.width-self.borderX) / @column_max
  3118. x = self.index % @column_max * (cursor_width + @column_spacing)
  3119. y = self.index / @column_max * @row_height - @virtualOy
  3120. self.cursor_rect.set(x, y, cursor_width, @row_height)
  3121. self.refresh if dorefresh || force
  3122. end
  3123. end
  3124.  
  3125.  
  3126.  
  3127. module UpDownArrowMixin
  3128. def initUpDownArrow
  3129. @uparrow=AnimatedSprite.create("Graphics/Pictures/uparrow",8,2,self.viewport)
  3130. @downarrow=AnimatedSprite.create("Graphics/Pictures/downarrow",8,2,self.viewport)
  3131. @uparrow.z=99998
  3132. @downarrow.z=99998
  3133. @uparrow.visible=false
  3134. @downarrow.visible=false
  3135. @uparrow.play
  3136. @downarrow.play
  3137. end
  3138.  
  3139. def dispose
  3140. @uparrow.dispose
  3141. @downarrow.dispose
  3142. super
  3143. end
  3144.  
  3145. def viewport=(value)
  3146. super
  3147. @uparrow.viewport=self.viewport
  3148. @downarrow.viewport=self.viewport
  3149. end
  3150.  
  3151. def color=(value)
  3152. super
  3153. @uparrow.color=value
  3154. @downarrow.color=value
  3155. end
  3156.  
  3157. def adjustForZoom(sprite)
  3158. sprite.zoom_x=self.zoom_x
  3159. sprite.zoom_y=self.zoom_y
  3160. sprite.x=(sprite.x*self.zoom_x+self.offset_x/self.zoom_x)
  3161. sprite.y=(sprite.y*self.zoom_y+self.offset_y/self.zoom_y)
  3162. end
  3163.  
  3164. def update
  3165. super
  3166. @uparrow.x=self.x+(self.width/2)-(@uparrow.framewidth/2)
  3167. @downarrow.x=self.x+(self.width/2)-(@downarrow.framewidth/2)
  3168. @uparrow.y=self.y
  3169. @downarrow.y=self.y+self.height-@downarrow.frameheight
  3170. @uparrow.visible=self.visible && self.active && (self.top_item!=0 &&
  3171. @item_max > self.page_item_max)
  3172. @downarrow.visible=self.visible && self.active &&
  3173. (self.top_item+self.page_item_max<@item_max && @item_max > self.page_item_max)
  3174. @uparrow.z=self.z+1
  3175. @downarrow.z=self.z+1
  3176. adjustForZoom(@uparrow)
  3177. adjustForZoom(@downarrow)
  3178. @uparrow.viewport=self.viewport
  3179. @downarrow.viewport=self.viewport
  3180. @uparrow.update
  3181. @downarrow.update
  3182. end
  3183. end
  3184.  
  3185.  
  3186.  
  3187. class SpriteWindow_SelectableEx < SpriteWindow_Selectable
  3188. include UpDownArrowMixin
  3189.  
  3190. def initialize(*arg)
  3191. super(*arg)
  3192. initUpDownArrow
  3193. end
  3194. end
  3195.  
  3196.  
  3197.  
  3198. class Window_DrawableCommand < SpriteWindow_SelectableEx
  3199. attr_reader :baseColor
  3200. attr_reader :shadowColor
  3201.  
  3202. def textWidth(bitmap,text)
  3203. return tmpbitmap.text_size(i).width
  3204. end
  3205.  
  3206. def getAutoDims(commands,dims,width=nil)
  3207. rowMax=((commands.length + self.columns - 1) / self.columns).to_i
  3208. windowheight=(rowMax*self.rowHeight)
  3209. windowheight+=self.borderY
  3210. if !width || width<0
  3211. width=0
  3212. tmpbitmap=BitmapWrapper.new(1,1)
  3213. pbSetSystemFont(tmpbitmap)
  3214. for i in commands
  3215. width=[width,tmpbitmap.text_size(i).width].max
  3216. end
  3217. # one 16 to allow cursor
  3218. width+=16+16+SpriteWindow_Base::TEXTPADDING
  3219. tmpbitmap.dispose
  3220. end
  3221. # Store suggested width and height of window
  3222. dims[0]=[self.borderX+1,(width*self.columns)+self.borderX+
  3223. (self.columns-1)*self.columnSpacing].max
  3224. dims[1]=[self.borderY+1,windowheight].max
  3225. dims[1]=[dims[1],Graphics.height].min
  3226. end
  3227.  
  3228. def initialize(x,y,width,height,viewport=nil)
  3229. super(x,y,width,height)
  3230. self.viewport=viewport if viewport
  3231. @selarrow=AnimatedBitmap.new("Graphics/Pictures/selarrow")
  3232. @index=0
  3233. colors=getDefaultTextColors(self.windowskin)
  3234. @baseColor=colors[0]
  3235. @shadowColor=colors[1]
  3236. refresh
  3237. end
  3238.  
  3239. def drawCursor(index,rect)
  3240. if self.index==index
  3241. pbCopyBitmap(self.contents,@selarrow.bitmap,rect.x,rect.y)
  3242. end
  3243. return Rect.new(rect.x+16,rect.y,rect.width-16,rect.height)
  3244. end
  3245.  
  3246. def dispose
  3247. @selarrow.dispose
  3248. super
  3249. end
  3250.  
  3251. def baseColor=(value)
  3252. @baseColor=value
  3253. refresh
  3254. end
  3255.  
  3256. def shadowColor=(value)
  3257. @shadowColor=value
  3258. refresh
  3259. end
  3260.  
  3261. def itemCount # to be implemented by derived classes
  3262. return 0
  3263. end
  3264.  
  3265. def drawItem(index,count,rect) # to be implemented by derived classes
  3266. end
  3267.  
  3268. def refresh
  3269. @item_max=itemCount()
  3270. dwidth=self.width-self.borderX
  3271. dheight=self.height-self.borderY
  3272. self.contents=pbDoEnsureBitmap(self.contents,dwidth,dheight)
  3273. self.contents.clear
  3274. for i in 0...@item_max
  3275. if i<self.top_item || i>self.top_item+self.page_item_max
  3276. next
  3277. end
  3278. drawItem(i,@item_max,itemRect(i))
  3279. end
  3280. end
  3281.  
  3282. def update
  3283. oldindex=self.index
  3284. super
  3285. refresh if self.index!=oldindex
  3286. end
  3287. end
  3288.  
  3289.  
  3290.  
  3291. class Window_CommandPokemon < Window_DrawableCommand
  3292. attr_reader :commands
  3293.  
  3294. def initialize(commands,width=nil)
  3295. @starting=true
  3296. @commands=[]
  3297. dims=[]
  3298. super(0,0,32,32)
  3299. getAutoDims(commands,dims,width)
  3300. self.width=dims[0]
  3301. self.height=dims[1]
  3302. @commands=commands
  3303. self.active=true
  3304. colors=getDefaultTextColors(self.windowskin)
  3305. self.baseColor=colors[0]
  3306. self.shadowColor=colors[1]
  3307. refresh
  3308. @starting=false
  3309. end
  3310.  
  3311. def self.newWithSize(commands,x,y,width,height,viewport=nil)
  3312. ret=self.new(commands,width)
  3313. ret.x=x
  3314. ret.y=y
  3315. ret.width=width
  3316. ret.height=height
  3317. ret.viewport=viewport
  3318. return ret
  3319. end
  3320.  
  3321. def self.newEmpty(x,y,width,height,viewport=nil)
  3322. ret=self.new([],width)
  3323. ret.x=x
  3324. ret.y=y
  3325. ret.width=width
  3326. ret.height=height
  3327. ret.viewport=viewport
  3328. return ret
  3329. end
  3330.  
  3331. def index=(value)
  3332. super
  3333. refresh if !@starting
  3334. end
  3335.  
  3336. def commands=(value)
  3337. @commands=value
  3338. @item_max=commands.length
  3339. self.update_cursor_rect
  3340. self.refresh
  3341. end
  3342.  
  3343. def width=(value)
  3344. super
  3345. if !@starting
  3346. self.index=self.index
  3347. self.update_cursor_rect
  3348. end
  3349. end
  3350.  
  3351. def height=(value)
  3352. super
  3353. if !@starting
  3354. self.index=self.index
  3355. self.update_cursor_rect
  3356. end
  3357. end
  3358.  
  3359. def resizeToFit(commands,width=nil)
  3360. dims=[]
  3361. getAutoDims(commands,dims,width)
  3362. self.width=dims[0]
  3363. self.height=dims[1]
  3364. end
  3365.  
  3366. def itemCount
  3367. return @commands ? @commands.length : 0
  3368. end
  3369.  
  3370. def drawItem(index,count,rect)
  3371. pbSetSystemFont(self.contents) if @starting
  3372. rect=drawCursor(index,rect)
  3373. pbDrawShadowText(self.contents,rect.x,rect.y,rect.width,rect.height,
  3374. @commands[index],self.baseColor,self.shadowColor)
  3375. end
  3376. end
  3377.  
  3378.  
  3379.  
  3380. class Window_AdvancedCommandPokemon < Window_DrawableCommand
  3381. attr_reader :commands
  3382.  
  3383. def textWidth(bitmap,text)
  3384. dims=[nil,0]
  3385. chars=getFormattedText(bitmap,0,0,
  3386. Graphics.width-self.borderX-SpriteWindow_Base::TEXTPADDING-16,
  3387. -1,text,self.rowHeight,true,true)
  3388. for ch in chars
  3389. dims[0]=dims[0] ? [dims[0],ch[1]].min : ch[1]
  3390. dims[1]=[dims[1],ch[1]+ch[3]].max
  3391. end
  3392. dims[0]=0 if !dims[0]
  3393. return dims[1]-dims[0]
  3394. end
  3395.  
  3396. def initialize(commands,width=nil)
  3397. @starting=true
  3398. @commands=[]
  3399. dims=[]
  3400. super(0,0,32,32)
  3401. getAutoDims(commands,dims,width)
  3402. self.width=dims[0]
  3403. self.height=dims[1]
  3404. @commands=commands
  3405. self.active=true
  3406. colors=getDefaultTextColors(self.windowskin)
  3407. self.baseColor=colors[0]
  3408. self.shadowColor=colors[1]
  3409. refresh
  3410. @starting=false
  3411. end
  3412.  
  3413. def self.newWithSize(commands,x,y,width,height,viewport=nil)
  3414. ret=self.new(commands,width)
  3415. ret.x=x
  3416. ret.y=y
  3417. ret.width=width
  3418. ret.height=height
  3419. ret.viewport=viewport
  3420. return ret
  3421. end
  3422.  
  3423. def self.newEmpty(x,y,width,height,viewport=nil)
  3424. ret=self.new([],width)
  3425. ret.x=x
  3426. ret.y=y
  3427. ret.width=width
  3428. ret.height=height
  3429. ret.viewport=viewport
  3430. return ret
  3431. end
  3432.  
  3433. def index=(value)
  3434. super
  3435. refresh if !@starting
  3436. end
  3437.  
  3438. def commands=(value)
  3439. @commands=value
  3440. @item_max=commands.length
  3441. self.update_cursor_rect
  3442. self.refresh
  3443. end
  3444.  
  3445. def width=(value)
  3446. oldvalue=self.width
  3447. super
  3448. if !@starting && oldvalue!=value
  3449. self.index=self.index
  3450. self.update_cursor_rect
  3451. end
  3452. end
  3453.  
  3454. def height=(value)
  3455. oldvalue=self.height
  3456. super
  3457. if !@starting && oldvalue!=value
  3458. self.index=self.index
  3459. self.update_cursor_rect
  3460. end
  3461. end
  3462.  
  3463. def resizeToFit(commands,width=nil)
  3464. dims=[]
  3465. getAutoDims(commands,dims,width)
  3466. self.width=dims[0]
  3467. self.height=dims[1]
  3468. end
  3469.  
  3470. def itemCount
  3471. return @commands ? @commands.length : 0
  3472. end
  3473.  
  3474. def drawItem(index,count,rect)
  3475. pbSetSystemFont(self.contents)
  3476. rect=drawCursor(index,rect)
  3477. if toUnformattedText(@commands[index]).gsub(/\n/,"")==@commands[index]
  3478. # Use faster alternative for unformatted text without line breaks
  3479. pbDrawShadowText(self.contents,rect.x,rect.y,rect.width,rect.height,
  3480. @commands[index],self.baseColor,self.shadowColor)
  3481. else
  3482. chars=getFormattedText(
  3483. self.contents,rect.x,rect.y,rect.width,rect.height,
  3484. @commands[index],rect.height,true,true)
  3485. drawFormattedChars(self.contents,chars)
  3486. end
  3487. end
  3488. end
  3489.  
  3490.  
  3491.  
  3492. # Represents a window with no formatting capabilities. Its text color can be set,
  3493. # though, and line breaks are supported, but the text is generally unformatted.
  3494. class Window_UnformattedTextPokemon < SpriteWindow_Base
  3495. attr_reader :text
  3496. attr_reader :baseColor
  3497. attr_reader :shadowColor
  3498. # Letter-by-letter mode. This mode is not supported in this class.
  3499. attr_accessor :letterbyletter
  3500.  
  3501. def text=(value)
  3502. @text=value
  3503. refresh
  3504. end
  3505.  
  3506. def baseColor=(value)
  3507. @baseColor=value
  3508. refresh
  3509. end
  3510.  
  3511. def shadowColor=(value)
  3512. @shadowColor=value
  3513. refresh
  3514. end
  3515.  
  3516. def initialize(text="")
  3517. super(0,0,33,33)
  3518. self.contents=Bitmap.new(1,1)
  3519. pbSetSystemFont(self.contents)
  3520. @text=text
  3521. @letterbyletter=false # Not supported in this class
  3522. colors=getDefaultTextColors(self.windowskin)
  3523. @baseColor=colors[0]
  3524. @shadowColor=colors[1]
  3525. resizeToFit(text)
  3526. end
  3527.  
  3528. def self.newWithSize(text,x,y,width,height,viewport=nil)
  3529. ret=self.new(text)
  3530. ret.x=x
  3531. ret.y=y
  3532. ret.width=width
  3533. ret.height=height
  3534. ret.viewport=viewport
  3535. ret.refresh
  3536. return ret
  3537. end
  3538.  
  3539. def resizeToFitInternal(text,maxwidth) # maxwidth is maximum acceptable window width
  3540. dims=[0,0]
  3541. cwidth=maxwidth<0 ? Graphics.width : maxwidth
  3542. getLineBrokenChunks(self.contents,text,
  3543. cwidth-self.borderX-SpriteWindow_Base::TEXTPADDING,dims,true)
  3544. return dims
  3545. end
  3546.  
  3547. def setTextToFit(text,maxwidth=-1)
  3548. resizeToFit(text,maxwidth)
  3549. self.text=text
  3550. end
  3551.  
  3552. def resizeToFit(text,maxwidth=-1) # maxwidth is maximum acceptable window width
  3553. dims=resizeToFitInternal(text,maxwidth)
  3554. self.width=dims[0]+self.borderX+SpriteWindow_Base::TEXTPADDING
  3555. self.height=dims[1]+self.borderY
  3556. refresh
  3557. end
  3558.  
  3559. def resizeHeightToFit(text,width=-1) # width is current window width
  3560. dims=resizeToFitInternal(text,width)
  3561. self.width=width<0 ? Graphics.width : width
  3562. self.height=dims[1]+self.borderY
  3563. refresh
  3564. end
  3565.  
  3566. def refresh
  3567. self.contents=pbDoEnsureBitmap(self.contents,self.width-self.borderX,
  3568. self.height-self.borderY)
  3569. self.contents.clear
  3570. drawTextEx(self.contents,0,0,self.contents.width,0,
  3571. @text.gsub(/\r/,""),@baseColor,@shadowColor)
  3572. end
  3573. end
  3574.  
  3575.  
  3576.  
  3577. class Window_AdvancedTextPokemon < SpriteWindow_Base
  3578. attr_reader :text
  3579. attr_reader :baseColor
  3580. attr_reader :shadowColor
  3581. attr_accessor :letterbyletter
  3582. attr_reader :lineHeight
  3583.  
  3584. def lineHeight(value)
  3585. @lineHeight=value
  3586. self.text=self.text
  3587. end
  3588.  
  3589. def text=(value)
  3590. setText(value)
  3591. end
  3592.  
  3593. def textspeed
  3594. @frameskip
  3595. end
  3596.  
  3597. def textspeed=(value)
  3598. @frameskip=value
  3599. @frameskipChanged=true
  3600. end
  3601.  
  3602. def waitcount
  3603. @waitcount
  3604. end
  3605.  
  3606. def waitcount=(value)
  3607. @waitcount=(value<=0) ? 0 : value
  3608. end
  3609.  
  3610. def setText(value)
  3611. @waitcount=0
  3612. @curchar=0
  3613. @drawncurchar=-1
  3614. @lastDrawnChar=-1
  3615. oldtext=@text
  3616. @text=value
  3617. @textlength=unformattedTextLength(value)
  3618. @scrollstate=0
  3619. @scrollY=0
  3620. @linesdrawn=0
  3621. @realframes=0
  3622. @textchars=[]
  3623. width=1
  3624. height=1
  3625. numlines=0
  3626. visiblelines=(self.height-self.borderY)/32
  3627. if value.length==0
  3628. @fmtchars=[]
  3629. @bitmapwidth=width
  3630. @bitmapheight=height
  3631. @numtextchars=0
  3632. else
  3633. if !@letterbyletter
  3634. @fmtchars=getFormattedText(self.contents,0,0,
  3635. self.width-self.borderX-SpriteWindow_Base::TEXTPADDING,-1,
  3636. shadowctag(@baseColor,@shadowColor)+value,32,true)
  3637. @oldfont=self.contents.font.clone
  3638. for ch in @fmtchars
  3639. chx=ch[1]+ch[3]
  3640. chy=ch[2]+ch[4]
  3641. width=chx if width<chx
  3642. height=chy if height<chy
  3643. @textchars.push(ch[5] ? "" : ch[0])
  3644. end
  3645. else
  3646. @fmtchars=[]
  3647. fmt=getFormattedText(self.contents,0,0,
  3648. self.width-self.borderX-SpriteWindow_Base::TEXTPADDING,-1,
  3649. shadowctag(@baseColor,@shadowColor)+value,32,true)
  3650. @oldfont=self.contents.font.clone
  3651. for ch in fmt
  3652. chx=ch[1]+ch[3]
  3653. chy=ch[2]+ch[4]
  3654. width=chx if width<chx
  3655. height=chy if height<chy
  3656. if !ch[5] && ch[0]=="\n" && @letterbyletter
  3657. numlines+=1
  3658. if numlines>=visiblelines
  3659. fclone=ch.clone
  3660. fclone[0]="\1"
  3661. @fmtchars.push(fclone)
  3662. @textchars.push("\1")
  3663. end
  3664. end
  3665. # Don't add newline characters, since they
  3666. # can slow down letter-by-letter display
  3667. if ch[5] || (ch[0]!="\r")
  3668. @fmtchars.push(ch)
  3669. @textchars.push(ch[5] ? "" : ch[0])
  3670. end
  3671. end
  3672. fmt.clear
  3673. end
  3674. @bitmapwidth=width
  3675. @bitmapheight=height
  3676. @numtextchars=@textchars.length
  3677. end
  3678. stopPause
  3679. @displaying=@letterbyletter
  3680. @needclear=true
  3681. @nodraw=@letterbyletter
  3682. refresh
  3683. end
  3684.  
  3685. def baseColor=(value)
  3686. @baseColor=value
  3687. refresh
  3688. end
  3689.  
  3690. def shadowColor=(value)
  3691. @shadowColor=value
  3692. refresh
  3693. end
  3694.  
  3695. def busy?
  3696. return @displaying
  3697. end
  3698.  
  3699. def pausing?
  3700. return @pausing && @displaying
  3701. end
  3702.  
  3703. def resume
  3704. if !busy?
  3705. self.stopPause
  3706. return true
  3707. end
  3708. if @pausing
  3709. @pausing=false
  3710. self.stopPause
  3711. return false
  3712. else
  3713. return true
  3714. end
  3715. end
  3716.  
  3717. def dispose
  3718. return if disposed?
  3719. @pausesprite.dispose if @pausesprite
  3720. @pausesprite=nil
  3721. super
  3722. end
  3723.  
  3724. attr_reader :cursorMode
  3725.  
  3726. def cursorMode=(value)
  3727. @cursorMode=value
  3728. moveCursor
  3729. end
  3730.  
  3731. def moveCursor
  3732. if @pausesprite
  3733. cursor=@cursorMode
  3734. cursor=2 if cursor==0 && !@endOfText
  3735. case cursor
  3736. when 0 # End of text
  3737. @pausesprite.x=self.x+self.startX+@endOfText.x+@endOfText.width-2
  3738. @pausesprite.y=self.y+self.startY+@endOfText.y-@scrollY
  3739. when 1 # Lower right
  3740. pauseWidth=@pausesprite.bitmap ? @pausesprite.framewidth : 16
  3741. pauseHeight=@pausesprite.bitmap ? @pausesprite.frameheight : 16
  3742. @pausesprite.x=self.x+self.width-(20*2)+(pauseWidth/2)
  3743. @pausesprite.y=self.y+self.height-(30*2)+(pauseHeight/2)
  3744. when 2 # Lower middle
  3745. pauseWidth=@pausesprite.bitmap ? @pausesprite.framewidth : 16
  3746. pauseHeight=@pausesprite.bitmap ? @pausesprite.frameheight : 16
  3747. @pausesprite.x=self.x+(self.width/2)-(pauseWidth/2)
  3748. @pausesprite.y=self.y+self.height-(18*2)+(pauseHeight/2)
  3749. end
  3750. end
  3751. end
  3752.  
  3753. def initialize(text="")
  3754. @cursorMode=MessageConfig::CURSORMODE
  3755. @endOfText=nil
  3756. @scrollstate=0
  3757. @realframes=0
  3758. @scrollY=0
  3759. @nodraw=false
  3760. @lineHeight=32
  3761. @linesdrawn=0
  3762. @bufferbitmap=nil
  3763. @letterbyletter=false
  3764. @starting=true
  3765. @displaying=false
  3766. @lastDrawnChar=-1
  3767. @fmtchars=[]
  3768. @frameskipChanged=false
  3769. @frameskip=MessageConfig.pbGetTextSpeed()
  3770. super(0,0,33,33)
  3771. @pausesprite=nil
  3772. @text=""
  3773. self.contents=Bitmap.new(1,1)
  3774. pbSetSystemFont(self.contents)
  3775. self.resizeToFit(text,Graphics.width)
  3776. colors=getDefaultTextColors(self.windowskin)
  3777. @baseColor=colors[0]
  3778. @shadowColor=colors[1]
  3779. self.text=text
  3780. @starting=false
  3781. end
  3782.  
  3783. def self.newWithSize(text,x,y,width,height,viewport=nil)
  3784. ret=self.new(text)
  3785. ret.x=x
  3786. ret.y=y
  3787. ret.width=width
  3788. ret.height=height
  3789. ret.viewport=viewport
  3790. return ret
  3791. end
  3792.  
  3793. def width=(value)
  3794. super
  3795. if !@starting
  3796. self.text=self.text
  3797. end
  3798. end
  3799.  
  3800. def height=(value)
  3801. super
  3802. if !@starting
  3803. self.text=self.text
  3804. end
  3805. end
  3806.  
  3807. def resizeToFitInternal(text,maxwidth)
  3808. dims=[0,0]
  3809. cwidth=maxwidth<0 ? Graphics.width : maxwidth
  3810. chars=getFormattedTextForDims(self.contents,0,0,
  3811. cwidth-self.borderX-2-6,-1,text,@lineHeight,true)
  3812. for ch in chars
  3813. dims[0]=[dims[0],ch[1]+ch[3]].max
  3814. dims[1]=[dims[1],ch[2]+ch[4]].max
  3815. end
  3816. return dims
  3817. end
  3818.  
  3819. def resizeToFit2(text,maxwidth,maxheight)
  3820. dims=resizeToFitInternal(text,maxwidth)
  3821. oldstarting=@starting
  3822. @starting=true
  3823. self.width=[dims[0]+self.borderX+SpriteWindow_Base::TEXTPADDING,maxwidth].min
  3824. self.height=[dims[1]+self.borderY,maxheight].min
  3825. @starting=oldstarting
  3826. redrawText
  3827. end
  3828.  
  3829. def setTextToFit(text,maxwidth=-1)
  3830. resizeToFit(text,maxwidth)
  3831. self.text=text
  3832. end
  3833.  
  3834. def resizeToFit(text,maxwidth=-1)
  3835. dims=resizeToFitInternal(text,maxwidth)
  3836. oldstarting=@starting
  3837. @starting=true
  3838. self.width=dims[0]+self.borderX+SpriteWindow_Base::TEXTPADDING
  3839. self.height=dims[1]+self.borderY
  3840. @starting=oldstarting
  3841. redrawText
  3842. end
  3843.  
  3844. def resizeHeightToFit(text,width=-1)
  3845. dims=resizeToFitInternal(text,width)
  3846. oldstarting=@starting
  3847. @starting=true
  3848. self.width=width<0 ? Graphics.width : width
  3849. self.height=dims[1]+self.borderY
  3850. @starting=oldstarting
  3851. redrawText
  3852. end
  3853.  
  3854. def refresh
  3855. oldcontents=self.contents
  3856. self.contents=pbDoEnsureBitmap(oldcontents,@bitmapwidth,@bitmapheight)
  3857. self.oy=@scrollY
  3858. numchars=@numtextchars
  3859. startchar=0
  3860. numchars=[@curchar,@numtextchars].min if self.letterbyletter
  3861. if busy? && @drawncurchar==@curchar && @scrollstate==0
  3862. return
  3863. end
  3864. if !self.letterbyletter || !oldcontents.equal?(self.contents)
  3865. @drawncurchar=-1
  3866. @needclear=true
  3867. end
  3868. if @needclear
  3869. self.contents.font=@oldfont if @oldfont
  3870. self.contents.clear
  3871. @needclear=false
  3872. end
  3873. if @nodraw
  3874. @nodraw=false
  3875. return
  3876. end
  3877. maxX=self.width-self.borderX
  3878. maxY=self.height-self.borderY
  3879. for i in @drawncurchar+1..numchars
  3880. next if i>=@fmtchars.length
  3881. if !self.letterbyletter
  3882. next if @fmtchars[i][1]>=maxX
  3883. next if @fmtchars[i][2]>=maxY
  3884. end
  3885. drawSingleFormattedChar(self.contents,@fmtchars[i])
  3886. @lastDrawnChar=i
  3887. end
  3888. if !self.letterbyletter
  3889. # all characters were drawn, reset old font
  3890. self.contents.font=@oldfont if @oldfont
  3891. end
  3892. if numchars>0 && numchars!=@numtextchars
  3893. fch=@fmtchars[numchars-1]
  3894. if fch
  3895. rcdst=Rect.new(fch[1],fch[2],fch[3],fch[4])
  3896. if @textchars[numchars]=="\1"
  3897. @endOfText=rcdst
  3898. allocPause
  3899. moveCursor()
  3900. else
  3901. @endOfText=Rect.new(rcdst.x+rcdst.width,rcdst.y,8,1)
  3902. end
  3903. end
  3904. end
  3905. @drawncurchar=@curchar
  3906. end
  3907.  
  3908. def maxPosition
  3909. pos=0
  3910. for ch in @fmtchars
  3911. # index after the last character's index
  3912. pos=ch[14]+1 if pos<ch[14]+1
  3913. end
  3914. return pos
  3915. end
  3916.  
  3917. def position
  3918. if @lastDrawnChar<0
  3919. return 0
  3920. elsif @lastDrawnChar>=@fmtchars.length
  3921. return @numtextchars
  3922. else
  3923. # index after the last character's index
  3924. return @fmtchars[@lastDrawnChar][14]+1
  3925. end
  3926. end
  3927.  
  3928. def redrawText
  3929. if !@letterbyletter
  3930. self.text=self.text
  3931. else
  3932. oldPosition=self.position
  3933. self.text=self.text
  3934. oldPosition=@numtextchars if oldPosition>@numtextchars
  3935. while self.position!=oldPosition
  3936. refresh
  3937. updateInternal
  3938. end
  3939. end
  3940. end
  3941.  
  3942. def updateInternal
  3943. curcharskip=@frameskip<0 ? @frameskip.abs : 1
  3944. visiblelines=(self.height-self.borderY)/@lineHeight
  3945. if @textchars[@curchar]=="\1"
  3946. if !@pausing
  3947. @realframes+=1
  3948. if @realframes>=@frameskip || @frameskip<0
  3949. curcharSkip(curcharskip)
  3950. @realframes=0
  3951. end
  3952. end
  3953. elsif @textchars[@curchar]=="\n"
  3954. if @linesdrawn>=visiblelines-1
  3955. if @scrollstate<@lineHeight
  3956. @scrollstate+=[(@lineHeight/4),1].max
  3957. @scrollY+=[(@lineHeight/4),1].max
  3958. end
  3959. if @scrollstate>=@lineHeight
  3960. @realframes+=1
  3961. if @realframes>=@frameskip || @frameskip<0
  3962. curcharSkip(curcharskip)
  3963. @linesdrawn+=1
  3964. @scrollstate=0
  3965. @realframes=0
  3966. end
  3967. end
  3968. else
  3969. @realframes+=1
  3970. if @realframes>=@frameskip || @frameskip<0
  3971. curcharSkip(curcharskip)
  3972. @linesdrawn+=1
  3973. @realframes=0
  3974. end
  3975. end
  3976. elsif @curchar<=@numtextchars
  3977. @realframes+=1
  3978. if @realframes>=@frameskip || @frameskip<0
  3979. curcharSkip(curcharskip)
  3980. @realframes=0
  3981. end
  3982. if @textchars[@curchar]=="\1"
  3983. @pausing=true if @curchar<@numtextchars-1
  3984. self.startPause
  3985. refresh
  3986. end
  3987. else
  3988. @displaying=false
  3989. @scrollstate=0
  3990. @scrollY=0
  3991. @linesdrawn=0
  3992. end
  3993. end
  3994.  
  3995. def update
  3996. super
  3997. if @pausesprite && @pausesprite.visible
  3998. @pausesprite.update
  3999. end
  4000. if @waitcount>0
  4001. @waitcount-=1
  4002. return
  4003. end
  4004. if busy?
  4005. refresh if !@frameskipChanged
  4006. updateInternal
  4007. # following line needed to allow "textspeed=-999" to work seamlessly
  4008. refresh if @frameskipChanged
  4009. end
  4010. @frameskipChanged=false
  4011. end
  4012.  
  4013. def allocPause
  4014. if !@pausesprite
  4015. @pausesprite=AnimatedSprite.create("Graphics/Pictures/pause",4,3)
  4016. @pausesprite.z=100000
  4017. @pausesprite.visible=false
  4018. end
  4019. end
  4020.  
  4021. def startPause
  4022. allocPause
  4023. @pausesprite.visible=true
  4024. @pausesprite.frame=0
  4025. @pausesprite.start
  4026. moveCursor
  4027. end
  4028.  
  4029. def stopPause
  4030. if @pausesprite
  4031. @pausesprite.stop
  4032. @pausesprite.visible=false
  4033. end
  4034. end
  4035.  
  4036. private
  4037.  
  4038. def curcharSkip(skip)
  4039. skip.times do
  4040. @curchar+=1
  4041. break if @textchars[@curchar]=="\n" || # newline
  4042. @textchars[@curchar]=="\1" || # pause
  4043. @textchars[@curchar]=="\2" || # letter-by-letter break
  4044. @textchars[@curchar]==nil
  4045. end
  4046. end
  4047. end
  4048.  
  4049.  
  4050.  
  4051. class Window_InputNumberPokemon < SpriteWindow_Base
  4052. attr_reader :number
  4053. attr_reader :sign
  4054.  
  4055. def initialize(digits_max)
  4056. @digits_max=digits_max
  4057. @number=0
  4058. @frame=0
  4059. @sign=false
  4060. @negative=false
  4061. super(0,0,32,32)
  4062. self.width=digits_max*24+8+self.borderX
  4063. self.height=32+self.borderY
  4064. colors=getDefaultTextColors(self.windowskin)
  4065. @baseColor=colors[0]
  4066. @shadowColor=colors[1]
  4067. @index=digits_max-1
  4068. self.active=true
  4069. refresh
  4070. end
  4071.  
  4072. def active=(value)
  4073. super
  4074. refresh
  4075. end
  4076.  
  4077. def number
  4078. @number*(@sign && @negative ? -1 : 1)
  4079. end
  4080.  
  4081. def sign=(value)
  4082. @sign=value
  4083. self.width=@digits_max*24+8+self.borderX+(@sign ? 24 : 0)
  4084. @index=(@digits_max-1)+(@sign ? 1 : 0)
  4085. refresh
  4086. end
  4087.  
  4088. def number=(value)
  4089. value=0 if !value.is_a?(Numeric)
  4090. if @sign
  4091. @negative=(value<0)
  4092. @number = [value.abs, 10 ** @digits_max - 1].min
  4093. else
  4094. @number = [[value, 0].max, 10 ** @digits_max - 1].min
  4095. end
  4096. refresh
  4097. end
  4098.  
  4099. def refresh
  4100. self.contents=pbDoEnsureBitmap(self.contents,
  4101. self.width-self.borderX,self.height-self.borderY)
  4102. pbSetSystemFont(self.contents)
  4103. self.contents.clear
  4104. s=sprintf("%0*d",@digits_max,@number.abs)
  4105. x=0
  4106. if @sign
  4107. textHelper(0,0,@negative ? "-" : "+",0)
  4108. end
  4109. for i in 0...@digits_max
  4110. index=i+(@sign ? 1 : 0)
  4111. textHelper(index*24,0,s[i,1],index)
  4112. end
  4113. end
  4114.  
  4115. def update
  4116. super
  4117. digits=@digits_max+(@sign ? 1 : 0)
  4118. refresh if @frame%15==0
  4119. if self.active
  4120. if Input.repeat?(Input::UP) or Input.repeat?(Input::DOWN)
  4121. pbPlayCursorSE()
  4122. if @index==0 && @sign
  4123. @negative=!@negative
  4124. else
  4125. place = 10 ** (digits - 1 - @index)
  4126. n = @number / place % 10
  4127. @number -= n*place
  4128. if Input.repeat?(Input::UP)
  4129. n = (n + 1) % 10
  4130. elsif Input.repeat?(Input::DOWN)
  4131. n = (n + 9) % 10
  4132. end
  4133. @number += n*place
  4134. end
  4135. refresh
  4136. elsif Input.repeat?(Input::RIGHT)
  4137. if digits >= 2
  4138. pbPlayCursorSE()
  4139. @index = (@index + 1) % digits
  4140. @frame=0
  4141. refresh
  4142. end
  4143. elsif Input.repeat?(Input::LEFT)
  4144. if digits >= 2
  4145. pbPlayCursorSE()
  4146. @index = (@index + digits - 1) % digits
  4147. @frame=0
  4148. refresh
  4149. end
  4150. end
  4151. end
  4152. @frame=(@frame+1)%30
  4153. end
  4154.  
  4155. private
  4156.  
  4157. def textHelper(x,y,text,i)
  4158. textwidth=self.contents.text_size(text).width
  4159. self.contents.font.color=@shadowColor
  4160. pbDrawShadow(self.contents,x+(12-textwidth/2),y, textwidth+4, 32, text)
  4161. self.contents.font.color=@baseColor
  4162. self.contents.draw_text(x+(12-textwidth/2),y, textwidth+4, 32, text)
  4163. if @index==i && @active && @frame/15==0
  4164. colors=getDefaultTextColors(self.windowskin)
  4165. self.contents.fill_rect(x+(12-textwidth/2),y+30,textwidth,2,colors[0])
  4166. end
  4167. end
  4168. end
  4169.  
  4170.  
  4171.  
  4172. class AnimatedSprite < SpriteWrapper
  4173. attr_reader :frame
  4174. attr_reader :framewidth
  4175. attr_reader :frameheight
  4176. attr_reader :framecount
  4177. attr_reader :animname
  4178.  
  4179. def initializeLong(animname,framecount,framewidth,frameheight,frameskip)
  4180. @animname=pbBitmapName(animname)
  4181. @realframes=0
  4182. @frameskip=[1,frameskip].max
  4183. raise _INTL("Frame width is 0") if framewidth==0
  4184. raise _INTL("Frame height is 0") if frameheight==0
  4185. begin
  4186. @animbitmap=AnimatedBitmap.new(animname).deanimate
  4187. rescue
  4188. @animbitmap=Bitmap.new(framewidth,frameheight)
  4189. end
  4190. if @animbitmap.width%framewidth!=0
  4191. raise _INTL("Bitmap's width ({1}) is not a multiple of frame width ({2}) [Bitmap={3}]",
  4192. @animbitmap.width,framewidth,animname)
  4193. end
  4194. if @animbitmap.height%frameheight!=0
  4195. raise _INTL("Bitmap's height ({1}) is not a multiple of frame height ({2}) [Bitmap={3}]",
  4196. @animbitmap.height,frameheight,animname)
  4197. end
  4198. @framecount=framecount
  4199. @framewidth=framewidth
  4200. @frameheight=frameheight
  4201. @framesperrow=@animbitmap.width/@framewidth
  4202. @playing=false
  4203. self.bitmap=@animbitmap
  4204. self.src_rect.width=@framewidth
  4205. self.src_rect.height=@frameheight
  4206. self.frame=0
  4207. end
  4208.  
  4209. # Shorter version of AnimationSprite. All frames are placed on a single row
  4210. # of the bitmap, so that the width and height need not be defined beforehand
  4211. def initializeShort(animname,framecount,frameskip)
  4212. @animname=pbBitmapName(animname)
  4213. @realframes=0
  4214. @frameskip=[1,frameskip].max
  4215. begin
  4216. @animbitmap=AnimatedBitmap.new(animname).deanimate
  4217. rescue
  4218. @animbitmap=Bitmap.new(framecount*4,32)
  4219. end
  4220. if @animbitmap.width%framecount!=0
  4221. raise _INTL("Bitmap's width ({1}) is not a multiple of frame count ({2}) [Bitmap={3}]",
  4222. @animbitmap.width,framewidth,animname)
  4223. end
  4224. @framecount=framecount
  4225. @framewidth=@animbitmap.width/@framecount
  4226. @frameheight=@animbitmap.height
  4227. @framesperrow=framecount
  4228. @playing=false
  4229. self.bitmap=@animbitmap
  4230. self.src_rect.width=@framewidth
  4231. self.src_rect.height=@frameheight
  4232. self.frame=0
  4233. end
  4234.  
  4235. def initialize(*args)
  4236. if args.length==1
  4237. super(args[0][3])
  4238. initializeShort(args[0][0],args[0][1],args[0][2])
  4239. else
  4240. super(args[5])
  4241. initializeLong(args[0],args[1],args[2],args[3],args[4])
  4242. end
  4243. end
  4244.  
  4245. def self.create(animname,framecount,frameskip,viewport=nil)
  4246. return self.new([animname,framecount,frameskip,viewport])
  4247. end
  4248.  
  4249. def dispose
  4250. return if disposed?
  4251. @animbitmap.dispose
  4252. @animbitmap=nil
  4253. super
  4254. end
  4255.  
  4256. def playing?
  4257. return @playing
  4258. end
  4259.  
  4260. def frame=(value)
  4261. @frame=value
  4262. @realframes=0
  4263. self.src_rect.x=@frame%@framesperrow*@framewidth
  4264. self.src_rect.y=@frame/@framesperrow*@frameheight
  4265. end
  4266.  
  4267. def start
  4268. @playing=true
  4269. @realframes=0
  4270. end
  4271.  
  4272. alias play start
  4273.  
  4274. def stop
  4275. @playing=false
  4276. end
  4277.  
  4278. def update
  4279. super
  4280. if @playing
  4281. @realframes+=1
  4282. if @realframes==@frameskip
  4283. @realframes=0
  4284. self.frame+=1
  4285. self.frame%=self.framecount
  4286. end
  4287. end
  4288. end
  4289. end
  4290.  
  4291.  
  4292.  
  4293. # Displays an icon bitmap in a sprite. Supports animated images.
  4294. class IconSprite < SpriteWrapper
  4295. attr_reader :name
  4296.  
  4297. def initialize(*args)
  4298. if args.length==0
  4299. super(nil)
  4300. self.bitmap=nil
  4301. elsif args.length==1
  4302. super(args[0])
  4303. self.bitmap=nil
  4304. elsif args.length==2
  4305. super(nil)
  4306. self.x=args[0]
  4307. self.y=args[1]
  4308. else
  4309. super(args[2])
  4310. self.x=args[0]
  4311. self.y=args[1]
  4312. end
  4313. @name=""
  4314. @_iconbitmap=nil
  4315. end
  4316.  
  4317. def dispose
  4318. clearBitmaps()
  4319. super
  4320. end
  4321.  
  4322. def update
  4323. super
  4324. if @_iconbitmap
  4325. @_iconbitmap.update
  4326. if self.bitmap!=@_iconbitmap.bitmap
  4327. oldrc=self.src_rect
  4328. self.bitmap=@_iconbitmap.bitmap
  4329. self.src_rect=oldrc
  4330. end
  4331. end
  4332. end
  4333.  
  4334. def clearBitmaps
  4335. @_iconbitmap.dispose if @_iconbitmap
  4336. @_iconbitmap=nil
  4337. self.bitmap=nil if !self.disposed?
  4338. end
  4339.  
  4340. # Sets the icon's filename. Alias for setBitmap.
  4341. def name=(value)
  4342. setBitmap(value)
  4343. end
  4344.  
  4345. # Sets the icon's filename.
  4346. def setBitmap(file,hue=0)
  4347. oldrc=self.src_rect
  4348. clearBitmaps()
  4349. @name=file
  4350. return if file==nil
  4351. if file!=""
  4352. @_iconbitmap=AnimatedBitmap.new(file,hue)
  4353. # for compatibility
  4354. self.bitmap=@_iconbitmap ? @_iconbitmap.bitmap : nil
  4355. self.src_rect=oldrc
  4356. else
  4357. @_iconbitmap=nil
  4358. end
  4359. end
  4360. end
  4361.  
  4362.  
  4363.  
  4364. # Old GifSprite class, retained for compatibility
  4365. class GifSprite < IconSprite
  4366. def initialize(path)
  4367. super(0,0)
  4368. setBitmap(path)
  4369. end
  4370. end
  4371.  
  4372.  
  4373.  
  4374. # Sprite class that maintains a bitmap of its own.
  4375. # This bitmap can't be changed to a different one.
  4376. class BitmapSprite < SpriteWrapper
  4377. def initialize(width,height,viewport=nil)
  4378. super(viewport)
  4379. self.bitmap=Bitmap.new(width,height)
  4380. @initialized=true
  4381. end
  4382.  
  4383. def bitmap=(value)
  4384. super(value) if !@initialized
  4385. end
  4386.  
  4387. def dispose
  4388. self.bitmap.dispose if !self.disposed?
  4389. super
  4390. end
  4391. end
  4392.  
  4393.  
  4394.  
  4395. class Plane
  4396. def update; end
  4397. def refresh; end
  4398. end
  4399.  
  4400.  
  4401.  
  4402. # This class works around a limitation that planes are always
  4403. # 640 by 480 pixels in size regardless of the window's size.
  4404. class LargePlane < Plane
  4405. attr_accessor :borderX
  4406. attr_accessor :borderY
  4407.  
  4408. def initialize(viewport=nil)
  4409. @__sprite=Sprite.new(viewport)
  4410. @__disposed=false
  4411. @__ox=0
  4412. @__oy=0
  4413. @__bitmap=nil
  4414. @__visible=true
  4415. @__sprite.visible=false
  4416. @borderX=0
  4417. @borderY=0
  4418. end
  4419.  
  4420. def disposed?
  4421. return @__disposed
  4422. end
  4423.  
  4424. def dispose
  4425. if !@__disposed
  4426. @__sprite.bitmap.dispose if @__sprite.bitmap
  4427. @__sprite.dispose
  4428. @__sprite=nil
  4429. @__bitmap=nil
  4430. @__disposed=true
  4431. end
  4432. super
  4433. end
  4434.  
  4435. def ox; @__ox; end
  4436. def oy; @__oy; end
  4437.  
  4438. def ox=(value);
  4439. if @__ox!=value
  4440. @__ox=value; refresh
  4441. end
  4442. end
  4443.  
  4444. def oy=(value);
  4445. if @__oy!=value
  4446. @__oy=value; refresh
  4447. end
  4448. end
  4449.  
  4450. def bitmap
  4451. return @__bitmap
  4452. end
  4453.  
  4454. def bitmap=(value)
  4455. if value==nil
  4456. if @__bitmap!=nil
  4457. @__bitmap=nil
  4458. @__sprite.visible=(@__visible && !@__bitmap.nil?)
  4459. end
  4460. elsif @__bitmap!=value && !value.disposed?
  4461. @__bitmap=value
  4462. refresh
  4463. elsif value.disposed?
  4464. if @__bitmap!=nil
  4465. @__bitmap=nil
  4466. @__sprite.visible=(@__visible && !@__bitmap.nil?)
  4467. end
  4468. end
  4469. end
  4470.  
  4471. def viewport; @__sprite.viewport; end
  4472. def zoom_x; @__sprite.zoom_x; end
  4473. def zoom_y; @__sprite.zoom_y; end
  4474. def opacity; @__sprite.opacity; end
  4475. def blend_type; @__sprite.blend_type; end
  4476. def visible; @__visible; end
  4477. def z; @__sprite.z; end
  4478. def color; @__sprite.color; end
  4479. def tone; @__sprite.tone; end
  4480.  
  4481. def zoom_x=(v);
  4482. if @__sprite.zoom_x!=v
  4483. @__sprite.zoom_x=v; refresh
  4484. end
  4485. end
  4486.  
  4487. def zoom_y=(v);
  4488. if @__sprite.zoom_y!=v
  4489. @__sprite.zoom_y=v; refresh
  4490. end
  4491. end
  4492.  
  4493. def opacity=(v); @__sprite.opacity=(v); end
  4494. def blend_type=(v); @__sprite.blend_type=(v); end
  4495. def visible=(v); @__visible=v; @__sprite.visible=(@__visible && !@__bitmap.nil?); end
  4496. def z=(v); @__sprite.z=(v); end
  4497. def color=(v); @__sprite.color=(v); end
  4498. def tone=(v); @__sprite.tone=(v); end
  4499. def update; ;end
  4500.  
  4501. def refresh
  4502. @__sprite.visible=(@__visible && !@__bitmap.nil?)
  4503. if @__bitmap
  4504. if !@__bitmap.disposed?
  4505. @__ox+=@__bitmap.width*@__sprite.zoom_x if @__ox<0
  4506. @__oy+=@__bitmap.height*@__sprite.zoom_y if @__oy<0
  4507. @__ox-=@__bitmap.width*@__sprite.zoom_x if @__ox>@__bitmap.width
  4508. @__oy-=@__bitmap.height*@__sprite.zoom_y if @__oy>@__bitmap.height
  4509. dwidth=(Graphics.width/@__sprite.zoom_x+@borderX).to_i # +2
  4510. dheight=(Graphics.height/@__sprite.zoom_y+@borderY).to_i # +2
  4511. @__sprite.bitmap=ensureBitmap(@__sprite.bitmap,dwidth,dheight)
  4512. @__sprite.bitmap.clear
  4513. tileBitmap(@__sprite.bitmap,@__bitmap,@__bitmap.rect)
  4514. else
  4515. @__sprite.visible=false
  4516. end
  4517. end
  4518. end
  4519.  
  4520. private
  4521.  
  4522. def ensureBitmap(bitmap,dwidth,dheight)
  4523. if !bitmap||bitmap.disposed?||bitmap.width<dwidth||bitmap.height<dheight
  4524. bitmap.dispose if bitmap
  4525. bitmap=Bitmap.new([1,dwidth].max,[1,dheight].max)
  4526. end
  4527. return bitmap
  4528. end
  4529.  
  4530. def tileBitmap(dstbitmap,srcbitmap,srcrect)
  4531. return if !srcbitmap || srcbitmap.disposed?
  4532. dstrect=dstbitmap.rect
  4533. left=dstrect.x-@__ox/@__sprite.zoom_x
  4534. top=dstrect.y-@__oy/@__sprite.zoom_y
  4535. left=left.to_i; top=top.to_i
  4536. while left>0; left-=srcbitmap.width; end
  4537. while top>0; top-=srcbitmap.height; end
  4538. y=top; while y<dstrect.height
  4539. x=left; while x<dstrect.width
  4540. dstbitmap.blt(x+@borderX,y+@borderY,srcbitmap,srcrect)
  4541. x+=srcrect.width
  4542. end
  4543. y+=srcrect.height
  4544. end
  4545. end
  4546. end
  4547.  
  4548.  
  4549.  
  4550. # A plane class that displays a single color.
  4551. class ColoredPlane < LargePlane
  4552. def initialize(color,viewport=nil)
  4553. super(viewport)
  4554. self.bitmap=Bitmap.new(32,32)
  4555. setPlaneColor(color)
  4556. end
  4557.  
  4558. def dispose
  4559. self.bitmap.dispose if self.bitmap
  4560. super
  4561. end
  4562.  
  4563. def update; super; end
  4564.  
  4565. def setPlaneColor(value)
  4566. self.bitmap.fill_rect(0,0,self.bitmap.width,self.bitmap.height,value)
  4567. self.refresh
  4568. end
  4569. end
  4570.  
  4571.  
  4572.  
  4573. # A plane class that supports animated images.
  4574. class AnimatedPlane < LargePlane
  4575. def initialize(viewport)
  4576. super(viewport)
  4577. @bitmap=nil
  4578. end
  4579.  
  4580. def dispose
  4581. clearBitmaps()
  4582. super
  4583. end
  4584.  
  4585. def update
  4586. super
  4587. if @bitmap
  4588. @bitmap.update
  4589. self.bitmap=@bitmap.bitmap
  4590. end
  4591. end
  4592.  
  4593. def clearBitmaps
  4594. @bitmap.dispose if @bitmap
  4595. @bitmap=nil
  4596. self.bitmap=nil if !self.disposed?
  4597. end
  4598.  
  4599. def setPanorama(file, hue=0)
  4600. clearBitmaps()
  4601. return if file==nil
  4602. @bitmap=AnimatedBitmap.new("Graphics/Panoramas/"+file,hue)
  4603. end
  4604.  
  4605. def setFog(file, hue=0)
  4606. clearBitmaps()
  4607. return if file==nil
  4608. @bitmap=AnimatedBitmap.new("Graphics/Fogs/"+file,hue)
  4609. end
  4610.  
  4611. def setBitmap(file, hue=0)
  4612. clearBitmaps()
  4613. return if file==nil
  4614. @bitmap=AnimatedBitmap.new(file,hue)
  4615. end
  4616. end
  4617.  
  4618.  
  4619.  
  4620. # Displays an icon bitmap in a window. Supports animated images.
  4621. class IconWindow < SpriteWindow_Base
  4622. attr_reader :name
  4623.  
  4624. def initialize(x,y,width,height,viewport=nil)
  4625. super(x,y,width,height)
  4626. self.viewport=viewport
  4627. self.contents=nil
  4628. @name=""
  4629. @_iconbitmap=nil
  4630. end
  4631.  
  4632. def dispose
  4633. clearBitmaps()
  4634. super
  4635. end
  4636.  
  4637. def update
  4638. super
  4639. if @_iconbitmap
  4640. @_iconbitmap.update
  4641. self.contents=@_iconbitmap.bitmap
  4642. end
  4643. end
  4644.  
  4645. def clearBitmaps
  4646. @_iconbitmap.dispose if @_iconbitmap
  4647. @_iconbitmap=nil
  4648. self.contents=nil if !self.disposed?
  4649. end
  4650.  
  4651. # Sets the icon's filename. Alias for setBitmap.
  4652. def name=(value)
  4653. setBitmap(value)
  4654. end
  4655.  
  4656. # Sets the icon's filename.
  4657. def setBitmap(file,hue=0)
  4658. clearBitmaps()
  4659. @name=file
  4660. return if file==nil
  4661. if file!=""
  4662. @_iconbitmap=AnimatedBitmap.new(file,hue)
  4663. # for compatibility
  4664. self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil
  4665. else
  4666. @_iconbitmap=nil
  4667. end
  4668. end
  4669. end
  4670.  
  4671.  
  4672.  
  4673. # Displays an icon bitmap in a window. Supports animated images.
  4674. # Accepts bitmaps and paths to bitmap files in its constructor
  4675. class PictureWindow < SpriteWindow_Base
  4676. def initialize(pathOrBitmap)
  4677. super(0,0,32,32)
  4678. self.viewport=viewport
  4679. self.contents=nil
  4680. @_iconbitmap=nil
  4681. setBitmap(pathOrBitmap)
  4682. end
  4683.  
  4684. def dispose
  4685. clearBitmaps()
  4686. super
  4687. end
  4688.  
  4689. def update
  4690. super
  4691. if @_iconbitmap
  4692. if @_iconbitmap.is_a?(Bitmap)
  4693. self.contents=@_iconbitmap
  4694. else
  4695. @_iconbitmap.update
  4696. self.contents=@_iconbitmap.bitmap
  4697. end
  4698. end
  4699. end
  4700.  
  4701. def clearBitmaps
  4702. @_iconbitmap.dispose if @_iconbitmap
  4703. @_iconbitmap=nil
  4704. self.contents=nil if !self.disposed?
  4705. end
  4706.  
  4707. # Sets the icon's bitmap or filename. (hue parameter
  4708. # is ignored unless pathOrBitmap is a filename)
  4709. def setBitmap(pathOrBitmap,hue=0)
  4710. clearBitmaps()
  4711. if pathOrBitmap!=nil && pathOrBitmap!=""
  4712. if pathOrBitmap.is_a?(Bitmap)
  4713. @_iconbitmap=pathOrBitmap
  4714. self.contents=@_iconbitmap
  4715. self.width=@_iconbitmap.width+self.borderX
  4716. self.height=@_iconbitmap.height+self.borderY
  4717. elsif pathOrBitmap.is_a?(AnimatedBitmap)
  4718. @_iconbitmap=pathOrBitmap
  4719. self.contents=@_iconbitmap.bitmap
  4720. self.width=@_iconbitmap.bitmap.width+self.borderX
  4721. self.height=@_iconbitmap.bitmap.height+self.borderY
  4722. else
  4723. @_iconbitmap=AnimatedBitmap.new(pathOrBitmap,hue)
  4724. self.contents=@_iconbitmap ? @_iconbitmap.bitmap : nil
  4725. self.width=@_iconbitmap ? @_iconbitmap.bitmap.width+self.borderX :
  4726. 32+self.borderX
  4727. self.height=@_iconbitmap ? @_iconbitmap.bitmap.height+self.borderY :
  4728. 32+self.borderY
  4729. end
  4730. else
  4731. @_iconbitmap=nil
  4732. self.width=32+self.borderX
  4733. self.height=32+self.borderY
  4734. end
  4735. end
  4736. end
  4737.  
  4738.  
  4739.  
  4740. class Window_CommandPokemonEx < Window_CommandPokemon
  4741. end
  4742.  
  4743.  
  4744.  
  4745. class Window_AdvancedCommandPokemonEx < Window_AdvancedCommandPokemon
  4746. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement