This commit is contained in:
lifestorm
2024-08-04 23:12:27 +03:00
parent 8064ba84d8
commit 9c918c46e5
7081 changed files with 2173485 additions and 14 deletions

View File

@@ -0,0 +1,344 @@
--[[
| 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/
--]]
TOOL.Category = "Poser"
TOOL.Name = "#tool.eyeposer.name"
TOOL.Information = {
{ name = "left" },
{ name = "left_use" },
{ name = "right" },
{ name = "reload" },
}
TOOL.ClientConVar[ "x" ] = "0"
TOOL.ClientConVar[ "y" ] = "0"
TOOL.ClientConVar[ "strabismus" ] = "0"
local function SetEyeTarget( ply, ent, data )
if ( data.EyeTarget ) then ent:SetEyeTarget( data.EyeTarget ) end
if ( SERVER ) then
if ( data.EyeTarget == vector_origin ) then
duplicator.ClearEntityModifier( ent, "eyetarget" )
else
duplicator.StoreEntityModifier( ent, "eyetarget", data )
end
end
end
if ( SERVER ) then
duplicator.RegisterEntityModifier( "eyetarget", SetEyeTarget )
end
local function ConvertRelativeToEyesAttachment( ent, pos )
if ( ent:IsNPC() ) then return pos end
-- Convert relative to eye attachment
local eyeattachment = ent:LookupAttachment( "eyes" )
if ( eyeattachment == 0 ) then return end
local attachment = ent:GetAttachment( eyeattachment )
if ( !attachment ) then return end
return WorldToLocal( pos, angle_zero, attachment.Pos, attachment.Ang )
end
function TOOL:CalculateEyeTarget()
local x = math.Remap( self:GetClientNumber( "x" ), 0, 1, -1, 1 )
local y = math.Remap( self:GetClientNumber( "y" ), 0, 1, -1, 1 )
local fwd = Angle( y * 45, x * 45, 0 ):Forward()
local s = math.Clamp( self:GetClientNumber( "strabismus" ), -1, 1 )
local distance = 1000
if ( s < 0 ) then
s = math.Remap( s, -1, 0, 0, 1 )
distance = distance * math.pow( 10000, s - 1 )
elseif ( s > 0 ) then
distance = distance * -math.pow( 10000, -s )
end
-- Gotta do this for NPCs...
local ent = self:GetSelectedEntity()
if ( IsValid( ent ) and ent:IsNPC() ) then
local eyeattachment = ent:LookupAttachment( "eyes" )
if ( eyeattachment == 0 ) then return fwd * distance end
local attachment = ent:GetAttachment( eyeattachment )
if ( !attachment ) then return fwd * distance end
return LocalToWorld( fwd * distance, angle_zero, attachment.Pos, attachment.Ang )
end
return fwd * distance
end
function TOOL:GetSelectedEntity()
return self:GetWeapon():GetNWEntity( "eyeposer_ent" )
end
function TOOL:SetSelectedEntity( ent )
if ( !IsValid( ent ) ) then self:SetOperation( 0 ) end
if ( IsValid( ent ) and ent:GetClass() == "prop_effect" ) then ent = ent.AttachedEntity end
return self:GetWeapon():SetNWEntity( "eyeposer_ent", ent )
end
-- Selects entity and aims their eyes
function TOOL:LeftClick( trace )
if ( self:GetOwner():KeyDown( IN_USE ) ) then
return self:MakeLookAtMe( trace )
end
if ( !IsValid( self:GetSelectedEntity() ) or self:GetOperation() != 1 ) then
self:SetSelectedEntity( trace.Entity )
if ( !IsValid( self:GetSelectedEntity() ) ) then return false end
local eyeAtt = self:GetSelectedEntity():LookupAttachment( "eyes" )
if ( eyeAtt == 0 ) then
self:SetSelectedEntity( NULL )
return false
end
self:SetOperation( 1 ) -- For UI
return true
end
local selectedEnt = self:GetSelectedEntity()
self:SetSelectedEntity( NULL )
self:SetOperation( 0 )
if ( !IsValid( selectedEnt ) ) then return false end
local LocalPos = ConvertRelativeToEyesAttachment( selectedEnt, trace.HitPos )
if ( !LocalPos ) then return false end
SetEyeTarget( self:GetOwner(), selectedEnt, { EyeTarget = LocalPos } )
return true
end
-- Select the eyes for posing through UI
function TOOL:RightClick( trace )
local hadEntity = IsValid( self:GetSelectedEntity() )
self:SetSelectedEntity( trace.Entity )
if ( !IsValid( self:GetSelectedEntity() ) ) then return hadEntity end
local eyeAtt = self:GetSelectedEntity():LookupAttachment( "eyes" )
if ( eyeAtt == 0 ) then
self:SetSelectedEntity( NULL )
return false
end
-- TODO: Reset? Save and load these raw values from the entity modifier?
--RunConsoleCommand( "eyeposer_x", 0.5 )
--RunConsoleCommand( "eyeposer_y", 0.5 )
--RunConsoleCommand( "eyeposer_strabismus", 0 )
self:SetOperation( 2 ) -- For UI
return true
end
-- Makes the eyes look at the player
function TOOL:MakeLookAtMe( trace )
self:SetSelectedEntity( NULL )
self:SetOperation( 0 )
local ent = trace.Entity
if ( IsValid( ent ) and ent:GetClass() == "prop_effect" ) then ent = ent.AttachedEntity end
if ( !IsValid( ent ) ) then return false end
if ( CLIENT ) then return true end
local pos = self:GetOwner():EyePos()
local LocalPos = ConvertRelativeToEyesAttachment( ent, pos )
if ( !LocalPos ) then return false end
SetEyeTarget( self:GetOwner(), ent, { EyeTarget = LocalPos } )
return true
end
-- Reset eye position
function TOOL:Reload( trace )
self:SetSelectedEntity( NULL )
self:SetOperation( 0 )
local ent = trace.Entity
if ( IsValid( ent ) and ent:GetClass() == "prop_effect" ) then ent = ent.AttachedEntity end
if ( !IsValid( ent ) ) then return false end
if ( CLIENT ) then return true end
SetEyeTarget( self:GetOwner(), ent, { EyeTarget = vector_origin } )
return true
end
local validEntityLast = false
function TOOL:Think()
local ent = self:GetSelectedEntity()
-- If we're on the client just make sure the context menu is up to date
if ( CLIENT ) then
if ( IsValid( ent ) == validEntityLast ) then return end
validEntityLast = IsValid( ent )
self:RebuildControlPanel( validEntityLast )
return
end
if ( !IsValid( ent ) ) then self:SetOperation( 0 ) return end
if ( self:GetOperation() != 2 ) then return end
-- On the server we continually set the eye position
SetEyeTarget( self:GetOwner(), ent, { EyeTarget = self:CalculateEyeTarget() } )
end
-- The rest of the code is clientside only, it is not used on server
if ( SERVER ) then return end
local SelectionRing = surface.GetTextureID( "gui/faceposer_indicator" )
-- Draw a box indicating the face we have selected
function TOOL:DrawHUD()
local selected = self:GetSelectedEntity()
if ( !IsValid( selected ) ) then return end
local eyeattachment = selected:LookupAttachment( "eyes" )
if ( eyeattachment == 0 ) then return end
local attachment = selected:GetAttachment( eyeattachment )
local scrpos = attachment.Pos:ToScreen()
if ( !scrpos.visible ) then return end
if ( self:GetOperation() == 1 ) then
-- Get Target
local trace = self:GetOwner():GetEyeTrace()
-- Clientside preview
local LocalPos = ConvertRelativeToEyesAttachment( selected, trace.HitPos )
if ( LocalPos ) then
selected:SetEyeTarget( LocalPos )
end
-- Try to get each eye position.. this is a real guess and won't work on non-humans
local Leye = ( attachment.Pos + attachment.Ang:Right() * 1.5 ):ToScreen()
local Reye = ( attachment.Pos - attachment.Ang:Right() * 1.5 ):ToScreen()
-- Todo, make the line look less like ass
local scrhit = trace.HitPos:ToScreen()
local x = scrhit.x
local y = scrhit.y
surface.SetDrawColor( 0, 0, 0, 100 )
surface.DrawLine( Leye.x - 1, Leye.y + 1, x - 1, y + 1 )
surface.DrawLine( Leye.x - 1, Leye.y - 1, x - 1, y - 1 )
surface.DrawLine( Leye.x + 1, Leye.y + 1, x + 1, y + 1 )
surface.DrawLine( Leye.x + 1, Leye.y - 1, x + 1, y - 1 )
surface.DrawLine( Reye.x - 1, Reye.y + 1, x - 1, y + 1 )
surface.DrawLine( Reye.x - 1, Reye.y - 1, x - 1, y - 1 )
surface.DrawLine( Reye.x + 1, Reye.y + 1, x + 1, y + 1 )
surface.DrawLine( Reye.x + 1, Reye.y - 1, x + 1, y - 1 )
surface.SetDrawColor( 0, 255, 0, 255 )
surface.DrawLine( Leye.x, Leye.y, x, y )
surface.DrawLine( Leye.x, Leye.y - 1, x, y - 1 )
surface.DrawLine( Reye.x, Reye.y, x, y )
surface.DrawLine( Reye.x, Reye.y - 1, x, y - 1 )
end
if ( self:GetOperation() == 2 ) then
-- Clientside preview
--selected:SetEyeTarget( self:CalculateEyeTarget() )
-- Work out the side distance to give a rough headsize box..
local player_eyes = LocalPlayer():EyeAngles()
local side = ( attachment.Pos + player_eyes:Right() * 20 ):ToScreen()
local size = math.abs( side.x - scrpos.x )
-- Draw the selection ring
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetTexture( SelectionRing )
surface.DrawTexturedRect( scrpos.x - size, scrpos.y - size, size * 2, size * 2 )
end
end
function TOOL.BuildCPanel( CPanel, hasEntity )
CPanel:AddControl( "Header", { Description = "#tool.eyeposer.desc" } )
if ( hasEntity ) then
-- Panel for Slider ( limiting edge )
local SliderBackground = vgui.Create( "DPanel", CPanel )
SliderBackground:Dock( TOP )
SliderBackground:SetTall( 225 )
CPanel:AddItem( SliderBackground )
-- 2 axis slider for the eye position
local EyeSlider = vgui.Create( "DSlider", SliderBackground )
EyeSlider:Dock( FILL )
EyeSlider:SetLockY()
EyeSlider:SetSlideX( 0.5 )
EyeSlider:SetSlideY( 0.5 )
EyeSlider:SetTrapInside( true )
EyeSlider:SetConVarX( "eyeposer_x" )
EyeSlider:SetConVarY( "eyeposer_y" )
-- Draw the 'button' different from the slider
EyeSlider.Knob.Paint = function( panel, w, h ) derma.SkinHook( "Paint", "Button", panel, w, h ) end
function EyeSlider:Paint( w, h )
local knobX, knobY = self.Knob:GetPos()
local knobW, knobH = self.Knob:GetSize()
surface.SetDrawColor( 0, 0, 0, 250 )
surface.DrawLine( knobX + knobW / 2, knobY + knobH / 2, w / 2, h / 2 )
surface.DrawRect( w / 2 - 2, h / 2 - 2, 5, 5 )
end
CPanel:AddControl( "Slider", { Label = "#tool.eyeposer.strabismus", Command = "eyeposer_strabismus", Type = "Float", Min = -1, Max = 1, Default = 0 } )
end
CPanel:AddControl( "Slider", { Label = "#tool.eyeposer.size_eyes", Command = "r_eyesize", Type = "Float", Min = -0.5, Max = 2, Help = true, Default = 0 } )
end