Startle (Direct alternative)

I’ve been working on an alternative to Direct for a bit. It’s still in a bit of flux so I wouldn’t recommend using it in production yet, but figured people here would dig it.

Goals:

  • Modular design. Direct tries to do everything. Startle just wants to give you a window, scenegraph and input. The rest should be separate modules.
  • Easier code to follow and tweak. Direct is many many thousands of lines and everything is inherited from something else. I want to keep it short and sweet, trimmed and neat.
  • Depend on core more. A lot of Direct’s methods are just aliases to core functions. Just call those instead, silly!
  • Refresh technical debt. Direct is very old and showing it’s age. There’s a number of things unfriendly to newcomers that are there because of historical reasons.
  • No builtins, everything_snake_cassssse, PEP-8 compliant.
  • Make panda3d less dependent on Direct by providing alternatives. They’re kind of married at the moment, but I’ve found out the panda3d core is even more flexible than previously imagined when Direct is out of the way.

Right now it is basically 3 modules:

The main bit here is panda3d-startle, which is kind of like ShowBase except more procedural and minimal:

import sys
import startle

window = startle.Output("window")
scene  = startle.SceneGraph("scene", window)
# scene here now contains scene.root, scene.camera, scene.lens, etc. These can be stacked to give you what you'd expect from aspect2d and render2d.

sinput = startle.Input(window)
# sinput is kind of similar to base.mouseWatcherNode to handle input

turntable = startle.TurnTable(scene.root, scene.camera, startle.task_mgr, sinput)
turntable.header.set_h(180)
# instead of base.disableMouse, we have to start a default viewing method manually. Here a simple TurnTable class I wrote (that doesn't have the wonky camera roll!)

startle.event_mgr.add("escape", sys.exit)
startle.run() # Alias of startle.task_mgr.run()

As you can see there is no DirectObject-like things going on here. In fact, there is zero inheritance making for sparse and friendly code. Go ahead, read startle/startle.py and tell me that doesn’t make you smile. There’s also a working roaming-ralph-like example called prancing_panda.py featuring peter panda, that works 100% without direct and in only a few handful of lines.

Up next it’s panda3d-animator, an alternative to Actor.

At the moment it does pretty everything you’d want and then some, except Actor’s advanced stuff like makeSubPart, multiPartActors and ActorLod, all of which can be implemented on your own pretty easily with exposeJoint.

It can also do simple IK thanks to @Germanunkol 's marvelous CCDIK function and I’m planning on adding bullet constrains for joints, to make implementing rigs like ragdolls easier.

import sys
from startle import StartleBase # Sorry I couldn't resist. But it's only very small.

from animator import Animator, IKRig


base = StartleBase()

peter = base.load_model("assets/peter_panda.bam").copy_to(base.scene.root)
animator = Animator(peter)
animator.draw_joints(base.task_mgr)

# Playing 2 blended animations, you don't have to enable blending manually.
# If you're going to set a blend, animator assumes you want your animations to blend.
animator.set_blend("run_forward", 0.5)
animator.set_blend("sprint_forward", 0.5)
# Instead of a huge arrangement of methods only there as sugar to call AnimationControl function, you get a dictionary of AnimationControls. You're welcome.
animator.animations["run_forward"].loop(True)
animator.animations["sprint_forward"].loop(True)

# Arm follows target with IK
target = base.scene.root.attach_new_node("arm target")

ik_rig = IKRig(animator)
ik_rig.new_chain(["shoulder.l", "arm.l"], target)
ik_rig.start_ik(base.task_mgr)
def move_target(task):
    target.set_pos(target, (-0.01,0.01,0.01))
    return task.DSCont
base.task_mgr.add(move_target, "move target")

base.event_mgr.add("escape", sys.exit)
base.run()

Last but not least there’s a simplified port of my panda3d-workshop library. I’ve posted about this thing on the forums before, but it’s improved and direct-less now. It is used to generate procedural geometry. You can use it with panda3d-animator to make animated models. There’s also a live-coding environment so you don’t have to keep restarting panda3d to see what your oodles of tweaks result in.

Cool huh?

I’m still missing a lot of stuff (particularly the Interval and FilterManager systems), and I will either try to provide alternative packages (like panda3d-lion-renderer) or write my own, or just not bother (do you really need an FSM?).

There’s also no documentation, though I feel the code is readable enough to be able to follow along. Once the dust settles more I might write some.

That’s all for now. I’ll try to keep y’all posted.

3 Likes

Also in case anyone was wondering how I came up with the name:

1 Like

If this is a janEntikan that I know, then I have a tip to use one accounting record. I’m just saying that you don’t have to create a new account, I’m already confused by similar nicknames.

yeah not sure what happened there

I used to see someone’s nickname disguised as the original janEntikan, but it was mirrored and written in small letters. The user under this nickname, as far as I remember, posted a link to a website with a sample code for first-person viewing or so. There is no such account at the moment, the search does not find anything, I think it has something to do with this.

This looks very very promising. I’ll give it a go in a bit. Way to go!

Thanks! Let me know if anything works :wink: