It is currently February 23rd, 2024, 4:11 am

Missing Text

Discuss the use of Lua in Script measures.
zIa1yBX5
Posts: 4
Joined: January 2nd, 2024, 11:55 am

Missing Text

Post by zIa1yBX5 »

Image

I have debugged the code and found the w of MeterString had the right value I want, but somehow a part of it missed.

```ini

Code: Select all

[Rainmeter]
Update = #Update#



; Variables option is to define variables
[Variables]
; all time variable's unit is millisecond
Update = 100
RefreshTime = 300*1000
Scale = 1



[Script]
Measure = Script
ScriptFile = text.lua



; define a kind of style for the text
[TextStyle]
; family name of the font to be used in the skin
FontFace = 宋体
FontColor = 255, 255, 255, 255
; you could categorize sections by group, it will make it convenient to put bang into
; multiple sections. It means you only to invoke a bang with parameter, whose type is group,
; to achive it.
Group = StringGroup
StringEffect = Shadow
; determine the background color of the text, and (0, 0, 0, 1) has a benefit when you execute
; mouse actions while the background color is virtually transparent
SolidColor = 0, 0, 0, 1
AntiAlias = 1



; the main part of a motto
[MeterString]
DynamicVariables = 1
Meter = String
; you can regard measure section as a function and it will return a string value
; [] denotes a bang which is a kind of function represented by section
; & denotes the section is a customized section but a built-in section
Text = "        [&Script:GetText()]"
; a meter has different types, and a type of meter has different styles
; however, the MeterStyle is customizable, and it is represented by a section
MeterStyle = TextStyle
FontSize = 17*#Scale#
; to decide the position of the meter
X = 0L
W = [&Script:Calc()]
clipString = 2
LeftMouseUpAction = !CommandMeasure Script "MyUpdate()"



; the secondary of a motto
[MeterSecondaryString]
DynamicVariables = 1
Meter = String
Text = [&Script:GetSecondaryText()]
FontSize = (14*#Scale#)
MeterStyle = TextStyle
X = (-25*#Scale#)R
; Y = (-15*#Scale#)R
Y = [MeterString:H]
H = 30*#Scale#
clipString = 2
LeftMouseUpAction = !CommandMeasure Script "MyUpdate()"


```
```lua

Code: Select all

function GetText()
    return JSON[ID].Text
end



function GetSecondaryText()
    return JSON[ID].SecondaryText
end



MyUpdate = function()
    ID = math.random(1, #JSON)
end



function Initialize()
-- *** retrieve the content of a file ***
    -- io is a class in lua and read funtion in it creats a instance as return value
    local relativePath = "motto.json"
    -- io.open could not directly resolve to relative path and you have use
    -- SKIN:MakePathAbsolute to convert the relative to the absolute.
    -- through colon we can infer that SKIN is an object and the object has to be a parameter
    -- in the function and the SKIN is an unique object representing current skin
    local absolutePath = SKIN:MakePathAbsolute(relativePath)
    local file = io.open(absolutePath, "r")
    if file then
        -- if you need to have a object parameter, then use colon
        -- if you need not to have a object parameter, then use dot
        -- string "*a" is a kind of control parameters and means to
        -- read whole content of the file
        -- beaware that a local variable has its scope limited to the
        -- block where it is declared. a block is the body of a control structure
        Content = file:read("*a")
        -- like c++, a opened file needs closing after using
        file:close()
    -- the second parameter's type is number and means the error's level
    -- if it is 2, the error output will include the number column where
    -- the error occurs.
    else error("The file doesn't exits.", 2)
    end

-- *** parse the content of json ***
    -- dofile is to include external library or lua snippet into the current script
    -- GetVariable is a function of skin aiming to retrieve variables in the skin
    -- @ represents the directory of current skin resource folder
    -- the return value is an object indicating a lua file
    cjson = dofile(SKIN:GetVariable("@")..'Script\\json.lua')
    -- decode is a function in the json.lua file
    JSON = cjson.decode(Content)

-- *** Initialize which motto is chosen ***
    -- math is a object and you do not need to use data in math object so
    ID = math.random(1, #JSON)
end

function Min(a, b)
    return a < b and a or b
end

function Calc()
    local length = #JSON[ID].Text
    -- like document in javascript
    local scale = SKIN:GetVariable("Scale")
    local result = Min(700, 15*scale*length)
    print(result)
    return result
end
    
```
Last edited by balala on January 2nd, 2024, 6:26 pm, edited 1 time in total.
Reason: Please use <code> tags whenever are posting code snippets. It's the </> button.
User avatar
balala
Rainmeter Sage
Posts: 16007
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Missing Text

Post by balala »

What is the content of the motto.json file? Additionally I think you should have to pack all the config and upload the package.
User avatar
Yincognito
Rainmeter Sage
Posts: 6781
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Missing Text

Post by Yincognito »

Didn't check the code thoroughly, but there are 2 things you might want to know here:
- Rainmeter by default trims the leading and ending spaces from an option, including the Text one from your meter; to avoid that, you might want to add TrailingSpaces=1 to the meter:
https://docs.rainmeter.net/manual/meters/string/
- the width of a string meter is almost never the length of the string, especially for proportional fonts where letters have different widths, doesn't matter how you set the Calc() function in your Lua; the most you can do in that regard is to approximate a maximum, but that can also fail depending on the font face being used; if you need the true width of that string meter, the only way I'm aware of would be to duplicate the meter with a transparent FontColor=0,0,0,0 or similar, place it before the actual meter in the code, then use the duplicated meter's width as the width of your actual meter, e.g. W=[DuplicatedMeter:W] in your actual meter, obviously with a DynamicVariables=1 added to the meter as well
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth