pixijs / layers

Separate the z-hierarchy of your scene tree from its canonical structure.
https://pixijs.io/layers/docs/
MIT License
224 stars 57 forks source link

pixi-display + pixi-light Crash #25

Closed jonlepage closed 6 years ago

jonlepage commented 6 years ago

Hi ivan I have a small crash experimenting with pixi light and the layer system. I do not know if these my group system would cause this? I separated the process in 2 steps for easy debug.

Step1, the loader will inject resource in a global variable. at this step are all fine.

// ┌------------------------------------------------------------------------------┐
// PIXI LOADER for light ressources (testing)
//└------------------------------------------------------------------------------┘
_SLL.prototype.load_pixiLight = function() {
    const loader_light = new PIXI.loaders.Loader();
    loader_light.add('bg_diffuse', 'lightIMG/BGTextureTest.jpg')
        .add('bg_normal', 'lightIMG/BGTextureNORM.jpg')
        .add('block_diffuse', 'lightIMG/block.png')
        .add('block_normal', 'lightIMG/blockNormalMap.png');
    loader_light.load(onAssetsLoaded);

    function onAssetsLoaded(loader, res) {
        $SLL.resourceLight = { // add reference to $SLL global (debug only)
             bg:[res.bg_diffuse.texture, res.bg_normal.texture],
             block:[res.block_diffuse.texture, res.block_normal.texture],
             block1:[res.block_diffuse.texture, res.block_normal.texture],
             block2:[res.block_diffuse.texture, res.block_normal.texture]
        }
    };

    loader_light.onComplete.add(() => {$SLL.setLightLoaded()}); // tell the light loader are finish
};

step2 i initialise my layers system (original) and after inject light feature in the stage. the stage "this" are initialise before in other module. stage

Stage.prototype = Object.create(PIXI.display.Stage.prototype);
Stage.prototype.constructor = Stage;
Stage.prototype.initialize = function() {
    PIXI.display.Stage.call(this);
    this.interactive = false; // The interactive flag causes a memory leak.
};

step2 look at end on // PIXI LIGHT TEST IMPLEMENTATION

// LAYER ASIGNATION TO MAP STAGE
Spriteset_Map.prototype.createLowerLayer = function() {
    Spriteset_Base.prototype.createLowerLayer.call(this);
    // TODO: create global display.Group for avoid init each time new map loaded
    this.displayGroup = [
        new PIXI.display.Group(0, false), // backgroud Map. BG tile elements will no update and no interaction
        new PIXI.display.Group(1, true), // map elements default player, chara and all basic sprite update z and interaction
        new PIXI.display.Group(2, true), // map elements 2er
        new PIXI.display.Group(3, true), // map elements 3er
        new PIXI.display.Group(4, false), //levelGui: GUI Elements over maps
        new PIXI.display.Group(5, false), //levelMenu: MENU Elements over maps
        new PIXI.display.Group(6, false), //levelTxt: txt bubble, or SFX over all
    ];
    this.displayLayers = [];
    for (let l = 0, len = this.displayGroup.length; l < len; l++) {
        const DG = this.displayGroup[l];
        const DL = new PIXI.display.Layer(DG);
        this.displayLayers.push(DL);//(debugOnly) reference acces ref
        this.addChild(DL); // add to Stage PIXI.display
    };

    // PIXI LIGHT TEST IMPLEMENTATION
    var light = new PIXI.lights.PointLight(0xffffff, 1);
    this.addChild(new PIXI.display.Layer(PIXI.lights.diffuseGroup));
    this.addChild(new PIXI.display.Layer(PIXI.lights.normalGroup));
    this.addChild(new PIXI.display.Layer(PIXI.lights.lightGroup));
    // create ligth and normal
    function createPair(diffuseTex, normalTex) {
        var container = new PIXI.Container();
        var diffuseSprite = new PIXI.Sprite(diffuseTex);
        diffuseSprite.parentGroup = PIXI.lights.diffuseGroup;
        var normalSprite = new PIXI.Sprite(normalTex);
        normalSprite.parentGroup = PIXI.lights.normalGroup;
        container.addChild(diffuseSprite);
        container.addChild(normalSprite);
        return container;
    }

    let PAIR = {};
    for (const key in $SLL.resourceLight) {
        const res = $SLL.resourceLight[key];
        PAIR[key] = createPair(res[0], res[1]);
    }
    console.log('PAIR: ', PAIR); // add to stage
    this.addChild(PAIR.bg);
    this.addChild(PAIR.block);
    this.addChild(PAIR.block1);
    this.addChild(PAIR.block2);

    this.addChild(new PIXI.lights.AmbientLight(null, 0.4)); // GET ERROR !!!

    //... other stuff
};

