Desktop Pet

approved

by xiaosong8584

A cute 3D cartoon robot inside your note-taking editor. - This plugin has not been manually reviewed by Obsidian staff.

โ†“ 57 downloadsUpdated 9d agoMIT

Desktop Pet for Obsidian

Project: https://github.com/xiaosong8584/obsidian-desktoppet

license version obsidian three.js

A cute 3D cartoon robot desktop pet floating inside your Obsidian window. Built with parametric geometry (Sphere / Cylinder / Capsule / Torus), zero external assets, install and play.


โœจ Features

  • ๐ŸŽจ 3D Cartoon Robot โ€” Rounded head + dot eyes (with highlights) + antenna + chest core + blush, all parametric, no external assets
  • ๐Ÿ–ฑ๏ธ Drag & Click โ€” Drag with mouse, touch or stylus to reposition; click triggers scale pulse + happy eyes + speech bubble
  • ๐Ÿ’ค Idle Animations โ€” Breathing float, gentle sway, random blinks (2.5โ€“6s), arm swing, antenna wiggle
  • ๐ŸŽญ 5 Color Schemes โ€” Soft Blue, Mint, Coral Pink, Lavender, Warm Orange
  • ๐Ÿ“ Size Slider โ€” 0.5x to 2.0x
  • ๐ŸŒ— Theme Aware โ€” Bubble & shadow use Obsidian CSS variables (--background-secondary, --background-modifier-box-shadow), auto-follow theme
  • ๐ŸŽš๏ธ Status Bar Toggle โ€” One-click show/hide, also via Ctrl+P command palette (status bar is desktop-only)
  • ๐Ÿ”Œ Fully Transparent โ€” Doesn't block Obsidian content (outer pointer-events: none, only pet is interactive)
  • โ™ป๏ธ Full Lifecycle โ€” onunload releases renderer / geometry / material / rAF / listeners

๐Ÿ“ธ Screenshots

Settings panel โ€” pet floating in the bottom-right corner with a speech bubble

Settings panel โ€” visibility toggle, size slider (1.25x), primary color, position X/Y and reset. The pet itself is visible in the bottom-right corner, showing a speech bubble.

โš™๏ธ Development Setup

  1. Install Node.js 18+ (20 LTS recommended)
  2. Clone or open the project:
    cd obsidian-desktoppet
    npm install
    
  3. Build commands:
    npm run dev          # watch mode: rebuild on save (non-minified, inline sourcemap)
    npm run build        # production build: tsc type-check + minified main.js
    npm run build:dev    # one-off development build (non-minified, inline sourcemap; exits when done)
    

๐Ÿ“ฆ Install to Obsidian

  1. Run npm run build to generate main.js
  2. Open Obsidian โ†’ Settings โ†’ Third-party plugins โ†’ Disable Restricted Mode
  3. Copy the build artifacts only into .obsidian/plugins/desktoppet/:
    <your-vault>/.obsidian/plugins/desktoppet/
      โ”œโ”€โ”€ main.js          # required (build artifact)
      โ”œโ”€โ”€ manifest.json    # required
      โ””โ”€โ”€ styles.css       # required
    
    Source .ts files are not needed in the plugin directory.
  4. Restart Obsidian (or refresh the plugin list)
  5. Search "Desktop Pet" in the plugin list and enable

Note: Works on both desktop and mobile (isDesktopOnly: false). Interaction is built on Pointer Events, so mouse, touch and stylus all drive the same drag / click logic.

๐ŸŽฎ Usage

  • Command palette โ€” Ctrl+P โ†’ search "Show/Hide Pet"
  • Status bar โ€” Robot icon in the bottom-right corner, click to toggle (desktop only)
  • Drag โ€” Press and drag the pet (mouse, touch or stylus) to any position
  • Click โ€” Click the pet body โ†’ scale pulse + happy eyes + speech bubble
  • Settings โ€” Settings โ†’ Community plugins โ†’ Desktop Pet
    • Visibility toggle
    • Pet size (0.5x โ€“ 2.0x)
    • Primary color (5 soft schemes)
    • Position X / Y (pixels)
    • Reset to default

๐Ÿ“š Documentation

๐Ÿ—‚๏ธ Project Structure

