--[[ | 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 settings local bg_color = Color(255,255,255) local slider_col = Color(91,156,214) local b_alpha = Color(0,0,0,60) local c_alpha = Color(0,0,0,20) -- Add SF Setting vgui local function empty() end local function wrapText(sText, wide) wide = wide - 10 local tw,th = surface.GetTextSize(language.GetPhrase(sText)) local lines,b = 1, false local tab = {""} for w in string.gmatch(sText, "[^%s,]+") do local tt = tab[#tab] .. (b and " " or "") .. w if surface.GetTextSize(tt) >= wide then table.insert(tab, w) lines = lines + 1 else tab[#tab] = tt end b = true end return tab, lines end local function niceName(sName) sName = string.Replace(sName, "_", " ") local str = "" for s in string.gmatch(sName, "[^%s]+") do str = str .. string.upper(s[1]) .. string.sub(s, 2) .. " " end return string.TrimRight(str, " ") end -- function to overwrite the textentity, and display the current temp setting. local function makeTempDisplay( panel ) panel._DrawTextEntryText = panel.DrawTextEntryText function panel:DrawTextEntryText( ... ) local s = self:GetText() self:SetText(s .. StormFox2.Temperature.GetDisplaySymbol()) self:_DrawTextEntryText( ... ) self:SetText(s) end end -- Functions to convert the temperature to the clients settings local function valToTemp( val ) return StormFox2.Temperature.GetDisplay(val) .. StormFox2.Temperature.GetDisplaySymbol() end local function tempToVal( val ) return StormFox2.Temperature.Convert(StormFox2.Temperature.GetDisplayType(),"celsius",val) end local function PaintOver(self, w, h) --surface.SetDrawColor(color_black) --surface.DrawOutlinedRect(0,0,w,h) if not self.dMark then return end local b = self.dMark - CurTime() if b <= 0 then self.dMark = nil return end local a = math.sin(b * math.pi * 2 ) surface.SetDrawColor(0,0,0, a * 100) surface.DrawRect(0,0,w,h) end local function FindPercent( x, a, b ) return (x - a) / (b - a) end local function FindPercentClam( x, a, b ) return math.Clamp(FindPercent( x, a, b ), 0, 1) end local vgui_Create do local function overrideConVar( PANEL ) function PANEL:SetConVar( sName ) self._sfobj = StormFox2.Setting.GetObject( sName ) end function PANEL:ConVarChanged( strNewValue ) if not self._sfobj then return end self._sfobj:SetFromString( strNewValue ) end -- Todo: Think only every 0.1 seconds? function PANEL:ConVarStringThink() if not self._sfobj then return end if self.m_LV ~= nil and self._sfobj:GetValue() == self.m_LV then return end self.m_LV = self._sfobj:GetValue() self:SetValue( self._sfobj:GetString() ) end function PANEL:ConVarNumberThink() if not self._sfobj then return end if self.m_NV ~= nil and self._sfobj:GetValue() == self.m_NV then return end self.m_NV = self._sfobj:GetValue() self:SetValue( tonumber(num) ) end end local function overrideAll( PANEL ) if not IsValid( PANEL ) then return end if PANEL.ConVarChanged then overrideConVar(PANEL) end for _, v in ipairs( PANEL:GetChildren() ) do overrideAll( v ) end end function vgui_Create( str_type, self ) local PANEL = vgui.Create( str_type, self ) -- Override convar functions overrideAll(PANEL) return PANEL end end -- Title do local PANEL = {} PANEL.PaintOver = PaintOver derma.DefineControl( "SFTitle", "", PANEL, "DLabel" ) end -- Slider do local cir_size = 14 local barSize = 6 local shadowSize = 18 local sh = Material("vgui/slider") local barSpace = 7 local PANEL = {} AccessorFunc(PANEL, "min", "Min") AccessorFunc(PANEL, "max", "Max") AccessorFunc(PANEL, "value", "Value") AccessorFunc(PANEL, "float", "Float") -- Make sure we set a flag, if edited function PANEL:SetMin( v ) self._set = true self.min = v end function PANEL:SetMax( v ) self._set = true self.max = v end function PANEL:Init() self:SetValue( -1 ) self:SetMin(0) self:SetMax(1) self._set = false -- Reset flag self:SetCursor( "hand" ) self._flagOff = false end function PANEL:GetValueFromPercent( p ) local range = self:GetMax() - self:GetMin() return self:GetMin() + range * p end function PANEL:GetPercentFromValue( var ) return FindPercentClam( var, self:GetMin(), self:GetMax() ) end function PANEL:GetPercentFromPoint( xPos ) local bar_width = self:GetWide() - barSpace * 2 local range = self:GetMax() - self:GetMin() return math.Clamp((xPos - barSpace) / bar_width, 0, 1) end function PANEL:GetPointFromPercent( p ) local bar_width = self:GetWide() - barSpace * 2 return barSpace + bar_width * p end local m_cir = Material("vgui/circle") -- Tells the slider that -1, is used to indecate it can be turned off function PANEL:SetFlagOff( bool ) self._flagOff = bool self:SetMin(0) end function PANEL:SetSetting( sName, sType, Description ) self._sfobj = StormFox2.Setting.GetObject( sName ) if not self._sfobj then return end -- If we haven't edited the min / max, then use the convars setting. If not then make a range. local min = self._set and self:GetMin() or self._sfobj:GetMin() or 0 local max = self._set and self:GetMax() or self._sfobj:GetMax() or self._sfobj:GetDefault() or 1 if self._flagOff then self:SetMin(0) else self:SetMin(min) end self:SetMax(max) local target = math.Clamp(self._sfobj:GetValue(), min, max) self:SetValue(target) end function PANEL:Think() if not self._sfobj then return end local range = self:GetMax() - self:GetMin() local target = self._sfobj:GetValue() if self._flagOff and target <= 0 then target = 0 end local delta = math.abs(self:GetValue() - target) self:SetValue( math.Approach(self:GetValue(), target, FrameTime() * math.max(range * 0.1, delta * 10)) ) end function PANEL:OnMousePressed( keyCode ) if keyCode ~= MOUSE_LEFT then return end self._down = true self:MouseCapture( true ) end function PANEL:OnMouseReleased( keyCode ) if keyCode == MOUSE_RIGHT then local menu = DermaMenu(false, self) menu:AddOption( "Reset", function() self._sfobj:Revert() end):SetIcon( "icon16/package.png" ) menu:Open() return true elseif keyCode == MOUSE_LEFT then if not self._down then return end self._down = false self:MouseCapture( false ) if not self._sfobj then return end local val = self:GetValueFromPercent(self:GetPercentFromPoint( self:CursorPos() )) if not self:GetFloat() then val = math.Round(val, 0) else val = math.Round(val, 3) end self._sfobj:SetValue(val) self:SetValue(val) end end function PANEL:Paint(w, h) local bar_width = w - barSpace * 2 local bar_y = math.Round(h / 2) local val local min, max = self:GetMin(), self:GetMax() if self._flagOff and self:GetValue() < 0 then val = 0 elseif self._down then val = self:GetValueFromPercent(self:GetPercentFromPoint( self:CursorPos() )) if not self:GetFloat() then self._downvalue = math.Clamp(math.Round(val), min, max) else self._downvalue = math.Clamp(math.Round(val,3), min, max) end elseif self:GetValue() < 0 and false then -- Unset local p = ((math.sin(SysTime() * 3) + 1) / 2) val = min + p * max else val = self:GetValue() end local percentage = FindPercentClam( val , self:GetMin() or 0, max or 1 ) if percentage < 1 then draw.RoundedBox(30, barSpace, bar_y - barSize / 2, bar_width ,barSize, b_alpha) end if percentage > 0 then draw.RoundedBox(30, barSpace, bar_y - barSize / 2, bar_width * percentage, barSize, slider_col) end local cir_x = self:GetPointFromPercent( percentage ) surface.SetMaterial(sh) surface.SetDrawColor(c_alpha) surface.DrawTexturedRectRotated(cir_x, bar_y, shadowSize, shadowSize,0) surface.DrawTexturedRectRotated(cir_x, bar_y, shadowSize + 2, shadowSize + 2,0) surface.SetMaterial(m_cir) if self._down then surface.SetDrawColor(slider_col) else surface.SetDrawColor(bg_color) end surface.DrawTexturedRectRotated(cir_x, bar_y, cir_size, cir_size,0) end derma.DefineControl( "SF_Slider", "", PANEL, "DPanel" ) -- DoubleSlider local PANEL = {} AccessorFunc(PANEL, "min", "Min") AccessorFunc(PANEL, "max", "Max") AccessorFunc(PANEL, "value", "MinValue") AccessorFunc(PANEL, "value2", "MaxValue") AccessorFunc(PANEL, "float", "Float") function PANEL:Init() self:SetMinValue( 0 ) self:SetMaxValue( 0 ) self:SetMin(0) self:SetMax(1) self:SetCursor( "hand" ) end local m_cir = Material("vgui/circle") function PANEL:SetSettingMin( sName, sType, Description ) self._sfobj = StormFox2.Setting.GetObject( sName ) if not self._sfobj then return end local min = self._sfobj:GetMin() or self:GetMin() or 0 self:SetMin(min) self:SetMax(math.max(min, self:GetMax() or 1)) end function PANEL:SetSettingMax( sName, sType, Description ) self._sfobj2 = StormFox2.Setting.GetObject( sName ) if not self._sfobj2 then return end local max = self._sfobj:GetMax() or self:GetMax() or 1 self:SetMax(max) self:SetMin(max, self:GetMax() or 1) end function PANEL:Think() if not self._sfobj then return end if not self._sfobj2 then return end local range = self:GetMax() - self:GetMin() -- Min local delta = math.abs(self:GetMinValue() - self._sfobj:GetValue()) self:SetMinValue( math.Approach(self:GetMinValue(), self._sfobj:GetValue(), FrameTime() * math.max(range * 0.1, delta * 10)) ) -- Max local delta = math.abs(self:GetMaxValue() - self._sfobj2:GetValue()) self:SetMaxValue( math.Approach(self:GetMaxValue(), self._sfobj2:GetValue(), FrameTime() * math.max(range * 0.1, delta * 10)) ) end local cir_size = 14 local barSize = 6 local shadowSize = 18 local sh = Material("vgui/slider") local barSpace = 7 function PANEL:OnMousePressed( keyCode ) if keyCode ~= MOUSE_LEFT then return end -- Select the closest type local cur_p = self:GetPercentFromPoint( self:CursorPos() ) local percentage = FindPercentClam( (self:GetMinValue() + self:GetMaxValue()) / 2 , self:GetMin() or 0, self:GetMax() or 1 ) -- Center if cur_p < percentage then self._down = 1 -- Min else self._down = 2 -- Max end self:MouseCapture( true ) end function PANEL:OnMouseReleased( keyCode ) if keyCode ~= MOUSE_LEFT then return end if not self._down then return end self:MouseCapture( false ) if not self._sfobj then return end local val = self:GetValueFromPercent(self:GetPercentFromPoint( self:CursorPos() )) if not self:GetFloat() then val = math.Round(val, 0) else val = math.Round(val, 3) end if self._down == 0 then self._sfobj:SetValue(val) self:SetMinValue(val) else self._sfobj2:SetValue(val) self:SetMaxValue(val) end self._down = false end function PANEL:Paint(w, h) local bar_width = w - barSpace * 2 local bar_y = math.Round(h / 2) local valMin, valMax = self:GetMinValue(), self:GetMaxValue() if self._down then local val = self:GetValueFromPercent(self:GetPercentFromPoint( self:CursorPos() )) if not self:GetFloat() then self._downvalue = math.Clamp(math.Round(val), self:GetMin(), self:GetMax()) else self._downvalue = math.Clamp(math.Round(val,3), self:GetMin(), self:GetMax()) end if self._down == 1 then valMin = val else valMax = val end end local minP = FindPercentClam( valMin , self:GetMin() or 0, self:GetMax() or 1 ) local maxP = FindPercentClam( valMax , self:GetMin() or 0, self:GetMax() or 1 ) -- BG bar draw.RoundedBox(30, barSpace, bar_y - barSize / 2, bar_width ,barSize, b_alpha) local cir_x = self:GetPointFromPercent( minP ) local cir_x2 = self:GetPointFromPercent( maxP ) draw.RoundedBox(30, cir_x, bar_y - barSize / 2, cir_x2 - cir_x, barSize, slider_col) -- Min surface.SetMaterial(sh) surface.SetDrawColor(c_alpha) surface.DrawTexturedRectRotated(cir_x, bar_y, shadowSize, shadowSize,0) surface.DrawTexturedRectRotated(cir_x, bar_y, shadowSize + 2, shadowSize + 2,0) surface.SetMaterial(m_cir) if self._down then surface.SetDrawColor(slider_col) else surface.SetDrawColor(bg_color) end surface.DrawTexturedRectRotated(cir_x, bar_y, cir_size, cir_size,0) -- Max surface.SetMaterial(sh) surface.SetDrawColor(c_alpha) surface.DrawTexturedRectRotated(cir_x2, bar_y, shadowSize, shadowSize,0) surface.DrawTexturedRectRotated(cir_x2, bar_y, shadowSize + 2, shadowSize + 2,0) surface.SetMaterial(m_cir) if self._down then surface.SetDrawColor(slider_col) else surface.SetDrawColor(bg_color) end surface.DrawTexturedRectRotated(cir_x2, bar_y, cir_size, cir_size,0) end derma.DefineControl( "SF_DoubleSlider", "", PANEL, "SF_Slider" ) end -- Description Box do local lineHeight local function getLineHeight() if lineHeight then return lineHeight end local ws,hs = surface.GetTextSize("ABCDEFGHIJKLMNOPQRSTUVWXYZ") lineHeight = hs return hs end local PANEL = {} function PANEL:Init() self.t_text = {} self.text = "No description" self.font = "DermaDefault" self.strikeout = false end function PANEL:SetFont( str ) self.font = str end function PANEL:SetStrikeOut( b ) self.strikeout = b end function PANEL:SetText( str ) self.text = str surface.SetFont(self.font) local t_text, lines = wrapText(str, self:GetWide()) self:SetTall(lines * getLineHeight()) self.t_text = t_text end function PANEL:PerformLayout(w, h) surface.SetFont(self.font) local t_text, lines = wrapText(self.text, w) self:SetTall(lines * getLineHeight()) self.t_text = t_text end function PANEL:GetTextLines() if not self.t_text then return 1 end return math.max(1, #self.t_text) end function PANEL:Paint(w, h) surface.SetDrawColor(color_white) surface.DrawRect(0,0,w,h) surface.SetFont(self.font) surface.SetTextColor(color_black) local lh = getLineHeight() for y, str in ipairs( self.t_text ) do local z = (y - 1) * lh surface.SetTextPos(0, z ) surface.DrawText( str ) if self.strikeout then surface.SetDrawColor(color_black) local wide = #self.t_text > 1 and w or surface.GetTextSize(str) local c = z + lh / 2 + 1 surface.DrawLine(0, c, wide, c) end end end derma.DefineControl( "SF2_TextBox", "", PANEL, "DPanel" ) end -- Setting Tab do local PANEL = {} PANEL.PaintOver = PaintOver --PANEL.Paint = empty function PANEL:Init() self:DockMargin(5,0,10,0) local label_name = vgui_Create( "DLabel", self ) label_name:SetText("Unknown Setting") label_name:SetColor(color_black) label_name:SetFont("DermaDefaultBold") label_name:SizeToContents() label_name:Dock(TOP) self.label_name = label_name local description = vgui_Create( "SF2_TextBox", self ) description:SetText("No description.") description:SetPos(25, label_name:GetTall() + 2) self.description = description self._SetSetting = self.SetSetting self:DockMargin(15,0,15,5) self._cross = false end function PANEL:SetStrikeOut( b ) self.description:SetStrikeOut( b ) end function PANEL:SetTitle( str ) self.label_name:SetText( language.GetPhrase(str) or str ) end function PANEL:SetDescription( str ) self.description:SetText( language.GetPhrase(str) or str ) end function PANEL:PerformLayout(w, h) local maxH = 0 local x = self.description:GetPos() self.description:SetWide(w - x) for _, v in ipairs( self:GetChildren() ) do local x, y = v:GetPos() maxH = math.max(maxH, y + v:GetTall()) end if h == maxH then return end self:SetTall(maxH + 5) end function PANEL:HideTitle( bool ) if bool == false then self.label_name:Show() for _, v in ipairs( self:GetChildren() ) do local x, y = v:GetPos() v:SetPos(x, y + self.label_name:GetTall()) end else self.label_name:Hide() for _, v in ipairs( self:GetChildren() ) do local x, y = v:GetPos() v:SetPos(x, y - self.label_name:GetTall()) end end self:InvalidateLayout() return self end PANEL.Paint = empty function PANEL:SetSetting( sName, sType, Description ) sType = sType or StormFox2.Setting.GetType( sName ) local obj = StormFox2.Setting.GetObject( sName ) local tName = Description and "#" .. Description or (obj and "sf_" .. obj:GetName()) or "Unknown" self.label_name:SetText( language.GetPhrase(tName) or tName ) self.description:SetText( language.GetPhrase(tName .. ".desc") or "Unknown" ) for _, v in ipairs( self:GetChildren() ) do if not v.SetSetting then continue end v:SetSetting( sName, sType, Description ) end end function PANEL:MoveDescription( x, y ) if y then self.description:SetPos( math.max(25, 10 + x), self.label_name:GetTall() + math.max(2, y) ) else local x2, y2 = self.description:GetPos() self.description:SetPos( math.max(25, 10 + x), y2 ) end end derma.DefineControl( "SF_Setting", "", PANEL, "DPanel" ) end -- Boolean setting do local PANEL = {} function PANEL:Init() self.check = vgui_Create("DCheckBox", self) self.check:SetPos(5,14) function self.check:DoClick() -- If we're a radio-type. Never turn off. if not self._sfobj then return end if self:GetChecked() and self._block then return end self._sfobj:SetValue( not self:GetChecked() ) end function self.check:DragMousePress( keyCode ) if keyCode ~= MOUSE_RIGHT then return end local menu = DermaMenu(false, self) menu:AddOption( "Reset", function() self._sfobj:Revert() end):SetIcon( "icon16/package.png" ) menu:Open() end function self.check:Think() if not self._sfobj then return end self:SetChecked(self._sfobj:GetValue()) end end function PANEL:SetSetting( sName, sType, Description ) self:_SetSetting( sName, sType, Description ) -- Set title and textbox self.check._sfobj = StormFox2.Setting.GetObject(sName) self.check._block = self.check._sfobj:IsRadio() end derma.DefineControl( "SF_Setting_Bool", "", PANEL, "SF_Setting" ) end -- String setting do local PANEL = {} function PANEL:Init() self.text = vgui_Create("DTextEntry", self) self.text:SetPos(5,14) self.text:SetWide(120) self:MoveDescription(120) end function PANEL:SetSetting( sName, sType, Description ) self:_SetSetting( sName, sType, Description ) -- Set title and textbox self.text:SetConVar( sName ) return self end derma.DefineControl( "SF_Setting_String", "", PANEL, "SF_Setting" ) end -- Float setting local barLength = 220 + 50 do local PANEL = {} function PANEL:Init() self.text = vgui_Create("DTextEntry", self) self.text:SetNumeric(true) self.text:SetDrawLanguageID( false ) self.slider = vgui_Create("SF_Slider", self) self.slider:SetPos(5,14) self.slider:SetWide(barLength) self.slider:SetFloat(true) self.text:SetPos(barLength + 8,18) self.text:SetSize(55,18) self:MoveDescription(barLength + 60, 6) self._isTemp = false end function PANEL:SetMin( v ) self.slider:SetMin( v ) return self end function PANEL:SetMax( v ) self.slider:SetMax( v ) return self end function PANEL:SetTemperature(bool) self._isTemp = bool return self end function PANEL:Think() if not self._sfobj then return end if self.slider._down and self.slider._downvalue then local text if self._isTemp then text = self.slider._downvalue and valToTemp(self.slider._downvalue) or "?" else text = self.slider._downvalue end self.text:SetText(text) elseif not self.text:IsEditing() then local text if self._flagoff and self._sfobj:GetValue() <= (self._sfobj:GetMin() or -1) then text = "" elseif self._isTemp then text = valToTemp(self._sfobj:GetValue()) else text = self._sfobj:GetValue() end self.text:SetText(text) end end function PANEL:SetSetting( sName, sType, Description ) local _sfobj = StormFox2.Setting.GetObject( sName ) self._sfobj = _sfobj self:_SetSetting( sName, sType, Description ) -- Set title and textbox --self.text:SetConVar( sName ) function self.text:OnEnter( val ) val = string.match(val, "[%d%.-]+") or val if _sfobj:GetMin() then val = math.max(_sfobj:GetMin(), val) end if _sfobj:GetMax() then val = math.min(_sfobj:GetMax(), val) end _sfobj:SetValue(val) self:SetText(tostring(val)) end return self end derma.DefineControl( "SF_Setting_Float", "", PANEL, "SF_Setting" ) end -- Int setting do local PANEL = {} function PANEL:Init() self.text = vgui_Create("DTextEntry", self) self.text:SetNumeric(true) self.text:SetDrawLanguageID( false ) self.slider = vgui_Create("SF_Slider", self) self.slider:SetPos(5,14) self.slider:SetWide(barLength) self.text:SetPos(barLength + 8,18) self.text:SetSize(55,18) self:MoveDescription(barLength + 60, 6) self._isTemp = false end function PANEL:SetMin( v ) self.slider:SetMin( v ) return self end function PANEL:SetMax( v ) self.slider:SetMax( v ) return self end function PANEL:SetTemperature(bool) self._isTemp = bool return self end function PANEL:Think() if not self._sfobj then return end if self.slider._down and self.slider._downvalue then local text if self._isTemp then text = self.slider._downvalue and valToTemp(self.slider._downvalue) or "?" else text = self.slider._downvalue end self.text:SetText(text) elseif not self.text:IsEditing() then local text if self._isTemp then text = valToTemp(self._sfobj:GetValue()) else text = self._sfobj:GetValue() end self.text:SetText(text) end end function PANEL:SetSetting( sName, sType, Description ) local _sfobj = StormFox2.Setting.GetObject( sName ) self._sfobj = _sfobj self:_SetSetting( sName, sType, Description ) -- Set title and textbox --self.text:SetConVar( sName ) function self.text:OnEnter( val ) val = string.match(val, "[%d%.-]+") or val local clamp = tonumber( val ) or 0 if _sfobj:GetMax() then clamp = math.min(clamp, _sfobj:GetMax()) end if _sfobj:GetMin() then clamp = math.max(clamp, _sfobj:GetMin()) end _sfobj:SetValue(clamp) self:SetText(tostring(clamp)) end return self end derma.DefineControl( "SF_Setting_Int", "", PANEL, "SF_Setting" ) end -- Table / Enums do local sortNum = function(a,b) if type(a) == "boolean" then return a or b end return a>b end local sortStr = function(a,b) return a 0 or self:IsHovered() then return end surface.SetMaterial(mat) surface.SetDrawColor(color_white) surface.DrawTexturedRect(w / 2 - 8, h / 2 - 8, 16, 16) end function self.check:DoClick() -- If we're a radio-type. Never turn off. if self:GetChecked() and self._block then return end self:Toggle() end self:MoveDescription(barLength + 60, 6) end function PANEL:SetMin( v ) self.slider:SetMin( v ) return self end function PANEL:SetMax( v ) self.slider:SetMax( v ) return self end function PANEL:Think() if not self._sfobj then return end OldPanel["Think"](self) local min = self._sfobj:GetMin() or -1 self.check:SetChecked(self._sfobj:GetValue() > min) end function PANEL:SetDefaultEnable( var ) self.defaultEnable = var end function PANEL:SetSetting( sName, sType, Description ) self:_SetSetting( sName, sType, Description ) -- Set title and textbox local _sfobj = StormFox2.Setting.GetObject( sName ) self._sfobj = _sfobj --self.text:SetConVar( sName ) self.check._block = _sfobj:IsRadio() function self.text:OnEnter( val ) val = tonumber( string.match(val, "[%d%.-]+") or val ) or 0 if _sfobj:GetMin() then val = math.max(_sfobj:GetMin(), val) end if _sfobj:GetMax() then val = math.min(_sfobj:GetMax(), val) end _sfobj:SetValue(val) self:SetText(tostring(val)) end local mainPanel = self function self.check:DoClick() local min = _sfobj:GetMin() or -1 local b = _sfobj:GetValue() > 0 if b then _sfobj:SetValue(min) else local n = math.max(mainPanel.defaultEnable or _sfobj:GetDefault(), 1) _sfobj:SetValue(n) end end return self end derma.DefineControl( "SF_Setting_FloatSpecial", "", PANEL, "SF_Setting_Float" ) end -- Time Object local PANEL = {} local function OnMousePressed( self, mcode ) if ( mcode == MOUSE_LEFT ) then self:OnGetFocus() else local menu = DermaMenu(false, self.base) local obj = StormFox2.Setting.GetObject("12h_display") local text = (obj:GetValue() and "24-" or "12-") .. language.GetPhrase("clock") menu:AddOption( text, function() obj:SetValue( not obj:GetValue()) end):SetIcon( "icon16/clock.png" ) return true end end local function NewPaint(self, w, h, off) surface.SetFont("SF2_TimeSet") local tex = (self:GetValue() or "") local tw,th = surface.GetTextSize(tex) surface.SetTextColor(self.color or color_black) surface.SetTextPos(w / 2 - tw / 2,h / 2 - th / 2) if self:HasFocus() then local e = (math.Round(SysTime() % 1) == 1 and "_" or "") surface.DrawText( tex .. e ) else surface.DrawText( tex ) end end function PANEL:BGThink() if self.lastDisplay ~= cDis then self:InvalidateLayout() self.lastDisplay = cDis end local _12 = StormFox2.Setting.Get("12h_display") if not self.hour:IsEditing() and not self.hour._SETONLOST then local h = StormFox2.Time.GetHours( self.value, _12 ) if h < 10 then h = "0" .. h end self.hour:SetText(h) end if not self.min:IsEditing() then local m = StormFox2.Time.GetMinutes( self.value ) if m < 10 then m = "0" .. m end self.min:SetText(m) end if _12 then self.ampm:SetText( StormFox2.Time.GetAMPM() ) end end function PANEL:Init() self.bg = vgui_Create("DPanel",self) function self.bg:IsSelected() return false end function self.bg:GetToggle() return false end local hour = vgui.Create("DTextEntry", self.bg) self.hour = hour local min = vgui.Create("DTextEntry", self.bg) self.min = min self.ampm = vgui.Create("DButton", self) function self.bg:Paint( w, h ) local cDis = StormFox2.Setting.Get("12h_display") self.Hovered = hour.Hovered or min.Hovered self.Depressed= hour:IsEditing() or min:IsEditing() derma.SkinHook( "Paint", "Button", self, w, h ) surface.SetFont("SF2_TimeSet") local tw,th = surface.GetTextSize(":") surface.SetTextColor(self.color or color_black) surface.SetTextPos(w / 2 - tw / 2,h / 2 - th / 2 - 2) surface.DrawText(":") end function self.bg:IsHovered() return hour:IsHovered() or min:IsHovered() end function self.bg:IsDown() return hour:IsEditing() or min:IsEditing() end function self.hour.OnGetFocus(self) local tex = self._SETONFOC or "" self:SetValue(tex) self:SetCaretPos(#tex) self._SETONFOC = nil end self.min.OnGetFocus = self.hour.OnGetFocus function self.min:OnLoseFocus() if hour._SETONLOST then -- hour got unset variables self.base:_SetNewVar( ) hour._SETONLOST = nil end end self.bg:SetPos( 2,0 ) self.hour:SetPos(0,0) self.hour:SetWide(30) self.hour:SetTall(30) self.hour.Paint = NewPaint self.hour.OnMousePressed = OnMousePressed self.hour.base = self self.min:SetPos(32,0) self.min:SetWide(30) self.min:SetTall(30) self.min.Paint = NewPaint self.min.OnMousePressed = OnMousePressed self.min.base = self self.ampm:SetPos(66 + 2,0) self.ampm:SetWide(34) self.ampm:SetTall(30) self.ampm:SetFont("SF2_TimeSetAM") self.ampm.base = self if not StormFox2.Setting.Get("12h_display") then self.ampm:Hide() self.lastDisplay = false else self.lastDisplay = true self.ampm:SetText("AM") end self.hour:SetDrawLanguageID( false ) self.min:SetDrawLanguageID( false ) self.hour:SetNumeric(true) self.min:SetNumeric(true) self:SetValue( 0 ) self:SetTall( 30 ) -- Logic function self.hour:OnChange( str ) if #self:GetValue() <= 2 then return end self._SETONLOST = self:GetValue():sub(0,2) min._SETONFOC = self:GetValue():sub(3) self:KillFocus() min:RequestFocus() self:SetText(self._SETONLOST ) end function self.hour:OnEnter() self.base:_SetNewVar() end self.min.OnEnter = self.hour.OnEnter function self.ampm:DoClick() self:SetText( self:GetText() == "AM" and "PM" or "AM") self.base:_SetNewVar() end end function PANEL:SetValue( num ) self.value = num end function PANEL:GetValue() return self.value end function PANEL:_SetNewVar() local str = self.hour:GetText() .. ":" .. self.min:GetText() if StormFox2.Setting.Get("12h_display") then str = str .. " " .. self.ampm:GetText() end self.value = StormFox2.Time.StringToTime( str ) self:OnNewValue( self.value ) end PANEL.OnNewValue = function() end PANEL.Paint = PANEL.BGThink function PANEL:PerformLayout(pw, ph) local w = (pw - 8) / 2 if StormFox2.Setting.Get("12h_display") then w = (pw - 8) / 3 self.ampm:Show( ) else self.ampm:Hide( true ) end self.hour:SetWide(w) self.min:SetWide(w) self.ampm:SetWide(w) self.bg:SetWide(w * 2) self.bg:SetHeight( ph ) --self.hour:SetPos(0,0) self.min:SetPos(w, 0) self.ampm:SetPos(w * 2 + 6, 0) self.hour:SetHeight( ph ) self.min:SetHeight( ph ) self.ampm:SetHeight( ph ) end derma.DefineControl( "SF_TIME", "", PANEL, "DPanel" ) -- Time do local PANEL = {} surface.CreateFont("SF2_TimeSet", { font = "Arial", -- Use the font-name which is shown to you by your operating system Font Viewer, not the file name extended = false, size = 26, weight = 50, blursize = 0, scanlines = 0, antialias = true, underline = false, italic = false, strikeout = false, symbol = false, rotary = false, shadow = false, additive = false, outline = false, } ) surface.CreateFont("SF2_TimeSetAM", { font = "Arial", -- Use the font-name which is shown to you by your operating system Font Viewer, not the file name extended = false, size = 22, weight = 50, blursize = 0, scanlines = 0, antialias = true, underline = false, italic = false, strikeout = false, symbol = false, rotary = false, shadow = false, additive = false, outline = false, } ) local function NewPaint(self, w, h, off) surface.SetFont("SF2_TimeSet") local tw,th = surface.GetTextSize("ABCDEFGHIJ") surface.SetTextColor(color_black) surface.SetTextPos(2,h / 2 - th / 2) local tex = (self:GetValue() or "") local e = (math.Round(SysTime() % 1) == 1 and "_" or "") if self:HasFocus() and #tex < 2 then surface.DrawText( tex .. e ) else surface.DrawText( tex ) end if self:HasFocus() and #tex == 2 then local tw = surface.GetTextSize(tex:sub(0,1)) surface.SetTextPos(2 + tw,h / 2 - th / 2) surface.DrawText( e ) end end local function OnMousePressed( self, mcode ) if ( mcode == MOUSE_LEFT ) then self:OnGetFocus() else local menu = DermaMenu(false, self) local obj = StormFox2.Setting.GetObject("12h_display") local text = (obj:GetValue() and "24-" or "12-") .. language.GetPhrase("clock") menu:AddOption( text, function() obj:SetValue( not obj:GetValue()) end):SetIcon( "icon16/clock.png" ) menu:AddOption( "Reset", function() self._sfobj:Revert() end):SetIcon( "icon16/package.png" ) menu:Open() return true end end function PANEL:Init() local b = vgui_Create("DPanel", self) -- All options b.Paint = empty local bg = vgui_Create("DPanel", b) -- Background self.hour = vgui.Create("DTextEntry", b) self.min = vgui.Create("DTextEntry", b) self.ampm = vgui.Create("DButton", b) self.bg = bg self.b = b self.bar_ex = 0 b:SetPos(6,14) b:SetSize(66 + 34 + 2, 30) bg:SetSize(66, 30) function bg:IsSelected() return false end function bg:GetToggle() return false end function bg:IsDown() return hour:IsEditing() or min:IsEditing() end local hour, min = self.hour, self.min do function bg:Paint( w, h ) self.Hovered = hour.Hovered or min.Hovered self.Depressed= hour:IsEditing() or min:IsEditing() derma.SkinHook( "Paint", "Button", self, w, h ) surface.SetFont("SF2_TimeSet") local tw,th = surface.GetTextSize(":") surface.SetTextColor(color_black) surface.SetTextPos(w / 2 - tw / 2,h / 2 - th / 2 - 2) surface.DrawText(":") end end self.hour:SetPos(2,0) self.hour:SetWide(30) self.hour:SetTall(30) self.min:SetPos(34,0) self.min:SetWide(30) self.min:SetTall(30) self.ampm:SetPos(66 + 2,0) self.ampm:SetWide(34) self.ampm:SetTall(30) self.ampm:SetFont("SF2_TimeSetAM") function self.ampm:UpdateColours( skin ) if ( !self:IsEnabled() ) then return self:SetTextStyleColor( skin.Colours.Button.Disabled ) end if ( self:IsDown() || self.m_bSelected ) then return self:SetTextStyleColor( skin.Colours.Button.Down ) end if ( self.Hovered ) then return self:SetTextStyleColor( skin.Colours.Button.Hover ) end return self:SetTextStyleColor( color_black ) end self.hour:SetNumeric(true) self.hour:SetDrawLanguageID( false ) self.hour.Paint = NewPaint self.hour:SetText("00") local panel = self function self.hour.OnGetFocus(self) self:SetValue("") end function self.hour:OnEnter() local num = tonumber( self:GetValue() or "" ) or 0 local lim = StormFox2.Setting.Get("12h_display") and 12 or 24 num = math.Clamp(num, 0, lim) if num < 10 then self:SetText("0" .. num) else self:SetText(num) end panel:OnNewValue() end function self.hour:OnChange() if string.find(self:GetValue(), "-") then self:SetText(string.Replace(self:GetValue(), "-", "")) end if #self:GetValue() >= 3 then -- Can't enter more numbers self:FocusPrevious() self:OnEnter() elseif #self:GetValue() == 2 then --self:OnEnter() self:KillFocus() min:RequestFocus() min._setonlosefocus = true end end function self.hour.OnLoseFocus( self ) if #self:GetText() < 2 then return end -- We lost focus and the player has entered two numbers in. Should be set. Not everyone hits enter self:OnEnter() end self.min:SetNumeric(true) self.min:SetDrawLanguageID( false ) self.min.Paint = NewPaint self.min:SetText("00") function self.min.OnGetFocus(self) self._oldVar = self:GetValue() self:SetValue("") end function self.min:OnEnter() -- Hour value has changed, and this is empty. We then use the last value instead. if #self:GetText() < 1 and self._setonlosefocus and self._oldVar then self:SetValue( self._oldVar ) end self._setonlosefocus = nil local num = tonumber( self:GetValue() or "" ) or 0 num = math.Clamp(num, 0, 59) if num < 10 then self:SetText("0" .. num) else self:SetText(num) end panel:OnNewValue( num ) end function self.min:OnChange() if string.find(self:GetValue(), "-") then self:SetText(string.Replace(self:GetValue(), "-", "")) end if #self:GetValue() >= 2 then -- Can't enter more numbers self:FocusPrevious() self:OnEnter() end end function self.min.OnLoseFocus( self ) -- We lost focus and the player has entered two numbers in. Should be set if #self:GetText() < 2 and not (self._oldVar and self._setonlosefocus) then return end -- We have a set-on-leave flag if self._setonlosefocus and self._oldVar then self:SetValue(self._oldVar) end self._setonlosefocus = nil self:OnEnter() end function self.ampm:DoClick() if self:GetText() == "AM" then self:SetText("PM") else self:SetText("AM") end panel:OnNewValue() end hour.OnMousePressed = OnMousePressed min.OnMousePressed = OnMousePressed self:MoveDescription(105 + self.bar_ex,4) end function PANEL:OnNewValue() local str = tonumber(self.hour:GetText()) .. ":" .. tonumber(self.min:GetText()) if StormFox2.Setting.Get("12h_display") then str = str .. self.ampm:GetText() end self._sfobj:SetValue( StormFox2.Time.StringToTime(str) ) end function PANEL:Think() var = var or 0 if not self._sfobj then return end local _12 = StormFox2.Setting.Get("12h_display") local var = self._sfobj:GetValue() if var < 0 then self.b:SetDisabled( true ) self.hour:SetText("00") self.min:SetText("00") self.ampm:SetText("AM") if _12 then self.ampm:SetText(StormFox2.Time.GetAMPM( self._sfobj:GetValue() )) if not self.ampm:IsVisible() then self.ampm:Show() self:MoveDescription(105 + self.bar_ex,4) end else if self.ampm:IsVisible() then self.ampm:Hide() self:MoveDescription(70 + self.bar_ex,4) end end else self.b:SetDisabled( false ) if not self.hour:IsEditing() then local h = StormFox2.Time.GetHours( self._sfobj:GetValue(), _12 ) if h < 10 then h = "0" .. h end self.hour:SetText(h) end if not self.min:IsEditing() then local h = StormFox2.Time.GetMinutes( self._sfobj:GetValue(), _12 ) if h < 10 then h = "0" .. h end self.min:SetText(h) end if _12 then self.ampm:SetText(StormFox2.Time.GetAMPM( self._sfobj:GetValue() )) if not self.ampm:IsVisible() then self.ampm:Show() self:MoveDescription(105 + self.bar_ex,4) end else if self.ampm:IsVisible() then self.ampm:Hide() self:MoveDescription(70 + self.bar_ex,4) end end end end function PANEL:SetSetting( sName, sType, Description ) self:_SetSetting( sName, sType, Description ) -- Set title and textbox self._sfobj = StormFox2.Setting.GetObject( sName ) self.min._sfobj = self._sfobj self.hour._sfobj = self._sfobj --self.check:SetConVar( sName ) return self end derma.DefineControl( "SF_Setting_Time", "", PANEL, "SF_Setting" ) end -- Time Toggle do local OldPanel = vgui.GetControlTable("SF_Setting_Time") local PANEL = {} function PANEL:Init() self.check = vgui_Create("DCheckBox", self) self.check:SetPos(5,20) self.b:SetPos(24,14) self:MoveDescription(105 + 18,4) self.bar_ex = 18 end function PANEL:Think() OldPanel.Think(self) if not self._sfobj then return end local b = self._sfobj:GetValue() >= 0 self.check:SetChecked(b) end function PANEL:SetSetting( sName, sType, Description ) OldPanel.SetSetting( self, sName, sType, Description ) local _sfobj = StormFox2.Setting.GetObject( sName ) self.check._block = _sfobj:IsRadio() function self.check:DoClick() if self:GetChecked() and self._block then return end local b = _sfobj:GetValue() > 0 if b then _sfobj:SetValue(-1) else local default = _sfobj:GetDefault() if default < 0 then default = 720 end _sfobj:SetValue(default) end end return self end derma.DefineControl( "SF_Setting_TimeToggle", "", PANEL, "SF_Setting_Time" ) end -- DoubleInt setting do local PANEL = {} function PANEL:Init() self.text = vgui_Create("DTextEntry", self) self.text:SetNumeric(true) self.text:SetDrawLanguageID( false ) self.slider = vgui_Create("SF_DoubleSlider", self) self.slider:SetPos(5,14) self.slider:SetWide(barLength) self.text:SetPos(barLength + 8,18) self.text:SetSize(55,18) self:MoveDescription(barLength + 60, 6) self._isTemp = false end function PANEL:SetTemperature(bool) self._isTemp = bool end function PANEL:Think() if not self._sfobj then return end if self.slider._down and self.slider._downvalue then local text if self._isTemp then text = self.slider._downvalue and valToTemp(self.slider._downvalue) or "?" else text = self.slider._downvalue end self.text:SetText(text) elseif not self.text:IsEditing() then local text if self._isTemp then text = valToTemp(self._sfobj:GetValue()) else text = self._sfobj:GetValue() end self.text:SetText(text) end end function PANEL:SetSettingMin( sName, sType, Description ) local _sfobj = StormFox2.Setting.GetObject( sName ) self._sfobj = _sfobj self:_SetSetting( sName, sType, Description ) -- Set title and textbox self.slider:SetSettingMin( sName, sType, Description ) --self.text:SetConVar( sName ) function self.text:OnEnter( val ) val = string.match(val, "[%d%.]+") or val local clamp = math.Clamp(tonumber( val ), _sfobj:GetMin(), _sfobj:GetMax()) _sfobj:SetValue(clamp) self:SetText(tostring(clamp)) end end function PANEL:SetSettingMax( sName, sType, Description ) local _sfobj2 = StormFox2.Setting.GetObject( sName ) self._sfobj2 = _sfobj self:_SetSetting( sName, sType, Description ) -- Set title and textbox self.slider:SetSettingMax( sName, sType, Description ) --self.text:SetConVar( sName ) end function PANEL:SetMin( var ) self.slider:SetMin( var ) end function PANEL:SetMax( var ) self.slider:SetMax( var ) end derma.DefineControl( "SF_Setting_Double", "", PANEL, "SF_Setting" ) end -- Hud Ring do local PANEL = {} local m_ring = Material("stormfox2/hud/hudring.png") local cCol1 = Color(55,55,55,55) local cCol2 = Color(55,55,255,105) local seg = 40 function PANEL:SetColor(r,g,b,a) self.cCol2 = (r and g and b) and Color(r,g,b,a or 105) or r return self end function PANEL:Init() self._val = 1 self._off = 0.05 self.cCol1 = cCol1 self.cCol2 = cCol2 end function PANEL:SetValue(nNum) self._val = math.Clamp(nNum, 0, 1) self:RebuildPoly() return self end function PANEL:SetText(sText) self._text = sText return self end function PANEL:RebuildPoly() local pw, ph = self:GetWide(), self:GetTall() local x,y = pw / 2, ph / 2 local polyMul = 1.2 local radius = math.min(pw, ph) / 2 * polyMul local mul2 = 2 / polyMul -- Generate poly self._poly = {} local seg = 40 table.insert( self._poly, { x = x, y = y, u = 0.5, v = 0.5 } ) local n = self._val * seg for i = 0, n do local a = math.rad( ( i / seg ) * -360 ) table.insert( self._poly, { x = x + math.sin( a ) * radius, y = y + math.cos( a ) * radius, u = math.sin( a ) / mul2 + 0.5, v = math.cos( a ) / mul2 + 0.5 } ) end local a = math.rad( ( n / seg ) * -360 ) table.insert( self._poly, { x = x + math.sin( a ) * radius, y = y + math.cos( a ) * radius, u = math.sin( a ) / mul2 + 0.5, v = math.cos( a ) / mul2 + 0.5 } ) table.insert( self._poly, { x = x, y = y, u = 0.5, v = 0.5 } ) end function PANEL:PerformLayout(pw, ph) self:RebuildPoly() end function PANEL:Paint(w,h) if self._text then local td = string.Explode("\n",self._text) for k,v in ipairs(td) do local n = k - 1 draw.SimpleText(v, "DermaDefault", w / 2, h / 2 + n * 12 - (#td - 1) * 6, color_black, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end else draw.SimpleText(self._val, "DermaDefault", w / 2, h / 2, color_black, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end if not self._poly then return end surface.SetMaterial(m_ring) surface.SetDrawColor(self.cCol1) surface.DrawTexturedRect(self._x or 0,self._y or 0,self._w or w,self._h or h) surface.SetDrawColor(self.cCol2) surface.DrawPoly(self._poly) end derma.DefineControl( "SF_Setting_Ring", "", PANEL, "DPanel" ) end -- Old -- Ring do local PANEL = {} derma.DefineControl( "SF_HudRing", "", PANEL, "DPanel" ) end -- World Display do local PANEL = {} local owm = Material("stormfox2/hud/openweather.png") local PANEL = {} AccessorFunc( PANEL, "m_lat", "Lat" ) AccessorFunc( PANEL, "m_lon", "Lon" ) AccessorFunc( PANEL, "m_zoom","Zoom" ) local w_map = Material("stormfox2/hud/world.png") local c = Color(0,0,0,55) function PANEL:GetUV( lat, lon ) lat = math.Clamp(lat / 90, -1, 1) * 0.5 lon = math.Clamp(lon / 180, -1, 1) * 0.5 return 0.5 + lon, 0.5 - lat end function PANEL:Init() self._map = vgui.Create("DPanel", self) self:SetLat(StormFox2.Setting.Get("openweathermap_lat", 52.6139095)) self:SetLon(StormFox2.Setting.Get("openweathermap_lon", -2.0059601)) self:SetSize(400, 300) self:SetZoom(0) self._range = 1 self._map._s = self function self._map:GetUV( lat, lon ) return self._s:GetUV( lat, lon ) end function self._map:Paint(w,h) if self._s:GetDisabled() then return end surface.SetDrawColor(color_white) surface.SetMaterial( w_map ) surface.DrawTexturedRect(0,0,w,h) local u, v = self:GetUV( self._s:GetLat(), self._s:GetLon()) local ws = math.ceil(w / 360) local hs = math.ceil(h / 180) surface.SetDrawColor(color_black) local xx,yy = u * w - ws / 2, v * h - hs / 2 surface.DrawOutlinedRect(xx,yy, ws, hs) surface.SetDrawColor(c) c.a = 150 + math.sin(SysTime() * 10) * 50 local xT = math.max(1, ws / 4) local yT = math.max(1, hs / 4) -- X surface.DrawRect(0, yy + hs * .5 - xT / 2, xx, yT) surface.DrawRect(xx + ws, yy + hs * .5 - xT / 2, w - xx - ws, yT) --Y surface.DrawRect(xx + ws * 0.5 - yT / 2, 0, xT, yy) surface.DrawRect(xx + ws * 0.5 - yT / 2, yy + hs, xT, h - yy - hs) end self:SetMouseInputEnabled( true ) StormFox2.Setting.Callback("openweathermap_lat",function(vVar,_,_, self) self:SetLat( tonumber(vVar) ) self:ReSize() end,self) StormFox2.Setting.Callback("openweathermap_lon",function(vVar,_,_, self) self:SetLon( tonumber(vVar) ) self:ReSize() end,self) end function PANEL:ReSize() local z = self:GetZoom() * 0.5 local w,h = 1617 * z, 808 * z if w < self:GetWide() or h < self:GetTall() then z = math.max(self:GetWide() / 1617, self:GetTall() / 808) w = 1617 * z h = 808 * z end self._map:SetSize(w, h) local u, v = self:GetUV( self:GetLat(), self:GetLon()) local px,py = -w * u + self:GetWide() / 2, -h * v + self:GetTall() / 2 px = math.Clamp(px, -w, 0) py = math.Clamp(py, -h, 0) self._map:SetPos(px,py) end function PANEL:OnMouseWheeled( sD ) local z = self:GetZoom() + sD / 2 self:SetZoom( math.Clamp(z, 1, 28) ) self:ReSize() return true end function PANEL:PerformLayout() self:ReSize() end local c = Color( 254, 254, 234 ) function PANEL:Paint(w,h) if self:GetDisabled() then return end surface.SetDrawColor(c) surface.DrawRect(0,0,w,h) local x, y = self._map:GetPos() local ws, hs = self._map:GetSize() surface.SetDrawColor(color_white) surface.SetMaterial( w_map ) if x < 0 then surface.DrawTexturedRect(x + ws,y,ws,hs) else surface.DrawTexturedRect(x - ws,y,ws,hs) end end function PANEL:PaintOver(w,h) surface.SetDrawColor(color_black) surface.SetMaterial(owm) local tw = w / 5 local th = tw * 0.42 surface.DrawTexturedRect(0, h - th, tw, th) end derma.DefineControl( "SF_WorldMap", "", PANEL, "DPanel" ) end -- Day Display do local PANEL = {} derma.DefineControl( "SF_WeatherHour", "", PANEL, "DPanel" ) end -- Weather Display do local PANEL = {} derma.DefineControl( "SF_WeatherMap", "", PANEL, "DPanel" ) end -- Menu do local function empty() end local function switch(sName, tab, buttons, sCookie) sName = string.lower(sName) local pnl for k, v in pairs(tab) do if k == sName then v:Show() pnl = v else v:Hide() end end if not IsValid(pnl) or pnl:GetDisabled() then pnl = tab["start"] sName = "start" if IsValid(pnl) then pnl:Show() end end for k,v in pairs(buttons) do v._selected = k == sName end if sCookie then cookie.Set(sCookie, sName) end return pnl end local function addSetting(sName, pPanel, _type, _desc) local setting if type(_type) == "table" then setting = vgui_Create("SF_Setting_Enum", pPanel) elseif _type == "boolean" or _type == "bool" then setting = vgui_Create("SF_Setting_Bool", pPanel) elseif _type == "float" then setting = vgui_Create("SF_Setting_Float", pPanel) elseif _type == "special_float" then setting = vgui_Create("SF_Setting_FloatSpecial", pPanel) elseif _type == "number" then setting = vgui_Create("SF_Setting_Int", pPanel) elseif _type == "time" then setting = vgui_Create("SF_Setting_Time", pPanel) elseif _type == "string" then setting = vgui_Create("SF_Setting_String", pPanel) elseif _type == "time_toggle" then setting = vgui_Create("SF_Setting_TimeToggle", pPanel) elseif _type == "temp" or _type == "temperature" then setting = vgui_Create("SF_Setting_Float", pPanel) setting:SetTemperature( true ) elseif _type == "double_number" then setting = vgui_Create("SF_DDSliderNum", pPanel) setting:SetSetting(sName[1],sName[2], _type, _desc) return setting else StormFox2.Warning("Unknown Setting Variable: " .. sName .. " [" .. tostring(_type) .. "]") return end if not setting then StormFox2.Warning("Unknown Setting Variable: " .. sName .. " [" .. tostring(_type) .. "]") return end --local setting = _type == "boolean" and vgui_Create("SFConVar_Bool", board) or vgui_Create("SFConVar", board) setting:SetSetting(sName, _type, _desc) return setting end local col = {Color(230,230,230), color_white} local col_dis = Color(0,0,0,55) local col_dis2 = Color(0,0,0,55) local bh_col = Color(55,55,55,55) local sb_col = Color(91,155,213) local icon = Material("icon16/zoom.png") local icon_c = Color(255,255,255,180) local s = 20 local side_button = function(self, w, h) if self:IsHovered() and not self:GetDisabled() then surface.SetDrawColor(bh_col) surface.DrawRect(0,0,w,h) end surface.SetDrawColor(self:GetDisabled() and col_dis or color_black) surface.SetMaterial(self.icon) surface.DrawTexturedRect(24 - s / 2, (h - s) / 2, s,s) local t = self.text or "ERROR" surface.SetFont("DermaDefault") local tw,th = surface.GetTextSize( t ) surface.SetTextColor(self:GetDisabled() and col_dis2 or color_black) surface.SetTextPos(48, h / 2 - th / 2) surface.DrawText(t) if self._selected then surface.SetDrawColor(sb_col) surface.DrawRect(4,4,4,h - 8) end end local t_mat = "icon16/font.png" local s_mat = "icon16/cog.png" local s = 60 local n_vc = Color(55,255,55) local n_bm = Material("vgui/notices/undo") local PANEL = {} function PANEL:Init() -- BG self:SetTitle("") function self:SetTitle( str ) self._title = str end self:SetSize(64 * 11, 500) self:Center() self:DockPadding(0,24,0,0) function self:Paint(w, h) surface.SetDrawColor( col[2] ) surface.DrawRect(0,0,w,h) surface.SetDrawColor( col[1] ) if self.p_left then surface.DrawRect(0,0,self.p_left:GetWide(),24) else surface.DrawRect(0,0,w,24) end surface.SetDrawColor(55,55,55,255) surface.DrawRect(0, 0, w, 24) local t = self._title or "Window" surface.SetFont("DermaDefault") local tw,th = surface.GetTextSize( t ) surface.SetTextColor(color_white) surface.SetTextPos(5, 12 - th / 2) surface.DrawText(t) end -- Left panel local p_left = vgui_Create("DPanel", self) self.p_left = p_left p_left:SetWide(180) p_left:Dock( LEFT ) p_left:DockPadding(0,0,0,0) function p_left:Paint(w, h) surface.SetDrawColor( col[1] ) surface.DrawRect(0,0,w,h) end -- Right panel local p_right = vgui_Create("DPanel", self) self.p_right = p_right p_right:Dock( FILL ) p_right.Paint = empty p_right.sub = {} end function PANEL:CreateLayout( tabs, setting_list ) local p = self local p_right = self.p_right local p_left = self.p_left p_right.sub = {} for k,v in ipairs( tabs ) do local p = vgui_Create("DScrollPanel", self.p_right) p:Dock(FILL) self.p_right.sub[string.lower(v[1])] = p p:Hide() end p_right.sub["start"]._isstart = true p_left.buttons = {} -- Add Start local b = vgui_Create("DButton", p_left) b:Dock(TOP) b:SetTall(40) b:SetText("") b.icon = tabs[1][3] b.text = niceName( language.GetPhrase(tabs[1][2]) ) b.Paint = side_button p_left.buttons["start"] = b function b:DoClick() switch("start", p_right.sub, p_left.buttons, p._cookie) end -- Add search bar local sp = vgui_Create("DPanel", p_left) p_left.sp = sp local search_tab = {} sp:Dock(TOP) sp:SetTall(40) function sp:Paint() end sp.searchbar = vgui_Create("DTextEntry",sp) sp.searchbar:SetText("") sp.searchbar:Dock(TOP) sp.searchbar:SetHeight(20) sp.searchbar:DockMargin(4,10,4,0) function sp.searchbar:OptionSelected( sName, page, vguiObj ) local board = switch(page, p_right.sub, p_left.buttons, p._cookie) if vguiObj then vguiObj.dMark = 2 + CurTime() if board then board:ScrollToChild(vguiObj) end timer.Simple(1, function() vguiObj:RequestFocus() end ) end self:SetText("") self:KillFocus() end function sp.searchbar:OnChange( ) local val = self:GetText() local tab = {} if self.result and IsValid(self.result) then self.result:Remove() end local OnlyTitles = val == "" self.result = vgui_Create("DMenu") function self.result:OptionSelected( pnl, text ) if not search_tab[pnl.sName] then return end sp.searchbar:OptionSelected( text, search_tab[pnl.sName][1], search_tab[pnl.sName][2] ) end for sName, v in pairs( search_tab ) do local phrase = language.GetPhrase( sName ) if string.find(string.lower(phrase),string.lower(val), nil, true) then if OnlyTitles and v[3]~=t_mat then continue end table.insert(tab, {sName, v[1], v[2]}) local op = self.result:AddOption( phrase ) if v[3] then op:SetIcon(v[3]) end op.sName = sName end end local x,y = self:LocalToScreen(0,0) self.result:Open(x, y + self:GetTall()) end function sp.searchbar:OnGetFocus() self:OnChange( ) end function sp.searchbar:OnLoseFocus() if not self.result then return end self.result:Remove() self.result = nil end function sp.searchbar:Paint(w,h) surface.SetDrawColor(color_white) surface.DrawRect(0,0,w,h) surface.SetDrawColor(color_black) surface.DrawOutlinedRect(0,0,w,h) local text = self:GetText() if self:IsEditing() then if math.Round(SysTime() * 2) % 2 == 0 then text = text .. "|" end elseif #text < 1 then text = "#searchbar_placeholer" end surface.SetMaterial(icon) surface.SetDrawColor(icon_c) local s = 4 surface.DrawTexturedRect(w - h + s / 2, s / 2, h - s, h - s) draw.DrawText(text, "DermaDefault", 5, 2, color_black, TEXT_ALIGN_BOTTOM) end for i = 2, #tabs do v = tabs[i] local b = vgui_Create("DButton", p_left) b:Dock(TOP) b:SetTall(40) b:SetText("") b.icon = v[3] b.text = niceName( language.GetPhrase(tabs[i][2]) ) b.sTab = v[1] b.Paint = side_button p_left.buttons[string.lower(tabs[i][1])] = b function b:DoClick() switch(self.sTab, p_right.sub,p_left.buttons, p._cookie) end end -- Move changelog down if p_left.buttons["changelog"] then p_left.buttons["changelog"]:Dock(BOTTOM) p_left.buttons["changelog"]:SetZPos(1) end -- Add workshop button local b = vgui_Create("DButton", p_left) b:Dock(BOTTOM) b:SetTall(40) b:SetText("") b.icon = tabs[1][3] b.text = "Workshop" b.Paint = side_button b.r = 180 if StormFox2.NewVersion() then function b:PaintOver(w,h) surface.SetDrawColor(color_white) surface.SetMaterial(n_bm) if self:IsHovered() then local dif = math.abs(math.AngleDifference(self.r, 0)) + 5 self.r = (self.r + math.max(0.01,dif) * FrameTime() * 5) % 360 else self.r = 180 end surface.DrawTexturedRectRotated(w - 20, h / 2, 20, 20, self.r) --surface.DrawRect( - w,0,w,h - 1) draw.DrawText( StormFox2.NewVersion() , "SF_Menu_H2", w - 34 , h / 2 - 8, color_black, TEXT_ALIGN_RIGHT) end end p_left.buttons["workshop"] = b function b:DoClick() gui.OpenURL( StormFox2.WorkShopURL ) end if not StormFox2.WorkShopURL then b:SetDisabled(true) end do local b = vgui_Create("DButton", p_left) b:Dock(BOTTOM) b:SetTall(40) b:SetText("") b.icon = Material("stormfox2/discord.png") b.text = "Discord" b.Paint = side_button b.r = 180 p_left.buttons["discord"] = b function b:DoClick() gui.OpenURL( "https://discord.gg/mefXXt4u9E" ) end end local used = {} function p:AddSetting( sName, group, _type, sDesc ) if not group then group = select(2, StormFox2.Setting.GetType(sName)) end if not group then group = "misc" elseif not p_right.sub[group] then group = "misc" end local board = p_right.sub[group] return board:AddSetting( sName, _type, sDesc ) end function p:MarkUsed( sName ) used[sName] = true end for sBName, pnl in pairs(p_right.sub) do pnl.sBName = string.lower(sBName) pnl._other = false function pnl:AddSetting( sName, _type, sDesc ) if self._other then self:AddTitle("#other", true) pnl._other = false end local mul = type( sName ) == "table" if not _type then _type = StormFox2.Setting.GetType(mul and sName[1] or sName) end local setting = addSetting(sName, self, _type, sDesc) if not setting then return end if not mul then if not search_tab["sf_" .. sName] or not self._isstart then search_tab["sf_" .. sName] = {self.sBName, setting, s_mat} end used[sName] = true else for k,v in ipairs(sName) do if not search_tab["sf_" .. v] or not self._isstart then search_tab["sf_" .. v] = {self.sBName, setting, s_mat} end used[v] = true end end --local setting = _type == "boolean" and vgui_Create("SFConVar_Bool", board) or vgui_Create("SFConVar", board) setting:Dock(TOP) self:AddItem(setting) return setting end function pnl:AddTitle( sName, bIgnoreSearch ) local dL = vgui_Create("SFTitle", self) local text = niceName( language.GetPhrase(sName) ) dL:SetText( text ) dL:SetDark(true) dL:SetFont("SF_Menu_H2") dL:SizeToContents() dL:Dock(TOP) dL:DockMargin(5,self._title and 20 or 0,0,0) self._title = true self:AddItem(dL) if (not search_tab[text] or not self._isstart) and #sName > 0 and not bIgnoreSearch then search_tab[text] = {self.sBName, dL, t_mat} end return dL end function pnl:MarkUsed( sName ) p:MarkUsed( sName ) end end -- Make the layout for _,v in ipairs(tabs) do if not v[4] then continue end local b = p_right.sub[string.lower(v[1])] if not b then continue end v[4]( b ) end -- Add all other settings for sBName, pnl in pairs(p_right.sub) do pnl._other = true end for _, sName in ipairs( setting_list ) do if used[sName] then continue end p:AddSetting( sName ) end -- If there are empty setting-pages, remove them for sBName, pnl in pairs(p_right.sub) do local n = #pnl:GetChildren()[1]:GetChildren() if n > 0 then continue end local b = self.p_left.buttons[sBName] if IsValid(b) then b:SetDisabled(true) end local p = self.p_right.sub[string.lower(sBName)] if IsValid(p) then p:SetDisabled(true) end end -- Add space at bottom for sBName, pnl in pairs(p_right.sub) do pnl.bottom = pnl:AddTitle("") end end function PANEL:SetCookie( sCookie ) self._cookie = sCookie local selected = cookie.GetString(sCookie, "start") or "start" if not self.p_right.sub[selected] then -- Unknown page, set it to "start" selected = "start" end switch(selected, self.p_right.sub,self.p_left.buttons, sCookie) end function PANEL:Select( str_page ) switch(str_page, self.p_right.sub,self.p_left.buttons, self._cookie) end derma.DefineControl( "SF_Menu", "", PANEL, "DFrame" ) end --StormFox2.Menu.OpenController() -- Test vgui objects if true then return end if SF_MENU_TEST then SF_MENU_TEST:Remove() end SF_MENU_TEST = vgui.Create("DFrame") SF_MENU_TEST:MakePopup() SF_MENU_TEST:SetSize(600,500) SF_MENU_TEST:SetPos(320,ScrH() / 2 - 100) local function Add(_type, _setting) local setting = vgui.Create(_type, SF_MENU_TEST) setting:SetSetting(_setting) setting:SetSize(50,20) setting:Dock(TOP) return setting end Add("SF_Setting_Bool", "footprint_enabled") Add("SF_Setting_String", "footprint_enabled") Add("SF_Setting_Float", "overwrite_extra_darkness") Add("SF_Setting_Int", "window_distance"):SetTemperature(true) Add("SF_Setting_FloatSpecial", "window_distance") Add("SF_Setting_Enum", "12h_display") Add("SF_Setting_Time", "sunrise") Add("SF_Setting_TimeToggle", "sunrise")