My questions thread

I have a scene where a spaceship travels through a warp tunnel, similar to a map in Quake III Team Arena:

s4b.directupload.net/images/090628/cfengvqs.jpg

I would like the texture to swirl and move towards the player. I guess one could do it via a shader, but I am not familiar with CG or GLSL.

(1)
I’d like to move a texture by a lerp interval. Pro pointed me at LerpTexOffsetInterval (btw, how is one supposed to find this stuff?). Why do I get an assertion error for:

warpcolumn_movetexture_interval = LerpTexOffsetInterval(self.warpcolumn1, 4, texOffset = Vec2(-0.4,0), startTexOffset = None, other = None, blendType="noblend", textureStage=None, bakeInStart = 1, name = None, override = None)

(2)
There’s an older thread on running PStats on a Mac. I don’t want to mess with my system by installing all kinds of GUIs or fight with compiling anything myself. Is there some click&install solution?

(3)
I had no success in customizing the look of the DirectGrid class beyond stuff from the init function, like

DG = DirectGrid(gridSize=5.0, gridSpacing=2, planeColor=(0, 0, 0, 0), parent=render)

To set parameters like line thickness or color and deactivating the center bubble I copy&paste’d the whole DirectGrid, renamed it, edited it and imported it. Works fine. That wouldn’t get me into legal trouble, would it?

(4)
In the Infinite Tunnel sample, line 161, there is:

I understand segment x-1 depends on x, starting with 3, going to 0. But where do these values come from? There must be some math behind it, instead of just trial&error?

(5)
In the Infinite Tunnel sample, fog was used to hide the end of the tunnel. I would need something similar, but in my scene the cam is off center. The manual says you cant specify where fog is spawned from, like in my case, the end of the tunnel. Furthermore, I use setShaderAuto on the spaceship and activating fog gives me a “fog and shader generator do not work together, yet” type error.

(6)
What is the stuff in lib/direct/controls/ for?

Well, that’s it for now.

(1) Check the Reference section. It’s not 100% complete/accurate, but it has a bunch of stuff. What exactly is the assertion being violated?

(3) I don’t think that would be a problem, as long as any authorship headers were also kept, but since parent parameters propagate to children unless the children have their own parameters set, I’d imagine there would be a way to force setColor(), setRenderModeThickness(), etc. on instances from the unmodified code.

(5) “Fog” is really a misleading term in computer graphics. It’s not so much the concentrated volumetric fill that you see in the real world, just a function that multiplies the color of a piece of geometry with a fixed other color proportional to its distance from the camera. Hence, specifying the ‘origin’ or ‘spawn point’ of a fog is conceptually meaningless, and furthermore, fog can’t really be defined as part of a scene, just part of the rendering process, which shaders by their nature override. Writing a fog effect into a shader is fairly trivial, but if you’re using the autoshaders and they don’t yet support Panda’s fog declaration, you’re SOL.

Note that the reason why Fog is not implemented into the shader generator is that it’s easier (and maybe even more efficient) to achieve per-pixel accurate fog in a postprocessing filter.

What would that be, basically? Render * depth buffer + fog * (1 - depth buffer)?

Something like that, yes, you could do that with the combine mode CMInterpolate.

For more advanced fog control you can create a postprocessing shader that translates the depth values back to 3d space using the world projection matrix and colors accordingly.

Pro, your answer is a bit beyond me :slight_smile: In the end all I want to do is hide the end of the tunnel. All that shader stuff would be just another thing to dig into and I’ve got other more core related things to learn.

Uh can’t say, it always crashes as the whole line. If I distribute the variables over multiple lines, it indicates the last line crashing.

Like:

warpcolumn_movetexture_interval = LerpTexOffsetInterval(
		self.warpcolumn1,
		duration = 4,
		texOffset = Vec2(-0.4,0),
		startTexOffset = None,
		other = None,
		blendType="noblend",
		textureStage=None,
		bakeInStart = 1,
		name = None,
		override = None
		)