desktoppet/
โ”œโ”€โ”€ main.ts              # Plugin entry (Plugin class + lifecycle + commands + status bar)
โ”œโ”€โ”€ pet/
โ”‚   โ”œโ”€โ”€ PetScene.ts      # Three.js scene (renderer / scene / camera / lights / rAF loop)
โ”‚   โ”œโ”€โ”€ PetModel.ts      # Parametric 3D robot model (geometry composition)
โ”‚   โ”œโ”€โ”€ PetAnimator.ts   # Animation controller (idle / blink / click / drag tilt)
โ”‚   โ””โ”€โ”€ PetInteraction.ts # Interaction layer (Pointer Events drag + click)
โ”œโ”€โ”€ settings/
โ”‚   โ””โ”€โ”€ SettingsTab.ts   # Settings panel + DEFAULT_SETTINGS
โ”œโ”€โ”€ styles.css           # Floating container / bubble / status bar styles (theme aware)
โ”œโ”€โ”€ manifest.json        # Obsidian plugin manifest
โ”œโ”€โ”€ package.json         # npm dependencies
โ”œโ”€โ”€ tsconfig.json        # TypeScript config
โ”œโ”€โ”€ esbuild.config.mjs   # Build script
โ”œโ”€โ”€ images/              # README screenshots
โ””โ”€โ”€ README.md            # This file

๐Ÿ› ๏ธ Tech Stack

  • Language โ€” TypeScript (strict mode, no any)
  • 3D Rendering โ€” Three.js 0.160.x
  • Build โ€” esbuild + Obsidian standard plugin template
  • Dependencies โ€” Only three at runtime; everything else is dev-only

๐Ÿ” Key Implementation Details

Primary Color Replacement

PetModel tags the material it builds for the body/antenna/limbs with material.userData.isPrimary = true. PetScene.applyColor() walks the model and swaps exactly those materials to the target color โ€” nothing else is touched.

No color-value heuristics ("white/dark/blush are not primary"): a heuristic both under-matches (the primary color could never be changed back if it happened to equal the detail color) and over-matches (any new auxiliary material of an unexpected shade would be repainted as primary).

Click Pulse

Click feedback (scale pulse + happy eyes + antenna bounce) is driven entirely by the animation loop's elapsed clock:

scalePulse = 1 + Math.sin(t * Math.PI) * 0.3;
group.scale.setScalar(scalePulse);

PetAnimator.triggerClickFeedback() reads the cached lastElapsed written by update(). It must not query performance.now() โ€” that clock counts from page load while the loop's elapsed counts from scene creation, so mixing the two made elapsed - clickStartAt permanently negative and the feedback never converged.

The pet's visual size is controlled solely by the container / canvas size; the model itself always stays at 1:1 inside it.

Speed-Aware Drag Tilt

During drag, compute a tilt target from the X velocity (-0.3 ~ +0.3 rad), then smooth it with a first-order low-pass filter:

tiltCurrent += (tiltTarget - tiltCurrent) * Math.min(1, delta * 8);

The filter runs every frame (not only while dragging), so releasing the pointer lets the tilt decay back to zero instead of staying frozen at its last angle.

Transparent Background

  • WebGLRenderer({ alpha: true }) + setClearColor(0x000000, 0)
  • CSS container pointer-events: none, only inner canvas pointer-events: auto
  • Outer layer doesn't block Obsidian content interaction
  • While hidden, the canvas gets an explicit pointer-events: none โ€” opacity: 0 alone still receives hits

โš ๏ธ Known Limitations

  • On touch devices the pet area captures the pointer (touch-action: none), so scrolling / zooming gestures that start on the pet itself are suppressed by design โ€” drag it from elsewhere if you need to scroll
  • Position is clamped to the viewport, so the pet can never be dragged (or configured) off-screen; on a very small window a large pet will sit pinned to the top-left corner
  • Speech bubble appears at the top of the container; may be clipped if the pet is near the window top edge
  • No hover effect yet (could add slight scale + highlight boost)

๐Ÿš€ Future Directions

  • Hover effects
  • Multiple robot shapes (sphere / block / humanoid)
  • Emotion system (fall asleep after idle)
  • Custom keyboard shortcuts
  • Multi-touch gestures (e.g. pinch to resize)
  • More phrases, multi-language
  • Obsidian note integration (e.g. open new note on click, show last-modified time)

๐Ÿ“„ License

MIT ยฉ xiaosong8584

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.