Cannot set the texture from a actor created from copyActor()

Hey, long time no see guys, sorry to come back under these circumstances, but I am at a loss, I have been trying for hours to set the texture to a actor copied using copyActor(), from my own research, i seems you cannot simply getTexture from the actor itself, rather you need to do so from the first child.

my theory is a empty parent is built then the actor is copied in the from of a child node into it, I did try to set the texture from the child, but no results, anyway, thanks for listening

According to the post linked-to below, “copyActor” isn’t really intended to be used by itself, but rather is called when copy-constructing an Actor.

Further, it suggests that the result of so copying shouldn’t be all that different to the results of simply reloading the Actor. (Unless, I imagine, you’re using a procedurally-generated Actor.)

Now, you talk both about setting a texture, and about getting a texture. What, precisely, are you trying to do…?

If you want to retrieve a texture from an Actor, you might try NodePath’s “findTexture” methods.

For reference, if you’re wondering about the structure of a node-hierarchy, you can call NodePath’s “ls” method to get that hierarchy printed out. Like so:

self.someNodePath.ls()

(Note that this doesn’t return anything! It simply prints the result to the console/terminal.)

I think you missed the priority.

set_texture(texture, 1)

You need to set a number to override the previously assigned texture.

thanks for the replies guys, your help means a lot to me, I forgot how to multi- quote reply, so my apologies here is my response to both of you.


thaumaturge: would this be considered using it bytself?

player = Actor()
player.copyActor(other=source, overwrite=False)

serega-kkz: I actually did try that, and it worked in one of the tries, but I couldn’t repeat it again

I hadn’t even thought about it before.

from direct.showbase.ShowBase import ShowBase
from direct.actor.Actor import Actor
from panda3d.core import Texture

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        texture = Texture("models/ralph.jpg")

        ralph = Actor("models/ralph", {"run": "models/ralph-run",
                                       "walk": "models/ralph-walk"})
        ralph.reparent_to(render)
        ralph.set_texture(texture, 1)

app = MyApp()
app.run()

This gives me a black model, even without copying. The direct module has something wrong, constantly unexpected behavior…

Yes, it would.

The expected usage is like so, I believe:
player = Actor(source)

Is there a reason that you’re not just reloading the model? Panda caches its models, as I recall, so it shouldn’t incur much more overhead.

[edit]

This seems to be a result of the way that your code is loading the texture (or not loading it, I’d guess)–in a quick test on my side, I found that a texture loaded via “loader.loadTexture” worked as expected.

1 Like

oh, okay, let me try that, I will be back in a while

LoL I forgot how to use the Texture class

from direct.showbase.ShowBase import ShowBase
from direct.actor.Actor import Actor
from panda3d.core import Texture

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        texture = Texture("texture")
        texture.read("models/ground.jpg")

        ralph = Actor("models/ralph", {"run": "models/ralph-run",
                                       "walk": "models/ralph-walk"})

        player = Actor()
        player.copyActor(other = ralph, overwrite = False)
        player.set_pos(0, 5, 0)
        player.set_texture(texture, 1)
        player.reparent_to(render)

app = MyApp()
app.run()

It’s working.

2 Likes

so the data is identical when I print it out but still it does not let me set texture. as for the reason, it is for data banking, as I am trying to make my game “console ready”

alright, let me try this out now.

What is “data banking”? I’m not seeing any relevant-looking definitions via a quick search.

Let me note that Panda already caches models, I believe, so a second call to “loadModel” or the string-based “Actor”-constructor doesn’t actually load a second time from disk. Instead, it pulls from the cache, if I’m not much mistaken.

yes, panda indeed does, but from what I researched and to my knowledge, it cannot be controlled directly, it caches whatever is loaded at the time when loader is called the first time.

this is great, as I have seen it handle repeat data seamlessly and pop in didn’t really interrupt gameplay but lets say there is a new enemy in the middle of the level, not popped in yet, you would get a pause that would interrupt gameplay because it would have to cache the new data.

so a solution to this problem is to load all game world data in one load screen before hand including the un-pop-in enemies. in memory so it all loads seamless when need to, this is especially important for weaker consoles like the Nintendo switch which relies on vary slow SD cards.

Okay, fair enough. But then why not use normal loading for that…? Why the copy-construction…?

object templates (or master copies if you will) to be used for repeat data for the world when it needs it, for example, lets say I have a world made of 7 dogs, 3 cats, and 2 birds all in 3 load zones in that world, in a load screen I would load 1 dog, 1 cat and 1 bird, and have those in memory.

lets say zone 1 had 3 dogs 2 cats, and zone 2 had a bird and dog, if I were to move from zone 1 to 2 I would get a pause because panda would need to cache the bird, but with my method, since the bird is already in memory, the zone transition would be seamless.


the truth is, the method is a cheap patch to the way my game was written, that is load everything on the spot when needed.

You don’t take into account that there is a dynamic cache, ModelPool, TexturePool and so on.

https://docs.panda3d.org/1.10/python/reference/panda3d.core.TexturePool#texturepool
https://docs.panda3d.org/1.10/cpp/reference/panda3d.core.ModelPool#modelpool

When you call load a model or texture, the data, if available in memory, is not reloaded, a shallow copy of objects is created.

1 Like

Just as serega says: Panda caches its models, etc. So even if you have seven of a given model, only once will it be loaded from disk.

Thus you should be able to load your “master” via “loadModel”–and your “copies” the same way.

1 Like

alright, well the good news is that this works in the conditions you provided, however I found my problem, I forgot to mention that the source actor is already equipped with a texture and said texture is copied over too, it, some reason, it cannot be override.

is there anyway to override the texture that comes with the copy?

yeah, this looks like a better way to handle things, though I would have to rewrite my game to a degree for this to work, I wonder, is there pools for actor animations and sounds?

If an actor is equipped with a texture, then it would be more correct to create an actor without textures. When moving from zone to zone, just change the texture.

As for the other pools, However, you don’t need to do anything extra, panda is already using them.

https://docs.panda3d.org/1.10/python/search?q=Pool&check_keywords=yes&area=default

You can just as easily check this by creating a dictionary and a loop for loading something, if there is a pool, the memory will It will not increase

1 Like

hmm, interesting, I cannot use this on my current project, but on a new one, I just might opt to use this and build that game’s load methods around this, thank you for this, I will definitely save this for later.


I am going to try your other solution though, I will be back in a while.