2026年9月21日月曜日

Privacy Policy for Spatial Book

 

Privacy Policy for Spatial Book

Effective Date: September 21, 2026

Spatial Book respects your privacy. The app does not collect, store, transmit, or share any personal information or user data.

Information Collection

Spatial Book does not collect any personal information.

The app does not use:

  • User accounts

  • Analytics services

  • Advertising services

  • Tracking technologies

  • Cookies

  • Third-party data collection services

  • Remote servers for storing user data

Documents and Files

Spatial Book allows you to open documents such as text files and PDF files from your device.

Documents opened in Spatial Book are used only to display their contents within the app. Their contents are not uploaded to external servers, transmitted to the developer, or shared with third parties.

Hand Tracking

Spatial Book may use hand tracking provided by visionOS to recognize gestures used to interact with books and pages in immersive space.

Hand tracking data is used only for real-time interaction within the app and is not collected, stored, transmitted, or shared by Spatial Book.

Data Sharing

Spatial Book does not collect user data and therefore does not sell, share, or provide personal data to third parties.

Children's Privacy

Spatial Book does not knowingly collect personal information from anyone, including children.

Changes to This Privacy Policy

This Privacy Policy may be updated if the features of Spatial Book change in the future. Any changes will be reflected on this page.

Contact

If you have questions about this Privacy Policy, please contact the developer through the Spatial Book support page.

