pixi-display + pixi-light Crash
Closed this issue · 52 comments
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
if i remove this line, i can see all the element normal seem loaded.
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
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 :)
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.
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
because i dont have automatic build for that. And im lazy to add it.
@ivanpopelyshev
ok on the rock , thank.
Now it time to study this , Youpii
@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 .
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
deal with it.
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.
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.
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 automatically name+"_n"
prefix on each textures.
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.
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.
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*
you have to enable the same kind of sorting inside pixi-lights groups.
I know its a problem that you need sort all those things and modify groups :( ill help you if it goes wrong
ok thank i make some test and i will maybe back to you in some hour
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 );
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.
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
i mean with addChild :) parent doesnt have to sort it.
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.
@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);
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:
- hack the diffuse layer that way it stores the index of element in sorted array somewhere in that element.
- normal layer should use it somehow.
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.
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
Nice! Ok, tomorrow ill have something for you.
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 :)
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.
I guess the double buffer
https://github.com/pixijs/pixi-display/blob/layers/src/
will be part of your solution ?
No, that's for another problem. I'm testing solution for normals right now :)
oh ok, sorry!, I updated anyway, and all works well.
Here we go: http://pixijs.io/examples/#/layers/normals-drag.js
Now you can just set 'sortPriority=1` for your sorting group.
you are awesome , thank a lot, i check this now
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.
you can add light wherever you want - it has PIXI.lights.lightGroup
as a parentGroup
by default.
I sent your video to russian telegram chat, there are clients who want to try it :)
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
Does it produce JSON output that can be read without RMMV?
I want to help you releasing this as a independend pixi scene editor
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.
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.
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 :)
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.
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.
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.
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.
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!
@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
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.
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.
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
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.
The best idea is to illuminate whole atlas,
hum... i need go sleep :)
dreams sometimes reveals a solution.
ok a add i little hack to ytour plugin spine, see
if(slot.attachment && slot.attachment.name.indexOf("_n")>-1){
/* function Spine(spineData) {
var _this = _super.call(this) || this;
if (!spineData) {
throw new Error('The spineData param is required.');
}
if ((typeof spineData) === "string") {
throw new Error('spineData param cant be string. Please use spine.Spine.fromAtlas("YOUR_RESOURCE_NAME") from now on.');
}
_this.spineData = spineData;
_this.skeleton = new pixi_spine.core.Skeleton(spineData);
_this.skeleton.updateWorldTransform();
_this.stateData = new pixi_spine.core.AnimationStateData(spineData);
_this.state = new pixi_spine.core.AnimationState(_this.stateData);
_this.slotContainers = [];
_this.tempClipContainers = [];
for (var i = 0, n = _this.skeleton.slots.length; i < n; i++) {
var slot = _this.skeleton.slots[i];
var attachment = slot.attachment;
var slotContainer = _this.newContainer();
*/
_this.slotContainers.push(slotContainer);
// check if the name have '_n', if yes it a normal, else a diffuse
if(slot.attachment && slot.attachment.name.indexOf("_n")>-1){
slotContainer.parentGroup = PIXI.lights.normalGroup;
}else{
slotContainer.parentGroup = PIXI.lights.diffuseGroup;
}
I find it pretty easy to duplicate a slot and inject a normal.
Ideally it would be to prepare the photoshop file so that it includes all the '_n' names.
It's a little longer to update a file that was not have normal at the base.
I will definitely wait for you to offer a more intelligent code
I discussed it with dev from codeandweb, they tell me they will add new meta for detect more easy normal map with a atlas in next update.
a guy tell me a nice idea, attache a skin to say the current spine have a normal map.
I need look this .
Edit:
ok solved, i add this to your spine.js for now.
I am going to wait for a more professional suggestion from you.
For the moment it works well, what is important for allow me progress.
The idea is simply to add a skin named "normal_n" when you work in SPINE2D sofware, that tell to your spine.js to add special extra parentgroup to slots and slots with "_n".
I dont know about performance on this hack, but it make the workflow very easy.
what do you think about this?
var haveNormal = !!spineData.findSkin("normal_n") || false; // is have skin named Normal_n
for (var i = 0, n = _this.skeleton.slots.length; i < n; i++) {
var slot = _this.skeleton.slots[i];
var attachment = slot.attachment;
var slotContainer = _this.newContainer();
_this.slotContainers.push(slotContainer);
if(haveNormal){
if(slot.attachment && slot.attachment.name.indexOf("_n")>-1){
slotContainer.parentGroup = PIXI.lights.normalGroup;
slotContainer.isNormal = true; //allow easy debug
}else{
slotContainer.parentGroup = PIXI.lights.diffuseGroup;
}
};