1 /**
2     Inochi2D Solo Node
3 
4     Copyright: 
5         Copyright © 2020-2026, Inochi2D Project
6     
7     License:
8         $(LINK2 https://github.com/Inochi2D/inochi2d/blob/main/LICENSE, BSD 2-clause License)
9     
10     Authors:
11         Luna Nielsen
12 */
13 module inochi2d.nodes.visual.solo;
14 import inochi2d.nodes.visual;
15 import inochi2d.nodes;
16 import inochi2d.core.math;
17 import inochi2d.core;
18 import nulib;
19 import numem;
20 
21 /**
22     A node which only allows a single child node to be displayed
23     at a time.
24 */
25 @TypeId("Solo", IN_MAKE_TAG!(4, 1))
26 class Solo : Visual {
27 private:
28 @nogc:
29     uint lastActiveLayer_;
30     uint activeLayer_;
31 
32     void changeLayer(uint value) @nogc nothrow {
33         this.lastActiveLayer_ = clamp(activeLayer_, 0, cast(uint)children.length);
34         this.activeLayer_ = clamp(cast(uint)value, 0, cast(uint)children.length);
35     }
36 
37 protected:
38 
39     /**
40         Called during the early update phase of a new frame.
41         
42         Params:
43             drawList =  The drawlist for the active scene.
44     */
45     override
46     void onPreUpdate(DrawList drawList) {
47 
48         // NOTE:    If we changed the active layer, force the puppet to rescan its visuals
49         //          hirearchy.
50         //          We do this since we want the Solo's hirearchy to blend
51         //          with the outer hirearchy sorting wise.
52         if (lastActiveLayer_ != activeLayer_)
53             puppet.rescanNodes();
54     }
55 
56     /**
57         Requests that the list gather sub-visuals to be rendered, if applicable.
58 
59         Params:
60             visuals =           The list to write to, the list may be resized by the
61                                 implementation.
62             recurseDelegates =  Whether to recurse through delegate visuals.
63             append =            Whether to append to the visuals list.
64     */
65     override
66     void onDelegateFindVisuals(ref weak_vector!Visual visuals, bool recurseDelegates, bool append) {
67         if (children.length > 0) {
68 
69             
70 
71                 .findVisuals(children[activeLayer_], visuals, recurseDelegates, false, append);
72         }
73     }
74 
75     /**
76         Called when the node is to define its properties.
77 
78         Call $(D propList.define) with a quark to do this.
79 
80         Params:
81             propList = The property list to populate.
82     */
83     override
84     void onDefineProperties(ref PropertyStore propList) {
85         super.onDefineProperties(propList);
86         propList.define(PROP_ACTIVE_LAYER, 0);
87     }
88 
89 public:
90 
91     /**
92         Whether the renderer should delegate rendering logic
93         to the visual node.
94     */
95     override @property bool isDelegated() @nogc nothrow pure => true;
96 
97     /**
98         Whether the node can be used as a source of masking operations.
99     */
100     override @property bool isMasking() @nogc nothrow pure => true;
101 
102     /**
103         The active layer that will be rendered.
104     */
105     final @property Node activeLayer() @nogc nothrow pure => children.length > 0 ? children[activeLayer_] : null;
106 
107     /**
108         Constructs a new Solo node.
109 
110         Params:
111             parent = The parent of the solo node.
112     */
113     this(Node parent = null) {
114         super(inNewGUID(), parent);
115     }
116 
117     /**
118         Constructs a new Solo node.
119 
120         Params:
121             guid =      The new GUID of the
122             parent =    The parent of the solo node.
123     */
124     this(GUID guid, Node parent = null) {
125         super(guid, parent);
126     }
127 }
128 
129 mixin Register!(Solo, in_node_registry);
130 // dfmt off
131 
132 
133 
134 
135 //
136 //          QUARKS
137 //
138 
139 mixin RegisterQuarks!();
140 
141 /**
142     Active layer.
143 */
144 @propkey("activeLayer")
145 __gshared immutable(quark) PROP_ACTIVE_LAYER;