Skip to content

Reloading during development

I strongly recommend adding a development reload path early when building an OpenAxis integration. Restarting a large CAD or 3D application for each camera adapter change slows down the native testing that integration work needs. A reload command lets you keep a useful scene open while testing changes to coordinate conversion, picking and viewport behavior.

These are optional development recommendations. Choose a reload mechanism that fits your application’s plugin system; OpenAxis supplies connection and session lifecycle APIs, while your integration owns code replacement and native resources.

Use the application’s existing script or plugin reload facility where available. Otherwise, consider a small stable entry point that stops the current implementation and loads a replacement. A menu action or developer command is a good first step: it gives you control over when a gesture or native operation is interrupted. Add file watching only after this explicit reload path works reliably.

Keep the edit loop short: edit the adapter, build or copy the changed files if needed, reload, then repeat the same navigation action in the same scene. Show the loaded build or source location in development logs so you can confirm that you are testing the intended code. See diagnostics and logging for inspecting navigation behavior.

A reload command coordinates three steps: shut down the current integration, load the edited code, then create and start a fresh integration. Keep the code that coordinates these steps outside the implementation it replaces, so it can report a failed load and let you retry.

Reuse the integration’s normal shutdown path. Stop new work, finish networking and retries, close the navigation session, and release native callbacks, timers and graphics while the host resources needed for cleanup still exist. Follow connection recovery and shutdown for the language-specific API sequence.

Keep the host scheduler available for cleanup that needs its thread. Avoid blocking that thread while waiting for work that itself needs the thread to finish. If a worker fails to stop within a timeout, retain its owner and abort reload; retry shutdown or restart the application before replacing code.

Once shutdown succeeds, replace the code and construct a fresh integration that announces current capabilities, tags and focus. Normal server reconnection can reuse an existing client and session. Reloading code also requires replacing the objects and callbacks created by the old implementation.

The host and runtime determine how code can be replaced. Use the approach for your language below, and identify which edits it can pick up without restarting the application.

For an embedded Python host, maintain an explicit list of reloadable modules in dependency order: shared types and helpers, adapters, then the module that creates the integration. Call importlib.reload() on each, then construct a fresh integration. Reloading a package’s __init__.py alone does not reload its submodules.

The Rotatrix Blender integration uses this approach through Blender’s Reload Scripts command; disconnect first so its modal cursor tracker can finish. The FreeCAD integration provides a toolbar action that stops its handler, reloads runtime modules and starts a fresh handler. Its workbench entry points and installed dependencies still have a separate update workflow.

Prefer import camera_adapter and lookup through camera_adapter.CameraAdapter in the coordinator. A from camera_adapter import CameraAdapter binding keeps the old class until that import runs again. Existing instances also retain their old class. If you reload SDK types, reload their consumers too, including the connection manager; mixing old and new enum or class identities can break startup.

Run reload on the host’s permitted thread after stopping workers and unregistering native classes, timers and callbacks. Limit the module list to packages your integration owns. Purging entries from sys.modules neither stops existing objects nor isolates other plugins using those package names.

Use importlib.invalidate_caches() when newly created modules need discovery; it does not update existing objects. Restart for native extension changes unless the extension explicitly supports reinitialization. Refresh vendored SDK files before reloading their modules. See Python’s reload caveats.

Write down the setup command, installed source or build location, reload action, and changes that require a full restart. Source links can make adapter edits immediately available on disk; vendored SDK copies and compiled dependencies still need their own refresh step.

Exercise reload repeatedly, including during navigation, connection retry and pending native callbacks. Confirm that the old worker has stopped, only one connection remains, overlays disappear, and callbacks or timers do not accumulate. Also try a failed build or import and verify that the next successful reload can recover. These checks complement the integration checklist and must include testing inside the actual host application.