--by exechack.cc Toxicbadkazuin ANALM = ANALM or {} local comparision_model = "models/humans/group01/male_07.mdl" -- male_07 my beloved local title_color = Color(80, 30, 30, 255) local panel_title_color = Color(50, 30, 30, 255) local bg_color = Color(40,40,40,255) local color_grey = Color( 127, 127, 127, 255 ) local fg_color = Color(30,30,30,255) local panel_color = Color(50,50,50,255) local hitbox_colors = { [1] = Color(240, 100, 60, 255), -- head [2] = Color(240, 50, 30, 255), -- chest [3] = Color(230, 230, 0, 255), -- stomach [4] = Color(20, 90, 250, 255), -- left arm [5] = Color(255, 130, 255, 255), -- right arm [6] = Color(90, 210, 250, 255), -- left leg [7] = Color(255, 220, 255, 255) -- right leg } local hitboxnames = {"head", "chest", "stomach", "left arm", "right arm", "left leg", "right leg"} if !ANALM.FONTS_CREATED then local start = 8 for i = 1, 61 do surface.CreateFont( "char_title"..start.."r", { font = "Roboto", size = start, antialias = true }) start=start+2 end ANALM.FONTS_CREATED = true end local function PaintButtons(self, w, h) local font = self:GetFont() != "DermaDefault" and self:GetFont() or "char_title16r" local color = self.bcol or Color(60, 60, 60, 255) local text_color = self.tcol or Color(200,200,200,255) if self:IsHovered() && !self.nohov then color = self.hcol or Color(50, 50, 50, 255) end if self:GetDisabled() then if self.dcol then color = self.dcol end self:SetCursor("no") else self:SetCursor("hand") end local text = self:GetText() if text != "" then self:SetText("") self.text = text end draw.RoundedBox( 0, 0, 0, w, h, color ) if !self.text then return end surface.SetFont(font) local x, y = surface.GetTextSize(self.text) draw.DrawText( self.text, font, w/2, h/2-(y/2) + (self._ty or 0), text_color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER ) end local function FrameToPanel( frame ) frame:ShowCloseButton(false) frame:SetTitle("") frame:MakePopup() frame:DockPadding( 0, 24, 0, 0 ) frame.PerformLayout = function() end -- we dont want it frame.btnMaxim:Remove() frame.btnMinim:Remove() frame.lblTitle:Remove() function frame:Think() local mousex = math.Clamp( gui.MouseX(), 1, ScrW() - 1 ) local mousey = math.Clamp( gui.MouseY(), 1, ScrH() - 1 ) if ( self.Dragging ) then local x = mousex - self.Dragging[1] local y = mousey - self.Dragging[2] -- Lock to screen bounds if screenlock is enabled if ( self:GetScreenLock() ) then x = math.Clamp( x, 0, ScrW() - self:GetWide() ) y = math.Clamp( y, 0, ScrH() - self:GetTall() ) end self:SetPos( x, y ) end if ( self.Sizing ) then local x = mousex - self.Sizing[1] local y = mousey - self.Sizing[2] local px, py = self:GetPos() if ( x < self.m_iMinWidth ) then x = self.m_iMinWidth elseif ( x > ScrW() - px && self:GetScreenLock() ) then x = ScrW() - px end if ( y < self.m_iMinHeight ) then y = self.m_iMinHeight elseif ( y > ScrH() - py && self:GetScreenLock() ) then y = ScrH() - py end self:SetSize( x, y ) self:SetCursor( "sizenwse" ) self:Center() if self.div then self.div:SetLeftWidth( self:GetWide()/2 ) end return end local screenX, screenY = self:LocalToScreen( 0, 0 ) if ( self.Hovered && self.m_bSizable && mousex > ( screenX + self:GetWide() - 20 ) && mousey > ( screenY + self:GetTall() - 20 ) ) then self:SetCursor( "sizenwse" ) return end if ( self.Hovered && self:GetDraggable() && mousey < ( screenY + 24 ) ) then self:SetCursor( "sizeall" ) return end self:SetCursor( "arrow" ) -- Don't allow the frame to go higher than 0 if ( self.y < 0 ) then self:SetPos( self.x, 0 ) end end local title = vgui.Create("DPanel", frame) title:SetWide(frame:GetWide()) title:SetTall(24) title.Paint = function(self, w, h) draw.RoundedBoxEx(4, 0, 0, w, h, title_color, true, true, false, false) draw.SimpleText("Playermodel Analyser", "char_title16r", w/2, 4, color_nearwhite, TEXT_ALIGN_CENTER) self:SetWide(frame:GetWide()) end title:SetCursor( "sizeall" ) function title:OnMousePressed() local screenX, screenY = frame:LocalToScreen( 0, 0 ) if ( gui.MouseY() < ( screenY + 24 ) ) then frame.Dragging = { gui.MouseX() - frame.x, gui.MouseY() - frame.y } self:MouseCapture( true ) return end end function title:OnMouseReleased() frame.Dragging = nil frame.Sizing = nil self:MouseCapture( false ) end local close = vgui.Create("DButton", title) close:Dock(RIGHT) close:SetWide(20) close:DockMargin(0, 2, 2, 0) close:SetTextColor(color_white) close:SetText("x") close:SetFont("char_title18r") close.Paint = function(self, w, h) end close.DoClick = function() frame:Remove() end end local function formatBytes(bytes) local units = {"B", "KB", "MB", "GB"} local size = bytes local i = 1 while size > 1024 and i < #units do size = size / 1024 i = i + 1 end return string.format("%.2f %s", size, units[i]) end local function GetModelFileSize(model_path) -- Returns size of all model, mat, texture files in bytes 0 local modelSize = 0 local name = player_manager.TranslateToPlayerModelName(model_path or "") local pm = player_manager.TranslatePlayerModel(name) local hands = player_manager.TranslatePlayerHands(name).model local has_hands = hands != "models/weapons/c_arms_citizen.mdl" local pm_file = string.sub(pm, 1, -5) local pm_files = { pm_file .. ".mdl", pm_file .. ".dx80.vtx", pm_file .. ".dx90.vtx", pm_file .. ".phy", pm_file .. ".sw.vtx", pm_file .. ".vvd", } for _, mdl_file in ipairs(pm_files) do modelSize = modelSize + file.Size(mdl_file, "GAME") --print(mdl_file, file.Size(mdl_file, "GAME")) end if has_hands then local hand_file = string.sub(hands, 1, -5) local hand_files = { hand_file .. ".mdl", hand_file .. ".dx80.vtx", hand_file .. ".dx90.vtx", hand_file .. ".phy", hand_file .. ".sw.vtx", hand_file .. ".vvd", } for _, mdl_file in ipairs(hand_files) do modelSize = modelSize + file.Size(mdl_file, "GAME") --print(mdl_file, file.Size(mdl_file, "GAME")) end end local pm_ent = ClientsideModel(pm, RENDERGROUP_OPAQUE) local hands_ent = ClientsideModel(hands, RENDERGROUP_OPAQUE) local mats = pm_ent:GetMaterials() if has_hands then table.Add(mats, hands_ent:GetMaterials()) end local processed = {} for _, mat in ipairs(mats) do local searchable_vars = { "$basetexture", "$bumpmap", "$phongexponenttexture", "$Iris" } if processed[mat .. ".vmt"] then continue end processed[mat .. ".vmt"] = true modelSize = modelSize + file.Size("materials/" .. mat .. ".vmt", "GAME") --print("materials/" .. mat .. ".vmt", file.Size("materials/" .. mat .. ".vmt", "GAME")) for _, var in ipairs(searchable_vars) do local texture = Material(mat):GetTexture(var) if texture then texture = texture:GetName() if processed[texture .. ".vtf"] then continue end processed[texture .. ".vtf"] = true modelSize = modelSize + file.Size("materials/" .. texture .. ".vtf", "GAME") --print("materials/" .. texture .. ".vtf", file.Size("materials/" .. texture .. ".vtf", "GAME")) end end end pm_ent:Remove() hands_ent:Remove() return modelSize end local good_mat = Material("icon16/accept.png") local info_mat = Material("icon16/information.png") local bad_mat = Material("icon16/delete.png") local default_animations = { "idle_all_01", "menu_walk" } local function modelCompare() if IsValid(ANALM.Frame) then ANALM.Frame:Remove() end local fram = vgui.Create("DFrame") ANALM.Frame = fram fram:SetSize(800, 600) fram:Center() fram:MakePopup() FrameToPanel(fram) fram.Paint = function(self, w, h) draw.RoundedBox(4, 0, 0, w, h, bg_color) end fram:SetDraggable(true) fram:SetSizable(false) local compari = ClientsideModel(comparision_model) compari:SetNoDraw(true) compari:SetSequence(1) local height_compari = ClientsideModel(comparision_model) height_compari:SetNoDraw(true) height_compari:SetSequence(1) local scale = Vector( 1, 1, 0.87 ) local mat = Matrix() mat:Scale(scale) height_compari:EnableMatrix("RenderMultiply", mat) local model_cache = {} fram.OnRemove = function() for k, v in pairs(model_cache) do if IsValid(v) then v:Remove() -- gc end end if IsValid(compari) then compari:Remove() end if IsValid(height_compari) then height_compari:Remove() end end local panels = {} local names = {"Model Selector", "Preview"} for i = 1, 2 do local panel = vgui.Create("DPanel", fram) panel:Dock(LEFT) panel:SetWide( fram:GetWide() / 2 ) panel:DockMargin(0, 0, 5, 0) panel.Paint = function(self, w, h) draw.RoundedBox(4, 0, 0, w, h, panel_color) draw.RoundedBoxEx(4, 0, 0, w, 28, panel_title_color, true, true, false, false) draw.SimpleText(names[i], "char_title24r", w/2, 3, color_nearwhite, TEXT_ALIGN_CENTER) if self.postPaint then self.postPaint(self, w, h) end end panels[i] = panel end local selectpanel, modelpanel = panels[1], panels[2] local Search_clear local Search = vgui.Create("DTextEntry", selectpanel) Search:Dock(TOP) Search:SetTall(30) Search:SetFont("char_title18r") Search:DockMargin(0, 28, 0, 0) Search:SetMouseInputEnabled(true) Search:SetTextColor(Color(200,200,200,255)) Search:SetCursorColor(Color(200,200,200,255)) Search.Paint = function(self, w, h) -- Hack on a hack, but this produces the most close appearance to what it will actually look if text was actually there if ( self:HasFocus() ) then draw.RoundedBox(0,0,0,w,h,bg_color) else draw.RoundedBox(0,0,0,w,h,fg_color) end if ( self.GetPlaceholderText && self.GetPlaceholderColor && self:GetPlaceholderText() && self:GetPlaceholderText():Trim() != "" && self:GetPlaceholderColor() && ( !self:GetText() || self:GetText() == "" ) ) then local oldText = self:GetText() local str = self:GetPlaceholderText() if ( str:StartWith( "#" ) ) then str = str:sub( 2 ) end str = language.GetPhrase( str ) self:SetText( str ) self:DrawTextEntryText( self:GetPlaceholderColor(), self:GetHighlightColor(), self:GetCursorColor() ) self:SetText( oldText ) return end self:DrawTextEntryText( self:GetPlaceholderColor(), self:GetHighlightColor(), self:GetCursorColor() ) end Search:SetKeyboardInputEnabled(true) Search:SetPlaceholderText("Type model name or path to search...") Search.OnChange = function( s ) local val = string.lower( s:GetText() ) if val != "" then fram.ModelSearched = val if IsValid(Search_clear) then Search_clear:SetVisible(true) end else fram.ModelSearched = nil end timer.Create("anal_debounce_searchbar", 0.5, 1, function() fram:UpdateModels() end) end Search_clear = vgui.Create("DButton", Search) Search_clear:Dock(RIGHT) Search_clear:SetSize(20,18) Search_clear:SetText("") Search_clear:DockMargin(0, 5, 5, 5) Search_clear.bcol = Color(50,50,50,255) Search_clear.hcol = Color(60,60,60,255) Search_clear.Paint = function(self, w, h) PaintButtons(self, w, h) draw.SimpleText("x", "char_title18r", w/2, h/2-1, color_white, 1, 1) end Search_clear.DoClick = function() Search_clear:SetVisible(false) Search:SetValue("") fram.ModelSearched = nil fram:UpdateModels() end Search_clear:SetVisible(false) local scroll = vgui.Create("DScrollPanel", selectpanel) scroll:Dock(FILL) scroll:DockMargin(0,0,0,0) scroll:InvalidateLayout(true) local iconf = vgui.Create("DIconLayout", scroll) iconf:Dock(FILL) iconf:DockMargin(0, 0, 0, 0) iconf:SetSpaceX(0) iconf:SetSpaceY(0) iconf:InvalidateLayout(true) local BodyGrouper = vgui.Create("DPanel", selectpanel) local xx, yy = selectpanel:GetSize() BodyGrouper:SetSize(xx, yy) BodyGrouper:SetPos(0, 58) function BodyGrouper:Update() self:Clear() self:SetTall( selectpanel:GetTall()-58 ) -- set it tall for layouting local window = self local mdl = fram.pmodel local sheet = window:Add( "DPanel" ) sheet:Dock( FILL ) sheet:DockPadding( 8, 8, 8, 8 ) sheet.Paint = function(self, w, h) draw.RoundedBox(0, 0, 0, w, h, color_grey) end local bdcontrols = sheet:Add( "DPanel" ) bdcontrols:DockPadding( 8, 8, 8, 8 ) bdcontrols:Dock( FILL ) bdcontrols.Paint = function(self, w, h) draw.RoundedBox(4, 0, 0, w, h, color_black) end local bdcontrolspanel = bdcontrols:Add( "DPanelList" ) bdcontrolspanel:EnableVerticalScrollbar( true ) bdcontrolspanel:Dock( FILL ) local ScrollBar = bdcontrolspanel.VBar ScrollBar.Paint = function(self, w, h) draw.RoundedBox(0,0,0,w,h,fg_color) end ScrollBar.btnUp.Paint = function(self, w, h) draw.RoundedBox(0,0,0,w,h,bg_color) draw.SimpleText("в–ґ", "char_title20r", w/2 - 1, h/2, t_color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end ScrollBar.btnDown.Paint = function(self, w, h) draw.RoundedBox(0,0,0,w,h,bg_color) draw.SimpleText("в–ѕ", "char_title20r", w/2 - 2, h/2, t_color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end ScrollBar.btnGrip.Paint = function(self, w, h) draw.RoundedBox(0,0,0,w,h,bg_color) end local plycol = bdcontrols:Add( "DColorMixer" ) plycol:SetAlphaBar( false ) plycol:SetPalette( false ) plycol:Dock( TOP ) plycol:SetSize( 200, math.min( window:GetTall() / 3, 260 ) ) plycol:SetVector( Vector( GetConVarString( "cl_playercolor" ) ) ) -- Helper functions local function MakeNiceName( str ) local newname = {} for _, s in pairs( string.Explode( "_", str ) ) do if ( string.len( s ) == 1 ) then table.insert( newname, string.upper( s ) ) continue end table.insert( newname, string.upper( string.Left( s, 1 ) ) .. string.Right( s, string.len( s ) - 1 ) ) -- Ugly way to capitalize first letters. end return string.Implode( " ", newname ) end -- Updating local function UpdateBodyGroups( pnl, val ) if ( pnl.type == "bgroup" ) then mdl.Entity:SetBodygroup( pnl.typenum, math.Round( val ) ) local info = LocalPlayer():GetInfo( "cl_playerbodygroups" ) local str = string.Explode( " ", info ) if ( #str < pnl.typenum + 1 ) then for i = 1, pnl.typenum + 1 do str[ i ] = str[ i ] or 0 end end str[ pnl.typenum + 1 ] = math.Round( val ) elseif ( pnl.type == "skin" ) then mdl.Entity:SetSkin( math.Round( val ) ) end end local function RebuildBodygroupTab() bdcontrolspanel:Clear() local nskins = mdl.Entity:SkinCount() - 1 if ( nskins > 0 ) then local skins = vgui.Create( "DNumSlider" ) skins:Dock( TOP ) skins:SetText( "Skin" ) skins:SetDark( true ) skins:SetTall( 50 ) skins:SetDecimals( 0 ) skins:SetDark( false ) skins:SetMax( nskins ) skins:SetValue( GetConVarNumber( "cl_playerskin" ) ) skins.type = "skin" skins.OnValueChanged = UpdateBodyGroups bdcontrolspanel:AddItem( skins ) mdl.Entity:SetSkin( GetConVarNumber( "cl_playerskin" ) ) end local info = LocalPlayer():GetInfo( "cl_playerbodygroups" ) local groups = string.Explode( " ", info ) for k = 0, mdl.Entity:GetNumBodyGroups() - 1 do if ( mdl.Entity:GetBodygroupCount( k ) <= 1 ) then continue end local bgroup = vgui.Create( "DNumSlider" ) bgroup:Dock( TOP ) bgroup:SetText( MakeNiceName( mdl.Entity:GetBodygroupName( k ) ) ) bgroup:SetDark( true ) bgroup:SetTall( 50 ) bgroup:SetDark( false ) bgroup:SetDecimals( 0 ) bgroup.type = "bgroup" bgroup.typenum = k bgroup:SetMax( mdl.Entity:GetBodygroupCount( k ) - 1 ) bgroup:SetValue( groups[ k + 1 ] or 0 ) bgroup.OnValueChanged = UpdateBodyGroups bdcontrolspanel:AddItem( bgroup ) mdl.Entity:SetBodygroup( k, groups[ k + 1 ] or 0 ) end end local function UpdateFromConvars() local modelname = mdl.Entity:GetModel() util.PrecacheModel( modelname ) mdl:SetModel( modelname ) mdl.Entity.GetPlayerColor = function() return plycol:GetVector() end local groups = LocalPlayer():GetInfo( "cl_playerbodygroups" ) if ( groups == nil ) then groups = "" end local groups = string.Explode( " ", groups ) for k = 0, mdl.Entity:GetNumBodyGroups() - 1 do local a = tonumber( groups[ k + 1 ] ) or 0 mdl.Entity:SetBodygroup( k, a ) end RebuildBodygroupTab() end UpdateFromConvars() end local pmodel_panel = vgui.Create("DModelPanel", modelpanel) pmodel_panel:Dock(FILL) fram.pmodel = pmodel_panel local hide_model = vgui.Create("DCheckBoxLabel", pmodel_panel) hide_model:SetWide(100) hide_model:SetPos( 163, 55 ) hide_model:SetText("Show hitboxes?") hide_model:SetChecked(true) local show_joints = vgui.Create("DCheckBoxLabel", pmodel_panel) show_joints:SetWide(100) show_joints:SetPos( 268, 55 ) show_joints:SetText("Show Bones/Joints?") show_joints:SetChecked(true) local force_model = vgui.Create("DCheckBoxLabel", pmodel_panel) force_model:SetWide(100) force_model:SetPos( 5, 55 ) force_model:SetText("Always show playermodel?") force_model:SetChecked(true) local overlay_model = vgui.Create("DCheckBoxLabel", pmodel_panel) overlay_model:SetWide(100) overlay_model:SetPos( 5, 35 ) overlay_model:SetText("Overlay default playermodel (for height comparisons)?") local acceptable_height = vgui.Create("DCheckBoxLabel", pmodel_panel) acceptable_height:SetWide(100) acceptable_height:SetPos( 5, 75 ) acceptable_height:SetText("Minimum Height?") acceptable_height:SetTooltip("Some servers may have a requirement for player models being this tall to enter the ride!") acceptable_height:SetChecked(false) local color_yellow = Color(200, 200, 0, 255) modelpanel.postPaint = function(self, w, h) end local pm_filesize = 0 local font = "char_title16r" local color_nee = Color(0,0,0,200) local function drawPlaque(x, y, name) local alignment = TEXT_ALIGN_CENTER local mx, my = gui.MousePos() local screenx, screeny = modelpanel:LocalToScreen(x, y) local dist = Vector(mx, my):Distance( Vector( screenx, screeny ) ) if dist <= 30 then surface.SetFont(font) local wid, _ = surface.GetTextSize(name) local w, h = wid+5, 18 draw.RoundedBox(4, x-w/2, y, w, h, color_nee) draw.SimpleText(name, font, x, y, color_nearwhite, alignment) end end local joint_col = Color( 0, 175, 175, 255 ) function pmodel_panel:DrawModelPost(ent) if !hide_model:GetChecked() then return end self.cur_bones = {} local max, i = 20, 0 -- only check the first 18 for shitboxes for hitbox = 0, ent:GetHitBoxCount(0) do local bone = ent:GetHitBoxBone( hitbox, 0 ) if !bone then continue end local bpos, bang = ent:GetBonePosition( bone ) local min, max = ent:GetHitBoxBounds( hitbox, 0 ) if( min == nil || max == nil ) then continue end local hit_group = ent:GetHitBoxHitGroup( hitbox, 0 ) local that_other_color = hitbox_colors[ent:GetHitBoxHitGroup( hitbox, 0 )] render.DrawWireframeBox( bpos, bang, min, max, that_other_color, !IGNOREZ ) local bname = ent:GetBoneName( bone ) if show_joints:GetChecked() then render.SetColorMaterial() render.DrawSphere( bpos, 1.4, 4, 3, joint_col ) local vv = bpos/2 vv.x = vv.x / 2 vv.y = vv.y / 2 local dat = (vv + Vector(0,0,23)):ToScreen() local x, y = dat.x, dat.y x=x+self:GetWide()/2 + 7 --y=y+self:GetFOV() local d, c = self:ScreenToLocal( x, y ) bname = string.Replace(bname, "ValveBiped.Bip01_", "") table.insert( self.cur_bones, { d, c, bname, hit_group } ) end end end function pmodel_panel:DrawModel() -- Causes issues with stencils, but only for some people? render.ClearDepth() local ret = self:PreDrawModel( self.Entity ) if ( ret != false ) then if !hide_model:GetChecked() or force_model:GetChecked() then self.Entity:DrawModel() end self:DrawModelPost( self.Entity ) end end local default_bonecount = 17 local color_green = Color(0,200,0,255) local default_fov = pmodel_panel:GetFOV() function pmodel_panel:Paint( w, h ) local ent = self.Entity if ( !IsValid( ent ) ) then return end local x, y = self:LocalToScreen( 0, 0 ) self:LayoutEntity( ent ) local ang = self.aLookAngle if ( !ang ) then ang = ( self.vLookatPos - self.vCamPos ):Angle() end cam.Start3D( self.vCamPos, ang, self.fFOV, x, y, w, h, 5, self.FarZ ) render.SuppressEngineLighting( true ) render.SetLightingOrigin( ent:GetPos() ) render.ResetModelLighting( self.colAmbientLight.r / 255, self.colAmbientLight.g / 255, self.colAmbientLight.b / 255 ) render.SetColorModulation( self.colColor.r / 255, self.colColor.g / 255, self.colColor.b / 255 ) render.SetBlend( ( self:GetAlpha() / 255 ) * ( self.colColor.a / 255 ) ) -- * surface.GetAlphaMultiplier() for i = 0, 6 do local col = self.DirectionalLight[ i ] if ( col ) then render.SetModelLighting( i, col.r / 255, col.g / 255, col.b / 255 ) end end self:DrawModel() render.SuppressEngineLighting( false ) cam.End3D() self.LastPaint = RealTime() local bones = ent:GetHitBoxCount(0) local shitboxes = 0 local hitgroupsd = {} local max, i = 20, 0 -- only check the first 18 for shitboxes for hitbox = 0, ent:GetHitBoxCount(0) do i=i+1 --if i>=max then break end local hitgroup = ent:GetHitBoxHitGroup(hitbox, 0) if i <= max && hitgroup == 0 then shitboxes = shitboxes + 1 elseif hitgroup then hitgroupsd[hitgroup] = true end end --cam.Start3D() --cam.End3D() for k, v in pairs(self.cur_bones) do drawPlaque(v[1], v[2], v[3], v[4]) end local enough_hitboxes = table.Count(hitgroupsd) > 6 -- we got good ones local hei = 210 if shitboxes <= 0 then hei = hei - 15 end draw.RoundedBoxEx(4, 0, h-hei, 85, 150, Color(30, 30, 30, 200), false, true, false, false) draw.SimpleText("Legend", "char_title16r", 5, h-hei+2, color_nearwhite) local i = h-hei+5 for k, v in ipairs(hitbox_colors) do local name = hitboxnames[k] i=i+16 draw.SimpleText(name, "char_title16r", 23, i, v) surface.SetDrawColor(color_white) surface.SetMaterial(hitgroupsd[k] and good_mat or bad_mat) surface.DrawTexturedRect( 5, i, 16, 16) end draw.SimpleText("shitbox", "char_title16r", 5, i+16, color_nearwhite) if pm_filesize > 0 then draw.RoundedBoxEx(4, 0, h-hei-40, 85, 35, Color(30, 30, 30, 200), false, true, false, true) draw.SimpleText("Model Size", "char_title16r", 5, h-hei-38, color_nearwhite) surface.SetDrawColor(color_white) surface.SetMaterial(info_mat) surface.DrawTexturedRect( 5, h-hei-23, 16, 16) local byte_color = color_green if pm_filesize > 104857600 then byte_color = color_red elseif pm_filesize > 104857600/2 then byte_color = color_yellow end draw.SimpleText(formatBytes(pm_filesize), "char_title14r", 22, h-hei-21, byte_color) local x, y = gui.MousePos() local xx, yy = self:LocalToScreen(0, h-hei-40) if x > xx && x < xx+85 then if y > yy && y < yy+35 then draw.RoundedBox(4, 85, h-hei-40, 235, 35, Color(0, 0, 0, 240)) draw.SimpleText("Estimated model size may differ if it is", "char_title16r", 90, h-hei-38, color_nearwhite) draw.SimpleText("in a workshop multi-pack with others!", "char_title16r", 90, h-hei-23, color_nearwhite) end end local cur_fov = pmodel_panel:GetFOV() draw.RoundedBoxEx(4, 0, h-hei-65, 85, 20, Color(30, 30, 30, 200), false, true, false, true) surface.SetDrawColor(color_white) surface.SetMaterial(cur_fov == default_fov and good_mat or bad_mat) surface.DrawTexturedRect( 5, h-hei-63, 16, 16) draw.SimpleText("FOV: "..math.Round(cur_fov), "char_title16r", 22, h-hei-63, color_nearwhite) end local he = shitboxes != 0 and 55 or 40 draw.RoundedBoxEx(4, 0, h-he, 170, he, Color(30, 30, 30, 200), false, true, false, false) if shitboxes != 0 then draw.SimpleText("SHITBOXES DETECTED: "..shitboxes, "char_title16r", 5, h-55, color_red) end draw.SimpleText("Hitbox differences: "..math.abs(default_bonecount - bones), "char_title16r", 5, h-40, color_nearwhite) draw.SimpleText("Hitbox Count: "..bones, "char_title24r", 5, h-25, color_nearwhite) draw.SimpleText("with love from hbn.gg", "char_title12r", w-8, h-15, color_nearwhite, TEXT_ALIGN_RIGHT) end function pmodel_panel:PreDrawModel(ent) for k, v in pairs(model_cache) do if IsValid(v) then v:DrawModel() end end --l--ocal cycle = ent:GetCycle() + FrameTime() --if cycle > 1 then cycle = 0 end --local cycle = ent:GetCycle() + FrameTime()/5 --if cycle >= 1 then cycle = -1 end --ent:SetCycle( cycle ) if overlay_model:GetChecked() && IsValid(compari) then compari:DrawModel() compari:SetAngles( self.Angles ) --compari:FrameAdvance() end if acceptable_height:GetChecked() && IsValid(height_compari) then height_compari:DrawModel() height_compari:SetAngles( self.Angles ) --compari:FrameAdvance() end end local floor = ClientsideModel("models/props_wasteland/rockcliff06d.mdl") floor:SetNoDraw(true) floor:SetPos(Vector(-20,-5,-125)) table.insert(model_cache, floor) local function pairsByKeys (t, f) local a = {} for n in pairs(t) do table.insert(a, n) end table.sort(a, f) local i = 0 -- iterator variable local iter = function () -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end local player_models = player_manager.AllValidModels() //list.Get( "PlayerOptionsModel" ) local valid_playermodels = {} for k, v in pairs(player_models) do if !file.Exists(v, "GAME") then continue end valid_playermodels[k] = v end local preview_model local default_seq ANALM.FileCache = ANALM.FileCache or {} function fram:UpdateModels() --BodyGrouper:SetTall(0) BodyGrouper:SizeTo(-1, 0, 1, 0, 0.4) iconf:Clear() for k, v in pairsByKeys(valid_playermodels) do if self.ModelSearched != nil && !(string.find( v:lower(), self.ModelSearched, nil, true ) or string.find( k:lower(), self.ModelSearched, nil, true )) then continue end local d = vgui.Create("SpawnIcon", iconf) d:SetModel(v) d:SetSize(64, 64) d.DoClick = function(self) pmodel_panel:SetModel(v) pm_filesize = GetModelFileSize(pmodel_panel:GetModel()) default_seq = pmodel_panel.Entity:GetSequence() pmodel_panel:SetFOV( default_fov ) overlay_model:SetChecked(false) BodyGrouper:Update() BodyGrouper:SetTall(0) end d.DoRightClick = function(self) print("rebuilding spawnicon "..v) d:RebuildSpawnIcon() end d:SetTooltip( k:gsub("^%l", string.upper).." | "..v ) iconf:Add(d) if !preview_model then preview_model = v end end iconf:InvalidateParent(true) end fram:UpdateModels() pmodel_panel:SetModel(comparision_model) default_seq = pmodel_panel.Entity:GetSequence() local PModelControls = vgui.Create("DPanel", pmodel_panel) PModelControls:SetSize(100, 145) PModelControls:SetPos( pmodel_panel:GetWide() - (PModelControls:GetWide()-5), pmodel_panel:GetTall() - (PModelControls:GetTall()+15) ) PModelControls.Paint = function(self, w, h) self:SetPos( pmodel_panel:GetWide() - 105, pmodel_panel:GetTall() - 110 ) end local ft = vgui.Create("DButton", PModelControls) ft:Dock(TOP) ft:SetText("BodyGroups") ft:SetFont("char_title16r") ft:SetTall(30) ft.Paint = function(self, w, h) PaintButtons(self, w, h) end ft.bcol = Color(70, 10, 70, 255) ft.hcol = Color(60, 10, 60, 255) ft.DoClick = function(self) if BodyGrouper:GetTall() == 0 then BodyGrouper:SizeTo(-1, selectpanel:GetTall()-58, 1, 0, 0.4) else BodyGrouper:SizeTo(-1, 0, 1, 0, 0.4) end end ft:DockMargin(5, 5, 5, 0) local ft = vgui.Create("DButton", PModelControls) ft:Dock(TOP) ft:SetText("Animate") ft:SetFont("char_title16r") ft:SetTall(30) ft.Paint = function(self, w, h) PaintButtons(self, w, h) end ft.bcol = Color(70, 70, 10, 255) ft.hcol = Color(60, 60, 10, 255) ft.DoClick = function(self) local ent = pmodel_panel.Entity local model = ent:GetModel() local seqs = {} for k, v in pairs(ent:GetSequenceList()) do table.insert(seqs, v) end local s = table.Random( seqs ) local seq = ent:LookupSequence( s ) ent:SetSequence(seq) end ft:DockMargin(5, 5, 5, 5) local ft = vgui.Create("DButton", PModelControls) ft:Dock(TOP) ft:SetFont("char_title16r") ft:SetText("Default") ft:SetTall(30) ft.Paint = function(self, w, h) PaintButtons(self, w, h) end ft.bcol = Color(10, 70, 70, 255) ft.hcol = Color(10, 60, 60, 255) ft.DoClick = function(self) local ent = pmodel_panel.Entity ent:SetSequence(default_seq) pmodel_panel:SetFOV(default_fov) end ft:DockMargin(5, 0, 5, 5) local default_bonecount = 17 local ScrollBar = scroll:GetVBar() ScrollBar.Paint = function(self, w, h) draw.RoundedBox(0,0,0,w,h,fg_color) end ScrollBar.btnUp.Paint = function(self, w, h) draw.RoundedBox(0,0,0,w,h,bg_color) draw.SimpleText("в–ґ", "char_title20r", w/2 - 1, h/2, t_color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end ScrollBar.btnDown.Paint = function(self, w, h) draw.RoundedBox(0,0,0,w,h,bg_color) draw.SimpleText("в–ѕ", "char_title20r", w/2 - 2, h/2, t_color, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end ScrollBar.btnGrip.Paint = function(self, w, h) draw.RoundedBox(0,0,0,w,h,bg_color) end local x, y = modelpanel:GetPos() -- Hold to rotate pmodel_panel.Angles = Angle( 0, 0, 0 ) function pmodel_panel:DragMousePress() self.PressX, self.PressY = gui.MousePos() self.Pressed = true end function pmodel_panel:OnMouseWheeled(dlta) self:SetFOV( math.Clamp( self:GetFOV() - dlta*5, 40, 100 ) ) return true end function pmodel_panel:DragMouseRelease() self.Pressed = false end if DisplayModelEquips then DisplayModelEquips(pmodel_panel, nil, nil, Local_Character) end local ent = pmodel_panel.Entity local bone = ent:LookupBone("ValveBiped.Bip01_Head1") if bone then pmodel_panel.headpos = ent:GetBonePosition(bone) local off = Vector(0,0,20) pmodel_panel:SetLookAt(pmodel_panel.headpos - off) pmodel_panel:SetCamPos(pmodel_panel.headpos-Vector(-45, 0, -10) -off) end function pmodel_panel:LayoutEntity( ent ) self:RunAnimation() if ( self.Pressed ) then local mx, my = gui.MousePos() self.Angles = self.Angles - Angle( 0, ( ( self.PressX or mx ) - mx ) / 2, 0 ) --local hei = Vector(0, 0, ( self.PressY or my ) - my)/6 --pmodel_panel:SetLookAt(pmodel_panel:GetLookAt()-hei) --pmodel_panel:SetCamPos(pmodel_panel:GetCamPos()-hei) self.PressX, self.PressY = gui.MousePos() end ent:SetAngles( self.Angles ) --floor:SetAngles( self.Angles ) end BodyGrouper:Update() end modelCompare()