-
Notifications
You must be signed in to change notification settings - Fork 89
Expand file tree
/
Copy pathProcessingContext.java
More file actions
186 lines (153 loc) · 5.56 KB
/
ProcessingContext.java
File metadata and controls
186 lines (153 loc) · 5.56 KB
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package nodebox.node;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* The processing context contains metadata about the processing operation.
* <p/>
* Note: the context is currently empty. Later on, we will add the frame number etc.
*/
public class ProcessingContext {
public static final String FRAME = "FRAME";
public static final String TOP = "TOP";
public static final String LEFT = "LEFT";
public static final String BOTTOM = "BOTTOM";
public static final String RIGHT = "RIGHT";
public static final String WIDTH = "WIDTH";
public static final String HEIGHT = "HEIGHT";
private static ThreadLocal<ProcessingContext> currentContext = new ThreadLocal<ProcessingContext>();
static void setCurrentContext(ProcessingContext context) {
currentContext.set(context);
}
public static ProcessingContext getCurrentContext() {
return currentContext.get();
}
private HashMap<String, Object> valueMap = new HashMap<String, Object>();
private ByteArrayOutputStream outputBytes;
private ByteArrayOutputStream errorBytes;
private PrintStream outputStream;
private PrintStream errorStream;
private Node node;
private enum State {
UPDATING, PROCESSED
}
/**
* A list of parameters that have already been started updating.
* This set is used to detect cycles.
*/
private Map<Parameter, State> updatedParameters = new HashMap<Parameter, State>();
public ProcessingContext() {
put(FRAME, 1f);
putBounds(0f, 0f, 1000f, 1000f);
outputBytes = new ByteArrayOutputStream();
outputStream = new PrintStream(outputBytes);
errorBytes = new ByteArrayOutputStream();
errorStream = new PrintStream(errorBytes);
}
public ProcessingContext(Node node) {
this();
this.node = node;
float frame = 1f;
float canvasX = 0f;
float canvasY = 0f;
float canvasWidth = NodeLibrary.DEFAULT_CANVAS_WIDTH;
float canvasHeight = NodeLibrary.DEFAULT_CANVAS_HEIGHT;
if (node != null) {
frame = node.getLibrary().getFrame();
Node root = node.getLibrary().getRootNode();
canvasX = getParameterValue(root, NodeLibrary.CANVAS_X, 0f);
canvasY = getParameterValue(root, NodeLibrary.CANVAS_Y, 0f);
canvasWidth = getParameterValue(root, NodeLibrary.CANVAS_WIDTH, NodeLibrary.DEFAULT_CANVAS_WIDTH);
canvasHeight = getParameterValue(root, NodeLibrary.CANVAS_HEIGHT, NodeLibrary.DEFAULT_CANVAS_HEIGHT);
}
put(FRAME, frame);
putBounds(canvasX, canvasY, canvasWidth, canvasHeight);
}
private float getParameterValue(Node node, String parameterName, float defaultValue) {
Parameter p = node.getParameter(parameterName);
if (p != null) {
return p.asFloat();
} else {
return defaultValue;
}
}
private void putBounds(float x, float y, float width, float height) {
put(WIDTH, width);
put(HEIGHT, height);
put(TOP, y - height / 2);
put(LEFT, x - width / 2);
put(BOTTOM, y + height / 2);
put(RIGHT, x + width / 2);
}
//// Current node ////
/**
* Get the node that is currently processing.
*
* @return the current node.
*/
public Node getNode() {
return node;
}
void setNode(Node node) {
this.node = node;
}
//// Map operations ////
public void put(String key, Object value) {
valueMap.put(key, value);
}
public Object get(String key) {
return valueMap.get(key);
}
public boolean containsKey(String key) {
return valueMap.containsKey(key);
}
public Set<String> keySet() {
return valueMap.keySet();
}
//// Map shortcuts ////
public float getFrame() {
return (Float) get("FRAME");
}
//// Output/error streams ////
public PrintStream getOutputStream() {
return outputStream;
}
public PrintStream getErrorStream() {
return errorStream;
}
public String getOutput() {
return outputBytes.toString();
}
public String getError() {
return errorBytes.toString();
}
// TODO: These are no longer used. Check and remove.
public void beginUpdating(Parameter parameter) {
State state = updatedParameters.get(parameter);
if (state == null) {
updatedParameters.put(parameter, State.UPDATING);
} else if (state == State.UPDATING) {
throw new AssertionError("You should check beforehand if a parameter was updating.");
} else if (state == State.PROCESSED) {
throw new RuntimeException("Parameter " + parameter + " has already been processed: infinite recursion detected.");
}
}
public void endUpdating(Parameter parameter) {
State state = updatedParameters.get(parameter);
if (state == null) {
throw new AssertionError("You should have called beginUpdating first.");
} else if (state == State.UPDATING) {
updatedParameters.put(parameter, State.PROCESSED);
} else if (state == State.PROCESSED) {
throw new AssertionError("You should only call endUpdating once.");
}
}
public boolean isUpdating(Parameter p) {
return updatedParameters.get(p) == State.UPDATING;
}
public boolean hasProcessed(Parameter p) {
return updatedParameters.get(p) == State.PROCESSED;
}
}