Initial version - 1.2.0.60

EN: 1.2.0.60
CN: 1.2.0.61
JP: 1.2.0.63
KR: 1.2.0.67
This commit is contained in:
SL1900
2025-12-03 01:00:00 +09:00
commit 5e0d58cfad
3595 changed files with 9373562 additions and 0 deletions
@@ -0,0 +1,401 @@
local BBVEditorCtrl = class("BBVEditorCtrl", BaseCtrl)
local BubbleVoiceManager = require("Game.Actor2D.BubbleVoiceManager")
local Actor2DManager = require("Game.Actor2D.Actor2DManager")
BBVEditorCtrl._mapNodeConfig = {
rawImage = {
sNodeName = "----Actor2D----",
sComponentName = "RawImage"
},
ipt_SrcContent = {sComponentName = "InputField"},
dd_PlayerSex = {
sComponentName = "Dropdown",
callback = "OnDD_PlayerSex"
},
dd_Language_Vo = {
sComponentName = "Dropdown",
callback = "OnEvent_SwitchVoLan"
},
dd_Language_Txt = {
sComponentName = "Dropdown",
callback = "OnEvent_SwitchTxtLan"
},
btn_SaveSplitContent = {},
btn_UseCn_Time_Anim = {
sComponentName = "Button",
callback = "OnBtn_ReuseCnTimeAnim"
},
btn_UseJp_Time_Anim = {
sComponentName = "Button",
callback = "OnBtn_ReuseJpTimeAnim"
},
btn_SaveByDefault = {
sComponentName = "Button",
callback = "OnBtn_SaveNewDataByDefault"
},
dd_VoResName = {sComponentName = "Dropdown"},
btn_Back = {sComponentName = "Button", callback = "OnBtn_Back"},
tog_CnM = {sComponentName = "Toggle"},
tog_CnF = {sComponentName = "Toggle"},
tog_JpM = {sComponentName = "Toggle"},
CnMText = {nCount = 4, sComponentName = "InputField"},
CnMTextFallback = {nCount = 4, sComponentName = "Text"},
CnMTime = {nCount = 4, sComponentName = "InputField"},
CnMTimeFallback = {nCount = 4, sComponentName = "Text"},
CnMAnim = {nCount = 4, sComponentName = "Dropdown"},
CnFText = {nCount = 4, sComponentName = "InputField"},
CnFTextFallback = {nCount = 4, sComponentName = "Text"},
CnFTime = {nCount = 4, sComponentName = "InputField"},
CnFTimeFallback = {nCount = 4, sComponentName = "Text"},
CnFAnim = {nCount = 4, sComponentName = "Dropdown"},
JpMText = {nCount = 4, sComponentName = "InputField"},
JpMTextFallback = {nCount = 4, sComponentName = "Text"},
JpMTime = {nCount = 4, sComponentName = "InputField"},
JpMTimeFallback = {nCount = 4, sComponentName = "Text"},
JpMAnim = {nCount = 4, sComponentName = "Dropdown"},
JpFText = {nCount = 4, sComponentName = "InputField"},
JpFTextFallback = {nCount = 4, sComponentName = "Text"},
JpFTime = {nCount = 4, sComponentName = "InputField"},
JpFTimeFallback = {nCount = 4, sComponentName = "Text"},
JpFAnim = {nCount = 4, sComponentName = "Dropdown"},
goBubbleRoot = {
sNodeName = "----bubble----"
},
rtBubbleRoot = {
sNodeName = "----bubble----",
sComponentName = "RectTransform"
},
dd_BBLeftRight = {sComponentName = "Dropdown"},
tmp_CurVosResLen = {sComponentName = "TMP_Text"}
}
BBVEditorCtrl._mapEventConfig = {
BBVE_SetTextTime = "onEvent_SetTextTime",
BBVE_SaveTextTime = "onEvent_SaveTextTime",
BBVE_SetCharL2D = "onEvent_SetCharL2D",
BBVE_SaveOffset = "onEvent_SaveOffset",
BBVE_Play = "onEvent_Play",
BBVE_Stop = "onEvent_Stop",
BBVE_Pause = "onEvent_Pause",
BBVE_Resume = "onEvent_Resume",
BBVE_CheckNewData = "onEvent_CheckNewData"
}
function BBVEditorCtrl:OnEnable()
if Settings.sCurrentTxtLanguage == AllEnum.Language.CN then
NovaAPI.SetToggleIsOn(self._mapNode.tog_CnF, true)
NovaAPI.SetToggleInteractable(self._mapNode.tog_CnM, false)
NovaAPI.SetToggleInteractable(self._mapNode.tog_JpM, false)
for i = 1, 4 do
self._mapNode.CnFAnim[i].gameObject:SetActive(true)
self._mapNode.JpFAnim[i].gameObject:SetActive(false)
end
else
if Settings.sCurrentTxtLanguage == AllEnum.Language.JP then
NovaAPI.SetToggleInteractable(self._mapNode.tog_CnM, false)
NovaAPI.SetToggleInteractable(self._mapNode.tog_CnF, false)
else
end
end
local ListString = CS.System.Collections.Generic.List(CS.System.String)
local listLanguage = ListString()
for i, v in ipairs(AllEnum.LanguageInfo) do
listLanguage:Add(v[2])
end
NovaAPI.ClearDropDownOptions(self._mapNode.dd_Language_Vo)
NovaAPI.DropDownAddOptions(self._mapNode.dd_Language_Vo, listLanguage)
NovaAPI.SetDDValueWithoutNotify(self._mapNode.dd_Language_Vo, GetLanguageIndex(Settings.sCurrentVoLanguage) - 1)
self.mapText = {
male_cn = self._mapNode.CnMText,
female_cn = self._mapNode.CnFText,
male_jp = self._mapNode.JpMText,
female_jp = self._mapNode.JpFText
}
self.mapTextFallback = {
male_cn = self._mapNode.CnMTextFallback,
female_cn = self._mapNode.CnFTextFallback,
male_jp = self._mapNode.JpMTextFallback,
female_jp = self._mapNode.JpFTextFallback
}
self.mapTime = {
male_cn = self._mapNode.CnMTime,
female_cn = self._mapNode.CnFTime,
male_jp = self._mapNode.JpMTime,
female_jp = self._mapNode.JpFTime
}
self.mapTimeFallback = {
male_cn = self._mapNode.CnMTimeFallback,
female_cn = self._mapNode.CnFTimeFallback,
male_jp = self._mapNode.JpMTimeFallback,
female_jp = self._mapNode.JpFTimeFallback
}
self.mapAnim = {
male_cn = self._mapNode.CnMAnim,
female_cn = self._mapNode.CnFAnim,
male_jp = self._mapNode.JpMAnim,
female_jp = self._mapNode.JpFAnim
}
self.tbCheckOrder = {
"male_cn",
"female_cn",
"male_jp",
"female_jp"
}
if Settings.sCurrentTxtLanguage == AllEnum.Language.CN then
self.tbCheckOrder = {
"male_jp",
"female_jp",
"male_cn",
"female_cn"
}
elseif Settings.sCurrentTxtLanguage == AllEnum.Language.JP then
self.tbCheckOrder = {"male_jp", "female_jp"}
end
self:InitL2DAnimDD()
BubbleVoiceManager.Init(true)
local bReuseFunc = Settings.sCurrentTxtLanguage ~= AllEnum.Language.CN and Settings.sCurrentTxtLanguage ~= AllEnum.Language.JP
self._mapNode.btn_UseCn_Time_Anim.gameObject:SetActive(bReuseFunc)
self._mapNode.btn_UseJp_Time_Anim.gameObject:SetActive(bReuseFunc)
end
function BBVEditorCtrl:OnDisable()
Actor2DManager.DestroyL2D_InBBVEditor()
end
function BBVEditorCtrl:InitL2DAnimDD()
self.tbAnimName = {
"",
"presents_a",
"presents_b",
"chat_a",
"chat_b",
"chat_c",
"chat_d",
"think_a",
"shy_a",
"special_a",
"special_b"
}
local ListString = CS.System.Collections.Generic.List(CS.System.String)
local listAnim = ListString()
for i, v in ipairs(self.tbAnimName) do
listAnim:Add(v)
end
for i = 1, 4 do
NovaAPI.ClearDropDownOptions(self._mapNode.CnMAnim[i])
NovaAPI.ClearDropDownOptions(self._mapNode.CnFAnim[i])
NovaAPI.ClearDropDownOptions(self._mapNode.JpMAnim[i])
NovaAPI.ClearDropDownOptions(self._mapNode.JpFAnim[i])
end
for i = 1, 4 do
NovaAPI.DropDownAddOptions(self._mapNode.CnMAnim[i], listAnim)
NovaAPI.DropDownAddOptions(self._mapNode.CnFAnim[i], listAnim)
NovaAPI.DropDownAddOptions(self._mapNode.JpMAnim[i], listAnim)
NovaAPI.DropDownAddOptions(self._mapNode.JpFAnim[i], listAnim)
end
end
function BBVEditorCtrl:OnDD_PlayerSex()
local bIsMale = NovaAPI.GetDropDownValue(self._mapNode.dd_PlayerSex) == 1
PlayerData.Base:SetPlayerSex(bIsMale)
end
function BBVEditorCtrl:OnBtn_Back()
EventManager.Hit(EventId.OpenPanel, PanelId.ExeEditor)
end
function BBVEditorCtrl:OnEvent_SwitchVoLan(dd)
local nIndex = NovaAPI.GetDropDownValue(dd)
local sVoLan = AllEnum.LanguageInfo[nIndex + 1][1]
if sVoLan ~= AllEnum.Language.CN and sVoLan ~= AllEnum.Language.JP then
sVoLan = Settings.sCurrentVoLanguage
nIndex = GetLanguageIndex(sVoLan)
NovaAPI.SetDDValueWithoutNotify(dd, nIndex - 1)
return
end
local bDownloaded, nTotalSize, nNeedDownloadSize = NovaAPI.HasDownload_VoLanguage(sVoLan)
if bDownloaded == false and 0 < nNeedDownloadSize then
NovaAPI.Enable_VoLanguage(sVoLan)
PanelManager.OnConfirmBackToLogIn()
return
end
NovaAPI.SetCur_VoiceLanguage(sVoLan)
Settings.sCurrentVoLanguage = sVoLan
end
function BBVEditorCtrl:OnEvent_SwitchTxtLan(dd)
local nLanIdx = NovaAPI.GetDropDownValue(dd) + 1
local sLan = GetLanguageByIndex(nLanIdx)
NovaAPI.SetCur_TextLanguage(sLan)
Settings.sCurrentTxtLanguage = sLan
PanelManager.OnConfirmBackToLogIn()
end
function BBVEditorCtrl:_ReuseData(_sLan, _sKey)
local data = BubbleVoiceManager.GetReuseData(_sLan)
if data == nil then
return
end
local tbFallbackTime = {
0,
0,
0,
0
}
local nCount = #self.tbCheckOrder
for i = nCount, 1, -1 do
local sKey = self.tbCheckOrder[i]
local bTimeFB = false
for ii = 1, 4 do
local nTime = data.time[sKey][ii]
bTimeFB = nTime <= 0
if bTimeFB == false then
tbFallbackTime[ii] = nTime
end
local _nTime = tbFallbackTime[ii]
NovaAPI.SetInputFieldText(self.mapTime[sKey][ii], bTimeFB == true and "" or tostring(nTime))
NovaAPI.SetText(self.mapTimeFallback[sKey][ii], bTimeFB == true and tostring(_nTime) or "")
if sKey == "female_jp" then
local nDDIndex = table.indexof(self.tbAnimName, data.anim[_sKey][ii]) - 1
NovaAPI.SetDropDownValue(self.mapAnim[sKey][ii], nDDIndex)
end
end
end
self._mapNode.btn_SaveSplitContent:SetActive(true)
end
function BBVEditorCtrl:OnBtn_ReuseCnTimeAnim()
self:_ReuseData(AllEnum.Language.CN, "female_cn")
end
function BBVEditorCtrl:OnBtn_ReuseJpTimeAnim()
self:_ReuseData(AllEnum.Language.JP, "female_jp")
end
function BBVEditorCtrl:OnBtn_SaveNewDataByDefault()
local sCurVoResName = self.sVoResName
self.bSaveByDefault = true
if type(self.tbVoResName) == "table" then
for i, sVoResName in ipairs(self.tbVoResName) do
if BubbleVoiceManager.IsNew(sVoResName) == true then
NovaAPI.SetDropDownValue(self._mapNode.dd_VoResName, i - 1)
end
end
end
self.bSaveByDefault = nil
NovaAPI.SetDropDownValue(self._mapNode.dd_VoResName, table.indexof(self.tbVoResName, sCurVoResName) - 1)
end
function BBVEditorCtrl:onEvent_SetTextTime(sVoResName)
self.sVoResName = sVoResName
self.mapAllData, self.bIsNewData = BubbleVoiceManager.GetBubbleData_All(sVoResName)
local tbFallbackText = {
"",
"",
"",
""
}
local tbFallbackTime = {
0,
0,
0,
0
}
local nCount = #self.tbCheckOrder
NovaAPI.SetTMPText(self._mapNode.tmp_CurVosResLen, tostring(BubbleVoiceManager.GetVoResLen(sVoResName)))
if self.bIsNewData == true then
local sKey = self.tbCheckOrder[nCount]
self.mapAllData.text[sKey][1] = NovaAPI.GetInputFieldText(self._mapNode.ipt_SrcContent)
self.mapAllData.time[sKey][1] = BubbleVoiceManager.GetVoResLen(sVoResName)
end
for i = nCount, 1, -1 do
local sKey = self.tbCheckOrder[i]
local bTextFB = false
local bTimeFB = false
for ii = 1, 4 do
local sText = self.mapAllData.text[sKey][ii]
local nTime = self.mapAllData.time[sKey][ii]
sText = string.gsub(sText, "==RT==", "\n")
if ii == 1 and i ~= nCount then
bTextFB = sText == ""
bTimeFB = nTime <= 0
end
if bTextFB == false then
tbFallbackText[ii] = sText
end
if bTimeFB == false then
tbFallbackTime[ii] = nTime
end
local _sText = tbFallbackText[ii]
local _nTime = tbFallbackTime[ii]
NovaAPI.SetInputFieldText(self.mapText[sKey][ii], bTextFB == true and "" or sText)
NovaAPI.SetText(self.mapTextFallback[sKey][ii], bTextFB == true and _sText or "")
NovaAPI.SetInputFieldText(self.mapTime[sKey][ii], bTimeFB == true and "" or tostring(nTime))
NovaAPI.SetText(self.mapTimeFallback[sKey][ii], bTimeFB == true and tostring(_nTime) or "")
if i == nCount then
local nDDIndex = table.indexof(self.tbAnimName, self.mapAllData.anim[sKey][ii]) - 1
NovaAPI.SetDropDownValue(self.mapAnim[sKey][ii], nDDIndex)
end
end
end
if self.bSaveByDefault == true then
self:onEvent_SaveTextTime()
else
self._mapNode.btn_SaveSplitContent:SetActive(self.bIsNewData == true)
end
end
function BBVEditorCtrl:onEvent_SaveTextTime()
if self.mapAllData ~= nil then
local nCount = #self.tbCheckOrder
for i = 1, nCount do
local sKey = self.tbCheckOrder[i]
local bTextFB = false
local bTimeFB = false
for ii = 1, 4 do
local sText = NovaAPI.GetInputFieldText(self.mapText[sKey][ii])
local sTime = NovaAPI.GetInputFieldText(self.mapTime[sKey][ii])
sText = string.gsub(sText, "\r\n", "==RT==")
sText = string.gsub(sText, "\r", "==RT==")
sText = string.gsub(sText, "\n", "==RT==")
sText = string.gsub(sText, "\\", "")
sText = string.gsub(sText, "\"", "\"")
if ii == 1 and i ~= nCount then
bTextFB = sText == ""
bTimeFB = sTime == ""
end
if sTime == "" then
sTime = "0"
end
self.mapAllData.text[sKey][ii] = bTextFB == true and "" or sText
self.mapAllData.time[sKey][ii] = bTimeFB == true and 0 or tonumber(sTime)
if i == nCount then
local nDDIndex = NovaAPI.GetDropDownValue(self.mapAnim[sKey][ii]) + 1
self.mapAllData.anim[sKey][ii] = self.tbAnimName[nDDIndex]
end
end
end
BubbleVoiceManager.DoSaveData(self.mapAllData)
if self.bSaveByDefault ~= true then
self:onEvent_SetTextTime(self.sVoResName)
end
end
end
function BBVEditorCtrl:onEvent_SetCharL2D(bIsNpc, nCharSkinId, bIsCG)
Actor2DManager.SetL2D_InBBVEditor(self._mapNode.rawImage, bIsNpc, nCharSkinId, bIsCG)
local bIsLeft, x, y = BubbleVoiceManager.BBVEditor_GetBBPos(nCharSkinId, bIsCG)
self._mapNode.rtBubbleRoot.anchoredPosition = Vector2(x, y)
NovaAPI.SetDDValueWithoutNotify(self._mapNode.dd_BBLeftRight, bIsLeft == true and 0 or 1)
end
function BBVEditorCtrl:onEvent_SaveOffset(nCharSkinId, bIsCG, bIsLeft, x, y)
BubbleVoiceManager.DoSaveOffset(nCharSkinId, bIsCG, bIsLeft, x / 100, y / 100)
end
function BBVEditorCtrl:onEvent_Play(sVoResName, nCharSkinId, bIsCG)
BubbleVoiceManager.PlayBubbleAnim(self._mapNode.goBubbleRoot, sVoResName, nCharSkinId, bIsCG)
end
function BBVEditorCtrl:onEvent_Stop()
BubbleVoiceManager.StopBubbleAnim()
end
function BBVEditorCtrl:onEvent_Pause()
BubbleVoiceManager.PauseBubbleAnim()
end
function BBVEditorCtrl:onEvent_Resume()
BubbleVoiceManager.ResumeBubbleAnim()
end
function BBVEditorCtrl:onEvent_CheckNewData(listVoResName, nCount)
self.tbVoResName = {}
nCount = nCount - 1
for i = 0, nCount do
local sVoResName = listVoResName[i]
if type(sVoResName) == "string" then
table.insert(self.tbVoResName, sVoResName)
end
end
self._mapNode.btn_SaveByDefault.gameObject:SetActive(BubbleVoiceManager.HasNewDataToSave(self.tbVoResName) == true)
end
return BBVEditorCtrl
@@ -0,0 +1,8 @@
local BBVEditorPanel = class("BBVEditorPanel", BasePanel)
BBVEditorPanel._tbDefine = {
{
sPrefabPath = "BubbleVoiceEditor/BubbleVoiceEditorPanel.prefab",
sCtrlName = "Game.Actor2D.Editor_BBV.BBVEditorCtrl"
}
}
return BBVEditorPanel
@@ -0,0 +1,164 @@
local ExeEditorCtrl = class("ExeEditorCtrl", BaseCtrl)
ExeEditorCtrl._mapNodeConfig = {
btn_AvgEditor = {
sComponentName = "Button",
callback = "onBtn_AvgEditor"
},
btn_BubbleVoiceEditor = {
sComponentName = "Button",
callback = "onBtn_BubbleVoiceEditor"
},
btn_TEST = {sComponentName = "Button", callback = "onBtn_TEST"}
}
ExeEditorCtrl._mapEventConfig = {}
function ExeEditorCtrl:onBtn_AvgEditor()
require("Game.UI.Avg.Editor.main")
EventManager.Hit(EventId.OpenPanel, PanelId.AvgEditor)
end
function ExeEditorCtrl:onBtn_BubbleVoiceEditor()
require("Game.Actor2D.Editor_BBV.main")
EventManager.Hit(EventId.OpenPanel, PanelId.BBVEditor)
end
function ExeEditorCtrl:onBtn_TEST()
end
function ExeEditorCtrl:CheckMissingAvgCharacterId()
local rootPath = CS.UnityEngine.Application.dataPath .. "/../Lua/Game/UI/Avg/"
local sourceDir = {
rootPath .. "_cn/Config",
rootPath .. "_en/Config",
rootPath .. "_jp/Config",
rootPath .. "_kr/Config",
rootPath .. "_tw/Config"
}
local targetFile = rootPath .. "AvgCharacter/AvgCharacter.lua"
local cmdGroup = self:ScanCmdGetParamTarget()
local allFields = {}
for k, v in ipairs(sourceDir) do
print("开始扫描源目录: " .. v)
local sourceFiles = self:ScanDirectoryForLuaFiles(v)
for _, filePath in ipairs(sourceFiles) do
local allParamTables = self:ExtractFieldsFromFile(filePath, cmdGroup)
allFields[filePath] = allParamTables
end
end
local missing = self:CheckFieldsInTarget(allFields, targetFile)
self:ExportTxtFile(missing)
end
function ExeEditorCtrl:ScanCmdGetParamTarget()
local filePath = "D:/NewNovaProject/Nova_Client/Lua/Game/UI/Avg/Editor/CmdInfo.lua"
local paramTables = {}
if CS.System.IO.File.Exists(filePath) then
local lines = CS.System.IO.File.ReadAllLines(filePath)
local funcName = ""
for i = 0, lines.Length - 1 do
local line = lines[i]
if line:match("function") then
funcName = line:match("_([^%(]+)%(")
end
if funcName ~= "" and line:match("SetAvgCharId") then
local number = line:match("%[(%d+)%]")
if number ~= nil then
paramTables[funcName] = tonumber(number)
end
end
end
end
return paramTables
end
function ExeEditorCtrl:ScanDirectoryForLuaFiles(directory)
local files = {}
if CS.System.IO.Directory.Exists(directory) then
local fileEntries = CS.System.IO.Directory.GetFiles(directory, "*.lua", CS.System.IO.SearchOption.AllDirectories)
for i = 0, fileEntries.Length - 1 do
table.insert(files, fileEntries[i])
end
else
print("[错误] 目录不存在: " .. directory)
end
return files
end
function ExeEditorCtrl:ExtractFieldsFromFile(filePath, tbCmd)
local paramTables = {}
if CS.System.IO.File.Exists(filePath) then
local lines = CS.System.IO.File.ReadAllLines(filePath)
for i = 0, lines.Length - 1 do
do
local line = lines[i]
local content = line:match("cmd=\"(.-)\"")
if tbCmd[content] ~= nil then
local paramTableStr = line:match("param%s*=%s*(%b{})")
if paramTableStr then
do
local success, result = pcall(function()
local env = {
table = table
}
local func, err = load("return " .. paramTableStr, "tmp", "t", env)
if func then
return func()
else
print("[解析错误] 行 " .. i + 1 .. ": " .. err)
return nil
end
end)
if success and result then
local num = tbCmd[content]
local AvgCharacterId = result[num]
table.insert(paramTables, {
line = i + 1,
value = AvgCharacterId
})
end
end
end
end
end
end
end
return paramTables
end
function ExeEditorCtrl:CheckFieldsInTarget(fields, targetDir)
local missing = {}
local tbAllIds = {}
if CS.System.IO.File.Exists(targetDir) then
local lines = CS.System.IO.File.ReadAllLines(targetDir)
for i = 0, lines.Length - 1 do
local line = lines[i]
local content = line:match("id = \"(.-)\"")
if content ~= nil then
table.insert(tbAllIds, content)
end
end
end
for k, v in pairs(fields) do
if 0 < #v then
for _, param in ipairs(v) do
if 0 >= table.indexof(tbAllIds, param.value) then
if missing[k] == nil then
missing[k] = {}
end
table.insert(missing[k], param)
end
end
end
end
return missing
end
function ExeEditorCtrl:ExportTxtFile(missing)
local exportDir = CS.UnityEngine.Application.dataPath .. "/../AvgCharacterMissingId/"
local filePath = exportDir .. "output.txt"
if not CS.System.IO.Directory.Exists(exportDir) then
CS.System.IO.Directory.CreateDirectory(exportDir)
end
local streamWriter = CS.System.IO.File.CreateText(filePath)
for filePath, params in pairs(missing) do
streamWriter:WriteLine(filePath)
for _, param in pairs(params) do
local line = string.format(" 第%s行, name:%s", param.line, param.value)
streamWriter:WriteLine(line)
end
end
streamWriter:Close()
print("导出成功!路径: " .. filePath)
end
return ExeEditorCtrl
@@ -0,0 +1,5 @@
EXE_EDITOR = true
require("GameCore.GameCore")
EventManager.Hit(EventId.OpenPanel, PanelId.ExeEditor)
local goLaunchUI = GameObject.Find("==== Builtin UI ====/LaunchUI")
GameObject.Destroy(goLaunchUI)
@@ -0,0 +1,8 @@
local ExeEditorPanel = class("ExeEditorPanel", BasePanel)
ExeEditorPanel._tbDefine = {
{
sPrefabPath = "BubbleVoiceEditor/ExeEditorPanel.prefab",
sCtrlName = "Game.Actor2D.Editor_BBV.ExeEditorCtrl"
}
}
return ExeEditorPanel
+1
View File
@@ -0,0 +1 @@
RUNNING_BBV_EDITOR = true