at the line this.addChild(new PIXI.lights.AmbientLight(null, 0.4)); i get a error texLayer.getRenderTexture is not a function

image

if i remove this line, i can see all the element normal seem loaded. image

did you know what i'm doing wrong in my context ? i think it where and how i add light with new PIXI.display.Group? thank

ivanpopelyshev commented 6 years ago

https://github.com/pixijs/pixi-display/tree/layers/dist

ivanpopelyshev commented 6 years ago

Also, if you are going to add it above everything else, you have to use extra trick, otherwise there will be a problem with transparency. You have to render all "lighted" objects black-colored before they get lighted:

 var diffuseLayer = new PIXI.display.Layer(PIXI.lights.diffuseGroup);
  diffuseLayer.clearColor = [0,0,0,0];
  stage.addChild(diffuseLayer);
  var blackSprite = new PIXI.Sprite(diffuseLayer.getRenderTexture());
  blackSprite.tint = 0;
  stage.addChild(blackSprite);
  stage.addChild(new PIXI.display.Layer(PIXI.lights.normalGroup));
  stage.addChild(new PIXI.display.Layer(PIXI.lights.lightGroup));

Also, you can make your groups global, you dont have to re-create them for each scene :)

jonlepage commented 6 years ago

ok so the link you give to me, i need to replace by my current pixi-layers.js ? I did not have the right one?

you have to use extra trick, otherwise there will be a problem with transparency.

ok i will take a look, am on this experimentation today. Il will try to figure if it a good idea to add to my project :)

edit:, am not shure if i will add above all, am just testing to try understand how it work for now. I will maybe do in another way, when i will succeed in making it work.

jonlepage commented 6 years ago

ok i just look the file , a lot change , i will update! thank a question, why do you no longer write the //commented version in the top in the file? I wonder because, I found it useful

ivanpopelyshev commented 6 years ago

because i dont have automatic build for that. And im lazy to add it.

jonlepage commented 6 years ago

@ivanpopelyshev ok on the rock , thank. Now it time to study this , Youpii image

jonlepage commented 6 years ago

@ivanpopelyshev did you know if the loader can autoDetect normal map prefix ? Or i need to do it in my node path scanner? I do not find in the resources the normal version and when I export with texture packer, the json does not seem to have the information indicating that there have a normal append .

packer with same layout image

file + prefix image

and json data

{"frames": {

"4w46477ut.png":
{
    "frame": {"x":74,"y":456,"w":65,"h":49},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":65,"h":49},
    "sourceSize": {"w":65,"h":49}
},
"46whh.png":
{
    "frame": {"x":1,"y":456,"w":71,"h":52},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":71,"h":52},
    "sourceSize": {"w":71,"h":52}
},
"66464hfgj.png":
{
    "frame": {"x":1,"y":1,"w":358,"h":453},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":358,"h":453},
    "sourceSize": {"w":358,"h":453}
},
"e7jsdt.png":
{
    "frame": {"x":760,"y":138,"w":47,"h":145},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":47,"h":145},
    "sourceSize": {"w":47,"h":145}
},
"m9sum93rts.png":
{
    "frame": {"x":667,"y":367,"w":93,"h":139},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":93,"h":139},
    "sourceSize": {"w":93,"h":139}
},
"nys8esn8r.png":
{
    "frame": {"x":569,"y":138,"w":163,"h":114},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":163,"h":114},
    "sourceSize": {"w":163,"h":114}
},
"roundcase.png":
{
    "frame": {"x":361,"y":447,"w":100,"h":59},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":100,"h":59},
    "sourceSize": {"w":100,"h":59}
},
"roundcasedir4.png":
{
    "frame": {"x":463,"y":447,"w":100,"h":59},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":100,"h":59},
    "sourceSize": {"w":100,"h":59}
},
"roundcaseunknow.png":
{
    "frame": {"x":565,"y":447,"w":100,"h":59},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":100,"h":59},
    "sourceSize": {"w":100,"h":59}
},
"s8un389uq4.png":
{
    "frame": {"x":612,"y":254,"w":146,"h":111},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":146,"h":111},
    "sourceSize": {"w":146,"h":111}
},
"tswetytyt.png":
{
    "frame": {"x":361,"y":270,"w":249,"h":175},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":249,"h":175},
    "sourceSize": {"w":249,"h":175}
},
"udty7634634.png":
{
    "frame": {"x":361,"y":1,"w":206,"h":267},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":206,"h":267},
    "sourceSize": {"w":206,"h":267}
},
"w6n4n6wn.png":
{
    "frame": {"x":569,"y":1,"w":202,"h":135},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":202,"h":135},
    "sourceSize": {"w":202,"h":135}
},
"we64b7utuy.png":
{
    "frame": {"x":773,"y":1,"w":17,"h":116},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":17,"h":116},
    "sourceSize": {"w":17,"h":116}
}},
"meta": {
    "app": "https://www.codeandweb.com/texturepacker",
    "version": "1.0",
    "image": "house1Test.png",
    "format": "RGBA8888",
    "size": {"w":808,"h":509},
    "scale": "1",
    "smartupdate": "$TexturePacker:SmartUpdate:8e2c65cd8ff2b68aa7705f0c5a221e72:68dc3bc61427f8f4faf3c15e35cd1e87:af9fc7f2dc2c1f6ea254735ecd3a73dc$"
}
}

