import ObjectRenderer from "../2d/renderers/webgl/ObjectRenderer";
import { WebglRenderer } from "../2d/renderers/WebglRenderer";
import { Camera } from "./cameras/Camera";
import { LightsConfig } from "./Scene3D";
import { GLShader, GLBuffer, VertexArrayObject } from "../glCore";
import { Mesh3D } from "./Mesh3D";
import { BaseShader } from "./shaders/BaseShader";
import { LightShader } from "./shaders/LightShader";
import { hex2rgb, rgb2hex } from "../2d/utils";
import { Matrix4 } from "./math/Matrix4";
import { BLEND_MODES } from "../2d/const";
import { BatchBuffer } from "../2d/renderers/webgl/BatchBuffer";
import { BaseMaterial, RenderSideType } from "./materials/BaseMaterial";
import { getCusShader } from "./shaders/getCusShader";
import { Geometry, VaoBufferInt } from ".";
import { SkinnedMesh3D } from "./bones/SkinnedMesh3D";
import { nextPow2 } from "../2d/utils"
import { BaseTexture } from "../2d/texture";
import { Vector3 } from "./math/Vector3";

let tempVec3 = new Vector3()
let tempMatrix4 = new Matrix4();
//需要管理渲染的状态 resetToDefault  resetTo3D
export class D3Renderer extends ObjectRenderer {
    /**
     * 赋值的相机，需要里面的worldMatrixInverse和projectionMatrix
     */
    camera: Camera;
    /**
     * 灯光数据，用来初始化着色器和着色器传值
     */
    lightsConfig: LightsConfig;

