945 lines
26 KiB
Lua
945 lines
26 KiB
Lua
// A sound browser for the sound emitter and the expression 2 editor.
|
|
// Made by Grocel.
|
|
|
|
local max_char_count = 200 //File length limit
|
|
local max_char_chat_count = 110 // chat has a ~128 char limit, varies depending on char wide.
|
|
|
|
local Disabled_Gray = Color(140, 140, 140, 255)
|
|
|
|
local SoundBrowserPanel = nil
|
|
local TabFileBrowser = nil
|
|
local TabSoundPropertyList = nil
|
|
local TabFavourites = nil
|
|
local SoundInfoTree = nil
|
|
local SoundInfoTreeRoot = nil
|
|
|
|
local SoundObj = nil
|
|
local SoundObjNoEffect = nil
|
|
|
|
local TranslateCHAN = {
|
|
[CHAN_REPLACE] = "CHAN_REPLACE",
|
|
[CHAN_AUTO] = "CHAN_AUTO",
|
|
[CHAN_WEAPON] = "CHAN_WEAPON",
|
|
[CHAN_VOICE] = "CHAN_VOICE",
|
|
[CHAN_ITEM] = "CHAN_ITEM",
|
|
[CHAN_BODY] = "CHAN_BODY",
|
|
[CHAN_STREAM] = "CHAN_STREAM",
|
|
[CHAN_STATIC] = "CHAN_STATIC",
|
|
[CHAN_VOICE2] = "CHAN_VOICE2",
|
|
[CHAN_VOICE_BASE] = "CHAN_VOICE_BASE",
|
|
[CHAN_USER_BASE] = "CHAN_USER_BASE"
|
|
}
|
|
|
|
// Output the infos about the given sound.
|
|
local function GetFileInfos(strfile)
|
|
if (!isstring(strfile) or strfile == "") then return end
|
|
|
|
local nsize = tonumber(file.Size("sound/" .. strfile, "GAME") or "-1")
|
|
local strformat = string.lower(string.GetExtensionFromFilename(strfile) or "n/a")
|
|
|
|
return nsize, strformat
|
|
end
|
|
|
|
local function FormatSize(nsize)
|
|
if (!nsize) then return end
|
|
|
|
//Negative filessizes aren't Valid.
|
|
if (nsize < 0) then return end
|
|
|
|
return nsize, string.NiceSize(nsize)
|
|
end
|
|
|
|
local function FormatLength(nduration)
|
|
if (!nduration) then return end
|
|
|
|
//Negative durations aren't Valid.
|
|
if (nduration < 0) then return end
|
|
|
|
local nm = math.floor(nduration / 60)
|
|
local ns = math.floor(nduration % 60)
|
|
local nms = (nduration % 1) * 1000
|
|
return nduration, (string.format("%01d", nm)..":"..string.format("%02d", ns).."."..string.format("%03d", nms))
|
|
end
|
|
|
|
local function GetInfoTable(strfile)
|
|
local nsize, strformat, nduration = GetFileInfos(strfile)
|
|
if (!nsize) then return end
|
|
|
|
nduration = SoundDuration(strfile) //Get the duration for the info text only.
|
|
if(nduration) then
|
|
nduration = math.Round(nduration * 1000) / 1000
|
|
end
|
|
local nduration, strduration = FormatLength(nduration, nsize)
|
|
local nsizeB, strsize = FormatSize(nsize)
|
|
|
|
local T = {}
|
|
local tabproperty = sound.GetProperties(strfile)
|
|
|
|
if (tabproperty) then
|
|
T = tabproperty
|
|
else
|
|
T.Path = strfile
|
|
T.Duration = {strduration or "n/a", nduration and nduration.." sec"}
|
|
T.Size = {strsize or "n/a", nsizeB and nsizeB.." Bytes"}
|
|
T.Format = strformat
|
|
end
|
|
|
|
return T, !tabproperty
|
|
end
|
|
|
|
|
|
// Output the infos about the given sound.
|
|
local oldstrfile
|
|
local function GenerateInfoTree(strfile, backnode, count)
|
|
if(oldstrfile == strfile and strfile) then return end
|
|
oldstrfile = strfile
|
|
|
|
local SoundData, IsFile = GetInfoTable(strfile)
|
|
|
|
if (!IsValid(backnode)) then
|
|
if (IsValid(SoundInfoTreeRoot)) then
|
|
SoundInfoTreeRoot:Remove()
|
|
end
|
|
end
|
|
if(!SoundData) then return end
|
|
|
|
local strcount = ""
|
|
if (count) then
|
|
strcount = " ("..count..")"
|
|
end
|
|
|
|
if (IsFile) then
|
|
local index = ""
|
|
local node = nil
|
|
local mainnode = nil
|
|
local subnode = nil
|
|
|
|
if (IsValid(backnode)) then
|
|
mainnode = backnode:AddNode("Sound File"..strcount, "icon16/sound.png")
|
|
else
|
|
mainnode = SoundInfoTree:AddNode("Sound File", "icon16/sound.png")
|
|
SoundInfoTreeRoot = mainnode
|
|
end
|
|
|
|
|
|
do
|
|
index = "Path"
|
|
node = mainnode:AddNode(index, "icon16/sound.png")
|
|
subnode = node:AddNode(SoundData[index], "icon16/page.png")
|
|
subnode.IsSoundNode = true
|
|
subnode.IsDataNode = true
|
|
end
|
|
do
|
|
index = "Duration"
|
|
node = mainnode:AddNode(index, "icon16/time.png")
|
|
for k, v in pairs(SoundData[index]) do
|
|
subnode = node:AddNode(v, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
end
|
|
do
|
|
index = "Size"
|
|
node = mainnode:AddNode(index, "icon16/disk.png")
|
|
for k, v in pairs(SoundData[index]) do
|
|
subnode = node:AddNode(v, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
end
|
|
do
|
|
index = "Format"
|
|
node = mainnode:AddNode(index, "icon16/page_white_key.png")
|
|
subnode = node:AddNode(SoundData[index], "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
else
|
|
local node = nil
|
|
local mainnode = nil
|
|
|
|
if (IsValid(backnode)) then
|
|
mainnode = backnode:AddNode("Sound Property"..strcount, "icon16/table_gear.png")
|
|
else
|
|
mainnode = SoundInfoTree:AddNode("Sound Property", "icon16/table_gear.png")
|
|
SoundInfoTreeRoot = mainnode
|
|
end
|
|
|
|
do
|
|
node = mainnode:AddNode("Name", "icon16/sound.png")
|
|
subnode = node:AddNode(SoundData["name"], "icon16/page.png")
|
|
subnode.IsSoundNode = true
|
|
subnode.IsDataNode = true
|
|
end
|
|
do
|
|
local tabchannel = SoundData["channel"] or 0
|
|
if (istable(tabchannel)) then
|
|
node = mainnode:AddNode("Channel", "icon16/page_white_gear.png")
|
|
for k, v in pairs(tabchannel) do
|
|
subnode = node:AddNode(v, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
subnode = node:AddNode(TranslateCHAN[v] or TranslateCHAN[CHAN_USER_BASE], "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
else
|
|
node = mainnode:AddNode("Channel", "icon16/page_white_gear.png")
|
|
subnode = node:AddNode(tabchannel, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
subnode = node:AddNode(TranslateCHAN[tabchannel] or TranslateCHAN[CHAN_USER_BASE], "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
end
|
|
do
|
|
local tablevel = SoundData["level"] or 0
|
|
if (istable(tablevel)) then
|
|
node = mainnode:AddNode("Level", "icon16/page_white_gear.png")
|
|
for k, v in pairs(tablevel) do
|
|
subnode = node:AddNode(v, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
subnode = node:AddNode(v, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
else
|
|
node = mainnode:AddNode("Level", "icon16/page_white_gear.png")
|
|
subnode = node:AddNode(tablevel, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
end
|
|
do
|
|
local tabpitch = SoundData["volume"] or 0
|
|
if (istable(tabpitch)) then
|
|
node = mainnode:AddNode("Volume", "icon16/page_white_gear.png")
|
|
for k, v in pairs(tabpitch) do
|
|
subnode = node:AddNode(v, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
else
|
|
node = mainnode:AddNode("Volume", "icon16/page_white_gear.png")
|
|
subnode = node:AddNode(tabpitch, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
end
|
|
do
|
|
local tabpitch = SoundData["pitch"] or 0
|
|
if (istable(tabpitch)) then
|
|
node = mainnode:AddNode("Pitch", "icon16/page_white_gear.png")
|
|
for k, v in pairs(tabpitch) do
|
|
subnode = node:AddNode(v, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
else
|
|
node = mainnode:AddNode("Pitch", "icon16/page_white_gear.png")
|
|
subnode = node:AddNode(tabpitch, "icon16/page.png")
|
|
subnode.IsDataNode = true
|
|
end
|
|
end
|
|
do
|
|
local tabsound = SoundData["sound"] or ""
|
|
if (istable(tabsound)) then
|
|
node = mainnode:AddNode("Sounds", "icon16/table_multiple.png")
|
|
else
|
|
node = mainnode:AddNode("Sound", "icon16/table.png")
|
|
end
|
|
|
|
node.SubData = tabsound
|
|
node.BackNode = mainnode
|
|
node.Expander.DoClick = function(self)
|
|
if (!IsValid(SoundInfoTree)) then return end
|
|
if (!IsValid(node)) then return end
|
|
|
|
node:SetExpanded(false)
|
|
SoundInfoTree:SetSelectedItem(node)
|
|
end
|
|
node:AddNode("Dummy")
|
|
end
|
|
end
|
|
|
|
if (IsValid(backnode)) then
|
|
return
|
|
end
|
|
|
|
if (IsValid(SoundInfoTreeRoot)) then
|
|
SoundInfoTreeRoot:SetExpanded(true)
|
|
end
|
|
end
|
|
|
|
// Set the volume of the sound.
|
|
local function SetSoundVolume(volume)
|
|
if(!SoundObj) then return end
|
|
|
|
SoundObj:ChangeVolume(tonumber(volume) or 1, 0.1)
|
|
end
|
|
|
|
// Set the pitch of the sound.
|
|
local function SetSoundPitch(pitch)
|
|
if(!SoundObj) then return end
|
|
|
|
SoundObj:ChangePitch(tonumber(pitch) or 100, 0.1)
|
|
end
|
|
|
|
// Play the given sound, if no sound is given then mute a playing sound.
|
|
local function PlaySound(file, volume, pitch)
|
|
if(SoundObj) then
|
|
SoundObj:Stop()
|
|
SoundObj = nil
|
|
end
|
|
|
|
if (!file or file == "") then return end
|
|
|
|
local ply = LocalPlayer()
|
|
if (!IsValid(ply)) then return end
|
|
|
|
util.PrecacheSound(file)
|
|
|
|
SoundObj = CreateSound(ply, file)
|
|
if(SoundObj) then
|
|
SoundObj:PlayEx(tonumber(volume) or 1, tonumber(pitch) or 100)
|
|
end
|
|
end
|
|
|
|
// Play the given sound without effects, if no sound is given then mute a playing sound.
|
|
local function PlaySoundNoEffect(file)
|
|
if(SoundObjNoEffect) then
|
|
SoundObjNoEffect:Stop()
|
|
SoundObjNoEffect = nil
|
|
end
|
|
|
|
if (!file or file == "") then return end
|
|
|
|
local ply = LocalPlayer()
|
|
if (!IsValid(ply)) then return end
|
|
|
|
util.PrecacheSound(file)
|
|
|
|
SoundObjNoEffect = CreateSound(ply, file)
|
|
if(SoundObjNoEffect) then
|
|
SoundObjNoEffect:PlayEx(1, 100)
|
|
end
|
|
end
|
|
|
|
local function SetupSoundemitter(strSound)
|
|
// Setup the Soundemitter stool with the soundpath.
|
|
RunConsoleCommand("wire_soundemitter_sound", strSound)
|
|
|
|
// Pull out the soundemitter stool after setup.
|
|
spawnmenu.ActivateTool("wire_soundemitter")
|
|
end
|
|
|
|
local function SetupClipboard(strSound)
|
|
// Copy the soundpath to Clipboard.
|
|
SetClipboardText(strSound)
|
|
end
|
|
|
|
local function Sendmenu(strSound, SoundEmitter, nSoundVolume, nSoundPitch) // Open a sending and setup menu on right click on a sound file.
|
|
if (!isstring(strSound)) then return end
|
|
if (strSound == "") then return end
|
|
|
|
local Menu = DermaMenu()
|
|
local MenuItem = nil
|
|
|
|
if (SoundEmitter) then
|
|
|
|
//Setup soundemitter
|
|
MenuItem = Menu:AddOption("Setup soundemitter", function()
|
|
SetupSoundemitter(strSound)
|
|
end)
|
|
MenuItem:SetImage("icon16/sound.png")
|
|
|
|
//Setup soundemitter and close
|
|
MenuItem = Menu:AddOption("Setup soundemitter and close", function()
|
|
SetupSoundemitter(strSound)
|
|
SoundBrowserPanel:Close()
|
|
end)
|
|
MenuItem:SetImage("icon16/sound.png")
|
|
|
|
//Copy to clipboard
|
|
MenuItem = Menu:AddOption("Copy to clipboard", function()
|
|
SetupClipboard(strSound)
|
|
end)
|
|
MenuItem:SetImage("icon16/page_paste.png")
|
|
|
|
//Copy to clipboard and close
|
|
MenuItem = Menu:AddOption("Copy to clipboard and close", function()
|
|
SetupClipboard(strSound)
|
|
SoundBrowserPanel:Close()
|
|
end)
|
|
MenuItem:SetImage("icon16/page_paste.png")
|
|
|
|
else
|
|
|
|
//Copy to clipboard
|
|
MenuItem = Menu:AddOption("Copy to clipboard", function()
|
|
SetupClipboard(strSound)
|
|
end)
|
|
MenuItem:SetImage("icon16/page_paste.png")
|
|
|
|
//Copy to clipboard and close
|
|
MenuItem = Menu:AddOption("Copy to clipboard and close", function()
|
|
SetupClipboard(strSound)
|
|
SoundBrowserPanel:Close()
|
|
end)
|
|
MenuItem:SetImage("icon16/page_paste.png")
|
|
|
|
//Setup soundemitter
|
|
MenuItem = Menu:AddOption("Setup soundemitter", function()
|
|
SetupSoundemitter(strSound)
|
|
end)
|
|
MenuItem:SetImage("icon16/sound.png")
|
|
|
|
//Setup soundemitter and close
|
|
MenuItem = Menu:AddOption("Setup soundemitter and close", function()
|
|
SetupSoundemitter(strSound)
|
|
SoundBrowserPanel:Close()
|
|
end)
|
|
MenuItem:SetImage("icon16/sound.png")
|
|
|
|
end
|
|
|
|
Menu:AddSpacer()
|
|
|
|
if (IsValid(TabFavourites)) then
|
|
// Add the soundpath to the favourites.
|
|
if (TabFavourites:ItemInList(strSound)) then
|
|
|
|
//Remove from favourites
|
|
MenuItem = Menu:AddOption("Remove from favourites", function()
|
|
TabFavourites:RemoveItem(strSound)
|
|
end)
|
|
MenuItem:SetImage("icon16/bin_closed.png")
|
|
|
|
else
|
|
|
|
//Add to favourites
|
|
MenuItem = Menu:AddOption("Add to favourites", function()
|
|
TabFavourites:AddItem(strSound, sound.GetProperties(strSound) and "property" or "file")
|
|
end)
|
|
MenuItem:SetImage("icon16/star.png")
|
|
local max_item_count = TabFavourites:GetMaxItems()
|
|
local count = TabFavourites.TabfileCount
|
|
if (count >= max_item_count) then
|
|
MenuItem:SetTextColor(Disabled_Gray) // custom disabling
|
|
MenuItem.DoClick = function() end
|
|
|
|
MenuItem:SetToolTip("The favourites list is Full! It can't hold more than "..max_item_count.." items!")
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
Menu:AddSpacer()
|
|
|
|
//Print to console
|
|
MenuItem = Menu:AddOption("Print to console", function()
|
|
// Print the soundpath in the Console/HUD.
|
|
local ply = LocalPlayer()
|
|
if (!IsValid(ply)) then return end
|
|
|
|
ply:PrintMessage( HUD_PRINTTALK, strSound)
|
|
end)
|
|
MenuItem:SetImage("icon16/monitor_go.png")
|
|
|
|
//Print to Chat
|
|
MenuItem = Menu:AddOption("Print to Chat", function()
|
|
// Say the the soundpath.
|
|
RunConsoleCommand("say", strSound)
|
|
end)
|
|
MenuItem:SetImage("icon16/group_go.png")
|
|
|
|
local len = #strSound
|
|
if (len > max_char_chat_count) then
|
|
MenuItem:SetTextColor(Disabled_Gray) // custom disabling
|
|
MenuItem.DoClick = function() end
|
|
|
|
MenuItem:SetToolTip("The filepath ("..len.." chars) is too long to print in chat. It should be shorter than "..max_char_chat_count.." chars!")
|
|
end
|
|
|
|
Menu:AddSpacer()
|
|
|
|
//Play
|
|
MenuItem = Menu:AddOption("Play", function()
|
|
PlaySound(strSound, nSoundVolume, nSoundPitch, strtype)
|
|
PlaySoundNoEffect()
|
|
end)
|
|
MenuItem:SetImage("icon16/control_play.png")
|
|
|
|
//Play without effects
|
|
MenuItem = Menu:AddOption("Play without effects", function()
|
|
PlaySound()
|
|
PlaySoundNoEffect(strSound, strtype)
|
|
end)
|
|
MenuItem:SetImage("icon16/control_play_blue.png")
|
|
|
|
Menu:Open()
|
|
end
|
|
|
|
local function Infomenu(parent, node, SoundEmitter, nSoundVolume, nSoundPitch)
|
|
if(!IsValid(node)) then return end
|
|
if(!node.IsDataNode) then return end
|
|
|
|
local strNodeName = node:GetText()
|
|
local IsSoundNode = node.IsSoundNode
|
|
|
|
if(IsSoundNode) then
|
|
Sendmenu(strNodeName, SoundEmitter, nSoundVolume, nSoundPitch)
|
|
return
|
|
end
|
|
|
|
local Menu = DermaMenu()
|
|
|
|
//Copy to clipboard
|
|
MenuItem = Menu:AddOption("Copy to clipboard", function()
|
|
SetupClipboard(strNodeName)
|
|
end)
|
|
MenuItem:SetImage("icon16/page_paste.png")
|
|
|
|
//Print to console
|
|
MenuItem = Menu:AddOption("Print to console", function()
|
|
// Print the soundpath in the Console/HUD.
|
|
local ply = LocalPlayer()
|
|
if (!IsValid(ply)) then return end
|
|
|
|
ply:PrintMessage( HUD_PRINTTALK, strNodeName)
|
|
end)
|
|
MenuItem:SetImage("icon16/monitor_go.png")
|
|
|
|
//Print to Chat
|
|
MenuItem = Menu:AddOption("Print to Chat", function()
|
|
// Say the the soundpath.
|
|
RunConsoleCommand("say", strNodeName)
|
|
end)
|
|
MenuItem:SetImage("icon16/group_go.png")
|
|
|
|
local len = #strNodeName
|
|
if (len > max_char_chat_count) then
|
|
MenuItem:SetTextColor(Disabled_Gray) // custom disabling
|
|
MenuItem.DoClick = function() end
|
|
|
|
MenuItem:SetToolTip("The filepath ("..len.." chars) is too long to print in chat. It should be shorter than "..max_char_chat_count.." chars!")
|
|
end
|
|
|
|
Menu:Open()
|
|
end
|
|
|
|
// Save the file path. It should be cross session.
|
|
// It's used when opening the browser in the e2 editor.
|
|
local function SaveFilePath(panel, file)
|
|
if (!IsValid(panel)) then return end
|
|
if (panel.Soundemitter) then return end
|
|
|
|
panel:SetCookie("wire_soundfile", file)
|
|
end
|
|
|
|
// Open the Sound Browser.
|
|
local function CreateSoundBrowser(path, se)
|
|
local soundemitter = false
|
|
if (isstring(path) and path ~= "") then
|
|
soundemitter = true
|
|
|
|
if (tonumber(se) ~= 1) then
|
|
soundemitter = false
|
|
end
|
|
end
|
|
|
|
if (tonumber(se) == 1) then
|
|
soundemitter = true
|
|
end
|
|
|
|
local strSound = ""
|
|
local nSoundVolume = 1
|
|
local nSoundPitch = 100
|
|
|
|
if(IsValid(SoundBrowserPanel)) then SoundBrowserPanel:Remove() end
|
|
if(IsValid(TabFileBrowser)) then TabFileBrowser:Remove() end
|
|
if(IsValid(TabSoundPropertyList)) then TabSoundPropertyList:Remove() end
|
|
if(IsValid(TabFavourites)) then TabFavourites:Remove() end
|
|
if(IsValid(SoundInfoTree)) then SoundInfoTree:Remove() end
|
|
if(IsValid(SoundInfoTreeRoot)) then SoundInfoTreeRoot:Remove() end
|
|
|
|
SoundBrowserPanel = vgui.Create("DFrame") // The main frame.
|
|
SoundBrowserPanel:SetPos(50,25)
|
|
SoundBrowserPanel:SetSize(750, 500)
|
|
|
|
SoundBrowserPanel:SetMinWidth(700)
|
|
SoundBrowserPanel:SetMinHeight(400)
|
|
|
|
SoundBrowserPanel:SetSizable(true)
|
|
SoundBrowserPanel:SetDeleteOnClose( false )
|
|
SoundBrowserPanel:SetTitle("Sound Browser")
|
|
SoundBrowserPanel:SetVisible(false)
|
|
SoundBrowserPanel:SetCookieName( "wire_sound_browser" )
|
|
|
|
TabFileBrowser = vgui.Create("wire_filebrowser") // The file tree browser.
|
|
TabSoundPropertyList = vgui.Create("wire_soundpropertylist") // The sound property browser.
|
|
TabFavourites = vgui.Create("wire_listeditor") // The favourites manager.
|
|
|
|
TabFileBrowser:SetListSpeed(6)
|
|
TabFileBrowser:SetMaxItemsPerPage(200)
|
|
|
|
TabSoundPropertyList:SetListSpeed(100)
|
|
TabSoundPropertyList:SetMaxItems(400)
|
|
|
|
TabFavourites:SetListSpeed(40)
|
|
TabFavourites:SetMaxItems(512)
|
|
|
|
local BrowserTabs = vgui.Create("DPropertySheet") // The tabs.
|
|
BrowserTabs:DockMargin(5, 5, 5, 5)
|
|
BrowserTabs:AddSheet("File Browser", TabFileBrowser, "icon16/folder.png", false, false, "Browse your sound folder.")
|
|
BrowserTabs:AddSheet("Sound Property Browser", TabSoundPropertyList, "icon16/table_gear.png", false, false, "Browse the sound properties.")
|
|
BrowserTabs:AddSheet("Favourites", TabFavourites, "icon16/star.png", false, false, "View your favourites.")
|
|
|
|
SoundInfoTree = vgui.Create("DTree") // The info tree.
|
|
SoundInfoTree:SetClickOnDragHover(false)
|
|
local oldClicktime = CurTime()
|
|
SoundInfoTree.DoClick = function( parent, node )
|
|
if (!IsValid(parent)) then return end
|
|
if (!IsValid(node)) then return end
|
|
parent:SetSelectedItem(node)
|
|
|
|
local Clicktime = CurTime()
|
|
if ((Clicktime - oldClicktime) > 0.3) then oldClicktime = Clicktime return end
|
|
oldClicktime = Clicktime
|
|
|
|
if (!node.IsSoundNode) then return end
|
|
|
|
local file = node:GetText()
|
|
PlaySound(file, nSoundVolume, nSoundPitch)
|
|
PlaySoundNoEffect()
|
|
end
|
|
SoundInfoTree.DoRightClick = function( parent, node )
|
|
if (!IsValid(parent)) then return end
|
|
if (!IsValid(node)) then return end
|
|
|
|
parent:SetSelectedItem(node)
|
|
Infomenu(parent, node, SoundEmitter, nSoundVolume, nSoundPitch)
|
|
end
|
|
|
|
SoundInfoTree.OnNodeSelected = function( parent, node )
|
|
if (!IsValid(parent)) then return end
|
|
if (!IsValid(node)) then return end
|
|
|
|
local backnode = node.BackNode
|
|
if (!IsValid(node.BackNode)) then
|
|
node:SetExpanded(!node.m_bExpanded)
|
|
return
|
|
end
|
|
|
|
local tabsound = node.SubData
|
|
if (!tabsound) then
|
|
node:SetExpanded(!node.m_bExpanded)
|
|
return
|
|
end
|
|
|
|
node:SetExpanded(false)
|
|
node:Remove()
|
|
|
|
if (istable(tabsound)) then
|
|
node = backnode:AddNode("Sounds", "icon16/table_multiple.png")
|
|
for k, v in pairs(tabsound) do
|
|
GenerateInfoTree(v, node, k)
|
|
end
|
|
else
|
|
node = backnode:AddNode("Sound", "icon16/table.png")
|
|
GenerateInfoTree(tabsound, node)
|
|
end
|
|
|
|
node:SetExpanded(false)
|
|
parent:SetSelectedItem(node)
|
|
node:SetExpanded(!node.m_bExpanded)
|
|
end
|
|
|
|
local SplitPanel = SoundBrowserPanel:Add( "DHorizontalDivider" )
|
|
SplitPanel:Dock(FILL)
|
|
SplitPanel:SetLeft(BrowserTabs)
|
|
SplitPanel:SetRight(SoundInfoTree)
|
|
SplitPanel:SetLeftWidth(570)
|
|
SplitPanel:SetLeftMin(500)
|
|
SplitPanel:SetRightMin(150)
|
|
SplitPanel:SetDividerWidth(3)
|
|
|
|
TabFileBrowser:SetRootName("sound")
|
|
TabFileBrowser:SetRootPath("sound")
|
|
TabFileBrowser:SetWildCard("GAME")
|
|
TabFileBrowser:SetFileTyps({"*.mp3","*.wav","*.ogg"})
|
|
|
|
//TabFileBrowser:AddColumns("Type", "Size", "Length") //getting the duration is very slow.
|
|
local Columns = TabFileBrowser:AddColumns("Format", "Size")
|
|
Columns[1]:SetFixedWidth(70)
|
|
Columns[1]:SetWide(70)
|
|
Columns[2]:SetFixedWidth(70)
|
|
Columns[2]:SetWide(70)
|
|
|
|
TabFileBrowser.LineData = function(self, id, strfile, ...)
|
|
if (#strfile > max_char_count) then return nil, true end // skip and hide to long filenames.
|
|
|
|
local nsize, strformat, nduration = GetFileInfos(strfile)
|
|
if (!nsize) then return end
|
|
|
|
local nsizeB, strsize = FormatSize(nsize, nduration)
|
|
local nduration, strduration = FormatLength(nduration, nsize)
|
|
|
|
//return {strformat, strsize or "n/a", strduration or "n/a"} //getting the duration is very slow.
|
|
return {strformat, strsize or "n/a"}
|
|
end
|
|
|
|
TabFileBrowser.OnLineAdded = function(self, id, line, strfile, ...)
|
|
|
|
end
|
|
|
|
TabFileBrowser.DoClick = function(parent, file)
|
|
SaveFilePath(SoundBrowserPanel, file)
|
|
|
|
strSound = file
|
|
GenerateInfoTree(file)
|
|
end
|
|
|
|
TabFileBrowser.DoDoubleClick = function(parent, file)
|
|
PlaySound(file, nSoundVolume, nSoundPitch)
|
|
PlaySoundNoEffect()
|
|
SaveFilePath(SoundBrowserPanel, file)
|
|
|
|
strSound = file
|
|
end
|
|
|
|
TabFileBrowser.DoRightClick = function(parent, file)
|
|
Sendmenu(file, SoundBrowserPanel.Soundemitter, nSoundVolume, nSoundPitch)
|
|
SaveFilePath(SoundBrowserPanel, file)
|
|
|
|
strSound = file
|
|
GenerateInfoTree(file)
|
|
end
|
|
|
|
|
|
TabSoundPropertyList.DoClick = function(parent, property)
|
|
SaveFilePath(SoundBrowserPanel, property)
|
|
|
|
strSound = property
|
|
GenerateInfoTree(property)
|
|
end
|
|
|
|
TabSoundPropertyList.DoDoubleClick = function(parent, property)
|
|
PlaySound(property, nSoundVolume, nSoundPitch)
|
|
PlaySoundNoEffect()
|
|
SaveFilePath(SoundBrowserPanel, property)
|
|
|
|
strSound = property
|
|
end
|
|
|
|
TabSoundPropertyList.DoRightClick = function(parent, property)
|
|
Sendmenu(property, SoundBrowserPanel.Soundemitter, nSoundVolume, nSoundPitch)
|
|
SaveFilePath(SoundBrowserPanel, property)
|
|
|
|
strSound = property
|
|
GenerateInfoTree(property)
|
|
end
|
|
|
|
file.CreateDir("soundlists")
|
|
TabFavourites:SetRootPath("soundlists")
|
|
|
|
TabFavourites.DoClick = function(parent, item, data)
|
|
if(file.Exists("sound/"..item, "GAME")) then
|
|
TabFileBrowser:SetOpenFile(item)
|
|
end
|
|
|
|
strSound = item
|
|
GenerateInfoTree(item)
|
|
end
|
|
|
|
TabFavourites.DoDoubleClick = function(parent, item, data)
|
|
if(file.Exists("sound/"..item, "GAME")) then
|
|
TabFileBrowser:SetOpenFile(item)
|
|
end
|
|
|
|
PlaySound(item, nSoundVolume, nSoundPitch)
|
|
PlaySoundNoEffect()
|
|
strSound = item
|
|
end
|
|
|
|
TabFavourites.DoRightClick = function(parent, item, data)
|
|
if(file.Exists("sound/"..item, "GAME")) then
|
|
TabFileBrowser:SetOpenFile(item)
|
|
end
|
|
|
|
Sendmenu(item, SoundBrowserPanel.Soundemitter, nSoundVolume, nSoundPitch)
|
|
strSound = item
|
|
GenerateInfoTree(item)
|
|
end
|
|
|
|
local ControlPanel = SoundBrowserPanel:Add("DPanel") // The bottom part of the frame.
|
|
ControlPanel:DockMargin(0, 5, 0, 0)
|
|
ControlPanel:Dock(BOTTOM)
|
|
ControlPanel:SetTall(60)
|
|
ControlPanel:SetDrawBackground(false)
|
|
|
|
local ButtonsPanel = ControlPanel:Add("DPanel") // The buttons.
|
|
ButtonsPanel:DockMargin(4, 0, 0, 0)
|
|
ButtonsPanel:Dock(RIGHT)
|
|
ButtonsPanel:SetWide(250)
|
|
ButtonsPanel:SetDrawBackground(false)
|
|
|
|
local TunePanel = ControlPanel:Add("DPanel") // The effect Sliders.
|
|
TunePanel:DockMargin(0, 4, 0, 0)
|
|
TunePanel:Dock(LEFT)
|
|
TunePanel:SetWide(350)
|
|
TunePanel:SetDrawBackground(false)
|
|
|
|
local TuneVolumeSlider = TunePanel:Add("DNumSlider") // The volume slider.
|
|
TuneVolumeSlider:DockMargin(2, 0, 0, 0)
|
|
TuneVolumeSlider:Dock(TOP)
|
|
TuneVolumeSlider:SetText("Volume")
|
|
TuneVolumeSlider:SetDecimals(0)
|
|
TuneVolumeSlider:SetMinMax(0, 100)
|
|
TuneVolumeSlider:SetValue(100)
|
|
TuneVolumeSlider.Label:SetWide(40)
|
|
TuneVolumeSlider.OnValueChanged = function(self, val)
|
|
nSoundVolume = val / 100
|
|
SetSoundVolume(nSoundVolume)
|
|
end
|
|
|
|
local TunePitchSlider = TunePanel:Add("DNumSlider") // The pitch slider.
|
|
TunePitchSlider:DockMargin(2, 0, 0, 0)
|
|
TunePitchSlider:Dock(BOTTOM)
|
|
TunePitchSlider:SetText("Pitch")
|
|
TunePitchSlider:SetDecimals(0)
|
|
TunePitchSlider:SetMinMax(0, 255)
|
|
TunePitchSlider:SetValue(100)
|
|
TunePitchSlider.Label:SetWide(40)
|
|
TunePitchSlider.OnValueChanged = function(self, val)
|
|
nSoundPitch = val
|
|
SetSoundPitch(nSoundPitch)
|
|
end
|
|
|
|
local PlayStopPanel = ButtonsPanel:Add("DPanel") // Play and stop.
|
|
PlayStopPanel:DockMargin(0, 0, 0, 2)
|
|
PlayStopPanel:Dock(TOP)
|
|
PlayStopPanel:SetDrawBackground(false)
|
|
|
|
local PlayButton = PlayStopPanel:Add("DButton") // The play button.
|
|
PlayButton:SetText("Play")
|
|
PlayButton:Dock(LEFT)
|
|
PlayButton:SetWide(PlayStopPanel:GetWide() / 2 - 2)
|
|
PlayButton.DoClick = function()
|
|
PlaySound(strSound, nSoundVolume, nSoundPitch)
|
|
PlaySoundNoEffect()
|
|
end
|
|
|
|
local StopButton = PlayStopPanel:Add("DButton") // The stop button.
|
|
StopButton:SetText("Stop")
|
|
StopButton:Dock(RIGHT)
|
|
StopButton:SetWide(PlayButton:GetWide())
|
|
StopButton.DoClick = function()
|
|
PlaySound() // Mute a playing sound by not giving a sound.
|
|
PlaySoundNoEffect()
|
|
end
|
|
|
|
local SoundemitterButton = ButtonsPanel:Add("DButton") // The soundemitter button. Hidden in e2 mode.
|
|
SoundemitterButton:SetText("Send to soundemitter")
|
|
SoundemitterButton:DockMargin(0, 2, 0, 0)
|
|
SoundemitterButton:Dock(FILL)
|
|
SoundemitterButton:SetVisible(false)
|
|
SoundemitterButton.DoClick = function(btn)
|
|
SetupSoundemitter(strSound)
|
|
end
|
|
|
|
local ClipboardButton = ButtonsPanel:Add("DButton") // The soundemitter button. Hidden in soundemitter mode.
|
|
ClipboardButton:SetText("Copy to clipboard")
|
|
ClipboardButton:DockMargin(0, 2, 0, 0)
|
|
ClipboardButton:Dock(FILL)
|
|
ClipboardButton:SetVisible(false)
|
|
ClipboardButton.DoClick = function(btn)
|
|
SetupClipboard(strSound)
|
|
end
|
|
|
|
local oldw, oldh = SoundBrowserPanel:GetSize()
|
|
SoundBrowserPanel.PerformLayout = function(self, ...)
|
|
SoundemitterButton:SetVisible(self.Soundemitter)
|
|
ClipboardButton:SetVisible(!self.Soundemitter)
|
|
|
|
local w = self:GetWide()
|
|
local rightw = SplitPanel:GetLeftWidth() + w - oldw
|
|
|
|
if (rightw < SplitPanel:GetLeftMin()) then
|
|
rightw = SplitPanel:GetLeftMin()
|
|
end
|
|
SplitPanel:SetLeftWidth(rightw)
|
|
|
|
local minw = w - SplitPanel:GetRightMin() + SplitPanel:GetDividerWidth()
|
|
if (SplitPanel:GetLeftWidth() > minw) then
|
|
SplitPanel:SetLeftWidth(minw)
|
|
end
|
|
|
|
PlayStopPanel:SetTall(ControlPanel:GetTall() / 2 - 2)
|
|
PlayButton:SetWide(PlayStopPanel:GetWide() / 2 - 2)
|
|
StopButton:SetWide(PlayButton:GetWide())
|
|
|
|
if (self.Soundemitter) then
|
|
SoundemitterButton:SetTall(PlayStopPanel:GetTall() - 2)
|
|
else
|
|
ClipboardButton:SetTall(PlayStopPanel:GetTall() - 2)
|
|
end
|
|
|
|
oldw, oldh = self:GetSize()
|
|
|
|
DFrame.PerformLayout(self, ...)
|
|
end
|
|
|
|
SoundBrowserPanel.OnClose = function() // Set effects back and mute when closing.
|
|
nSoundVolume = 1
|
|
nSoundPitch = 100
|
|
TuneVolumeSlider:SetValue(nSoundVolume * 100)
|
|
TunePitchSlider:SetValue(nSoundPitch)
|
|
vgui.GetWorldPanel():SetWorldClicker(false) -- Not allow the breakage of other addons installed.
|
|
PlaySound()
|
|
PlaySoundNoEffect()
|
|
end
|
|
|
|
SoundBrowserPanel:InvalidateLayout(true)
|
|
end
|
|
|
|
// Open the Sound Browser.
|
|
local function OpenSoundBrowser(pl, cmd, args)
|
|
local path = args[1] // nil or "" will put the browser in e2 mode else the soundemitter mode is applied.
|
|
local se = args[2]
|
|
|
|
if (!IsValid(SoundBrowserPanel)) then
|
|
CreateSoundBrowser(path, se)
|
|
end
|
|
|
|
SoundBrowserPanel:SetVisible(true)
|
|
SoundBrowserPanel:MakePopup()
|
|
SoundBrowserPanel:InvalidateLayout(true)
|
|
|
|
vgui.GetWorldPanel():SetWorldClicker(true)
|
|
|
|
if (!IsValid(TabFileBrowser)) then return end
|
|
|
|
//Replaces the timer, doesn't get paused in singleplayer.
|
|
WireLib.Timedcall(function(SoundBrowserPanel, TabFileBrowser, path, se)
|
|
if (!IsValid(SoundBrowserPanel)) then return end
|
|
if (!IsValid(TabFileBrowser)) then return end
|
|
|
|
local soundemitter = false
|
|
if (isstring(path) and path ~= "") then
|
|
soundemitter = true
|
|
end
|
|
|
|
local soundemitter = false
|
|
if (isstring(path) and path ~= "") then
|
|
soundemitter = true
|
|
|
|
if (tonumber(se) ~= 1) then
|
|
soundemitter = false
|
|
end
|
|
end
|
|
|
|
if (tonumber(se) == 1) then
|
|
soundemitter = true
|
|
end
|
|
|
|
SoundBrowserPanel.Soundemitter = soundemitter
|
|
SoundBrowserPanel:InvalidateLayout(true)
|
|
|
|
if (!soundemitter) then
|
|
path = SoundBrowserPanel:GetCookie("wire_soundfile", "") // load last session
|
|
end
|
|
TabFileBrowser:SetOpenFile(path)
|
|
end, SoundBrowserPanel, TabFileBrowser, path, se)
|
|
end
|
|
|
|
concommand.Add("wire_sound_browser_open", OpenSoundBrowser)
|