do i need to write myself the code, or you have already a option somewhere in the loader that can auto-load normal ? thank

ivanpopelyshev commented 6 years ago

deal with it.

ivanpopelyshev commented 6 years ago

You can extend Spritesheet that it creates several textures per every frame, based on several base textures. We dont have solution for that yet, and honestly, we didnt need it because we had no deferred rendering support.

ivanpopelyshev commented 6 years ago

I also advice you to think , which kind of lighting do you want to use. Normals are fun, but its all up to you to decide whether something like modified AdjustmentFilter will work better.

Even "Enter The Gungeon" game uses simple lightmaps instead of that.

jonlepage commented 6 years ago

I will see if a can extend manually metadata from the loader. maybe something like

"meta": {
        "LAYOUT": "true", ******
    "app": "https://www.codeandweb.com/texturepacker",
    "version": "1.0",
    "image": "house1Test.png",
    "format": "RGBA8888",
    "size": {"w":808,"h":509},
    "scale": "1",
    "smartupdate": "$TexturePacker:SmartUpdate:8e2c65cd8ff2b68aa7705f0c5a221e72:68dc3bc61427f8f4faf3c15e35cd1e87:af9fc7f2dc2c1f6ea254735ecd3a73dc$"
}

this should avoid me to add extra scan folder with node , to try find a _prefix. Normal textures will have automaticallyname+"_n" prefix on each textures. image

which kind of lighting do you want to use

For the moment I experiment, the tests with Spriteilluminator seem satisfactory to me, it remains to see what it will give once implement correctly.

all the images you see have nothing to do with my project, they are models quickly made to set up a structure of development.

For my light system, Ideally, a global light that will have the role of the sun and its global position, which day on the luminosity according to an internal clock of the game. And I will love to see what it will look like with the active camera.

jonlepage commented 6 years ago

did you have a idea or suggest how i can merge multiple level layers groupe with light ? http://pixijs.io/examples/#/layers/zorder.js http://pixijs.io/examples/#/layers/normals.js

i succeed understand how deal with loader and add to stage. But am not sure how proceed to keep or merge multi group sorting with z-index. ygvdbzcp_o 1

    new PIXI.display.Group(0, false), // ALLOW LIGHT
    new PIXI.display.Group(1, true), //  ALLOW LIGHT
    new PIXI.display.Group(2, true), // ALLOW LIGHT
    new PIXI.display.Group(3, false), //  ALLOW LIGHT
    new PIXI.display.Group(4, false), //levelGui: GUI NOT LIGHT*
    new PIXI.display.Group(5, false), //levelMenu: MENU NOT LIGHT*
    new PIXI.display.Group(6, false), //levelTxt: txt,sfx NOT LIGHT*
ivanpopelyshev commented 6 years ago

you have to enable the same kind of sorting inside pixi-lights groups.

ivanpopelyshev commented 6 years ago

I know its a problem that you need sort all those things and modify groups :( ill help you if it goes wrong

jonlepage commented 6 years ago

ok thank i make some test and i will maybe back to you in some hour

jonlepage commented 6 years ago

I think it not possible in my context?, i need to create multi diffuse Group new PIXI.lights.diffuseGroup(zIndex, sorting) that not seem possible actually with pixi.light ?

i also try other way...

cage_mouse = new PIXI.Container(); // cage follow mouse 
cage_mouse.parentGroup = new PIXI.display.Group(1, true);
cage_mouse.zIndex = 999; // update with mouse Y
cage_sprite = createPair(tex, normalTex); // merged light sprite container
cage_mouse.addChild(cage_sprite );  // unable to sorting ?cage_mouse

Maybe a functional demo or code can help me a lot :) the only way I can interpret is to be able to replace

var dg = new PIXI.display.Group(1, true);
var dl = new PIXI.display.Layer(dg ); 

by

var dg = PIXI.lights.diffuseGroup(1,true);
var dl = new PIXI.display.Layer(dg );
ivanpopelyshev commented 6 years ago

You can put several layers INSIDE diffuseLayer and normalLayer as a children. inner layers will sort things for you, and outer layer will render it to textures that are needed for lights.