    /**
     * 顶点着色器可传的最大uniform通道
     */
    maxVertexUniforms: number
    floatVertexTextures: boolean;
    private curLightkey: string;
    constructor(renderer: WebglRenderer) {
        super(renderer);
    }
    onContextChange() {
        var gl = this.renderer.gl;
        this.maxVertexUniforms = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);
        var maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
        var vertexTextures = maxVertexTextures > 0;
        var floatFragmentTextures = !!gl.getExtension("OES_texture_float");
        //传入的数据纹理暂时有问题，是UNPACK_ALIGNMENT还是UNPACK_FLIP_Y_WEBGL的问题未知，所以不管先
        this.floatVertexTextures = false//vertexTextures && floatFragmentTextures;
    }
    start() {
        //设置3d状态机属性
        // this.renderer.state.resetTo3D();
        //自行设置状态机，原先的有太多问题
        //允许深度检测
        this.renderer.state.setDepthTest(1);
        //混色模式重新设置
        this.renderer.state.setBlendMode(BLEND_MODES.NORMAL_NPM);
        //设置逆时针为正面，下面根据材质自行设置
        //this.renderer.state.setFrontFace(0);
        //设置剔除，下面根据材质自行设置
        //this.setCullFace(1);
    }
    stop() {
        this.flush();
        //原先的视窗需要重新//讲道理应该渲染器自己搞，算了
        this.renderer._activeRenderTarget.activate();
        // this.renderer.rootRenderTarget.activate();

        this.renderer.state.setState(this.renderer.state.defaultState)
    }

    private meshes: Mesh3D[] = [];
    //继续需要的数据
    render(obj: Mesh3D) {
        if (!obj.geometry || !obj.material) return;
        var mat = obj.material;
        var geo = obj.geometry;
        //提取渲染对象及材质，分组渲染，怎么考虑同一个geometry只需要处理一次attr，
        //分组按
        // if (!this.meshes.length) {
        //     this.meshes.push(obj);
        // } else {
        for (var i = 0; i < this.meshes.length; i++) {
            if (this.meshes[i].material == mat) {//没啥软用
                this.meshes.splice(i, 0, obj)
                return
            }
        }
        // }
        this.meshes.push(obj);
    }
    flush() {
        //同一材质的模型一起处理，同一个着色器，webglRenderer里会判断，不会重复绑定
        var curShader: GLShader = null;
        var pointLightNum = this.lightsConfig.pointLights.length;
        var dirLightNum = this.lightsConfig.directionalLights.length;
        var gl: WebGLRenderingContext = this.renderer.gl;
        for (var i = 0; i < this.meshes.length; i++) {
            let mesh = this.meshes[i];//怎么判断是否要重新绑定
            let mat: BaseMaterial = mesh.material;
            let geo = mesh.geometry;
            let maxBones = this.getMaxBones(mesh)

            let shader = getCusShader(this.renderer, mat, this.lightsConfig, mesh, maxBones, this.floatVertexTextures);
            if (curShader !== shader) {//同一着色器只需要传一次相机参数和光照参数（因为都是场景全局）
                curShader = shader;
                //先绑定着色器，project不设置
                this.renderer.bindShader(curShader, false);
                //相机
                curShader.uniforms["uViewMatrix"] = this.camera.worldMatrixInverse.toArray();;
                curShader.uniforms["uProjectionMatrix"] = this.camera.projectionMatrix.toArray();
                //光照
                if (mat._lightAffect) {
                    //只能给当前绑定的shader传值，否则location不存在
                    for (var j = 0; j < pointLightNum; j++) {
                        let key = "pointLights[" + j + "]";
                        curShader.uniforms[key].color = this.lightsConfig.pointLights[j].color;
                        curShader.uniforms[key].position = this.lightsConfig.pointLights[j].position;
                        curShader.uniforms[key].distance = this.lightsConfig.pointLights[j].distance;
                        curShader.uniforms[key].decay = this.lightsConfig.pointLights[j].decay;
                    }
                    for (var j = 0; j < dirLightNum; j++) {
                        let key = "directionalLights[" + j + "]";
                        curShader.uniforms[key].color = this.lightsConfig.directionalLights[j].color;
                        curShader.uniforms[key].direction = this.lightsConfig.directionalLights[j].direction;
                    }
                    curShader.uniforms.uAmbientLightColor = this.lightsConfig.ambientLightColor;
                }
            }
            //是否带贴图
            if (mat.map) {
                //找纹理，绑定纹理，多个纹理也是一样的方法
                curShader.uniforms["uMap"] = this.renderer.textureManager.bindTexture(mat.map, undefined, false);
            }
            //是否带环境贴图
            if (mat.envMap) {
                //找纹理，绑定纹理，多个纹理也是一样的方法
                curShader.uniforms["uEnvMap"] = this.renderer.textureManager.bindTexture(mat.envMap, undefined, false);;
                //反射率
                curShader.uniforms["uReflectivity"] = mat.reflectivity;
                //传相机位置
                curShader.uniforms["uCameraPosition"] = tempVec3.setFromMatrixPosition(this.camera._worldMatrix).toArray();
            }
            //uniform参数修改，好像目前就几个，且固定的，以后得仿three建数组
            curShader.uniforms["uMatColor"] = mat.colorArr;
            curShader.uniforms["uMatAlpha"] = mat.alpha;

            //mesh的模型矩阵
            curShader.uniforms["uModelMatrix"] = mesh._worldMatrix.toArray();
            //法线矩阵
            if (curShader.uniforms.uNormalMatrix) {
                var modelViewMatrix = tempMatrix4.multiplyMatrices(this.camera.worldMatrixInverse, mesh._worldMatrix)
                var normalMatrix = modelViewMatrix.invert().transpose();
                // var normalMatrix = mesh._worldMatrix.invert().transpose();
                curShader.uniforms["uNormalMatrix"] = normalMatrix.toArray()
                // this.setShaderUniform(curShader, "uNormalMatrix", normalMatrix.toArray());
            }
            //骨骼需要的uniform
            if (mat.skinning && maxBones > 0) {
                //@ts-ignore
                let sMesh: SkinnedMesh3D = mesh;
                curShader.uniforms["uBindMatrix"] = sMesh.bindMatrix.toArray();
                curShader.uniforms["uBindMatrixInverse"] = sMesh.bindMatrixInverse.toArray();
                // sMesh.skeleton.update()
                var skeleton = sMesh.skeleton;
                if (skeleton) {
                    var bones = skeleton.bones;
                    if (this.floatVertexTextures) {
                        if (!skeleton.boneTexture) {
                            // layout (1 matrix = 4 pixels)
                            //      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
                            //  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
                            //       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
                            //       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
                            //       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
                            var size = Math.sqrt(bones.length * 4); // 4 pixels needed for 1 matrix
                            size = (function (value) {
                                return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2));
                            })(size);
                            size = Math.max(size, 4);
                            var boneMatrices = new Float32Array(size * size * 4); // 4 floats per RGBA pixel
                            boneMatrices.set(skeleton.boneMatrices); // copy current values
                            var boneTexture = new BaseTexture({ data: boneMatrices, width: size, height: size });
                            boneTexture.mipmap = false;
                            skeleton.boneMatrices = boneMatrices;
                            skeleton.boneTexture = boneTexture;
                            skeleton.boneTextureSize = size;
                        }
                        let location: number = this.renderer.textureManager.bindTexture(skeleton.boneTexture, undefined, false);
                        curShader.uniforms["uBoneTexture"] = location;
                        curShader.uniforms["uBoneTextureSize"] = skeleton.boneTextureSize;
                    } else {
                        curShader.uniforms["uBoneMatrices"] = sMesh.skeleton.boneMatrices;
                    }
                }

            }

            //几何属性
            var glVaoBuffer = geo._glVaoBuffer[this.renderer.CONTEXT_UID];
            if (!glVaoBuffer) {
                glVaoBuffer = geo._glVaoBuffer[this.renderer.CONTEXT_UID] = {
                    // indexBuffer: GLBuffer.createIndexBuffer(gl, null, gl.STATIC_DRAW),
                    attrBuffer: GLBuffer.createVertexBuffer(gl, null, gl.STATIC_DRAW),
                    vaos: {}
                }
                //有索引
                if (geo._indices) glVaoBuffer.indexBuffer = GLBuffer.createIndexBuffer(gl, null, gl.STATIC_DRAW);
                //TODO 有变形顶点，数据直接干进去，有性能问题再说 ，还是先不绑了，影响下面的vao
                if (geo._morphPositions) {//长度可以根据位置，还是根据，可能很多，用到时再建
                    glVaoBuffer.morphTargetBuffers = []; //mesh.morphTargetInfluences.length
                    // for (let m = 0; m < geo._morphPositions.length; m++) {
                    //     glVaoBuffer.morphTargetBuffers.push(
                    //         GLBuffer.createVertexBuffer(gl, /*geo._morphPositions[m]*/null, gl.STATIC_DRAW)
                    //     )
                    // }
                }
                //有变形法线
                if (geo._morphNormals) {
                    glVaoBuffer.morphNormalBuffers = [];
                    // for (let m = 0; m < geo._morphNormals.length; m++) {
                    //     glVaoBuffer.morphNormalBuffers.push(
                    //         GLBuffer.createVertexBuffer(gl, /*geo._morphNormals[m]*/null, gl.STATIC_DRAW)
                    //     )
                    // }
                }
                //骨骼
                if (geo._skinWeight) glVaoBuffer.skinWeightBuffer = GLBuffer.createVertexBuffer(gl, null, gl.STATIC_DRAW);
                if (geo._skinIndex) glVaoBuffer.skinIndexBuffer = GLBuffer.createVertexBuffer(gl, null, gl.STATIC_DRAW);

                //计算一次，打包所有的顶点属性，位置，颜色，uv，法线
                packGeometry(geo);
            }
            //@ts-ignore
            var vao = glVaoBuffer.vaos[curShader._glShaderKey];
            var attrs = curShader.attributes;
            if (!vao) {
                //@ts-ignore vao添加各种attribute
                vao = glVaoBuffer.vaos[curShader._glShaderKey] = this.renderer.createVao()
                    //索引
                    // .addIndex(glVaoBuffer.indexBuffer)
                    //顶点
                    .addAttribute(glVaoBuffer.attrBuffer, attrs.aPosition, gl.FLOAT, false, geo._vertByteSize, 0 * 4)
                //颜色
                // .addAttribute(glVaoBuffer.attrBuffer, attrs.aColor, gl.FLOAT, true, geo._vertByteSize, 3 * 4)
                //uv
                // .addAttribute(glVaoBuffer.attrBuffer, attrs.aTextureCoord, gl.FLOAT, true, geo._vertByteSize, 6 * 4)
                //法线
                // .addAttribute(glVaoBuffer.attrBuffer, attrs.aNormal, gl.FLOAT, false, geo._vertByteSize, 8 * 4);
                //颜色不一定有
                if (attrs.aColor) vao.addAttribute(glVaoBuffer.attrBuffer, attrs.aColor, gl.FLOAT, true, geo._vertByteSize, 3 * 4)
                //uv不一定有
                if (attrs.aTextureCoord) vao.addAttribute(glVaoBuffer.attrBuffer, attrs.aTextureCoord, gl.FLOAT, true, geo._vertByteSize, 6 * 4)
                //法线不一定有
                if (attrs.aNormal) vao.addAttribute(glVaoBuffer.attrBuffer, attrs.aNormal, gl.FLOAT, false, geo._vertByteSize, 8 * 4);

                //索引看情况加
                if (geo._indices) vao.addIndex(glVaoBuffer.indexBuffer);
                //骨骼的
                if (attrs.aSkinWeight) vao.addAttribute(glVaoBuffer.skinWeightBuffer, attrs.aSkinWeight, gl.FLOAT, false, 0, 0);
                if (attrs.aSkinIndex) vao.addAttribute(glVaoBuffer.skinIndexBuffer, attrs.aSkinIndex, gl.UNSIGNED_BYTE, false, 0, 0);
                //变形数据，首次直接addAttribute
                var uploadBufferDatas: UploadBufferData[];
                if (mesh.morphTargetInfluences && mat.morphTargets) {
                    uploadBufferDatas = addMorphtargetsAttr(
                        mesh.morphTargetInfluences,
                        geo,
                        glVaoBuffer,
                        vao,
                        curShader,
                        gl
                    )
                }
                // 首次需要绑定buffer到vao，先绑定vao再绑定buffer和上传数据（upload里传false）,其实bindVao貌似已经绑定过了，再说吧
                this.renderer.bindVao(vao);
                //所有数据绑定buffer，其实可以在上面构造GLBuffer里传数据，现在还是单独处理吧，这样判断比较多
                //需要分别绑定
                glVaoBuffer.attrBuffer.upload(geo._attrBuffer.vertices, 0, false);//首次还是bind吧，必须bind，否则buffer溢出
                //有索引才改
                if (geo._indices) glVaoBuffer.indexBuffer.upload(geo._indices, 0, false);//首次还是bind吧
                //骨骼的
                if (attrs.aSkinWeight) glVaoBuffer.skinWeightBuffer.upload(new Float32Array(geo._skinWeight), 0, false)
                if (attrs.aSkinIndex) glVaoBuffer.skinIndexBuffer.upload(new Uint8Array(geo._skinIndex), 0, false)
                //还得在这里做数据的变形
                if (uploadBufferDatas) uploadBufferDatas.forEach((e) => {
                    e.buffer.upload(e.data, 0, false);
                })
            } else {
                //变形数据，暂时只有这个要做改变，其他的估计到时也要搞，TODO
                var uploadBufferDatas: UploadBufferData[];
                if (mesh.morphTargetInfluences && mat.morphTargets) {
                    uploadBufferDatas = addMorphtargetsAttr(
                        mesh.morphTargetInfluences,
                        geo,
                        glVaoBuffer,
                        vao,
                        curShader,
                        gl
                    )
                }
                //进过上面判断，必有uploadBufferDatas，TODO,到时考虑不传force，用vao.dirty判断是否bind
                this.renderer.bindVao(vao, !!uploadBufferDatas);
                //不修改，估计都不要变，需要修改时候TODO.好多数据，包括vao可能也需要重新bind
                // glVaoBuffer.attrBuffer.upload(glVaoBuffer._attrBuffer.vertices, 0, true)
                // glVaoBuffer.indexBuffer.upload(glVaoBuffer._indexBuffer, 0, true)

                //变形的数据可能传入的会改变，所以需要upload，还要重新修改数据，有removeAttribute的情况，TODO
                //还得在这里做数据的变形，不绑定
                if (uploadBufferDatas) uploadBufferDatas.forEach((e) => {
                    e.buffer.upload(e.data, 0, false/*true*/);//貌似里面有修改的Attribute队列，所以还是绑定下buffer
                })
            }
            //根据材质切换渲染面
            if (mat.side == RenderSideType.DoubleSide) {
                this.renderer.state.setCullFace(0)//不开启剔除
            } else {
                this.renderer.state.setCullFace(1)
                //设置剔除面
                this.renderer.state.setFrontFace(mat.side)
            }
            //绘制
            vao.draw(mat.wireframe ? gl.LINES : gl.TRIANGLES);
        }
        this.meshes.length = 0
    }

    private getMaxBones(object) {
        if (object.instanceType !== "SkinnedMesh3D") return 0;
        if (this.floatVertexTextures) return 1024;
        var skeleton = object.skeleton;
        var bones = skeleton.bones;
        var nVertexMatrices = Math.floor((this.maxVertexUniforms - 20) / 4);
        var maxBones = Math.min(nVertexMatrices, bones.length);
        if (maxBones < bones.length) {
            console.warn('Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.');
            return 0;
        }
        return maxBones;
    }
}