Spatial Book — Features and How to Use

 

  • Core Concept

    • Spatial Book is a spatial document reader designed for Apple Vision Pro.

    • It can import text files and PDF documents and display them as three-dimensional books.

    • Pages can be turned directly by pinching and dragging them, similar to turning a physical sheet of paper.

    • Pages bend dynamically as they are dragged.

    • If you release a page midway through a turn, it falls toward the nearer side depending on its position.

    • Documents can be opened either in a standard Window or in Immersive Space.

    • When Advanced Mode is enabled, pages can also be treated as individual spatial objects rather than only as pages inside a book.

  • Supported Files

    • PDF files can be imported.

    • Text files can be imported.

    • The current text importer supports UTF-8, Shift_JIS, EUC-JP, and UTF-16 encoding detection.

    • The imported file name is used as the book title.

    • A built-in sample book is included.

    • Multiple imported documents can be kept in the library and opened independently.

  • Library

    • Use “Open File” to import a text file or PDF.

    • Use “Open Sample” to open the built-in sample document.

    • Imported documents appear in the Bookshelf.

    • Each document can be opened either:

      • in a Window

      • in Immersive Space

    • Multiple books can also be sent into Immersive Space together.

    • The Library window can be reopened while Immersive Space is active.

    • The entire Immersive Space can be closed from the Library.

    • A confirmation is shown before closing the whole space because spatial layouts and placed pages cannot currently be restored afterward.

  • Text Typesetting

    • Text size can be adjusted for imported text files.

    • The current range is 13 pt to 26 pt.

    • Horizontal left-to-right layout is supported.

    • Vertical right-to-left layout is also supported.

    • In vertical mode, book opening direction and page navigation are adjusted to match a right-bound book.

    • PDF documents use their original page layout and are always treated as left-bound documents.

    • Changing typesetting settings rebuilds affected books using the new settings.

  • Paper Quality / Rendering Quality

    • The rendering quality of spatial page cards used in Advanced Mode can be adjusted.

    • Standard

      • Prioritizes the number of visible pages and lower resource usage.

    • High

      • Balances rendering quality and page count.

    • Ultra

      • Prioritizes image quality and renders spatial cards at a resolution closer to the main book pages.

    • Higher quality settings reduce the number of high-resolution page textures kept in memory at the same time.

    • For Stack and Grid layouts, the current number of detailed pages per group is:

      • Standard: up to 60 pages

      • High: up to 40 pages

      • Ultra: up to 24 pages

    • Row Mode can represent many pages while only loading detailed textures around the currently focused page.

    • The current detailed texture windows for Row Mode are:

      • Standard: focused page + 12 pages on each side, up to 25 loaded pages

      • High: focused page + 8 pages on each side, up to 17 loaded pages

      • Ultra: focused page + 5 pages on each side, up to 11 loaded pages

    • Stack, Grid, and Row layouts are designed so that large documents do not require every page image to remain loaded on the GPU at the same time.

  • Window Mode

    • Displays the document as a 3D book inside a visionOS volume window.

    • Pages can be turned directly with pinch-and-drag gestures.

    • Previous and next page buttons are provided below the book.

    • Page buttons support press-and-hold for continuous page turning.

    • The current page or spread position is displayed.

    • A slider allows quick navigation to distant parts of the document.

    • In vertical text mode, page navigation and slider direction are reversed to match right-to-left book progression.

    • Resizing the volume window also scales the 3D book accordingly.

  • Immersive Mode — Basics

    • Books can be placed as 3D objects in the surrounding space.

    • Multiple books can be opened in the same Immersive Space.

    • Newly opened books are initially arranged next to one another.

    • Each book can be read and moved independently.

    • One book is treated as the currently focused book for menu operations.

    • When focus changes, a temporary light-blue marker appears above the selected book so you can see which book is active.

    • The marker gradually shrinks and disappears after a short time.

  • Immersive Mode — Page Turning

    • Pages can be turned directly with pinch-and-drag gestures, just like in Window Mode.

    • Previous and next page controls are also available from the spatial menu.

    • Vertical text uses right-to-left page progression.

  • Immersive Mode — Moving Books by Hand

    • Either hand can be used.

    • Making a fist near a movable book grabs the nearest eligible book.

    • If several books are nearby, the nearest one to the hand is selected.

    • While keeping the hand closed, moving the hand moves the book with it.

    • Opening the hand releases the book and leaves it at the current location.

    • A grab begins only when the fist gesture is first detected, which helps prevent unintended repeated grabbing while the hand remains closed.

    • While holding a book, wrist orientation can also be used to adjust the viewing tilt.

    • A “Reset Tilt” control restores the book to its default reading angle.

  • Immersive Mode — Summoning Distant Books

    • Look at a distant book and double-pinch to bring it toward you.

    • This allows books to be retrieved without physically moving across the room.

    • The summoned book is placed slightly in front of and below the user’s head position.

  • Immersive Mode — Resizing Books

    • A light-blue spherical handle appears at the lower-right corner of the focused book.

    • Pinch and drag the handle to resize the entire book.

    • The resize handle appears only when that book is focused and its control menu is expanded, helping keep the reading view uncluttered.

  • Immersive Mode — Spatial Control Menu

    • A shared control panel is used for the currently focused book.

    • The panel displays information such as the book title and current mode or status.

    • By default, the panel appears in front of the user.

    • It does not rigidly follow every small head movement.

    • Instead, it begins moving only after the user moves far enough away, then smoothly catches up.

    • The panel continually rotates to face the user.

    • The panel can be pinned in place.

    • When pinned, it stops following the user.

    • A light-blue handle appears above the pinned panel.

    • Pinch and drag that handle to reposition the panel anywhere in space.

    • Unpinning the panel restores its head-following behavior.

    • The panel can also be collapsed.

    • When collapsed, it becomes a small “…” button to reduce visual obstruction while reading.

    • Pressing the button expands the full panel again.

    • A Library button reopens the Library window.

    • “Close Book” closes only the currently focused book from Immersive Space.

    • A confirmation is shown before closing a book if spatial layouts or detached pages will be removed.

    • Other open books and the Immersive Space itself remain active when one book is closed.

  • Focus Mode / Background

    • Passthrough (MR)

      • Displays books over the real environment.

    • Focus - Dark

      • Hides passthrough and places the user in a dark fully immersive environment.

    • Focus - Grid Room

      • Uses a fully immersive environment with a large grid floor.

      • Hides the real environment while preserving a strong sense of spatial position.

      • The grid fades into darkness toward the edges to create the impression of a larger continuous space.

  • Advanced Mode

    • Advanced Mode is disabled by default.

    • With Advanced Mode off, Spatial Book focuses on the standard reading experience.

    • Enabling Advanced Mode adds the following spatial document layouts:

      • Book

      • Stack

      • Grid

      • Row

    • You can switch directly between Book, Stack, Grid, and Row modes.

    • Accordion is a special interactive expansion state entered from Stack Mode.

    • Turning Advanced Mode off while another layout is active returns documents to normal Book Mode.

    • This allows users who only want a traditional reader to ignore the more experimental spatial tools entirely.

  • Advanced — Book Mode

    • Standard 3D book presentation.

    • Pages can be turned directly.

    • Previous and next page controls are available from the menu.

    • The book can be grabbed and moved with a fist gesture.

    • The blue handle can be used to resize the book.

    • “Reset Tilt” restores the default reading angle.

    • Other Advanced layouts can always be returned to Book Mode.

  • Advanced — Stack Mode

    • Breaks the document into individual page cards and displays them as physical stacks of paper.

    • Large documents are divided into multiple manageable stacks instead of one extremely thick stack.

    • Stack size depends on the selected Paper Quality setting.

    • Each stack can be positioned independently.

    • Tapping a stack selects it as the active stack.

    • Detailed textures are loaded around the currently selected stack.

    • A stack can be grabbed with a fist and moved through space.

    • When several stacks are present, only the stack nearest to the grabbing hand is moved.

    • Other stacks remain where they are.

    • Looking at a stack and double-pinching summons only that stack toward the user.

    • While holding a stack with one fist, bringing the other fist close to it begins Accordion expansion.

  • Advanced — Accordion Expansion

    • Accordion is a special spatial expansion entered from Stack Mode.

    • Grab a stack with one fist.

    • Bring the other hand close while also making a fist.

    • The pages expand between the two hands.

    • The positions of the hands determine the two ends of the expanded page sequence.

    • Moving the hands farther apart increases spacing between pages.

    • Moving them closer together compresses the layout.

    • The pages are oriented to remain readable from the user’s position.

    • Opening either hand freezes the current arrangement in space.

    • Once frozen, both hands can be released while the pages remain spread out.

    • Previously frozen stacks can remain expanded even while another stack is manipulated.

    • After freezing, moving a fingertip close to a page causes the nearest page to protrude slightly as a preview.

    • Pinching that page pulls a single page out of the Accordion layout.

    • The detached page immediately follows the pinching hand.

    • Releasing the pinch leaves the page at that position.

    • The two ends of a frozen Accordion layout can be grabbed again with two fists to resume adjusting the spread.

    • The layout also supports grabbing the two ends with opposite hands.

    • An “Adjust” button is available as an alternative way to resume editing if the gesture is difficult to perform.

    • “To Stack” collapses the expanded Accordion back into Stack form.

  • Advanced — Grid Mode

    • Displays pages as a spatial grid for overview and comparison.

    • Many pages can be viewed simultaneously.

    • Large documents are divided into multiple Grid panels.

    • Each panel contains a manageable number of pages.

    • Only pages near the currently active panel keep detailed textures loaded.

    • Looking at another Grid panel and pinching brings that panel into the active position.

    • Looking at and pinching a page on the active Grid detaches that page and places it into the surrounding space.

    • Detached pages are initially positioned in front of the user.

    • Multiple detached pages are offset horizontally to avoid directly overlapping one another.

    • Detached pages remain in space when switching to another Grid panel.

    • Pinching the original Grid slot of a detached page again returns that page to the Grid.

    • The Grid itself can be grabbed with a fist and repositioned.

    • The menu displays information such as page count, current panel, and number of detached pages.

    • A Return control can return detached pages to their source layout.

  • Advanced — Manipulating Detached Pages

    • Pages can be detached from Grid, Accordion, and Row layouts and treated as independent spatial objects.

    • Detached pages remain in space independently of their source layout.

    • Pinch and drag a detached page to move it.

    • A placed page can be grabbed again later.

    • Re-grabbing uses a stricter proximity and pinch threshold to reduce accidental page pickup.

    • Detached pages can be scaled using a magnification gesture.

    • Detached pages can be rotated freely using a 3D rotation gesture.

    • The same page can also be pinched with both hands.

    • The distance between the hands controls page scale.

    • Hand orientation can be used to rotate the page.

    • If one hand is released during a two-handed transformation, the remaining hand can continue holding the page.

    • A page can also be transferred from one hand to the other.

    • This allows pages from different parts of a document to be placed next to one another for comparison.

    • Detached pages can also be returned to their original layout in a batch.

  • Advanced — Row Mode

    • Arranges document pages in one long horizontal row.

    • Instead of turning one page at a time, the entire document can be browsed as a continuous spatial sequence.

    • Pinch and drag horizontally to scroll through the row.

    • Larger swipe distances can move through multiple pages continuously.

    • When the gesture ends, the row snaps to the nearest page.

    • Previous and next controls are also available from the menu.

    • The current page and total page count are displayed.

    • Tapping a Row card selects that Row as the active document.

    • Pinching and holding a page without immediately swiping allows that page to be detached from the Row.

    • Detached pages can then be placed and manipulated independently like pages from Grid or Accordion.

    • The entire Row can be grabbed with a fist and repositioned in space.

    • Two visual styles are available:

      • Flat

      • Emphasized

    • Flat mode keeps pages aligned uniformly in the row.

    • Emphasized mode moves the focused page forward and enlarges it for easier reading.

    • Row Mode does not keep full-resolution textures on every page simultaneously.

    • Only the pages near the current focus are loaded in detail.

    • The current implementation can represent up to 1,000 Row cards.

  • Using Multiple Documents in Space

    • Multiple books can coexist in the same Immersive Space.

    • Each document can independently use Book, Stack, Grid, or Row layout.

    • For example, one document can remain open as a normal book while another is displayed as a Grid.

    • The shared control panel operates on one focused document at a time.

    • Interacting with another book, stack, Grid, or Row changes the focused document.

    • A light-blue indicator briefly shows which document is now active.

    • Closing one document does not close the others.

  • Interaction Safeguards

    • Closing a book requires confirmation when spatial content may be lost.

    • Closing the entire Immersive Space also requires confirmation.

    • The interface warns that current spatial layouts cannot be restored after closing.

    • If detached pages exist, the close confirmation indicates that they will also be removed.

    • Fist-based grabbing is triggered only when the fist gesture begins, helping prevent repeated unintended grabs.

    • Page extraction from Accordion also reacts to the start of a pinch rather than a continuously held pinch.

    • Picking up an already detached page uses a stricter pinch threshold.

    • During two-handed Accordion manipulation, normal book grabbing is temporarily suppressed.

    • The spatial menu does not rigidly follow every small head movement, reducing distracting motion.

    • Large documents use selective texture loading so that only nearby or relevant pages stay at high resolution.

  • In Short

    • In its simplest form, Spatial Book is a reader that turns text files and PDFs into 3D books that can be read by physically turning their pages.

    • In Immersive Mode, it becomes a spatial library where multiple books can be placed around the user.

    • With Advanced Mode enabled, it also becomes a spatial document viewer where pages can be separated from the book, stacked, expanded, arranged in grids or rows, detached, moved, scaled, rotated, and compared directly in space.