I hope you dont have any non-lighted layers between, but even in that case, i have some crazy ideas ;) Your case is a best one for testing my pixi-layers idea.

jonlepage commented 6 years ago

You can put several layers INSIDE diffuseLayer

ok so maybe i made a mistake somewhere, thank to say is possible. i try several layers INSIDE layer, but the parent not sorting. I will check this

ivanpopelyshev commented 6 years ago

i mean with addChild :) parent doesnt have to sort it.

ivanpopelyshev commented 6 years ago

I understand that for every old layer that you want to light you need two layers now, and they will sort independently. Unfortunately, there're no shortcuts in pixi-layers for that. It will use z-index and z-order from the normal/diffuse instead their parent, you might want to change either sorting function either pass z-index z-order inside.

Try more, then i'll help you if you become stuck.

Again, im telling you that im proud that you are doing it. you are proving that its possible to make custom rendering pipeline with pixi-layers.

jonlepage commented 6 years ago

@ivanpopelyshev plz copy past the code block in the pixi demo.

A rather complex hack to do could be to create a factor on the index z which multiplies by the maximum height of the scene if it is based on a Sort by Y. This can become very complex because it will eventually take into consideration the zoom and position of the pivot of the scene.

Logically could the z-order not represent a layer factor? Knowing that the z-inder sort work. If i set block1.zOrder=1,block2.zOrder=6; zorder not have impact if z Index existe.

I made you a demo, can you copy paste this snippet to http://pixijs.io/examples/#/layers/normals.js I also add a little debugger with pixi text. z index works, where I stuck, these for the group system. You can drag block to see all work fine. Where am stuck, is how i can told block1 are now in a group1, block2 are in a groupe2. and sort z of groupe 1 will have not impact on sort z of group2 Click on G to bind a zOrder on block.

var WIDTH = 800, HEIGHT = 600;
var mX,mY; //global mouse position
var block1,block2; // global block

// LAYERS plugin is here: https://github.com/pixijs/pixi-display/tree/layers
// LIGHTS plugin is here: https://github.com/pixijs/pixi-lights/tree/v4.x
var app = new PIXI.Application(WIDTH, HEIGHT);
document.body.appendChild(app.view);
var stage = app.stage = new PIXI.display.Stage();
function hexColors() { return ('0x' + Math.floor(Math.random() * 16777215).toString(16) || 0xffffff) }; // rancolor
var light = new PIXI.lights.PointLight(0xffffff, 2);
    light.position.set(WIDTH/2, HEIGHT/2); // fixed light
(function(){//info top key 
    var style = new PIXI.TextStyle({fill:0xffffff,fontSize:16});
    var text = new PIXI.Text(`click on key "G" to bind a zOrder or reset position`, style);
    text.position.x = WIDTH/2;
    stage.addChild(text);
})();

// put all layers for deferred rendering of normals
stage.addChild(new PIXI.display.Layer(PIXI.lights.diffuseGroup));
stage.addChild(new PIXI.display.Layer(PIXI.lights.normalGroup));
stage.addChild(new PIXI.display.Layer(PIXI.lights.lightGroup));
PIXI.lights.diffuseGroup.enableSort = true;
PIXI.lights.normalGroup.enableSort = true;
PIXI.lights.normalGroup.lightGroup = true;
PIXI.loader.baseUrl = 'https://cdn.rawgit.com/pixijs/pixi-lights/b7fd7924fdf4e6a6b913ff29161402e7b36f0c0f/';
PIXI.loader
    .add('bg_diffuse', 'test/BGTextureTest.jpg')
    .add('bg_normal', 'test/BGTextureNORM.jpg')
    .add('block_diffuse', 'test/block.png')
    .add('block_normal', 'test/blockNormalMap.png')
    .load(onAssetsLoaded);

