Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
mamayaya1
GitHub Repository: mamayaya1/game
Path: blob/main/projects/HexGL/libs/Editor_files/CanvasRenderer.js
4627 views
1
var pgli = pgli || {};
2
pgli.render = pgli.render || {};
3
4
pgli.render.CanvasRenderer = gamecore.Base.extend('CanvasRenderer',
5
{ // static
6
7
SCOPE_KEYWORDS: {
8
'use': 0,
9
'repeat': 1,
10
'comment': 2
11
},
12
SCOPE_XFORMS: {
13
'x': 1,
14
'y': 2,
15
'width': 3,
16
'height': 4,
17
'scale': 0
18
},
19
REPEAT_TYPES: {
20
'none': 'no-repeat',
21
'x': 'repeat-x',
22
'y': 'repeat-y',
23
'xy': 'repeat'
24
}
25
26
},
27
{ // instance
28
29
dom: null,
30
container: null,
31
canvas: null,
32
context: null,
33
width: 1024,
34
height: 768,
35
project: null,
36
xform: [],
37
xseek: -1,
38
scope: [],
39
sseek: -1,
40
resources: {
41
images: []
42
},
43
variables: null,
44
45
/**
46
* Bind a new renderer to given canvas
47
* @param jQuery.DOMElement domElement [description]
48
* @param Integer width [description]
49
* @param Integer height [description]
50
*/
51
init: function(domElement)
52
{
53
this.dom = domElement;
54
this.container = $('#'+this.dom);
55
this.canvas = document.createElement("Canvas");
56
this.container.append(this.canvas);
57
58
this.resize();
59
60
this.variables = new gamecore.Hashtable();
61
},
62
63
draw: function()
64
{
65
clearTrace();
66
67
if(!this.project)
68
{
69
trace("#Render failed: No project loaded");
70
return;
71
}
72
trace("#Starting renderer...");
73
74
this.context.clearRect(0, 0, this.width, this.height);
75
76
var ratio = this.getRenderRatio();
77
var root = this.project.getRootModule();
78
var w = root.width*ratio;
79
var h = root.height*ratio;
80
var x = Math.round((this.width - w)/2);
81
var y = Math.round((this.height - h)/2);
82
83
this.sreset();
84
this.xreset(ratio, x, y, w, h);
85
this.walkModule(root);
86
},
87
88
walkModule: function(module)
89
{
90
if(!module) return;
91
92
trace("#Render: "+module.name);
93
94
if("params" in module) for(p in module.params)
95
this.sset(p, module.params[p]);
96
97
if("vars" in module)
98
this.actionVars(module.vars);
99
100
if("fill" in module)
101
this.actionFill(module.fill);
102
103
if("layers" in module) for(var i=0, len=module.layers.length; i<len; ++i)
104
{
105
var layer = module.layers[i];
106
if("use" in layer)
107
{
108
if("repeat" in layer)
109
{
110
var iterator;
111
112
try {
113
iterator = pgli.lang.Parser.parseRepeat(layer.repeat, this.sget());
114
trace("# Found repeat layer ["+iterator.varname+" from "+iterator.start+" to "+iterator.end+"]");
115
} catch(e) {
116
trace("(!) Syntax error in repeat expression ["+layer.repeat+"]");
117
continue;
118
}
119
120
while(iterator.loop())
121
{
122
this.sset(iterator.varname, iterator.step);
123
this.walkLayer(layer);
124
iterator.next();
125
}
126
}
127
else
128
{
129
this.walkLayer(layer);
130
}
131
}
132
}
133
},
134
135
walkLayer: function(layer)
136
{
137
var static = pgli.render.CanvasRenderer;
138
139
this.xpush();
140
this.spush();
141
142
for(k in layer)
143
{
144
if(k in static.SCOPE_KEYWORDS)
145
continue;
146
else if(k in static.SCOPE_XFORMS)
147
{
148
var val = pgli.lang.Parser.parseExpression(layer[k], this.sget(), this.xget());
149
if(typeof(val) == "number")
150
{
151
val = Number(val)*this.xgetr();
152
}
153
else
154
{
155
var p = val.search("%");
156
if(p > 0)
157
val = (Number(val.substr(O, p))/100)*this.xget()[static.SCOPE_XFORMS[k]];
158
else continue;
159
}
160
if(k == "x" || k == "y")
161
{
162
val += this.xget()[static.SCOPE_XFORMS[k]];
163
}
164
this.xset(static.SCOPE_XFORMS[k], val);
165
}
166
else
167
this.sset(k, pgli.lang.Parser.parseExpression(layer[k], this.sget()), this.xget());
168
}
169
170
this.walkModule(this.project.getModule(layer.use));
171
172
this.spop();
173
this.xpop();
174
},
175
176
actionVars: function(opts)
177
{
178
var static = pgli.render.CanvasRenderer;
179
180
for(k in opts)
181
{
182
if(k in static.SCOPE_KEYWORDS || k in static.SCOPE_XFORMS)
183
continue;
184
else
185
this.sset(k, pgli.lang.Parser.parseExpression(opts[k], this.sget(), this.xget()));
186
}
187
},
188
189
actionFill: function(opts)
190
{
191
var static = pgli.render.CanvasRenderer;
192
193
if(opts.type == "image")
194
{
195
//trace("# Fill(image)...")
196
var image = this.loadImage(
197
pgli.lang.Parser.parseExpression(opts.value, this.sget(), this.xget())
198
);
199
200
if("repeat" in opts && opts.repeat in static.REPEAT_TYPES)
201
{
202
var pattern = this.context.createPattern(image, static.REPEAT_TYPES[opts.repeat]);
203
204
this.context.rect(this.xgetx(), this.xgety(), this.xgetw(), this.xgeth());
205
this.context.fillStyle = pattern;
206
this.context.fill();
207
208
//pattern = null;
209
}
210
else
211
{
212
this.context.drawImage(image, this.xgetx(), this.xgety(), this.xgetw(), this.xgeth());
213
}
214
}
215
else if(opts.type == "color")
216
{
217
//trace("# Fill(color)...")
218
this.context.beginPath();
219
this.context.rect(this.xgetx(), this.xgety(), this.xgetw(), this.xgeth());
220
this.context.fillStyle = pgli.lang.Parser.parseExpression(opts.value, this.sget(), this.xget());
221
this.context.fill();
222
}
223
else if(opts.type == "line")
224
{
225
//trace("# Fill(line)...")
226
this.context.beginPath();
227
this.context.rect(this.xgetx(), this.xgety(), this.xgetw(), this.xgeth());
228
this.context.lineWidth = 1;
229
this.context.strokeStyle = pgli.lang.Parser.parseExpression(opts.value, this.sget(), this.xget());
230
this.context.stroke();
231
}
232
},
233
234
loadImage: function(url)
235
{
236
var self = this;
237
if(url in this.resources.images)
238
{
239
return this.resources.images[url];
240
}
241
else
242
{
243
trace("/!\\ Image is loading, will redraw onload.");
244
var img = new Image();
245
img.onload = function(){
246
trace("#Image loaded, redrawing...");
247
self.draw();
248
};
249
img.src = url;
250
this.resources.images[url] = img;
251
return img;
252
}
253
},
254
255
spush: function()
256
{
257
this.scope.push(this.cloneScope(this.sget()));
258
this.sseek++;
259
},
260
261
spop: function()
262
{
263
this.sseek--;
264
return this.scope.pop();
265
},
266
267
sreset: function()
268
{
269
this.scope = [{}];
270
this.sseek = 0;
271
},
272
273
sget: function()
274
{
275
return this.scope[this.sseek];
276
},
277
278
sset: function(key, value)
279
{
280
this.scope[this.sseek][key] = value;
281
},
282
283
xpush: function(ratio, x, y, h, w)
284
{
285
if(ratio == undefined)
286
if(this.xseek == -1)
287
this.xform.push([1.0, 0, 0, this.width, this.height]);
288
else
289
this.xform.push(this.xget().slice(0))
290
else
291
this.xform.push([ratio, x, y, h, w]);
292
293
this.xseek++;
294
},
295
296
xpop: function()
297
{
298
this.xseek--;
299
return this.xform.pop();
300
},
301
302
xget: function()
303
{
304
return this.xform[this.xseek];
305
},
306
307
xset: function(key, value)
308
{
309
this.xform[this.xseek][key] = value;
310
},
311
312
xreset: function(ratio, x, y, h, w)
313
{
314
this.xseek = -1;
315
this.xform = [];
316
this.xpush(ratio, x, y, h, w);
317
},
318
319
xgetr: function()
320
{
321
return this.xform[this.xseek][0];
322
},
323
324
xgetx: function()
325
{
326
return this.xform[this.xseek][1];
327
},
328
329
xgety: function()
330
{
331
return this.xform[this.xseek][2];
332
},
333
334
xgetw: function()
335
{
336
return this.xform[this.xseek][3];
337
},
338
339
xgeth: function()
340
{
341
return this.xform[this.xseek][4];
342
},
343
344
cloneScope: (function()
345
{
346
return function (obj) { Clone.prototype=obj; return new Clone() };
347
function Clone(){}
348
}()),
349
350
bindProject: function(project)
351
{
352
this.project = project;
353
},
354
355
resize: function()
356
{
357
var w = this.container.width();
358
var h = this.container.height();
359
360
var size = 0.9*Math.min(w, h);
361
this.width = size;
362
this.height = size;
363
var $canvas = $(this.canvas);
364
$canvas.width(size);
365
$canvas.height(size);
366
this.canvas.width = size;
367
this.canvas.height = size;
368
$canvas.css('marginTop', this.container.height() / 2 - size / 2);
369
$canvas.css('marginLeft', this.container.width() / 2 - size / 2);
370
371
this.context = this.canvas.getContext("2d");
372
373
/*var ctx = this.canvas.getContext("2d");
374
ctx.clearRect(0, 0, size, size);
375
ctx.canvas.width = ctx.canvas.height = size;
376
ctx.font = 'bold 40px Arial';
377
ctx.textAlign = 'center';
378
ctx.fillStyle = '#444';
379
ctx.fillText("Preview", size/2, size/2);*/
380
},
381
382
getRenderRatio: function()
383
{
384
var root = this.project.getRootModule();
385
if(!root) return;
386
return Math.min(this.width/root.width, this.height/root.height);
387
}
388
389
});
390