1 /*************************************************************************/
2 /* editor_preview_plugins.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30 #include "editor_preview_plugins.h"
31 #include "editor/editor_scale.h"
32 #include "editor/editor_settings.h"
33 #include "io/file_access_memory.h"
34 #include "io/resource_loader.h"
35 #include "os/os.h"
36 #include "scene/resources/bit_mask.h"
37 #include "scene/resources/material.h"
38 #include "scene/resources/mesh.h"
39 #include "scene/resources/sample.h"
40
handles(const String & p_type) const41 bool EditorTexturePreviewPlugin::handles(const String &p_type) const {
42
43 return (ObjectTypeDB::is_type(p_type, "ImageTexture") || ObjectTypeDB::is_type(p_type, "AtlasTexture"));
44 }
45
generate(const RES & p_from)46 Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) {
47
48 Image img;
49 Ref<AtlasTexture> atex = p_from;
50 if (atex.is_valid()) {
51 Ref<ImageTexture> tex = atex->get_atlas();
52 if (!tex.is_valid()) {
53 return Ref<Texture>();
54 }
55 Image atlas = tex->get_data();
56 img = atlas.get_rect(atex->get_region());
57 } else {
58 Ref<ImageTexture> tex = p_from;
59 img = tex->get_data();
60 }
61
62 if (img.empty())
63 return Ref<Texture>();
64
65 img.clear_mipmaps();
66
67 int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
68 thumbnail_size *= EDSCALE;
69 if (img.is_compressed()) {
70 if (img.decompress() != OK)
71 return Ref<Texture>();
72 } else if (img.get_format() != Image::FORMAT_RGB && img.get_format() != Image::FORMAT_RGBA) {
73 img.convert(Image::FORMAT_RGBA);
74 }
75
76 int width, height;
77 if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
78
79 width = thumbnail_size;
80 height = img.get_height() * thumbnail_size / img.get_width();
81 } else if (img.get_height() > thumbnail_size && img.get_height() >= img.get_width()) {
82
83 height = thumbnail_size;
84 width = img.get_width() * thumbnail_size / img.get_height();
85 } else {
86
87 width = img.get_width();
88 height = img.get_height();
89 }
90
91 img.resize(width, height);
92
93 Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
94
95 ptex->create_from_image(img, 0);
96 return ptex;
97 }
98
EditorTexturePreviewPlugin()99 EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
100 }
101
102 ////////////////////////////////////////////////////////////////////////////
103
handles(const String & p_type) const104 bool EditorBitmapPreviewPlugin::handles(const String &p_type) const {
105
106 return ObjectTypeDB::is_type(p_type, "BitMap");
107 }
108
generate(const RES & p_from)109 Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) {
110
111 Ref<BitMap> bm = p_from;
112
113 if (bm->get_size() == Size2()) {
114 return Ref<Texture>();
115 }
116
117 DVector<uint8_t> data;
118
119 data.resize(bm->get_size().width * bm->get_size().height);
120
121 {
122 DVector<uint8_t>::Write w = data.write();
123
124 for (int i = 0; i < bm->get_size().width; i++) {
125 for (int j = 0; j < bm->get_size().height; j++) {
126 if (bm->get_bit(Point2i(i, j))) {
127 w[j * bm->get_size().width + i] = 255;
128 } else {
129 w[j * bm->get_size().width + i] = 0;
130 }
131 }
132 }
133 }
134
135 Image img(bm->get_size().width, bm->get_size().height, 0, Image::FORMAT_GRAYSCALE, data);
136
137 int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
138 thumbnail_size *= EDSCALE;
139 if (img.is_compressed()) {
140 if (img.decompress() != OK)
141 return Ref<Texture>();
142 } else if (img.get_format() != Image::FORMAT_RGB && img.get_format() != Image::FORMAT_RGBA) {
143 img.convert(Image::FORMAT_RGBA);
144 }
145
146 int width, height;
147 if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
148
149 width = thumbnail_size;
150 height = img.get_height() * thumbnail_size / img.get_width();
151 } else if (img.get_height() > thumbnail_size && img.get_height() >= img.get_width()) {
152
153 height = thumbnail_size;
154 width = img.get_width() * thumbnail_size / img.get_height();
155 } else {
156
157 width = img.get_width();
158 height = img.get_height();
159 }
160
161 img.resize(width, height);
162
163 Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
164
165 ptex->create_from_image(img, 0);
166 return ptex;
167 }
168
EditorBitmapPreviewPlugin()169 EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() {
170 }
171
172 ///////////////////////////////////////////////////////////////////////////
173
_gen_from_imd(Ref<ResourceImportMetadata> p_imd)174 Ref<Texture> EditorPackedScenePreviewPlugin::_gen_from_imd(Ref<ResourceImportMetadata> p_imd) {
175
176 if (p_imd.is_null()) {
177 return Ref<Texture>();
178 }
179
180 if (!p_imd->has_option("thumbnail"))
181 return Ref<Texture>();
182
183 Variant tn = p_imd->get_option("thumbnail");
184 //print_line(Variant::get_type_name(tn.get_type()));
185 DVector<uint8_t> thumbnail = tn;
186
187 int len = thumbnail.size();
188 if (len == 0)
189 return Ref<Texture>();
190
191 DVector<uint8_t>::Read r = thumbnail.read();
192
193 Image img(r.ptr(), len);
194 if (img.empty())
195 return Ref<Texture>();
196
197 Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
198 ptex->create_from_image(img, 0);
199 return ptex;
200 }
201
handles(const String & p_type) const202 bool EditorPackedScenePreviewPlugin::handles(const String &p_type) const {
203
204 return ObjectTypeDB::is_type(p_type, "PackedScene");
205 }
generate(const RES & p_from)206 Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) {
207
208 Ref<ResourceImportMetadata> imd = p_from->get_import_metadata();
209 return _gen_from_imd(imd);
210 }
211
generate_from_path(const String & p_path)212 Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) {
213
214 Ref<ResourceImportMetadata> imd = ResourceLoader::load_import_metadata(p_path);
215 return _gen_from_imd(imd);
216 }
217
EditorPackedScenePreviewPlugin()218 EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
219 }
220
221 //////////////////////////////////////////////////////////////////
222
handles(const String & p_type) const223 bool EditorMaterialPreviewPlugin::handles(const String &p_type) const {
224
225 return ObjectTypeDB::is_type(p_type, "Material"); //any material
226 }
227
generate(const RES & p_from)228 Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) {
229
230 Ref<Material> material = p_from;
231 ERR_FAIL_COND_V(material.is_null(), Ref<Texture>());
232
233 VS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid());
234
235 VS::get_singleton()->viewport_queue_screen_capture(viewport);
236 VS::get_singleton()->viewport_set_render_target_update_mode(viewport, VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
237 // print_line("queue capture!");
238 Image img;
239
240 int timeout = 1000;
241 while (timeout) {
242 //print_line("try capture?");
243 OS::get_singleton()->delay_usec(10);
244 img = VS::get_singleton()->viewport_get_screen_capture(viewport);
245 if (!img.empty())
246 break;
247 timeout--;
248 }
249
250 //print_line("captured!");
251 VS::get_singleton()->mesh_surface_set_material(sphere, 0, RID());
252
253 int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
254 thumbnail_size *= EDSCALE;
255 img.resize(thumbnail_size, thumbnail_size);
256
257 Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
258 ptex->create_from_image(img, 0);
259 return ptex;
260 }
261
EditorMaterialPreviewPlugin()262 EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
263
264 scenario = VS::get_singleton()->scenario_create();
265
266 viewport = VS::get_singleton()->viewport_create();
267 VS::get_singleton()->viewport_set_as_render_target(viewport, true);
268 VS::get_singleton()->viewport_set_render_target_update_mode(viewport, VS::RENDER_TARGET_UPDATE_DISABLED);
269 VS::get_singleton()->viewport_set_scenario(viewport, scenario);
270 VS::ViewportRect vr;
271 vr.x = 0;
272 vr.y = 0;
273 vr.width = 128;
274 vr.height = 128;
275 VS::get_singleton()->viewport_set_rect(viewport, vr);
276
277 camera = VS::get_singleton()->camera_create();
278 VS::get_singleton()->viewport_attach_camera(viewport, camera);
279 VS::get_singleton()->camera_set_transform(camera, Transform(Matrix3(), Vector3(0, 0, 3)));
280 VS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10);
281
282 light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
283 light_instance = VS::get_singleton()->instance_create2(light, scenario);
284 VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
285
286 light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
287 VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_DIFFUSE, Color(0.7, 0.7, 0.7));
288 VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
289 light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
290
291 VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
292
293 sphere = VS::get_singleton()->mesh_create();
294 sphere_instance = VS::get_singleton()->instance_create2(sphere, scenario);
295
296 int lats = 32;
297 int lons = 32;
298 float radius = 1.0;
299
300 DVector<Vector3> vertices;
301 DVector<Vector3> normals;
302 DVector<Vector2> uvs;
303 DVector<float> tangents;
304 Matrix3 tt = Matrix3(Vector3(0, 1, 0), Math_PI * 0.5);
305
306 for (int i = 1; i <= lats; i++) {
307 double lat0 = Math_PI * (-0.5 + (double)(i - 1) / lats);
308 double z0 = Math::sin(lat0);
309 double zr0 = Math::cos(lat0);
310
311 double lat1 = Math_PI * (-0.5 + (double)i / lats);
312 double z1 = Math::sin(lat1);
313 double zr1 = Math::cos(lat1);
314
315 for (int j = lons; j >= 1; j--) {
316
317 double lng0 = 2 * Math_PI * (double)(j - 1) / lons;
318 double x0 = Math::cos(lng0);
319 double y0 = Math::sin(lng0);
320
321 double lng1 = 2 * Math_PI * (double)(j) / lons;
322 double x1 = Math::cos(lng1);
323 double y1 = Math::sin(lng1);
324
325 Vector3 v[4] = {
326 Vector3(x1 * zr0, z0, y1 * zr0),
327 Vector3(x1 * zr1, z1, y1 * zr1),
328 Vector3(x0 * zr1, z1, y0 * zr1),
329 Vector3(x0 * zr0, z0, y0 * zr0)
330 };
331
332 #define ADD_POINT(m_idx) \
333 normals.push_back(v[m_idx]); \
334 vertices.push_back(v[m_idx] * radius); \
335 { \
336 Vector2 uv(Math::atan2(v[m_idx].x, v[m_idx].z), Math::atan2(-v[m_idx].y, v[m_idx].z)); \
337 uv /= Math_PI; \
338 uv *= 4.0; \
339 uv = uv * 0.5 + Vector2(0.5, 0.5); \
340 uvs.push_back(uv); \
341 } \
342 { \
343 Vector3 t = tt.xform(v[m_idx]); \
344 tangents.push_back(t.x); \
345 tangents.push_back(t.y); \
346 tangents.push_back(t.z); \
347 tangents.push_back(1.0); \
348 }
349
350 ADD_POINT(0);
351 ADD_POINT(1);
352 ADD_POINT(2);
353
354 ADD_POINT(2);
355 ADD_POINT(3);
356 ADD_POINT(0);
357 }
358 }
359
360 Array arr;
361 arr.resize(VS::ARRAY_MAX);
362 arr[VS::ARRAY_VERTEX] = vertices;
363 arr[VS::ARRAY_NORMAL] = normals;
364 arr[VS::ARRAY_TANGENT] = tangents;
365 arr[VS::ARRAY_TEX_UV] = uvs;
366 VS::get_singleton()->mesh_add_surface(sphere, VS::PRIMITIVE_TRIANGLES, arr);
367 }
368
~EditorMaterialPreviewPlugin()369 EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
370
371 VS::get_singleton()->free(sphere);
372 VS::get_singleton()->free(sphere_instance);
373 VS::get_singleton()->free(viewport);
374 VS::get_singleton()->free(light);
375 VS::get_singleton()->free(light_instance);
376 VS::get_singleton()->free(light2);
377 VS::get_singleton()->free(light_instance2);
378 VS::get_singleton()->free(camera);
379 VS::get_singleton()->free(scenario);
380 }
381
382 ///////////////////////////////////////////////////////////////////////////
383
_is_text_char(CharType c)384 static bool _is_text_char(CharType c) {
385
386 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
387 }
388
handles(const String & p_type) const389 bool EditorScriptPreviewPlugin::handles(const String &p_type) const {
390
391 return ObjectTypeDB::is_type(p_type, "Script");
392 }
393
generate(const RES & p_from)394 Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
395
396 Ref<Script> scr = p_from;
397 if (scr.is_null())
398 return Ref<Texture>();
399
400 String code = scr->get_source_code().strip_edges();
401 if (code == "")
402 return Ref<Texture>();
403
404 List<String> kwors;
405 scr->get_language()->get_reserved_words(&kwors);
406
407 Set<String> keywords;
408
409 for (List<String>::Element *E = kwors.front(); E; E = E->next()) {
410
411 keywords.insert(E->get());
412 }
413
414 int line = 0;
415 int col = 0;
416 int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
417 thumbnail_size *= EDSCALE;
418 Image img(thumbnail_size, thumbnail_size, 0, Image::FORMAT_RGBA);
419
420 Color bg_color = EditorSettings::get_singleton()->get("text_editor/background_color");
421 bg_color.a = 1.0;
422 Color keyword_color = EditorSettings::get_singleton()->get("text_editor/keyword_color");
423 Color text_color = EditorSettings::get_singleton()->get("text_editor/text_color");
424 Color symbol_color = EditorSettings::get_singleton()->get("text_editor/symbol_color");
425
426 for (int i = 0; i < thumbnail_size; i++) {
427 for (int j = 0; j < thumbnail_size; j++) {
428 img.put_pixel(i, j, bg_color);
429 }
430 }
431
432 bool prev_is_text = false;
433 bool in_keyword = false;
434 for (int i = 0; i < code.length(); i++) {
435
436 CharType c = code[i];
437 if (c > 32) {
438 if (col < thumbnail_size) {
439 Color color = text_color;
440
441 if (c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t')) {
442 //make symbol a little visible
443 color = symbol_color;
444 in_keyword = false;
445 } else if (!prev_is_text && _is_text_char(c)) {
446 int pos = i;
447
448 while (_is_text_char(code[pos])) {
449 pos++;
450 }
451 ///print_line("from "+itos(i)+" to "+itos(pos));
452 String word = code.substr(i, pos - i);
453 //print_line("found word: "+word);
454 if (keywords.has(word))
455 in_keyword = true;
456
457 } else if (!_is_text_char(c)) {
458 in_keyword = false;
459 }
460
461 if (in_keyword)
462 color = keyword_color;
463
464 Color ul = color;
465 ul.a *= 0.5;
466 img.put_pixel(col, line * 2, bg_color.blend(ul));
467 img.put_pixel(col, line * 2 + 1, color);
468
469 prev_is_text = _is_text_char(c);
470 }
471 } else {
472
473 prev_is_text = false;
474 in_keyword = false;
475
476 if (c == '\n') {
477 col = 0;
478 line++;
479 if (line >= thumbnail_size / 2)
480 break;
481 } else if (c == '\t') {
482 col += 3;
483 }
484 }
485 col++;
486 }
487
488 Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
489
490 ptex->create_from_image(img, 0);
491 return ptex;
492 }
493
EditorScriptPreviewPlugin()494 EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
495 }
496 ///////////////////////////////////////////////////////////////////
497
handles(const String & p_type) const498 bool EditorSamplePreviewPlugin::handles(const String &p_type) const {
499
500 return ObjectTypeDB::is_type(p_type, "Sample");
501 }
502
generate(const RES & p_from)503 Ref<Texture> EditorSamplePreviewPlugin::generate(const RES &p_from) {
504
505 Ref<Sample> smp = p_from;
506 ERR_FAIL_COND_V(smp.is_null(), Ref<Texture>());
507
508 int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
509 thumbnail_size *= EDSCALE;
510 DVector<uint8_t> img;
511 int w = thumbnail_size;
512 int h = thumbnail_size;
513 img.resize(w * h * 3);
514
515 DVector<uint8_t>::Write imgdata = img.write();
516 uint8_t *imgw = imgdata.ptr();
517 DVector<uint8_t> data = smp->get_data();
518 DVector<uint8_t>::Read sampledata = data.read();
519 const uint8_t *sdata = sampledata.ptr();
520
521 bool stereo = smp->is_stereo();
522 bool _16 = smp->get_format() == Sample::FORMAT_PCM16;
523 int len = smp->get_length();
524
525 if (len < 1)
526 return Ref<Texture>();
527
528 if (smp->get_format() == Sample::FORMAT_IMA_ADPCM) {
529
530 struct IMA_ADPCM_State {
531
532 int16_t step_index;
533 int32_t predictor;
534 /* values at loop point */
535 int16_t loop_step_index;
536 int32_t loop_predictor;
537 int32_t last_nibble;
538 int32_t loop_pos;
539 int32_t window_ofs;
540 const uint8_t *ptr;
541 } ima_adpcm;
542
543 ima_adpcm.step_index = 0;
544 ima_adpcm.predictor = 0;
545 ima_adpcm.loop_step_index = 0;
546 ima_adpcm.loop_predictor = 0;
547 ima_adpcm.last_nibble = -1;
548 ima_adpcm.loop_pos = 0x7FFFFFFF;
549 ima_adpcm.window_ofs = 0;
550 ima_adpcm.ptr = NULL;
551
552 for (int i = 0; i < w; i++) {
553
554 float max[2] = { -1e10, -1e10 };
555 float min[2] = { 1e10, 1e10 };
556 int from = i * len / w;
557 int to = (i + 1) * len / w;
558 if (to >= len)
559 to = len - 1;
560
561 for (int j = from; j < to; j++) {
562
563 while (j > ima_adpcm.last_nibble) {
564
565 static const int16_t _ima_adpcm_step_table[89] = {
566 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
567 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
568 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
569 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
570 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
571 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
572 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
573 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
574 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
575 };
576
577 static const int8_t _ima_adpcm_index_table[16] = {
578 -1, -1, -1, -1, 2, 4, 6, 8,
579 -1, -1, -1, -1, 2, 4, 6, 8
580 };
581
582 int16_t nibble, diff, step;
583
584 ima_adpcm.last_nibble++;
585 const uint8_t *src_ptr = sdata;
586
587 int ofs = ima_adpcm.last_nibble >> 1;
588
589 if (stereo)
590 ofs *= 2;
591
592 nibble = (ima_adpcm.last_nibble & 1) ?
593 (src_ptr[ofs] >> 4) :
594 (src_ptr[ofs] & 0xF);
595 step = _ima_adpcm_step_table[ima_adpcm.step_index];
596
597 ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
598 if (ima_adpcm.step_index < 0)
599 ima_adpcm.step_index = 0;
600 if (ima_adpcm.step_index > 88)
601 ima_adpcm.step_index = 88;
602
603 diff = step >> 3;
604 if (nibble & 1)
605 diff += step >> 2;
606 if (nibble & 2)
607 diff += step >> 1;
608 if (nibble & 4)
609 diff += step;
610 if (nibble & 8)
611 diff = -diff;
612
613 ima_adpcm.predictor += diff;
614 if (ima_adpcm.predictor < -0x8000)
615 ima_adpcm.predictor = -0x8000;
616 else if (ima_adpcm.predictor > 0x7FFF)
617 ima_adpcm.predictor = 0x7FFF;
618
619 /* store loop if there */
620 if (ima_adpcm.last_nibble == ima_adpcm.loop_pos) {
621
622 ima_adpcm.loop_step_index = ima_adpcm.step_index;
623 ima_adpcm.loop_predictor = ima_adpcm.predictor;
624 }
625 }
626
627 float v = ima_adpcm.predictor / 32767.0;
628 if (v > max[0])
629 max[0] = v;
630 if (v < min[0])
631 min[0] = v;
632 }
633 max[0] *= 0.8;
634 min[0] *= 0.8;
635
636 for (int j = 0; j < h; j++) {
637 float v = (j / (float)h) * 2.0 - 1.0;
638 uint8_t *imgofs = &imgw[(uint64_t(j) * w + i) * 3];
639 if (v > min[0] && v < max[0]) {
640 imgofs[0] = 255;
641 imgofs[1] = 150;
642 imgofs[2] = 80;
643 } else {
644 imgofs[0] = 0;
645 imgofs[1] = 0;
646 imgofs[2] = 0;
647 }
648 }
649 }
650 } else {
651 for (int i = 0; i < w; i++) {
652 // i trust gcc will optimize this loop
653 float max[2] = { -1e10, -1e10 };
654 float min[2] = { 1e10, 1e10 };
655 int c = stereo ? 2 : 1;
656 int from = uint64_t(i) * len / w;
657 int to = (uint64_t(i) + 1) * len / w;
658 if (to >= len)
659 to = len - 1;
660
661 if (_16) {
662 const int16_t *src = (const int16_t *)sdata;
663
664 for (int j = 0; j < c; j++) {
665
666 for (int k = from; k <= to; k++) {
667
668 float v = src[uint64_t(k) * c + j] / 32768.0;
669 if (v > max[j])
670 max[j] = v;
671 if (v < min[j])
672 min[j] = v;
673 }
674 }
675 } else {
676
677 const int8_t *src = (const int8_t *)sdata;
678
679 for (int j = 0; j < c; j++) {
680
681 for (int k = from; k <= to; k++) {
682
683 float v = src[uint64_t(k) * c + j] / 128.0;
684 if (v > max[j])
685 max[j] = v;
686 if (v < min[j])
687 min[j] = v;
688 }
689 }
690 }
691
692 max[0] *= 0.8;
693 max[1] *= 0.8;
694 min[0] *= 0.8;
695 min[1] *= 0.8;
696
697 if (!stereo) {
698 for (int j = 0; j < h; j++) {
699 float v = (j / (float)h) * 2.0 - 1.0;
700 uint8_t *imgofs = &imgw[(j * w + i) * 3];
701 if (v > min[0] && v < max[0]) {
702 imgofs[0] = 255;
703 imgofs[1] = 150;
704 imgofs[2] = 80;
705 } else {
706 imgofs[0] = 0;
707 imgofs[1] = 0;
708 imgofs[2] = 0;
709 }
710 }
711 } else {
712
713 for (int j = 0; j < h; j++) {
714
715 int half;
716 float v;
717 if (j < (h / 2)) {
718 half = 0;
719 v = (j / (float)(h / 2)) * 2.0 - 1.0;
720 } else {
721 half = 1;
722 if ((float)(h / 2) != 0) {
723 v = ((j - (h / 2)) / (float)(h / 2)) * 2.0 - 1.0;
724 } else {
725 v = ((j - (h / 2)) / (float)(1 / 2)) * 2.0 - 1.0;
726 }
727 }
728
729 uint8_t *imgofs = &imgw[(j * w + i) * 3];
730 if (v > min[half] && v < max[half]) {
731 imgofs[0] = 255;
732 imgofs[1] = 150;
733 imgofs[2] = 80;
734 } else {
735 imgofs[0] = 0;
736 imgofs[1] = 0;
737 imgofs[2] = 0;
738 }
739 }
740 }
741 }
742 }
743
744 imgdata = DVector<uint8_t>::Write();
745
746 Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
747 ptex->create_from_image(Image(w, h, 0, Image::FORMAT_RGB, img), 0);
748 return ptex;
749 }
750
EditorSamplePreviewPlugin()751 EditorSamplePreviewPlugin::EditorSamplePreviewPlugin() {
752 }
753
754 ///////////////////////////////////////////////////////////////////////////
755
handles(const String & p_type) const756 bool EditorMeshPreviewPlugin::handles(const String &p_type) const {
757
758 return ObjectTypeDB::is_type(p_type, "Mesh"); //any Mesh
759 }
760
generate(const RES & p_from)761 Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) {
762
763 Ref<Mesh> mesh = p_from;
764 ERR_FAIL_COND_V(mesh.is_null(), Ref<Texture>());
765
766 VS::get_singleton()->instance_set_base(mesh_instance, mesh->get_rid());
767
768 AABB aabb = mesh->get_aabb();
769 Vector3 ofs = aabb.pos + aabb.size * 0.5;
770 aabb.pos -= ofs;
771 Transform xform;
772 xform.basis = Matrix3().rotated(Vector3(0, 1, 0), Math_PI * 0.125);
773 xform.basis = Matrix3().rotated(Vector3(1, 0, 0), -Math_PI * 0.125) * xform.basis;
774 AABB rot_aabb = xform.xform(aabb);
775 float m = MAX(rot_aabb.size.x, rot_aabb.size.y) * 0.5;
776 if (m == 0)
777 return Ref<Texture>();
778 m = 1.0 / m;
779 m *= 0.5;
780 //print_line("scale: "+rtos(m));
781 xform.basis.scale(Vector3(m, m, m));
782 xform.origin = -xform.basis.xform(ofs); //-ofs*m;
783 xform.origin.z -= rot_aabb.size.z * 2;
784 VS::get_singleton()->instance_set_transform(mesh_instance, xform);
785
786 VS::get_singleton()->viewport_queue_screen_capture(viewport);
787 VS::get_singleton()->viewport_set_render_target_update_mode(viewport, VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
788 // print_line("queue capture!");
789 Image img;
790
791 int timeout = 1000;
792 while (timeout) {
793 //print_line("try capture?");
794 OS::get_singleton()->delay_usec(10);
795 img = VS::get_singleton()->viewport_get_screen_capture(viewport);
796 if (!img.empty())
797 break;
798 timeout--;
799 }
800
801 //print_line("captured!");
802 VS::get_singleton()->instance_set_base(mesh_instance, RID());
803
804 int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
805 thumbnail_size *= EDSCALE;
806 img.resize(thumbnail_size, thumbnail_size);
807
808 Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
809 ptex->create_from_image(img, 0);
810 return ptex;
811 }
812
EditorMeshPreviewPlugin()813 EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
814
815 scenario = VS::get_singleton()->scenario_create();
816 viewport = VS::get_singleton()->viewport_create();
817 VS::get_singleton()->viewport_set_as_render_target(viewport, true);
818 VS::get_singleton()->viewport_set_render_target_update_mode(viewport, VS::RENDER_TARGET_UPDATE_DISABLED);
819 VS::get_singleton()->viewport_set_scenario(viewport, scenario);
820 VS::ViewportRect vr;
821 vr.x = 0;
822 vr.y = 0;
823 vr.width = 128;
824 vr.height = 128;
825 VS::get_singleton()->viewport_set_rect(viewport, vr);
826
827 camera = VS::get_singleton()->camera_create();
828 VS::get_singleton()->viewport_attach_camera(viewport, camera);
829 VS::get_singleton()->camera_set_transform(camera, Transform(Matrix3(), Vector3(0, 0, 3)));
830 // VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
831 VS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
832
833 light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
834 light_instance = VS::get_singleton()->instance_create2(light, scenario);
835 VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
836
837 light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
838 VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_DIFFUSE, Color(0.7, 0.7, 0.7));
839 VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
840 light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
841
842 VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
843
844 // sphere = VS::get_singleton()->mesh_create();
845 mesh_instance = VS::get_singleton()->instance_create();
846 VS::get_singleton()->instance_set_scenario(mesh_instance, scenario);
847 }
848
~EditorMeshPreviewPlugin()849 EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
850
851 //VS::get_singleton()->free(sphere);
852 VS::get_singleton()->free(mesh_instance);
853 VS::get_singleton()->free(viewport);
854 VS::get_singleton()->free(light);
855 VS::get_singleton()->free(light_instance);
856 VS::get_singleton()->free(light2);
857 VS::get_singleton()->free(light_instance2);
858 VS::get_singleton()->free(camera);
859 VS::get_singleton()->free(scenario);
860 }
861