Добавлен , опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
Lua
Тип:
Алгоритм
Версия Warcraft:
1.32
Конверт hex-числа в hex-строку
пример: 255 => 'FF' или 16711680 => 'FF0000'
был исправлен недостаток: в lua дополнительные нули не отображались. 0=>'' (должен '00') или у однозначного числа 01=>'1' (должен '01'). Это очень важно для color-кодов, иначе след вычисления собьются.
Недостаток исправлен не полностью. Поскольку рассчитан 0-255 значение. Дело в том, что неизвестно сколько символов должно быть. Для rgb норм иметь 6 символов, для rgba 8 символов. Если ввести больше 255, то опять же lua не рисует впереди нули. Пример 65280 => 'FF00'
код от 0-255 (устарел)
function decimalToHex(num)
    local num = math.tointeger(num)
    if num == 0 then
        return '00'
    end
    local neg = false
    if num < 0 then
        neg = true
        num = num * -1
    end
    local hexstr = "0123456789ABCDEF"
    local result = ""
    while num > 0 do
        local n = math.fmod(num, 16)
        result = string.sub(hexstr, n + 1, n + 1) .. result
        num = math.floor(num / 16)
    end
            
    if #result < 2 then
        result = "0" .. result
    end
            
    if neg then
        result = '-' .. result
    end
    return result
end
переделанный код (не актуально)
Тут нужно указывать сколько символов в строке должно быть. для rgb - 6, для rgba - 8. А можно вообще 2 символа (00-FF) для какого то одного аргумента цвета. Тогда функция сама дорисует недостающие нули. А можно и не указывать, тогда впереди нолики не будет.
function decimalToHex(num,sum)
    local num = math.tointeger(num)

    local neg = false
    if num < 0 then
        neg = true
        num = num * -1
    end
    local hexstr = "0123456789ABCDEF"
    local result = ""
    while num > 0 do
        local n = math.fmod(num, 16)
        result = string.sub(hexstr, n + 1, n + 1) .. result
        num = math.floor(num / 16)
    end
    if sum then --если число sum введено 
        if #result<sum then
            local k = sum-#result

            for i=1,k do
                result = '0'..result
            end
        end
    end
            
    if neg then
        result = '-' .. result
    end
    return result
end
переделанный код (улучшенный)
Тут нужно указывать сколько символов в строке должно быть. для rgb - 6, для rgba - 8. А можно вообще 2 символа (00-FF) для какого то одного аргумента цвета. Тогда функция сама дорисует недостающие нули. А можно и не указывать, тогда впереди нолики не будет.
--num - число, sum - кол-во символов
function decimalToHex(num,sum)
    local num = num//1 --math.tointeger(float) возвращает целое от float. Но есть частный случай с нулями, как целое ноль не показывается. Пример 0.5 => вместо ноль,  показывает nil. Поэтому используем другой способ - деление a//b при котором получаем целое число 
    local d="%x" --спецификатор форматирования, который определяет как отобразить строку. если sum не указан, то string.format с таким спецификатором не рисует впереди нули.
	if sum then
		 d='%0'..sum..'x' --другой спецификатор, в котором указано в строке какое-то число символов. при недостающих символах дорисовывает впереди нули
	end
	return string.format(d,num)