2026年8月30日日曜日

Spatial Room Toybox

 Included Experiences

💧 Spatial Water — Interactive Water Simulation

Touch the water surface in front of you and watch ripples spread outward in real time. Create splashes, turn on rainfall, and interact directly with waves simulated on the GPU.

🌀 Fluid Board — Interactive Fluid Simulation

Use your finger to stir colorful fluid on a floating board. Draw through the flow, create vortices, and watch streams collide and evolve through a real-time fluid simulation.

✨ Particles — Fingertip Particles

Emit thousands of GPU particles directly from your fingertips. Choose from styles such as Sparkler, Magic Dust, and Fountain, move your hands to shape their motion, or trigger bursts of fireworks in space.

🌌 Morph Nebula — Shape-Shifting Nebula

Tens of thousands of particles continuously transform between shapes such as a Galaxy, Knot, Sphere, DNA helix, and Torus.

Reach into the nebula with your hands to scatter the particles. Once you move away, they gradually reform into their original shape.

🏠 Room Dust — Turn Your Room into Luminous Particles

The app scans the geometry of your real room and covers walls, floors, and other surfaces with tens of thousands of glowing particles.

Touch the room to send waves through the particles, dissolve the entire environment into floating dust, and watch it assemble itself again.

You can also import your own music. Low frequencies and detected beats make the room pulse and generate waves in sync with the sound.