Error report:

 File "Panda3D-tpl-rw/Panda3D/1.6.2/lib/direct/interval/LerpInterval.py", line 667, in __init__
  File "Panda3D-tpl-rw/Panda3D/1.6.2/lib/direct/interval/LerpInterval.py", line 45, in __init__
AssertionError

Line 45 is the blend type, 667 the init.

Ah. Sometimes the system is friendly and states, e.g., AssertCallable (usually meaning you passed in the returned value functionName() rather than the function functionName).
I’m guessing one of those None arguments is something the interval thinks it needs to function, or else it’s a but in Panda itself, since I can’t imagine too many people use lerpTexIntervals.

If your tunnel is a hollow tube, I’m not sure there’s any compelling way to magically close off the end- even fog would fade out the rest of your scene unless you somehow applied it only to the tunnel, in which case, with no back geometry, there’d be nothing to blend the fog with at the end of the tunnel, and you’d just get a hole. I’d suggest tapering the back of the tunnel into a point and applying some sort of static gradient at the back end on another texture layer. Your swirl should be able to operate independently if you take advantage of the textureStage input to the tex lerp.

Found it, it’s

blendType="noBlend",

instead of

blendType="noblend",

Now I will experiment with the

texOffset = Vec2(-1,0)

values. But what already strikes me is that it seems like the lerp is not looping:

warpcolumn_movetexture_interval.loop()

Only a movement of the texture for 4 seconds, and then business as usual.

Alright, got it working with:

warpcolumn_movetexture_interval = LerpTexOffsetInterval(
		self.warpcolumn1,
		duration = 4,
		texOffset = Vec2(0,-1),
		startTexOffset = Vec2(0,0),
		other = None,
		blendType="noBlend",
		textureStage=None,
		bakeInStart = 0,
		override = None
		)
warpcolumn_movetexture_interval.loop()

Problem is you have to set startTexOffset. bakeInStart 0 or 1 does not make a difference.
Also interesting that you cant do:

warpcolumn_movetexture_interval = self.warpcolumn1.LerpTexOffsetInterval()

… like with all other intervals in my scene. You get:

AttributeError: 'libpanda.NodePath' object has no attribute 'LerpTexOffsetInterval'

if you try.

(7)
In my game I am using minimalist style buttons, i.e. no graphics, at least not if I can avoid it.
I like the look of DirectFrames filled with a solid dark color and DirectButtons above them for the clickable text.

Now I’d like to have a 1px or 2px solid color border around the frame, just like:

Now the manual afair says a frame cant have a border? What else could I do to achieve the desired look?

In your DirectFrame constructor, try passing pad = (px, py), where px, py are the amount of padding you want in x and y, respectively.

David

Thanks, will try that. Though I’m a bit sceptical, because where do I set what the padding should reveal underneath?

Btw I got some strange (I guess Mac-related) behaviour today. Until now I had all my assets in
Applications/Panda/1.6.2/
along the usual Panda files.

After thing grew a little (still totally basic stuff), I left the Panda stuff there, but moved the game-related assets to
Applications/mygame/

I can still start scripts as usual, but quitting Panda causes the Python executable to hang up. It’s not crashing, just hanging up (white window, but the window size from the prc file is correct, so it’s definitely Panda). In Apple’s activity utility the “nice” CPU usage (blue) turns to “system” (red), with way too much CPU used. The process is listed as not receiving inputs anymore.

  • Some scripts are not affected, i.e. they dont hang up at all. The only non-Panda-Python script I have ever created. All DirectButton examples from the manual. My own menu script.
  • Most scripts work fine, but hang up on quit. The default Panda samples. My own game script sometimes runs, sometimes hangs up immediately.

This is all very annoying since scripts I develop are supposed to crash all the time for syntax errors or whatever, then they hang up and I have to force-quit Python.
I could post some error reports, but they are lengthy. Now I haven’t done a restart yet and maybe it’s just user file system rights. But just to already mention it …

Now, is this a Python cache issue? Is there a way to flush those cache files out? Is this a path issue? Can’t be?