end
применение: для отображения hex-кода на экран. Пример, динамичная покраска текста в фреймах '|cffrrggbb |r'
код
можно менять цвет в зависимости от хп/маны или чего то еще. к примеру: 100% хп - зеленый. ближе к 0% хп - красный. Берем пропорции
r =decimalToHex( (( (max_hp-current_hp)/max_hp)*255 )
g =decimalToHex( (current_hp/max_hp)*255 )
b =decimalToHex(0) --синий в данном примере игнорируем, поэтому значение обнулено
string='|cff'..r..g..b..text..'|r' --склеиваем все в одну строку
эта реализация была реализована в BonusMod для перекраски строк хп и маны. В зависимости от хп и маны показывают различный цвет.
в lua 'одинарные' или "двойные" кавычки означает строку. можно либо одинарными или двойными.
в jass мы делали сцепление строк через плюс: a+b. Но в lua не распознает синтаксис, ругается. Поэтому делаем сцепление через точки a..b или запятую a,b. А так все одно и то же.
конверт hex-строки в dec-число
Преобразует строку с Hex числом (допустимые значения "00" до "ff") в десятичное целое число (взято с хгм):
код из хгм, переписанный на lua. ограничение 00-ff (устарел)
код переделан на lua, тк в в online не проверишь. некоторые нативки типа SubString не распознаются. плюс учтены ошибки, когда строка пуста или введен 1 символ. Не знаю чтоило ли исправлять
function H2D(hex)
  local abc = "0123456789abcdef"
  local i = 0
  local dec 
  if hex then
    if #hex==2 then
        repeat  --циклом находим символ из строки abc
            i = i + 1
        until ( abc:sub(i,i)==hex:sub(1,1) or i>16 )

        dec = (i-1) * 16
        
        i = 0
        repeat --циклом находим символ из строки abc
            i = i + 1
        until ( abc:sub(i,i)==hex:sub(2,2) or i>16 ) 
        dec = dec + i - 1
    elseif #hex==1 then
      i = 0
      repeat
        i = i + 1
      until ( abc:sub(i,i)==hex:sub(1,1) or i>16 )
      dec = i - 1
    end
    return dec
  else
    return 0
  end
end
переделанный код (без ограничении и циклов) - не актуален
Можно вводить разной длины hex-строки. Но длинной не стоит делать. Но это должно хватить. Мне вот хватит и 8 символов (хз, хотя куда стока). 'ffffffff' => 4294967295
function H2D(hex)
    hex = hex:gsub("#","")
    return tonumber("0x"..hex:sub(1,#hex))
end
улучшенный код
function H2D(hex)
    return tonumber(hex, 16)
end
конверт rgb в hex-строку
значения a,r,g,b (0-255). пример r=255,b=255,g=255 => 'ffffff'
Минус: в lua ноль не отображается. типа 0 => ' ' или 01 => '1'. Это очень важно для color-кодов, иначе след вычисления собьются. Но можно дописать условия. Проще проверить кол-во символов, если 0 -> добавляем 2 нуля '00'. Если 1, добавляем 1 ноль '0'. Пришлось исправить в коде. string.format("%x", string) не отображает ноль, или передние нолики. Нам просто нужно спереди добавить несколько ноликов
Мб применение этому не много. Но можно например, узнать hex-строку. Мне че-то хотелось своей мини-редактор цвета запилить как тут Тогда я сделал совсем по-другому, мне пришлось использовать decimalToHex(num) на каждый аргумент и склеивать строку.
код не актуален
function rgbToHex(r,g,b)
    local rgb = (r * 0x10000) + (g * 0x100) + b
    local s = string.format("%x", rgb)
    local k = 6-#s

    for i=1,k do
        s = '0'..s
    end

    return s
end
function argbToHex(a,r,g,b)
    local argb = (a * 0x1000000) + (r * 0x10000) + (g * 0x100) + b
    local s = string.format("%x", argb)
    local k = 8-#s

    for i=1,k do
        s = '0'..s
    end
    return s
end
улучшенный код от Прометея
function rgba2hex(r, g, b, a)
  return string.format('%02x%02x%02x%02x', a or 255, r, g, b)
end
Заметка: в рефордже не очень хорошо работает string.format. Выдает длинные символы, вместо hex-строки.
пример
	function rgba2hex(r, g, b, a)
	  return string.format('%02x%02x%02x%02x', a or 255, r, g, b)
	end
    
    print('|c'..rgba2hex(255, 0, 0)..'красный перец|r')
получает
конверт rgb в dec-число
Пример r=255, g=0, b=0 => 16711680
Аналогичной функцией обладает рефорджет. BlzConvertColor takes integer a, integer r, integer g, integer b - вводите alpha (0-255), red (0-255), green (0-255), blue (0-255), и эта функция возвращает 16-ричный цветовой код.
Применение: перегонка из rgb в dec-integer нужна для задания цвета фрейму. Это объясняется в статье про texture
мой код
function rgbToDec(r,g,b)
    local rh = string.format("%02x", r) -- minimum returned numbers 2, left padded with 0's see https://developer.roblox.com/en-us/articles/Format-String
    local gh = string.format("%02x", g)
    local bh = string.format("%02x", b)
    local hex = "0x"..rh..gh..bh
    local dec = tonumber(hex) --или можно сразу tonumber(rh..gh..bh,16)
    --print("Vals: " .. r .. ", " .. g .. ", " .. b)
    --print("Hex: " .. hex)
    --print("Decimal: " .. dec)
    return dec
end
улучшенный код от Прометея
function rgba2dec(r, g, b, a)
  return ((a or 255) << 24) + (r << 16) + (g << 8) + b
end
Преобразует hex-строку в rgb
Применение: из hex-строки подставляем в texttag/unit/effect/frame (функции принимают только числа). Выгоднее иногда hex-строку вставить в аргументах функции, а потом специально разбивать. тк в функции забивать еще и новыми аргументами неудобно мб.
пояснение
Пример есть такая функция создания Images, и в ней уже итак много аргументов. А тут надо 2 цвета добавить, это представляете скока надо аргументов понапихать, это 6-8 добавить. Невыгодно
function CreateCircleShapeImage(data,file,size,cx,cy,radius,imagetype,line_width,color1,color2)
	
	local a1,r1,g1,b1 
	local a2,r2,g2,b2
	if color1 then --если указан цвет внутреннего круга
		a1,r1,g1,b1 = hex2argb(color1)
	end
	if color2 then --если указан цвет кольца/контура 
		a2,r2,g2,b2 = hex2argb(color2)
	end
	
	--тело функции
end
пример 'ffffff' => 255,255,255
первый код
function hex2rgb(hex)
    hex = hex:gsub("#","")
    return tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6))
end
function hex2argb(hex)
    hex = hex:gsub("#","")
    return tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6)), tonumber("0x"..hex:sub(7,8))