In Space Void Mode, the real environment gives way to a fully immersive space filled with optional light streaks, tunnel gates, concentric rings, and meteors synchronized to the music. Meteors can even be intercepted with your hands.

🔆 Glow Room — Light Waves Across Your Environment

Your real walls and tables remain invisible until you touch them. Light waves then travel outward across their surfaces, revealing the geometry of the room only as the wave passes.

Choose between soft glowing waves and sharper ring-like pulses, or reveal the entire room as a futuristic illuminated grid.

🧊 3D Cellular Automata — Living 3D Cells

Explore a three-dimensional cellular automaton containing approximately 260,000 cells.

Choose from several rule sets including 3D Life, Clouds, Pyro, Brian's Brain, Amoeba, and more. Place your fingertips inside the grid to create new living cells and watch complex structures grow, move, and disappear.

🖌️ Spatial Paint — Paint Directly in 3D Space

Use your fingertips as brushes and draw physical 3D strokes directly into the world around you.

Extend one finger to draw one line, two fingers to draw two, or open your hand to paint with all five fingers at once.

Pick different colors independently for each finger from a floating 3D color palette. Switch between Neon, Matte, and Glossy materials, erase strokes with your hands, undo previous actions, and freely combine different materials and colors in the same artwork.

Finished creations can also be exported as USDZ files.