EDIT:
Alright, a restart it seems fixed it. I guess a restart is required for a asset reorganisation :confused:

(8)
In my main menu I got a lot of DirectFrames for button backgrounds, then DirectButtons over them.

Changing from the menu to the game I remove all nodes, but removing the buttons doesn’t work.

menuButtons1 = ["Play Pilot", "New Pilot", "Load Pilot"]
menuButtons2 = ["Help", "Settings", "About", "QUIT GAME"]

Backgrounds:

for i in range(len(menuButtons1)):
	self.menuButtonBackgroundsLeft = DirectFrame(frameColor=(0,0,0,0.6),
	frameSize=(-0.4,0.4,0.055,-0.055), pos=(-0.8,0,-0.15-0.16*i), sortOrder=-1)

for i in range(len(menuButtons2)):
	self.menuButtonBackgroundsRight = DirectFrame(frameColor=(0,0,0,0.6),
	frameSize=(-0.4,0.4,0.055,-0.055), pos=(0.8,0,-0.15-0.16*i), sortOrder=-1)

The buttons:

for i in range(len(menuButtons1)):
	self.menuButtonsLeft = DirectButton(
	text = str(menuButtons1[i]), pos=(-0.8,0,-0.165-0.16*i), scale=0.07, text_fg=(1,1,1,0.75), frameColor=(0,0,0,0), 	command=self.printButtonInput, extraArgs=[str(menuButtons1[i])])

for i in range(len(menuButtons2)):
	self.menuButtonsRight = DirectButton(
	text = str(menuButtons2[i]), pos=(0.8,0,-0.165-0.16*i), scale=0.07, text_fg=(1,1,1,0.75), frameColor=(0,0,0,0), command=self.printButtonInput, extraArgs=[str(menuButtons2[i])])

The cleanup:

def cleanup(self):
	self.spaceship.removeNode()
	self.warpcolumn1.removeNode()
	self.warpcolumn2.removeNode()
	self.menuButtonBackgroundsLeft.removeNode()
	self.menuButtonBackgroundsRight.removeNode()
	self.menuButtonsLeft.removeNode()
	self.menuButtonsRight.removeNode()
	render.clearLight(self.thatdirlight)
	render.clearLight(self.thatamblight)

No errors. Seems I am not addressing the backgrounds and buttons correctly.

First, you should call button.destroy() instead of just button.removeNode(), to clean up any DirectGui object.

But that’s not your problem here. Your problem is the way you create your buttons:

for i in range(len(menuButtons2)):
   self.menuButtonsRight = DirectButton( ... )

Each button you create, you assign it to self.menuButtonsRight, replacing what you had previously assigned to self.menuButtonsRight. Thus, at the end of your loop, you have stored only one button in self.menuButtonsRight, the last one you created. All of the other buttons have been lost, and do not ever get removeNode() called on them.

Instead of assigning them all to the same member, you can store them in a list or something.

Alternatively, set the parent of each of your buttons to your DirectFrame. Then, when you call directFrame.destroy(), it will automatically destroy all of your buttons as well. (Destroying a parent object automatically destroys all of its children.)

David

Thx, I did not understand your suggestions though. Or I did unterstand them but could not translate that into code. If I append my stuff to a list, and then delete that list, how would that remove my buttons? Delete would be a Python method, would that even work? During creation I have 9 background frames and 9 buttons above them. So that list would contain 18 items.
And reparent to DirectFrame?

Anyway, I get the desired effect with:

menuButtons1 = ["Play Pilot", "New Pilot", "Load Pilot"]
menuButtons2 = ["Help", "Settings", "About", "QUIT GAME"]
self.menuButtonsNode = aspect2d.attachNewNode("MenuButtonsNode")
for i in range(len(menuButtons1)):
self.menuButtonBackgroundsLeft = DirectFrame()	self.menuButtonBackgroundsLeft.reparentTo(self.menuButtonsNode)

for i in range(len(menuButtons2)):
self.menuButtonBackgroundsRight = DirectFrame()	self.menuButtonBackgroundsRight.reparentTo(self.menuButtonsNode)