end
Преобразует hex-строку в rgb
пример 'ffffff' => 255,255,255
второй код
-- Hex string value in the form '#cccccc' or 'cccccc'
function HEXtoRGB(hexArg)

   hexArg = hexArg:gsub('#','')

   if(string.len(hexArg) == 3) then
      return tonumber('0x'..hexArg:sub(1,1)) * 17, tonumber('0x'..hexArg:sub(2,2)) * 17, tonumber('0x'..hexArg:sub(3,3)) * 17
   elseif(string.len(hexArg) == 6) then
      return tonumber('0x'..hexArg:sub(1,2)), tonumber('0x'..hexArg:sub(3,4)), tonumber('0x'..hexArg:sub(5,6))
   else
      return 0, 0, 0
   end

end
код Прометея
function hex2rgba(h)
  local n = tonumber(h, 16)
  return n >> 16 & 255, n >> 8 & 255, n & 255, n >> 24 & 255
end
был пример как смешивать цвета. он был реализован на фреймах. там и перекраска, и вывод hex-строки, и пр. тот пример сделал быстро на тяп ляп для статьи. старая статья
тут варкрафт использует argb, а не rgba. Мб кому неудобно будет. Всегда привыкать использовать подсветку текста таким образом.
Если что в интернете можно найти функции получше/короче/красивее итд. По lua задают очень много вопросов. Набираете в google 'hex rgb lua'. Но перед этим проверяйте работу функции. При необходимости можно сделать самим, если знаем как. В lua библиотека функции богата, различными способами можно преобразовать строку.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
35
2 года назад
0
Может картинку, видео или гиф показать, что из себя представляет данный алгоритм действий?
2
27
2 года назад
2
x10azgmfx, зачем? тут и так все понятно.
www.lua.org/cgi-bin/demo --вот тут тестим функцию через print выводим
colorscheme.ru/color-converter.html --тут для непонятных =\
1
37
2 года назад
Отредактирован ScorpioT1000
1
В луа же есть бинарные операторы, можно любой int превратить в любую строку, хоть по битам расписать, и обратно
print(3 & 5)  -- bitwise and
print(3 | 5)  -- bitwise or
print(3 ~ 5)  -- bitwise xor
print(7 >> 1) -- bitwise right shift
print(7 << 1) -- bitwise left shift
print(~7)     -- bitwise not
В жассе приходилось вот колдовать с арифметикой, но все равно не такой огромный код получался.
2
27
2 года назад
Отредактирован MpW
2
ScorpioT1000, честно, я такое не понимаю =/.
Но Прометей мне показывал пример с байтами, но я уже забыл о чем там. но там точно должны нули 010101
код
	function IsFlagSet(flags, pos)
		if pos == nil then
			return false
		else
			return flags >> pos & 1 == 1
		end
	end
0
37
2 года назад
0
Надо подучить информатику, с этого в школе начинают курс, бинарная арифметика
4
28
2 года назад
Отредактирован PT153
4
Плохо.

Конверт hex-числа в hex-строку
Не нужно, есть в самом луа (string.format).
0=>'' (должен '00')
Если число есть ноль, то один ноль всегда выводится

hex-строки в dec-число
Не нужно, есть в самом Lua (tonumber(str, 16)).

конверт rgb в hex-строку
function rgba2hex(r, g, b, a)
  return string.format('%02x%02x%02x%02x', a or 255, r, g, b)
end

