共享node层级变换代码

提了很多关于节点层级改变时相关操作的问题,大家都很积极的帮助,现在把代码分享出来,谢谢大家。
cocos creator考虑升级时内置类似的功能吧。
主要就是变换父节点时,选择性保持原有世界变换。

1赞
var utils = {
    node: {
        /**
         * 将parentNode设置为childNode的父节点
         * @param {cc.Node} parentNode 
         * @param {cc.Node} childNode 
         * @param {bool} keepWorldTransform true,则维持childNode之前的世界变换
         */
        setParent(parentNode, childNode, keepWorldTransform) {
            if (parentNode === childNode.parent)
                return;

            if (keepWorldTransform === true) {
                // keep world transform not changed
                let worldPos = utils.node.getWorldPosition(childNode);
                let worldRotation = utils.node.getWorldRotation(childNode);
                let lossyScale = utils.node.getWorldScale(childNode);
    
                childNode.parent = parentNode;
    
                // restore world transform
                utils.node.setWorldPosition(childNode, worldPos);
                utils.node.setWorldRotation(childNode, worldRotation);
                if (parentNode) {
                    let parentWorldScale = utils.node.getWorldScale(parentNode);
                    lossyScale.x /= parentWorldScale.x;
                    lossyScale.y /= parentWorldScale.y;
                    childNode.scale = lossyScale;
                } else {
                    childNode.scale = lossyScale;
                }
            } else {
                childNode.parent = parentNode;
            }
        },
        /**
         * 获得node的世界坐标
         * @param {cc.Node} node 
         * @returns {cc.Vec2}
         */
        getWorldPosition(node) {
            return node.parent.convertToWorldSpaceAR(node.position);
        },
        /**
         * 将node设置到世界坐标worldPos处
         * @param {cc.Node} node
         * @param {cc.Vec2} worldPos
         */
        setWorldPosition(node, worldPos) {
            var parent = node.parent;
            if (parent) {
                node.position = parent.convertToNodeSpaceAR(worldPos);
            } else {
                node.position = worldPos;
            }
            return node.position;
        },
        /**
         * 获得node在世界坐标系下的旋转
         * @param {cc.Node} node 
         * @return {float}
         */
        getWorldRotation(node) {
            return utils.node.getNodeToWorldRotation(node.parent, node.rotation);
        },
        /**
         * 将node设置为世界坐标系下旋转worldRotation的姿态
         * @param {cc.Node} node 
         * @param {cc.Vec2} worldRotation 
         */
        setWorldRotation(node, worldRotation){
            node.rotation = utils.node.getWorldToNodeRotation(node.parent, worldRotation);
            //
            return node.rotation;
        },
        /**
         * 获得node在世界坐标下的缩放
         * @param {cc.Node} node 
         * @returns {cc.Vec2}
         */
        getWorldScale(node){
            return utils.node.getNodeToWorldScale(node.parent, node.scaleX, node.scaleY);
        },
        /**
         * 将node设置为在世界坐标下缩放worldScale的形态
         * @param {cc.Node} node 
         * @param {*} worldScale 
         */
        setWorldScale(node, worldScale){
            var s = utils.node.getWorldToNodeScale(node.parent, worldScale.x, worldScale.y);
            node.scale = s;
            //
            return node.scale;
        },
        /**
         * 获得node本地坐标系下的点在世界坐标系下的位置
         * @param {cc.Node} node 
         * @param {cc.Vec2} positionInNode 
         */
        getNodeToWorldPosition(node, positionInNode){
            if (node === null)
                return positionInNode;
            return node.convertToWorldSpaceAR(positionInNode);
        },
        /**
         * 获得世界坐标系下的点在node本地坐标下的位置
         * @param {cc.Node} node 
         * @param {cc.Vec2} positionInWorld 
         */
        getWorldToNodePosition(node, positionInWorld){
            if (node === null)
                return positionInWorld;
            return node.convertToNodeSpaceAR(positionInWorld);
        },
        /**
         * 获得node本地坐标下的缩放在世界坐标下的缩放量
         * @param {cc.Node} node 
         * @param {float} scaleXInNode 
         * @param {float} scaleYInNode 
         */
        getNodeToWorldScale(node, scaleXInNode, scaleYInNode) {
            // if (node === null)
            //     return new cc.Vec2(scaleXInNode, scaleYInNode);
            var scaleX = scaleXInNode;//node.scaleX;
            var scaleY = scaleYInNode;//node.scaleY;
            var parent = node;//.parent;
            while (parent){// && parent.parent) {
                scaleX *= parent.scaleX;
                scaleY *= parent.scaleY;
                parent = parent.parent;
            }
            // return new cc.Vec2(scaleX, scaleY);
            return new cc.Vec2(scaleX, scaleY);
        },
        /**
         * 获得世界缩放在node本地坐标下的缩放量
         * @param {cc.Node} node 
         * @param {float} scaleXInWorld 
         * @param {float} scaleYInWorld 
         */
        getWorldToNodeScale(node, scaleXInWorld, scaleYInWorld) {
            // if (node === null)
            //     return new cc.Vec2(scaleXInWorld, scaleYInWorld);
            // var scale = utils.node.getNodeToWorldScale(node.parent, node.scaleX, node.scaleY);
            var scale = utils.node.getWorldScale(node);
            return new cc.Vec2(scaleXInWorld / scale.x, scaleYInWorld / scale.y);
        },
        /**
         * 获得node本地坐标下的旋转在世界坐标下的旋转量
         * @param {cc.Node} node 
         * @param {float} rotationInNode 
         */
        getNodeToWorldRotation(node, rotationInNode) {
            // if (node === null)
            //     return rotationInNode;
            var rot = rotationInNode;//node.rotationX;
            var parent = node;//.parent;
            while (parent){//} && parent.parent) {
                rot += parent.rotation;
                parent = parent.parent;
            }
            return rot;
        },
        /**
         * 获得世界坐标下的旋转在node本地坐标下的旋转量
         * @param {cc.Node} node 
         * @param {float} rotationInWorld 
         */
        getWorldToNodeRotation(node, rotationInWorld) {
            // if (node === null)
            //     return rotationInWorld;
            var rotation = rotationInWorld;
            // rotation -= node.rotation;
            var parent = node;//.parent;
            while (parent){//} && parent.parent) {
                rotation -= parent.rotation;
                parent = parent.parent;
            }
            return rotation;
        },
    },
};
module.exports = utils;
5赞

很好的代码,记录一下

感谢分享代码,正需要这个功能,不知道官方有没有类似的API。

你好,谢谢你的热心反馈,我们现在已经计划在 3.x 版本支持这个设计。具体支持版本尚不明确。