function onAssetsLoaded(loader, res) {
    function addInfoTxt(container){
        var color = hexColors();
        var style = new PIXI.TextStyle({fill:color,fontSize:14});
        var text0 = new PIXI.Text(`x:0 y:0, w:0, h:0`, style);
            text0.pivot.set(text0.width/2,text0.height/2);
        var text1 = new PIXI.Text(`zIndex:0 zOrder:0`, style);
            text1.pivot.set(text1.width/2,text1.height/2);
            text1.position.y = container.height;
        container.addChild(text0,text1);
        return [text0,text1];
    };

    //create container and merge [tex_d,tex_n]
    function createPair(diffuseTex, normalTex, _pivot) {
        var container = new PIXI.Container();
        var diffuseSprite = new PIXI.Sprite(diffuseTex);
            diffuseSprite.parentGroup = PIXI.lights.diffuseGroup;
        var normalSprite = new PIXI.Sprite(normalTex);
            normalSprite.parentGroup = PIXI.lights.normalGroup;
        container.addChild(diffuseSprite,normalSprite);
        // bad pivot ? compute ?
        _pivot && container.pivot.set(container.width/2,container.height);
        container.txt = addInfoTxt(container);
        container.mergedSprites = [diffuseSprite,normalSprite];
        return container;
    };

    var bg = createPair(res.bg_diffuse.texture, res.bg_normal.texture);
        bg.zIndex = 0, bg.zOrder =0;
    block1 = createPair(res.block_diffuse.texture, res.block_normal.texture, true);
        block1.mergedSprites[0].tint = 0xf45642; // change tint block
        block1.position.set(100, 100);
        block1.interactive = true;
        block1.on('mousedown', onDragStart).on('touchstart', onDragStart);
    block2 = createPair(res.block_diffuse.texture, res.block_normal.texture, true);
        block2.position.set(300, 400);
        block2.interactive = true;
        block2.on('mousedown', onDragStart).on('touchstart', onDragStart);

    stage.addChild(bg);
    stage.addChild(block1);
    stage.addChild(block2);

    stage.addChild(new PIXI.lights.AmbientLight(null, 0.4));
    stage.addChild(new PIXI.lights.DirectionalLight(null, 1, block1));
    stage.addChild(light);

    bg.interactive = true;
    bg.on('pointerdown', function (event) {
        var clickLight = new PIXI.lights.PointLight(0xffffff);
        clickLight.position.copy(event.data.global);
        stage.addChild(clickLight);
    });
};

// EVENTS
function onDragStart(event) {
    this.dragging = true;
};

// update data text,order,zindex
function updateData(block){
    block.x=mX, block.y = mY;
    block.mergedSprites.forEach(sprite => { // update z for _difuse && _normal
        //sprite.zOrder = block.y;
        sprite.zIndex = block.y;
    });
    block.txt[0].text = `x:${mX} y:${mY} w:${block.width} h:${block.height}`;
    block.txt[1].text = `zIndex:${block.mergedSprites[0].zIndex} zOrder:${block.mergedSprites[0].zOrder}`;
};

// mouse x,y update
function mousemove_(event){
    mX = event.clientX, mY = event.clientY
    block1.dragging && updateData(block1);
    block2.dragging && updateData(block2);
};

// mouse x,y update
function mouseup_(event){ 
    block1.dragging = false;
    block2.dragging = false;
};

// inverse order groupe ?!
function keydown_changeGroupe(event){
    console.log('event: ', event);
    if(event.key==="g"){
        block1.mergedSprites.forEach(sprite => { // update z for _difuse && _normal
            sprite.zOrder = block1.y;
        });
        block2.mergedSprites.forEach(sprite => { // update z for _difuse && _normal
            sprite.zOrder = block2.y;
        });
    updateData(block1),updateData(block2);
    }
};
// classic listener
document.addEventListener('mousemove', mousemove_);
document.addEventListener('mouseup',mouseup_);
document.addEventListener('keydown', keydown_changeGroupe);
ivanpopelyshev commented 6 years ago

how default sorting works: https://github.com/pixijs/pixi-display/blob/layers/src/Group.ts#L77

And yes, that's the problem - sort z of groupe 1 will have not impact on sort z of group2.

You have to change layer sorting algorithm somehow, override group doSort method: https://github.com/pixijs/pixi-display/blob/layers/src/Group.ts#L64 , I dont know how, just think about it for a day. I do not have easy answer on it yet.

I have an idea:

  1. hack the diffuse layer that way it stores the index of element in sorted array somewhere in that element.
  2. normal layer should use it somehow.
ivanpopelyshev commented 6 years ago

We're working with cutting edge pixi api there. If you have any ideas of API to show that normals and sprites are "together", please tell me

One of my ideas- add special flag to the group that elements inside need the sorting to other groups after the container was sorted in this one.

Let me think about it tomorrow, maybe its easy to make and I'll update the library for you.

jonlepage commented 6 years ago

An idea that quickly turned out bad, but could possibly be your inspiration. copy paste snippet to http://pixijs.io/examples/#/layers/normals.js Try hold click on a block and push a key number to change the layerGroupe of the current block dragging.

var WIDTH = 800, HEIGHT = 600;
var mX,mY; //global mouse position
var block1,block2; // global block

// LAYERS plugin is here: https://github.com/pixijs/pixi-display/tree/layers
// LIGHTS plugin is here: https://github.com/pixijs/pixi-lights/tree/v4.x
var app = new PIXI.Application(WIDTH, HEIGHT);
document.body.appendChild(app.view);
var stage = app.stage = new PIXI.display.Stage();
function hexColors() { return ('0x' + Math.floor(Math.random() * 16777215).toString(16) || 0xffffff) }; // rancolor
var light = new PIXI.lights.PointLight(0xffffff, 2);
    light.position.set(WIDTH/2, HEIGHT/2); // fixed light