/**
 * 组转集合的所有属性到一个_attrBuffer
 * @param geo 
 */
function packGeometry(geo: Geometry): void {
    const float32View = geo._attrBuffer.float32View;
    var count = 0;
    for (var j = 0; j < geo._vertices.length / 3; j++) {
        //顶点
        float32View[count++] = geo._vertices[j * 3];
        float32View[count++] = geo._vertices[j * 3 + 1];
        float32View[count++] = geo._vertices[j * 3 + 2];
        //@ts-ignore 颜色，以后搞成一位，现在有bug
        // geo._attrBuffer.uint32View[count++] = rgb2hex(geo._colors.slice(j * 3, j * 3 + 3)) + (1 * 255 << 24)
        float32View[count++] = geo._colors[j * 3];
        float32View[count++] = geo._colors[j * 3 + 1];
        float32View[count++] = geo._colors[j * 3 + 2];
        // float32View[count++] = 1;
        //uv
        float32View[count++] = geo._uvs[j * 2];
        float32View[count++] = geo._uvs[j * 2 + 1];
        //法线,可能不需要法线的情况，也加上先
        float32View[count++] = geo._normals[j * 3];
        float32View[count++] = geo._normals[j * 3 + 1];
        float32View[count++] = geo._normals[j * 3 + 2];
    }
}

