Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ShaderMaterial: How do you create a JS object based on an interface with no class implementation? #33

Open
limefrogyank opened this issue Jan 26, 2021 · 6 comments

Comments

@limefrogyank
Copy link

I tried adding ShaderMaterial to the generator project. However, one of the parameters for the constructor takes an IShaderMaterialOptions. That has no constructor in the Babylon library, it's just an interface. I have no idea how to use that via the generated classes... as far as I can tell, you need a typescript class implementing the interface.

@limefrogyank
Copy link
Author

What I ended up doing is make a copy of the generated class for ShaderMaterial, then remove it from the generator, then modify the copied class in my own project to accept an object rather than the interface. The property accessors for options were changed to be similar to those for shaderPath.

I'm not sure if this will work, but it's not throwing any errors anymore.

@limefrogyank
Copy link
Author

Ah, it works!

For those interested, I urge you to add "DebugLayer" to the generator classes and add this to any scene:

var debugLayer = new DebugLayer(scene);
            debugLayer.show();

It's nice to verify that the shaders have been loaded (even if they're not working as intended)

@canhorn
Copy link
Owner

canhorn commented Jan 28, 2021

Hello @limefrogyank,

Sorry for not getting back to you sooner on this issue!
The generator should create an <interface-name>CachedEntity that implements the interface.
This generated CachedEntity does JsonConverter attributing, a plain object will bypass the caching layer, but in this case is probably not much of an issue.

Here is an example of a generated interface: IAudioEngine.cs

If you have any other issues or questions that would be appreciated!

And thanks for showing interest in this project!

@badcommandorfilename
Copy link
Contributor

badcommandorfilename commented Oct 22, 2021

Hi @canhorn

How do you create a new instance of an interface-nameCachedEntity? If I look at

it generates two constructors:

        public IAudioEngineCachedEntity() : base() { }

        public IAudioEngineCachedEntity(
            ICachedEntity entity
        ) : base(entity)
        {
        }

But neither of these actually calls EventHorizonBlazorInterop.New (e.g. Engine.cs)

and therefore __guid is always null.

When I try to set a property on a CachedEntity using EventHorizonBlazorInterop.Set it throws:

"TypeError: Cannot set properties of undefined ... at Object.set (http://localhost:5000/_content/EventHorizon.Blazor.Interop/interop-bridge.js:351:56)

@canhorn
Copy link
Owner

canhorn commented Oct 22, 2021

@badcommandorfilename
I am still working on an pattern for the interface scenario, since these are interfaces they do not have constructors or concert implementation in the libraries. These are usually assumed to be json literals.
But below I have a some work in progress C# and JavaScript, that creates an empty json object. And a C# method that can be used to correlate the JS and C# interface to the Cached Entity.

(I have not tested this fully)

function createEmptyObject() {
    return {};
}
public static IAudioEnginCachedEntity CreateNew() 
{
    return EventHorizonBlazorInterop.FuncClass(
        entity => new IAudioEnginCachedEntity(entity),
        new string[] { "createEmptyObject" }
    );
}

This will run the object through the caching layers giving it a GUID that will allow for it to be resolved, fixing the type error from the bridge.

I will see if I can get something into the generator or supporting library that will bake this into the implementations for the interface in C#.

@badcommandorfilename
Copy link
Contributor

badcommandorfilename commented Oct 22, 2021

Thanks for confirming @canhorn !

I came up with a similar solution by shimming in:

            var entity = EventHorizonBlazorInterop.New(new string[] { "Object" }, null);
            ___guid = entity.___guid;

Into the parameterless constructors where needed.

If adding that to GenerateInteropClassStatement.cs seems like an acceptable solution I can make a PR, but if you've already got a fix in mind this is fine for me as a workaround.

I actually even tried just adding it to:

    public CachedEntityObject()
    {
        _invokableReference = DotNetObjectReference.Create(
            this
        );
        var entity = EventHorizonBlazorInterop.New(new string[] { "Object" }, null);
        ___guid = entity.___guid;
    }

And so far that hasn't broken anything (although it is probably allocating too many excess entity objects) =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants