objective-c - 如何将适用于 UIView 的 View 转换应用到 NSView?

标签 objective-c cocoa nsview transformation cgaffinetransform

我有一个 View 转换,可以使任何 UIView 对象遵循 cocos2d 节点。在 iOS 上运行良好,在此示例中,UIButton 遵循其 Box2D 主体:

enter image description here

现在,对于 Mac,我首先验证了我是否正确设置了覆盖 NSWindow,以便在 cocos2d OpenGL View 之上绘制 NSView 对象。这是可行的,就像在本例中使用 NSButton 一样:

enter image description here

但后来我了解到 NSView 没有 [NSView setTransform:..] 方法。我不确定这在 Mac 上是否有效,但我是这样做的:

// sometime after initializing the view
[nsView setWantsLayer:YES];

// every time I update transform:
nsView.layer.affineTransform = transform;

我验证了该层不为零。我还重新验证了启用 setWantsLayer 后 NSView 是否被绘制。结果令人失望,整个窗口上都看不到按钮,甚至看起来没有稍微偏移或镜像,只是不再存在了:

enter image description here

这让我看到了转换代码。正如我所说,这与 iOS 的代码相同(除了最后分配的转换)。它在 iOS 上完美运行(也可以在任何方向),但在带有 NSView 对象的 Mac OS X 上运行不正常,在 Mac OS X 上我根本看不到 NSView 对象。

我不确定这里可能出了什么问题,也许 CALayer 的工作方式不同,也许我只是犯了一个非常愚蠢而明显的错误。我就是找不到任何东西。

KKAppDelegate* ad = (KKAppDelegate*)[KTApplication sharedApplication].delegate;
float windowHeight = ad.window.frame.size.height;

float x = _position.x - _contentSize.width * _anchorPoint.x;
float y = windowHeight - (_position.y + _contentSize.height * _anchorPoint.y);

if (_ignoreAnchorPointForPosition)
{
    x += _anchorPointInPoints.x;
    y += _anchorPointInPoints.y;
}

float cx = 1, sx = 0, cy = 1, sy = 0;
if (_rotationX || _rotationY)
{
    float radiansX = CC_DEGREES_TO_RADIANS(_rotationX);
    float radiansY = CC_DEGREES_TO_RADIANS(_rotationY);
    cx = cosf(radiansX);
    sx = sinf(radiansX);
    cy = cosf(radiansY);
    sy = sinf(radiansY);
}

CGAffineTransform transform = 
    CGAffineTransformMake(cy * _scaleX, sy * _scaleX,
                          -sx * _scaleY, cx * _scaleY, x, y);

#if KK_PLATFORM_IOS
    _cocoaView.transform = transform;
#elif KK_PLATFORM_MAC
    _cocoaView.layer.affineTransform = transform;
#endif

我验证了代码运行并且 x/y 值符合预期(即没有负位置或疯狂值)。第一步甚至没有执行旋转,但在第一帧变换和绘制后我仍然看不到 NSView。

我完全不懂 CALayer 并将转换应用于 NSView。如果不是解决方案,那么我将不胜感激,然后提供有关如何调试此问题的一些提示。谢谢!

更新:

我开始尝试通过较小的值更改图层的变换,看看会发生什么。

CGAffineTransform transform = _cocoaView.layer.affineTransform;
transform = CGAffineTransformTranslate(transform, 0.1, 0.1);
_cocoaView.layer.affineTransform = transform;

其效果是一个缓慢移动的 NSButton。它不断向上和向右移动,但在 View 框架的边界矩形处消失:

enter image description here

所以我相信我的问题是 View 没有转换,只是图层 - 当我转换图层时,它会快速将 View 的内容绘制到图层边界之外,因此不再显示任何内容。

我是否可以假设我必须直接更改 View 的属性?文档也强调了这一点。我现在只是不知道如何将转换应用于 View (即我回到了原点)。我尝试手动设置旋转和框架原点,但这样我无法将旋转中心与cocos2d节点的中心(anchorPoint)对齐。

最佳答案

UIButtonNSButton 之间有一个重要的区别。即使 NSButton 最后是 NSView 的子类,NSButton 的渲染也是由它的单元格 NSButtonCell 完成的。 Cells 是作为 NSView 的“更轻”版本创建的。正如 Apple 的文档所述:

The NSCell class provides a mechanism for displaying text or images in an NSView object without the overhead of a full NSView subclass. It’s used heavily by most of the NSControl classes to implement their internal workings.

虽然这在早期的 Mac OS X 时代很有用,但现在已经不再是这样了,希望 Apple 在某个阶段能够在 AppKit 中改变这一点。

发生在你身上的是单元格被旋转,但随后它被 View 剪切,在你的例子中是按钮本身。

要解决这个问题,让 NSButton 的 super View 也支持图层,我相信剪辑将会消失:

[nsView.superview setWantsLayer:YES];

关于objective-c - 如何将适用于 UIView 的 View 转换应用到 NSView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16003803/

相关文章:

iphone - CATransform3DMakeRotation 的奇怪视角

iphone - 从另一个类更改 UILabel 的文本

objective-c - UITabBarController 带有 Storyboard 的自定义操作

objective-c - 使用自定义类属性使两个 NSMutableSet 相等

Cocoa - 高效 View 绘制

cocoa - 如何从 Cocoa 中的窗口 Controller 获取当前的第一响应者?

ios - 如何将.rtf文件显示到UITextView中

objective-c - 如何捕捉 NSWorkspaceDidPerformFileOperationNotification?

objective-c - 基于核心数据文档的基于选择的多个 Nib

cocoa - 在 NSView 中重复背景图像