🔵 Water Sphere — A Sphere Made of Waves

Hold a responsive water sphere above your left palm.

Touch it with your other hand or tap its surface to generate ripples that propagate across the entire sphere.

🫠 Liquid Metal Hands — Turn Your Hands into Liquid Metal

Cover both hands with a reflective liquid-metal surface created from dynamically merging metaballs.

Move your hands quickly to fling droplets into the environment. The scattered metal can gradually return to your hands, gather into a sphere when you make a fist, collapse onto the floor, or crawl across walls and surfaces when recalled.

A game mode is also included: collect glowing targets appearing around the room using only your liquid-metal hands before time runs out.

🌠 Particle Hands — Become a Body of Light

Enter a fully immersive dark space where your hands are transformed into tens of thousands of glowing particles.

Choose from visual styles such as Skin, Aura, Stardust, and Comet. Particles can cling to your hands, flow outward from your fingers, or leave luminous trails as you move.

🌿 L-System Garden — Grow Plants in Your Room

Tap a real floor or wall to plant a seed and watch a procedural plant grow directly from that surface.

Adjust branching angle, growth generations, foliage density, leaf color, bark shape, and more. Once grown, branches and leaves continue to sway in the wind.

🐦 Boids Flock — Control a Living Flock with Your Hands

Thousands of birds or fish move together using a real-time Boids flocking simulation.

Make a fist to attract and swirl the flock around your hand, or open your palm to repel it. Your left and right hands can control the flock independently.

The creatures also react to the geometry of your real room and avoid walls as they move. In the immersive space mode, the room itself can be visualized as a field of glowing points.

🫧 Goo Flock — A Living Liquid Swarm

Combine Boids flocking behavior with metaball surface generation.

Hundreds of moving agents continuously merge into a single evolving liquid surface, creating something between a flock of creatures and a living blob.

Close your hand into a fist to gather the swarm into one mass, then open your palm to blast it apart.

Different visual styles including Chrome, Jelly, and Neon can completely change its appearance.

🪸 Reaction Coral — Growing Reaction-Diffusion Forms

Watch three-dimensional structures resembling coral and living organisms emerge from a real-time Gray-Scott reaction-diffusion simulation.

Reach into the structure to create new growth points and watch the form develop around your hands.

Choose from patterns including Coral, Mitosis, Maze, Spirals, and Waves to generate dramatically different forms.

🪐 Living Planet — A Living World in Your Hand

Hold a small procedural planet above your left palm.

Touch its surface with your other hand to seed reaction-diffusion patterns that spread across the sphere like evolving crust, biological growth, or glowing lava.

Different reaction rules continuously transform the appearance of the planet.

🦓 Turing Walls — Living Patterns Across Your Real Room

Use the surfaces of your actual room as the simulation itself.

Trace your finger across walls, floors, or tables to seed Turing-style reaction-diffusion patterns. The patterns then spread organically across the captured room geometry, transforming ordinary surfaces into glowing, evolving structures.

🍃 Overgrowth — Let Ivy Invade Your Room

Touch a wall or floor and watch ivy begin growing directly from that point.

The vines crawl across the actual surfaces of your room, branch, twist, produce leaves and tendrils, and gradually spread through the environment.

Adjust growth speed, branching, wandering, vine length, leaf density, wind, and other parameters to create anything from a few delicate vines to an entire room overtaken by vegetation.

Spatial Room Toybox Privacy Policy

Privacy Policy

Last updated: August 30, 2026

Spatial Room Toybox respects your privacy.

Data Collection

Spatial Room Toybox does not collect, store, transmit, or share any personal data.

The app does not require an account and does not use advertising, analytics, tracking, or third-party services that collect user information.

Camera, Hand Tracking, and Room Data

Spatial Room Toybox uses Apple Vision Pro system features such as hand tracking and spatial room geometry to provide interactive mixed-reality experiences.

This information is processed locally on your device and is not collected, stored on external servers, or transmitted to the developer or any third party.

Imported Audio Files

Some experiences allow you to select an audio file from your device for real-time audio visualization.

Selected audio files are processed locally on your device. They are not uploaded, transmitted, or collected by the developer.

User-Created Content

Some features may allow you to create or export content, such as 3D artwork. This content remains under your control and is not automatically uploaded or transmitted to the developer.

Third-Party Sharing

Spatial Room Toybox does not sell, rent, share, or disclose personal information to third parties.

