font_editor_plugin.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. /*************************************************************************/
  2. /* font_editor_plugin.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "font_editor_plugin.h"
  30. #include "os/file_access.h"
  31. #ifdef FREETYPE_ENABLED
  32. #include <ft2build.h>
  33. #include FT_FREETYPE_H
  34. #endif
  35. #include "core/io/resource_saver.h"
  36. void FontEditor::edit(const Ref<Font>& p_font) {
  37. font=p_font;
  38. label->add_font_override("font",font);
  39. }
  40. void FontEditor::_preview_text_changed(const String& p_text) {
  41. label->set_text(p_text);
  42. }
  43. struct FontData {
  44. Vector<uint8_t> bitmap;
  45. int width,height;
  46. int ofs_x; //ofset to center, from ABOVE
  47. int ofs_y; //ofset to begining, from LEFT
  48. int valign; //vertical alignment
  49. int halign;
  50. int advance;
  51. int character;
  52. int glyph;
  53. int texture;
  54. // bool printable;
  55. };
  56. struct FontDataSort {
  57. bool operator()(const FontData *p_A,const FontData *p_B) const {
  58. return p_A->height > p_B->height;
  59. };
  60. };
  61. struct KerningKey {
  62. CharType A,B;
  63. bool operator<(const KerningKey& p_k) const { return (A==p_k.A)?(B<p_k.B):(A<p_k.A); }
  64. };
  65. void FontEditor::_export_fnt(const String& p_name, Ref<Font> p_font) {
  66. String fnt_name = p_name + ".fnt";
  67. FileAccess* f = FileAccess::open(fnt_name, FileAccess::WRITE);
  68. ERR_FAIL_COND(!f);
  69. f->store_string(String("info face=\"") + p_font->get_name() + "\" size=" + String::num_real(font->get_height()) + " bold=0 italic=0 charset=\"\" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=4,4\n");
  70. Vector2 size = p_font->get_texture(0)->get_size();
  71. f->store_string(String("common lineHeight=") + String::num(font->get_height()) + " base=" + String::num(font->get_ascent()) + " scaleW=" + String::num(size.x) + " scaleH=" + String::num(size.y) + " pages="+String::num(p_font->get_texture_count()) + " packed=0\n");
  72. for (int i=0; i<p_font->get_texture_count(); i++) {
  73. f->store_string(String("page id=")+String::num(i)+ " file=\""+ p_name.get_file() + "_" +String::num(i)+".png\"\n");
  74. };
  75. f->store_string(String("chars count=")+String::num(p_font->get_character_count()) + "\n");
  76. Vector<CharType> keys = p_font->get_char_keys();
  77. keys.sort();
  78. for (int i=0; i<keys.size(); i++) {
  79. Font::Character c = p_font->get_character(keys[i]);
  80. int width = c.rect.size.x;
  81. if (keys[i] == 32) {
  82. width = c.advance;
  83. };
  84. f->store_string(String("char id=") + String::num(keys[i]) + " x=" + String::num(c.rect.pos.x) + " y=" + String::num(c.rect.pos.y) +
  85. " width=" + String::num(width) + " height=" + String::num(c.rect.size.y) +
  86. " xoffset=" + String::num(c.h_align) + " yoffset=" + String::num(c.v_align) +
  87. " xadvance=" + String::num(c.advance) + " page=" + String::num(c.texture_idx) +
  88. " chnl=0 letter=\"\"\n");
  89. };
  90. f->close();
  91. for (int i=0; i<p_font->get_texture_count(); i++) {
  92. ResourceSaver::save(p_name + "_" + String::num(i) + ".png", p_font->get_texture(i));
  93. };
  94. };
  95. void FontEditor::_import_fnt(const String& p_string) {
  96. //fnt format used by angelcode bmfont
  97. //http://www.angelcode.com/products/bmfont/
  98. FileAccess *f = FileAccess::open(p_string,FileAccess::READ);
  99. if (!f) {
  100. ERR_EXPLAIN("Can't open font: "+p_string);
  101. ERR_FAIL();
  102. }
  103. font->clear();
  104. while(true) {
  105. String line=f->get_line();
  106. int delimiter=line.find(" ");
  107. String type=line.substr(0,delimiter);
  108. int pos = delimiter+1;
  109. Map<String,String> keys;
  110. while (pos < line.size() && line[pos]==' ')
  111. pos++;
  112. while(pos<line.size()) {
  113. int eq = line.find("=",pos);
  114. if (eq==-1)
  115. break;
  116. String key=line.substr(pos,eq-pos);
  117. int end=-1;
  118. String value;
  119. if (line[eq+1]=='"') {
  120. end=line.find("\"",eq+2);
  121. if (end==-1)
  122. break;
  123. value=line.substr(eq+2,end-1-eq-1);
  124. pos=end+1;
  125. } else {
  126. end=line.find(" ",eq+1);
  127. if (end==-1)
  128. end=line.size();
  129. value=line.substr(eq+1,end-eq);
  130. pos=end;
  131. }
  132. while (pos<line.size() && line[pos]==' ')
  133. pos++;
  134. keys[key]=value;
  135. }
  136. if (type=="info") {
  137. if (keys.has("face"))
  138. font->set_name(keys["face"]);
  139. //if (keys.has("size"))
  140. // font->set_height(keys["size"].to_int());
  141. } else if (type=="common") {
  142. if (keys.has("lineHeight"))
  143. font->set_height(keys["lineHeight"].to_int());
  144. if (keys.has("base"))
  145. font->set_ascent(keys["base"].to_int());
  146. } else if (type=="page") {
  147. if (keys.has("file")) {
  148. String file = keys["file"];
  149. file=p_string.get_base_dir()+"/"+file;
  150. Ref<Texture> tex = ResourceLoader::load(file);
  151. if (tex.is_null()) {
  152. ERR_PRINT("Can't load font texture!");
  153. } else {
  154. font->add_texture(tex);
  155. }
  156. }
  157. } else if (type=="char") {
  158. CharType idx=0;
  159. if (keys.has("id"))
  160. idx=keys["id"].to_int();
  161. Rect2 rect;
  162. if (keys.has("x"))
  163. rect.pos.x=keys["x"].to_int();
  164. if (keys.has("y"))
  165. rect.pos.y=keys["y"].to_int();
  166. if (keys.has("width"))
  167. rect.size.width=keys["width"].to_int();
  168. if (keys.has("height"))
  169. rect.size.height=keys["height"].to_int();
  170. Point2 ofs;
  171. if (keys.has("xoffset"))
  172. ofs.x=keys["xoffset"].to_int();
  173. if (keys.has("yoffset"))
  174. ofs.y=keys["yoffset"].to_int();
  175. int texture=0;
  176. if (keys.has("page"))
  177. texture=keys["page"].to_int();
  178. int advance=-1;
  179. if (keys.has("xadvance"))
  180. advance=keys["xadvance"].to_int();
  181. font->add_char(idx,texture,rect,ofs,advance);
  182. } else if (type=="kerning") {
  183. CharType first=0,second=0;
  184. int k=0;
  185. if (keys.has("first"))
  186. first=keys["first"].to_int();
  187. if (keys.has("second"))
  188. second=keys["second"].to_int();
  189. if (keys.has("amount"))
  190. k=keys["amount"].to_int();
  191. font->add_kerning_pair(first,second,-k);
  192. }
  193. if (f->eof_reached())
  194. break;
  195. }
  196. memdelete(f);
  197. }
  198. void FontEditor::_import_ttf(const String& p_string) {
  199. #ifdef FREETYPE_ENABLED
  200. FT_Library library; /* handle to library */
  201. FT_Face face; /* handle to face object */
  202. Vector<FontData*> font_data_list;
  203. int error = FT_Init_FreeType( &library );
  204. ERR_EXPLAIN("Error initializing FreeType.");
  205. ERR_FAIL_COND( error !=0 );
  206. error = FT_New_Face( library, p_string.utf8().get_data(),0,&face );
  207. if ( error == FT_Err_Unknown_File_Format ) {
  208. ERR_EXPLAIN("Unknown font format.");
  209. FT_Done_FreeType( library );
  210. } else if ( error ) {
  211. ERR_EXPLAIN("Error loading font.");
  212. FT_Done_FreeType( library );
  213. }
  214. ERR_FAIL_COND(error);
  215. int height=0;
  216. int ascent=0;
  217. int font_spacing=0;
  218. int size=font_size->get_text().to_int();
  219. error = FT_Set_Char_Size(face,0,64*size,512,512);
  220. if ( error ) {
  221. FT_Done_FreeType( library );
  222. ERR_EXPLAIN("Invalid font size. ");
  223. ERR_FAIL_COND( error );
  224. }
  225. error = FT_Set_Pixel_Sizes(face,0,size);
  226. FT_GlyphSlot slot = face->glyph;
  227. // error = FT_Set_Charmap(face,ft_encoding_unicode ); /* encoding.. */
  228. /* PRINT CHARACTERS TO INDIVIDUAL BITMAPS */
  229. // int space_size=5; //size for space, if none found.. 5!
  230. // int min_valign=500; //some ridiculous number
  231. FT_ULong charcode;
  232. FT_UInt gindex;
  233. int max_up=-1324345; ///gibberish
  234. int max_down=124232;
  235. Map<KerningKey,int> kerning_map;
  236. charcode = FT_Get_First_Char( face, &gindex );
  237. int xsize=0;
  238. while ( gindex != 0 )
  239. {
  240. bool skip=false;
  241. error = FT_Load_Char( face, charcode, FT_LOAD_RENDER );
  242. if (error) skip=true;
  243. else error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
  244. if (error) skip=true;
  245. if (!skip && (import_chars.has(charcode) && import_chars[charcode] != 0)) {
  246. skip = false;
  247. } else {
  248. if (import_option->get_selected() == 0 && charcode>127)
  249. skip=true;
  250. if (import_option->get_selected() == 1 && charcode>0xFE)
  251. skip=true;
  252. };
  253. if (charcode<=32) //
  254. skip=true;
  255. if (skip) {
  256. charcode=FT_Get_Next_Char(face,charcode,&gindex);
  257. continue;
  258. }
  259. FontData * fdata = memnew( FontData );
  260. fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows );
  261. fdata->width=slot->bitmap.width;
  262. fdata->height=slot->bitmap.rows;
  263. fdata->character=charcode;
  264. fdata->glyph=FT_Get_Char_Index(face,charcode);
  265. if (charcode=='x')
  266. xsize=slot->bitmap.width;
  267. if (charcode<127) {
  268. if (slot->bitmap_top>max_up) {
  269. max_up=slot->bitmap_top;
  270. }
  271. if ( (slot->bitmap_top - fdata->height)<max_down ) {
  272. max_down=slot->bitmap_top - fdata->height;
  273. }
  274. }
  275. fdata->valign=slot->bitmap_top;
  276. fdata->halign=slot->bitmap_left;
  277. fdata->advance=(slot->advance.x+(1<<5))>>6;
  278. fdata->advance+=font_spacing;
  279. for (int i=0;i<slot->bitmap.width;i++) {
  280. for (int j=0;j<slot->bitmap.rows;j++) {
  281. fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
  282. }
  283. }
  284. font_data_list.push_back(fdata);
  285. charcode=FT_Get_Next_Char(face,charcode,&gindex);
  286. // printf("reading char %i\n",charcode);
  287. }
  288. /* SPACE */
  289. FontData *spd = memnew( FontData );
  290. spd->advance=0;
  291. spd->character=' ';
  292. spd->halign=0;
  293. spd->valign=0;
  294. spd->width=0;
  295. spd->height=0;
  296. spd->ofs_x=0;
  297. spd->ofs_y=0;
  298. if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, ft_render_mode_normal )) {
  299. spd->advance = slot->advance.x>>6;
  300. spd->advance+=font_spacing;
  301. } else {
  302. spd->advance=xsize;
  303. spd->advance+=font_spacing;
  304. }
  305. font_data_list.push_back(spd);
  306. Map<CharType, bool> exported;
  307. for (int i=0; i<font_data_list.size(); i++) {
  308. exported[font_data_list[i]->character] = true;
  309. };
  310. int missing = 0;
  311. for(Map<CharType,int>::Element *E=import_chars.front();E;E=E->next()) {
  312. CharType c = E->key();
  313. if (!exported.has(c)) {
  314. CharType str[2] = {c, 0};
  315. printf("** Warning: character %i (%ls) not exported\n", (int)c, str);
  316. ++missing;
  317. };
  318. };
  319. printf("total %i/%i\n", missing, import_chars.size());
  320. /* KERNING */
  321. for(int i=0;i<font_data_list.size();i++) {
  322. for(int j=0;j<font_data_list.size();j++) {
  323. FT_Vector delta;
  324. FT_Get_Kerning( face, font_data_list[i]->glyph,font_data_list[j]->glyph, FT_KERNING_DEFAULT, &delta );
  325. if (delta.x!=0) {
  326. KerningKey kpk;
  327. kpk.A = font_data_list[i]->character;
  328. kpk.B = font_data_list[j]->character;
  329. int kern = ((-delta.x)+(1<<5))>>6;
  330. if (kern==0)
  331. continue;
  332. kerning_map[kpk]=kern;
  333. }
  334. }
  335. }
  336. height=max_up-max_down;
  337. ascent=max_up;
  338. /* FIND OUT WHAT THE FONT HEIGHT FOR THIS IS */
  339. /* ADJUST THE VALIGN FOR EACH CHARACTER */
  340. for (int i=0;i<(int)font_data_list.size();i++) {
  341. font_data_list[i]->valign=max_up-font_data_list[i]->valign;
  342. }
  343. /* ADD THE SPACEBAR CHARACTER */
  344. /*
  345. FontData * fdata = new FontData;
  346. fdata->character=32;
  347. fdata->bitmap=0;
  348. fdata->width=xsize;
  349. fdata->height=1;
  350. fdata->valign=0;
  351. font_data_list.push_back(fdata);
  352. */
  353. /* SORT BY HEIGHT, SO THEY FIT BETTER ON THE TEXTURE */
  354. font_data_list.sort_custom<FontDataSort>();
  355. int spacing=2;
  356. int use_width=256;
  357. int use_max_height=256;
  358. // int surf_idx=-1;
  359. List<Size2> tex_sizes;
  360. // int current_texture=0;
  361. Size2 first(use_width,nearest_power_of_2( font_data_list[0]->height + spacing ));
  362. Size2 *curtex=&tex_sizes.push_back(first)->get();
  363. Point2 tex_ofs;
  364. /* FIT (NOT COPY YEY) FACES IN TEXTURES */
  365. int current_height=font_data_list[0]->height + spacing;
  366. int font_margin=2;
  367. for(int i=0;i<font_data_list.size();i++) {
  368. FontData *fd=font_data_list[i];
  369. if (tex_ofs.x+fd->width >= use_width) {
  370. //end of column, advance a row
  371. tex_ofs.x=0;
  372. tex_ofs.y+=current_height+font_margin;
  373. current_height=fd->height + spacing;
  374. int new_tex_h = curtex->height;
  375. while( tex_ofs.y+current_height > new_tex_h ) {
  376. if (curtex->height * 2 > use_max_height) {
  377. //oops, can't use this texture anymore..
  378. Size2 newtex( use_width, nearest_power_of_2( fd->height + spacing ));
  379. new_tex_h=newtex.height;
  380. curtex=&tex_sizes.push_back(newtex)->get();
  381. tex_ofs=Point2(0,0);
  382. } else {
  383. new_tex_h*=2;
  384. }
  385. }
  386. curtex->height=new_tex_h;
  387. }
  388. fd->ofs_x=tex_ofs.x;
  389. fd->ofs_y=tex_ofs.y;
  390. fd->texture=tex_sizes.size()-1;
  391. tex_ofs.x+=fd->width+font_margin;
  392. }
  393. /* WRITE FACES IN TEXTURES */
  394. // create textures
  395. Vector<DVector<uint8_t> >image_data;
  396. Vector<int> image_widths;
  397. Vector<DVector<uint8_t>::Write> image_ptrs;
  398. image_ptrs.resize(tex_sizes.size());
  399. for(int i=0;i<tex_sizes.size();i++) {
  400. DVector<uint8_t> pixels;
  401. int texsize=tex_sizes[i].width * tex_sizes[i].height * 2;
  402. pixels.resize(texsize );
  403. image_data.push_back(pixels);
  404. image_widths.push_back( tex_sizes[i].width );
  405. image_ptrs[i] = image_data[i].write();
  406. for(int j=0;j<texsize;j++) {
  407. image_ptrs[i][j]=0;
  408. }
  409. }
  410. //blit textures with fonts
  411. for(int i=0;i<font_data_list.size();i++) {
  412. FontData *fd=font_data_list[i];
  413. uint8_t *pixels = image_ptrs[fd->texture].ptr();
  414. int width = image_widths[fd->texture];
  415. for(int y=0;y<fd->height;y++) {
  416. const uint8_t *src = &fd->bitmap[y*fd->width];
  417. uint8_t *dst = &pixels[((fd->ofs_y+y)*width+fd->ofs_x)*2];
  418. for(int x=0;x<fd->width;x++) {
  419. dst[x<<1]=255; //white always
  420. dst[(x<<1) +1]=src[x];
  421. }
  422. }
  423. }
  424. //unlock writing
  425. for(int i=0;i<image_ptrs.size();i++)
  426. image_ptrs[i]=DVector<uint8_t>::Write();
  427. /* CREATE FONT */
  428. font->clear();
  429. font->set_height(height);
  430. font->set_ascent(ascent);
  431. //register texures
  432. for(int i=0;i<tex_sizes.size();i++) {
  433. Image img(tex_sizes[i].width,tex_sizes[i].height,0,Image::FORMAT_GRAYSCALE_ALPHA,image_data[i]);
  434. Ref<ImageTexture> tex = memnew( ImageTexture );
  435. tex->create_from_image(img,0); //no filter, no repeat
  436. font->add_texture(tex);
  437. //tframe->set_texture(tex);
  438. }
  439. //register characters
  440. for(int i=0;i<font_data_list.size();i++) {
  441. FontData *fd=font_data_list[i];
  442. font->add_char(fd->character,fd->texture,Rect2( fd->ofs_x, fd->ofs_y, fd->width, fd->height),Point2(fd->halign,fd->valign), fd->advance);
  443. memdelete(fd);
  444. }
  445. for(Map<KerningKey,int>::Element *E=kerning_map.front();E;E=E->next()) {
  446. font->add_kerning_pair(E->key().A,E->key().B,E->get());
  447. }
  448. FT_Done_FreeType( library );
  449. #endif
  450. }
  451. void FontEditor::_add_source() {
  452. _source_file->popup_centered_ratio();
  453. };
  454. void FontEditor::_add_source_accept(const String& p_file) {
  455. FileAccess* f = FileAccess::open(p_file, FileAccess::READ);
  456. ERR_FAIL_COND(!f);
  457. String line;
  458. while ( !f->eof_reached() ) {
  459. line = f->get_line();
  460. for (int i=0; i<line.length(); i++) {
  461. if (import_chars.has(line[i])) {
  462. import_chars[line[i]] = import_chars[line[i]] + 1;
  463. } else {
  464. import_chars[line[i]] = 1;
  465. };
  466. };
  467. };
  468. };
  469. void FontEditor::_export_fnt_pressed() {
  470. _export_file->popup_centered_ratio();
  471. };
  472. void FontEditor::_export_fnt_accept(const String& p_file) {
  473. String name = p_file.replace(".fnt", "");
  474. _export_fnt(name, font);
  475. };
  476. void FontEditor::_import_accept(const String& p_string) {
  477. #ifdef FREETYPE_ENABLED
  478. if (p_string.extension().nocasecmp_to("ttf")==0 || p_string.extension().nocasecmp_to("otf")==0) {
  479. _import_ttf(p_string);
  480. }
  481. #endif
  482. if (p_string.extension().nocasecmp_to("fnt")==0) {
  483. _import_fnt(p_string);
  484. }
  485. label->add_font_override("font",font);
  486. label->notification(Control::NOTIFICATION_THEME_CHANGED);
  487. label->update();
  488. }
  489. void FontEditor::_import() {
  490. file->popup_centered_ratio();
  491. }
  492. void FontEditor::_bind_methods() {
  493. ObjectTypeDB::bind_method("_import",&FontEditor::_import);
  494. ObjectTypeDB::bind_method("_import_accept",&FontEditor::_import_accept);
  495. ObjectTypeDB::bind_method("_preview_text_changed",&FontEditor::_preview_text_changed);
  496. ObjectTypeDB::bind_method("_add_source",&FontEditor::_add_source);
  497. ObjectTypeDB::bind_method("_add_source_accept",&FontEditor::_add_source_accept);
  498. ObjectTypeDB::bind_method("_export_fnt_pressed",&FontEditor::_export_fnt_pressed);
  499. ObjectTypeDB::bind_method("_export_fnt_accept",&FontEditor::_export_fnt_accept);
  500. }
  501. FontEditor::FontEditor() {
  502. panel = memnew( Panel );
  503. add_child(panel);
  504. panel->set_area_as_parent_rect();
  505. /*
  506. tframe = memnew( TextureFrame );
  507. tframe->set_anchor( MARGIN_RIGHT, ANCHOR_END );
  508. tframe->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
  509. tframe->set_begin( Point2(5, 40 ) );
  510. tframe->set_end( Point2(5,55 ) );
  511. panel->add_child(tframe);
  512. */
  513. Label *l = memnew( Label );
  514. l->set_pos( Point2(5,13 ) );
  515. l->set_text("Import: ");
  516. panel->add_child(l);
  517. l = memnew( Label );
  518. l->set_pos( Point2(25,37 ) );
  519. l->set_text("Size: ");
  520. panel->add_child(l);
  521. font_size = memnew( LineEdit );
  522. font_size->set_text("12");
  523. font_size->set_pos( Point2(70,35 ) );
  524. font_size->set_size( Size2(40,10 ) );
  525. panel->add_child(font_size);
  526. l = memnew( Label );
  527. l->set_pos( Point2(140,37 ) );
  528. l->set_text("Encoding: ");
  529. panel->add_child(l);
  530. import_option = memnew( OptionButton );
  531. import_option->add_item("Ascii");
  532. import_option->add_item("Latin");
  533. import_option->add_item("Full Unicode");
  534. import_option->select(1);
  535. import_option->set_pos( Point2( 215,35 ) );
  536. import_option->set_size( Point2( 100,12 ) );
  537. panel->add_child(import_option);
  538. Button* import = memnew( Button );
  539. import->set_text("Import:..");
  540. import->set_begin( Point2(80,35) );
  541. import->set_end( Point2(10,45) );
  542. import->set_anchor( MARGIN_LEFT, ANCHOR_END );
  543. import->set_anchor( MARGIN_RIGHT, ANCHOR_END );
  544. panel->add_child(import);
  545. Button* add_source = memnew( Button );
  546. add_source->set_text("Add Source...");
  547. add_source->set_begin( Point2(180,35) );
  548. add_source->set_end( Point2(90,45) );
  549. add_source->set_anchor( MARGIN_LEFT, ANCHOR_END );
  550. add_source->set_anchor( MARGIN_RIGHT, ANCHOR_END );
  551. panel->add_child(add_source);
  552. file = memnew( FileDialog );
  553. file->set_access(FileDialog::ACCESS_FILESYSTEM);
  554. _source_file = memnew( FileDialog );
  555. _source_file->set_access(FileDialog::ACCESS_FILESYSTEM);
  556. _source_file->set_mode(FileDialog::MODE_OPEN_FILE);
  557. _source_file->connect("file_selected", this, "_add_source_accept");
  558. panel->add_child( _source_file );
  559. Button* export_fnt = memnew(Button);
  560. export_fnt->set_text("Export fnt");
  561. export_fnt->set_begin(Point2(80, 65));
  562. export_fnt->set_end(Point2(10, 75));
  563. export_fnt->set_anchor( MARGIN_LEFT, ANCHOR_END );
  564. export_fnt->set_anchor( MARGIN_RIGHT, ANCHOR_END );
  565. export_fnt->connect("pressed", this, "_export_fnt_pressed");
  566. panel->add_child( export_fnt );
  567. _export_file = memnew(FileDialog);
  568. _export_file->set_access(FileDialog::ACCESS_FILESYSTEM);
  569. _export_file->set_mode(FileDialog::MODE_SAVE_FILE);
  570. _export_file->connect("file_selected", this, "_export_fnt_accept");
  571. panel->add_child(_export_file);
  572. l = memnew( Label );
  573. l->set_pos( Point2(5,65 ) );
  574. l->set_text("Preview Text: ");
  575. panel->add_child(l);
  576. preview_text = memnew( LineEdit );
  577. preview_text->set_anchor( MARGIN_RIGHT, ANCHOR_END );
  578. preview_text->set_begin( Point2(25,85 ) );
  579. preview_text->set_end( Point2(10,95 ) );
  580. panel->add_child(preview_text);
  581. preview_text->connect("text_changed", this,"_preview_text_changed");
  582. preview_text->set_text("The quick brown fox jumped over the lazy dog.");
  583. l = memnew( Label );
  584. l->set_pos( Point2(5,115 ) );
  585. l->set_text("Preview: ");
  586. panel->add_child(l);
  587. label = memnew( Label );
  588. label->set_autowrap(true);
  589. label->set_anchor( MARGIN_RIGHT, ANCHOR_END );
  590. label->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
  591. label->set_begin( Point2(5, 135 ) );
  592. label->set_end( Point2(5,5 ) );
  593. label->set_text("The quick brown fox jumped over the lazy dog.");
  594. label->set_align( Label::ALIGN_CENTER );
  595. panel->add_child(label);
  596. #ifdef FREETYPE_ENABLED
  597. file->add_filter("*.ttf");
  598. file->add_filter("*.otf");
  599. #endif
  600. file->add_filter("*.fnt ; AngelCode BMFont");
  601. file->set_mode(FileDialog::MODE_OPEN_FILE);
  602. panel->add_child( file );
  603. import->connect("pressed", this,"_import");
  604. file->connect("file_selected", this,"_import_accept");
  605. add_source->connect("pressed", this, "_add_source");
  606. }
  607. void FontEditorPlugin::edit(Object *p_node) {
  608. if (p_node && p_node->cast_to<Font>()) {
  609. font_editor->edit( p_node->cast_to<Font>() );
  610. font_editor->show();
  611. } else
  612. font_editor->hide();
  613. }
  614. bool FontEditorPlugin::handles(Object *p_node) const{
  615. return p_node->is_type("Font");
  616. }
  617. void FontEditorPlugin::make_visible(bool p_visible){
  618. if (p_visible)
  619. font_editor->show();
  620. else
  621. font_editor->hide();
  622. }
  623. FontEditorPlugin::FontEditorPlugin(EditorNode *p_node) {
  624. font_editor = memnew( FontEditor );
  625. p_node->get_viewport()->add_child(font_editor);
  626. font_editor->set_area_as_parent_rect();
  627. font_editor->hide();
  628. }