Library globals

Source modules . canvas_efis . display-unit.nas

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
#------------------------------------------
# display-unit.nas - Canvas EFIS framework
# author:       jsb
# created:      12/2017
#------------------------------------------


# Class DisplayUnit (DU) - handles a named display 3D object in the cockpit
#  * creates a canvas that is placed on the 3D object once
#  * creates an image element on canvas to show source input
#  * handles power on/off by (un-)hiding canvas root group

var DisplayUnit =
{
    #-- static members
    _instances: [],
    bgcolor: [0.01, 0.01, 0.01, 1],
    
    # call del() on all instances
    unload: func() {
        foreach (var instance; DisplayUnit._instances) {
            instance.del();
        }
        DisplayUnit._instances = [];
    },
    
    del: func() {
        if (me.window != nil) {
            me.window.del();
            me.window = nil;
        }
        if (me.placement != nil) { 
            me.placement.remove();
            me.placement = nil;
        }
        if (me.du_canvas != nil) {
            me.du_canvas.del();
            me.du_canvas = nil;
        }
    },

    # name: string, used in canvas window title and on DU test canvas
    # canvas_settings: hash
    # screen_obj: string, name of 3D object for canvas placement
    # parent_obj: string, optional parent 3D object for placement
    new: func(name, canvas_settings, screen_obj, parent_obj = nil) {
        var obj = {
            parents: [me],
            _id: size(DisplayUnit._instances),
            canvas_settings: canvas_settings,
            placement_node: screen_obj,
            placement_parent: parent_obj,
            placement: nil,
            du_canvas: nil,
            root: nil,
            window: nil,
            name: name,
            img: nil,     # canvas image element, shall use other canvas as source
            powerN: nil,
        };
        append(DisplayUnit._instances, obj);
        return obj._init();
    },

    _init: func() {
        me.canvas_settings["name"] = "DisplayUnit " ~ size(DisplayUnit._instances);
        me.du_canvas = canvas.new(me.canvas_settings).setColorBackground(DisplayUnit.bgcolor);
        me.root = me.du_canvas.createGroup();
        #-- optional for development: create test image
        me._test_img();
        
        me.img = me.root.createChild("image", "DisplayUnit "~me.name);
        var place = { parent: me.placement_parent, node: me.placement_node };
        me.placement = me.du_canvas.addPlacement(place);
        #var status = me.placement.getNode("status-msg",1);
        return me;
    },

    _test_img: func() {
        var x = num(me.canvas_settings.view[0])/2 or 20;
        var y = num(me.canvas_settings.view[1])/2 or 20;
        me.root.createChild("text").setText("'"~me.name~"'\n no source ")
            .setColor(1,1,1,1)
            .setAlignment("center-center")
            .setTranslation(x, y);

        var L = int(y/16);
        var black = [0, 0, 0, 1];
        var blue = [0, 0.2, 0.9, 1];
        var yellow = [1, 1, 0, 1];
        var grey = [0.7, 0.7, 0.7, 1];
        var tl = me.root.createChild("group", "top-left");
        var r = tl.createChild("path").rect(L, L, 8*L, 8*L)
            .setColorFill(grey);
        for (var i=1; i <= 3; i += 1) {
            for (var j=1; j <= 8; j += 1) {
                var r = tl.createChild("path").rect(i*L, j*L, L, L);
                # .setStrokeLineWidth(0);
                math.mod(i+j, 2) ?  r.setColorFill(black) : r.setColorFill(yellow);
            }
        }
        var F = tl.createChild("path")
            .setColorFill(blue)
            .setColor(blue)
            .setStrokeLineJoin("round")
            .setStrokeLineWidth(3);
        F.moveTo(5*L, 2*L)
            .line(3.5*L, 0).line(0, L).line(-2.5*L, 0)
            .line(0, L)
            .line(2*L, 0).line(0, L).line(-2*L, 0)
            .line(0, 3*L)
            .line(-L, 0)
            .close();
        x = me.canvas_settings.view[0]-L;
        y = me.canvas_settings.view[1]-L;
        me.root.createChild("path", "square-top-left").rect(0, 0, L, L)
            .setColorFill(1,1,1,1);
        me.root.createChild("path", "square-top-right").rect(x, 0, L, L)
            .setColorFill(1,1,1,1);
        me.root.createChild("path", "square-btm-left").rect(0, y, L, L)
            .setColorFill(1,1,1,1);
        me.root.createChild("path", "square-btm-right").rect(x, y, L, L)
            .setColorFill(1,1,1,1);
    },
    
    # set a new source path for canvas image element
    setSource: func(path) {
        #print("DisplayUnit.setSource for "~me.du_canvas.getPath()~" ("~me.name~") to "~path);
        if (path == "")
            me.img.hide();
        else {
            me.img.set("src", path);
            me.img.show();
        }
        return me;
    },

    setPowerSource: func(prop, min) {
        me.powerN = props.getNode(prop,1);
        setlistener(me.powerN, func(n) {
            if ((n.getValue() or 0) >= min) me.root.show();
            else me.root.hide();
        }, 1, 0);
    },
    
    asWindow: func(window_size) {
        me.window = canvas.Window.new(window_size, "dialog");
        me.window.set('title', "EFIS " ~ me.name)
            .set("resize", 1)
            .setCanvas(me.du_canvas);
        me.window.move(me._id*200, me._id*40);
        if (typeof(me.window.lockAspectRatio) == "func")
            me.window.lockAspectRatio(1);
        me.window.del = func() { call(canvas.Window.del, [], me); }
        return me.window
    },    
};