2

Currently I am working with Angular2 version 2.1.2 with a Unity visualizer, built with Unity 5.5.

What I need to be able to do is communicate from Unity to Angular2.
I was using code similar to below

public void GetBillOfMaterials(string callbackFn)
    {
        var result = LightSystem.BillOfMaterials.Aggregate("", (current, material) => current + (material + Environment.NewLine));

        Application.ExternalCall(callbackFn, result);
    }

Where the above function would be called in Angular2 like below

public GetBillOfMaterial() 
{
  SendMessage("Manager", "GetBillOfMaterials", "alert");
}

The problem is that when I try any angular2 function inside of the "callbackFn" it won't find my function.

The function I am trying to call is inside of a service that looks like this:

import { Injectable } from '@angular/core';
import { FinishService } from "./sysWideComps/finish/finish.service";
import { ColorService } from "./sysWideComps/colorTemp/color.service";
import { CircuitService } from "./filters/tabs/circuit/circuit-service";
import { StandoffService } from "./filters/tabs/standoff/standoff-tab.service";
@Injectable()
export class UnityService {
  private isFirstCall: boolean = true;
  constructor(private colorService: ColorService, private finishService:FinishService, private circuitService: CircuitService, private standoffService: StandoffService) { }

public ChangeFinish(finishType: string) {
  console.log(`This is the finish type ${finishType}`);
  this.sendMsgParam("ChangeFinish", finishType);
}

public ChangeColorTemp(colorTemp: number) {
  this.sendMsgParam("ChangeColorTemperature", colorTemp);
}
public ChangeCircuit(circuitType: string) {
  this.sendMsgParam("ChangeCircuit", circuitType);
}

public CreateModel(params: string) {
if (this.isFirstCall) {
  this.ChangeCircuit(this.circuitService.getCircuit());
  this.ChangeFinish(this.finishService.getFinish().FinishName.replace(" ", ""));
  this.ChangeStandoffLength(this.standoffService.getStandoffLength());
  //Dropdown goes here
  let tempCTemp = this.colorService.getColorTemp().Temperature.replace("k", "");
  let tempNum: number =+ tempCTemp;
  this.ChangeColorTemp(tempNum);
  this.isFirstCall = false;
}
  this.sendMsgParam("CreateModel", params);
}
public Delete() {
  this.sendMsg("Delete");
}

public ResetView() {
  this.sendMsg("ResetCamera");
}

public RotateObject() {
  this.sendMsg("RotateCurrentObject");
}

public Unselect() {
  this.sendMsg("Unselect");
}

ChangeStandoffLength(input: number) {
  this.sendMsgParam("ChangeSystemDropdownLength", input.toString());
}

public AddStandoff(params: string) {
  let data: string = params;
  this.sendMsgParam("AddStandoffs", data);
}

public GetBillOfMaterial() {
  SendMessage("Manager", "GetBillOfMaterials", "alert");
}

public testFunction(input: string) {
  alert(input);
}

sendMsgParam(functionName: string, params: any) {
  SendMessage("Manager", functionName, params);
}

sendMsg(functionName: string) {
  SendMessage("Manager", functionName);
}
}

I basically need to be able to call "TestFunction" inside of the above service from Unity using Application.ExternalCall() or whatever function would work.
Let me know if there is any further clarification I can do.

Thanks!

gman
  • 100,619
  • 31
  • 269
  • 393
NewDeveloper
  • 301
  • 1
  • 9
  • 1
    `testFunction` is inside an Angular module, so as a guess it would be something like `Application.ExternalCall("UnityService.testFunction","Hello angular");`. – Luke Briggs Feb 20 '17 at 19:10
  • Have you tried using `Application.ExternalCall`? What did or didn't work with that? – rutter Feb 20 '17 at 19:12
  • I have tried Application.ExternalCall("testFunction", "hello") and that didn't work but I'll try the scoping to see if that fixes it. Edit: I've tried scoping to "UnityService.testFunction" and that didn't work – NewDeveloper Feb 20 '17 at 19:17
  • In response to the above comment I got a "UnityService" not defined javascript error. There has to be a way to tell unity where the function is and what they have to find. – NewDeveloper Feb 20 '17 at 19:24
  • 1
    @NewDeveloper It depends what your angular module is available as - that was just a guess based on your export line. Maybe try thinking of it this way: what do you need to put in your JS console just on the webpage to make testFunction run? => Put that in ExternalCall. – Luke Briggs Feb 20 '17 at 19:31
  • @LukeBriggs it seems like this might be a solution to what you're talking about, I'm just not sure how to wire it? http://stackoverflow.com/questions/35296704/angular2-how-to-call-component-function-from-outside-the-app – NewDeveloper Feb 20 '17 at 19:39
  • 1
    @NewDeveloper Yep; you need to expose testFunction globally (so you can call it from "anywhere", such as via the JS console or from Unity). Angular modules are private by design (not available globally) so during the setup of your module (in an init function) you have to catch it as a global variable. Because of that private design, angular makes a bunch of assumptions (which are broken by calling it globally) so you must then also manually call the apply method to make sure any changes on your angular module are up to date. – Luke Briggs Feb 20 '17 at 19:59
  • 1
    I'm not much of a fan of angular but hopefully that should help describe what those answers are doing so you can apply it as needed to your module :) – Luke Briggs Feb 20 '17 at 20:01
  • 1
    Thanks a bunch for your advice. I posted the solution that got working thanks to your help! That was a huge hurdle to overcome haha – NewDeveloper Feb 20 '17 at 20:02

1 Answers1

2

I've actually solved the question for anyone who is interested in the solution.

Following the example from this SO question: Angular2 - how to call component function from outside the app

I've updated the service function of "GetBillOfMaterial" to look as below:

constructor(
 private colorService: ColorService
,private finishService:FinishService  
,private circuitService: CircuitService
,private standoffService: StandoffService
,private ngZone:NgZone) { }

public GetBillOfMaterial{
  if(!this.isConfigured) {
    this.isConfigured = true;
    window.my = window.my || {};
    window.my.namespace = window.my.namespace || {};
    window.my.namespace.publicFunc = this.PubFunc.bind(this);
  }
  SendMessage("Manager", "GetBillOfMaterials", "window.my.namespace.publicFunc");
}

public PubFunc(input: string) {
  this.ngZone.run(() => this.testFunction(input));
}

public testFunction(input: string) {
  alert(input);
}

The above solution will allow you to call ANY angular2 function from module/service from unity while still using the "Application.ExternalCall()" method.

Community
  • 1
  • 1
NewDeveloper
  • 301
  • 1
  • 9