pixeltris / USharp

C# plugin for Unreal Engine 4
MIT License
401 stars 65 forks source link

Missing binding for some methods #74

Closed demonixis closed 5 years ago

demonixis commented 5 years ago

Hello,

I'm trying to convert some C++ code to C#. It's for testing purpose only. I noticed few changes from C++ to C# as well as some missing methods or properties. This is my code, comments indicates the missing property or method.

public override void Initialize(FObjectInitializer initializer)
{
    base.Initialize(initializer);

    VROrigin = initializer.CreateDefaultSubobject<USceneComponent>(this, new FName("VROrigin"));
    //VROrigin.SetupAttachment(RootComponent);
    VROrigin.SetRelativeLocation(new FVector(0.0f, 0.0f, 80.0f), false, out FHitResult sr, false);

    MainCamera = initializer.CreateDefaultSubobject<UCameraComponent>(this, new FName("MainCamera"));
    //MainCamera.SetupAttachment(VROrigin);

    UIWidgetInteraction = initializer.CreateDefaultSubobject<UWidgetInteractionComponent>(this, new FName("UIWidgetInteraction"));
    //MainCamera.SetupAttachment(MainCamera);

    SetupMotionController(initializer, true);
    SetupMotionController(initializer, false);

    ForwardVRMode = ForwardVRMode.Pawn;

    //PrimaryActorTick.CanEverTick = true;
}

private void SetupMotionController(FObjectInitializer initializer, bool left)
{
    var mc = initializer.CreateDefaultSubobject<UMotionControllerComponent>(this, new FName(left ? "LeftHand" : "RightHand"));
    //mc.SetupAttachment(VROrigin);
    //mc.SetTrackingSource(ControllerHand.Right);
    mc.SetTrackingMotionSource(left ? new FName("Left") : new FName("Right"));
    mc.SetRelativeLocation(new FVector(36.0f, left ? -20.0f : 20.0f, -26.0f), false, out FHitResult sr, false);
}

How can we add those missing methods? Maybe I can try to add some of them? If you give me a starting point?

Tanner555 commented 5 years ago

The primary tick part should be written into the wiki. You have to create an instance variable of the PrimaryActorTick property. Here's an example.

var myATick = this.PrimaryActorTick;
myATick.CanEverTick = true;

It's a bit weird. Creating a variable like this actually returns a reference to the primary actor tick property. I forgot why Pixeltris didn't just use the conventional method. Something to do with interrop and memory management issues.

demonixis commented 5 years ago

Ok it's not a big deal ;) However how do you use SetupAttachment?

pixeltris commented 5 years ago

The reason why a local var of PrimaryActorTick is require is that PrimaryActorTick is a property and FTickFunction is a struct, so you can't set CanEverTick directly. There are now function such as this.PrimaryActorTick.SetCanEverTick(true) which should work though.

Is SetupAttachment the same as AttachToComponent? https://github.com/pixeltris/USharp/blob/b984bb26decd31ccd10ce8b849c08f1bf11ba4fb/Templates/TP_Puzzle/Managed/TP_Puzzle.Managed/PuzzleBlockGrid.cs#L37

It looks like SetupAttachment isn't exposed as a UFUNCTION in C++, where as AttachToComponent is. It might be worth manually adding support for SetupAttachment as the logic behind it is a lot simpler.

demonixis commented 5 years ago

SetupAttachment takes one argument (the component) while the other one take many parameters. Not sure to the difference of them. I'll take a look at the source code..

pixeltris commented 5 years ago

AttachToComponent is a lot more verbose in terms of source code. SetupAttachment just sets 2 members. I think it would be worth manually wrapping SetupAttachment. I'll look into doing this soon.

pixeltris commented 5 years ago

As for SetTrackingSource; it's possibly merged into a property called TrackingSource which should have a getter/setter. USharp will currently merge any property which has GetXXX / SetXXX functions into a single property. Or maybe it wasn't generated at all? The functions are marked as deprecated in C++.

demonixis commented 5 years ago

I simulated SetupAttachment using an extension method

public static class UActorComponentExtensions
{
    public static void SetupAttachment(this USceneComponent thisComponent, USceneComponent Parent)
    {
        thisComponent.AttachToComponent(Parent, FName.None, EAttachmentRule.KeepRelative, EAttachmentRule.KeepRelative, EAttachmentRule.KeepRelative, false);
    }
}

It's ok for the rest , thanks.

Tanner555 commented 5 years ago

You can create a PR if you like.

demonixis commented 5 years ago

Why not if it's OK for you. Where do you put this kind of code?

pixeltris commented 5 years ago

I think it would be better to call the native C++ SetupAttachment function as the code path in the AttachToComponent function does seem a little overkill. But to answer where you put that kind of code: https://github.com/pixeltris/USharp/tree/master/Managed/UnrealEngine.Runtime/UnrealEngine.Runtime/Internal/InjectedClasses/Engine these files get copied over when the C# engine wrapper code generator runs.

Tanner555 commented 5 years ago

I don't think it's overkill. You should add it demonixis. Every bit helps. 😄

pixeltris commented 5 years ago

I'm not saying don't add SetupAttachment. I'm saying add SetupAttachment but call the C++ function. Doing so is a little more complicated as a new C++ pinvoke method is needed. But I'll link the solution here for future reference of doing something similar.

demonixis commented 5 years ago

I agree a call to the native method is better

pixeltris commented 5 years ago

https://github.com/pixeltris/USharp/commit/19245458ab5b3568ac352af20fc7e03c41cf6854 so this commit shows adding a new pinvoke method, and calling the method from an InjectedClasses file. You will need to regenerate the C# engine wrapper code for this (which can be done in the console via USharpGen modules / USharpGen compile or delete your modules folder at /USharp/Binaries/Managed/Modules/ and then reopen your unreal project file (it should prompt to regenerate / compile the wrapper code).

demonixis commented 5 years ago

Thank you! That way I'll be able to add native methods if they're missing.