Children’s Privacy

Because Spatial Room Toybox does not collect personal information, it does not knowingly collect personal information from children.

Changes to This Privacy Policy

This Privacy Policy may be updated if the app’s features or data practices change. Any updates will be posted on this page.

Contact

If you have any questions about this Privacy Policy, please contact the developer through the support contact listed on the App Store page.

2026年7月20日月曜日

How to transfer root bone pose animation to the animation of the entire armature 5.x

import bpy

import math


from mathutils import Matrix

from bpy_extras import anim_utils



# ============================================================

# Settings

# ============================================================


ROOT_BONE_NAME = "Root"


# If True:

#   Bake a keyframe on every frame between the first and last

#   root bone keyframe.

#   This preserves interpolation more accurately, but creates

#   many additional keyframes.

#

# If False:

#   Process only frames that already contain root bone keys.

#   This behaves similarly to the original version of the script.

BAKE_EVERY_FRAME = False


# Delete the root bone after the transfer is complete.

DELETE_ROOT_BONE = True



# ============================================================

# Blender 5.x / Legacy Action Compatibility

# ============================================================


def get_action_fcurves(animated_id):

    """

    Return all F-Curves from the Action currently assigned

    to the specified animated datablock.


    Blender 4.x and earlier:

        action.fcurves


    Blender 5.x:

        Action Slot

            -> Channelbag

                -> F-Curves

    """


    animation_data = animated_id.animation_data


    if animation_data is None:

        return []


    action = animation_data.action


    if action is None:

        return []


    # Legacy Blender API.

    if hasattr(action, "fcurves"):

        return list(action.fcurves)


    # Blender 5.x layered Action API.

    action_slot = getattr(animation_data, "action_slot", None)


    # Normally animation_data.action_slot is available.

    # As a fallback, use the only slot if the Action has exactly one.

    if action_slot is None:

        slots = getattr(action, "slots", None)


        if slots is not None and len(slots) == 1:

            action_slot = slots[0]


    if action_slot is None:

        print(

            f"Warning: No Action slot was found for "

            f"'{animated_id.name}'."

        )

        return []


    channelbag = anim_utils.action_get_channelbag_for_slot(

        action,

        action_slot

    )


    if channelbag is None:

        return []


    return list(channelbag.fcurves)



def collect_keyframes(fcurves, data_path_prefix=None):

    """

    Collect all unique keyframe times from a list of F-Curves.


    If data_path_prefix is specified, only F-Curves whose

    data paths start with that prefix are included.

    """


    frames = set()


    for fcurve in fcurves:

        if (

            data_path_prefix is not None

            and not fcurve.data_path.startswith(data_path_prefix)

        ):

            continue


        for keyframe in fcurve.keyframe_points:

            frames.add(float(keyframe.co.x))


    return sorted(frames)



def set_scene_frame(scene, frame):

    """

    Set the current timeline position with subframe support,

    then update the dependency graph.

    """


    whole_frame = math.floor(frame)

    subframe = frame - whole_frame


    scene.frame_set(whole_frame, subframe=subframe)

    bpy.context.view_layer.update()



# ============================================================

# Main

# ============================================================


scene = bpy.context.scene


# Store the original timeline position so it can be restored later.

original_frame = scene.frame_current + scene.frame_subframe


# Use the currently active object as the source armature.

armature = bpy.context.active_object


if armature is None or armature.type != 'ARMATURE':

    raise ValueError("Please select an armature object.")


bpy.context.view_layer.objects.active = armature

armature.select_set(True)


# Switch to Object Mode before reading transforms.

if armature.mode != 'OBJECT':

    bpy.ops.object.mode_set(mode='OBJECT')



# ============================================================

# Validate Root Bone

# ============================================================


root_pose_bone = armature.pose.bones.get(ROOT_BONE_NAME)


if root_pose_bone is None:

    raise ValueError(

        f"Root bone '{ROOT_BONE_NAME}' was not found."

    )


root_data_bone = armature.data.bones.get(ROOT_BONE_NAME)


if root_data_bone is None:

    raise ValueError(

        f"Root data bone '{ROOT_BONE_NAME}' was not found."

    )



# ============================================================

# Store Root Bone Rest Transform

# ============================================================


armature_matrix_world = armature.matrix_world.copy()

root_bone_matrix_rest = root_data_bone.matrix_local.copy()


root_bone_matrix_world_rest = (

    armature_matrix_world

    @ root_bone_matrix_rest

)


