ID:2428364
 
When you have a root canal coming and that's the good news, and also less expensive than the bad news, you know it's been a crappy week.

But development continues. This week I put out build 512.1464 to address a number of fixes that were queued up and ready to go, plus some more recent fixes I had gotten to. As expected there were still a couple of hiccups left in the icon editor.

For 513, I got further with Unicode stuff but also veered away from it a bit to work on some other features on the list. First off, tan() and atan() have been requested for some time, so I'm putting them in. atan() will also have a two-parameter format that works like atan2() in most languages, and will therefore supplant my own soft-code version.

Another feature I'm working on is getting the dimensions of maptext. The new measuretext() proc (I considered client.MeasureText() but this works better as a built-in call rather than an object proc, for numerous reasons) will allow you to get the width or height required for maptext, by providing a client and a string of text that will be applied to their map style, as well as an optional max width. Currently it's setup to return a string in the form of "[width]x[height]" like you'd get from winget(), but I'm actually wondering if it'd be better to return a number: width if you didn't specify width (or it was 0 or negative), or height if you did. It would be easier to work with a number, but then it's a matter of adding some logic to tell the difference.

Querying sound status on the client is also in my early to-do list for this build. People have wanted it forever, so why not do it now?

As you can see it's short and sweet this week. Big thanks again to our Members, donors, and Patrons who keep the lights on. It's all the more appreciated with a car payment now staring me and my wife in the face. (Yup, that's the kind of week it's been.)
Great Lummox JR
Sound status will be super helpful! Cheers!
+1
Great plans! Thanks, Lummox!
For measuretext(), I still imagine you’d want the height without including the width. If you want to know the height and width, you don’t want to have to do this:
var/width = measuretext(c, s)
var/height = measuretext(c, s, width)


I’ve also never been a particular fan of the “WxH” format for sizes. Seems like it would be best to just make an official internal /size type with width and height vars. I doubt it would break any codebases, and if it did their code probably looks identical to the following and could be deleted:
size
var/width
var/height

New(w, h)
width = w
height = h


Doesn’t this just seem more natural?
// Unconstrained width.

var/size/s = measuretext(c, str)
// Math on s.width and s.height.

// Constrained width.

var/size/w_size = measuretext(c, “W”)
s = measuretext(c, str, w_size.width * 80)
// Math on s.width and s.height.
As for myself, I don't mind the "WxH" format for sizes. Though, I do have to make a proc to extract width and/or height separately, when I need them. I might like built-in procs for extracting width or height from the WxH format.
Technically you could extract with macros.

#define WXH_TO_WIDTH(a) text2num(copytext((a), 1, findtextEx((a),"x")))
#define WXH_TO_HEIGHT(a) text2num(copytext((a), findtextEx((a),"x")+1))

In response to Lummox JR
Lummox JR wrote:
#define WXH_TO_WIDTH(a) text2num(copytext((a), 1, findtextEx((a),"x")))
#define WXH_TO_HEIGHT(a) text2num(copytext((a), findtextEx((a),"x")+1))


It just seems to me that in a platform constantly playing catch-up on performance, we wouldn’t want to introduce more operationally complex instructions where otherwise simple ones would do. Like for this:
var/size = measuretext(c, str)
var/width = WXH_TO_WIDTH(size)
var/height = WXH_TO_HEIGHT(size)

We:
- Create 3 strings and 2 ints.
- Perform 2 findtextEx(). (Note this is necessarily becoming slightly more complex/expensive with the addition of UTF-8 support.)
- Perform one arthmetic expression.
- Perform 2 copytext().
- Perform 2 text2num().
- Perform 7 proc calls total.

For this:
var/size/s = measuretext(c, str)

- Get the exact same info in an object-oriented manner.
- Create 2 ints and 1 datum.
- Make a total of 1 proc call.

Since the calculations are per-client, you’d also want to weigh the possibility of these snippets occurring in a loop over every client in the game rather than in single-use isolation.
You can probably get away with just doing one client and assuming it's valid for the others, but I see your point about the loop.

The backend of the language doesn't use a lot of built-in datum types, though, and I think a /size datum would mess up a crapload of existing code.
In response to Lummox JR
Lummox JR wrote:
The backend of the language doesn't use a lot of built-in datum types, though, and I think a /size datum would mess up a crapload of existing code.

I’d be willing to wager that there are far (FAR) fewer instances of a /size datum (if any) than there are of uglier things like /obj/size or /obj/var/width + /obj/var/height.

On the contrary, I’d argue that in a language with no namespaces and a public library system, there should be more built-in, standard types. For example, you and I can both write libraries which have a /size requirement. It’s unlikely we used some common lib that had a /size datum and 2 vars, so now our users have to either deal with /lummy_size and /hi_size or else make a choice between our libraries. Maybe yours is some cool fonts library and mine is something else entirely.

With standardized types like /size, it would be as natural for us to develop against them as with /mob or /icon, and users of our hypothetical libraries reap the benefit of standardized types and tooling.
What makes the most sense is just returning a list with both values that can be used as needed.

It could be returned like
list("width"=123,"height"=123)
ever going to address standalones?
In response to Orange55
Orange55 wrote:
ever going to address standalones?