35static bool message_box_displayed=
false;
36bool ThumbnailManagerClass::CreateThumbnailIfNotFound=
false;
44 WWASSERT(!stricmp(&name[len-4],
".tga") || !stricmp(&name[len-4],
".dds"));
69ThumbnailClass::ThumbnailClass(
72 unsigned char* bitmap,
77 unsigned original_mip_level_count,
80 unsigned long date_time)
88 OriginalTextureWidth(original_w),
89 OriginalTextureHeight(original_h),
90 OriginalTextureMipLevelCount(original_mip_level_count),
91 OriginalTextureFormat(original_format),
94 Manager->Insert_To_Hash(
this);
114 OriginalTextureWidth(0),
115 OriginalTextureHeight(0),
116 OriginalTextureMipLevelCount(0),
120 WWPROFILE((
"ThumbnailClass::ThumbnailClass"));
121 unsigned reduction_factor=3;
125 if (dds_file.Is_Available() && dds_file.Load()) {
126 DateTime=dds_file.Get_Date_Time();
128 int len=Name.Get_Length();
135 while (dds_file.Get_Width(level)>32 || dds_file.Get_Height(level)>32) {
136 if (level>=dds_file.Get_Mip_Level_Count())
break;
140 OriginalTextureWidth=dds_file.Get_Full_Width();
141 OriginalTextureHeight=dds_file.Get_Full_Height();
142 OriginalTextureFormat=dds_file.Get_Format();
143 OriginalTextureMipLevelCount=dds_file.Get_Mip_Level_Count();
144 Width=dds_file.Get_Width(0);
145 Height=dds_file.Get_Height(0);
148 dds_file.Copy_Level_To_Surface(
170 WWDEBUG_SAY((
"Unknown texture format for %s\n",filename));
175 OriginalTextureWidth=targa.
Header.Width;
176 OriginalTextureHeight=targa.
Header.Height;
177 OriginalTextureFormat=src_format;
178 Width=targa.
Header.Width>>reduction_factor;
179 Height=targa.
Header.Height>>reduction_factor;
180 OriginalTextureMipLevelCount=1;
183 while (iw<OriginalTextureWidth && ih<OriginalTextureHeight) {
186 OriginalTextureMipLevelCount++;
189 while (Width>32 || Height>32) {
195 unsigned poweroftwowidth = 1;
196 while (poweroftwowidth < Width) {
197 poweroftwowidth <<= 1;
200 unsigned poweroftwoheight = 1;
201 while (poweroftwoheight < Height) {
202 poweroftwoheight <<= 1;
205 Width=poweroftwowidth;
206 Height=poweroftwoheight;
208 unsigned src_width=targa.
Header.Width;
209 unsigned src_height=targa.
Header.Height;
219 WWASSERT(my_tga_file->Is_Available());
221 DateTime=my_tga_file->Get_Date_Time();
222 my_tga_file->Close();
225 unsigned char* src_surface=(
unsigned char*)targa.
GetImage();
227 int len=Name.Get_Length();
249 targa.
Header.CMapDepth>>3,
253 Manager->Insert_To_Hash(
this);
256ThumbnailClass::~ThumbnailClass()
258 if (Allocated)
delete[] Bitmap;
259 Manager->Remove_From_Hash(
this);
262void ThumbnailManagerClass::Create_Thumbnails()
264 SimpleFileFactoryClass ff;
268 MixFileFactoryClass mix(MixFileName, &ff);
271 if (mix.Is_Valid()) {
272 DynamicVectorClass<StringClass> list;
273 list.Set_Growth_Step (1000);
274 mix.Build_Filename_List(list);
275 for (
int i=0;i<list.Count();++i) {
276 int len=list[i].Get_Length();
277 if (!stricmp(&list[i][len-4],
".tga") || !stricmp(&list[i][len-4],
".dds")) {
278 StringClass tex_name(list[i]);
280 new ThumbnailClass(
this,tex_name);
283 if (GlobalThumbnailManager) {
295void ThumbnailManagerClass::Load()
302 SimpleFileFactoryClass ff;
304 FileClass* thumb_file=ff.
Get_File(ThumbnailFileName);
312 thumb_file->
Read(tmp,4);
318 int total_thumb_count;
319 int total_header_length;
320 int total_data_length;
321 thumb_file->
Read(&total_thumb_count,
sizeof(
int));
322 thumb_file->
Read(&total_header_length,
sizeof(
int));
323 thumb_file->
Read(&total_data_length,
sizeof(
int));
324 if (total_thumb_count) {
325 WWASSERT(total_data_length && total_header_length);
326 ThumbnailMemory=
W3DNEWARRAY unsigned char[total_data_length];
328 for (
int i=0;i<total_thumb_count;++i) {
335 int original_mip_level_count;
338 unsigned long date_time;
339 thumb_file->
Read(&date_time,
sizeof(
unsigned long));
340 thumb_file->
Read(&offset,
sizeof(
int));
341 thumb_file->
Read(&width,
sizeof(
int));
342 thumb_file->
Read(&height,
sizeof(
int));
343 thumb_file->
Read(&original_width,
sizeof(
int));
344 thumb_file->
Read(&original_height,
sizeof(
int));
345 thumb_file->
Read(&original_mip_level_count,
sizeof(
int));
346 thumb_file->
Read(&original_format,
sizeof(
int));
347 thumb_file->
Read(&name_len,
sizeof(
int));
349 thumb_file->
Read(name,name_len);
357 if (texture_file->Is_Available()) {
358 texture_file->Open();
359 if (texture_file->Get_Date_Time()!=date_time) {
362 texture_file->Close();
373 ThumbnailMemory+offset-total_header_length,
378 original_mip_level_count,
384 thumb_file->
Read(ThumbnailMemory,total_data_length);
394void ThumbnailManagerClass::Save(
bool force)
397 if (!Changed && !force)
return;
403 HashTemplateIterator<StringClass,ThumbnailClass*> ite(ThumbnailHash);
404 int total_header_length=0;
405 int total_data_length=0;
406 int total_thumb_count=0;
407 total_header_length+=4;
408 total_header_length+=4;
409 total_header_length+=4;
410 total_header_length+=4;
412 for (ite.First();!ite.Is_Done();ite.Next()) {
413 ThumbnailClass* thumb=ite.Peek_Value();
414 total_header_length+=4;
415 total_header_length+=4;
416 total_header_length+=4;
417 total_header_length+=4;
418 total_header_length+=4;
419 total_header_length+=4;
420 total_header_length+=4;
421 total_header_length+=4;
422 total_header_length+=4;
424 total_header_length+=strlen(thumb->
Get_Name());
428 int offset=total_header_length;
430 SimpleFileFactoryClass ff;
432 FileClass* thumb_file=ff.
Get_File(ThumbnailFileName);
442 thumb_file->
Write(&total_thumb_count,
sizeof(
int));
443 thumb_file->
Write(&total_header_length,
sizeof(
int));
444 thumb_file->
Write(&total_data_length,
sizeof(
int));
447 for (ite.First();!ite.Is_Done();ite.Next()) {
448 ThumbnailClass* thumb=ite.Peek_Value();
450 int name_len=strlen(name);
459 thumb_file->
Write(&date_time,
sizeof(
unsigned long));
460 thumb_file->
Write(&offset,
sizeof(
int));
461 thumb_file->
Write(&width,
sizeof(
int));
462 thumb_file->
Write(&height,
sizeof(
int));
463 thumb_file->
Write(&original_width,
sizeof(
int));
464 thumb_file->
Write(&original_height,
sizeof(
int));
465 thumb_file->
Write(&original_mip_level_count,
sizeof(
int));
466 thumb_file->
Write(&original_format,
sizeof(
int));
467 thumb_file->
Write(&name_len,
sizeof(
int));
468 thumb_file->
Write(name,name_len);
469 offset+=width*height*2;
473 offset=total_header_length;
474 for (ite.First();!ite.Is_Done();ite.Next()) {
475 ThumbnailClass* thumb=ite.Peek_Value();
488ThumbnailManagerClass::ThumbnailManagerClass(
const char* thumbnail_filename,
const char* mix_filename)
490 ThumbnailMemory(
NULL),
491 ThumbnailFileName(thumbnail_filename),
492 MixFileName(mix_filename),
493 PerTextureTimeStampUsed(
false),
501ThumbnailManagerClass::~ThumbnailManagerClass()
504 HashTemplateIterator<StringClass,ThumbnailClass*> ite(ThumbnailHash);
506 while (!ite.Is_Done()) {
507 ThumbnailClass* thumb=ite.Peek_Value();
512 if (ThumbnailMemory)
delete[] ThumbnailMemory;
513 ThumbnailMemory=
NULL;
519 ThumbnailManagerClass* man=ThumbnailManagerList.Head();
521 if (man->ThumbnailFileName==thumbnail_filename)
return man;
524 if (GlobalThumbnailManager &&
525 GlobalThumbnailManager->ThumbnailFileName==thumbnail_filename)
return GlobalThumbnailManager;
543 Update_Thumbnail_File(mix_filename,
false);
546 man=
new ThumbnailManagerClass(thumbnail_filename,mix_filename);
547 ThumbnailManagerList.Add_Tail(man);
552 ThumbnailManagerClass* man=ThumbnailManagerList.Head();
554 if (man->ThumbnailFileName==thumbnail_filename) {
560 if (GlobalThumbnailManager &&
561 GlobalThumbnailManager->ThumbnailFileName==thumbnail_filename) {
562 delete GlobalThumbnailManager;
563 GlobalThumbnailManager=
NULL;
570 return Get_From_Hash(name);
575 WWPROFILE((
"Peek_Thumbnail_Instance_From_Any_Manager"));
576 ThumbnailManagerClass* thumb_man=ThumbnailManagerList.Head();
579 if (thumb)
return thumb;
580 thumb_man=thumb_man->
Succ();
583 if (GlobalThumbnailManager) {
584 ThumbnailClass* thumb=GlobalThumbnailManager->Peek_Thumbnail_Instance(filename);
585 if (thumb)
return thumb;
592 if (GlobalThumbnailManager) {
593 ThumbnailClass* thumb=
new ThumbnailClass(GlobalThumbnailManager,filename);
610 Create_Hash_Name(hash_name,thumb->
Get_Name());
611 ThumbnailHash.
Insert(hash_name,thumb);
616 StringClass hash_name(0,
true);
617 Create_Hash_Name(hash_name,name);
618 return ThumbnailHash.Get(hash_name);
621void ThumbnailManagerClass::Remove_From_Hash(
ThumbnailClass* thumb)
624 StringClass hash_name(0,
true);
625 Create_Hash_Name(hash_name,thumb->
Get_Name());
626 ThumbnailHash.Remove(hash_name);
629void ThumbnailManagerClass::Update_Thumbnail_File(
const char* mix_file_name,
bool display_message_box)
631 if (!mix_file_name)
return;
633 SimpleFileFactoryClass ff;
636 StringClass thumb_file_name(mix_file_name,
true);
637 int len=thumb_file_name.Get_Length();
639 thumb_file_name[len-3]=
't';
640 thumb_file_name[len-2]=
'h';
641 thumb_file_name[len-1]=
'6';
642 FileClass* mix_file=ff.
Get_File(mix_file_name);
643 FileClass* thumb_file=ff.
Get_File(thumb_file_name);
664 if (mix_date_time!=thumb_date_time) {
669 thumb_file->
Read(tmp,4);
686 if (display_message_box && !message_box_displayed) {
687 message_box_displayed=
true;
689 "Some or all texture thumbnails need to be updated.\n"
690 "This will take a while. The update will only be done once\n"
691 "each time a mix file changes and thumb database hasn't been\n"
693 "Updating texture thumbnails",
699 ThumbnailManagerClass* manager=
new ThumbnailManagerClass(thumb_file_name, mix_file_name);
700 manager->DateTime=mix_date_time;
701 manager->Create_Thumbnails();
715 WWASSERT(!ThumbnailManagerList.Head());
721 GetCurrentDirectory(
sizeof(cur_dir),cur_dir);
724 SetCurrentDirectory(new_dir);
726 WIN32_FIND_DATA find_data;
727 HANDLE handle=FindFirstFile(
"*.mix",&find_data);
728 if (handle!=INVALID_HANDLE_VALUE) {
730 if (!(find_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) {
731 mix_names.
Add(find_data.cFileName);
733 if (!FindNextFile(handle,&find_data)) {
739 SetCurrentDirectory(cur_dir);
742 Update_Thumbnail_File(
"always.dat",display_message_box);
745 for (
int i=0;i<mix_names.
Count();++i) {
746 Update_Thumbnail_File(mix_names[i],display_message_box);
754 GlobalThumbnailManager->Enable_Per_Texture_Time_Stamp(
true);
759 while (ThumbnailManagerClass* man=ThumbnailManagerList.Head()) {
762 if (GlobalThumbnailManager) {
763 delete GlobalThumbnailManager;
764 GlobalThumbnailManager=
NULL;
#define TARGA_ERROR_HANDLER(call, filename)
static void Copy_Image(unsigned char *dest_surface, unsigned dest_surface_width, unsigned dest_surface_height, unsigned dest_surface_pitch, WW3DFormat dest_surface_format, unsigned char *src_surface, unsigned src_surface_width, unsigned src_surface_height, unsigned src_surface_pitch, WW3DFormat src_surface_format, const unsigned char *src_palette, unsigned src_palette_bpp, bool generate_mip_level, const Vector3 &hsv_shift=Vector3(0.0f, 0.0f, 0.0f))
bool Add(T const &object)
virtual int Create(void)=0
virtual unsigned long Get_Date_Time(void)
virtual bool Set_Date_Time(unsigned long)
virtual bool Is_Available(int forced=false)=0
virtual int Delete(void)=0
virtual int Read(void *buffer, int size)=0
virtual void Close(void)=0
virtual int Open(char const *filename, int rights=READ)=0
virtual int Write(void const *buffer, int size)=0
void Insert(const KeyType &s, const ValueType &d)
virtual void Return_File(FileClass *file)
virtual FileClass * Get_File(char const *filename)
void Set_Sub_Directory(const char *sub_directory)
int Get_Length(void) const
TCHAR * Peek_Buffer(void)
char * SetPalette(char *buffer)
char * GetPalette(void) const
long Load(const char *name, char *palette, char *image, bool invert_image=true)
char * GetImage(void) const
long Open(const char *name, long mode)
WW3DFormat Get_Original_Texture_Format() const
unsigned long Get_Date_Time() const
unsigned Get_Width() const
unsigned Get_Height() const
unsigned Get_Original_Texture_Mip_Level_Count() const
unsigned Get_Original_Texture_Height() const
unsigned char * Peek_Bitmap()
unsigned Get_Original_Texture_Width() const
const StringClass & Get_Name() const
static bool Is_Thumbnail_Created_If_Not_Found()
ThumbnailClass * Peek_Thumbnail_Instance(const StringClass &name)
bool Is_Per_Texture_Time_Stamp_Used() const
static void Pre_Init(bool display_message_box)
static ThumbnailClass * Peek_Thumbnail_Instance_From_Any_Manager(const StringClass &name)
static void Add_Thumbnail_Manager(const char *thumbnail_filename, const char *mix_file_name)
static ThumbnailManagerClass * Peek_Thumbnail_Manager(const char *thumbnail_filename)
static void Remove_Thumbnail_Manager(const char *thumbnail_filename)
FileFactoryClass * _TheFileFactory
const char * ThumbFileHeader
#define GLOBAL_THUMBNAIL_MANAGER_FILENAME