interface UploadBufferData {
    //几何上的GLbuffer的索引
    buffer: GLBuffer,
    //几何上buffer的数据
    data: any//Float32Array | number[],
    //是否要绑定
    // dontBind: boolean,
}

//每个几何的权重缓存
const influencesList = {};
//每个几何的通道对应数据索引
const attrChannelHash = {}
//给uniform传值用
var morphInfluences = new Float32Array(8);

/**
 * 更新变形数据，考虑是否要变动attribute，只有
 * 返回要upload的数据
 * @param objectInfluences mesh上的权重数组
 * @param geo 几何
 * @param vao 
 */
function addMorphtargetsAttr(
    objectInfluences: number[],
    geo: Geometry,
    glVaoBuffer: VaoBufferInt,
    vao: VertexArrayObject,
    shader: GLShader,
    gl: WebGLRenderingContext,
): UploadBufferData[] {
    var morphTargets = geo._morphPositions;
    var morphNormals = geo._morphNormals;

    var length = objectInfluences.length;//权重数据总长度，基本不会被手动修改，到时排序只取权重大的，最多8
    //记录需要修改的数据
    var uploadBufferDatas: UploadBufferData[] = [];

    //原来几何上的权重，第一个元素标识数据索引，第二个元素标识值，第三个标识现在用的通道
    var influences: [number, number][] = influencesList[geo.instanceId];
    //如果原先不存在
    if (!influences) {
        influences = [];
        for (var i = 0; i < length; i++) {
            influences[i] = [i, 0];
        }
        influencesList[geo.instanceId] = influences;
    }
    //通道对应的数据，确定哪些通道的数据要重新upload
    var attrChannel: number[] = attrChannelHash[geo.instanceId];
    if (!attrChannel) {
        attrChannel = [];//通道对应，数据索引
        attrChannel.length = 8;
        attrChannelHash[geo.instanceId] = attrChannel;
    }

    //vao上挂着有变形数据的移除，讲道理也是最多8
    for (var i = 0; i < 8/*length*/; i++) {
        var influence = influences[i];
        if (influence && influence[1] !== 0) {
            if (morphTargets) vao.removeAttribute('morphTarget' + i);
            if (morphNormals && i < 4) vao.removeAttribute('morphNormal' + i);
        }
    }
    //重新处理变形数据，这个得排所有的
    for (var i = 0; i < length; i++) {
        var influence = influences[i];
        influence[0] = i;
        influence[1] = objectInfluences[i];
    }
    //按权重大小排序，大的优先
    influences.sort(absNumericalSort);


    var attrs = shader.attributes;
    //只取8个，不传着色器里计算并不会报错
    //有法线时只用4个，
    var attrLen = morphNormals ? 4 : 8;
    for (var i = 0; i < attrLen; i++) {
        var influence = influences[i];
        if (influence) {
            //索引
            var index = influence[0];
            var value = influence[1];
            if (value) {
                if (morphTargets && morphTargets[index]) {
                    //buffer没有就加
                    let targetBuffer = glVaoBuffer.morphTargetBuffers[index];
                    if (!targetBuffer) {
                        targetBuffer = glVaoBuffer.morphTargetBuffers[index] = GLBuffer.createVertexBuffer(gl, null, gl.STATIC_DRAW)
                    }
                    //记录需要修改传数据，通道值对应的buffer值不一致时，需要upload
                    if (attrChannel[i] !== index) {
                        attrChannel[i] = index;
                        uploadBufferDatas.push({
                            buffer: targetBuffer,
                            data: new Float32Array(morphTargets[index]) //data.vertices
                        })
                    }
                    vao.addAttribute(
                        targetBuffer,
                        attrs['morphTarget' + i],
                        gl.FLOAT,
                        false,
                        0,//3 * 4,
                        0 * 4,
                        'morphTarget' + i,
                    )
                }
                if (morphNormals && morphNormals[index]) {//法线只有4个
                    //buffer没有就加
                    let normalBuffer = glVaoBuffer.morphNormalBuffers[index];
                    if (!normalBuffer) {
                        normalBuffer = glVaoBuffer.morphNormalBuffers[index] = GLBuffer.createVertexBuffer(gl, null, gl.STATIC_DRAW)
                    }
                    //记录需要修改传数据，通道值对应的buffer值不一致时，需要upload，用后四个记录
                    if (attrChannel[i + 4] !== index) {
                        attrChannel[i + 4] = index;
                        uploadBufferDatas.push({
                            buffer: normalBuffer,
                            data: new Float32Array(morphNormals[index])
                        })
                    }
                    vao.addAttribute(
                        glVaoBuffer.morphNormalBuffers[index],
                        attrs['morphNormal' + i],
                        gl.FLOAT,
                        false,
                        0,// 3 * 4,
                        0 * 4,
                        'morphNormal' + i,
                    )
                }
                morphInfluences[i] = value;
                continue;
            }
        }
        morphInfluences[i] = 0;
    }
    //着色器修改
    shader.uniforms["morphTargetInfluences"] = morphInfluences;
    //需要修改数据的
    return uploadBufferDatas
}

