TexturePalette.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. #import "qedefs.h"
  2. id texturepalette_i;
  3. #define TYP_MIPTEX 67
  4. int tex_count;
  5. qtexture_t qtextures[MAX_TEXTURES];
  6. typedef struct
  7. {
  8. char name[16];
  9. unsigned width, height;
  10. unsigned offsets[4]; // four mip maps stored
  11. } miptex_t;
  12. unsigned tex_palette[256];
  13. unsigned badtex_d[] =
  14. {
  15. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  16. 0,0,0,0,0,0,0,0,
  17. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  18. 0,0,0,0,0,0,0,0,
  19. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  20. 0,0,0,0,0,0,0,0,
  21. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  22. 0,0,0,0,0,0,0,0,
  23. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  24. 0,0,0,0,0,0,0,0,
  25. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  26. 0,0,0,0,0,0,0,0,
  27. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  28. 0,0,0,0,0,0,0,0,
  29. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  30. 0,0,0,0,0,0,0,0,
  31. 0,0,0,0,0,0,0,0,
  32. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  33. 0,0,0,0,0,0,0,0,
  34. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  35. 0,0,0,0,0,0,0,0,
  36. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  37. 0,0,0,0,0,0,0,0,
  38. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  39. 0,0,0,0,0,0,0,0,
  40. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  41. 0,0,0,0,0,0,0,0,
  42. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  43. 0,0,0,0,0,0,0,0,
  44. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  45. 0,0,0,0,0,0,0,0,
  46. 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
  47. };
  48. qtexture_t badtex = {"notexture",16,16,NULL, badtex_d, {0,0,255,255}};
  49. /*
  50. ==============
  51. TEX_InitPalette
  52. ==============
  53. */
  54. void TEX_InitPalette (byte *pal)
  55. {
  56. int r,g,b,v;
  57. int i;
  58. for (i=0 ; i<256 ; i++)
  59. {
  60. r = pal[0];
  61. g = pal[1];
  62. b = pal[2];
  63. pal += 3;
  64. v = (r<<24) + (g<<16) + (b<<8) + 255;
  65. v = BigLong (v);
  66. tex_palette[i] = v;
  67. }
  68. }
  69. /*
  70. =================
  71. TEX_ImageFromMiptex
  72. =================
  73. */
  74. void TEX_ImageFromMiptex (miptex_t *qtex)
  75. {
  76. NXBitmapImageRep *bm;
  77. byte *source;
  78. unsigned *dest;
  79. int width, height, i, count;
  80. qtexture_t *q;
  81. int tr, tg, tb;
  82. width = LittleLong(qtex->width);
  83. height = LittleLong(qtex->height);
  84. bm = [[NXBitmapImageRep alloc]
  85. initData: NULL
  86. pixelsWide: width
  87. pixelsHigh: height
  88. bitsPerSample: 8
  89. samplesPerPixel:3
  90. hasAlpha: NO
  91. isPlanar: NO
  92. colorSpace: NX_RGBColorSpace
  93. bytesPerRow: width*4
  94. bitsPerPixel: 32];
  95. dest = (unsigned *)[bm data];
  96. count = width*height;
  97. source = (byte *)qtex + LittleLong(qtex->offsets[0]);
  98. q = &qtextures[tex_count];
  99. tex_count++;
  100. q->width = width;
  101. q->height = height;
  102. q->rep = bm;
  103. q->data = dest;
  104. tr = tg = tb = 0;
  105. for (i=0 ; i<count ; i++)
  106. {
  107. dest[i] = tex_palette[source[i]];
  108. tr += ((pixel32_t *)&dest[i])->chan[0];
  109. tg += ((pixel32_t *)&dest[i])->chan[1];
  110. tb += ((pixel32_t *)&dest[i])->chan[2];
  111. }
  112. q->flatcolor.chan[0] = tr / count;
  113. q->flatcolor.chan[1] = tg / count;
  114. q->flatcolor.chan[2] = tb / count;
  115. q->flatcolor.chan[3] = 0xff;
  116. }
  117. //=============================================================================
  118. typedef struct
  119. {
  120. char identification[4]; // should be WAD2 or 2DAW
  121. int numlumps;
  122. int infotableofs;
  123. } wadinfo_t;
  124. typedef struct
  125. {
  126. int filepos;
  127. int disksize;
  128. int size; // uncompressed
  129. char type;
  130. char compression;
  131. char pad1, pad2;
  132. char name[16]; // must be null terminated
  133. } lumpinfo_t;
  134. /*
  135. =================
  136. TEX_InitFromWad
  137. =================
  138. */
  139. void TEX_InitFromWad (char *path)
  140. {
  141. int i;
  142. char local[1024];
  143. char newpath[1024];
  144. byte *wadfile;
  145. wadinfo_t *wadinfo;
  146. lumpinfo_t *lumpinfo;
  147. int numlumps;
  148. float start, stop;
  149. start = I_FloatTime ();
  150. strcpy(newpath, [preferences_i getProjectPath]);
  151. strcat(newpath,"/");
  152. strcat(newpath, path);
  153. // free any textures
  154. for (i=0 ; i<tex_count ; i++)
  155. [qtextures[i].rep free];
  156. tex_count = 0;
  157. // try and use the cached wadfile
  158. sprintf (local, "/qcache%s", newpath);
  159. Sys_UpdateFile (local, newpath);
  160. LoadFile (local, (void **)&wadfile);
  161. wadinfo = (wadinfo_t *)wadfile;
  162. if (strncmp (wadfile, "WAD2", 4))
  163. {
  164. unlink (local);
  165. Error ("TEX_InitFromWad: %s isn't a wadfile", newpath);
  166. }
  167. numlumps = LittleLong (wadinfo->numlumps);
  168. lumpinfo = (lumpinfo_t *)(wadfile + LittleLong (wadinfo->infotableofs));
  169. if (strcmp (lumpinfo->name, "PALETTE"))
  170. {
  171. unlink (local);
  172. Error ("TEX_InitFromWad: %s doesn't have palette as 0",path);
  173. }
  174. TEX_InitPalette (wadfile + LittleLong(lumpinfo->filepos));
  175. lumpinfo++;
  176. for (i=1 ; i<numlumps ; i++, lumpinfo++)
  177. {
  178. if (lumpinfo->type != TYP_MIPTEX)
  179. Error ("TEX_InitFromWad: %s is not a miptex!",lumpinfo->name);
  180. CleanupName (lumpinfo->name,qtextures[tex_count].name);
  181. TEX_ImageFromMiptex ( (miptex_t *)(wadfile +
  182. LittleLong(lumpinfo->filepos) ));
  183. }
  184. free (wadfile);
  185. stop = I_FloatTime ();
  186. qprintf ("loaded %s (%5.1f)", local, stop - start);
  187. }
  188. /*
  189. =================
  190. TEX_NumForName
  191. =================
  192. */
  193. qtexture_t *TEX_ForName (char *name)
  194. {
  195. char newname[16];
  196. int i;
  197. qtexture_t *q;
  198. CleanupName (name, newname);
  199. for (i=0,q = qtextures ; i< tex_count ; i++, q++)
  200. {
  201. if (!strcmp(name, q->name))
  202. return q;
  203. }
  204. return &badtex;
  205. }
  206. //===========================================================================
  207. @implementation TexturePalette
  208. - init
  209. {
  210. [super init];
  211. texturepalette_i = self;
  212. selectedTexture = -1;
  213. return self;
  214. }
  215. - display
  216. {
  217. [[textureView_i superview] display];
  218. return self;
  219. }
  220. - (char *)currentWad
  221. {
  222. return currentwad;
  223. }
  224. - initPaletteFromWadfile:(char *)wf
  225. {
  226. int i;
  227. texpal_t t;
  228. qtexture_t *q;
  229. strcpy (currentwad, wf);
  230. [map_i makeGlobalPerform: @selector(flushTextures)];
  231. selectedTexture = -1;
  232. // Init textures WAD
  233. TEX_InitFromWad(wf);
  234. // Create STORAGE
  235. if (textureList_i)
  236. [textureList_i empty];
  237. else
  238. textureList_i = [[Storage alloc]
  239. initCount:0
  240. elementSize:sizeof(texpal_t)
  241. description:NULL];
  242. // Init STORAGE
  243. for (i = 0,q=qtextures;i < tex_count; i++,q++)
  244. {
  245. t.image = q->rep;
  246. t.r.size.width = [t.image pixelsWide];
  247. if (t.r.size.width < 64)
  248. t.r.size.width = 64;
  249. t.r.size.height = [t.image pixelsHigh] + TEX_SPACING;
  250. t.name = q->name;
  251. t.index = i;
  252. t.display = 1;
  253. [textureList_i addElement:&t];
  254. }
  255. // Calculate size of TextureView
  256. [self alphabetize];
  257. [self computeTextureViewSize];
  258. [textureView_i setParent:self];
  259. [self setSelectedTexture:0];
  260. return self;
  261. }
  262. // Return texture STORAGE list
  263. - getList
  264. {
  265. return textureList_i;
  266. }
  267. // Alphabetize texture list - reverse order!
  268. - alphabetize
  269. {
  270. int i;
  271. int max;
  272. texpal_t *t1p;
  273. texpal_t *t2p;
  274. texpal_t t1;
  275. texpal_t t2;
  276. int found;
  277. max = [textureList_i count];
  278. found = 1;
  279. while(found)
  280. {
  281. found = 0;
  282. for (i = 0;i < max-1;i++)
  283. {
  284. t1p = [textureList_i elementAt:i];
  285. t2p = [textureList_i elementAt:i+1];
  286. if (strcmp(t1p->name,t2p->name) < 0)
  287. {
  288. t1 = *t1p;
  289. t2 = *t2p;
  290. [textureList_i replaceElementAt:i with:&t2];
  291. [textureList_i replaceElementAt:i+1 with:&t1];
  292. found = 1;
  293. }
  294. }
  295. }
  296. return self;
  297. }
  298. - computeTextureViewSize
  299. {
  300. int i;
  301. int max;
  302. int x;
  303. texpal_t *t;
  304. int y;
  305. id view;
  306. NXRect b;
  307. int maxwidth;
  308. int maxheight;
  309. NXPoint pt;
  310. max = [textureList_i count];
  311. y = 0;
  312. maxheight = 0;
  313. x = TEX_INDENT;
  314. view = [textureView_i superview];
  315. [view getBounds:&b];
  316. maxwidth = b.size.width;
  317. for (i = 0;i < max; i++)
  318. {
  319. t = [textureList_i elementAt:i];
  320. if (x + t->r.size.width + TEX_INDENT > maxwidth)
  321. {
  322. x = TEX_INDENT;
  323. y += maxheight;
  324. maxheight = 0;
  325. }
  326. if (t->r.size.height > maxheight)
  327. maxheight = t->r.size.height;
  328. t->r.origin.x = x;
  329. t->r.origin.y = y;
  330. x += t->r.size.width + TEX_INDENT;
  331. if (i == max - 1)
  332. y += t->r.size.height;
  333. }
  334. viewWidth = maxwidth;
  335. viewHeight = y + TEX_SPACING;
  336. [textureView_i sizeTo:viewWidth :viewHeight];
  337. pt.x = pt.y = 0;
  338. [textureView_i scrollPoint:&pt];
  339. return self;
  340. }
  341. - windowResized
  342. {
  343. [self computeTextureViewSize];
  344. return self;
  345. }
  346. - texturedefChanged: sender
  347. {
  348. if ([map_i numSelected])
  349. {
  350. if ( [[map_i currentEntity] modifiable] )
  351. {
  352. [map_i makeSelectedPerform: @selector(takeCurrentTexture)];
  353. [quakeed_i updateAll];
  354. }
  355. else
  356. qprintf ("can't modify spawned entities");
  357. }
  358. [quakeed_i makeFirstResponder: quakeed_i];
  359. return self;
  360. }
  361. - clearTexinfo: sender
  362. {
  363. [field_Xshift_i setFloatValue:0];
  364. [field_Yshift_i setFloatValue:0];
  365. [field_Xscale_i setFloatValue:1];
  366. [field_Yscale_i setFloatValue:1];
  367. [field_Rotate_i setFloatValue:0];
  368. [self texturedefChanged: self];
  369. return self;
  370. }
  371. //
  372. // Set the selected texture
  373. //
  374. - setSelectedTexture:(int)which
  375. {
  376. texpal_t *t;
  377. NXRect r;
  378. char string[16];
  379. // wipe the fields
  380. [self clearTexinfo: self];
  381. if (which != selectedTexture)
  382. {
  383. [textureView_i deselect];
  384. selectedTexture = which;
  385. t = [textureList_i elementAt:which];
  386. r = t->r;
  387. r.size.width += TEX_INDENT*2;
  388. r.size.height += TEX_INDENT*2;
  389. r.origin.x -= TEX_INDENT;
  390. r.origin.y -= TEX_INDENT;
  391. [textureView_i scrollRectToVisible:&r];
  392. [textureView_i display];
  393. sprintf(string,"%d x %d",(int)t->r.size.width,
  394. (int)t->r.size.height - TEX_SPACING);
  395. [sizeField_i setStringValue:string];
  396. }
  397. [self texturedefChanged:self];
  398. return self;
  399. }
  400. //
  401. // Return the selected texture index
  402. //
  403. - (int)getSelectedTexture
  404. {
  405. return selectedTexture;
  406. }
  407. //
  408. // Return the original tex_ index of the selected texture
  409. // so the texture info can be indexed from tex_images, etc.
  410. //
  411. - (int)getSelectedTexIndex
  412. {
  413. texpal_t *t;
  414. if (selectedTexture == -1)
  415. return -1;
  416. t = [textureList_i elementAt:selectedTexture];
  417. return t->index;
  418. }
  419. //
  420. // Return the name of the selected texture
  421. //
  422. - (char *)getSelTextureName
  423. {
  424. texpal_t *t;
  425. if (selectedTexture == -1)
  426. return NULL;
  427. t = [textureList_i elementAt:selectedTexture];
  428. return t->name;
  429. }
  430. //
  431. // Set selected texture by texture name
  432. //
  433. - setTextureByName:(char *)name
  434. {
  435. texpal_t *t;
  436. int i;
  437. int max;
  438. max = [textureList_i count];
  439. CleanupName(name,name);
  440. for (i = 0;i < max;i++)
  441. {
  442. t = [textureList_i elementAt:i];
  443. if (!strcmp(t->name,name))
  444. {
  445. [self setSelectedTexture: i];
  446. return self;
  447. }
  448. }
  449. return self;
  450. }
  451. //===================================================
  452. //
  453. // Action methods
  454. //
  455. //===================================================
  456. //
  457. // Search for texture named in searchField
  458. //
  459. - searchForTexture:sender
  460. {
  461. int i;
  462. int max;
  463. int len;
  464. char name[32];
  465. texpal_t *t;
  466. if (selectedTexture == -1)
  467. return self;
  468. max = [textureList_i count];
  469. strcpy(name,(const char *)[sender stringValue]);
  470. [sender setStringValue:strupr(name)];
  471. len = strlen(name);
  472. for (i = selectedTexture-1;i >= 0; i--)
  473. {
  474. t = [textureList_i elementAt:i];
  475. if (!strncmp(t->name,name,len))
  476. {
  477. [self setTextureByName:t->name];
  478. [sender selectText:sender];
  479. [self texturedefChanged:self];
  480. return self;
  481. }
  482. }
  483. for (i = max-1;i >= selectedTexture; i--)
  484. {
  485. t = [textureList_i elementAt:i];
  486. if (!strncmp(t->name,name,len))
  487. {
  488. [self setTextureByName:t->name];
  489. [sender selectText:sender];
  490. [self texturedefChanged:self];
  491. return self;
  492. }
  493. }
  494. [self texturedefChanged:self];
  495. return self;
  496. }
  497. //
  498. // Set texture def from outside TexturePalette
  499. //
  500. - setTextureDef:(texturedef_t *)td
  501. {
  502. [self setTextureByName:td->texture];
  503. [field_Xshift_i setFloatValue:td->shift[0]];
  504. [field_Yshift_i setFloatValue:td->shift[1]];
  505. [field_Xscale_i setFloatValue:td->scale[0]];
  506. [field_Yscale_i setFloatValue:td->scale[1]];
  507. [field_Rotate_i setFloatValue:td->rotate];
  508. [self texturedefChanged:self];
  509. return self;
  510. }
  511. //
  512. // Return the current texture def to passed *
  513. //
  514. - getTextureDef:(texturedef_t *)td
  515. {
  516. if (selectedTexture == -1)
  517. {
  518. memset (td, 0, sizeof(*td));
  519. strcpy (td->texture, "notexture");
  520. return self;
  521. }
  522. strncpy(td->texture,[self getSelTextureName],16);
  523. td->shift[0] = [field_Xshift_i floatValue];
  524. td->shift[1] = [field_Yshift_i floatValue];
  525. td->scale[0] = [field_Xscale_i floatValue];
  526. td->scale[1] = [field_Yscale_i floatValue];
  527. td->rotate = [field_Rotate_i floatValue];
  528. return self;
  529. }
  530. //============================================================================
  531. //
  532. // Change value in a field
  533. //
  534. - changeField:(id)field by:(int)amount
  535. {
  536. int val;
  537. val = [field intValue];
  538. val += amount;
  539. [field setIntValue:val];
  540. [self texturedefChanged:self];
  541. return self;
  542. }
  543. //
  544. // Inc/Dec the XShift field
  545. //
  546. - incXShift:sender
  547. {
  548. [self changeField:field_Xshift_i by:8];
  549. return self;
  550. }
  551. - decXShift:sender
  552. {
  553. [self changeField:field_Xshift_i by:-8];
  554. return self;
  555. }
  556. //
  557. // Inc/Dec the YShift field
  558. //
  559. - incYShift:sender
  560. {
  561. [self changeField:field_Yshift_i by:8];
  562. return self;
  563. }
  564. - decYShift:sender
  565. {
  566. [self changeField:field_Yshift_i by:-8];
  567. return self;
  568. }
  569. //
  570. // Inc/Dec the Rotate field
  571. //
  572. - incRotate:sender
  573. {
  574. [self changeField:field_Rotate_i by:90];
  575. return self;
  576. }
  577. - decRotate:sender
  578. {
  579. [self changeField:field_Rotate_i by:-90];
  580. return self;
  581. }
  582. //
  583. // Inc/Dec the Xscale field
  584. //
  585. - incXScale:sender
  586. {
  587. [field_Xscale_i setIntValue: 1];
  588. [self texturedefChanged:self];
  589. return self;
  590. }
  591. - decXScale:sender
  592. {
  593. [field_Xscale_i setIntValue: -1];
  594. [self texturedefChanged:self];
  595. return self;
  596. }
  597. //
  598. // Inc/Dec the Yscale field
  599. //
  600. - incYScale:sender
  601. {
  602. [field_Yscale_i setIntValue: 1];
  603. [self texturedefChanged:self];
  604. return self;
  605. }
  606. - decYScale:sender
  607. {
  608. [field_Yscale_i setIntValue: -1];
  609. [self texturedefChanged:self];
  610. return self;
  611. }
  612. //============================================================================
  613. //
  614. // Search for texture in entire palette
  615. // Return index of texturedef, or -1 if unsuccessful
  616. //
  617. - (int) searchForTextureInPalette:(char *)texture
  618. {
  619. int i;
  620. int max;
  621. char name[32];
  622. texpal_t *t;
  623. if (selectedTexture == -1)
  624. return -1;
  625. max = [textureList_i count];
  626. strcpy(name,texture);
  627. for (i = 0; i < max; i++)
  628. {
  629. t = [textureList_i elementAt:i];
  630. if (!strcmp(t->name,name))
  631. return i;
  632. }
  633. return -1;
  634. };
  635. //
  636. // Scan thru map & only display textures that are in map
  637. //
  638. - onlyShowMapTextures:sender
  639. {
  640. int max;
  641. int i;
  642. int j;
  643. id brushes;
  644. SetBrush *b;
  645. int numfaces;
  646. face_t *f;
  647. int index;
  648. // Turn 'em off
  649. if ([sender intValue])
  650. {
  651. max = [textureList_i count];
  652. for (i = 0;i < max; i++)
  653. [self setDisplayFlag:i to:0];
  654. brushes = [map_i objectAt:0];
  655. max = [brushes count];
  656. for (i = 0;i < max; i++)
  657. {
  658. b = (SetBrush *)[brushes objectAt:i];
  659. numfaces = [b getNumBrushFaces];
  660. for (j = 0; j < numfaces; j++)
  661. {
  662. f = [b getBrushFace:j];
  663. index = [self searchForTextureInPalette:f->texture.texture];
  664. if (index >= 0)
  665. [self setDisplayFlag:index to:1];
  666. }
  667. }
  668. }
  669. // Turn 'em on
  670. else
  671. {
  672. max = [textureList_i count];
  673. for (i = 0;i < max; i++)
  674. [self setDisplayFlag:i to:1];
  675. }
  676. [textureView_i display];
  677. return self;
  678. }
  679. - setDisplayFlag:(int)index to:(int)value
  680. {
  681. texpal_t *tp;
  682. tp = [textureList_i elementAt:index];
  683. tp->display = value;
  684. return self;
  685. };
  686. @end