(function(){//info top key 
    var style = new PIXI.TextStyle({fill:0xffffff,fontSize:16});
    var text = new PIXI.Text(`hold click on block + key number for change groupe`, style);
    text.position.x = 50;
    stage.addChild(text);
})();

// put all layers for deferred rendering of normals
stage.addChild(new PIXI.display.Layer(PIXI.lights.diffuseGroup));
stage.addChild(new PIXI.display.Layer(PIXI.lights.normalGroup));
stage.addChild(new PIXI.display.Layer(PIXI.lights.lightGroup));
PIXI.lights.diffuseGroup.enableSort = true;
PIXI.lights.normalGroup.enableSort = true;
PIXI.lights.normalGroup.lightGroup = true;
PIXI.loader.baseUrl = 'https://cdn.rawgit.com/pixijs/pixi-lights/b7fd7924fdf4e6a6b913ff29161402e7b36f0c0f/';
PIXI.loader
    .add('bg_diffuse', 'test/BGTextureTest.jpg')
    .add('bg_normal', 'test/BGTextureNORM.jpg')
    .add('block_diffuse', 'test/block.png')
    .add('block_normal', 'test/blockNormalMap.png')
    .load(onAssetsLoaded);

function onAssetsLoaded(loader, res) {
    function addInfoTxt(container){
        var color = hexColors();
        var style = new PIXI.TextStyle({fill:color,fontSize:14});
        var text0 = new PIXI.Text(`x:0 y:0, w:0, h:0`, style);
            text0.pivot.set(text0.width/2,text0.height/2);
        var text1 = new PIXI.Text(`zIndex:0 zOrder:0 groupe:0`, style);
            text1.pivot.set(text1.width/2,text1.height/2);
            text1.position.y = container.height;
        container.addChild(text0,text1);
        return [text0,text1];
    };

    //create container and merge [tex_d,tex_n]
    function createPair(diffuseTex, normalTex, _pivot) {
        var container = new PIXI.Container();
        var diffuseSprite = new PIXI.Sprite(diffuseTex);
            diffuseSprite.parentGroup = PIXI.lights.diffuseGroup;
        var normalSprite = new PIXI.Sprite(normalTex);
            normalSprite.parentGroup = PIXI.lights.normalGroup;
        container.addChild(diffuseSprite,normalSprite);
        // bad pivot ? compute ?
        _pivot && container.pivot.set(container.width/2,container.height);
        container.txt = addInfoTxt(container);
        container.mergedSprites = [diffuseSprite,normalSprite];
        return container;
    };

    var bg = createPair(res.bg_diffuse.texture, res.bg_normal.texture);
        bg.zIndex = 0, bg.zOrder =0;
        bg.groupe = 0;
    block1 = createPair(res.block_diffuse.texture, res.block_normal.texture, true);
        block1.groupe = 0;
        block1.mergedSprites[0].tint = 0xf45642; // change tint block
        block1.position.set(100, 100);
        block1.interactive = true;
        block1.on('mousedown', onDragStart).on('touchstart', onDragStart);
    block2 = createPair(res.block_diffuse.texture, res.block_normal.texture, true);
        block2.groupe = 0;
        block2.position.set(300, 400);
        block2.interactive = true;
        block2.on('mousedown', onDragStart).on('touchstart', onDragStart);

    stage.addChild(bg);
    stage.addChild(block1);
    stage.addChild(block2);

    stage.addChild(new PIXI.lights.AmbientLight(null, 0.4));
    stage.addChild(new PIXI.lights.DirectionalLight(null, 1, block1));
    stage.addChild(light);

    bg.interactive = true;
    bg.on('pointerdown', function (event) {
        var clickLight = new PIXI.lights.PointLight(0xffffff);
        clickLight.position.copy(event.data.global);
        stage.addChild(clickLight);
    });
};

// EVENTS
function onDragStart(event) {
    this.dragging = true;
};

// update data text,order,zindex
function updateData(block){
    block.x=mX, block.y = mY;
    block.mergedSprites.forEach(sprite => { // update z for _difuse && _normal
        //sprite.zOrder = block.y;
        sprite.zIndex = block.y+(block.groupe*HEIGHT);
    });
    block.txt[0].text = `x:${mX} y:${mY} w:${block.width} h:${block.height}`;
    block.txt[1].text = `zIndex:${block.mergedSprites[0].zIndex} zOrder:${block.mergedSprites[0].zOrder} groupe:${ block.groupe }`;
};

// mouse x,y update
function mousemove_(event){
    mX = event.clientX, mY = event.clientY
    block1.dragging && updateData(block1);
    block2.dragging && updateData(block2);
};