(

    root_bone_default_loc,

    root_bone_default_rot,

    root_bone_default_scale

) = root_bone_matrix_world_rest.decompose()


inverse_root_bone_default_rot = (

    root_bone_default_rot.inverted()

)



# ============================================================

# Collect IK Targets

# ============================================================


ik_targets = []


for pose_bone in armature.pose.bones:

    for constraint in pose_bone.constraints:


        if constraint.type != 'IK':

            continue


        target = constraint.target


        if target is None:

            continue


        # Only process external IK target objects parented

        # to the selected armature.

        if target.parent != armature:

            continue


        # Prevent duplicate targets from being added.

        if target not in ik_targets:

            ik_targets.append(target)



# ============================================================

# Store Original IK Target World Positions

# ============================================================


ik_target_keyframes = {}


for target in ik_targets:

    target_fcurves = get_action_fcurves(target)

    target_frames = collect_keyframes(target_fcurves)


    ik_target_keyframes[target.name] = {}


    for frame in target_frames:

        set_scene_frame(scene, frame)


        ik_target_keyframes[target.name][frame] = (

            target.matrix_world.translation.copy()

        )



# ============================================================

# Get Armature Action

# ============================================================


animation_data = armature.animation_data


if animation_data is None:

    raise ValueError("Animation data was not found.")


action = animation_data.action


if action is None:

    raise ValueError("No Action is assigned to the armature.")


armature_fcurves = get_action_fcurves(armature)


if not armature_fcurves:

    raise ValueError(

        "No F-Curves were found in the armature Action."

    )



# ============================================================

# Collect Root Bone Keyframes

# ============================================================


root_data_path_prefix = (

    f'pose.bones["{ROOT_BONE_NAME}"]'

)


root_keyframes = collect_keyframes(

    armature_fcurves,

    root_data_path_prefix

)


if not root_keyframes:

    raise ValueError(

        f"No animation keys were found for "

        f"root bone '{ROOT_BONE_NAME}'."

    )


# Optionally bake every integer frame between

# the first and last root bone keyframe.

if BAKE_EVERY_FRAME:

    first_frame = math.floor(min(root_keyframes))

    last_frame = math.ceil(max(root_keyframes))


    sample_frames = [

        float(frame)

        for frame in range(first_frame, last_frame + 1)

    ]


else:

    sample_frames = root_keyframes



# ============================================================

# Sample Root Bone Transforms

#

# At this stage, transforms are only recorded.

# No keys are written to the armature object yet.

#

# This prevents newly inserted armature object keyframes

# from affecting transform evaluation on later frames.

# ============================================================


transform_data = {}


for frame in sample_frames:

    set_scene_frame(scene, frame)


    # PoseBone.matrix is expressed in armature object space.

    root_bone_matrix = root_pose_bone.matrix.copy()


    # Convert the root bone transform to world space.

    global_matrix = (

        armature.matrix_world

        @ root_bone_matrix

    )


    global_loc, global_rot, global_scale = (

        global_matrix.decompose()

    )


    transform_data[frame] = {

        "location": global_loc.copy(),

        "rotation": global_rot.copy(),

        "scale": global_scale.copy(),

    }



# ============================================================

# Bake the Root Bone Transform to the Armature Object

# ============================================================


bpy.ops.object.mode_set(mode='OBJECT')


# Quaternion rotation avoids Euler angle discontinuities

# during the transfer.

armature.rotation_mode = 'QUATERNION'


translation_matrix_to_default = Matrix.Translation(

    -root_bone_default_loc

)


for frame in sample_frames:

    data = transform_data[frame]


    loc = data["location"]

    rot = data["rotation"]

    scale = data["scale"]


    # Remove the root bone's rest rotation.

    corrected_rot = (

        rot

        @ inverse_root_bone_default_rot

    )


    translation_matrix_current = Matrix.Translation(loc)

    rotation_matrix = corrected_rot.to_matrix().to_4x4()


    # Apply the same transform order as the original script:

    #   1. Translate relative to the root bone's rest location.

    #   2. Apply the corrected root bone rotation.

    #   3. Move to the current root bone location.

    final_matrix = (

        translation_matrix_current

        @ rotation_matrix

        @ translation_matrix_to_default

    )


    final_loc, final_rot, _ = final_matrix.decompose()


    armature.location = final_loc

    armature.rotation_quaternion = final_rot

    armature.scale = scale


    armature.keyframe_insert(

        data_path="location",

        frame=frame

    )


    armature.keyframe_insert(

        data_path="rotation_quaternion",

        frame=frame

    )


    armature.keyframe_insert(

        data_path="scale",

        frame=frame

    )



