<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[PetPal Studio]]></title><description><![CDATA[PetPal Studio]]></description><link>https://petpalstudio.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>PetPal Studio</title><link>https://petpalstudio.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 16 Sep 2026 00:54:58 GMT</lastBuildDate><atom:link href="https://petpalstudio.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Importing animated pet packages in Tauri: the JavaScript-to-Rust path]]></title><description><![CDATA[By the PetPal Studio team.
A desktop pet importer has two jobs: read an animation package from disk and give the renderer assets it can display. In our PetPal Desktop client, JavaScript handles the in]]></description><link>https://petpalstudio.hashnode.dev/importing-animated-pet-packages-in-tauri-the-javascript-to-rust-path</link><guid isPermaLink="true">https://petpalstudio.hashnode.dev/importing-animated-pet-packages-in-tauri-the-javascript-to-rust-path</guid><category><![CDATA[Tauri]]></category><dc:creator><![CDATA[谢天]]></dc:creator><pubDate>Sat, 12 Sep 2026 02:36:28 GMT</pubDate><content:encoded><![CDATA[<p>By the PetPal Studio team.</p>
<p>A desktop pet importer has two jobs: read an animation package from disk and give the renderer assets it can display. In our <a href="https://github.com/ethmoon/petpal-desktop">PetPal Desktop client</a>, JavaScript handles the interface and animation, while Tauri commands let Rust load local files.</p>
<p>Here is the import path in the public source, including where to look when a package fails to load.</p>
<h2>1. Treat the manifest as the package contract</h2>
<p>The file picker accepts <code>.petpet</code>, <code>.petpack</code>, and <code>.zip</code> archives. The loader expects a recognized manifest and its referenced animation assets. The supported layouts are:</p>
<ul>
<li><code>petpet.json</code> with a sprite sheet.</li>
<li><code>petwebp.json</code> with WebP action files.</li>
<li>Legacy <code>manifest.json</code> with sprite strips.</li>
</ul>
<p>The <a href="https://github.com/ethmoon/petpal-desktop/blob/main/docs/petpet-format.md">format guide</a> provides examples. Renaming a photo changes its filename, but does not supply this structure. Available actions depend on the imported package.</p>
<h2>2. Pass a path across the Tauri boundary</h2>
<p>In <a href="https://github.com/ethmoon/petpal-desktop/blob/main/src/main.js"><code>src/main.js</code></a>, <code>importPetpackFile()</code> opens the native dialog. This is the relevant part, with UI-state and error handling omitted:</p>
<pre><code class="language-javascript">const selected = await open({
  directory: false,
  multiple: false,
  filters: [{ name: "PetPet", extensions: ["petpet", "petpack", "zip"] }],
});
if (selected) await importPetpackPath(selected);
</code></pre>
<p><code>importPetpackPath()</code> calls Rust through <code>invoke</code>. After a successful response, it records the installed file and applies the returned assets:</p>
<pre><code class="language-javascript">const installed = await invoke("install_petpack_file", { path });
await saveRecentPetpack("file", installed.path, installed.loaded.manifest.name);
applyPetpack(installed.loaded.manifest, installed.loaded.assets, "installed .petpack");
</code></pre>
<p>The saved path points to the application's installed copy. Import requires the native Tauri runtime; a browser-only Vite preview lacks this file-import bridge.</p>
<h2>3. Follow the archive through Rust</h2>
<p>In <a href="https://github.com/ethmoon/petpal-desktop/blob/main/src-tauri/src/lib.rs"><code>src-tauri/src/lib.rs</code></a>, <code>install_petpack_file()</code> checks the source file and extension, creates an <code>installed-petpacks</code> directory under app data, and copies the package there. It then calls <code>load_petpack_file()</code> on that copy.</p>
<p>The loader opens a <code>ZipArchive</code>, reads the manifest, and asks <code>collect_asset_paths()</code> which assets to load. Each asset is read by its archive path and encoded as a MIME-labelled Base64 data URL. The returned <code>LoadedPetpack</code> contains a manifest and an asset map for the frontend.</p>
<p>These stages give useful debugging boundaries. A corrupt archive produces <code>failed to read petpack zip</code>. A missing referenced file produces <code>failed to find asset</code>. Start by checking the container, then the manifest's paths, before investigating the animation renderer. These messages describe failures handled in the source, not test results from this article.</p>
<h2>4. Inspect the flow with public samples</h2>
<p>Install Node.js 20 or later, Rust stable, and your operating system's <a href="https://v2.tauri.app/start/prerequisites/">Tauri 2 prerequisites</a>, then run:</p>
<pre><code class="language-bash">git clone https://github.com/ethmoon/petpal-desktop.git
cd petpal-desktop
npm install
npm run tauri:dev
</code></pre>
<p>Open the system-tray menu, or menu-bar icon on macOS, choose <strong>Import .petpet</strong>, and select <code>public/standard-mochi.petpet</code> from your checkout. The tray also provides visibility, click-through, and quit controls. Use public samples when reporting problems, alongside your OS, client version, and reproduction steps.</p>
<p>The source includes Mac and Windows build targets, but a target is not a compatibility test. Check installer requirements; the default bundle configuration has no Linux installer.</p>
<h2>5. Keep the hosted service boundary clear</h2>
<p>The MIT-licensed client and public demos can be explored without a custom order. <a href="https://petpal.studio/">PetPal Studio</a> separately generates pets from uploaded photos. A custom pack currently costs US$10 once; payment unlocks the generated preview, and the private package becomes available when ready. The paid backend and customer files are not in the repository. The <a href="https://petpal.studio/blog/how-to-make-a-desktop-pet">customer walkthrough</a> covers that workflow.</p>
]]></content:encoded></item></channel></rss>