// mouse x,y update
function mouseup_(event){ 
    block1.dragging = false;
    block2.dragging = false;
};

// inverse order groupe ?!
function keydown_changeGroupe(event){
    console.log('event: ', event);
    if(event.key==="g"){
        block1.mergedSprites.forEach(sprite => { // update z for _difuse && _normal
            sprite.zOrder = block1.y;
        });
        block2.mergedSprites.forEach(sprite => { // update z for _difuse && _normal
            sprite.zOrder = block2.y;
        });
    updateData(block1),updateData(block2);
    }
    switch (event.key) {
        case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7":
        block1.dragging && (block1.groupe = Number(event.key));
        block2.dragging && (block2.groupe = Number(event.key));
        updateData(block1),updateData(block2);
            break;
    };

};
// classic listener
document.addEventListener('mousemove', mousemove_);
document.addEventListener('mouseup',mouseup_);
document.addEventListener('keydown', keydown_changeGroupe);

this idea had potential if we use the y, but quickly proved bad in combination of the zoom and the position of the scene

Let me think about it tomorrow, maybe its easy to make and I'll update the library for you.

It a good idea. And thank , I do not have your experience, there is hardly a year, I didn't even know what was a variable in javascript , so it's difficult for me to dive deep into your work, my brain regularly overheated try to understand what you are doing lol !

another small video that could inspire you to factorize the problem. It is easy to manage without the light system. https://youtu.be/J2d36nC8VgU

ivanpopelyshev commented 6 years ago

Nice! Ok, tomorrow ill have something for you.

ivanpopelyshev commented 6 years ago

I consulted with my friend who has that kind of problem in his engine. I believe I have a solution, but that's for tomorrow again. Dont add normals yet, it seems that you'll have to do less changes that we anticipated :)

jonlepage commented 6 years ago

ok perfect, i can not wait to see that, I put the normal part in standby, I prepare my module to welcome the light and the light editor personalize.

jonlepage commented 6 years ago

I guess the double buffer https://github.com/pixijs/pixi-display/blob/layers/src/ will be part of your solution ?

ivanpopelyshev commented 6 years ago

No, that's for another problem. I'm testing solution for normals right now :)

jonlepage commented 6 years ago

oh ok, sorry!, I updated anyway, and all works well.

ivanpopelyshev commented 6 years ago

Here we go: http://pixijs.io/examples/#/layers/normals-drag.js

Now you can just set 'sortPriority=1` for your sorting group.

jonlepage commented 6 years ago

you are awesome , thank a lot, i check this now

jonlepage commented 6 years ago

little technical question. PS: all work fine it very awesome and very easy to manage thank.

There is a reason why add new PIXI.lights.PointLight(0xffffff) inside a simple container will not rendering light ? I use a container to store object mouse because it is necessary for run spine animation correctly.

ex

var objLight = new PIXI.lights.PointLight(0xffffff);
cage_mouse.addChild(objLight);
cage_mouse.parentGroup = group1;

cage_mouse have the stage for parent. If i add directly objLight to stage it work, but no if i add inside a container before.

if it is not possible I will do otherwise for my mouse light.

ivanpopelyshev commented 6 years ago

you can add light wherever you want - it has PIXI.lights.lightGroup as a parentGroup by default.

ivanpopelyshev commented 6 years ago

I sent your video to russian telegram chat, there are clients who want to try it :)

jonlepage commented 6 years ago

what is a telegram ? the video from editor ? I will release a full demo and also a project for rmmv when i will finish v1.0 only Am from v0.97A for now , but they can follow progress on my youtube channel Or on on this link https://forums.rpgmakerweb.com/index.php?threads/rmmv-pro-map-editor.91843/ They can add me to follow to get live alert for update.

They will can not use for now , because i split on custom multi module

ivanpopelyshev commented 6 years ago

Does it produce JSON output that can be read without RMMV?

I want to help you releasing this as a independend pixi scene editor

jonlepage commented 6 years ago

yep all object (+ light now) you add are export in json, after you only need to make a custom project and and use json data from the editor.

jonlepage commented 6 years ago