function absNumericalSort(a: [number, number], b: [number, number]) {
    return Math.abs(b[1]) - Math.abs(a[1]);
}

interface renderObjInt {



}

WebglRenderer.registerPlugin('d3', D3Renderer);

// class FreeScroll extends FYGE.Container {
//     viewWidth;
//     viewHeight;
//     maxWidth;
//     maxHeight;
//     view
//     bg
//     constructor(viewWidth, viewHeight, maxWidth, maxHeight) {
//         super()
//         this.viewWidth = viewWidth
//         this.viewHeight = viewHeight
//         this.maxWidth = maxWidth
//         this.maxHeight = maxHeight

//         //鼠标事件捕捉用
//         this.bg = this.addChild(new FYGE.Graphics())
//             .beginFill(0x000000)
//             .drawRect(0, 0, viewWidth, viewHeight)
//             .endFill()
//         this.alpha = 0;
//         //内容视图
//         this.view = this.addChild(new FYGE.Container());
//         //x范围viewWidth-maxWidth到0，y范围viewHeight-maxHeight到0
//         this.addEventListener(FYGE.MouseEvent.MOUSE_DOWN, (e: FYGE.MouseEvent) => {
//             let offset = [e.stageX - this.view.x, e.stageY - this.view.y];
//             //加移动事件
//             this.addEventListener(FYGE.MouseEvent.MOUSE_MOVE, move, this)
//             this.addEventListener(FYGE.MouseEvent.MOUSE_UP, up, this)
//             this.addEventListener(FYGE.MouseEvent.MOUSE_OUT, up, this)
//             //移动
//             function move(me: FYGE.MouseEvent) {
//                 //赋值x
//                 this.view.x = me.stageX - offset[0];
//                 this.view.y = me.stageY - offset[1];
//                 //x有限制
//                 if (this.view.x < this.viewWidth - this.maxWidth) this.view.x = this.viewWidth - this.maxWidth;
//                 if (this.view.x > 0) this.view.x = 0;
//                 //y限制
//                 if (this.view.y < this.viewHeight - this.maxHeight) this.view.y = this.viewHeight - this.maxHeight;
//                 if (this.view.y > 0) this.view.y = 0;
//             }
//             function up() {
//                 this.removeEventListener(FYGE.MouseEvent.MOUSE_MOVE, move, this);
//                 this.removeEventListener(FYGE.MouseEvent.MOUSE_UP, up, this);
//                 this.removeEventListener(FYGE.MouseEvent.MOUSE_OUT, up, this);
//             }
//         }, this)
//     }
// }