Home > Software design >  SCNText ignores NSAttributedString attributes
SCNText ignores NSAttributedString attributes

Time:09-30

Although the docs claim that SceneKit's SCNText works with NSAttributedString, the following NSAttributedString attributes seem to be ignored completely (and perhaps others, too):

  1. shadow
  2. strokeColor
  3. strokeWidth
  4. foregroundColor

SCNText does obey NSAttributedString's font attribute, however -- and it does display on screen.

What I'm trying to do is add a stroke to my SCNText. I do not want to use a SpriteKit overlay for such a simple use case.

From the docs:

When you create a text geometry from an attributed string, SceneKit styles the text according to the attributes in the string, and the properties of the SCNText object determine the default style for portions of the string that have no style attributes.

Here's what I'm doing in code. This code results in a white-filled text in the correct font, but without shadow or stroke of any kind:

let labelNode = SCNNode()
let label = SCNText(string: "\(targetLevel)", extrusionDepth: 0.0)
let font = UIFont(name: "Whatever", size: 4.0)
let shadow = NSShadow()
shadow.shadowBlurRadius = 1.0
shadow.shadowColor = UIColor.black

let attStr = NSAttributedString(string: "\(targetLevel)", attributes: [.font: font!, .shadow: shadow, .strokeColor: UIColor.black, .strokeWidth: 0.5])
 
label.string = attStr
label.alignmentMode = "kCAAlignmentCenter"
label.flatness = 0.01

//Using a big font and then scaling the node down to make it look less jagged:
labelNode.scale = SCNVector3(0.25,0.25,0.25)
labelNode.geometry = label
labelNode.castsShadow = false

parent.addChildNode(labelNode)

Questions: Am I doing something wrong -- or is this a limitation of SceneKit? Is there any other way to stroke an SCNText? I saw this question, but it's about fill color, not stroke, and didn't fix my problem.

CodePudding user response:

As you've found (and others have noted), you don't automatically get all of the properties of the attributed string rendered in SceneKit. Think of them in terms of what you are drawing (e.g. the shape of the text), rather than how you draw them (e.g. color, shadow etc). All SceneKit uses is the geometry.

If you want outline-stroked 3D text then you may have to get the path from the font and use that for your geometry instead of SCNText. I wrote this category but the code is pretty ancient now, I have no idea if it still works, but it should be enough to get you there.

You could also perhaps render the text as an image and put it as a texture on a billboard, unless you actually want it to be part of the 3D scene. But by this point, a sprite kit overlay isn't looking that complicated, is it?

  • Related