DragonBones / DragonBonesJS

DragonBones TypeScript / JavaScript Runtime
MIT License
746 stars 320 forks source link

[Phaser 3] Can't reuse the dragonboneName on 2+ scenes #119

Open eponesh opened 4 years ago

eponesh commented 4 years ago

Only the first scene, which started and used this.add.armature, can use the dragonbonesName loaded.

/**
 * Preload scene
 * mecha_1002_101d_show - daragonbonesName
 */
preload(): void {
    this.load.dragonbone(
        "mecha_1002_101d_show",
        "resource/mecha_1002_101d_show/mecha_1002_101d_show_tex.png",
        "resource/mecha_1002_101d_show/mecha_1002_101d_show_tex.json",
        "resource/mecha_1002_101d_show/mecha_1002_101d_show_ske.dbbin",
        null,
        null,
        { responseType: "arraybuffer" }
    );
}
/**
 * Fisrt and Second scenes
 */
create(): void {
    const armatureDisplay = this.add.armature(
        "mecha_1002_101d",
        "mecha_1002_101d_show"
    );
    armatureDisplay.animation.play("idle");
}

Result: image

But if use the different dragonboneName

this.load.dragonbone(
    "mecha_1002_101d_show_SCENE_FIRST", // first name
    "resource/mecha_1002_101d_show/mecha_1002_101d_show_tex.png",
    "resource/mecha_1002_101d_show/mecha_1002_101d_show_tex.json",
    "resource/mecha_1002_101d_show/mecha_1002_101d_show_ske.dbbin",
    null,
    null,
    { responseType: "arraybuffer" }
);

this.load.dragonbone(
    "mecha_1002_101d_show_SCENE_SECOND", // second name
    "resource/mecha_1002_101d_show/mecha_1002_101d_show_tex.png",
    "resource/mecha_1002_101d_show/mecha_1002_101d_show_tex.json",
    "resource/mecha_1002_101d_show/mecha_1002_101d_show_ske.dbbin",
    null,
    null,
    { responseType: "arraybuffer" }
);

And use unique name on scene

// First Scene
const armatureDisplay = this.add.armature(
    "mecha_1002_101d",
    "mecha_1002_101d_show_SCENE_FIRST"
);

// Second Scene
const armatureDisplay = this.add.armature(
    "mecha_1002_101d",
    "mecha_1002_101d_show_SCENE_SECOND"
);

Then result: image

Is there a solution to use only one name? This solution is not good. I don't want to create many names for each scene. Thanks.

jcyuan commented 4 years ago

sorry don't quite understand what you mean.

db plugin is a Scene Level plugin, which means the loaded data are seperated for each scenes.

if load db files in different scenes you can specify the same name.

or is this the bug you mentioned above? (even in different scenes you can't specify with the same name?)

eponesh commented 4 years ago

@jcyuan

even in different scenes you can't specify with same the name

Yes, I can't add an armatute with the same dragonbonesName (e.g. mecha_1002_101d_show) in two different scenes. I need to preload same resources twice with different dragonbonesName.

if load db files in different scenes you can specify the same name.

No, I can't. If I do this code below on two scenes, on the first running scene the model is displayed. The second scene will be empty.

preload () {
    this.load.dragonbone(
        "mecha_uique_name",
        "resource/mecha_1002_101d_show/mecha_1002_101d_show_tex.png",
        "resource/mecha_1002_101d_show/mecha_1002_101d_show_tex.json",
        "resource/mecha_1002_101d_show/mecha_1002_101d_show_ske.dbbin",
        null,
        null,
        { responseType: "arraybuffer" }
    );
}

create(): void {
    const armatureDisplay = this.add.armature(
        "mecha_1002_101d",
        "mecha_uique_name"
    );
    armatureDisplay.animation.play("idle");
}

It doesn't matter which scene comes first. If I do game.scene.start('SecondScene') and then game.scene.start('FirstScene'). The model is displayed on SecondScene only.

jcyuan commented 4 years ago

ok, will do an investigation later.

MadDogMayCry0 commented 3 years ago

@eponesh @jcyuan i got it! :) i found a solution. Give me a litle bit more time to fix one more solution (animation order problem) and i share all bug fixes here. :)

In dragonbones.js find line

var frame = this._renderTexture.add(k, 0,

and you will see, that this method calls every load and call phaser.method add frame to the texture.

This one.

add: function (name, sourceIndex, x, y, width, height)
    {
        if (this.has(name))
        {
            return null;
        }

So, as you can see the last one will return NULL if frames has been already exists.

So, just replace in dragonbones.js (sorry, i dont understand TypeScript compilation)

var frame = this._renderTexture.add(k, 0, // all textures were added through `textures.addImage`, so their sourceIndex are all 0
                            data.region.x, data.region.y, data.region.width, data.region.height);

by

if(!this._renderTexture.frames[data.name]){
                                var frame = this._renderTexture.add(k, 0, data.region.x, data.region.y, data.region.width, data.region.height);
                            }
                            else {
                                var frame = this._renderTexture.frames[data.name]
                            }
MadDogMayCry0 commented 3 years ago

https://github.com/DragonBones/DragonBonesJS/pull/152/commits/95fc7fab7369a5c9627f64373308c2f24f6cb7ad