CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-panda3d

Panda3D is a framework for 3D rendering and game development for Python and C++ programs.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

animation.mddocs/

Animation and Characters

Panda3D provides comprehensive animation capabilities including character animation, procedural animation, and smooth interpolation systems for creating dynamic 3D content.

Capabilities

Actor - Animated Character System

The Actor class handles animated 3D characters with skeletal animation, multiple animation sets, and advanced playback control.

class Actor:
    def __init__(self, 
                 model: str = None,
                 anims: dict = None,
                 copy: bool = True,
                 flattenable: bool = True,
                 setFinal: bool = False) -> None:
        """
        Create animated character.
        
        Args:
            model: Path to character model file
            anims: Dictionary mapping animation names to file paths
            copy: Whether to copy geometry (True) or instance it (False)
            flattenable: Whether model can be flattened for optimization
            setFinal: Whether to finalize model structure
        """
    
    def loadModel(self, modelPath: str) -> None:
        """Load character model from file."""
    
    def loadAnims(self, anims: dict) -> None:
        """Load animation files. Dict maps names to file paths."""
    
    def bindAnim(self, animName: str, animPath: str, partName: str = None) -> None:
        """Bind single animation to character or part."""
    
    def unloadAnims(self, animNames: list = None, partNames: list = None) -> None:
        """Unload specified animations."""
    
    def getAnimNames(self, partName: str = None) -> list:
        """Get list of loaded animation names."""
    
    def hasAnim(self, animName: str) -> bool:
        """Check if animation is loaded."""

Animation Playback Control

Control animation playback with various modes, blending, and timing options.

class Actor:
    def play(self, animName: str, partName: str = None, fromFrame: int = None, toFrame: int = None) -> None:
        """Play animation once from start to end."""
    
    def loop(self, animName: str, partName: str = None, fromFrame: int = None, toFrame: int = None) -> None:
        """Loop animation continuously."""
    
    def pingpong(self, animName: str, partName: str = None, fromFrame: int = None, toFrame: int = None) -> None:
        """Play animation back and forth."""
    
    def stop(self, partName: str = None) -> None:
        """Stop animation playback."""
    
    def pause(self, partName: str = None) -> None:
        """Pause animation at current frame."""
    
    def resume(self, partName: str = None) -> None:
        """Resume paused animation."""
    
    def pose(self, animName: str, frame: int, partName: str = None) -> None:
        """Set character to specific animation frame."""
    
    def isPlaying(self, animName: str = None, partName: str = None) -> bool:
        """Check if animation is currently playing."""
    
    def getCurrentAnim(self, partName: str = None) -> str:
        """Get name of currently playing animation."""
    
    def getCurrentFrame(self, partName: str = None) -> int:
        """Get current animation frame number."""
    
    def getNumFrames(self, animName: str = None, partName: str = None) -> int:
        """Get total frames in animation."""
    
    def getDuration(self, animName: str = None, partName: str = None) -> float:
        """Get animation duration in seconds."""
    
    def getFrameRate(self, animName: str = None, partName: str = None) -> float:
        """Get animation frame rate."""
    
    def setPlayRate(self, rate: float, animName: str = None, partName: str = None) -> None:
        """Set animation playback speed multiplier."""
    
    def getPlayRate(self, animName: str = None, partName: str = None) -> float:
        """Get current playback rate."""

Animation Blending and Transitions

Advanced animation features for smooth transitions and blending between animations.

class Actor:
    def enableBlend(self, blendType: int = 0, partName: str = None) -> None:
        """Enable animation blending."""
    
    def disableBlend(self, partName: str = None) -> None:
        """Disable animation blending."""
    
    def setBlend(self, 
                 animBlend: bool = True,
                 frameBlend: bool = True, 
                 blendType: int = 0,
                 partName: str = None) -> None:
        """Configure blending options."""
    
    def setControlEffect(self, animName: str, effect: float, partName: str = None) -> None:
        """Set animation influence/weight (0.0-1.0)."""
    
    def getControlEffect(self, animName: str, partName: str = None) -> float:
        """Get animation influence/weight."""

Multi-Part Characters

Support for characters with multiple independently animated parts.

class Actor:
    def makeSubpart(self, partName: str, includeJoints: list, excludeJoints: list = []) -> None:
        """Create animation subpart from specified joints."""
    
    def getPartNames(self) -> list:
        """Get list of all part names."""
    
    def removePart(self, partName: str) -> None:
        """Remove animation part."""
    
    def hidePart(self, partName: str) -> None:
        """Hide part geometry."""
    
    def showPart(self, partName: str) -> None:
        """Show part geometry."""
    
    def showAllParts(self) -> None:
        """Show all parts."""

