# Particle Reader Plugins

## Particle Reader Plugin Manager

The `ParticleReaderPluginManager` supports runtime discovery and loading of particle reader plugins. Plugins are shared libraries following the naming convention `cpt_{NAME}.dll` (Windows), `libcpt_{NAME}.so` (Linux), or `libcpt_{NAME}.dylib` (macOS).

    #include "CeeParticleModel/ParticleReaderPluginManager.h"

    auto* mgr = cee::pt::ParticleReaderPluginManager::instance();
    mgr->setPluginFolder("/opt/envision/plugins");
    mgr->loadPlugins();

    // List available reader factories
    for (size_t i = 0; i < mgr->readerFactoryCount(); ++i)
    {
        cee::Str name = mgr->readerName(i);
        // ...
    }

    // Create a reader for a specific file (auto-selects the right plugin)
    cee::pt::ParticleDatasetReader* reader = mgr->createReaderForFile("data/sim.custom");

    // IMPORTANT: destroy via the manager (the plugin owns the memory)
    mgr->destroyReader(0, reader);

Once plugins are loaded, they are also available for automatic format detection when calling `ParticleModel::open(filePath)`.

Call `shutdown()` before application exit to unload plugin libraries cleanly.

## Writing a Particle Reader Plugin

A reader plugin is a shared library that exports a single C entry point:

    #include "CeeParticleModel/ParticleReaderPluginApi.h"

    extern "C" CPT_PLUGIN_EXPORT CPT_PluginExitFunc
    initializeReaderPlugin(const CPT_FrameworkServices* services)
    {
        // Register one or more readers
        CPT_RegisterReaderParams params = {};
        params.pluginApiMajorVer = CPT_API_MAJOR_VER;
        params.pluginApiMinorVer = CPT_API_MINOR_VER;
        params.createReaderFunc  = &myCreateReader;
        params.destroyReaderFunc = &myDestroyReader;
        params.canReadFunc       = &myCanRead;

        services->registerReaderFunc("MyFormat", &params);

        // Optionally set plugin metadata
        services->setPluginInfoFunc("version", "1.0.0");
        services->setPluginInfoFunc("author", "My Company");

        return &myPluginExit;  // Called on shutdown
    }

The `createReaderFunc` must return a new `ParticleDatasetReader` subclass instance. The `canReadFunc` should return `true` if the plugin can handle the given file path (typically by checking the file extension or magic bytes).

See /api/ParticleReaderPluginApi_8h for the complete C API reference.

Conversation saved
HOOPSY BETA

### Hello! I'm HOOPSY

Your multilingual generative AI assistant for documentation. Ask me anything about HOOPS Envision for Desktop in your own language, or choose a sample question below to start a conversation:

What is HOOPS Envision for Desktop?
What are the latest release notes for HOOPS Envision for Desktop?
How do I start evaluating HOOPS Envision for Desktop?
How do I write my first sample application?
How can I get assistance?

HOOPSY may store conversations according to OpenAI's policy. Responses may not always be accurate.

HOOPSY is thinking...