the json will look like this for a obj , so this will are the data proprety will can use inside a custom project, + type of obj ex: spine, tile, animatedsprite, ....

    function createProprety_obj (objSprite){
        // basic
        const proprety = {
            scale:[[1,1],[1,1]], // ['def'[x,y], 'asign'[x,y]]
            skew:[[0,0],[0,0]],
            pivot:[[0,0],[0,0]],
            anchor:[[0.5,1],[0.5,1]],
            rotation:[0,0],
            alpha:[1,1],
            tint:['0xffffff' ,'0xffffff'],
            setDark:[[0,0,0] ,[0,0,0]],
            setLight:[[1,1,1] ,[1,1,1]],
            autoDisplayGroup:[[false,false,false,false,false,false,false],[false,false,false,false,false,false,false]]
            // zIndexMode:[false,'Y','Y'], //TODO:
            //  parentGroup:[false,'Y','Y'],//TODO:
        };
        // if is spine
        if(objSprite.type==="spinesheets"){
            delete proprety.anchor;
            const defaultAni = objSprite.spineData.findAnimation('idle') && 'idle' || objSprite.spineData.animations[0].name;
            Object.assign(proprety, {
                defaultAni:[defaultAni,defaultAni],
                startTime:['default','random'],
                timeScale:[1,1],
            });
        }
        // create actived case _props
        const props = Object.keys(proprety);
        for (let [i,len] = [0,props.length]; i < len; i++) {
            proprety[`_${props[i]}`] = false; // case mode, list[i]:name
        };
        return proprety;
    };

AutoDisplay group allow a object to follow the group where player are . This fix the issus when the player are between 2 group layer. where we have talk here at end #23 When player change layer, those obj will follow player layer.

jonlepage commented 6 years ago

I want to help you releasing this as a independend pixi scene editor

i will share you the source code tomorrow, am on you pixi light integration for now. But I do not know if you will understand my codes, I am a generalist and you are a professional coder. We probably have a completely different way of working. I will share you source code tomorrow and will see if you will can use or help. But you already helped me a lot :)

ivanpopelyshev commented 6 years ago

I'm used to work with big projects, I have experience with refactoring while making sure that it still works. I'm generalist in terms of coding.

jonlepage commented 6 years ago

do you have rmmv 1.6 with the last node and chromium ? i will share you all project source. This will more easy for you to debug and understand how all work.

jonlepage commented 6 years ago

I'm generalist in terms of coding.

you are rather professional and specialized, by generalist I mean mastering most of the computer subdomain. for my side am try mastering Software and specific language: AffectEffect, AffectEffect Scripting Photoshop, Photoshop Scripting Spine, spine Atlas libs, TexturePacker, Sprite Illuminator sound forge Basic Language: HTML,CSS,PHP,JS,NPM,PowerShell,... Libs Language: RMMV, PIXI + Modules, Excel(VBA), Wordpress ... General Informatique and hardware: Deep Windows, hardware computer,manage VPS , draw with tablet, general electric ... a lot more !..

Save, if you're lucky enough to be amphetamine-fueled and neuro-stimulant, which Americans do legally through their doctor. It is difficult to be an independent developer and master all areas, a good reason why studios prefer to hire specialists for each area, rather than generalist. The specialists master their fields very well.

ivanpopelyshev commented 6 years ago

I'm hardcore generalist: I know how to code apps on Delphi/FreePascal, JVM languages (Java,Scala,Kotlin), Flash/ActionScript, a few SQL dialects, many scripting languages, how to setup a linux server for it.

My education allows me to embed huge chunks of math and computer science in my code, and to participate in world-level algorithm competitions.

I happen to be specialist in PixiJS, its the first big OpenSource project I participate in :)

That's why I belong to R&D department of https://cpdecision.com , not every company has R&D.

Of course I love indies, I was independent dev for some time and I'll go back to making my own games later. I'm helping many people with their projects.

jonlepage commented 6 years ago

yes, indeed, I find you and consult your Linkedin. You have a very impressive profiling! Besides without your help, I could not have developed my project, you are a super efficient resource! I'm surprised you're not INDI, you have everything to gain!

jonlepage commented 6 years ago

@ivanpopelyshev I think it will need update spine libs . Safe if I'm wrong spine object cannot be output with objects light. i test a lot and it alway sort top image or maybe i need sleep, am not understand why ! 2 hour on this In this picture the tree supposed to be below house ,, but not work. It a basic spine for now , am no testing make a spine+normal.

ivanpopelyshev commented 6 years ago

you can make lighted spine, you have to make your own Spine class based on heaven or pixi-spine Spine class, override createSprite property - create two sprites, one diffuse and one normal.

To make normal texture, you can just create PIXI.Texture with different baseTexture but same frame/crop/orig combo.

I can make lighted spine example in weekend.

jonlepage commented 6 years ago

ho ok so it because i need made a normal for the spine . I don't try work with spine + normal . i need take a look how i can do this. You have suggest ? i ask also here but am not understand sorry http://esotericsoftware.com/forum/how-work-with-spine-normal-spriteilluminator-10154

ivanpopelyshev commented 6 years ago

Lets see how they crack the issue :)

The best idea is to illuminate whole atlas, ensure that loader also gets normals png, and override Spine createXXX functions. Either spend time on it, either wait when I look at it in weekend.

jonlepage commented 6 years ago

The best idea is to illuminate whole atlas, hum... i need go sleep :) dreams sometimes reveals a solution.