mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
334 lines
10 KiB
Lua
334 lines
10 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
|
|
local ActiveVideo = nil
|
|
|
|
VideoSettings = nil
|
|
|
|
local stats = {
|
|
reset = 0,
|
|
encodetime = 0,
|
|
|
|
starttime = 0,
|
|
last_encodetime = 0
|
|
}
|
|
|
|
concommand.Add( "gm_demo_to_video", function( ply, cmd, args )
|
|
|
|
local demoname = args[ 1 ]
|
|
if ( !demoname ) then return end
|
|
|
|
local settings = {
|
|
name = "filled_in_later",
|
|
container = "webm",
|
|
video = "vp8",
|
|
audio = "vorbis",
|
|
bitrate = 25000,
|
|
quality = 1,
|
|
width = 640,
|
|
height = 480,
|
|
fps = 25,
|
|
frameblend = 1,
|
|
fbshutter = 0.5,
|
|
dofsteps = 0,
|
|
dofpasses = 0,
|
|
doffocusspeed = 1.0,
|
|
dofsize = 1.0,
|
|
viewsmooth = 0.0,
|
|
possmooth = 0.0
|
|
}
|
|
|
|
local Window = vgui.Create( "DFrame" )
|
|
Window:SetTitle( "Render Video" )
|
|
Window:SetSize( 600, 400 )
|
|
Window:LoadGWENFile( "resource/ui/DemoToVideo.gwen" )
|
|
Window:Center()
|
|
Window:MakePopup()
|
|
|
|
local inCodec = Window:Find( "inCodec" )
|
|
local inQuality = Window:Find( "inQuality" )
|
|
local inSize = Window:Find( "inSize" )
|
|
local btnStart = Window:Find( "btnStart" )
|
|
local inBitRate = Window:Find( "inBitRate" )
|
|
local inFPS = Window:Find( "inFPS" )
|
|
local inFrameBlend = Window:Find( "inFrameBlend" )
|
|
local inFBShutter = Window:Find( "inFBShutter" )
|
|
local inDOF = Window:Find( "inDepthOfField" )
|
|
local inDOFSpeed = Window:Find( "inDOFFocusSpeed" )
|
|
local inDOFSize = Window:Find( "inDOFBlurSize" )
|
|
local inViewSmooth = Window:Find( "inViewSmooth" )
|
|
local inPosSmooth = Window:Find( "inPosSmooth" )
|
|
|
|
inFPS.OnChange = function() settings.fps = inFPS:GetInt() end
|
|
inFPS:SetText( settings.fps )
|
|
|
|
inBitRate.OnChange = function() settings.bitrate = inBitRate:GetInt() end
|
|
inBitRate:SetText( settings.bitrate )
|
|
|
|
-- TODO!!!
|
|
inCodec.OnSelect = function( _, index, value, data ) settings.container = data[1]; settings.video = data[2]; settings.audio = data[3] end
|
|
inCodec:AddChoice( "webm", { "webm", "vp8", "vorbis" }, true )
|
|
inCodec:AddChoice( "ogg", { "ogg", "theora", "vorbis" } )
|
|
|
|
inQuality.OnSelect = function( _, index, value, data ) settings.quality = data end
|
|
inQuality:AddChoice( "0.0 - Low (but fast)", 0 )
|
|
inQuality:AddChoice( "0.5 - Medium", 0.5 )
|
|
inQuality:AddChoice( "1.0 - Highest (but slow)", 1, true )
|
|
|
|
-- TODO!!!
|
|
inSize.OnSelect = function( _, index, value, data ) settings.width = data[1] settings.height = data[2] end
|
|
local sw, sh = ScrW(), ScrH()
|
|
inSize:AddChoice( sw .. " x " .. sh .. " (highest)", { sw, sh }, true )
|
|
|
|
sw, sh = sw * 0.66666, sh * 0.66666
|
|
inSize:AddChoice( math.ceil( sw ) .. " x " .. math.ceil( sh ), { sw, sh }, true )
|
|
|
|
sw, sh = sw * 0.5, sh * 0.5
|
|
inSize:AddChoice( math.ceil( sw ) .. " x " .. math.ceil( sh ), { sw, sh }, true )
|
|
|
|
inFrameBlend.OnSelect = function( _, index, value, data ) settings.frameblend = data end
|
|
inFrameBlend:AddChoice( "Off", 1, true )
|
|
inFrameBlend:AddChoice( "Draft (8 Samples)", 8 )
|
|
inFrameBlend:AddChoice( "Good (16 Samples)", 16 )
|
|
inFrameBlend:AddChoice( "Great (32 Samples)", 32 )
|
|
inFrameBlend:AddChoice( "Overkill (64 Samples)", 64 )
|
|
inFrameBlend:AddChoice( "OverOverKill (128 Samples)", 128 )
|
|
|
|
inFBShutter.OnSelect = function( _, index, value, data ) settings.fbshutter = data end
|
|
inFBShutter:AddChoice( "90", 0.75 )
|
|
inFBShutter:AddChoice( "180", 0.5, true )
|
|
inFBShutter:AddChoice( "240", 0.25 )
|
|
inFBShutter:AddChoice( "360", 0.0 )
|
|
|
|
--
|
|
-- DOF
|
|
--
|
|
inDOF.OnSelect = function( _, index, value, data ) settings.dofsteps = data[1]; settings.dofpasses = data[2] end
|
|
inDOF:AddChoice( "Off", { 0, 0 }, true )
|
|
inDOF:AddChoice( "Draft (21 Samples)", { 6, 3 } )
|
|
inDOF:AddChoice( "Good (72 Samples)", { 12, 6 } )
|
|
inDOF:AddChoice( "Best (288 Samples)", { 24, 12 } )
|
|
|
|
inDOFSpeed.OnChange = function() settings.doffocusspeed = inDOFSpeed:GetFloat() end
|
|
inDOFSpeed:SetText( "1.0" )
|
|
|
|
inDOFSize.OnChange = function() settings.dofsize = inDOFSize:GetFloat() end
|
|
inDOFSize:SetText( "1.0" )
|
|
|
|
--
|
|
-- Smoothing
|
|
--
|
|
inViewSmooth.OnSelect = function( _, index, value, data ) settings.viewsmooth = data end
|
|
inViewSmooth:AddChoice( "Off", 0.0, true )
|
|
inViewSmooth:AddChoice( "Minimal", 0.2 )
|
|
inViewSmooth:AddChoice( "Low", 0.4 )
|
|
inViewSmooth:AddChoice( "Medium", 0.7 )
|
|
inViewSmooth:AddChoice( "High", 0.8 )
|
|
inViewSmooth:AddChoice( "Lots", 0.9 )
|
|
inViewSmooth:AddChoice( "Too Smooth", 0.97 )
|
|
|
|
inPosSmooth.OnSelect = function( _, index, value, data ) settings.possmooth = data end
|
|
inPosSmooth:AddChoice( "Off", 0.0, true )
|
|
inPosSmooth:AddChoice( "Minimal", 0.2 )
|
|
inPosSmooth:AddChoice( "Low", 0.4 )
|
|
inPosSmooth:AddChoice( "Medium", 0.7 )
|
|
inPosSmooth:AddChoice( "High", 0.8 )
|
|
inPosSmooth:AddChoice( "Lots", 0.9 )
|
|
inPosSmooth:AddChoice( "Too Smooth", 0.97 )
|
|
|
|
btnStart.DoClick = function()
|
|
|
|
-- Fill in the name here, or we'll be overwriting the same video!
|
|
local cleanname = string.GetFileFromFilename( demoname )
|
|
cleanname = cleanname:Replace( ".", "_" )
|
|
cleanname = cleanname .. " " .. util.DateStamp()
|
|
settings.name = cleanname
|
|
|
|
PrintTable( settings )
|
|
ActiveVideo, error = video.Record( settings )
|
|
|
|
if ( !ActiveVideo ) then
|
|
Derma_Message( "Couldn't record video: \n" .. error, "Make Video Error", "OK" )
|
|
return
|
|
end
|
|
|
|
RunConsoleCommand( "sv_cheats", 1 )
|
|
RunConsoleCommand( "host_framerate", settings.fps * settings.frameblend )
|
|
RunConsoleCommand( "snd_fixed_rate", 1 )
|
|
RunConsoleCommand( "progress_enable", 1 )
|
|
RunConsoleCommand( "playdemo", demoname )
|
|
|
|
VideoSettings = table.Copy( settings )
|
|
|
|
Window:Remove()
|
|
|
|
end
|
|
|
|
end, nil, "", { FCVAR_DONTRECORD } )
|
|
|
|
local function FinishRecording()
|
|
|
|
VideoSettings = nil
|
|
ActiveVideo:Finish()
|
|
ActiveVideo = nil
|
|
|
|
RunConsoleCommand( "host_framerate", 0 )
|
|
RunConsoleCommand( "sv_cheats", 0 )
|
|
RunConsoleCommand( "snd_fixed_rate", 0 )
|
|
|
|
MsgN( "Rendering Finished - Took ", SysTime() - stats.starttime, " seconds" )
|
|
|
|
end
|
|
|
|
|
|
|
|
local function UpdateFrame()
|
|
|
|
if ( !engine.IsPlayingDemo() ) then
|
|
|
|
if ( !VideoSettings.started ) then return end
|
|
FinishRecording()
|
|
return
|
|
|
|
end
|
|
|
|
if ( !VideoSettings.started ) then
|
|
|
|
if ( gui.IsGameUIVisible() ) then return end
|
|
|
|
VideoSettings.started = true
|
|
VideoSettings.framecount = 0
|
|
stats.starttime = SysTime()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
local function DrawOverlay()
|
|
|
|
if ( !VideoSettings ) then return end
|
|
|
|
local complete = engine.GetDemoPlaybackTick() / engine.GetDemoPlaybackTotalTicks()
|
|
|
|
local x = ScrW() * 0.1
|
|
local y = ScrH() * 0.8
|
|
local w = ScrW() * 0.8
|
|
local h = ScrH() * 0.05
|
|
|
|
surface.SetFont( "DermaDefault" )
|
|
surface.SetTextColor( 255, 255, 255, 255 )
|
|
|
|
-- Static text
|
|
local info = "Rendering " .. math.floor( VideoSettings.width ) .. "x" .. math.floor( VideoSettings.height ) .. " at " .. math.floor( VideoSettings.fps ) .. "fps "
|
|
|
|
local with = {}
|
|
if ( VideoSettings.dofsteps > 0 ) then table.insert( with, "DOF" ) end
|
|
if ( VideoSettings.frameblend > 1 ) then table.insert( with, "Frame Blending" ) end
|
|
if ( VideoSettings.viewsmooth > 0 ) then table.insert( with, "View Smoothing" ) end
|
|
if ( VideoSettings.possmooth > 0 ) then table.insert( with, "Position Smoothing" ) end
|
|
|
|
if ( #with > 0 ) then
|
|
local withS = table.concat( with, ", " )
|
|
info = info .. "with " .. withS
|
|
end
|
|
|
|
info = info .. " (rendering " .. ( VideoSettings.frameblend * math.max( VideoSettings.dofsteps, 1 ) * math.max( VideoSettings.dofpasses, 1 ) ) .. " frames per frame)"
|
|
|
|
local tw, th = surface.GetTextSize( info )
|
|
surface.SetTextPos( x, y - th - 10 )
|
|
surface.DrawText( info )
|
|
|
|
-- The box
|
|
surface.SetDrawColor( 0, 0, 0, 50 )
|
|
surface.DrawRect( x-3, y-3, w + 6, h + 6 )
|
|
|
|
surface.SetDrawColor( 255, 255, 255, 200 )
|
|
surface.DrawRect( x -2, y-2, w + 4, 2 )
|
|
surface.DrawRect( x - 2, y, 2, h )
|
|
surface.DrawRect( x + w, y, 2, h )
|
|
surface.DrawRect( x-2, y + h, w + 4, 2 )
|
|
|
|
surface.SetDrawColor( 255, 255, 100, 150 )
|
|
surface.DrawRect( x + 1, y + 1, w * complete - 2, h - 2 )
|
|
|
|
-- Demo length
|
|
local demolength = "Demo Length: " .. string.FormattedTime( engine.GetDemoPlaybackTotalTicks() * engine.TickInterval(), "%2i:%02i" )
|
|
local tw, th = surface.GetTextSize( demolength )
|
|
surface.SetTextPos( x + w - tw, y - th - 10 )
|
|
surface.DrawText( demolength )
|
|
|
|
if ( !VideoSettings.started ) then return end
|
|
|
|
-- Timers
|
|
surface.SetTextPos( x, y + h + 10 )
|
|
surface.DrawText( "Time Taken: " .. string.NiceTime( SysTime() - stats.starttime ) )
|
|
|
|
local tw, th = surface.GetTextSize( "Time Left: " .. string.NiceTime( stats.timeremaining ) )
|
|
surface.SetTextPos( x + w - tw, y + h + 10 )
|
|
surface.DrawText( "Time Left: " .. string.NiceTime( stats.timeremaining ) )
|
|
|
|
|
|
local demotime = string.FormattedTime( engine.GetDemoPlaybackTick() * engine.TickInterval(), "%2i:%02i" )
|
|
local tw, th = surface.GetTextSize( demotime )
|
|
if ( w * complete > tw + 20 ) then
|
|
surface.SetTextColor( 0, 0, 0, 200 )
|
|
surface.SetTextPos( x + w * complete - tw - 10, y + h * 0.5 - th * 0.5 )
|
|
surface.DrawText( demotime )
|
|
end
|
|
|
|
local demotime = string.FormattedTime( ( engine.GetDemoPlaybackTotalTicks() - engine.GetDemoPlaybackTick() ) * engine.TickInterval(), "%2i:%02i" )
|
|
local tw, th = surface.GetTextSize( demotime )
|
|
if ( w - w * complete > tw + 20 ) then
|
|
surface.SetTextColor( 255, 255, 255, 200 )
|
|
surface.SetTextPos( x + w * complete + 10, y + h * 0.5 - th * 0.5 )
|
|
surface.DrawText( demotime )
|
|
end
|
|
|
|
end
|
|
|
|
hook.Add( "CaptureVideo", "CaptureDemoFrames", function()
|
|
|
|
if ( !ActiveVideo ) then return end
|
|
if ( !VideoSettings ) then return end
|
|
|
|
UpdateFrame()
|
|
|
|
DrawOverlay()
|
|
|
|
if ( stats.reset < SysTime() ) then
|
|
|
|
stats.reset = SysTime() + 1
|
|
|
|
stats.last_encodetime = stats.encodetime
|
|
stats.encodetime = 0
|
|
|
|
local timetaken = SysTime() - stats.starttime
|
|
local fractioncomplete = engine.GetDemoPlaybackTotalTicks() / engine.GetDemoPlaybackTick()
|
|
|
|
stats.timeremaining = ( timetaken * fractioncomplete ) - timetaken
|
|
if ( stats.timeremaining < 0 ) then stats.timeremaining = 0 end
|
|
|
|
end
|
|
|
|
end )
|
|
|
|
function RecordDemoFrame()
|
|
|
|
if ( !ActiveVideo ) then return end
|
|
if ( !VideoSettings ) then return end
|
|
if ( !VideoSettings.started ) then return end
|
|
|
|
ActiveVideo:AddFrame( 1 / VideoSettings.fps, true )
|
|
VideoSettings.framecount = VideoSettings.framecount + 1
|
|
|
|
end
|