конверт rgb в dec-число
function rgba2dec(r, g, b, a)
  return ((a or 255) << 24) + (r << 16) + (g << 8) + b
end

hex-строку в rgb
function hex2rgba(h)
  local n = tonumber(h, 16)
  return n >> 16 & 255, n >> 8 & 255, n & 255, n >> 24 & 255
end

Надо подучить информатику, с этого в школе начинают курс, бинарная арифметика
У меня в школе этого не было, зависит от страны и программы, которая была на момент обучения.
1
37
2 года назад
1
return n >> 24 & 255, n >> 16 & 255, n >> 8 & 255, n & 255
Там & 0xFF можно писать :)
0
28
2 года назад
0
ScorpioT1000, 0xff длиннее 255)
2
27
2 года назад
Отредактирован MpW
2
PT153, огромный плюс тебе +
Не нужно, есть в самом луа (string.format).
local s = string.format("%x", 1) 
print(s)-- получается '1', а не '01'
другой случай
local s = string.format('%06x',1)
print(s) --получается '000001'
единственное, что float числа нельзя вставлять. нужно в math.tointeger(output)
local a = 1
local input = math.tointeger(0.5*a) --не знаю почему, но эта функция не выдает ноль. пример 0.5 => 0 целых

if input then
local output = string.format("%x", input )
print(output)
end
0
35
2 года назад
0
МрачныйВорон, для тебя понятно, а для милишников и гуишников нет.
2
27
2 года назад
Отредактирован MpW
2
Ruti Ragnason, эм.. ну тогда засунь в мой блог. буду единственным, кто сможет их использовать. разжевывать для гуишников мне не хочется, не знаю что должен им еще показать. примеры уже есть. не могут в код, значит, им рано
пригодиться. тк я наверное три раза собирал лазил в интернет, чтобы найти конвертер
0
37
2 года назад
0
получается '1', а не '01'
Поэтому и показали %02x, а не %x

Не надо ни в какие блоги засовывать, политика наоборот переноса контента из блогов
2
27
2 года назад
2
ScorpioT1000, я уже понял))
0
28
2 года назад
0
МрачныйВорон:
If the value x is convertible to an integer, returns that integer. Otherwise, returns nil.
0.5 не конвертируется в целое число, поэтому возвращает nil. Для флоатов преобразование в 16-ричное не нужно.
2
27
2 года назад
Отредактирован MpW
2
PT153,
0.5 не конвертируется в целое число, поэтому возвращает nil.
почему? а вот lua demo 1.5 вернет 1. math.tointeger(float) не дружит с нулями
Для флоатов преобразование в 16-ричное не нужно.
а вдруг какой-нибудь идиот введет. плюс, в lua integer может легко превращаться в float, например, при арифметических операциях. у меня уже был опыт. например работа с хп
если не делать это, будет это ниже, типа у вас float:
input:11: bad argument #2 to 'format' (number has no integer representation)
типа этой функции string.format нельзя указывать 0.5, в то варемя как другие 1.5 , 20.7 и другие флоаты норм
1
37
2 года назад
Отредактирован ScorpioT1000
1
В луа есть целочисленное деление специальным оператором: //
0
27
2 года назад
Отредактирован MpW
0
интересно. типа
5 // 2 = 2
0.5 // 1 = 0.0
проверил, теперь работает =)
0
28
2 года назад
Отредактирован PT153
0
почему? а вот lua demo 1.5 вернет 1. math.tointeger(float) не дружит с нулями

Как и написано в документации, вернётся nil.
Загруженные файлы
0
27
2 года назад
0
ошибка в
function rgba2hex(r, g, b, a)
  return string.format('%02x%02x%02x%02x', a or 255, r, g, b)
end
print(rgba2hex(0.5, 255, 255))
input:2: bad argument #3 to 'format' (number has no integer representation)
придеться также делить. а так я доволен. пробовал всякими способами забаговать функции. не получается
0
28
2 года назад
0
типа этой функции string.format нельзя указывать 0.5, в то варемя как другие 1.5 , 20.7 и другие флоаты норм
Для флоатов есть форматы для флоатов. Читаем документацию.
0
37
2 года назад
Отредактирован ScorpioT1000
0
Всегда можно сделать Math.floor, но это тебе не надо, не в такой функции. Более жесткие проверки делаются ближе к пользовательскому вводу, а не к выводу и хранению
2
27
2 года назад
2
PT153, значит lua demo это не работает?
0
28
2 года назад
0
МрачныйВорон, math.tointeger работает так, как описано в документации, которую я процитировал.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.