felixmariotto / three-mesh-ui

⏹ Make VR user interfaces for Three.js
https://felixmariotto.github.io/three-mesh-ui/#basic_setup
MIT License
1.26k stars 134 forks source link

Fallback Font Files #256

Open kalegd opened 1 year ago

kalegd commented 1 year ago

Wondering what your thoughts would be on using a default font file for when users don't provide one? I know people usually prefer having full control over dependency version in javascript, but I'd view this more as a fallback than a dependency as such

let fontJSON = "https://cdn.jsdelivr.net/npm/msdf-fonts/build/OpenSans-Regular-msdf.json";
let fontImage = "https://cdn.jsdelivr.net/npm/msdf-fonts/build/OpenSans-Regular-msdf.png";
swingingtom commented 1 year ago

Hi @kalegd, That would actually be great. But I don't know how it should be handle. As this is recommended to preload font, to fit that path the font could be embedded instead of loaded. But it will add an extra amount on kb on the library, even for people which don't use it. And it should also handle multiple alphabet instead of only Latin.

Wha't are your thoughts on those?

kalegd commented 1 year ago

If it needs to be embedded I definitely vote against it. No need to add the bloat for a fallback many users might not need. I'll try to make some time in the coming weeks and sift through the code to see if we could find some sort of non-bloating way to make it work and give a demo if so

swingingtom commented 1 year ago

Agreed, but... This would really be great to provide a default/getstarted font for new users. This is one of the very first issue @felixmariotto added #20
What if we stay with your first approach, and each "example" or "sample" would have a comment such as // Replace by your own font...?

// Using `ThreeMeshUI.FontLibrary.prepare( fontFamily, [...fontFamily] )
// We can ensure any fontFamily passed in that function and theirs variants are properly loaded and setup
FontLibrary.prepare(
    FontLibrary.addFontFamily("Default").addVariant(400,"normal",
        // replace by your own font if needed                    
        "https://cdn.jsdelivr.net/npm/msdf-fonts/build/OpenSans-Regular-msdf.json",
    "https://cdn.jsdelivr.net/npm/msdf-fonts/build/OpenSans-Regular-msdf.png" )
).then( () => {
// build blocks and texts...
}

charset as additional option in the url? I still think something we are missing something obvious that might be a better solution, but at least it goes in the right direction. right? What do you think?

kalegd commented 1 year ago

I like that idea! I definitely think using an externally hosted font library is easier for new users to onboard vs making their own Font files, and we can revisit if this repo providing a default font is feasible in the future depending on if/how FontLibrary changes over time

+1 on adding charset to the url. I'll publish some changes to the msdf-fonts repo for that. What are your thoughts on the following format?

{font}-{charset}-msdf.json {font}-{charset}-msdf.png

where {charset} might be

^For charset naming I'm leaning towards using the names for unicode character blocks with allowances for custom character sets for other useful open source projects like this repo

swingingtom commented 1 year ago

Sounds great. If I may, if you could also put font variant (weight & style), that would be very useful. Would it be possible to organise font per directories?

not sure about the order thou {font}/{charset}/{weight}[-style]-msdf

kalegd commented 1 year ago

I'm fine with creating directories for organization purposes, but I'll likely maintain all details in the filename in case users decide to download them and host it themselves

With that in mind, I've gone ahead with {charset}/{fontLowerCase}/{font}-{weight+style}-{charset}-msdf

With {weight+style} following the naming convention of the fonts .ttf file. Usually I see something like Roboto-MediumItalic.ttf instead of Roboto-Medium-Italic.ttf

Can always change this in future versions if needed

You can access the fonts that should support all three-mesh-ui examples below. I added a few characters like |<> to the character set defined in the wiki

https://cdn.jsdelivr.net/npm/msdf-fonts/build/custom/three-mesh-ui/roboto/Roboto-Regular-three-mesh-ui-msdf.png https://cdn.jsdelivr.net/npm/msdf-fonts/build/custom/three-mesh-ui/roboto/Roboto-Regular-three-mesh-ui-msdf.json

Hopefully in a few weeks I'll make a nice general msdf font file with everything you need that's not in the custom folder, but I need to look into some Unicode blocks like the general punctuation block and think about how I want to organize things more before then

swingingtom commented 1 year ago

I'm fine with creating directories for organization purposes, but I'll likely maintain all details in the filename in case users decide to download them and host it themselves.

Make perfect sens. So I would avoid repeating information on path too. It would lead to extra long path with no more values.

kalegd commented 1 year ago

Alright, I've removed the redundant folders and also added general msdf files to support all characters that the corresponding .ttf files support. So every character that Roboto supports can be found in

https://cdn.jsdelivr.net/npm/msdf-fonts/build/Roboto-Regular-msdf.json + https://cdn.jsdelivr.net/npm/msdf-fonts/build/Roboto-Regular-msdf.png

But the character subsets based on unicode blocks are now under a /build/subsets folder as those are much smaller to load

To support all three-mesh-ui examples you could use either the full /build/Roboto-Regular-msdf files (~3.2 MB total) or the custom character set via /build/custom/three-mesh-ui-Roboto-Regular-msdf files (~545 KB)