Procedural Animation with Intervals

The interval system provides procedural animation through interpolation of object properties over time.

class LerpPosInterval:
    def __init__(self, nodePath: NodePath, 
                    duration: float,
                    pos: Vec3,
                    startPos: Vec3 = None,
                    blendType: str = 'noBlend') -> None:
        """Animate object position over time."""

class LerpHprInterval:
    def __init__(self, nodePath: NodePath,
                    duration: float, 
                    hpr: Vec3,
                    startHpr: Vec3 = None,
                    blendType: str = 'noBlend') -> None:
        """Animate object rotation over time."""

class LerpScaleInterval:
    def __init__(self, nodePath: NodePath,
                      duration: float,
                      scale: Vec3,
                      startScale: Vec3 = None,
                      blendType: str = 'noBlend') -> None:
        """Animate object scale over time."""

class LerpColorInterval:
    def __init__(self, nodePath: NodePath,
                      duration: float,
                      color: Vec4,
                      startColor: Vec4 = None,
                      blendType: str = 'noBlend') -> None:
        """Animate object color over time."""

class LerpColorScaleInterval:
    def __init__(self, nodePath: NodePath,
                           duration: float,
                           colorScale: Vec4,
                           startColorScale: Vec4 = None,
                           blendType: str = 'noBlend') -> None:
        """Animate color scale over time."""

Composite Animation Sequences

Create complex animations by combining multiple intervals in sequences and parallel groups.

class Sequence:
    def __init__(self, *intervals) -> None:
        """Create sequence of intervals that play one after another."""
    
    def start(self) -> None:
        """Start the sequence."""
    
    def finish(self) -> None:
        """Jump to end of sequence."""
    
    def pause(self) -> None:
        """Pause sequence playback."""
    
    def resume(self) -> None:
        """Resume paused sequence."""
    
    def loop(self) -> None:
        """Loop sequence continuously."""
    
    def isPlaying(self) -> bool:
        """Check if sequence is playing."""
    
    def getDuration(self) -> float:
        """Get total sequence duration."""

class Parallel:
    def __init__(self, *intervals) -> None:
        """Create group of intervals that play simultaneously."""
    
    def start(self) -> None: ...
    def finish(self) -> None: ...
    def pause(self) -> None: ...
    def resume(self) -> None: ...
    def loop(self) -> None: ...
    def isPlaying(self) -> bool: ...
    def getDuration(self) -> float: ...

def Wait(duration: float) -> WaitInterval:
    """Create pause/delay interval."""

def Func(function: callable, *args) -> FunctionInterval:
    """Create interval that calls function."""

Animation Easing and Blending

Control animation curves and transitions for more natural motion.

# Easing functions for smooth animation curves
def easeIn(t: float) -> float:
    """Ease-in curve (slow start)."""

def easeOut(t: float) -> float:
    """Ease-out curve (slow end)."""

def easeInOut(t: float) -> float:
    """Ease-in-out curve (slow start and end)."""

# Blend types for intervals
BLEND_EASE_IN = "easeIn"
BLEND_EASE_OUT = "easeOut" 
BLEND_EASE_IN_OUT = "easeInOut"
BLEND_NO_BLEND = "noBlend"

Usage Examples

Basic Character Animation

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

