#encoding: utf-8
#
# ■ [SIN]Video(RGD兼容)
# MPEG Player for RPG Maker / RGDirect (RGD)
#
# 使用你的精灵来播放 MPEG 视频(RGD/XP/VX/VA通用)
#
# [更新记录]
# - 2013.04.21 By Shy07, Syalon(真正的作者)
# * 初版亦终版
#
# - 2022.07.27 By 岚风 雷(gqxastg)
# * 优化代码,改造为RGD兼容版
#
# [使用方法]
# - SIN::PLAYER.play("Video/title.avi") #=> 加载并开始播放视频(可追加音量)
# - SIN::PLAYER.update #=> 更新视频画面,原则上必须每帧调用
# - SIN::PLAYER.stop #=> 停止播放并释放视频
#
# - SIN::PLAYER.playing? #=> 获取视频是否播放中
# - SIN::PLAYER.rewind #=> 从头重新开始播放
# - SIN::PLAYER.replay_at_finish #=> 播放完成后则重新播放
# - SIN::PLAYER.volume #=> 获取播放音量(-10000~0)
# - SIN::PLAYER.volume = 0 #=> 设置播放音量
# - SIN::Video.regen #=> 重新生成播放器精灵(可追加参数)
#
# - 其余使用方法请参考下面的代码以及范例工程中的 SINVideoDemo
#
#
module SIN
module VideoConfig
#------------------------------------------------------------------------
# ■ 以下为设定部分
#------------------------------------------------------------------------
# SINVideo.dll的存放路径
DLLPATH = 'System/SINVideo.dll'
# 使用原版时的视频更新模式
# 该项为true时: 效率优先,直接修改位图数据
# 该项为false时:稳定优先,通过缓存中转修改
# 默认为true,如使用RGD则无须修改此项
ORIMODE = true
# 使用RGD时的视频显示模式
# RGD因位图存储格式不同,相对原版从下往上显示将导致颠倒
# 该项为0时:初始会自动将mirror和angle分别设为true和180以矫正颠倒
# 该项为1时:每帧更新视频时,自动翻转位图数据以矫正颠倒
# 该项为nil时则不作任何处理
# 默认为0,如使用原版则无须修改此项
RGDFlip = 0
#------------------------------------------------------------------------
# ■ 设定部分到此结束,使用者无须修改以下内容
#------------------------------------------------------------------------
ORIMODE = false if defined?(RGD)
RGDFlip = nil unless defined?(RGD)
end
#
class ::Bitmap
# API
@@RtlMoveMemory_pl = Win32API.new('kernel32', 'RtlMoveMemory', 'pll', 'l')
@@RtlMoveMemory_lp = Win32API.new('kernel32', 'RtlMoveMemory', 'lpl', 'l')
@@RtlMoveMemory_ll = Win32API.new('kernel32', 'RtlMoveMemory', 'lll', 'l')##
def _dump(limit) ############
data = "rgba" * width * height
if respond_to?(:process_color)
process_color {|color_arr| color_arr.save_data(data, width * height) }
else
@@RtlMoveMemory_pl.call(data, address, width * height * 4)
end
[width, height, Zlib::Deflate.deflate(data)].pack("LLa*")
end
def self._load(str) #############
w, h, zdata = str.unpack("LLa*")
data = Zlib::Inflate.inflate(zdata)
bmp = self.new(w, h)
if method_defined?(:process_color)
bmp.process_color {|color_arr| color_arr.load_data(data, w * h) }
else
@@RtlMoveMemory_lp.call(bmp.address, Zlib::Inflate.inflate(zdata),
w * h * 4)
end
return bmp
end
def direct_load(str, rev = false) #############
if rev
buf = "\0" * 4 * width * height # str.bytesize
len = width * 4
src = [str].pack('p').unpack('L').first + width * height * 4
dst = [buf].pack('p').unpack('L').first
height.times do |i|
src -= len
@@RtlMoveMemory_ll.call(dst, src, len)
dst += len
end
str = buf
end
#str = str.scan(/.{#{width * 4}}/m).reverse.join if rev
if respond_to?(:process_color)
process_color {|color_arr| color_arr.load_data(str, width * height) }
else
@@RtlMoveMemory_lp.call(address, str, width * height * 4)
end
self
end
# [[[bitmap.object_id * 2 + 16] + 8] + 16] == header
def address
buffer, ad = "rgba", object_id * 2 + 16
@@RtlMoveMemory_pl.call(buffer, ad, 4)
ad = buffer.unpack("L")[0] + 8
@@RtlMoveMemory_pl.call(buffer, ad, 4)
ad = buffer.unpack("L")[0] + 16
@@RtlMoveMemory_pl.call(buffer, ad, 4)
return buffer.unpack("L")[0]
end
#
def g_fill_rect(*arg)
if arg[0].is_a? Rect
col1, col2 = 1, 2
else
col1, col2 = 4, 5
end
color1, color2 = arg[col1], arg[col2]
arg[col1] = Color.new((color1 >> 16) & 0xFF,
(color1 >> 8) & 0xFF, (color1 & 0xFF), (color1 >> 24))
arg[col2] = Color.new((color2 >> 16) & 0xFF,
(color2 >> 8) & 0xFF, (color2 & 0xFF), (color2 >> 24))
gradient_fill_rect(*arg)
end
end
#
class Video < Sprite
DLLPATH = VideoConfig::DLLPATH ############# 'System/SINVideo.dll'
@@__video__ = nil
def self.new(viewport = nil)
return @@__video__ ||= super(viewport)
end
def self.regen(*args) #############
@@__video__.dispose if @@__video__ && !@@__video__.disposed?
@@__video__ = nil
::SIN.const_set(:PLAYER, Video.new(*args))
end
undef clone rescue nil
undef dup rescue nil
VideoLoad = Win32API.new(DLLPATH, "__rgssx_video_load", "ppp", "i")
VideoPlay = Win32API.new(DLLPATH, "__rgssx_video_play", "ll", "v")
VideoPlay_p = Win32API.new(DLLPATH, "__rgssx_video_play", "pl", "v")###
VideoPlaying = Win32API.new(DLLPATH, "__rgssx_video_is_playing", "v", "i")
VideoUpdate = Win32API.new(DLLPATH, "__rgssx_video_update", "v", "v")
VideoStop = Win32API.new(DLLPATH, "__rgssx_video_stop", "v", "v")
VideoRewind = Win32API.new(DLLPATH, "__rgssx_video_rewind", "v", "v")
VideoGetVolume = Win32API.new(DLLPATH, "__rgssx_video_get_volume", "v", "l")
VideoSetVolume = Win32API.new(DLLPATH, "__rgssx_video_set_volume", "l", "v")
def initialize(*args) ############## viewport = nil
super(*args) ############## viewport
@__playing = false
##############
return unless VideoConfig::RGDFlip == 0
self.angle = 180
self.mirror = true
end
def dispose
stop
super
end
def volume
return VideoGetVolume.call
end
def volume=(v)
VideoSetVolume.call(v)
end
def playing?
return false unless @__playing
return true if VideoPlaying.call != 0
false #stop ############## 取消自动停止,避免出错
end
def replay_at_finish
return unless @__playing
return if VideoPlaying.call != 0
VideoRewind.call
end
def stop
return unless @__playing
VideoStop.call
bitmap.dispose
self.bitmap = nil
@bmpbuf = nil ##############
@__playing = false
end
def rewind
VideoRewind.call
end
def play(filename, volume = 0)
return Video.regen.play(filename, volume) if disposed? ##############
w = [0].pack("L")
h = [0].pack("L")
return false if VideoLoad.call(filename, w, h) == 0
w = w.unpack("L").first
h = h.unpack("L").first
bitmap.dispose if bitmap
self.bitmap = Bitmap.new(w, h)
self.ox = w / 2
self.oy = h / 2
self.x = Graphics.width / 2
self.y = Graphics.height / 2
@bmpbuf = "\0" * w * h * 4 ##############
#@bmpbuf.force_encoding('ASCII-8BIT')
##############
if VideoConfig::ORIMODE
VideoPlay.call(bitmap.address, volume)
else
VideoPlay_p.call(@bmpbuf, volume) ##############
end
##############
#self.bitmap.direct_load(@bmpbuf, VideoConfig::RGDFlip == 1)##############
@__playing = true
return true
end
def update
return unless @__playing
VideoUpdate.call
self.bitmap.direct_load(@bmpbuf, VideoConfig::RGDFlip == 1) unless
VideoConfig::ORIMODE ##############
super
end
end
PLAYER.dispose if const_defined?(:PLAYER) && !PLAYER.disposed? ##############
PLAYER = Video.new # ||=
end
#encoding: utf-8
#
# ■ [SIN]Video Hacker
# Extension Plugin for SINVideo
#
# SINVideo(视频功能增强)拓展插件
#
# [更新记录]
# - 2022.07.27 By 岚风 雷(gqxastg)
# * 初版
#
# [使用方法]
# - 首先请确保安装了SINVideo脚本(原版或RGD兼容版皆可),并将此脚本置于其下
#
# - SIN::PLAYER.convert_time(1, :SECOND, :MEDIA) #=>
# 转换播放时间单位(:SECOND为秒,:MEDIA为默认单位)
#
# - SIN::PLAYER.getDuration #=> 获取视频的完整长度(不受结束位置影响)
# - SIN::PLAYER.getCurrentPosition #=> 获取播放的当前位置
# - SIN::PLAYER.getStopPosition #=> 获取播放的结束位置
# - SIN::PLAYER.getPositions #=> 获取播放的当前位置和结束位置
# - SIN::PLAYER.setPositions(0) #=> 设置播放的当前位置和结束位置
# 可使用 :AbsolutePositioning 和 :NoPositioning 标志来分别指定是否要设置
# 如:(0, :NoPositioning, 100, :AbsolutePositioning) 则只设置结束位置
#
# - SIN::PLAYER.getCurFile #=> 获取当前播放视频的文件名
# - SIN::PLAYER.getState #=> 获取当前播放状态(0结束、1暂停、2播放)
# - SIN::PLAYER.pausing? #=> 获取视频是否暂停中
# - SIN::PLAYER.pause #=> 暂停播放
# - SIN::PLAYER.run #=> 继续播放(暂停时)
# - SIN::PLAYER.getRate #=> 获取播放倍速(正常速度为1.0)
# - SIN::PLAYER.setRate(2.0) #=> 设置播放倍速
#
# - SIN::PLAYER.get_Balance #=> 获取播放声道平衡(-100~100)
# - SIN::PLAYER.put_Balance(-5.0) #=> 设置播放声道平衡
# - SIN::PLAYER.get_Volume #=> 获取播放音量(0~100)
# - SIN::PLAYER.put_Volume(50.0) #=> 设置播放音量
#
# - SIN::PLAYER.playing? 判断播放中包括暂停状态
# - SIN::PLAYER.getPositions 等方法涉及时间的数值请用convert_time进行转换
#
# - 其余使用方法请参考下面的代码以及范例工程中的 SINVideoDemo
#
#
module SIN
raise '未检测到SINVideo,请将此脚本置于其下' unless defined?(SIN::Video)
# 兼容XP/VX
class ::String
def bytesize; size; end unless method_defined?(:bytesize)
def start_with?(*args)
args.any? {|s| self[0, s.size] == s.to_s }
end unless method_defined?(:start_with?)
end
class ::Symbol
def upcase; self.to_s.upcase.to_sym; end unless method_defined?(:upcase)
def to_proc; proc {|a| a.send(self) }; end unless method_defined?(:to_proc)
end
class ::Array
alias videohacker_flatten flatten unless ([].flatten(0) rescue false)
def flatten(level = nil)
return self.videohacker_flatten if !level || (level < 0)
return self if level == 0
from, to = nil, self
level.times do
from, to = to, []
from.each {|a| a.is_a?(Array) ? to.push(*a) : to.push(a) }
end
to
end if method_defined?(:videohacker_flatten)
end
#----------------------------------------------------------------------------
module VideoHacker
MultiByteToWideChar =
Win32API.new('kernel32', 'MultiByteToWideChar', 'iipipi', 'i')
WideCharToMultiByte =
Win32API.new('kernel32', 'WideCharToMultiByte', 'iipipipp', 'i')
#--------------------------------------------------------------------------
def self.u2w(str)
buf = "\0" * 2 *
MultiByteToWideChar.call(65001, 0, str, -1, nil, 0)
MultiByteToWideChar.call(65001, 0, str, -1, buf, buf.bytesize / 2)
buf
end
#--------------------------------------------------------------------------
def self.w2u(str, zero = true)
buf = "\0" *
WideCharToMultiByte.call(65001, 0, str, -1, nil, 0, nil, nil)
WideCharToMultiByte.call(65001, 0, str, -1, buf, buf.bytesize, nil, nil)
buf.sub!(/\0+$/, '') if zero
buf
end
#--------------------------------------------------------------------------
RtlMoveMemory_pl = Win32API.new('kernel32', 'RtlMoveMemory', 'pll', 'l')
RtlMoveMemory_lp = Win32API.new('kernel32', 'RtlMoveMemory', 'lpl', 'l')
RtlMoveMemory_ll = Win32API.new('kernel32', 'RtlMoveMemory', 'lll', 'l')
#RtlMoveMemory_pp = Win32API.new('kernel32', 'RtlMoveMemory', 'ppl', 'l')
GetModuleHandle = Win32API.new('kernel32', 'GetModuleHandle', 'p', 'l')
CallWindowProc_lplll =
Win32API.new('user32', 'CallWindowProc', 'lpLLL', 'i')
CallWindowProc_lllll =
Win32API.new('user32', 'CallWindowProc', 'llLLL', 'i')
CallWindowProc_lpppp =
Win32API.new('user32', 'CallWindowProc', 'lpppp', 'i')
#CallWindowProc_lplpl =
#Win32API.new('user32', 'CallWindowProc', 'lpLpL', 'i')
MEM_COMMIT = 0x00001000
MEM_RESERVE = 0x00002000
MEM_RELEASE = 0x00008000
PAGE_EXECUTE_READWRITE = 0x40
VirtualAlloc = Win32API.new('kernel32', 'VirtualAlloc', 'llll', 'l')
VirtualFree = Win32API.new('kernel32', 'VirtualFree', 'lll', 'l')
#VirtualProtect = Win32API.new('kernel32', 'VirtualProtect', 'llll', 'l')
#--------------------------------------------------------------------------
S_OK = 0x00000000
S_FALSE = 0x00000001
E_INVALIDARG = 0x80070057
E_OUTOFMEMORY = 0x8007000E
E_UNEXPECTED = 0x8000FFFF
E_NOTIMPL = 0x80004001
E_FAIL = 0x80004005
E_POINTER = 0x80004003
E_HANDLE = 0x80070006
E_ABORT = 0x80004004
E_ACCESSDENIED = 0x80070005
E_NOINTERFACE = 0x80004002
VFW_S_STATE_INTERMEDIATE = 0x00040237
VFW_S_CANT_CUE = 0x00040268
VFW_E_NOT_CONNECTED = 0x80040209
VFW_E_WRONG_STATE = 0x80040227
VFW_E_UNSUPPORTED_AUDIO = 0x8004025C
VFW_E_UNSUPPORTED_VIDEO = 0x8004025D
ReturnValueList = constants.select {|sym|
sym.to_s.start_with?('S_', 'E_', 'VFW_S_', 'VFW_E_') }.collect(&:to_sym)
AM_SEEKING_NoPositioning = 0x00
AM_SEEKING_AbsolutePositioning = 0x01
AM_SEEKING_RelativePositioning = 0x02
AM_SEEKING_IncrementalPositioning = 0x03
AM_SEEKING_PositioningBitsMask = 0x03
AM_SEEKING_SeekToKeyFrame = 0x04
AM_SEEKING_ReturnTime = 0x08
AM_SEEKING_Segment = 0x10
AM_SEEKING_NoFlush = 0x20
ALL_TIME_FORMAT = %w{TIME_FORMAT_NONE TIME_FORMAT_FRAME TIME_FORMAT_SAMPLE
TIME_FORMAT_FIELD TIME_FORMAT_BYTE TIME_FORMAT_MEDIA_TIME}.collect(&:to_sym)
ConvertTimeList = %w{SECOND FRAME MEDIA}.collect(&:to_sym)
TIME_FORMAT_NONE = "\0" * 16
TIME_FORMAT_FRAME = [0x7b785570, 0x8c82, 0x11cf,
0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6].pack('LSSC8')
TIME_FORMAT_SAMPLE = [0x7b785572, 0x8c82, 0x11cf,
0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6].pack('LSSC8')
TIME_FORMAT_FIELD = [0x7b785573, 0x8c82, 0x11cf,
0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6].pack('LSSC8')
TIME_FORMAT_BYTE = [0x7b785571, 0x8c82, 0x11cf,
0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6].pack('LSSC8')
TIME_FORMAT_MEDIA_TIME = [0x7b785574, 0x8c82, 0x11cf,
0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6].pack('LSSC8')
#--------------------------------------------------------------------------
DSHOWprocList = {
:m_pBasicAudio => [
[:put_Volume, 0x1C, 'put_Volume'],
[:get_Volume, 0x20, 'get_Volume'],
[:put_Balance, 0x24, 'put_Balance'],
[:get_Balance, 0x28, 'get_Balance'],
],
:m_pSampleGrabber => [
[:GetCurrentBuffer, 0x1C, 'getCurrentBuffer'],
],
:m_pMediaSeeking => [
[:SetTimeFormat, 0x18, 'setTimeFormat'],
[:GetTimeFormat, 0x1C, 'getTimeFormat'],
[:IsUsingTimeFormat, 0x20, 'isUsingTimeFormat'],
[:IsFormatSupported, 0x24, 'isFormatSupported'],
[:GetDuration, 0x28, 'getDuration'],
[:GetStopPosition, 0x2C, 'getStopPosition'],
[:GetCurrentPosition, 0x30, 'getCurrentPosition'],
[:ConvertTimeFormat, 0x34, 'convertTimeFormat'],
[:SetPositions, 0x38, 'setPositions'],
[:GetPositions, 0x3C, 'getPositions'],
[:GetAvailable, 0x40, 'getAvailable'],
[:SetRate, 0x44, 'setRate'],
[:GetRate, 0x48, 'getRate'],
],
:m_pMediaControl => [
[:Run, 0x1C, 'run'],
[:Pause, 0x20, 'pause'],
[:Stop, 0x24, nil],
[:GetState, 0x28, 'getState'],
],
:m_pMediaEvent => [
],
:pFileSourceFilter => [
[:Load, 0x0C, nil],
[:GetCurFile, 0x10, 'getCurFile'],
],
}
#--------------------------------------------------------------------------
arr = DSHOWprocList.values.flatten(1)
ProcSym = arr.collect {|a| a[0] }
MethodSym = arr.collect {|a| a[2] }.compact
DLLmodule = GetModuleHandle.call(File.basename(::SIN::Video::DLLPATH))
DLLproc = {}
DSHOWproc = {}
ProcSym.each {|key| DSHOWproc[key] = 0 }
#DSHOWproc_p = DSHOWproc.clone
#DSHOWproc_p.each {|key, value| DSHOWproc_p[key] = [value].pack('L') }
#--------------------------------------------------------------------------
if const_defined?(:MACHproc) && (ptr = MACHproc.values[0]) && ptr != 0
VirtualFree.call(ptr, 0, MEM_RELEASE)
end
MACHcode = {
:BASE =>
[0x8B, 0x44, 0x24, 0x04, 0x8B, 0x4C, 0x24, 0x08, 0xFF, 0x34, 0x88, 0xE2,
0xFB, 0xFF, 0x10, 0xC3].pack('C*'),
:GetCurrentBuffer =>
[0x8B, 0x44, 0x24, 0x04, 0x8B, 0x4C, 0x24, 0x08, 0xB2, 0xFF, 0x83, 0xC0,
0x03, 0x88, 0x10, 0x83, 0xC0, 0x04, 0xE2, 0xF9, 0xC2, 0x10, 0x00].
pack('C*'),
}
#~ [0x8B, 0x44, 0x24, 0x04, 0xFF, 0x70, 0x14, 0xFF, 0x70, 0x10, 0xFF, 0x70,
#~ 0x0C, 0xFF, 0x70, 0x08, 0xFF, 0x70, 0x04, 0xFF, 0x10, 0xC3].pack('C*'),
#~ [0x89, 0xE0, 0xFF, 0x70, 0x10, 0xFF, 0x70, 0x0C, 0xFF, 0x70, 0x08, 0xFF,
#~ 0x70, 0x04, 0x68].pack('C*') +
#~ [DLLproc[1]].pack('L') +
#~ [0xFF, 0x15].pack('C*') +
#~ [DSHOWproc_p[:SetPositions]].pack('p') +
#~ [0xC3].pack('C*')
MACHproc = {}
hash = MACHcode#.clone
#hash.each {|key, value| hash[key] = value.call }
all = hash.values.join
ptr = VirtualAlloc.call(0, all.bytesize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
raise '无法申请内存' if ptr == 0
RtlMoveMemory_lp.call(ptr, all, all.bytesize)
hash.each do |key, value|
MACHproc[key] = ptr
ptr += value.bytesize
end
#--------------------------------------------------------------------------
buf = "\0" * 4
RtlMoveMemory_pl.call(buf, DLLmodule + 0xD8AC, 4)
DLLproc[:BASE] = buf.unpack('L').first
#--------------------------------------------------------------------------
def self.recalc_DSHOWproc#(resetMACH = true)
buf = "\0" * 4
# mov esi,[SINVideo.dll+D8AC]
# m_pBasicAudio
# mov eax,[esi+14]
RtlMoveMemory_pl.call(buf, DLLproc[:BASE] + 0x14, 4)
DLLproc[:m_pBasicAudio] = buf.unpack('L').first
# m_pSampleGrabber
# mov eax,[esi+10]
RtlMoveMemory_pl.call(buf, DLLproc[:BASE] + 0x10, 4)
DLLproc[:m_pSampleGrabber] = buf.unpack('L').first
# m_pMediaSeeking->SetPositions
# mov eax,[esi+0C]
RtlMoveMemory_pl.call(buf, DLLproc[:BASE] + 0x0C, 4)
DLLproc[:m_pMediaSeeking] = buf.unpack('L').first
# m_pMediaControl->Stop
# mov eax,[esi+04]
RtlMoveMemory_pl.call(buf, DLLproc[:BASE] + 0x04, 4)
DLLproc[:m_pMediaControl] = buf.unpack('L').first
# m_pMediaEvent
# mov eax,[esi+08]
RtlMoveMemory_pl.call(buf, DLLproc[:BASE] + 0x08, 4)
DLLproc[:m_pMediaEvent] = buf.unpack('L').first
# m_pGraphBuilder
# mov eax,[esi]
RtlMoveMemory_pl.call(buf, DLLproc[:BASE], 4)
DLLproc[:m_pGraphBuilder] = buf.unpack('L').first
# pFileSourceFilter
# [[[[[SINVideo.dll+D8AC]]+BC]+8]]+44
adr = DLLproc[:BASE]
[0, 0xBC, 8, 0].each do |off|
buf = "\0" * 4
RtlMoveMemory_pl.call(buf, adr + off, 4)
adr = buf.unpack('L').first
break if adr == 0
end
adr += 0x44 unless adr == 0
DLLproc[:pFileSourceFilter] = adr
#------------------------------------------------------------------------
DSHOWprocList.each do |key, value|
value.each do |arr|
sym, off = arr
# mov eax,[SINVideo.dll+D8AC]
# mov eax,[eax+**]
adr = DLLproc[key]
break value.each {|a| DSHOWproc[a[0]] = 0 } if adr == 0
buf = "\0" * 4
# mov eax,[eax]
RtlMoveMemory_pl.call(buf, adr, 4)
adr = buf.unpack('L').first
next DSHOWproc[sym] = 0 if adr == 0
# mov eax,[eax+**]
RtlMoveMemory_pl.call(buf, adr + off, 4)
DSHOWproc[sym] = buf.unpack('L').first
end
end
#DSHOWproc_p.each {|key, value|
#RtlMoveMemory_pp.call(value, [DSHOWproc[key]].pack('L'), 4) }
#reset_MACHcode if resetMACH
end
#--------------------------------------------------------------------------
def self.clear_DSHOWproc
DSHOWproc.each_key {|key| DSHOWproc[key] = 0 }
end
#--------------------------------------------------------------------------
#~ def self.reset_MACHcode
#~ return if MACHproc.values[0] == 0
#~ all = MACHcode.values.collect(&:call).join
#~ RtlMoveMemory_lp.call(MACHproc.values[0], all, all.bytesize)
#~ end
#--------------------------------------------------------------------------
def self.convert_ret(ret)
ret = ret + 0x100000000 if ret < 0
sym = ReturnValueList.find {|s| const_get(s) == ret }
sym ? sym : ret
end
#--------------------------------------------------------------------------
def self.convert_time(time, from = :SECOND, to = :MEDIA)
2.times do |i|
format = (i == 0) ? from : to
format = (format.is_a?(Symbol) || format.is_a?(String)) ?
format.to_sym.upcase : ConvertTimeList[format.to_i]
(i == 0) ? from = format : to = format
end
case from
when :SECOND
when :FRAME then time = time / Graphics.frame_rate.to_f
when :MEDIA then time = time / 10000000.0
end
case to
when :SECOND
when :FRAME then time = (time * Graphics.frame_rate).to_i
when :MEDIA then time = (time * 10000000).to_i
end
time
end
#--------------------------------------------------------------------------
# m_pBasicAudio
#--------------------------------------------------------------------------
def self.put_Volume(lVolume = 100)
key, sym = :m_pBasicAudio, :put_Volume
return false if DSHOWproc[sym] == 0
lVolume = (lVolume * 100 - 10000).to_i
params = [DSHOWproc[sym], DLLproc[key], lVolume].pack('LLl')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
convert_ret(ret)
end
#--------------------------------------------------------------------------
def self.get_Volume
key, sym = :m_pBasicAudio, :get_Volume
return false if DSHOWproc[sym] == 0
plVolume = "\0" * 4 #[0].pack('L')
params = [DSHOWproc[sym], DLLproc[key], plVolume].pack('LLp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
(plVolume.unpack('l').first + 10000) / 100.0
end
#--------------------------------------------------------------------------
def self.put_Balance(lBalance = 0)
key, sym = :m_pBasicAudio, :put_Balance
return false if DSHOWproc[sym] == 0
lBalance = (lBalance * 100).to_i
params = [DSHOWproc[sym], DLLproc[key], lBalance].pack('LLl')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
convert_ret(ret)
end
#--------------------------------------------------------------------------
def self.get_Balance
key, sym = :m_pBasicAudio, :get_Balance
return false if DSHOWproc[sym] == 0
plBalance = "\0" * 4 #[0].pack('L')
params = [DSHOWproc[sym], DLLproc[key], plBalance].pack('LLp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
plBalance.unpack('l').first / 100.0
end
#--------------------------------------------------------------------------
# m_pSampleGrabber
#--------------------------------------------------------------------------
def self.getCurrentBuffer(dst = nil)
key, sym = :m_pSampleGrabber, :GetCurrentBuffer
return false if DSHOWproc[sym] == 0
pBufferSize = "\0" * 4 #[0].pack('L')
pBuffer = nil
params = [DSHOWproc[sym], DLLproc[key], pBufferSize, pBuffer].pack('LLpp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 3, 0, 0)
size = pBufferSize.unpack('L').first
return false if size == 0
if dst.is_a?(Integer)
pBuffer = true
params = [DSHOWproc[sym], DLLproc[key], pBufferSize, dst].pack('LLpL')
else
pBuffer = dst ? dst : ("\0" * size)
params =
[DSHOWproc[sym], DLLproc[key], pBufferSize, pBuffer].pack('LLpp')
end
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 3, 0, 0)
return false if ret != 0
pBuffer
end
#--------------------------------------------------------------------------
# m_pMediaSeeking
#--------------------------------------------------------------------------
def self.setTimeFormat(pFormat = :TIME_FORMAT_MEDIA_TIME)
key, sym = :m_pMediaSeeking, :SetTimeFormat
return false if DSHOWproc[sym] == 0
pFormat = const_get(pFormat)
params = [DSHOWproc[sym], DLLproc[key], pFormat].pack('LLp')
CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
end
#--------------------------------------------------------------------------
def self.getTimeFormat
key, sym = :m_pMediaSeeking, :GetTimeFormat
return false if DSHOWproc[sym] == 0
pFormat = "\0" * 16
params = [DSHOWproc[sym], DLLproc[key], pFormat].pack('LLp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
ALL_TIME_FORMAT.find {|key| const_get(key) == pFormat }
end
#--------------------------------------------------------------------------
def self.isUsingTimeFormat(pFormat)
key, sym = :m_pMediaSeeking, :IsUsingTimeFormat
return false if DSHOWproc[sym] == 0
pFormat = const_get(pFormat)
params = [DSHOWproc[sym], DLLproc[key], pFormat].pack('LLp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
ret == 0
end
#--------------------------------------------------------------------------
def self.isFormatSupported(pFormat)
key, sym = :m_pMediaSeeking, :IsFormatSupported
return false if DSHOWproc[sym] == 0
pFormat = const_get(pFormat)
params = [DSHOWproc[sym], DLLproc[key], pFormat].pack('LLp')
CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
end
#--------------------------------------------------------------------------
def self.getDuration
key, sym = :m_pMediaSeeking, :GetDuration
return false if DSHOWproc[sym] == 0
pDuration = "\0" * 8 #[0].pack('q')
params = [DSHOWproc[sym], DLLproc[key], pDuration].pack('LLp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
pDuration.unpack('q').first
end
#--------------------------------------------------------------------------
def self.getStopPosition
key, sym = :m_pMediaSeeking, :GetStopPosition
return false if DSHOWproc[sym] == 0
pStop = "\0" * 8 #[0].pack('q')
params = [DSHOWproc[sym], DLLproc[key], pStop].pack('LLp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
pStop.unpack('q').first
end
#--------------------------------------------------------------------------
def self.getCurrentPosition
key, sym = :m_pMediaSeeking, :GetCurrentPosition
return false if DSHOWproc[sym] == 0
pCurrent = "\0" * 8 #[0].pack('q')
params = [DSHOWproc[sym], DLLproc[key], pCurrent].pack('LLp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
pCurrent.unpack('q').first
end
#--------------------------------------------------------------------------
def self.convertTimeFormat(pTargetFormat, source, pSourceFormat = nil)
key, sym = :m_pMediaSeeking, :ConvertTimeFormat
return false if DSHOWproc[sym] == 0
pTarget = "\0" * 8 #[0].pack('q')
pTargetFormat = const_get(pTargetFormat) if pTargetFormat
pSourceFormat = const_get(pSourceFormat) if pSourceFormat
params = [DSHOWproc[sym], DLLproc[key],
pTarget, pTargetFormat, source, pSourceFormat].pack('LLppqp')
# 因为传的是longlong(8字节)所以多占一个参数
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 6, 0, 0)
pTarget.unpack('q').first
end
#--------------------------------------------------------------------------
def self.setPositions(pCurrent = 0, dwCurrentFlags = 1, pStop = 0,
dwStopFlags = 0)
key, sym = :m_pMediaSeeking, :SetPositions
return false if DSHOWproc[sym] == 0
pCurrent = [pCurrent].pack('q')
pStop = [pStop].pack('q')
2.times do |i|
flags = (i == 0) ? dwCurrentFlags : dwStopFlags
flags = flags.is_a?(Array) ?
flags.inject(0) {|r, m| r | const_get("AM_SEEKING_#{m}") } :
(flags.is_a?(Symbol) || flags.is_a?(String)) ?
const_get("AM_SEEKING_#{flags}") : flags.to_i
(i == 0) ? dwCurrentFlags = flags : dwStopFlags = flags
end
params = [DSHOWproc[sym], DLLproc[key],
pCurrent, dwCurrentFlags, pStop, dwStopFlags].pack('LLpLpL')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 5, 0, 0)
#CallWindowProc_lplpl.call(MACHproc[:SetPositions],
#pCurrent, dwCurrentFlags, pStop, dwStopFlags)
ret = convert_ret(ret)
ret = [ret, pCurrent.unpack('q').first, pStop.unpack('q').first] if
(dwCurrentFlags & AM_SEEKING_ReturnTime != 0) ||
(dwStopFlags & AM_SEEKING_ReturnTime != 0)
ret
end
#--------------------------------------------------------------------------
def self.getPositions
key, sym = :m_pMediaSeeking, :GetPositions
return false if DSHOWproc[sym] == 0
pCurrent = "\0" * 8 #[0].pack('q')
pStop = "\0" * 8 #[0].pack('q')
params = [DSHOWproc[sym], DLLproc[key], pCurrent, pStop].pack('LLpp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 3, 0, 0)
[pCurrent.unpack('q').first, pStop.unpack('q').first]
end
#--------------------------------------------------------------------------
def self.getAvailable
key, sym = :m_pMediaSeeking, :GetAvailable
return false if DSHOWproc[sym] == 0
pEarliest = "\0" * 8 #[0].pack('q')
pLatest = "\0" * 8 #[0].pack('q')
params = [DSHOWproc[sym], DLLproc[key], pEarliest, pLatest].pack('LLpp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 3, 0, 0)
[pEarliest.unpack('q').first, pLatest.unpack('q').first]
end
#--------------------------------------------------------------------------
def self.setRate(dRate = 1)
key, sym = :m_pMediaSeeking, :SetRate
return false if DSHOWproc[sym] == 0
params = [DSHOWproc[sym], DLLproc[key], dRate].pack('LLD')
# 因为传的是double(8字节)所以多占一个参数
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 3, 0, 0)
convert_ret(ret)
end
#--------------------------------------------------------------------------
def self.getRate
key, sym = :m_pMediaSeeking, :GetRate
return false if DSHOWproc[sym] == 0
pdRate = "\0" * 8 #[0].pack('D')
params = [DSHOWproc[sym], DLLproc[key], pdRate].pack('LLp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 2, 0, 0)
pdRate.unpack('D').first
end
#--------------------------------------------------------------------------
# m_pMediaControl
#--------------------------------------------------------------------------
def self.run
key, sym = :m_pMediaControl, :Run
return false if DSHOWproc[sym] == 0
params = [DSHOWproc[sym], DLLproc[key]].pack('LL')
CallWindowProc_lplll.call(MACHproc[:BASE], params, 1, 0, 0)
end
#--------------------------------------------------------------------------
def self.pause
key, sym = :m_pMediaControl, :Pause
return false if DSHOWproc[sym] == 0
params = [DSHOWproc[sym], DLLproc[key]].pack('LL')
CallWindowProc_lplll.call(MACHproc[:BASE], params, 1, 0, 0)
end
#--------------------------------------------------------------------------
def self.getState(msTimeout = 0)
key, sym = :m_pMediaControl, :GetState
return false if DSHOWproc[sym] == 0
params = [DSHOWproc[sym], DLLproc[key],
msTimeout, state = "\0" * 4].pack('LLlp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 3, 0, 0)
# State_Stopped = 0, State_Paused = 1, State_Running = 2
state.unpack('L').first
end
#--------------------------------------------------------------------------
# pFileSourceFilter
#--------------------------------------------------------------------------
def self.getCurFile
key, sym = :pFileSourceFilter, :GetCurFile
return false if DSHOWproc[sym] == 0
ppszFileName = "\0" * 4 #[0].pack('L')
pmt = nil #"\0" * (32 + 2 + 4 + 16 + 4 + 4 + 1)
params = [DSHOWproc[sym], DLLproc[key], ppszFileName, pmt].pack('LLpp')
ret = CallWindowProc_lplll.call(MACHproc[:BASE], params, 3, 0, 0)
adr = ppszFileName.unpack('L').first
if adr == 0
name = nil
else
name, buf = '', "\0" * 2
begin
RtlMoveMemory_pl.call(buf, adr, 2)
name << buf
adr += 2
end until buf == "\0\0"
name = w2u(name)
end
#[name, pmt.unpack('a16a16C2La16LLC')]
name
end
end
class Video < Sprite
class VideoUpdate_caller
CallWindowProc_lplll = ::SIN::VideoHacker::CallWindowProc_lplll
attr_accessor :mode, :default
#------------------------------------------------------------------------
def initialize(default)
@default, @mode = default, false
end
#------------------------------------------------------------------------
def call
return @default.call unless @mode
::SIN::PLAYER.instance_eval do
return 1 unless @bmpbuf
getCurrentBuffer(@bmpbuf)
return 1 unless @bmpbuf
CallWindowProc_lplll.call(
::SIN::VideoHacker::MACHproc[:GetCurrentBuffer],
@bmpbuf, width * height, 0, 0)
end
0
end
end
#~ VideoUpdate = VideoUpdate_caller.new(VideoUpdate) unless
#~ VideoUpdate.is_a?(VideoUpdate_caller)
#~ VideoUpdate.mode = true
#--------------------------------------------------------------------------
alias hackerold_play play
def play(*args)
return hackerold_play(*args) if disposed?
hackerold_play(*args)
::SIN::VideoHacker.recalc_DSHOWproc if @__playing
end
#--------------------------------------------------------------------------
alias hackerold_stop stop
def stop
hackerold_stop
::SIN::VideoHacker.clear_DSHOWproc if
::SIN::VideoHacker::DSHOWproc.values[0] != 0
end
#--------------------------------------------------------------------------
alias hackerold_playing? playing?
def playing?
return false unless @__playing
return true if getState == 1 # 避免暂停状态被误判
hackerold_playing?
end
#--------------------------------------------------------------------------
alias hackerold_replay_at_finish replay_at_finish
def replay_at_finish
return unless @__playing
return unless (s = getState) && s != 1 # 避免暂停状态被误判
hackerold_replay_at_finish
end
#--------------------------------------------------------------------------
def pausing?
return false unless @__playing
return true if getState == 1
false
end
#--------------------------------------------------------------------------
def convert_time(*args)
::SIN::VideoHacker.convert_time(*args)
end
#--------------------------------------------------------------------------
::SIN::VideoHacker::MethodSym.each do |name|
define_method(name) do |*args|
return unless @__playing
::SIN::VideoHacker.send(name, *args)
end
end
end
end
#------------------------------------------------------------------------------
# ○ 改造自原版范例,仅供参考不建议直接使用
#------------------------------------------------------------------------------
Graphics.resize_screen(640, 480)
@viewport = Viewport.new ##########
$data_system ||= load_data("Data/System.rvdata2") ##########
SIN::PLAYER.viewport = @viewport ##########
SIN::PLAYER.play("Video/title.avi")
SIN::PLAYER.z = 50
#################################################################
@fps_spr = Sprite.new
@fps_spr.z = 0xFFFF
@fps_spr.bitmap = Bitmap.new(56, 40)
@fps_spr.bitmap.font.size = 32
lastfps = (Graphics.fps rescue '')
@fps_spr.bitmap.draw_text(@fps_spr.bitmap.rect, lastfps, 1)
updatefps = -> do
if (n = (Graphics.fps rescue '')) != lastfps
lastfps = n
@fps_spr.bitmap.clear
@fps_spr.bitmap.draw_text(@fps_spr.bitmap.rect, lastfps, 1)
end
end
#################################################################
#################################################################
class << SIN::PLAYER
alias videodemo_update update
def update
videodemo_update
return unless @__playing
begin
@tt ||= 0
p [::SIN::VideoHacker::MACHproc[:BASE],
::SIN::VideoHacker::DLLproc[:m_pMediaSeeking],
::SIN::VideoHacker::DSHOWproc[:SetPositions]].collect {|n|
n.to_s(16) } if @tt == 0
if @tt == 0
s = convert_time(11) # * 10000000
p setPositions(0, :NoPositioning, s, :AbsolutePositioning)
#setTimeFormat(:TIME_FORMAT_FRAME)
#p isUsingTimeFormat(:TIME_FORMAT_FRAME)
#p isUsingTimeFormat(:TIME_FORMAT_MEDIA_TIME)
#p isFormatSupported(:TIME_FORMAT_FRAME)
#p isFormatSupported(:TIME_FORMAT_MEDIA_TIME)
p getTimeFormat
#p [getCurrentPosition, getStopPosition]
p [t = getPositions, getDuration]
p [t.collect {|n| convert_time(n, -1, 0) },
convert_time(getDuration, -1, 0)]
#p getAvailable
#p setRate(2)
#p getRate
#p convertTimeFormat(:TIME_FORMAT_FRAME, t[0], :TIME_FORMAT_MEDIA_TIME)
#p getState
#p pause
p getCurFile
end
#p run if @tt == 29
@tt = (@tt + 1) % 60
end
end
end
#################################################################
@spt1 = Sprite.new
@spt1.bitmap = Bitmap.new(Graphics.width, Graphics.height) # 640, 480
@spt1.bitmap.font.size = 24
@spt1.bitmap.font.shadow = true
@spt1.bitmap.font.outline = false
@spt1.z = 100
@spt2 = Sprite.new(@viewport) ###########
@spt2.bitmap = Bitmap.new(Graphics.width, Graphics.height) # 640, 480
@spt2.bitmap.g_fill_rect(@spt2.bitmap.rect, 0xffff0000, 0xff0000ff)
@spt2.visible = false
@spt2.z = 0
#################################################################
if defined?(RGD) # RGD中Sprite的波效果无法显示位图尺寸外的部分 此处特别处理
@display = Sprite.new(@viewport)
@display.visible = false
@display.bitmap = Bitmap.new(Graphics.width, Graphics.height)
@display.ox = @display.bitmap.width / 2
@display.oy = @display.bitmap.height / 2
@display.x = Graphics.width / 2
@display.y = Graphics.height / 2
@display.z = 50
rect = Rect.new((@display.bitmap.width - SIN::PLAYER.bitmap.width * 0.5) / 2,
(@display.bitmap.height - SIN::PLAYER.bitmap.height * 0.5) / 2,
SIN::PLAYER.bitmap.width * 0.5, SIN::PLAYER.bitmap.height * 0.5)
@display.bitmap.stretch_blt(rect, SIN::PLAYER.bitmap, SIN::PLAYER.src_rect)
class << SIN::PLAYER
def bind_flash_sprite(sprite); @flash_sprite = sprite; end
alias oldtest_flash flash
def flash(*args) # color, duration
@flash_sprite.flash(*args) if @flash_sprite && !@flash_sprite.disposed?
oldtest_flash(*args)
end
end
SIN::PLAYER.bind_flash_sprite(@display)
end
#################################################################
def show_msg(argh)
return @spt1.bitmap.clear if argh[:clear]
x = argh[:x].nil? ? 0 : argh[:x]
y = argh[:y].nil? ? 0 : argh[:y]
width = argh[:width].nil? ? 640 : argh[:width]
height = argh[:height].nil? ? 480 : argh[:height]
y = (Graphics.height - height) / 2 if y == :middle
str = argh[:str].nil? ? "" : argh[:str]
align = argh[:align].nil? ? 0 : argh[:align]
align = 0 if align == :left
align = 1 if align == :middle
align = 2 if align == :right
@spt1.bitmap.draw_text(x, y, width, height, str, align)
end
@step = 0
@wait = 30
@rotating = false
while true
Graphics.update
Input.update
SIN::PLAYER.update
SIN::PLAYER.replay_at_finish
@spt1.update
SIN::PLAYER.angle += 1 if @rotating
updatefps.call ##########
if Input.trigger?(:C) && @wait == -7
show_msg({ :clear => true })
case @step
when 0
SIN::PLAYER.zoom_x = 0.5
SIN::PLAYER.zoom_y = 0.5
when 1
SIN::PLAYER.zoom_x = (Graphics.width * 1.0) / SIN::PLAYER.width
SIN::PLAYER.zoom_y = (Graphics.height * 1.0) / SIN::PLAYER.height
when 2
SIN::PLAYER.mirror = SIN::VideoConfig::RGDFlip != 0 ########## true
when 3
SIN::PLAYER.zoom_x = 0.5
SIN::PLAYER.zoom_y = 0.5
@rotating = true
when 4
@spt2.visible = true
SIN::PLAYER.blend_type = 2
when 5
SIN::PLAYER.blend_type = 0
SIN::PLAYER.tone = Tone.new(0, 0, 0, 255)
when 6
SIN::PLAYER.tone = Tone.new(0, 0, 0, 0)
SIN::PLAYER.flash(Color.new(0, 255, 0), 30)
when 7
SIN::PLAYER.wave_amp = 8
SIN::PLAYER.wave_length = 240
SIN::PLAYER.wave_speed = 360
when 8
#疑似开始旋转后角度置0以外的值会导致图片无法更新 原版就存在这个问题(RGD没事)
SIN::PLAYER.angle = SIN::VideoConfig::RGDFlip == 0 ? 180 : 0 ##########
@rotating = false
when 9
@spt2.visible = false
SIN::PLAYER.mirror = SIN::VideoConfig::RGDFlip == 0 ########## false
SIN::PLAYER.wave_amp = 0
#SIN::PLAYER.wave_length = 0 # RGD里这样设置会崩溃(预设是360) ##########
SIN::PLAYER.wave_speed = 0
SIN::PLAYER.zoom_x = (Graphics.width * 1.0) / SIN::PLAYER.width
SIN::PLAYER.zoom_y = (Graphics.height * 1.0) / SIN::PLAYER.height
when 10
rate = 255 / 60
90.times do |i|
Graphics.update
updatefps.call ##########
SIN::PLAYER.update
SIN::PLAYER.opacity -= rate
end
SIN::PLAYER.stop
break
end
@step += 1
@wait = 30
#################################################################
elsif Input.trigger?(:B)
p t = SIN::PLAYER.getPositions
p t.collect {|n| SIN::PLAYER.convert_time(n, :MEDIA, :SECOND) }
SIN::PLAYER.getState != 2 ?
(Sound.play_ok rescue nil; p SIN::PLAYER.run) :
(Sound.play_cancel rescue nil; p SIN::PLAYER.pause)
elsif key = [:LEFT, :RIGHT].find {|k| Input.repeat?(k) }
if key == :LEFT
a = SIN::PLAYER.getRate - 0.25
a = -0.25 if a == 0
else
a = SIN::PLAYER.getRate + 0.25
a = 0.25 if a == 0
end
Sound.play_cursor rescue nil
p SIN::PLAYER.setRate(a)
p SIN::PLAYER.getRate
elsif key = [:DOWN, :UP].find {|k| Input.repeat?(k) }
if key == :DOWN
a = SIN::PLAYER.get_Volume - 1
else
a = SIN::PLAYER.get_Volume + 1
end
Sound.play_cursor rescue nil
p SIN::PLAYER.put_Volume(a)
p SIN::PLAYER.get_Volume
elsif key = [:X, :Y].find {|k| Input.repeat?(k) }
if key == :X
a = SIN::PLAYER.get_Balance - 1
else
a = SIN::PLAYER.get_Balance + 1
end
Sound.play_cursor rescue nil
p SIN::PLAYER.put_Balance(a)
p SIN::PLAYER.get_Balance
end
#################################################################
#################################################################
if SIN::PLAYER.zoom_x == 0.5
@display.bitmap.clear
rect = Rect.new((@display.bitmap.width - SIN::PLAYER.bitmap.width * 0.5) / 2,
(@display.bitmap.height - SIN::PLAYER.bitmap.height * 0.5) / 2,
SIN::PLAYER.bitmap.width * 0.5, SIN::PLAYER.bitmap.height * 0.5)
@display.bitmap.stretch_blt(rect, SIN::PLAYER.bitmap, SIN::PLAYER.src_rect)
%w{angle wave_amp wave_length wave_speed mirror opacity blend_type
color tone}.each {|var|
@display.send("#{var}=", SIN::PLAYER.send(var)) }
@display.update
@display.wave_phase = SIN::PLAYER.wave_phase
@display.visible, SIN::PLAYER.visible = true, false
else
@display.visible, SIN::PLAYER.visible = false, true
end if @display
#################################################################
next if @wait == -7
if @wait.zero?
case @step
when 0
show_msg({ :y => :middle,
:height => 24,
:str => "窗口太小,看不到全部画面?按下空格试试",
:align => :middle
})
when 1
show_msg({ :y => 32,
:height => 24,
:str => "画面太小,黑边难看?按下空格试试",
:align => :middle
})
when 2
show_msg({ :y => :middle,
:height => 24,
:str => "这样可以吧?但是再按下空格试试",
:align => :middle
})
when 3
show_msg({ :y => 32,
:height => 24,
:str => "再按下空格试试",
:align => :middle
})
when 4
show_msg({ :y => 32,
:height => 24,
:str => "再按下空格试试",
:align => :middle
})
when 5
show_msg({ :y => 32,
:height => 24,
:str => "再按……累死了,您自便吧,等结束了,我再回来",
:align => :middle
})
when 10
show_msg({ :y => :middle,
:height => 24,
:str => "演示就到这里,最后再按下空格,转到标题吧",
:align => :middle
})
end
@wait = -7
next
end
@wait -= 1
end
#################################################################
@fps_spr.bitmap.dispose
@fps_spr.dispose
@spt1.bitmap.dispose
@spt2.bitmap.dispose
@spt1.dispose
@spt2.dispose
SIN::PLAYER.viewport = nil
@viewport.dispose
if @display
@display.bitmap.dispose
@display.dispose
SIN::Video.regen
end
#################################################################
module RGD
class << self
alias videopause_focus_out focus_out if method_defined?(:focus_out)
alias videopause_focus_in focus_in if method_defined?(:focus_in)
end
# 失去焦点
def self.focus_out
SIN::PLAYER.pause if SIN::PLAYER.getState == 2
videopause_focus_out if respond_to?(:videopause_focus_out)
end
# 获得焦点
def self.focus_in
SIN::PLAYER.run if SIN::PLAYER.getState == 1
videopause_focus_in if respond_to?(:videopause_focus_in)
end
end if defined?(RGD)