NSAttributedString 不适用于 SCNText

NSAttributedString doesn't work with SCNText

我想在 SceneKit 场景中显示一些文本,其中字符具有不同的颜色。 documentation of SCNText 状态:

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.

我试过了,但没用。 SCNText 似乎忽略了我的字符串的属性。我检查了我的 NSAttributedString 的内容是否正确,并将其添加到 UILabel,并按预期显示。

为什么 3D 文字没有颜色?

这是一个小型测试应用程序(来自单视图应用程序模板)和屏幕截图:

#import "ViewController.h"

#import <SceneKit/SceneKit.h>

@interface ViewController ()

@end

@implementation ViewController

- (void) viewDidLoad
{
    [super viewDidLoad];

    NSAttributedString* str = [ViewController makeSomeText];

    [self addSceneViewWithText: str];
    [self addLabelWithText: str];
}

+ (NSMutableAttributedString*) makeSomeText
{
    NSDictionary* redAttr   = @{NSForegroundColorAttributeName : [UIColor redColor]};
    NSDictionary* greenAttr = @{NSForegroundColorAttributeName : [UIColor greenColor]};
    NSDictionary* blueAttr  = @{NSForegroundColorAttributeName : [UIColor blueColor]};

    NSAttributedString* redStr   = [[NSAttributedString alloc] initWithString: @"red"   attributes: redAttr];
    NSAttributedString* greenStr = [[NSAttributedString alloc] initWithString: @"green" attributes: greenAttr];
    NSAttributedString* blueStr  = [[NSAttributedString alloc] initWithString: @"blue"  attributes: blueAttr];

    NSMutableAttributedString* str = [[NSMutableAttributedString alloc] init];
    [str appendAttributedString: redStr];
    [str appendAttributedString: greenStr];
    [str appendAttributedString: blueStr];

    return str;
}

- (void) addSceneViewWithText: (NSAttributedString*) string
{
    SCNView* view = [[SCNView alloc] initWithFrame: self.view.bounds];
    view.scene = [SCNScene scene];
    view.backgroundColor = [UIColor grayColor];
    view.autoenablesDefaultLighting = true;
    view.allowsCameraControl = true;
    SCNNode* root = view.scene.rootNode;
    [self.view addSubview: view];

    SCNNode* cameraNode = [SCNNode node];
    cameraNode.camera = [SCNCamera camera];
    cameraNode.camera.automaticallyAdjustsZRange = true;
    [root addChildNode: cameraNode];

    SCNText* text = [SCNText textWithString: string extrusionDepth: 3];
    // text.firstMaterial.diffuse.contents = [UIColor yellowColor];
    SCNNode* textNode = [SCNNode nodeWithGeometry: text];
    textNode.rotation = SCNVector4Make (1, 0, 0, 0.5f);
    [root addChildNode: textNode];

    SCNVector3 text_center;
    float dummy;
    [text getBoundingSphereCenter: &text_center radius: &dummy];
    textNode.position = SCNVector3Make (-text_center.x, -text_center.y, -150);
}

- (void) addLabelWithText: (NSAttributedString*) string
{
    CGRect bounds = self.view.bounds;
    UILabel* label = [[UILabel alloc] initWithFrame: CGRectMake (0, 50, bounds.size.width, 50)];
    label.attributedText = string;
    label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview: label];
}

- (void) didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

@end

直接回答你的问题:"Why is the 3D text not colored?"

颜色可能不被视为 "style" 的一部分,因为他们在文档中使用了这个词。这也可能是使用错误的词,因为它是对文本质量的描述,在它曾经使用过的每个地方都会弯曲和扭曲。

他们的意思很可能是诸如粗细、对齐、下划线、删除线、字距调整和行距之类的东西……这种性质的东西由 SceneKit 解释。但只有反复试验才能确定什么行得通,什么行不通。

Apple 应该提供 table,其中包含 SceneKit 识别和使用的 attributes/qualities 文本列表。

我在 Core Text 和 NSAttributedString 文档中可以找到的 "style" 的唯一用途建议那些框架考虑将每个段落的这些质量分组的词,这在考虑 SceneKit 时也几乎没有帮助文字.


编辑:关于 3D 和 Materials 的其他内容,以防万一这对您来说是新闻:

'Materials' in 3D speak 在 3D 对象上创建 material 的颜色印象、对光的响应、反射率和其他品质,需要创建和应用。这远不像说 "make objectABC be red" 那样简单,因为它在 2D 思维中。

单个文本对象(在 3D 中,不是你在 Cocoa 中对这些东西的看法)可能无法自动用不同的 materials and/or Material SceneKit 中的 ID。 Material ID 是如何将不同的 material 应用于单个对象的不同部分,例如 3ds Max,大多数人在其中创建几何体和 materials。

不幸的是,SceneKit 不遵循此约定,而是使用 'elements' 作为几何对象的一部分,每个对象都是索引的一部分,该索引对应于您提供的任何 material 几何.

您可以在此处阅读更多相关信息:

https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SCNGeometry_Class/index.html#//apple_ref/doc/uid/TP40012000-CLSCHSCNGeometry-SW15

因此,要获得您正在寻找的内容,您可能需要制作 3 个文本对象并为每个对象指定您想要的唯一 material 颜色, 或者将 3 个单词对象分解为 3 个元素,然后猜测如何将正确的 material 放到每个元素上。

编辑:忽略上一段的最后一部分。您需要制作 3 个文本对象以获得您想要的外观。 Scene Kit 中 material 分布的元素特性保留在文本对象上,因此您不能将单词级别的文本分解为不同的元素。

来自文档:

A text geometry may contain one, three, or five geometry elements:

  • If its extrusionDepth property is 0.0, the text geometry has one element corresponding to its one visible side.

  • If its extrusion depth is greater than zero and its chamferRadius property is 0.0, the text geometry has three elements, corresponding to its front, back, and extruded sides.

  • If both extrusion depth and chamfer radius are greater than zero, the text geometry has five elements, corresponding to its front, back, extruded sides, front chamfer, and back chamfer.