# ============================================================

# Preserve IK Target World Positions

# ============================================================


for target in ik_targets:

    saved_frames = ik_target_keyframes.get(target.name, {})


    for frame, initial_world_position in saved_frames.items():

        set_scene_frame(scene, frame)


        # Convert the stored world-space position back into

        # the target's armature-relative local space using

        # the armature transform at the current frame.

        local_position = (

            armature.matrix_world.inverted()

            @ initial_world_position

        )


        target.location = local_position


        target.keyframe_insert(

            data_path="location",

            frame=frame

        )



# ============================================================

# Delete Root Bone

# ============================================================


if DELETE_ROOT_BONE:

    bpy.context.view_layer.objects.active = armature

    armature.select_set(True)


    bpy.ops.object.mode_set(mode='EDIT')


    edit_root_bone = armature.data.edit_bones.get(

        ROOT_BONE_NAME

    )


    if edit_root_bone is not None:

        armature.data.edit_bones.remove(edit_root_bone)


    bpy.ops.object.mode_set(mode='OBJECT')



# ============================================================

# Restore Original Timeline Position

# ============================================================


set_scene_frame(scene, original_frame)


print(

    f"Finished. Root bone animation has been transferred "

    f"to the armature object '{armature.name}'."

)


2026年7月19日日曜日

Privacy Policy for Living Diorama

Privacy Policy for Living Diorama

Last updated: 19 July 2026

Living Diorama respects your privacy.

Data Collection

Living Diorama does not collect, store, transmit or share any personal information or usage data.

The app does not collect information such as:

  • Names or contact details

  • Location data

  • Device identifiers

  • Usage or interaction data

  • Photos, videos or audio

  • Health or fitness data

  • Purchase information

Interactions with animals, food and other elements within the app are not recorded or transmitted to the developer.

Analytics, Advertising and Tracking

Living Diorama does not use third-party analytics services, advertising networks or tracking technologies.

The app does not track users across apps or websites and does not display personalised advertising.

Third-Party Data Sharing

Living Diorama does not share user data with third parties because the app does not collect user data.

Data Storage and Deletion

Living Diorama does not store personal information on external servers.

As no personal information is collected or retained by the developer, there is no personal data to access, export or delete.

Children’s Privacy

Living Diorama does not knowingly collect personal information from children or any other users.

Changes to This Privacy Policy

This Privacy Policy may be updated if the app’s features or data practices change. Any changes will be published on this page, together with an updated revision date.


2026年7月8日水曜日

Swipe to Collapse - A Quantum Wave Game

 Overview

Swipe to Collapse is a single-player iPhone game and interactive quantum wave simulation.

This app displays a real-time simulation of the Schrödinger equation using compute shaders.

A quantum wave function lives on the grid. Its colour is the phase and its brightness is how likely the particle is to be there (|ψ|²). You play by observing it.

App purpose and target audience

The app lets users play with a quantum wave function. The color represents phase, and the brightness represents probability density, |ψ|². Users interact with the wave by dragging across the field to observe a selected region. When the user releases, the wave function collapses probabilistically according to the Born rule.

The app is designed for users who enjoy physics-inspired games, experimental arcade games, and interactive science visualizations. Its value is to turn abstract quantum concepts such as observation, probability density, phase, wave function collapse, and position/momentum representations into an interactive visual experience.

The app is intended for entertainment and educational exploration. It is not a professional scientific, medical, financial, or regulated-industry tool.

Observe

Drag across the field to outline a region, then let go to measure it. The wave collapses by the Born rule — the particle is either found inside your region (it snaps bright there) or not (that area goes dark). Pick a stage and try it freely before starting a game.

Game

Tap Start for a 30-second round. Green particles roam the field and score continuously — the brighter the wave |ψ| where a particle sits, the faster it scores. Observe (drag) to collapse the wave and pile it onto the green particles. Red particles (stage 2+) drain your score the same way, so keep the wave dark around them. Best 3 scores per stage are saved. Tap × to quit.

Z/pZ Lab — position & momentum together

An experimental mode on the finite set Z/pZ, where position and momentum are both finite and the Fourier transform links them. Two strips show \psi(x) and \hat{\psi}(k) at once — drag either one to observe in that basis. The carpet below charts the wave over time; watch the fractal revivals. Switch p, potential, kinetic term, initial state and more.