showColor() Question

Post Reply
jbrumble
Posts: 15
Joined: Sat Jan 09, 2021 4:31 am

showColor() Question

Post by jbrumble »

Hello Folks,

I'm trying to create a menu where I can set the default color for objects and items to appear. I'd like to use something like showColor() but with raising an event with the choice or using some similar message to skip the step of entering the color after clicking on it.

Does something like this already exist? If not, can I access the showColor() code and try modifying it myself?

Thanks!

User avatar
demonnic
Posts: 884
Joined: Sat Dec 05, 2009 3:19 pm

Re: showColor() Question

Post by demonnic »

I don't know that something like this has been ready made per se no, but you can look at the code that goes into showColors doing what it does and use it to make something like what you're trying to do. https://github.com/Mudlet/Mudlet/blob/d ... #L764-L908

A lot of that code is to handle sorting the display by color instead of by color name, if that isn't something you need you could get by with a lot less.

jbrumble
Posts: 15
Joined: Sat Jan 09, 2021 4:31 am

Re: showColor() Question

Post by jbrumble »

Thank you for the response! That was exactly what I needed. I suspect you're right about removing the name, I might revisit that later.

Here is the very slightly modified script for anyone who might want to use it.

Code: Select all

-- internal sorting function, sorts first by hue, then luminosity, then value
local sortColorsByHue = function(lhs,rhs)
  local lh,ll,lv = unpack(lhs.sort)
  local rh,rl,rv = unpack(rhs.sort)
  if lh < rh then
    return true
  elseif lh > rh then
    return false
  elseif ll < rl then
    return true
  elseif ll > rl then
    return false
  else
    return lv < rv
  end
end

-- internal sorting function, removes _ from snake_case and compares to camelCase
local sortColorsByName = function(a,b)
  local aname = string.gsub(string.lower(a.name), "_", "")
  local bname = string.gsub(string.lower(b.name), "_", "")
  return aname < bname
end

-- internal function, converts rgb to hsv
-- found at https://github.com/EmmanuelOga/columns/blob/master/utils/color.lua#L89
local rgbToHsv = function(r, g, b)
  r, g, b = r / 255, g / 255, b / 255
  local max, min = math.max(r, g, b), math.min(r, g, b)
  local h, s, v
  v = max

  local d = max - min
  if max == 0 then
    s = 0
  else
    s = d / max
  end

  if max == min then
    h = 0 -- achromatic
  else
    if max == r then
      h = (g - b) / d
      if g < b then h = h + 6 end
    elseif max == g then
      h = (b - r) / d + 2
    elseif max == b then
      h = (r - g) / d + 4
    end
    h = h / 6
  end

  return h, s, v
end

-- internal stepping function, removes some of the noise for a more pleasing sort
-- cribbed from the python on https://www.alanzucconi.com/2015/09/30/colour-sorting/
local step = function(r,g,b)
  local lum = math.sqrt( .241 * r + .691 * g + .068 * b )
  local reps = 8

  local h, s, v = rgbToHsv(r,g,b)

  local h2 = math.floor(h * reps)
  local v2 = math.floor(v * reps)
  if h2 % 2 == 1 then
    v2 = reps - v2
    lum = reps - lum
  end
  return h2, lum, v2
end

local function calc_luminosity(r,g,b)
  r = r < 11 and r / (255 * 12.92) or ((0.055 + r / 255) / 1.055) ^ 2.4
  g = g < 11 and g / (255 * 12.92) or ((0.055 + g / 255) / 1.055) ^ 2.4
  b = b < 11 and b / (255 * 12.92) or ((0.055 + b / 255) / 1.055) ^ 2.4
  return (0.2126 * r) + (0.7152 * g) + (0.0722 * b)
end


--- Prints out a formatted list of all available named colors (EXCEPT FOR
--- the 256 colors with names of form "ansi_###" where ### is 000 to 255),
--- optional args specifies:
--- * (number) number of columns to print in, defaults to 4;
--- * (string) substring required to match to include in output, defaults to
--- showing all if not supplied;
--- * (boolean) whether to sort the output, defaults to false.
--- @usage Print list in 4 columns by default.
---   <pre>
---   showColors()
---   </pre>
--- @usage Print list in 2 columns.
---   <pre>
---   showColors(2)
---   </pre>
---
--- @see color_table

function DisplayColors(...)
  local cols, search, sort = 4, "", false
  for _, val in ipairs(arg) do
    if type(val) == "string" then
      search = val:lower()
    elseif type(val) == "number" then
      cols = val
    elseif type(val) == "boolean" then
      sort = val
    end
  end

  local colors = {}
  for k, v in pairs(color_table) do
    local color = {}
    color.rgb = v
    color.name = k
    color.sort = {step(unpack(v))}
    if not string.find(k, "ansi_%d%d%d") then
      table.insert(colors,color)
    end
  end

  if sort then
    table.sort(colors, sortColorsByName)
  else
    table.sort(colors,sortColorsByHue)
  end
  local i = 1
  for _, k in ipairs(colors) do
    if k.name:lower():find(search) then
      local v = k.rgb
      local fgc = "white"
      if calc_luminosity(v[1],v[2],v[3]) > 0.5 then
        fgc = "black"
      end
      cechoLink(string.format('<%s:%s> %-23s<reset> ',fgc,k.name,k.name), [[raiseEvent("onColorChosen", "]] .. k.name .. [[")]], table.concat(v, ", "), true)
      if i == cols then
        echo("\n")
        i = 1
      else
        i = i + 1
      end
    end
  end
  if i ~= 1 then echo("\n") end
end

function FindColor(event, input)
  echo(input)

end
registerAnonymousEventHandler("onColorChosen", "FindColor")

Post Reply