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.