Windows 11
I am not a scripter, i know very basic Scripting in Lua and have experience in hmtl, css ,and some c++ and C# basics. So Im not at all a programmer, but i have gotten this far so far with the help of the amazing Mohoscripting.com ( Huge Shoutout!!!) and GPT4o, and Shout out to the AE_Recolor Script on mohoscrips.com for being a greet example of what i want to achieve but instead of a UI i want to achieve it with JSON.
My Goal:
# DEFINING OUR SCRIPTS GOALS
1. **Gather All Layer Names**:
- Recursively scan through all layers and sublayers in the Moho document.
- Maintain a list of all layer names found during the scan.
2. **Disregard Any Layers Not Mentioned in the JSON**:
- Compare the gathered layer names with those specified in the JSON.
- Filter out any layers that do not match the names provided in the JSON.
3. **Parse Through Shapes Only in Identified Layers**:
- For each identified layer, iterate through its shapes to access their color properties.
4. **Identify Each Shape's Current Color**:
- For each shape in the identified layers, retrieve its current fill and line colors.
- If the current colors of the shape are not mentioned in the JSON, skip further processing for that shape.
5. **Change Colors as Specified in the JSON**:
- If the current colors of the shape match those specified in the JSON, update the shape's fill and line colors to the new values provided.
- Ensure that both fill and line colors are handled separately, as specified by the JSON.
6. **Apply and Refresh the Document**:
- Once all shapes have been processed, apply the changes to the document.
- Refresh or redraw the document to ensure that all changes are visible and committed.
The Attached a MVP i have developed so far in an attempt to meet the above goals. The script and json only works so far in Moho for my character models to change the colors to white, regardless of the colors iIm trying to map form the JSON..
ChangeColorViaJSON.lua
Code: Select all
-- **************************************************
-- Provide Moho with the name of this script object
-- **************************************************
ScriptName = "ChangeColorViaJSON"
ChangeColorViaJSON = {}
-- **************************************************
-- General information about this script
-- **************************************************
function ChangeColorViaJSON:Name()
    return "Change Colors Based on JSON"
end
function ChangeColorViaJSON:Version()
    return "1.0"
end
function ChangeColorViaJSON:UILabel()
    return "Change Colors Based on JSON"
end
function ChangeColorViaJSON:Creator()
    return "JeffSaamanen"
end
function ChangeColorViaJSON:Description()
    return "Change shape colors based on a provided JSON file"
end
-- Helper function to read JSON file
function ChangeColorViaJSON:ReadJSONFile(filePath)
    local file = io.open(filePath, "r")
    if not file then
        print("Error: Could not open file " .. filePath)
        return nil
    end
    local json_data = file:read("*all")
    file:close()
    return json_data
end
-- Function to get the script directory
function getScriptDirectory()
    local str = debug.getinfo(2, "S").source:sub(2)
    return str:match("(.*[\\])")
end
-- Helper function to parse JSON
function ChangeColorViaJSON:ParseJSON(jsonString)
    local scriptDir = getScriptDirectory()
    if not scriptDir then
        print("Error: Could not get script directory")
        return nil
    end
    local json = dofile(scriptDir .. "/dkjson.lua")
    local jsonObj, pos, err = json.decode(jsonString, 1, nil)
    if err then
        print("Error:", err)
        return nil
    end
    return jsonObj
end
-- Helper function to get JSON file path from user
function ChangeColorViaJSON:GetJSONFilePath()
    local filePath = LM.GUI.OpenFile("Select JSON File")
    if filePath == "" then
        print("File dialog canceled")
        return nil
    end
    return filePath
end
-- Helper function to compare colors
function ChangeColorViaJSON:EqualColors(colorVector, colorTable)
    return math.abs(colorVector.r - colorTable.r) < 0.01 and
           math.abs(colorVector.g - colorTable.g) < 0.01 and
           math.abs(colorVector.b - colorTable.b) < 0.01 and
           math.abs(colorVector.a - colorTable.a) < 0.01
end
-- Helper function to convert color structure to color vector
function ChangeColorViaJSON:CreateColorVector(colorTable)
    return LM.ColorVector:new_local(colorTable.r, colorTable.g, colorTable.b, colorTable.a)
end
-- Main function to run the script
function ChangeColorViaJSON:Run(moho)
    print("Run function called")
    if moho == nil then
        print("Error: moho is nil")
        return
    end
    -- Get JSON file path from user
    local jsonFilePath = self:GetJSONFilePath()
    if not jsonFilePath then
        return
    end
    -- Read JSON data from file
    local json_data = self:ReadJSONFile(jsonFilePath)
    if not json_data then
        return
    end
    -- Parse the JSON data
    local colorData = self:ParseJSON(json_data)
    if not colorData then
        return
    end
    -- Iterate through all layers to find and process vector layers
    for i = 0, moho.document:CountLayers() - 1 do
        local layer = moho.document:Layer(i)
        self:ProcessLayers(moho, layer, colorData, moho.frame)
    end
    -- Refresh the document
    moho.document:SetDirty()
    moho:UpdateSelectedChannels()
    moho.layer:UpdateCurFrame()
end
-- Recursive function to process all layers and sublayers
function ChangeColorViaJSON:ProcessLayers(moho, layer, colorData, frame)
    if layer:IsGroupType() then
        local group = moho:LayerAsGroup(layer)
        for i = 0, group:CountLayers() - 1 do
            self:ProcessLayers(moho, group:Layer(i), colorData, frame)
        end
    elseif layer:LayerType() == MOHO.LT_VECTOR then
        print("Processing vector layer: " .. layer:Name())
        self:ProcessShapes(moho, layer, colorData, frame)
    end
end
-- Function to process shapes in a vector layer
function ChangeColorViaJSON:ProcessShapes(moho, layer, colorData, frame)
    local vectorLayer = moho:LayerAsVector(layer)
    local mesh = vectorLayer:Mesh()
    for i = 0, mesh:CountShapes() - 1 do
        local shape = mesh:Shape(i)
        if shape and shape.fMyStyle then
            local fillColor = shape.fMyStyle.fFillCol:GetValue(frame)
            local lineColor = shape.fMyStyle.fLineCol:GetValue(frame)
            for _, colorPair in ipairs(colorData.colors) do
                local oldFillColor = colorPair.oldFillColor
                local newFillColor = colorPair.newFillColor
                local oldLineColor = colorPair.oldLineColor
                local newLineColor = colorPair.newLineColor
                if self:EqualColors(fillColor, oldFillColor) then
                    print(string.format("Changing fill color from (%.2f, %.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f, %.2f)",
                                        fillColor.r, fillColor.g, fillColor.b, fillColor.a,
                                        newFillColor.r, newFillColor.g, newFillColor.b, newFillColor.a))
                    shape.fMyStyle.fFillCol:SetValue(frame, self:CreateColorVector(newFillColor))
                end
                if self:EqualColors(lineColor, oldLineColor) then
                    print(string.format("Changing line color from (%.2f, %.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f, %.2f)",
                                        lineColor.r, lineColor.g, lineColor.b, lineColor.a,
                                        newLineColor.r, newLineColor.g, newLineColor.b, newLineColor.a))
                    shape.fMyStyle.fLineCol:SetValue(frame, self:CreateColorVector(newLineColor))
                end
            end
        else
            print("Error: shape or shape.fMyStyle is nil")
        end
    end
end
return ChangeColorViaJSON
colorchange-v3.json
Code: Select all
{
    "colors": [
        {
            "oldFillColor": {"r": 0.44, "g": 0.19, "b": 0.19, "a": 1.00},
            "newFillColor": {"r": 0.00, "g": 0.25, "b": 0.25, "a": 1.00},
            "oldLineColor": {"r": 0.32, "g": 0.07, "b": 0.07, "a": 1.00},
            "newLineColor": {"r": 0.00, "g": 0.16, "b": 0.16, "a": 1.00}
        }
    ]
}
Everything works except the recoloring. As you can see, there is a major discrepancy between the color defined by the JSON input and the colors the script actually applies to each vector shape.
Code: Select all
{
    "colors": [
        {
            "oldFillColor": {"r": 0.44, "g": 0.19, "b": 0.19, "a": 1.00},
            "newFillColor": {"r": 0.00, "g": 0.25, "b": 0.25, "a": 1.00},
            "oldLineColor": {"r": 0.32, "g": 0.07, "b": 0.07, "a": 1.00},
            "newLineColor": {"r": 0.00, "g": 0.16, "b": 0.16, "a": 1.00}
        }
    ]
}In the Lua console, it's displaying the correct colors that are supposed to be changed, as if it has successfully changed to the proper color. However, as we can see from the provided image, this is not true; it just changes everything to white.
Please advise as to why this is happening? I feel like i'm just missing something Fundamental about access and passing color information to shapes to change them properly based on the JSON data provided.