zoukankan      html  css  js  c++  java
  • JSBinding + SharpKit / 原理篇:Delegate

     

    以 NGUI 的 UIEventListener 为例:

    有一个类:

     1 using SharpKit.JavaScript;
     2 using UnityEngine;
     3 using System.Collections;
     4 
     5 [JsType(JsMode.Clr,"../StreamingAssets/JavaScript/SharpKitGenerated/z_temp/test0610.javascript")]
     6 public class test0610 : MonoBehaviour {
     7     public UIButton btn;
     8 
     9     void Start () 
    10     {
    11         // 在此注册回调
    12         UIEventListener.Get(btn.gameObject).onClick = this.OnClick; // (*)
    13     }
    14 
    15     void OnClick(GameObject go)
    16     {
    17         Debug.Log("onclick ");
    18     }
    19 }

    这个类有一个 public UIButton btn;  变量,可以在 Inspector 里赋值。我们用这个类来响应 btn 的点击事件。重点就是第12行。

     

    生成的JS如下:

     1 if (typeof(JsTypes) == "undefined")
     2     var JsTypes = [];
     3 var test0610 = {
     4     fullname: "test0610",
     5     baseTypeName: "UnityEngine.MonoBehaviour",
     6     assemblyName: "SharpKitProj",
     7     Kind: "Class",
     8     definition: {
     9         ctor: function (){
    10             this.btn = null;
    11             UnityEngine.MonoBehaviour.ctor.call(this);
    12         },
    13         Start: function (){
    14             UIEventListener.Get(this.btn.get_gameObject()).onClick = $CreateDelegate(this, this.OnClick); // (*)
    15         },
    16         Update: function (){
    17         },
    18         OnClick: function (go){
    19             UnityEngine.Debug.Log$$Object("onclick ");
    20         }
    21     }
    22 };
    23 JsTypes.push(test0610);

     

    看 JS代码 第14行,将 onClick 赋值为 $CreateDelegate 的返回值

    $CreateDelegate 的作用是返回一个函数,具体可以看 jsclr.javascript 文件里这个函数的定义。这里不讨论这个函数的实现细节,只要知道他返回一个函数就可以了。这个函数传到 C# 后就变成一个ID。

     

    当然,如果要让这段JS可以正常执行,当然要将 UIEventListener 配置到 JSBindingSettings.classes 数组让他导出,来看一下 onClick 这个字段的C#代码:

     1 public static UIEventListener.VoidDelegate UIEventListener_onClick_GetDelegate_member2_arg0(CSRepresentedObject objFunction)
     2 {
     3     if (objFunction == null || objFunction.jsObjID == 0)
     4     {
     5         return null;
     6     }
     7     UIEventListener.VoidDelegate action = (go) => 
     8     {
     9         JSMgr.vCall.CallJSFunctionValue(0, objFunction.jsObjID, go);
    10     };
    11     return action;
    12 }
    13 static void UIEventListener_onClick(JSVCall vc)
    14 {
    15     if (vc.bGet) {
    16         UIEventListener _this = (UIEventListener)vc.csObj;
    17         var result = _this.onClick;
    18         JSMgr.vCall.datax.setObject((int)JSApi.SetType.Rval, result);
    19     }
    20     else {
    21         UIEventListener _this = (UIEventListener)vc.csObj;
    22         _this.onClick = JSDataExchangeMgr.GetJSArg<UIEventListener.VoidDelegate>(()=>{
    23     if (JSApi.isFunctionS((int)JSApi.GetType.Arg))
    24         return UIEventListener_onClick_GetDelegate_member2_arg0(JSApi.getFunctionS((int)JSApi.GetType.Arg));
    25     else
    26         return (UIEventListener.VoidDelegate)vc.datax.getObject((int)JSApi.GetType.Arg);
    27 })
    28 ;
    29     }
    30 }

    第22行在赋值 onClick 字段。因为 onClick 是 Delegate,所以赋值也要给他一个 Delegate,这个 Delegate 是由函数 UIEventListener_onClick_GetDelegate_member2_arg0 返回的(第1行)。

    第24行首先调用 JSApi.getFunctionS(..) 获取 JS 函数 ID。CSRepresentedObject 只是对 JS 对象的一个封装而已。UIEventListener_onClick_GetDelegate_member2_arg0 拿到这个函数ID后,

    构造了一个 UIEventListener.VoidDelegate 类型的 Delegate ,最终赋值给了 UIEventListener.onClick。

     

    以上是比较简单的情况:将 JS 函数存储在 C#。

    再来看一种情况,将 C# 函数存储在 JS。

    // C#

    1 TweenEasingCallback func = TweenEasingFunctions.GetFunction(this.EaseType );
    2 
    3 transform.TweenPosition()
    4 .SetEndValue( transform.position + ( Vector3.right * 9f ) )
    5 .SetDelay( 0.5f, false )
    6 .SetDuration( 1.33f )
    7 .SetEasing( func )
    8 .SetLoopType( TweenLoopType.Loop )
    9 .Play();

    // JS代码

    1 var func = DaikonForge.Tween.TweenEasingFunctions.GetFunction(this.EaseType); // get a delegate from C# (1)
    2 TweenTransformExtensions.TweenPosition$$Transform(this.get_transform())
    3     .SetEndValue(UnityEngine.Vector3.op_Addition(this.get_transform().get_position(), (UnityEngine.Vector3.op_Multiply$$Vector3$$Single(UnityEngine.Vector3.get_right(), 9))))
    4     .SetDelay$$Single$$Boolean(0.5, false)
    5     .SetDuration(1.33)
    6     .SetEasing(func) // give back to C# (2)
    7     .SetLoopType(1)
    8     .Play();

     

    这种情况下也是要事先将 TweenEasingFunctions 配置到 JSBindingSettings.classes,让他导出,JS才可以使用。

    // TweenEasingFunctions.GetFunction 的绑定代码:

     1 static bool TweenEasingFunctions_GetFunction__EasingType(JSVCall vc, int argc)
     2 {
     3     int len = argc;
     4     if (len == 1) 
     5     {
     6         DaikonForge.Tween.EasingType arg0 = (DaikonForge.Tween.EasingType)JSApi.getEnum((int)JSApi.GetType.Arg);
     7         JSMgr.vCall.datax.setObject((int)JSApi.SetType.Rval, DaikonForge.Tween.TweenEasingFunctions.GetFunction(arg0));
     8     }
     9 
    10     return true;
    11 }

    可以看到,当 JS 从 C# 获得一个 delegate 时,会调用 JSDataExchange.setObject 函数。

    这里不贴出 setObject 的具体代码,请查看源代码。

    在 setObject 函数中,会判断,如果这个对象是个 delegate,那么就创建一个 JSRepresentedObject 对象返回给 JS,同时保存这2者的对应关系。

    JSRepresentedObject 的定义在 StreamingAssets/JavaScript/SharpKit/myclrhandler.javascript 最前面。

    那么,JS拿到这个对象后,是无法使用的。因为他是C#这边的函数。他只能把这个东西再还给C#。请看上面JS代码标记 (2) 那一句。当他返回给C#时,C#可以根据之前存储的对应关系找到 Delegate。

     

     

     

    返回首页:

    Unity代码热更新方案 JSBinding + SharpKit 首页

  • 相关阅读:
    我为什么支持从中学课本中撤下鲁迅的文章?
    【老孙随笔】技术不行别人就不服你,怎么办?
    【老孙随笔】求职,不要无的放矢
    读者来信(1)——项目经理,不要迷信制度!
    欣闻鲁迅文章下架
    知道力读书会,欢迎大家参加
    【老孙随笔】是谁杀死了QQ?
    技术,项目经理的命?——项目经理的误区(3)
    可以不封神,但是不能不修炼——亚特兰蒂斯之神特斯拉的启示
    分布式开发2WCF如何正确调用LINQTO SQL
  • 原文地址:https://www.cnblogs.com/answerwinner/p/4568226.html
Copyright © 2011-2022 走看看