Serge! 127 Опубликовано 23 Сентября 2015 Внесу и свои три копейки) не уверен, что требуются такие сложности (свои классы и т.д. и т.п.), в реальной жизни все, как правило, намного проще...К примеру, имеем таблицу соответствия кодов символов разных раскладок, типаtbl_code = {[097] = 244, -- a --> ф[098] = 232, -- b --> и...}имеем языковой флаг режима ввода текста, типаmode_lang = true -- false - Eng; true - Руси дале просто при вводе проверяем и добавляем в строку либо английский, либо русский символif mode_lang then str = str.. string.char(tbl_code[csim])else str = str.. string.char(csim) endпри переключении режима ввода (варианты самые различные: от кнопок до "горячих" клавиш), просто переключаем флагmode_lang = not mode_lang 1 1 Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 23 Сентября 2015 Почему идея? Я таким пользуюсь. Чтобы не творить велосипед, вот полная таблица перекодировки. А остальное? Вы же все профи. Все вопросы по ограничению к DS. local tbl_ansii = { [ 039 ] = 253, -- ' --> э [ 044 ] = 225, -- , --> б [ 046 ] = 254, -- . --> ю [ 047 ] = 046, -- / --> . [ 058 ] = 198, -- : --> Ж [ 059 ] = 230, -- ; --> ж [ 060 ] = 193, -- < --> Б [ 062 ] = 222, -- > --> Ю [ 065 ] = 212, -- A --> Ф [ 066 ] = 200, -- B --> И [ 067 ] = 209, -- C --> С [ 068 ] = 194, -- D --> В [ 069 ] = 211, -- E --> У [ 070 ] = 192, -- F --> А [ 071 ] = 207, -- G --> П [ 072 ] = 208, -- H --> Р [ 073 ] = 216, -- I --> Ш [ 074 ] = 206, -- J --> О [ 075 ] = 203, -- K --> Л [ 076 ] = 196, -- L --> Д [ 077 ] = 220, -- M --> Ь [ 078 ] = 210, -- N --> Т [ 079 ] = 217, -- O --> Щ [ 080 ] = 199, -- P --> З [ 081 ] = 201, -- Q --> Й [ 082 ] = 202, -- R --> К [ 083 ] = 219, -- S --> Ы [ 084 ] = 197, -- T --> Е [ 085 ] = 195, -- U --> Г [ 086 ] = 204, -- V --> М [ 087 ] = 214, -- W --> Ц [ 088 ] = 215, -- X --> Ч [ 089 ] = 205, -- Y --> Н [ 090 ] = 223, -- Z --> Я [ 091 ] = 245, -- [ --> х [ 093 ] = 250, -- ] --> ъ [ 097 ] = 244, -- a --> ф [ 098 ] = 232, -- b --> и [ 099 ] = 241, -- c --> с [ 100 ] = 226, -- d --> в [ 101 ] = 243, -- e --> у [ 102 ] = 224, -- f --> а [ 103 ] = 239, -- g --> п [ 104 ] = 240, -- h --> р [ 105 ] = 248, -- i --> ш [ 106 ] = 238, -- j --> о [ 107 ] = 235, -- k --> л [ 108 ] = 228, -- l --> д [ 109 ] = 252, -- m --> ь [ 110 ] = 242, -- n --> т [ 111 ] = 249, -- o --> щ [ 112 ] = 231, -- p --> з [ 113 ] = 233, -- q --> й [ 114 ] = 234, -- r --> к [ 115 ] = 251, -- s --> ы [ 116 ] = 229, -- t --> е [ 117 ] = 227, -- u --> г [ 118 ] = 236, -- v --> м [ 119 ] = 246, -- w --> ц [ 120 ] = 247, -- x --> ч [ 121 ] = 237, -- y --> н [ 122 ] = 255, -- z --> я [ 123 ] = 213, -- { --> Х [ 125 ] = 218, -- } --> Ъ } 1 1 Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 23 Сентября 2015 (изменено) ...если это не CUIEditBox из Сталкера. нет, это именно оттуда ...если это не CUIEditBox из Сталкера. а, если это не это, то и вообще проблем нет. т.к. уже прозвучали намёки на флуд с моей стороны, то привожу полный код скрипта,который реализует всё о чём я сказал в сообщении #55.Код таблицы перекодировки я уже приводил раньше. В скрипте она подключается из внешнего файла (мне так удобнее). --[[--------------------------------------------------ui_money_wnd.scriptAuthors: Serge!Version: 1.02015------------------------------------------------------Описание:Ввод кириллицы в EditBoxПлатформа: ТЧ (1.0.0.4)Используется: внешний файл com_dlg.script------------------------------------------------------Содержание:Необходим скрипт com_dlg.script--]]---------------------------------------------------- Предопределённые данныеlocal t_lang = com_tbl.tbl_ansii-- точка входа из внешних скриптов (ui_money_wnd.main())function main()super_dlg = ui_test_edit_wnd.ui_test_edit()level.start_stop_menu(super_dlg, true)end-- определяем класс и активируем егоclass "ui_test_edit" (CUIScriptWnd)function ui_test_edit:__init() super()self:InitControls()self:InitCallBacks()endfunction ui_test_edit:__finalize() end-- инициализируем элементы и переменные классаfunction ui_test_edit:InitControls()self:Init(400,325,240,103)local xml = CScriptXmlInit() -- создаем класс для файла описанияxml:ParseFile("ui_edit_wnd.xml") -- подключаем файл описания элементов окнаxml:InitStatic("edit_dlg_fon", self) -- устанавливаем статик фона-- регистрируем элементы окна-- кнопкиlocal ctrl = xml:Init3tButton("edit_btn_exit", self) -- Отменаself:Register(ctrl, "btn_1")self.btn_lan = xml:Init3tButton("edit_btn_lan", self) -- язык вводаself.mode_lang = trueself.btn_lan:SetText("Рус")self:Register(self.btn_lan, "btn_2")local ctrl = xml:Init3tButton("edit_btn_clr", self) -- очистить полеself:Register(ctrl, "btn_3")-- поле вводаself.str_edit = xml:InitEditBox("edit_str", self)self:Register(self.str_edit, "str_edit")endfunction ui_test_edit:InitCallBacks()self:AddCallback("btn_1", ui_events.BUTTON_CLICKED, self.OnButton_CANCEL, self)self:AddCallback("btn_2", ui_events.BUTTON_CLICKED, self.OnButton_LANG, self)self:AddCallback("btn_3", ui_events.BUTTON_CLICKED, self.OnButton_CLEAR, self)self:AddCallback("str_edit", ui_events.EDIT_TEXT_CHANGED, self.OnEdit_CHANGED, self)end-- выбор языкаfunction ui_test_edit:OnButton_LANG()self.mode_lang = not self.mode_langif self.mode_lang then self.btn_lan:SetText("Рус")else self.btn_lan:SetText("Eng") endend-- поле вводаfunction ui_test_edit:OnEdit_CHANGED()local txt = self.str_edit:GetText()if self.mode_lang thenlocal copy_txt, cls = ""for n = 1, string.len(txt) docls = string.byte(txt, n)if t_lang[cls] ~= nil then copy_txt = copy_txt..string.char(t_lang[cls])else copy_txt = copy_txt..string.char(cls) endendself.str_edit:SetText(copy_txt)endend-- очистить поле вводаfunction ui_test_edit:OnButton_CLEAR()self.str_edit:SetText("")end-- Выйтиfunction ui_test_edit:OnButton_CANCEL()level.start_stop_menu(self, true)end-- клавишыfunction ui_test_edit:OnKeyboard(dik, keyboard_action)CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)local bind = dik_to_bind(dik)local console = get_console()if keyboard_action == ui_events.WINDOW_KEY_PRESSED thenif dik == DIK_keys.DIK_ESCAPE thenself:OnButton_CANCEL()endendreturn trueendP.S. Это упрощённая демо-версия. В реальной жизни он немного усложнен проверками на ввод смешанного текста, но это уже частности.забыл вставить каритнку с результатом.http://j-p-g.net/if/2015/09/25/0141137001443202007.jpg Изменено 14 Октября 2015 пользователем Black Hawk Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 13 Октября 2015 (изменено) Класс "Список_Значений" а-ля 1С. Все описания и инструкции в коде, поэтому длинновато. --[[-------------------------------------------------- valueList.script Authors: Serge! Version: 1.0 ------------------------------------------------------ Description: Класс "СписокЗначений" ------------------------------------------------------ Connection: Тип "значения" допускается только string или number. Перед использованием во внешних скриптах объект класса valueList необходимо создать командой: valst = valueList and valueList.valueList([mode, nameFile]) or nil Параметры: . <mode, nameFile> - Необязательные. mode - флаг режима пред/пост формирования списка. True - при создании экземпляра класса, список заполняется содержанием из файла указанного в <nameFile>. False - перед очисткой, содержание списка сохраняется в файле <nameFile>. --]]-------------------------------------------------- -- локальные параметры и функции local lst = {} local curID = 0 local isValue = function(val) return (val and (type(val) == "string" or type(val) == "number")) and true or false end local isBool = function(var) return var ~= nil and var ~= 0 and var ~= false and var ~= '' end local defDir = '$fs_root$\\' local SOC = system_ini():r_string("script","current_server_entity_version") < '8' -- true - ТЧ; false - ЧН, ЗП local getRandName = function() return (tostring(function() end):gsub('.','',10)) end -- определение и инициализация класса class "valueList" function valueList:__init(mode, nameFile) if isBool(nameFile) then self.mode = mode self.nameFile = nameFile if mode then self:Restore(nameFile) end end end function valueList:__finalize() if isBool(self.nameFile) and not self.mode then self:Save(self.nameFile) end end --[[ Определить размер списка. Позволяет определить общее количество элементов в списке. Возвращает численное значение или 0 для пустого списка ]] function valueList:GetListSize() return #lst end --[[ Позволяет установить (если требуется) и/или считать текущее значение шндекса строки списка. Возвращает текущее значение индекса до его изменения. Если заданное значение больше размера списка, то индекс не изменяется Параметры: <ns> - Необязательный параметр. Новое текущее значение индекса в списке. Возвращаемое значение: текушая позиция ]] function valueList:CurSel(ns) local old = curID curID = (ns and ns <= #lst) and ns or old return curID end --[[ Добавить значение в список. Метод добавляет значение и его символьное представление в конец списка. Символьное представление значения должно быть уникальным. Если такое представление уже есть в списке, то значение не добавляется. Параметры: <val> - Выражение со значением, которое добавляется в список. <str> - Необязательный параметр. Строка, содержащая задаваемое символьное представление добавляемого значения. Если опущен, то строка заполняется значением по умолчанию. Возвращаемое значение: true - действие выполнено; false - нет. ]] function valueList:AddValue(val, str) local out = false if isValue(val) and not isBool(self:FindName(str)) then table.insert(lst,{}) curID = #lst lst[curID].val = val; lst[curID].name = str or tostring(type(val))..'_'..tostring(curID) out = true end return out end --[[ Вставить значение в указанную позицию списка. Добавляет значение и его символьное представление в указанную позицию списка заданное число раз. Если заданная позиция превышает размер списка, то значения вставляются в его конец. Символьное представление значения должно быть уникальным. Если такое представление уже есть в списке, то значение не добавляется. Параметры: <val> - Выражение со значением, которое добавляется в список. <str> - Необязательный параметр. Строка, содержащая задаваемое символьное представление добавляемого значения. Если опущен, то строка заполняется значением по умолчанию. <pos> - Необязательный параметр. Номер позиции в вписке, начиная с которой будут вставляться значения. Если больше длины списка или опушен, то в конец. <num> - Необязательный параметр. Количество повторов. Если опущен, то 1 Возвращаемое значение: true - действие выполнено; false - нет. ]] function valueList:InsertValue( val, str, pos, num) local out if isValue(val) and not isBool(self:FindName(str)) then num = num and num or 1 pos = (pos and pos <= #lst) and pos or #lst + 1 for i = 1, num do table.insert(lst,pos,{}) lst[pos].val = val; lst[pos].name = str or tostring(type(val))..'_'..tostring(curID) pos = pos + 1 end out = true end curID = #lst return isBool(out) end --[[ Определить номер позиции в списке для элемента, имеющего заданное значение. С помощью метода FindValue можно определить номер позиции в списке для элемента, имеющего значение <val>. Строка с найденным элементом становится текущей. Параметры: <val> - Выражение со значением, которое требуется найти в списке. Возвращаемое значение: Номер позиции в списке, где расположено требуемое значение. Если значение не найдено, то — 0. ]] function valueList:FindValue(val) local out = 0 if isValue(val) then for k,v in pairs(lst) do if v.val == val then curID = k return k end end end return out end --[[ Определить номер позиции в списке для элемента, имеющего заданное символьное представление значения. С помощью метода FindValue можно определить номер позиции в списке для элемента, имеющего значение <name>. Строка с найденным элементом становится текущей. Параметры: <name> - Выражение содержащее символьное представление значения, которое требуется найти в списке. Возвращаемое значение: Номер позиции в списке, где расположено требуемое значение. Если не найдено, то — 0. ]] function valueList:FindName(name) local out = 0 for k,v in pairs(lst) do if v.name == name then curID = k return k end end return out end --[[ Получить значение элемента по его индексу в списке. Метод находит и возвращает значение находяшееся в заданной позиции. Позиция найденного значения становится текущей. Параметры: <id> - Числовое выражение — номер элемента в списке, значение которого будет возвращено. Номер позиции может быть от 1 до количества элементов в списке. <str> - Идентификатор переменной в которую (если передан) будет возвращено строковое выражение, содержащее символьное представление получаемого значения. Возвращаемое значение: Полученное значение из списка или nil. ]] function valueList:GetValueById(id, str) local out = nil if lst[id] then out = lst[id].val if str then str = lst[id].name end curID = id end return out end --[[ Получить символьное представление элемента по его индексу в списке. Метод находит и возвращает символьное представление элемента находяшегосяся в заданной позиции. Позиция найденного значения становится текущей. Параметры: <id> - Числовое выражение — номер элемента в списке, значение которого будет возвращено. Номер позиции может быть от 1 до количества элементов в списке. Возвращаемое значение: Полученное символьное представление или пустая строка. ]] function valueList:GetNameById(id) local out = '' if lst[id] then out = lst[id].name; curID = id end return out end --[[ Установить значение в указанной позиции списка. Метод устанавливает значения и его символьные лредставления элементов, начиная с указанной позиции списка, заданное число повторов. Имеющиеся в списке до вызова метода значения, будут заменнены. Если позиция больше размера списка, то значения будут добавлены в конец. Текущей становится позиция последнего вставленного элемента. Параметры: <pos> - Номер позиции в вписке, начиная с которой будут устанавливаться значения. Если больше длины списка, то в конец. <val> - Выражение со значением, которое устанавливается в список. <str> - Необязательный параметр. Строка, содержащая задаваемое символьное представление значения. Если опущен, то строка заполняется значением по умолчанию. <num> - Необязательный параметр. Количество повторов. Если опущен, то 1 Возвращаемое значение: нет. ]] function valueList:SetValue(pos, val, str, num) if isValue(val) and not isBool(self:FindName(str)) then num = num and num or 1 pos = (pos and pos <= #lst) and pos or #lst + 1 for i = 1, num do if pos > #lst then table.insert(lst,{}) end lst[pos].val = val; lst[pos].name = str or tostring(type(val))..'_'..tostring(curID) pos = pos + 1 end curID = pos - 1 end end --[[ Получить значение элемента по указанному символьному представлению. Метод возвращает значение по указанному представлению. Если значения с таким представлением нет, то возвращается пустое значение. Параметры: <str> - Строка, содержащая задаваемое символьное представление значения. Возвращаемое значение: Значение из списка или nil. ]] function valueList:Get(str) local out = nil for k,v in pairs(lst) do if v.name == str then return v.val end end return out end --[[ Установить значение с указанным представлением. Метод устанавливает в списке значение с указанным представлением, если значение с таким представлением уже есть — изменятеся значение, если нет — добавляется в конец списка значение с указанным представлением. Параметры: <str> - Строка, содержащая задаваемое символьное представление значения. <val> - Выражение со значением, которое устанавливается в список. Возвращаемое значение: Нет. ]] function valueList:Set(str, val) if isValue(val) then for k,v in pairs(lst) do if v.name == str then v.val = val return end end table.insert(lst,{}) curID = #lst; lst[curID].val = val; lst[curID].name = str end end --[[ Удалить значение в указанной позиции списка. Метод удаляет заданное количество значений, начиная с указаний позиции. Параметры: <pos> - Числовое выражение — номер позиции в списке, начиная с которой будут удалены значения. Номер позиции может быть от 1 до количества элементов в списке. <num> - Необязательный параметр. Числовое выражение — количество повторов. По умолчанию — 1. Возвращаемое значение: Нет. ]] function valueList:RemoveValue(pos, num) num = num and num or 1 local endPos = ((pos+num-1) <= #lst) and pos+num-1 or #lst for i = pos, endPos do table.remove(lst, i) end curID = pos end --[[ Удалить все элементы спискаа. Метод удаляет все элементы списка. Параметры: Нет Возвращаемое значение: Нет. ]] function valueList:RemoveAll() curID = 0 lst = {} end --[[ Проверяет вхождение в список указанного значения. Метод оптимизирует проверку принадлежности при массовых последовательных сравнениях, если между сравнениями сам список значений не меняется. Параметры: <val> - Выражение со значением, которое проверяется на вхождение в список. Возвращаемое значение: true — если проверяемое значение входит в список; false — если не входит. ]] function valueList:ValueInList(val) return isBool(self:FindValue(val)) end --[[ Проверяет вхождение в список указанного символьного представления. Метод оптимизирует проверку принадлежности при массовых последовательных сравнениях, если между сравнениями сам список значений не меняется. Параметры: <name> - Выражение со значением символьного представления, которое проверяется на вхождение в список. Возвращаемое значение: true — если проверяемое представление входит в список; false — если не входит. ]] function valueList:NameInList(name) return isBool(self:FindName(name)) end --[[ Загрузить/выгрузить список сначений. Метод позволяет загрузить или выгрузить список значений в другой список. Можно задать начальные индекси строк и их количество. Параметры: <list> - Значение типа "Список значений", в которое нужно загрузить/выгрузить данные. Если переданное значение пустое (nil), то при выгрузке будет создан новый объект типа «Список значений». При выгрузке в этот параметр будет помещен список с добавленными позициями. <mode> - Флаг устанавливающий направление: true - загрузка; false - выгрузка. <pos_b> - Необязательный параметр. Индекс начальной позиции в базовом списке, с которой надо начинать загрузку/выгрузку. Значение по умолчанию: 1 - при выгрузке; длина_списка+1 - при загрузке. <pos_c> - Необязательный параметр. Индекс начальной позиции в подключаемом списке, с которой надо начинать загрузку/выгрузку. Значение по умолчанию: длина_списка+1 - при загрузке в него; 1 - при выгрузке из него. <num> - Необязательный параметр. Числовое выражение — количество загружаемых/выгружаемых строк. По умолчанию — весь список. Возвращаемое значение: true — если операция успешна; false — если нет. ]] function valueList:LoadUnload(list, mode, pos_b, pos_c, num) list = (list and type(list) == "table") and list or {} if mode and not isBool(#list) then return false end pos_b = pos_b and pos_b or (mode and 1 or #tbl+1) pos_c = pos_c and pos_c or (mode and #list or 1) local source, pos_source = mode and list or tbl, mode and pos_c or pos_b -- источник local sink, pos_sink = mode and tbl or list, mode and pos_b or pos_c -- приемник num = num and num or (mode and #list or #tbl) for n = 1, num do table.insert(sink,pos_sink,{}) sink[pos_sink].var = source[pos_source].var; sink[pos_sink].name = source[pos_source].name pos_sink = pos_sink + 1; pos_source = pos_source + 1 end if not mode then list = sink end return true end --[[ Сохранить список во внешний файл. Метод сохраняет список значений в текстовый файл на диске. Если функции в качестве параметра передается полное имя файла, то файл сохраняется в заданной папке. Если передается только имя, то в корневой папке с установленной игрой (папка по умолчанию). Если файл с таким именем уже существует, то он будет перезаписан без каких-либо запросов и подтверждений. Если параметр имени файла опущен, то имя файла будет сгенерировано автоматически (это приемлемо только при отладке, т.к. для использования такого имени требуется правка текста этого или вызываюшего скрипта). Файл будет сохраняться в папке по умолчанию. Параметры: <nf> - Строка, содержащая имя сохраняемого файла или nil. Возвращаемое значение: true — если операция успешна; false — если нет. Примечание: Для ТЧ требуется наличние пакета RvP. Если его нет, то вылетов не будет, но и никаких действий произведено тоже не будет. ]] function valueList:Save(fn) local out = false if SOC and m_netpk and not isBool(_G.io) then RvP() else return out end if not isBool(fn) then fn = defDir..getRandName()..'.vlt' end -- генерируем случайное имя local fs = io.open(fn,'w') if isBool(fs) then local str, tv for k,v in pairs(lst) do tv = (type(v.val) == 'string') and 's' or 'n' str = string.format("%s|%s|%s\n",tv,tostring(v.val),v.name) fs:write(str) end fs:flush() fs:close() out = true end return out end --[[ Восстановить список из внешнего файла. Метод восстановить список значений из ранее сохраненного текстовый файла на диске. Если функции в качестве параметра передается полное имя файла, то файл восстанвливается из файла в заданной папке. Если передается только имя, то из корневой папки с установленной игрой (папка по умолчанию). Если файл с таким именем нет, то никаких действий не производится. Параметры: <nf> - Строка, содержащая имя файла. Возвращаемое значение: true — если операция успешна; false — если нет. Примечание: Для ТЧ требуется наличние пакета RvP. Если его нет, то вылетов не будет, но и никаких действий произведено тоже не будет. ]] function valueList:Restore(fn) local t = {} if not isBool(_G.io) then if m_netpk then RvP() else return t end end local fs = io.open(fn,'r') if isBool(fs) then fs:close() local tstr for line in io.lines(fn) do tstr = {} for par in line:gfind("%s*([^|]+)%s*") do table.insert(tstr,par) end table.insert(t,{}) t.val = tstr[1] == 's' and tstr[2] or tonumber(tstr[2]) t.name = tstr[3] end fs:close() end return t end Если подобное кому-то надо, то оформю в соответствии с правилами форума аналогичный "Таблица_Значений".У него функционал поболее. Изменено 20 Октября 2015 пользователем Murarius Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 20 Ноября 2015 набор инструментов управляемого массового спавна/респавна надо кому?...< пропущено > ... Хотя с другой стороны это же банальщина которую наверняка каждый сам сделал. Если смотреть со стороны вас - профи, то, как было отмечено, они "могут и помидорами закидать". А, если смотреть с другой стороны, тех которые только начинают в этом разбирать, то это очень даже хорошо и полезно. На чём же они еще могут учиться? Я думаю, что эта ветка форума в основном и должна быть сориентирована именно на эту категорию. Выкладывайте, кому-то обязательно пригодится. 1 Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 16 Декабря 2015 (изменено) Расширение базовой библиотеки Lua string. Наверное такое будет полезно начинающим и тем кто не очень себя уверенно чувствует в применении шаблонов. Остальные могут пропустить. Если требуется подробное описание и примеры применения, то (они у меня есть, но это занимает значительный объем) могу добавить и это. --[[-------------------------------------------------- _s.script Authors: Serge! Version: 1.0 2015 ------------------------------------------------------ Описание: Расширение таблицы string стандартной библиотеки Lua "Работа со строками" (string manipulation). Для любой "чистой" платформы "Сталкера" с версией Lua не ниже 5.1 и модификаций игр на их основе. Вызовы функций производятся способами принятыми при работе со строковыми данными: sting.Метод(str [,arg]) или str:Метод([arg]). Все передаваемые аргументы проверяются/приводятся к требуемому типу. Легко расширяется при появлении дополнительных потребностей или, наоборот, урезается до требуемого уровня. Для этого надо просто добавить новые функции или закомментировать/удалить имеющиеся. Также допускается выборочное использование отдельных функций или только их содержательного наполнения. ------------------------------------------------------ Подключение: Поместить данный файл в папку gamedata\scripts\ с установленной игрой. В любой из скриптов, которые запускаются при загрузке/старте игры, или скрипт, где планируется использование этих методов, добавить строки: if not sstring then dofile(getFS():update_path("$game_data$","scripts\\_s.script")) end --]]-------------------------------------------------- ---- глобальная переменная (флаг подключения) sstring = true ---- локальные переменные local tblW = function (str) t = {}; for w in tostring(str):gmatch("%s-(%S+)%s-") do t[#t+1] = w end; return t end local ssep = [[!@#$%*.:;,-?/|\]] ---- строка (последовательность символов между началом и концом строки) -- Проверить строку на наличие значащих символов (не пустая строка) --function string.sNotBlk(s) return (tostring(s):find('%S')) and true or false end string.sNotBlk = function(s) return (tostring(s):find('^(%S)')) and true or false end -- Отбросить в строке стоящие слева пробелы string.sTrimL = function(s) return (tostring(s):gsub("^%s+",'')) or s end -- Отбросить в строке стоящие справа пробелы string.sTrimR = function(s) return (tostring(s):gsub("%s*$",'')) or s end -- Отбросить в строке пробелы, стоящие слева и справа string.sTrim = function(s) return (tostring(s):gsub('^%s*(.-)%s*$', '%1')) or s end -- Выбрать в строке символы слева string.sLeft = function(s, n) return tostring(s):sub(1,tonumber(n)) or s end -- Выбрать в строке символы справа string.sRight = function(s, n) return tostring(s):sub(tonumber(-n)) or s end -- Выбрать подстроку string.sMid = function(s, ind ,n) s,ind,n = tostring(s),tonumber(ind),tonumber(n); return (n and s:sub(ind,ind+n-1) or s:sub(ind)) or s end -- Преобразовать строку в массив входящих в неё символов string.sArrayCh = function(s) t = {}; for w in tostring(s):gmatch('.') do table.insert(t,w) end; return t end -- Преобразовать строку в массив кодов входящих в неё символовв string.sArrayCode = function(s) t = {}; for ch in tostring(s):gmatch('.') do table.insert(t,string.byte(ch)) end; return t end -- Получить строку кодов входящих в неё символов string.sStrCode = function(s) t = {}; for ch in tostring(s):gmatch('.') do table.insert(t,string.byte(ch)) end; return string.sNotBlk(s) and '\\'..table.concat(t,'\\') or t end ---- символ (символ или последовательность любых символов, если противное специально не оговорено) -- Получить количество вхождений символа (символов) в строку string.sCountCh = function(s, ch) _,b = tostring(s):gsub(tostring(ch), ''); return b or 0 end -- Получить первое вхождение символа (подстроки) в строку string.sFindCh = function(s, ch) return (tostring(s):find(tostring(ch))) or 0 end -- Получить все вхождения символа (последовательности символов) в строку string.sFindChAll = function(s, ch, mode) local s,ch,n,t,p = tostring(s),tostring(ch),1,{}; repeat p = (s:find(ch,n)); if p then table.insert(t,p) n = p+#ch else n = n+#s end until n>#s; return #t>0 and (mode and table.concat(t,',') or t) or (mode and '' or t) end -- Получить символ в заданной позиции строки string.sGetCh = function(s, ind) return tostring(s):match('.', tonumber(ind)) or '' end -- Вставить символ (символы) в заданную позицию строки string.sInsCh = function(s, ch, ind) s = tostring(s); ind = tonumber(ind) return s:sLeft(ind-1)..tostring(ch)..s:sRight(#s-ind+1) end -- Заменить первое вхождение символа (последовательность символов) в строке на заданный символ (последовательность символов) string.sRepCh = function(s, sm, srp) rep = srp and tostring(srp) or ''; return (tostring(s):gsub(tostring(sm), rep, 1)) or s end -- Заменить все вхождения символа (или последовательности символов) в строке на заданный символ (последовательность символов) string.sRepChAll = function(s, sm, srp) rep = srp and tostring(srp) or ''; return (tostring(s):gsub(tostring(sm), rep)) or s end -- Заменить символ (последовательность символов) в заданной позиции строки string.sRepChInd = function(s, sm, ind) t = s:sArrayCh(); t[tonumber(ind)] = tostring(sm); return table.concat(t) or s end -- слово (последовательность символов ограниченная пробелами, а также началом и концом строки) string.sCountW = function(s) return #tblW(s) or 0 end -- Получить массив слов string.sArrayW = function(s) return tblW(s) end -- Получить первое слово string.sFirstW = function(s) return tostring(s):match('^%s?(%S+)%s') or s end -- Получить последнее слово string.sLastW = function(s) return tostring(s):match("(%S+)%s-$") or s end -- Получить слово по индексу string.sMidW = function(s, ind) id = tonumber(ind); return s:sArrayW()[id <= sCountW(s) and id or 0] or '' end -- Удалить первое слово string.sclrFirstW = function(s) return tostring(s):gsub("%s-(%S+)%s+",'',1) or s end -- Удалить последнее слово string.sclrLastW = function(s) return tostring(s):gsub("%s+(%S+)%s-$",'',1) or s end -- Удалить слово по индексу string.sclrMidW = function(s,ind) t = tblW(s); table.remove(t,tonumber(ind) or 0); return table.concat(t,' ') or s end -- подстрока -- Проверить строку на наличие символов разделителей (из заданного набора) string.sIsSep = function(s) return (tostring(s):find('['..ssep..']')) and true or false end -- Проверяет есть ли разделитель из заданного набора в определённой позиции строки string.sIsSepInd = function(s,ind) return ((ssep:find(tostring(s):match('.',tonumber(ind))))) and true or false end -- Проверяет является ли символ в позиции строки из заданного набора string.sIsChSep = function(ch) return (ssep:find(tostring(ch))) and true or false end -- Получить количество подстрок в строке с разделителем string.sCountSep = function(s, ss) _,b = tostring(s):gsub(tostring(ss),''); return b end -- Получить массив подстрок из строки с разделителем string.sArraySub = function(s, sep) t = {}; sep = sep and tostring(sep) or ','; for w in tostring(s):gfind("%s*([^"..sep.."]+)%s*") do table.insert(t,w:sTrim()) end; return t end -- Получить подстроку по индексу из строки с разделителями string.sSubInd = function(s, sep, ind) return tostring(s):sArraySub(sep)[tonumber(ind)] or '' end -- Вставить подстроку в строку с разделителями в заданную позицию string.sInsSub = function(s, sub, ind) t = s:sArraySub(); table.insert(t, tostring(sub), tonumber(id)); return table.concat(t) or s end -- Преобразовать строку в массив подстрок заданной длины (без разделения слов) string.sText = function(s, n) local rez = {} for sub in tostring(s):gmatch("([^%\n]+)") do rez[#rez+1] = sub end if not n then return rez end local st, t, len, start, last = {} for _,sub in pairs(rez) do t, len, start, last = sub:sArrayW(), 0, 1, 1 while last <= #t do len = len + #t[last] if len >= n then st[#st+1] = table.concat(t,' ', start, last-1); len, start = 0, last else last = last + 1; len = len + 1 end end st[#st+1] = table.concat(t,' ', start) end return st end и ещё одна функция (чуть подправил под общий стиль) от Artos, которую вычитал где-то в старых постах на этом ресурсе -- Artos --/ конвертер числа (number) в 'dec' или 'hex' строку (string) string.Num2Str = function(iNum) --/< любое число, применяемое в игре Сталкер if iNum == math.modf(iNum) then --/ целочисленное? local iAbs = math.abs(iNum) --/ модуль числа if iAbs > 9 then --/ число 2-x и более разрядное? --/ степень ближайшего к модулю бОльшего числа кратного 10-ти local iLv = math.floor(math.log10(iAbs+1)) if iAbs >= 10^iLv and iAbs < 2^(4*iLv) then --/ разрядность 'dec' > 'hex'? if iNum >= 0 then --/ не отрицательное? return string.format('%X', iAbs) --/> 'hex'-строка end --/ отрицательное - упаковываем со знаком return "-" .. string.format('%X', iAbs) --/> 'hex'-строка со знаком end end end return tostring(iNum) --/> 'dec'-строка end Описание к функциям из этого поста, от автора: https://yadi.sk/d/3e6oJoTVsbAgp Изменено 18 Июня 2016 пользователем Zander_driver 3 Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 17 Августа 2016 (изменено) Недавно, просматривая старые публикации, наткнулся на некоторые проблемы сообщества, которые я для себя уже давно решил. Привёл эти, некоторые, свои решения в удобочитаемый вид и решил выложить (постепенно, разумеется).Проблема 1. ComboBox для ТЧ (и ЧН я так думаю) Уже в далёком 2010 году Malandrinus в своём классичесом посте об оконных классах написал: : "CUIComboBox - выпадающий список. В ТЧ есть, но недоэкспортирован, в связи с чем применять его можно только в ЗП". И он был прав. В том же году IQDDD сказал: "а по идее можно создать собственный ComboBox, используя классы CUIButtonWnd, CUIStaticWnd и CUIListWnd.". И тоже был прав. А вот далее много лет т и ш и н а! Но ведь это действительно не так уж и сложно. Например, можно сделать так. Можно, если нет желания замарачиваться с текстурами, использовать визуал ComboBox из ТЧ (gamedata\textures\ui\ui_common.dds). Но, он мне не нравится и поэтому я использую, чуть подправленный, аналог из ЗП (файл dds есть в секции ссылок). Однако, в любом случае, требуется файл описания текстур. В моём случае он имеет вид: <ui_texture> <!-- файл текстуры --> <file_name>ui\ui_ComboBoxEx</file_name> <!-- фон поля текста --> <texture id="ui_cbEx_text" x="1" y="0" width="38" height="19" /> <!-- кнопка --> <texture id="ui_cbEx_btn" x="45" y="0" width="19" height="19" /> <!-- фон списка --> <texture id="ui_cbEx_list" x="1" y="1" width="38" height="17" /> </ui_texture> Ну и наконец сам сприпт класса ComboBoxEx: --[[-------------------------------------------------- ui_ComboBoxEx.script Authors: Serge! Version: 1.0 Date: 2016 ------------------------------------------------------ Описание: Платформа - ТЧ ver 1.004 (без расширений) ------------------------------------------------------ Содержание: Класс (псевдо) ComboBoxEx (поле с выпадающим списом для ТЧ) ------------------------------------------------------ Необходимые файлы: gamedata\scripts\ui_ComboBoxEx.script, gamedata\config\ui\ui_ComboBoxEx.xml, gamedata\textures\ui\ui_ComboBoxEx.dds --]]-------------------------------------------------- -- класса строки выпадающего списка class "cb_item" (CUIListItemEx) function cb_item:__init() super() self.sn = CUIStatic() self:AttachChild(self.sn) self.sn:ClipperOn() self.sn:SetFont(GetFontLetterica16Russian()) end function cb_item:__finalize() end -- скрытые члены класса local tcb = { own = nil, X = 0, y = 0, width = 0, height = 19, listSize = 0, itemScroll = 4, listHeight = 73, showList = false, vScroll = true, enable = true, show = true, autoDelete = true, wndName = "", ComBox = nil, curItem = 0, cbTxt = nil, cbList = nil, frmList = nil, cbBtn = nil, } -- скрытые методы класса -- добавить строку в список local function InstItem(text) local _itm = cb_item() _itm.sn:SetWndRect(2,0, tcb.width-22,18) _itm.sn:SetTextColor(255,216,186,140) _itm.sn:SetText(tostring(text)) tcb.cbList:AddItem(_itm) end -- показать/скрыть список local function DidplayHideList() tcb.showList = not tcb.showList tcb.frmList:Show(tcb.showList) end -- показать текущий выбор local function ShowCurID() tcb.curItem = tcb.cbList:GetSelectedItem() local str = tcb.cbList:GetItem(tcb.curItem) tcb.cbTxt:SetText(str.sn:GetText()) end -- вернуть выбор в списке (от 1 до ListSize) local function GetItemList() DidplayHideList() tcb.own:GetComboBox(tcb.curItem+1) end -- определение класса/конструктор class "ComboBoxEx" (CUIScriptWnd) function ComboBoxEx:__init(owner) super() tcb.own = owner self:SetAutoDelete(true) tcb.ComBox = CUIStatic() tcb.ComBox:SetAutoDelete(tcb.autoDelete) owner:AttachChild(tcb.ComBox) end -- деструктор function ComboBoxEx:__finalize() end -- публичные методы класса -- инициализация function ComboBoxEx:Init(x,y,w) tcb.x = x; tcb.y = y; tcb.width = w -- полный ComboBox с раскрытым списком tcb.ComBox:Init(x,y,w,tcb.listHeight+tcb.height) local ctl -- поле полоски текста ctl = CUIStatic() ctl:Init(0,0,tcb.width-tcb.height,tcb.height) tcb.ComBox:AttachChild(ctl) ctl:InitTexture("ui_cbEx_text") ctl:SetStretchTexture(true) -- поле самого текста tcb.cbTxt = CUIStatic() ctl:AttachChild(tcb.cbTxt) tcb.cbTxt:Init(5,1,tcb.width-tcb.height-7,17) -- кнопка раскрытия/свёртования списка ctl = CUIButton() tcb.ComBox:AttachChild(ctl) ctl:Init(tcb.width-tcb.height,0,tcb.height,tcb.height) ctl:InitTexture("ui_cbEx_btn") self:Register(ctl,"but_cb") -- прерывание кнопки self:AddCallback("but_cb", ui_events.BUTTON_CLICKED, DidplayHideList) -- поле вывода списка tcb.frmList = CUIStatic() tcb.frmList:Init(0,tcb.height,tcb.width,tcb.listHeight+5) tcb.ComBox:AttachChild(tcb.frmList) tcb.frmList:InitTexture("ui_cbEx_list") tcb.frmList:SetStretchTexture(true) tcb.frmList:Show(showList) -- сам список tcb.cbList = CUIListWnd() tcb.frmList:AttachChild(tcb.cbList) tcb.cbList:Init(3,3,tcb.width-5,tcb.listHeight) tcb.cbList:SetItemHeight(18) tcb.cbList:Enable(true) tcb.cbList:EnableScrollBar(true) tcb.cbList:ShowSelectedItem(true) self:Register(tcb.cbList,"list_wnd") -- прерывания списка self:AddCallback("list_wnd", ui_events.LIST_ITEM_CLICKED, ShowCurID) self:AddCallback("list_wnd", ui_events.WINDOW_LBUTTON_DB_CLICK, GetItemList) end -- добавление строки/массива строк в список function ComboBoxEx:AddComBox(text) if type(text) == "table" then for _, value in pairs(text) do InstItem(value) end tcb.listSize = tcb.listSize + #text elseif text ~= nil then InstItem(text) tcb.listSize = tcb.listSize + 1 end end -- возврат текущией позиции в списке ( от 1 до size) function ComboBoxEx:CurrentID() return (tcb.curItem + 1) end -- установить режим доступа к полю ComboBox function ComboBoxEx:Enable(val) tcb.enable = val tcb.ComBox:Enable(tcb.enable) end -- получить режим доступа к полю ComboBox function ComboBoxEx:IsEnable() return tcb.enable end -- установить режим вывода поля ComboBox function ComboBoxEx:Show(val) tcb.show = val tcb.ComBox:Show(tcb.show) end -- получить режим вывода поля ComboBox function ComboBoxEx:IsShow() return tcb.show end Просто скопировать файлы в соответствуюшие папки с установленной игрой. В Родительском скрипте определяем переменную класса ComboBoxEx (см. код примера) и после этого получаем 2 основных метода (их чуть больше, но я не усерствовал):1. Инициализации - Init()2. Формирование выпадающего списка - AddComBox()Также в родительском скрипте необходимо создать метод получения результатов монипуляций с ComboBox. Это функция с предопределённым именем GetComboBox(numItem).Данная реализация предоставляет следующие методы (я сам использую только 3 основных и поэтому мне их писать было просто лениво):1. ComboBoxEx(self) - определение класса2. Init(x,y,w) - инициализация3. AddComBox(text) - добавление строки/массива строк в список (text - string или table)4. number CurrentID() - возврат текущией позиции в списке ( от 1 до size)5. Enable(bool val) - установить режим доступа к полю ComboBox6. bool IsEnable() - получить режим доступа к полю ComboBox7. Show(bool val) - установить режим вывода поля ComboBox8. bool IsShow() - получить режим вывода поля ComboBoxЕсли Вам надо больше, то Вы можете легко, по данному шаблону, добавить свои. Это пример использования данного класса. --[[-------------------------------------------------- ui_test_cb.script Authors: Serge! Version: 1.0 Date: 2016 ------------------------------------------------------ Описание: Платформа - ТЧ ver 1.004 (без расширений) ------------------------------------------------------ Содержание: Пример использования класса ComboBoxEx (поле с выпадающим списом для ТЧ) ------------------------------------------------------ Необходимые файлы: gamedata\scripts\ui_test_cb.script, gamedata\scripts\ui_ComboBoxEx.script, gamedata\config\ui\ui_ComboBoxEx.xml, gamedata\textures\ui\ui_ComboBoxEx.dds, gamedata\textures\ui\ui_pda.dds --]]-------------------------------------------------- -- точка входа из внешних скриптов -- или вызываем так: ui_test_cb.test_cb() function main() ui_test_cb.test_cb() end -- локальные переменные local cb -- надёжнее всегда её делать внешней локальной, а не внутри конструктора -- определяем класс окна и активируем его class "test_cb" (CUIScriptWnd) function test_cb:__init() super() -- создаём фон self:SetFont(GetFontMedium()) self:SetWndRect(312,150,400,543) local fon = CUIStatic() fon:SetAutoDelete(true) self:AttachChild(fon) fon:Init(0,0,400,543) fon:InitTexture("ui\\ui_pda") -- это просто ПДА из дистрибутива, которое просто повернуто на 90 гр. fon:SetStretchTexture(true) -- определяем элемент класса ComboBox cb = ui_ComboBoxEx.ComboBoxEx(self) cb:SetAutoDelete(true) cb:Init(65,60,280) -- можно задать любые (в пределах разумного) -- вставим несколько строк (массивом) cb:AddComBox({"String 1","String 2","String 3","String 4","String 5"}) -- покажем всё это level.start_stop_menu(self, true) end function test_cb:__finalize() end -- обработка результата манипуляций в ComboBox (должна быть обязательно! и именно с таким именем) function test_cb:GetComboBox(numItem) -- просто выводим сообщение с результатом news_manager.send_tip(db.actor, "Строка из ComboBox: "..tostring(numItem)) end P.S. Напоминаю, что в любом случае имя файла описания текстур требуется добавить в секцию [texture_desc] файла system.ltx https://yadi.sk/d/YlzEnHHCuGgWj https://disk.yandex.ru/client/disk Изменено 17 Августа 2016 пользователем Serge! 1 6 Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 17 Августа 2016 (изменено) @Карлан, Наверное Вы и правы, но я пользуюсь таким давно и без всяких нареканий и последствий. А править движок? я хоть и могу это, но не делаю такого принципиально (у каждого в голове свои тараканы). У всех свой путь и они все (эти тропинки) правильны для идушего, но не все они оптимальны и верны. Нужно переписывать, писать родительский класс, который можно было бы использовать везде, а текущий движковый далее чистить и наследовать от нашего новосозданного Вот именно такой подход мне и претит! Вы заметили, что я не трогал "родительский класс"? Я просто сделал свой. Не надо шуровать там, где не ты ничего не сделал. Творите дополнения, dll-ки, которые пользователи подключают по СВОЕМУ желанию или не подключают, а не правьте то, к созданию чего вы не имели никакого отношения. Правильно же решили проблемы Atros и RVP с нет-пакетами и io? без всяких правок движка и удачно, спасибо им за это. А Вы? Теория это конечно замечательно, но практика она более доходчива и востребована, как правило. Я, к примеру, ни один мод, требущий версию отличную от 1.004, даже не рассматриваю. я уже неоднократно писал в чем кроется загадка этих "недоэкспортированных" классов Да дело же не в "загадках", а в их решениях и доступности/популярности этих решений. Вы это понимаете? Творите и дальше, и удачи Вам в этом творчестве. Никакой иронии. Изменено 17 Августа 2016 пользователем Serge! 3 Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 1 Сентября 2016 Немного ранее я показал как скриптами, не трогая движок, можно сделать в ТЧ поле с выпадающим списком. Там все работает, но не всё меня до конца устраивало. Вот ещё один исправленный и доработанный вариант. 1. В каждом диалоговом окне можно определить любое количество элементов ComboBox. Раньше правильно работал только один. 2. Каждый элемент имеет свой собственный обработчик выбора, имя которого определяется разработчиком. Раньше имя процедуры было предопределено.3. Добавлен метод предустановки выбора. Иногда такое бывает очень удобно.4. Исправлено кое-что по мелочам. --[[-------------------------------------------------- ui_ComboBoxEx.script Authors: Serge! Version: 1.01 Date: 2016 ------------------------------------------------------ Описание: Платформа - ТЧ ver 1.004 (без расширений) ------------------------------------------------------ Содержание: Класс (псевдо) ComboBoxEx (поле с выпадающим списом для ТЧ) ------------------------------------------------------ Необходимые файлы: gamedata\scripts\ui_ComboBoxEx.script, gamedata\config\ui\ui_ComboBoxEx.xml, gamedata\textures\ui\ui_ComboBoxEx.dds требуется корректировка файла system.ltx --]]-------------------------------------------------- -- определение класса строки выпадающего списка class "cb_item" (CUIListItemEx) function cb_item:__init() super() self.sn = CUIStatic() self:AttachChild(self.sn) self.sn:ClipperOn() self.sn:SetFont(GetFontLetterica16Russian()) end function cb_item:__finalize() end -- определение класса ComboBoxEx (через параметр получаем родителя) class "ComboBoxEx" (CUIScriptWnd) function ComboBoxEx:__init(owner) super() self.owner = owner end function ComboBoxEx:__finalize() end -- инициализация function ComboBoxEx:Init(pX,pY,w) -- скрытые члены класса local width = w and w or 120 -- если ширина не задана, то устанавливается 120 local height = 19 -- высота поля текста local itemScroll = 4 -- строк в списке local listHeight = 73 -- высота списка (для 4-х строк) local listItHeight = 18 -- высота строки списка local own = self.owner -- родитель local retFun -- функция возврата -- полный ComboBox с раскрытым списком local ComBox = CUIStatic() ComBox:SetAutoDelete(true) self.owner:AttachChild(ComBox) ComBox:Init(pX,pY,width,listHeight+height) -- поле полоски текста local ctl = CUIStatic() ctl:Init(0,0,width-height,height) ComBox:AttachChild(ctl) ctl:InitTexture("ui_cbEx_text") ctl:SetStretchTexture(true) -- поле самого текста local cbTxt = CUIStatic() ctl:AttachChild(cbTxt) cbTxt:Init(5,1,width-height-7,17) -- кнопка раскрытия/свёртования списка local btn = CUIButton() ComBox:AttachChild(btn) btn:Init(width-height,0,height,height) btn:InitTexture("ui_cbEx_btn") self:Register(btn,"but_cb") -- поле вывода списка local frmList = CUIStatic() ComBox:AttachChild(frmList) frmList:Init(0,height,width,listHeight+5) frmList:InitTexture("ui_cbEx_list") frmList:SetStretchTexture(true) local showList = false frmList:Show(showList) -- показать/скрыть список local DidplayHideList = function() showList = not showList frmList:Show(showList) end -- сам список local cbList = CUIListWnd() cbList:SetAutoDelete(true) frmList:AttachChild(cbList) cbList:Init(3,3,width-5,listHeight) cbList:SetItemHeight(listItHeight) cbList:Enable(true) cbList:EnableScrollBar(true) cbList:ShowSelectedItem(true) self:Register(cbList,"list_wnd") -- добавить строку в список self.InstItem = function(text) local _itm = cb_item() _itm.sn:SetWndRect(2,0, width-22,listItHeight) _itm.sn:SetTextColor(255,216,186,140) _itm.sn:SetText(tostring(text)) cbList:AddItem(_itm) end -- установим функцию возврата результата выбора self.SetRetFun = function(fun) retFun = fun end -- вернуть родителю выбор в списке (первая строка - 1) local GetItemList = function () DidplayHideList() local curItem = cbList:GetSelectedItem() local str = cbList:GetItem(curItem) cbTxt:SetText(str.sn:GetText()) if retFun then retFun(curItem+1) end end -- установить выбор в списке self.SetSelectItem = function (num) if num <= cbList:GetSize() then local curItem = num-1 cbList:SetFocusedItem(curItem) local str = cbList:GetItem(curItem) cbTxt:SetText(str.sn:GetText()) if retFun then retFun(curItem+1) end end end -- прерывания self:AddCallback("but_cb", ui_events.BUTTON_CLICKED, DidplayHideList) self:AddCallback("list_wnd", ui_events.WINDOW_LBUTTON_DB_CLICK, GetItemList) end -- заполнение списка function ComboBoxEx:AddComBox (text) if type(text) == "table" then for _, value in pairs(text) do self.InstItem(value) end elseif text ~= nil then self.InstItem(text) end end --[[-------------------------------------------------- ui_test_cb.script Authors: Serge! Version: 1.01 Date: 2016 ------------------------------------------------------ Описание: Платформа - ТЧ ver 1.004 (без расширений) ------------------------------------------------------ Содержание: Пример использования класса ComboBoxEx (поле с выпадающим списом для ТЧ) ------------------------------------------------------ Необходимые файлы: gamedata\scripts\ui_test_cb.script, gamedata\scripts\ui_ComboBoxEx.script, gamedata\config\ui\ui_ComboBoxEx.xml, gamedata\textures\ui\ui_ComboBoxEx.dds, gamedata\textures\ui\ui_pda.dds требуется корректировка файла system.ltx --]]-------------------------------------------------- -- точка входа из внешних скриптов -- или вызываем так: ui_test_cb.test_cb() function main() ui_test_cb.test_cb() end -- локальные переменные local cb1, cb2 -- надёжнее определять внешней локальной, а не внутри конструктора, чтобы их не убрал сборщик class "test_cb" (CUIScriptWnd) function test_cb:__init() super() -- создаём фон для примера self:SetFont(GetFontMedium()) self:SetWndRect(312,150,400,543) local fon = CUIStatic() fon:SetAutoDelete(true) self:AttachChild(fon) fon:Init(0,0,400,543) fon:InitTexture("ui\\ui_pda") -- это просто ПДА из дистрибутива, которое повернуто на 90 гр. fon:SetStretchTexture(true) -- определяем 1-й элемент класса ComboBoxEx cb1 = ui_ComboBoxEx.ComboBoxEx(self) cb1:SetAutoDelete(true) -- инициализация. Координаты - относительно родительского окна, ширину элемента можно опустить. cb1:Init(65,60,280) -- вставим несколько строк (массивом). Круглые скобки в данном случае можно не указывать. cb1:AddComBox {"String 1","String 2","String 3","String 4","String 5"} cb1.SetRetFun (self.get_cb1) -- устанавливаем обработчик cb1.SetSelectItem(3) -- устанавливам предопределённый выбор строки списка -- определяем 2-й элемент класса ComboBoxEx cb2 = ui_ComboBoxEx.ComboBoxEx(self) cb2:SetAutoDelete(true) cb2:Init(65,260) -- зададим ширину по умолчанию -- вставим несколько строк (по одной). Здесь тоже скобки можно опустить cb2:AddComBox "Строка 1" cb2:AddComBox ("Строка 2") -- при добавдении по одному можно также использовать InstItem() cb2.InstItem "Строка 3" cb2.SetRetFun (self.get_cb2) -- устанавливаем обработчик -- покажем всё это level.start_stop_menu(self, true) end function test_cb:__finalize() end -- определим функции возврата из ComboBoxEx (своя для каждого ComboBox) test_cb.get_cb1 = function(num) -- просто выводим сообщение news_manager.send_tip(db.actor, "1: ".."Строка: "..tostring(num)) end test_cb.get_cb2 = function(num) -- просто выводим сообщение news_manager.send_tip(db.actor, "2: ".."Строка: "..tostring(num)) end ui_ComboBoxExПример Всё гарантировано работает на чистой ТЧ 1.004. На других версиях и расширениях просто не проверял, т.к. не пользуюсь. 1 Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 1 Сентября 2016 судя по названиям, ссылки перепутаны.Увы да. Но править не буду, т.к. движок форума так устроен, что придется иправлять все скрытые элементы и коды. Просто лениво. Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 4 Сентября 2016 (изменено) Подправил немного код и ссылки уж заодно. ui_ComboBoxExПример Картинка Изменено 4 Сентября 2016 пользователем Serge! 1 1 1 Поделиться этим сообщением Ссылка на сообщение