nglviewer / ngl

WebGL protein viewer
http://nglviewer.org/ngl/
MIT License
664 stars 169 forks source link

Allow more export of components #1028

Closed FLIGHTLAMA closed 6 months ago

FLIGHTLAMA commented 6 months ago

I'm currently working on a React project using the NGL Viewer and I've noticed that the export options are somewhat limited. The current export options work well, but having additional options would greatly enhance the flexibility and functionality of the NGL Viewer in projects.

I understand that this might be a significant addition to the project, but I believe it would be a valuable enhancement that could benefit many users.

I have created a sample PR for some basic components that I think might be useful to have direct access to. This is only an example of course and should start a discussion.

https://github.com/nglviewer/ngl/pull/1026

ppillot commented 6 months ago

Thanks for your contribution. I think it's fine to export things we need from the library given that NGL is quite monolithic and not amenable to tree shaking.

Regarding the parser, I've used in past projects the ParserRegistry object that is exported from NGL to get some parsers in my code and even redefine some methods via their prototype.

const pdbParser = ParserRegistry.get('pdb')
pdbParser.prototype._beforeParse = // ... overriding code goes there

What is the use case for exporting the NetworkStreamer? Is it to override some of its methods?

FLIGHTLAMA commented 6 months ago

Thanks for the answer, I didn't know about the possibility to use the ParserRegistry, but it should solve the problem,

Yes indeed, it is to overwrite a method (see example). The main reason for this is that the state and api queries are conveniently managed via React/Redux. This makes it very easy to integrate the viewer into the normal flow and let the react/redux handel all the data/api calls updates caching etc...

// Use Structure data from the state
   const compound3DStructure = useAppSelector(getStructure3D);

  const createNetworkStreamer = (result: string) => {
    const networkInputStream = new NetworkStreamer("custom", {
      compressed: false,
      binary: false,
      json: false,
      xml: false,
    });
    networkInputStream._read = () => {
      return new Promise((resolve) => {
        return resolve(result);
      });
    };
    return networkInputStream;
  };

  // State result can be directly used here
  const targetInputStream = createNetworkStreamer(compound3DStructure.structure);
ppillot commented 6 months ago

If I understand this correctly, the NetworkSreamer is redefined to bypass the network transfer and directly use a known file content instead.

What can be done instead is to pass a Blob containing the file content as the first argument of the stage.loadFile method. Something like

const compound3DStructure = useAppSelector(getStructure3D);
const blob = new Blob([compound3DStructure.structure], {type: 'text/plain'});
stage.loadFile(blob, {ext: 'pdb'}).then((component: StructureComponent) => {
    // rest of the code goes there
}) 
FLIGHTLAMA commented 6 months ago

Thank you I think we can close this. I just described a simple case to show why I would like to override certain methods, of course there are some ways to have a workaround but that is not directly what I had in mind.

I will do the customization locally, I think that is more effective. Thanks again for your time