class CharacterDemo(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        # Load animated character
        self.character = Actor(
            "models/characters/panda",
            {
                "walk": "models/characters/panda-walk",
                "run": "models/characters/panda-run", 
                "idle": "models/characters/panda-idle"
            }
        )
        
        self.character.reparentTo(self.render)
        self.character.setScale(0.5)
        self.character.setPos(0, 10, 0)
        
        # Start with idle animation
        self.character.loop("idle")
        
        # Setup input
        self.accept("1", self.playIdle)
        self.accept("2", self.playWalk) 
        self.accept("3", self.playRun)
    
    def playIdle(self):
        """Switch to idle animation."""
        self.character.loop("idle")
        
    def playWalk(self):
        """Switch to walking animation."""
        self.character.loop("walk")
        
    def playRun(self):
        """Switch to running animation.""" 
        self.character.loop("run")

app = CharacterDemo()
app.run()

Procedural Animation with Intervals

from direct.showbase.ShowBase import ShowBase
from direct.interval.IntervalGlobal import *
from panda3d.core import Vec3

class AnimationDemo(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        # Create object to animate
        self.cube = self.loader.loadModel("models/cube")
        self.cube.reparentTo(self.render)
        self.cube.setPos(-5, 10, 0)
        
        # Create complex animation sequence
        self.createAnimation()
        
        # Start animation
        self.accept("space", self.startAnimation)
    
    def createAnimation(self):
        """Create complex animation sequence."""
        # Move right while growing
        move_right = LerpPosInterval(
            self.cube, 2.0, Vec3(5, 10, 0), blendType='easeInOut'
        )
        grow = LerpScaleInterval(
            self.cube, 2.0, Vec3(2, 2, 2), blendType='easeInOut'
        )
        
        # Parallel movement and scaling
        phase1 = Parallel(move_right, grow)
        
        # Rotate and change color
        rotate = LerpHprInterval(
            self.cube, 1.5, Vec3(360, 0, 0)
        )
        color_change = LerpColorInterval(
            self.cube, 1.5, (1, 0, 0, 1)  # Red
        )
        
        phase2 = Parallel(rotate, color_change)
        
        # Move up with pause
        pause = Wait(0.5)
        move_up = LerpPosInterval(
            self.cube, 1.0, Vec3(5, 10, 3), blendType='easeOut'
        )
        
        # Final callback
        finish_func = Func(self.onAnimationComplete)
        
        # Combine into sequence
        self.animation = Sequence(
            phase1,
            phase2, 
            pause,
            move_up,
            finish_func
        )
    
    def startAnimation(self):
        """Start the animation sequence."""
        # Reset object state
        self.cube.setPos(-5, 10, 0)
        self.cube.setScale(1, 1, 1)
        self.cube.setHpr(0, 0, 0)
        self.cube.clearColor()
        
        # Start animation
        self.animation.start()
    
    def onAnimationComplete(self):
        """Called when animation finishes."""
        print("Animation completed!")
        
        # Loop the animation
        self.startAnimation()

app = AnimationDemo()
app.run()

Multi-Part Character Animation

from direct.showbase.ShowBase import ShowBase
from direct.actor.Actor import Actor

class MultiPartDemo(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        # Load character with multiple parts
        self.character = Actor("models/characters/robot")
        self.character.loadAnims({
            "torso_idle": "models/anims/robot-torso-idle",
            "torso_wave": "models/anims/robot-torso-wave",
            "legs_walk": "models/anims/robot-legs-walk",
            "legs_run": "models/anims/robot-legs-run"
        })
        
        self.character.reparentTo(self.render)
        
        # Create animation parts
        self.character.makeSubpart(
            "torso", 
            ["torso", "left_arm", "right_arm", "head"]
        )
        self.character.makeSubpart(
            "legs",
            ["left_leg", "right_leg", "pelvis"]
        )
        
        # Start different animations on different parts
        self.character.loop("torso_idle", partName="torso")
        self.character.loop("legs_walk", partName="legs")
        
        # Setup controls
        self.accept("w", self.wave)
        self.accept("r", self.run)
        self.accept("s", self.stop)
    
    def wave(self):
        """Play wave animation on torso."""
        self.character.play("torso_wave", partName="torso")
        
        # Return to idle after wave completes
        duration = self.character.getDuration("torso_wave", "torso")
        self.taskMgr.doMethodLater(
            duration, self.returnToIdle, "return-idle"
        )
    
    def returnToIdle(self, task):
        """Return torso to idle animation."""
        self.character.loop("torso_idle", partName="torso")
        return task.done
    
    def run(self):
        """Switch legs to running."""
        self.character.loop("legs_run", partName="legs")
    
    def stop(self):
        """Switch legs to walking."""
        self.character.loop("legs_walk", partName="legs")

app = MultiPartDemo()
app.run()

Types

class AnimControl:
    """Animation control object for fine-tuned animation management."""
    def play(self) -> None: ...
    def stop(self) -> None: ...
    def pose(self, frame: int) -> None: ...

class PartBundle:
    """Animation part bundle for multi-part characters."""
    def getName(self) -> str: ...
    def update(self) -> None: ...

# Animation blend types
BT_NO_BLEND = 0          # No blending
BT_NORMAL_BLEND = 1      # Normal animation blending
BT_ADDITIVE_BLEND = 2    # Additive blending

# Interval blend type constants
from direct.interval.IntervalGlobal import *
# Available blend types: 'noBlend', 'easeIn', 'easeOut', 'easeInOut'

Install with Tessl CLI

npx tessl i tessl/pypi-panda3d

docs

animation.md

application-framework.md

asset-loading.md

audio.md

index.md

input.md

mathematics.md

scene-graph.md

task-event.md

user-interface.md

tile.json