for i in range(len(menuButtons1)):
	self.menuButtonsLeft = DirectButton()
	self.menuButtonsLeft.reparentTo(self.menuButtonsNode)

for i in range(len(menuButtons2)):
	self.menuButtonsRight = DirectButton()
	self.menuButtonsRight.reparentTo(self.menuButtonsNode)
def cleanup(self):
		self.menuButtonsNode.removeNode()

delete() is not possible here of course.

Good? Bad? Good enough?

(9)
I once had sounds in that menu, just defined them in the DirectButton field (rollover and click). I don’t have the syntax anymore, but it was something totally simple. Now, I guess this is a common issue, the sounds played when the menu was first loaded (Class first instanced), but not on rollover or click. Now here on the bottom http://www.panda3d.org/manual/index.php/Loading_and_Playing_Sounds_and_Music it says something pointing in that direction. Is that it?

I meant, after appending them to the list, you should then clean them up by iterating through the items of the list and calling destroy() on each one of them. (Then you may delete the list if you like.)

Your current solution is still not quite right, because you are only calling removeNode() and not destroy(). This makes the buttons disappear from the screen, but they are still listening for their button events–you have created a leak in the event handler table. It’s true you cannot call destroy() on the plain PandaNode you are parenting the buttons to now. So you either have to go with the list approach, or parent them all to a DirectFrame instead. I believe it is possible to create an invisible DirectFrame for this purpose if the buttons really don’t have any visible frame they’re associated with, though the name “menuButtonsBackgroundLeft” and “menuButtonsBackgroundRight” gave me the idea that these frames are intended to be background frames for your buttons (meaning the buttons should be parented to them). Of course, the frames themselves still need to be parented to something else you can destroy, or retained in a list so you can destroy them explicitly.

David

Alright, parenting it to an invisible DirectFrame at 0,0,0 worked. The former solution - removing the Node - did not pose problems, the buttons where gone. No rollover sound when one moved the mouse to where the buttons where and no reaction on clicking blindly :slight_smile: No difference now, but you are right of course.

Any ideas on that sound thing (9)?

I tried your pad=(x,y) thing, but that did not make any difference:

self.backgroundwhite = DirectFrame(frameColor=(1,1,1,1), frameSize=(-0.8,0.8,0.45,-0.45), pos=(0,0,0), sortOrder=-3)
self.foregroundblack = DirectFrame(frameColor=(0,0,0,1),	frameSize=(-0.8,0.8,0.45,-0.45), pad=(2,2), pos=(0,0,0), sortOrder=-2)

Where supposedly the black foreground has the same size like the white background and the padding makes it visible.

(10)
Old issue … In my game, the cam looks from above onto the scene and moves with the spaceship at the center. We had endless discussions on IRC about this … Currently it’s a thread that corrects the cam pos each frame, but then the movement of the ship/cam jitters.
Reparenting the cam to the ship smoothes things, but then my coords are of course no longer valid. More importantly, the cam turns with the ship, like in a typical shooter or the Ralph example. But, I want the cam fixed and the spaceship to turn underneath.
I know there is a syntax like

cam.setPos(target,x,y,z)

but when I tried that something was ugly. Don’t remember what. And I don’t find the syntax anywhere.

Is there a solution for this? Suppressing certain values forced from target to cam?

(11)
Are there some bugs in DirectScrolledFrame?

I’ve got a DirectScrolledFrame with:

self.Starmap = DirectScrolledFrame(frameSize=(-329*0.8/480,329*0.8/480,221*0.45/270,-221*0.45/270),
		pos=(-135*0.8/480,0,32*0.45/270), canvasSize=(-658*0.8/480,658*0.8/480,221*0.45/270,-221*0.45/270)

As you can see, the canvas is wider then the frame, but of equal height. But it looks like this:
s4.directupload.net/images/090813/zzcbelr6.jpg
The horizontal scrolling works fine, but the vertical gets displayed too, where it wouldn’t be necessary. I guess the auto manage thing does not distinguish between the horizontal and vertical bar?

Let’s increase the height of the canvas, too:

self.Starmap = DirectScrolledFrame(frameSize=(-329*0.8/480,329*0.8/480,221*0.45/270,-221*0.45/270),
		pos=(-135*0.8/480,0,32*0.45/270), canvasSize=(-658*0.8/480,658*0.8/480,442*0.45/270,-422*0.45/270) 

Looks like:
s7.directupload.net/images/090813/ztthf9nq.jpg

And good bye to the lil’ blue dots I came to know and love! Could it be there’s some position bug on the vertical axis?
On the other hand, I can call

self.Starmap.getCanvas().getPos()

for both a same-size and double-size canvas, the Pos of the canvas is always (0,0,0), as it should be. Also notice how the visuals of the horizontal bar changed, without me doing anything.
Is there maybe some align option I am missing?

The DirectScrolledFrame is getting confused because you are creating an inside-out frame, specifying a “bottom” value that is larger than the “top” value. (Remember, in Panda, the coordinate system increases from the bottom to the top, unlike most 2-d coordinate systems.) Arguably, the code should handle this inside-out case more gracefully, but it doesn’t.

If you correct these parameters, reversing the last two parameters of your frameSize and canvasSize, then both of your DirectScrolledFrame examples are well-behaved. Note that you still have a vertical scroll bar in the first example, because the horizontal scroll bar takes up some of the space within the frame.

You might also want to set something like borderWidth = (0.01, 0.01), so the bevels on the scroll bars make more sense.

David

You are right, that did it. This is actually an error I see in all my code, I define all DirectFrames by:

frameSize=(-x,x,y,-y)

instead of

frameSize=(-x,x,-y,y)

For naked DirectFrames that doesn’t seem to be a problem, but here it get’s me. Thanks for the help, I will get to formatting the bars later.

(12)
My Player is a FSM with a state “Jumping”, among others. The FSM works, but after I enter a state and request it again, I get a crash with

direct.fsm.FSM.RequestDenied: Jumping (from state: Jumping)

That is to be expected, but can’t I prevent that? Something like:

If FSM.Jumping.isPlaying():
    pass
else:
    FSM.request("Jumping")

One way I am using right now is to unaccept the key that evokes the function that request that state (here: J for Jumping) while being in that state. But that’s just not the real thing.

(13)
I’ve got a Starmap, a DirectScrolledFrame, as formerly mentioned. It looks like this (WIP):

Works fine, problem is it takes 4-6 seconds to build it on my relatively decent machine. It would be too much to post the full code, but here’s how it works.
I’ve got roughly 160 stellar systems, each represented by a dot on the map, which is a DirectRadioButton, each with a boxImage. The database is a dict looking like this:

StarmapData = {
'DSN-901': [-184, -89, None, None, None, None, 0],
(... 160 entries like this ...) }

The numbers being pixel coordinates. I then build the buttons like:

for Stob in self.StarmapData.keys():
    self.buildStobButton(Stob, self.StarmapData[Stob][0],
    self.StarmapData[Stob][1], StobButtonID, scalefactor)
    (...)
    StobButton.reparentTo(self.Starmap.getCanvas())

Right now I reparent all Buttons to the canvas upon creation - is that the problem?

The wrapper for the buttons contains stuff like:

def buildStobButton(self, stobname, buttonposx, buttonposy, indexno, scalefactor):
return DirectRadioButton = (...)
pos=(buttonposx*0.8*scalefactor/480,0,buttonposy*0.45*scalefactor/270))

for a 16:9 960x540 window. Those calculations can’t be the problem. The - and + you see in the screenshot do a scaling a la

StarmapElement.setPos(StarmapElement.getPos()*1.25)

and that one is almost instant for all 160 elements.
Building the dot graphics (DirectRadioButton - boxImage) is not the problem either - when I comment those out, it does not speed up.

So things must get slow earlier. In the beginning, when my database contained only like 10 instead of 160 entries, thing where a lot faster. Should I first reparent the buttons to a node and then reparent that to the canvas?